Exemple #1
0
 def GETorHEAD(self, req):
     """Handler for HTTP GET/HEAD requests."""
     partition, nodes = self.app.account_ring.get_nodes(self.account_name)
     nodes = self.app.sort_nodes(nodes)
     resp = self.GETorHEAD_base(
         req, _('Account'), partition, nodes, req.path_info.rstrip('/'),
         len(nodes))
     if resp.status_int == HTTP_NOT_FOUND and self.app.account_autocreate:
         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
         headers = {'X-Timestamp': normalize_timestamp(time.time()),
                    'X-Trans-Id': self.trans_id,
                    'Connection': 'close'}
         resp = self.make_requests(
             Request.blank('/v1/' + self.account_name),
             self.app.account_ring, partition, 'PUT',
             '/' + self.account_name, [headers] * len(nodes))
         if not is_success(resp.status_int):
             self.app.logger.warning('Could not autocreate account %r' %
                                     self.account_name)
             return resp
         resp = self.GETorHEAD_base(
             req, _('Account'), partition, nodes, req.path_info.rstrip('/'),
             len(nodes))
     return resp
Exemple #2
0
 def POST(self, req):
     """HTTP POST request handler."""
     error_response = check_metadata(req, 'account')
     if error_response:
         return error_response
     account_partition, accounts = \
         self.app.account_ring.get_nodes(self.account_name)
     headers = {'X-Timestamp': normalize_timestamp(time.time()),
                'X-Trans-Id': self.trans_id,
                'Connection': 'close'}
     self.transfer_headers(req.headers, headers)
     if self.app.memcache:
         self.app.memcache.delete(
             get_account_memcache_key(self.account_name))
     resp = self.make_requests(
         req, self.app.account_ring, account_partition, 'POST',
         req.path_info, [headers] * len(accounts))
     if resp.status_int == HTTP_NOT_FOUND and self.app.account_autocreate:
         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
         resp = self.make_requests(
             Request.blank('/v1/' + self.account_name),
             self.app.account_ring, account_partition, 'PUT',
             '/' + self.account_name, [headers] * len(accounts))
         if not is_success(resp.status_int):
             self.app.logger.warning('Could not autocreate account %r' %
                                     self.account_name)
             return resp
     return resp
Exemple #3
0
    def container_info(self, account, container, account_autocreate=False):
        """
        Get container information and thusly verify container existence.
        This will also make a call to account_info to verify that the
        account exists.

        :param account: account name for the container
        :param container: container name to look up
        :returns: dict containing at least container partition ('partition'),
                  container nodes ('containers'), container read
                  acl ('read_acl'), container write acl ('write_acl'),
                  and container sync key ('sync_key').
                  Values are set to None if the container does not exist.
        """
        part, nodes = self.app.container_ring.get_nodes(account, container)
        path = '/%s/%s' % (account, container)
        container_info = {'status': 0, 'read_acl': None,
                          'write_acl': None, 'sync_key': None,
                          'count': None, 'bytes': None,
                          'versions': None, 'partition': None,
                          'nodes': None}
        if self.app.memcache:
            cache_key = get_container_memcache_key(account, container)
            cache_value = self.app.memcache.get(cache_key)
            if isinstance(cache_value, dict):
                if 'container_size' in cache_value:
                    cache_value['count'] = cache_value['container_size']
                if is_success(cache_value['status']):
                    container_info.update(cache_value)
                    container_info['partition'] = part
                    container_info['nodes'] = nodes
                return container_info
        if not self.account_info(account, autocreate=account_autocreate)[1]:
            return container_info
        attempts_left = len(nodes)
        headers = {'x-trans-id': self.trans_id, 'Connection': 'close'}
        for node in self.iter_nodes(part, nodes, self.app.container_ring):
            try:
                start_node_timing = time.time()
                with ConnectionTimeout(self.app.conn_timeout):
                    conn = http_connect(node['ip'], node['port'],
                                        node['device'], part, 'HEAD',
                                        path, headers)
                self.app.set_node_timing(node, time.time() - start_node_timing)
                with Timeout(self.app.node_timeout):
                    resp = conn.getresponse()
                    resp.read()
                if is_success(resp.status):
                    container_info.update(
                        headers_to_container_info(resp.getheaders()))
                    break
                elif resp.status == HTTP_NOT_FOUND:
                    container_info['status'] = HTTP_NOT_FOUND
                else:
                    container_info['status'] = -1
                    if resp.status == HTTP_INSUFFICIENT_STORAGE:
                        self.error_limit(node)
            except (Exception, Timeout):
                self.exception_occurred(
                    node, _('Container'),
                    _('Trying to get container info for %s') % path)
            attempts_left -= 1
            if attempts_left <= 0:
                break
        if self.app.memcache:
            if container_info['status'] == HTTP_OK:
                self.app.memcache.set(
                    cache_key, container_info,
                    time=self.app.recheck_container_existence)
            elif container_info['status'] == HTTP_NOT_FOUND:
                self.app.memcache.set(
                    cache_key, container_info,
                    time=self.app.recheck_container_existence * 0.1)
        if container_info['status'] == HTTP_OK:
            container_info['partition'] = part
            container_info['nodes'] = nodes
        return container_info
Exemple #4
0
 def is_good_source(self, src):
     """
     Indicates whether or not the request made to the backend found
     what it was looking for.
     """
     return is_success(src.status) or is_redirection(src.status)
Exemple #5
0
    def case_info(self, case, autocreate=False):
        """
        Get case information, and also verify that the account exists.

        :param case: name of the case to get the info for
        :returns: tuple of (case id, evidence_count)
                  or (None, None) if it does not exist
        """
        partition, nodes = self.app.account_ring.get_nodes(account)
        account_info = {'status': 0,
                        'container_count': 0,
                        'total_object_count': None,
                        'bytes': None,
                        'meta': {}}
        # 0 = no responses, 200 = found, 404 = not found, -1 = mixed responses
        if self.app.memcache:
            cache_key = get_account_memcache_key(account)
            cache_value = self.app.memcache.get(cache_key)
            if not isinstance(cache_value, dict):
                result_code = cache_value
                container_count = 0
            else:
                result_code = cache_value['status']
                try:
                    container_count = int(cache_value['container_count'])
                except ValueError:
                    container_count = 0
            if result_code == HTTP_OK:
                return partition, nodes, container_count
            elif result_code == HTTP_NOT_FOUND and not autocreate:
                return None, None, None
        result_code = 0
        attempts_left = len(nodes)
        path = '/%s' % account
        headers = {'x-trans-id': self.trans_id, 'Connection': 'close'}
        iternodes = self.iter_nodes(partition, nodes, self.app.account_ring)
        while attempts_left > 0:
            try:
                node = iternodes.next()
            except StopIteration:
                break
            attempts_left -= 1
            try:
                start_node_timing = time.time()
                with ConnectionTimeout(self.app.conn_timeout):
                    conn = http_connect(node['ip'], node['port'],
                                        node['device'], partition, 'HEAD',
                                        path, headers)
                self.app.set_node_timing(node, time.time() - start_node_timing)
                with Timeout(self.app.node_timeout):
                    resp = conn.getresponse()
                    resp.read()
                    if is_success(resp.status):
                        result_code = HTTP_OK
                        account_info.update(
                            headers_to_account_info(resp.getheaders()))
                        break
                    elif resp.status == HTTP_NOT_FOUND:
                        if result_code == 0:
                            result_code = HTTP_NOT_FOUND
                        elif result_code != HTTP_NOT_FOUND:
                            result_code = -1
                    elif resp.status == HTTP_INSUFFICIENT_STORAGE:
                        self.error_limit(node)
                        continue
                    else:
                        result_code = -1
            except (Exception, Timeout):
                self.exception_occurred(node, _('Account'),
                                        _('Trying to get account info for %s')
                                        % path)
        if result_code == HTTP_NOT_FOUND and autocreate:
            if len(account) > MAX_ACCOUNT_NAME_LENGTH:
                return None, None, None
            headers = {'X-Timestamp': normalize_timestamp(time.time()),
                       'X-Trans-Id': self.trans_id,
                       'Connection': 'close'}
            resp = self.make_requests(Request.blank('/v1' + path),
                                      self.app.account_ring, partition, 'PUT',
                                      path, [headers] * len(nodes))
            if not is_success(resp.status_int):
                self.app.logger.warning('Could not autocreate account %r' %
                                        path)
                return None, None, None
            result_code = HTTP_OK
        if self.app.memcache and result_code in (HTTP_OK, HTTP_NOT_FOUND):
            if result_code == HTTP_OK:
                cache_timeout = self.app.recheck_account_existence
            else:
                cache_timeout = self.app.recheck_account_existence * 0.1
            account_info.update(status=result_code)
            self.app.memcache.set(cache_key,
                                  account_info,
                                  time=cache_timeout)
        if result_code == HTTP_OK:
            try:
                container_count = int(account_info['container_count'])
            except ValueError:
                container_count = 0
            return partition, nodes, container_count
        return None, None, None