Пример #1
0
    def DELETE(self, env, start_response):
        """
        Handle DELETE both container and data object removal.
        """

        path = '/v1/' + self.account_name + '/' + self.container_name
        query_string = 'delimiter=/'
        if self.object_name:
            query_string += '&prefix=' + concat_parts(self.parent_name,
                                                      self.object_name) + '/'
        exists, dummy, body = check_resource(env, 'GET', path, self.logger,
                                             True, query_string)
        # Not even the top container exist, so there is no such resource.
        if not exists:
            return get_err_response('NoSuchKey')
        # Top container exists, check if there is anything under.
        else:
            try:
                children = json.loads(body)
                #there are some children under
                if len(children) > 0:
                    return get_err_response('ContainerNotEmpty')
            except ValueError:
                return get_err_response('InconsistantState')

        # Create a new WebOb Request object according to the current request
        req = Request(env)
        # Now send the request over.
        return req.get_response(self.app)
Пример #2
0
    def __call__(self, env, start_response):

        path = unquote(env.get("PATH_INFO", ""))
        cdmi_version = env.get("HTTP_X_CDMI_SPECIFICATION_VERSION", False)
        method = env.get("REQUEST_METHOD").upper()
        # All CDMI requests have to have header with
        # the X-CDMI-Specification-Version
        if cdmi_version and self.cdmi_version_supported.find(cdmi_version) < 0:
            return get_err_response("VersionNotSupported")(env, start_response)

        # All non-CDMI request should not have the header
        # We use this header as the identifier to identify CDMI request.
        try:
            account, controller, path_parts = self.get_controller(env, path, cdmi_version, method)
        except ValueError:
            return get_err_response("InvalidURI")(env, start_response)

        if controller is not None:
            controller = controller(env, self.conf, self.app, self.logger, account, **path_parts)
            if hasattr(controller, method) and not method.startswith("_"):
                res = getattr(controller, method)(env, start_response)
                return res(env, start_response)
            else:
                return get_err_response("BadRequest")(env, start_response)
        # Not CDMI request, move on
        else:
            return self.app(env, start_response)
Пример #3
0
    def PUT(self, env, start_response):
        """ Handle non-CDMI Object update and create request. """

        # First check if the resource exists and if it is a directory
        path = '/' + concat_parts('v1', self.account_name, self.container_name,
                                  self.parent_name, self.object_name)

        exists, headers, body = check_resource(env, 'HEAD', path, self.logger,
                                               False, None)

        if exists:
            content_type = headers.get('content-type', '')
            content_type = content_type.lower() if content_type else ''
            if content_type.find('application/directory') >= 0:
                return get_err_response('Conflict')
        else:
            path = '/' + concat_parts('v1', self.account_name,
                                      self.container_name)

            query_string = 'delimiter=/&prefix=' + \
                concat_parts(self.parent_name, self.object_name) + '/'

            parent_exists, dummy, body = check_resource(env, 'GET', path,
                                                        self.logger, True,
                                                        query_string)

            if parent_exists:
                try:
                    children = json.loads(body)
                    if len(children) > 0:
                        #No children under, no resource exist
                        return get_err_response('Conflict')
                except ValueError:
                    return get_err_response('InconsistantState')
            else:
                return get_err_response('NoParentContainer')

        # Check if the parent is OK. it should be either a real directory
        # or a virtual directory
        res = self._check_parent(env, start_response)
        if res:
            return res

        # Create a new WebOb Request object according to the current request
        req = Request(env)

        if not req.body or len(req.body) == 0:
            req.headers['content-length'] = '0'
        res = req.get_response(self.app)
        return res
Пример #4
0
    def PUT(self, env, start_response):
        """ Handle Container update and create request """

        # First check if the resource exists and if it is a directory
        path = '/' + concat_parts('v1', self.account_name, self.container_name,
                                  self.parent_name, self.object_name)

        exists, headers, body = check_resource(env, 'HEAD', path,
                                               self.logger, False)

        if exists:
            content_type = headers.get('content-type', '')
            content_type = content_type.lower() if content_type else ''
            if (content_type.find('application/directory') < 0 and
                self.object_name):
                return get_err_response('Conflict')
        else:
            res = self._check_parent(env, start_response)
            if res:
                return res

        req = Request(env)
        req.headers['content-type'] = 'application/directory'
        req.headers['content-length'] = '0'
        req.body = ''
        res = req.get_response(self.app)
        return res
Пример #5
0
    def _check_parent(self, env, start_response):
        """
        This method checks if the parent really represents a directory.
        Returns error if parent does not exist or the parent actually points
        to a non directory. Returns None means that the parent points to a
        valid container (top container or virtual container)
        """
        if self.parent_name:
            # Try to hit the resource url and see if it exists
            path = '/' + concat_parts('v1', self.account_name,
                                      self.container_name, self.parent_name)
            exists, headers, dummy = check_resource(env, 'HEAD',
                                                    path, self.logger)
            if exists:
                content_type = str(headers.get('content-type', ''))
                if content_type.find('application/directory') < 0:
                    return get_err_response('InvalidContainerName')
                else:
                    return None
            else:
                # Check if there is anything below that parent, if it is,
                # then this is actually a virtual container.
                path = '/' + concat_parts('v1', self.account_name,
                                          self.container_name)
                query_string = 'delimiter=/&prefix=' + self.parent_name + '/'
                parent_exists, dummy, body = check_resource(env, 'GET', path,
                                                            self.logger, True,
                                                            query_string)
                if parent_exists:
                    try:
                        children = json.loads(body)
                        if len(children) <= 0:
                            # No children under, no resource exist
                            return get_err_response('NoParentContainer')
                        else:
                            return None
                    except ValueError:
                        return get_err_response('InconsistantState')
                # The root container does not event exist, this is an error
                else:
                    return get_err_response('NoParentContainer')

        return None
Пример #6
0
    def _read_entity(self, env, start_response):
        res, is_container, headers, children = \
            self._check_resource_attribute(env, start_response)

        if res is None:
            if ((is_container and not env.get('X-WANTS-CONTAINER')) or
                (not is_container and env.get('X-WANTS-CONTAINER'))):
                return get_err_response('Conflict')

            if is_container:
                return self._read_container(env, start_response,
                                            headers, children)
            else:
                return self._read_object(env, start_response, headers)
        else:
            return res
Пример #7
0
    def PUT(self, env, start_response):
        """
        Handle Container update and create request
        """

        # First check if the resource exists and if it is a directory
        path = '/' + concat_parts('v1', self.account_name, self.container_name,
                                  self.parent_name, self.object_name)
        exists, headers, dummy = check_resource(env, 'HEAD', path,
                                                self.logger, False)
        if exists:
            content_type = headers.get('content-type', '')
            content_type = content_type.lower() if content_type else ''
            if (content_type.find('application/directory') < 0 and
                self.object_name):
                return get_err_response('Conflict')
        # Not a top container, so it has to be virtual container
        else:
            res = self._check_parent(env, start_response)
            if res:
                return res

        # Create a new WebOb Request object according to the current request
        req = Request(env)

        # We are creating a container, set the content-type to be
        # application/directory
        req.headers['content-type'] = 'application/directory'

        metadata = {}
        if req.body:
            try:
                body = json.loads(req.body)
            except ValueError:
                return get_err_response('InvalidContent')

            metadata = body.get('metadata')
            if metadata:
                for key in metadata:
                    if metadata[key] == '':
                        req.headers[self.metadata_prefix + key] = ''
                    else:
                        req.headers[self.metadata_prefix + key] = \
                            key + ":" + str(metadata[key])
            else:
                metadata = {}

        # Now set the body to be empty and content-length to 0
        req.body = ''
        req.headers['Content-Length'] = 0

        res = req.get_response(self.app)

        # Deal with the response now.
        # Build the response message body according to CDMI specification
        # if the response status is 201, then we know we have successfully
        # created the container. According to CDMI spec, only send response
        # body when creating new container
        if res.status_int == 201:
            body = {}
            body['objectType'] = Consts.CDMI_APP_CONTAINER
            body['objectName'] = self.object_name if self.object_name else \
                self.container_name
            if self.object_name:
                body['parentURI'] = concat_parts(self.account_name,
                                                 self.container_name,
                                                 self.parent_name) + '/'
            else:
                body['parentURI'] = self.account_name + '/'
            body['completionStatus'] = 'Complete'
            body['metadata'] = metadata
            res.body = json.dumps(body, indent=2)
        # Otherwise, no body should be returned.
        else:
            res.body = ''

        return res
Пример #8
0
    def PUT(self, env, start_response):
        """
        Handle Container update and create request
        """
        # First check if the resource exists and if it is a directory
        path = '/' + concat_parts('v1', self.account_name, self.container_name,
                                  self.parent_name, self.object_name)
        exists, headers, body = check_resource(env, 'HEAD', path, self.logger,
                                               False, None)
        if exists:
            content_type = headers.get('content-type', '')
            content_type = content_type.lower() if content_type else ''
            if content_type.find('application/directory') >= 0:
                return get_err_response('Conflict')
        else:
            path = '/' + concat_parts('v1', self.account_name,
                                      self.container_name)
            query_string = 'delimiter=/&prefix=' + \
                concat_parts(self.parent_name, self.object_name) + '/'
            parent_exists, dummy, body = check_resource(env, 'GET', path,
                                                        self.logger, True,
                                                        query_string)
            if parent_exists:
                try:
                    children = json.loads(body)
                    if len(children) > 0:
                        # No children under, no resource exist
                        return get_err_response('Conflict')
                except ValueError:
                    return get_err_response('InconsistantState')
            else:
                return get_err_response('NoParentContainer')

        # Check if the parent is OK. it should be either a real directory or
        # a virtual directory
        res = self._check_parent(env, start_response)
        if res:
            return res

        # Create a new WebOb Request object according to the current request
        req = Request(env)

        metadata = {}
        if req.body:
            try:
                body = json.loads(req.body)
            except ValueError:
                return get_err_response('InvalidContent')

            if body.get('metadata'):
                metadata = body['metadata']
                for key in metadata:
                    if metadata[key] == '':
                        req.headers[Consts.META_OBJECT_ID + key] = ''
                    else:
                        req.headers[Consts.META_OBJECT_ID + key] = \
                            key + ":" + str(metadata[key])
            else:
                metadata = {}

            try:
                req.body = str(body.get('value', ''))
                req.headers['content-type'] = body.get('mimetype',
                                                       'text/plain')
                req.headers[Consts.VALUE_ENCODING] = \
                    body.get('valuetransferencoding', 'utf-8')
            except KeyError:
                return get_err_response('InvalidContent')
        else:
            req.headers['content-length'] = '0'

        res = req.get_response(self.app)

        # Deal with the response now.
        # Build the response message body according to CDMI specification
        # If the response status is 201, then we know we have successfully
        # created the object. According to CDMI spec, only send response body
        # when creating new object.
        if res.status_int == 201:
            body = {}
            body['objectType'] = Consts.CDMI_APP_OBJECT
            body['objectName'] = self.object_name
            body['parentURI'] = concat_parts(self.account_name,
                                             self.container_name,
                                             self.parent_name) + '/'
            body['completionStatus'] = 'Complete'
            body['metadata'] = metadata
            res.body = json.dumps(body, indent=2)
        # Otherwise, no response body should be returned.
        else:
            res.body = ''

        return res
Пример #9
0
    def _check_resource_attribute(self, env, start_response):
        """
        This method checks if a given url points to either a container, or
        an object or does not exist. It will also check if a resource is a
        virtual container in CDMI term. If a resource exists, the headers
        will also be return in following sequence.
        res - The response which containers errors, None means there is no
        error
        is_container - if it is a container, it is True, otherwise, it is
        False
        headers - if the resource exists, this holds the headers
        children - if it is a container, return container's child list
        """
        path = env['PATH_INFO']
        res, is_container, headers, children = None, False, {}, None
        exists, headers, dummy = check_resource(env, 'HEAD', path, self.logger)
        # If exists, we need to check if the resource is a container
        if exists:
            content_type = (headers.get('content-type') or '').lower()
            if (content_type.find('application/directory') < 0 and
                self.object_name):
                is_container = False
            else:
                is_container = True
        # None self.object_name means that we are dealing with a real OS
        # container, return resource not found error
        elif not self.object_name:
            res = get_err_response('NoSuchKey')

        if res is None and (not exists or is_container):
            # Now we will try to get the children of the container and also
            # do more checks to see if there is any virtual resources.
            path = '/' + concat_parts('v1', self.account_name,
                                      self.container_name)
            query_string = 'delimiter=/'
            if self.object_name:
                query_string += ('&prefix=' +
                                 concat_parts(self.parent_name,
                                              self.object_name) +
                                 '/')

            container_exists, dummy, body = check_resource(env, 'GET', path,
                                                           self.logger, True,
                                                           query_string)
            if container_exists:
                try:
                    children = json.loads(body)
                    no_of_children = len(children)
                    # The entity could be a virtual container since it
                    # does not exist
                    if not exists:
                        # There is no children under also not exists,
                        # it is not virtual container.
                        if no_of_children <= 0:
                            res = get_err_response('NoSuchKey')
                        # There are children under and not exist, it is
                        # a virtual container
                        elif no_of_children > 0 and not exists:
                            is_container = True
                except ValueError:
                    res = get_err_response('InconsistantState')
            else:
                res = get_err_response('NoSuchKey')

        self.logger.info('is_container=' + str(is_container))
        self.logger.info(res)
        return res, is_container, headers, children