def get_instances_without_type( context: 'nova_context.RequestContext', cell_uuid: ty.Optional[str] = None, ) -> ty.List[objects.instance.Instance]: """Find instances without hw_machine_type set, optionally within a cell. :param context: Request context :param cell_uuid: Optional cell UUID to look within :returns: A list of Instance objects or an empty list """ if cell_uuid: cell_mapping = objects.CellMapping.get_by_uuid(context, cell_uuid) results = nova_context.scatter_gather_single_cell( context, cell_mapping, _get_instances_without_mtype ) results = nova_context.scatter_gather_skip_cell0( context, _get_instances_without_mtype ) # Flatten the returned list of results into a single list of instances return list(itertools.chain(*[r for c, r in results.items()]))
def test_scatter_gather_cells(self): self._create_cell_mappings() # Create an instance in cell0 with context.target_cell(self.context, self.mapping0) as cctxt: instance = objects.Instance(context=cctxt, uuid=uuids.instance0, project_id='fake-project') instance.create() # Create an instance in first cell with context.target_cell(self.context, self.mapping1) as cctxt: instance = objects.Instance(context=cctxt, uuid=uuids.instance1, project_id='fake-project') instance.create() # Create an instance in second cell with context.target_cell(self.context, self.mapping2) as cctxt: instance = objects.Instance(context=cctxt, uuid=uuids.instance2, project_id='fake-project') instance.create() filters = {'deleted': False, 'project_id': 'fake-project'} results = context.scatter_gather_all_cells( self.context, objects.InstanceList.get_by_filters, filters, sort_dir='asc') instances = objects.InstanceList() for result in results.values(): instances = instances + result # Should have 3 instances across cells self.assertEqual(3, len(instances)) # Verify we skip cell0 when specified results = context.scatter_gather_skip_cell0( self.context, objects.InstanceList.get_by_filters, filters) instances = objects.InstanceList() for result in results.values(): instances = instances + result # Should have gotten only the instances from the last two cells self.assertEqual(2, len(instances)) self.assertIn(self.mapping1.uuid, results) self.assertIn(self.mapping2.uuid, results) instance_uuids = [inst.uuid for inst in instances] self.assertIn(uuids.instance1, instance_uuids) self.assertIn(uuids.instance2, instance_uuids) # Try passing one cell results = context.scatter_gather_cells( self.context, [self.mapping1], 60, objects.InstanceList.get_by_filters, filters) instances = objects.InstanceList() for result in results.values(): instances = instances + result # Should have gotten only one instance from cell1 self.assertEqual(1, len(instances)) self.assertIn(self.mapping1.uuid, results) self.assertEqual(uuids.instance1, instances[0].uuid)
def test_scatter_gather_skip_cell0(self, mock_get_all, mock_scatter): ctxt = context.get_context() mapping0 = objects.CellMapping(database_connection='fake://db0', transport_url='none:///', uuid=objects.CellMapping.CELL0_UUID) mapping1 = objects.CellMapping(database_connection='fake://db1', transport_url='fake://mq1', uuid=uuids.cell1) mock_get_all.return_value = objects.CellMappingList( objects=[mapping0, mapping1]) filters = {'deleted': False} context.scatter_gather_skip_cell0( ctxt, objects.InstanceList.get_by_filters, filters, sort_dir='foo') mock_scatter.assert_called_once_with( ctxt, [mapping1], 60, objects.InstanceList.get_by_filters, filters, sort_dir='foo')
def get_marker_record(self, ctx, marker): """Get the marker migration from its cell. This returns the marker migration from the cell in which it lives """ results = context.scatter_gather_skip_cell0( ctx, db.migration_get_by_uuid, marker) db_migration = None for result_cell_uuid, result in results.items(): if not context.is_cell_failure_sentinel(result): db_migration = result cell_uuid = result_cell_uuid break if not db_migration: raise exception.MarkerNotFound(marker=marker) return cell_uuid, db_migration
def get_marker_record(self, ctx, marker): """Get the marker migration from its cell. This returns the marker migration from the cell in which it lives """ results = context.scatter_gather_skip_cell0( ctx, db.migration_get_by_uuid, marker) db_migration = None for result in results.values(): if result not in (context.did_not_respond_sentinel, context.raised_exception_sentinel): db_migration = result break if not db_migration: raise exception.MarkerNotFound(marker=marker) return db_migration
def get_marker_record(self, ctx, marker): """Get the marker migration from its cell. This returns the marker migration from the cell in which it lives """ results = context.scatter_gather_skip_cell0(ctx, db.migration_get_by_uuid, marker) db_migration = None for result in results.values(): if result not in (context.did_not_respond_sentinel, context.raised_exception_sentinel): db_migration = result break if not db_migration: raise exception.MarkerNotFound(marker=marker) return db_migration
def get_marker_record(self, ctx, marker): """Get the marker migration from its cell. This returns the marker migration from the cell in which it lives """ results = context.scatter_gather_skip_cell0(ctx, db.migration_get_by_uuid, marker) db_migration = None for result_cell_uuid, result in results.items(): if not context.is_cell_failure_sentinel(result): db_migration = result cell_uuid = result_cell_uuid break if not db_migration: raise exception.MarkerNotFound(marker=marker) return cell_uuid, db_migration
def _show(self, req, id, rdp_only): """Checks a console auth token and returns the related connect info.""" context = req.environ['nova.context'] context.can(cat_policies.BASE_POLICY_NAME) token = id if not token: msg = _("token not provided") raise webob.exc.HTTPBadRequest(explanation=msg) connect_info = None if CONF.workarounds.enable_consoleauth: connect_info = self._consoleauth_rpcapi.check_token(context, token) else: results = nova_context.scatter_gather_skip_cell0( context, objects.ConsoleAuthToken.validate, token) # NOTE(melwitt): Console token auths are stored in cell databases, # but with only the token as a request param, we can't know which # cell database contains the token's corresponding connection info. # So, we must query all cells for the info and we can break the # loop as soon as we find a result because the token is associated # with one instance, which can only be in one cell. for result in results.values(): if result not in (nova_context.did_not_respond_sentinel, nova_context.raised_exception_sentinel): connect_info = result.to_dict() break if not connect_info: raise webob.exc.HTTPNotFound(explanation=_("Token not found")) console_type = connect_info.get('console_type') if rdp_only and console_type != "rdp-html5": raise webob.exc.HTTPUnauthorized( explanation=_("The requested console type details are not " "accessible")) return { 'console': { i: connect_info[i] for i in ['instance_uuid', 'host', 'port', 'internal_access_path'] if i in connect_info } }
def _show(self, req, id, rdp_only): """Checks a console auth token and returns the related connect info.""" context = req.environ['nova.context'] context.can(cat_policies.BASE_POLICY_NAME) token = id if not token: msg = _("token not provided") raise webob.exc.HTTPBadRequest(explanation=msg) connect_info = None results = nova_context.scatter_gather_skip_cell0( context, objects.ConsoleAuthToken.validate, token) # NOTE(melwitt): Console token auths are stored in cell databases, # but with only the token as a request param, we can't know which # cell database contains the token's corresponding connection info. # So, we must query all cells for the info and we can break the # loop as soon as we find a result because the token is associated # with one instance, which can only be in one cell. for result in results.values(): if not nova_context.is_cell_failure_sentinel(result): connect_info = result break if not connect_info: raise webob.exc.HTTPNotFound(explanation=_("Token not found")) console_type = connect_info.console_type if rdp_only and console_type != "rdp-html5": raise webob.exc.HTTPUnauthorized( explanation=_("The requested console type details are not " "accessible")) return { 'console': { 'instance_uuid': connect_info.instance_uuid, 'host': connect_info.host, 'port': connect_info.port, 'internal_access_path': connect_info.internal_access_path, } }
def _show(self, req, id, rdp_only): """Checks a console auth token and returns the related connect info.""" context = req.environ['nova.context'] context.can(cat_policies.BASE_POLICY_NAME) token = id if not token: msg = _("token not provided") raise webob.exc.HTTPBadRequest(explanation=msg) connect_info = None if CONF.workarounds.enable_consoleauth: connect_info = self._consoleauth_rpcapi.check_token(context, token) else: results = nova_context.scatter_gather_skip_cell0( context, objects.ConsoleAuthToken.validate, token) # NOTE(melwitt): Console token auths are stored in cell databases, # but with only the token as a request param, we can't know which # cell database contains the token's corresponding connection info. # So, we must query all cells for the info and we can break the # loop as soon as we find a result because the token is associated # with one instance, which can only be in one cell. for result in results.values(): if not nova_context.is_cell_failure_sentinel(result): connect_info = result.to_dict() break if not connect_info: raise webob.exc.HTTPNotFound(explanation=_("Token not found")) console_type = connect_info.get('console_type') if rdp_only and console_type != "rdp-html5": raise webob.exc.HTTPUnauthorized( explanation=_("The requested console type details are not " "accessible")) return {'console': {i: connect_info[i] for i in ['instance_uuid', 'host', 'port', 'internal_access_path'] if i in connect_info}}
def _get_instance_group_hosts_all_cells(context, instance_group): def get_hosts_in_cell(cell_context): # NOTE(melwitt): The obj_alternate_context is going to mutate the # cell_instance_group._context and to do this in a scatter-gather # with multiple parallel greenthreads, we need the instance groups # to be separate object copies. cell_instance_group = instance_group.obj_clone() with cell_instance_group.obj_alternate_context(cell_context): return cell_instance_group.get_hosts() results = nova_context.scatter_gather_skip_cell0(context, get_hosts_in_cell) hosts = [] for result in results.values(): # TODO(melwitt): We will need to handle scenarios where an exception # is raised while targeting a cell and when a cell does not respond # as part of the "handling of a down cell" spec: # https://blueprints.launchpad.net/nova/+spec/handling-down-cell if not nova_context.is_cell_failure_sentinel(result): hosts.extend(result) return hosts