CLOUDSTACK-2328: Linux native VXLAN support on KVM hypervisor

Initial patch for VXLAN support.
Fully functional, hopefully, for GuestNetwork - AdvancedZone.

Patch Note:
 in cloudstack-server
- Add isolation method VXLAN
- Add VxlanGuestNetworkGuru as plugin for VXLAN isolation
- Modify NetworkServiceImpl to handle extended vNet range for VXLAN isolation
- Add VXLAN isolation option in zoneWizard UI

 in cloudstack-agent (kvm)
- Add modifyvxlan.sh script that handle bridge/vxlan interface manipulation script
-- Usage is exactly same to modifyvlan.sh
- BridgeVifDriver will call modifyvxlan.sh instead of modifyvlan.sh when VXLAN is used for isolation

Database changes:
- No change in database structure.
- VXLAN isolation uses same tables that VLAN uses to store vNet allocation status.

Known Issue and/or TODO:
- Some resource still says 'VLAN' in log even if VXLAN is used
- in UI, "Network - GuestNetworks" dosen't display VNI
-- VLAN ID field displays "N/A"
- Documentation!

Signed-off-by : Toshiaki Hatano <haeena@haeena.net>
This commit is contained in:
ynojima 2013-09-23 21:37:38 -06:00 committed by Toshiaki Hatano
parent 6f970c6ff9
commit a45ee749ac
24 changed files with 859 additions and 30 deletions

View File

@ -108,6 +108,7 @@ public class Networks {
},
Mido("mido", String.class),
Pvlan("pvlan", String.class),
Vxlan("vxlan", Long.class),
UnDecided(null, null);
private final String scheme;

View File

@ -39,7 +39,8 @@ public interface PhysicalNetwork extends Identity, InternalIdentity {
STT,
VNS,
MIDO,
SSP;
SSP,
VXLAN;
}
public enum BroadcastDomainRange {

View File

@ -315,6 +315,7 @@ label.add.template=Add Template
label.add.to.group=Add to group
label.add.user=Add User
label.add.vlan=Add VLAN
label.add.vxlan=Add VXLAN
label.add.VM.to.tier=Add VM to tier
label.add.vm=Add VM
label.add.vms.to.lb=Add VM(s) to load balancer rule
@ -545,6 +546,7 @@ label.end.IP=End IP
label.end.port=End Port
label.end.reserved.system.IP=End Reserved system IP
label.end.vlan=End Vlan
label.end.vxlan=End Vxlan
label.endpoint.or.operation=Endpoint or Operation
label.endpoint=Endpoint
label.enter.token=Enter token
@ -1031,12 +1033,14 @@ label.source.nat=Source NAT
label.source=Source
label.specify.IP.ranges=Specify IP ranges
label.specify.vlan=Specify VLAN
label.specify.vxlan=Specify VXLAN
label.SR.name = SR Name-Label
label.srx=SRX
label.start.IP=Start IP
label.start.port=Start Port
label.start.reserved.system.IP=Start Reserved system IP
label.start.vlan=Start Vlan
label.start.vxlan=Start Vxlan
label.state=State
label.static.nat.enabled=Static NAT Enabled
label.static.nat.to=Static NAT to
@ -1163,6 +1167,9 @@ label.virtual.routers=Virtual Routers
label.vlan.id=VLAN ID
label.vlan.range=VLAN Range
label.vlan=VLAN
label.vxlan.id=VXLAN ID
label.vxlan.range=VXLAN Range
label.vxlan=VXLAN
label.vm.add=Add Instance
label.vm.destroy=Destroy
label.vm.display.name=VM display name

View File

@ -224,6 +224,7 @@ label.add.system.service.offering=System-Service-Angebot hinzuf\u00fcgen
label.add.template=Vorlage hinzuf\u00fcgen
label.add.user=Benutzer hinzuf\u00fcgen
label.add.vlan=VLAN hinzuf\u00fcgen
label.add.vxlan=VXLAN hinzuf\u00fcgen
label.add.volume=Volume hinzuf\u00fcgen
label.add.zone=Zone hinzuf\u00fcgen
label.admin.accounts=Administrator-Konten
@ -621,6 +622,9 @@ label.virtual.network=Virtuelles Netzwerk
label.vlan.id=VLAN ID
label.vlan.range=VLAN Reichweite
label.vlan=VLAN
label.vxlan.id=VXLAN ID
label.vxlan.range=VXLAN Reichweite
label.vxlan=VXLAN
label.vm.add=Instanz hinzuf\u00fcgen
label.vm.destroy=Zerst\u00f6ren
label.VMFS.datastore=VMFS Datenspeicher

View File

@ -238,6 +238,7 @@ label.add.template=A\u00c3\u00b1adir plantilla
label.add.to.group=Agregar al grupo
label.add.user=Agregar usuario
label.add.vlan=A\u00c3\u00b1adir VLAN
label.add.vxlan=A\u00c3\u00b1adir VXLAN
label.add.volume=A\u00c3\u00b1adir volumen
label.add.zone=A\u00c3\u00b1adir Zona
label.admin.accounts=Administrador de Cuentas
@ -606,6 +607,7 @@ label.snapshot.s=Instant\u00c3\u00a1nea (s)
label.snapshots=instant\u00c3\u00a1neas
label.source.nat=NAT Fuente
label.specify.vlan=Especifique VLAN
label.specify.vxlan=Especifique VXLAN
label.SR.name = SR Nombre de etiqueta
label.start.port=Iniciar Puerto
label.state=Estado
@ -685,6 +687,9 @@ label.virtual.network=Red Virtual
label.vlan.id=ID de VLAN
label.vlan.range=VLAN Gama
label.vlan=VLAN
label.vxlan.id=ID de VXLAN
label.vxlan.range=VXLAN Gama
label.vxlan=VXLAN
label.vm.add=A\u00c3\u00b1adir Instancia
label.vm.destroy=Destroy
label.VMFS.datastore=VMFS de datos tienda

View File

@ -300,6 +300,7 @@ label.add.template=Ajouter un mod\u00e8le
label.add.to.group=Ajouter au groupe
label.add.user=Ajouter un utilisateur
label.add.vlan=Ajouter un VLAN
label.add.vxlan=Ajouter un VXLAN
label.add.vm=Ajouter VM
label.add.vms=Ajouter VMs
label.add.vms.to.lb=Ajouter une/des VM(s) \u00e0 la r\u00e8gle de r\u00e9partition de charge
@ -512,6 +513,7 @@ label.endpoint=Terminaison
label.end.port=Port de fin
label.end.reserved.system.IP=Adresse IP de fin r\u00e9serv\u00e9e Syst\u00e8me
label.end.vlan=VLAN de fin
label.end.vxlan=VXLAN de fin
label.enter.token=Entrez le jeton unique
label.error.code=Code d\\'erreur
label.error=Erreur
@ -995,12 +997,14 @@ label.source.nat=NAT Source
label.source=Origine
label.specify.IP.ranges=Sp\u00e9cifier des plages IP
label.specify.vlan=Pr\u00e9ciser le VLAN
label.specify.vxlan=Pr\u00e9ciser le VXLAN
label.SR.name = Nom du point de montage
label.srx=SRX
label.start.IP=Plage de d\u00e9but IP
label.start.port=Port de d\u00e9but
label.start.reserved.system.IP=Adresse IP de d\u00e9but r\u00e9serv\u00e9e Syst\u00e8me
label.start.vlan=VLAN de d\u00e9part
label.start.vxlan=VXLAN de d\u00e9part
label.state=\u00c9tat
label.static.nat.enabled=NAT statique activ\u00e9
label.static.nat=NAT Statique
@ -1127,6 +1131,9 @@ label.virtual.routers=Routeurs virtuels
label.vlan.id=ID du VLAN
label.vlan.range=Plage du VLAN
label.vlan=VLAN
label.vxlan.id=VXLAN ID
label.vxlan.range=Plage du VXLAN
label.vxlan=VXLAN
label.vm.add=Ajouter une instance
label.vm.destroy=D\u00e9truire
label.vm.display.name=Nom commun VM

View File

@ -1,4 +1,4 @@
# Licensed to the Apache Software Foundation (ASF) under one
a# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
@ -313,6 +313,7 @@ label.add.template=\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u306e\u8ffd\u52a0
label.add.to.group=\u8ffd\u52a0\u5148\u30b0\u30eb\u30fc\u30d7
label.add.user=\u30e6\u30fc\u30b6\u30fc\u306e\u8ffd\u52a0
label.add.vlan=VLAN \u306e\u8ffd\u52a0
label.add.vxlan=VXLAN \u306e\u8ffd\u52a0
label.add.VM.to.tier=\u968e\u5c64\u3078\u306e VM \u306e\u8ffd\u52a0
label.add.vm=VM \u306e\u8ffd\u52a0
label.add.vms.to.lb=\u8ca0\u8377\u5206\u6563\u898f\u5247\u3078\u306e VM \u306e\u8ffd\u52a0
@ -532,6 +533,7 @@ label.end.IP=\u7d42\u4e86 IP \u30a2\u30c9\u30ec\u30b9
label.end.port=\u7d42\u4e86\u30dd\u30fc\u30c8
label.end.reserved.system.IP=\u4e88\u7d04\u6e08\u307f\u7d42\u4e86\u30b7\u30b9\u30c6\u30e0 IP \u30a2\u30c9\u30ec\u30b9
label.end.vlan=\u7d42\u4e86 VLAN
label.end.vxlan=\u7d42\u4e86 VXLAN
label.endpoint.or.operation=\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u307e\u305f\u306f\u64cd\u4f5c
label.endpoint=\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8
label.enter.token=\u30c8\u30fc\u30af\u30f3\u306e\u5165\u529b
@ -1007,12 +1009,14 @@ label.source.nat=\u9001\u4fe1\u5143 NAT
label.source=\u9001\u4fe1\u5143
label.specify.IP.ranges=IP \u30a2\u30c9\u30ec\u30b9\u306e\u7bc4\u56f2\u306e\u6307\u5b9a
label.specify.vlan=VLAN \u3092\u6307\u5b9a\u3059\u308b
label.specify.vxlan=VXLAN \u3092\u6307\u5b9a\u3059\u308b
label.SR.name = SR \u540d\u30e9\u30d9\u30eb
label.srx=SRX
label.start.IP=\u958b\u59cb IP \u30a2\u30c9\u30ec\u30b9
label.start.port=\u958b\u59cb\u30dd\u30fc\u30c8
label.start.reserved.system.IP=\u4e88\u7d04\u6e08\u307f\u958b\u59cb\u30b7\u30b9\u30c6\u30e0 IP \u30a2\u30c9\u30ec\u30b9
label.start.vlan=\u958b\u59cb VLAN
label.start.vxlan=\u958b\u59cb VXLAN
label.state=\u72b6\u614b
label.static.nat.enabled=\u9759\u7684 NAT \u6709\u52b9
label.static.nat.to=\u9759\u7684 NAT \u306e\u8a2d\u5b9a\u5148:
@ -1139,6 +1143,9 @@ label.virtual.routers=\u4eee\u60f3\u30eb\u30fc\u30bf\u30fc
label.vlan.id=VLAN ID
label.vlan.range=VLAN \u306e\u7bc4\u56f2
label.vlan=VLAN
label.vxlan.id=VXLAN ID
label.vxlan.range=VXLAN \u306e\u7bc4\u56f2
label.vxlan=VXLAN
label.vm.add=\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306e\u8ffd\u52a0
label.vm.destroy=\u7834\u68c4
label.vm.display.name=VM \u8868\u793a\u540d

View File

@ -289,6 +289,7 @@ label.add.to.group=\uadf8\ub8f9\uc5d0 \ucd94\uac00
label.add=\ucd94\uac00
label.add.user=\uc0ac\uc6a9\uc790 \ucd94\uac00
label.add.vlan=VLAN \ucd94\uac00
label.add.vxlan=VXLAN \ucd94\uac00
label.add.vms.to.lb=\ub124\ud2b8\uc6cc\ud06c \ub85c\ub4dc \uacf5\uc720 \uaddc\uce59\uc5d0 VM \ucd94\uac00
label.add.vms=VM \ucd94\uac00
label.add.VM.to.tier=\uacc4\uce35\uc5d0 VM \ucd94\uac00
@ -479,6 +480,7 @@ label.endpoint.or.operation=\uc5d4\ub4dc \ud3ec\uc778\ud2b8 \ub610\ub294 \uc791\
label.end.port=\uc885\ub8cc \ud3ec\ud1a0
label.end.reserved.system.IP=\uc608\uc57d\ub41c \uc885\ub8cc \uc2dc\uc2a4\ud15c IP \uc8fc\uc18c
label.end.vlan=\uc885\ub8cc VLAN
label.end.vxlan=\uc885\ub8cc VXLAN
label.enter.token=\ud1a0\ud070 \uc785\ub825
label.error.code=\uc624\ub958 \ucf54\ub4dc
label.error=\uc624\ub958
@ -925,12 +927,14 @@ label.source.nat=\uc804\uc1a1\uc6d0 NAT
label.source=\uc2dc\uc791 \uc704\uce58
label.specify.IP.ranges=IP \uc8fc\uc18c \ubc94\uc704 \uc9c0\uc815
label.specify.vlan=VLAN \uc9c0\uc815
label.specify.vxlan=VXLAN \uc9c0\uc815
label.SR.name = SR \uba85 \ub77c\ubca8
label.srx=SRX
label.start.IP=\uc2dc\uc791 IP \uc8fc\uc18c
label.start.port=\uc2dc\uc791 \ud3ec\ud1a0
label.start.reserved.system.IP=\uc608\uc57d\ub41c \uc2dc\uc791 \uc2dc\uc2a4\ud15c IP \uc8fc\uc18c
label.start.vlan=\uc2dc\uc791 VLAN
label.start.vxlan=\uc2dc\uc791 VXLAN
label.state=\uc0c1\ud0dc
label.static.nat.enabled=\uc815\uc801 NAT \uc720\ud6a8
label.static.nat.to=\uc815\uc801 NAT \uc124\uc815 \uc704\uce58\:
@ -1055,6 +1059,9 @@ label.virtual.router=\uac00\uc0c1 \ub77c\uc6b0\ud130
label.vlan.id=VLAN ID
label.vlan.range=VLAN \ubc94\uc704
label.vlan=\uac00\uc0c1 \ub124\ud2b8\uc6cc\ud06c(VLAN)
label.vxlan.id=VXLAN ID
label.vxlan.range=VXLAN \ubc94\uc704
label.vxlan=VXLAN
label.vm.add=\uc778\uc2a4\ud134\uc2a4 \ucd94\uac00
label.vm.destroy=\ud30c\uae30
label.vm.display.name=VM \ud45c\uc2dc\uba85

View File

@ -288,6 +288,7 @@ label.add.template=Adicionar Template
label.add.to.group=Adicionar ao grupo
label.add.user=Adicionar Usu\u00e1rio
label.add.vlan=Adicionar VLAN
label.add.vxlan=Adicionar VXLAN
label.add.vm=Adicionar VM
label.add.vms=Adicionar VMs
label.add.vms.to.lb=Add VM(s) na regra de balanceamento de carga
@ -480,6 +481,7 @@ label.endpoint=Ponto de acesso
label.end.port=Porta Final
label.end.reserved.system.IP=Fim dos IPs reservados para o sistema
label.end.vlan=Vlan do fim
label.end.vxlan=Vxlan do fim
label.enter.token=Digite o token
label.error.code=C\u00f3digo de Erro
label.error=Erro
@ -931,12 +933,14 @@ label.source.nat=Source NAT
label.source=Origem
label.specify.IP.ranges=Especifique range de IP
label.specify.vlan=Especificar VLAN
label.specify.vxlan=Especificar VXLAN
label.SR.name = SR Name-Label
label.srx=SRX
label.start.IP=IP do in\u00edcio
label.start.port=Porta de In\u00edcio
label.start.reserved.system.IP=In\u00edcio dos IPs reservados para o sistema
label.start.vlan=Vlan do in\u00edcio
label.start.vxlan=Vxlan do in\u00edcio
label.state=Estado
label.static.nat.enabled=NAT est\u00e1tico Habilitado
label.static.nat=NAT Est\u00e1tico
@ -1059,6 +1063,9 @@ label.virtual.routers=Roteadores Virtuais
label.vlan.id=VLAN ID
label.vlan.range=Intervalo de VLAN
label.vlan=VLAN
label.vxlan.id=VXLAN ID
label.vxlan.range=Intervalo de VXLAN
label.vxlan=VXLAN
label.vm.add=Adicionar Cloud Server
label.vm.destroy=Apagar
label.vm.display.name=Nome de exibi\u00e7\u00e3o da VM

View File

@ -283,6 +283,7 @@ label.add.to.group=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043
label.add=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c
label.add.user=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
label.add.vlan=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c VLAN
label.add.vxlan=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c VXLAN
label.add.vms.to.lb=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0412\u041c \u0432 \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0438 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438
label.add.vms=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0412\u041c
label.add.vm=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0412\u041c
@ -454,6 +455,7 @@ label.endpoint.or.operation=\u041a\u043e\u043d\u0435\u0447\u043d\u0430\u044f \u0
label.end.port=\u041a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u043f\u043e\u0440\u0442
label.end.reserved.system.IP=\u041a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0439 IP-\u0430\u0434\u0440\u0435\u0441
label.end.vlan=\u041a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 VLAN
label.end.vxlan=\u041a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 VXLAN
label.enter.token=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0430\u043b\u043e\u043d
label.error.code=\u041a\u043e\u0434 \u043e\u0448\u0438\u0431\u043a\u0438
label.error=\u041e\u0448\u0438\u0431\u043a\u0430
@ -874,12 +876,14 @@ label.source.nat=Source NAT
label.source=\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a
label.specify.IP.ranges=\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d IP-\u0430\u0434\u0440\u0435\u0441\u043e\u0432
label.specify.vlan=\u0423\u043a\u0430\u0436\u0438\u0442\u0435 VLAN
label.specify.vxlan=\u0423\u043a\u0430\u0436\u0438\u0442\u0435 VXLAN
label.SR.name = SR Name-Label
label.srx=SRX
label.start.IP=\u041d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 IP
label.start.port=\u041d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0440\u0442
label.start.reserved.system.IP=\u041d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0439 IP-\u0430\u0434\u0440\u0435\u0441
label.start.vlan=\u041d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 VLAN
label.start.vxlan=\u041d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 VXLAN
label.state=\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435
label.static.nat.enabled=\u0421\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 NAT \u0432\u043a\u043b\u044e\u0447\u0435\u043d
label.static.nat.to=\u0421\u0442\u0430\u0442\u0438\u0447\u043d\u044b\u0439 NAT \u043a
@ -1001,6 +1005,9 @@ label.virtual.router=\u0412\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044
label.vlan.id=ID VLAN
label.vlan.range=\u0414\u0438\u0430\u043f\u0430\u0437\u043e\u043d VLAN
label.vlan=VLAN
label.vxlan.id=VXLAN ID
label.vxlan.range=\u0414\u0438\u0430\u043f\u0430\u0437\u043e\u043d Range
label.vxlan=VXLAN
label.vm.add=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u0430\u0448\u0438\u043d\u044b
label.vm.destroy=\u0423\u043d\u0438\u0447\u0442\u043e\u0436\u0438\u0442\u044c
label.vm.display.name=\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u043e\u0435 \u0438\u043c\u044f \u0412\u041c

View File

@ -314,6 +314,7 @@ label.add.template=\u6dfb\u52a0\u6a21\u677f
label.add.to.group=\u6dfb\u52a0\u5230\u7ec4
label.add.user=\u6dfb\u52a0\u7528\u6237
label.add.vlan=\u6dfb\u52a0 VLAN
label.add.vxlan=\u6dfb\u52a0 VXLAN
label.add.VM.to.tier=\u5411\u5c42\u4e2d\u6dfb\u52a0 VM
label.add.vm=\u6dfb\u52a0 VM
label.add.vms.to.lb=\u5411\u8d1f\u8f7d\u5e73\u8861\u5668\u89c4\u5219\u4e2d\u6dfb\u52a0 VM
@ -539,6 +540,7 @@ label.end.IP=\u7ed3\u675f IP
label.end.port=\u7ed3\u675f\u7aef\u53e3
label.end.reserved.system.IP=\u7ed3\u675f\u9884\u7559\u7cfb\u7edf IP
label.end.vlan=\u7ed3\u675f VLAN
label.end.vxlan=\u7ed3\u675f VXLAN
label.endpoint.or.operation=\u7aef\u70b9\u6216\u64cd\u4f5c
label.endpoint=\u7aef\u70b9
label.enter.token=\u8f93\u5165\u4ee4\u724c
@ -1025,12 +1027,14 @@ label.source.nat=\u6e90 NAT
label.source=\u6e90\u7b97\u6cd5
label.specify.IP.ranges=\u6307\u5b9a IP \u8303\u56f4
label.specify.vlan=\u6307\u5b9a VLAN
label.specify.vxlan=\u6307\u5b9a VXLAN
label.SR.name = SR \u540d\u79f0\u6807\u7b7e
label.srx=SRX
label.start.IP=\u8d77\u59cb IP
label.start.port=\u8d77\u59cb\u7aef\u53e3
label.start.reserved.system.IP=\u8d77\u59cb\u9884\u7559\u7cfb\u7edf IP
label.start.vlan=\u8d77\u59cb VLAN
label.start.vxlan=\u8d77\u59cb VXLAN
label.state=\u72b6\u6001
label.static.nat.enabled=\u5df2\u542f\u7528\u9759\u6001 NAT
label.static.nat.to=\u9759\u6001 NAT \u76ee\u6807
@ -1157,6 +1161,9 @@ label.virtual.routers=\u865a\u62df\u8def\u7531\u5668
label.vlan.id=VLAN ID
label.vlan.range=VLAN \u8303\u56f4
label.vlan=VLAN
label.vxlan.id=VXLAN ID
label.vxlan.range=VXLAN Range
label.vxlan=VXLAN
label.vm.add=\u6dfb\u52a0\u5b9e\u4f8b
label.vm.destroy=\u9500\u6bc1
label.vm.display.name=VM \u663e\u793a\u540d\u79f0

View File

@ -105,6 +105,11 @@
<artifactId>cloud-plugin-network-internallb</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-plugin-network-vxlan</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-plugin-hypervisor-xen</artifactId>

View File

@ -91,6 +91,13 @@
<bean id="ucsBladeDaoImpl" class="com.cloud.ucs.database.UcsBladeDaoImpl" />
<bean id="ucsManagerDaoImpl" class="com.cloud.ucs.database.UcsManagerDaoImpl" />
<!--
VXLAN support components
-->
<bean id="VxlanGuestNetworkGuru" class="com.cloud.network.guru.VxlanGuestNetworkGuru">
<property name="name" value="VxlanGuestNetworkGuru"/>
</bean>
<!--
Deployment configurations of various adapters
@ -266,6 +273,7 @@
<ref bean="NiciraNvpGuestNetworkGuru"/>
<ref bean="MidoNetGuestNetworkGuru"/>
<ref bean="SspGuestNetworkGuru"/>
<ref bean="VxlanGuestNetworkGuru"/>
</list>
</property>
</bean>

View File

@ -600,8 +600,11 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
}
try {
if (predefined == null ||
(offering.getTrafficType() != TrafficType.Guest && predefined.getCidr() == null && predefined.getBroadcastUri() == null && !(predefined.getBroadcastDomainType() == BroadcastDomainType.Vlan || predefined.getBroadcastDomainType() == BroadcastDomainType.Lswitch))) {
if (predefined == null || (offering.getTrafficType() != TrafficType.Guest && predefined.getCidr() == null && predefined.getBroadcastUri() == null &&
!(predefined.getBroadcastDomainType() == BroadcastDomainType.Vlan ||
predefined.getBroadcastDomainType() == BroadcastDomainType.Lswitch ||
predefined.getBroadcastDomainType() == BroadcastDomainType.Vxlan)
)) {
List<NetworkVO> configs = _networksDao.listBy(owner.getId(), offering.getId(), plan.getDataCenterId());
if (configs.size() > 0) {
if (s_logger.isDebugEnabled()) {
@ -1698,6 +1701,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
}
}
//TODO(VXLAN): Support VNI specified
// VlanId can be specified only when network offering supports it
boolean vlanSpecified = (vlanId != null);
if (vlanSpecified != ntwkOff.getSpecifyVlan()) {

View File

@ -23,6 +23,7 @@ import java.io.File;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.net.URI;
import javax.naming.ConfigurationException;
@ -45,7 +46,9 @@ public class BridgeVifDriver extends VifDriverBase {
private static final Object _vnetBridgeMonitor = new Object();
private String _modifyVlanPath;
private String _modifyVxlanPath;
private String bridgeNameSchema;
@Override
public void configure(Map<String, Object> params) throws ConfigurationException {
@ -69,7 +72,11 @@ public class BridgeVifDriver extends VifDriverBase {
if (_modifyVlanPath == null) {
throw new ConfigurationException("Unable to find modifyvlan.sh");
}
_modifyVxlanPath = Script.findScript(networkScriptsDir, "modifyvxlan.sh");
if (_modifyVxlanPath == null) {
throw new ConfigurationException("Unable to find modifyvxlan.sh");
}
try {
createControlNetwork();
} catch (LibvirtException e) {
@ -87,9 +94,11 @@ public class BridgeVifDriver extends VifDriverBase {
LibvirtVMDef.InterfaceDef intf = new LibvirtVMDef.InterfaceDef();
String vlanId = null;
if (nic.getBroadcastType() == Networks.BroadcastDomainType.Vlan) {
vlanId = Networks.BroadcastDomainType.getValue(nic.getBroadcastUri());
String vNetId = null;
String protocol = null;
if (nic.getBroadcastType() == Networks.BroadcastDomainType.Vlan || nic.getBroadcastType() == Networks.BroadcastDomainType.Vxlan) {
vNetId = Networks.BroadcastDomainType.getValue(nic.getBroadcastUri());
protocol = Networks.BroadcastDomainType.getSchemeValue(nic.getBroadcastUri()).scheme();
}
else if (nic.getBroadcastType() == Networks.BroadcastDomainType.Lswitch) {
throw new InternalErrorException("Nicira NVP Logicalswitches are not supported by the BridgeVifDriver");
@ -97,14 +106,14 @@ public class BridgeVifDriver extends VifDriverBase {
String trafficLabel = nic.getName();
if (nic.getType() == Networks.TrafficType.Guest) {
Integer networkRateKBps = (nic.getNetworkRateMbps() != null && nic.getNetworkRateMbps().intValue() != -1) ? nic.getNetworkRateMbps().intValue() * 128 : 0;
if (nic.getBroadcastType() == Networks.BroadcastDomainType.Vlan
&& !vlanId.equalsIgnoreCase("untagged")) {
if (trafficLabel != null && !trafficLabel.isEmpty()) {
s_logger.debug("creating a vlan dev and bridge for guest traffic per traffic label " + trafficLabel);
String brName = createVlanBr(vlanId, _pifs.get(trafficLabel));
if (nic.getBroadcastType() == Networks.BroadcastDomainType.Vlan && !vNetId.equalsIgnoreCase("untagged")
|| nic.getBroadcastType() == Networks.BroadcastDomainType.Vxlan) {
if(trafficLabel != null && !trafficLabel.isEmpty()) {
s_logger.debug("creating a vNet dev and bridge for guest traffic per traffic label " + trafficLabel);
String brName = createVnetBr(vNetId, _pifs.get(trafficLabel), protocol);
intf.defBridgeNet(brName, null, nic.getMac(), getGuestNicModel(guestOsType), networkRateKBps);
} else {
String brName = createVlanBr(vlanId, _pifs.get("private"));
String brName = createVnetBr(vNetId, _pifs.get("private"), protocol);
intf.defBridgeNet(brName, null, nic.getMac(), getGuestNicModel(guestOsType), networkRateKBps);
}
} else {
@ -117,13 +126,13 @@ public class BridgeVifDriver extends VifDriverBase {
} else if (nic.getType() == Networks.TrafficType.Public) {
Integer networkRateKBps = (nic.getNetworkRateMbps() != null && nic.getNetworkRateMbps().intValue() != -1) ? nic.getNetworkRateMbps().intValue() * 128 : 0;
if (nic.getBroadcastType() == Networks.BroadcastDomainType.Vlan
&& !vlanId.equalsIgnoreCase("untagged")) {
if (trafficLabel != null && !trafficLabel.isEmpty()) {
s_logger.debug("creating a vlan dev and bridge for public traffic per traffic label " + trafficLabel);
String brName = createVlanBr(vlanId, _pifs.get(trafficLabel));
&& !vNetId.equalsIgnoreCase("untagged")) {
if(trafficLabel != null && !trafficLabel.isEmpty()){
s_logger.debug("creating a vNet dev and bridge for public traffic per traffic label " + trafficLabel);
String brName = createVnetBr(vNetId, _pifs.get(trafficLabel), protocol);
intf.defBridgeNet(brName, null, nic.getMac(), getGuestNicModel(guestOsType), networkRateKBps);
} else {
String brName = createVlanBr(vlanId, _pifs.get("public"));
String brName = createVnetBr(vNetId, _pifs.get("public"), protocol);
intf.defBridgeNet(brName, null, nic.getMac(), getGuestNicModel(guestOsType), networkRateKBps);
}
} else {
@ -148,17 +157,22 @@ public class BridgeVifDriver extends VifDriverBase {
return "br" + pifName + "-"+ vnetId;
}
private String createVlanBr(String vlanId, String nic)
private String createVnetBr(String vNetId, String nic, String protocol)
throws InternalErrorException {
String brName = setVnetBrName(nic, vlanId);
createVnet(vlanId, nic, brName);
String brName = setVnetBrName(nic, vNetId);
createVnet(vNetId, nic, brName, protocol);
return brName;
}
private void createVnet(String vnetId, String pif, String brName)
private void createVnet(String vnetId, String pif, String brName, String protocol)
throws InternalErrorException {
synchronized (_vnetBridgeMonitor) {
final Script command = new Script(_modifyVlanPath, _timeout, s_logger);
String script = _modifyVlanPath;
if(protocol.equals(Networks.BroadcastDomainType.Vxlan.scheme())) {
script = _modifyVxlanPath;
}
final Script command = new Script(script, _timeout, s_logger);
command.add("-v", vnetId);
command.add("-p", pif);
command.add("-b", brName);
@ -174,7 +188,7 @@ public class BridgeVifDriver extends VifDriverBase {
private void deleteVnetBr(String brName) {
synchronized (_vnetBridgeMonitor) {
String cmdout = Script.runSimpleBashScript("ls /sys/class/net/" + brName + "/brif | grep vnet");
String cmdout = Script.runSimpleBashScript("ls /sys/class/net/" + brName + "/brif | tr '\n' ' '");
if (cmdout != null && cmdout.contains("vnet")) {
// Active VM remains on that bridge
return;
@ -204,8 +218,16 @@ public class BridgeVifDriver extends VifDriverBase {
s_logger.debug("unable to get a vNet ID from name " + brName);
return;
}
final Script command = new Script(_modifyVlanPath, _timeout, s_logger);
String scriptPath = null;
if (cmdout != null && cmdout.contains("vxlan")) {
scriptPath = _modifyVxlanPath;
} else{
scriptPath = _modifyVlanPath;
}
final Script command = new Script(scriptPath, _timeout, s_logger);
command.add("-o", "delete");
command.add("-v", vNetId);
command.add("-p", pName);

View File

@ -0,0 +1,29 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-plugin-network-vxlan</artifactId>
<name>Apache CloudStack Plugin - Network VXLAN</name>
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
<version>4.3.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
</project>

View File

@ -0,0 +1,179 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.network.guru;
import javax.ejb.Local;
import org.apache.cloudstack.context.CallContext;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.event.ActionEventUtils;
import com.cloud.event.EventTypes;
import com.cloud.event.EventVO;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
import com.cloud.network.Network;
import com.cloud.network.NetworkProfile;
import com.cloud.network.Network.GuestType;
import com.cloud.network.Network.State;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.PhysicalNetwork;
import com.cloud.network.PhysicalNetwork.IsolationMethod;
import com.cloud.network.dao.NetworkVO;
import com.cloud.offering.NetworkOffering;
import com.cloud.user.Account;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
@Component
@Local(value=NetworkGuru.class)
public class VxlanGuestNetworkGuru extends GuestNetworkGuru {
private static final Logger s_logger = Logger.getLogger(VxlanGuestNetworkGuru.class);
public VxlanGuestNetworkGuru() {
super();
_isolationMethods = new IsolationMethod[] { IsolationMethod.VXLAN };
}
@Override
protected boolean canHandle(NetworkOffering offering, final NetworkType networkType, final PhysicalNetwork physicalNetwork) {
// This guru handles only Guest Isolated network that supports Source nat service
if (networkType == NetworkType.Advanced
&& isMyTrafficType(offering.getTrafficType())
&& offering.getGuestType() == Network.GuestType.Isolated
&& isMyIsolationMethod(physicalNetwork)) {
return true;
} else {
s_logger.trace("We only take care of Guest networks of type " + GuestType.Isolated + " in zone of type " + NetworkType.Advanced);
return false;
}
}
@Override
public Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, Account owner) {
NetworkVO network = (NetworkVO) super.design(offering, plan, userSpecified, owner);
if (network == null) {
return null;
}
network.setBroadcastDomainType(BroadcastDomainType.Vxlan);
return network;
}
protected void allocateVnet(Network network, NetworkVO implemented, long dcId,
long physicalNetworkId, String reservationId) throws InsufficientVirtualNetworkCapcityException {
if (network.getBroadcastUri() == null) {
String vnet = _dcDao.allocateVnet(dcId, physicalNetworkId, network.getAccountId(), reservationId,
UseSystemGuestVlans.valueIn(network.getAccountId()));
if (vnet == null) {
throw new InsufficientVirtualNetworkCapcityException("Unable to allocate vnet as a " +
"part of network " + network + " implement ", DataCenter.class, dcId);
}
implemented.setBroadcastUri(BroadcastDomainType.Vxlan.toUri(vnet));
allocateVnetComplete(network, implemented, dcId, physicalNetworkId, reservationId, vnet);
} else {
implemented.setBroadcastUri(network.getBroadcastUri());
}
}
// For Test: Mockit cannot mock static method, wrap it
protected void allocateVnetComplete(Network network, NetworkVO implemented, long dcId,
long physicalNetworkId, String reservationId, String vnet) {
//TODO(VXLAN): Add new event type for vxlan?
ActionEventUtils.onCompletedActionEvent(CallContext.current().getCallingUserId(), network.getAccountId(),
EventVO.LEVEL_INFO, EventTypes.EVENT_ZONE_VLAN_ASSIGN, "Assigned Zone vNet: " + vnet + " Network Id: " + network.getId(), 0);
}
@Override
public Network implement(Network network, NetworkOffering offering,
DeployDestination dest, ReservationContext context)
throws InsufficientVirtualNetworkCapcityException {
assert (network.getState() == State.Implementing) : "Why are we implementing " + network;
long dcId = dest.getDataCenter().getId();
//get physical network id
Long physicalNetworkId = network.getPhysicalNetworkId();
// physical network id can be null in Guest Network in Basic zone, so locate the physical network
if (physicalNetworkId == null) {
physicalNetworkId = _networkModel.findPhysicalNetworkId(dcId, offering.getTags(), offering.getTrafficType());
}
NetworkVO implemented = new NetworkVO(network.getTrafficType(), network.getMode(), network.getBroadcastDomainType(), network.getNetworkOfferingId(), State.Allocated,
network.getDataCenterId(), physicalNetworkId);
allocateVnet(network, implemented, dcId, physicalNetworkId, context.getReservationId());
if (network.getGateway() != null) {
implemented.setGateway(network.getGateway());
}
if (network.getCidr() != null) {
implemented.setCidr(network.getCidr());
}
return implemented;
}
@Override
public void reserve(NicProfile nic, Network network,
VirtualMachineProfile vm,
DeployDestination dest, ReservationContext context)
throws InsufficientVirtualNetworkCapcityException,
InsufficientAddressCapacityException {
super.reserve(nic, network, vm, dest, context);
}
@Override
public boolean release(NicProfile nic,
VirtualMachineProfile vm,
String reservationId) {
return super.release(nic, vm, reservationId);
}
@Override
public void shutdown(NetworkProfile profile, NetworkOffering offering) {
NetworkVO networkObject = _networkDao.findById(profile.getId());
if (networkObject.getBroadcastDomainType() != BroadcastDomainType.Vxlan ||
networkObject.getBroadcastUri() == null) {
s_logger.warn("BroadcastUri is empty or incorrect for guestnetwork " + networkObject.getDisplayText());
return;
}
super.shutdown(profile, offering);
}
@Override
public boolean trash(Network network, NetworkOffering offering) {
return super.trash(network, offering);
}
}

View File

@ -0,0 +1,274 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.network.guru;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Command;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.domain.Domain;
import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
import com.cloud.network.Network;
import com.cloud.network.Network.GuestType;
import com.cloud.network.Network.Service;
import com.cloud.network.Network.State;
import com.cloud.network.NetworkModel;
import com.cloud.network.NetworkProfile;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.PhysicalNetworkVO;
import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
import com.cloud.server.ConfigurationServer;
import com.cloud.user.Account;
import com.cloud.vm.ReservationContext;
import java.util.Arrays;
public class VxlanGuestNetworkGuruTest {
PhysicalNetworkDao physnetdao = mock (PhysicalNetworkDao.class);
DataCenterDao dcdao = mock(DataCenterDao.class);
AgentManager agentmgr = mock (AgentManager.class);
NetworkOrchestrationService netmgr = mock (NetworkOrchestrationService.class);
NetworkModel netmodel = mock (NetworkModel.class);
ConfigurationServer confsvr = mock(ConfigurationServer.class);
NetworkDao netdao = mock(NetworkDao.class);
VxlanGuestNetworkGuru guru;
@Before
public void setUp() {
guru = spy( new VxlanGuestNetworkGuru() );
((GuestNetworkGuru) guru)._physicalNetworkDao = physnetdao;
guru._physicalNetworkDao = physnetdao;
guru._dcDao = dcdao;
guru._networkModel = netmodel;
guru._networkDao = netdao;
((GuestNetworkGuru) guru)._configServer = confsvr;
DataCenterVO dc = mock(DataCenterVO.class);
when(dc.getNetworkType()).thenReturn(NetworkType.Advanced);
when(dc.getGuestNetworkCidr()).thenReturn("10.1.1.1/24");
when(dcdao.findById(anyLong())).thenReturn((DataCenterVO) dc);
}
@Test
public void testCanHandle() {
NetworkOffering offering = mock(NetworkOffering.class);
when(offering.getId()).thenReturn(42L);
when(offering.getTrafficType()).thenReturn(TrafficType.Guest);
when(offering.getGuestType()).thenReturn(GuestType.Isolated);
PhysicalNetworkVO physnet = mock(PhysicalNetworkVO.class);
when(physnet.getIsolationMethods()).thenReturn(Arrays.asList(new String[] { "VXLAN" }));
when(physnet.getId()).thenReturn(42L);
assertTrue(guru.canHandle(offering, NetworkType.Advanced, physnet) == true);
// Not supported TrafficType != Guest
when(offering.getTrafficType()).thenReturn(TrafficType.Management);
assertFalse(guru.canHandle(offering, NetworkType.Advanced, physnet) == true);
// Not supported: GuestType Shared
when(offering.getTrafficType()).thenReturn(TrafficType.Guest);
when(offering.getGuestType()).thenReturn(GuestType.Shared);
assertFalse(guru.canHandle(offering, NetworkType.Advanced, physnet) == true);
// Not supported: Basic networking
when(offering.getGuestType()).thenReturn(GuestType.Isolated);
assertFalse(guru.canHandle(offering, NetworkType.Basic, physnet) == true);
// Not supported: IsolationMethod != VXLAN
when(physnet.getIsolationMethods()).thenReturn(Arrays.asList(new String[] { "VLAN" }));
assertFalse(guru.canHandle(offering, NetworkType.Advanced, physnet) == true);
}
@Test
public void testDesign() {
PhysicalNetworkVO physnet = mock(PhysicalNetworkVO.class);
when(physnetdao.findById(anyLong())).thenReturn(physnet);
when(physnet.getIsolationMethods()).thenReturn(Arrays.asList(new String[] { "VXLAN" }));
when(physnet.getId()).thenReturn(42L);
NetworkOffering offering = mock(NetworkOffering.class);
when(offering.getId()).thenReturn(42L);
when(offering.getTrafficType()).thenReturn(TrafficType.Guest);
when(offering.getGuestType()).thenReturn(GuestType.Isolated);
DeploymentPlan plan = mock(DeploymentPlan.class);
Network network = mock(Network.class);
Account account = mock(Account.class);
Network designednetwork = guru.design(offering, plan, network, account);
assertTrue(designednetwork != null);
assertTrue(designednetwork.getBroadcastDomainType() == BroadcastDomainType.Vxlan);
}
@Test
public void testImplement() throws InsufficientVirtualNetworkCapcityException {
PhysicalNetworkVO physnet = mock(PhysicalNetworkVO.class);
when(physnetdao.findById(anyLong())).thenReturn(physnet);
when(physnet.getIsolationMethods()).thenReturn(Arrays.asList(new String[] { "VXLAN" }));
when(physnet.getId()).thenReturn(42L);
NetworkOffering offering = mock(NetworkOffering.class);
when(offering.getId()).thenReturn(42L);
when(offering.getTrafficType()).thenReturn(TrafficType.Guest);
when(offering.getGuestType()).thenReturn(GuestType.Isolated);
NetworkVO network = mock(NetworkVO.class);
when(network.getName()).thenReturn("testnetwork");
when(network.getState()).thenReturn(State.Implementing);
when(network.getPhysicalNetworkId()).thenReturn(42L);
DeployDestination dest = mock(DeployDestination.class);
DataCenter dc = mock(DataCenter.class);
when(dest.getDataCenter()).thenReturn(dc);
when(netmodel.findPhysicalNetworkId(anyLong(), (String) any(), (TrafficType) any())).thenReturn(42L);
//TODO(VXLAN): doesn't support VNI specified
//when(confsvr.getConfigValue((String) any(), (String) any(), anyLong())).thenReturn("true");
when(dcdao.allocateVnet(anyLong(), anyLong(), anyLong(), (String) any(), eq(true))).thenReturn("42");
doNothing().when(guru).allocateVnetComplete((Network) any(), (NetworkVO) any(), anyLong(), anyLong(), (String) any(), eq("42"));
Domain dom = mock(Domain.class);
when(dom.getName()).thenReturn("domain");
Account acc = mock(Account.class);
when(acc.getAccountName()).thenReturn("accountname");
ReservationContext res = mock(ReservationContext.class);
when(res.getDomain()).thenReturn(dom);
when(res.getAccount()).thenReturn(acc);
Network implementednetwork = guru.implement(network, offering, dest, res);
assertTrue(implementednetwork != null);
}
@Test
public void testImplementWithCidr() throws InsufficientVirtualNetworkCapcityException {
PhysicalNetworkVO physnet = mock(PhysicalNetworkVO.class);
when(physnetdao.findById(anyLong())).thenReturn(physnet);
when(physnet.getIsolationMethods()).thenReturn(Arrays.asList(new String[] { "VXLAN" }));
when(physnet.getId()).thenReturn(42L);
NetworkOffering offering = mock(NetworkOffering.class);
when(offering.getId()).thenReturn(42L);
when(offering.getTrafficType()).thenReturn(TrafficType.Guest);
when(offering.getGuestType()).thenReturn(GuestType.Isolated);
NetworkVO network = mock(NetworkVO.class);
when(network.getName()).thenReturn("testnetwork");
when(network.getState()).thenReturn(State.Implementing);
when(network.getGateway()).thenReturn("10.1.1.1");
when(network.getCidr()).thenReturn("10.1.1.0/24");
when(network.getPhysicalNetworkId()).thenReturn(42L);
DeployDestination dest = mock(DeployDestination.class);
DataCenter dc = mock(DataCenter.class);
when(dest.getDataCenter()).thenReturn(dc);
when(netmodel.findPhysicalNetworkId(anyLong(), (String) any(), (TrafficType) any())).thenReturn(42L);
//TODO(VXLAN): doesn't support VNI specified
//when(confsvr.getConfigValue((String) any(), (String) any(), anyLong())).thenReturn("true");
when(dcdao.allocateVnet(anyLong(), anyLong(), anyLong(), (String) any(), eq(true))).thenReturn("42");
doNothing().when(guru).allocateVnetComplete((Network) any(), (NetworkVO) any(), anyLong(), anyLong(), (String) any(), eq("42"));
Domain dom = mock(Domain.class);
when(dom.getName()).thenReturn("domain");
Account acc = mock(Account.class);
when(acc.getAccountName()).thenReturn("accountname");
ReservationContext res = mock(ReservationContext.class);
when(res.getDomain()).thenReturn(dom);
when(res.getAccount()).thenReturn(acc);
Network implementednetwork = guru.implement(network, offering, dest, res);
assertTrue(implementednetwork != null);
assertTrue(implementednetwork.getCidr().equals("10.1.1.0/24"));
assertTrue(implementednetwork.getGateway().equals("10.1.1.1"));
}
@Test
public void testShutdown() throws InsufficientVirtualNetworkCapcityException, URISyntaxException {
PhysicalNetworkVO physnet = mock(PhysicalNetworkVO.class);
when(physnetdao.findById(anyLong())).thenReturn(physnet);
when(physnet.getIsolationMethods()).thenReturn(Arrays.asList(new String[] { "VXLAN" }));
when(physnet.getId()).thenReturn(42L);
NetworkOffering offering = mock(NetworkOffering.class);
when(offering.getId()).thenReturn(42L);
when(offering.getTrafficType()).thenReturn(TrafficType.Guest);
when(offering.getGuestType()).thenReturn(GuestType.Isolated);
NetworkVO network = mock(NetworkVO.class);
when(network.getName()).thenReturn("testnetwork");
when(network.getState()).thenReturn(State.Implementing);
when(network.getBroadcastDomainType()).thenReturn(BroadcastDomainType.Vxlan);
when(network.getBroadcastUri()).thenReturn(new URI("vxlan:12345"));
when(network.getPhysicalNetworkId()).thenReturn(42L);
when(netdao.findById(42L)).thenReturn(network);
DeployDestination dest = mock(DeployDestination.class);
DataCenter dc = mock(DataCenter.class);
when(dest.getDataCenter()).thenReturn(dc);
when(netmodel.findPhysicalNetworkId(anyLong(), (String) any(), (TrafficType) any())).thenReturn(42L);
Domain dom = mock(Domain.class);
when(dom.getName()).thenReturn("domain");
Account acc = mock(Account.class);
when(acc.getAccountName()).thenReturn("accountname");
ReservationContext res = mock(ReservationContext.class);
when(res.getDomain()).thenReturn(dom);
when(res.getAccount()).thenReturn(acc);
NetworkProfile implementednetwork = mock(NetworkProfile.class);
when(implementednetwork.getId()).thenReturn(42L);
when(implementednetwork.getBroadcastUri()).thenReturn(new URI("vxlan:12345"));
when(offering.getSpecifyVlan()).thenReturn(false);
guru.shutdown(implementednetwork, offering);
verify(implementednetwork, times(1)).setBroadcastUri(null);
}
}

View File

@ -62,6 +62,7 @@
<module>alert-handlers/snmp-alerts</module>
<module>alert-handlers/syslog-alerts</module>
<module>network-elements/internal-loadbalancer</module>
<module>network-elements/vxlan</module>
</modules>
<dependencies>

View File

@ -0,0 +1,230 @@
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# modifyvnet.sh -- adds and deletes VXLANs from a Routing Server
# set -x
## TODO(VXLAN): MTU, IPv6 underlying
usage() {
printf "Usage: %s: -o <op>(add | delete) -v <vxlan id> -p <pif> -b <bridge name>\n"
}
addVxlan() {
local vxlanId=$1
local pif=$2
local vxlanDev=vxlan$vxlanId
local vxlanBr=$3
local mcastGrp="239.$(( $vxlanId >> 16 % 256 )).$(( $vxlanId >> 8 % 256 )).$(( $vxlanId % 256 ))"
## TODO(VXLAN): $brif (trafficlabel) should be passed from caller because we cannot assume 1:1 mapping between pif and brif.
# lookup bridge interface
local sysfs_dir=/sys/devices/virtual/net/
local brif=`find ${sysfs_dir}*/brif/ -name $pif | sed -e "s,$sysfs_dir,," | sed -e 's,/brif/.*$,,'`
if [ "$brif " == " " ]
then
printf "Failed to lookup bridge interface which includes pif: $pif."
return 1
fi
# confirm ip address of $brif
ip addr show $brif | grep -w inet
if [ $? -gt 0 ]
then
printf "Failed to find vxlan multicast source ip address on brif: $brif."
return 1
fi
# mcast route
## TODO(VXLAN): Can we assume there're only one IP address which can be multicast src IP on the IF?
ip route get $mcastGrp | grep -w "dev $brif"
if [ $? -gt 0 ]
then
ip route add $mcastGrp/32 dev $brif
if [ $? -gt 0 ]
then
printf "Failed to add vxlan multicast route on brif: $brif."
return 1
fi
fi
if [ ! -d /sys/class/net/$vxlanDev ]
then
ip link add $vxlanDev type vxlan id $vxlanId group $mcastGrp ttl 10 dev $brif
if [ $? -gt 0 ]
then
# race condition that someone already creates the vxlan
if [ ! -d /sys/class/net/$vxlanDev ]
then
printf "Failed to create vxlan $vxlanId on brif: $brif."
return 1
fi
fi
fi
# is up?
ip link show $vxlanDev | grep -w UP > /dev/null
if [ $? -gt 0 ]
then
ip link set $vxlanDev up > /dev/null
fi
if [ ! -d /sys/class/net/$vxlanBr ]
then
brctl addbr $vxlanBr > /dev/null
if [ $? -gt 0 ]
then
if [ ! -d /sys/class/net/$vxlanBr ]
then
printf "Failed to create br: $vxlanBr"
return 2
fi
fi
brctl setfd $vxlanBr 0
fi
#pif is eslaved into vxlanBr?
ls /sys/class/net/$vxlanBr/brif/ | grep -w "$vxlanDev" > /dev/null
if [ $? -gt 0 ]
then
brctl addif $vxlanBr $vxlanDev > /dev/null
if [ $? -gt 0 ]
then
ls /sys/class/net/$vxlanBr/brif/ | grep -w "$vxlanDev" > /dev/null
if [ $? -gt 0 ]
then
printf "Failed to add vxlan: $vxlanDev to $vxlanBr"
return 3
fi
fi
fi
# is vxlanBr up?
ip link show $vxlanBr | grep -w UP > /dev/null
if [ $? -gt 0 ]
then
ip link set $vxlanBr up
fi
return 0
}
deleteVxlan() {
local vxlanId=$1
local pif=$2
local vxlanDev=vxlan$vxlanId
local vxlanBr=$3
local mcastGrp="239.$(( $vxlanId >> 16 % 256 )).$(( $vxlanId >> 8 % 256 )).$(( $vxlanId % 256 ))"
ip route del $mcastGrp/32 dev $brif
ip link delete $vxlanDev
if [ $? -gt 0 ]
then
printf "Failed to del vxlan: $vxlanId"
printf "Continue..."
fi
ip link set $vxlanBr down
if [ $? -gt 0 ]
then
return 1
fi
brctl delbr $vxlanBr
if [ $? -gt 0 ]
then
printf "Failed to del bridge $vxlanBr"
return 1
fi
return 0
}
op=
vxlanId=
option=$@
while getopts 'o:v:p:b:' OPTION
do
case $OPTION in
o) oflag=1
op="$OPTARG"
;;
v) vflag=1
vxlanId="$OPTARG"
;;
p) pflag=1
pif="$OPTARG"
;;
b) bflag=1
brName="$OPTARG"
;;
?) usage
exit 2
;;
esac
done
# Check that all arguments were passed in
if [ "$oflag$vflag$pflag$bflag" != "1111" ]
then
usage
exit 2
fi
# Do we support Vxlan?
lsmod|grep ^vxlan >& /dev/null
if [ $? -gt 0 ]
then
modprobe=`modprobe vxlan 2>&1`
if [ $? -gt 0 ]
then
printf "Failed to load vxlan kernel module: $modprobe"
exit 1
fi
fi
if [ "$op" == "add" ]
then
# Add the vxlan
addVxlan $vxlanId $pif $brName
# If the add fails then return failure
if [ $? -gt 0 ]
then
exit 1
fi
else
if [ "$op" == "delete" ]
then
# Delete the vxlan
deleteVxlan $vxlanId $pif $brName
# Always exit with success
exit 0
fi
fi

View File

@ -190,6 +190,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
private static final long MAX_VLAN_ID = 4095L; // 2^12 - 1
private static final long MIN_GRE_KEY = 0L;
private static final long MAX_GRE_KEY = 4294967295L; // 2^32 -1
private static final long MIN_VXLAN_VNI = 0L;
private static final long MAX_VXLAN_VNI = 16777215L; // 2^24 -1
@Inject
DataCenterDao _dcDao = null;
@ -2648,6 +2650,9 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
if (network.getIsolationMethods().contains("GRE")) {
minVnet = MIN_GRE_KEY;
maxVnet = MAX_GRE_KEY;
} else if (network.getIsolationMethods().contains("VXLAN")) {
minVnet = MIN_VXLAN_VNI;
maxVnet = MAX_VXLAN_VNI;
}
String rangeMessage = " between " + minVnet + " and " + maxVnet;
if (VnetRange.length == 1 && VnetRange[0].equals("")) {

View File

@ -331,6 +331,7 @@ dictionary = {
'label.add.to.group': '<fmt:message key="label.add.to.group" />',
'label.add.user': '<fmt:message key="label.add.user" />',
'label.add.vlan': '<fmt:message key="label.add.vlan" />',
'label.add.vxlan': '<fmt:message key="label.add.vxlan" />',
'label.add.vm': '<fmt:message key="label.add.vm" />',
'label.add.vms': '<fmt:message key="label.add.vms" />',
'label.add.vms.to.lb': '<fmt:message key="label.add.vms.to.lb" />',
@ -548,6 +549,7 @@ dictionary = {
'label.end.port': '<fmt:message key="label.end.port" />',
'label.end.reserved.system.IP': '<fmt:message key="label.end.reserved.system.IP" />',
'label.end.vlan': '<fmt:message key="label.end.vlan" />',
'label.end.vxlan': '<fmt:message key="label.end.vxlan" />',
'label.enter.token': '<fmt:message key="label.enter.token" />',
'label.error.code': '<fmt:message key="label.error.code" />',
'label.error': '<fmt:message key="label.error" />',
@ -1014,12 +1016,14 @@ dictionary = {
'label.source.nat': '<fmt:message key="label.source.nat" />',
'label.specify.IP.ranges': '<fmt:message key="label.specify.IP.ranges" />',
'label.specify.vlan': '<fmt:message key="label.specify.vlan" />',
'label.specify.vxlan': '<fmt:message key="label.specify.vxlan" />',
'label.SR.name ': '<fmt:message key="label.SR.name " />',
'label.srx': '<fmt:message key="label.srx" />',
'label.start.IP': '<fmt:message key="label.start.IP" />',
'label.start.port': '<fmt:message key="label.start.port" />',
'label.start.reserved.system.IP': '<fmt:message key="label.start.reserved.system.IP" />',
'label.start.vlan': '<fmt:message key="label.start.vlan" />',
'label.start.vxlan': '<fmt:message key="label.start.vxlan" />',
'label.state': '<fmt:message key="label.state" />',
'label.static.nat': '<fmt:message key="label.static.nat" />',
'label.static.nat.to': '<fmt:message key="label.static.nat.to" />',
@ -1138,6 +1142,9 @@ dictionary = {
'label.vlan': '<fmt:message key="label.vlan" />',
'label.vlan.id': '<fmt:message key="label.vlan.id" />',
'label.vlan.range': '<fmt:message key="label.vlan.range" />',
'label.vxlan': '<fmt:message key="label.vxlan" />',
'label.vxlan.id': '<fmt:message key="label.vxlan.id" />',
'label.vxlan.range': '<fmt:message key="label.vxlan.range" />',
'label.vm.add': '<fmt:message key="label.vm.add" />',
'label.vm.destroy': '<fmt:message key="label.vm.destroy" />',
'label.vm.display.name': '<fmt:message key="label.vm.display.name" />',

View File

@ -1168,9 +1168,12 @@ var addExtraPropertiesToGuestNetworkObject = function(jsonObj) {
jsonObj.scope = "Account (" + jsonObj.domain + ", " + jsonObj.account + ")";
}
if (jsonObj.vlan == null && jsonObj.broadcasturi != null) {
if (jsonObj.vlan == null && jsonObj.broadcasturi != null && jsonObj.broadcasturi.substring(0,7) == "vlan://") {
jsonObj.vlan = jsonObj.broadcasturi.replace("vlan://", "");
}
if(jsonObj.vxlan == null && jsonObj.broadcasturi != null && jsonObj.broadcasturi.substring(0,8) == "vxlan://") {
jsonObj.vxlan = jsonObj.broadcasturi.replace("vxlan://", "");
}
}
//used by infrastructure page

View File

@ -715,10 +715,12 @@
$('<option>').attr({
value: 'VNS'
}).html('VNS'),
$('<option>').attr({
value: 'SSP'
}).html('SSP')
}).html('SSP'),
$('<option>').attr({
value: 'VXLAN'
}).html('VXLAN')
)
)
);