Example #1
0
    def test_copy_with_same_chunkid(self):
        metachunk_hash = md5().hexdigest()
        trailers = {
            'x-oio-chunk-meta-metachunk-size': 1,
            'x-oio-chunk-meta-metachunk-hash': metachunk_hash
        }

        chunkid1 = random_chunk_id()
        chunkdata1 = random_buffer(string.printable, 1)
        chunkurl1 = self._rawx_url(chunkid1)
        headers1 = self._chunk_attr(chunkid1, chunkdata1)
        self._check_not_present(chunkurl1)
        resp, _ = self._http_request(chunkurl1, 'PUT', chunkdata1, headers1,
                                     trailers)
        self.assertEqual(201, resp.status)
        self.assertEqual(headers1['x-oio-chunk-meta-chunk-hash'].upper(),
                         resp.getheader('x-oio-chunk-meta-chunk-hash'))
        self.assertEqual(headers1['x-oio-chunk-meta-chunk-size'].upper(),
                         resp.getheader('x-oio-chunk-meta-chunk-size'))

        headers = {}
        headers["Destination"] = chunkurl1
        headers['x-oio-chunk-meta-full-path'] = encode_fullpath(
            "account-snapshot", "container-snapshot", "content-snapshot",
            1456938361143741, random_id(32))
        resp, _ = self._http_request(chunkurl1, 'COPY', '', headers)
        self.assertEqual(403, resp.status)
Example #2
0
 def _put_chunk(self):
     account = random_str(16)
     container = random_str(16)
     cid = cid_from_name(account, container)
     content_path = random_str(16)
     content_version = 1234567890
     content_id = random_id(32)
     fullpath = encode_fullpath(account, container, content_path,
                                content_version, content_id)
     chunk_id = random_chunk_id()
     data = random_buffer(string.printable, 100)
     meta = {
         'full_path': fullpath,
         'container_id': cid,
         'content_path': content_path,
         'version': content_version,
         'id': content_id,
         'chunk_method': 'ec/algo=liberasurecode_rs_vand,k=6,m=3',
         'policy': 'TESTPOLICY',
         'chunk_hash': md5(data).hexdigest().upper(),
         'oio_version': OIO_VERSION,
         'chunk_pos': 0,
         'metachunk_hash': md5().hexdigest(),
         'metachunk_size': 1024
     }
     self.blob_client.chunk_put('http://' + self.rawx_id + '/' + chunk_id,
                                meta, data)
     sleep(1)  # ensure chunk event have been processed
     return account, container, cid, content_path, content_version, \
         content_id, chunk_id
Example #3
0
    def test_copy_with_nonexistent_source(self):
        metachunk_hash = md5().hexdigest()
        trailers = {'x-oio-chunk-meta-metachunk-size': '1',
                    'x-oio-chunk-meta-metachunk-hash': metachunk_hash}

        chunkid1 = random_chunk_id()
        chunkurl1 = self._rawx_url(chunkid1)

        chunkid2 = random_chunk_id()
        chunkdata2 = random_buffer(string.printable, 1).encode('utf-8')
        chunkurl2 = self._rawx_url(chunkid2)
        headers2 = self._chunk_attr(chunkid2, chunkdata2)
        self._check_not_present(chunkurl2)
        resp, _ = self._http_request(chunkurl2, 'PUT', chunkdata2, headers2,
                                     trailers)
        self.assertEqual(201, resp.status)
        self.assertEqual(headers2['x-oio-chunk-meta-chunk-hash'].upper(),
                         resp.getheader('x-oio-chunk-meta-chunk-hash'))
        self.assertEqual(headers2['x-oio-chunk-meta-chunk-size'],
                         resp.getheader('x-oio-chunk-meta-chunk-size'))

        headers = {}
        headers["Destination"] = chunkurl2
        headers['x-oio-chunk-meta-full-path'] = encode_fullpath(
                "account-snapshot", "container-snapshot", "content-snapshot",
                1456938361143741, random_id(32))
        resp, _ = self._http_request(chunkurl1, 'COPY', '', headers)
        self.assertEqual(404, resp.status)
Example #4
0
    def test_HEAD_chunk(self):
        length = 100
        chunkid = random_chunk_id()
        chunkdata = random_buffer(string.printable, length)
        chunkurl = self._rawx_url(chunkid)
        self._check_not_present(chunkurl)
        headers = self._chunk_attr(chunkid, chunkdata)
        metachunk_size = 9 * length
        metachunk_hash = md5(chunkdata).hexdigest()
        # TODO should also include meta-chunk-hash
        trailers = {
            'x-oio-chunk-meta-metachunk-size': metachunk_size,
            'x-oio-chunk-meta-metachunk-hash': metachunk_hash
        }
        # Initial put that must succeed
        resp, body = self._http_request(chunkurl, 'PUT', chunkdata, headers,
                                        trailers)
        self.assertEqual(201, resp.status)

        # default HEAD
        resp, body = self._http_request(chunkurl, 'HEAD', "", {})
        self.assertEqual(200, resp.status)

        resp, body = self._http_request(chunkurl, 'HEAD', '',
                                        {'X-oio-check-hash': True})
        self.assertEqual(200, resp.status)

        # Check with valid header
        resp, body = self._http_request(
            chunkurl, 'HEAD', "", {
                'X-oio-check-hash':
                "true",
                'x-oio-chunk-meta-chunk-hash':
                headers['x-oio-chunk-meta-chunk-hash'].upper()
            })
        self.assertEqual(200, resp.status)

        # Check with invalid header
        resp, body = self._http_request(chunkurl, 'HEAD', "", {
            'X-oio-check-hash': "true",
            'x-oio-chunk-meta-chunk-hash': 'xxx'
        })
        self.assertEqual(412, resp.status)

        # Check with corrupted chunk
        with open(self._chunk_path(chunkid), "wb") as fp:
            fp.write("chunk is dead")
        resp, body = self._http_request(chunkurl, 'HEAD', "",
                                        {'X-oio-check-hash': "true"})
        self.assertEqual(412, resp.status)
Example #5
0
    def test_copy_errors(self):
        length = 100
        chunkid = random_chunk_id()
        chunkdata = random_buffer(string.printable, length)
        chunkurl = self._rawx_url(chunkid)
        self._check_not_present(chunkurl)
        headers = self._chunk_attr(chunkid, chunkdata)
        metachunk_size = 9 * length
        # TODO take random legit value
        metachunk_hash = md5().hexdigest()
        # TODO should also include meta-chunk-hash
        trailers = {
            'x-oio-chunk-meta-metachunk-size': metachunk_size,
            'x-oio-chunk-meta-metachunk-hash': metachunk_hash
        }
        # Initial put that must succeed
        resp, body = self._http_request(chunkurl, 'PUT', chunkdata, headers,
                                        trailers)
        self.assertEqual(201, resp.status)
        self.assertEqual(headers['x-oio-chunk-meta-chunk-hash'].upper(),
                         resp.getheader('x-oio-chunk-meta-chunk-hash'))
        self.assertEqual(headers['x-oio-chunk-meta-chunk-size'],
                         resp.getheader('x-oio-chunk-meta-chunk-size'))
        copyid = random_chunk_id()
        copyid = chunkid[:-60] + copyid[-60:]
        copyurl = self._rawx_url(copyid)
        headers = {}
        headers["Destination"] = copyurl
        resp, _ = self._http_request(chunkurl, 'COPY', '', headers)
        self.assertEqual(400, resp.status)

        headers = {}
        headers["Destination"] = chunkurl
        headers['x-oio-chunk-meta-full-path'] = encode_fullpath(
            "account-snapshot", "container-snapshot", "test" + "-snapshot",
            1456938361143741, random_id(32))
        resp, _ = self._http_request(chunkurl, 'COPY', '', headers)
        self.assertEqual(403, resp.status)

        headers = {}
        resp, _ = self._http_request(chunkurl, 'COPY', '', headers)
        self.assertEqual(400, resp.status)
Example #6
0
    def _check_bad_headers(self, length, bad_headers=None, bad_trailers=None):
        chunkid = random_chunk_id()
        chunkdata = random_buffer(string.printable, length).encode('utf-8')
        chunkurl = self._rawx_url(chunkid)
        headers = self._chunk_attr(chunkid, chunkdata)
        # force the bad headers
        if bad_headers:
            for k, v in bad_headers.items():
                headers[k] = v
        trailers = None
        if bad_trailers:
            trailers = {}
            for k, v in bad_trailers.items():
                trailers[k] = v
                if headers.get(k, None):
                    del headers[k]

        self._check_not_present(chunkurl)

        resp, body = self._http_request(chunkurl, 'PUT', chunkdata, headers,
                                        trailers)
        self.assertEqual(400, resp.status)

        self._check_not_present(chunkurl)
Example #7
0
    def test_HEAD_chunk(self):
        length = 100
        chunkid = random_chunk_id()
        chunkdata = random_buffer(string.printable, length).encode('utf-8')
        chunkurl = self._rawx_url(chunkid)
        self._check_not_present(chunkurl)
        headers = self._chunk_attr(chunkid, chunkdata)
        metachunk_size = 9 * length
        metachunk_hash = md5(chunkdata).hexdigest()
        # TODO should also include meta-chunk-hash
        trailers = {'x-oio-chunk-meta-metachunk-size': str(metachunk_size),
                    'x-oio-chunk-meta-metachunk-hash': metachunk_hash}
        # Initial put that must succeed
        resp, body = self._http_request(chunkurl, 'PUT', chunkdata, headers,
                                        trailers)
        self.assertEqual(201, resp.status)

        # default HEAD
        resp, body = self._http_request(chunkurl, 'HEAD', "", {})
        self.assertEqual(200, resp.status)

        # Check the hash
        resp, body = self._http_request(
            chunkurl, 'HEAD', '',
            {'x-oio-check-hash': True})
        self.assertEqual(200, resp.status)

        # Check the hash with valid header
        resp, body = self._http_request(
            chunkurl, 'HEAD', '',
            {'x-oio-check-hash': True,
             'x-oio-chunk-meta-chunk-hash':
                headers['x-oio-chunk-meta-chunk-hash']})
        self.assertEqual(200, resp.status)

        # Check the hash with invalid header
        resp, body = self._http_request(
            chunkurl, 'HEAD', '',
            {'x-oio-check-hash': True,
             'x-oio-chunk-meta-chunk-hash': 'xxx'})
        self.assertEqual(412, resp.status)
        resp, body = self._http_request(
            chunkurl, 'HEAD', '',
            {'x-oio-check-hash': True,
             'x-oio-chunk-meta-chunk-hash': 'A'*32})
        self.assertEqual(412, resp.status)

        # Corrupt the chunk
        corrupted_data = b'chunk is dead'
        with open(self._chunk_path(chunkid), "wb") as fp:
            fp.write(corrupted_data)

        # Check the hash with corrupted chunk
        resp, body = self._http_request(
            chunkurl, 'HEAD', '',
            {'x-oio-check-hash': True})
        self.assertEqual(412, resp.status)

        if not self._compression():
            # Check the hash with corrupted chunk and valid header
            newh = md5(corrupted_data).hexdigest()
            resp, body = self._http_request(
                chunkurl, 'HEAD', '',
                {'x-oio-check-hash': True,
                 'x-oio-chunk-meta-chunk-hash': newh})
            self.assertEqual(200, resp.status)

        # Check the hash with corrupted chunk and invalid header
        resp, body = self._http_request(
            chunkurl, 'HEAD', '',
            {'x-oio-check-hash': True,
             'x-oio-chunk-meta-chunk-hash': 'xxx'})
        self.assertEqual(412, resp.status)
        resp, body = self._http_request(
            chunkurl, 'HEAD', '',
            {'x-oio-check-hash': True,
             'x-oio-chunk-meta-chunk-hash': 'A'*32})
        self.assertEqual(412, resp.status)

        # Check without xattr
        chunkid_woattr = chunkid[:3] + random_chunk_id()[3:]
        chunkurl_woattr = self._rawx_url(chunkid_woattr)
        with open(self._chunk_path(chunkid_woattr), "wb") as fp:
            fp.write(b"without xattrs")
        resp, body = self._http_request(
            chunkurl_woattr, 'HEAD', "",
            {'X-oio-check-hash': "true",
             REQID_HEADER: request_id('test_HEAD_chunk')})
        # If the size xattr is missing, we cannot read the chunk
        self.assertEqual(500, resp.status)
Example #8
0
    def test_read_old_chunk(self):
        metachunk_hash = md5().hexdigest()
        trailers = {'x-oio-chunk-meta-metachunk-size': '1',
                    'x-oio-chunk-meta-metachunk-hash': metachunk_hash}

        chunkid = random_chunk_id()
        chunkdata = random_buffer(string.printable, 1).encode('utf-8')
        chunkurl = self._rawx_url(chunkid)
        chunkpath = self._chunk_path(chunkid)
        headers = self._chunk_attr(chunkid, chunkdata)
        self._check_not_present(chunkurl)

        resp, _ = self._http_request(chunkurl, 'PUT', chunkdata, headers,
                                     trailers)
        self.assertEqual(201, resp.status)

        resp1, data1 = self._http_request(chunkurl, 'GET', '', {})
        self.assertEqual(200, resp1.status)
        headers1 = HeadersDict(resp1.getheaders())
        with open(chunkpath, 'r') as fd:
            meta1, _ = read_chunk_metadata(fd, chunkid)

        convert_to_old_chunk(
            chunkpath, self.account, self.container, self.content_path,
            self.content_version, self.content_id)

        resp2, data2 = self._http_request(chunkurl, 'GET', '', {})
        self.assertEqual(200, resp2.status)
        headers2 = HeadersDict(resp2.getheaders())
        with open(chunkpath, 'r') as fd:
            meta2, _ = read_chunk_metadata(fd, chunkid)

        self.assertEqual(data1, data2)
        del headers1[CHUNK_HEADERS['full_path']]
        del headers1[CHUNK_HEADERS['oio_version']]
        del headers2[CHUNK_HEADERS['oio_version']]
        del headers1["date"]
        del headers2["date"]
        self.assertDictEqual(headers1, headers2)
        del meta1['full_path']
        del meta1['oio_version']
        del meta2['oio_version']
        self.assertDictEqual(meta1, meta2)

        # Copy old chunk
        copyid = random_chunk_id()
        copyid = chunkid[:-60] + copyid[-60:]
        copyurl = self._rawx_url(copyid)
        copypath = self._chunk_path(copyid)
        copycontentid = random_id(32)
        copyheaders = {}
        copyheaders["Destination"] = copyurl
        copyheaders['x-oio-chunk-meta-full-path'] = encode_fullpath(
            "account-snapshot", "container-snapshot",
            self.content_path+"-snapshot", 1456938361143741, copycontentid)
        resp, _ = self._http_request(chunkurl, 'COPY', '', copyheaders)
        self.assertEqual(201, resp.status)

        resp2, data2 = self._http_request(chunkurl, 'GET', '', {})
        self.assertEqual(200, resp2.status)
        headers2 = HeadersDict(resp2.getheaders())
        with open(chunkpath, 'r') as fd:
            meta2, _ = read_chunk_metadata(fd, chunkid)

        self.assertEqual(1, len(meta2['links']))
        self.assertEqual(copyheaders['x-oio-chunk-meta-full-path'],
                         meta2['links'][copyid])
        meta2['links'] = dict()

        self.assertEqual(data1, data2)
        del headers2[CHUNK_HEADERS['oio_version']]
        del headers2["date"]
        self.assertDictEqual(headers1, headers2)
        del meta2['oio_version']
        self.assertDictEqual(meta1, meta2)

        resp3, data3 = self._http_request(copyurl, 'GET', '', {})
        self.assertEqual(200, resp3.status)
        headers3 = HeadersDict(resp3.getheaders())
        with open(copypath, 'r') as fd:
            meta3, _ = read_chunk_metadata(fd, copyid)

        self.assertEqual(
            copyheaders['x-oio-chunk-meta-full-path'],
            headers3['x-oio-chunk-meta-full-path'])
        del headers3['x-oio-chunk-meta-full-path']
        self.assertEqual(
            cid_from_name("account-snapshot", "container-snapshot"),
            headers3['x-oio-chunk-meta-container-id'])
        del headers1['x-oio-chunk-meta-container-id']
        del headers3['x-oio-chunk-meta-container-id']
        self.assertEqual(
            self.content_path+"-snapshot",
            unquote(headers3['x-oio-chunk-meta-content-path']))
        del headers1['x-oio-chunk-meta-content-path']
        del headers3['x-oio-chunk-meta-content-path']
        self.assertEqual(
            '1456938361143741',
            headers3['x-oio-chunk-meta-content-version'])
        del headers1['x-oio-chunk-meta-content-version']
        del headers3['x-oio-chunk-meta-content-version']
        self.assertEqual(
            copycontentid, headers3['x-oio-chunk-meta-content-id'])
        del headers1['x-oio-chunk-meta-content-id']
        del headers3['x-oio-chunk-meta-content-id']
        self.assertEqual(copyid, headers3['x-oio-chunk-meta-chunk-id'])
        del headers1['x-oio-chunk-meta-chunk-id']
        del headers3['x-oio-chunk-meta-chunk-id']

        self.assertEqual(
            copyheaders['x-oio-chunk-meta-full-path'], meta3['full_path'])
        del meta3['full_path']
        self.assertEqual(
            cid_from_name("account-snapshot", "container-snapshot"),
            meta3['container_id'])
        del meta1['container_id']
        del meta3['container_id']
        self.assertEqual(self.content_path+"-snapshot", meta3['content_path'])
        del meta1['content_path']
        del meta3['content_path']
        self.assertEqual('1456938361143741', meta3['content_version'])
        del meta1['content_version']
        del meta3['content_version']
        self.assertEqual(copycontentid, meta3['content_id'])
        del meta1['content_id']
        del meta3['content_id']
        self.assertEqual(copyid, meta3['chunk_id'])
        del meta1['chunk_id']
        del meta3['chunk_id']
        # FIXME the old chunk is invisible
        self.assertEqual(0, len(meta3['links']))

        self.assertEqual(data1, data3)
        del headers3[CHUNK_HEADERS['oio_version']]
        del headers3["date"]
        self.assertDictEqual(headers1, headers3)
        del meta3['oio_version']
        self.assertDictEqual(meta1, meta3)
Example #9
0
    def test_wrong_fullpath(self):
        metachunk_hash = md5().hexdigest()
        trailers = {'x-oio-chunk-meta-metachunk-size': '1',
                    'x-oio-chunk-meta-metachunk-hash': metachunk_hash}

        chunkid = random_chunk_id()
        chunkdata = random_buffer(string.printable, 1).encode('utf-8')
        chunkurl = self._rawx_url(chunkid)
        hdrs = self._chunk_attr(chunkid, chunkdata)
        self._check_not_present(chunkurl)

        headers = hdrs.copy()
        headers['x-oio-chunk-meta-full-path'] = encode_fullpath(
            self.account, 'blob', self.content_path, self.content_version,
            self.content_id) + "/too_long"
        resp, _ = self._http_request(chunkurl, 'PUT', chunkdata, headers,
                                     trailers)
        self.assertEqual(400, resp.status)

        headers = hdrs.copy()
        headers['x-oio-chunk-meta-full-path'] = encode_fullpath(
            self.account, 'blob', self.content_path, self.content_version,
            self.content_id).rsplit('/', 2)[0]
        resp, _ = self._http_request(chunkurl, 'PUT', chunkdata, headers,
                                     trailers)
        self.assertEqual(400, resp.status)

        headers = hdrs.copy()
        headers['x-oio-chunk-meta-full-path'] = encode_fullpath(
            'wrong-account', 'blob', self.content_path, self.content_version,
            self.content_id)
        resp, _ = self._http_request(chunkurl, 'PUT', chunkdata, headers,
                                     trailers)
        self.assertEqual(400, resp.status)

        headers = hdrs.copy()
        headers['x-oio-chunk-meta-full-path'] = encode_fullpath(
            self.account, 'wrong-container', self.content_path,
            self.content_version, self.content_id)
        resp, _ = self._http_request(chunkurl, 'PUT', chunkdata, headers,
                                     trailers)
        self.assertEqual(400, resp.status)

        headers = hdrs.copy()
        headers['x-oio-chunk-meta-full-path'] = encode_fullpath(
            self.account, 'blob', 'wrong-path', self.content_version,
            self.content_id)
        resp, _ = self._http_request(chunkurl, 'PUT', chunkdata, headers,
                                     trailers)
        self.assertEqual(400, resp.status)

        headers = hdrs.copy()
        headers['x-oio-chunk-meta-full-path'] = encode_fullpath(
            self.account, 'blob', self.content_path, 9999999999999999,
            self.content_id)
        resp, _ = self._http_request(chunkurl, 'PUT', chunkdata, headers,
                                     trailers)
        self.assertEqual(400, resp.status)

        headers = hdrs.copy()
        headers['x-oio-chunk-meta-full-path'] = encode_fullpath(
            self.account, 'blob', self.content_path, self.content_version,
            '9999999999999999')
        resp, _ = self._http_request(chunkurl, 'PUT', chunkdata, headers,
                                     trailers)
        self.assertEqual(400, resp.status)

        headers = hdrs.copy()
        del headers['x-oio-chunk-meta-container-id']
        headers['x-oio-chunk-meta-full-path'] = encode_fullpath(
            'empty', 'blob', self.content_path, self.content_version,
            self.content_id).replace('empty', '')
        resp, _ = self._http_request(chunkurl, 'PUT', chunkdata, headers,
                                     trailers)
        self.assertEqual(400, resp.status)

        headers = hdrs.copy()
        del headers['x-oio-chunk-meta-container-id']
        headers['x-oio-chunk-meta-full-path'] = encode_fullpath(
            self.account, 'empty', self.content_path, self.content_version,
            self.content_id).replace('empty', '')
        resp, _ = self._http_request(chunkurl, 'PUT', chunkdata, headers,
                                     trailers)
        self.assertEqual(400, resp.status)

        headers = hdrs.copy()
        del headers['x-oio-chunk-meta-content-path']
        headers['x-oio-chunk-meta-full-path'] = encode_fullpath(
            self.account, 'blob', 'empty', self.content_version,
            self.content_id).replace('empty', '')
        resp, _ = self._http_request(chunkurl, 'PUT', chunkdata, headers,
                                     trailers)
        self.assertEqual(400, resp.status)

        headers = hdrs.copy()
        del headers['x-oio-chunk-meta-content-version']
        headers['x-oio-chunk-meta-full-path'] = encode_fullpath(
            self.account, 'blob', self.content_path, 'empty',
            self.content_id).replace('empty', '')
        resp, _ = self._http_request(chunkurl, 'PUT', chunkdata, headers,
                                     trailers)
        self.assertEqual(400, resp.status)

        headers = hdrs.copy()
        del headers['x-oio-chunk-meta-content-id']
        headers['x-oio-chunk-meta-full-path'] = encode_fullpath(
            self.account, 'blob', self.content_path, self.content_version,
            'empty').replace('empty', '')
        resp, _ = self._http_request(chunkurl, 'PUT', chunkdata, headers,
                                     trailers)
        self.assertEqual(400, resp.status)

        headers = hdrs.copy()
        del headers['x-oio-chunk-meta-content-version']
        headers['x-oio-chunk-meta-full-path'] = encode_fullpath(
            self.account, 'blob', self.content_path, 'digit', self.content_id)
        resp, _ = self._http_request(chunkurl, 'PUT', chunkdata, headers,
                                     trailers)
        self.assertEqual(400, resp.status)

        headers = hdrs.copy()
        del headers['x-oio-chunk-meta-content-id']
        headers['x-oio-chunk-meta-full-path'] = encode_fullpath(
            self.account, 'blob', self.content_path, self.content_version,
            'hexa')
        resp, _ = self._http_request(chunkurl, 'PUT', chunkdata, headers,
                                     trailers)
        self.assertEqual(400, resp.status)
Example #10
0
    def _cycle_copy(self, path):
        if path:
            self.path = path
        chunkid = random_chunk_id()
        chunkdata = random_buffer(string.printable, 1).encode('utf-8')
        chunkurl = self._rawx_url(chunkid)
        chunkpath = self._chunk_path(chunkid)
        headers1 = self._chunk_attr(chunkid, chunkdata)
        metachunk_hash = md5().hexdigest()
        trailers = {'x-oio-chunk-meta-metachunk-size': '1',
                    'x-oio-chunk-meta-metachunk-hash': metachunk_hash}

        self._check_not_present(chunkurl)
        resp, _ = self._http_request(chunkurl, 'PUT', chunkdata, headers1,
                                     trailers)
        self.assertEqual(201, resp.status)
        self.assertEqual(headers1['x-oio-chunk-meta-chunk-hash'].upper(),
                         resp.getheader('x-oio-chunk-meta-chunk-hash'))
        self.assertEqual(headers1['x-oio-chunk-meta-chunk-size'],
                         resp.getheader('x-oio-chunk-meta-chunk-size'))

        copyid = random_chunk_id()
        copyid = chunkid[:-60] + copyid[-60:]
        copyurl = self._rawx_url(copyid)
        copypath = self._chunk_path(copyid)

        headers2 = {}
        headers2["Destination"] = copyurl
        copy_account = "account-snapshot"
        copy_container = "container-snapshot"
        copy_container_id = cid_from_name(copy_account, copy_container)
        copy_path = path+"-snapshot"
        copy_version = 1456938361143741
        copy_id = random_id(32)
        copy_fullpath = encode_fullpath(
            copy_account, copy_container, copy_path, copy_version, copy_id)
        headers2['x-oio-chunk-meta-full-path'] = copy_fullpath
        resp, _ = self._http_request(chunkurl, 'COPY', '', headers2)
        self.assertEqual(201, resp.status)

        resp, body = self._http_request(chunkurl, 'GET', '', {})
        self.assertEqual(200, resp.status)
        headers1['x-oio-chunk-meta-chunk-hash'] = \
            headers1['x-oio-chunk-meta-chunk-hash'].upper()
        for k, v in headers1.items():
            if k == 'x-oio-chunk-meta-content-path':
                self.assertEqual(unquote(resp.getheader(k)), unquote(str(v)))
            else:
                self.assertEqual(resp.getheader(k), str(v))

        resp, body = self._http_request(copyurl, 'GET', '', {})
        self.assertEqual(200, resp.status)
        headers2_bis = headers1.copy()
        headers2_bis['x-oio-chunk-meta-full-path'] = \
            headers2['x-oio-chunk-meta-full-path']
        headers2_bis['x-oio-chunk-meta-content-path'] = copy_path
        headers2_bis['x-oio-chunk-meta-content-version'] = copy_version
        headers2_bis['x-oio-chunk-meta-content-id'] = copy_id
        headers2_bis['x-oio-chunk-meta-container-id'] = copy_container_id
        headers2_bis['x-oio-chunk-meta-chunk-id'] = copyid
        for k, v in headers2_bis.items():
            if k == 'x-oio-chunk-meta-content-path':
                self.assertEqual(unquote(resp.getheader(k)), unquote(str(v)))
            else:
                self.assertEqual(resp.getheader(k), str(v))

        with open(chunkpath, 'r') as fd:
            meta, _ = read_chunk_metadata(fd, chunkid)
            self.assertEqual(headers1['x-oio-chunk-meta-full-path'],
                             meta['full_path'])
            self.assertEqual(1, len(meta['links']))
            self.assertEqual(headers2['x-oio-chunk-meta-full-path'],
                             meta['links'][copyid])

        with open(copypath, 'r') as fd:
            meta, _ = read_chunk_metadata(fd, copyid)
            self.assertEqual(headers2['x-oio-chunk-meta-full-path'],
                             meta['full_path'])
            self.assertEqual(1, len(meta['links']))
            self.assertEqual(headers1['x-oio-chunk-meta-full-path'],
                             meta['links'][chunkid])

        resp, body = self._http_request(chunkurl, 'DELETE', '', {})
        self.assertEqual(204, resp.status)
        resp, body = self._http_request(chunkurl, 'GET', '', {})
        self.assertEqual(404, resp.status)

        resp, body = self._http_request(copyurl, 'GET', '', {})
        self.assertEqual(200, resp.status)
        self.assertEqual(headers2['x-oio-chunk-meta-full-path'],
                         resp.getheader('x-oio-chunk-meta-full-path'))

        with open(copypath, 'r') as fd:
            meta, _ = read_chunk_metadata(fd, copyid)
            self.assertEqual(headers2['x-oio-chunk-meta-full-path'],
                             meta['full_path'])
            self.assertEqual(0, len(meta['links']))

        resp, body = self._http_request(copyurl, 'DELETE', '', {})
        self.assertEqual(204, resp.status)
        resp, body = self._http_request(copyurl, 'GET', '', {})
        self.assertEqual(404, resp.status)
Example #11
0
    def _cycle_put(self, length, expected, remove_headers=None, path=None,
                   old_fullpath=False, chunkid_lowercase=False):
        if path:
            self.path = path
        chunkid = random_chunk_id()
        chunkdata = random_buffer(string.printable, length).encode('utf-8')
        if chunkid_lowercase:
            chunkurl = self._rawx_url(chunkid.lower())
        else:
            chunkurl = self._rawx_url(chunkid)
        chunkpath = self._chunk_path(chunkid)
        headers = self._chunk_attr(chunkid, chunkdata)
        fullpath = headers['x-oio-chunk-meta-full-path']
        if old_fullpath:
            headers['x-oio-chunk-meta-full-path'] = \
                headers['x-oio-chunk-meta-full-path'].rsplit('/', 1)[0]
        if remove_headers:
            for h in remove_headers:
                del headers[h]

        # we do not really care about the actual value
        metachunk_size = 9 * length
        # TODO take random legit value
        metachunk_hash = md5().hexdigest()
        # TODO should also include meta-chunk-hash
        trailers = {'x-oio-chunk-meta-metachunk-size': str(metachunk_size),
                    'x-oio-chunk-meta-metachunk-hash': metachunk_hash}

        self._check_not_present(chunkurl)

        # Initial put that must succeed
        resp, body = self._http_request(chunkurl, 'PUT', chunkdata, headers,
                                        trailers)
        self.assertEqual(expected, resp.status)
        if expected // 100 != 2:
            self.assertFalse(isfile(chunkpath))
            return
        chunk_hash = headers.get('x-oio-chunk-meta-chunk-hash',
                                 md5(chunkdata).hexdigest()).upper()
        chunk_size = headers.get('x-oio-chunk-meta-chunk-size', str(length))
        self.assertEqual(chunk_hash,
                         resp.getheader('x-oio-chunk-meta-chunk-hash'))
        self.assertEqual(chunk_size,
                         resp.getheader('x-oio-chunk-meta-chunk-size'))

        # the first PUT succeeded, the second MUST fail
        resp, body = self._http_request(chunkurl, 'PUT', chunkdata, headers,
                                        trailers)
        self.assertEqual(409, resp.status)
        if not self._compression():
            # check the file if is correct
            with open(chunkpath, 'rb') as chunkf:
                data = chunkf.read()
                self.assertEqual(data, chunkdata)

        # check the whole download is correct
        # TODO FIXME getting an empty content should return 204
        resp, body = self._http_request(chunkurl, 'GET', '', {})
        self.assertEqual(200, resp.status)
        self.assertEqual(body, chunkdata)
        self.assertEqual(fullpath,
                         resp.getheader('x-oio-chunk-meta-full-path'))
        headers.pop('x-oio-chunk-meta-full-path')

        headers['x-oio-chunk-meta-metachunk-size'] = metachunk_size
        headers['x-oio-chunk-meta-metachunk-hash'] = metachunk_hash.upper()
        headers['x-oio-chunk-meta-chunk-hash'] = chunk_hash
        headers['x-oio-chunk-meta-chunk-size'] = chunk_size
        for k, v in headers.items():
            if k == 'x-oio-chunk-meta-content-path':
                self.assertEqual(unquote(resp.getheader(k)), unquote(str(v)))
            else:
                self.assertEqual(resp.getheader(k), str(v))

        # check ranges can be downloaded
        def ranges():
            if length <= 0:
                return
            yield (0, 0)
            if length > 1:
                yield (0, 1)
                yield (0, length-1)
                yield (length-2, length-1)
            if length > 4:
                yield (2, length-3)
        for start, end in ranges():
            r = "bytes={0}-{1}".format(start, end)
            resp, body = self._http_request(chunkurl, 'GET', '', {'Range': r})
            self.assertEqual(resp.status // 100, 2)
            self.assertEqual(len(body), end-start+1)
            self.assertEqual(body, chunkdata[start:end+1])
        if length > 0:
            # TODO FIXME getting an unsatisfiable range on an empty content
            # returns "200 OK" with an empty body, but should return 416
            r = "bytes={0}-{1}".format(length, length+1)
            resp, body = self._http_request(chunkurl, 'GET', '', {'Range': r})
            self.assertEqual(416, resp.status)

        # verify chunk checksum
        resp, body = self._http_request(chunkurl, 'HEAD', '',
                                        {'x-oio-check-hash': True})
        self.assertEqual(200, resp.status)

        # delete the chunk, check it is missing as expected
        resp, body = self._http_request(chunkurl, 'DELETE', '', {})
        self.assertEqual(204, resp.status)
        self.assertFalse(isfile(chunkpath))

        self._check_not_present(chunkurl)