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
Exemple #2
0
    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
Exemple #7
0
 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
Exemple #8
0
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
Exemple #9
0
    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
Exemple #10
0
    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
Exemple #11
0
    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
Exemple #12
0
    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