示例#1
0
 def test_sort_ec(self):
     ec_chunks = ChunksHelper([
         self.ec_c1_2, self.ec_c1_1, self.ec_c1_0,
         self.ec_c0_2, self.ec_c0_1, self.ec_c0_0
     ])
     self.assertEqual(ec_chunks.raw(), [
         self.ec_c0_0, self.ec_c0_1, self.ec_c0_2,
         self.ec_c1_0, self.ec_c1_1, self.ec_c1_2
     ])
示例#2
0
 def test_sort_rain(self):
     rain_chunks = ChunksHelper([
         self.rain_c1_p, self.rain_c1_1, self.rain_c1_0,
         self.rain_c0_p, self.rain_c0_1, self.rain_c0_0
     ])
     self.assertEqual(rain_chunks.raw(), [
         self.rain_c0_0, self.rain_c0_1, self.rain_c0_p,
         self.rain_c1_0, self.rain_c1_1, self.rain_c1_p
     ])
示例#3
0
 def test_sort_dup(self):
     chunks = ChunksHelper([
         self.dup_c2_2, self.dup_c2_1,
         self.dup_c1_2, self.dup_c1_1
     ])
     self.assertEqual(chunks.raw(), [
         self.dup_c1_1, self.dup_c1_2,
         self.dup_c2_1, self.dup_c2_2
     ])
示例#4
0
 def test_sort_ec(self):
     ec_chunks = ChunksHelper([
         self.ec_c1_2, self.ec_c1_1, self.ec_c1_0,
         self.ec_c0_2, self.ec_c0_1, self.ec_c0_0
     ])
     self.assertEqual(ec_chunks.raw(), [
         self.ec_c0_0, self.ec_c0_1, self.ec_c0_2,
         self.ec_c1_0, self.ec_c1_1, self.ec_c1_2
     ])
示例#5
0
 def test_sort_dup(self):
     chunks = ChunksHelper([
         self.dup_c2_2, self.dup_c2_1,
         self.dup_c1_2, self.dup_c1_1
     ])
     self.assertEqual(chunks.raw(), [
         self.dup_c1_1, self.dup_c1_2,
         self.dup_c2_1, self.dup_c2_2
     ])
示例#6
0
 def test_sort_rain(self):
     rain_chunks = ChunksHelper([
         self.rain_c1_p, self.rain_c1_1, self.rain_c1_0, self.rain_c0_p,
         self.rain_c0_1, self.rain_c0_0
     ])
     self.assertEqual(rain_chunks.raw(), [
         self.rain_c0_0, self.rain_c0_1, self.rain_c0_p, self.rain_c1_0,
         self.rain_c1_1, self.rain_c1_p
     ])
示例#7
0
    def _test_create(self, stgpol, data_size):
        data = random_data(data_size)
        content = self.content_factory.new(self.container_id, self.content,
                                           len(data), stgpol)

        content.create(BytesIO(data))

        meta, chunks = self.container_client.content_locate(
            cid=self.container_id, content=content.content_id)
        self.assertEqual(meta['hash'], md5_data(data))
        self.assertEqual(meta['length'], str(len(data)))
        self.assertEqual(meta['policy'], stgpol)
        self.assertEqual(meta['name'], self.content)

        metachunk_nb = int(math.ceil(float(len(data)) / self.chunk_size))
        if metachunk_nb == 0:
            metachunk_nb = 1  # special case for empty content

        chunks = ChunksHelper(chunks)

        # TODO NO NO NO
        if stgpol == self.stgpol_threecopies:
            nb_copy = 3
        elif stgpol == self.stgpol_twocopies:
            nb_copy = 2
        elif stgpol == self.stgpol:
            nb_copy = 1

        self.assertEqual(len(chunks), metachunk_nb * nb_copy)

        for pos in range(metachunk_nb):
            chunks_at_pos = chunks.filter(pos=pos)
            self.assertEqual(len(chunks_at_pos), nb_copy)

            data_begin = pos * self.chunk_size
            data_end = pos * self.chunk_size + self.chunk_size
            chunk_hash = md5_data(data[data_begin:data_end])

            for chunk in chunks_at_pos:
                meta, stream = self.blob_client.chunk_get(chunk.url)
                self.assertEqual(md5_stream(stream), chunk_hash)
                self.assertEqual(meta['content_path'], self.content)
                self.assertEqual(meta['container_id'], self.container_id)
                self.assertEqual(meta['content_id'], meta['content_id'])
                self.assertEqual(meta['chunk_id'], chunk.id)
                self.assertEqual(meta['chunk_pos'], str(pos))
                # Check that chunk data matches chunk hash from xattr
                self.assertEqual(meta['chunk_hash'], chunk_hash)
                # Check that chunk data matches chunk hash from database
                self.assertEqual(chunk.checksum, chunk_hash)
                full_path = encode_fullpath(self.account, self.container_name,
                                            self.content,
                                            meta['content_version'],
                                            meta['content_id'])
                self.assertEqual(meta['full_path'], full_path)
                self.assertEqual(meta['oio_version'], '4.2')
示例#8
0
    def setUp(self):
        super(TestChunksHelper, self).setUp()

        self.dup_c1_1 = {
            "url": "http://127.0.0.1:6011/C1C1",
            "pos": "0", "size": 1048576,
            "hash": "2E47D13C3E2C47E0C537028AD637CCBF"}
        self.dup_c1_2 = {
            "url": "http://127.0.0.1:6010/C1C2",
            "pos": "0", "size": 1048576,
            "hash": "2E47D13C3E2C47E0C537028AD637CCBF"}
        self.dup_c2_1 = {
            "url": "http://127.0.0.1:6012/C2C1",
            "pos": "1", "size": 1048576,
            "hash": "045B70673D8271767D4D21BCDB040F6C"}
        self.dup_c2_2 = {
            "url": "http://127.0.0.1:6011/C2C2",
            "pos": "1", "size": 1048576,
            "hash": "045B70673D8271767D4D21BCDB040F6C"
        }
        self.dup_chunks_raw = [self.dup_c1_1, self.dup_c1_2,
                               self.dup_c2_1, self.dup_c2_2]
        self.dup_chunks = ChunksHelper(self.dup_chunks_raw)

        self.ec_c0_0 = {
            "url": "http://127.0.0.1:6017/C0_0",
            "pos": "0.0", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_c0_1 = {
            "url": "http://127.0.0.1:6016/C0_1",
            "pos": "0.1", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_c0_2 = {
            "url": "http://127.0.0.1:6011/C0_P",
            "pos": "0.2", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_c1_0 = {
            "url": "http://127.0.0.1:6017/C1_0",
            "pos": "1.0", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_c1_1 = {
            "url": "http://127.0.0.1:6016/C1_1",
            "pos": "1.1", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_c1_2 = {
            "url": "http://127.0.0.1:6011/C1_P",
            "pos": "1.2", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_chunks_raw = [self.ec_c0_0, self.ec_c0_1, self.ec_c0_2,
                              self.ec_c1_0, self.ec_c1_1, self.ec_c1_2]
        self.ec_chunks = ChunksHelper(self.ec_chunks_raw)
示例#9
0
    def setUp(self):
        super(TestChunksHelper, self).setUp()

        self.dup_c1_1 = {
            "url": "http://127.0.0.1:6011/C1C1",
            "pos": "0", "size": 1048576,
            "hash": "2E47D13C3E2C47E0C537028AD637CCBF"}
        self.dup_c1_2 = {
            "url": "http://127.0.0.1:6010/C1C2",
            "pos": "0", "size": 1048576,
            "hash": "2E47D13C3E2C47E0C537028AD637CCBF"}
        self.dup_c2_1 = {
            "url": "http://127.0.0.1:6012/C2C1",
            "pos": "1", "size": 1048576,
            "hash": "045B70673D8271767D4D21BCDB040F6C"}
        self.dup_c2_2 = {
            "url": "http://127.0.0.1:6011/C2C2",
            "pos": "1", "size": 1048576,
            "hash": "045B70673D8271767D4D21BCDB040F6C"
        }
        self.dup_chunks_raw = [self.dup_c1_1, self.dup_c1_2,
                               self.dup_c2_1, self.dup_c2_2]
        self.dup_chunks = ChunksHelper(self.dup_chunks_raw)

        self.ec_c0_0 = {
            "url": "http://127.0.0.1:6017/C0_0",
            "pos": "0.0", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_c0_1 = {
            "url": "http://127.0.0.1:6016/C0_1",
            "pos": "0.1", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_c0_2 = {
            "url": "http://127.0.0.1:6011/C0_P",
            "pos": "0.2", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_c1_0 = {
            "url": "http://127.0.0.1:6017/C1_0",
            "pos": "1.0", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_c1_1 = {
            "url": "http://127.0.0.1:6016/C1_1",
            "pos": "1.1", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_c1_2 = {
            "url": "http://127.0.0.1:6011/C1_P",
            "pos": "1.2", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_chunks_raw = [self.ec_c0_0, self.ec_c0_1, self.ec_c0_2,
                              self.ec_c1_0, self.ec_c1_1, self.ec_c1_2]
        self.ec_chunks = ChunksHelper(self.ec_chunks_raw)
示例#10
0
    def _test_upload(self, stgpol, data_size):
        data = random_data(data_size)
        content = self.content_factory.new(self.container_id, "titi",
                                           len(data), stgpol)
        self.assertEqual(type(content), DupContent)

        content.upload(StringIO.StringIO(data))

        meta, chunks = self.container_client.content_show(
            cid=self.container_id, content=content.content_id)
        chunks = ChunksHelper(chunks)
        self.assertEqual(meta['hash'], md5_data(data))
        self.assertEqual(meta['length'], str(len(data)))
        self.assertEqual(meta['policy'], stgpol)
        self.assertEqual(meta['name'], "titi")

        metachunk_nb = int(math.ceil(float(len(data)) / self.chunk_size))
        if metachunk_nb == 0:
            metachunk_nb = 1  # special case for empty content

        if stgpol == "THREECOPIES":
            nb_copy = 3
        elif stgpol == "TWOCOPIES":
            nb_copy = 2
        elif stgpol == "SINGLE":
            nb_copy = 1

        self.assertEqual(len(chunks), metachunk_nb * nb_copy)

        for pos in range(metachunk_nb):
            chunks_at_pos = chunks.filter(pos=pos)
            self.assertEqual(len(chunks_at_pos), nb_copy)

            data_begin = pos * self.chunk_size
            data_end = pos * self.chunk_size + self.chunk_size
            chunk_hash = md5_data(data[data_begin:data_end])

            for chunk in chunks_at_pos:
                meta, stream = self.blob_client.chunk_get(chunk.url)
                self.assertEqual(md5_stream(stream), chunk_hash)
                self.assertEqual(meta['content_size'], str(len(data)))
                self.assertEqual(meta['content_path'], "titi")
                self.assertEqual(meta['content_cid'], self.container_id)
                self.assertEqual(meta['content_id'], meta['content_id'])
                self.assertEqual(meta['chunk_id'], chunk.id)
                self.assertEqual(meta['chunk_pos'], str(pos))
                self.assertEqual(meta['chunk_hash'], chunk_hash)
示例#11
0
    def _test_create(self, stgpol, data_size):
        data = random_data(data_size)
        content = self.content_factory.new(self.container_id, self.content,
                                           len(data), stgpol)

        content.create(StringIO(data))

        meta, chunks = self.container_client.content_show(
            cid=self.container_id, content=content.content_id)
        self.assertEqual(meta['hash'], md5_data(data))
        self.assertEqual(meta['length'], str(len(data)))
        self.assertEqual(meta['policy'], stgpol)
        self.assertEqual(meta['name'], self.content)

        metachunk_nb = int(math.ceil(float(len(data)) / self.chunk_size))
        if metachunk_nb == 0:
            metachunk_nb = 1  # special case for empty content

        chunks = ChunksHelper(chunks)

        # TODO NO NO NO
        if stgpol == self.stgpol_threecopies:
            nb_copy = 3
        elif stgpol == self.stgpol_twocopies:
            nb_copy = 2
        elif stgpol == self.stgpol:
            nb_copy = 1

        self.assertEqual(len(chunks), metachunk_nb * nb_copy)

        for pos in range(metachunk_nb):
            chunks_at_pos = chunks.filter(pos=pos)
            self.assertEqual(len(chunks_at_pos), nb_copy)

            data_begin = pos * self.chunk_size
            data_end = pos * self.chunk_size + self.chunk_size
            chunk_hash = md5_data(data[data_begin:data_end])

            for chunk in chunks_at_pos:
                meta, stream = self.blob_client.chunk_get(chunk.url)
                self.assertEqual(md5_stream(stream), chunk_hash)
                self.assertEqual(meta['content_path'], self.content)
                self.assertEqual(meta['container_id'], self.container_id)
                self.assertEqual(meta['content_id'], meta['content_id'])
                self.assertEqual(meta['chunk_id'], chunk.id)
                self.assertEqual(meta['chunk_pos'], str(pos))
                self.assertEqual(meta['chunk_hash'], chunk_hash)
示例#12
0
    def _test_upload(self, stgpol, data_size):
        data = random_data(data_size)
        content = self.content_factory.new(self.container_id, "titi",
                                           len(data), stgpol)
        self.assertEqual(type(content), DupContent)

        content.upload(StringIO.StringIO(data))

        meta, chunks = self.container_client.content_show(
            cid=self.container_id, content=content.content_id)
        chunks = ChunksHelper(chunks)
        self.assertEqual(meta['hash'], md5_data(data))
        self.assertEqual(meta['length'], str(len(data)))
        self.assertEqual(meta['policy'], stgpol)
        self.assertEqual(meta['name'], "titi")

        metachunk_nb = int(math.ceil(float(len(data)) / self.chunk_size))
        if metachunk_nb == 0:
            metachunk_nb = 1  # special case for empty content

        if stgpol == "THREECOPIES":
            nb_copy = 3
        elif stgpol == "TWOCOPIES":
            nb_copy = 2
        elif stgpol == "SINGLE":
            nb_copy = 1

        self.assertEqual(len(chunks), metachunk_nb * nb_copy)

        for pos in range(metachunk_nb):
            chunks_at_pos = chunks.filter(pos=pos)
            self.assertEqual(len(chunks_at_pos), nb_copy)

            data_begin = pos * self.chunk_size
            data_end = pos * self.chunk_size + self.chunk_size
            chunk_hash = md5_data(data[data_begin:data_end])

            for chunk in chunks_at_pos:
                meta, stream = self.blob_client.chunk_get(chunk.url)
                self.assertEqual(md5_stream(stream), chunk_hash)
                self.assertEqual(meta['content_size'], str(len(data)))
                self.assertEqual(meta['content_path'], "titi")
                self.assertEqual(meta['content_cid'], self.container_id)
                self.assertEqual(meta['content_id'], meta['content_id'])
                self.assertEqual(meta['chunk_id'], chunk.id)
                self.assertEqual(meta['chunk_pos'], str(pos))
                self.assertEqual(meta['chunk_hash'], chunk_hash)
示例#13
0
    def _test_create(self, stgpol, data_size):
        data = random_data(data_size)
        content = self.content_factory.new(self.container_id, self.content,
                                           len(data), stgpol)

        content.create(StringIO(data))

        meta, chunks = self.container_client.content_show(
            cid=self.container_id, content=content.content_id)
        self.assertEqual(meta['hash'], md5_data(data))
        self.assertEqual(meta['length'], str(len(data)))
        self.assertEqual(meta['policy'], stgpol)
        self.assertEqual(meta['name'], self.content)

        metachunk_nb = int(math.ceil(float(len(data)) / self.chunk_size))
        if metachunk_nb == 0:
            metachunk_nb = 1  # special case for empty content

        chunks = ChunksHelper(chunks)

        # TODO NO NO NO
        if stgpol == self.stgpol_threecopies:
            nb_copy = 3
        elif stgpol == self.stgpol_twocopies:
            nb_copy = 2
        elif stgpol == self.stgpol:
            nb_copy = 1

        self.assertEqual(len(chunks), metachunk_nb * nb_copy)

        for pos in range(metachunk_nb):
            chunks_at_pos = chunks.filter(pos=pos)
            self.assertEqual(len(chunks_at_pos), nb_copy)

            data_begin = pos * self.chunk_size
            data_end = pos * self.chunk_size + self.chunk_size
            chunk_hash = md5_data(data[data_begin:data_end])

            for chunk in chunks_at_pos:
                meta, stream = self.blob_client.chunk_get(chunk.url)
                self.assertEqual(md5_stream(stream), chunk_hash)
                self.assertEqual(meta['content_path'], self.content)
                self.assertEqual(meta['container_id'], self.container_id)
                self.assertEqual(meta['content_id'], meta['content_id'])
                self.assertEqual(meta['chunk_id'], chunk.id)
                self.assertEqual(meta['chunk_pos'], str(pos))
                self.assertEqual(meta['chunk_hash'], chunk_hash)
示例#14
0
    def _test_upload(self, data_size):
        data = random_data(data_size)
        content = self.content_factory.new(self.container_id, "titi",
                                           len(data), "RAIN")
        k = 6
        m = 2
        self.assertEqual(type(content), RainContent)

        content.upload(StringIO.StringIO(data))

        meta, chunks = self.container_client.content_show(
            cid=self.container_id, content=content.content_id)
        chunks = ChunksHelper(chunks)
        self.assertEqual(meta['hash'], md5_data(data))
        self.assertEqual(meta['length'], str(len(data)))
        self.assertEqual(meta['policy'], "RAIN")
        self.assertEqual(meta['name'], "titi")

        metachunk_nb = int(math.ceil(float(len(data)) / self.chunk_size))
        if metachunk_nb == 0:
            metachunk_nb = 1  # special case for empty content

        nb_chunks_min = metachunk_nb * (1 + m)
        nb_chunks_max = metachunk_nb * (k + m)
        self.assertGreaterEqual(len(chunks), nb_chunks_min)
        self.assertLessEqual(len(chunks), nb_chunks_max)

        for metapos in range(metachunk_nb):
            chunks_at_pos = content.chunks.filter(metapos=metapos)
            data_chunks_at_pos = chunks_at_pos.filter(is_parity=False)
            parity_chunks_at_pos = chunks_at_pos.filter(is_parity=True)

            self.assertEquals(len(data_chunks_at_pos) >= 1, True)
            self.assertEquals(len(data_chunks_at_pos) <= k, True)
            self.assertEqual(len(parity_chunks_at_pos), m)

            for chunk in chunks_at_pos:
                meta, stream = self.blob_client.chunk_get(chunk.url)
                self.assertEqual(md5_stream(stream), chunk.hash)
                self.assertEqual(meta['content_size'], str(len(data)))
                self.assertEqual(meta['content_path'], "titi")
                self.assertEqual(meta['content_cid'], self.container_id)
                self.assertEqual(meta['content_id'], meta['content_id'])
                self.assertEqual(meta['chunk_id'], chunk.id)
                self.assertEqual(meta['chunk_pos'], chunk.pos)
                self.assertEqual(meta['chunk_hash'], chunk.hash)

            data_begin = metapos * self.chunk_size
            data_end = metapos * self.chunk_size + self.chunk_size
            target_metachunk_hash = md5_data(data[data_begin:data_end])

            metachunk_hash = hashlib.md5()
            for chunk in data_chunks_at_pos:
                meta, stream = self.blob_client.chunk_get(chunk.url)
                for d in stream:
                    metachunk_hash.update(d)
            self.assertEqual(metachunk_hash.hexdigest().upper(),
                             target_metachunk_hash)
示例#15
0
    def _test_create(self, data_size):
        # generate random test data
        data = random_data(data_size)
        # using factory create new EC content
        content = self.content_factory.new(self.container_id, self.content,
                                           len(data), self.stgpol)
        # verify the factory gave us an ECContent
        self.assertEqual(type(content), ECContent)

        # perform the content creation
        content.create(BytesIO(data))

        meta, chunks = self.container_client.content_locate(
            cid=self.container_id, content=content.content_id)
        # verify metadata
        chunks = ChunksHelper(chunks)
        self.assertEqual(meta['hash'], md5_data(data))
        self.assertEqual(meta['length'], str(len(data)))
        self.assertEqual(meta['policy'], self.stgpol)
        self.assertEqual(meta['name'], self.content)

        metachunk_nb = int(math.ceil(float(len(data)) / self.chunk_size)) \
            if len(data) != 0 else 1

        offset = 0
        # verify each metachunk
        for metapos in range(metachunk_nb):
            chunks_at_pos = content.chunks.filter(metapos=metapos)
            if len(chunks_at_pos) < 1:
                break
            metachunk_size = chunks_at_pos[0].size
            metachunk_hash = md5_data(data[offset:offset + metachunk_size])

            for chunk in chunks_at_pos:
                meta, stream = self.blob_client.chunk_get(chunk.url)
                self.assertEqual(meta['metachunk_size'], str(chunk.size))
                self.assertEqual(meta['metachunk_hash'], chunk.checksum)
                self.assertEqual(meta['content_path'], self.content)
                self.assertEqual(meta['container_id'], self.container_id)
                self.assertEqual(meta['content_id'], meta['content_id'])
                self.assertEqual(meta['chunk_id'], chunk.id)
                self.assertEqual(meta['chunk_pos'], chunk.pos)
                self.assertEqual(meta['chunk_hash'], md5_stream(stream))
                full_path = encode_fullpath(self.account, self.container_name,
                                            self.content,
                                            meta['content_version'],
                                            meta['content_id'])
                self.assertEqual(meta['full_path'], full_path)
                self.assertEqual(meta['oio_version'], '4.2')
                self.assertEqual(metachunk_hash, chunk.checksum)

            offset += metachunk_size
示例#16
0
    def _test_create(self, data_size):
        # generate random test data
        data = random_data(data_size)
        # using factory create new EC content
        content = self.content_factory.new(
            self.container_id, self.content, len(data), self.stgpol)
        # verify the factory gave us an ECContent
        self.assertEqual(type(content), ECContent)

        # perform the content creation
        content.create(StringIO(data))

        meta, chunks = self.container_client.content_show(
            cid=self.container_id, content=content.content_id)
        # verify metadata
        chunks = ChunksHelper(chunks)
        self.assertEqual(meta['hash'], md5_data(data))
        self.assertEqual(meta['length'], str(len(data)))
        self.assertEqual(meta['policy'], self.stgpol)
        self.assertEqual(meta['name'], self.content)

        metachunk_nb = int(math.ceil(float(len(data)) / self.chunk_size)) \
            if len(data) != 0 else 1

        # verify each metachunk
        for metapos in range(metachunk_nb):
            chunks_at_pos = content.chunks.filter(metapos=metapos)

            for chunk in chunks_at_pos:
                meta, stream = self.blob_client.chunk_get(chunk.url)
                self.assertEqual(meta['metachunk_size'], str(chunk.size))
                self.assertEqual(meta['metachunk_hash'], chunk.checksum)
                self.assertEqual(meta['content_path'], self.content)
                self.assertEqual(meta['container_id'], self.container_id)
                self.assertEqual(meta['content_id'], meta['content_id'])
                self.assertEqual(meta['chunk_id'], chunk.id)
                self.assertEqual(meta['chunk_pos'], chunk.pos)
                self.assertEqual(meta['chunk_hash'], md5_stream(stream))
示例#17
0
class RainContent(Content):
    def __init__(self, conf, container_id, metadata, chunks, stgpol_args):
        super(RainContent, self).__init__(conf, container_id, metadata,
                                          chunks, stgpol_args)
        self.algo = stgpol_args["algo"]
        self.k = int(stgpol_args["k"])
        self.m = int(stgpol_args["m"])

    def _get_rain_addr(self, on_the_fly=False):
        try:
            rainx_instance = self.cs_client.next_instance("rainx")
            rainx_addr = "http://%s" % rainx_instance.get('addr')
        except Exception as e:
            self.logger.error("No rainx service found (%s)" % e.message)
            raise ServiceUnavailable("No rainx service found")
        if on_the_fly:
            rainx_addr += "/on-the-fly"
        return rainx_addr

    def _get_metachunk_nb(self):
        return len(self.chunks.filter(subpos="0"))

    def _get_metachunk_size(self, metapos):
        metachunk_size = 0
        for c in self.chunks.filter(metapos=metapos, is_parity=False):
            metachunk_size += c.size
        return metachunk_size

    def _encode_rawxlist(self, chunks):
        res_chunks = []
        for c in chunks:
            res_chunks.append("%s/%s" % (c.host, c.id))
        return '|'.join(res_chunks)

    def rebuild_metachunk(self, metapos, force_broken_chunk=None,
                          on_the_fly=False):
        def _encode_sparerawxlist(broken_chunks, spare_urls):
            res = []
            for i, bc in enumerate(broken_chunks):
                if bc.is_parity:
                    broken_idx = self.k + int(bc.paritypos)
                else:
                    broken_idx = int(bc.subpos)
                spare_url = spare_urls[i].split('/', 2)[2]  # remove http//
                res.append("%s|%d|%s" % (spare_url, broken_idx, bc.hash))
            return ';'.join(res)

        current_chunks = self.chunks.filter(metapos=metapos)
        broken_chunks = []
        notin_chunks = []
        for c in current_chunks:
            if force_broken_chunk is not None \
                    and force_broken_chunk.id == c.id:
                broken_chunks.append(c)
                continue
            try:
                self.blob_client.chunk_head(c.url)
            except Exception as e:
                self.logger.debug("Failed to download chunk %s: %s"
                                  % (c.url, e.message))
                broken_chunks.append(c)
                continue
            notin_chunks.append(c)

        if len(broken_chunks) > self.m:
            raise UnrecoverableContent(
                "Not enough chunks to rebuild the metachunk")

        spare_urls = self._meta2_get_spare_chunk(notin_chunks, broken_chunks)

        headers = {}
        headers["X-oio-chunk-meta-content-storage-policy"] = self.stgpol_name
        headers["X-oio-chunk-meta-rawxlist"] = \
            self._encode_rawxlist(current_chunks)
        headers["X-oio-chunk-meta-sparerawxlist"] = \
            _encode_sparerawxlist(broken_chunks, spare_urls)
        headers[chunk_headers["content_id"]] = self.content_id
        headers[chunk_headers["content_version"]] = self.version
        headers[chunk_headers["content_path"]] = self.path
        headers[chunk_headers["content_size"]] = self.length
        headers[chunk_headers["content_chunksnb"]] = \
            self._get_metachunk_nb()
        headers[chunk_headers["content_cid"]] = self.container_id
        headers[chunk_headers["chunk_pos"]] = metapos
        headers["X-oio-chunk-meta-chunk-size"] = \
            self._get_metachunk_size(metapos)
        headers[chunk_headers["content_mimetype"]] = self.mime_type
        headers[chunk_headers["content_chunkmethod"]] = self.chunk_method

        resp = self.session.get(self._get_rain_addr(on_the_fly),
                                headers=headers, stream=True)
        resp.raise_for_status()
        if on_the_fly:
            return resp.iter_content(READ_CHUNK_SIZE)
        resp.close()

        for i, bc in enumerate(broken_chunks):
            # TODO send only one request with all chunks modifications
            self._meta2_update_spare_chunk(bc, spare_urls[i])
            bc.url = spare_urls[i]  # update current content

    def rebuild_chunk(self, chunk_id):
        # FIXME rebuild only the broken subchunk and not all broken
        # subchunks in the metachunk.The current rainx rebuilds all
        # subchunks. We can't download only the faulty chunk from the rainx
        # without specifying all faulty chunks. Rainx sends only the data of
        # the metachunk and not the parity data so we must rebuild metachunk
        # through rainx services.
        current_chunk = self.chunks.filter(id=chunk_id).one()
        if current_chunk is None:
            raise OrphanChunk("Chunk not found in content")

        self.rebuild_metachunk(current_chunk.metapos,
                               force_broken_chunk=current_chunk)

    def _upload(self, stream):
        global_checksum = hashlib.md5()
        total_bytes_transferred = 0
        content_chunks = []

        def _limit_stream(stream, size):
            read_size = 0
            while read_size < size:
                to_read = size - read_size
                if to_read > WRITE_CHUNK_SIZE:
                    to_read = WRITE_CHUNK_SIZE
                data = stream.read(to_read)
                global_checksum.update(data)
                read_size += to_read
                yield data

        def _decode_chunklist(chunklist):
            res = []
            for c in chunklist.split(';'):
                pos, url, size, hash = c.split('|')
                res.append({
                    "url": "http://%s" % url,
                    "pos": pos,
                    "size": int(size),
                    "hash": hash
                })
            return res

        for pos in xrange(self._get_metachunk_nb()):
            chunks_at_pos = self.chunks.filter(metapos=pos)

            chunk_size = self.chunks[0].size
            remaining_bytes = self.length - total_bytes_transferred
            if chunk_size > remaining_bytes:
                chunk_size = remaining_bytes

            headers = {}
            headers["X-oio-chunk-meta-content-storage-policy"] = \
                self.stgpol_name
            headers["X-oio-chunk-meta-rawxlist"] = \
                self._encode_rawxlist(chunks_at_pos)
            headers[chunk_headers["content_id"]] = self.content_id
            headers[chunk_headers["content_version"]] = self.version
            headers[chunk_headers["content_path"]] = self.path
            headers[chunk_headers["content_size"]] = self.length
            headers[chunk_headers["content_chunksnb"]] = \
                self._get_metachunk_nb()
            headers[chunk_headers["content_cid"]] = self.container_id
            headers[chunk_headers["chunk_pos"]] = pos
            headers["X-oio-chunk-meta-chunk-size"] = chunk_size
            headers[chunk_headers["content_mimetype"]] = self.mime_type
            headers[chunk_headers["content_chunkmethod"]] = self.chunk_method

            resp = self.session.put(self._get_rain_addr(),
                                    data=_limit_stream(stream, chunk_size),
                                    headers=headers)
            resp.raise_for_status()

            content_chunks.extend(_decode_chunklist(resp.headers['chunklist']))

            total_bytes_transferred += chunk_size

        self.chunks = ChunksHelper(content_chunks)
        self.hash = global_checksum.hexdigest().upper()

        self._meta2_create_object()

    def _download_metachunk(self, metapos):
        streams = []
        try:
            try:
                for c in self.chunks.filter(metapos=metapos, is_parity=False):
                    meta, stream = self.blob_client.chunk_get(c.url)
                    streams.append(stream)
            except NotFound:
                self.logger.debug("Chunk %s not found" % c.url)
                for s in streams:
                    s.close()
                streams = [self.rebuild_metachunk(metapos, on_the_fly=True)]

            for stream in streams:
                for data in stream:
                    yield data
        finally:
            for stream in streams:
                stream.close()

    def download(self):
        for pos in xrange(self._get_metachunk_nb()):
            for d in self._download_metachunk(pos):
                yield d
示例#18
0
    def _upload(self, stream):
        global_checksum = hashlib.md5()
        total_bytes_transferred = 0
        content_chunks = []

        def _limit_stream(stream, size):
            read_size = 0
            while read_size < size:
                to_read = size - read_size
                if to_read > WRITE_CHUNK_SIZE:
                    to_read = WRITE_CHUNK_SIZE
                data = stream.read(to_read)
                global_checksum.update(data)
                read_size += to_read
                yield data

        def _decode_chunklist(chunklist):
            res = []
            for c in chunklist.split(';'):
                pos, url, size, hash = c.split('|')
                res.append({
                    "url": "http://%s" % url,
                    "pos": pos,
                    "size": int(size),
                    "hash": hash
                })
            return res

        for pos in xrange(self._get_metachunk_nb()):
            chunks_at_pos = self.chunks.filter(metapos=pos)

            chunk_size = self.chunks[0].size
            remaining_bytes = self.length - total_bytes_transferred
            if chunk_size > remaining_bytes:
                chunk_size = remaining_bytes

            headers = {}
            headers["X-oio-chunk-meta-content-storage-policy"] = \
                self.stgpol_name
            headers["X-oio-chunk-meta-rawxlist"] = \
                self._encode_rawxlist(chunks_at_pos)
            headers[chunk_headers["content_id"]] = self.content_id
            headers[chunk_headers["content_version"]] = self.version
            headers[chunk_headers["content_path"]] = self.path
            headers[chunk_headers["content_size"]] = self.length
            headers[chunk_headers["content_chunksnb"]] = \
                self._get_metachunk_nb()
            headers[chunk_headers["content_cid"]] = self.container_id
            headers[chunk_headers["chunk_pos"]] = pos
            headers["X-oio-chunk-meta-chunk-size"] = chunk_size
            headers[chunk_headers["content_mimetype"]] = self.mime_type
            headers[chunk_headers["content_chunkmethod"]] = self.chunk_method

            resp = self.session.put(self._get_rain_addr(),
                                    data=_limit_stream(stream, chunk_size),
                                    headers=headers)
            resp.raise_for_status()

            content_chunks.extend(_decode_chunklist(resp.headers['chunklist']))

            total_bytes_transferred += chunk_size

        self.chunks = ChunksHelper(content_chunks)
        self.hash = global_checksum.hexdigest().upper()

        self._meta2_create_object()
示例#19
0
class TestChunksHelper(unittest.TestCase):
    def setUp(self):
        super(TestChunksHelper, self).setUp()

        self.dup_c1_1 = {
            "url": "http://127.0.0.1:6011/C1C1",
            "pos": "0", "size": 1048576,
            "hash": "2E47D13C3E2C47E0C537028AD637CCBF"}
        self.dup_c1_2 = {
            "url": "http://127.0.0.1:6010/C1C2",
            "pos": "0", "size": 1048576,
            "hash": "2E47D13C3E2C47E0C537028AD637CCBF"}
        self.dup_c2_1 = {
            "url": "http://127.0.0.1:6012/C2C1",
            "pos": "1", "size": 1048576,
            "hash": "045B70673D8271767D4D21BCDB040F6C"}
        self.dup_c2_2 = {
            "url": "http://127.0.0.1:6011/C2C2",
            "pos": "1", "size": 1048576,
            "hash": "045B70673D8271767D4D21BCDB040F6C"
        }
        self.dup_chunks_raw = [self.dup_c1_1, self.dup_c1_2,
                               self.dup_c2_1, self.dup_c2_2]
        self.dup_chunks = ChunksHelper(self.dup_chunks_raw)

        self.ec_c0_0 = {
            "url": "http://127.0.0.1:6017/C0_0",
            "pos": "0.0", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_c0_1 = {
            "url": "http://127.0.0.1:6016/C0_1",
            "pos": "0.1", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_c0_2 = {
            "url": "http://127.0.0.1:6011/C0_P",
            "pos": "0.2", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_c1_0 = {
            "url": "http://127.0.0.1:6017/C1_0",
            "pos": "1.0", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_c1_1 = {
            "url": "http://127.0.0.1:6016/C1_1",
            "pos": "1.1", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_c1_2 = {
            "url": "http://127.0.0.1:6011/C1_P",
            "pos": "1.2", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_chunks_raw = [self.ec_c0_0, self.ec_c0_1, self.ec_c0_2,
                              self.ec_c1_0, self.ec_c1_1, self.ec_c1_2]
        self.ec_chunks = ChunksHelper(self.ec_chunks_raw)

    def tearDown(self):
        super(TestChunksHelper, self).tearDown()

    def test_sort_dup(self):
        chunks = ChunksHelper([
            self.dup_c2_2, self.dup_c2_1,
            self.dup_c1_2, self.dup_c1_1
        ])
        self.assertEqual(chunks.raw(), [
            self.dup_c1_1, self.dup_c1_2,
            self.dup_c2_1, self.dup_c2_2
        ])

    def test_sort_ec(self):
        ec_chunks = ChunksHelper([
            self.ec_c1_2, self.ec_c1_1, self.ec_c1_0,
            self.ec_c0_2, self.ec_c0_1, self.ec_c0_0
        ])
        self.assertEqual(ec_chunks.raw(), [
            self.ec_c0_0, self.ec_c0_1, self.ec_c0_2,
            self.ec_c1_0, self.ec_c1_1, self.ec_c1_2
        ])

    def test_dup_search(self):
        res1 = self.dup_chunks.filter(pos="1")
        self.assertEqual(res1.raw(), [self.dup_c2_1, self.dup_c2_2])

        res2 = res1.filter(id="C2C2")
        self.assertEqual(res2.raw(), [self.dup_c2_2])

        res3 = self.dup_chunks.filter(pos="1", id="C2C2")
        self.assertEqual(res3.raw(), [self.dup_c2_2])

        res4 = res3.filter()
        self.assertEqual(res4.raw(), [self.dup_c2_2])

        res5 = res1.filter(id="UnKnOwN")
        self.assertEqual(res5.raw(), [])

    def test_dup_exclude(self):
        res1 = self.dup_chunks.exclude(id="C1C2")
        self.assertEqual(res1.raw(), [self.dup_c1_1, self.dup_c2_1,
                                      self.dup_c2_2])

        res2 = res1.exclude(pos="1")
        self.assertEqual(res2.raw(), [self.dup_c1_1])

        res3 = self.dup_chunks.exclude(pos="1", id="C1C2")
        self.assertEqual(res3.raw(), [self.dup_c1_1])

        res4 = res3.exclude()
        self.assertEqual(res4.raw(), [self.dup_c1_1])

    def test_ec_search(self):
        res1 = self.ec_chunks.filter(metapos=1)
        self.assertEqual(res1.raw(), [self.ec_c1_0, self.ec_c1_1,
                                      self.ec_c1_2])

        res3 = self.ec_chunks.filter(subpos=1)
        self.assertEqual(res3.raw(), [self.ec_c0_1, self.ec_c1_1])

    def test_ec_exclude(self):
        res2 = self.ec_chunks.exclude(metapos=1)
        self.assertEqual(res2.raw(), [self.ec_c0_0, self.ec_c0_1,
                                      self.ec_c0_2])

        res3 = self.ec_chunks.exclude(subpos=2)
        self.assertEqual(res3.raw(), [self.ec_c0_0, self.ec_c0_1,
                                      self.ec_c1_0, self.ec_c1_1])

    def test_one(self):
        res1 = self.dup_chunks.filter(id="C2C2").one()
        self.assertEqual(res1.raw(), self.dup_c2_2)

        res2 = self.dup_chunks.one()
        self.assertIsNone(res2)

        res3 = self.dup_chunks.filter(id="UnKnOwN").one()
        self.assertIsNone(res3)

    def test_all(self):
        res1 = self.dup_chunks.all()
        self.assertEqual(res1[0].raw(), self.dup_c1_1)
        self.assertEqual(res1[1].raw(), self.dup_c1_2)
        self.assertEqual(res1[2].raw(), self.dup_c2_1)
        self.assertEqual(res1[3].raw(), self.dup_c2_2)

        res2 = self.dup_chunks.filter(id="UnKnOwN").all()
        self.assertEqual(res2, [])

    def test_len(self):
        self.assertEqual(len(self.dup_chunks), 4)

    def test_iterator(self):
        chunk_iter = iter(self.dup_chunks)
        self.assertEqual(next(chunk_iter).raw(), self.dup_c1_1)
        self.assertEqual(next(chunk_iter).raw(), self.dup_c1_2)
        self.assertEqual(next(chunk_iter).raw(), self.dup_c2_1)
        self.assertEqual(next(chunk_iter).raw(), self.dup_c2_2)
        self.assertRaises(StopIteration, lambda: next(chunk_iter))

    def test_getitem(self):
        self.assertEqual(self.dup_chunks[0].raw(), self.dup_c1_1)
        self.assertEqual(self.dup_chunks[-1].raw(), self.dup_c2_2)
示例#20
0
class TestChunksHelper(unittest.TestCase):
    def setUp(self):
        super(TestChunksHelper, self).setUp()

        self.dup_c1_1 = {
            "url": "http://127.0.0.1:6011/C1C1",
            "pos": "0", "size": 1048576,
            "hash": "2E47D13C3E2C47E0C537028AD637CCBF"}
        self.dup_c1_2 = {
            "url": "http://127.0.0.1:6010/C1C2",
            "pos": "0", "size": 1048576,
            "hash": "2E47D13C3E2C47E0C537028AD637CCBF"}
        self.dup_c2_1 = {
            "url": "http://127.0.0.1:6012/C2C1",
            "pos": "1", "size": 1048576,
            "hash": "045B70673D8271767D4D21BCDB040F6C"}
        self.dup_c2_2 = {
            "url": "http://127.0.0.1:6011/C2C2",
            "pos": "1", "size": 1048576,
            "hash": "045B70673D8271767D4D21BCDB040F6C"
        }
        self.dup_chunks_raw = [self.dup_c1_1, self.dup_c1_2,
                               self.dup_c2_1, self.dup_c2_2]
        self.dup_chunks = ChunksHelper(self.dup_chunks_raw)

        self.ec_c0_0 = {
            "url": "http://127.0.0.1:6017/C0_0",
            "pos": "0.0", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_c0_1 = {
            "url": "http://127.0.0.1:6016/C0_1",
            "pos": "0.1", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_c0_2 = {
            "url": "http://127.0.0.1:6011/C0_P",
            "pos": "0.2", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_c1_0 = {
            "url": "http://127.0.0.1:6017/C1_0",
            "pos": "1.0", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_c1_1 = {
            "url": "http://127.0.0.1:6016/C1_1",
            "pos": "1.1", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_c1_2 = {
            "url": "http://127.0.0.1:6011/C1_P",
            "pos": "1.2", "size": 1048576,
            "hash": "00000000000000000000000000000000"}
        self.ec_chunks_raw = [self.ec_c0_0, self.ec_c0_1, self.ec_c0_2,
                              self.ec_c1_0, self.ec_c1_1, self.ec_c1_2]
        self.ec_chunks = ChunksHelper(self.ec_chunks_raw)

    def tearDown(self):
        super(TestChunksHelper, self).tearDown()

    def test_sort_dup(self):
        chunks = ChunksHelper([
            self.dup_c2_2, self.dup_c2_1,
            self.dup_c1_2, self.dup_c1_1
        ])
        self.assertEqual(chunks.raw(), [
            self.dup_c1_1, self.dup_c1_2,
            self.dup_c2_1, self.dup_c2_2
        ])

    def test_sort_ec(self):
        ec_chunks = ChunksHelper([
            self.ec_c1_2, self.ec_c1_1, self.ec_c1_0,
            self.ec_c0_2, self.ec_c0_1, self.ec_c0_0
        ])
        self.assertEqual(ec_chunks.raw(), [
            self.ec_c0_0, self.ec_c0_1, self.ec_c0_2,
            self.ec_c1_0, self.ec_c1_1, self.ec_c1_2
        ])

    def test_dup_search(self):
        res1 = self.dup_chunks.filter(pos="1")
        self.assertEqual(res1.raw(), [self.dup_c2_1, self.dup_c2_2])

        res2 = res1.filter(id="C2C2")
        self.assertEqual(res2.raw(), [self.dup_c2_2])

        res3 = self.dup_chunks.filter(pos="1", id="C2C2")
        self.assertEqual(res3.raw(), [self.dup_c2_2])

        res4 = res3.filter()
        self.assertEqual(res4.raw(), [self.dup_c2_2])

        res5 = res1.filter(id="UnKnOwN")
        self.assertEqual(res5.raw(), [])

    def test_dup_exclude(self):
        res1 = self.dup_chunks.exclude(id="C1C2")
        self.assertEqual(res1.raw(), [self.dup_c1_1, self.dup_c2_1,
                                      self.dup_c2_2])

        res2 = res1.exclude(pos="1")
        self.assertEqual(res2.raw(), [self.dup_c1_1])

        res3 = self.dup_chunks.exclude(pos="1", id="C1C2")
        self.assertEqual(res3.raw(), [self.dup_c1_1])

        res4 = res3.exclude()
        self.assertEqual(res4.raw(), [self.dup_c1_1])

    def test_ec_search(self):
        res1 = self.ec_chunks.filter(metapos=1)
        self.assertEqual(res1.raw(), [self.ec_c1_0, self.ec_c1_1,
                                      self.ec_c1_2])

        res3 = self.ec_chunks.filter(subpos=1)
        self.assertEqual(res3.raw(), [self.ec_c0_1, self.ec_c1_1])

    def test_ec_exclude(self):
        res2 = self.ec_chunks.exclude(metapos=1)
        self.assertEqual(res2.raw(), [self.ec_c0_0, self.ec_c0_1,
                                      self.ec_c0_2])

        res3 = self.ec_chunks.exclude(subpos=2)
        self.assertEqual(res3.raw(), [self.ec_c0_0, self.ec_c0_1,
                                      self.ec_c1_0, self.ec_c1_1])

    def test_one(self):
        res1 = self.dup_chunks.filter(id="C2C2").one()
        self.assertEqual(res1.raw(), self.dup_c2_2)

        res2 = self.dup_chunks.one()
        self.assertIsNone(res2)

        res3 = self.dup_chunks.filter(id="UnKnOwN").one()
        self.assertIsNone(res3)

    def test_all(self):
        res1 = self.dup_chunks.all()
        self.assertEqual(res1[0].raw(), self.dup_c1_1)
        self.assertEqual(res1[1].raw(), self.dup_c1_2)
        self.assertEqual(res1[2].raw(), self.dup_c2_1)
        self.assertEqual(res1[3].raw(), self.dup_c2_2)

        res2 = self.dup_chunks.filter(id="UnKnOwN").all()
        self.assertEqual(res2, [])

    def test_len(self):
        self.assertEqual(len(self.dup_chunks), 4)

    def test_iterator(self):
        chunk_iter = iter(self.dup_chunks)
        self.assertEqual(chunk_iter.next().raw(), self.dup_c1_1)
        self.assertEqual(chunk_iter.next().raw(), self.dup_c1_2)
        self.assertEqual(chunk_iter.next().raw(), self.dup_c2_1)
        self.assertEqual(chunk_iter.next().raw(), self.dup_c2_2)
        self.assertRaises(StopIteration, chunk_iter.next)

    def test_getitem(self):
        self.assertEqual(self.dup_chunks[0].raw(), self.dup_c1_1)
        self.assertEqual(self.dup_chunks[-1].raw(), self.dup_c2_2)