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 @@ $('