Merge "Reject migration with QoS port from conductor if RPC pinned"
This commit is contained in:
commit
ffd4dbf817
|
@ -806,6 +806,13 @@ class ComputeAPI(object):
|
|||
block_migration=block_migration,
|
||||
disk=disk, migrate_data=migrate_data)
|
||||
|
||||
def supports_resize_with_qos_port(self, ctxt):
|
||||
"""Returns whether we can send 5.2, needed for migrating and resizing
|
||||
servers with ports having resource request.
|
||||
"""
|
||||
client = self.router.client(ctxt)
|
||||
return client.can_send_version('5.2')
|
||||
|
||||
def prep_resize(self, ctxt, instance, image, instance_type, host,
|
||||
migration, request_spec, filter_properties, node,
|
||||
clean_shutdown, host_list):
|
||||
|
|
|
@ -187,11 +187,14 @@ class MigrationTask(base.TaskBase):
|
|||
|
||||
def _support_resource_request(self, selection):
|
||||
"""Returns true if the host is new enough to support resource request
|
||||
during migration.
|
||||
during migration and that the RPC API version is not pinned during
|
||||
rolling upgrade.
|
||||
"""
|
||||
svc = objects.Service.get_by_host_and_binary(
|
||||
self.context, selection.service_host, 'nova-compute')
|
||||
return svc.version >= 39
|
||||
return (svc.version >= 39 and
|
||||
self.compute_rpcapi.supports_resize_with_qos_port(
|
||||
self.context))
|
||||
|
||||
# TODO(gibi): Remove this compat code when nova doesn't need to support
|
||||
# Train computes any more.
|
||||
|
@ -226,7 +229,8 @@ class MigrationTask(base.TaskBase):
|
|||
LOG.debug(
|
||||
'Scheduler returned host %(host)s as a possible migration target '
|
||||
'but that host is not new enough to support the migration with '
|
||||
'resource request %(request)s. Trying alternate hosts.',
|
||||
'resource request %(request)s or the compute RPC is pinned to '
|
||||
'less than 5.2. Trying alternate hosts.',
|
||||
{'host': selection_list[0].service_host,
|
||||
'request': self.request_spec.requested_resources},
|
||||
instance=self.instance)
|
||||
|
@ -267,7 +271,8 @@ class MigrationTask(base.TaskBase):
|
|||
LOG.debug(
|
||||
'Scheduler returned alternate host %(host)s as a possible '
|
||||
'migration target but that host is not new enough to '
|
||||
'support the migration with resource request %(request)s. '
|
||||
'support the migration with resource request %(request)s '
|
||||
'or the compute RPC is pinned to less than 5.2. '
|
||||
'Trying another alternate.',
|
||||
{'host': selection.service_host,
|
||||
'request': self.request_spec.requested_resources},
|
||||
|
|
|
@ -6873,77 +6873,51 @@ class ServerMoveWithPortResourceRequestTest(
|
|||
server = self._create_server_with_ports(
|
||||
non_qos_normal_port, qos_normal_port)
|
||||
|
||||
self.api.post_server_action(server['id'], {'migrate': None})
|
||||
# There are ports with resource request but the finish_resize is
|
||||
# called without request_spec (as that is only added in 5.2 an we are
|
||||
# pinned to 5.1) and therefore the request group - resource provider
|
||||
# mapping cannot be calculated for these ports so the server goes to
|
||||
# ERROR on the target host. This is bug 1844993.
|
||||
server = self._wait_for_server_parameter(
|
||||
self.api, server,
|
||||
# Note that the server remains on the dest host after the
|
||||
# failure as we are failing in finish_resize
|
||||
{'OS-EXT-SRV-ATTR:host': 'host2',
|
||||
'OS-EXT-STS:task_state': None,
|
||||
'status': 'ERROR'})
|
||||
# This migration expected to fail as the old RPC does not provide
|
||||
# enough information to do a proper port binding on the target host.
|
||||
# The MigrationTask in the conductor checks that the RPC is new enough
|
||||
# for this request for each possible destination provided by the
|
||||
# scheduler and skips the old hosts.
|
||||
ex = self.assertRaises(
|
||||
client.OpenStackApiException, self.api.post_server_action,
|
||||
server['id'], {'migrate': None})
|
||||
|
||||
self.assertEqual(400, ex.response.status_code)
|
||||
self.assertIn('No valid host was found.', six.text_type(ex))
|
||||
|
||||
# The migration is put into error
|
||||
self._wait_for_migration_status(server, ['error'])
|
||||
|
||||
self.assertIn(
|
||||
'Provider mappings are not available to the compute service but '
|
||||
'are required for ports with a resource request. If compute RPC '
|
||||
'API versions are pinned for a rolling upgrade, you will need to '
|
||||
'retry this operation once the RPC version is unpinned and the '
|
||||
'nova-compute services are all upgraded',
|
||||
self.stdlog.logger.output)
|
||||
|
||||
self.assertIn(
|
||||
'Provider mappings are not available to the compute service but '
|
||||
'are required for ports with a resource request.',
|
||||
server['fault']['message'])
|
||||
|
||||
self._wait_for_action_fail_completion(
|
||||
server, instance_actions.MIGRATE, 'compute_finish_resize',
|
||||
self.admin_api)
|
||||
|
||||
# Note that we don't get error notification about the failed resize
|
||||
fake_notifier.wait_for_versioned_notifications(
|
||||
'instance.resize.end')
|
||||
# Just a generic error notification
|
||||
fake_notifier.wait_for_versioned_notifications(
|
||||
'compute.exception')
|
||||
# The migration is rejected so the instance remains on the source host
|
||||
server = self.api.get_server(server['id'])
|
||||
self.assertEqual('ACTIVE', server['status'])
|
||||
self.assertEqual('host1', server['OS-EXT-SRV-ATTR:host'])
|
||||
|
||||
migration_uuid = self.get_migration_uuid_for_instance(server['id'])
|
||||
|
||||
# The migration is failed the migration allocation on the source host
|
||||
# is deleted
|
||||
# The migration allocation is deleted
|
||||
migration_allocations = self.placement_api.get(
|
||||
'/allocations/%s' % migration_uuid).body['allocations']
|
||||
self.assertEqual({}, migration_allocations)
|
||||
|
||||
# Note(gibi): inlined _check_allocation() as the current state of the
|
||||
# port binding is complicated that cannot be handled with
|
||||
# _check_allocation
|
||||
# The instance is still allocated from the source host
|
||||
updated_non_qos_port = self.neutron.show_port(
|
||||
non_qos_normal_port['id'])['port']
|
||||
updated_qos_port = self.neutron.show_port(
|
||||
qos_normal_port['id'])['port']
|
||||
allocations = self.placement_api.get(
|
||||
'/allocations/%s' % server['id']).body['allocations']
|
||||
|
||||
# We expect one set of allocations for the compute resources on the
|
||||
# compute rp and one set for the networking resources on the ovs
|
||||
# bridge rp due to the qos_port resource request
|
||||
# Note that the resource allocation is on the dest host...
|
||||
self.assertEqual(2, len(allocations))
|
||||
self.assertComputeAllocationMatchesFlavor(
|
||||
allocations, self.compute2_rp_uuid, self.flavor_with_group_policy)
|
||||
allocations, self.compute1_rp_uuid, self.flavor_with_group_policy)
|
||||
ovs_allocations = allocations[
|
||||
self.ovs_bridge_rp_per_host[self.compute2_rp_uuid]]['resources']
|
||||
self.ovs_bridge_rp_per_host[self.compute1_rp_uuid]]['resources']
|
||||
self.assertPortMatchesAllocation(qos_normal_port, ovs_allocations)
|
||||
|
||||
# ... but the binding update failed so the allocation key in the
|
||||
# binding:profile still points to the networking RP on the source host
|
||||
# (host1). This is bug 1844993.
|
||||
qos_binding_profile = updated_qos_port['binding:profile']
|
||||
self.assertEqual(self.ovs_bridge_rp_per_host[self.compute1_rp_uuid],
|
||||
qos_binding_profile['allocation'])
|
||||
|
|
|
@ -491,7 +491,8 @@ class MigrationTaskTestCase(test.NoDBTestCase):
|
|||
mock_debug.assert_called_once_with(
|
||||
'Scheduler returned host %(host)s as a possible migration target '
|
||||
'but that host is not new enough to support the migration with '
|
||||
'resource request %(request)s. Trying alternate hosts.',
|
||||
'resource request %(request)s or the compute RPC is pinned to '
|
||||
'less than 5.2. Trying alternate hosts.',
|
||||
{'host': 'host1',
|
||||
'request': self.request_spec.requested_resources},
|
||||
instance=self.instance)
|
||||
|
@ -582,8 +583,8 @@ class MigrationTaskTestCase(test.NoDBTestCase):
|
|||
mock.call(
|
||||
'Scheduler returned host %(host)s as a possible migration '
|
||||
'target but that host is not new enough to support the '
|
||||
'migration with resource request %(request)s. Trying '
|
||||
'alternate hosts.',
|
||||
'migration with resource request %(request)s or the compute '
|
||||
'RPC is pinned to less than 5.2. Trying alternate hosts.',
|
||||
{'host': 'host1',
|
||||
'request': self.request_spec.requested_resources},
|
||||
instance=self.instance),
|
||||
|
@ -674,16 +675,17 @@ class MigrationTaskTestCase(test.NoDBTestCase):
|
|||
mock.call(
|
||||
'Scheduler returned host %(host)s as a possible migration '
|
||||
'target but that host is not new enough to support the '
|
||||
'migration with resource request %(request)s. Trying '
|
||||
'alternate hosts.',
|
||||
'migration with resource request %(request)s or the compute '
|
||||
'RPC is pinned to less than 5.2. Trying alternate hosts.',
|
||||
{'host': 'host1',
|
||||
'request': self.request_spec.requested_resources},
|
||||
instance=self.instance),
|
||||
mock.call(
|
||||
'Scheduler returned alternate host %(host)s as a possible '
|
||||
'migration target but that host is not new enough to support '
|
||||
'the migration with resource request %(request)s. Trying '
|
||||
'another alternate.',
|
||||
'the migration with resource request %(request)s or the '
|
||||
'compute RPC is pinned to less than 5.2. Trying another '
|
||||
'alternate.',
|
||||
{'host': 'host2',
|
||||
'request': self.request_spec.requested_resources},
|
||||
instance=self.instance),
|
||||
|
|
Loading…
Reference in New Issue