Example #1
0
    def test_chain_after_finalize(self, base_fmt):
        with self.make_env(format=base_fmt, chain_len=3) as env:
            base_vol = env.chain[0]
            # We write data to the base and will read it from the child volume
            # to verify that the chain is valid after qemu-rebase.
            offset = 0
            pattern = 0xf0
            length = 1024
            qemu_pattern_write(base_vol.volumePath,
                               sc.fmt2str(base_vol.getFormat()),
                               offset=offset,
                               len=length,
                               pattern=pattern)

            top_vol = env.chain[1]
            child_vol = env.chain[2]

            subchain_info = dict(sd_id=base_vol.sdUUID,
                                 img_id=base_vol.imgUUID,
                                 base_id=base_vol.volUUID,
                                 top_id=top_vol.volUUID,
                                 base_generation=0)
            subchain = merge.SubchainInfo(subchain_info, 0)

            merge.finalize(subchain)

            qemu_pattern_verify(child_vol.volumePath,
                                sc.fmt2str(child_vol.getFormat()),
                                offset=offset,
                                len=length,
                                pattern=pattern)
Example #2
0
    def test_subchain_validation(self):
        job_id = make_uuid()
        with self.make_env(sd_type='file', chain_len=2) as env:
            write_qemu_chain(env.chain)
            base_index = 0
            top_index = 1
            base_vol = env.chain[base_index]
            base_vol.setLegality(sc.ILLEGAL_VOL)
            top_vol = env.chain[top_index]
            subchain_info = dict(sd_id=top_vol.sdUUID,
                                 img_id=top_vol.imgUUID,
                                 base_id=base_vol.imgUUID,
                                 top_id=top_vol.volUUID,
                                 base_generation=0)
            subchain = merge.SubchainInfo(subchain_info, 0)

            def fail():
                raise se.VolumeIsNotInChain(None, None, None)

            # We already tested that subchain validate does the right thing,
            # here we test that this job care to call subchain validate.
            subchain.validate = fail
            job = storage.sdm.api.merge.Job(job_id, subchain)
            job.run()
            wait_for_job(job)
            self.assertEqual(job.status, jobs.STATUS.FAILED)
            self.assertEqual(type(job.error), se.VolumeIsNotInChain)

            # Check that validate is called *before* attempting - verify that
            # the chain data was *not* merged
            offset = base_index * 1024
            pattern = 0xf0 + base_index
            qemu_pattern_verify(base_vol.volumePath, qemuimg.FORMAT.RAW,
                                offset=offset, len=1024, pattern=pattern)
            self.assertEqual(base_vol.getMetaParam(sc.GENERATION), 0)
Example #3
0
    def test_chain_after_finalize(self, base_fmt):
        with self.make_env(format=base_fmt, chain_len=3) as env:
            base_vol = env.chain[0]
            # We write data to the base and will read it from the child volume
            # to verify that the chain is valid after qemu-rebase.
            offset = 0
            pattern = 0xf0
            length = 1024
            qemu_pattern_write(base_vol.volumePath,
                               sc.fmt2str(base_vol.getFormat()),
                               offset=offset,
                               len=length, pattern=pattern)

            top_vol = env.chain[1]
            child_vol = env.chain[2]

            subchain_info = dict(sd_id=base_vol.sdUUID,
                                 img_id=base_vol.imgUUID,
                                 base_id=base_vol.volUUID,
                                 top_id=top_vol.volUUID,
                                 base_generation=0)
            subchain = merge.SubchainInfo(subchain_info, 0)

            merge.finalize(subchain)

            qemu_pattern_verify(child_vol.volumePath,
                                sc.fmt2str(child_vol.getFormat()),
                                offset=offset,
                                len=length, pattern=pattern)
Example #4
0
 def test_match_custom_offset_and_len(self, offset, len):
     with namedTemporaryDir() as tmpdir:
         path = os.path.join(tmpdir, 'test')
         qemuimg.create(path, '1m', qemuimg.FORMAT.QCOW2)
         qemu_pattern_write(path, qemuimg.FORMAT.QCOW2,
                            offset=offset, len=len)
         qemu_pattern_verify(path, qemuimg.FORMAT.QCOW2, offset=offset,
                             len=len)
Example #5
0
 def test_match_custom_offset_and_len(self, offset, len):
     with namedTemporaryDir() as tmpdir:
         path = os.path.join(tmpdir, 'test')
         qemuimg.create(path, '1m', qemuimg.FORMAT.QCOW2)
         qemu_pattern_write(path,
                            qemuimg.FORMAT.QCOW2,
                            offset=offset,
                            len=len)
         qemu_pattern_verify(path,
                             qemuimg.FORMAT.QCOW2,
                             offset=offset,
                             len=len)
Example #6
0
    def test_commit(self, qcow2_compat, base, top, use_base):
        size = 1048576
        with namedTemporaryDir() as tmpdir:
            chain = []
            parent = None
            # Create a chain of 4 volumes.
            for i in range(4):
                vol = os.path.join(tmpdir, "vol%d.img" % i)
                format = (qemuimg.FORMAT.RAW
                          if i == 0 else qemuimg.FORMAT.QCOW2)
                make_image(vol, size, format, i, qcow2_compat, parent)
                orig_offset = qemuimg.check(vol)["offset"] if i > 0 else None
                chain.append((vol, orig_offset))
                parent = vol

            base_vol = chain[base][0]
            top_vol = chain[top][0]
            op = qemuimg.commit(top_vol,
                                topFormat=qemuimg.FORMAT.QCOW2,
                                base=base_vol if use_base else None)
            with utils.closing(op):
                op.wait_for_completion()

            base_fmt = (qemuimg.FORMAT.RAW
                        if base == 0 else qemuimg.FORMAT.QCOW2)
            for i in range(base, top + 1):
                offset = i * 1024
                pattern = 0xf0 + i
                # The base volume must have the data from all the volumes
                # merged into it.
                qemu_pattern_verify(base_vol,
                                    base_fmt,
                                    offset=offset,
                                    len=1024,
                                    pattern=pattern)
                if i > base:
                    # internal and top volumes should keep the data, we
                    # may want to wipe this data when deleting the volumes
                    # later.
                    vol, orig_offset = chain[i]
                    actual_offset = qemuimg.check(vol)["offset"]
                    self.assertEqual(actual_offset, orig_offset)
Example #7
0
    def test_read_bad_chain_raises(self):
        with namedTemporaryDir() as tmpdir:
            # Create a good chain.
            base_qcow2 = os.path.join(tmpdir, "base.qcow2")
            qemuimg.create(base_qcow2, "1m", qemuimg.FORMAT.QCOW2)
            top = os.path.join(tmpdir, "top.qcow2")
            qemuimg.create(top, "1m", qemuimg.FORMAT.QCOW2, backing=base_qcow2,
                           backingFormat=qemuimg.FORMAT.QCOW2)

            # Create a broken chain using unsafe rebase with the wrong backing
            # format.
            base_raw = os.path.join(tmpdir, "base.raw")
            qemuimg.create(base_raw, "1m", qemuimg.FORMAT.RAW)
            operation = qemuimg.rebase(top,
                                       backing=base_raw,
                                       format=qemuimg.FORMAT.QCOW2,
                                       backingFormat=qemuimg.FORMAT.QCOW2,
                                       unsafe=True)
            operation.run()
            with self.assertRaises(cmdutils.Error):
                qemu_pattern_verify(top, qemuimg.FORMAT.QCOW2)
Example #8
0
    def test_merge_subchain(self, sd_type, chain_len, base_index, top_index):
        job_id = make_uuid()
        with self.make_env(sd_type=sd_type, chain_len=chain_len) as env:
            write_qemu_chain(env.chain)
            base_vol = env.chain[base_index]
            top_vol = env.chain[top_index]

            subchain_info = dict(sd_id=base_vol.sdUUID,
                                 img_id=base_vol.imgUUID,
                                 base_id=base_vol.volUUID,
                                 top_id=top_vol.volUUID,
                                 base_generation=0)
            subchain = merge.SubchainInfo(subchain_info, 0)
            job = storage.sdm.api.merge.Job(job_id, subchain)
            job.run()
            wait_for_job(job)
            self.assertEqual(job.status, jobs.STATUS.DONE)

            # Verify that the chain data was merged
            for i in range(base_index, top_index + 1):
                offset = i * 1024
                pattern = 0xf0 + i
                # We expect to read all data from top
                qemu_pattern_verify(top_vol.volumePath,
                                    qemuimg.FORMAT.QCOW2,
                                    offset=offset,
                                    len=1024,
                                    pattern=pattern)
                # And base, since top was merged into base
                qemu_pattern_verify(base_vol.volumePath,
                                    sc.fmt2str(base_vol.getFormat()),
                                    offset=offset,
                                    len=1024,
                                    pattern=pattern)

            self.assertEqual(sorted(self.expected_locks(base_vol)),
                             sorted(guarded.context.locks))

            self.assertEqual(base_vol.getLegality(), sc.LEGAL_VOL)
            self.assertEqual(base_vol.getMetaParam(sc.GENERATION), 1)
Example #9
0
    def test_subchain_validation(self):
        job_id = make_uuid()
        with self.make_env(sd_type='file', chain_len=2) as env:
            write_qemu_chain(env.chain)
            base_index = 0
            top_index = 1
            base_vol = env.chain[base_index]
            base_vol.setLegality(sc.ILLEGAL_VOL)
            top_vol = env.chain[top_index]
            subchain_info = dict(sd_id=top_vol.sdUUID,
                                 img_id=top_vol.imgUUID,
                                 base_id=base_vol.imgUUID,
                                 top_id=top_vol.volUUID,
                                 base_generation=0)
            subchain = merge.SubchainInfo(subchain_info, 0)

            def fail():
                raise se.VolumeIsNotInChain(None, None, None)

            # We already tested that subchain validate does the right thing,
            # here we test that this job care to call subchain validate.
            subchain.validate = fail
            job = storage.sdm.api.merge.Job(job_id, subchain)
            job.run()
            wait_for_job(job)
            self.assertEqual(job.status, jobs.STATUS.FAILED)
            self.assertEqual(type(job.error), se.VolumeIsNotInChain)

            # Check that validate is called *before* attempting - verify that
            # the chain data was *not* merged
            offset = base_index * 1024
            pattern = 0xf0 + base_index
            qemu_pattern_verify(base_vol.volumePath,
                                qemuimg.FORMAT.RAW,
                                offset=offset,
                                len=1024,
                                pattern=pattern)
            self.assertEqual(base_vol.getMetaParam(sc.GENERATION), 0)
Example #10
0
    def test_commit(self, qcow2_compat, base, top, use_base):
        size = 1048576
        with namedTemporaryDir() as tmpdir:
            chain = []
            parent = None
            # Create a chain of 4 volumes.
            for i in range(4):
                vol = os.path.join(tmpdir, "vol%d.img" % i)
                format = (qemuimg.FORMAT.RAW if i == 0 else
                          qemuimg.FORMAT.QCOW2)
                make_image(vol, size, format, i, qcow2_compat, parent)
                blocks = os.stat(vol).st_blocks
                chain.append((vol, blocks))
                parent = vol

            base_vol = chain[base][0]
            top_vol = chain[top][0]
            op = qemuimg.commit(top_vol,
                                topFormat=qemuimg.FORMAT.QCOW2,
                                base=base_vol if use_base else None)
            with utils.closing(op):
                op.wait_for_completion()

            for i in range(base, top + 1):
                offset = i * 1024
                pattern = 0xf0 + i
                # The base volume must have the data from all the volumes
                # merged into it.
                format = (qemuimg.FORMAT.RAW if i == 0 else
                          qemuimg.FORMAT.QCOW2)
                qemu_pattern_verify(base_vol, format, offset=offset,
                                    len=1024, pattern=pattern)
                if i > base:
                    # internal and top volumes should keep the data, we
                    # may want to wipe this data when deleting the volumes
                    # later.
                    vol, blocks = chain[i]
                    self.assertEqual(os.stat(vol).st_blocks, blocks)
Example #11
0
    def test_merge_subchain(self, sd_type, chain_len, base_index, top_index):
        job_id = make_uuid()
        with self.make_env(sd_type=sd_type, chain_len=chain_len) as env:
            write_qemu_chain(env.chain)
            base_vol = env.chain[base_index]
            base_vol.setLegality(sc.ILLEGAL_VOL)
            top_vol = env.chain[top_index]

            subchain_info = dict(sd_id=base_vol.sdUUID,
                                 img_id=base_vol.imgUUID,
                                 base_id=base_vol.volUUID,
                                 top_id=top_vol.volUUID,
                                 base_generation=0)
            subchain = merge.SubchainInfo(subchain_info, 0)
            job = storage.sdm.api.merge.Job(job_id, subchain)
            job.run()
            wait_for_job(job)
            self.assertEqual(job.status, jobs.STATUS.DONE)

            # Verify that the chain data was merged
            for i in range(base_index, top_index + 1):
                offset = i * 1024
                pattern = 0xf0 + i
                # We expect to read all data from top
                qemu_pattern_verify(top_vol.volumePath, qemuimg.FORMAT.QCOW2,
                                    offset=offset, len=1024, pattern=pattern)
                base_format = (qemuimg.FORMAT.RAW if i == 0 else
                               qemuimg.FORMAT.QCOW2)
                # And base, since top was merged into base
                qemu_pattern_verify(base_vol.volumePath, base_format,
                                    offset=offset, len=1024, pattern=pattern)

            self.assertEqual(sorted(self.expected_locks(base_vol)),
                             sorted(guarded.context.locks))

            self.assertEqual(base_vol.getLegality(), sc.ILLEGAL_VOL)
            self.assertEqual(base_vol.getMetaParam(sc.GENERATION), 1)
Example #12
0
    def test_read_bad_chain_raises(self):
        with namedTemporaryDir() as tmpdir:
            # Create a good chain.
            base_qcow2 = os.path.join(tmpdir, "base.qcow2")
            qemuimg.create(base_qcow2, "1m", qemuimg.FORMAT.QCOW2)
            top = os.path.join(tmpdir, "top.qcow2")
            qemuimg.create(top,
                           "1m",
                           qemuimg.FORMAT.QCOW2,
                           backing=base_qcow2,
                           backingFormat=qemuimg.FORMAT.QCOW2)

            # Create a broken chain using unsafe rebase with the wrong backing
            # format.
            base_raw = os.path.join(tmpdir, "base.raw")
            qemuimg.create(base_raw, "1m", qemuimg.FORMAT.RAW)
            operation = qemuimg.rebase(top,
                                       backing=base_raw,
                                       format=qemuimg.FORMAT.QCOW2,
                                       backingFormat=qemuimg.FORMAT.QCOW2,
                                       unsafe=True)
            operation.run()
            with self.assertRaises(cmdutils.Error):
                qemu_pattern_verify(top, qemuimg.FORMAT.QCOW2)
Example #13
0
 def test_read_missing_file_raises(self, format):
     with self.assertRaises(cmdutils.Error):
         qemu_pattern_verify("/no/such/file", format)
Example #14
0
 def test_match(self, img_format):
     with namedTemporaryDir() as tmpdir:
         path = os.path.join(tmpdir, 'test')
         qemuimg.create(path, '1m', img_format)
         qemu_pattern_write(path, img_format)
         qemu_pattern_verify(path, img_format)
Example #15
0
 def test_read_wrong_format_raises(self):
     with namedTemporaryDir() as tmpdir:
         path = os.path.join(tmpdir, "test.qcow2")
         qemuimg.create(path, "1m", qemuimg.FORMAT.RAW)
         with self.assertRaises(cmdutils.Error):
             qemu_pattern_verify(path, qemuimg.FORMAT.QCOW2)
Example #16
0
 def test_read_missing_file_raises(self, format):
     with self.assertRaises(cmdutils.Error):
         qemu_pattern_verify("/no/such/file", format)
Example #17
0
 def test_read_wrong_format_raises(self):
     with namedTemporaryDir() as tmpdir:
         path = os.path.join(tmpdir, "test.qcow2")
         qemuimg.create(path, "1m", qemuimg.FORMAT.RAW)
         with self.assertRaises(cmdutils.Error):
             qemu_pattern_verify(path, qemuimg.FORMAT.QCOW2)
Example #18
0
 def test_match(self, img_format):
     with namedTemporaryDir() as tmpdir:
         path = os.path.join(tmpdir, 'test')
         qemuimg.create(path, '1m', img_format)
         qemu_pattern_write(path, img_format)
         qemu_pattern_verify(path, img_format)