diff --git a/nova/api/openstack/compute/migrate_server.py b/nova/api/openstack/compute/migrate_server.py index 3a3f84158f..17c1975fa1 100644 --- a/nova/api/openstack/compute/migrate_server.py +++ b/nova/api/openstack/compute/migrate_server.py @@ -27,10 +27,13 @@ from nova.compute import api as compute from nova import exception from nova.i18n import _ from nova import network +from nova import objects from nova.policies import migrate_server as ms_policies LOG = logging.getLogger(__name__) +MIN_COMPUTE_MOVE_BANDWIDTH = 39 + class MigrateServerController(wsgi.Controller): def __init__(self): @@ -58,14 +61,25 @@ class MigrateServerController(wsgi.Controller): # We could potentially move this check to conductor and avoid the # extra API call to neutron when we support move operations with ports # having resource requests. - if (common.instance_has_port_with_resource_request( - context, instance.uuid, self.network_api) and not - common.supports_port_resource_request_during_move(req)): - msg = _("The migrate action on a server with ports having " - "resource requests, like a port with a QoS minimum " - "bandwidth policy, is not supported with this " - "microversion") - raise exc.HTTPBadRequest(explanation=msg) + if common.instance_has_port_with_resource_request( + context, instance.uuid, self.network_api): + if not common.supports_port_resource_request_during_move(req): + msg = _("The migrate action on a server with ports having " + "resource requests, like a port with a QoS minimum " + "bandwidth policy, is not supported with this " + "microversion") + raise exc.HTTPBadRequest(explanation=msg) + + # TODO(gibi): Remove when nova only supports compute newer than + # Train + source_service = objects.Service.get_by_host_and_binary( + context, instance.host, 'nova-compute') + if source_service.version < MIN_COMPUTE_MOVE_BANDWIDTH: + msg = _("The migrate action on a server with ports having " + "resource requests, like a port with a QoS " + "minimum bandwidth policy, is not yet supported " + "on the source compute") + raise exc.HTTPConflict(explanation=msg) try: self.compute_api.resize(req.environ['nova.context'], instance, diff --git a/nova/tests/unit/api/openstack/compute/test_migrate_server.py b/nova/tests/unit/api/openstack/compute/test_migrate_server.py index 916f9b16d2..dfc4638fde 100644 --- a/nova/tests/unit/api/openstack/compute/test_migrate_server.py +++ b/nova/tests/unit/api/openstack/compute/test_migrate_server.py @@ -296,6 +296,29 @@ class MigrateServerTestsV21(admin_only_action_common.CommonTests): expected_exc=webob.exc.HTTPInternalServerError, check_response=False) + @mock.patch('nova.api.openstack.common.' + 'supports_port_resource_request_during_move', + return_value=True) + @mock.patch('nova.objects.Service.get_by_host_and_binary') + @mock.patch('nova.api.openstack.common.' + 'instance_has_port_with_resource_request', return_value=True) + def test_migrate_with_bandwidth_from_old_compute_not_supported( + self, mock_has_res_req, mock_get_service, mock_support): + instance = self._stub_instance_get() + + mock_get_service.return_value = objects.Service(host=instance['host']) + mock_get_service.return_value.version = 38 + + self.assertRaises( + webob.exc.HTTPConflict, self.controller._migrate, self.req, + instance['uuid'], body={'migrate': None}) + + mock_has_res_req.assert_called_once_with( + self.req.environ['nova.context'], instance['uuid'], + self.controller.network_api) + mock_get_service.assert_called_once_with( + self.req.environ['nova.context'], instance['host'], 'nova-compute') + class MigrateServerTestsV225(MigrateServerTestsV21):