diff options
-rw-r--r-- | nova/tests/test_hypervapi.py | 107 | ||||
-rw-r--r-- | nova/virt/hyperv/migrationops.py | 18 | ||||
-rw-r--r-- | nova/virt/hyperv/vmutils.py | 8 |
3 files changed, 90 insertions, 43 deletions
diff --git a/nova/tests/test_hypervapi.py b/nova/tests/test_hypervapi.py index 45466f783..52e5f55c8 100644 --- a/nova/tests/test_hypervapi.py +++ b/nova/tests/test_hypervapi.py @@ -1046,95 +1046,120 @@ class HyperVAPITestCase(test.TestCase): self.assertEquals(len(self._instance_volume_disks), 1) def _setup_test_migrate_disk_and_power_off_mocks(self, same_host=False, - with_exception=False): + copy_exception=False, + size_exception=False): self._instance_data = self._get_instance_data() instance = db.instance_create(self._context, self._instance_data) network_info = fake_network.fake_get_instance_nw_info( self.stubs, spectacular=True) + instance['root_gb'] = 10 + fake_local_ip = '10.0.0.1' if same_host: fake_dest_ip = fake_local_ip else: fake_dest_ip = '10.0.0.2' - fake_root_vhd_path = 'C:\\FakePath\\root.vhd' - 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) + if size_exception: + flavor = 'm1.tiny' + else: + flavor = 'm1.small' - m = vmutils.VMUtils.get_vm_storage_paths(func) - m.AndReturn(([fake_root_vhd_path], [])) + instance_type = db.instance_type_get_by_name(self._context, flavor) - m = hostutils.HostUtils.get_local_ips() - m.AndReturn([fake_local_ip]) + if not size_exception: + fake_root_vhd_path = 'C:\\FakePath\\root.vhd' + fake_revert_path = os.path.join(self._test_instance_dir, '_revert') - m = fake.PathUtils.get_instance_dir(mox.IsA(str)) - m.AndReturn(self._test_instance_dir) + func = mox.Func(self._check_instance_name) + vmutils.VMUtils.set_vm_state(func, + constants.HYPERV_VM_STATE_DISABLED) - m = pathutils.PathUtils.get_instance_migr_revert_dir(instance['name'], - remove_dir=True) - m.AndReturn(fake_revert_path) + m = vmutils.VMUtils.get_vm_storage_paths(func) + m.AndReturn(([fake_root_vhd_path], [])) - if same_host: - fake.PathUtils.makedirs(mox.IsA(str)) + m = hostutils.HostUtils.get_local_ips() + m.AndReturn([fake_local_ip]) - 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 = fake.PathUtils.get_instance_dir(mox.IsA(str)) 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) + m = pathutils.PathUtils.get_instance_migr_revert_dir( + instance['name'], remove_dir=True) + m.AndReturn(fake_revert_path) + + if same_host: + fake.PathUtils.makedirs(mox.IsA(str)) - if destroy_disks: + m = fake.PathUtils.copy(fake_root_vhd_path, mox.IsA(str)) + if copy_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) - return (instance, fake_dest_ip, network_info) + 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, instance_type) def test_migrate_disk_and_power_off(self): (instance, fake_dest_ip, - network_info) = self._setup_test_migrate_disk_and_power_off_mocks() + network_info, + instance_type) = self._setup_test_migrate_disk_and_power_off_mocks() self._mox.ReplayAll() self._conn.migrate_disk_and_power_off(self._context, instance, - fake_dest_ip, None, + fake_dest_ip, instance_type, network_info) self._mox.VerifyAll() def test_migrate_disk_and_power_off_same_host(self): args = self._setup_test_migrate_disk_and_power_off_mocks( same_host=True) - (instance, fake_dest_ip, network_info) = args + (instance, fake_dest_ip, network_info, instance_type) = args self._mox.ReplayAll() self._conn.migrate_disk_and_power_off(self._context, instance, - fake_dest_ip, None, + fake_dest_ip, instance_type, network_info) self._mox.VerifyAll() - def test_migrate_disk_and_power_off_exception(self): + def test_migrate_disk_and_power_off_copy_exception(self): args = self._setup_test_migrate_disk_and_power_off_mocks( - with_exception=True) - (instance, fake_dest_ip, network_info) = args + copy_exception=True) + (instance, fake_dest_ip, network_info, instance_type) = args self._mox.ReplayAll() self.assertRaises(shutil.Error, self._conn.migrate_disk_and_power_off, - self._context, instance, fake_dest_ip, None, - network_info) + self._context, instance, fake_dest_ip, + instance_type, network_info) + self._mox.VerifyAll() + + def test_migrate_disk_and_power_off_smaller_root_vhd_size_exception(self): + args = self._setup_test_migrate_disk_and_power_off_mocks( + size_exception=True) + (instance, fake_dest_ip, network_info, instance_type) = args + + self._mox.ReplayAll() + self.assertRaises(vmutils.VHDResizeException, + self._conn.migrate_disk_and_power_off, + self._context, instance, fake_dest_ip, + instance_type, network_info) self._mox.VerifyAll() def test_finish_migration(self): diff --git a/nova/virt/hyperv/migrationops.py b/nova/virt/hyperv/migrationops.py index 07bf453e5..ff8651efe 100644 --- a/nova/virt/hyperv/migrationops.py +++ b/nova/virt/hyperv/migrationops.py @@ -95,11 +95,25 @@ class MigrationOps(object): LOG.exception(ex) LOG.error(_("Cannot cleanup migration files")) + def _check_target_instance_type(self, instance, instance_type): + new_root_gb = instance_type['root_gb'] + curr_root_gb = instance['root_gb'] + + if new_root_gb < curr_root_gb: + raise vmutils.VHDResizeException(_("Cannot resize the root disk " + "to a smaller size. Current " + "size: %(curr_root_gb)s GB. " + "Requested size: " + "%(new_root_gb)s GB") % + locals()) + def migrate_disk_and_power_off(self, context, instance, dest, instance_type, network_info, block_device_info=None): LOG.debug(_("migrate_disk_and_power_off called"), instance=instance) + self._check_target_instance_type(instance, instance_type) + self._vmops.power_off(instance) instance_name = instance["name"] @@ -218,8 +232,8 @@ class MigrationOps(object): curr_size = vhd_info['MaxInternalSize'] new_size = instance['root_gb'] * 1024 ** 3 if new_size < curr_size: - raise vmutils.HyperVException(_("Cannot resize a VHD to a " - "smaller size")) + raise vmutils.VHDResizeException(_("Cannot resize a VHD " + "to a smaller size")) elif new_size > curr_size: self._resize_vhd(root_vhd_path, new_size) diff --git a/nova/virt/hyperv/vmutils.py b/nova/virt/hyperv/vmutils.py index 45fea329d..680ec2d61 100644 --- a/nova/virt/hyperv/vmutils.py +++ b/nova/virt/hyperv/vmutils.py @@ -37,11 +37,19 @@ CONF = cfg.CONF LOG = logging.getLogger(__name__) +# TODO(alexpilotti): Move the exceptions to a separate module +# TODO(alexpilotti): Add more domain exceptions class HyperVException(exception.NovaException): def __init__(self, message=None): super(HyperVException, self).__init__(message) +# TODO(alexpilotti): Add a storage exception base class +class VHDResizeException(HyperVException): + def __init__(self, message=None): + super(HyperVException, self).__init__(message) + + class VMUtils(object): def __init__(self, host='.'): |