Example #1
0
    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
Example #2
0
    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
Example #3
0
    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
Example #4
0
    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