diff --git a/api/src/com/cloud/network/Networks.java b/api/src/com/cloud/network/Networks.java
index 7069282a669..0412bf45982 100755
--- a/api/src/com/cloud/network/Networks.java
+++ b/api/src/com/cloud/network/Networks.java
@@ -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;
diff --git a/api/src/com/cloud/network/PhysicalNetwork.java b/api/src/com/cloud/network/PhysicalNetwork.java
index f6cb1a6e0b6..55b18e67ba9 100644
--- a/api/src/com/cloud/network/PhysicalNetwork.java
+++ b/api/src/com/cloud/network/PhysicalNetwork.java
@@ -39,7 +39,8 @@ public interface PhysicalNetwork extends Identity, InternalIdentity {
STT,
VNS,
MIDO,
- SSP;
+ SSP,
+ VXLAN;
}
public enum BroadcastDomainRange {
diff --git a/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties
index 459a4edad22..774a15b1d59 100644
--- a/client/WEB-INF/classes/resources/messages.properties
+++ b/client/WEB-INF/classes/resources/messages.properties
@@ -40,7 +40,7 @@ message.acquire.ip.nic=Please confirm that you would like to acquire a new secon
message.select.affinity.groups=Please select any affinity groups you want this VM to belong to:
message.no.affinity.groups=You do not have any affinity groups. Please continue to the next step.
label.action.delete.nic=Remove NIC
-message.action.delete.nic=Please confirm that want to remove this NIC, which will also remove the associated network from the VM.
+message.action.delete.nic=Please confirm that want to remove this NIC, which will also remove the associated network from the VM.
changed.item.properties=Changed item properties
confirm.enable.s3=Please fill in the following information to enable support for S3-backed Secondary Storage
confirm.enable.swift=Please fill in the following information to enable support for Swift
@@ -316,6 +316,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
@@ -413,6 +414,11 @@ label.cluster.type=Cluster Type
label.cluster=Cluster
label.clusters=Clusters
label.clvm=CLVM
+label.rbd=RBD
+label.rbd.monitor=Ceph monitor
+label.rbd.pool=Ceph pool
+label.rbd.id=Cephx user
+label.rbd.secret=Cephx secret
label.code=Code
label.community=Community
label.compute.and.storage=Compute and Storage
@@ -541,6 +547,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
@@ -1027,12 +1034,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
@@ -1159,6 +1168,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
diff --git a/client/WEB-INF/classes/resources/messages_de_DE.properties b/client/WEB-INF/classes/resources/messages_de_DE.properties
index 3c0c8deaabd..2f164609d00 100644
--- a/client/WEB-INF/classes/resources/messages_de_DE.properties
+++ b/client/WEB-INF/classes/resources/messages_de_DE.properties
@@ -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
diff --git a/client/WEB-INF/classes/resources/messages_es.properties b/client/WEB-INF/classes/resources/messages_es.properties
index 86eb596689c..3620047a275 100644
--- a/client/WEB-INF/classes/resources/messages_es.properties
+++ b/client/WEB-INF/classes/resources/messages_es.properties
@@ -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
diff --git a/client/WEB-INF/classes/resources/messages_fr_FR.properties b/client/WEB-INF/classes/resources/messages_fr_FR.properties
index 284fde89386..db624221ddf 100644
--- a/client/WEB-INF/classes/resources/messages_fr_FR.properties
+++ b/client/WEB-INF/classes/resources/messages_fr_FR.properties
@@ -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
diff --git a/client/WEB-INF/classes/resources/messages_ja.properties b/client/WEB-INF/classes/resources/messages_ja.properties
index 56fa55a3e4c..d01efe88ff1 100644
--- a/client/WEB-INF/classes/resources/messages_ja.properties
+++ b/client/WEB-INF/classes/resources/messages_ja.properties
@@ -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
diff --git a/client/WEB-INF/classes/resources/messages_ko_KR.properties b/client/WEB-INF/classes/resources/messages_ko_KR.properties
index 7f3d5ebae75..b755072d613 100644
--- a/client/WEB-INF/classes/resources/messages_ko_KR.properties
+++ b/client/WEB-INF/classes/resources/messages_ko_KR.properties
@@ -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
diff --git a/client/WEB-INF/classes/resources/messages_pt_BR.properties b/client/WEB-INF/classes/resources/messages_pt_BR.properties
index 9f7a663657f..86bb83177a8 100644
--- a/client/WEB-INF/classes/resources/messages_pt_BR.properties
+++ b/client/WEB-INF/classes/resources/messages_pt_BR.properties
@@ -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
diff --git a/client/WEB-INF/classes/resources/messages_ru_RU.properties b/client/WEB-INF/classes/resources/messages_ru_RU.properties
index 37a36a9b022..62c791f61b9 100644
--- a/client/WEB-INF/classes/resources/messages_ru_RU.properties
+++ b/client/WEB-INF/classes/resources/messages_ru_RU.properties
@@ -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
diff --git a/client/WEB-INF/classes/resources/messages_zh_CN.properties b/client/WEB-INF/classes/resources/messages_zh_CN.properties
index 6ab251faaed..acb67bb51f7 100644
--- a/client/WEB-INF/classes/resources/messages_zh_CN.properties
+++ b/client/WEB-INF/classes/resources/messages_zh_CN.properties
@@ -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
diff --git a/client/pom.xml b/client/pom.xml
index 009bc71a691..fd1f13a173e 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -105,6 +105,11 @@
cloud-plugin-network-internallb
${project.version}
+
+ org.apache.cloudstack
+ cloud-plugin-network-vxlan
+ ${project.version}
+
org.apache.cloudstack
cloud-plugin-hypervisor-xen
diff --git a/client/tomcatconf/componentContext.xml.in b/client/tomcatconf/componentContext.xml.in
index 315c95bce27..df5b002f39b 100644
--- a/client/tomcatconf/componentContext.xml.in
+++ b/client/tomcatconf/componentContext.xml.in
@@ -91,6 +91,13 @@
+
+
+
+
+
+
+ 4.0.0
+ cloud-plugin-network-vxlan
+ Apache CloudStack Plugin - Network VXLAN
+
+ org.apache.cloudstack
+ cloudstack-plugins
+ 4.3.0-SNAPSHOT
+ ../../pom.xml
+
+
diff --git a/plugins/network-elements/vxlan/src/com/cloud/network/guru/VxlanGuestNetworkGuru.java b/plugins/network-elements/vxlan/src/com/cloud/network/guru/VxlanGuestNetworkGuru.java
new file mode 100644
index 00000000000..e2ba8689ad8
--- /dev/null
+++ b/plugins/network-elements/vxlan/src/com/cloud/network/guru/VxlanGuestNetworkGuru.java
@@ -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);
+ }
+
+
+
+
+
+}
diff --git a/plugins/network-elements/vxlan/test/com/cloud/network/guru/VxlanGuestNetworkGuruTest.java b/plugins/network-elements/vxlan/test/com/cloud/network/guru/VxlanGuestNetworkGuruTest.java
new file mode 100644
index 00000000000..fc1767444a3
--- /dev/null
+++ b/plugins/network-elements/vxlan/test/com/cloud/network/guru/VxlanGuestNetworkGuruTest.java
@@ -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);
+ }
+}
diff --git a/plugins/pom.xml b/plugins/pom.xml
index ff18e837714..ca41dff9376 100755
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -62,6 +62,7 @@
alert-handlers/snmp-alerts
alert-handlers/syslog-alerts
network-elements/internal-loadbalancer
+ network-elements/vxlan
diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
index a854d2ef415..3eaeb1f080c 100644
--- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
+++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
@@ -25,9 +25,12 @@ import com.cloud.agent.api.to.DataObjectType;
import com.cloud.agent.api.to.DataStoreTO;
import com.cloud.agent.api.to.DataTO;
import com.cloud.agent.api.to.StorageFilerTO;
+import com.cloud.configuration.Config;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.host.dao.HostDao;
+import com.cloud.storage.DataStoreRole;
import com.cloud.storage.ResizeVolumePayload;
+import com.cloud.storage.Storage;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool;
import com.cloud.storage.dao.DiskOfferingDao;
@@ -35,20 +38,28 @@ import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.snapshot.SnapshotManager;
+import com.cloud.template.TemplateManager;
+import com.cloud.utils.NumbersUtil;
import com.cloud.vm.dao.VMInstanceDao;
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.engine.subsystem.api.storage.*;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.storage.command.CommandResult;
+import org.apache.cloudstack.storage.command.CopyCmdAnswer;
+import org.apache.cloudstack.storage.command.CopyCommand;
import org.apache.cloudstack.storage.command.CreateObjectCommand;
import org.apache.cloudstack.storage.command.DeleteCommand;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
+import org.apache.cloudstack.storage.to.TemplateObjectTO;
import org.apache.cloudstack.storage.volume.VolumeObject;
import org.apache.log4j.Logger;
import javax.inject.Inject;
+import java.util.UUID;
public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver {
private static final Logger s_logger = Logger.getLogger(CloudStackPrimaryDataStoreDriverImpl.class);
@@ -74,7 +85,12 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri
SnapshotManager snapshotMgr;
@Inject
EndPointSelector epSelector;
-
+ @Inject
+ ConfigurationDao configDao;
+ @Inject
+ TemplateManager templateManager;
+ @Inject
+ TemplateDataFactory templateDataFactory;
@Override
public DataTO getTO(DataObject data) {
return null;
@@ -165,10 +181,49 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri
@Override
public void copyAsync(DataObject srcdata, DataObject destData, AsyncCompletionCallback callback) {
+ DataStore store = destData.getDataStore();
+ if (store.getRole() == DataStoreRole.Primary) {
+ if ((srcdata.getType() == DataObjectType.TEMPLATE && destData.getType() == DataObjectType.TEMPLATE)) {
+ //For CLVM, we need to copy template to primary storage at all, just fake the copy result.
+ TemplateObjectTO templateObjectTO = new TemplateObjectTO();
+ templateObjectTO.setPath(UUID.randomUUID().toString());
+ templateObjectTO.setSize(srcdata.getSize());
+ templateObjectTO.setPhysicalSize(srcdata.getSize());
+ templateObjectTO.setFormat(Storage.ImageFormat.RAW);
+ CopyCmdAnswer answer = new CopyCmdAnswer(templateObjectTO);
+ CopyCommandResult result = new CopyCommandResult("", answer);
+ callback.complete(result);
+ } else if (srcdata.getType() == DataObjectType.TEMPLATE && destData.getType() == DataObjectType.VOLUME) {
+ //For CLVM, we need to pass template on secondary storage to hypervisor
+ String value = configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
+ int _primaryStorageDownloadWait = NumbersUtil.parseInt(value,
+ Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
+ StoragePoolVO storagePoolVO = primaryStoreDao.findById(store.getId());
+ DataStore imageStore = templateManager.getImageStore(storagePoolVO.getDataCenterId(), srcdata.getId());
+ DataObject srcData = templateDataFactory.getTemplate(srcdata.getId(), imageStore);
+
+ CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _primaryStorageDownloadWait, true);
+ EndPoint ep = epSelector.select(srcData, destData);
+ Answer answer = ep.sendMessage(cmd);
+ CopyCommandResult result = new CopyCommandResult("", answer);
+ callback.complete(result);
+ }
+ }
}
@Override
public boolean canCopy(DataObject srcData, DataObject destData) {
+ //BUG fix for CLOUDSTACK-4618
+ DataStore store = destData.getDataStore();
+ if (store.getRole() == DataStoreRole.Primary) {
+ if ((srcData.getType() == DataObjectType.TEMPLATE && destData.getType() == DataObjectType.TEMPLATE) ||
+ (srcData.getType() == DataObjectType.TEMPLATE && destData.getType() == DataObjectType.VOLUME)) {
+ StoragePoolVO storagePoolVO = primaryStoreDao.findById(store.getId());
+ if (storagePoolVO != null && storagePoolVO.getPoolType() == Storage.StoragePoolType.CLVM) {
+ return true;
+ }
+ }
+ }
return false;
}
diff --git a/pom.xml b/pom.xml
index a8778f11402..1c85bc43d30 100644
--- a/pom.xml
+++ b/pom.xml
@@ -81,7 +81,7 @@
0.9.8
0.10
build/replace.properties
- 0.5.0
+ 0.5.1
0.1.3
target
1.0.10
diff --git a/python/lib/cloudutils/serviceConfig.py b/python/lib/cloudutils/serviceConfig.py
index d129e00c45b..5c552c0b756 100755
--- a/python/lib/cloudutils/serviceConfig.py
+++ b/python/lib/cloudutils/serviceConfig.py
@@ -388,7 +388,8 @@ class nfsConfig(serviceCfgBase):
return True
cfo = configFileOps("/etc/nfsmount.conf")
- cfo.addEntry("AC", "False")
+ cfo.addEntry("Ac", "False")
+ cfo.addEntry("actimeo", "0")
cfo.save()
self.syscfg.svo.enableService("rpcbind")
diff --git a/scripts/storage/qcow2/managesnapshot.sh b/scripts/storage/qcow2/managesnapshot.sh
index 368ff549ee6..42bd1eb2613 100755
--- a/scripts/storage/qcow2/managesnapshot.sh
+++ b/scripts/storage/qcow2/managesnapshot.sh
@@ -42,11 +42,11 @@ fi
is_lv() {
# Must be a block device
- if [ -b "${1}" ]; then
+ if [ -b "${1}" -o -L "{1}" ]; then
# But not a volume group or physical volume
lvm vgs "${1}" > /dev/null 2>&1 && return 1
# And a logical volume
- lvm lvs "${1}" > /dev/null 2>&1 && return 0
+ lvm lvs "${1}" > /dev/null 2>&1 && return 1
fi
return 0
}
diff --git a/scripts/vm/hypervisor/xenserver/xcposs/vmopsSnapshot b/scripts/vm/hypervisor/xenserver/xcposs/vmopsSnapshot
index 31f26ad3c3e..53f31a99eed 100644
--- a/scripts/vm/hypervisor/xenserver/xcposs/vmopsSnapshot
+++ b/scripts/vm/hypervisor/xenserver/xcposs/vmopsSnapshot
@@ -372,8 +372,16 @@ def unmountSnapshotsDir(session, args):
return "1"
-def getPrimarySRPath(primaryStorageSRUuid, isISCSI):
- if isISCSI:
+def getPrimarySRPath(session, primaryStorageSRUuid, isISCSI):
+ sr = session.xenapi.SR.get_by_uuid(primaryStorageSRUuid)
+ srrec = session.xenapi.SR.get_record(sr)
+ srtype = srrec["type"]
+ if srtype == "file":
+ pbd = session.xenapi.SR.get_PBDs(sr)[0]
+ pbdrec = session.xenapi.PBD.get_record(pbd)
+ primarySRPath = pbdrec["device_config"]["location"]
+ return primarySRPath
+ elif isISCSI:
primarySRDir = lvhdutil.VG_PREFIX + primaryStorageSRUuid
return os.path.join(lvhdutil.VG_LOCATION, primarySRDir)
else:
@@ -472,7 +480,7 @@ def getVhdParent(session, args):
snapshotUuid = args['snapshotUuid']
isISCSI = getIsTrueString(args['isISCSI'])
- primarySRPath = getPrimarySRPath(primaryStorageSRUuid, isISCSI)
+ primarySRPath = getPrimarySRPath(session, primaryStorageSRUuid, isISCSI)
util.SMlog("primarySRPath: " + primarySRPath)
baseCopyUuid = getParentOfSnapshot(snapshotUuid, primarySRPath, isISCSI)
@@ -490,7 +498,7 @@ def backupSnapshot(session, args):
isISCSI = getIsTrueString(args['isISCSI'])
path = args['path']
localMountPoint = args['localMountPoint']
- primarySRPath = getPrimarySRPath(primaryStorageSRUuid, isISCSI)
+ primarySRPath = getPrimarySRPath(session, primaryStorageSRUuid, isISCSI)
util.SMlog("primarySRPath: " + primarySRPath)
baseCopyUuid = getParentOfSnapshot(snapshotUuid, primarySRPath, isISCSI)
diff --git a/scripts/vm/network/vnet/modifyvxlan.sh b/scripts/vm/network/vnet/modifyvxlan.sh
new file mode 100755
index 00000000000..45d141a70db
--- /dev/null
+++ b/scripts/vm/network/vnet/modifyvxlan.sh
@@ -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 (add | delete) -v -p -b \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
+
diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
index 3c77958fe30..8a0f7a65a12 100755
--- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -3770,7 +3770,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
}
validateLoadBalancerServiceCapabilities(lbServiceCapabilityMap);
- if (!serviceProviderMap.containsKey(Service.Lb) && lbServiceCapabilityMap != null && !lbServiceCapabilityMap.isEmpty()) {
+ if (lbServiceCapabilityMap != null && !lbServiceCapabilityMap.isEmpty()) {
maxconn = cmd.getMaxconnections();
if (maxconn == null) {
maxconn=Integer.parseInt(_configDao.getValue(Config.NetworkLBHaproxyMaxConn.key()));
@@ -3924,42 +3924,27 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
void validateStaticNatServiceCapablities(Map staticNatServiceCapabilityMap) {
if (staticNatServiceCapabilityMap != null && !staticNatServiceCapabilityMap.isEmpty()) {
- if (staticNatServiceCapabilityMap.keySet().size() > 2) {
- throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " and "
- + Capability.AssociatePublicIP.getName()
- + " capabilitiy can be sepcified for static nat service");
- }
-
boolean eipEnabled = false;
- boolean eipDisabled = false;
boolean associatePublicIP = true;
for (Capability capability : staticNatServiceCapabilityMap.keySet()) {
- String value = staticNatServiceCapabilityMap.get(capability);
+ String value = staticNatServiceCapabilityMap.get(capability).toLowerCase();
+ if (! (value.contains("true") ^ value.contains("false"))) {
+ throw new InvalidParameterValueException("Unknown specified value (" + value + ") for "
+ + capability);
+ }
if (capability == Capability.ElasticIp) {
eipEnabled = value.contains("true");
- eipDisabled = value.contains("false");
- if (!eipEnabled && !eipDisabled) {
- throw new InvalidParameterValueException("Unknown specified value for "
- + Capability.ElasticIp.getName());
- }
} else if (capability == Capability.AssociatePublicIP) {
- if (value.contains("true")) {
- associatePublicIP = true;
- } else if (value.contains("false")) {
- associatePublicIP = false;
- } else {
- throw new InvalidParameterValueException("Unknown specified value for "
- + Capability.AssociatePublicIP.getName());
- }
+ associatePublicIP = value.contains("true");
} else {
throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " and "
+ Capability.AssociatePublicIP.getName()
+ " capabilitiy can be sepcified for static nat service");
}
- if (eipDisabled && associatePublicIP) {
- throw new InvalidParameterValueException("Capability " + Capability.AssociatePublicIP.getName()
- + " can only be set when capability " + Capability.ElasticIp.getName() + " is true");
- }
+ }
+ if ((! eipEnabled) && associatePublicIP) {
+ throw new InvalidParameterValueException("Capability " + Capability.AssociatePublicIP.getName()
+ + " can only be set when capability " + Capability.ElasticIp.getName() + " is true");
}
}
}
diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java
index 52520d43c86..4dbf48693f0 100755
--- a/server/src/com/cloud/network/NetworkServiceImpl.java
+++ b/server/src/com/cloud/network/NetworkServiceImpl.java
@@ -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("")) {
diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java
index 8417066cffb..96ffe35756d 100755
--- a/server/src/com/cloud/storage/StorageManagerImpl.java
+++ b/server/src/com/cloud/storage/StorageManagerImpl.java
@@ -1042,6 +1042,10 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
List snapshots = _snapshotDao.listAllByStatus(Snapshot.State.Error);
for (SnapshotVO snapshotVO : snapshots) {
try {
+ List storeRefs = _snapshotStoreDao.findBySnapshotId(snapshotVO.getId());
+ for(SnapshotDataStoreVO ref : storeRefs) {
+ _snapshotStoreDao.expunge(ref.getId());
+ }
_snapshotDao.expunge(snapshotVO.getId());
} catch (Exception e) {
s_logger.warn("Unable to destroy " + snapshotVO.getId(), e);
diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
index cc995892eb3..16eecd60bc3 100644
--- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
@@ -757,7 +757,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
}
if (diskOffering.getTags() != null) {
- if (!newDiskOffering.getTags().equals(diskOffering.getTags())) {
+ if (newDiskOffering.getTags() == null || !newDiskOffering.getTags().equals(diskOffering.getTags())) {
throw new InvalidParameterValueException("Tags on new and old disk offerings must match");
}
} else if (newDiskOffering.getTags() != null) {
diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
index a884b9542c8..2297e6adde3 100755
--- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
@@ -140,8 +140,6 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
@Inject
protected VMTemplateDao _templateDao;
@Inject
- protected HostDao _hostDao;
- @Inject
protected UserVmDao _vmDao;
@Inject
protected VolumeDao _volsDao;
@@ -158,8 +156,6 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
@Inject
protected PrimaryDataStoreDao _storagePoolDao;
@Inject
- protected EventDao _eventDao;
- @Inject
protected SnapshotPolicyDao _snapshotPolicyDao = null;
@Inject
protected SnapshotScheduleDao _snapshotScheduleDao;
@@ -463,7 +459,9 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
while (snaps.size() > maxSnaps && snaps.size() > 1) {
SnapshotVO oldestSnapshot = snaps.get(0);
long oldSnapId = oldestSnapshot.getId();
- s_logger.debug("Max snaps: " + policy.getMaxSnaps() + " exceeded for snapshot policy with Id: " + policyId + ". Deleting oldest snapshot: " + oldSnapId);
+ if (policy != null) {
+ s_logger.debug("Max snaps: " + policy.getMaxSnaps() + " exceeded for snapshot policy with Id: " + policyId + ". Deleting oldest snapshot: " + oldSnapId);
+ }
if(deleteSnapshot(oldSnapId)){
//log Snapshot delete event
ActionEventUtils.onCompletedActionEvent(User.UID_SYSTEM, oldestSnapshot.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_SNAPSHOT_DELETE, "Successfully deleted oldest snapshot: " + oldSnapId, 0);
@@ -1001,6 +999,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
return true;
}
@Override
+ @DB
public SnapshotInfo takeSnapshot(VolumeInfo volume) throws ResourceAllocationException {
CreateSnapshotPayload payload = (CreateSnapshotPayload)volume.getpayload();
Long snapshotId = payload.getSnapshotId();
@@ -1019,15 +1018,17 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
if (!processed) {
throw new CloudRuntimeException("Can't find snapshot strategy to deal with snapshot:" + snapshotId);
}
- postCreateSnapshot(volume.getId(), snapshotId, payload.getSnapshotPolicyId());
- UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_CREATE, snapshot.getAccountId(),
- snapshot.getDataCenterId(), snapshotId, snapshot.getName(), null, null,
- volume.getSize(), snapshot.getClass().getName(), snapshot.getUuid());
-
-
- _resourceLimitMgr.incrementResourceCount(snapshotOwner.getId(), ResourceType.snapshot);
+ try {
+ postCreateSnapshot(volume.getId(), snapshotId, payload.getSnapshotPolicyId());
+ UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_CREATE, snapshot.getAccountId(),
+ snapshot.getDataCenterId(), snapshotId, snapshot.getName(), null, null,
+ volume.getSize(), snapshot.getClass().getName(), snapshot.getUuid());
+ _resourceLimitMgr.incrementResourceCount(snapshotOwner.getId(), ResourceType.snapshot);
+ } catch (Exception e) {
+ s_logger.debug("post process snapshot failed", e);
+ }
} catch(Exception e) {
s_logger.debug("Failed to create snapshot", e);
if (backup) {
diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java
index e11ac0db3c2..9fa2e8bf2f2 100755
--- a/server/src/com/cloud/template/TemplateManagerImpl.java
+++ b/server/src/com/cloud/template/TemplateManagerImpl.java
@@ -770,29 +770,42 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
}
@Override
+ @DB
public void evictTemplateFromStoragePool(VMTemplateStoragePoolVO templatePoolVO) {
- StoragePool pool = (StoragePool) _dataStoreMgr.getPrimaryDataStore(templatePoolVO.getPoolId());
- VMTemplateVO template = _tmpltDao.findByIdIncludingRemoved(templatePoolVO.getTemplateId());
-
- if (s_logger.isDebugEnabled()) {
- s_logger.debug("Evicting " + templatePoolVO);
+ //Need to hold the lock, otherwise, another thread may create a volume from the template at the same time.
+ //Assumption here is that, we will hold the same lock during create volume from template
+ VMTemplateStoragePoolVO templatePoolRef = _tmpltPoolDao.acquireInLockTable(templatePoolVO.getId());
+ if (templatePoolRef == null) {
+ s_logger.debug("can't aquire the lock for template pool ref:" + templatePoolVO.getId());
+ return;
}
- DestroyCommand cmd = new DestroyCommand(pool, templatePoolVO);
try {
- Answer answer = _storageMgr.sendToPool(pool, cmd);
+ StoragePool pool = (StoragePool) this._dataStoreMgr.getPrimaryDataStore(templatePoolVO.getPoolId());
+ VMTemplateVO template = _tmpltDao.findByIdIncludingRemoved(templatePoolVO.getTemplateId());
- if (answer != null && answer.getResult()) {
- // Remove the templatePoolVO
- if (_tmpltPoolDao.remove(templatePoolVO.getId())) {
- s_logger.debug("Successfully evicted template: " + template.getName() + " from storage pool: " + pool.getName());
- }
- } else {
- s_logger.info("Will retry evicte template: " + template.getName() + " from storage pool: " + pool.getName());
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Evicting " + templatePoolVO);
}
- } catch (StorageUnavailableException e) {
- s_logger.info("Storage is unavailable currently. Will retry evicte template: " + template.getName() + " from storage pool: "
- + pool.getName());
+ DestroyCommand cmd = new DestroyCommand(pool, templatePoolVO);
+
+ try {
+ Answer answer = _storageMgr.sendToPool(pool, cmd);
+
+ if (answer != null && answer.getResult()) {
+ // Remove the templatePoolVO
+ if (_tmpltPoolDao.remove(templatePoolVO.getId())) {
+ s_logger.debug("Successfully evicted template: " + template.getName() + " from storage pool: " + pool.getName());
+ }
+ } else {
+ s_logger.info("Will retry evicte template: " + template.getName() + " from storage pool: " + pool.getName());
+ }
+ } catch (StorageUnavailableException e) {
+ s_logger.info("Storage is unavailable currently. Will retry evicte template: " + template.getName() + " from storage pool: "
+ + pool.getName());
+ }
+ } finally {
+ _tmpltPoolDao.releaseFromLockTable(templatePoolRef.getId());
}
}
@@ -1376,16 +1389,23 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
//getting the prent volume
long parentVolumeId=_snapshotDao.findById(snapshotId).getVolumeId();
VolumeVO parentVolume = _volumeDao.findById(parentVolumeId);
- if (parentVolume.getIsoId() != null) {
+
+ if (parentVolume != null && parentVolume.getIsoId() != null && parentVolume.getIsoId() != 0) {
privateTemplate.setSourceTemplateId(parentVolume.getIsoId());
_tmpltDao.update(privateTemplate.getId(), privateTemplate);
+ } else if (parentVolume != null && parentVolume.getTemplateId() != null) {
+ privateTemplate.setSourceTemplateId(parentVolume.getTemplateId());
+ _tmpltDao.update(privateTemplate.getId(), privateTemplate);
}
}
else if (volumeId != null) {
VolumeVO parentVolume = _volumeDao.findById(volumeId);
- if (parentVolume.getIsoId() != null) {
+ if (parentVolume.getIsoId() != null && parentVolume.getIsoId() != 0) {
privateTemplate.setSourceTemplateId(parentVolume.getIsoId());
_tmpltDao.update(privateTemplate.getId(), privateTemplate);
+ } else if (parentVolume.getTemplateId() != null) {
+ privateTemplate.setSourceTemplateId(parentVolume.getTemplateId());
+ _tmpltDao.update(privateTemplate.getId(), privateTemplate);
}
}
TemplateDataStoreVO srcTmpltStore = _tmplStoreDao.findByStoreTemplate(store.getId(), templateId);
diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java
index 9a035903fbc..396319af538 100755
--- a/server/src/com/cloud/user/AccountManagerImpl.java
+++ b/server/src/com/cloud/user/AccountManagerImpl.java
@@ -857,7 +857,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
@DB
@ActionEvents({
@ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_CREATE, eventDescription = "creating Account"),
- @ActionEvent(eventType = EventTypes.EVENT_USER_CREATE, eventDescription = "creating User"),
+ @ActionEvent(eventType = EventTypes.EVENT_USER_CREATE, eventDescription = "creating User")
})
public UserAccount createUserAccount(String userName, String password, String firstName, String lastName, String email, String timezone, String accountName, short accountType,
Long domainId, String networkDomain, Map details, String accountUUID, String userUUID) {
diff --git a/server/test/com/cloud/configuration/ConfigurationManagerTest.java b/server/test/com/cloud/configuration/ConfigurationManagerTest.java
index e49d93adb47..908f0d01056 100755
--- a/server/test/com/cloud/configuration/ConfigurationManagerTest.java
+++ b/server/test/com/cloud/configuration/ConfigurationManagerTest.java
@@ -27,7 +27,9 @@ import static org.mockito.Mockito.when;
import java.lang.reflect.Field;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.UUID;
import junit.framework.Assert;
@@ -53,7 +55,9 @@ import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.AccountVlanMapDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.VlanDao;
+import com.cloud.exception.InvalidParameterValueException;
import com.cloud.network.IpAddressManager;
+import com.cloud.network.Network.Capability;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.IPAddressVO;
@@ -415,6 +419,70 @@ public class ConfigurationManagerTest {
}
}
+ @Test
+ public void validateEmptyStaticNatServiceCapablitiesTest() {
+ Map staticNatServiceCapabilityMap = new HashMap();
+
+ configurationMgr.validateStaticNatServiceCapablities(staticNatServiceCapabilityMap);
+ }
+
+ @Test
+ public void validateInvalidStaticNatServiceCapablitiesTest() {
+ Map staticNatServiceCapabilityMap = new HashMap();
+ staticNatServiceCapabilityMap.put(Capability.AssociatePublicIP, "Frue and Talse");
+
+ boolean caught = false;
+ try {
+ configurationMgr.validateStaticNatServiceCapablities(staticNatServiceCapabilityMap);
+ }
+ catch (InvalidParameterValueException e) {
+ Assert.assertTrue(e.getMessage(),e.getMessage().contains("(frue and talse)"));
+ caught = true;
+ }
+ Assert.assertTrue("should not be accepted",caught);
+ }
+
+ @Test
+ public void validateTTStaticNatServiceCapablitiesTest() {
+ Map staticNatServiceCapabilityMap = new HashMap();
+ staticNatServiceCapabilityMap.put(Capability.AssociatePublicIP, "true and Talse");
+ staticNatServiceCapabilityMap.put(Capability.ElasticIp, "True");
+
+ configurationMgr.validateStaticNatServiceCapablities(staticNatServiceCapabilityMap);
+ }
+ @Test
+ public void validateFTStaticNatServiceCapablitiesTest() {
+ Map staticNatServiceCapabilityMap = new HashMap();
+ staticNatServiceCapabilityMap.put(Capability.AssociatePublicIP, "false");
+ staticNatServiceCapabilityMap.put(Capability.ElasticIp, "True");
+
+ configurationMgr.validateStaticNatServiceCapablities(staticNatServiceCapabilityMap);
+ }
+ @Test
+ public void validateTFStaticNatServiceCapablitiesTest() {
+ Map staticNatServiceCapabilityMap = new HashMap();
+ staticNatServiceCapabilityMap.put(Capability.AssociatePublicIP, "true and Talse");
+ staticNatServiceCapabilityMap.put(Capability.ElasticIp, "false");
+
+ boolean caught = false;
+ try {
+ configurationMgr.validateStaticNatServiceCapablities(staticNatServiceCapabilityMap);
+ }
+ catch (InvalidParameterValueException e) {
+ Assert.assertTrue(e.getMessage(),e.getMessage().contains("Capability " + Capability.AssociatePublicIP.getName()
+ + " can only be set when capability " + Capability.ElasticIp.getName() + " is true"));
+ caught = true;
+ }
+ Assert.assertTrue("should not be accepted",caught);
+ }
+ @Test
+ public void validateFFStaticNatServiceCapablitiesTest() {
+ Map staticNatServiceCapabilityMap = new HashMap();
+ staticNatServiceCapabilityMap.put(Capability.AssociatePublicIP, "false");
+ staticNatServiceCapabilityMap.put(Capability.ElasticIp, "False");
+
+ configurationMgr.validateStaticNatServiceCapablities(staticNatServiceCapabilityMap);
+ }
public class DedicatePublicIpRangeCmdExtn extends DedicatePublicIpRangeCmd {
@Override
diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql
index e7d9f4423be..522ccc4a272 100644
--- a/setup/db/db/schema-410to420.sql
+++ b/setup/db/db/schema-410to420.sql
@@ -2371,3 +2371,7 @@ CREATE VIEW `cloud`.`data_center_view` AS
`cloud`.`dedicated_resources` ON data_center.id = dedicated_resources.data_center_id
left join
`cloud`.`affinity_group` ON dedicated_resources.affinity_group_id = affinity_group.id;
+
+
+
+UPDATE `cloud`.`ntwk_offering_service_map` SET Provider='VpcVirtualRouter' WHERE network_offering_id IN (SELECT id from `cloud`.`network_offerings` WHERE name IN ('DefaultIsolatedNetworkOfferingForVpcNetworks', 'DefaultIsolatedNetworkOfferingForVpcNetworksNoLB'));
diff --git a/tools/marvin/marvin/deployAndRun.py b/tools/marvin/marvin/deployAndRun.py
index 78c161789a7..d162fb39685 100644
--- a/tools/marvin/marvin/deployAndRun.py
+++ b/tools/marvin/marvin/deployAndRun.py
@@ -17,6 +17,7 @@
import deployDataCenter
import TestCaseExecuteEngine
+import sys
from argparse import ArgumentParser
if __name__ == "__main__":
@@ -37,6 +38,8 @@ if __name__ == "__main__":
parser.add_argument("-l", "--load", dest="load", action="store_true",
help="only load config, do not deploy,\
it will only run testcase")
+ parser.add_argument("-n", "--num", dest="number",
+ help="how many times you want run the test case")
options = parser.parse_args()
@@ -52,23 +55,38 @@ if __name__ == "__main__":
deploy.loadCfg()
else:
deploy.deploy()
+ iterates = 1
+ if options.number is not None:
+ if options.number == "loop":
+ iterates = sys.maxint
+ else:
+ try:
+ iterates = int(options.number)
+ except:
+ iterates = 1
if options.testCaseFolder is None:
if options.module is None:
parser.print_usage()
exit(1)
else:
- engine = \
- TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient,
+ n = 0
+ while(n < iterates):
+ engine = \
+ TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient,
deploy.getCfg(),
testCaseLogFile,
testResultLogFile)
- engine.loadTestsFromFile(options.module)
- engine.run()
+ engine.loadTestsFromFile(options.module)
+ engine.run()
+ n = n + 1
else:
- engine = TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient,
+ n = 0
+ while(n',
'label.add.user': '',
'label.add.vlan': '',
+'label.add.vxlan': '',
'label.add.vm': '',
'label.add.vms': '',
'label.add.vms.to.lb': '',
@@ -549,6 +550,7 @@ dictionary = {
'label.end.port': '',
'label.end.reserved.system.IP': '',
'label.end.vlan': '',
+'label.end.vxlan': '',
'label.enter.token': '',
'label.error.code': '',
'label.error': '',
@@ -904,6 +906,10 @@ dictionary = {
'label.Pxe.server.type': '',
'label.quickview': '',
'label.rbd': '',
+'label.rbd.monitor': '',
+'label.rbd.pool': '',
+'label.rbd.id': '',
+'label.rbd.secret': '',
'label.reboot': '',
'label.recent.errors': '',
'label.redundant.router.capability': '',
@@ -1011,12 +1017,14 @@ dictionary = {
'label.source.nat': '',
'label.specify.IP.ranges': '',
'label.specify.vlan': '',
+'label.specify.vxlan': '',
'label.SR.name ': '',
'label.srx': '',
'label.start.IP': '',
'label.start.port': '',
'label.start.reserved.system.IP': '',
'label.start.vlan': '',
+'label.start.vxlan': '',
'label.state': '',
'label.static.nat': '',
'label.static.nat.to': '',
@@ -1135,6 +1143,9 @@ dictionary = {
'label.vlan': '',
'label.vlan.id': '',
'label.vlan.range': '',
+'label.vxlan': '',
+'label.vxlan.id': '',
+'label.vxlan.range': '',
'label.vm.add': '',
'label.vm.destroy': '',
'label.vm.display.name': '',
diff --git a/ui/scripts/docs.js b/ui/scripts/docs.js
index 1431c1b7b1f..3a4f8ca604f 100755
--- a/ui/scripts/docs.js
+++ b/ui/scripts/docs.js
@@ -643,6 +643,22 @@ cloudStack.docs = {
desc: 'In iSCSI, this is the LUN number. For example, 3.',
externalLink: ''
},
+ helpPrimaryStorageRBDMonitor: {
+ desc: 'The address of a Ceph monitor. Can also be a Round Robin DNS record',
+ externalLink: ''
+ },
+ helpPrimaryStorageRBDPool: {
+ desc: 'The pool to use on the Ceph cluster. This pool should already exist',
+ externalLink: ''
+ },
+ helpPrimaryStorageRBDId: {
+ desc: 'The cephx user to use without the client. prefix. For example: admin',
+ externalLink: ''
+ },
+ helpPrimaryStorageRBDSecret: {
+ desc: 'The base64 encoded secret of the cephx user.',
+ externalLink: ''
+ },
helpPrimaryStorageTags: {
desc: 'Comma-separated list of tags for this storage device. Must be the same set or a superset of the tags on your disk offerings.',
externalLink: ''
diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js
index f1c4ad63c1e..d2c776cb0d8 100644
--- a/ui/scripts/sharedFunctions.js
+++ b/ui/scripts/sharedFunctions.js
@@ -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
diff --git a/ui/scripts/system.js b/ui/scripts/system.js
index ad2c9955a6d..f5ed9a20c43 100644
--- a/ui/scripts/system.js
+++ b/ui/scripts/system.js
@@ -12803,10 +12803,6 @@
id: "SharedMountPoint",
description: "SharedMountPoint"
});
- items.push({
- id: "rbd",
- description: "RBD"
- });
args.response.success({
data: items
});
@@ -13117,6 +13113,7 @@
// RBD
rbdmonitor: {
label: 'label.rbd.monitor',
+ docID: 'helpPrimaryStorageRBDMonitor',
validation: {
required: true
},
@@ -13124,6 +13121,7 @@
},
rbdpool: {
label: 'label.rbd.pool',
+ docID: 'helpPrimaryStorageRBDPool',
validation: {
required: true
},
@@ -13131,6 +13129,7 @@
},
rbdid: {
label: 'label.rbd.id',
+ docID: 'helpPrimaryStorageRBDId',
validation: {
required: false
},
@@ -13138,6 +13137,7 @@
},
rbdsecret: {
label: 'label.rbd.secret',
+ docID: 'helpPrimaryStorageRBDSecret',
validation: {
required: false
},
diff --git a/ui/scripts/ui-custom/zoneWizard.js b/ui/scripts/ui-custom/zoneWizard.js
index cf52107ed33..28df1933fb2 100644
--- a/ui/scripts/ui-custom/zoneWizard.js
+++ b/ui/scripts/ui-custom/zoneWizard.js
@@ -715,10 +715,12 @@
$('