From 4a6a9da8e7d283b781ceee1b20a7f6f25144de57 Mon Sep 17 00:00:00 2001 From: Ben Nemec Date: Thu, 7 Mar 2013 23:00:03 +0000 Subject: Fix Hyper V instance conflicts Fixes bug 1152368 If the hyperv driver attempts to boot an instance and a previous instance with the same name was not properly removed, the boot will fail due to an error creating root.vhd. This only happens when using CoW images. This fix deletes the instance directory before creating the new instance so that there will never be an old image to interfere with creation of the new one. This is most likely to be an issue in development and test environments that toggle between versions of nova with no migration path. Change-Id: I21eab01590c426234b4b9a55abec4b2d2df0e168 --- nova/tests/test_hypervapi.py | 81 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 12 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_hypervapi.py b/nova/tests/test_hypervapi.py index 0ddfe080d..b50709512 100644 --- a/nova/tests/test_hypervapi.py +++ b/nova/tests/test_hypervapi.py @@ -84,6 +84,7 @@ class HyperVAPITestCase(test.TestCase): self._instance_ide_dvds = [] self._instance_volume_disks = [] self._test_vm_name = None + self._test_instance_dir = 'C:\\FakeInstancesPath\\instance-0000001' self._setup_stubs() @@ -134,6 +135,7 @@ class HyperVAPITestCase(test.TestCase): self._mox.StubOutWithMock(fake.PathUtils, 'makedirs') self._mox.StubOutWithMock(fake.PathUtils, 'get_instance_migr_revert_dir') + self._mox.StubOutWithMock(fake.PathUtils, 'get_instance_dir') self._mox.StubOutWithMock(vmutils.VMUtils, 'vm_exists') self._mox.StubOutWithMock(vmutils.VMUtils, 'create_vm') @@ -336,6 +338,9 @@ class HyperVAPITestCase(test.TestCase): content=mox.IsA(list), extra_md=mox.IsA(dict)) + m = fake.PathUtils.get_instance_dir(mox.IsA(str)) + m.AndReturn(self._test_instance_dir) + cdb = self._mox.CreateMockAnything() m = configdrive.ConfigDriveBuilder(instance_md=mox.IgnoreArg()) m.AndReturn(cdb) @@ -368,8 +373,6 @@ class HyperVAPITestCase(test.TestCase): self.flags(config_drive_cdrom=use_cdrom, group='hyperv') self.flags(mkisofs_cmd='mkisofs.exe') - self._setup_spawn_config_drive_mocks(use_cdrom) - if use_cdrom: expected_ide_disks = 1 expected_ide_dvds = 1 @@ -378,7 +381,9 @@ class HyperVAPITestCase(test.TestCase): expected_ide_dvds = 0 self._test_spawn_instance(expected_ide_disks=expected_ide_disks, - expected_ide_dvds=expected_ide_dvds) + expected_ide_dvds=expected_ide_dvds, + config_drive=True, + use_cdrom=use_cdrom) def test_spawn_config_drive(self): self._test_spawn_config_drive(False) @@ -512,7 +517,7 @@ class HyperVAPITestCase(test.TestCase): None) self._mox.VerifyAll() - def _setup_destroy_mocks(self): + def _setup_destroy_mocks(self, destroy_disks=True): m = vmutils.VMUtils.vm_exists(mox.Func(self._check_instance_name)) m.AndReturn(True) @@ -524,6 +529,12 @@ class HyperVAPITestCase(test.TestCase): vmutils.VMUtils.destroy_vm(func) + if destroy_disks: + m = fake.PathUtils.get_instance_dir(mox.IsA(str), + create_dir=False, + remove_dir=True) + m.AndReturn(self._test_instance_dir) + def test_destroy(self): self._instance_data = self._get_instance_data() @@ -691,6 +702,9 @@ class HyperVAPITestCase(test.TestCase): m = vmutils.VMUtils.take_vm_snapshot(func) m.AndReturn(fake_hv_snapshot_path) + m = fake.PathUtils.get_instance_dir(mox.IsA(str)) + m.AndReturn(self._test_instance_dir) + m = vhdutils.VHDUtils.get_vhd_parent_path(mox.IsA(str)) m.AndReturn(fake_parent_vhd_path) @@ -831,10 +845,17 @@ class HyperVAPITestCase(test.TestCase): def _setup_spawn_instance_mocks(self, cow, setup_vif_mocks_func=None, with_exception=False, block_device_info=None, - boot_from_volume=False): + boot_from_volume=False, + config_drive=False, + use_cdrom=False): m = vmutils.VMUtils.vm_exists(mox.IsA(str)) m.WithSideEffects(self._set_vm_name).AndReturn(False) + m = fake.PathUtils.get_instance_dir(mox.IsA(str), + create_dir=False, + remove_dir=True) + m.AndReturn(self._test_instance_dir) + m = basevolumeutils.BaseVolumeUtils.volume_in_mapping( mox.IsA(str), block_device_info) m.AndReturn(boot_from_volume) @@ -856,6 +877,9 @@ class HyperVAPITestCase(test.TestCase): boot_from_volume, block_device_info) + if config_drive: + self._setup_spawn_config_drive_mocks(use_cdrom) + # TODO(alexpilotti) Based on where the exception is thrown # some of the above mock calls need to be skipped if with_exception: @@ -871,9 +895,17 @@ class HyperVAPITestCase(test.TestCase): expected_ide_disks=1, expected_ide_dvds=0, setup_vif_mocks_func=None, - with_exception=False): - self._setup_spawn_instance_mocks(cow, setup_vif_mocks_func, - with_exception) + with_exception=False, + config_drive=False, + use_cdrom=False): + self._setup_spawn_instance_mocks(cow, + setup_vif_mocks_func, + with_exception, + config_drive=config_drive, + use_cdrom=use_cdrom) + + m = fake.PathUtils.get_instance_dir(mox.IsA(str)) + m.AndReturn(self._test_instance_dir) self._mox.ReplayAll() self._spawn_instance(cow) @@ -882,7 +914,7 @@ class HyperVAPITestCase(test.TestCase): self.assertEquals(len(self._instance_ide_disks), expected_ide_disks) self.assertEquals(len(self._instance_ide_dvds), expected_ide_dvds) - vhd_path = pathutils.PathUtils().get_vhd_path(self._test_vm_name) + vhd_path = os.path.join(self._test_instance_dir, 'root.vhd') self.assertEquals(vhd_path, self._instance_ide_disks[0]) def _mock_get_mounted_disk_from_lun(self, target_iqn, target_lun, @@ -1028,8 +1060,7 @@ class HyperVAPITestCase(test.TestCase): fake_dest_ip = '10.0.0.2' fake_root_vhd_path = 'C:\\FakePath\\root.vhd' - fake_revert_path = ('C:\\FakeInstancesPath\\%s\\_revert' % - instance['name']) + fake_revert_path = os.path.join(self._test_instance_dir, '_revert') func = mox.Func(self._check_instance_name) vmutils.VMUtils.set_vm_state(func, constants.HYPERV_VM_STATE_DISABLED) @@ -1040,6 +1071,9 @@ class HyperVAPITestCase(test.TestCase): m = hostutils.HostUtils.get_local_ips() m.AndReturn([fake_local_ip]) + m = fake.PathUtils.get_instance_dir(mox.IsA(str)) + m.AndReturn(self._test_instance_dir) + m = pathutils.PathUtils.get_instance_migr_revert_dir(instance['name'], remove_dir=True) m.AndReturn(fake_revert_path) @@ -1050,12 +1084,24 @@ class HyperVAPITestCase(test.TestCase): m = fake.PathUtils.copy(fake_root_vhd_path, mox.IsA(str)) if with_exception: m.AndRaise(shutil.Error('Simulated copy error')) + m = fake.PathUtils.get_instance_dir(mox.IsA(str), + mox.IsA(str), + remove_dir=True) + m.AndReturn(self._test_instance_dir) else: fake.PathUtils.rename(mox.IsA(str), mox.IsA(str)) + destroy_disks = True if same_host: fake.PathUtils.rename(mox.IsA(str), mox.IsA(str)) + destroy_disks = False + + self._setup_destroy_mocks(False) - self._setup_destroy_mocks() + if destroy_disks: + m = fake.PathUtils.get_instance_dir(mox.IsA(str), + mox.IsA(str), + remove_dir=True) + m.AndReturn(self._test_instance_dir) return (instance, fake_dest_ip, network_info) @@ -1103,6 +1149,9 @@ class HyperVAPITestCase(test.TestCase): None) m.AndReturn(False) + m = fake.PathUtils.get_instance_dir(mox.IsA(str)) + m.AndReturn(self._test_instance_dir) + self._mox.StubOutWithMock(fake.PathUtils, 'exists') m = fake.PathUtils.exists(mox.IsA(str)) m.AndReturn(True) @@ -1161,10 +1210,18 @@ class HyperVAPITestCase(test.TestCase): None) m.AndReturn(False) + m = fake.PathUtils.get_instance_dir(mox.IsA(str), + create_dir=False, + remove_dir=True) + m.AndReturn(self._test_instance_dir) + m = pathutils.PathUtils.get_instance_migr_revert_dir(instance['name']) m.AndReturn(fake_revert_path) fake.PathUtils.rename(fake_revert_path, mox.IsA(str)) + m = fake.PathUtils.get_instance_dir(mox.IsA(str)) + m.AndReturn(self._test_instance_dir) + self._set_vm_name(instance['name']) self._setup_create_instance_mocks(None, False) -- cgit