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