diff --git a/nova/compute/api.py b/nova/compute/api.py index 8828ad89c32a..1ed8fc0b2049 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -88,10 +88,6 @@ compute_opts = [ default=False, help='Allow destination machine to match source for resize. ' 'Useful when testing in single-host environments.'), - cfg.BoolOpt('allow_migrate_to_same_host', - default=False, - help='Allow migrate machine to the same host. ' - 'Useful when testing in single-host environments.'), cfg.StrOpt('default_schedule_zone', help='Availability zone to use when user doesn\'t specify one'), cfg.ListOpt('non_inheritable_image_properties', @@ -2643,10 +2639,6 @@ class API(base.Base): if not CONF.allow_resize_to_same_host: filter_properties['ignore_hosts'].append(instance.host) - # Here when flavor_id is None, the process is considered as migrate. - if (not flavor_id and not CONF.allow_migrate_to_same_host): - filter_properties['ignore_hosts'].append(instance.host) - if self.cell_type == 'api': # Commit reservations early and create migration record. self._resize_cells_support(context, quotas, instance, diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 93ef584799e3..3d2d1daacc61 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -3828,7 +3828,13 @@ class ComputeManager(manager.Manager): raise exception.MigrationError(reason=msg) same_host = instance.host == self.host - if same_host and not CONF.allow_resize_to_same_host: + # if the flavor IDs match, it's migrate; otherwise resize + if same_host and instance_type['id'] == instance['instance_type_id']: + # check driver whether support migrate to same host + if not self.driver.capabilities['supports_migrate_to_same_host']: + raise exception.UnableToMigrateToSelf( + instance_id=instance.uuid, host=self.host) + elif same_host and not CONF.allow_resize_to_same_host: self._set_instance_error_state(context, instance) msg = _('destination same as source!') raise exception.MigrationError(reason=msg) diff --git a/nova/tests/unit/compute/test_compute_api.py b/nova/tests/unit/compute/test_compute_api.py index 47848a92bca1..340bf3b55153 100644 --- a/nova/tests/unit/compute/test_compute_api.py +++ b/nova/tests/unit/compute/test_compute_api.py @@ -1246,7 +1246,6 @@ class _ComputeAPIUnitTestMixIn(object): def _test_resize(self, flavor_id_passed=True, same_host=False, allow_same_host=False, - allow_mig_same_host=False, project_id=None, extra_kwargs=None, same_flavor=False, @@ -1254,8 +1253,7 @@ class _ComputeAPIUnitTestMixIn(object): if extra_kwargs is None: extra_kwargs = {} - self.flags(allow_resize_to_same_host=allow_same_host, - allow_migrate_to_same_host=allow_mig_same_host) + self.flags(allow_resize_to_same_host=allow_same_host) params = {} if project_id is not None: @@ -1312,8 +1310,6 @@ class _ComputeAPIUnitTestMixIn(object): else: filter_properties = {'ignore_hosts': [fake_inst['host']]} - if not flavor_id_passed and not allow_mig_same_host: - filter_properties['ignore_hosts'].append(fake_inst['host']) if flavor_id_passed: expected_reservations = fake_quotas.reservations else: diff --git a/nova/tests/unit/virt/vmwareapi/test_driver_api.py b/nova/tests/unit/virt/vmwareapi/test_driver_api.py index aabb1103e90e..de83a727ee9c 100644 --- a/nova/tests/unit/virt/vmwareapi/test_driver_api.py +++ b/nova/tests/unit/virt/vmwareapi/test_driver_api.py @@ -306,6 +306,8 @@ class VMwareAPIVMTestCase(test.NoDBTestCase): def test_driver_capabilities(self): self.assertTrue(self.conn.capabilities['has_imagecache']) self.assertFalse(self.conn.capabilities['supports_recreate']) + self.assertTrue( + self.conn.capabilities['supports_migrate_to_same_host']) def test_configuration_linked_clone(self): self.flags(use_linked_clone=None, group='vmware') diff --git a/nova/virt/driver.py b/nova/virt/driver.py index f2ba0d8ec91e..a15bb47ce423 100644 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -136,7 +136,8 @@ class ComputeDriver(object): capabilities = { "has_imagecache": False, "supports_recreate": False, - } + "supports_migrate_to_same_host": False + } def __init__(self, virtapi): self.virtapi = virtapi diff --git a/nova/virt/fake.py b/nova/virt/fake.py index c99005f05b57..e84f241d5f6d 100644 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -125,6 +125,7 @@ class FakeDriver(driver.ComputeDriver): capabilities = { "has_imagecache": True, "supports_recreate": True, + "supports_migrate_to_same_host": True } # Since we don't have a real hypervisor, pretend we have lots of diff --git a/nova/virt/ironic/driver.py b/nova/virt/ironic/driver.py index 8c46192059df..ef7ff0f92a2b 100644 --- a/nova/virt/ironic/driver.py +++ b/nova/virt/ironic/driver.py @@ -162,7 +162,8 @@ class IronicDriver(virt_driver.ComputeDriver): """Hypervisor driver for Ironic - bare metal provisioning.""" capabilities = {"has_imagecache": False, - "supports_recreate": False} + "supports_recreate": False, + "supports_migrate_to_same_host": False} def __init__(self, virtapi, read_only=False): super(IronicDriver, self).__init__(virtapi) diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index d348570fc364..0afaa0c41370 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -381,11 +381,11 @@ MIN_LIBVIRT_PARALLELS_VERSION = (1, 2, 12) class LibvirtDriver(driver.ComputeDriver): - capabilities = { "has_imagecache": True, "supports_recreate": True, - } + "supports_migrate_to_same_host": False + } def __init__(self, virtapi, read_only=False): super(LibvirtDriver, self).__init__(virtapi) diff --git a/nova/virt/vmwareapi/driver.py b/nova/virt/vmwareapi/driver.py index e06f7adf0fe0..1eafe615217c 100644 --- a/nova/virt/vmwareapi/driver.py +++ b/nova/virt/vmwareapi/driver.py @@ -110,7 +110,8 @@ class VMwareVCDriver(driver.ComputeDriver): capabilities = { "has_imagecache": True, "supports_recreate": False, - } + "supports_migrate_to_same_host": True + } # The vCenter driver includes API that acts on ESX hosts or groups # of ESX hosts in clusters or non-cluster logical-groupings.