Beispiel #1
0
    def get(self, request):
        """List all Category instance registered in the system"""
        # Parse request
        try:
            parser, renderer = self._request_init(request)
        except HttpRequestError as e:
            return e.response

        # Category filter
        categories = []
        if not parser.objects or not parser.objects[0].categories:
            categories = self.backend.registry.all()
        else:
            for category in parser.objects[0].categories:
                try:
                    category = self.backend.registry.lookup_id(str(category))
                except Category.DoesNotExist:
                    return hrc.NOT_FOUND('%s: Category not found' % category)
                else:
                    categories.append(category)

        dao = DataObject(translator=self.translator, categories=categories)
        dao.render_flags['category_discovery'] = True

        # Render response
        renderer.render(dao)
        return HttpResponse(renderer.headers, renderer.body)
Beispiel #2
0
    def get(self, request):
        """List all Category instance registered in the system"""
        # Parse request
        try:
            parser, renderer = self._request_init(request)
        except HttpRequestError as e:
            return e.response

        # Category filter
        categories = []
        if not parser.objects or not parser.objects[0].categories:
            categories = self.backend.registry.all()
        else:
            for category in parser.objects[0].categories:
                try:
                    category = self.backend.registry.lookup_id(str(category))
                except Category.DoesNotExist:
                    return hrc.NOT_FOUND("%s: Category not found" % category)
                else:
                    categories.append(category)

        dao = DataObject(translator=self.translator, categories=categories)
        dao.render_flags["category_discovery"] = True

        # Render response
        renderer.render(dao)
        return HttpResponse(renderer.headers, renderer.body)
Beispiel #3
0
    def get(self, request, path):
        """Retrieve a resource instance."""

        try:
            location, entity_id = path.rsplit("/", 1)
        except ValueError:
            location = None
            entity_id = path

        if location:
            location_category = self.backend.registry.lookup_location(location)
        else:
            location_category = None

        try:
            parser, renderer = self._request_init(request)
            entity = self._get_entity(entity_id, user=request.user)
        except HttpRequestError as e:
            return e.response

        if (
            location_category
            and location_category != entity.occi_get_kind()
            and location_category in entity.occi_get_mixins()
        ):
            return hrc.NOT_FOUND()

        dao = DataObject(translator=self.translator)
        dao.load_from_entity(entity)
        renderer.render(dao)

        return HttpResponse(renderer.headers, renderer.body)
Beispiel #4
0
    def get(self, request, path):
        """Retrieve a resource instance."""

        try:
            location, entity_id = path.rsplit('/', 1)
        except ValueError:
            location = None
            entity_id = path

        if location:
            location_category = self.backend.registry.lookup_location(location)
        else:
            location_category = None

        try:
            parser, renderer = self._request_init(request)
            entity = self._get_entity(entity_id, user=request.user)
        except HttpRequestError as e:
            return e.response

        if (location_category and location_category != entity.occi_get_kind()
                and location_category in entity.occi_get_mixins()):
            return hrc.NOT_FOUND()

        dao = DataObject(translator=self.translator)
        dao.load_from_entity(entity)
        renderer.render(dao)

        return HttpResponse(renderer.headers, renderer.body)
Beispiel #5
0
    def get(self, request, path):
        """Get the resource instances in the specified `Kind` collection"""

        # Lookup location path
        categories = self.backend.registry.lookup_recursive(path or '')

        # Parse request
        try:
            parser, renderer = self._request_init(request)
        except HttpRequestError as e:
            return e.response

        # Retrieve resource instances from backend
        entities = []
        try:
            for category in categories:
                if isinstance(category, Kind):
                    entities.extend(self._filter_entities(categories=[category],
                            dao_filter=parser.objects, user=request.user))
        except HttpRequestError as e:
            return e.response

        # Render response
        objects = []
        for entity in entities:
            dao = DataObject(translator=self.translator)
            dao.load_from_entity(entity)
            objects.append(dao)
        renderer.render(objects)

        return HttpResponse(renderer.headers, renderer.body)
Beispiel #6
0
    def get(self, request):
        """List all Category instance registered in the system"""
        # Parse request
        try:
            parser, renderer = self._request_init(request)
        except HttpRequestError as e:
            return e.response

        dao = DataObject(translator=self.translator,
                categories=self.backend.registry.all())
        dao.render_flags['category_discovery'] = True

        # Render response
        renderer.render(dao)
        return HttpResponse(renderer.headers, renderer.body)
Beispiel #7
0
 def parse(self, headers=None, body=None):
     super(TextURIListParser, self).parse(headers, body)
     body = body or ''
     for loc in body.replace('\r', '').split('\n'):
         loc = loc.strip()
         if loc:
             self.objects.append(DataObject(location=loc))
Beispiel #8
0
    def get(self, request, path):
        """Get the resource instances in the specified collection"""

        # Lookup location path
        categories = self.backend.registry.lookup_recursive(path or '')

        # If path is not a Kind/Mixin location filter out everything but Kind
        # categories
        if len(categories) > 1:
            t = []
            for category in categories:
                if isinstance(category, Kind):
                    t.append(category)
            categories = t

        # Parse request
        try:
            parser, renderer = self._request_init(request)
        except HttpRequestError as e:
            return e.response

        # Retrieve resource instances from backend
        entities = []
        try:
            for category in categories:
                entities.extend(
                    self._filter_entities(categories=[category],
                                          dao_filter=parser.objects,
                                          user=request.user))

        except HttpRequestError as e:
            return e.response

        # Render response
        objects = []
        for entity in entities:
            dao = DataObject(translator=self.translator)
            dao.load_from_entity(entity)
            objects.append(dao)
        renderer.render(objects)

        return HttpResponse(renderer.headers, renderer.body)
Beispiel #9
0
    def parse(self, headers=None, body=None):
        categories = []
        links = []
        attributes = []
        locations = []

        # Walk list of HTTP header name-value pairs
        for name, value in headers or ():
            name = name.lower()

            if name == 'accept':
                self._parse_accept_header(value)
            elif name == 'category':
                categories.extend(self._parse_category_header(value))
            elif name == 'link':
                # FIXME - not allowing Link create/update using POST/PUT yet
                pass
            elif name == 'x-occi-attribute':
                attribute_headers = HttpAttributeHeaders()
                attribute_headers.parse(value)
                attributes.extend(attribute_headers.all())
            elif name == 'x-occi-location':
                location_headers = HttpHeadersBase()
                location_headers.parse(value)
                locations.extend(location_headers.all())

        # Only possible to represent one "full" data object with HTTP Headers.
        # Multiple data objects can only be represented with a location.
        locations = locations or [None]
        self.objects.append(DataObject(
            categories=categories,
            links=links,
            attributes=attributes,
            location=locations[0]))
        for loc in locations[1:]:
            self.objects.append(DataObject(location=loc))
Beispiel #10
0
    def _post_update(self, request, entity_id):
        """Update an existing resource instance."""
        # Parse request
        try:
            parser, renderer = self._request_init(request)
            entity = self._get_entity(entity_id, user=request.user)
        except HttpRequestError as e:
            return e.response

        # Only a single data object allowed
        if not parser.objects:
            return hrc.BAD_REQUEST('No resource instance specified')
        elif len(parser.objects) > 1:
            return hrc.BAD_REQUEST('More than one resource instance specified')
        dao = parser.objects[0]
        dao.translator = self.translator

        # Update entity object from request data
        try:
            dao.save_to_entity(entity=entity,
                               category_registry=self.backend.registry)
        except DataObject.Invalid as e:
            return hrc.BAD_REQUEST(e)

        # Save the updated entity object
        try:
            id_list = self._save_entities([entity], user=request.user)
        except HttpRequestError as e:
            return e.response

        # Response is a list of locations
        dao_list = []
        for entity_id in id_list:
            dao_list.append(
                DataObject(location=self.translator.from_native(entity_id)))

        # Render response
        renderer.render(dao_list)

        # Set Location header to the first ID
        renderer.headers.append(
            ('Location', self.translator.from_native(id_list[0])))

        return HttpResponse(renderer.headers, renderer.body)
Beispiel #11
0
    def _update_collection(self, request, location_category, replace=False):
        # Parse request
        try:
            parser, renderer = self._request_init(request)
        except HttpRequestError as e:
            return e.response

        # Any data-objects submitted?
        if not parser.objects:
            return hrc.BAD_REQUEST("No resource instance(s) specified")

        # Entities to update and delete
        entities_updated = {}
        entities_deleted = {}

        # Only possible to replace a pure Kind/Mixin location
        if replace:
            assert location_category
            # When replacing the whole collection we need to:
            #  - Remove the all entities of Kind not part of the update.
            #  - Remove the Mixin from all entities not part of the update.
            try:
                if isinstance(location_category, Kind):
                    for entity in self._filter_entities(categories=[location_category], user=request.user):
                        entities_deleted[entity_id] = True
                elif isinstance(location_category, Mixin):
                    for entity in self._filter_entities(categories=[location_category], user=request.user):
                        try:
                            entity.occi_remove_mixin(location_category)
                        except Entity.UnknownCategory:
                            pass
                        else:
                            entities_updated[entity.id] = entity
            except HttpRequestError as e:
                return e.response

        # Convert request objects to entity instances
        try:
            for dao in parser.objects:
                # Add location category to entity dao
                if location_category:
                    dao.categories.append(location_category)
                dao.translator = self.translator

                # Get Entity ID from request
                entity_id = dao.get_entity_id()

                # COMPAT: OCCI HTTP Rendering 1.1 does not threat PUT
                # /mixin_loc/ as a resource create/replace operation.
                # Use non-replace mode as workaround.
                _do_replace = replace
                if replace and parser.specification() in ("occi-http-1.1"):
                    _do_replace = False

                # Attempt to load existing Entity
                if entity_id and not _do_replace:
                    try:
                        entity = entities_updated[entity_id]
                    except KeyError:
                        entity = self._get_entity(entity_id, user=request.user)
                else:
                    entity = None

                # Create/update entity object
                # FIXME: If replacing the entity we leave all links untouched.
                # This is according to spec but is it convenient?
                entity = dao.save_to_entity(
                    entity=entity, save_links=(not replace), category_registry=self.backend.registry
                )
                entities_updated[entity.id] = entity
                entities_deleted.pop(entity.id, None)

                # Add Link objects to list of modified entities
                if hasattr(entity, "links"):
                    for link in entity.links:
                        entities_updated[link.id] = link
        except DataObject.Invalid as e:
            return hrc.BAD_REQUEST(e)
        except HttpRequestError as e:
            return e.response

        # Save (and delete) all affected entities using a single backend operation
        try:
            entities = self._save_entities(
                entities_updated.values(), delete_entity_ids=entities_deleted.keys(), user=request.user
            )
        except HttpRequestError as e:
            return e.response

        # Response is a list of created/updated entities
        dao_list = []
        for entity in entities:
            dao = DataObject(translator=self.translator)
            dao.load_from_entity(entity)
            dao_list.append(dao)

        # Render response
        if len(dao_list) == 1:
            renderer.render(dao_list[0])
        else:
            renderer.render(dao_list)

        # Set Location header to the first ID
        renderer.headers.append(("Location", dao_list[0].location))

        return HttpResponse(renderer.headers, renderer.body)
Beispiel #12
0
    def _update_collection(self, request, location_category, replace=False):
        # Parse request
        try:
            parser, renderer = self._request_init(request)
        except HttpRequestError as e:
            return e.response

        # Any data-objects submitted?
        if not parser.objects:
            return hrc.BAD_REQUEST('No resource instance(s) specified')

        # Entities to update and delete
        entities_updated = {}
        entities_deleted = {}

        # Only possible to replace a pure Kind/Mixin location
        if replace:
            assert (location_category)
            # When replacing the whole collection we need to:
            #  - Remove the all entities of Kind not part of the update.
            #  - Remove the Mixin from all entities not part of the update.
            try:
                if isinstance(location_category, Kind):
                    for entity in self._filter_entities(
                            categories=[location_category], user=request.user):
                        entities_deleted[entity_id] = True
                elif isinstance(location_category, Mixin):
                    for entity in self._filter_entities(
                            categories=[location_category], user=request.user):
                        try:
                            entity.occi_remove_mixin(location_category)
                        except Entity.UnknownCategory:
                            pass
                        else:
                            entities_updated[entity.id] = entity
            except HttpRequestError as e:
                return e.response

        # Convert request objects to entity instances
        try:
            for dao in parser.objects:
                # Add location category to entity dao
                if location_category:
                    dao.categories.append(location_category)
                dao.translator = self.translator

                # Get Entity ID from request
                entity_id = dao.get_entity_id()

                # COMPAT: OCCI HTTP Rendering 1.1 does not threat PUT
                # /mixin_loc/ as a resource create/replace operation.
                # Use non-replace mode as workaround.
                _do_replace = replace
                if replace and parser.specification() in ('occi-http-1.1'):
                    _do_replace = False

                # Attempt to load existing Entity
                if entity_id and not _do_replace:
                    try:
                        entity = entities_updated[entity_id]
                    except KeyError:
                        entity = self._get_entity(entity_id, user=request.user)
                else:
                    entity = None

                # Create/update entity object
                # FIXME: If replacing the entity we leave all links untouched.
                # This is according to spec but is it convenient?
                entity = dao.save_to_entity(
                    entity=entity,
                    save_links=(not replace),
                    category_registry=self.backend.registry)
                entities_updated[entity.id] = entity
                entities_deleted.pop(entity.id, None)

                # Add Link objects to list of modified entities
                if hasattr(entity, 'links'):
                    for link in entity.links:
                        entities_updated[link.id] = link
        except DataObject.Invalid as e:
            return hrc.BAD_REQUEST(e)
        except HttpRequestError as e:
            return e.response

        # Save (and delete) all affected entities using a single backend operation
        try:
            entities = self._save_entities(
                entities_updated.values(),
                delete_entity_ids=entities_deleted.keys(),
                user=request.user)
        except HttpRequestError as e:
            return e.response

        # Response is a list of created/updated entities
        dao_list = []
        for entity in entities:
            dao = DataObject(translator=self.translator)
            dao.load_from_entity(entity)
            dao_list.append(dao)

        # Render response
        if len(dao_list) == 1:
            renderer.render(dao_list[0])
        else:
            renderer.render(dao_list)

        # Set Location header to the first ID
        renderer.headers.append(('Location', dao_list[0].location))

        return HttpResponse(renderer.headers, renderer.body)
Beispiel #13
0
    def post(self, request, path):
        """Create or update resource instance(s) OR execute an action on the
        specified collection.
        """
        # Lookup location path
        location_category = self.backend.registry.lookup_location(path)

        # Action request?
        if request.query_args:
            if not location_category:
                return hrc.BAD_REQUEST('%s: not a Kind nor Mixin location' % path)
            return self._collection_action(request, location_category)

        # Parse request
        try:
            parser, renderer = self._request_init(request)
        except HttpRequestError as e:
            return e.response

        # Any data-objects submitted?
        if not parser.objects:
            return hrc.BAD_REQUEST('No resource instance(s) specified')

        # Convert request objects to entity instances
        entities = []
        try:
            for dao in parser.objects:
                # Add location category to entity dao
                if location_category:
                    dao.categories.append(location_category)
                dao.translator = self.translator

                # Entity ID specified in request?
                entity_id = None
                if dao.attributes:
                    for attr, value in dao.attributes:
                        if attr == 'occi.core.id':
                            entity_id = value
                elif dao.location:
                    entity = self.translator.to_native(dao.location)
                    if entity: entity_id = entity.id

                # Attempt to load existing Entity
                if entity_id:
                    entity = self._get_entity(entity_id, user=request.user)
                else:
                    entity = None

                # Create/update entity object
                entity = dao.save_to_entity(entity=entity, save_links=True,
                        category_registry=self.backend.registry)
                entities.append(entity)

                # Add Link objects to list of modified entities
                if hasattr(entity, 'links'):
                    for link in entity.links:
                        entities.append(link)
        except DataObject.Invalid as e:
            return hrc.BAD_REQUEST(e)
        except HttpRequestError as e:
            return e.response

        # Save all entities using a single backend operation
        try:
            entities = self._save_entities(entities, user=request.user)
        except HttpRequestError as e:
            return e.response

        # Response is a list of created/updated entities
        dao_list = []
        for entity in entities:
            dao = DataObject(translator=self.translator)
            dao.load_from_entity(entity)
            dao_list.append(dao)

        # Render response
        if len(dao_list) == 1:
            renderer.render(dao_list[0])
        else:
            renderer.render(dao_list)

        # Set Location header to the first ID
        renderer.headers.append(('Location', dao_list[0].location))

        return HttpResponse(renderer.headers, renderer.body)