Beispiel #1
0
    def test_convert_image(self, mock_stat):

        mox = self._mox
        mox.StubOutWithMock(utils, 'execute')
        mox.StubOutWithMock(utils, 'is_blk_device')

        TEST_OUT_FORMAT = 'vmdk'
        TEST_SOURCE = 'img/qemu.img'
        TEST_DEST = '/img/vmware.vmdk'

        utils.is_blk_device(TEST_DEST).AndReturn(True)
        utils.execute('dd',
                      'count=0',
                      'if=img/qemu.img',
                      'of=/img/vmware.vmdk',
                      'oflag=direct',
                      run_as_root=True)
        utils.execute('qemu-img',
                      'convert',
                      '-t',
                      'none',
                      '-O',
                      TEST_OUT_FORMAT,
                      TEST_SOURCE,
                      TEST_DEST,
                      run_as_root=True)

        mox.ReplayAll()

        image_utils.convert_image(TEST_SOURCE,
                                  TEST_DEST,
                                  TEST_OUT_FORMAT,
                                  run_as_root=True)

        mox.VerifyAll()
    def _test_fetch_to_raw(self, has_qemu=True, src_inf=None, dest_inf=None, bps_limit=0):
        mox = self._mox
        mox.StubOutWithMock(image_utils, "create_temporary_file")
        mox.StubOutWithMock(utils, "execute")
        mox.StubOutWithMock(image_utils, "fetch")
        mox.StubOutWithMock(volume_utils, "setup_blkio_cgroup")
        mox.StubOutWithMock(utils, "is_blk_device")

        TEST_INFO = "image: qemu.qcow2\n" "file format: raw\n" "virtual size: 0 (0 bytes)\n" "disk size: 0"

        utils.is_blk_device(self.TEST_DEV_PATH).AndReturn(True)
        self.override_config("volume_copy_bps_limit", bps_limit)

        image_utils.create_temporary_file().AndReturn(self.TEST_DEV_PATH)

        test_qemu_img = utils.execute("env", "LC_ALL=C", "qemu-img", "info", self.TEST_DEV_PATH, run_as_root=True)

        if has_qemu:
            test_qemu_img.AndReturn((TEST_INFO, "ignored"))
            image_utils.fetch(context, self._image_service, self.TEST_IMAGE_ID, self.TEST_DEV_PATH, None, None)
        else:
            test_qemu_img.AndRaise(processutils.ProcessExecutionError())

        if has_qemu and src_inf:
            utils.execute("env", "LC_ALL=C", "qemu-img", "info", self.TEST_DEV_PATH, run_as_root=True).AndReturn(
                (src_inf, "ignored")
            )

        if has_qemu and dest_inf:
            if bps_limit:
                prefix = ("cgexec", "-g", "blkio:test")
            else:
                prefix = ()

            utils.execute(
                "dd", "count=0", "if=/dev/ether/fake_dev", "of=/dev/ether/fake_dev", "oflag=direct", run_as_root=True
            )

            cmd = prefix + ("qemu-img", "convert", "-t", "none", "-O", "raw", self.TEST_DEV_PATH, self.TEST_DEV_PATH)

            volume_utils.setup_blkio_cgroup(self.TEST_DEV_PATH, self.TEST_DEV_PATH, bps_limit).AndReturn(prefix)

            utils.execute(*cmd, run_as_root=True)

            utils.execute("env", "LC_ALL=C", "qemu-img", "info", self.TEST_DEV_PATH, run_as_root=True).AndReturn(
                (dest_inf, "ignored")
            )

        self._mox.ReplayAll()
Beispiel #3
0
def _convert_image(prefix, source, dest, out_format,
                   out_subformat=None, src_format=None,
                   run_as_root=True):
    """Convert image to other format."""

    # Check whether O_DIRECT is supported and set '-t none' if it is
    # This is needed to ensure that all data hit the device before
    # it gets unmapped remotely from the host for some backends
    # Reference Bug: #1363016

    # NOTE(jdg): In the case of file devices qemu does the
    # flush properly and more efficiently than would be done
    # setting O_DIRECT, so check for that and skip the
    # setting for non BLK devs
    if (utils.is_blk_device(dest) and
            volume_utils.check_for_odirect_support(source,
                                                   dest,
                                                   'oflag=direct')):
        cache_mode = 'none'
    else:
        # use default
        cache_mode = None

    cmd = _get_qemu_convert_cmd(source, dest,
                                out_format=out_format,
                                src_format=src_format,
                                out_subformat=out_subformat,
                                cache_mode=cache_mode,
                                prefix=prefix)

    start_time = timeutils.utcnow()
    utils.execute(*cmd, run_as_root=run_as_root)
    duration = timeutils.delta_seconds(start_time, timeutils.utcnow())

    # NOTE(jdg): use a default of 1, mostly for unit test, but in
    # some incredible event this is 0 (cirros image?) don't barf
    if duration < 1:
        duration = 1
    try:
        image_size = qemu_img_info(source,
                                   run_as_root=run_as_root).virtual_size
    except ValueError as e:
        msg = ("The image was successfully converted, but image size "
               "is unavailable. src %(src)s, dest %(dest)s. %(error)s")
        LOG.info(msg, {"src": source,
                       "dest": dest,
                       "error": e})
        return

    fsz_mb = image_size / units.Mi
    mbps = (fsz_mb / duration)
    msg = ("Image conversion details: src %(src)s, size %(sz).2f MB, "
           "duration %(duration).2f sec, destination %(dest)s")
    LOG.debug(msg, {"src": source,
                    "sz": fsz_mb,
                    "duration": duration,
                    "dest": dest})

    msg = "Converted %(sz).2f MB image at %(mbps).2f MB/s"
    LOG.info(msg, {"sz": fsz_mb, "mbps": mbps})
Beispiel #4
0
def convert_image(source, dest, out_format, bps_limit=None, is_qcow_compress=False):
    """Convert image to other format."""

    cmd = ('qemu-img', 'convert',
           '-O', out_format, source, dest)

    if is_qcow_compress and out_format=='qcow2':
        cmd = ('qemu-img', 'convert',
               '-c',
               '-O', out_format, source, dest)
    else:
        cmd = ('qemu-img', 'convert',
               '-O', out_format, source, dest)

    # Check whether O_DIRECT is supported and set '-t none' if it is
    # This is needed to ensure that all data hit the device before
    # it gets unmapped remotely from the host for some backends
    # Reference Bug: #1363016

    # NOTE(jdg): In the case of file devices qemu does the
    # flush properly and more efficiently than would be done
    # setting O_DIRECT, so check for that and skip the
    # setting for non BLK devs
    if (utils.is_blk_device(dest) and
            volume_utils.check_for_odirect_support(source,
                                                   dest,
                                                   'oflag=direct')):
        cmd = ('qemu-img', 'convert',
               '-t', 'none',
               '-O', out_format, source, dest)

    start_time = timeutils.utcnow()
    cgcmd = volume_utils.setup_blkio_cgroup(source, dest, bps_limit)
    if cgcmd:
        cmd = tuple(cgcmd) + cmd
    utils.execute(*cmd, run_as_root=True)

    duration = timeutils.delta_seconds(start_time, timeutils.utcnow())

    # NOTE(jdg): use a default of 1, mostly for unit test, but in
    # some incredible event this is 0 (cirros image?) don't barf
    if duration < 1:
        duration = 1
    fsz_mb = os.stat(source).st_size / units.Mi
    mbps = (fsz_mb / duration)
    msg = ("Image conversion details: src %(src)s, size %(sz).2f MB, "
           "duration %(duration).2f sec, destination %(dest)s")
    LOG.debug(msg % {"src": source,
                     "sz": fsz_mb,
                     "duration": duration,
                     "dest": dest})

    msg = _("Converted %(sz).2f MB image at %(mbps).2f MB/s")
    LOG.info(msg % {"sz": fsz_mb, "mbps": mbps})
Beispiel #5
0
def convert_image(source,
                  dest,
                  out_format,
                  bps_limit=None,
                  is_qcow_compress=False):
    """Convert image to other format."""

    cmd = ('qemu-img', 'convert', '-O', out_format, source, dest)

    if is_qcow_compress and out_format == 'qcow2':
        cmd = ('qemu-img', 'convert', '-c', '-O', out_format, source, dest)
    else:
        cmd = ('qemu-img', 'convert', '-O', out_format, source, dest)

    # Check whether O_DIRECT is supported and set '-t none' if it is
    # This is needed to ensure that all data hit the device before
    # it gets unmapped remotely from the host for some backends
    # Reference Bug: #1363016

    # NOTE(jdg): In the case of file devices qemu does the
    # flush properly and more efficiently than would be done
    # setting O_DIRECT, so check for that and skip the
    # setting for non BLK devs
    if (utils.is_blk_device(dest) and volume_utils.check_for_odirect_support(
            source, dest, 'oflag=direct')):
        cmd = ('qemu-img', 'convert', '-t', 'none', '-O', out_format, source,
               dest)

    start_time = timeutils.utcnow()
    cgcmd = volume_utils.setup_blkio_cgroup(source, dest, bps_limit)
    if cgcmd:
        cmd = tuple(cgcmd) + cmd
    utils.execute(*cmd, run_as_root=True)

    duration = timeutils.delta_seconds(start_time, timeutils.utcnow())

    # NOTE(jdg): use a default of 1, mostly for unit test, but in
    # some incredible event this is 0 (cirros image?) don't barf
    if duration < 1:
        duration = 1
    fsz_mb = os.stat(source).st_size / units.Mi
    mbps = (fsz_mb / duration)
    msg = ("Image conversion details: src %(src)s, size %(sz).2f MB, "
           "duration %(duration).2f sec, destination %(dest)s")
    LOG.debug(msg % {
        "src": source,
        "sz": fsz_mb,
        "duration": duration,
        "dest": dest
    })

    msg = _("Converted %(sz).2f MB image at %(mbps).2f MB/s")
    LOG.info(msg % {"sz": fsz_mb, "mbps": mbps})
    def test_convert_image(self, mock_stat):

        mox = self._mox
        mox.StubOutWithMock(utils, "execute")
        mox.StubOutWithMock(utils, "is_blk_device")

        TEST_OUT_FORMAT = "vmdk"
        TEST_SOURCE = "img/qemu.img"
        TEST_DEST = "/img/vmware.vmdk"

        utils.is_blk_device(TEST_DEST).AndReturn(True)
        utils.execute("dd", "count=0", "if=img/qemu.img", "of=/img/vmware.vmdk", "oflag=direct", run_as_root=True)
        utils.execute(
            "qemu-img", "convert", "-t", "none", "-O", TEST_OUT_FORMAT, TEST_SOURCE, TEST_DEST, run_as_root=True
        )

        mox.ReplayAll()

        image_utils.convert_image(TEST_SOURCE, TEST_DEST, TEST_OUT_FORMAT, run_as_root=True)

        mox.VerifyAll()
Beispiel #7
0
def _convert_image(prefix, source, dest, out_format, run_as_root=True):
    """Convert image to other format."""

    cmd = prefix + ('qemu-img', 'convert',
                    '-O', out_format, source, dest)

    # Check whether O_DIRECT is supported and set '-t none' if it is
    # This is needed to ensure that all data hit the device before
    # it gets unmapped remotely from the host for some backends
    # Reference Bug: #1363016

    # NOTE(jdg): In the case of file devices qemu does the
    # flush properly and more efficiently than would be done
    # setting O_DIRECT, so check for that and skip the
    # setting for non BLK devs
    if (utils.is_blk_device(dest) and
            volume_utils.check_for_odirect_support(source,
                                                   dest,
                                                   'oflag=direct')):
        cmd = prefix + ('qemu-img', 'convert',
                        '-t', 'none',
                        '-O', out_format, source, dest)

    start_time = timeutils.utcnow()
    utils.execute(*cmd, run_as_root=run_as_root)
    duration = timeutils.delta_seconds(start_time, timeutils.utcnow())

    # NOTE(jdg): use a default of 1, mostly for unit test, but in
    # some incredible event this is 0 (cirros image?) don't barf
    if duration < 1:
        duration = 1
    try:
        image_size = qemu_img_info(source, run_as_root=True).virtual_size
    except ValueError as e:
        msg = _LI("The image was successfully converted, but image size "
                  "is unavailable. src %(src)s, dest %(dest)s. %(error)s")
        LOG.info(msg, {"src": source,
                       "dest": dest,
                       "error": e})
        return

    fsz_mb = image_size / units.Mi
    mbps = (fsz_mb / duration)
    msg = ("Image conversion details: src %(src)s, size %(sz).2f MB, "
           "duration %(duration).2f sec, destination %(dest)s")
    LOG.debug(msg, {"src": source,
                    "sz": fsz_mb,
                    "duration": duration,
                    "dest": dest})

    msg = _LI("Converted %(sz).2f MB image at %(mbps).2f MB/s")
    LOG.info(msg, {"sz": fsz_mb, "mbps": mbps})
Beispiel #8
0
    def test_convert_image(self, mock_stat):

        mox = self._mox
        mox.StubOutWithMock(utils, 'execute')
        mox.StubOutWithMock(utils, 'is_blk_device')

        TEST_OUT_FORMAT = 'vmdk'
        TEST_SOURCE = 'img/qemu.img'
        TEST_DEST = '/img/vmware.vmdk'

        utils.is_blk_device(TEST_DEST).AndReturn(True)
        utils.execute('dd', 'count=0', 'if=img/qemu.img',
                      'of=/img/vmware.vmdk', 'oflag=direct',
                      run_as_root=True)
        utils.execute(
            'qemu-img', 'convert', '-t', 'none', '-O', TEST_OUT_FORMAT,
            TEST_SOURCE, TEST_DEST, run_as_root=True)

        mox.ReplayAll()

        image_utils.convert_image(TEST_SOURCE, TEST_DEST, TEST_OUT_FORMAT)

        mox.VerifyAll()
Beispiel #9
0
    def _test_fetch_to_raw(self,
                           has_qemu=True,
                           src_inf=None,
                           dest_inf=None,
                           bps_limit=0):
        mox = self._mox
        mox.StubOutWithMock(image_utils, 'create_temporary_file')
        mox.StubOutWithMock(utils, 'execute')
        mox.StubOutWithMock(image_utils, 'fetch')
        mox.StubOutWithMock(volume_utils, 'setup_blkio_cgroup')
        mox.StubOutWithMock(utils, 'is_blk_device')

        TEST_INFO = ("image: qemu.qcow2\n"
                     "file format: raw\n"
                     "virtual size: 0 (0 bytes)\n"
                     "disk size: 0")

        utils.is_blk_device(self.TEST_DEV_PATH).AndReturn(True)
        self.override_config('volume_copy_bps_limit', bps_limit)

        image_utils.create_temporary_file().AndReturn(self.TEST_DEV_PATH)

        test_qemu_img = utils.execute('env',
                                      'LC_ALL=C',
                                      'qemu-img',
                                      'info',
                                      self.TEST_DEV_PATH,
                                      run_as_root=True)

        if has_qemu:
            test_qemu_img.AndReturn((TEST_INFO, 'ignored'))
            image_utils.fetch(context, self._image_service, self.TEST_IMAGE_ID,
                              self.TEST_DEV_PATH, None, None)
        else:
            test_qemu_img.AndRaise(processutils.ProcessExecutionError())

        if has_qemu and src_inf:
            utils.execute('env',
                          'LC_ALL=C',
                          'qemu-img',
                          'info',
                          self.TEST_DEV_PATH,
                          run_as_root=True).AndReturn((src_inf, 'ignored'))

        if has_qemu and dest_inf:
            if bps_limit:
                prefix = ('cgexec', '-g', 'blkio:test')
            else:
                prefix = ()

            utils.execute('dd',
                          'count=0',
                          'if=/dev/ether/fake_dev',
                          'of=/dev/ether/fake_dev',
                          'oflag=direct',
                          run_as_root=True)

            cmd = prefix + ('qemu-img', 'convert', '-t', 'none', '-O', 'raw',
                            self.TEST_DEV_PATH, self.TEST_DEV_PATH)

            volume_utils.setup_blkio_cgroup(self.TEST_DEV_PATH,
                                            self.TEST_DEV_PATH,
                                            bps_limit).AndReturn(prefix)

            utils.execute(*cmd, run_as_root=True)

            utils.execute('env',
                          'LC_ALL=C',
                          'qemu-img',
                          'info',
                          self.TEST_DEV_PATH,
                          run_as_root=True).AndReturn((dest_inf, 'ignored'))

        self._mox.ReplayAll()
Beispiel #10
0
def _convert_image(prefix, source, dest, out_format,
                   src_format=None, run_as_root=True):
    """Convert image to other format."""

    cmd = prefix + ('qemu-img', 'convert',
                    '-O', out_format, source, dest)

    # Check whether O_DIRECT is supported and set '-t none' if it is
    # This is needed to ensure that all data hit the device before
    # it gets unmapped remotely from the host for some backends
    # Reference Bug: #1363016

    # NOTE(jdg): In the case of file devices qemu does the
    # flush properly and more efficiently than would be done
    # setting O_DIRECT, so check for that and skip the
    # setting for non BLK devs
    if (utils.is_blk_device(dest) and
            volume_utils.check_for_odirect_support(source,
                                                   dest,
                                                   'oflag=direct')):
        cmd = prefix + ('qemu-img', 'convert',
                        '-t', 'none')

        # AMI images can be raw or qcow2 but qemu-img doesn't accept "ami" as
        # an image format, so we use automatic detection.
        # TODO(geguileo): This fixes unencrypted AMI image case, but we need to
        # fix the encrypted case.
        if (src_format or '').lower() not in ('', 'ami'):
            cmd += ('-f', src_format)  # prevent detection of format

        cmd += ('-O', out_format, source, dest)

    start_time = timeutils.utcnow()
    utils.execute(*cmd, run_as_root=run_as_root)
    duration = timeutils.delta_seconds(start_time, timeutils.utcnow())

    # NOTE(jdg): use a default of 1, mostly for unit test, but in
    # some incredible event this is 0 (cirros image?) don't barf
    if duration < 1:
        duration = 1
    try:
        image_size = qemu_img_info(source,
                                   run_as_root=run_as_root).virtual_size
    except ValueError as e:
        msg = ("The image was successfully converted, but image size "
               "is unavailable. src %(src)s, dest %(dest)s. %(error)s")
        LOG.info(msg, {"src": source,
                       "dest": dest,
                       "error": e})
        return

    fsz_mb = image_size / units.Mi
    mbps = (fsz_mb / duration)
    msg = ("Image conversion details: src %(src)s, size %(sz).2f MB, "
           "duration %(duration).2f sec, destination %(dest)s")
    LOG.debug(msg, {"src": source,
                    "sz": fsz_mb,
                    "duration": duration,
                    "dest": dest})

    msg = "Converted %(sz).2f MB image at %(mbps).2f MB/s"
    LOG.info(msg, {"sz": fsz_mb, "mbps": mbps})
def _convert_image(prefix,
                   source,
                   dest,
                   out_format,
                   out_subformat=None,
                   src_format=None,
                   run_as_root=True,
                   cipher_spec=None,
                   passphrase_file=None,
                   compress=False):
    """Convert image to other format.

    :param prefix: command prefix, i.e. cgexec for throttling
    :param source: source filename
    :param dest: destination filename
    :param out_format: output image format of qemu-img
    :param out_subformat: output image subformat
    :param src_format: source image format
    :param run_as_root: run qemu-img as root
    :param cipher_spec: encryption details
    :param passphrase_file: filename containing luks passphrase
    :param compress: compress w/ qemu-img when possible (best effort)
    """

    # Check whether O_DIRECT is supported and set '-t none' if it is
    # This is needed to ensure that all data hit the device before
    # it gets unmapped remotely from the host for some backends
    # Reference Bug: #1363016

    # NOTE(jdg): In the case of file devices qemu does the
    # flush properly and more efficiently than would be done
    # setting O_DIRECT, so check for that and skip the
    # setting for non BLK devs
    if (utils.is_blk_device(dest) and volume_utils.check_for_odirect_support(
            source, dest, 'oflag=direct')):
        cache_mode = 'none'
    else:
        # use default
        cache_mode = None

    cmd = _get_qemu_convert_cmd(source,
                                dest,
                                out_format=out_format,
                                src_format=src_format,
                                out_subformat=out_subformat,
                                cache_mode=cache_mode,
                                prefix=prefix,
                                cipher_spec=cipher_spec,
                                passphrase_file=passphrase_file,
                                compress=compress)

    start_time = timeutils.utcnow()

    # If there is not enough space on the conversion partition, include
    # the partitions's name in the error message.
    try:
        utils.execute(*cmd, run_as_root=run_as_root)
    except processutils.ProcessExecutionError as ex:
        if "No space left" in ex.stderr and CONF.image_conversion_dir in dest:
            conversion_dir = CONF.image_conversion_dir
            while not os.path.ismount(conversion_dir):
                conversion_dir = os.path.dirname(conversion_dir)

            message = _("Insufficient free space on %(location)s for image "
                        "conversion.") % {
                            'location': conversion_dir
                        }
            LOG.error(message)

        raise
    duration = timeutils.delta_seconds(start_time, timeutils.utcnow())

    # NOTE(jdg): use a default of 1, mostly for unit test, but in
    # some incredible event this is 0 (cirros image?) don't barf
    if duration < 1:
        duration = 1
    try:
        image_size = qemu_img_info(source,
                                   run_as_root=run_as_root).virtual_size
    except ValueError as e:
        msg = ("The image was successfully converted, but image size "
               "is unavailable. src %(src)s, dest %(dest)s. %(error)s")
        LOG.info(msg, {"src": source, "dest": dest, "error": e})
        return

    fsz_mb = image_size / units.Mi
    mbps = (fsz_mb / duration)
    msg = ("Image conversion details: src %(src)s, size %(sz).2f MB, "
           "duration %(duration).2f sec, destination %(dest)s")
    LOG.debug(msg, {
        "src": source,
        "sz": fsz_mb,
        "duration": duration,
        "dest": dest
    })

    msg = "Converted %(sz).2f MB image at %(mbps).2f MB/s"
    LOG.info(msg, {"sz": fsz_mb, "mbps": mbps})
Beispiel #12
0
 def test_not_is_blk_device(self, mock_os_stat, mock_S_ISBLK):
     dev = 'not_some_device'
     self.assertFalse(utils.is_blk_device(dev))
Beispiel #13
0
 def test_fail_is_blk_device(self, mock_os_stat, mock_S_ISBLK):
     dev = 'device_exception'
     self.assertFalse(utils.is_blk_device(dev))
Beispiel #14
0
def _convert_image(prefix, source, dest, out_format,
                   out_subformat=None, src_format=None,
                   run_as_root=True, cipher_spec=None, passphrase_file=None):
    """Convert image to other format."""

    # Check whether O_DIRECT is supported and set '-t none' if it is
    # This is needed to ensure that all data hit the device before
    # it gets unmapped remotely from the host for some backends
    # Reference Bug: #1363016

    # NOTE(jdg): In the case of file devices qemu does the
    # flush properly and more efficiently than would be done
    # setting O_DIRECT, so check for that and skip the
    # setting for non BLK devs
    if (utils.is_blk_device(dest) and
            volume_utils.check_for_odirect_support(source,
                                                   dest,
                                                   'oflag=direct')):
        cache_mode = 'none'
    else:
        # use default
        cache_mode = None

    cmd = _get_qemu_convert_cmd(source, dest,
                                out_format=out_format,
                                src_format=src_format,
                                out_subformat=out_subformat,
                                cache_mode=cache_mode,
                                prefix=prefix,
                                cipher_spec=cipher_spec,
                                passphrase_file=passphrase_file)

    start_time = timeutils.utcnow()

    # If there is not enough space on the conversion partition, include
    # the partitions's name in the error message.
    try:
        utils.execute(*cmd, run_as_root=run_as_root)
    except processutils.ProcessExecutionError as ex:
        if "No space left" in ex.stderr and CONF.image_conversion_dir in dest:
            conversion_dir = CONF.image_conversion_dir
            while not os.path.ismount(conversion_dir):
                conversion_dir = os.path.dirname(conversion_dir)

            message = _("Insufficient free space on %(location)s for image "
                        "conversion.") % {'location': conversion_dir}
            LOG.error(message)

        raise

    duration = timeutils.delta_seconds(start_time, timeutils.utcnow())

    # NOTE(jdg): use a default of 1, mostly for unit test, but in
    # some incredible event this is 0 (cirros image?) don't barf
    if duration < 1:
        duration = 1
    try:
        image_size = qemu_img_info(source,
                                   run_as_root=run_as_root).virtual_size
    except ValueError as e:
        msg = ("The image was successfully converted, but image size "
               "is unavailable. src %(src)s, dest %(dest)s. %(error)s")
        LOG.info(msg, {"src": source,
                       "dest": dest,
                       "error": e})
        return

    fsz_mb = image_size / units.Mi
    mbps = (fsz_mb / duration)
    msg = ("Image conversion details: src %(src)s, size %(sz).2f MB, "
           "duration %(duration).2f sec, destination %(dest)s")
    LOG.debug(msg, {"src": source,
                    "sz": fsz_mb,
                    "duration": duration,
                    "dest": dest})

    msg = "Converted %(sz).2f MB image at %(mbps).2f MB/s"
    LOG.info(msg, {"sz": fsz_mb, "mbps": mbps})
Beispiel #15
0
 def test_is_blk_device(self, mock_os_stat, mock_S_ISBLK):
     dev = 'some_device'
     self.assertTrue(utils.is_blk_device(dev))
def _convert_image(prefix,
                   source,
                   dest,
                   out_format,
                   src_format=None,
                   run_as_root=True):
    """Convert image to other format."""

    # WRS: Append '-W' option to write out-of-order instead of sequential.
    cmd = prefix + ('qemu-img', 'convert', '-W', '-O', out_format, source,
                    dest)

    # Check whether O_DIRECT is supported and set '-t none' if it is
    # This is needed to ensure that all data hit the device before
    # it gets unmapped remotely from the host for some backends
    # Reference Bug: #1363016

    # NOTE(jdg): In the case of file devices qemu does the
    # flush properly and more efficiently than would be done
    # setting O_DIRECT, so check for that and skip the
    # setting for non BLK devs
    if (utils.is_blk_device(dest) and volume_utils.check_for_odirect_support(
            source, dest, 'oflag=direct')):
        cmd = prefix + ('qemu-img', 'convert', '-t', 'none', '-W')

        # AMI images can be raw or qcow2 but qemu-img doesn't accept "ami" as
        # an image format, so we use automatic detection.
        # TODO(geguileo): This fixes unencrypted AMI image case, but we need to
        # fix the encrypted case.
        if (src_format or '').lower() not in ('', 'ami'):
            cmd += ('-f', src_format)  # prevent detection of format

        cmd += ('-O', out_format, source, dest)

    start_time = timeutils.utcnow()

    # If there is not enough space on the conversion partition, include
    # the partitions's name in the error message.
    try:
        utils.execute(*cmd, run_as_root=run_as_root)
    except processutils.ProcessExecutionError as ex:
        if "No space left" in ex.stderr and CONF.image_conversion_dir in dest:
            conversion_dir = CONF.image_conversion_dir
            while not os.path.ismount(conversion_dir):
                conversion_dir = os.path.dirname(conversion_dir)

            raise exception.InsufficientConversionSpace(
                location=conversion_dir)
        raise

    duration = timeutils.delta_seconds(start_time, timeutils.utcnow())

    # NOTE(jdg): use a default of 1, mostly for unit test, but in
    # some incredible event this is 0 (cirros image?) don't barf
    if duration < 1:
        duration = 1
    try:
        image_size = qemu_img_info(source,
                                   run_as_root=run_as_root).virtual_size
    except ValueError as e:
        msg = ("The image was successfully converted, but image size "
               "is unavailable. src %(src)s, dest %(dest)s. %(error)s")
        LOG.info(msg, {"src": source, "dest": dest, "error": e})
        return

    fsz_mb = image_size / units.Mi
    mbps = (fsz_mb / duration)
    msg = ("Image conversion details: src %(src)s, size %(sz).2f MB, "
           "duration %(duration).2f sec, destination %(dest)s")
    LOG.debug(msg, {
        "src": source,
        "sz": fsz_mb,
        "duration": duration,
        "dest": dest
    })

    msg = ("Converted %(sz).2f MB image at %(mbps).2f MB/s, "
           "duration %(dur).1f sec")
    LOG.info(msg, {"sz": fsz_mb, "mbps": mbps, 'dur': duration})
Beispiel #17
0
    def _test_fetch_to_raw(self, has_qemu=True, src_inf=None, dest_inf=None,
                           bps_limit=0):
        mox = self._mox
        mox.StubOutWithMock(image_utils, 'create_temporary_file')
        mox.StubOutWithMock(utils, 'execute')
        mox.StubOutWithMock(image_utils, 'fetch')
        mox.StubOutWithMock(volume_utils, 'setup_blkio_cgroup')
        mox.StubOutWithMock(utils, 'is_blk_device')

        TEST_INFO = ("image: qemu.qcow2\n"
                     "file format: raw\n"
                     "virtual size: 0 (0 bytes)\n"
                     "disk size: 0")

        utils.is_blk_device(self.TEST_DEV_PATH).AndReturn(True)
        self.override_config('volume_copy_bps_limit', bps_limit)

        image_utils.create_temporary_file().AndReturn(self.TEST_DEV_PATH)

        test_qemu_img = utils.execute(
            'env', 'LC_ALL=C', 'qemu-img', 'info', self.TEST_DEV_PATH,
            run_as_root=True)

        if has_qemu:
            test_qemu_img.AndReturn((TEST_INFO, 'ignored'))
            image_utils.fetch(context, self._image_service, self.TEST_IMAGE_ID,
                              self.TEST_DEV_PATH, None, None)
        else:
            test_qemu_img.AndRaise(processutils.ProcessExecutionError())

        if has_qemu and src_inf:
            utils.execute(
                'env', 'LC_ALL=C', 'qemu-img', 'info',
                self.TEST_DEV_PATH, run_as_root=True).AndReturn(
                    (src_inf, 'ignored'))

        if has_qemu and dest_inf:
            if bps_limit:
                prefix = ('cgexec', '-g', 'blkio:test')
            else:
                prefix = ()

            utils.execute('dd', 'count=0', 'if=/dev/ether/fake_dev',
                          'of=/dev/ether/fake_dev', 'oflag=direct',
                          run_as_root=True)

            cmd = prefix + ('qemu-img', 'convert', '-t', 'none', '-O', 'raw',
                            self.TEST_DEV_PATH, self.TEST_DEV_PATH)

            volume_utils.setup_blkio_cgroup(
                self.TEST_DEV_PATH, self.TEST_DEV_PATH,
                bps_limit).AndReturn(prefix)

            utils.execute(*cmd, run_as_root=True)

            utils.execute(
                'env', 'LC_ALL=C', 'qemu-img', 'info',
                self.TEST_DEV_PATH, run_as_root=True).AndReturn(
                    (dest_inf, 'ignored'))

        self._mox.ReplayAll()
 def test_fail_is_blk_device(self, mock_os_stat, mock_S_ISBLK):
     dev = 'device_exception'
     self.assertFalse(utils.is_blk_device(dev))
 def test_not_is_blk_device(self, mock_os_stat, mock_S_ISBLK):
     dev = 'not_some_device'
     self.assertFalse(utils.is_blk_device(dev))
 def test_is_blk_device(self, mock_os_stat, mock_S_ISBLK):
     dev = 'some_device'
     self.assertTrue(utils.is_blk_device(dev))