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)
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)
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
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
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
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
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
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
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