mirror of https://github.com/apache/cloudstack.git
Merge branch 'master' into ui-restyle
This commit is contained in:
commit
23093ed05c
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@ public interface PhysicalNetwork extends Identity, InternalIdentity {
|
|||
STT,
|
||||
VNS,
|
||||
MIDO,
|
||||
SSP;
|
||||
SSP,
|
||||
VXLAN;
|
||||
}
|
||||
|
||||
public enum BroadcastDomainRange {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -105,6 +105,11 @@
|
|||
<artifactId>cloud-plugin-network-internallb</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-plugin-network-vxlan</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-plugin-hypervisor-xen</artifactId>
|
||||
|
|
|
|||
|
|
@ -91,6 +91,13 @@
|
|||
<bean id="ucsBladeDaoImpl" class="com.cloud.ucs.database.UcsBladeDaoImpl" />
|
||||
<bean id="ucsManagerDaoImpl" class="com.cloud.ucs.database.UcsManagerDaoImpl" />
|
||||
|
||||
<!--
|
||||
VXLAN support components
|
||||
-->
|
||||
<bean id="VxlanGuestNetworkGuru" class="com.cloud.network.guru.VxlanGuestNetworkGuru">
|
||||
<property name="name" value="VxlanGuestNetworkGuru"/>
|
||||
</bean>
|
||||
|
||||
<!--
|
||||
|
||||
Deployment configurations of various adapters
|
||||
|
|
@ -266,6 +273,7 @@
|
|||
<ref bean="NiciraNvpGuestNetworkGuru"/>
|
||||
<ref bean="MidoNetGuestNetworkGuru"/>
|
||||
<ref bean="SspGuestNetworkGuru"/>
|
||||
<ref bean="VxlanGuestNetworkGuru"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
|
|
|||
|
|
@ -1215,6 +1215,41 @@ public class VirtualRoutingResource implements Manager {
|
|||
return "Unable to connect";
|
||||
}
|
||||
|
||||
public boolean connect(final String ipAddress, int retry, int sleep) {
|
||||
for (int i = 0; i <= retry; i++) {
|
||||
SocketChannel sch = null;
|
||||
try {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Trying to connect to " + ipAddress);
|
||||
}
|
||||
sch = SocketChannel.open();
|
||||
sch.configureBlocking(true);
|
||||
|
||||
final InetSocketAddress addr = new InetSocketAddress(ipAddress, _port);
|
||||
sch.connect(addr);
|
||||
return true;
|
||||
} catch (final IOException e) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Could not connect to " + ipAddress);
|
||||
}
|
||||
} finally {
|
||||
if (sch != null) {
|
||||
try {
|
||||
sch.close();
|
||||
} catch (final IOException e) {}
|
||||
}
|
||||
}
|
||||
try {
|
||||
Thread.sleep(sleep);
|
||||
} catch (final InterruptedException e) {
|
||||
}
|
||||
}
|
||||
|
||||
s_logger.debug("Unable to logon to " + ipAddress);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return _name;
|
||||
|
|
|
|||
|
|
@ -63,4 +63,8 @@ public final class CopyCommand extends Command implements StorageSubSystemComman
|
|||
this.cacheTO = cacheTO;
|
||||
}
|
||||
|
||||
public int getWaitInMillSeconds() {
|
||||
return this.getWait() * 1000;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1203,10 +1203,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
|
||||
} catch (AgentUnavailableException e) {
|
||||
s_logger.warn("Unable to stop vm, agent unavailable: " + e.toString());
|
||||
throw e;
|
||||
} catch (OperationTimedoutException e) {
|
||||
s_logger.warn("Unable to stop vm, operation timed out: " + e.toString());
|
||||
throw e;
|
||||
} finally {
|
||||
if (!stopped) {
|
||||
if (!cleanUpEvenIfUnableToStop) {
|
||||
|
|
|
|||
|
|
@ -390,7 +390,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
|
||||
Map<Network.Service, Set<Network.Provider>> defaultVPCOffProviders = new HashMap<Network.Service, Set<Network.Provider>>();
|
||||
defaultProviders.clear();
|
||||
defaultProviders.add(Network.Provider.VirtualRouter);
|
||||
defaultProviders.add(Network.Provider.VPCVirtualRouter);
|
||||
defaultVPCOffProviders.put(Service.Dhcp, defaultProviders);
|
||||
defaultVPCOffProviders.put(Service.Dns, defaultProviders);
|
||||
defaultVPCOffProviders.put(Service.UserData, defaultProviders);
|
||||
|
|
@ -600,8 +600,11 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
}
|
||||
|
||||
try {
|
||||
if (predefined == null ||
|
||||
(offering.getTrafficType() != TrafficType.Guest && predefined.getCidr() == null && predefined.getBroadcastUri() == null && !(predefined.getBroadcastDomainType() == BroadcastDomainType.Vlan || predefined.getBroadcastDomainType() == BroadcastDomainType.Lswitch))) {
|
||||
if (predefined == null || (offering.getTrafficType() != TrafficType.Guest && predefined.getCidr() == null && predefined.getBroadcastUri() == null &&
|
||||
!(predefined.getBroadcastDomainType() == BroadcastDomainType.Vlan ||
|
||||
predefined.getBroadcastDomainType() == BroadcastDomainType.Lswitch ||
|
||||
predefined.getBroadcastDomainType() == BroadcastDomainType.Vxlan)
|
||||
)) {
|
||||
List<NetworkVO> configs = _networksDao.listBy(owner.getId(), offering.getId(), plan.getDataCenterId());
|
||||
if (configs.size() > 0) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
|
|
@ -1698,6 +1701,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
}
|
||||
}
|
||||
|
||||
//TODO(VXLAN): Support VNI specified
|
||||
// VlanId can be specified only when network offering supports it
|
||||
boolean vlanSpecified = (vlanId != null);
|
||||
if (vlanSpecified != ntwkOff.getSpecifyVlan()) {
|
||||
|
|
|
|||
|
|
@ -1084,7 +1084,8 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
|
|||
public boolean canVmRestartOnAnotherServer(long vmId) {
|
||||
List<VolumeVO> vols = _volsDao.findCreatedByInstance(vmId);
|
||||
for (VolumeVO vol : vols) {
|
||||
if (!vol.isRecreatable() && !vol.getPoolType().isShared()) {
|
||||
StoragePoolVO storagePoolVO = _storagePoolDao.findById(vol.getPoolId());
|
||||
if (!vol.isRecreatable() && storagePoolVO != null && storagePoolVO.getPoolType() != null && !(storagePoolVO.getPoolType().isShared())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -383,9 +383,6 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker {
|
|||
try {
|
||||
String dbVersion = _dao.getCurrentVersion();
|
||||
String currentVersion = this.getClass().getPackage().getImplementationVersion();
|
||||
if (currentVersion == null) {
|
||||
currentVersion = this.getClass().getSuperclass().getPackage().getImplementationVersion();
|
||||
}
|
||||
|
||||
if (currentVersion == null)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -40,4 +40,5 @@ StateDao<ObjectInDataStoreStateMachine.State, ObjectInDataStoreStateMachine.Even
|
|||
SnapshotDataStoreVO findBySnapshot(long snapshotId, DataStoreRole role);
|
||||
|
||||
List<SnapshotDataStoreVO> listDestroyed(long storeId);
|
||||
List<SnapshotDataStoreVO> findBySnapshotId(long snapshotId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ package org.apache.cloudstack.storage.test;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.cloud.event.ActionEventUtils;
|
||||
import com.cloud.event.dao.EventDaoImpl;
|
||||
import org.apache.cloudstack.acl.APIChecker;
|
||||
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
|
||||
import org.apache.cloudstack.engine.service.api.OrchestrationService;
|
||||
|
|
@ -107,7 +109,7 @@ import com.cloud.vm.snapshot.dao.VMSnapshotDaoImpl;
|
|||
VMSnapshotDaoImpl.class, OCFS2ManagerImpl.class, ClusterDetailsDaoImpl.class, SecondaryStorageVmDaoImpl.class,
|
||||
ConsoleProxyDaoImpl.class, StoragePoolWorkDaoImpl.class, StorageCacheManagerImpl.class, UserDaoImpl.class,
|
||||
DataCenterDaoImpl.class, StoragePoolDetailsDaoImpl.class, DomainDaoImpl.class, DownloadMonitorImpl.class,
|
||||
AccountDaoImpl.class }, includeFilters = { @Filter(value = Library.class, type = FilterType.CUSTOM) },
|
||||
AccountDaoImpl.class, ActionEventUtils.class, EventDaoImpl.class}, includeFilters = { @Filter(value = Library.class, type = FilterType.CUSTOM) },
|
||||
useDefaultFilters = false)
|
||||
public class ChildTestConfiguration extends TestConfiguration {
|
||||
|
||||
|
|
@ -186,12 +188,6 @@ public class ChildTestConfiguration extends TestConfiguration {
|
|||
return Mockito.mock(VirtualMachineManager.class);
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public SnapshotManager snapshotMgr() {
|
||||
return Mockito.mock(SnapshotManager.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ResourceManager resourceMgr() {
|
||||
return Mockito.mock(ResourceManager.class);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@ import java.util.Map;
|
|||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.Status;
|
||||
import com.cloud.utils.fsm.NoTransitionException;
|
||||
import com.cloud.utils.fsm.StateMachine2;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.AgentManager;
|
||||
|
|
@ -246,6 +250,7 @@ public class DirectAgentManagerSimpleImpl extends ManagerBase implements AgentMa
|
|||
e1.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
package org.apache.cloudstack.storage.test;
|
||||
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
|
@ -28,6 +29,7 @@ import java.util.UUID;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.server.LockMasterListener;
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Before;
|
||||
|
|
@ -58,6 +60,9 @@ import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
|
|||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
|
||||
import com.cloud.agent.AgentManager;
|
||||
|
||||
import com.cloud.agent.AgentManager;
|
||||
|
||||
import com.cloud.dc.ClusterVO;
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
|
|
@ -88,6 +93,7 @@ import com.cloud.user.User;
|
|||
import com.cloud.utils.component.ComponentContext;
|
||||
import com.cloud.utils.db.Merovingian2;
|
||||
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = { "classpath:/fakeDriverTestContext.xml" })
|
||||
public class EndpointSelectorTest {
|
||||
|
|
@ -121,6 +127,8 @@ public class EndpointSelectorTest {
|
|||
ImageStoreVO imageStore;
|
||||
@Inject
|
||||
AccountManager accountManager;
|
||||
|
||||
LockMasterListener lockMasterListener;
|
||||
VolumeInfo vol = null;
|
||||
FakePrimaryDataStoreDriver driver = new FakePrimaryDataStoreDriver();
|
||||
@Inject
|
||||
|
|
|
|||
|
|
@ -18,10 +18,12 @@
|
|||
*/
|
||||
package org.apache.cloudstack.storage.test;
|
||||
|
||||
|
||||
import com.cloud.storage.snapshot.SnapshotScheduler;
|
||||
import com.cloud.storage.snapshot.SnapshotSchedulerImpl;
|
||||
import com.cloud.user.DomainManager;
|
||||
import com.cloud.utils.component.ComponentContext;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
|
||||
|
|
@ -63,5 +65,5 @@ public class FakeDriverTestConfiguration extends ChildTestConfiguration{
|
|||
public EndPointSelector selector() {
|
||||
return ComponentContext.inject(DefaultEndPointSelector.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,25 +19,39 @@
|
|||
package org.apache.cloudstack.storage.test;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.storage.Storage;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
|
||||
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
import com.cloud.host.Host;
|
||||
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
|
||||
import org.apache.cloudstack.storage.snapshot.SnapshotObject;
|
||||
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
|
||||
import org.apache.cloudstack.storage.to.TemplateObjectTO;
|
||||
|
||||
public class MockStorageMotionStrategy implements DataMotionStrategy {
|
||||
|
||||
boolean success = true;
|
||||
@Override
|
||||
public boolean canHandle(DataObject srcData, DataObject destData) {
|
||||
// TODO Auto-generated method stub
|
||||
return true;
|
||||
}
|
||||
|
||||
public void makeBackupSnapshotSucceed(boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHandle(Map<VolumeInfo, DataStore> volumeMap, Host srcHost, Host destHost) {
|
||||
return true;
|
||||
|
|
@ -45,7 +59,32 @@ public class MockStorageMotionStrategy implements DataMotionStrategy {
|
|||
|
||||
@Override
|
||||
public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
|
||||
CopyCommandResult result = new CopyCommandResult("something", null);
|
||||
CopyCmdAnswer answer = null;
|
||||
DataTO data = null;
|
||||
if (!success) {
|
||||
CopyCommandResult result = new CopyCommandResult(null, null);
|
||||
result.setResult("Failed");
|
||||
callback.complete(result);
|
||||
}
|
||||
if (destData.getType() == DataObjectType.SNAPSHOT) {
|
||||
SnapshotInfo srcSnapshot = (SnapshotInfo)srcData;
|
||||
|
||||
SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
|
||||
newSnapshot.setPath(UUID.randomUUID().toString());
|
||||
if (srcSnapshot.getParent() != null) {
|
||||
newSnapshot.setParentSnapshotPath(srcSnapshot.getParent().getPath());
|
||||
}
|
||||
data = newSnapshot;
|
||||
} else if (destData.getType() == DataObjectType.TEMPLATE) {
|
||||
TemplateObjectTO newTemplate = new TemplateObjectTO();
|
||||
newTemplate.setPath(UUID.randomUUID().toString());
|
||||
newTemplate.setFormat(Storage.ImageFormat.QCOW2);
|
||||
newTemplate.setSize(10L);
|
||||
newTemplate.setPhysicalSize(10L);
|
||||
data = newTemplate;
|
||||
}
|
||||
answer = new CopyCmdAnswer(data);
|
||||
CopyCommandResult result = new CopyCommandResult("something", answer);
|
||||
callback.complete(result);
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,17 +18,37 @@
|
|||
*/
|
||||
package org.apache.cloudstack.storage.test;
|
||||
|
||||
import com.cloud.cluster.LockMasterListener;
|
||||
import com.cloud.dc.ClusterVO;
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
import com.cloud.dc.HostPodVO;
|
||||
import com.cloud.dc.dao.ClusterDao;
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.dc.dao.HostPodDao;
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.org.Cluster;
|
||||
import com.cloud.org.Managed;
|
||||
import com.cloud.storage.CreateSnapshotPayload;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.ScopeType;
|
||||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.storage.SnapshotPolicyVO;
|
||||
import com.cloud.storage.SnapshotVO;
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.StoragePoolStatus;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.dao.SnapshotDao;
|
||||
import com.cloud.storage.dao.SnapshotPolicyDao;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.User;
|
||||
import com.cloud.utils.DateUtil;
|
||||
import com.cloud.utils.component.ComponentContext;
|
||||
import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.db.Merovingian2;
|
||||
import junit.framework.Assert;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
|
|
@ -44,10 +64,14 @@ import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
|
|||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService;
|
||||
import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
import org.apache.cloudstack.storage.volume.VolumeObject;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
|
@ -58,13 +82,25 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
|||
import javax.inject.Inject;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = { "classpath:/fakeDriverTestContext.xml" })
|
||||
public class SnapshotTestWithFakeData {
|
||||
public class SnapshotTestWithFakeData {
|
||||
@Inject
|
||||
SnapshotService snapshotService;
|
||||
@Inject
|
||||
|
|
@ -85,30 +121,106 @@ public class SnapshotTestWithFakeData {
|
|||
VolumeService volumeService;
|
||||
@Inject
|
||||
VolumeDataFactory volumeDataFactory;
|
||||
@Inject
|
||||
DataCenterDao dcDao;
|
||||
Long dcId;
|
||||
@Inject
|
||||
HostPodDao podDao;
|
||||
Long podId;
|
||||
@Inject
|
||||
ClusterDao clusterDao;
|
||||
Long clusterId;
|
||||
@Inject
|
||||
ImageStoreDao imageStoreDao;
|
||||
ImageStoreVO imageStore;
|
||||
@Inject
|
||||
AccountManager accountManager;
|
||||
LockMasterListener lockMasterListener;
|
||||
VolumeInfo vol = null;
|
||||
FakePrimaryDataStoreDriver driver = new FakePrimaryDataStoreDriver();
|
||||
@Inject
|
||||
MockStorageMotionStrategy mockStorageMotionStrategy;
|
||||
Merovingian2 _lockMaster;
|
||||
@Inject
|
||||
SnapshotPolicyDao snapshotPolicyDao;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
Mockito.when(primaryDataStoreProvider.configure(Mockito.anyMap())).thenReturn(true);
|
||||
// create data center
|
||||
|
||||
DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null,
|
||||
"10.0.0.1/24", null, null, DataCenter.NetworkType.Basic, null, null, true, true, null, null);
|
||||
dc = dcDao.persist(dc);
|
||||
dcId = dc.getId();
|
||||
// create pod
|
||||
|
||||
HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), "10.223.0.1",
|
||||
"10.233.2.2/25", 8, "test");
|
||||
pod = podDao.persist(pod);
|
||||
podId = pod.getId();
|
||||
// create xen cluster
|
||||
ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster");
|
||||
cluster.setHypervisorType(Hypervisor.HypervisorType.XenServer.toString());
|
||||
cluster.setClusterType(Cluster.ClusterType.CloudManaged);
|
||||
cluster.setManagedState(Managed.ManagedState.Managed);
|
||||
cluster = clusterDao.persist(cluster);
|
||||
clusterId = cluster.getId();
|
||||
|
||||
imageStore = new ImageStoreVO();
|
||||
imageStore.setName(UUID.randomUUID().toString());
|
||||
imageStore.setDataCenterId(dcId);
|
||||
imageStore.setProviderName(DataStoreProvider.NFS_IMAGE);
|
||||
imageStore.setRole(DataStoreRole.Image);
|
||||
imageStore.setUrl(UUID.randomUUID().toString());
|
||||
imageStore.setUuid(UUID.randomUUID().toString());
|
||||
imageStore.setProtocol("nfs");
|
||||
imageStore = imageStoreDao.persist(imageStore);
|
||||
|
||||
when(primaryDataStoreProvider.configure(Mockito.anyMap())).thenReturn(true);
|
||||
Set<DataStoreProvider.DataStoreProviderType> types = new HashSet<DataStoreProvider.DataStoreProviderType>();
|
||||
types.add(DataStoreProvider.DataStoreProviderType.PRIMARY);
|
||||
|
||||
Mockito.when(primaryDataStoreProvider.getTypes()).thenReturn(types);
|
||||
Mockito.when(primaryDataStoreProvider.getName()).thenReturn(DataStoreProvider.DEFAULT_PRIMARY);
|
||||
Mockito.when(primaryDataStoreProvider.getDataStoreDriver()).thenReturn(driver);
|
||||
when(primaryDataStoreProvider.getTypes()).thenReturn(types);
|
||||
when(primaryDataStoreProvider.getName()).thenReturn(DataStoreProvider.DEFAULT_PRIMARY);
|
||||
when(primaryDataStoreProvider.getDataStoreDriver()).thenReturn(driver);
|
||||
User user = mock(User.class);
|
||||
when(user.getId()).thenReturn(1L);
|
||||
Account account = mock(Account.class);
|
||||
when(account.getId()).thenReturn(1L);
|
||||
when(accountManager.getSystemAccount()).thenReturn(account);
|
||||
when(accountManager.getSystemUser()).thenReturn(user);
|
||||
|
||||
if(Merovingian2.getLockMaster() == null) {
|
||||
_lockMaster = Merovingian2.createLockMaster(1234);
|
||||
} else {
|
||||
_lockMaster = Merovingian2.getLockMaster();
|
||||
}
|
||||
_lockMaster.cleanupThisServer();
|
||||
ComponentContext.initComponentsLifeCycle();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
_lockMaster.cleanupThisServer();
|
||||
}
|
||||
private SnapshotVO createSnapshotInDb() {
|
||||
Snapshot.Type snapshotType = Snapshot.Type.MANUAL;
|
||||
SnapshotVO snapshotVO = new SnapshotVO(1, 2, 1, 1L, 1L, UUID.randomUUID()
|
||||
Snapshot.Type snapshotType = Snapshot.Type.RECURRING;
|
||||
SnapshotVO snapshotVO = new SnapshotVO(dcId, 2, 1, 1L, 1L, UUID.randomUUID()
|
||||
.toString(), (short) snapshotType.ordinal(), snapshotType.name(), 100,
|
||||
Hypervisor.HypervisorType.XenServer);
|
||||
return this.snapshotDao.persist(snapshotVO);
|
||||
}
|
||||
|
||||
private SnapshotVO createSnapshotInDb(Long volumeId) {
|
||||
Snapshot.Type snapshotType = Snapshot.Type.DAILY;
|
||||
SnapshotVO snapshotVO = new SnapshotVO(dcId, 2, 1, volumeId, 1L, UUID.randomUUID()
|
||||
.toString(), (short) snapshotType.ordinal(), snapshotType.name(), 100,
|
||||
Hypervisor.HypervisorType.XenServer);
|
||||
return this.snapshotDao.persist(snapshotVO);
|
||||
}
|
||||
|
||||
private VolumeInfo createVolume(Long templateId, DataStore store) {
|
||||
VolumeVO volume = new VolumeVO(Volume.Type.DATADISK, UUID.randomUUID().toString(), 1L, 1L, 1L, 1L, 1000, 0L, 0L, "");
|
||||
VolumeVO volume = new VolumeVO(Volume.Type.DATADISK, UUID.randomUUID().toString(), dcId, 1L, 1L, 1L, 1000, 0L, 0L, "");
|
||||
;
|
||||
volume.setPoolId(store.getId());
|
||||
|
||||
|
|
@ -120,8 +232,8 @@ public class SnapshotTestWithFakeData {
|
|||
}
|
||||
private DataStore createDataStore() throws URISyntaxException {
|
||||
StoragePoolVO pool = new StoragePoolVO();
|
||||
pool.setClusterId(1L);
|
||||
pool.setDataCenterId(1);
|
||||
pool.setClusterId(clusterId);
|
||||
pool.setDataCenterId(dcId);
|
||||
URI uri = new URI("nfs://jfkdkf/fjdkfj");
|
||||
pool.setHostAddress(uri.getHost());
|
||||
pool.setPath(uri.getPath());
|
||||
|
|
@ -130,14 +242,14 @@ public class SnapshotTestWithFakeData {
|
|||
pool.setUuid(UUID.randomUUID().toString());
|
||||
pool.setStatus(StoragePoolStatus.Up);
|
||||
pool.setPoolType(Storage.StoragePoolType.NetworkFilesystem);
|
||||
pool.setPodId(1L);
|
||||
pool.setPodId(podId);
|
||||
pool.setScope(ScopeType.CLUSTER);
|
||||
pool.setStorageProviderName(DataStoreProvider.DEFAULT_PRIMARY);
|
||||
pool = this.primaryDataStoreDao.persist(pool);
|
||||
DataStore store = this.dataStoreManager.getPrimaryDataStore(pool.getId());
|
||||
return store;
|
||||
}
|
||||
@Test
|
||||
//@Test
|
||||
public void testTakeSnapshot() throws URISyntaxException {
|
||||
SnapshotVO snapshotVO = createSnapshotInDb();
|
||||
DataStore store = createDataStore();
|
||||
|
|
@ -158,7 +270,7 @@ public class SnapshotTestWithFakeData {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
//@Test
|
||||
public void testTakeSnapshotWithFailed() throws URISyntaxException {
|
||||
SnapshotVO snapshotVO = createSnapshotInDb();
|
||||
DataStore store = null;
|
||||
|
|
@ -179,7 +291,7 @@ public class SnapshotTestWithFakeData {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
//@Test
|
||||
public void testTakeSnapshotFromVolume() throws URISyntaxException {
|
||||
DataStore store = createDataStore();
|
||||
FakePrimaryDataStoreDriver dataStoreDriver = (FakePrimaryDataStoreDriver)store.getDriver();
|
||||
|
|
@ -191,4 +303,57 @@ public class SnapshotTestWithFakeData {
|
|||
Assert.assertTrue(result == null);
|
||||
}
|
||||
|
||||
protected SnapshotPolicyVO createSnapshotPolicy(Long volId) {
|
||||
SnapshotPolicyVO policyVO = new SnapshotPolicyVO(volId, "jfkd", "fdfd", DateUtil.IntervalType.DAILY, 8);
|
||||
policyVO = snapshotPolicyDao.persist(policyVO);
|
||||
return policyVO;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcurrentSnapshot() throws URISyntaxException, InterruptedException, ExecutionException {
|
||||
DataStore store = createDataStore();
|
||||
final FakePrimaryDataStoreDriver dataStoreDriver = (FakePrimaryDataStoreDriver)store.getDriver();
|
||||
dataStoreDriver.makeTakeSnapshotSucceed(true);
|
||||
final VolumeInfo volumeInfo = createVolume(1L, store);
|
||||
Assert.assertTrue(volumeInfo.getState() == Volume.State.Ready);
|
||||
vol = volumeInfo;
|
||||
// final SnapshotPolicyVO policyVO = createSnapshotPolicy(vol.getId());
|
||||
|
||||
|
||||
ExecutorService pool = Executors.newFixedThreadPool(2);
|
||||
boolean result = false;
|
||||
List<Future<Boolean>> future = new ArrayList<Future<Boolean>>();
|
||||
for(int i = 0; i < 12; i++) {
|
||||
final int cnt = i;
|
||||
Future<Boolean> task = pool.submit(new Callable<Boolean>() {
|
||||
@Override
|
||||
public Boolean call() throws Exception {
|
||||
boolean r = true;
|
||||
try {
|
||||
SnapshotVO snapshotVO = createSnapshotInDb(vol.getId());
|
||||
VolumeObject volumeObject = (VolumeObject)vol;
|
||||
Account account = mock(Account.class);
|
||||
when(account.getId()).thenReturn(1L);
|
||||
CreateSnapshotPayload createSnapshotPayload = mock(CreateSnapshotPayload.class);
|
||||
when(createSnapshotPayload.getAccount()).thenReturn(account);
|
||||
when(createSnapshotPayload.getSnapshotId()).thenReturn(snapshotVO.getId());
|
||||
when(createSnapshotPayload.getSnapshotPolicyId()).thenReturn(0L);
|
||||
volumeObject.addPayload(createSnapshotPayload);
|
||||
if (cnt > 8) {
|
||||
mockStorageMotionStrategy.makeBackupSnapshotSucceed(false);
|
||||
}
|
||||
SnapshotInfo newSnapshot = volumeService.takeSnapshot(vol);
|
||||
if (newSnapshot == null) {
|
||||
r = false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
r = false;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
});
|
||||
Assert.assertTrue(task.get());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@
|
|||
<bean id="clusterScopeStoragePoolAllocator" class="org.apache.cloudstack.storage.allocator.ClusterScopeStoragePoolAllocator" />
|
||||
<bean id="zoneWideStoragePoolAllocator" class="org.apache.cloudstack.storage.allocator.ZoneWideStoragePoolAllocator" />
|
||||
<bean id="dataStoreProviderManagerImpl" class="org.apache.cloudstack.storage.datastore.provider.DataStoreProviderManagerImpl" />
|
||||
<bean id="ancientDataMotionStrategy" class="org.apache.cloudstack.storage.motion.AncientDataMotionStrategy" />
|
||||
<bean id="storageCacheManagerImpl" class="org.apache.cloudstack.storage.cache.manager.StorageCacheManagerImpl" />
|
||||
<bean id="storageCacheRandomAllocator" class="org.apache.cloudstack.storage.cache.allocator.StorageCacheRandomAllocator" />
|
||||
<bean id="xenserverSnapshotStrategy" class="org.apache.cloudstack.storage.snapshot.XenserverSnapshotStrategy" />
|
||||
|
|
@ -84,4 +83,9 @@
|
|||
<bean id="AccountGuestVlanMapDaoImpl" class="com.cloud.network.dao.AccountGuestVlanMapDaoImpl" />
|
||||
<bean id="StorageCacheReplacementAlgorithm" class="org.apache.cloudstack.storage.cache.manager.StorageCacheReplacementAlgorithmLRU" />
|
||||
<bean id="ServiceOfferingDetailsDao" class="com.cloud.service.dao.ServiceOfferingDetailsDaoImpl" />
|
||||
<bean id='SnapshotManagerImpl' class='com.cloud.storage.snapshot.SnapshotManagerImpl'/>
|
||||
<bean id='SnapshotPolicyDao' class='com.cloud.storage.dao.SnapshotPolicyDaoImpl'/>
|
||||
<bean id='SnapshotScheduleDao' class='com.cloud.storage.dao.SnapshotScheduleDaoImpl' />
|
||||
<bean id='UserContextInitializer' class='com.cloud.user.UserContextInitializer' />
|
||||
|
||||
</beans>
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ public class SnapshotObject implements SnapshotInfo {
|
|||
this.snapshotStoreDao.update(snapshotStore.getId(), snapshotStore);
|
||||
|
||||
// update side-effect of snapshot operation
|
||||
if(snapshotTO.getVolume().getPath() != null) {
|
||||
if(snapshotTO.getVolume() != null && snapshotTO.getVolume().getPath() != null) {
|
||||
VolumeVO vol = this.volumeDao.findByUuid(snapshotTO.getVolume().getUuid());
|
||||
if(vol != null) {
|
||||
s_logger.info("Update volume path change due to snapshot operation, volume " + vol.getId() + " path: "
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ package org.apache.cloudstack.storage.snapshot;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.utils.db.DB;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.*;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
|
||||
|
|
@ -189,7 +191,7 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
|
|||
|
||||
if (!Snapshot.State.BackedUp.equals(snapshotVO.getState())) {
|
||||
throw new InvalidParameterValueException("Can't delete snapshotshot " + snapshotId
|
||||
+ " due to it is not in BackedUp Status");
|
||||
+ " due to it is in " + snapshotVO.getState() + " Status");
|
||||
}
|
||||
|
||||
// first mark the snapshot as destroyed, so that ui can't see it, but we
|
||||
|
|
@ -235,40 +237,65 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
|
|||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public SnapshotInfo takeSnapshot(SnapshotInfo snapshot) {
|
||||
SnapshotResult result = snapshotSvr.takeSnapshot(snapshot);
|
||||
if (result.isFailed()) {
|
||||
s_logger.debug("Failed to take snapshot: " + result.getResult());
|
||||
throw new CloudRuntimeException(result.getResult());
|
||||
SnapshotVO snapshotVO = snapshotDao.acquireInLockTable(snapshot.getId());
|
||||
if (snapshotVO == null) {
|
||||
throw new CloudRuntimeException("Failed to get lock on snapshot:" + snapshot.getId());
|
||||
}
|
||||
snapshot = result.getSnashot();
|
||||
DataStore primaryStore = snapshot.getDataStore();
|
||||
|
||||
SnapshotInfo backupedSnapshot = this.backupSnapshot(snapshot);
|
||||
try {
|
||||
SnapshotInfo parent = snapshot.getParent();
|
||||
if (backupedSnapshot != null && parent != null) {
|
||||
Long parentSnapshotId = parent.getId();
|
||||
while (parentSnapshotId != null && parentSnapshotId != 0L) {
|
||||
SnapshotDataStoreVO snapshotDataStoreVO = snapshotStoreDao.findByStoreSnapshot(primaryStore.getRole(),primaryStore.getId(), parentSnapshotId);
|
||||
if (snapshotDataStoreVO != null) {
|
||||
parentSnapshotId = snapshotDataStoreVO.getParentSnapshotId();
|
||||
snapshotStoreDao.remove(snapshotDataStoreVO.getId());
|
||||
} else {
|
||||
parentSnapshotId = null;
|
||||
}
|
||||
VolumeInfo volumeInfo = snapshot.getBaseVolume();
|
||||
volumeInfo.stateTransit(Volume.Event.SnapshotRequested);
|
||||
SnapshotResult result = null;
|
||||
try {
|
||||
result = snapshotSvr.takeSnapshot(snapshot);
|
||||
if (result.isFailed()) {
|
||||
s_logger.debug("Failed to take snapshot: " + result.getResult());
|
||||
throw new CloudRuntimeException(result.getResult());
|
||||
}
|
||||
SnapshotDataStoreVO snapshotDataStoreVO = snapshotStoreDao.findByStoreSnapshot(primaryStore.getRole(), primaryStore.getId(),
|
||||
snapshot.getId());
|
||||
if (snapshotDataStoreVO != null) {
|
||||
snapshotDataStoreVO.setParentSnapshotId(0L);
|
||||
snapshotStoreDao.update(snapshotDataStoreVO.getId(), snapshotDataStoreVO);
|
||||
} finally {
|
||||
if (result != null && result.isSuccess()) {
|
||||
volumeInfo.stateTransit(Volume.Event.OperationSucceeded);
|
||||
} else {
|
||||
volumeInfo.stateTransit(Volume.Event.OperationFailed);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Failed to clean up snapshots on primary storage", e);
|
||||
|
||||
snapshot = result.getSnashot();
|
||||
DataStore primaryStore = snapshot.getDataStore();
|
||||
|
||||
SnapshotInfo backupedSnapshot = this.backupSnapshot(snapshot);
|
||||
|
||||
try {
|
||||
SnapshotInfo parent = snapshot.getParent();
|
||||
if (backupedSnapshot != null && parent != null) {
|
||||
Long parentSnapshotId = parent.getId();
|
||||
while (parentSnapshotId != null && parentSnapshotId != 0L) {
|
||||
SnapshotDataStoreVO snapshotDataStoreVO = snapshotStoreDao.findByStoreSnapshot(primaryStore.getRole(),primaryStore.getId(), parentSnapshotId);
|
||||
if (snapshotDataStoreVO != null) {
|
||||
parentSnapshotId = snapshotDataStoreVO.getParentSnapshotId();
|
||||
snapshotStoreDao.remove(snapshotDataStoreVO.getId());
|
||||
} else {
|
||||
parentSnapshotId = null;
|
||||
}
|
||||
}
|
||||
SnapshotDataStoreVO snapshotDataStoreVO = snapshotStoreDao.findByStoreSnapshot(primaryStore.getRole(), primaryStore.getId(),
|
||||
snapshot.getId());
|
||||
if (snapshotDataStoreVO != null) {
|
||||
snapshotDataStoreVO.setParentSnapshotId(0L);
|
||||
snapshotStoreDao.update(snapshotDataStoreVO.getId(), snapshotDataStoreVO);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Failed to clean up snapshots on primary storage", e);
|
||||
}
|
||||
return backupedSnapshot;
|
||||
} finally {
|
||||
if (snapshotVO != null) {
|
||||
snapshotDao.releaseFromLockTable(snapshot.getId());
|
||||
}
|
||||
}
|
||||
return backupedSnapshot;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ import java.util.Map;
|
|||
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
|
||||
import com.cloud.utils.db.DB;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
|
||||
|
|
@ -51,6 +53,7 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
|
|||
private SearchBuilder<SnapshotDataStoreVO> cacheSearch;
|
||||
private SearchBuilder<SnapshotDataStoreVO> snapshotSearch;
|
||||
private SearchBuilder<SnapshotDataStoreVO> storeSnapshotSearch;
|
||||
private SearchBuilder<SnapshotDataStoreVO> snapshotIdSearch;
|
||||
private String parentSearch = "select store_id, store_role, snapshot_id from cloud.snapshot_store_ref where store_id = ? " +
|
||||
" and store_role = ? and volume_id = ? and state = 'Ready'" +
|
||||
" order by created DESC " +
|
||||
|
|
@ -101,6 +104,10 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
|
|||
storeSnapshotSearch.and("store_role", storeSnapshotSearch.entity().getRole(), SearchCriteria.Op.EQ);
|
||||
storeSnapshotSearch.done();
|
||||
|
||||
snapshotIdSearch = createSearchBuilder();
|
||||
snapshotIdSearch.and("snapshot_id", snapshotIdSearch.entity().getSnapshotId(), SearchCriteria.Op.EQ);
|
||||
snapshotIdSearch.done();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -173,6 +180,7 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
|
|||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public SnapshotDataStoreVO findParent(DataStoreRole role, Long storeId, Long volumeId) {
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
PreparedStatement pstmt = null;
|
||||
|
|
@ -191,8 +199,6 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
|
|||
}
|
||||
} catch (SQLException e) {
|
||||
s_logger.debug("Failed to find parent snapshot: " + e.toString());
|
||||
} finally {
|
||||
txn.close();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -205,6 +211,13 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
|
|||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SnapshotDataStoreVO> findBySnapshotId(long snapshotId) {
|
||||
SearchCriteria<SnapshotDataStoreVO> sc = snapshotIdSearch.create();
|
||||
sc.setParameters("snapshot_id", snapshotId);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SnapshotDataStoreVO> listDestroyed(long id) {
|
||||
SearchCriteria<SnapshotDataStoreVO> sc = destroyedSearch.create();
|
||||
|
|
|
|||
|
|
@ -266,6 +266,12 @@ public class PrimaryDataStoreImpl implements PrimaryDataStore {
|
|||
}
|
||||
} else if (obj.getType() == DataObjectType.SNAPSHOT) {
|
||||
return objectInStoreMgr.create(obj, this);
|
||||
} else if (obj.getType() == DataObjectType.VOLUME) {
|
||||
VolumeVO vol = volumeDao.findById(obj.getId());
|
||||
if (vol != null) {
|
||||
vol.setPoolId(this.getId());
|
||||
volumeDao.update(vol.getId(), vol);
|
||||
}
|
||||
}
|
||||
|
||||
return objectInStoreMgr.get(obj, this);
|
||||
|
|
|
|||
|
|
@ -518,6 +518,7 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
if (result.isSuccess()) {
|
||||
vo.processEvent(Event.OperationSuccessed, result.getAnswer());
|
||||
} else {
|
||||
|
||||
vo.processEvent(Event.OperationFailed);
|
||||
volResult.setResult(result.getResult());
|
||||
// hack for Vmware: host is down, previously download template to the host needs to be re-downloaded, so we need to reset
|
||||
|
|
@ -1291,20 +1292,11 @@ public class VolumeServiceImpl implements VolumeService {
|
|||
|
||||
@Override
|
||||
public SnapshotInfo takeSnapshot(VolumeInfo volume) {
|
||||
VolumeObject vol = (VolumeObject) volume;
|
||||
vol.stateTransit(Volume.Event.SnapshotRequested);
|
||||
|
||||
SnapshotInfo snapshot = null;
|
||||
try {
|
||||
snapshot = snapshotMgr.takeSnapshot(volume);
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Take snapshot: " + volume.getId() + " failed", e);
|
||||
} finally {
|
||||
if (snapshot != null) {
|
||||
vol.stateTransit(Volume.Event.OperationSucceeded);
|
||||
} else {
|
||||
vol.stateTransit(Volume.Event.OperationFailed);
|
||||
}
|
||||
}
|
||||
|
||||
return snapshot;
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@
|
|||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
<scope>provided</scope>
|
||||
<version>${cs.jna.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
|
|
|||
|
|
@ -58,15 +58,19 @@ public class KVMInvestigator extends AdapterBase implements Investigator {
|
|||
return null;
|
||||
}
|
||||
CheckOnHostCommand cmd = new CheckOnHostCommand(agent);
|
||||
List<HostVO> neighbors = _resourceMgr.listAllHostsInCluster(agent.getClusterId());
|
||||
List<HostVO> neighbors = _resourceMgr.listHostsInClusterByStatus(agent.getClusterId(), Status.Up);
|
||||
for (HostVO neighbor : neighbors) {
|
||||
if (neighbor.getId() == agent.getId() || neighbor.getHypervisorType() != Hypervisor.HypervisorType.KVM) {
|
||||
continue;
|
||||
}
|
||||
Answer answer = _agentMgr.easySend(neighbor.getId(), cmd);
|
||||
|
||||
return answer.getResult() ? Status.Down : Status.Up;
|
||||
|
||||
try {
|
||||
Answer answer = _agentMgr.easySend(neighbor.getId(), cmd);
|
||||
if (answer != null) {
|
||||
return answer.getResult() ? Status.Down : Status.Up;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Failed to send command to host: " + neighbor.getId());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import java.io.File;
|
|||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.net.URI;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
|
|
@ -45,6 +46,9 @@ public class BridgeVifDriver extends VifDriverBase {
|
|||
|
||||
private static final Object _vnetBridgeMonitor = new Object();
|
||||
private String _modifyVlanPath;
|
||||
private String _modifyVxlanPath;
|
||||
private String bridgeNameSchema;
|
||||
|
||||
|
||||
@Override
|
||||
public void configure(Map<String, Object> params) throws ConfigurationException {
|
||||
|
|
@ -59,6 +63,8 @@ public class BridgeVifDriver extends VifDriverBase {
|
|||
networkScriptsDir = "scripts/vm/network/vnet";
|
||||
}
|
||||
|
||||
bridgeNameSchema = (String) params.get("network.bridge.name.schema");
|
||||
|
||||
String value = (String) params.get("scripts.timeout");
|
||||
_timeout = NumbersUtil.parseInt(value, 30 * 60) * 1000;
|
||||
|
||||
|
|
@ -66,7 +72,11 @@ public class BridgeVifDriver extends VifDriverBase {
|
|||
if (_modifyVlanPath == null) {
|
||||
throw new ConfigurationException("Unable to find modifyvlan.sh");
|
||||
}
|
||||
|
||||
_modifyVxlanPath = Script.findScript(networkScriptsDir, "modifyvxlan.sh");
|
||||
if (_modifyVxlanPath == null) {
|
||||
throw new ConfigurationException("Unable to find modifyvxlan.sh");
|
||||
}
|
||||
|
||||
try {
|
||||
createControlNetwork();
|
||||
} catch (LibvirtException e) {
|
||||
|
|
@ -84,9 +94,11 @@ public class BridgeVifDriver extends VifDriverBase {
|
|||
|
||||
LibvirtVMDef.InterfaceDef intf = new LibvirtVMDef.InterfaceDef();
|
||||
|
||||
String vlanId = null;
|
||||
if (nic.getBroadcastType() == Networks.BroadcastDomainType.Vlan) {
|
||||
vlanId = Networks.BroadcastDomainType.getValue(nic.getBroadcastUri());
|
||||
String vNetId = null;
|
||||
String protocol = null;
|
||||
if (nic.getBroadcastType() == Networks.BroadcastDomainType.Vlan || nic.getBroadcastType() == Networks.BroadcastDomainType.Vxlan) {
|
||||
vNetId = Networks.BroadcastDomainType.getValue(nic.getBroadcastUri());
|
||||
protocol = Networks.BroadcastDomainType.getSchemeValue(nic.getBroadcastUri()).scheme();
|
||||
}
|
||||
else if (nic.getBroadcastType() == Networks.BroadcastDomainType.Lswitch) {
|
||||
throw new InternalErrorException("Nicira NVP Logicalswitches are not supported by the BridgeVifDriver");
|
||||
|
|
@ -94,14 +106,14 @@ public class BridgeVifDriver extends VifDriverBase {
|
|||
String trafficLabel = nic.getName();
|
||||
if (nic.getType() == Networks.TrafficType.Guest) {
|
||||
Integer networkRateKBps = (nic.getNetworkRateMbps() != null && nic.getNetworkRateMbps().intValue() != -1) ? nic.getNetworkRateMbps().intValue() * 128 : 0;
|
||||
if (nic.getBroadcastType() == Networks.BroadcastDomainType.Vlan
|
||||
&& !vlanId.equalsIgnoreCase("untagged")) {
|
||||
if (trafficLabel != null && !trafficLabel.isEmpty()) {
|
||||
s_logger.debug("creating a vlan dev and bridge for guest traffic per traffic label " + trafficLabel);
|
||||
String brName = createVlanBr(vlanId, _pifs.get(trafficLabel));
|
||||
if (nic.getBroadcastType() == Networks.BroadcastDomainType.Vlan && !vNetId.equalsIgnoreCase("untagged")
|
||||
|| nic.getBroadcastType() == Networks.BroadcastDomainType.Vxlan) {
|
||||
if(trafficLabel != null && !trafficLabel.isEmpty()) {
|
||||
s_logger.debug("creating a vNet dev and bridge for guest traffic per traffic label " + trafficLabel);
|
||||
String brName = createVnetBr(vNetId, _pifs.get(trafficLabel), protocol);
|
||||
intf.defBridgeNet(brName, null, nic.getMac(), getGuestNicModel(guestOsType), networkRateKBps);
|
||||
} else {
|
||||
String brName = createVlanBr(vlanId, _pifs.get("private"));
|
||||
String brName = createVnetBr(vNetId, _pifs.get("private"), protocol);
|
||||
intf.defBridgeNet(brName, null, nic.getMac(), getGuestNicModel(guestOsType), networkRateKBps);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -114,13 +126,13 @@ public class BridgeVifDriver extends VifDriverBase {
|
|||
} else if (nic.getType() == Networks.TrafficType.Public) {
|
||||
Integer networkRateKBps = (nic.getNetworkRateMbps() != null && nic.getNetworkRateMbps().intValue() != -1) ? nic.getNetworkRateMbps().intValue() * 128 : 0;
|
||||
if (nic.getBroadcastType() == Networks.BroadcastDomainType.Vlan
|
||||
&& !vlanId.equalsIgnoreCase("untagged")) {
|
||||
if (trafficLabel != null && !trafficLabel.isEmpty()) {
|
||||
s_logger.debug("creating a vlan dev and bridge for public traffic per traffic label " + trafficLabel);
|
||||
String brName = createVlanBr(vlanId, _pifs.get(trafficLabel));
|
||||
&& !vNetId.equalsIgnoreCase("untagged")) {
|
||||
if(trafficLabel != null && !trafficLabel.isEmpty()){
|
||||
s_logger.debug("creating a vNet dev and bridge for public traffic per traffic label " + trafficLabel);
|
||||
String brName = createVnetBr(vNetId, _pifs.get(trafficLabel), protocol);
|
||||
intf.defBridgeNet(brName, null, nic.getMac(), getGuestNicModel(guestOsType), networkRateKBps);
|
||||
} else {
|
||||
String brName = createVlanBr(vlanId, _pifs.get("public"));
|
||||
String brName = createVnetBr(vNetId, _pifs.get("public"), protocol);
|
||||
intf.defBridgeNet(brName, null, nic.getMac(), getGuestNicModel(guestOsType), networkRateKBps);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -145,17 +157,22 @@ public class BridgeVifDriver extends VifDriverBase {
|
|||
return "br" + pifName + "-"+ vnetId;
|
||||
}
|
||||
|
||||
private String createVlanBr(String vlanId, String nic)
|
||||
private String createVnetBr(String vNetId, String nic, String protocol)
|
||||
throws InternalErrorException {
|
||||
String brName = setVnetBrName(nic, vlanId);
|
||||
createVnet(vlanId, nic, brName);
|
||||
String brName = setVnetBrName(nic, vNetId);
|
||||
createVnet(vNetId, nic, brName, protocol);
|
||||
return brName;
|
||||
}
|
||||
|
||||
private void createVnet(String vnetId, String pif, String brName)
|
||||
|
||||
private void createVnet(String vnetId, String pif, String brName, String protocol)
|
||||
throws InternalErrorException {
|
||||
synchronized (_vnetBridgeMonitor) {
|
||||
final Script command = new Script(_modifyVlanPath, _timeout, s_logger);
|
||||
String script = _modifyVlanPath;
|
||||
if(protocol.equals(Networks.BroadcastDomainType.Vxlan.scheme())) {
|
||||
script = _modifyVxlanPath;
|
||||
}
|
||||
final Script command = new Script(script, _timeout, s_logger);
|
||||
command.add("-v", vnetId);
|
||||
command.add("-p", pif);
|
||||
command.add("-b", brName);
|
||||
|
|
@ -171,7 +188,7 @@ public class BridgeVifDriver extends VifDriverBase {
|
|||
|
||||
private void deleteVnetBr(String brName) {
|
||||
synchronized (_vnetBridgeMonitor) {
|
||||
String cmdout = Script.runSimpleBashScript("ls /sys/class/net/" + brName + "/brif | grep vnet");
|
||||
String cmdout = Script.runSimpleBashScript("ls /sys/class/net/" + brName + "/brif | tr '\n' ' '");
|
||||
if (cmdout != null && cmdout.contains("vnet")) {
|
||||
// Active VM remains on that bridge
|
||||
return;
|
||||
|
|
@ -201,8 +218,16 @@ public class BridgeVifDriver extends VifDriverBase {
|
|||
s_logger.debug("unable to get a vNet ID from name " + brName);
|
||||
return;
|
||||
}
|
||||
|
||||
final Script command = new Script(_modifyVlanPath, _timeout, s_logger);
|
||||
|
||||
String scriptPath = null;
|
||||
if (cmdout != null && cmdout.contains("vxlan")) {
|
||||
scriptPath = _modifyVxlanPath;
|
||||
} else{
|
||||
scriptPath = _modifyVlanPath;
|
||||
}
|
||||
|
||||
|
||||
final Script command = new Script(scriptPath, _timeout, s_logger);
|
||||
command.add("-o", "delete");
|
||||
command.add("-v", vNetId);
|
||||
command.add("-p", pName);
|
||||
|
|
|
|||
|
|
@ -1365,7 +1365,7 @@ ServerResource {
|
|||
secondaryStorageUrl
|
||||
+ volumeDestPath);
|
||||
_storagePoolMgr.copyPhysicalDisk(volume,
|
||||
destVolumeName,secondaryStoragePool);
|
||||
destVolumeName,secondaryStoragePool, 0);
|
||||
return new CopyVolumeAnswer(cmd, true, null, null, volumeName);
|
||||
} else {
|
||||
volumePath = "/volumes/" + cmd.getVolumeId() + File.separator;
|
||||
|
|
@ -1375,7 +1375,7 @@ ServerResource {
|
|||
KVMPhysicalDisk volume = secondaryStoragePool
|
||||
.getPhysicalDisk(cmd.getVolumePath() + ".qcow2");
|
||||
_storagePoolMgr.copyPhysicalDisk(volume, volumeName,
|
||||
primaryPool);
|
||||
primaryPool, 0);
|
||||
return new CopyVolumeAnswer(cmd, true, null, null, volumeName);
|
||||
}
|
||||
} catch (CloudRuntimeException e) {
|
||||
|
|
@ -1461,7 +1461,7 @@ ServerResource {
|
|||
} else {
|
||||
BaseVol = primaryPool.getPhysicalDisk(cmd.getTemplateUrl());
|
||||
vol = _storagePoolMgr.createDiskFromTemplate(BaseVol, UUID
|
||||
.randomUUID().toString(), primaryPool);
|
||||
.randomUUID().toString(), primaryPool, 0);
|
||||
}
|
||||
if (vol == null) {
|
||||
return new Answer(cmd, false,
|
||||
|
|
@ -1522,7 +1522,7 @@ ServerResource {
|
|||
|
||||
/* Copy volume to primary storage */
|
||||
|
||||
KVMPhysicalDisk primaryVol = _storagePoolMgr.copyPhysicalDisk(templateVol, UUID.randomUUID().toString(), primaryPool);
|
||||
KVMPhysicalDisk primaryVol = _storagePoolMgr.copyPhysicalDisk(templateVol, UUID.randomUUID().toString(), primaryPool, 0);
|
||||
return primaryVol;
|
||||
} catch (CloudRuntimeException e) {
|
||||
s_logger.error("Failed to download template to primary storage",e);
|
||||
|
|
@ -2347,7 +2347,7 @@ ServerResource {
|
|||
primaryUuid);
|
||||
String volUuid = UUID.randomUUID().toString();
|
||||
KVMPhysicalDisk disk = _storagePoolMgr.copyPhysicalDisk(snapshot,
|
||||
volUuid, primaryPool);
|
||||
volUuid, primaryPool, 0);
|
||||
return new CreateVolumeFromSnapshotAnswer(cmd, true, "",
|
||||
disk.getName());
|
||||
} catch (CloudRuntimeException e) {
|
||||
|
|
@ -2498,7 +2498,7 @@ ServerResource {
|
|||
QemuImgFile destFile = new QemuImgFile(tmpltPath + "/" + cmd.getUniqueName() + ".qcow2");
|
||||
destFile.setFormat(PhysicalDiskFormat.QCOW2);
|
||||
|
||||
QemuImg q = new QemuImg();
|
||||
QemuImg q = new QemuImg(0);
|
||||
try {
|
||||
q.convert(srcFile, destFile);
|
||||
} catch (QemuImgException e) {
|
||||
|
|
@ -2601,7 +2601,7 @@ ServerResource {
|
|||
cmd.getPoolUuid());
|
||||
|
||||
KVMPhysicalDisk primaryVol = _storagePoolMgr.copyPhysicalDisk(
|
||||
tmplVol, UUID.randomUUID().toString(), primaryPool);
|
||||
tmplVol, UUID.randomUUID().toString(), primaryPool, 0);
|
||||
|
||||
return new PrimaryStorageDownloadAnswer(primaryVol.getName(),
|
||||
primaryVol.getSize());
|
||||
|
|
@ -3357,10 +3357,28 @@ ServerResource {
|
|||
}
|
||||
}
|
||||
|
||||
protected String getUuid(String uuid) {
|
||||
if (uuid == null) {
|
||||
uuid = UUID.randomUUID().toString();
|
||||
} else {
|
||||
try {
|
||||
UUID uuid2 = UUID.fromString(uuid);
|
||||
String uuid3 = uuid2.toString();
|
||||
if (!uuid3.equals(uuid)) {
|
||||
uuid = UUID.randomUUID().toString();
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
uuid = UUID.randomUUID().toString();
|
||||
}
|
||||
}
|
||||
return uuid;
|
||||
}
|
||||
protected LibvirtVMDef createVMFromSpec(VirtualMachineTO vmTO) {
|
||||
LibvirtVMDef vm = new LibvirtVMDef();
|
||||
vm.setDomainName(vmTO.getName());
|
||||
vm.setDomUUID(vmTO.getUuid());
|
||||
String uuid = vmTO.getUuid();
|
||||
uuid = getUuid(uuid);
|
||||
vm.setDomUUID(uuid);
|
||||
vm.setDomDescription(vmTO.getOs());
|
||||
|
||||
GuestDef guest = new GuestDef();
|
||||
|
|
@ -3534,15 +3552,18 @@ ServerResource {
|
|||
if (vmSpec.getType() != VirtualMachine.Type.User) {
|
||||
if ((_kernelVersion < 2006034) && (conn.getVersion() < 1001000)) { // CLOUDSTACK-2823: try passCmdLine some times if kernel < 2.6.34 and qemu < 1.1.0 on hypervisor (for instance, CentOS 6.4)
|
||||
//wait for 5 minutes at most
|
||||
for (int count = 0; count < 30; count ++) {
|
||||
boolean succeed = passCmdLine(vmName, vmSpec.getBootArgs());
|
||||
if (succeed) {
|
||||
break;
|
||||
String controlIp = null;
|
||||
for (NicTO nic : nics) {
|
||||
if (nic.getType() == TrafficType.Control) {
|
||||
controlIp = nic.getIp();
|
||||
}
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException e) {
|
||||
s_logger.trace("Ignoring InterruptedException.", e);
|
||||
}
|
||||
for (int count = 0; count < 30; count ++) {
|
||||
passCmdLine(vmName, vmSpec.getBootArgs());
|
||||
//check router is up?
|
||||
boolean result = _virtRouterResource.connect(controlIp, 1, 5000);
|
||||
if (result) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -3627,10 +3648,10 @@ ServerResource {
|
|||
physicalDisk = secondaryStorage.getPhysicalDisk(volName);
|
||||
} else if (volume.getType() != Volume.Type.ISO) {
|
||||
PrimaryDataStoreTO store = (PrimaryDataStoreTO)data.getDataStore();
|
||||
pool = _storagePoolMgr.getStoragePool(
|
||||
store.getPoolType(),
|
||||
store.getUuid());
|
||||
physicalDisk = pool.getPhysicalDisk(data.getPath());
|
||||
physicalDisk = _storagePoolMgr.getPhysicalDisk( store.getPoolType(),
|
||||
store.getUuid(),
|
||||
data.getPath());
|
||||
pool = physicalDisk.getPool();
|
||||
}
|
||||
|
||||
String volPath = null;
|
||||
|
|
@ -3703,10 +3724,9 @@ ServerResource {
|
|||
if (volume.getType() == Volume.Type.ROOT) {
|
||||
DataTO data = volume.getData();
|
||||
PrimaryDataStoreTO store = (PrimaryDataStoreTO)data.getDataStore();
|
||||
KVMStoragePool pool = _storagePoolMgr.getStoragePool(
|
||||
store.getPoolType(),
|
||||
store.getUuid());
|
||||
KVMPhysicalDisk physicalDisk = pool.getPhysicalDisk(data.getPath());
|
||||
KVMPhysicalDisk physicalDisk = _storagePoolMgr.getPhysicalDisk( store.getPoolType(),
|
||||
store.getUuid(),
|
||||
data.getPath());
|
||||
FilesystemDef rootFs = new FilesystemDef(physicalDisk.getPath(), "/");
|
||||
vm.getDevices().addDevice(rootFs);
|
||||
break;
|
||||
|
|
@ -3748,6 +3768,10 @@ ServerResource {
|
|||
// need to umount secondary storage
|
||||
String path = disk.getDiskPath();
|
||||
String poolUuid = null;
|
||||
if (path.endsWith("systemvm.iso")) {
|
||||
//Don't need to clean up system vm iso, as it's stored in local
|
||||
return true;
|
||||
}
|
||||
if (path != null) {
|
||||
String[] token = path.split("/");
|
||||
if (token.length > 3) {
|
||||
|
|
|
|||
|
|
@ -31,11 +31,40 @@ import com.cloud.hypervisor.kvm.resource.KVMHAMonitor;
|
|||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.StorageLayer;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
public class KVMStoragePoolManager {
|
||||
private static final Logger s_logger = Logger
|
||||
.getLogger(KVMStoragePoolManager.class);
|
||||
private class StoragePoolInformation {
|
||||
String name;
|
||||
String host;
|
||||
int port;
|
||||
String path;
|
||||
String userInfo;
|
||||
boolean type;
|
||||
StoragePoolType poolType;
|
||||
|
||||
|
||||
public StoragePoolInformation(String name,
|
||||
String host,
|
||||
int port,
|
||||
String path,
|
||||
String userInfo,
|
||||
StoragePoolType poolType,
|
||||
boolean type) {
|
||||
this.name = name;
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.path = path;
|
||||
this.userInfo = userInfo;
|
||||
this.type = type;
|
||||
this.poolType = poolType;
|
||||
}
|
||||
}
|
||||
private StorageAdaptor _storageAdaptor;
|
||||
private KVMHAMonitor _haMonitor;
|
||||
private final Map<String, Object> _storagePools = new ConcurrentHashMap<String, Object>();
|
||||
private final Map<String, StoragePoolInformation> _storagePools = new ConcurrentHashMap<String, StoragePoolInformation>();
|
||||
private final Map<String, StorageAdaptor> _storageMapper = new HashMap<String, StorageAdaptor>();
|
||||
|
||||
private StorageAdaptor getStorageAdaptor(StoragePoolType type) {
|
||||
|
|
@ -51,10 +80,10 @@ public class KVMStoragePoolManager {
|
|||
return adaptor;
|
||||
}
|
||||
|
||||
private void addStoragePool(String uuid) {
|
||||
private void addStoragePool(String uuid, StoragePoolInformation pool) {
|
||||
synchronized (_storagePools) {
|
||||
if (!_storagePools.containsKey(uuid)) {
|
||||
_storagePools.put(uuid, new Object());
|
||||
_storagePools.put(uuid, pool);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -68,8 +97,18 @@ public class KVMStoragePoolManager {
|
|||
}
|
||||
|
||||
public KVMStoragePool getStoragePool(StoragePoolType type, String uuid) {
|
||||
|
||||
StorageAdaptor adaptor = getStorageAdaptor(type);
|
||||
return adaptor.getStoragePool(uuid);
|
||||
KVMStoragePool pool = null;
|
||||
try {
|
||||
pool = adaptor.getStoragePool(uuid);
|
||||
} catch(Exception e) {
|
||||
StoragePoolInformation info = _storagePools.get(uuid);
|
||||
if (info != null) {
|
||||
pool = createStoragePool(info.name, info.host, info.port, info.path, info.userInfo, info.poolType, info.type);
|
||||
}
|
||||
}
|
||||
return pool;
|
||||
}
|
||||
|
||||
public KVMStoragePool getStoragePoolByURI(String uri) {
|
||||
|
|
@ -98,6 +137,39 @@ public class KVMStoragePoolManager {
|
|||
return createStoragePool(uuid, sourceHost, 0, sourcePath, "", protocol, false);
|
||||
}
|
||||
|
||||
public KVMPhysicalDisk getPhysicalDisk(StoragePoolType type, String poolUuid, String volName) {
|
||||
int cnt = 0;
|
||||
int retries = 10;
|
||||
KVMPhysicalDisk vol = null;
|
||||
//harden get volume, try cnt times to get volume, in case volume is created on other host
|
||||
String errMsg = "";
|
||||
while (cnt < retries) {
|
||||
try {
|
||||
KVMStoragePool pool = getStoragePool(type, poolUuid);
|
||||
vol = pool.getPhysicalDisk(volName);
|
||||
if (vol != null) {
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Failed to find volume:" + volName + " due to" + e.toString() + ", retry:" + cnt);
|
||||
errMsg = e.toString();
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(30000);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
|
||||
if (vol == null) {
|
||||
throw new CloudRuntimeException(errMsg);
|
||||
} else {
|
||||
return vol;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public KVMStoragePool createStoragePool( String name, String host, int port,
|
||||
String path, String userInfo,
|
||||
StoragePoolType type) {
|
||||
|
|
@ -105,7 +177,8 @@ public class KVMStoragePoolManager {
|
|||
return createStoragePool(name, host, port, path, userInfo, type, true);
|
||||
}
|
||||
|
||||
private KVMStoragePool createStoragePool( String name, String host, int port,
|
||||
//Note: due to bug CLOUDSTACK-4459, createStoragepool can be called in parallel, so need to be synced.
|
||||
private synchronized KVMStoragePool createStoragePool( String name, String host, int port,
|
||||
String path, String userInfo,
|
||||
StoragePoolType type, boolean primaryStorage) {
|
||||
StorageAdaptor adaptor = getStorageAdaptor(type);
|
||||
|
|
@ -119,7 +192,8 @@ public class KVMStoragePoolManager {
|
|||
PoolType.PrimaryStorage);
|
||||
_haMonitor.addStoragePool(nfspool);
|
||||
}
|
||||
addStoragePool(pool.getUuid());
|
||||
StoragePoolInformation info = new StoragePoolInformation(name, host, port, path, userInfo, type, primaryStorage);
|
||||
addStoragePool(pool.getUuid(), info);
|
||||
return pool;
|
||||
}
|
||||
|
||||
|
|
@ -132,25 +206,25 @@ public class KVMStoragePoolManager {
|
|||
}
|
||||
|
||||
public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template, String name,
|
||||
KVMStoragePool destPool) {
|
||||
KVMStoragePool destPool, int timeout) {
|
||||
StorageAdaptor adaptor = getStorageAdaptor(destPool.getType());
|
||||
|
||||
// LibvirtStorageAdaptor-specific statement
|
||||
if (destPool.getType() == StoragePoolType.RBD) {
|
||||
return adaptor.createDiskFromTemplate(template, name,
|
||||
PhysicalDiskFormat.RAW, template.getSize(), destPool);
|
||||
PhysicalDiskFormat.RAW, template.getSize(), destPool, timeout);
|
||||
} else if (destPool.getType() == StoragePoolType.CLVM) {
|
||||
return adaptor.createDiskFromTemplate(template, name,
|
||||
PhysicalDiskFormat.RAW, template.getSize(),
|
||||
destPool);
|
||||
destPool, timeout);
|
||||
} else if (template.getFormat() == PhysicalDiskFormat.DIR) {
|
||||
return adaptor.createDiskFromTemplate(template, name,
|
||||
PhysicalDiskFormat.DIR,
|
||||
template.getSize(), destPool);
|
||||
template.getSize(), destPool, timeout);
|
||||
} else {
|
||||
return adaptor.createDiskFromTemplate(template, name,
|
||||
PhysicalDiskFormat.QCOW2,
|
||||
template.getSize(), destPool);
|
||||
template.getSize(), destPool, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -163,9 +237,9 @@ public class KVMStoragePoolManager {
|
|||
}
|
||||
|
||||
public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name,
|
||||
KVMStoragePool destPool) {
|
||||
KVMStoragePool destPool, int timeout) {
|
||||
StorageAdaptor adaptor = getStorageAdaptor(destPool.getType());
|
||||
return adaptor.copyPhysicalDisk(disk, name, destPool);
|
||||
return adaptor.copyPhysicalDisk(disk, name, destPool, timeout);
|
||||
}
|
||||
|
||||
public KVMPhysicalDisk createDiskFromSnapshot(KVMPhysicalDisk snapshot,
|
||||
|
|
|
|||
|
|
@ -147,8 +147,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
DataTO destData = cmd.getDestTO();
|
||||
TemplateObjectTO template = (TemplateObjectTO) srcData;
|
||||
DataStoreTO imageStore = template.getDataStore();
|
||||
TemplateObjectTO volume = (TemplateObjectTO) destData;
|
||||
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) volume.getDataStore();
|
||||
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) destData.getDataStore();
|
||||
|
||||
if (!(imageStore instanceof NfsTO)) {
|
||||
return new CopyCmdAnswer("unsupported protocol");
|
||||
|
|
@ -195,21 +194,34 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
primaryStore.getUuid());
|
||||
|
||||
KVMPhysicalDisk primaryVol = storagePoolMgr.copyPhysicalDisk(tmplVol, UUID.randomUUID().toString(),
|
||||
primaryPool);
|
||||
primaryPool, cmd.getWaitInMillSeconds());
|
||||
|
||||
TemplateObjectTO newTemplate = new TemplateObjectTO();
|
||||
newTemplate.setPath(primaryVol.getName());
|
||||
|
||||
DataTO data = null;
|
||||
/**
|
||||
* Force the ImageFormat for RBD templates to RAW
|
||||
*
|
||||
*/
|
||||
if (primaryPool.getType() == StoragePoolType.RBD) {
|
||||
newTemplate.setFormat(ImageFormat.RAW);
|
||||
} else {
|
||||
newTemplate.setFormat(ImageFormat.QCOW2);
|
||||
if (destData.getObjectType() == DataObjectType.TEMPLATE) {
|
||||
TemplateObjectTO newTemplate = new TemplateObjectTO();
|
||||
newTemplate.setPath(primaryVol.getName());
|
||||
if (primaryPool.getType() == StoragePoolType.RBD) {
|
||||
newTemplate.setFormat(ImageFormat.RAW);
|
||||
} else {
|
||||
newTemplate.setFormat(ImageFormat.QCOW2);
|
||||
}
|
||||
data = newTemplate;
|
||||
} else if (destData.getObjectType() == DataObjectType.VOLUME) {
|
||||
VolumeObjectTO volumeObjectTO = new VolumeObjectTO();
|
||||
volumeObjectTO.setPath(primaryVol.getName());
|
||||
if (primaryVol.getFormat() == PhysicalDiskFormat.RAW)
|
||||
volumeObjectTO.setFormat(ImageFormat.RAW);
|
||||
else if (primaryVol.getFormat() == PhysicalDiskFormat.QCOW2) {
|
||||
volumeObjectTO.setFormat(ImageFormat.QCOW2);
|
||||
}
|
||||
data = volumeObjectTO;
|
||||
}
|
||||
return new CopyCmdAnswer(newTemplate);
|
||||
return new CopyCmdAnswer(data);
|
||||
} catch (CloudRuntimeException e) {
|
||||
return new CopyCmdAnswer(e.toString());
|
||||
} finally {
|
||||
|
|
@ -220,7 +232,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
}
|
||||
|
||||
// this is much like PrimaryStorageDownloadCommand, but keeping it separate
|
||||
private KVMPhysicalDisk templateToPrimaryDownload(String templateUrl, KVMStoragePool primaryPool) {
|
||||
private KVMPhysicalDisk templateToPrimaryDownload(String templateUrl, KVMStoragePool primaryPool, int timeout) {
|
||||
int index = templateUrl.lastIndexOf("/");
|
||||
String mountpoint = templateUrl.substring(0, index);
|
||||
String templateName = null;
|
||||
|
|
@ -257,7 +269,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
/* Copy volume to primary storage */
|
||||
|
||||
KVMPhysicalDisk primaryVol = storagePoolMgr.copyPhysicalDisk(templateVol, UUID.randomUUID().toString(),
|
||||
primaryPool);
|
||||
primaryPool, timeout);
|
||||
return primaryVol;
|
||||
} catch (CloudRuntimeException e) {
|
||||
s_logger.error("Failed to download template to primary storage", e);
|
||||
|
|
@ -287,10 +299,15 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
String templatePath = template.getPath();
|
||||
|
||||
if (primaryPool.getType() == StoragePoolType.CLVM) {
|
||||
vol = templateToPrimaryDownload(templatePath, primaryPool);
|
||||
templatePath = ((NfsTO)imageStore).getUrl() + File.separator + templatePath;
|
||||
vol = templateToPrimaryDownload(templatePath, primaryPool, cmd.getWaitInMillSeconds());
|
||||
} else {
|
||||
BaseVol = primaryPool.getPhysicalDisk(templatePath);
|
||||
vol = storagePoolMgr.createDiskFromTemplate(BaseVol, UUID.randomUUID().toString(), primaryPool);
|
||||
if (templatePath.contains("/mnt")) {
|
||||
//upgrade issue, if the path contains path, need to extract the volume uuid from path
|
||||
templatePath = templatePath.substring(templatePath.lastIndexOf(File.separator) + 1);
|
||||
}
|
||||
BaseVol = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), templatePath);
|
||||
vol = storagePoolMgr.createDiskFromTemplate(BaseVol, UUID.randomUUID().toString(), BaseVol.getPool(), cmd.getWaitInMillSeconds());
|
||||
}
|
||||
if (vol == null) {
|
||||
return new CopyCmdAnswer(" Can't create storage volume on storage pool");
|
||||
|
|
@ -361,7 +378,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
.getPhysicalDisk(srcVolumeName);
|
||||
volume.setFormat(PhysicalDiskFormat.valueOf(srcFormat.toString()));
|
||||
KVMPhysicalDisk newDisk = storagePoolMgr.copyPhysicalDisk(volume, volumeName,
|
||||
primaryPool);
|
||||
primaryPool, cmd.getWaitInMillSeconds());
|
||||
VolumeObjectTO newVol = new VolumeObjectTO();
|
||||
newVol.setFormat(ImageFormat.valueOf(newDisk.getFormat().toString().toUpperCase()));
|
||||
newVol.setPath(volumeName);
|
||||
|
|
@ -394,28 +411,14 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
String destVolumePath = destData.getPath();
|
||||
String secondaryStorageUrl = nfsStore.getUrl();
|
||||
KVMStoragePool secondaryStoragePool = null;
|
||||
KVMStoragePool primaryPool = null;
|
||||
try {
|
||||
try {
|
||||
primaryPool = storagePoolMgr.getStoragePool(
|
||||
primaryStore.getPoolType(),
|
||||
primaryStore.getUuid());
|
||||
} catch (CloudRuntimeException e) {
|
||||
if (e.getMessage().contains("not found")) {
|
||||
primaryPool = storagePoolMgr.createStoragePool(primaryStore.getUuid(),
|
||||
primaryStore.getHost(), primaryStore.getPort(),
|
||||
primaryStore.getPath(), null,
|
||||
primaryStore.getPoolType());
|
||||
} else {
|
||||
return new CopyCmdAnswer(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
String volumeName = UUID.randomUUID().toString();
|
||||
|
||||
String destVolumeName = volumeName + "." + destFormat.getFileExtension();
|
||||
KVMPhysicalDisk volume = primaryPool.getPhysicalDisk(srcVolumePath);
|
||||
KVMPhysicalDisk volume = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), srcVolumePath);
|
||||
volume.setFormat(PhysicalDiskFormat.valueOf(srcFormat.toString()));
|
||||
|
||||
secondaryStoragePool = storagePoolMgr.getStoragePoolByURI(
|
||||
secondaryStorageUrl);
|
||||
secondaryStoragePool.createFolder(destVolumePath);
|
||||
|
|
@ -423,7 +426,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
secondaryStoragePool = storagePoolMgr.getStoragePoolByURI(
|
||||
secondaryStorageUrl + File.separator + destVolumePath);
|
||||
storagePoolMgr.copyPhysicalDisk(volume,
|
||||
destVolumeName,secondaryStoragePool);
|
||||
destVolumeName,secondaryStoragePool, cmd.getWaitInMillSeconds());
|
||||
VolumeObjectTO newVol = new VolumeObjectTO();
|
||||
newVol.setPath(destVolumePath + File.separator + destVolumeName);
|
||||
newVol.setFormat(destFormat);
|
||||
|
|
@ -441,7 +444,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
public Answer createTemplateFromVolume(CopyCommand cmd) {
|
||||
DataTO srcData = cmd.getSrcTO();
|
||||
DataTO destData = cmd.getDestTO();
|
||||
int wait = cmd.getWait();
|
||||
int wait = cmd.getWaitInMillSeconds();
|
||||
TemplateObjectTO template = (TemplateObjectTO) destData;
|
||||
DataStoreTO imageStore = template.getDataStore();
|
||||
VolumeObjectTO volume = (VolumeObjectTO) srcData;
|
||||
|
|
@ -459,24 +462,15 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
|
||||
secondaryStorage = storagePoolMgr.getStoragePoolByURI(nfsImageStore.getUrl());
|
||||
|
||||
try {
|
||||
primary = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid());
|
||||
} catch (CloudRuntimeException e) {
|
||||
if (e.getMessage().contains("not found")) {
|
||||
primary = storagePoolMgr.createStoragePool(primaryStore.getUuid(), primaryStore.getHost(),
|
||||
primaryStore.getPort(), primaryStore.getPath(), null, primaryStore.getPoolType());
|
||||
} else {
|
||||
return new CopyCmdAnswer(e.getMessage());
|
||||
}
|
||||
}
|
||||
primary = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid());
|
||||
|
||||
KVMPhysicalDisk disk = primary.getPhysicalDisk(volume.getPath());
|
||||
KVMPhysicalDisk disk = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), volume.getPath());
|
||||
String tmpltPath = secondaryStorage.getLocalPath() + File.separator + templateFolder;
|
||||
this.storageLayer.mkdirs(tmpltPath);
|
||||
String templateName = UUID.randomUUID().toString();
|
||||
|
||||
if (primary.getType() != StoragePoolType.RBD) {
|
||||
Script command = new Script(_createTmplPath, wait * 1000, s_logger);
|
||||
Script command = new Script(_createTmplPath, wait, s_logger);
|
||||
command.add("-f", disk.getPath());
|
||||
command.add("-t", tmpltPath);
|
||||
command.add("-n", templateName + ".qcow2");
|
||||
|
|
@ -497,7 +491,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
QemuImgFile destFile = new QemuImgFile(tmpltPath + "/" + templateName + ".qcow2");
|
||||
destFile.setFormat(PhysicalDiskFormat.QCOW2);
|
||||
|
||||
QemuImg q = new QemuImg();
|
||||
QemuImg q = new QemuImg(cmd.getWaitInMillSeconds());
|
||||
try {
|
||||
q.convert(srcFile, destFile);
|
||||
} catch (QemuImgException e) {
|
||||
|
|
@ -625,7 +619,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
SnapshotObjectTO snapshotOnCacheStore = (SnapshotObjectTO)answer.getNewData();
|
||||
snapshotOnCacheStore.setDataStore(cacheStore);
|
||||
((SnapshotObjectTO) destData).setDataStore(imageStore);
|
||||
CopyCommand newCpyCmd = new CopyCommand(snapshotOnCacheStore, destData, cmd.getWait(), cmd.executeInSequence());
|
||||
CopyCommand newCpyCmd = new CopyCommand(snapshotOnCacheStore, destData, cmd.getWaitInMillSeconds(), cmd.executeInSequence());
|
||||
return copyToObjectStore(newCpyCmd);
|
||||
}
|
||||
@Override
|
||||
|
|
@ -661,9 +655,9 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
snapshotRelPath = destSnapshot.getPath();
|
||||
|
||||
snapshotDestPath = ssPmountPath + File.separator + snapshotRelPath;
|
||||
KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(),
|
||||
primaryStore.getUuid());
|
||||
KVMPhysicalDisk snapshotDisk = primaryPool.getPhysicalDisk(volumePath);
|
||||
KVMPhysicalDisk snapshotDisk = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(),
|
||||
primaryStore.getUuid(), volumePath);
|
||||
KVMStoragePool primaryPool = snapshotDisk.getPool();
|
||||
|
||||
/**
|
||||
* RBD snapshots can't be copied using qemu-img, so we have to use
|
||||
|
|
@ -729,7 +723,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
return new CopyCmdAnswer(e.toString());
|
||||
}
|
||||
} else {
|
||||
Script command = new Script(_manageSnapshotPath, cmd.getWait() * 1000, s_logger);
|
||||
Script command = new Script(_manageSnapshotPath, cmd.getWaitInMillSeconds(), s_logger);
|
||||
command.add("-b", snapshotDisk.getPath());
|
||||
command.add("-n", snapshotName);
|
||||
command.add("-p", snapshotDestPath);
|
||||
|
|
@ -798,6 +792,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
protected synchronized String attachOrDetachISO(Connect conn, String vmName, String isoPath, boolean isAttach)
|
||||
throws LibvirtException, URISyntaxException, InternalErrorException {
|
||||
String isoXml = null;
|
||||
|
|
@ -967,9 +962,8 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
String vmName = cmd.getVmName();
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(vmName);
|
||||
KVMStoragePool primary = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid());
|
||||
KVMPhysicalDisk phyDisk = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), vol.getPath());
|
||||
|
||||
KVMPhysicalDisk phyDisk = primary.getPhysicalDisk(vol.getPath());
|
||||
attachOrDetachDisk(conn, true, vmName, phyDisk, disk.getDiskSeq().intValue());
|
||||
|
||||
return new AttachAnswer(disk);
|
||||
|
|
@ -990,9 +984,8 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
String vmName = cmd.getVmName();
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(vmName);
|
||||
KVMStoragePool primary = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid());
|
||||
KVMPhysicalDisk phyDisk = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), vol.getPath());
|
||||
|
||||
KVMPhysicalDisk phyDisk = primary.getPhysicalDisk(vol.getPath());
|
||||
attachOrDetachDisk(conn, false, vmName, phyDisk, disk.getDiskSeq().intValue());
|
||||
|
||||
return new DettachAnswer(disk);
|
||||
|
|
@ -1064,7 +1057,8 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(),
|
||||
primaryStore.getUuid());
|
||||
|
||||
KVMPhysicalDisk disk = primaryPool.getPhysicalDisk(volume.getPath());
|
||||
KVMPhysicalDisk disk = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(),
|
||||
primaryStore.getUuid(), volume.getPath());
|
||||
if (state == DomainInfo.DomainState.VIR_DOMAIN_RUNNING && !primaryPool.isExternalSnapshot()) {
|
||||
String vmUuid = vm.getUUIDString();
|
||||
Object[] args = new Object[] { snapshotName, vmUuid };
|
||||
|
|
@ -1191,7 +1185,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
String primaryUuid = pool.getUuid();
|
||||
KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(pool.getPoolType(), primaryUuid);
|
||||
String volUuid = UUID.randomUUID().toString();
|
||||
KVMPhysicalDisk disk = storagePoolMgr.copyPhysicalDisk(snapshotDisk, volUuid, primaryPool);
|
||||
KVMPhysicalDisk disk = storagePoolMgr.copyPhysicalDisk(snapshotDisk, volUuid, primaryPool, cmd.getWaitInMillSeconds());
|
||||
VolumeObjectTO newVol = new VolumeObjectTO();
|
||||
newVol.setPath(disk.getName());
|
||||
newVol.setSize(disk.getVirtualSize());
|
||||
|
|
|
|||
|
|
@ -101,10 +101,15 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
try {
|
||||
vol = pool.storageVolLookupByName(volName);
|
||||
} catch (LibvirtException e) {
|
||||
|
||||
s_logger.debug("Can't find volume: " + e.toString());
|
||||
}
|
||||
if (vol == null) {
|
||||
storagePoolRefresh(pool);
|
||||
try {
|
||||
refreshPool(pool);
|
||||
} catch (LibvirtException e) {
|
||||
s_logger.debug("failed to refresh pool: " + e.toString());
|
||||
}
|
||||
|
||||
try {
|
||||
vol = pool.storageVolLookupByName(volName);
|
||||
} catch (LibvirtException e) {
|
||||
|
|
@ -119,6 +124,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
LibvirtStorageVolumeDef volDef = new LibvirtStorageVolumeDef(UUID
|
||||
.randomUUID().toString(), size, format, null, null);
|
||||
s_logger.debug(volDef.toString());
|
||||
|
||||
return pool.storageVolCreateXML(volDef.toString(), 0);
|
||||
}
|
||||
|
||||
|
|
@ -128,7 +134,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
refreshPool(pool);
|
||||
}
|
||||
} catch (LibvirtException e) {
|
||||
|
||||
s_logger.debug("refresh storage pool failed: " + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -397,7 +403,8 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
|
||||
return pool;
|
||||
} catch (LibvirtException e) {
|
||||
throw new CloudRuntimeException(e.toString());
|
||||
s_logger.debug("can't get storage pool",e);
|
||||
throw new CloudRuntimeException(e.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -437,6 +444,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
}
|
||||
return disk;
|
||||
} catch (LibvirtException e) {
|
||||
s_logger.debug("Failed to get physical disk:", e);
|
||||
throw new CloudRuntimeException(e.toString());
|
||||
}
|
||||
|
||||
|
|
@ -758,7 +766,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
*/
|
||||
@Override
|
||||
public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template,
|
||||
String name, PhysicalDiskFormat format, long size, KVMStoragePool destPool) {
|
||||
String name, PhysicalDiskFormat format, long size, KVMStoragePool destPool, int timeout) {
|
||||
|
||||
String newUuid = UUID.randomUUID().toString();
|
||||
KVMStoragePool srcPool = template.getPool();
|
||||
|
|
@ -775,20 +783,20 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
if (destPool.getType() != StoragePoolType.RBD) {
|
||||
disk = destPool.createPhysicalDisk(newUuid, format, template.getVirtualSize());
|
||||
if (template.getFormat() == PhysicalDiskFormat.TAR) {
|
||||
Script.runSimpleBashScript("tar -x -f " + template.getPath() + " -C " + disk.getPath());
|
||||
Script.runSimpleBashScript("tar -x -f " + template.getPath() + " -C " + disk.getPath(), timeout);
|
||||
} else if (template.getFormat() == PhysicalDiskFormat.DIR) {
|
||||
Script.runSimpleBashScript("mkdir -p " + disk.getPath());
|
||||
Script.runSimpleBashScript("chmod 755 " + disk.getPath());
|
||||
Script.runSimpleBashScript("cp -p -r " + template.getPath() + "/* " + disk.getPath());
|
||||
Script.runSimpleBashScript("cp -p -r " + template.getPath() + "/* " + disk.getPath(), timeout);
|
||||
} else if (format == PhysicalDiskFormat.QCOW2) {
|
||||
QemuImgFile backingFile = new QemuImgFile(template.getPath(), template.getFormat());
|
||||
QemuImgFile destFile = new QemuImgFile(disk.getPath());
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(timeout);
|
||||
qemu.create(destFile, backingFile);
|
||||
} else if (format == PhysicalDiskFormat.RAW) {
|
||||
QemuImgFile sourceFile = new QemuImgFile(template.getPath(), template.getFormat());
|
||||
QemuImgFile destFile = new QemuImgFile(disk.getPath(), PhysicalDiskFormat.RAW);
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(timeout);
|
||||
qemu.convert(sourceFile, destFile);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -798,7 +806,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
disk.setSize(template.getVirtualSize());
|
||||
disk.setVirtualSize(disk.getSize());
|
||||
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(timeout);
|
||||
QemuImgFile srcFile;
|
||||
QemuImgFile destFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(),
|
||||
destPool.getSourcePort(),
|
||||
|
|
@ -952,7 +960,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
*/
|
||||
@Override
|
||||
public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name,
|
||||
KVMStoragePool destPool) {
|
||||
KVMStoragePool destPool, int timeout) {
|
||||
|
||||
/**
|
||||
With RBD you can't run qemu-img convert with an existing RBD image as destination
|
||||
|
|
@ -991,24 +999,27 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
String destPath = newDisk.getPath();
|
||||
PhysicalDiskFormat destFormat = newDisk.getFormat();
|
||||
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(timeout);
|
||||
QemuImgFile srcFile = null;
|
||||
QemuImgFile destFile = null;
|
||||
|
||||
if ((srcPool.getType() != StoragePoolType.RBD) && (destPool.getType() != StoragePoolType.RBD)) {
|
||||
if (sourceFormat == PhysicalDiskFormat.TAR) {
|
||||
Script.runSimpleBashScript("tar -x -f " + sourcePath + " -C " + destPath);
|
||||
Script.runSimpleBashScript("tar -x -f " + sourcePath + " -C " + destPath, timeout);
|
||||
} else if (sourceFormat == PhysicalDiskFormat.DIR) {
|
||||
Script.runSimpleBashScript("mkdir -p " + destPath);
|
||||
Script.runSimpleBashScript("chmod 755 " + destPath);
|
||||
Script.runSimpleBashScript("cp -p -r " + sourcePath + "/* " + destPath);
|
||||
Script.runSimpleBashScript("cp -p -r " + sourcePath + "/* " + destPath, timeout);
|
||||
} else {
|
||||
srcFile = new QemuImgFile(sourcePath, sourceFormat);
|
||||
try {
|
||||
Map<String, String> info = qemu.info(srcFile);
|
||||
String backingFile = info.get(new String("backing_file"));
|
||||
if (sourceFormat.equals(destFormat) && backingFile == null) {
|
||||
Script.runSimpleBashScript("cp -f " + sourcePath + " " + destPath);
|
||||
String result = Script.runSimpleBashScript("cp -f " + sourcePath + " " + destPath, timeout);
|
||||
if (result != null) {
|
||||
throw new CloudRuntimeException("Failed to create disk: " + result);
|
||||
}
|
||||
} else {
|
||||
destFile = new QemuImgFile(destPath, destFormat);
|
||||
try {
|
||||
|
|
@ -1169,45 +1180,12 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
// However, we also need to fix the issues in CloudStack source code.
|
||||
// A file lock is used to prevent deleting a volume from a KVM storage pool when refresh it.
|
||||
private void refreshPool(StoragePool pool) throws LibvirtException {
|
||||
Connect conn = LibvirtConnection.getConnection();
|
||||
LibvirtStoragePoolDef spd = getStoragePoolDef(conn, pool);
|
||||
if ((! spd.getPoolType().equals(LibvirtStoragePoolDef.poolType.NETFS))
|
||||
&& (! spd.getPoolType().equals(LibvirtStoragePoolDef.poolType.DIR))) {
|
||||
pool.refresh(0);
|
||||
return;
|
||||
}
|
||||
String lockFile = spd.getTargetPath() + File.separator + _lockfile;
|
||||
s_logger.debug("Attempting to lock pool " + pool.getName() + " with file " + lockFile);
|
||||
if (lock(lockFile, ACQUIRE_GLOBAL_FILELOCK_TIMEOUT_FOR_KVM)) {
|
||||
try {
|
||||
pool.refresh(0);
|
||||
} finally {
|
||||
s_logger.debug("Releasing the lock on pool " + pool.getName() + " with file " + lockFile);
|
||||
unlock(lockFile);
|
||||
}
|
||||
} else {
|
||||
throw new CloudRuntimeException("Can not get file lock to refresh the pool " + pool.getName());
|
||||
}
|
||||
pool.refresh(0);
|
||||
return;
|
||||
}
|
||||
|
||||
private void deleteVol(LibvirtStoragePool pool, StorageVol vol) throws LibvirtException {
|
||||
if ((! pool.getType().equals(StoragePoolType.NetworkFilesystem))
|
||||
&& (! pool.getType().equals(StoragePoolType.Filesystem))) {
|
||||
vol.delete(0);
|
||||
return;
|
||||
}
|
||||
String lockFile = pool.getLocalPath() + File.separator + _lockfile;
|
||||
s_logger.debug("Attempting to lock pool " + pool.getName() + " with file " + lockFile);
|
||||
if (lock(lockFile, ACQUIRE_GLOBAL_FILELOCK_TIMEOUT_FOR_KVM)) {
|
||||
try {
|
||||
vol.delete(0);
|
||||
} finally {
|
||||
s_logger.debug("Releasing the lock on pool " + pool.getName() + " with file " + lockFile);
|
||||
unlock(lockFile);
|
||||
}
|
||||
} else {
|
||||
throw new CloudRuntimeException("Can not get file lock to delete the volume " + vol.getName());
|
||||
}
|
||||
vol.delete(0);
|
||||
}
|
||||
|
||||
private boolean lock(String path, int wait) {
|
||||
|
|
|
|||
|
|
@ -16,14 +16,19 @@
|
|||
// under the License.
|
||||
package com.cloud.hypervisor.kvm.storage;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.libvirt.StoragePool;
|
||||
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
|
||||
public class LibvirtStoragePool implements KVMStoragePool {
|
||||
private static final Logger s_logger = Logger
|
||||
.getLogger(LibvirtStoragePool.class);
|
||||
protected String uuid;
|
||||
protected String uri;
|
||||
protected long capacity;
|
||||
|
|
@ -120,7 +125,32 @@ public class LibvirtStoragePool implements KVMStoragePool {
|
|||
|
||||
@Override
|
||||
public KVMPhysicalDisk getPhysicalDisk(String volumeUuid) {
|
||||
return this._storageAdaptor.getPhysicalDisk(volumeUuid, this);
|
||||
KVMPhysicalDisk disk = null;
|
||||
try {
|
||||
disk = this._storageAdaptor.getPhysicalDisk(volumeUuid, this);
|
||||
} catch (CloudRuntimeException e) {
|
||||
if ((this.getStoragePoolType() != StoragePoolType.NetworkFilesystem) &&
|
||||
(this.getStoragePoolType() != StoragePoolType.Filesystem)) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
if (disk != null) {
|
||||
return disk;
|
||||
}
|
||||
s_logger.debug("find volume bypass libvirt");
|
||||
//For network file system or file system, try to use java file to find the volume, instead of through libvirt. BUG:CLOUDSTACK-4459
|
||||
String localPoolPath = this.getLocalPath();
|
||||
File f = new File(localPoolPath + File.separator + volumeUuid);
|
||||
if (!f.exists()) {
|
||||
s_logger.debug("volume: " + volumeUuid + " not exist on storage pool");
|
||||
throw new CloudRuntimeException("Can't find volume:" + volumeUuid);
|
||||
}
|
||||
disk = new KVMPhysicalDisk(f.getPath(), volumeUuid, this);
|
||||
disk.setFormat(PhysicalDiskFormat.QCOW2);
|
||||
disk.setSize(f.length());
|
||||
disk.setVirtualSize(f.length());
|
||||
return disk;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ public interface StorageAdaptor {
|
|||
|
||||
public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template,
|
||||
String name, PhysicalDiskFormat format, long size,
|
||||
KVMStoragePool destPool);
|
||||
KVMStoragePool destPool, int timeout);
|
||||
|
||||
public KVMPhysicalDisk createTemplateFromDisk(KVMPhysicalDisk disk,
|
||||
String name, PhysicalDiskFormat format, long size,
|
||||
|
|
@ -50,7 +50,7 @@ public interface StorageAdaptor {
|
|||
KVMStoragePool pool);
|
||||
|
||||
public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name,
|
||||
KVMStoragePool destPools);
|
||||
KVMStoragePool destPools, int timeout);
|
||||
|
||||
public KVMPhysicalDisk createDiskFromSnapshot(KVMPhysicalDisk snapshot,
|
||||
String snapshotName, String name, KVMStoragePool destPool);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ public class QemuImg {
|
|||
|
||||
/* The qemu-img binary. We expect this to be in $PATH */
|
||||
public String _qemuImgPath = "qemu-img";
|
||||
private int timeout;
|
||||
|
||||
/* Shouldn't we have KVMPhysicalDisk and LibvirtVMDef read this? */
|
||||
public static enum PhysicalDiskFormat {
|
||||
|
|
@ -46,8 +47,12 @@ public class QemuImg {
|
|||
}
|
||||
}
|
||||
|
||||
public QemuImg() {
|
||||
public QemuImg(int timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public void setTimeout(int timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -84,7 +89,7 @@ public class QemuImg {
|
|||
* @return void
|
||||
*/
|
||||
public void create(QemuImgFile file, QemuImgFile backingFile, Map<String, String> options) throws QemuImgException {
|
||||
Script s = new Script(_qemuImgPath);
|
||||
Script s = new Script(_qemuImgPath, timeout);
|
||||
s.add("create");
|
||||
|
||||
if (options != null && !options.isEmpty()) {
|
||||
|
|
@ -181,7 +186,7 @@ public class QemuImg {
|
|||
* @return void
|
||||
*/
|
||||
public void convert(QemuImgFile srcFile, QemuImgFile destFile, Map<String, String> options) throws QemuImgException {
|
||||
Script s = new Script(_qemuImgPath);
|
||||
Script s = new Script(_qemuImgPath, timeout);
|
||||
s.add("convert");
|
||||
s.add("-f");
|
||||
s.add(srcFile.getFormat().toString());
|
||||
|
|
|
|||
|
|
@ -24,11 +24,13 @@ import com.cloud.template.VirtualMachineTemplate.BootloaderType;
|
|||
import com.cloud.utils.Pair;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import org.apache.commons.lang.SystemUtils;
|
||||
import org.junit.Assume;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
|
@ -195,4 +197,17 @@ public class LibvirtComputingResourceTest {
|
|||
Pair<Double, Double> stats = LibvirtComputingResource.getNicStats("lo");
|
||||
assertNotNull(stats);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUUID() {
|
||||
String uuid = "1";
|
||||
LibvirtComputingResource lcr = new LibvirtComputingResource();
|
||||
uuid =lcr.getUuid(uuid);
|
||||
Assert.assertTrue(!uuid.equals("1"));
|
||||
|
||||
String oldUuid = UUID.randomUUID().toString();
|
||||
uuid = oldUuid;
|
||||
uuid = lcr.getUuid(uuid);
|
||||
Assert.assertTrue(uuid.equals(oldUuid));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ public class QemuImgTest {
|
|||
long size = 10995116277760l;
|
||||
QemuImgFile file = new QemuImgFile(filename, size, PhysicalDiskFormat.QCOW2);
|
||||
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(0);
|
||||
qemu.create(file);
|
||||
Map<String, String> info = qemu.info(file);
|
||||
|
||||
|
|
@ -69,7 +69,7 @@ public class QemuImgTest {
|
|||
|
||||
options.put("cluster_size", clusterSize);
|
||||
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(0);
|
||||
qemu.create(file, options);
|
||||
Map<String, String> info = qemu.info(file);
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ public class QemuImgTest {
|
|||
QemuImgFile file = new QemuImgFile(filename, startSize, PhysicalDiskFormat.QCOW2);
|
||||
|
||||
try {
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(0);
|
||||
qemu.create(file);
|
||||
qemu.resize(file, endSize);
|
||||
Map<String, String> info = qemu.info(file);
|
||||
|
|
@ -125,7 +125,7 @@ public class QemuImgTest {
|
|||
QemuImgFile file = new QemuImgFile(filename, startSize, PhysicalDiskFormat.RAW);
|
||||
|
||||
try {
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(0);
|
||||
qemu.create(file);
|
||||
qemu.resize(file, increment, true);
|
||||
Map<String, String> info = qemu.info(file);
|
||||
|
|
@ -153,7 +153,7 @@ public class QemuImgTest {
|
|||
QemuImgFile file = new QemuImgFile(filename, startSize, PhysicalDiskFormat.RAW);
|
||||
|
||||
try {
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(0);
|
||||
qemu.create(file);
|
||||
qemu.resize(file, increment, true);
|
||||
Map<String, String> info = qemu.info(file);
|
||||
|
|
@ -182,7 +182,7 @@ public class QemuImgTest {
|
|||
long endSize = -1;
|
||||
QemuImgFile file = new QemuImgFile(filename, startSize, PhysicalDiskFormat.QCOW2);
|
||||
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(0);
|
||||
try {
|
||||
qemu.create(file);
|
||||
qemu.resize(file, endSize);
|
||||
|
|
@ -199,7 +199,7 @@ public class QemuImgTest {
|
|||
long startSize = 20480;
|
||||
QemuImgFile file = new QemuImgFile(filename, 20480, PhysicalDiskFormat.QCOW2);
|
||||
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(0);
|
||||
qemu.create(file);
|
||||
qemu.resize(file, 0);
|
||||
|
||||
|
|
@ -216,7 +216,7 @@ public class QemuImgTest {
|
|||
QemuImgFile firstFile = new QemuImgFile(firstFileName, 20480, PhysicalDiskFormat.QCOW2);
|
||||
QemuImgFile secondFile = new QemuImgFile(secondFileName, PhysicalDiskFormat.QCOW2);
|
||||
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(0);
|
||||
qemu.create(firstFile);
|
||||
qemu.create(secondFile, firstFile);
|
||||
|
||||
|
|
@ -240,7 +240,7 @@ public class QemuImgTest {
|
|||
QemuImgFile srcFile = new QemuImgFile(srcFileName, srcSize);
|
||||
QemuImgFile destFile = new QemuImgFile(destFileName);
|
||||
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(0);
|
||||
qemu.create(srcFile);
|
||||
qemu.convert(srcFile, destFile);
|
||||
Map<String, String> info = qemu.info(destFile);
|
||||
|
|
@ -267,7 +267,7 @@ public class QemuImgTest {
|
|||
QemuImgFile srcFile = new QemuImgFile(srcFileName, srcSize, srcFormat);
|
||||
QemuImgFile destFile = new QemuImgFile(destFileName, destFormat);
|
||||
|
||||
QemuImg qemu = new QemuImg();
|
||||
QemuImg qemu = new QemuImg(0);
|
||||
qemu.create(srcFile);
|
||||
qemu.convert(srcFile, destFile);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>cloud-plugin-network-vxlan</artifactId>
|
||||
<name>Apache CloudStack Plugin - Network VXLAN</name>
|
||||
<parent>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloudstack-plugins</artifactId>
|
||||
<version>4.3.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
</project>
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -62,6 +62,7 @@
|
|||
<module>alert-handlers/snmp-alerts</module>
|
||||
<module>alert-handlers/syslog-alerts</module>
|
||||
<module>network-elements/internal-loadbalancer</module>
|
||||
<module>network-elements/vxlan</module>
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
|
|
|
|||
|
|
@ -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<CopyCommandResult> 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;
|
||||
}
|
||||
|
||||
|
|
|
|||
2
pom.xml
2
pom.xml
|
|
@ -81,7 +81,7 @@
|
|||
<cs.reflections.version>0.9.8</cs.reflections.version>
|
||||
<cs.java-ipv6.version>0.10</cs.java-ipv6.version>
|
||||
<cs.replace.properties>build/replace.properties</cs.replace.properties>
|
||||
<cs.libvirt-java.version>0.5.0</cs.libvirt-java.version>
|
||||
<cs.libvirt-java.version>0.5.1</cs.libvirt-java.version>
|
||||
<cs.rados-java.version>0.1.3</cs.rados-java.version>
|
||||
<cs.target.dir>target</cs.target.dir>
|
||||
<cs.daemon.version>1.0.10</cs.daemon.version>
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,230 @@
|
|||
#!/usr/bin/env bash
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# modifyvnet.sh -- adds and deletes VXLANs from a Routing Server
|
||||
# set -x
|
||||
|
||||
## TODO(VXLAN): MTU, IPv6 underlying
|
||||
|
||||
usage() {
|
||||
printf "Usage: %s: -o <op>(add | delete) -v <vxlan id> -p <pif> -b <bridge name>\n"
|
||||
}
|
||||
|
||||
addVxlan() {
|
||||
local vxlanId=$1
|
||||
local pif=$2
|
||||
local vxlanDev=vxlan$vxlanId
|
||||
local vxlanBr=$3
|
||||
local mcastGrp="239.$(( $vxlanId >> 16 % 256 )).$(( $vxlanId >> 8 % 256 )).$(( $vxlanId % 256 ))"
|
||||
|
||||
## TODO(VXLAN): $brif (trafficlabel) should be passed from caller because we cannot assume 1:1 mapping between pif and brif.
|
||||
# lookup bridge interface
|
||||
local sysfs_dir=/sys/devices/virtual/net/
|
||||
local brif=`find ${sysfs_dir}*/brif/ -name $pif | sed -e "s,$sysfs_dir,," | sed -e 's,/brif/.*$,,'`
|
||||
|
||||
if [ "$brif " == " " ]
|
||||
then
|
||||
printf "Failed to lookup bridge interface which includes pif: $pif."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# confirm ip address of $brif
|
||||
ip addr show $brif | grep -w inet
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
printf "Failed to find vxlan multicast source ip address on brif: $brif."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# mcast route
|
||||
## TODO(VXLAN): Can we assume there're only one IP address which can be multicast src IP on the IF?
|
||||
ip route get $mcastGrp | grep -w "dev $brif"
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
ip route add $mcastGrp/32 dev $brif
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
printf "Failed to add vxlan multicast route on brif: $brif."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -d /sys/class/net/$vxlanDev ]
|
||||
then
|
||||
ip link add $vxlanDev type vxlan id $vxlanId group $mcastGrp ttl 10 dev $brif
|
||||
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
# race condition that someone already creates the vxlan
|
||||
if [ ! -d /sys/class/net/$vxlanDev ]
|
||||
then
|
||||
printf "Failed to create vxlan $vxlanId on brif: $brif."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# is up?
|
||||
ip link show $vxlanDev | grep -w UP > /dev/null
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
ip link set $vxlanDev up > /dev/null
|
||||
fi
|
||||
|
||||
if [ ! -d /sys/class/net/$vxlanBr ]
|
||||
then
|
||||
brctl addbr $vxlanBr > /dev/null
|
||||
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
if [ ! -d /sys/class/net/$vxlanBr ]
|
||||
then
|
||||
printf "Failed to create br: $vxlanBr"
|
||||
return 2
|
||||
fi
|
||||
fi
|
||||
|
||||
brctl setfd $vxlanBr 0
|
||||
fi
|
||||
|
||||
#pif is eslaved into vxlanBr?
|
||||
ls /sys/class/net/$vxlanBr/brif/ | grep -w "$vxlanDev" > /dev/null
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
brctl addif $vxlanBr $vxlanDev > /dev/null
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
ls /sys/class/net/$vxlanBr/brif/ | grep -w "$vxlanDev" > /dev/null
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
printf "Failed to add vxlan: $vxlanDev to $vxlanBr"
|
||||
return 3
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# is vxlanBr up?
|
||||
ip link show $vxlanBr | grep -w UP > /dev/null
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
ip link set $vxlanBr up
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
deleteVxlan() {
|
||||
local vxlanId=$1
|
||||
local pif=$2
|
||||
local vxlanDev=vxlan$vxlanId
|
||||
local vxlanBr=$3
|
||||
local mcastGrp="239.$(( $vxlanId >> 16 % 256 )).$(( $vxlanId >> 8 % 256 )).$(( $vxlanId % 256 ))"
|
||||
|
||||
ip route del $mcastGrp/32 dev $brif
|
||||
|
||||
ip link delete $vxlanDev
|
||||
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
printf "Failed to del vxlan: $vxlanId"
|
||||
printf "Continue..."
|
||||
fi
|
||||
|
||||
ip link set $vxlanBr down
|
||||
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
return 1
|
||||
fi
|
||||
|
||||
brctl delbr $vxlanBr
|
||||
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
printf "Failed to del bridge $vxlanBr"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
op=
|
||||
vxlanId=
|
||||
option=$@
|
||||
|
||||
while getopts 'o:v:p:b:' OPTION
|
||||
do
|
||||
case $OPTION in
|
||||
o) oflag=1
|
||||
op="$OPTARG"
|
||||
;;
|
||||
v) vflag=1
|
||||
vxlanId="$OPTARG"
|
||||
;;
|
||||
p) pflag=1
|
||||
pif="$OPTARG"
|
||||
;;
|
||||
b) bflag=1
|
||||
brName="$OPTARG"
|
||||
;;
|
||||
?) usage
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Check that all arguments were passed in
|
||||
if [ "$oflag$vflag$pflag$bflag" != "1111" ]
|
||||
then
|
||||
usage
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Do we support Vxlan?
|
||||
lsmod|grep ^vxlan >& /dev/null
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
modprobe=`modprobe vxlan 2>&1`
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
printf "Failed to load vxlan kernel module: $modprobe"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$op" == "add" ]
|
||||
then
|
||||
# Add the vxlan
|
||||
addVxlan $vxlanId $pif $brName
|
||||
|
||||
# If the add fails then return failure
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if [ "$op" == "delete" ]
|
||||
then
|
||||
# Delete the vxlan
|
||||
deleteVxlan $vxlanId $pif $brName
|
||||
|
||||
# Always exit with success
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
@ -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<Capability, String> 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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("")) {
|
||||
|
|
|
|||
|
|
@ -1042,6 +1042,10 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
|
|||
List<SnapshotVO> snapshots = _snapshotDao.listAllByStatus(Snapshot.State.Error);
|
||||
for (SnapshotVO snapshotVO : snapshots) {
|
||||
try {
|
||||
List<SnapshotDataStoreVO> 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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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<String, String> details, String accountUUID, String userUUID) {
|
||||
|
|
|
|||
|
|
@ -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<Capability, String> staticNatServiceCapabilityMap = new HashMap<Capability, String>();
|
||||
|
||||
configurationMgr.validateStaticNatServiceCapablities(staticNatServiceCapabilityMap);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateInvalidStaticNatServiceCapablitiesTest() {
|
||||
Map<Capability, String> staticNatServiceCapabilityMap = new HashMap<Capability, String>();
|
||||
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<Capability, String> staticNatServiceCapabilityMap = new HashMap<Capability, String>();
|
||||
staticNatServiceCapabilityMap.put(Capability.AssociatePublicIP, "true and Talse");
|
||||
staticNatServiceCapabilityMap.put(Capability.ElasticIp, "True");
|
||||
|
||||
configurationMgr.validateStaticNatServiceCapablities(staticNatServiceCapabilityMap);
|
||||
}
|
||||
@Test
|
||||
public void validateFTStaticNatServiceCapablitiesTest() {
|
||||
Map<Capability, String> staticNatServiceCapabilityMap = new HashMap<Capability, String>();
|
||||
staticNatServiceCapabilityMap.put(Capability.AssociatePublicIP, "false");
|
||||
staticNatServiceCapabilityMap.put(Capability.ElasticIp, "True");
|
||||
|
||||
configurationMgr.validateStaticNatServiceCapablities(staticNatServiceCapabilityMap);
|
||||
}
|
||||
@Test
|
||||
public void validateTFStaticNatServiceCapablitiesTest() {
|
||||
Map<Capability, String> staticNatServiceCapabilityMap = new HashMap<Capability, String>();
|
||||
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<Capability, String> staticNatServiceCapabilityMap = new HashMap<Capability, String>();
|
||||
staticNatServiceCapabilityMap.put(Capability.AssociatePublicIP, "false");
|
||||
staticNatServiceCapabilityMap.put(Capability.ElasticIp, "False");
|
||||
|
||||
configurationMgr.validateStaticNatServiceCapablities(staticNatServiceCapabilityMap);
|
||||
}
|
||||
|
||||
public class DedicatePublicIpRangeCmdExtn extends DedicatePublicIpRangeCmd {
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -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'));
|
||||
|
|
|
|||
|
|
@ -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<iterates):
|
||||
engine = TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient,
|
||||
deploy.getCfg(),
|
||||
testCaseLogFile,
|
||||
testResultLogFile)
|
||||
engine.loadTestsFromDir(options.testCaseFolder)
|
||||
engine.run()
|
||||
engine.loadTestsFromDir(options.testCaseFolder)
|
||||
engine.run()
|
||||
n = n + 1
|
||||
|
|
|
|||
|
|
@ -332,6 +332,7 @@ dictionary = {
|
|||
'label.add.to.group': '<fmt:message key="label.add.to.group" />',
|
||||
'label.add.user': '<fmt:message key="label.add.user" />',
|
||||
'label.add.vlan': '<fmt:message key="label.add.vlan" />',
|
||||
'label.add.vxlan': '<fmt:message key="label.add.vxlan" />',
|
||||
'label.add.vm': '<fmt:message key="label.add.vm" />',
|
||||
'label.add.vms': '<fmt:message key="label.add.vms" />',
|
||||
'label.add.vms.to.lb': '<fmt:message key="label.add.vms.to.lb" />',
|
||||
|
|
@ -549,6 +550,7 @@ dictionary = {
|
|||
'label.end.port': '<fmt:message key="label.end.port" />',
|
||||
'label.end.reserved.system.IP': '<fmt:message key="label.end.reserved.system.IP" />',
|
||||
'label.end.vlan': '<fmt:message key="label.end.vlan" />',
|
||||
'label.end.vxlan': '<fmt:message key="label.end.vxlan" />',
|
||||
'label.enter.token': '<fmt:message key="label.enter.token" />',
|
||||
'label.error.code': '<fmt:message key="label.error.code" />',
|
||||
'label.error': '<fmt:message key="label.error" />',
|
||||
|
|
@ -904,6 +906,10 @@ dictionary = {
|
|||
'label.Pxe.server.type': '<fmt:message key="label.Pxe.server.type" />',
|
||||
'label.quickview': '<fmt:message key="label.quickview" />',
|
||||
'label.rbd': '<fmt:message key="label.rbd" />',
|
||||
'label.rbd.monitor': '<fmt:message key="label.rbd.monitor" />',
|
||||
'label.rbd.pool': '<fmt:message key="label.rbd.pool" />',
|
||||
'label.rbd.id': '<fmt:message key="label.rbd.id" />',
|
||||
'label.rbd.secret': '<fmt:message key="label.rbd.secret" />',
|
||||
'label.reboot': '<fmt:message key="label.reboot" />',
|
||||
'label.recent.errors': '<fmt:message key="label.recent.errors" />',
|
||||
'label.redundant.router.capability': '<fmt:message key="label.redundant.router.capability" />',
|
||||
|
|
@ -1011,12 +1017,14 @@ dictionary = {
|
|||
'label.source.nat': '<fmt:message key="label.source.nat" />',
|
||||
'label.specify.IP.ranges': '<fmt:message key="label.specify.IP.ranges" />',
|
||||
'label.specify.vlan': '<fmt:message key="label.specify.vlan" />',
|
||||
'label.specify.vxlan': '<fmt:message key="label.specify.vxlan" />',
|
||||
'label.SR.name ': '<fmt:message key="label.SR.name " />',
|
||||
'label.srx': '<fmt:message key="label.srx" />',
|
||||
'label.start.IP': '<fmt:message key="label.start.IP" />',
|
||||
'label.start.port': '<fmt:message key="label.start.port" />',
|
||||
'label.start.reserved.system.IP': '<fmt:message key="label.start.reserved.system.IP" />',
|
||||
'label.start.vlan': '<fmt:message key="label.start.vlan" />',
|
||||
'label.start.vxlan': '<fmt:message key="label.start.vxlan" />',
|
||||
'label.state': '<fmt:message key="label.state" />',
|
||||
'label.static.nat': '<fmt:message key="label.static.nat" />',
|
||||
'label.static.nat.to': '<fmt:message key="label.static.nat.to" />',
|
||||
|
|
@ -1135,6 +1143,9 @@ dictionary = {
|
|||
'label.vlan': '<fmt:message key="label.vlan" />',
|
||||
'label.vlan.id': '<fmt:message key="label.vlan.id" />',
|
||||
'label.vlan.range': '<fmt:message key="label.vlan.range" />',
|
||||
'label.vxlan': '<fmt:message key="label.vxlan" />',
|
||||
'label.vxlan.id': '<fmt:message key="label.vxlan.id" />',
|
||||
'label.vxlan.range': '<fmt:message key="label.vxlan.range" />',
|
||||
'label.vm.add': '<fmt:message key="label.vm.add" />',
|
||||
'label.vm.destroy': '<fmt:message key="label.vm.destroy" />',
|
||||
'label.vm.display.name': '<fmt:message key="label.vm.display.name" />',
|
||||
|
|
|
|||
|
|
@ -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: ''
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
},
|
||||
|
|
|
|||
|
|
@ -715,10 +715,12 @@
|
|||
$('<option>').attr({
|
||||
value: 'VNS'
|
||||
}).html('VNS'),
|
||||
|
||||
$('<option>').attr({
|
||||
value: 'SSP'
|
||||
}).html('SSP')
|
||||
}).html('SSP'),
|
||||
$('<option>').attr({
|
||||
value: 'VXLAN'
|
||||
}).html('VXLAN')
|
||||
)
|
||||
)
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in New Issue