summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nova/tests/test_hypervapi.py107
-rw-r--r--nova/virt/hyperv/migrationops.py18
-rw-r--r--nova/virt/hyperv/vmutils.py8
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='.'):