def download_blob(self, artifact_id, blob_property, position=None, type_name=None, type_version=None, do_checksum=True): """Get blob data. :param artifact_id: ID of the artifact to download a blob :param blob_property: blob property name :param position: if blob_property is a list then the position must be specified :param do_checksum: Enable/disable checksum validation. """ type_name, type_version = self._check_type_params( type_name, type_version) url = '/v0.1/artifacts/%s/v%s/%s/%s' % (type_name, type_version, artifact_id, blob_property) if position: url += '/%s' % position url += '/download' resp, body = self.http_client.get(url) checksum = resp.headers.get('content-md5', None) content_length = int(resp.headers.get('content-length', 0)) if checksum is not None and do_checksum: body = utils.integrity_iter(body, checksum) return utils.IterableWithLength(body, content_length)
def download_blob(self, artifact_id, blob_property, position=None, type_name=None, type_version=None, do_checksum=True): """Get blob data. :param artifact_id: ID of the artifact to download a blob :param blob_property: blob property name :param position: if blob_property is a list then the position must be specified :param do_checksum: Enable/disable checksum validation. """ type_name, type_version = self._check_type_params(type_name, type_version) url = glare_urls['blob'].format(version=self.version, type_name=type_name, type_version=type_version, artifact_id=artifact_id, blob_property=blob_property) if position: url += '/%s' % position url += '/download' resp, body = self.http_client.get(url) checksum = resp.headers.get('content-md5', None) content_length = int(resp.headers.get('content-length', 0)) if checksum is not None and do_checksum: body = utils.integrity_iter(body, checksum) return utils.IterableWithLength(body, content_length)
def test_integrity_iter_with_wrong_checksum(self): try: data = ''.join([f for f in utils.integrity_iter('BB', 'wrong')]) self.fail('integrity checked passed with wrong checksum') except IOError as e: self.assertEqual(errno.EPIPE, e.errno) msg = 'was 9d3d9048db16a7eee539e93e3618cbe7 expected wrong' self.assertTrue('expected wrong' in str(e))
def test_integrity_iter_without_checksum(self): try: data = ''.join([f for f in utils.integrity_iter('A', None)]) self.fail('integrity checked passed without checksum.') except IOError as e: self.assertEqual(errno.EPIPE, e.errno) msg = 'was 7fc56270e7a70fa81a5935b72eacbe29 expected None' self.assertTrue(msg in str(e))
def test_integrity_iter_without_checksum(self): try: data = ''.join([f for f in utils.integrity_iter('A', None)]) self.fail('integrity checked passed without checksum.') except IOError, e: self.assertEqual(errno.EPIPE, e.errno) msg = 'was 7fc56270e7a70fa81a5935b72eacbe29 expected None' self.assertTrue(msg in str(e))
def test_integrity_iter_with_wrong_checksum(self): try: data = ''.join([f for f in utils.integrity_iter('BB', 'wrong')]) self.fail('integrity checked passed with wrong checksum') except IOError, e: self.assertEqual(errno.EPIPE, e.errno) msg = 'was 9d3d9048db16a7eee539e93e3618cbe7 expected wrong' self.assertTrue('expected wrong' in str(e))
def data(self, image, do_checksum=True): """Get the raw data for a specific image. :param image: image object or id to look up :param do_checksum: Enable/disable checksum validation :rtype: iterable containing image data """ image_id = base.getid(image) resp, body = self.api.raw_request('GET', '/v1/images/%s' % image_id) checksum = resp.getheader('x-image-meta-checksum', None) if do_checksum and checksum is not None: return utils.integrity_iter(body, checksum) else: return body
def data(self, image_id, do_checksum=True): """ Retrieve data of an image. :param image_id: ID of the image to download. :param do_checksum: Enable/disable checksum validation. """ url = '/v2/images/%s/file' % image_id resp, body = self.http_client.get(url) checksum = resp.headers.get('content-md5', None) if do_checksum and checksum is not None: return utils.integrity_iter(body, checksum) else: return body
def data(self, image_id, do_checksum=True): """ Retrieve data of an image. :param image_id: ID of the image to download. :param do_checksum: Enable/disable checksum validation. """ url = '/v2/images/%s/file' % image_id resp, body = self.http_client.raw_request('GET', url) checksum = resp.getheader('content-md5', None) if do_checksum and checksum is not None: return utils.integrity_iter(body, checksum) else: return body
def data(self, image_id, do_checksum=True): """Retrieve data of an image. :param image_id: ID of the image to download. :param do_checksum: Enable/disable checksum validation. """ url = '/v2/images/%s/file' % image_id resp, body = self.http_client.get(url) checksum = resp.headers.get('content-md5', None) content_length = int(resp.headers.get('content-length', 0)) if do_checksum and checksum is not None: body = utils.integrity_iter(body, checksum) return utils.IterableWithLength(body, content_length)
def data(self, image_id, do_checksum=True): """ Retrieve data of an image. :param image_id: ID of the image to download. :param do_checksum: Enable/disable checksum validation. """ url = "/v2/images/%s/file" % image_id resp, body = self.http_client.get(url) checksum = resp.headers.get("content-md5", None) content_length = int(resp.headers.get("content-length", 0)) if do_checksum and checksum is not None: body = utils.integrity_iter(body, checksum) return utils.IterableWithLength(body, content_length)
def data(self, image, do_checksum=True, **kwargs): """Get the raw data for a specific image. :param image: image object or id to look up :param do_checksum: Enable/disable checksum validation :rtype: iterable containing image data """ image_id = base.getid(image) resp, body = self.client.get("/v1/images/%s" % urlparse.quote(str(image_id))) content_length = int(resp.headers.get("content-length", 0)) checksum = resp.headers.get("x-image-meta-checksum", None) if do_checksum and checksum is not None: body = utils.integrity_iter(body, checksum) return_request_id = kwargs.get("return_req_id", None) if return_request_id is not None: return_request_id.append(resp.headers.get(OS_REQ_ID_HDR, None)) return utils.IterableWithLength(body, content_length)
def data(self, image, do_checksum=True, **kwargs): """Get the raw data for a specific image. :param image: image object or id to look up :param do_checksum: Enable/disable checksum validation :rtype: iterable containing image data """ image_id = base.getid(image) resp, body = self.client.get('/v1/images/%s' % urlparse.quote(str(image_id))) checksum = resp.headers.get('x-image-meta-checksum', None) if do_checksum and checksum is not None: return utils.integrity_iter(body, checksum) return_request_id = kwargs.get('return_req_id', None) if return_request_id is not None: return_request_id.append(resp.headers.get(OS_REQ_ID_HDR, None)) return body
def data(self, image_id, do_checksum=True): """Retrieve data of an image. :param image_id: ID of the image to download. :param do_checksum: Enable/disable checksum validation. :returns: An iterable body or None """ url = '/v2/images/%s/file' % image_id resp, body = self.http_client.get(url) if resp.status_code == codes.no_content: return None checksum = resp.headers.get('content-md5', None) content_length = int(resp.headers.get('content-length', 0)) if do_checksum and checksum is not None: body = utils.integrity_iter(body, checksum) return utils.IterableWithLength(body, content_length)
def data(self, image_id, do_checksum=True): """Retrieve data of an image. :param image_id: ID of the image to download. :param do_checksum: Enable/disable checksum validation. :returns: An iterable body or None """ url = '/v2/images/%s/file' % image_id resp, body = self.http_client.get(url) if resp.status_code == codes.no_content: LOG.error( "Got no content from url: %s. " "Request returned failure status %s.", url, resp.status_code) return None, resp checksum = resp.headers.get('content-md5', None) content_length = int(resp.headers.get('content-length', 0)) if do_checksum and checksum is not None: body = utils.integrity_iter(body, checksum) return utils.IterableWithLength(body, content_length), resp
def data(self, image_id, do_checksum=True, allow_md5_fallback=False): """Retrieve data of an image. When do_checksum is enabled, validation proceeds as follows: 1. if the image has a 'os_hash_value' property, the algorithm specified in the image's 'os_hash_algo' property will be used to validate against the 'os_hash_value' value. If the specified hash algorithm is not available AND allow_md5_fallback is True, then continue to step #2 2. else if the image has a checksum property, MD5 is used to validate against the 'checksum' value 3. else if the download response has a 'content-md5' header, MD5 is used to validate against the header value 4. if none of 1-3 obtain, the data is **not validated** (this is compatible with legacy behavior) :param image_id: ID of the image to download :param do_checksum: Enable/disable checksum validation :param allow_md5_fallback: Use the MD5 checksum for validation if the algorithm specified by the image's 'os_hash_algo' property is not available :returns: An iterable body or ``None`` """ if do_checksum: # doing this first to prevent race condition if image record # is deleted during the image download url = '/v2/images/%s' % image_id resp, image_meta = self.http_client.get(url) meta_checksum = image_meta.get('checksum', None) meta_hash_value = image_meta.get('os_hash_value', None) meta_hash_algo = image_meta.get('os_hash_algo', None) url = '/v2/images/%s/file' % image_id resp, body = self.http_client.get(url) if resp.status_code == codes.no_content: return None, resp checksum = resp.headers.get('content-md5', None) content_length = int(resp.headers.get('content-length', 0)) check_md5sum = do_checksum if do_checksum and meta_hash_value is not None: try: hasher = hashlib.new(str(meta_hash_algo)) body = utils.serious_integrity_iter(body, hasher, meta_hash_value) check_md5sum = False except ValueError as ve: if (str(ve).startswith('unsupported hash type') and allow_md5_fallback): check_md5sum = True else: raise if do_checksum and check_md5sum: if meta_checksum is not None: body = utils.integrity_iter(body, meta_checksum) elif checksum is not None: body = utils.integrity_iter(body, checksum) else: # NOTE(rosmaita): this preserves legacy behavior to return the # image data when checksumming is requested but there's no # 'content-md5' header in the response. Just want to make it # clear that we're doing this on purpose. pass return utils.IterableWithLength(body, content_length), resp
def data(self, image_id, do_checksum=True, allow_md5_fallback=False): """Retrieve data of an image. When do_checksum is enabled, validation proceeds as follows: 1. if the image has a 'os_hash_value' property, the algorithm specified in the image's 'os_hash_algo' property will be used to validate against the 'os_hash_value' value. If the specified hash algorithm is not available AND allow_md5_fallback is True, then continue to step #2 2. else if the image has a checksum property, MD5 is used to validate against the 'checksum' value. (If MD5 is not available to the client, the download fails.) 3. else if the download response has a 'content-md5' header, MD5 is used to validate against the header value. (If MD5 is not available to the client, the download fails.) 4. if none of 1-3 obtain, the data is **not validated** (this is compatible with legacy behavior) :param image_id: ID of the image to download :param do_checksum: Enable/disable checksum validation :param allow_md5_fallback: Use the MD5 checksum for validation if the algorithm specified by the image's 'os_hash_algo' property is not available :returns: An iterable body or ``None`` """ if do_checksum: # doing this first to prevent race condition if image record # is deleted during the image download url = '/v2/images/%s' % image_id resp, image_meta = self.http_client.get(url) meta_checksum = image_meta.get('checksum', None) meta_hash_value = image_meta.get('os_hash_value', None) meta_hash_algo = image_meta.get('os_hash_algo', None) url = '/v2/images/%s/file' % image_id resp, body = self.http_client.get(url) if resp.status_code == codes.no_content: return None, resp checksum = resp.headers.get('content-md5', None) content_length = int(resp.headers.get('content-length', 0)) check_md5sum = do_checksum if do_checksum and meta_hash_value is not None: try: hasher = hashlib.new(str(meta_hash_algo)) body = utils.serious_integrity_iter(body, hasher, meta_hash_value) check_md5sum = False except ValueError as ve: if (str(ve).startswith('unsupported hash type') and allow_md5_fallback): check_md5sum = True else: raise if do_checksum and check_md5sum: if meta_checksum is not None: body = utils.integrity_iter(body, meta_checksum) elif checksum is not None: body = utils.integrity_iter(body, checksum) else: # NOTE(rosmaita): this preserves legacy behavior to return the # image data when checksumming is requested but there's no # 'content-md5' header in the response. Just want to make it # clear that we're doing this on purpose. pass return utils.IterableWithLength(body, content_length), resp
def test_integrity_iter_with_checksum(self): fixture = 'CCC' checksum = 'defb99e69a9f1f6e06f15006b1f166ae' data = ''.join([f for f in utils.integrity_iter(fixture, checksum)])