Merge "[placement] Add sending global request ID in put (3)" into stable/queens
This commit is contained in:
commit
b2ae8fa2f5
|
@ -697,7 +697,7 @@ class ComputeManager(manager.Manager):
|
||||||
cn_uuid = compute_nodes[migration.source_node]
|
cn_uuid = compute_nodes[migration.source_node]
|
||||||
|
|
||||||
if not scheduler_utils.remove_allocation_from_compute(
|
if not scheduler_utils.remove_allocation_from_compute(
|
||||||
instance, cn_uuid, self.reportclient):
|
context, instance, cn_uuid, self.reportclient):
|
||||||
LOG.error("Failed to clean allocation of evacuated instance "
|
LOG.error("Failed to clean allocation of evacuated instance "
|
||||||
"on the source node %s",
|
"on the source node %s",
|
||||||
cn_uuid, instance=instance)
|
cn_uuid, instance=instance)
|
||||||
|
@ -2902,7 +2902,7 @@ class ComputeManager(manager.Manager):
|
||||||
# on the same host (not evacuate) uses the NopClaim which will
|
# on the same host (not evacuate) uses the NopClaim which will
|
||||||
# not raise ComputeResourcesUnavailable.
|
# not raise ComputeResourcesUnavailable.
|
||||||
rt.delete_allocation_for_evacuated_instance(
|
rt.delete_allocation_for_evacuated_instance(
|
||||||
instance, scheduled_node, node_type='destination')
|
context, instance, scheduled_node, node_type='destination')
|
||||||
self._notify_instance_rebuild_error(context, instance, e, bdms)
|
self._notify_instance_rebuild_error(context, instance, e, bdms)
|
||||||
raise exception.BuildAbortException(
|
raise exception.BuildAbortException(
|
||||||
instance_uuid=instance.uuid, reason=e.format_message())
|
instance_uuid=instance.uuid, reason=e.format_message())
|
||||||
|
@ -2916,7 +2916,8 @@ class ComputeManager(manager.Manager):
|
||||||
self._set_migration_status(migration, 'failed')
|
self._set_migration_status(migration, 'failed')
|
||||||
if recreate or scheduled_node is not None:
|
if recreate or scheduled_node is not None:
|
||||||
rt.delete_allocation_for_evacuated_instance(
|
rt.delete_allocation_for_evacuated_instance(
|
||||||
instance, scheduled_node, node_type='destination')
|
context, instance, scheduled_node,
|
||||||
|
node_type='destination')
|
||||||
self._notify_instance_rebuild_error(context, instance, e, bdms)
|
self._notify_instance_rebuild_error(context, instance, e, bdms)
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
|
@ -3832,7 +3833,7 @@ class ComputeManager(manager.Manager):
|
||||||
# any shared providers in the case of a confirm_resize operation and
|
# any shared providers in the case of a confirm_resize operation and
|
||||||
# the source host and shared providers for a revert_resize operation..
|
# the source host and shared providers for a revert_resize operation..
|
||||||
if not scheduler_utils.remove_allocation_from_compute(
|
if not scheduler_utils.remove_allocation_from_compute(
|
||||||
instance, cn_uuid, self.reportclient, flavor):
|
context, instance, cn_uuid, self.reportclient, flavor):
|
||||||
LOG.error("Failed to save manipulated allocation",
|
LOG.error("Failed to save manipulated allocation",
|
||||||
instance=instance)
|
instance=instance)
|
||||||
|
|
||||||
|
@ -6320,7 +6321,7 @@ class ComputeManager(manager.Manager):
|
||||||
# attempt to clean up any doubled per-instance allocation
|
# attempt to clean up any doubled per-instance allocation
|
||||||
rt = self._get_resource_tracker()
|
rt = self._get_resource_tracker()
|
||||||
rt.delete_allocation_for_migrated_instance(
|
rt.delete_allocation_for_migrated_instance(
|
||||||
instance, source_node)
|
ctxt, instance, source_node)
|
||||||
|
|
||||||
def _consoles_enabled(self):
|
def _consoles_enabled(self):
|
||||||
"""Returns whether a console is enable."""
|
"""Returns whether a console is enable."""
|
||||||
|
|
|
@ -894,7 +894,7 @@ class ResourceTracker(object):
|
||||||
# that the resource provider exists in the tree and has had its
|
# that the resource provider exists in the tree and has had its
|
||||||
# cached traits refreshed.
|
# cached traits refreshed.
|
||||||
self.reportclient.set_traits_for_provider(
|
self.reportclient.set_traits_for_provider(
|
||||||
compute_node.uuid, traits)
|
context, compute_node.uuid, traits)
|
||||||
|
|
||||||
if self.pci_tracker:
|
if self.pci_tracker:
|
||||||
self.pci_tracker.save(context)
|
self.pci_tracker.save(context)
|
||||||
|
@ -1316,27 +1316,30 @@ class ResourceTracker(object):
|
||||||
"host that might need to be removed: %s.",
|
"host that might need to be removed: %s.",
|
||||||
instance_uuid, instance.host, instance.node, alloc)
|
instance_uuid, instance.host, instance.node, alloc)
|
||||||
|
|
||||||
def delete_allocation_for_evacuated_instance(self, instance, node,
|
def delete_allocation_for_evacuated_instance(self, context, instance, node,
|
||||||
node_type='source'):
|
node_type='source'):
|
||||||
self._delete_allocation_for_moved_instance(
|
self._delete_allocation_for_moved_instance(
|
||||||
instance, node, 'evacuated', node_type)
|
context, instance, node, 'evacuated', node_type)
|
||||||
|
|
||||||
def delete_allocation_for_migrated_instance(self, instance, node):
|
def delete_allocation_for_migrated_instance(self, context, instance, node):
|
||||||
self._delete_allocation_for_moved_instance(instance, node, 'migrated')
|
self._delete_allocation_for_moved_instance(context, instance, node,
|
||||||
|
'migrated')
|
||||||
|
|
||||||
def _delete_allocation_for_moved_instance(
|
def _delete_allocation_for_moved_instance(
|
||||||
self, instance, node, move_type, node_type='source'):
|
self, context, instance, node, move_type, node_type='source'):
|
||||||
# Clean up the instance allocation from this node in placement
|
# Clean up the instance allocation from this node in placement
|
||||||
cn_uuid = self.compute_nodes[node].uuid
|
cn_uuid = self.compute_nodes[node].uuid
|
||||||
if not scheduler_utils.remove_allocation_from_compute(
|
if not scheduler_utils.remove_allocation_from_compute(
|
||||||
instance, cn_uuid, self.reportclient):
|
context, instance, cn_uuid, self.reportclient):
|
||||||
LOG.error("Failed to clean allocation of %s "
|
LOG.error("Failed to clean allocation of %s "
|
||||||
"instance on the %s node %s",
|
"instance on the %s node %s",
|
||||||
move_type, node_type, cn_uuid, instance=instance)
|
move_type, node_type, cn_uuid, instance=instance)
|
||||||
|
|
||||||
def delete_allocation_for_failed_resize(self, instance, node, flavor):
|
def delete_allocation_for_failed_resize(self, context, instance, node,
|
||||||
|
flavor):
|
||||||
"""Delete instance allocations for the node during a failed resize
|
"""Delete instance allocations for the node during a failed resize
|
||||||
|
|
||||||
|
:param context: The request context.
|
||||||
:param instance: The instance being resized/migrated.
|
:param instance: The instance being resized/migrated.
|
||||||
:param node: The node provider on which the instance should have
|
:param node: The node provider on which the instance should have
|
||||||
allocations to remove. If this is a resize to the same host, then
|
allocations to remove. If this is a resize to the same host, then
|
||||||
|
@ -1345,7 +1348,7 @@ class ResourceTracker(object):
|
||||||
"""
|
"""
|
||||||
cn = self.compute_nodes[node]
|
cn = self.compute_nodes[node]
|
||||||
if not scheduler_utils.remove_allocation_from_compute(
|
if not scheduler_utils.remove_allocation_from_compute(
|
||||||
instance, cn.uuid, self.reportclient, flavor):
|
context, instance, cn.uuid, self.reportclient, flavor):
|
||||||
if instance.instance_type_id == flavor.id:
|
if instance.instance_type_id == flavor.id:
|
||||||
operation = 'migration'
|
operation = 'migration'
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -376,8 +376,8 @@ class LiveMigrationTask(base.TaskBase):
|
||||||
# allocated for the given (destination) node.
|
# allocated for the given (destination) node.
|
||||||
self.scheduler_client.reportclient.\
|
self.scheduler_client.reportclient.\
|
||||||
remove_provider_from_instance_allocation(
|
remove_provider_from_instance_allocation(
|
||||||
self.instance.uuid, compute_node.uuid, self.instance.user_id,
|
self.context, self.instance.uuid, compute_node.uuid,
|
||||||
self.instance.project_id, resources)
|
self.instance.user_id, self.instance.project_id, resources)
|
||||||
|
|
||||||
def _check_not_over_max_retries(self, attempted_hosts):
|
def _check_not_over_max_retries(self, attempted_hosts):
|
||||||
if CONF.migrate_max_retries == -1:
|
if CONF.migrate_max_retries == -1:
|
||||||
|
|
|
@ -1090,9 +1090,10 @@ class SchedulerReportClient(object):
|
||||||
self._delete_inventory(context, rp_uuid)
|
self._delete_inventory(context, rp_uuid)
|
||||||
|
|
||||||
@safe_connect
|
@safe_connect
|
||||||
def _ensure_traits(self, traits):
|
def _ensure_traits(self, context, traits):
|
||||||
"""Make sure all specified traits exist in the placement service.
|
"""Make sure all specified traits exist in the placement service.
|
||||||
|
|
||||||
|
:param context: The security context
|
||||||
:param traits: Iterable of trait strings to ensure exist.
|
:param traits: Iterable of trait strings to ensure exist.
|
||||||
:raises: TraitCreationFailed if traits contains a trait that did not
|
:raises: TraitCreationFailed if traits contains a trait that did not
|
||||||
exist in placement, and couldn't be created. When this
|
exist in placement, and couldn't be created. When this
|
||||||
|
@ -1118,7 +1119,8 @@ class SchedulerReportClient(object):
|
||||||
# Might be neat to have a batch create. But creating multiple
|
# Might be neat to have a batch create. But creating multiple
|
||||||
# traits will generally happen once, at initial startup, if at all.
|
# traits will generally happen once, at initial startup, if at all.
|
||||||
for trait in traits_to_create:
|
for trait in traits_to_create:
|
||||||
resp = self.put('/traits/' + trait, None, version='1.6')
|
resp = self.put('/traits/' + trait, None, version='1.6',
|
||||||
|
global_request_id=context.global_id)
|
||||||
if not resp:
|
if not resp:
|
||||||
raise exception.TraitCreationFailed(name=trait,
|
raise exception.TraitCreationFailed(name=trait,
|
||||||
error=resp.text)
|
error=resp.text)
|
||||||
|
@ -1136,11 +1138,12 @@ class SchedulerReportClient(object):
|
||||||
raise exception.TraitRetrievalFailed(error=resp.text)
|
raise exception.TraitRetrievalFailed(error=resp.text)
|
||||||
|
|
||||||
@safe_connect
|
@safe_connect
|
||||||
def set_traits_for_provider(self, rp_uuid, traits):
|
def set_traits_for_provider(self, context, rp_uuid, traits):
|
||||||
"""Replace a provider's traits with those specified.
|
"""Replace a provider's traits with those specified.
|
||||||
|
|
||||||
The provider must exist - this method does not attempt to create it.
|
The provider must exist - this method does not attempt to create it.
|
||||||
|
|
||||||
|
:param context: The security context
|
||||||
:param rp_uuid: The UUID of the provider whose traits are to be updated
|
:param rp_uuid: The UUID of the provider whose traits are to be updated
|
||||||
:param traits: Iterable of traits to set on the provider
|
:param traits: Iterable of traits to set on the provider
|
||||||
:raises: ResourceProviderUpdateConflict if the provider's generation
|
:raises: ResourceProviderUpdateConflict if the provider's generation
|
||||||
|
@ -1158,7 +1161,7 @@ class SchedulerReportClient(object):
|
||||||
if not self._provider_tree.have_traits_changed(rp_uuid, traits):
|
if not self._provider_tree.have_traits_changed(rp_uuid, traits):
|
||||||
return
|
return
|
||||||
|
|
||||||
self._ensure_traits(traits)
|
self._ensure_traits(context, traits)
|
||||||
|
|
||||||
url = '/resource_providers/%s/traits' % rp_uuid
|
url = '/resource_providers/%s/traits' % rp_uuid
|
||||||
# NOTE(efried): Don't use the DELETE API when traits is empty, because
|
# NOTE(efried): Don't use the DELETE API when traits is empty, because
|
||||||
|
@ -1170,7 +1173,8 @@ class SchedulerReportClient(object):
|
||||||
'resource_provider_generation': generation,
|
'resource_provider_generation': generation,
|
||||||
'traits': traits,
|
'traits': traits,
|
||||||
}
|
}
|
||||||
resp = self.put(url, payload, version='1.6')
|
resp = self.put(url, payload, version='1.6',
|
||||||
|
global_request_id=context.global_id)
|
||||||
|
|
||||||
if resp.status_code == 200:
|
if resp.status_code == 200:
|
||||||
json = resp.json()
|
json = resp.json()
|
||||||
|
@ -1201,11 +1205,12 @@ class SchedulerReportClient(object):
|
||||||
raise exception.ResourceProviderUpdateFailed(url=url, error=resp.text)
|
raise exception.ResourceProviderUpdateFailed(url=url, error=resp.text)
|
||||||
|
|
||||||
@safe_connect
|
@safe_connect
|
||||||
def set_aggregates_for_provider(self, rp_uuid, aggregates):
|
def set_aggregates_for_provider(self, context, rp_uuid, aggregates):
|
||||||
"""Replace a provider's aggregates with those specified.
|
"""Replace a provider's aggregates with those specified.
|
||||||
|
|
||||||
The provider must exist - this method does not attempt to create it.
|
The provider must exist - this method does not attempt to create it.
|
||||||
|
|
||||||
|
:param context: The security context
|
||||||
:param rp_uuid: The UUID of the provider whose aggregates are to be
|
:param rp_uuid: The UUID of the provider whose aggregates are to be
|
||||||
updated.
|
updated.
|
||||||
:param aggregates: Iterable of aggregates to set on the provider.
|
:param aggregates: Iterable of aggregates to set on the provider.
|
||||||
|
@ -1214,7 +1219,8 @@ class SchedulerReportClient(object):
|
||||||
# TODO(efried): Handle generation conflicts when supported by placement
|
# TODO(efried): Handle generation conflicts when supported by placement
|
||||||
url = '/resource_providers/%s/aggregates' % rp_uuid
|
url = '/resource_providers/%s/aggregates' % rp_uuid
|
||||||
aggregates = list(aggregates) if aggregates else []
|
aggregates = list(aggregates) if aggregates else []
|
||||||
resp = self.put(url, aggregates, version='1.1')
|
resp = self.put(url, aggregates, version='1.1',
|
||||||
|
global_request_id=context.global_id)
|
||||||
|
|
||||||
if resp.status_code == 200:
|
if resp.status_code == 200:
|
||||||
placement_aggs = resp.json()['aggregates']
|
placement_aggs = resp.json()['aggregates']
|
||||||
|
@ -1376,7 +1382,7 @@ class SchedulerReportClient(object):
|
||||||
return allocations.get(
|
return allocations.get(
|
||||||
rp_uuid, {}).get('resources', {})
|
rp_uuid, {}).get('resources', {})
|
||||||
|
|
||||||
def _allocate_for_instance(self, rp_uuid, instance):
|
def _allocate_for_instance(self, context, rp_uuid, instance):
|
||||||
my_allocations = _instance_to_allocations_dict(instance)
|
my_allocations = _instance_to_allocations_dict(instance)
|
||||||
current_allocations = self.get_allocations_for_consumer_by_provider(
|
current_allocations = self.get_allocations_for_consumer_by_provider(
|
||||||
rp_uuid, instance.uuid)
|
rp_uuid, instance.uuid)
|
||||||
|
@ -1390,8 +1396,9 @@ class SchedulerReportClient(object):
|
||||||
LOG.debug('Sending allocation for instance %s',
|
LOG.debug('Sending allocation for instance %s',
|
||||||
my_allocations,
|
my_allocations,
|
||||||
instance=instance)
|
instance=instance)
|
||||||
res = self.put_allocations(rp_uuid, instance.uuid, my_allocations,
|
res = self.put_allocations(context, rp_uuid, instance.uuid,
|
||||||
instance.project_id, instance.user_id)
|
my_allocations, instance.project_id,
|
||||||
|
instance.user_id)
|
||||||
if res:
|
if res:
|
||||||
LOG.info('Submitted allocation for instance', instance=instance)
|
LOG.info('Submitted allocation for instance', instance=instance)
|
||||||
|
|
||||||
|
@ -1491,8 +1498,8 @@ class SchedulerReportClient(object):
|
||||||
return r.status_code == 204
|
return r.status_code == 204
|
||||||
|
|
||||||
@safe_connect
|
@safe_connect
|
||||||
def remove_provider_from_instance_allocation(self, consumer_uuid, rp_uuid,
|
def remove_provider_from_instance_allocation(self, context, consumer_uuid,
|
||||||
user_id, project_id,
|
rp_uuid, user_id, project_id,
|
||||||
resources):
|
resources):
|
||||||
"""Grabs an allocation for a particular consumer UUID, strips parts of
|
"""Grabs an allocation for a particular consumer UUID, strips parts of
|
||||||
the allocation that refer to a supplied resource provider UUID, and
|
the allocation that refer to a supplied resource provider UUID, and
|
||||||
|
@ -1508,6 +1515,7 @@ class SchedulerReportClient(object):
|
||||||
subtract resources from the single allocation to ensure we do not
|
subtract resources from the single allocation to ensure we do not
|
||||||
exceed the reserved or max_unit amounts for the resource on the host.
|
exceed the reserved or max_unit amounts for the resource on the host.
|
||||||
|
|
||||||
|
:param context: The security context
|
||||||
:param consumer_uuid: The instance/consumer UUID
|
:param consumer_uuid: The instance/consumer UUID
|
||||||
:param rp_uuid: The UUID of the provider whose resources we wish to
|
:param rp_uuid: The UUID of the provider whose resources we wish to
|
||||||
remove from the consumer's allocation
|
remove from the consumer's allocation
|
||||||
|
@ -1580,7 +1588,8 @@ class SchedulerReportClient(object):
|
||||||
LOG.debug("Sending updated allocation %s for instance %s after "
|
LOG.debug("Sending updated allocation %s for instance %s after "
|
||||||
"removing resources for %s.",
|
"removing resources for %s.",
|
||||||
new_allocs, consumer_uuid, rp_uuid)
|
new_allocs, consumer_uuid, rp_uuid)
|
||||||
r = self.put(url, payload, version='1.10')
|
r = self.put(url, payload, version='1.10',
|
||||||
|
global_request_id=context.global_id)
|
||||||
if r.status_code != 204:
|
if r.status_code != 204:
|
||||||
LOG.warning("Failed to save allocation for %s. Got HTTP %s: %s",
|
LOG.warning("Failed to save allocation for %s. Got HTTP %s: %s",
|
||||||
consumer_uuid, r.status_code, r.text)
|
consumer_uuid, r.status_code, r.text)
|
||||||
|
@ -1656,8 +1665,8 @@ class SchedulerReportClient(object):
|
||||||
|
|
||||||
@safe_connect
|
@safe_connect
|
||||||
@retries
|
@retries
|
||||||
def put_allocations(self, rp_uuid, consumer_uuid, alloc_data, project_id,
|
def put_allocations(self, context, rp_uuid, consumer_uuid, alloc_data,
|
||||||
user_id):
|
project_id, user_id):
|
||||||
"""Creates allocation records for the supplied instance UUID against
|
"""Creates allocation records for the supplied instance UUID against
|
||||||
the supplied resource provider.
|
the supplied resource provider.
|
||||||
|
|
||||||
|
@ -1665,6 +1674,7 @@ class SchedulerReportClient(object):
|
||||||
Once shared storage and things like NUMA allocations are a
|
Once shared storage and things like NUMA allocations are a
|
||||||
reality, this will change to allocate against multiple providers.
|
reality, this will change to allocate against multiple providers.
|
||||||
|
|
||||||
|
:param context: The security context
|
||||||
:param rp_uuid: The UUID of the resource provider to allocate against.
|
:param rp_uuid: The UUID of the resource provider to allocate against.
|
||||||
:param consumer_uuid: The instance's UUID.
|
:param consumer_uuid: The instance's UUID.
|
||||||
:param alloc_data: Dict, keyed by resource class, of amounts to
|
:param alloc_data: Dict, keyed by resource class, of amounts to
|
||||||
|
@ -1688,7 +1698,8 @@ class SchedulerReportClient(object):
|
||||||
'user_id': user_id,
|
'user_id': user_id,
|
||||||
}
|
}
|
||||||
url = '/allocations/%s' % consumer_uuid
|
url = '/allocations/%s' % consumer_uuid
|
||||||
r = self.put(url, payload, version='1.8')
|
r = self.put(url, payload, version='1.8',
|
||||||
|
global_request_id=context.global_id)
|
||||||
if r.status_code == 406:
|
if r.status_code == 406:
|
||||||
# microversion 1.8 not available so try the earlier way
|
# microversion 1.8 not available so try the earlier way
|
||||||
# TODO(melwitt): Remove this when we can be sure all placement
|
# TODO(melwitt): Remove this when we can be sure all placement
|
||||||
|
@ -1734,7 +1745,7 @@ class SchedulerReportClient(object):
|
||||||
def update_instance_allocation(self, context, compute_node, instance,
|
def update_instance_allocation(self, context, compute_node, instance,
|
||||||
sign):
|
sign):
|
||||||
if sign > 0:
|
if sign > 0:
|
||||||
self._allocate_for_instance(compute_node.uuid, instance)
|
self._allocate_for_instance(context, compute_node.uuid, instance)
|
||||||
else:
|
else:
|
||||||
self.delete_allocation_for_instance(context, instance.uuid)
|
self.delete_allocation_for_instance(context, instance.uuid)
|
||||||
|
|
||||||
|
|
|
@ -797,10 +797,11 @@ def claim_resources(ctx, client, spec_obj, instance_uuid, alloc_req,
|
||||||
user_id, allocation_request_version=allocation_request_version)
|
user_id, allocation_request_version=allocation_request_version)
|
||||||
|
|
||||||
|
|
||||||
def remove_allocation_from_compute(instance, compute_node_uuid, reportclient,
|
def remove_allocation_from_compute(context, instance, compute_node_uuid,
|
||||||
flavor=None):
|
reportclient, flavor=None):
|
||||||
"""Removes the instance allocation from the compute host.
|
"""Removes the instance allocation from the compute host.
|
||||||
|
|
||||||
|
:param context: The request context
|
||||||
:param instance: the instance object owning the allocation
|
:param instance: the instance object owning the allocation
|
||||||
:param compute_node_uuid: the UUID of the compute node where the allocation
|
:param compute_node_uuid: the UUID of the compute node where the allocation
|
||||||
needs to be removed
|
needs to be removed
|
||||||
|
@ -817,5 +818,5 @@ def remove_allocation_from_compute(instance, compute_node_uuid, reportclient,
|
||||||
|
|
||||||
my_resources = resources_from_flavor(instance, flavor)
|
my_resources = resources_from_flavor(instance, flavor)
|
||||||
return reportclient.remove_provider_from_instance_allocation(
|
return reportclient.remove_provider_from_instance_allocation(
|
||||||
instance.uuid, compute_node_uuid, instance.user_id,
|
context, instance.uuid, compute_node_uuid, instance.user_id,
|
||||||
instance.project_id, my_resources)
|
instance.project_id, my_resources)
|
||||||
|
|
|
@ -331,7 +331,8 @@ class SchedulerReportClientTests(test.TestCase):
|
||||||
self.client.update_compute_node(self.context, self.compute_node)
|
self.client.update_compute_node(self.context, self.compute_node)
|
||||||
# The compute node is associated with two of the shared storages
|
# The compute node is associated with two of the shared storages
|
||||||
self.client.set_aggregates_for_provider(
|
self.client.set_aggregates_for_provider(
|
||||||
self.compute_uuid, set([uuids.agg_disk_1, uuids.agg_disk_2]))
|
self.context, self.compute_uuid,
|
||||||
|
set([uuids.agg_disk_1, uuids.agg_disk_2]))
|
||||||
|
|
||||||
# Register two SR-IOV PFs with VF and bandwidth inventory
|
# Register two SR-IOV PFs with VF and bandwidth inventory
|
||||||
for x in (1, 2):
|
for x in (1, 2):
|
||||||
|
@ -357,10 +358,11 @@ class SchedulerReportClientTests(test.TestCase):
|
||||||
},
|
},
|
||||||
}, parent_provider_uuid=self.compute_uuid)
|
}, parent_provider_uuid=self.compute_uuid)
|
||||||
# They're associated with an IP address aggregate
|
# They're associated with an IP address aggregate
|
||||||
self.client.set_aggregates_for_provider(uuid, [uuids.agg_ip])
|
self.client.set_aggregates_for_provider(self.context, uuid,
|
||||||
|
[uuids.agg_ip])
|
||||||
# Set some traits on 'em
|
# Set some traits on 'em
|
||||||
self.client.set_traits_for_provider(
|
self.client.set_traits_for_provider(
|
||||||
uuid, ['CUSTOM_PHYSNET_%d' % x])
|
self.context, uuid, ['CUSTOM_PHYSNET_%d' % x])
|
||||||
|
|
||||||
# Register three shared storage pools with disk inventory
|
# Register three shared storage pools with disk inventory
|
||||||
for x in (1, 2, 3):
|
for x in (1, 2, 3):
|
||||||
|
@ -379,11 +381,12 @@ class SchedulerReportClientTests(test.TestCase):
|
||||||
})
|
})
|
||||||
# Mark as a sharing provider
|
# Mark as a sharing provider
|
||||||
self.client.set_traits_for_provider(
|
self.client.set_traits_for_provider(
|
||||||
uuid, ['MISC_SHARES_VIA_AGGREGATE'])
|
self.context, uuid, ['MISC_SHARES_VIA_AGGREGATE'])
|
||||||
# Associate each with its own aggregate. The compute node is
|
# Associate each with its own aggregate. The compute node is
|
||||||
# associated with the first two (agg_disk_1 and agg_disk_2).
|
# associated with the first two (agg_disk_1 and agg_disk_2).
|
||||||
agg = getattr(uuids, 'agg_disk_%d' % x)
|
agg = getattr(uuids, 'agg_disk_%d' % x)
|
||||||
self.client.set_aggregates_for_provider(uuid, [agg])
|
self.client.set_aggregates_for_provider(self.context, uuid,
|
||||||
|
[agg])
|
||||||
|
|
||||||
# Register a shared IP address provider with IP address inventory
|
# Register a shared IP address provider with IP address inventory
|
||||||
self.client.set_inventory_for_provider(
|
self.client.set_inventory_for_provider(
|
||||||
|
@ -399,9 +402,11 @@ class SchedulerReportClientTests(test.TestCase):
|
||||||
})
|
})
|
||||||
# Mark as a sharing provider, and add another trait
|
# Mark as a sharing provider, and add another trait
|
||||||
self.client.set_traits_for_provider(
|
self.client.set_traits_for_provider(
|
||||||
uuids.sip, set(['MISC_SHARES_VIA_AGGREGATE', 'CUSTOM_FOO']))
|
self.context, uuids.sip,
|
||||||
|
set(['MISC_SHARES_VIA_AGGREGATE', 'CUSTOM_FOO']))
|
||||||
# It's associated with the same aggregate as both PFs
|
# It's associated with the same aggregate as both PFs
|
||||||
self.client.set_aggregates_for_provider(uuids.sip, [uuids.agg_ip])
|
self.client.set_aggregates_for_provider(self.context, uuids.sip,
|
||||||
|
[uuids.agg_ip])
|
||||||
|
|
||||||
# Register a shared network bandwidth provider
|
# Register a shared network bandwidth provider
|
||||||
self.client.set_inventory_for_provider(
|
self.client.set_inventory_for_provider(
|
||||||
|
@ -417,9 +422,10 @@ class SchedulerReportClientTests(test.TestCase):
|
||||||
})
|
})
|
||||||
# Mark as a sharing provider
|
# Mark as a sharing provider
|
||||||
self.client.set_traits_for_provider(
|
self.client.set_traits_for_provider(
|
||||||
uuids.sbw, ['MISC_SHARES_VIA_AGGREGATE'])
|
self.context, uuids.sbw, ['MISC_SHARES_VIA_AGGREGATE'])
|
||||||
# It's associated with some other aggregate.
|
# It's associated with some other aggregate.
|
||||||
self.client.set_aggregates_for_provider(uuids.sbw, [uuids.agg_bw])
|
self.client.set_aggregates_for_provider(self.context, uuids.sbw,
|
||||||
|
[uuids.agg_bw])
|
||||||
|
|
||||||
# Setup is done. Grab the ProviderTree
|
# Setup is done. Grab the ProviderTree
|
||||||
prov_tree = self.client.get_provider_tree_and_ensure_root(
|
prov_tree = self.client.get_provider_tree_and_ensure_root(
|
||||||
|
|
|
@ -725,7 +725,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
|
||||||
self.compute.init_host()
|
self.compute.init_host()
|
||||||
|
|
||||||
mock_remove_allocation.assert_called_once_with(
|
mock_remove_allocation.assert_called_once_with(
|
||||||
deleted_instance.uuid, uuids.our_node_uuid,
|
self.context, deleted_instance.uuid, uuids.our_node_uuid,
|
||||||
deleted_instance.user_id, deleted_instance.project_id,
|
deleted_instance.user_id, deleted_instance.project_id,
|
||||||
mock.sentinel.my_resources)
|
mock.sentinel.my_resources)
|
||||||
|
|
||||||
|
@ -3595,8 +3595,8 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
|
||||||
get_node.assert_called_once_with(
|
get_node.assert_called_once_with(
|
||||||
self.context, our_host, migration.source_node)
|
self.context, our_host, migration.source_node)
|
||||||
remove_allocation.assert_called_once_with(
|
remove_allocation.assert_called_once_with(
|
||||||
instance_2.uuid, uuids.our_node_uuid, uuids.user_id,
|
self.context, instance_2.uuid, uuids.our_node_uuid,
|
||||||
uuids.project_id, mock.sentinel.resources)
|
uuids.user_id, uuids.project_id, mock.sentinel.resources)
|
||||||
|
|
||||||
def test_destroy_evacuated_instances_node_deleted(self):
|
def test_destroy_evacuated_instances_node_deleted(self):
|
||||||
our_host = self.compute.host
|
our_host = self.compute.host
|
||||||
|
@ -3672,8 +3672,8 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
|
||||||
# but only instance_2 is deallocated as the compute node for
|
# but only instance_2 is deallocated as the compute node for
|
||||||
# instance_1 is already deleted
|
# instance_1 is already deleted
|
||||||
remove_allocation.assert_called_once_with(
|
remove_allocation.assert_called_once_with(
|
||||||
instance_2.uuid, uuids.our_node_uuid, uuids.user_id,
|
self.context, instance_2.uuid, uuids.our_node_uuid,
|
||||||
uuids.project_id, mock.sentinel.resources)
|
uuids.user_id, uuids.project_id, mock.sentinel.resources)
|
||||||
|
|
||||||
self.assertEqual(2, get_node.call_count)
|
self.assertEqual(2, get_node.call_count)
|
||||||
|
|
||||||
|
@ -3923,10 +3923,13 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
rt.delete_allocation_for_evacuated_instance.called)
|
rt.delete_allocation_for_evacuated_instance.called)
|
||||||
|
|
||||||
|
@mock.patch('nova.context.RequestContext.elevated')
|
||||||
@mock.patch('nova.compute.utils.add_instance_fault_from_exc')
|
@mock.patch('nova.compute.utils.add_instance_fault_from_exc')
|
||||||
@mock.patch.object(manager.ComputeManager,
|
@mock.patch.object(manager.ComputeManager,
|
||||||
'_error_out_instance_on_exception')
|
'_error_out_instance_on_exception')
|
||||||
def test_rebuild_driver_error_evacuate(self, mock_error, mock_aiffe):
|
def test_rebuild_driver_error_evacuate(self, mock_error, mock_aiffe,
|
||||||
|
mock_elevated):
|
||||||
|
mock_elevated.return_value = self.context
|
||||||
instance = fake_instance.fake_instance_obj(self.context)
|
instance = fake_instance.fake_instance_obj(self.context)
|
||||||
ex = test.TestingException('foo')
|
ex = test.TestingException('foo')
|
||||||
with mock.patch.object(self.compute, '_get_resource_tracker') as mrt:
|
with mock.patch.object(self.compute, '_get_resource_tracker') as mrt:
|
||||||
|
@ -3935,7 +3938,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
|
||||||
recreate=True, scheduled_node='foo')
|
recreate=True, scheduled_node='foo')
|
||||||
rt = mrt.return_value
|
rt = mrt.return_value
|
||||||
delete_alloc = rt.delete_allocation_for_evacuated_instance
|
delete_alloc = rt.delete_allocation_for_evacuated_instance
|
||||||
delete_alloc.assert_called_once_with(instance, 'foo',
|
delete_alloc.assert_called_once_with(self.context, instance, 'foo',
|
||||||
node_type='destination')
|
node_type='destination')
|
||||||
|
|
||||||
@mock.patch('nova.context.RequestContext.elevated')
|
@mock.patch('nova.context.RequestContext.elevated')
|
||||||
|
@ -4018,7 +4021,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
|
||||||
mock_validate_policy.assert_called_once_with(
|
mock_validate_policy.assert_called_once_with(
|
||||||
elevated_context, instance, {'group': [uuids.group]})
|
elevated_context, instance, {'group': [uuids.group]})
|
||||||
mock_delete_allocation.assert_called_once_with(
|
mock_delete_allocation.assert_called_once_with(
|
||||||
instance, 'fake-node', node_type='destination')
|
elevated_context, instance, 'fake-node', node_type='destination')
|
||||||
mock_notify.assert_called_once_with(
|
mock_notify.assert_called_once_with(
|
||||||
elevated_context, instance, 'fake-mini', action='rebuild',
|
elevated_context, instance, 'fake-mini', action='rebuild',
|
||||||
bdms=None, exception=exc, phase='error')
|
bdms=None, exception=exc, phase='error')
|
||||||
|
@ -6394,7 +6397,7 @@ class ComputeManagerMigrationTestCase(test.NoDBTestCase):
|
||||||
rt.get_node_uuid.assert_called_once_with(mock.sentinel.node)
|
rt.get_node_uuid.assert_called_once_with(mock.sentinel.node)
|
||||||
remove = mock_rc.remove_provider_from_instance_allocation
|
remove = mock_rc.remove_provider_from_instance_allocation
|
||||||
remove.assert_called_once_with(
|
remove.assert_called_once_with(
|
||||||
instance.uuid, rt.get_node_uuid.return_value,
|
self.context, instance.uuid, rt.get_node_uuid.return_value,
|
||||||
instance.user_id, instance.project_id,
|
instance.user_id, instance.project_id,
|
||||||
mock_resources.return_value)
|
mock_resources.return_value)
|
||||||
do_it()
|
do_it()
|
||||||
|
@ -7023,7 +7026,8 @@ class ComputeManagerMigrationTestCase(test.NoDBTestCase):
|
||||||
# ...so we should have called the old style delete
|
# ...so we should have called the old style delete
|
||||||
mock_delete.assert_not_called()
|
mock_delete.assert_not_called()
|
||||||
fn = mock_rt.return_value.delete_allocation_for_migrated_instance
|
fn = mock_rt.return_value.delete_allocation_for_migrated_instance
|
||||||
fn.assert_called_once_with(self.instance, self.instance.node)
|
fn.assert_called_once_with(self.context, self.instance,
|
||||||
|
self.instance.node)
|
||||||
|
|
||||||
def test_post_live_migration_legacy(self):
|
def test_post_live_migration_legacy(self):
|
||||||
# We have no migrate_data...
|
# We have no migrate_data...
|
||||||
|
@ -7045,7 +7049,8 @@ class ComputeManagerMigrationTestCase(test.NoDBTestCase):
|
||||||
# ...so we should have called the old style delete
|
# ...so we should have called the old style delete
|
||||||
mock_delete.assert_not_called()
|
mock_delete.assert_not_called()
|
||||||
fn = mock_rt.return_value.delete_allocation_for_migrated_instance
|
fn = mock_rt.return_value.delete_allocation_for_migrated_instance
|
||||||
fn.assert_called_once_with(self.instance, self.instance.node)
|
fn.assert_called_once_with(self.context, self.instance,
|
||||||
|
self.instance.node)
|
||||||
|
|
||||||
def test_post_live_migration_cinder_v3_api(self):
|
def test_post_live_migration_cinder_v3_api(self):
|
||||||
# Because live migration has succeeded, _post_live_migration
|
# Because live migration has succeeded, _post_live_migration
|
||||||
|
|
|
@ -1315,6 +1315,7 @@ class TestUpdateComputeNode(BaseTestCase):
|
||||||
|
|
||||||
self.rt._update(mock.sentinel.ctx, new_compute)
|
self.rt._update(mock.sentinel.ctx, new_compute)
|
||||||
rc.set_traits_for_provider.assert_called_once_with(
|
rc.set_traits_for_provider.assert_called_once_with(
|
||||||
|
mock.sentinel.ctx,
|
||||||
new_compute.uuid,
|
new_compute.uuid,
|
||||||
mock.sentinel.traits,
|
mock.sentinel.traits,
|
||||||
)
|
)
|
||||||
|
@ -2842,13 +2843,15 @@ class TestUpdateUsageFromInstance(BaseTestCase):
|
||||||
mock_resource_from_flavor.return_value = mock_resource
|
mock_resource_from_flavor.return_value = mock_resource
|
||||||
instance = _INSTANCE_FIXTURES[0].obj_clone()
|
instance = _INSTANCE_FIXTURES[0].obj_clone()
|
||||||
instance.uuid = uuids.inst0
|
instance.uuid = uuids.inst0
|
||||||
|
ctxt = context.get_admin_context()
|
||||||
|
|
||||||
self.rt.delete_allocation_for_evacuated_instance(instance, _NODENAME)
|
self.rt.delete_allocation_for_evacuated_instance(
|
||||||
|
ctxt, instance, _NODENAME)
|
||||||
|
|
||||||
rc = self.rt.reportclient
|
rc = self.rt.reportclient
|
||||||
mock_remove_allocation = rc.remove_provider_from_instance_allocation
|
mock_remove_allocation = rc.remove_provider_from_instance_allocation
|
||||||
mock_remove_allocation.assert_called_once_with(
|
mock_remove_allocation.assert_called_once_with(
|
||||||
instance.uuid, self.rt.compute_nodes[_NODENAME].uuid,
|
ctxt, instance.uuid, self.rt.compute_nodes[_NODENAME].uuid,
|
||||||
instance.user_id, instance.project_id, mock_resource)
|
instance.user_id, instance.project_id, mock_resource)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -266,11 +266,14 @@ class TestPutAllocations(SchedulerReportClientTestCase):
|
||||||
consumer_uuid = mock.sentinel.consumer
|
consumer_uuid = mock.sentinel.consumer
|
||||||
data = {"MEMORY_MB": 1024}
|
data = {"MEMORY_MB": 1024}
|
||||||
expected_url = "/allocations/%s" % consumer_uuid
|
expected_url = "/allocations/%s" % consumer_uuid
|
||||||
resp = self.client.put_allocations(rp_uuid, consumer_uuid, data,
|
resp = self.client.put_allocations(self.context, rp_uuid,
|
||||||
|
consumer_uuid, data,
|
||||||
mock.sentinel.project_id,
|
mock.sentinel.project_id,
|
||||||
mock.sentinel.user_id)
|
mock.sentinel.user_id)
|
||||||
self.assertTrue(resp)
|
self.assertTrue(resp)
|
||||||
mock_put.assert_called_once_with(expected_url, mock.ANY, version='1.8')
|
mock_put.assert_called_once_with(
|
||||||
|
expected_url, mock.ANY, version='1.8',
|
||||||
|
global_request_id=self.context.global_id)
|
||||||
|
|
||||||
@mock.patch('nova.scheduler.client.report.SchedulerReportClient.put')
|
@mock.patch('nova.scheduler.client.report.SchedulerReportClient.put')
|
||||||
def test_put_allocations_fail_fallback_succeeds(self, mock_put):
|
def test_put_allocations_fail_fallback_succeeds(self, mock_put):
|
||||||
|
@ -285,12 +288,14 @@ class TestPutAllocations(SchedulerReportClientTestCase):
|
||||||
consumer_uuid = mock.sentinel.consumer
|
consumer_uuid = mock.sentinel.consumer
|
||||||
data = {"MEMORY_MB": 1024}
|
data = {"MEMORY_MB": 1024}
|
||||||
expected_url = "/allocations/%s" % consumer_uuid
|
expected_url = "/allocations/%s" % consumer_uuid
|
||||||
resp = self.client.put_allocations(rp_uuid, consumer_uuid, data,
|
resp = self.client.put_allocations(self.context, rp_uuid,
|
||||||
|
consumer_uuid, data,
|
||||||
mock.sentinel.project_id,
|
mock.sentinel.project_id,
|
||||||
mock.sentinel.user_id)
|
mock.sentinel.user_id)
|
||||||
self.assertTrue(resp)
|
self.assertTrue(resp)
|
||||||
# Should fall back to earlier way if 1.8 fails.
|
# Should fall back to earlier way if 1.8 fails.
|
||||||
call1 = mock.call(expected_url, mock.ANY, version='1.8')
|
call1 = mock.call(expected_url, mock.ANY, version='1.8',
|
||||||
|
global_request_id=self.context.global_id)
|
||||||
call2 = mock.call(expected_url, mock.ANY)
|
call2 = mock.call(expected_url, mock.ANY)
|
||||||
self.assertEqual(2, mock_put.call_count)
|
self.assertEqual(2, mock_put.call_count)
|
||||||
mock_put.assert_has_calls([call1, call2])
|
mock_put.assert_has_calls([call1, call2])
|
||||||
|
@ -304,11 +309,14 @@ class TestPutAllocations(SchedulerReportClientTestCase):
|
||||||
consumer_uuid = mock.sentinel.consumer
|
consumer_uuid = mock.sentinel.consumer
|
||||||
data = {"MEMORY_MB": 1024}
|
data = {"MEMORY_MB": 1024}
|
||||||
expected_url = "/allocations/%s" % consumer_uuid
|
expected_url = "/allocations/%s" % consumer_uuid
|
||||||
resp = self.client.put_allocations(rp_uuid, consumer_uuid, data,
|
resp = self.client.put_allocations(self.context, rp_uuid,
|
||||||
|
consumer_uuid, data,
|
||||||
mock.sentinel.project_id,
|
mock.sentinel.project_id,
|
||||||
mock.sentinel.user_id)
|
mock.sentinel.user_id)
|
||||||
self.assertFalse(resp)
|
self.assertFalse(resp)
|
||||||
mock_put.assert_called_once_with(expected_url, mock.ANY, version='1.8')
|
mock_put.assert_called_once_with(
|
||||||
|
expected_url, mock.ANY, version='1.8',
|
||||||
|
global_request_id=self.context.global_id)
|
||||||
log_msg = mock_warn.call_args[0][0]
|
log_msg = mock_warn.call_args[0][0]
|
||||||
self.assertIn("Unable to submit allocation for instance", log_msg)
|
self.assertIn("Unable to submit allocation for instance", log_msg)
|
||||||
|
|
||||||
|
@ -328,13 +336,14 @@ class TestPutAllocations(SchedulerReportClientTestCase):
|
||||||
consumer_uuid = mock.sentinel.consumer
|
consumer_uuid = mock.sentinel.consumer
|
||||||
data = {"MEMORY_MB": 1024}
|
data = {"MEMORY_MB": 1024}
|
||||||
expected_url = "/allocations/%s" % consumer_uuid
|
expected_url = "/allocations/%s" % consumer_uuid
|
||||||
resp = self.client.put_allocations(rp_uuid, consumer_uuid, data,
|
resp = self.client.put_allocations(self.context, rp_uuid,
|
||||||
|
consumer_uuid, data,
|
||||||
mock.sentinel.project_id,
|
mock.sentinel.project_id,
|
||||||
mock.sentinel.user_id)
|
mock.sentinel.user_id)
|
||||||
self.assertTrue(resp)
|
self.assertTrue(resp)
|
||||||
mock_put.assert_has_calls([
|
mock_put.assert_has_calls([
|
||||||
mock.call(expected_url, mock.ANY, version='1.8'),
|
mock.call(expected_url, mock.ANY, version='1.8',
|
||||||
mock.call(expected_url, mock.ANY, version='1.8')])
|
global_request_id=self.context.global_id)] * 2)
|
||||||
|
|
||||||
@mock.patch('nova.scheduler.client.report.SchedulerReportClient.put')
|
@mock.patch('nova.scheduler.client.report.SchedulerReportClient.put')
|
||||||
def test_put_allocations_retry_gives_up(self, mock_put):
|
def test_put_allocations_retry_gives_up(self, mock_put):
|
||||||
|
@ -349,14 +358,14 @@ class TestPutAllocations(SchedulerReportClientTestCase):
|
||||||
consumer_uuid = mock.sentinel.consumer
|
consumer_uuid = mock.sentinel.consumer
|
||||||
data = {"MEMORY_MB": 1024}
|
data = {"MEMORY_MB": 1024}
|
||||||
expected_url = "/allocations/%s" % consumer_uuid
|
expected_url = "/allocations/%s" % consumer_uuid
|
||||||
resp = self.client.put_allocations(rp_uuid, consumer_uuid, data,
|
resp = self.client.put_allocations(self.context, rp_uuid,
|
||||||
|
consumer_uuid, data,
|
||||||
mock.sentinel.project_id,
|
mock.sentinel.project_id,
|
||||||
mock.sentinel.user_id)
|
mock.sentinel.user_id)
|
||||||
self.assertFalse(resp)
|
self.assertFalse(resp)
|
||||||
mock_put.assert_has_calls([
|
mock_put.assert_has_calls([
|
||||||
mock.call(expected_url, mock.ANY, version='1.8'),
|
mock.call(expected_url, mock.ANY, version='1.8',
|
||||||
mock.call(expected_url, mock.ANY, version='1.8'),
|
global_request_id=self.context.global_id)] * 3)
|
||||||
mock.call(expected_url, mock.ANY, version='1.8')])
|
|
||||||
|
|
||||||
def test_claim_resources_success_with_old_version(self):
|
def test_claim_resources_success_with_old_version(self):
|
||||||
get_resp_mock = mock.Mock(status_code=200)
|
get_resp_mock = mock.Mock(status_code=200)
|
||||||
|
@ -898,7 +907,8 @@ class TestPutAllocations(SchedulerReportClientTestCase):
|
||||||
project_id = uuids.project_id
|
project_id = uuids.project_id
|
||||||
user_id = uuids.user_id
|
user_id = uuids.user_id
|
||||||
res = self.client.remove_provider_from_instance_allocation(
|
res = self.client.remove_provider_from_instance_allocation(
|
||||||
consumer_uuid, uuids.source, user_id, project_id, mock.Mock())
|
self.context, consumer_uuid, uuids.source, user_id, project_id,
|
||||||
|
mock.Mock())
|
||||||
|
|
||||||
expected_url = "/allocations/%s" % consumer_uuid
|
expected_url = "/allocations/%s" % consumer_uuid
|
||||||
# New allocations should only include the destination...
|
# New allocations should only include the destination...
|
||||||
|
@ -928,7 +938,7 @@ class TestPutAllocations(SchedulerReportClientTestCase):
|
||||||
self.assertEqual(expected_allocations, actual_allocations)
|
self.assertEqual(expected_allocations, actual_allocations)
|
||||||
self.ks_adap_mock.put.assert_called_once_with(
|
self.ks_adap_mock.put.assert_called_once_with(
|
||||||
expected_url, microversion='1.10', json=mock.ANY, raise_exc=False,
|
expected_url, microversion='1.10', json=mock.ANY, raise_exc=False,
|
||||||
headers={})
|
headers={'X-Openstack-Request-Id': self.context.global_id})
|
||||||
|
|
||||||
self.assertTrue(res)
|
self.assertTrue(res)
|
||||||
|
|
||||||
|
@ -971,7 +981,8 @@ class TestPutAllocations(SchedulerReportClientTestCase):
|
||||||
project_id = uuids.project_id
|
project_id = uuids.project_id
|
||||||
user_id = uuids.user_id
|
user_id = uuids.user_id
|
||||||
res = self.client.remove_provider_from_instance_allocation(
|
res = self.client.remove_provider_from_instance_allocation(
|
||||||
consumer_uuid, uuids.source, user_id, project_id, mock.Mock())
|
self.context, consumer_uuid, uuids.source, user_id, project_id,
|
||||||
|
mock.Mock())
|
||||||
|
|
||||||
expected_url = "/allocations/%s" % consumer_uuid
|
expected_url = "/allocations/%s" % consumer_uuid
|
||||||
# New allocations should only include the destination...
|
# New allocations should only include the destination...
|
||||||
|
@ -1009,7 +1020,7 @@ class TestPutAllocations(SchedulerReportClientTestCase):
|
||||||
self.assertEqual(expected_allocations, actual_allocations)
|
self.assertEqual(expected_allocations, actual_allocations)
|
||||||
self.ks_adap_mock.put.assert_called_once_with(
|
self.ks_adap_mock.put.assert_called_once_with(
|
||||||
expected_url, microversion='1.10', json=mock.ANY, raise_exc=False,
|
expected_url, microversion='1.10', json=mock.ANY, raise_exc=False,
|
||||||
headers={})
|
headers={'X-Openstack-Request-Id': self.context.global_id})
|
||||||
|
|
||||||
self.assertTrue(res)
|
self.assertTrue(res)
|
||||||
|
|
||||||
|
@ -1043,7 +1054,8 @@ class TestPutAllocations(SchedulerReportClientTestCase):
|
||||||
project_id = uuids.project_id
|
project_id = uuids.project_id
|
||||||
user_id = uuids.user_id
|
user_id = uuids.user_id
|
||||||
res = self.client.remove_provider_from_instance_allocation(
|
res = self.client.remove_provider_from_instance_allocation(
|
||||||
consumer_uuid, uuids.source, user_id, project_id, mock.Mock())
|
self.context, consumer_uuid, uuids.source, user_id, project_id,
|
||||||
|
mock.Mock())
|
||||||
|
|
||||||
self.ks_adap_mock.get.assert_called()
|
self.ks_adap_mock.get.assert_called()
|
||||||
self.ks_adap_mock.put.assert_not_called()
|
self.ks_adap_mock.put.assert_not_called()
|
||||||
|
@ -1061,7 +1073,8 @@ class TestPutAllocations(SchedulerReportClientTestCase):
|
||||||
project_id = uuids.project_id
|
project_id = uuids.project_id
|
||||||
user_id = uuids.user_id
|
user_id = uuids.user_id
|
||||||
res = self.client.remove_provider_from_instance_allocation(
|
res = self.client.remove_provider_from_instance_allocation(
|
||||||
consumer_uuid, uuids.source, user_id, project_id, mock.Mock())
|
self.context, consumer_uuid, uuids.source, user_id, project_id,
|
||||||
|
mock.Mock())
|
||||||
|
|
||||||
self.ks_adap_mock.get.assert_called()
|
self.ks_adap_mock.get.assert_called()
|
||||||
self.ks_adap_mock.put.assert_not_called()
|
self.ks_adap_mock.put.assert_not_called()
|
||||||
|
@ -1989,11 +2002,12 @@ class TestProviderOperations(SchedulerReportClientTestCase):
|
||||||
self.assertEqual(set(),
|
self.assertEqual(set(),
|
||||||
self.client._provider_tree.data(uuids.rp).aggregates)
|
self.client._provider_tree.data(uuids.rp).aggregates)
|
||||||
|
|
||||||
self.client.set_aggregates_for_provider(uuids.rp, aggs)
|
self.client.set_aggregates_for_provider(self.context, uuids.rp, aggs)
|
||||||
|
|
||||||
self.ks_adap_mock.put.assert_called_once_with(
|
self.ks_adap_mock.put.assert_called_once_with(
|
||||||
'/resource_providers/%s/aggregates' % uuids.rp, json=aggs,
|
'/resource_providers/%s/aggregates' % uuids.rp, json=aggs,
|
||||||
raise_exc=False, microversion='1.1', headers={})
|
raise_exc=False, microversion='1.1',
|
||||||
|
headers={'X-Openstack-Request-Id': self.context.global_id})
|
||||||
# Cache was updated
|
# Cache was updated
|
||||||
self.assertEqual(set(aggs),
|
self.assertEqual(set(aggs),
|
||||||
self.client._provider_tree.data(uuids.rp).aggregates)
|
self.client._provider_tree.data(uuids.rp).aggregates)
|
||||||
|
@ -2002,7 +2016,8 @@ class TestProviderOperations(SchedulerReportClientTestCase):
|
||||||
self.ks_adap_mock.put.return_value = mock.Mock(status_code=503)
|
self.ks_adap_mock.put.return_value = mock.Mock(status_code=503)
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.ResourceProviderUpdateFailed,
|
exception.ResourceProviderUpdateFailed,
|
||||||
self.client.set_aggregates_for_provider, uuids.rp, [])
|
self.client.set_aggregates_for_provider,
|
||||||
|
self.context, uuids.rp, [])
|
||||||
|
|
||||||
|
|
||||||
class TestAggregates(SchedulerReportClientTestCase):
|
class TestAggregates(SchedulerReportClientTestCase):
|
||||||
|
@ -2107,18 +2122,20 @@ class TestTraits(SchedulerReportClientTestCase):
|
||||||
|
|
||||||
# Request all traits; custom traits need to be created
|
# Request all traits; custom traits need to be created
|
||||||
get_mock.json.return_value = {'traits': standard_traits}
|
get_mock.json.return_value = {'traits': standard_traits}
|
||||||
self.client._ensure_traits(all_traits)
|
self.client._ensure_traits(self.context, all_traits)
|
||||||
self.ks_adap_mock.get.assert_called_once_with(
|
self.ks_adap_mock.get.assert_called_once_with(
|
||||||
'/traits?name=in:' + ','.join(all_traits), **self.trait_api_kwargs)
|
'/traits?name=in:' + ','.join(all_traits), **self.trait_api_kwargs)
|
||||||
self.ks_adap_mock.put.assert_has_calls(
|
self.ks_adap_mock.put.assert_has_calls(
|
||||||
[mock.call('/traits/' + trait, headers={}, **self.trait_api_kwargs)
|
[mock.call('/traits/' + trait,
|
||||||
|
headers={'X-Openstack-Request-Id': self.context.global_id},
|
||||||
|
**self.trait_api_kwargs)
|
||||||
for trait in custom_traits], any_order=True)
|
for trait in custom_traits], any_order=True)
|
||||||
|
|
||||||
self.ks_adap_mock.reset_mock()
|
self.ks_adap_mock.reset_mock()
|
||||||
|
|
||||||
# Request standard traits; no traits need to be created
|
# Request standard traits; no traits need to be created
|
||||||
get_mock.json.return_value = {'traits': standard_traits}
|
get_mock.json.return_value = {'traits': standard_traits}
|
||||||
self.client._ensure_traits(standard_traits)
|
self.client._ensure_traits(self.context, standard_traits)
|
||||||
self.ks_adap_mock.get.assert_called_once_with(
|
self.ks_adap_mock.get.assert_called_once_with(
|
||||||
'/traits?name=in:' + ','.join(standard_traits),
|
'/traits?name=in:' + ','.join(standard_traits),
|
||||||
**self.trait_api_kwargs)
|
**self.trait_api_kwargs)
|
||||||
|
@ -2127,8 +2144,8 @@ class TestTraits(SchedulerReportClientTestCase):
|
||||||
self.ks_adap_mock.reset_mock()
|
self.ks_adap_mock.reset_mock()
|
||||||
|
|
||||||
# Request no traits - short circuit
|
# Request no traits - short circuit
|
||||||
self.client._ensure_traits(None)
|
self.client._ensure_traits(self.context, None)
|
||||||
self.client._ensure_traits([])
|
self.client._ensure_traits(self.context, [])
|
||||||
self.ks_adap_mock.get.assert_not_called()
|
self.ks_adap_mock.get.assert_not_called()
|
||||||
self.ks_adap_mock.put.assert_not_called()
|
self.ks_adap_mock.put.assert_not_called()
|
||||||
|
|
||||||
|
@ -2136,7 +2153,8 @@ class TestTraits(SchedulerReportClientTestCase):
|
||||||
self.ks_adap_mock.get.return_value = mock.Mock(status_code=400)
|
self.ks_adap_mock.get.return_value = mock.Mock(status_code=400)
|
||||||
|
|
||||||
self.assertRaises(exception.TraitRetrievalFailed,
|
self.assertRaises(exception.TraitRetrievalFailed,
|
||||||
self.client._ensure_traits, ['FOO'])
|
self.client._ensure_traits,
|
||||||
|
self.context, ['FOO'])
|
||||||
|
|
||||||
self.ks_adap_mock.get.assert_called_once_with(
|
self.ks_adap_mock.get.assert_called_once_with(
|
||||||
'/traits?name=in:FOO', **self.trait_api_kwargs)
|
'/traits?name=in:FOO', **self.trait_api_kwargs)
|
||||||
|
@ -2151,12 +2169,15 @@ class TestTraits(SchedulerReportClientTestCase):
|
||||||
self.ks_adap_mock.put.return_value = put_mock
|
self.ks_adap_mock.put.return_value = put_mock
|
||||||
|
|
||||||
self.assertRaises(exception.TraitCreationFailed,
|
self.assertRaises(exception.TraitCreationFailed,
|
||||||
self.client._ensure_traits, ['FOO'])
|
self.client._ensure_traits,
|
||||||
|
self.context, ['FOO'])
|
||||||
|
|
||||||
self.ks_adap_mock.get.assert_called_once_with(
|
self.ks_adap_mock.get.assert_called_once_with(
|
||||||
'/traits?name=in:FOO', **self.trait_api_kwargs)
|
'/traits?name=in:FOO', **self.trait_api_kwargs)
|
||||||
self.ks_adap_mock.put.assert_called_once_with(
|
self.ks_adap_mock.put.assert_called_once_with(
|
||||||
'/traits/FOO', headers={}, **self.trait_api_kwargs)
|
'/traits/FOO',
|
||||||
|
headers={'X-Openstack-Request-Id': self.context.global_id},
|
||||||
|
**self.trait_api_kwargs)
|
||||||
|
|
||||||
def test_set_traits_for_provider(self):
|
def test_set_traits_for_provider(self):
|
||||||
traits = ['HW_NIC_OFFLOAD_UCS', 'HW_NIC_OFFLOAD_RDMA']
|
traits = ['HW_NIC_OFFLOAD_UCS', 'HW_NIC_OFFLOAD_RDMA']
|
||||||
|
@ -2176,7 +2197,7 @@ class TestTraits(SchedulerReportClientTestCase):
|
||||||
self.ks_adap_mock.put.return_value = put_mock
|
self.ks_adap_mock.put.return_value = put_mock
|
||||||
|
|
||||||
# Invoke
|
# Invoke
|
||||||
self.client.set_traits_for_provider(uuids.rp, traits)
|
self.client.set_traits_for_provider(self.context, uuids.rp, traits)
|
||||||
|
|
||||||
# Verify API calls
|
# Verify API calls
|
||||||
self.ks_adap_mock.get.assert_called_once_with(
|
self.ks_adap_mock.get.assert_called_once_with(
|
||||||
|
@ -2184,7 +2205,8 @@ class TestTraits(SchedulerReportClientTestCase):
|
||||||
self.ks_adap_mock.put.assert_called_once_with(
|
self.ks_adap_mock.put.assert_called_once_with(
|
||||||
'/resource_providers/%s/traits' % uuids.rp,
|
'/resource_providers/%s/traits' % uuids.rp,
|
||||||
json={'traits': traits, 'resource_provider_generation': 0},
|
json={'traits': traits, 'resource_provider_generation': 0},
|
||||||
headers={}, **self.trait_api_kwargs)
|
headers={'X-Openstack-Request-Id': self.context.global_id},
|
||||||
|
**self.trait_api_kwargs)
|
||||||
|
|
||||||
# And ensure the provider tree cache was updated appropriately
|
# And ensure the provider tree cache was updated appropriately
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
|
@ -2205,7 +2227,8 @@ class TestTraits(SchedulerReportClientTestCase):
|
||||||
get_mock.status_code = 400
|
get_mock.status_code = 400
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.TraitRetrievalFailed,
|
exception.TraitRetrievalFailed,
|
||||||
self.client.set_traits_for_provider, uuids.rp, traits)
|
self.client.set_traits_for_provider,
|
||||||
|
self.context, uuids.rp, traits)
|
||||||
self.ks_adap_mock.put.assert_not_called()
|
self.ks_adap_mock.put.assert_not_called()
|
||||||
|
|
||||||
get_mock.status_code = 200
|
get_mock.status_code = 200
|
||||||
|
@ -2215,13 +2238,15 @@ class TestTraits(SchedulerReportClientTestCase):
|
||||||
self.ks_adap_mock.put.return_value = mock.Mock(status_code=409)
|
self.ks_adap_mock.put.return_value = mock.Mock(status_code=409)
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.ResourceProviderUpdateConflict,
|
exception.ResourceProviderUpdateConflict,
|
||||||
self.client.set_traits_for_provider, uuids.rp, traits)
|
self.client.set_traits_for_provider,
|
||||||
|
self.context, uuids.rp, traits)
|
||||||
|
|
||||||
# Other error
|
# Other error
|
||||||
self.ks_adap_mock.put.return_value = mock.Mock(status_code=503)
|
self.ks_adap_mock.put.return_value = mock.Mock(status_code=503)
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.ResourceProviderUpdateFailed,
|
exception.ResourceProviderUpdateFailed,
|
||||||
self.client.set_traits_for_provider, uuids.rp, traits)
|
self.client.set_traits_for_provider,
|
||||||
|
self.context, uuids.rp, traits)
|
||||||
|
|
||||||
|
|
||||||
class TestAssociations(SchedulerReportClientTestCase):
|
class TestAssociations(SchedulerReportClientTestCase):
|
||||||
|
@ -3512,7 +3537,8 @@ class TestAllocations(SchedulerReportClientTestCase):
|
||||||
self.client.update_instance_allocation(self.context, cn, inst, 1)
|
self.client.update_instance_allocation(self.context, cn, inst, 1)
|
||||||
mock_put.assert_called_once_with(
|
mock_put.assert_called_once_with(
|
||||||
'/allocations/%s' % inst.uuid,
|
'/allocations/%s' % inst.uuid,
|
||||||
expected, version='1.8')
|
expected, version='1.8',
|
||||||
|
global_request_id=self.context.global_id)
|
||||||
self.assertTrue(mock_get.called)
|
self.assertTrue(mock_get.called)
|
||||||
|
|
||||||
@mock.patch('nova.scheduler.client.report.SchedulerReportClient.'
|
@mock.patch('nova.scheduler.client.report.SchedulerReportClient.'
|
||||||
|
|
Loading…
Reference in New Issue