Reject migrate with port having resource request
Nova does not consider the resource request of a Neutron port as of now. So this patch makes sure that server migrate and live migrate requests are rejected if they involve a port that has resource request. When the feature is ready on the nova side this limitation will be lifted. blueprint: bandwidth-resource-provider Change-Id: I48e6db9693e470b177bf4c75211d8b883c768433
This commit is contained in:
parent
bbfb3bcf79
commit
3730bd0791
@ -26,6 +26,7 @@ from nova.api import validation
|
||||
from nova import compute
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
from nova import network
|
||||
from nova.policies import migrate_server as ms_policies
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -35,6 +36,7 @@ class MigrateServerController(wsgi.Controller):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(MigrateServerController, self).__init__(*args, **kwargs)
|
||||
self.compute_api = compute.API()
|
||||
self.network_api = network.API()
|
||||
|
||||
@wsgi.response(202)
|
||||
@wsgi.expected_errors((400, 403, 404, 409))
|
||||
@ -51,6 +53,14 @@ class MigrateServerController(wsgi.Controller):
|
||||
host_name = body['migrate'].get('host')
|
||||
|
||||
instance = common.get_instance(self.compute_api, context, id)
|
||||
|
||||
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 server operation with port having QoS policy "
|
||||
"is not supported.")
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
try:
|
||||
self.compute_api.resize(req.environ['nova.context'], instance,
|
||||
host_name=host_name)
|
||||
@ -106,6 +116,14 @@ class MigrateServerController(wsgi.Controller):
|
||||
# conductor
|
||||
instance = common.get_instance(self.compute_api, context, id,
|
||||
expected_attrs=['numa_topology'])
|
||||
|
||||
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 live migrate server operation with port having QoS "
|
||||
"policy is not supported.")
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
try:
|
||||
self.compute_api.live_migrate(context, instance, block_migration,
|
||||
disk_over_commit, host, force,
|
||||
|
@ -23,6 +23,7 @@ from nova.tests.functional.api_sample_tests import test_servers
|
||||
|
||||
class MigrateServerSamplesJsonTest(test_servers.ServersSampleBase):
|
||||
sample_dir = "os-migrate-server"
|
||||
USE_NEUTRON = True
|
||||
|
||||
def setUp(self):
|
||||
"""setUp Method for MigrateServer api samples extension
|
||||
@ -148,6 +149,7 @@ class MigrateServerSamplesJsonTestV256(test_servers.ServersSampleBase):
|
||||
sample_dir = "os-migrate-server"
|
||||
microversion = '2.56'
|
||||
scenarios = [('v2_56', {'api_major_version': 'v2.1'})]
|
||||
USE_NEUTRON = True
|
||||
|
||||
def setUp(self):
|
||||
"""setUp Method for MigrateServer api samples extension
|
||||
|
@ -30,6 +30,7 @@ class ServerMigrationsSampleJsonTest(test_servers.ServersSampleBase):
|
||||
sample_dir = 'server-migrations'
|
||||
scenarios = [('v2_22', {'api_major_version': 'v2.1'})]
|
||||
microversion = '2.22'
|
||||
USE_NEUTRON = True
|
||||
|
||||
def setUp(self):
|
||||
"""setUp method for server usage."""
|
||||
@ -167,6 +168,7 @@ class ServerMigrationsSampleJsonTestV2_24(test_servers.ServersSampleBase):
|
||||
microversion = '2.24'
|
||||
sample_dir = "server-migrations"
|
||||
scenarios = [('v2_24', {'api_major_version': 'v2.1'})]
|
||||
USE_NEUTRON = True
|
||||
|
||||
def setUp(self):
|
||||
"""setUp method for server usage."""
|
||||
@ -233,6 +235,7 @@ class ServerMigrationsSampleJsonTestV2_65(ServerMigrationsSampleJsonTestV2_24):
|
||||
ADMIN_API = True
|
||||
microversion = '2.65'
|
||||
scenarios = [('v2_65', {'api_major_version': 'v2.1'})]
|
||||
USE_NEUTRON = True
|
||||
|
||||
@mock.patch.object(conductor_manager.ComputeTaskManager, '_live_migrate')
|
||||
def test_live_migrate_abort_migration_queued(self, _live_migrate):
|
||||
|
@ -45,6 +45,7 @@ class LiveMigrationCinderFailure(integrated_helpers._IntegratedTestBase,
|
||||
integrated_helpers.InstanceHelperMixin):
|
||||
api_major_version = 'v2.1'
|
||||
microversion = 'latest'
|
||||
USE_NEUTRON = True
|
||||
|
||||
def setUp(self):
|
||||
super(LiveMigrationCinderFailure, self).setUp()
|
||||
|
@ -5486,3 +5486,56 @@ class PortResourceRequestBasedSchedulingTest(
|
||||
self.assertIn(
|
||||
'The resize server operation with port having QoS policy is not '
|
||||
'supported.', six.text_type(ex))
|
||||
|
||||
def test_migrate_server_with_port_resource_request_old_microversion(self):
|
||||
server = self._create_server(
|
||||
flavor=self.flavor,
|
||||
networks=[{'port': self.neutron.port_1['id']}])
|
||||
self._wait_for_state_change(self.admin_api, server, 'ACTIVE')
|
||||
|
||||
# We need to simulate that the above server has a port that has
|
||||
# resource request, we cannot boot with such a port but legacy servers
|
||||
# can exists with such a port.
|
||||
bound_port = self.neutron._ports[self.neutron.port_1['id']]
|
||||
fake_resource_request = self.neutron.port_with_resource_request[
|
||||
'resource_request']
|
||||
bound_port['resource_request'] = fake_resource_request
|
||||
|
||||
ex = self.assertRaises(
|
||||
client.OpenStackApiException,
|
||||
self.api.post_server_action, server['id'], {'migrate': None})
|
||||
|
||||
self.assertEqual(400, ex.response.status_code)
|
||||
self.assertIn(
|
||||
'The migrate server operation with port having QoS policy is not '
|
||||
'supported.', six.text_type(ex))
|
||||
|
||||
def test_live_migrate_server_with_port_resource_request_old_microversion(
|
||||
self):
|
||||
server = self._create_server(
|
||||
flavor=self.flavor,
|
||||
networks=[{'port': self.neutron.port_1['id']}])
|
||||
self._wait_for_state_change(self.admin_api, server, 'ACTIVE')
|
||||
|
||||
# We need to simulate that the above server has a port that has
|
||||
# resource request, we cannot boot with such a port but legacy servers
|
||||
# can exists with such a port.
|
||||
bound_port = self.neutron._ports[self.neutron.port_1['id']]
|
||||
fake_resource_request = self.neutron.port_with_resource_request[
|
||||
'resource_request']
|
||||
bound_port['resource_request'] = fake_resource_request
|
||||
|
||||
post = {
|
||||
'os-migrateLive': {
|
||||
'host': None,
|
||||
'block_migration': False,
|
||||
}
|
||||
}
|
||||
ex = self.assertRaises(
|
||||
client.OpenStackApiException,
|
||||
self.api.post_server_action, server['id'], post)
|
||||
|
||||
self.assertEqual(400, ex.response.status_code)
|
||||
self.assertIn(
|
||||
'The live migrate server operation with port having QoS policy is '
|
||||
'not supported.', six.text_type(ex))
|
||||
|
@ -13,6 +13,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import fixtures
|
||||
import mock
|
||||
from oslo_utils.fixture import uuidsentinel as uuids
|
||||
from oslo_utils import uuidutils
|
||||
@ -46,6 +47,10 @@ class MigrateServerTestsV21(admin_only_action_common.CommonTests):
|
||||
self.stub_out('nova.api.openstack.compute.migrate_server.'
|
||||
'MigrateServerController',
|
||||
lambda *a, **kw: self.controller)
|
||||
self.mock_list_port = self.useFixture(
|
||||
fixtures.MockPatch(
|
||||
'nova.network.neutronv2.api.API.list_ports')).mock
|
||||
self.mock_list_port.return_value = {'ports': []}
|
||||
|
||||
def _get_migration_body(self, **kwargs):
|
||||
return {'os-migrateLive': self._get_params(**kwargs)}
|
||||
@ -101,6 +106,26 @@ class MigrateServerTestsV21(admin_only_action_common.CommonTests):
|
||||
args_map=args_map, method_translations=method_translations,
|
||||
exception_args=exception_arg)
|
||||
|
||||
def test_migrate_with_port_resource_request_old_microversion(self):
|
||||
self.mock_list_port.return_value = {'ports': [
|
||||
{'resource_request': {
|
||||
"resources": {'CUSTOM_FOO': 1}}}]
|
||||
}
|
||||
method_translations = {'_migrate': 'resize',
|
||||
'_migrate_live': 'live_migrate'}
|
||||
body_map = {'_migrate_live': self._get_migration_body(host='hostname')}
|
||||
args_map = {'_migrate_live': ((False, self.disk_over_commit,
|
||||
'hostname', self.force, self.async_),
|
||||
{}),
|
||||
'_migrate': ((), {'host_name': self.host_name})}
|
||||
ex = self.assertRaises(
|
||||
webob.exc.HTTPBadRequest, self._test_actions,
|
||||
['_migrate', '_migrate_live'], body_map=body_map,
|
||||
method_translations=method_translations, args_map=args_map)
|
||||
self.assertIn(
|
||||
'The migrate server operation with port having QoS policy is not '
|
||||
'supported.', six.text_type(ex))
|
||||
|
||||
def test_actions_with_locked_instance(self):
|
||||
method_translations = {'_migrate': 'resize',
|
||||
'_migrate_live': 'live_migrate'}
|
||||
@ -529,6 +554,20 @@ class MigrateServerTestsV256(MigrateServerTestsV234):
|
||||
method_translations=self.method_translations,
|
||||
exception_args=exception_arg)
|
||||
|
||||
def test_migrate_with_port_resource_request_old_microversion(self):
|
||||
self.mock_list_port.return_value = {'ports': [
|
||||
{'resource_request': {
|
||||
"resources": {'CUSTOM_FOO': 1}}}]
|
||||
}
|
||||
ex = self.assertRaises(
|
||||
webob.exc.HTTPBadRequest, self._test_actions,
|
||||
['_migrate'], body_map=self.body_map,
|
||||
method_translations=self.method_translations,
|
||||
args_map=self.args_map)
|
||||
self.assertIn(
|
||||
'The migrate server operation with port having QoS policy is not '
|
||||
'supported.', six.text_type(ex))
|
||||
|
||||
def test_actions_with_locked_instance(self):
|
||||
self._test_actions_with_locked_instance(
|
||||
['_migrate'], body_map=self.body_map,
|
||||
|
Loading…
Reference in New Issue
Block a user