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 = api_merge.Job(job_id, subchain) job.run() 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 verify_pattern(base_vol.volumePath, qemuimg.FORMAT.RAW, offset=offset, len=1024, pattern=pattern) self.assertEqual(base_vol.getMetaParam(sc.GENERATION), 0)
def test_merge_subchain_with_bitmaps( self, sd_type, chain_len, base_index, top_index): job_id = make_uuid() bitmap1_name = 'bitmap1' bitmap2_name = 'bitmap2' with self.make_env( sd_type=sd_type, chain_len=chain_len, base_format=sc.COW_FORMAT, qcow2_compat='1.1') as env: base_vol = env.chain[base_index] top_vol = env.chain[top_index] # Add new bitmap to base_vol and top_vol for vol in [base_vol, top_vol]: op = qemuimg.bitmap_add( vol.getVolumePath(), bitmap1_name, ) op.run() # Add another bitmap to top_vol only # to test add + merge op = qemuimg.bitmap_add( top_vol.getVolumePath(), bitmap2_name, ) op.run() # Writing data to the chain to modify the bitmaps write_qemu_chain(env.chain) 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 = api_merge.Job(job_id, subchain, merge_bitmaps=True) job.run() self.assertEqual(job.status, jobs.STATUS.DONE) info = qemuimg.info(base_vol.getVolumePath()) # TODO: we should improve this test by adding a # a verification to the extents that are reported # by qemu-nbd. assert info['format-specific']['data']['bitmaps'] == [ { "flags": ["auto"], "name": bitmap1_name, "granularity": 65536 }, { "flags": ["auto"], "name": bitmap2_name, "granularity": 65536 }, ]
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 = 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 verify_pattern( top_vol.volumePath, qemuimg.FORMAT.QCOW2, offset=offset, len=1024, pattern=pattern) # And base, since top was merged into base verify_pattern( 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)
def test_merge_illegal_volume(self, volume): job_id = make_uuid() with self.make_env(sd_type='block', chain_len=2) as env: write_qemu_chain(env.chain) base_vol = env.chain[0] top_vol = env.chain[1] if volume == 'base': base_vol.setLegality(sc.ILLEGAL_VOL) else: top_vol.setLegality(sc.ILLEGAL_VOL) 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 = api_merge.Job(job_id, subchain) job.run() self.assertEqual(job.status, jobs.STATUS.FAILED) self.assertEqual(type(job.error), se.prepareIllegalVolumeError)