Move to proper target_cell calling convention

When target_cell was originally written, the intent was to yield the
context that should be used. It currently mutates the input context,
which means you don't have to actually use the yielded one, because
we have a lot of stuff that would break otherwise. This fixes all the
current uses of it to be proper, and adjusts tests accordingly. This
is separate from changing target_cell's behavior to not mutate the
input context specifically to isolate the mechanical changes from ones
that actually need different behavior.

In addition to code that was already using target_cell() but not
depending on the yielded context, the _create_block_device_mapping()
method in conductor/manager.py was still depending on the shared
context switching to target the BDM objects on create. Since these
were prepared with the context prior to having determined where the
instanace was going to end up, we need to explicitly target the
object context on create (like the rest of the boot workflow does
for other objects in schedule_and_build_instances()).

Related to blueprint cells-aware-api

Change-Id: I35206e665f2c81531a2269dd66f8c5c0df834245
This commit is contained in:
Dan Smith 2017-04-20 11:36:07 -07:00
parent ffd6a42c00
commit bb7c6ebb56
20 changed files with 155 additions and 132 deletions

View File

@ -686,8 +686,8 @@ def get_metadata_by_instance_id(instance_id, address, ctxt=None):
expected_attrs=attrs) expected_attrs=attrs)
return InstanceMetadata(instance, address) return InstanceMetadata(instance, address)
with context.target_cell(ctxt, im.cell_mapping): with context.target_cell(ctxt, im.cell_mapping) as cctxt:
instance = objects.Instance.get_by_uuid(ctxt, instance_id, instance = objects.Instance.get_by_uuid(cctxt, instance_id,
expected_attrs=attrs) expected_attrs=attrs)
return InstanceMetadata(instance, address) return InstanceMetadata(instance, address)

View File

@ -73,9 +73,10 @@ class ServerExternalEventsController(wsgi.Controller):
# Load migration_context and info_cache here in a single DB # Load migration_context and info_cache here in a single DB
# operation because we need them later on # operation because we need them later on
with nova_context.target_cell(context, cell_mapping): with nova_context.target_cell(context,
cell_mapping) as cctxt:
instance = objects.Instance.get_by_uuid( instance = objects.Instance.get_by_uuid(
context, event.instance_uuid, cctxt, event.instance_uuid,
expected_attrs=['migration_context', 'info_cache']) expected_attrs=['migration_context', 'info_cache'])
instances[event.instance_uuid] = instance instances[event.instance_uuid] = instance
except (exception.InstanceNotFound, except (exception.InstanceNotFound,

View File

@ -72,8 +72,8 @@ class ServerTagsController(wsgi.Controller):
try: try:
im = objects.InstanceMapping.get_by_instance_uuid(context, im = objects.InstanceMapping.get_by_instance_uuid(context,
server_id) server_id)
with nova_context.target_cell(context, im.cell_mapping): with nova_context.target_cell(context, im.cell_mapping) as cctxt:
exists = objects.Tag.exists(context, server_id, id) exists = objects.Tag.exists(cctxt, server_id, id)
except (exception.InstanceNotFound, except (exception.InstanceNotFound,
exception.InstanceMappingNotFound) as e: exception.InstanceMappingNotFound) as e:
raise webob.exc.HTTPNotFound(explanation=e.format_message()) raise webob.exc.HTTPNotFound(explanation=e.format_message())
@ -92,8 +92,8 @@ class ServerTagsController(wsgi.Controller):
try: try:
im = objects.InstanceMapping.get_by_instance_uuid(context, im = objects.InstanceMapping.get_by_instance_uuid(context,
server_id) server_id)
with nova_context.target_cell(context, im.cell_mapping): with nova_context.target_cell(context, im.cell_mapping) as cctxt:
tags = objects.TagList.get_by_resource_id(context, server_id) tags = objects.TagList.get_by_resource_id(cctxt, server_id)
except (exception.InstanceNotFound, except (exception.InstanceNotFound,
exception.InstanceMappingNotFound) as e: exception.InstanceMappingNotFound) as e:
raise webob.exc.HTTPNotFound(explanation=e.format_message()) raise webob.exc.HTTPNotFound(explanation=e.format_message())
@ -108,8 +108,8 @@ class ServerTagsController(wsgi.Controller):
context.can(st_policies.POLICY_ROOT % 'update') context.can(st_policies.POLICY_ROOT % 'update')
im = _get_instance_mapping(context, server_id) im = _get_instance_mapping(context, server_id)
with nova_context.target_cell(context, im.cell_mapping): with nova_context.target_cell(context, im.cell_mapping) as cctxt:
self._check_instance_in_valid_state(context, server_id, self._check_instance_in_valid_state(cctxt, server_id,
'update tag') 'update tag')
try: try:
@ -121,8 +121,8 @@ class ServerTagsController(wsgi.Controller):
raise webob.exc.HTTPBadRequest(explanation=msg) raise webob.exc.HTTPBadRequest(explanation=msg)
try: try:
with nova_context.target_cell(context, im.cell_mapping): with nova_context.target_cell(context, im.cell_mapping) as cctxt:
tags = objects.TagList.get_by_resource_id(context, server_id) tags = objects.TagList.get_by_resource_id(cctxt, server_id)
except exception.InstanceNotFound as e: except exception.InstanceNotFound as e:
raise webob.exc.HTTPNotFound(explanation=e.format_message()) raise webob.exc.HTTPNotFound(explanation=e.format_message())
@ -135,10 +135,9 @@ class ServerTagsController(wsgi.Controller):
# NOTE(snikitin): server already has specified tag # NOTE(snikitin): server already has specified tag
return webob.Response(status_int=204) return webob.Response(status_int=204)
tag = objects.Tag(context=context, resource_id=server_id, tag=id)
try: try:
with nova_context.target_cell(context, im.cell_mapping): with nova_context.target_cell(context, im.cell_mapping) as cctxt:
tag = objects.Tag(context=cctxt, resource_id=server_id, tag=id)
tag.create() tag.create()
except exception.InstanceNotFound as e: except exception.InstanceNotFound as e:
raise webob.exc.HTTPNotFound(explanation=e.format_message()) raise webob.exc.HTTPNotFound(explanation=e.format_message())
@ -156,13 +155,13 @@ class ServerTagsController(wsgi.Controller):
context.can(st_policies.POLICY_ROOT % 'update_all') context.can(st_policies.POLICY_ROOT % 'update_all')
im = _get_instance_mapping(context, server_id) im = _get_instance_mapping(context, server_id)
with nova_context.target_cell(context, im.cell_mapping): with nova_context.target_cell(context, im.cell_mapping) as cctxt:
self._check_instance_in_valid_state(context, server_id, self._check_instance_in_valid_state(cctxt, server_id,
'update tags') 'update tags')
try: try:
with nova_context.target_cell(context, im.cell_mapping): with nova_context.target_cell(context, im.cell_mapping) as cctxt:
tags = objects.TagList.create(context, server_id, body['tags']) tags = objects.TagList.create(cctxt, server_id, body['tags'])
except exception.InstanceNotFound as e: except exception.InstanceNotFound as e:
raise webob.exc.HTTPNotFound(explanation=e.format_message()) raise webob.exc.HTTPNotFound(explanation=e.format_message())
@ -176,13 +175,13 @@ class ServerTagsController(wsgi.Controller):
context.can(st_policies.POLICY_ROOT % 'delete') context.can(st_policies.POLICY_ROOT % 'delete')
im = _get_instance_mapping(context, server_id) im = _get_instance_mapping(context, server_id)
with nova_context.target_cell(context, im.cell_mapping): with nova_context.target_cell(context, im.cell_mapping) as cctxt:
self._check_instance_in_valid_state(context, server_id, self._check_instance_in_valid_state(cctxt, server_id,
'delete tag') 'delete tag')
try: try:
with nova_context.target_cell(context, im.cell_mapping): with nova_context.target_cell(context, im.cell_mapping) as cctxt:
objects.Tag.destroy(context, server_id, id) objects.Tag.destroy(cctxt, server_id, id)
except (exception.InstanceTagNotFound, except (exception.InstanceTagNotFound,
exception.InstanceNotFound) as e: exception.InstanceNotFound) as e:
raise webob.exc.HTTPNotFound(explanation=e.format_message()) raise webob.exc.HTTPNotFound(explanation=e.format_message())
@ -195,13 +194,13 @@ class ServerTagsController(wsgi.Controller):
context.can(st_policies.POLICY_ROOT % 'delete_all') context.can(st_policies.POLICY_ROOT % 'delete_all')
im = _get_instance_mapping(context, server_id) im = _get_instance_mapping(context, server_id)
with nova_context.target_cell(context, im.cell_mapping): with nova_context.target_cell(context, im.cell_mapping) as cctxt:
self._check_instance_in_valid_state(context, server_id, self._check_instance_in_valid_state(cctxt, server_id,
'delete tags') 'delete tags')
try: try:
with nova_context.target_cell(context, im.cell_mapping): with nova_context.target_cell(context, im.cell_mapping) as cctxt:
objects.TagList.destroy(context, server_id) objects.TagList.destroy(cctxt, server_id)
except exception.InstanceNotFound as e: except exception.InstanceNotFound as e:
raise webob.exc.HTTPNotFound(explanation=e.format_message()) raise webob.exc.HTTPNotFound(explanation=e.format_message())

View File

@ -109,11 +109,11 @@ class SimpleTenantUsageController(wsgi.Controller):
all_instances = [] all_instances = []
cells = objects.CellMappingList.get_all(context) cells = objects.CellMappingList.get_all(context)
for cell in cells: for cell in cells:
with nova_context.target_cell(context, cell): with nova_context.target_cell(context, cell) as cctxt:
try: try:
instances = ( instances = (
objects.InstanceList.get_active_by_window_joined( objects.InstanceList.get_active_by_window_joined(
context, period_start, period_stop, tenant_id, cctxt, period_start, period_stop, tenant_id,
expected_attrs=['flavor'], limit=limit, expected_attrs=['flavor'], limit=limit,
marker=marker)) marker=marker))
except exception.MarkerNotFound: except exception.MarkerNotFound:

View File

@ -687,8 +687,8 @@ class DbCommands(object):
try: try:
cell_mapping = objects.CellMapping.get_by_uuid(ctxt, cell_mapping = objects.CellMapping.get_by_uuid(ctxt,
objects.CellMapping.CELL0_UUID) objects.CellMapping.CELL0_UUID)
with context.target_cell(ctxt, cell_mapping): with context.target_cell(ctxt, cell_mapping) as cctxt:
migration.db_sync(version, context=ctxt) migration.db_sync(version, context=cctxt)
except exception.CellMappingNotFound: except exception.CellMappingNotFound:
print(_('WARNING: cell0 mapping not found - not' print(_('WARNING: cell0 mapping not found - not'
' syncing cell0.')) ' syncing cell0.'))
@ -1167,9 +1167,9 @@ class CellV2Commands(object):
ctxt, objects.CellMapping.CELL0_UUID) ctxt, objects.CellMapping.CELL0_UUID)
# Run migrations so cell0 is usable # Run migrations so cell0 is usable
with context.target_cell(ctxt, cell0_mapping): with context.target_cell(ctxt, cell0_mapping) as cctxt:
try: try:
migration.db_sync(None, context=ctxt) migration.db_sync(None, context=cctxt)
except db_exc.DBError as ex: except db_exc.DBError as ex:
print(_('Unable to sync cell0 schema: %s') % ex) print(_('Unable to sync cell0 schema: %s') % ex)

View File

@ -290,8 +290,8 @@ class UpgradeCommands(object):
ctxt = nova_context.get_admin_context() ctxt = nova_context.get_admin_context()
num_computes = 0 num_computes = 0
for cell_mapping in cell_mappings: for cell_mapping in cell_mappings:
with nova_context.target_cell(ctxt, cell_mapping): with nova_context.target_cell(ctxt, cell_mapping) as cctxt:
num_computes += self._count_compute_nodes(ctxt) num_computes += self._count_compute_nodes(cctxt)
else: else:
# There are no cell mappings, cells v2 was maybe not deployed in # There are no cell mappings, cells v2 was maybe not deployed in
# Newton, but placement might have been, so let's check the single # Newton, but placement might have been, so let's check the single

View File

@ -1737,10 +1737,9 @@ class API(base.Base):
return None, None return None, None
else: else:
cell = inst_map.cell_mapping cell = inst_map.cell_mapping
with nova_context.target_cell(context, cell): with nova_context.target_cell(context, cell) as cctxt:
try: try:
instance = objects.Instance.get_by_uuid(context, instance = objects.Instance.get_by_uuid(cctxt, uuid)
uuid)
except exception.InstanceNotFound: except exception.InstanceNotFound:
# Since the cell_mapping exists we know the instance is in # Since the cell_mapping exists we know the instance is in
# the cell, however InstanceNotFound means it's already # the cell, however InstanceNotFound means it's already
@ -1799,9 +1798,11 @@ class API(base.Base):
if instance is not None: if instance is not None:
# If instance is None it has already been deleted. # If instance is None it has already been deleted.
if cell: if cell:
with nova_context.target_cell(context, cell): with nova_context.target_cell(context, cell) as cctxt:
# FIXME: When the instance context is targeted,
# we can remove this
with compute_utils.notify_about_instance_delete( with compute_utils.notify_about_instance_delete(
self.notifier, context, instance): self.notifier, cctxt, instance):
instance.destroy() instance.destroy()
else: else:
instance.destroy() instance.destroy()
@ -1873,31 +1874,35 @@ class API(base.Base):
# We have to get the flavor from the instance while the # We have to get the flavor from the instance while the
# context is still targeted to where the instance lives. # context is still targeted to where the instance lives.
with nova_context.target_cell(context, cell): with nova_context.target_cell(context, cell) as cctxt:
# If the instance has the targeted context in it then # FIXME: If the instance has the targeted context in
# we don't need the context manager. # it then we don't need the context manager.
quota_flavor = self._get_flavor_for_reservation( quota_flavor = self._get_flavor_for_reservation(
instance) instance)
with nova_context.target_cell(context, None): with nova_context.target_cell(context, None) as cctxt:
# This is confusing but actually decrements quota usage # This is confusing but actually decrements quota usage
quotas = self._create_reservations( quotas = self._create_reservations(
context, instance, instance.task_state, cctxt, instance, instance.task_state,
project_id, user_id, flavor=quota_flavor) project_id, user_id, flavor=quota_flavor)
try: try:
# Now destroy the instance from the cell it lives in. # Now destroy the instance from the cell it lives in.
with nova_context.target_cell(context, cell): with nova_context.target_cell(context, cell) as cctxt:
# If the instance has the targeted context in it # If the instance has the targeted context in it
# then we don't need the context manager. # then we don't need the context manager.
with compute_utils.notify_about_instance_delete( with compute_utils.notify_about_instance_delete(
self.notifier, context, instance): self.notifier, cctxt, instance):
instance.destroy() instance.destroy()
# Now commit the quota reservation to decrement usage. # Now commit the quota reservation to decrement usage.
with nova_context.target_cell(context, None): # NOTE(danms): When target_cell yields a context copy,
# we can remove this targeting.
with nova_context.target_cell(context, None) as cctxt:
quotas.commit() quotas.commit()
except exception.InstanceNotFound: except exception.InstanceNotFound:
with nova_context.target_cell(context, None): # NOTE(danms): When target_cell yields a context copy,
# we can remove this targeting.
with nova_context.target_cell(context, None) as cctxt:
quotas.rollback() quotas.rollback()
# The instance was deleted or is already gone. # The instance was deleted or is already gone.
return return
@ -2557,10 +2562,10 @@ class API(base.Base):
except exception.CellMappingNotFound: except exception.CellMappingNotFound:
cell0_instances = objects.InstanceList(objects=[]) cell0_instances = objects.InstanceList(objects=[])
else: else:
with nova_context.target_cell(context, cell0_mapping): with nova_context.target_cell(context, cell0_mapping) as cctxt:
try: try:
cell0_instances = self._get_instances_by_filters( cell0_instances = self._get_instances_by_filters(
context, filters, limit=limit, marker=marker, cctxt, filters, limit=limit, marker=marker,
expected_attrs=expected_attrs, sort_keys=sort_keys, expected_attrs=expected_attrs, sort_keys=sort_keys,
sort_dirs=sort_dirs) sort_dirs=sort_dirs)
except exception.MarkerNotFound: except exception.MarkerNotFound:
@ -2714,8 +2719,10 @@ class API(base.Base):
# look up the instance in the cell database # look up the instance in the cell database
if inst_map and (inst_map.cell_mapping is not None) and ( if inst_map and (inst_map.cell_mapping is not None) and (
not CONF.cells.enable): not CONF.cells.enable):
with nova_context.target_cell(context, inst_map.cell_mapping): with nova_context.target_cell(context,
instance.save() inst_map.cell_mapping) as cctxt:
with instance.obj_alternate_context(cctxt):
instance.save()
else: else:
# If inst_map.cell_mapping does not point at a cell then cell # If inst_map.cell_mapping does not point at a cell then cell
# migration has not happened yet. # migration has not happened yet.
@ -2756,10 +2763,11 @@ class API(base.Base):
inst_map = self._get_instance_map_or_none(context, inst_map = self._get_instance_map_or_none(context,
instance.uuid) instance.uuid)
if inst_map and (inst_map.cell_mapping is not None): if inst_map and (inst_map.cell_mapping is not None):
with nova_context.target_cell(context, with nova_context.target_cell(
inst_map.cell_mapping): context,
inst_map.cell_mapping) as cctxt:
instance = objects.Instance.get_by_uuid( instance = objects.Instance.get_by_uuid(
context, instance.uuid, cctxt, instance.uuid,
expected_attrs=expected_attrs) expected_attrs=expected_attrs)
instance.update(updates) instance.update(updates)
instance.save() instance.save()
@ -4161,9 +4169,9 @@ class API(base.Base):
for cell in CELLS: for cell in CELLS:
if cell.uuid == objects.CellMapping.CELL0_UUID: if cell.uuid == objects.CellMapping.CELL0_UUID:
continue continue
with nova_context.target_cell(context, cell): with nova_context.target_cell(context, cell) as cctxt:
migrations.extend(objects.MigrationList.get_by_filters( migrations.extend(objects.MigrationList.get_by_filters(
context, filters).objects) cctxt, filters).objects)
return objects.MigrationList(objects=migrations) return objects.MigrationList(objects=migrations)
def get_migrations_in_progress_by_instance(self, context, instance_uuid, def get_migrations_in_progress_by_instance(self, context, instance_uuid,
@ -4239,9 +4247,9 @@ class API(base.Base):
# TODO(salv-orlando): Handle exceptions raised by the rpc api layer # TODO(salv-orlando): Handle exceptions raised by the rpc api layer
# in order to ensure that a failure in processing events on a host # in order to ensure that a failure in processing events on a host
# will not prevent processing events on other hosts # will not prevent processing events on other hosts
with nova_context.target_cell(context, cell_mapping): with nova_context.target_cell(context, cell_mapping) as cctxt:
self.compute_rpcapi.external_instance_event( self.compute_rpcapi.external_instance_event(
context, instances_by_host[host], events_by_host[host], cctxt, instances_by_host[host], events_by_host[host],
host=host) host=host)
def _get_relevant_hosts(self, context, instance): def _get_relevant_hosts(self, context, instance):
@ -4406,9 +4414,9 @@ class HostAPI(base.Base):
load_cells() load_cells()
services = [] services = []
for cell in CELLS: for cell in CELLS:
with nova_context.target_cell(context, cell): with nova_context.target_cell(context, cell) as cctxt:
cell_services = objects.ServiceList.get_all( cell_services = objects.ServiceList.get_all(
context, disabled, set_zones=set_zones) cctxt, disabled, set_zones=set_zones)
services.extend(cell_services) services.extend(cell_services)
else: else:
services = objects.ServiceList.get_all(context, disabled, services = objects.ServiceList.get_all(context, disabled,
@ -4444,8 +4452,8 @@ class HostAPI(base.Base):
for cell in CELLS: for cell in CELLS:
# NOTE(danms): Services can be in cell0, so don't skip it here # NOTE(danms): Services can be in cell0, so don't skip it here
try: try:
with nova_context.target_cell(context, cell): with nova_context.target_cell(context, cell) as cctxt:
cell_service = objects.Service.get_by_id(context, cell_service = objects.Service.get_by_id(cctxt,
service_id) service_id)
except exception.ServiceNotFound: except exception.ServiceNotFound:
# NOTE(danms): Keep looking in other cells # NOTE(danms): Keep looking in other cells
@ -4523,9 +4531,9 @@ class HostAPI(base.Base):
for cell in CELLS: for cell in CELLS:
if cell.uuid == objects.CellMapping.CELL0_UUID: if cell.uuid == objects.CellMapping.CELL0_UUID:
continue continue
with nova_context.target_cell(context, cell): with nova_context.target_cell(context, cell) as cctxt:
try: try:
return objects.ComputeNode.get_by_id(context, return objects.ComputeNode.get_by_id(cctxt,
int(compute_id)) int(compute_id))
except exception.ComputeHostNotFound: except exception.ComputeHostNotFound:
# NOTE(danms): Keep looking in other cells # NOTE(danms): Keep looking in other cells
@ -4540,10 +4548,10 @@ class HostAPI(base.Base):
for cell in CELLS: for cell in CELLS:
if cell.uuid == objects.CellMapping.CELL0_UUID: if cell.uuid == objects.CellMapping.CELL0_UUID:
continue continue
with nova_context.target_cell(context, cell): with nova_context.target_cell(context, cell) as cctxt:
try: try:
cell_computes = objects.ComputeNodeList.get_by_pagination( cell_computes = objects.ComputeNodeList.get_by_pagination(
context, limit=limit, marker=marker) cctxt, limit=limit, marker=marker)
except exception.MarkerNotFound: except exception.MarkerNotFound:
# NOTE(danms): Keep looking through cells # NOTE(danms): Keep looking through cells
continue continue
@ -4570,9 +4578,9 @@ class HostAPI(base.Base):
for cell in CELLS: for cell in CELLS:
if cell.uuid == objects.CellMapping.CELL0_UUID: if cell.uuid == objects.CellMapping.CELL0_UUID:
continue continue
with nova_context.target_cell(context, cell): with nova_context.target_cell(context, cell) as cctxt:
cell_computes = objects.ComputeNodeList.get_by_hypervisor( cell_computes = objects.ComputeNodeList.get_by_hypervisor(
context, hypervisor_match) cctxt, hypervisor_match)
computes.extend(cell_computes) computes.extend(cell_computes)
return objects.ComputeNodeList(objects=computes) return objects.ComputeNodeList(objects=computes)

View File

@ -205,7 +205,7 @@ def obj_target_cell(obj, cell):
"""Run with object's context set to a specific cell""" """Run with object's context set to a specific cell"""
with try_target_cell(obj._context, cell) as target: with try_target_cell(obj._context, cell) as target:
with obj.obj_alternate_context(target): with obj.obj_alternate_context(target):
yield yield target
@profiler.trace_cls("rpc") @profiler.trace_cls("rpc")
@ -830,7 +830,7 @@ class ComputeTaskManager(base.Base):
size = instance_type.get('ephemeral_gb', 0) size = instance_type.get('ephemeral_gb', 0)
return size return size
def _create_block_device_mapping(self, instance_type, instance_uuid, def _create_block_device_mapping(self, cell, instance_type, instance_uuid,
block_device_mapping): block_device_mapping):
"""Create the BlockDeviceMapping objects in the db. """Create the BlockDeviceMapping objects in the db.
@ -843,7 +843,8 @@ class ComputeTaskManager(base.Base):
for bdm in instance_block_device_mapping: for bdm in instance_block_device_mapping:
bdm.volume_size = self._volume_size(instance_type, bdm) bdm.volume_size = self._volume_size(instance_type, bdm)
bdm.instance_uuid = instance_uuid bdm.instance_uuid = instance_uuid
bdm.update_or_create() with obj_target_cell(bdm, cell):
bdm.update_or_create()
return instance_block_device_mapping return instance_block_device_mapping
def _bury_in_cell0(self, context, request_spec, exc, def _bury_in_cell0(self, context, request_spec, exc,
@ -971,12 +972,12 @@ class ComputeTaskManager(base.Base):
notifications.send_update_with_states(context, instance, None, notifications.send_update_with_states(context, instance, None,
vm_states.BUILDING, None, None, service="conductor") vm_states.BUILDING, None, None, service="conductor")
with obj_target_cell(instance, cell): with obj_target_cell(instance, cell) as cctxt:
objects.InstanceAction.action_start( objects.InstanceAction.action_start(
context, instance.uuid, instance_actions.CREATE, cctxt, instance.uuid, instance_actions.CREATE,
want_result=False) want_result=False)
instance_bdms = self._create_block_device_mapping( instance_bdms = self._create_block_device_mapping(
instance.flavor, instance.uuid, block_device_mapping) cell, instance.flavor, instance.uuid, block_device_mapping)
# Update mapping for instance. Normally this check is guarded by # Update mapping for instance. Normally this check is guarded by
# a try/except but if we're here we know that a newer nova-api # a try/except but if we're here we know that a newer nova-api
@ -999,9 +1000,9 @@ class ComputeTaskManager(base.Base):
legacy_secgroups = [s.identifier legacy_secgroups = [s.identifier
for s in request_spec.security_groups] for s in request_spec.security_groups]
with obj_target_cell(instance, cell): with obj_target_cell(instance, cell) as cctxt:
self.compute_rpcapi.build_and_run_instance( self.compute_rpcapi.build_and_run_instance(
context, instance=instance, image=image, cctxt, instance=instance, image=image,
request_spec=request_spec, request_spec=request_spec,
filter_properties=filter_props, filter_properties=filter_props,
admin_password=admin_password, admin_password=admin_password,

View File

@ -119,11 +119,11 @@ class ConsoleAuthManager(manager.Manager):
mapping = objects.InstanceMapping.get_by_instance_uuid(context, mapping = objects.InstanceMapping.get_by_instance_uuid(context,
instance_uuid) instance_uuid)
with nova_context.target_cell(context, mapping.cell_mapping): with nova_context.target_cell(context, mapping.cell_mapping) as cctxt:
instance = objects.Instance.get_by_uuid(context, instance_uuid) instance = objects.Instance.get_by_uuid(cctxt, instance_uuid)
return self.compute_rpcapi.validate_console_port( return self.compute_rpcapi.validate_console_port(
context, cctxt,
instance, instance,
token['port'], token['port'],
token['console_type']) token['console_type'])

View File

@ -218,13 +218,14 @@ def discover_hosts(ctxt, cell_uuid=None, status_fn=None):
else: else:
status_fn(_("Getting compute nodes from cell: %(uuid)s") % status_fn(_("Getting compute nodes from cell: %(uuid)s") %
{'uuid': cm.uuid}) {'uuid': cm.uuid})
with context.target_cell(ctxt, cm): with context.target_cell(ctxt, cm) as cctxt:
compute_nodes = objects.ComputeNodeList.get_all_by_not_mapped( compute_nodes = objects.ComputeNodeList.get_all_by_not_mapped(
ctxt, 1) cctxt, 1)
status_fn(_('Found %(num)s unmapped computes in cell: %(uuid)s') % status_fn(_('Found %(num)s unmapped computes in cell: %(uuid)s') %
{'num': len(compute_nodes), {'num': len(compute_nodes),
'uuid': cm.uuid}) 'uuid': cm.uuid})
added_hm = _check_and_create_host_mappings(ctxt, cm, compute_nodes, added_hm = _check_and_create_host_mappings(cctxt, cm,
compute_nodes,
status_fn) status_fn)
host_mappings.extend(added_hm) host_mappings.extend(added_hm)

View File

@ -423,9 +423,9 @@ class HostManager(object):
if not computes_by_cell: if not computes_by_cell:
computes_by_cell = {} computes_by_cell = {}
for cell in self.cells: for cell in self.cells:
with context_module.target_cell(context, cell): with context_module.target_cell(context, cell) as cctxt:
cell_cns = objects.ComputeNodeList.get_all( cell_cns = objects.ComputeNodeList.get_all(
context).objects cctxt).objects
computes_by_cell[cell] = cell_cns computes_by_cell[cell] = cell_cns
count += len(cell_cns) count += len(cell_cns)
@ -444,9 +444,9 @@ class HostManager(object):
filters = {"host": [curr_node.host filters = {"host": [curr_node.host
for curr_node in curr_nodes], for curr_node in curr_nodes],
"deleted": False} "deleted": False}
with context_module.target_cell(context, cell): with context_module.target_cell(context, cell) as cctxt:
result = objects.InstanceList.get_by_filters( result = objects.InstanceList.get_by_filters(
context.elevated(), filters) cctxt.elevated(), filters)
instances = result.objects instances = result.objects
LOG.debug("Adding %s instances for hosts %s-%s", LOG.debug("Adding %s instances for hosts %s-%s",
len(instances), start_node, end_node) len(instances), start_node, end_node)
@ -603,19 +603,18 @@ class HostManager(object):
for cell in cells: for cell in cells:
LOG.debug('Getting compute nodes and services for cell %(cell)s', LOG.debug('Getting compute nodes and services for cell %(cell)s',
{'cell': cell.identity}) {'cell': cell.identity})
with context_module.target_cell(context, cell): with context_module.target_cell(context, cell) as cctxt:
if compute_uuids is None: if compute_uuids is None:
compute_nodes[cell.uuid].extend( compute_nodes[cell.uuid].extend(
objects.ComputeNodeList.get_all( objects.ComputeNodeList.get_all(cctxt))
context))
else: else:
compute_nodes[cell.uuid].extend( compute_nodes[cell.uuid].extend(
objects.ComputeNodeList.get_all_by_uuids( objects.ComputeNodeList.get_all_by_uuids(
context, compute_uuids)) cctxt, compute_uuids))
services.update( services.update(
{service.host: service {service.host: service
for service in objects.ServiceList.get_by_binary( for service in objects.ServiceList.get_by_binary(
context, 'nova-compute', cctxt, 'nova-compute',
include_disabled=True)}) include_disabled=True)})
return compute_nodes, services return compute_nodes, services
@ -708,8 +707,8 @@ class HostManager(object):
def _get_instances_by_host(self, context, host_name): def _get_instances_by_host(self, context, host_name):
hm = objects.HostMapping.get_by_host(context, host_name) hm = objects.HostMapping.get_by_host(context, host_name)
with context_module.target_cell(context, hm.cell_mapping): with context_module.target_cell(context, hm.cell_mapping) as cctxt:
inst_list = objects.InstanceList.get_by_host(context, host_name) inst_list = objects.InstanceList.get_by_host(cctxt, host_name)
return {inst.uuid: inst for inst in inst_list} return {inst.uuid: inst for inst in inst_list}
def _get_instance_info(self, context, compute): def _get_instance_info(self, context, compute):

View File

@ -112,9 +112,9 @@ class IronicHostManager(host_manager.HostManager):
if not computes_by_cell: if not computes_by_cell:
computes_by_cell = {} computes_by_cell = {}
for cell in self.cells: for cell in self.cells:
with context_module.target_cell(context, cell): with context_module.target_cell(context, cell) as cctxt:
computes_by_cell[cell] = ( computes_by_cell[cell] = (
objects.ComputeNodeList.get_all(context).objects) objects.ComputeNodeList.get_all(cctxt).objects)
non_ironic_computes = {cell: [c for c in compute_nodes non_ironic_computes = {cell: [c for c in compute_nodes
if not self._is_ironic_compute(c)] if not self._is_ironic_compute(c)]

View File

@ -52,16 +52,16 @@ class ConnectionSwitchTestCase(test.NoDBTestCase):
mapping.create() mapping.create()
# Create an instance in the cell database # Create an instance in the cell database
uuid = uuidutils.generate_uuid() uuid = uuidutils.generate_uuid()
with context.target_cell(ctxt, mapping): with context.target_cell(ctxt, mapping) as cctxt:
# Must set project_id because instance get specifies # Must set project_id because instance get specifies
# project_only=True to model_query, which means non-admin # project_only=True to model_query, which means non-admin
# users can only read instances for their project # users can only read instances for their project
instance = objects.Instance(context=ctxt, uuid=uuid, instance = objects.Instance(context=cctxt, uuid=uuid,
project_id='fake-project') project_id='fake-project')
instance.create() instance.create()
# Verify the instance is found in the cell database # Verify the instance is found in the cell database
inst = objects.Instance.get_by_uuid(ctxt, uuid) inst = objects.Instance.get_by_uuid(cctxt, uuid)
self.assertEqual(uuid, inst.uuid) self.assertEqual(uuid, inst.uuid)
# Verify the instance isn't found in the main database # Verify the instance isn't found in the main database
@ -95,35 +95,35 @@ class CellDatabasesTestCase(test.NoDBTestCase):
# Create an instance and read it from cell1 # Create an instance and read it from cell1
uuid = uuidutils.generate_uuid() uuid = uuidutils.generate_uuid()
with context.target_cell(ctxt, mapping1): with context.target_cell(ctxt, mapping1) as cctxt:
instance = objects.Instance(context=ctxt, uuid=uuid, instance = objects.Instance(context=cctxt, uuid=uuid,
project_id='fake-project') project_id='fake-project')
instance.create() instance.create()
inst = objects.Instance.get_by_uuid(ctxt, uuid) inst = objects.Instance.get_by_uuid(cctxt, uuid)
self.assertEqual(uuid, inst.uuid) self.assertEqual(uuid, inst.uuid)
# Make sure it can't be read from cell2 # Make sure it can't be read from cell2
with context.target_cell(ctxt, mapping2): with context.target_cell(ctxt, mapping2) as cctxt:
self.assertRaises(exception.InstanceNotFound, self.assertRaises(exception.InstanceNotFound,
objects.Instance.get_by_uuid, ctxt, uuid) objects.Instance.get_by_uuid, cctxt, uuid)
# Make sure it can still be read from cell1 # Make sure it can still be read from cell1
with context.target_cell(ctxt, mapping1): with context.target_cell(ctxt, mapping1) as cctxt:
inst = objects.Instance.get_by_uuid(ctxt, uuid) inst = objects.Instance.get_by_uuid(cctxt, uuid)
self.assertEqual(uuid, inst.uuid) self.assertEqual(uuid, inst.uuid)
# Create an instance and read it from cell2 # Create an instance and read it from cell2
uuid = uuidutils.generate_uuid() uuid = uuidutils.generate_uuid()
with context.target_cell(ctxt, mapping2): with context.target_cell(ctxt, mapping2) as cctxt:
instance = objects.Instance(context=ctxt, uuid=uuid, instance = objects.Instance(context=cctxt, uuid=uuid,
project_id='fake-project') project_id='fake-project')
instance.create() instance.create()
inst = objects.Instance.get_by_uuid(ctxt, uuid) inst = objects.Instance.get_by_uuid(cctxt, uuid)
self.assertEqual(uuid, inst.uuid) self.assertEqual(uuid, inst.uuid)
# Make sure it can't be read from cell1 # Make sure it can't be read from cell1
with context.target_cell(ctxt, mapping1): with context.target_cell(ctxt, mapping1) as cctxt:
self.assertRaises(exception.InstanceNotFound, self.assertRaises(exception.InstanceNotFound,
objects.Instance.get_by_uuid, ctxt, uuid) objects.Instance.get_by_uuid, cctxt, uuid)

View File

@ -335,7 +335,8 @@ class ServerGroupTestV21(test.NoDBTestCase):
# delete an instance # delete an instance
im = objects.InstanceMapping.get_by_instance_uuid(ctx, im = objects.InstanceMapping.get_by_instance_uuid(ctx,
instances[1].uuid) instances[1].uuid)
with context.target_cell(ctx, im.cell_mapping): with context.target_cell(ctx, im.cell_mapping) as cctxt:
instances[1]._context = cctxt
instances[1].destroy() instances[1].destroy()
# check that the instance does not exist # check that the instance does not exist

View File

@ -7922,6 +7922,7 @@ class ComputeTestCase(BaseTestCase):
minimum_server_version.return_value = 15 minimum_server_version.return_value = 15
im_get_by_instance.return_value = mock.Mock() im_get_by_instance.return_value = mock.Mock()
target_cell.return_value.__enter__.return_value = self.context
instance = self._create_fake_instance_obj() instance = self._create_fake_instance_obj()
instance.host = None instance.host = None
@ -7987,6 +7988,7 @@ class ComputeTestCase(BaseTestCase):
self, br_get_by_instance, notify, im_get_by_instance, target_cell, self, br_get_by_instance, notify, im_get_by_instance, target_cell,
instance_destroy): instance_destroy):
target_cell.return_value.__enter__.return_value = self.context
instance = self._create_fake_instance_obj() instance = self._create_fake_instance_obj()
instance.host = None instance.host = None
instance.save() instance.save()
@ -10899,8 +10901,8 @@ def _create_service_entries(ctxt, values=[['avail_zone1', ['fake_host1',
# NOTE(danms): spread these services across cells # NOTE(danms): spread these services across cells
cell = cells[index % len(cells)] cell = cells[index % len(cells)]
index += 1 index += 1
with context.target_cell(ctxt, cell): with context.target_cell(ctxt, cell) as cctxt:
s = objects.Service(context=ctxt, s = objects.Service(context=cctxt,
host=host, host=host,
binary='nova-compute', binary='nova-compute',
topic='compute', topic='compute',

View File

@ -1440,6 +1440,7 @@ class _ComputeAPIUnitTestMixIn(object):
instance = self._create_instance_obj({'host': None}) instance = self._create_instance_obj({'host': None})
cell0 = objects.CellMapping(uuid=objects.CellMapping.CELL0_UUID) cell0 = objects.CellMapping(uuid=objects.CellMapping.CELL0_UUID)
quota_mock = mock.MagicMock() quota_mock = mock.MagicMock()
target_cell_mock().__enter__.return_value = mock.sentinel.cctxt
with test.nested( with test.nested(
mock.patch.object(self.compute_api, '_delete_while_booting', mock.patch.object(self.compute_api, '_delete_while_booting',
@ -1462,7 +1463,7 @@ class _ComputeAPIUnitTestMixIn(object):
self.context, instance.uuid) self.context, instance.uuid)
_get_flavor_for_reservation.assert_called_once_with(instance) _get_flavor_for_reservation.assert_called_once_with(instance)
_create_reservations.assert_called_once_with( _create_reservations.assert_called_once_with(
self.context, instance, instance.task_state, mock.sentinel.cctxt, instance, instance.task_state,
self.context.project_id, instance.user_id, self.context.project_id, instance.user_id,
flavor=instance.flavor) flavor=instance.flavor)
quota_mock.commit.assert_called_once_with() quota_mock.commit.assert_called_once_with()
@ -1482,7 +1483,7 @@ class _ComputeAPIUnitTestMixIn(object):
] ]
target_cell_mock.assert_has_calls(expected_target_cell_calls) target_cell_mock.assert_has_calls(expected_target_cell_calls)
notify_mock.assert_called_once_with( notify_mock.assert_called_once_with(
self.compute_api.notifier, self.context, instance) self.compute_api.notifier, mock.sentinel.cctxt, instance)
destroy_mock.assert_called_once_with() destroy_mock.assert_called_once_with()
@mock.patch('nova.context.target_cell') @mock.patch('nova.context.target_cell')
@ -1503,6 +1504,7 @@ class _ComputeAPIUnitTestMixIn(object):
quota_mock = mock.MagicMock() quota_mock = mock.MagicMock()
destroy_mock.side_effect = exception.InstanceNotFound( destroy_mock.side_effect = exception.InstanceNotFound(
instance_id=instance.uuid) instance_id=instance.uuid)
target_cell_mock().__enter__.return_value = mock.sentinel.cctxt
with test.nested( with test.nested(
mock.patch.object(self.compute_api, '_delete_while_booting', mock.patch.object(self.compute_api, '_delete_while_booting',
@ -1525,11 +1527,11 @@ class _ComputeAPIUnitTestMixIn(object):
self.context, instance.uuid) self.context, instance.uuid)
_get_flavor_for_reservation.assert_called_once_with(instance) _get_flavor_for_reservation.assert_called_once_with(instance)
_create_reservations.assert_called_once_with( _create_reservations.assert_called_once_with(
self.context, instance, instance.task_state, mock.sentinel.cctxt, instance, instance.task_state,
self.context.project_id, instance.user_id, self.context.project_id, instance.user_id,
flavor=instance.flavor) flavor=instance.flavor)
notify_mock.assert_called_once_with( notify_mock.assert_called_once_with(
self.compute_api.notifier, self.context, instance) self.compute_api.notifier, mock.sentinel.cctxt, instance)
destroy_mock.assert_called_once_with() destroy_mock.assert_called_once_with()
expected_target_cell_calls = [ expected_target_cell_calls = [
# Get the instance.flavor. # Get the instance.flavor.
@ -1591,6 +1593,7 @@ class _ComputeAPIUnitTestMixIn(object):
@mock.patch.object(context, 'target_cell') @mock.patch.object(context, 'target_cell')
def test_lookup_instance_cell_mapping(self, mock_target_cell): def test_lookup_instance_cell_mapping(self, mock_target_cell):
instance = self._create_instance_obj() instance = self._create_instance_obj()
mock_target_cell.return_value.__enter__.return_value = self.context
inst_map = objects.InstanceMapping( inst_map = objects.InstanceMapping(
cell_mapping=objects.CellMapping(database_connection='', cell_mapping=objects.CellMapping(database_connection='',
@ -4692,6 +4695,8 @@ class _ComputeAPIUnitTestMixIn(object):
objects.CellMapping(uuid=uuids.cell1, name='1'), objects.CellMapping(uuid=uuids.cell1, name='1'),
] ]
cctxt = mock_target_cell.return_value.__enter__.return_value
with mock.patch.object(self.compute_api, with mock.patch.object(self.compute_api,
'_get_instances_by_filters') as mock_inst_get: '_get_instances_by_filters') as mock_inst_get:
mock_inst_get.side_effect = [objects.InstanceList( mock_inst_get.side_effect = [objects.InstanceList(
@ -4709,7 +4714,7 @@ class _ComputeAPIUnitTestMixIn(object):
if self.cell_type is None: if self.cell_type is None:
for cm in mock_cm_get_all.return_value: for cm in mock_cm_get_all.return_value:
mock_target_cell.assert_any_call(self.context, cm) mock_target_cell.assert_any_call(self.context, cm)
inst_get_calls = [mock.call(self.context, {'foo': 'bar'}, inst_get_calls = [mock.call(cctxt, {'foo': 'bar'},
limit=10, marker='fake-marker', limit=10, marker='fake-marker',
expected_attrs=None, sort_keys=['baz'], expected_attrs=None, sort_keys=['baz'],
sort_dirs=['desc']), sort_dirs=['desc']),
@ -4747,6 +4752,7 @@ class _ComputeAPIUnitTestMixIn(object):
cell_mapping, cell_mapping,
objects.CellMapping(uuid=uuids.cell1, name='1'), objects.CellMapping(uuid=uuids.cell1, name='1'),
] ]
cctxt = mock_target_cell.return_value.__enter__.return_value
with mock.patch.object(self.compute_api, with mock.patch.object(self.compute_api,
'_get_instances_by_filters') as mock_inst_get: '_get_instances_by_filters') as mock_inst_get:
@ -4765,7 +4771,7 @@ class _ComputeAPIUnitTestMixIn(object):
if self.cell_type is None: if self.cell_type is None:
for cm in mock_cm_get_all.return_value: for cm in mock_cm_get_all.return_value:
mock_target_cell.assert_any_call(self.context, cm) mock_target_cell.assert_any_call(self.context, cm)
inst_get_calls = [mock.call(self.context, {'foo': 'bar'}, inst_get_calls = [mock.call(cctxt, {'foo': 'bar'},
limit=8, marker='fake-marker', limit=8, marker='fake-marker',
expected_attrs=None, sort_keys=['baz'], expected_attrs=None, sort_keys=['baz'],
sort_dirs=['desc']), sort_dirs=['desc']),
@ -4804,6 +4810,7 @@ class _ComputeAPIUnitTestMixIn(object):
objects.CellMapping(uuid=uuids.cell1, name='1'), objects.CellMapping(uuid=uuids.cell1, name='1'),
] ]
marker = uuids.marker marker = uuids.marker
cctxt = mock_target_cell.return_value.__enter__.return_value
with mock.patch.object(self.compute_api, with mock.patch.object(self.compute_api,
'_get_instances_by_filters') as mock_inst_get: '_get_instances_by_filters') as mock_inst_get:
@ -4822,7 +4829,7 @@ class _ComputeAPIUnitTestMixIn(object):
if self.cell_type is None: if self.cell_type is None:
for cm in mock_cm_get_all.return_value: for cm in mock_cm_get_all.return_value:
mock_target_cell.assert_any_call(self.context, cm) mock_target_cell.assert_any_call(self.context, cm)
inst_get_calls = [mock.call(self.context, {'foo': 'bar'}, inst_get_calls = [mock.call(cctxt, {'foo': 'bar'},
limit=10, marker=marker, limit=10, marker=marker,
expected_attrs=None, sort_keys=['baz'], expected_attrs=None, sort_keys=['baz'],
sort_dirs=['desc']), sort_dirs=['desc']),

View File

@ -176,8 +176,8 @@ class ComputeHostAPITestCase(test.TestCase):
def test_service_get_all_cells(self): def test_service_get_all_cells(self):
cells = objects.CellMappingList.get_all(self.ctxt) cells = objects.CellMappingList.get_all(self.ctxt)
for cell in cells: for cell in cells:
with context.target_cell(self.ctxt, cell): with context.target_cell(self.ctxt, cell) as cctxt:
objects.Service(context=self.ctxt, objects.Service(context=cctxt,
binary='nova-compute', binary='nova-compute',
host='host-%s' % cell.uuid).create() host='host-%s' % cell.uuid).create()
services = self.host_api.service_get_all(self.ctxt, all_cells=True) services = self.host_api.service_get_all(self.ctxt, all_cells=True)

View File

@ -1479,9 +1479,9 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase):
# NOTE(danms): Assert that we created the InstanceAction in the # NOTE(danms): Assert that we created the InstanceAction in the
# correct cell # correct cell
for cell in cells: for cell in cells:
with context.target_cell(self.context, cell): with context.target_cell(self.context, cell) as cctxt:
actions = objects.InstanceActionList.get_by_instance_uuid( actions = objects.InstanceActionList.get_by_instance_uuid(
self.context, instance_uuid) cctxt, instance_uuid)
if cell.name == 'cell1': if cell.name == 'cell1':
self.assertEqual(1, len(actions)) self.assertEqual(1, len(actions))
else: else:

View File

@ -939,7 +939,7 @@ class HostManagerTestCase(test.NoDBTestCase):
@contextlib.contextmanager @contextlib.contextmanager
def fake_set_target(context, cell): def fake_set_target(context, cell):
yield yield mock.sentinel.cctxt
mock_target.side_effect = fake_set_target mock_target.side_effect = fake_set_target
@ -955,8 +955,8 @@ class HostManagerTestCase(test.NoDBTestCase):
# targeted one if we honored the only-cell destination requirement, # targeted one if we honored the only-cell destination requirement,
# and only looked up services and compute nodes in one # and only looked up services and compute nodes in one
mock_target.assert_called_once_with(context, cells[1]) mock_target.assert_called_once_with(context, cells[1])
mock_cn.assert_called_once_with(context) mock_cn.assert_called_once_with(mock.sentinel.cctxt)
mock_sl.assert_called_once_with(context, 'nova-compute', mock_sl.assert_called_once_with(mock.sentinel.cctxt, 'nova-compute',
include_disabled=True) include_disabled=True)

View File

@ -552,7 +552,7 @@ Archiving.....stopped
mock_target_cell.assert_called_once_with(ctxt, 'map') mock_target_cell.assert_called_once_with(ctxt, 'map')
db_sync_calls = [ db_sync_calls = [
mock.call(4, context=ctxt), mock.call(4, context=cell_ctxt),
mock.call(4) mock.call(4)
] ]
mock_db_sync.assert_has_calls(db_sync_calls) mock_db_sync.assert_has_calls(db_sync_calls)
@ -1268,6 +1268,8 @@ class CellV2CommandsTestCase(test.NoDBTestCase):
transport_url='fake:///mq') transport_url='fake:///mq')
cell_mapping.create() cell_mapping.create()
mock_target_cell.return_value.__enter__.return_value = ctxt
self.commands.discover_hosts(cell_uuid=cell_mapping.uuid) self.commands.discover_hosts(cell_uuid=cell_mapping.uuid)
# Check that the host mappings were created # Check that the host mappings were created
@ -1343,10 +1345,12 @@ class CellV2CommandsTestCase(test.NoDBTestCase):
compute_nodes = self._return_compute_nodes(ctxt, num=2) compute_nodes = self._return_compute_nodes(ctxt, num=2)
# Create the first compute node in cell1's db # Create the first compute node in cell1's db
with context.target_cell(ctxt, cell_mapping1): with context.target_cell(ctxt, cell_mapping1) as cctxt:
compute_nodes[0]._context = cctxt
compute_nodes[0].create() compute_nodes[0].create()
# Create the first compute node in cell2's db # Create the first compute node in cell2's db
with context.target_cell(ctxt, cell_mapping2): with context.target_cell(ctxt, cell_mapping2) as cctxt:
compute_nodes[1]._context = cctxt
compute_nodes[1].create() compute_nodes[1].create()
self.commands.discover_hosts(verbose=True) self.commands.discover_hosts(verbose=True)