예제 #1
0
    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))
예제 #5
0
 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))
예제 #6
0
 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))
예제 #7
0
    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
예제 #8
0
    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
예제 #9
0
    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
예제 #10
0
    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
예제 #11
0
    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)
예제 #12
0
    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)
예제 #13
0
    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)
예제 #14
0
    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
예제 #15
0
    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)
예제 #16
0
    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
예제 #17
0
    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
예제 #18
0
    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
예제 #19
0
 def test_integrity_iter_with_checksum(self):
     fixture = 'CCC'
     checksum = 'defb99e69a9f1f6e06f15006b1f166ae'
     data = ''.join([f for f in utils.integrity_iter(fixture, checksum)])
 def test_integrity_iter_with_checksum(self):
     fixture = 'CCC'
     checksum = 'defb99e69a9f1f6e06f15006b1f166ae'
     data = ''.join([f for f in utils.integrity_iter(fixture, checksum)])