def GETorHEAD(self, req): """Handler for HTTP GET/HEAD requests.""" if len(self.account_name) > MAX_ACCOUNT_NAME_LENGTH: resp = HTTPBadRequest(request=req) resp.body = 'Account name length of %d longer than %d' % \ (len(self.account_name), MAX_ACCOUNT_NAME_LENGTH) return resp path = get_param(req, 'path') #delimiter = get_param(req, 'delimiter') #prefix = get_param(req, 'prefix') limit = get_param(req, 'limit') if limit and not limit.isdigit(): return HTTPPreconditionFailed(request=req, body='Value of limit must ' 'be a positive integer') if path: return HTTPBadRequest(request=req, body='Unsupported query ' 'parameter path') # partition, nodes = self.app.account_ring.get_nodes(self.account_name) node, filesystem, directory, global_map_version, component_number = \ self.app.account_ring.get_node(self.account_name) if not len(node): self.app.logger.error(_('%(msg)s %(method)s %(path)s'), {'msg': _('ERROR Wrong ring file content'), 'method': 'GET/HEAD', 'path': req.path}) return HTTPInternalServerError(request=req) #TODO Currently same component request is blocked until previous same #component request's map version is not updated, need to check other provision if not self.is_req_blocked(_('Account'), component_number): #return HTTPTemporaryRedirect(request=req, body = 'Component' # 'movement is in progress') # resp = self.GETorHEAD_base( # req, _('Account'), self.app.account_ring, partition, # req.swift_entity_path.rstrip('/')) resp = self.GETorHEAD_base( req, _('Account'), self.app.account_ring, node, filesystem, directory, req.swift_entity_path.rstrip('/'), global_map_version, component_number) resp = self.account_req_for_comp_distribution(req, component_number,\ global_map_version, self.account_name, resp) if int(resp.status.split()[0]) in (301, 307): resp = HTTPInternalServerError(request=req) if resp.status_int == HTTP_NOT_FOUND: if resp.headers.get('X-Account-Status', '').lower() == 'deleted': resp.status = HTTP_GONE if self.app.account_autocreate: resp = account_listing_response(self.account_name, req, get_listing_content_type(req)) if req.environ.get('swift_owner'): self.add_acls_from_sys_metadata(resp) else: for header in self.app.swift_owner_headers: resp.headers.pop(header, None) return resp
def BULK_DELETE(self, req): """HTTP BULK_DELETE request handler.""" self.app.logger.debug("In BULK_DELETE____") account_node, account_filesystem, account_directory, container_count, \ account_component_number, head_status = self.account_info(\ self.account_name, req) if not account_node and not head_status: return HTTPInternalServerError(request=req) if head_status and int(str(head_status).split()[0]) == 503: #TODO need to check why head_status is int or sometimes str self.app.logger.info("account HEAD returning 503 service " \ "unavailable error due to which this request got failed") return HTTPServiceUnavailable(request=req) if not account_node: return HTTPNotFound(request=req) container_node, container_filesystem, container_directory, \ global_map_version, component_number = \ self.app.container_ring.get_node( \ self.account_name, self.container_name) if not len(container_node): self.app.logger.error( _('%(msg)s %(method)s %(path)s'), { 'msg': _('ERROR Wrong ring file content'), 'method': 'BULK_DELETE', 'path': req.path }) return HTTPInternalServerError(request=req) self.app.logger.debug("Going for backend call______") try: headers = self._backend_requests(req, len(container_node), account_node, account_filesystem, account_directory, \ global_map_version, component_number, account_component_number) except ZeroDivisionError: self.app.logger.error( _('%(msg)s %(method)s %(path)s'), { 'msg': _('ERROR Wrong ring file content'), 'method': 'BULK_DELETE', 'path': req.path }) return HTTPInternalServerError(request=req) clear_info_cache(self.app, req.environ, self.account_name, self.container_name) self.app.logger.debug("Now going to make request_____") resp = self.make_request_for_bulk_delete( req, self.app.container_ring, container_node, container_filesystem, container_directory, 'BULK_DELETE', req.swift_entity_path, headers) return resp
def POST(self, req): """HTTP POST request handler.""" if len(self.account_name) > MAX_ACCOUNT_NAME_LENGTH: resp = HTTPBadRequest(request=req) resp.body = 'Account name length of %d longer than %d' % \ (len(self.account_name), MAX_ACCOUNT_NAME_LENGTH) return resp error_response = check_metadata(req, 'account') if error_response: return error_response # account_partition, accounts = \ # self.app.account_ring.get_nodes(self.account_name) node, filesystem, directory, global_map_version, component_number = \ self.app.account_ring.get_node(self.account_name) if not len(node): self.app.logger.error(_('%(msg)s %(method)s %(path)s'), {'msg': _('ERROR Wrong ring file content'), 'method': 'POST', 'path': req.path}) return HTTPInternalServerError(request=req) headers = self.generate_request_headers(global_map_version, component_number, req, transfer=True) clear_info_cache(self.app, req.environ, self.account_name) if not self.is_req_blocked(_('Account'), component_number): #return HTTPTemporaryRedirect(request=req, body = 'Component' # 'movement is in progress') # resp = self.make_requests( # req, self.app.account_ring, account_partition, 'POST', # req.swift_entity_path, [headers] * len(accounts)) resp = self.make_requests( req, self.app.account_ring, node, filesystem, directory, 'POST', req.swift_entity_path, [headers] * len(node)) resp = self.account_req_for_comp_distribution(req, component_number,\ global_map_version, self.account_name, resp) if resp.status_int == HTTP_NOT_FOUND and self.app.account_autocreate: self.autocreate_account(req.environ, self.account_name) # resp = self.make_requests( # req, self.app.account_ring, account_partition, 'POST', # req.swift_entity_path, [headers] * len(accounts)) resp = self.make_requests( req, self.app.account_ring, node, filesystem, directory, 'POST', req.swift_entity_path, [headers] * len(node)) resp = self.account_req_for_comp_distribution(req, component_number,\ global_map_version, self.account_name, resp) if int(resp.status.split()[0]) in (301, 307): resp = HTTPInternalServerError(request=req) self.add_acls_from_sys_metadata(resp) return resp
def get(self, filesystem, acc_dir, cont_dir, account, container, req): """ Handles GET request for container param:filesystem: Filesystem name param:account: Account name param:container: Container name param:req: HTTP Request object """ try: # create path path = self.create_path(filesystem, acc_dir, cont_dir, account, container) self.logger.debug(('GET container called for path: %(path)s'), {'path' : path}) # get headers for response headers = self.__head_or_get(path) if headers == HTTP_INTERNAL_SERVER_ERROR: self.logger.debug('Internal error raised from library in HEAD') raise HTTPInternalServerError(request=req) elif headers == HTTP_NOT_FOUND: self.logger.debug('File not found error raised from ' 'library in HEAD') raise HTTPNotFound(request=req) else: out_content_type = get_listing_content_type(req) headers['Content-Type'] = out_content_type # get response to be send ret = self.__get_cont_list(path, container, req) if ret == OsdExceptionCode.OSD_INTERNAL_ERROR: self.logger.debug('Internal error raised from library in GET') raise HTTPInternalServerError(request=req) elif ret == OsdExceptionCode.OSD_NOT_FOUND: self.logger.debug('File not found error raised from ' 'library in GET') raise HTTPNotFound(request=req) else: pass return ret, headers except HTTPException as error: self.logger.exception(error) raise error except Exception as err: self.logger.error(('GET request failed for ' 'container: %(container)s '), {'container' : container}) self.logger.exception(err) raise err
def DELETE(self, req): """HTTP DELETE request handler.""" # Extra safety in case someone typos a query string for an # account-level DELETE request that was really meant to be caught by # some middleware. if req.query_string: return HTTPBadRequest(request=req) if not self.app.allow_account_management: return HTTPMethodNotAllowed( request=req, headers={'Allow': ', '.join(self.allowed_methods)}) # account_partition, accounts = \ # self.app.account_ring.get_nodes(self.account_name) node, filesystem, directory, global_map_version, component_number = \ self.app.account_ring.get_node(self.account_name) if not len(node): self.app.logger.error(_('%(msg)s %(method)s %(path)s'), {'msg': _('ERROR Wrong ring file content'), 'method': 'DELETE', 'path': req.path}) return HTTPInternalServerError(request=req) headers = self.generate_request_headers(global_map_version, component_number, req) clear_info_cache(self.app, req.environ, self.account_name) if not self.is_req_blocked(_('Account'), component_number): #return HTTPTemporaryRedirect(request=req, body = 'Component' # 'movement is in progress') # resp = self.make_requests( # req, self.app.account_ring, account_partition, 'DELETE', # req.swift_entity_path, [headers] * len(accounts)) resp = self.make_requests( req, self.app.account_ring, node, filesystem, directory, 'DELETE', req.swift_entity_path, [headers] * len(node)) resp = self.account_req_for_comp_distribution(req, component_number,\ global_map_version, self.account_name, resp) if int(resp.status.split()[0]) in (301, 307): resp = HTTPInternalServerError(request=req) return resp
def head(self, filesystem, acc_dir, cont_dir, account, container, req): """ Handles HEAD request for container param:filesystem: Filesystem name param:account: Account name param:container: Container name param:req: HTTP Request object """ try: # create path path, headers = '', '' if 'x-updater-request' in req.headers: path = self.create_updater_path(filesystem, acc_dir, cont_dir, account, container) self.logger.debug(('HEAD container called for path: %(path)s'), {'path' : path}) # get headers for updater request headers = self.__updater_headers(path , True) #pass True in updater request else: path = self.create_path(filesystem, acc_dir, cont_dir, account, container) self.logger.debug(('HEAD container called for path: %(path)s'), {'path' : path}) # get headers for request headers = self.__head_or_get(path) if headers == HTTP_INTERNAL_SERVER_ERROR: self.logger.debug('Internal error raised from library') raise HTTPInternalServerError(request=req) if headers == HTTP_NOT_FOUND and 'x-updater-request' in req.headers: self.logger.debug('File not found error raised from library: updater case') raise HTTPNotFound(request=req) elif headers == HTTP_NOT_FOUND: self.logger.debug('File not found error raised from library') raise HTTPNotFound(request=req) else: out_content_type = get_listing_content_type(req) headers['Content-Type'] = out_content_type return headers except HTTPException as error: self.logger.exception(error) raise error except Exception as err: self.logger.error \ (('HEAD request failed for container: %(container)s '), {'container' : container}) self.logger.exception(err) raise err
def get_lock(self, account, container, mode, operation): """ Method to call GET_LOCK of transcation handler component param:account: Account name param:container: Container name param:mode: mode type for operation param:operation: Type of operation """ service_id = get_container_id() full_path = '%s/%s/' % (account, container) req_mode = WRITE_MODE if mode == 'r': req_mode = READ_MODE req = Request(full_path, operation, req_mode, service_id) trans_id = self.__trans_obj.internal_get_lock(req) if trans_id == FAIL_ERROR: raise HTTPInternalServerError() elif trans_id == FAIL_TIMEOUT: raise HTTPRequestTimeout() else: return trans_id
class AccountServiceInterface: """An interface class between account service and library.""" account_lib_obj = libaccountLib.AccountLibraryImpl() asyn_helper = AsyncLibraryHelper(account_lib_obj) @classmethod def start_event_wait_func(cls, logger): logger.info('wait_event called!') AccountServiceInterface.asyn_helper.wait_event() @classmethod def stop_event_wait_func(cls, logger): logger.info('wait_event_stop called!') AccountServiceInterface.asyn_helper.wait_event_stop() @classmethod def get_metadata(self, req, logger): """ Creates metadata string from request object and container stat if present param: Request object Returns metadata dictionary """ try: new_meta = {} metadata = {} # get metadata from request headers metadata.update((key.lower(), value) for key, value in req.headers.iteritems() if key.lower() in HEADERS or is_sys_or_user_meta('account', key)) for key, value in metadata.iteritems(): if key == 'x-account-read': new_meta.update({'r-': value}) elif key == 'x-account-write': new_meta.update({'w-': value}) else: ser_key = key.split('-')[2] if ser_key == 'meta': new_key = '%s-%s' % ('m', key.split('-', 3)[-1]) new_meta.update({new_key: value}) elif ser_key == 'sysmeta': new_key = '%s-%s' % ('sm', key.split('-', 3)[-1]) new_meta.update({new_key: value}) else: logger.debug('Expected metadata not found') return new_meta except Exception as err: logger.error( ('get_metadata failed ', 'close failure: %(exc)s : %(stack)s'), { 'exc': err, 'stack': ''.join(traceback.format_stack()) }) raise err @classmethod def create_AccountStat_object(cls, info): """An interface to create an object of AccountStat, from info map""" if 'account' not in info: info['account'] = '-1' if 'created_at' not in info: info['created_at'] = '0' if 'put_timestamp' not in info: info['put_timestamp'] = '0' if 'delete_timestamp' not in info: info['delete_timestamp'] = '0' if 'container_count' not in info: info['container_count'] = 0 if 'object_count' not in info: info['object_count'] = 0 if 'bytes_used' not in info: info['bytes_used'] = 0 if 'hash' not in info: info['hash'] = '-1' if 'id' not in info: info['id'] = '-1' if 'status' not in info: info['status'] = '-1' if 'status_changed_at' not in info: info['status_changed_at'] = '0' if 'metadata' not in info: info['metadata'] = {} return libaccountLib.AccountStat( info['account'], info['created_at'], normalize_timestamp(\ info['put_timestamp']), normalize_timestamp(\ info['delete_timestamp']), info['container_count'], info['object_count'], info['bytes_used'], info['hash'], info['id'], info['status'], info['status_changed_at'], info['metadata'] ) @classmethod def create_container_record(cls, name, hash, info, deleted): """An interface to create an object of ContainerRecord, from info map""" if 'x-object-count' not in info: info['x-object-count'] = 0 if not info['x-put-timestamp']: info['x-put-timestamp'] = '0' if not info['x-delete-timestamp']: info['x-delete-timestamp'] = '0' return libaccountLib.ContainerRecord(0, name, hash, \ normalize_timestamp(str(info['x-put-timestamp'])), \ normalize_timestamp(str(info['x-delete-timestamp'])), \ long(info['x-object-count']), \ long(info['x-bytes-used']), deleted) @classmethod def create_container_record_for_updater(cls, name, hash, info): """An interface to create an object of ContainerRecord for account \ updater, from info map """ if 'x-object-count' not in info: info['x-object-count'] = 0 if not info['put_timestamp']: info['put_timestamp'] = '0' if not info['delete_timestamp']: info['delete_timestamp'] = '0' return libaccountLib.ContainerRecord(0, name, hash, \ normalize_timestamp(str(info['put_timestamp'])), \ normalize_timestamp(str(info['delete_timestamp'])), \ long(info['object_count']), \ long(info['bytes_used']), \ info['deleted']) @classmethod def list_account(cls, temp_path, account_path, out_content_type, req, limit, marker, \ end_marker, prefix, delimiter, logger): """An interface to list the containers in account.""" logger.debug("Get account stats for path: %s" % account_path) container_record_list = [] resp = libaccountLib.AccountStatWithStatus() AccountServiceInterface.__get_account_stat(resp, temp_path, account_path, logger) logger.info("Account library responded with: %s for get_account_stat \ in GET" % resp.get_return_status()) if resp.get_return_status() == INFO_FILE_OPERATION_SUCCESS: resp_headers = { 'X-Account-Container-Count': \ resp.get_account_stat().get_container_count(), 'X-Account-Object-Count': \ resp.get_account_stat().get_object_count(), 'X-Account-Bytes-Used': resp.get_account_stat().get_bytes_used(), 'X-Timestamp': resp.get_account_stat().get_created_at(), 'X-PUT-Timestamp': resp.get_account_stat().get_put_timestamp() } modified_meta = {} for key, value in resp.get_account_stat().get_metadata().iteritems( ): if key == 'r-': modified_meta.update({'x-account-read': value}) elif key == 'w-': modified_meta.update({'x-account-write': value}) else: ser_key = key.split('-')[0] if ser_key == 'm': key = 'x-account-meta-' + key.split('-', 1)[1] modified_meta.update({key: value}) resp_headers.update( (key, value) for (key, value) in modified_meta.iteritems()) if limit: logger.debug("Calling list_container") resp = libaccountLib.ListContainerWithStatus() try: AccountServiceInterface.asyn_helper.call("list_container", \ resp, account_path, limit, marker, \ end_marker, prefix, delimiter) except Exception, err: logger.error(('list_container for %(ac_dir)s failed ' \ 'close failure: %(exc)s : %(stack)s'), {'ac_dir' : \ account_path, 'exc': err, 'stack': \ ''.join(traceback.format_stack())}) raise err logger.info("Account library responded with: %s for \ list_container in GET" % resp.get_return_status()) if resp.get_return_status() == INFO_FILE_OPERATION_SUCCESS: container_record_list = resp.get_container_record() if delimiter: container_list_new = [] for obj in container_record_list: name = obj.get_name() if prefix: match = re.match("^" + prefix + ".*", name) if match: replace = re.sub("^" + prefix, '', name) replace = replace.split(delimiter) if len(replace) >= 2: obj.set_name(prefix + replace[0] + delimiter) if marker != obj.get_name( ) or marker > obj.get_name(): container_list_new.append((obj, (0, 1)[delimiter in obj.get_name() and \ obj.get_name().endswith(delimiter)])) else: obj.set_name(prefix + replace[0]) if marker != obj.get_name( ) or marker > obj.get_name(): container_list_new.append((obj, 0)) else: replace = name.split(delimiter) if len(replace) >= 2: obj.set_name(replace[0] + delimiter) if marker != obj.get_name( ) or marker > obj.get_name(): container_list_new.append((obj, (0, 1)[delimiter in obj.get_name() and \ obj.get_name().endswith(delimiter)])) container_record_list = container_list_new else: container_record_list = [ (record, 0) for record in container_record_list ] if resp.get_return_status() == INFO_FILE_OPERATION_SUCCESS: logger.debug("Populating container list") elif resp.get_return_status() == INFO_FILE_NOT_FOUND: return HTTPNotFound(request=req, charset='utf-8') elif resp.get_return_status() == INFO_FILE_DELETED: headers = {'X-Account-Status': 'Deleted'} return HTTPNotFound(request=req, headers=headers, charset='utf-8', body='') else: return HTTPInternalServerError(request=req) if out_content_type == 'application/json': data = [] for (container_record, is_subdir) in container_record_list: if is_subdir: data.append({'subdir': container_record.get_name()}) else: data.append({ 'name': container_record.get_name(), 'created_at': time.strftime( "%a, %d %b %Y %H:%M:%S GMT", time.gmtime( float(container_record.get_put_timestamp()))), 'count': container_record.get_object_count(), 'bytes': container_record.get_bytes_used() }) container_record_list = json.dumps(data) elif out_content_type.endswith('/xml'): #Directly used req.path to get account name. output_list = ['<?xml version="1.0" encoding="UTF-8"?>', '<account name=%s>' % \ saxutils.quoteattr(req.path.split('/')[3])] for (container_record, is_subdir) in container_record_list: if is_subdir: output_list.append( '<subdir name=%s />' % saxutils.quoteattr(container_record.get_name())) else: item = '<container><name>%s</name><created_at>%s</created_at><count>%s</count>' \ '<bytes>%s</bytes></container>' % \ (saxutils.escape(container_record.get_name()), \ time.strftime("%a, %d %b %Y %H:%M:%S GMT",time.gmtime(float(container_record.get_put_timestamp()))), \ container_record.get_object_count(), \ container_record.get_bytes_used() ) output_list.append(item) output_list.append('</account>') container_record_list = '\n'.join(output_list) else: if not container_record_list: logger.debug("No any container in account") resp = HTTPNoContent(request=req, headers=resp_headers) resp.content_type = out_content_type resp.charset = 'utf-8' return resp container_record_list = '\n'.join(container_record.get_name() for \ (container_record, is_subdir) in container_record_list) + '\n' ret = HTTPOk(body=container_record_list, request=req, headers=resp_headers) ret.content_type = out_content_type ret.charset = 'utf-8' return ret
def DELETE(self, req): """HTTP DELETE request handler.""" # account_partition, accounts, container_count = \ # self.account_info(self.account_name, req) # if not accounts: account_node, account_filesystem, account_directory, container_count, \ account_component_number, head_status = self.account_info(\ self.account_name, req) if not account_node and not head_status: return HTTPInternalServerError(request=req) if head_status and int(str(head_status).split()[0]) == 503: self.app.logger.info("account HEAD returning 503 service" \ "unavailable error due to which this request got failed") return HTTPServiceUnavailable(request=req) if head_status and int(str(head_status).split()[0]) == 500: return HTTPInternalServerError(request=req) if not account_node: return HTTPNotFound(request=req) # container_partition, containers = self.app.container_ring.get_nodes( # # self.account_name, self.container_name) container_node, container_filesystem, container_directory, \ global_map_version, component_number = \ self.app.container_ring.get_node( \ self.account_name, self.container_name) if not len(container_node): self.app.logger.error( _('%(msg)s %(method)s %(path)s'), { 'msg': _('ERROR Wrong ring file content'), 'method': 'DELETE', 'path': req.path }) return HTTPInternalServerError(request=req) # headers = self._backend_requests(req, len(containers), # account_partition, accounts) try: headers = self._backend_requests(req, len(container_node), account_node, account_filesystem, account_directory, global_map_version, component_number, account_component_number) except ZeroDivisionError: self.app.logger.error( _('%(msg)s %(method)s %(path)s'), { 'msg': _('ERROR Wrong ring file content'), 'method': 'DELETE', 'path': req.path }) return HTTPInternalServerError(request=req) clear_info_cache(self.app, req.environ, self.account_name, self.container_name) # resp = self.make_requests( # req, self.app.container_ring, container_partition, 'DELETE', # # req.swift_entity_path, headers) if not self.is_req_blocked(_('Container'), component_number): #return HTTPTemporaryRedirect(request=req, body = 'Component' # 'movement is in progress') resp = self.make_requests(req, self.app.container_ring, container_node, container_filesystem, container_directory, 'DELETE', req.swift_entity_path, headers) resp = self.container_req_for_comp_distribution(req, \ component_number, global_map_version, self.account_name, \ self.container_name, resp) if int(resp.status.split()[0]) in (301, 307): resp = HTTPInternalServerError(request=req) # Indicates no server had the container if resp.status_int == HTTP_ACCEPTED: return HTTPNotFound(request=req) return resp
def POST(self, req): """HTTP POST request handler.""" error_response = \ self.clean_acls(req) or check_metadata(req, 'container') if error_response: return error_response if not req.environ.get('swift_owner'): for key in self.app.swift_owner_headers: req.headers.pop(key, None) # account_partition, accounts, container_count = \ # self.account_info(self.account_name, req) # if not accounts: account_node, account_filesystem, account_directory, container_count, \ account_component_number, head_status = self.account_info(\ self.account_name, req) if not account_node and not head_status: return HTTPInternalServerError(request=req) if head_status and int(str(head_status).split()[0]) == 503: self.app.logger.info("account HEAD returning 503 service" \ "unavailable error due to which this request got failed") return HTTPServiceUnavailable(request=req) if head_status and int(str(head_status).split()[0]) == 500: return HTTPInternalServerError(request=req) if not account_node: return HTTPNotFound(request=req) # container_partition, containers = self.app.container_ring.get_nodes( # # self.account_name, self.container_name) container_node, container_filesystem, container_directory, \ global_map_version, component_number = \ self.app.container_ring.get_node( \ self.account_name, self.container_name) if not len(container_node): self.app.logger.error( _('%(msg)s %(method)s %(path)s'), { 'msg': _('ERROR Wrong ring file content'), 'method': 'POST', 'path': req.path }) return HTTPInternalServerError(request=req) headers = self.generate_request_headers(global_map_version, component_number, req, transfer=True) clear_info_cache(self.app, req.environ, self.account_name, self.container_name) if not self.is_req_blocked(_('Container'), component_number): #return HTTPTemporaryRedirect(request=req, body = 'Component' # 'movement is in progress') # resp = self.make_requests( # req, self.app.container_ring, container_partition, 'POST', # # req.swift_entity_path, [headers] * len(containers)) resp = self.make_requests(req, self.app.container_ring, container_node, container_filesystem, container_directory, 'POST', req.swift_entity_path, [headers] * len(container_node)) resp = self.container_req_for_comp_distribution(req, \ component_number, global_map_version, self.account_name, \ self.container_name, resp) if int(resp.status.split()[0]) in (301, 307): resp = HTTPInternalServerError(request=req) return resp
def PUT(self, req): """HTTP PUT request handler.""" error_response = \ self.clean_acls(req) or check_metadata(req, 'container') if error_response: return error_response if not req.environ.get('swift_owner'): for key in self.app.swift_owner_headers: req.headers.pop(key, None) if len(self.container_name) > MAX_CONTAINER_NAME_LENGTH: resp = HTTPBadRequest(request=req) resp.body = 'Container name length of %d longer than %d' % \ (len(self.container_name), MAX_CONTAINER_NAME_LENGTH) return resp # account_partition, accounts, container_count = \ # self.account_info(self.account_name, req) account_node, account_filesystem, account_directory, container_count, \ account_component_number, head_status = self.account_info(\ self.account_name, req) # if not accounts and self.app.account_autocreate: # self.autocreate_account(req.environ, self.account_name) # account_partition, accounts, container_count = \ # self.account_info(self.account_name, req) # if not accounts: if not account_node and not head_status: return HTTPInternalServerError(request=req) if head_status and int(str(head_status).split()[0]) == 503: #TODO need to check why head_status is int or sometimes str self.app.logger.info("account HEAD returning 503 service " \ "unavailable error due to which this request got failed") return HTTPServiceUnavailable(request=req) if head_status and int(str(head_status).split()[0]) == 500: return HTTPInternalServerError(request=req) if not account_node and self.app.account_autocreate: self.autocreate_account(req.environ, self.account_name) account_node, account_filesystem, account_directory, \ container_count, account_component_number, head_status = \ self.account_info(self.account_name, req) if not account_node and not head_status: return HTTPInternalServerError(request=req) if head_status and int(str(head_status).split()[0]) == 503: self.app.logger.info("account HEAD returning 503 service" \ "unavailable error due to which this request got failed") return HTTPServiceUnavailable(request=req) if head_status and int(str(head_status).split()[0]) == 500: return HTTPInternalServerError(request=req) if not account_node: return HTTPNotFound(request=req) if self.app.max_containers_per_account > 0 and \ container_count >= self.app.max_containers_per_account and \ self.account_name not in self.app.max_containers_whitelist: resp = HTTPForbidden(request=req) resp.body = 'Reached container limit of %s' % \ self.app.max_containers_per_account return resp # container_partition, containers = self.app.container_ring.get_nodes( # self.account_name, self.container_name) container_node, container_filesystem, container_directory, \ global_map_version, component_number = \ self.app.container_ring.get_node(self.account_name, self.container_name) if not len(container_node): self.app.logger.error( _('%(msg)s %(method)s %(path)s'), { 'msg': _('ERROR Wrong ring file content'), 'method': 'PUT', 'path': req.path }) return HTTPInternalServerError(request=req) # headers = self._backend_requests(req, len(containers), # account_partition, accounts) try: headers = self._backend_requests(req, len(container_node), account_node, account_filesystem, account_directory, global_map_version, component_number, account_component_number) except ZeroDivisionError: self.app.logger.error( _('%(msg)s %(method)s %(path)s'), { 'msg': _('ERROR Wrong ring file content'), 'method': 'PUT', 'path': req.path }) return HTTPInternalServerError(request=req) clear_info_cache(self.app, req.environ, self.account_name, self.container_name) if not self.is_req_blocked(_('Container'), component_number): #return HTTPTemporaryRedirect(request=req, body = 'Component' # 'movement is in progress') # resp = self.make_requests( # # # container_partition, 'PUT', req.swift_entity_path, headers) resp = self.make_requests(req, self.app.container_ring, container_node, container_filesystem, container_directory, 'PUT', req.swift_entity_path, headers) resp = self.container_req_for_comp_distribution(req, \ component_number, global_map_version, self.account_name, \ self.container_name, resp) if int(resp.status.split()[0]) in (301, 307): resp = HTTPInternalServerError(request=req) return resp
def GETorHEAD(self, req): """Handler for HTTP GET/HEAD requests.""" account_node, account_filesystem, account_directory, container_count, \ account_component_number, head_status = self.account_info(\ self.account_name, req) if not account_node and not head_status: return HTTPInternalServerError(request=req) if head_status and int(str(head_status).split()[0]) == 503: #TODO need to check why head_status is int or sometimes str self.app.logger.info("account HEAD returning 503 service " \ "unavailable error due to which this request got failed") return HTTPServiceUnavailable(request=req) if head_status and int(str(head_status).split()[0]) == 500: return HTTPInternalServerError(request=req) if not account_node: return HTTPNotFound(request=req) path = get_param(req, 'path') #delimiter = get_param(req, 'delimiter') #prefix = get_param(req, 'prefix') limit = get_param(req, 'limit') if limit and not limit.isdigit(): return HTTPPreconditionFailed(request=req, body='Value of limit must ' 'be a positive integer') if path: return HTTPBadRequest(request=req, body='Unsupported query parameter ' 'path') # part = self.app.container_ring.get_part( # self.account_name, self.container_name) node, filesystem, directory, global_map_version, component_number = \ self.app.container_ring.get_node(self.account_name, \ self.container_name) if not len(node): self.app.logger.error( _('%(msg)s %(method)s %(path)s'), { 'msg': _('ERROR Wrong ring file content'), 'method': 'GET/HEAD', 'path': req.path }) return HTTPInternalServerError(request=req) #TODO Currently same component request is blocked until previous same #component request's map version is not updated, need to check other provision if not self.is_req_blocked(_('Container'), component_number): #return HTTPTemporaryRedirect(request=req, body = 'Component' # 'movement is in progress') # resp = self.GETorHEAD_base( # req, _('Container'), self.app.container_ring, part, # req.swift_entity_path) resp = self.GETorHEAD_base(req, _('Container'), \ self.app.container_ring, node, filesystem, directory, \ req.swift_entity_path, global_map_version, component_number) resp = self.container_req_for_comp_distribution(req, \ component_number, global_map_version, self.account_name, \ self.container_name, resp) if int(resp.status.split()[0]) in (301, 307): resp = HTTPInternalServerError(request=req) if 'swift.authorize' in req.environ: req.acl = resp.headers.get('x-container-read') aresp = req.environ['swift.authorize'](req) if aresp: return aresp if not req.environ.get('swift_owner', False): for key in self.app.swift_owner_headers: if key in resp.headers: del resp.headers[key] return resp