4040from marvin .codes import FAILED , PASS
4141from nose .plugins .attrib import attr
4242
43- import uuid
4443import unittest
4544
4645class TestDeployVMFromSnapshotOrVolume (cloudstackTestCase ):
4746
47+ def rbd_snapshot_cannot_outlive_source_volume (self ):
48+ '''
49+ On RBD, a snapshot lives on primary storage with its parent
50+ volume, so with snapshot.backup.to.secondary=false, deleting the
51+ parent volume destroys the snapshot too - it can no longer be
52+ used to deploy a new volume/VM afterward.
53+ '''
54+ return self .storage_pool .type == 'RBD'
55+
4856 @classmethod
4957 def setUpClass (cls ):
5058 testClient = super (TestDeployVMFromSnapshotOrVolume , cls ).getClsTestClient ()
@@ -80,23 +88,33 @@ def setUpClass(cls):
8088 cls ._cleanup .append (cls .account )
8189 cls .debug (cls .account .id )
8290
91+ # Prefer a zone-wide pool, but also accept a cluster-scope NFS/RBD pool.
8392 storage_pools_response = list_storage_pools (cls .apiclient ,
8493 zoneid = cls .zone .id ,
8594 scope = "ZONE" )
8695
96+ if not storage_pools_response :
97+ cluster_storage_pools = list_storage_pools (cls .apiclient ,
98+ zoneid = cls .zone .id ,
99+ scope = "CLUSTER" ) or []
100+ storage_pools_response = [
101+ pool for pool in cluster_storage_pools
102+ if getattr (pool , "type" , None ) in ("NetworkFilesystem" , "RBD" )
103+ ]
104+
87105 if storage_pools_response :
88- cls .zone_wide_storage = storage_pools_response [0 ]
106+ cls .storage_pool = storage_pools_response [0 ]
89107
90108 cls .debug (
91- "zone wide storage id is %s" %
92- cls .zone_wide_storage .id )
109+ "storage pool id is %s, scope is %s" %
110+ ( cls .storage_pool .id , cls . storage_pool . scope ) )
93111 update1 = StoragePool .update (cls .apiclient ,
94- id = cls .zone_wide_storage .id ,
112+ id = cls .storage_pool .id ,
95113 tags = "test-vm"
96114 )
97115 cls .debug (
98116 "Storage %s pool tag%s" %
99- (cls .zone_wide_storage .id , update1 .tags ))
117+ (cls .storage_pool .id , update1 .tags ))
100118 cls .service_offering = ServiceOffering .create (
101119 cls .apiclient ,
102120 cls .services ["service_offerings" ]["small" ],
@@ -116,7 +134,7 @@ def setUpClass(cls):
116134 )
117135 cls ._cleanup .append (cls .disk_offering )
118136 else :
119- raise unittest .SkipTest ("No zone wide storage found. Skipping tests" )
137+ raise unittest .SkipTest ("No zone- wide or cluster-scope NFS/RBD storage pool found. Skipping tests" )
120138
121139
122140 cls .virtual_machine = VirtualMachine .create (
@@ -177,16 +195,16 @@ def test_03_deploy_vm_with_existing_volume_deleted_template(self):
177195 template = Template .create_from_snapshot (self .apiclient , self .snapshot , services )
178196 self ._cleanup .append (template )
179197 virtual_machine = VirtualMachine .create (self .apiclient ,
180- { "name" : "Test-%s" % uuid . uuid4 ()} ,
198+ self . services [ 'small' ] ,
181199 accountid = self .account .name ,
182200 domainid = self .account .domainid ,
183201 zoneid = self .zone .id ,
184202 serviceofferingid = self .service_offering .id ,
185203 templateid = template .id ,
186- mode = "basic" ,
204+ mode = self . services [ 'mode' ] ,
187205 )
188206 try :
189- ssh_client = virtual_machine .get_ssh_client ()
207+ ssh_client = virtual_machine .get_ssh_client (reconnect = True )
190208 except Exception as e :
191209 self .fail ("SSH failed for virtual machine: %s - %s" %
192210 (virtual_machine .ipaddress , e ))
@@ -202,29 +220,35 @@ def test_03_deploy_vm_with_existing_volume_deleted_template(self):
202220 root_volume .id ,
203221 )
204222 VirtualMachine .delete (virtual_machine , self .apiclient , expunge = True )
205- self .create_volume_from_snapshot_deploy_vm (snapshot .id )
223+ if not self .rbd_snapshot_cannot_outlive_source_volume ():
224+ self .create_volume_from_snapshot_deploy_vm (snapshot .id )
206225
207226 @attr (tags = ["advanced" ], required_hardware = "false" )
208227 def test_04_deploy_vm_with_existing_snapshot_deleted_template (self ):
209228 '''
210229 Deploy a Virtual machine with existing snapshot of a ROOT volume created from a templated which was deleted
211230 '''
231+ if self .rbd_snapshot_cannot_outlive_source_volume ():
232+ raise unittest .SkipTest (
233+ "Covered by test_03 on RBD: deploying from a snapshot after "
234+ "its source ROOT volume was deleted is not supported here."
235+ )
212236 services = {"displaytext" : "Template-1" , "name" : "Template-1-name" , "ostypeid" : self .template .ostypeid ,
213237 "ispublic" : "true" }
214238
215239 template = Template .create_from_snapshot (self .apiclient , self .snapshot , services )
216240 self ._cleanup .append (template )
217241 virtual_machine = VirtualMachine .create (self .apiclient ,
218- { "name" : "Test-%s" % uuid . uuid4 ()} ,
242+ self . services [ 'small' ] ,
219243 accountid = self .account .name ,
220244 domainid = self .account .domainid ,
221245 zoneid = self .zone .id ,
222246 serviceofferingid = self .service_offering .id ,
223247 templateid = template .id ,
224- mode = "basic" ,
248+ mode = self . services [ 'mode' ] ,
225249 )
226250 try :
227- ssh_client = virtual_machine .get_ssh_client ()
251+ ssh_client = virtual_machine .get_ssh_client (reconnect = True )
228252 except Exception as e :
229253 self .fail ("SSH failed for virtual machine: %s - %s" %
230254 (virtual_machine .ipaddress , e ))
@@ -247,18 +271,22 @@ def test_05_deploy_vm_with_existing_snapshot_deleted_volume(self):
247271 '''
248272 Deploy a Virtual machine with existing snapshot of a ROOT volume which was deleted
249273 '''
250-
274+ if self .rbd_snapshot_cannot_outlive_source_volume ():
275+ raise unittest .SkipTest (
276+ "Covered by test_03 on RBD: deploying from a snapshot after "
277+ "its source ROOT volume was deleted is not supported here."
278+ )
251279 virtual_machine = VirtualMachine .create (self .apiclient ,
252- { "name" : "Test-%s" % uuid . uuid4 ()} ,
280+ self . services [ 'small' ] ,
253281 accountid = self .account .name ,
254282 domainid = self .account .domainid ,
255283 zoneid = self .zone .id ,
256284 serviceofferingid = self .service_offering .id ,
257285 templateid = self .template .id ,
258- mode = "basic" ,
286+ mode = self . services [ 'mode' ] ,
259287 )
260288 try :
261- ssh_client = virtual_machine .get_ssh_client ()
289+ ssh_client = virtual_machine .get_ssh_client (reconnect = True )
262290 except Exception as e :
263291 self .fail ("SSH failed for virtual machine: %s - %s" %
264292 (virtual_machine .ipaddress , e ))
@@ -278,16 +306,16 @@ def test_05_deploy_vm_with_existing_snapshot_deleted_volume(self):
278306
279307 def deploy_vm_from_snapshot (self , snapshot ):
280308 virtual_machine = VirtualMachine .create (self .apiclient ,
281- { "name" : "Test-%s" % uuid . uuid4 ()} ,
309+ self . services [ 'small' ] ,
282310 accountid = self .account .name ,
283311 domainid = self .account .domainid ,
284312 zoneid = self .zone .id ,
285313 serviceofferingid = self .service_offering .id ,
286314 snapshotid = snapshot .id ,
287- mode = "basic" ,
315+ mode = self . services [ 'mode' ] ,
288316 )
289317 try :
290- ssh_client = virtual_machine .get_ssh_client ()
318+ ssh_client = virtual_machine .get_ssh_client (reconnect = True )
291319 except Exception as e :
292320 self .fail ("SSH failed for virtual machine: %s - %s" %
293321 (virtual_machine .ipaddress , e ))
@@ -303,16 +331,16 @@ def create_volume_from_snapshot_deploy_vm(self, snapshotid):
303331 zoneid = self .zone .id ,
304332 )
305333 virtual_machine = VirtualMachine .create (self .apiclient ,
306- { "name" : "Test-%s" % uuid . uuid4 ()} ,
334+ self . services [ 'small' ] ,
307335 accountid = self .account .name ,
308336 domainid = self .account .domainid ,
309337 zoneid = self .zone .id ,
310338 serviceofferingid = self .service_offering .id ,
311339 volumeid = volume .id ,
312- mode = "basic" ,
340+ mode = self . services [ 'mode' ] ,
313341 )
314342 try :
315- ssh_client = virtual_machine .get_ssh_client ()
343+ ssh_client = virtual_machine .get_ssh_client (reconnect = True )
316344 except Exception as e :
317345 self .fail ("SSH failed for virtual machine: %s - %s" %
318346 (virtual_machine .ipaddress , e ))
0 commit comments