Example #1
0
    def test_one_block(self, offset, length, expected_length, qcow2_compat):
        with namedTemporaryDir() as tmpdir:
            size = 1048576
            image = os.path.join(tmpdir, "base.img")
            qemuimg.create(image, size=size, format=self.FORMAT,
                           qcow2Compat=qcow2_compat)
            qemu_pattern_write(image, self.FORMAT, offset=offset, len=length,
                               pattern=0xf0)

            expected = [
                # run 1 - empty
                {
                    "start": 0,
                    "length": offset,
                    "data": False,
                    "zero": True,
                },
                # run 2 - data
                {
                    "start": offset,
                    "length": expected_length,
                    "data": True,
                    "zero": False,
                },
                # run 3 - empty
                {
                    "start": offset + expected_length,
                    "length": size - offset - expected_length,
                    "data": False,
                    "zero": True,
                },
            ]

            self.check_map(qemuimg.map(image), expected)
Example #2
0
 def test_check(self):
     with namedTemporaryDir() as tmpdir:
         path = os.path.join(tmpdir, 'test.qcow2')
         qemuimg.create(path, size=1048576, format=qemuimg.FORMAT.QCOW2)
         info = qemuimg.check(path)
         # The exact value depends on qcow2 internals
         self.assertEqual(int, type(info['offset']))
Example #3
0
 def clone(self, dstPath, volFormat):
     """
     Clone self volume to the specified dst_image_dir/dst_volUUID
     """
     wasleaf = False
     taskName = "parent volume rollback: " + self.volUUID
     vars.task.pushRecovery(
         task.Recovery(taskName, "volume", "Volume", "parentVolumeRollback",
                       [self.sdUUID, self.imgUUID, self.volUUID]))
     if self.isLeaf():
         wasleaf = True
         self.setInternal()
     try:
         self.prepare(rw=False)
         self.log.debug('cloning volume %s to %s', self.volumePath, dstPath)
         parent = getBackingVolumePath(self.imgUUID, self.volUUID)
         domain = sdCache.produce(self.sdUUID)
         qemuimg.create(dstPath,
                        backing=parent,
                        format=sc.fmt2str(volFormat),
                        qcow2Compat=domain.qcow2_compat(),
                        backingFormat=sc.fmt2str(self.getFormat()))
         self.teardown(self.sdUUID, self.volUUID)
     except Exception as e:
         self.log.exception('cannot clone image %s volume %s to %s',
                            self.imgUUID, self.volUUID, dstPath)
         # FIXME: might race with other clones
         if wasleaf:
             self.setLeaf()
         self.teardown(self.sdUUID, self.volUUID)
         raise se.CannotCloneVolume(self.volumePath, dstPath, str(e))
Example #4
0
 def test_wrong_format_raises(self, vol_fmt, qemu_fmt):
     with self.fake_volume(vol_fmt) as vol:
         qemuimg.create(vol.volumePath, size=self.SIZE, format=qemu_fmt)
         h = FakeHSM()
         self.assertRaises(se.ImageVerificationError,
                           h.verify_untrusted_volume,
                           'sp', vol.sdUUID, vol.imgUUID, vol.volUUID)
Example #5
0
    def _create(cls,
                dom,
                imgUUID,
                volUUID,
                size,
                volFormat,
                preallocate,
                volParent,
                srcImgUUID,
                srcVolUUID,
                volPath,
                initialSize=None):
        """
        Class specific implementation of volumeCreate. All the exceptions are
        properly handled and logged in volume.create()
        """
        if initialSize:
            cls.log.error("initialSize is not supported for file-based "
                          "volumes")
            raise se.InvalidParameterException("initial size", initialSize)

        sizeBytes = size * BLOCK_SIZE
        truncSize = sizeBytes if volFormat == volume.RAW_FORMAT else 0

        try:
            oop.getProcessPool(dom.sdUUID).truncateFile(
                volPath, truncSize, mode=VOLUME_PERMISSIONS, creatExcl=True)
        except OSError as e:
            if e.errno == errno.EEXIST:
                raise se.VolumeAlreadyExists(volUUID)
            raise

        if preallocate == volume.PREALLOCATED_VOL:
            try:
                # ddWatchCopy expects size to be in bytes
                misc.ddWatchCopy("/dev/zero", volPath, vars.task.aborting,
                                 sizeBytes)
            except ActionStopped:
                raise
            except Exception:
                cls.log.error("Unexpected error", exc_info=True)
                raise se.VolumesZeroingError(volPath)

        if not volParent:
            cls.log.info(
                "Request to create %s volume %s with size = %s "
                "sectors", volume.type2name(volFormat), volPath, size)
            if volFormat == volume.COW_FORMAT:
                qemuimg.create(volPath, sizeBytes, volume.fmt2str(volFormat))
        else:
            # Create hardlink to template and its meta file
            cls.log.info("Request to create snapshot %s/%s of volume %s/%s",
                         imgUUID, volUUID, srcImgUUID, srcVolUUID)
            volParent.clone(volPath, volFormat)

        # Forcing the volume permissions in case one of the tools we use
        # (dd, qemu-img, etc.) will mistakenly change the file permissiosn.
        dom.oop.os.chmod(volPath, VOLUME_PERMISSIONS)

        return (volPath, )
Example #6
0
 def test_invalid_config(self):
     config = make_config([('irs', 'qcow2_compat', '1.2')])
     with MonkeyPatchScope([(qemuimg, '_supports_qcow2_compat',
                             self.supported('create', True)),
                            (qemuimg, 'config', config)]):
         with self.assertRaises(exception.InvalidConfiguration):
             qemuimg.create('image', format='qcow2')
Example #7
0
def make_qemu_chain(env, size, base_vol_fmt, chain_len, qcow2_compat='0.10'):
    vol_list = []
    img_id = make_uuid()
    parent_vol_id = sc.BLANK_UUID
    vol_fmt = base_vol_fmt
    for i in range(chain_len):
        vol_id = make_uuid()
        if parent_vol_id != sc.BLANK_UUID:
            vol_fmt = sc.COW_FORMAT
        env.make_volume(size,
                        img_id,
                        vol_id,
                        parent_vol_id=parent_vol_id,
                        vol_format=vol_fmt)
        vol = env.sd_manifest.produceVolume(img_id, vol_id)
        if vol_fmt == sc.COW_FORMAT:
            backing = parent_vol_id if parent_vol_id != sc.BLANK_UUID else None
            qemuimg.create(vol.volumePath,
                           size=size,
                           format=qemuimg.FORMAT.QCOW2,
                           qcow2Compat=qcow2_compat,
                           backing=backing)
        vol_list.append(vol)
        parent_vol_id = vol_id
    return vol_list
Example #8
0
 def test_no_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, pattern=2)
         self.assertRaises(ChainVerificationError,
                           qemu_pattern_verify, path, img_format, pattern=4)
Example #9
0
 def test_ok(self, vol_fmt):
     with self.fake_volume(vol_fmt) as vol:
         qemu_fmt = sc.FMT2STR[vol_fmt]
         qemuimg.create(vol.volumePath, size=self.SIZE, format=qemu_fmt)
         h = FakeHSM()
         self.assertNotRaises(h.verify_untrusted_volume,
                              'sp', vol.sdUUID, vol.imgUUID, vol.volUUID)
Example #10
0
 def clone(self, dstPath, volFormat):
     """
     Clone self volume to the specified dst_image_dir/dst_volUUID
     """
     wasleaf = False
     taskName = "parent volume rollback: " + self.volUUID
     vars.task.pushRecovery(
         task.Recovery(taskName, "volume", "Volume",
                       "parentVolumeRollback",
                       [self.sdUUID, self.imgUUID, self.volUUID]))
     if self.isLeaf():
         wasleaf = True
         self.setInternal()
     try:
         self.prepare(rw=False)
         self.log.debug('cloning volume %s to %s', self.volumePath,
                        dstPath)
         parent = getBackingVolumePath(self.imgUUID, self.volUUID)
         qemuimg.create(dstPath, backing=parent,
                        format=fmt2str(volFormat),
                        backingFormat=fmt2str(self.getFormat()))
         self.teardown(self.sdUUID, self.volUUID)
     except Exception as e:
         self.log.exception('cannot clone image %s volume %s to %s',
                            self.imgUUID, self.volUUID, dstPath)
         # FIXME: might race with other clones
         if wasleaf:
             self.setLeaf()
         self.teardown(self.sdUUID, self.volUUID)
         raise se.CannotCloneVolume(self.volumePath, dstPath, str(e))
Example #11
0
def make_volume(env, size, md_fmt, real_fmt):
    img_id = make_uuid()
    vol_id = make_uuid()
    env.make_volume(size, img_id, vol_id, vol_format=md_formats[md_fmt])
    vol = env.sd_manifest.produceVolume(img_id, vol_id)
    qemuimg.create(vol.getVolumePath(), size, qemu_formats[real_fmt])
    return vol
Example #12
0
def make_volume(env, size, md_fmt, real_fmt):
    img_id = make_uuid()
    vol_id = make_uuid()
    env.make_volume(size, img_id, vol_id, vol_format=md_formats[md_fmt])
    vol = env.sd_manifest.produceVolume(img_id, vol_id)
    qemuimg.create(vol.getVolumePath(), size, qemu_formats[real_fmt])
    return vol
Example #13
0
 def test_check(self):
     with namedTemporaryDir() as tmpdir:
         path = os.path.join(tmpdir, 'test.qcow2')
         qemuimg.create(path, size=1048576, format=qemuimg.FORMAT.QCOW2)
         info = qemuimg.check(path)
         # The exact value depends on qcow2 internals
         self.assertEqual(int, type(info['offset']))
Example #14
0
    def test_one_block(self, offset, length, expected_length, qcow2_compat):
        with namedTemporaryDir() as tmpdir:
            size = 1048576
            image = os.path.join(tmpdir, "base.img")
            qemuimg.create(image, size=size, format=self.FORMAT,
                           qcow2Compat=qcow2_compat)
            qemu_pattern_write(image, self.FORMAT, offset=offset, len=length,
                               pattern=0xf0)

            expected = [
                # run 1 - empty
                {
                    "start": 0,
                    "length": offset,
                    "data": False,
                    "zero": True,
                },
                # run 2 - data
                {
                    "start": offset,
                    "length": expected_length,
                    "data": True,
                    "zero": False,
                },
                # run 3 - empty
                {
                    "start": offset + expected_length,
                    "length": size - offset - expected_length,
                    "data": False,
                    "zero": True,
                },
            ]

            self.check_map(qemuimg.map(image), expected)
Example #15
0
 def test_invalid_config(self):
     config = make_config([('irs', 'qcow2_compat', '1.2')])
     with MonkeyPatchScope([(qemuimg, '_supports_qcow2_compat',
                             self.supported('create', True)),
                            (qemuimg, 'config', config)]):
         with self.assertRaises(exception.InvalidConfiguration):
             qemuimg.create('image', format='qcow2')
Example #16
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 #17
0
    def test_zero_size(self):
        def create(cmd, **kw):
            expected = [QEMU_IMG, 'create', 'image', '0']
            self.assertEqual(cmd, expected)
            return 0, '', ''

        with MonkeyPatchScope([(commands, "execCmd", create)]):
            qemuimg.create('image', size=0)
Example #18
0
    def test_zero_size(self):
        def create(cmd, **kw):
            expected = [QEMU_IMG, 'create', 'image', '0']
            self.assertEqual(cmd, expected)
            return 0, '', ''

        with MonkeyPatchScope([(utils, "execCmd", create)]):
            qemuimg.create('image', size=0)
Example #19
0
    def test_no_format(self):

        def create_no_format(cmd, **kw):
            assert cmd == [qemuimg._qemuimg.cmd, 'create', 'image']
            return 0, '', ''

        with FakeExecCmd(create_no_format):
            qemuimg.create('image')
Example #20
0
    def test_no_format(self):
        def create(cmd, **kw):
            expected = [QEMU_IMG, 'create', 'image']
            self.assertEqual(cmd, expected)
            return 0, '', ''

        with MonkeyPatchScope([(utils, "execCmd", create)]):
            qemuimg.create('image')
Example #21
0
    def test_no_format(self):
        def create(cmd, **kw):
            expected = [QEMU_IMG, 'create', 'image']
            self.assertEqual(cmd, expected)
            return 0, '', ''

        with MonkeyPatchScope([(commands, "execCmd", create)]):
            qemuimg.create('image')
Example #22
0
    def test_no_format(self):
        def create(cmd, **kw):
            expected = [QEMU_IMG, 'create', 'image']
            self.assertEqual(cmd, expected)
            return 0, '', ''

        with FakeCmd(utils, 'execCmd', create):
            qemuimg.create('image')
Example #23
0
    def _create(cls, dom, imgUUID, volUUID, size, volFormat, preallocate,
                volParent, srcImgUUID, srcVolUUID, volPath,
                initialSize=None):
        """
        Class specific implementation of volumeCreate. All the exceptions are
        properly handled and logged in volume.create()
        """
        if initialSize:
            cls.log.error("initialSize is not supported for file-based "
                          "volumes")
            raise se.InvalidParameterException("initial size",
                                               initialSize)

        sizeBytes = size * BLOCK_SIZE
        truncSize = sizeBytes if volFormat == sc.RAW_FORMAT else 0

        try:
            oop.getProcessPool(dom.sdUUID).truncateFile(
                volPath, truncSize, mode=sc.FILE_VOLUME_PERMISSIONS,
                creatExcl=True)
        except OSError as e:
            if e.errno == errno.EEXIST:
                raise se.VolumeAlreadyExists(volUUID)
            raise

        if preallocate == sc.PREALLOCATED_VOL:
            try:
                operation = fallocate.allocate(volPath,
                                               sizeBytes)
                with vars.task.abort_callback(operation.abort):
                    with utils.stopwatch("Preallocating volume %s" % volPath):
                        operation.run()
            except exception.ActionStopped:
                raise
            except Exception:
                cls.log.error("Unexpected error", exc_info=True)
                raise se.VolumesZeroingError(volPath)

        if not volParent:
            cls.log.info("Request to create %s volume %s with size = %s "
                         "sectors", sc.type2name(volFormat), volPath,
                         size)
            if volFormat == sc.COW_FORMAT:
                qemuimg.create(volPath,
                               size=sizeBytes,
                               format=sc.fmt2str(volFormat),
                               qcow2Compat=dom.qcow2_compat())
        else:
            # Create hardlink to template and its meta file
            cls.log.info("Request to create snapshot %s/%s of volume %s/%s",
                         imgUUID, volUUID, srcImgUUID, srcVolUUID)
            volParent.clone(volPath, volFormat)

        # Forcing the volume permissions in case one of the tools we use
        # (dd, qemu-img, etc.) will mistakenly change the file permissiosn.
        dom.oop.os.chmod(volPath, sc.FILE_VOLUME_PERMISSIONS)

        return (volPath,)
Example #24
0
 def test_backingfile_raises(self):
     with self.fake_volume(sc.COW_FORMAT) as vol:
         qemu_fmt = qemuimg.FORMAT.QCOW2
         qemuimg.create(vol.volumePath, size=self.SIZE, format=qemu_fmt,
                        backing='foo')
         h = FakeHSM()
         self.assertRaises(se.ImageVerificationError,
                           h.verify_untrusted_volume,
                           'sp', vol.sdUUID, vol.imgUUID, vol.volUUID)
Example #25
0
    def test_qcow2_compat_unsupported(self):
        def create(cmd, **kw):
            expected = [QEMU_IMG, 'create', '-f', 'qcow2', 'image']
            self.assertEqual(cmd, expected)
            return 0, '', ''

        with MonkeyPatchScope([(qemuimg, '_supports_qcow2_compat',
                                self.supported('create', False)),
                               (utils, 'execCmd', create)]):
            qemuimg.create('image', format='qcow2')
Example #26
0
    def test_qcow2_compat_unsupported(self):
        def create(cmd, **kw):
            expected = [QEMU_IMG, 'create', '-f', 'qcow2', 'image']
            self.assertEqual(cmd, expected)
            return 0, '', ''

        with MonkeyPatchScope([(qemuimg, '_supports_qcow2_compat',
                                self.supported('create', False)),
                               (utils, 'execCmd', create)]):
            qemuimg.create('image', format='qcow2')
Example #27
0
 def test_no_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, pattern=2)
         self.assertRaises(ChainVerificationError,
                           qemu_pattern_verify,
                           path,
                           img_format,
                           pattern=4)
Example #28
0
    def _create(cls, dom, imgUUID, volUUID, size, volFormat, preallocate,
                volParent, srcImgUUID, srcVolUUID, volPath):
        """
        Class specific implementation of volumeCreate. All the exceptions are
        properly handled and logged in volume.create()
        """

        if preallocate == volume.SPARSE_VOL:
            volSize = "%s" % config.get("irs", "volume_utilization_chunk_mb")
        else:
            volSize = "%s" % ((size + SECTORS_TO_MB - 1) / SECTORS_TO_MB)

        lvm.createLV(dom.sdUUID,
                     volUUID,
                     volSize,
                     activate=True,
                     initialTag=TAG_VOL_UNINIT)

        utils.rmFile(volPath)
        os.symlink(lvm.lvPath(dom.sdUUID, volUUID), volPath)

        if not volParent:
            cls.log.info(
                "Request to create %s volume %s with size = %s "
                "sectors", volume.type2name(volFormat), volPath, size)
            if volFormat == volume.COW_FORMAT:
                qemuimg.create(volPath, size * BLOCK_SIZE,
                               volume.fmt2str(volFormat))
        else:
            # Create hardlink to template and its meta file
            cls.log.info("Request to create snapshot %s/%s of volume %s/%s",
                         imgUUID, volUUID, srcImgUUID, srcVolUUID)
            volParent.clone(volPath, volFormat)

        with cls._tagCreateLock:
            mdSlot = dom.getVolumeMetadataSlot(volUUID, VOLUME_MDNUMBLKS)
            mdTags = [
                "%s%s" % (TAG_PREFIX_MD, mdSlot),
                "%s%s" % (TAG_PREFIX_PARENT, srcVolUUID),
                "%s%s" % (TAG_PREFIX_IMAGE, imgUUID)
            ]
            lvm.changeLVTags(dom.sdUUID,
                             volUUID,
                             delTags=[TAG_VOL_UNINIT],
                             addTags=mdTags)

        try:
            lvm.deactivateLVs(dom.sdUUID, volUUID)
        except se.CannotDeactivateLogicalVolume:
            cls.log.warn("Cannot deactivate new created volume %s/%s",
                         dom.sdUUID,
                         volUUID,
                         exc_info=True)

        return (dom.sdUUID, mdSlot)
Example #29
0
 def test_empty_image(self, qcow2_compat, desired_qcow2_compat):
     with namedTemporaryDir() as tmpdir:
         base_path = os.path.join(tmpdir, 'base.img')
         leaf_path = os.path.join(tmpdir, 'leaf.img')
         size = 1048576
         qemuimg.create(base_path, size=size, format=qemuimg.FORMAT.RAW)
         qemuimg.create(leaf_path, format=qemuimg.FORMAT.QCOW2,
                        backing=base_path)
         qemuimg.amend(leaf_path, desired_qcow2_compat)
         self.assertEquals(qemuimg.info(leaf_path)['compat'],
                           desired_qcow2_compat)
Example #30
0
 def test_empty_image(self, qcow2_compat, desired_qcow2_compat):
     with namedTemporaryDir() as tmpdir:
         base_path = os.path.join(tmpdir, 'base.img')
         leaf_path = os.path.join(tmpdir, 'leaf.img')
         size = 1048576
         qemuimg.create(base_path, size=size, format=qemuimg.FORMAT.RAW)
         qemuimg.create(leaf_path, format=qemuimg.FORMAT.QCOW2,
                        backing=base_path)
         qemuimg.amend(leaf_path, desired_qcow2_compat)
         self.assertEquals(qemuimg.info(leaf_path)['compat'],
                           desired_qcow2_compat)
Example #31
0
    def test_qcow2_compat_version3(self):
        def create(cmd, **kw):
            expected = [
                QEMU_IMG, 'create', '-f', 'qcow2', '-o', 'compat=1.1', 'image'
            ]
            self.assertEqual(cmd, expected)
            return 0, '', ''

        with MonkeyPatchScope([(qemuimg, 'config', CONFIG),
                               (commands, 'execCmd', create)]):
            qemuimg.create('image', format='qcow2', qcow2Compat='1.1')
Example #32
0
    def test_qcow2_compat(self):

        def create(cmd, **kw):
            expected = [QEMU_IMG, 'create', '-f', 'qcow2', '-o', 'compat=0.10',
                        'image']
            self.assertEqual(cmd, expected)
            return 0, '', ''

        with MonkeyPatchScope([(qemuimg, 'config', CONFIG),
                               (commands, 'execCmd', create)]):
            qemuimg.create('image', format='qcow2')
 def make_volume(self, env, img_id, vol_id, parent_vol_id, vol_fmt):
     if parent_vol_id != sc.BLANK_UUID:
         vol_fmt = sc.COW_FORMAT
     env.make_volume(self.SIZE, img_id, vol_id,
                     parent_vol_id=parent_vol_id, vol_format=vol_fmt)
     vol = env.sd_manifest.produceVolume(img_id, vol_id)
     if vol_fmt == sc.COW_FORMAT:
         backing = parent_vol_id if parent_vol_id != sc.BLANK_UUID else None
         qemuimg.create(vol.volumePath, size=self.SIZE,
                        format=qemuimg.FORMAT.QCOW2, backing=backing)
     return vol
Example #34
0
 def test_disabled_compat_raises(self, qemu_compat, hsm_compat):
     with self.fake_volume(sc.COW_FORMAT) as vol:
         create_conf = make_config([('irs', 'qcow2_compat', qemu_compat)])
         check_conf = make_config([('irs', 'qcow2_compat', hsm_compat)])
         with MonkeyPatchScope([(qemuimg, 'config', create_conf),
                                (hsm, 'config', check_conf)]):
             qemuimg.create(vol.volumePath, size=self.SIZE,
                            format=qemuimg.FORMAT.QCOW2)
             h = FakeHSM()
             self.assertRaises(se.ImageVerificationError,
                               h.verify_untrusted_volume, 'sp',
                               vol.sdUUID, vol.imgUUID, vol.volUUID)
Example #35
0
 def test_valid_qcow2_compat(self, hsm_compat, config_compat, sd_version):
     with self.fake_volume(vol_fmt=sc.COW_FORMAT,
                           sd_version=sd_version) as vol:
         create_conf = make_config([('irs', 'qcow2_compat', config_compat)])
         info = {"format": qemuimg.FORMAT.QCOW2, "compat": hsm_compat}
         with MonkeyPatchScope([(qemuimg, 'config', create_conf),
                                (qemuimg, 'info', lambda unused: info)]):
             qemuimg.create(vol.volumePath, size=self.SIZE,
                            format=qemuimg.FORMAT.QCOW2)
             h = FakeHSM()
             self.assertNotRaises(h.verify_untrusted_volume, 'sp',
                                  vol.sdUUID, vol.imgUUID, vol.volUUID)
Example #36
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 #37
0
def make_image(path, size, format, index, qcow2_compat, backing=None):
    qemuimg.create(path,
                   size=size,
                   format=format,
                   qcow2Compat=qcow2_compat,
                   backing=backing)
    offset = index * 1024
    qemu_pattern_write(path,
                       format,
                       offset=offset,
                       len=1024,
                       pattern=0xf0 + index)
Example #38
0
    def test_qcow2_compat_unsupported(self):
        def qcow2_compat_unsupported(cmd, **kw):
            self.check_supports_qcow2_compat(cmd, **kw)
            return 0, 'Supported options:\nsize ...\n', ''

        def create(cmd, **kw):
            expected = [QEMU_IMG, 'create', '-f', 'qcow2', 'image']
            self.assertEqual(cmd, expected)
            return 0, '', ''

        with FakeCmd(utils, 'execCmd', qcow2_compat_unsupported, create):
            qemuimg.create('image', format='qcow2')
Example #39
0
 def test_valid_qcow2_compat(self, hsm_compat, config_compat, sd_version):
     with self.fake_volume(vol_fmt=sc.COW_FORMAT,
                           sd_version=sd_version) as vol:
         create_conf = make_config([('irs', 'qcow2_compat', config_compat)])
         info = {"format": qemuimg.FORMAT.QCOW2, "compat": hsm_compat}
         with MonkeyPatchScope([(qemuimg, 'config', create_conf),
                                (qemuimg, 'info', lambda unused: info)]):
             qemuimg.create(vol.volumePath,
                            size=self.SIZE,
                            format=qemuimg.FORMAT.QCOW2)
             h = FakeHSM()
             self.assertNotRaises(h.verify_untrusted_volume, 'sp',
                                  vol.sdUUID, vol.imgUUID, vol.volUUID)
Example #40
0
    def test_qcow2_compat_supported(self):

        def qcow2_compat_supported(cmd, **kw):
            assert cmd == [qemuimg._qemuimg.cmd, 'create', '-f', 'qcow2', '-o',
                           '?', '/dev/null']
            return 0, 'Supported options:\ncompat ...\n', ''

        def create_qcow2_compat(cmd, **kw):
            assert cmd == [qemuimg._qemuimg.cmd, 'create', '-f', 'qcow2', '-o',
                           'compat=0.10', 'image']
            return 0, '', ''

        with FakeExecCmd(qcow2_compat_supported, create_qcow2_compat):
            qemuimg.create('image', format='qcow2')
Example #41
0
    def test_info(self):
        with namedTemporaryDir() as tmpdir:
            base_path = os.path.join(tmpdir, 'base.img')
            leaf_path = os.path.join(tmpdir, 'leaf.img')
            size = 1048576
            leaf_fmt = qemuimg.FORMAT.QCOW2
            with MonkeyPatchScope([(qemuimg, 'config', CONFIG)]):
                qemuimg.create(base_path, size=size, format=qemuimg.FORMAT.RAW)
                qemuimg.create(leaf_path, format=leaf_fmt, backing=base_path)

            info = qemuimg.info(leaf_path)
            self.assertEqual(leaf_fmt, info['format'])
            self.assertEqual(size, info['virtualsize'])
            self.assertEqual(self.CLUSTER_SIZE, info['clustersize'])
            self.assertEqual(base_path, info['backingfile'])
            self.assertEqual('0.10', info['compat'])
 def make_volume(self, env, img_id, vol_id, parent_vol_id, vol_fmt):
     if parent_vol_id != sc.BLANK_UUID:
         vol_fmt = sc.COW_FORMAT
     env.make_volume(self.DEFAULT_SIZE,
                     img_id,
                     vol_id,
                     parent_vol_id=parent_vol_id,
                     vol_format=vol_fmt)
     vol = env.sd_manifest.produceVolume(img_id, vol_id)
     if vol_fmt == sc.COW_FORMAT:
         backing = parent_vol_id if parent_vol_id != sc.BLANK_UUID else None
         qemuimg.create(vol.volumePath,
                        size=self.DEFAULT_SIZE,
                        format=qemuimg.FORMAT.QCOW2,
                        backing=backing)
     return vol
Example #43
0
    def test_info(self):
        with namedTemporaryDir() as tmpdir:
            base_path = os.path.join(tmpdir, 'base.img')
            leaf_path = os.path.join(tmpdir, 'leaf.img')
            size = 1048576
            leaf_fmt = qemuimg.FORMAT.QCOW2
            with MonkeyPatchScope([(qemuimg, 'config', CONFIG)]):
                qemuimg.create(base_path, size=size, format=qemuimg.FORMAT.RAW)
                qemuimg.create(leaf_path, format=leaf_fmt, backing=base_path)

            info = qemuimg.info(leaf_path)
            self.assertEqual(leaf_fmt, info['format'])
            self.assertEqual(size, info['virtualsize'])
            self.assertEqual(self.CLUSTER_SIZE, info['clustersize'])
            self.assertEqual(base_path, info['backingfile'])
            self.assertEqual('0.10', info['compat'])
Example #44
0
    def _create(cls, dom, imgUUID, volUUID, size, volFormat, preallocate,
                volParent, srcImgUUID, srcVolUUID, volPath):
        """
        Class specific implementation of volumeCreate. All the exceptions are
        properly handled and logged in volume.create()
        """

        if preallocate == volume.SPARSE_VOL:
            volSize = "%s" % config.get("irs", "volume_utilization_chunk_mb")
        else:
            volSize = "%s" % ((size + SECTORS_TO_MB - 1) / SECTORS_TO_MB)

        lvm.createLV(dom.sdUUID, volUUID, volSize, activate=True,
                     initialTag=TAG_VOL_UNINIT)

        utils.rmFile(volPath)
        os.symlink(lvm.lvPath(dom.sdUUID, volUUID), volPath)

        if not volParent:
            cls.log.info("Request to create %s volume %s with size = %s "
                         "sectors", volume.type2name(volFormat), volPath,
                         size)
            if volFormat == volume.COW_FORMAT:
                qemuimg.create(
                    volPath, size * BLOCK_SIZE, volume.fmt2str(volFormat))
        else:
            # Create hardlink to template and its meta file
            cls.log.info("Request to create snapshot %s/%s of volume %s/%s",
                         imgUUID, volUUID, srcImgUUID, srcVolUUID)
            volParent.clone(volPath, volFormat)

        with cls._tagCreateLock:
            mdSlot = dom.getVolumeMetadataSlot(volUUID, VOLUME_MDNUMBLKS)
            mdTags = ["%s%s" % (TAG_PREFIX_MD, mdSlot),
                      "%s%s" % (TAG_PREFIX_PARENT, srcVolUUID),
                      "%s%s" % (TAG_PREFIX_IMAGE, imgUUID)]
            lvm.changeLVTags(dom.sdUUID, volUUID, delTags=[TAG_VOL_UNINIT],
                             addTags=mdTags)

        try:
            lvm.deactivateLVs(dom.sdUUID, volUUID)
        except se.CannotDeactivateLogicalVolume:
            cls.log.warn("Cannot deactivate new created volume %s/%s",
                         dom.sdUUID, volUUID, exc_info=True)

        return (dom.sdUUID, mdSlot)
Example #45
0
    def _create(cls, dom, imgUUID, volUUID, size, volFormat, preallocate,
                volParent, srcImgUUID, srcVolUUID, volPath, initialSize=None):
        """
        Class specific implementation of volumeCreate. All the exceptions are
        properly handled and logged in volume.create()
        """

        lvSize = cls.calculate_volume_alloc_size(preallocate,
                                                 size, initialSize)

        lvm.createLV(dom.sdUUID, volUUID, "%s" % lvSize, activate=True,
                     initialTags=(sc.TAG_VOL_UNINIT,))

        fileutils.rm_file(volPath)
        os.symlink(lvm.lvPath(dom.sdUUID, volUUID), volPath)

        if not volParent:
            cls.log.info("Request to create %s volume %s with size = %s "
                         "sectors", sc.type2name(volFormat), volPath,
                         size)
            if volFormat == sc.COW_FORMAT:
                qemuimg.create(volPath,
                               size=size * BLOCK_SIZE,
                               format=sc.fmt2str(volFormat),
                               qcow2Compat=dom.qcow2_compat())
        else:
            # Create hardlink to template and its meta file
            cls.log.info("Request to create snapshot %s/%s of volume %s/%s",
                         imgUUID, volUUID, srcImgUUID, srcVolUUID)
            volParent.clone(volPath, volFormat)

        with dom.acquireVolumeMetadataSlot(
                volUUID, sc.VOLUME_MDNUMBLKS) as slot:
            mdTags = ["%s%s" % (sc.TAG_PREFIX_MD, slot),
                      "%s%s" % (sc.TAG_PREFIX_PARENT, srcVolUUID),
                      "%s%s" % (sc.TAG_PREFIX_IMAGE, imgUUID)]
            lvm.changeLVTags(dom.sdUUID, volUUID, delTags=[sc.TAG_VOL_UNINIT],
                             addTags=mdTags)

        try:
            lvm.deactivateLVs(dom.sdUUID, [volUUID])
        except se.CannotDeactivateLogicalVolume:
            cls.log.warn("Cannot deactivate new created volume %s/%s",
                         dom.sdUUID, volUUID, exc_info=True)

        return (dom.sdUUID, slot)
Example #46
0
    def _create(cls, dom, imgUUID, volUUID, size, volFormat, preallocate,
                volParent, srcImgUUID, srcVolUUID, volPath):
        """
        Class specific implementation of volumeCreate. All the exceptions are
        properly handled and logged in volume.create()
        """

        sizeBytes = size * BLOCK_SIZE
        truncSize = sizeBytes if volFormat == volume.RAW_FORMAT else 0

        try:
            oop.getProcessPool(dom.sdUUID).truncateFile(
                volPath, truncSize, mode=VOLUME_PERMISSIONS, creatExcl=True)
        except OSError as e:
            if e.errno == errno.EEXIST:
                raise se.VolumeAlreadyExists(volUUID)
            raise

        if preallocate == volume.PREALLOCATED_VOL:
            try:
                # ddWatchCopy expects size to be in bytes
                misc.ddWatchCopy("/dev/zero", volPath,
                                 vars.task.aborting, sizeBytes)
            except ActionStopped:
                raise
            except Exception:
                cls.log.error("Unexpected error", exc_info=True)
                raise se.VolumesZeroingError(volPath)

        if not volParent:
            cls.log.info("Request to create %s volume %s with size = %s "
                         "sectors", volume.type2name(volFormat), volPath,
                         size)
            if volFormat == volume.COW_FORMAT:
                qemuimg.create(volPath, sizeBytes, volume.fmt2str(volFormat))
        else:
            # Create hardlink to template and its meta file
            cls.log.info("Request to create snapshot %s/%s of volume %s/%s",
                         imgUUID, volUUID, srcImgUUID, srcVolUUID)
            volParent.clone(volPath, volFormat)

        # Forcing the volume permissions in case one of the tools we use
        # (dd, qemu-img, etc.) will mistakenly change the file permissiosn.
        dom.oop.os.chmod(volPath, VOLUME_PERMISSIONS)

        return (volPath,)
Example #47
0
    def test_empty_image(self, qcow2_compat):
        with namedTemporaryDir() as tmpdir:
            size = 1048576
            image = os.path.join(tmpdir, "base.img")
            qemuimg.create(image, size=size, format=self.FORMAT,
                           qcow2Compat=qcow2_compat)

            expected = [
                # single run - empty
                {
                    "start": 0,
                    "length": size,
                    "data": False,
                    "zero": True,
                },
            ]

            self.check_map(qemuimg.map(image), expected)
Example #48
0
    def test_empty_image(self, qcow2_compat):
        with namedTemporaryDir() as tmpdir:
            size = 1048576
            image = os.path.join(tmpdir, "base.img")
            qemuimg.create(image, size=size, format=self.FORMAT,
                           qcow2Compat=qcow2_compat)

            expected = [
                # single run - empty
                {
                    "start": 0,
                    "length": size,
                    "data": False,
                    "zero": True,
                },
            ]

            self.check_map(qemuimg.map(image), expected)
Example #49
0
    def _create(cls, dom, imgUUID, volUUID, size, volFormat, preallocate,
                volParent, srcImgUUID, srcVolUUID, volPath, initialSize=None):
        """
        Class specific implementation of volumeCreate. All the exceptions are
        properly handled and logged in volume.create()
        """

        lvSize = cls.calculate_volume_alloc_size(preallocate,
                                                 size, initialSize)

        lvm.createLV(dom.sdUUID, volUUID, "%s" % lvSize, activate=True,
                     initialTags=(sc.TAG_VOL_UNINIT,))

        utils.rmFile(volPath)
        os.symlink(lvm.lvPath(dom.sdUUID, volUUID), volPath)

        if not volParent:
            cls.log.info("Request to create %s volume %s with size = %s "
                         "sectors", sc.type2name(volFormat), volPath,
                         size)
            if volFormat == sc.COW_FORMAT:
                qemuimg.create(
                    volPath, size * BLOCK_SIZE, sc.fmt2str(volFormat))
        else:
            # Create hardlink to template and its meta file
            cls.log.info("Request to create snapshot %s/%s of volume %s/%s",
                         imgUUID, volUUID, srcImgUUID, srcVolUUID)
            volParent.clone(volPath, volFormat)

        with dom.acquireVolumeMetadataSlot(
                volUUID, sc.VOLUME_MDNUMBLKS) as slot:
            mdTags = ["%s%s" % (sc.TAG_PREFIX_MD, slot),
                      "%s%s" % (sc.TAG_PREFIX_PARENT, srcVolUUID),
                      "%s%s" % (sc.TAG_PREFIX_IMAGE, imgUUID)]
            lvm.changeLVTags(dom.sdUUID, volUUID, delTags=[sc.TAG_VOL_UNINIT],
                             addTags=mdTags)

        try:
            lvm.deactivateLVs(dom.sdUUID, [volUUID])
        except se.CannotDeactivateLogicalVolume:
            cls.log.warn("Cannot deactivate new created volume %s/%s",
                         dom.sdUUID, volUUID, exc_info=True)

        return (dom.sdUUID, slot)
Example #50
0
def make_qemu_chain(env, size, base_vol_fmt, chain_len):
    vol_list = []
    img_id = str(uuid.uuid4())
    parent_vol_id = sc.BLANK_UUID
    vol_fmt = base_vol_fmt
    for i in range(chain_len):
        vol_id = str(uuid.uuid4())
        if parent_vol_id != sc.BLANK_UUID:
            vol_fmt = sc.COW_FORMAT
        env.make_volume(size, img_id, vol_id,
                        parent_vol_id=parent_vol_id, vol_format=vol_fmt)
        vol = env.sd_manifest.produceVolume(img_id, vol_id)
        if vol_fmt == sc.COW_FORMAT:
            backing = parent_vol_id if parent_vol_id != sc.BLANK_UUID else None
            qemuimg.create(vol.volumePath, size=size,
                           format=qemuimg.FORMAT.QCOW2, backing=backing)
        vol_list.append(vol)
        parent_vol_id = vol_id
    return vol_list
Example #51
0
def make_qemu_chain(env, size, base_vol_fmt, chain_len, qcow2_compat='0.10'):
    vol_list = []
    img_id = make_uuid()
    parent_vol_id = sc.BLANK_UUID
    vol_fmt = base_vol_fmt
    for i in range(chain_len):
        vol_id = make_uuid()
        if parent_vol_id != sc.BLANK_UUID:
            vol_fmt = sc.COW_FORMAT
        vol_type = sc.LEAF_VOL if i == chain_len - 1 else sc.INTERNAL_VOL
        env.make_volume(size, img_id, vol_id,
                        parent_vol_id=parent_vol_id, vol_format=vol_fmt,
                        vol_type=vol_type)
        vol = env.sd_manifest.produceVolume(img_id, vol_id)
        if vol_fmt == sc.COW_FORMAT:
            backing = parent_vol_id if parent_vol_id != sc.BLANK_UUID else None
            qemuimg.create(vol.volumePath,
                           size=size,
                           format=qemuimg.FORMAT.QCOW2,
                           qcow2Compat=qcow2_compat,
                           backing=backing)
        vol_list.append(vol)
        parent_vol_id = vol_id
    return vol_list
Example #52
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 #53
0
 def _initialize_volume(self, vol_format, size):
     if vol_format == sc.COW_FORMAT:
         qemuimg.create(self.volume_path, size, sc.fmt2str(vol_format))
Example #54
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 #55
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 #56
0
 def test_qcow2_compat_invalid(self):
     with self.assertRaises(ValueError):
         qemuimg.create('image', format='qcow2', qcow2Compat='1.11')