pull out put_allocation call from _heal_*
Both allocation healing steps calls the placement API. This patch pulls out the placement updating code to a single place. To do that it change the healing steps to only generate / update the allocation individually and then at the end of the healing there will be a single placement update with this allocation. This will help us to include the port related allocation into the instance allocation by modifying a single place in the code. Related-Bug: #1819923 Change-Id: I0e9f9a488141da599c10af8cabb4f6a5d111104f
This commit is contained in:
parent
307999c581
commit
e2866609bb
|
@ -1658,9 +1658,7 @@ class PlacementCommands(object):
|
||||||
node_cache[instance.node] = node_uuid
|
node_cache[instance.node] = node_uuid
|
||||||
return node_uuid
|
return node_uuid
|
||||||
|
|
||||||
def _heal_missing_alloc(
|
def _heal_missing_alloc(self, ctxt, instance, node_cache):
|
||||||
self, ctxt, instance, node_cache, dry_run, output, placement):
|
|
||||||
|
|
||||||
node_uuid = self._get_compute_node_uuid(
|
node_uuid = self._get_compute_node_uuid(
|
||||||
ctxt, instance, node_cache)
|
ctxt, instance, node_cache)
|
||||||
|
|
||||||
|
@ -1668,49 +1666,21 @@ class PlacementCommands(object):
|
||||||
# on its embedded flavor.
|
# on its embedded flavor.
|
||||||
resources = scheduler_utils.resources_from_flavor(
|
resources = scheduler_utils.resources_from_flavor(
|
||||||
instance, instance.flavor)
|
instance, instance.flavor)
|
||||||
if dry_run:
|
|
||||||
output(_('[dry-run] Create allocations for instance %(instance)s '
|
|
||||||
'on provider %(node_uuid)s: %(resources)s') %
|
|
||||||
{'instance': instance.uuid, 'node_uuid': node_uuid,
|
|
||||||
'resources': resources})
|
|
||||||
else:
|
|
||||||
payload = {
|
|
||||||
'allocations': {
|
|
||||||
node_uuid: {'resources': resources},
|
|
||||||
},
|
|
||||||
'project_id': instance.project_id,
|
|
||||||
'user_id': instance.user_id,
|
|
||||||
'consumer_generation': None
|
|
||||||
}
|
|
||||||
resp = placement.put_allocations(ctxt, instance.uuid, payload)
|
|
||||||
if resp:
|
|
||||||
output(_('Successfully created allocations for '
|
|
||||||
'instance %(instance)s against resource '
|
|
||||||
'provider %(provider)s.') %
|
|
||||||
{'instance': instance.uuid, 'provider': node_uuid})
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
raise exception.AllocationCreateFailed(
|
|
||||||
instance=instance.uuid, provider=node_uuid)
|
|
||||||
|
|
||||||
def _heal_missing_project_and_user_id(
|
payload = {
|
||||||
self, ctxt, allocations, instance, dry_run, output, placement):
|
'allocations': {
|
||||||
|
node_uuid: {'resources': resources},
|
||||||
|
},
|
||||||
|
'project_id': instance.project_id,
|
||||||
|
'user_id': instance.user_id,
|
||||||
|
'consumer_generation': None
|
||||||
|
}
|
||||||
|
return payload
|
||||||
|
|
||||||
|
def _heal_missing_project_and_user_id(self, allocations, instance):
|
||||||
allocations['project_id'] = instance.project_id
|
allocations['project_id'] = instance.project_id
|
||||||
allocations['user_id'] = instance.user_id
|
allocations['user_id'] = instance.user_id
|
||||||
if dry_run:
|
return allocations
|
||||||
output(_('[dry-run] Update allocations for instance '
|
|
||||||
'%(instance)s: %(allocations)s') %
|
|
||||||
{'instance': instance.uuid, 'allocations': allocations})
|
|
||||||
else:
|
|
||||||
resp = placement.put_allocations(ctxt, instance.uuid, allocations)
|
|
||||||
if resp:
|
|
||||||
output(_('Successfully updated allocations for '
|
|
||||||
'instance %s.') % instance.uuid)
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
raise exception.AllocationUpdateFailed(
|
|
||||||
consumer_uuid=instance.uuid, error=resp.text)
|
|
||||||
|
|
||||||
def _heal_allocations_for_instance(self, ctxt, instance, node_cache,
|
def _heal_allocations_for_instance(self, ctxt, instance, node_cache,
|
||||||
output, placement, dry_run):
|
output, placement, dry_run):
|
||||||
|
@ -1756,14 +1726,15 @@ class PlacementCommands(object):
|
||||||
output(_("Allocation retrieval failed: %s") % e)
|
output(_("Allocation retrieval failed: %s") % e)
|
||||||
allocations = None
|
allocations = None
|
||||||
|
|
||||||
|
need_healing = False
|
||||||
# get_allocations_for_consumer uses safe_connect which will
|
# get_allocations_for_consumer uses safe_connect which will
|
||||||
# return None if we can't communicate with Placement, and the
|
# return None if we can't communicate with Placement, and the
|
||||||
# response can have an empty {'allocations': {}} response if
|
# response can have an empty {'allocations': {}} response if
|
||||||
# there are no allocations for the instance so handle both
|
# there are no allocations for the instance so handle both
|
||||||
if not allocations or not allocations.get('allocations'):
|
if not allocations or not allocations.get('allocations'):
|
||||||
# This instance doesn't have allocations
|
# This instance doesn't have allocations
|
||||||
return self._heal_missing_alloc(
|
need_healing = 'Create'
|
||||||
ctxt, instance, node_cache, dry_run, output, placement)
|
allocations = self._heal_missing_alloc(ctxt, instance, node_cache)
|
||||||
|
|
||||||
if (allocations.get('project_id') != instance.project_id or
|
if (allocations.get('project_id') != instance.project_id or
|
||||||
allocations.get('user_id') != instance.user_id):
|
allocations.get('user_id') != instance.user_id):
|
||||||
|
@ -1772,12 +1743,33 @@ class PlacementCommands(object):
|
||||||
# and re-put them. We don't use put_allocations here
|
# and re-put them. We don't use put_allocations here
|
||||||
# because we don't want to mess up shared or nested
|
# because we don't want to mess up shared or nested
|
||||||
# provider allocations.
|
# provider allocations.
|
||||||
return self._heal_missing_project_and_user_id(
|
need_healing = 'Update'
|
||||||
ctxt, allocations, instance, dry_run, output, placement)
|
allocations = self._heal_missing_project_and_user_id(
|
||||||
|
allocations, instance)
|
||||||
|
|
||||||
output(_('Instance %s already has allocations with '
|
if need_healing:
|
||||||
'matching consumer project/user.') % instance.uuid)
|
if dry_run:
|
||||||
return
|
output(_('[dry-run] %(operation)s allocations for instance '
|
||||||
|
'%(instance)s: %(allocations)s') %
|
||||||
|
{'operation': need_healing,
|
||||||
|
'instance': instance.uuid,
|
||||||
|
'allocations': allocations})
|
||||||
|
else:
|
||||||
|
resp = placement.put_allocations(ctxt, instance.uuid,
|
||||||
|
allocations)
|
||||||
|
if resp:
|
||||||
|
output(_('Successfully %(operation)sd allocations for '
|
||||||
|
'instance %(instance)s.') %
|
||||||
|
{'operation': need_healing.lower(),
|
||||||
|
'instance': instance.uuid})
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
raise exception.AllocationUpdateFailed(
|
||||||
|
consumer_uuid=instance.uuid, error='')
|
||||||
|
else:
|
||||||
|
output(_('Instance %s already has allocations with '
|
||||||
|
'matching consumer project/user.') % instance.uuid)
|
||||||
|
return
|
||||||
|
|
||||||
def _heal_instances_in_cell(self, ctxt, max_count, unlimited, output,
|
def _heal_instances_in_cell(self, ctxt, max_count, unlimited, output,
|
||||||
placement, dry_run, instance_uuid):
|
placement, dry_run, instance_uuid):
|
||||||
|
|
|
@ -652,13 +652,14 @@ class TestNovaManagePlacementHealAllocations(
|
||||||
self.assertEqual(4, result, self.output.getvalue())
|
self.assertEqual(4, result, self.output.getvalue())
|
||||||
output = self.output.getvalue()
|
output = self.output.getvalue()
|
||||||
self.assertIn('Processed 0 instances.', output)
|
self.assertIn('Processed 0 instances.', output)
|
||||||
self.assertIn('[dry-run] Update allocations for instance %s' %
|
self.assertIn('[dry-run] Update allocations for instance %s'
|
||||||
server['id'], output)
|
% server['id'], output)
|
||||||
# Now run heal_allocations which should update the consumer info.
|
# Now run heal_allocations which should update the consumer info.
|
||||||
result = self.cli.heal_allocations(verbose=True)
|
result = self.cli.heal_allocations(verbose=True)
|
||||||
self.assertEqual(0, result, self.output.getvalue())
|
self.assertEqual(0, result, self.output.getvalue())
|
||||||
output = self.output.getvalue()
|
output = self.output.getvalue()
|
||||||
self.assertIn('Successfully updated allocations for instance', output)
|
self.assertIn(
|
||||||
|
'Successfully updated allocations for', output)
|
||||||
self.assertIn('Processed 1 instances.', output)
|
self.assertIn('Processed 1 instances.', output)
|
||||||
# Now assert that the consumer was actually updated.
|
# Now assert that the consumer was actually updated.
|
||||||
allocations = self.placement_api.get(
|
allocations = self.placement_api.get(
|
||||||
|
@ -676,8 +677,9 @@ class TestNovaManagePlacementHealAllocations(
|
||||||
self.assertEqual(4, result, self.output.getvalue())
|
self.assertEqual(4, result, self.output.getvalue())
|
||||||
output = self.output.getvalue()
|
output = self.output.getvalue()
|
||||||
self.assertIn('Processed 0 instances.', output)
|
self.assertIn('Processed 0 instances.', output)
|
||||||
self.assertIn('[dry-run] Create allocations for instance %s on '
|
self.assertIn('[dry-run] Create allocations for instance '
|
||||||
'provider %s' % (server['id'], rp_uuid), output)
|
'%s' % server['id'], output)
|
||||||
|
self.assertIn(rp_uuid, output)
|
||||||
|
|
||||||
def test_heal_allocations_specific_instance(self):
|
def test_heal_allocations_specific_instance(self):
|
||||||
"""Tests the case that a specific instance is processed and only that
|
"""Tests the case that a specific instance is processed and only that
|
||||||
|
|
|
@ -2478,7 +2478,7 @@ class TestNovaManagePlacement(test.NoDBTestCase):
|
||||||
mock_get_compute_node, mock_get_allocs, mock_get_instances,
|
mock_get_compute_node, mock_get_allocs, mock_get_instances,
|
||||||
mock_get_all_cells):
|
mock_get_all_cells):
|
||||||
self.assertEqual(3, self.cli.heal_allocations())
|
self.assertEqual(3, self.cli.heal_allocations())
|
||||||
self.assertIn('Failed to create allocations for instance',
|
self.assertIn('Failed to update allocations for consumer',
|
||||||
self.output.getvalue())
|
self.output.getvalue())
|
||||||
instance = mock_get_instances.return_value[0]
|
instance = mock_get_instances.return_value[0]
|
||||||
mock_res_from_flavor.assert_called_once_with(
|
mock_res_from_flavor.assert_called_once_with(
|
||||||
|
|
Loading…
Reference in New Issue