def test_write_connect_errors(self): test_cases = [ { 'error': green.ConnectionTimeout(1.0), 'msg': 'connect: Connection timeout 1.0 second' }, { 'error': Exception('failure'), 'msg': 'connect: failure' }, ] for test in test_cases: checksum = self.checksum() source = empty_stream() size = CHUNK_SIZE * self.storage_method.ec_nb_data nb = self.storage_method.ec_nb_data + \ self.storage_method.ec_nb_parity resps = [201] * (nb - 1) # Put the error in the middle to mess with chunk indices err_pos = random.randint(0, nb) resps.insert(err_pos, test['error']) with set_http_connect(*resps): handler = EcMetachunkWriter(self.sysmeta, self.meta_chunk_copy(), checksum, self.storage_method) bytes_transferred, checksum, chunks = handler.stream( source, size) self.assertEqual(len(chunks), nb) for i in range(nb - 1): self.assertEqual(chunks[i].get('error'), None) self.assertEqual(chunks[nb - 1].get('error'), test['msg']) self.assertEqual(bytes_transferred, 0) self.assertEqual(checksum, EMPTY_MD5)
def connect(cls, chunk, sysmeta, reqid=None, connection_timeout=None, write_timeout=None, **kwargs): raw_url = chunk.get("real_url", chunk["url"]) parsed = urlparse(raw_url) chunk_path = parsed.path.split('/')[-1] hdrs = headers_from_object_metadata(sysmeta) if reqid: hdrs['X-oio-req-id'] = reqid hdrs[CHUNK_HEADERS["chunk_pos"]] = chunk["pos"] hdrs[CHUNK_HEADERS["chunk_id"]] = chunk_path # in the trailer # metachunk_size & metachunk_hash trailers = (CHUNK_HEADERS["metachunk_size"], CHUNK_HEADERS["metachunk_hash"]) if kwargs.get('chunk_checksum_algo'): trailers = trailers + (CHUNK_HEADERS["chunk_hash"], ) hdrs["Trailer"] = ', '.join(trailers) with green.ConnectionTimeout( connection_timeout or io.CONNECTION_TIMEOUT): conn = io.http_connect( parsed.netloc, 'PUT', parsed.path, hdrs) conn.chunk = chunk return cls(chunk, conn, write_timeout=write_timeout, **kwargs)
def connect(cls, chunk, sysmeta, reqid=None, connection_timeout=None, write_timeout=None, **_kwargs): raw_url = chunk["url"] parsed = urlparse(raw_url) chunk_path = parsed.path.split('/')[-1] hdrs = headers_from_object_metadata(sysmeta) if reqid: hdrs['X-oio-req-id'] = reqid hdrs[chunk_headers["chunk_pos"]] = chunk["pos"] hdrs[chunk_headers["chunk_id"]] = chunk_path # in the trailer # metachunk_size & metachunk_hash hdrs["Trailer"] = ', '.join( (chunk_headers["metachunk_size"], chunk_headers["metachunk_hash"], chunk_headers["chunk_hash"])) with green.ConnectionTimeout(connection_timeout or io.CONNECTION_TIMEOUT): conn = io.http_connect(parsed.netloc, 'PUT', parsed.path, hdrs) conn.chunk = chunk return cls(chunk, conn, write_timeout=write_timeout)
def _connect_put(self, chunk): """ Create a connection in order to PUT `chunk`. :returns: a tuple with the connection object and `chunk` """ raw_url = chunk["url"] parsed = urlparse(raw_url) try: chunk_path = parsed.path.split('/')[-1] hdrs = headers_from_object_metadata(self.sysmeta) hdrs[CHUNK_HEADERS["chunk_pos"]] = chunk["pos"] hdrs[CHUNK_HEADERS["chunk_id"]] = chunk_path hdrs.update(self.headers) with green.ConnectionTimeout(self.connection_timeout): conn = io.http_connect( parsed.netloc, 'PUT', parsed.path, hdrs) conn.chunk = chunk return conn, chunk except (Exception, Timeout) as err: msg = str(err) logger.exception("Failed to connect to %s (%s)", chunk, msg) chunk['error'] = msg return None, chunk
def _get_request(self, chunk): """ Connect to a chunk, fetch headers but don't read data. Save the response object in `self.sources` list. """ try: with green.ConnectionTimeout(self.connection_timeout): raw_url = chunk["url"] parsed = urlparse(raw_url) conn = http_connect(parsed.netloc, 'GET', parsed.path, self.request_headers) with green.OioTimeout(self.read_timeout): source = conn.getresponse() source.conn = conn except (Exception, Timeout) as error: logger.exception('Connection failed to %s', chunk) self._resp_by_chunk[chunk["url"]] = (0, str(error)) return False if source.status in (200, 206): self.status = source.status self._headers = source.getheaders() self.sources.append((source, chunk)) return True else: logger.warn("Invalid response from %s: %d %s", chunk, source.status, source.reason) self._resp_by_chunk[chunk["url"]] = (source.status, str(source.reason)) return False
def connect(cls, chunk, sysmeta, reqid=None, connection_timeout=None, write_timeout=None, **_kwargs): raw_url = chunk["url"] parsed = urlparse(raw_url) chunk_path = parsed.path.split('/')[-1] h = {} h["transfer-encoding"] = "chunked" h[chunk_headers["content_id"]] = sysmeta['id'] h[chunk_headers["content_path"]] = sysmeta['content_path'] h[chunk_headers["content_chunkmethod"]] = sysmeta['chunk_method'] h[chunk_headers["container_id"]] = sysmeta['container_id'] h[chunk_headers["chunk_pos"]] = chunk["pos"] h[chunk_headers["chunk_id"]] = chunk_path h[chunk_headers["content_policy"]] = sysmeta['policy'] h[chunk_headers["content_version"]] = sysmeta['version'] if reqid: h['X-oio-req-id'] = reqid # in the trailer # metachunk_size & metachunk_hash h["Trailer"] = (chunk_headers["metachunk_size"], chunk_headers["metachunk_hash"]) with green.ConnectionTimeout(connection_timeout or io.CONNECTION_TIMEOUT): conn = io.http_connect(parsed.netloc, 'PUT', parsed.path, h) conn.chunk = chunk return cls(chunk, conn, write_timeout=write_timeout)
def _get_request(self, chunk): """ Connect to a chunk, fetch headers but don't read data. Save the response object in `self.sources` list. """ try: with green.ConnectionTimeout(self.connection_timeout): raw_url = chunk.get("real_url", chunk["url"]) parsed = urlparse(raw_url) if self.perfdata is not None: connect_start = monotonic_time() conn = http_connect(parsed.netloc, 'GET', parsed.path, self.request_headers, scheme=parsed.scheme) if self.perfdata is not None: connect_end = monotonic_time() rawx_perfdata = self.perfdata.setdefault('rawx', dict()) rawx_perfdata['connect.' + chunk['url']] = \ connect_end - connect_start with green.OioTimeout(self.read_timeout): source = conn.getresponse() source.conn = conn if self.perfdata is not None: source.download_start = monotonic_time() except (SocketError, Timeout) as err: self.logger.error('Connection failed to %s (reqid=%s): %s', chunk, self.reqid, err) self._resp_by_chunk[chunk["url"]] = (0, text_type(err)) return False except Exception as err: self.logger.exception('Connection failed to %s (reqid=%s)', chunk, self.reqid) self._resp_by_chunk[chunk["url"]] = (0, text_type(err)) return False if source.status in (200, 206): self.status = source.status self._headers = [(k.lower(), v) for k, v in source.getheaders()] self.sources.append((source, chunk)) return True else: self.logger.warn("Invalid response from %s (reqid=%s): %d %s", chunk, self.reqid, source.status, source.reason) self._resp_by_chunk[chunk["url"]] = (source.status, text_type(source.reason)) close_source(source, self.logger) return False
def _get_response(self, chunk, headers): resp = None parsed = urlparse(chunk['url']) try: with green.ConnectionTimeout(self.connection_timeout): conn = io.http_connect(parsed.netloc, 'GET', parsed.path, headers) with Timeout(self.read_timeout): resp = conn.getresponse() if resp.status != 200: logger.warning('Invalid GET response from %s', chunk) resp = None except (Exception, Timeout): logger.exception('ERROR fetching %s', chunk) return resp
def _get_response(self, chunk, headers): resp = None parsed = urlparse(chunk.get('real_url', chunk['url'])) try: with green.ConnectionTimeout(self.connection_timeout): conn = io.http_connect( parsed.netloc, 'GET', parsed.path, headers) with Timeout(self.read_timeout): resp = conn.getresponse() if resp.status != 200: logger.warning('Invalid GET response from %s: %s %s', chunk, resp.status, resp.reason) resp = None except (SocketError, Timeout) as err: logger.error('ERROR fetching %s: %s', chunk, err) except Exception: logger.exception('ERROR fetching %s', chunk) return resp
def _connect_put(self, chunk): """ Create a connection in order to PUT `chunk`. :returns: a tuple with the connection object and `chunk` """ raw_url = chunk.get("real_url", chunk["url"]) parsed = urlparse(raw_url) try: chunk_path = parsed.path.split('/')[-1] hdrs = headers_from_object_metadata(self.sysmeta) hdrs[CHUNK_HEADERS["chunk_pos"]] = chunk["pos"] hdrs[CHUNK_HEADERS["chunk_id"]] = chunk_path hdrs.update(self.headers) hdrs = encode(hdrs) with green.ConnectionTimeout(self.connection_timeout): if self.perfdata is not None: connect_start = monotonic_time() conn = io.http_connect(parsed.netloc, 'PUT', parsed.path, hdrs, scheme=parsed.scheme) conn.set_cork(True) if self.perfdata is not None: connect_end = monotonic_time() perfdata_rawx = self.perfdata.setdefault('rawx', dict()) perfdata_rawx['connect.' + chunk['url']] = \ connect_end - connect_start conn.chunk = chunk return conn, chunk except (SocketError, Timeout) as err: msg = str(err) self.logger.warn("Failed to connect to %s (reqid=%s): %s", chunk, self.reqid, err) except Exception as err: msg = str(err) self.logger.exception("Failed to connect to %s (reqid=%s)", chunk, self.reqid) chunk['error'] = msg return None, chunk