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, "GET", 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") return res, is_container, headers, children
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 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, 'GET', 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 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 _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, 'GET', 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 _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, 'GET', 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') return res, is_container, headers, children
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, 'GET', 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'] = '/'.join(['', self.cdmi_root, self.account_name, self.container_name, self.parent_name, '']) else: body['parentURI'] = '/'.join(['', self.cdmi_root, self.account_name, '']) body['capabilitiesURI'] = '/'.join(['', self.cdmi_root, self.account_name, self.cdmi_capability_id, 'container/']) 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, 'GET', 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 #if we found X-Object-UploadID in the header, we need know that #the request is uploading a piece of a large object, the piece #will need to go to the segments folder try: self._handle_part(env) except Exception as ex: return get_err_response(ex.message) req = Request(env) metadata = {} if req.body: try: body = self._handle_body(env, True) except Exception: return get_err_response('InvalidBody') # headling copy object if body.get('copy'): # add the copy-from header to indicate a copy operation # for swift req.headers['X-Copy-From'] = body.get('copy') req.body = '' else: 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').lower() encoding = body.get('valuetransferencoding', 'utf-8') req.headers[Consts.VALUE_ENCODING] = encoding # if the value is encoded using base64, then # we need to decode it and save as binary if encoding == Consts.ENCODING_BASE64: req.body = base64.decodestring(req.body) 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'] = '/'.join(['', self.cdmi_root, self.account_name, self.container_name, self.parent_name, '']) body['capabilitiesURI'] = '/'.join(['', self.cdmi_root, self.account_name, self.cdmi_capability_id, 'dataobject/']) if env.get('HTTP_X_USE_EXTRA_REQUEST'): extra_res = self._put_manifest(env) res.status_int = extra_res.status body['metadata'] = metadata res.body = json.dumps(body, indent=2) # Otherwise, no response body should be returned. else: res.body = '' return res
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, 'GET', 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 try: self._handle_part(env) except Exception as ex: return get_err_response(ex.message) try: body = self._handle_body(env, False) except Exception as ex: return get_err_response('InvalidBody') else: env['CONTENT_TYPE'] = body.get('mimetype', 'text/plain') req = Request(env) req.body = body.get('value', '') req.headers['content-length'] = len(req.body) res = req.get_response(self.app) if (res.status_int in [201, 204] and env.get('HTTP_X_USE_EXTRA_REQUEST')): extra_res = self._put_manifest(env) res.status_int = extra_res.status 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, 'GET', 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 #if we found X-Object-UploadID in the header, we need know that #the request is uploading a piece of a large object, the piece #will need to go to the segments folder try: self._handle_part(env) except Exception as ex: return get_err_response(ex.message) req = Request(env) metadata = {} if req.body: try: body = self._handle_body(env, True) except Exception: return get_err_response('InvalidBody') # headling copy object if body.get('copy'): # add the copy-from header to indicate a copy operation # for swift req.headers['X-Copy-From'] = body.get('copy') req.body = '' else: 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').lower() encoding = body.get('valuetransferencoding', '7BIT') req.headers[Consts.VALUE_ENCODING] = encoding # if the value is encoded using base64, then # we need to decode it and save as binary if encoding == Consts.ENCODING_BASE64: req.body = base64.decodestring(req.body) 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 if self.parent_name: body['parentURI'] = '/'.join(['', self.cdmi_root, self.account_name, self.container_name, self.parent_name, '']) else: body['parentURI'] = '/'.join(['', self.cdmi_root, self.account_name, self.container_name, '']) body['capabilitiesURI'] = '/'.join(['', self.cdmi_root, self.account_name, self.cdmi_capability_id, 'dataobject/']) if env.get('HTTP_X_USE_EXTRA_REQUEST'): extra_res = self._put_manifest(env) res.status_int = extra_res.status body['metadata'] = metadata res.body = json.dumps(body, indent=2) # Otherwise, no response body should be returned. else: res.body = '' return res
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, 'GET', 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 try: self._handle_part(env) except Exception as ex: return get_err_response(ex.message) try: body = self._handle_body(env, False) except Exception as ex: return get_err_response('InvalidBody') else: env['CONTENT_TYPE'] = body.get('mimetype', 'text/plain') req = Request(env) req.body = body.get('value', '') req.headers['content-length'] = len(req.body) res = req.get_response(self.app) if (res.status_int in [201, 204] and env.get('HTTP_X_USE_EXTRA_REQUEST')): extra_res = self._put_manifest(env) res.status_int = extra_res.status return res