def create(self, req, body): """Creates a new instance event.""" context = req.environ['nova.context'] authorize(context, action='create') events = [] accepted = [] instances = {} result = 200 body_events = body.get('events', []) if not isinstance(body_events, list) or not len(body_events): raise webob.exc.HTTPBadRequest() for _event in body_events: client_event = dict(_event) event = objects.InstanceExternalEvent(context) try: event.instance_uuid = client_event.pop('server_uuid') event.name = client_event.pop('name') event.status = client_event.pop('status', 'completed') event.tag = client_event.pop('tag', None) except KeyError as missing_key: msg = _('event entity requires key %(key)s') % missing_key raise webob.exc.HTTPBadRequest(explanation=msg) if client_event: msg = (_('event entity contains unsupported items: %s') % ', '.join(client_event.keys())) raise webob.exc.HTTPBadRequest(explanation=msg) if event.status not in external_event_obj.EVENT_STATUSES: raise webob.exc.HTTPBadRequest( _('Invalid event status `%s\'') % event.status) events.append(_event) if event.instance_uuid not in instances: try: instance = objects.Instance.get_by_uuid( context, event.instance_uuid) instances[event.instance_uuid] = instance except exception.InstanceNotFound: LOG.debug( 'Dropping event %(name)s:%(tag)s for unknown ' 'instance %(instance_uuid)s', dict(event.iteritems())) _event['status'] = 'failed' _event['code'] = 404 result = 207 if event.instance_uuid in instances: accepted.append(event) _event['code'] = 200 LOG.audit( _('Create event %(name)s:%(tag)s for instance ' '%(instance_uuid)s'), dict(event.iteritems())) if accepted: self.compute_api.external_instance_event(context, instances.values(), accepted) else: msg = _('No instances found for any event') raise webob.exc.HTTPNotFound(explanation=msg) # FIXME(cyeoh): This needs some infrastructure support so that # we have a general way to do this robj = wsgi.ResponseObject({'events': events}) robj._code = result return robj
def create(self, req, body): """Creates a new instance event.""" context = req.environ['nova.context'] authorize(context, action='create') response_events = [] accepted_events = [] accepted_instances = set() instances = {} result = 200 body_events = body['events'] for _event in body_events: client_event = dict(_event) event = objects.InstanceExternalEvent(context) event.instance_uuid = client_event.pop('server_uuid') event.name = client_event.pop('name') event.status = client_event.pop('status', 'completed') event.tag = client_event.pop('tag', None) instance = instances.get(event.instance_uuid) if not instance: try: instance = objects.Instance.get_by_uuid( context, event.instance_uuid) instances[event.instance_uuid] = instance except exception.InstanceNotFound: LOG.debug( 'Dropping event %(name)s:%(tag)s for unknown ' 'instance %(instance_uuid)s', { 'name': event.name, 'tag': event.tag, 'instance_uuid': event.instance_uuid }) _event['status'] = 'failed' _event['code'] = 404 result = 207 # NOTE: before accepting the event, make sure the instance # for which the event is sent is assigned to a host; otherwise # it will not be possible to dispatch the event if instance: if instance.host: accepted_events.append(event) accepted_instances.add(instance) LOG.info( _LI('Creating event %(name)s:%(tag)s for ' 'instance %(instance_uuid)s'), { 'name': event.name, 'tag': event.tag, 'instance_uuid': event.instance_uuid }) # NOTE: as the event is processed asynchronously verify # whether 202 is a more suitable response code than 200 _event['status'] = 'completed' _event['code'] = 200 else: LOG.debug( "Unable to find a host for instance " "%(instance)s. Dropping event %(event)s", { 'instance': event.instance_uuid, 'event': event.name }) _event['status'] = 'failed' _event['code'] = 422 result = 207 response_events.append(_event) if accepted_events: self.compute_api.external_instance_event(context, accepted_instances, accepted_events) else: msg = _('No instances found for any event') raise webob.exc.HTTPNotFound(explanation=msg) # FIXME(cyeoh): This needs some infrastructure support so that # we have a general way to do this robj = wsgi.ResponseObject({'events': response_events}) robj._code = result return robj
def create(self, req, body): """Creates a new instance event.""" context = req.environ['nova.context'] context.can(see_policies.POLICY_ROOT % 'create') response_events = [] accepted_events = [] accepted_instances = set() result = 200 body_events = body['events'] # Fetch instance objects for all relevant instances instance_uuids = set([event['server_uuid'] for event in body_events]) instance_mappings = objects.InstanceMappingList.get_by_instance_uuids( context, list(instance_uuids)) instances = self._get_instances_all_cells(context, instance_uuids, instance_mappings) for _event in body_events: client_event = dict(_event) event = objects.InstanceExternalEvent(context) event.instance_uuid = client_event.pop('server_uuid') event.name = client_event.pop('name') event.status = client_event.pop('status', 'completed') event.tag = client_event.pop('tag', None) response_events.append(_event) instance = instances.get(event.instance_uuid) if not instance: LOG.debug( 'Dropping event %(name)s:%(tag)s for unknown ' 'instance %(instance_uuid)s', { 'name': event.name, 'tag': event.tag, 'instance_uuid': event.instance_uuid }) _event['status'] = 'failed' _event['code'] = 404 result = 207 continue # NOTE: before accepting the event, make sure the instance # for which the event is sent is assigned to a host; otherwise # it will not be possible to dispatch the event if not self._is_event_tag_present_when_required(event): LOG.debug( "Event tag is missing for instance " "%(instance)s. Dropping event %(event)s", { 'instance': event.instance_uuid, 'event': event.name }) _event['status'] = 'failed' _event['code'] = 400 result = 207 elif instance.host: accepted_events.append(event) accepted_instances.add(instance) LOG.info( 'Creating event %(name)s:%(tag)s for ' 'instance %(instance_uuid)s on %(host)s', { 'name': event.name, 'tag': event.tag, 'instance_uuid': event.instance_uuid, 'host': instance.host }) # NOTE: as the event is processed asynchronously verify # whether 202 is a more suitable response code than 200 _event['status'] = 'completed' _event['code'] = 200 else: LOG.debug( "Unable to find a host for instance " "%(instance)s. Dropping event %(event)s", { 'instance': event.instance_uuid, 'event': event.name }) _event['status'] = 'failed' _event['code'] = 422 result = 207 if accepted_events: self.compute_api.external_instance_event(context, accepted_instances, accepted_events) else: msg = _('No instances found for any event') raise webob.exc.HTTPNotFound(explanation=msg) # FIXME(cyeoh): This needs some infrastructure support so that # we have a general way to do this robj = wsgi.ResponseObject({'events': response_events}) robj._code = result return robj
def create(self, req, body): """Creates a new instance event.""" context = req.environ['nova.context'] context.can(see_policies.POLICY_ROOT % 'create') response_events = [] accepted_events = [] accepted_instances = set() instances = {} mappings = {} result = 200 body_events = body['events'] for _event in body_events: client_event = dict(_event) event = objects.InstanceExternalEvent(context) event.instance_uuid = client_event.pop('server_uuid') event.name = client_event.pop('name') event.status = client_event.pop('status', 'completed') event.tag = client_event.pop('tag', None) instance = instances.get(event.instance_uuid) if not instance: try: mapping = objects.InstanceMapping.get_by_instance_uuid( context, event.instance_uuid) cell_mapping = mapping.cell_mapping mappings[event.instance_uuid] = cell_mapping # Load migration_context and info_cache here in a single DB # operation because we need them later on with nova_context.target_cell(context, cell_mapping) as cctxt: instance = objects.Instance.get_by_uuid( cctxt, event.instance_uuid, expected_attrs=['migration_context', 'info_cache']) instances[event.instance_uuid] = instance except (exception.InstanceNotFound, exception.InstanceMappingNotFound): LOG.debug( 'Dropping event %(name)s:%(tag)s for unknown ' 'instance %(instance_uuid)s', { 'name': event.name, 'tag': event.tag, 'instance_uuid': event.instance_uuid }) _event['status'] = 'failed' _event['code'] = 404 result = 207 # NOTE: before accepting the event, make sure the instance # for which the event is sent is assigned to a host; otherwise # it will not be possible to dispatch the event if instance: if instance.host: accepted_events.append(event) accepted_instances.add(instance) LOG.info( 'Creating event %(name)s:%(tag)s for ' 'instance %(instance_uuid)s on %(host)s', { 'name': event.name, 'tag': event.tag, 'instance_uuid': event.instance_uuid, 'host': instance.host }) # NOTE: as the event is processed asynchronously verify # whether 202 is a more suitable response code than 200 _event['status'] = 'completed' _event['code'] = 200 else: LOG.debug( "Unable to find a host for instance " "%(instance)s. Dropping event %(event)s", { 'instance': event.instance_uuid, 'event': event.name }) _event['status'] = 'failed' _event['code'] = 422 result = 207 response_events.append(_event) if accepted_events: self.compute_api.external_instance_event(context, accepted_instances, mappings, accepted_events) else: msg = _('No instances found for any event') raise webob.exc.HTTPNotFound(explanation=msg) # FIXME(cyeoh): This needs some infrastructure support so that # we have a general way to do this robj = wsgi.ResponseObject({'events': response_events}) robj._code = result return robj
def create(self, req, body): """Creates a new instance event.""" context = req.environ['nova.context'] authorize(context, action='create') response_events = [] accepted_events = [] accepted_instances = set() instances = {} result = 200 body_events = body.get('events', []) if not isinstance(body_events, list) or not len(body_events): raise webob.exc.HTTPBadRequest() for _event in body_events: client_event = dict(_event) event = objects.InstanceExternalEvent(context) try: event.instance_uuid = client_event.pop('server_uuid') event.name = client_event.pop('name') event.status = client_event.pop('status', 'completed') event.tag = client_event.pop('tag', None) except KeyError as missing_key: msg = _('event entity requires key %(key)s') % missing_key raise webob.exc.HTTPBadRequest(explanation=msg) if client_event: msg = (_('event entity contains unsupported items: %s') % ', '.join(client_event.keys())) raise webob.exc.HTTPBadRequest(explanation=msg) if event.status not in external_event_obj.EVENT_STATUSES: raise webob.exc.HTTPBadRequest( _('Invalid event status `%s\'') % event.status) instance = instances.get(event.instance_uuid) if not instance: try: instance = objects.Instance.get_by_uuid( context, event.instance_uuid) instances[event.instance_uuid] = instance except exception.InstanceNotFound: LOG.debug( 'Dropping event %(name)s:%(tag)s for unknown ' 'instance %(instance_uuid)s', dict(event.iteritems())) _event['status'] = 'failed' _event['code'] = 404 result = 207 # NOTE: before accepting the event, make sure the instance # for which the event is sent is assigned to a host; otherwise # it will not be possible to dispatch the event if instance: if instance.host: accepted_events.append(event) accepted_instances.add(instance) LOG.audit( _('Creating event %(name)s:%(tag)s for instance ' '%(instance_uuid)s'), dict(event.iteritems())) # NOTE: as the event is processed asynchronously verify # whether 202 is a more suitable response code than 200 _event['status'] = 'completed' _event['code'] = 200 else: LOG.debug( "Unable to find a host for instance " "%(instance)s. Dropping event %(event)s", { 'instance': event.instance_uuid, 'event': event.name }) _event['status'] = 'failed' _event['code'] = 422 result = 207 response_events.append(_event) if accepted_events: self.compute_api.external_instance_event(context, accepted_instances, accepted_events) else: msg = _('No instances found for any event') raise webob.exc.HTTPNotFound(explanation=msg) # FIXME(cyeoh): This needs some infrastructure support so that # we have a general way to do this robj = wsgi.ResponseObject({'events': response_events}) robj._code = result return robj