Beispiel #1
0
 def _create_image(context, instance, image_id):
     """Fetch image from glance and copy it to the remote system."""
     try:
         file_name = '.'.join([image_id, 'gz'])
         file_path = os.path.join(FLAGS.powervm_img_local_path,
                                  file_name)
         LOG.debug(_("Fetching image '%s' from glance") % image_id)
         images.fetch_to_raw(context,
                             image_id,
                             file_path,
                             instance['user_id'],
                             project_id=instance['project_id'])
         LOG.debug(_("Copying image '%s' to IVM") % file_path)
         remote_path = FLAGS.powervm_img_remote_path
         remote_file_name, size = self._operator.copy_image_file(
             file_path, remote_path)
         # Logical volume
         LOG.debug(_("Creating logical volume"))
         lpar_id = self._operator.get_lpar(instance['name'])['lpar_id']
         vhost = self._operator.get_vhost_by_instance_id(lpar_id)
         disk_name = self._operator.create_logical_volume(size)
         self._operator.attach_disk_to_vhost(disk_name, vhost)
         LOG.debug(_("Copying image to the device '%s'") % disk_name)
         self._operator.copy_file_to_device(remote_file_name, disk_name)
     except Exception, e:
         LOG.exception(_("PowerVM image creation failed: %s") % str(e))
         raise exception.PowerVMImageCreationFailed()
Beispiel #2
0
 def _create_image(context, instance, image_id):
     """Fetch image from glance and copy it to the remote system."""
     try:
         file_name = '.'.join([image_id, 'gz'])
         file_path = os.path.join(FLAGS.powervm_img_local_path,
                                  file_name)
         LOG.debug(_("Fetching image '%s' from glance") % image_id)
         images.fetch_to_raw(context, image_id, file_path,
                             instance['user_id'],
                             project_id=instance['project_id'])
         LOG.debug(_("Copying image '%s' to IVM") % file_path)
         remote_path = FLAGS.powervm_img_remote_path
         remote_file_name, size = self._operator.copy_image_file(
                                                 file_path, remote_path)
         # Logical volume
         LOG.debug(_("Creating logical volume"))
         lpar_id = self._operator.get_lpar(instance['name'])['lpar_id']
         vhost = self._operator.get_vhost_by_instance_id(lpar_id)
         disk_name = self._operator.create_logical_volume(size)
         self._operator.attach_disk_to_vhost(disk_name, vhost)
         LOG.debug(_("Copying image to the device '%s'") % disk_name)
         self._operator.copy_file_to_device(remote_file_name, disk_name)
     except Exception, e:
         LOG.exception(_("PowerVM image creation failed: %s") % str(e))
         raise exception.PowerVMImageCreationFailed()
Beispiel #3
0
 def ensure_created(self):
     self.image_temp_target = "/tmp/%s-tmp-img" % self.image_uuid
     if not self.check_image_exists_locally():
         LOG.debug("Fetching image from glance")
         images.fetch_to_raw(self.context, self.image_uuid,
             self.image_temp_target, self.user_id, self.tenant_id)
         self.register_image()
Beispiel #4
0
def fetch_image(context, target, image_id, user_id, project_id, max_size=0):
    """Grab image."""
    images.fetch_to_raw(context,
                        image_id,
                        target,
                        user_id,
                        project_id,
                        max_size=max_size)
Beispiel #5
0
def fetch_image(context, target, image_id, trusted_certs=None):
    """Grab image.

    :param context: nova.context.RequestContext auth request context
    :param target: target path to put the image
    :param image_id: id of the image to fetch
    :param trusted_certs: optional objects.TrustedCerts for image validation
    """
    images.fetch_to_raw(context, image_id, target, trusted_certs)
 def _setup_image(self, context, instance):
     base_dir = os.path.join(FLAGS.instances_path, FLAGS.base_dir_name)
     if not os.path.exists(base_dir):
         ensure_tree(base_dir)
     path = os.path.abspath(os.path.join(base_dir, instance["image_ref"]))
     if not os.path.exists(path):
         images.fetch_to_raw(context, instance["image_ref"], path,
                             instance["user_id"], instance["project_id"])
     return path
Beispiel #7
0
def fetch_image(context, target, image_id, trusted_certs=None):
    """Grab image.

    :param context: nova.context.RequestContext auth request context
    :param target: target path to put the image
    :param image_id: id of the image to fetch
    :param trusted_certs: optional objects.TrustedCerts for image validation
    """
    images.fetch_to_raw(context, image_id, target, trusted_certs)
 def _setup_image(self, context, instance):
     base_dir = os.path.join(FLAGS.instances_path, FLAGS.base_dir_name)
     if not os.path.exists(base_dir):
         ensure_tree(base_dir)
     path = os.path.abspath(os.path.join(base_dir, instance["image_ref"]))
     if not os.path.exists(path):
         images.fetch_to_raw(
             context, instance["image_ref"], path,
             instance["user_id"], instance["project_id"])
     return path
Beispiel #9
0
def fetch_image(context, target, image_id, user_id, project_id, max_size=0):
    """Grab image."""
    LOG.info("libvirt.utils.fetch.image.start")
    images.fetch_to_raw(context,
                        image_id,
                        target,
                        user_id,
                        project_id,
                        max_size=max_size)
    LOG.info("libvirt.utils.fetch.image.end")
Beispiel #10
0
    def create_volume_from_image(self, context, instance, image_id):
        """Creates a Logical Volume and copies the specified image to it

        :param context: nova context used to retrieve image from glance
        :param instance: instance to create the volume for
        :param image_id: image_id reference used to locate image in glance
        :returns: dictionary with the name of the created
                  Logical Volume device in 'device_name' key
        """

        file_name = '.'.join([image_id, 'gz'])
        file_path = os.path.join(CONF.powervm_img_local_path, file_name)

        if not os.path.isfile(file_path):
            LOG.debug(_("Fetching image '%s' from glance") % image_id)
            images.fetch_to_raw(context,
                                image_id,
                                file_path,
                                instance['user_id'],
                                project_id=instance['project_id'])
        else:
            LOG.debug((_("Using image found at '%s'") % file_path))

        LOG.debug(_("Ensuring image '%s' exists on IVM") % file_path)
        remote_path = CONF.powervm_img_remote_path
        remote_file_name, size = self._copy_image_file(file_path, remote_path)

        # calculate root device size in bytes
        # we respect the minimum root device size in constants
        size_gb = max(instance['instance_type']['root_gb'],
                      constants.POWERVM_MIN_ROOT_GB)
        size = size_gb * 1024 * 1024 * 1024

        try:
            LOG.debug(_("Creating logical volume of size %s bytes") % size)
            disk_name = self._create_logical_volume(size)

            LOG.debug(_("Copying image to the device '%s'") % disk_name)
            self._copy_file_to_device(remote_file_name, disk_name)
        except Exception:
            LOG.error(
                _("Error while creating logical volume from image. "
                  "Will attempt cleanup."))
            # attempt cleanup of logical volume before re-raising exception
            with excutils.save_and_reraise_exception():
                try:
                    self.delete_volume(disk_name)
                except Exception:
                    msg = _('Error while attempting cleanup of failed '
                            'deploy to logical volume.')
                    LOG.exception(msg)

        return {'device_name': disk_name}
Beispiel #11
0
    def test_fetch_image(self):
        self.mox.StubOutWithMock(images, "fetch_to_raw")

        context = "opaque context"
        target = "/tmp/targetfile"
        image_id = "4"
        user_id = "fake"
        project_id = "fake"
        images.fetch_to_raw(context, image_id, target, user_id, project_id, max_size=0)

        self.mox.ReplayAll()
        libvirt_utils.fetch_image(context, target, image_id, user_id, project_id)
Beispiel #12
0
def fetch_image(context, target, image_id, user_id, project_id, max_size=0):
    """Grab image."""
    path_dir = os.path.dirname(target)
    
    (image_service, image_id) = glance.get_remote_image_service(context, image_id)
    image = image_service.show(context, image_id)
    parent_id = image.get('parent_id', None)
    
    if parent_id is None:
        images.fetch_to_raw(context, image_id, target, user_id, project_id,
                             max_size, False)
    else:
        images.fetch_with_backing_file(context, image_id, target, path_dir, user_id, project_id, max_size)
Beispiel #13
0
    def create_volume_from_image(self, context, instance, image_id):
        """Creates a Logical Volume and copies the specified image to it

        :param context: nova context used to retrieve image from glance
        :param instance: instance to create the volume for
        :param image_id: image_id reference used to locate image in glance
        :returns: dictionary with the name of the created
                  Logical Volume device in 'device_name' key
        """

        file_name = '.'.join([image_id, 'gz'])
        file_path = os.path.join(CONF.powervm_img_local_path,
                                 file_name)

        if not os.path.isfile(file_path):
            LOG.debug(_("Fetching image '%s' from glance") % image_id)
            images.fetch_to_raw(context, image_id, file_path,
                                instance['user_id'],
                                project_id=instance['project_id'])
        else:
            LOG.debug((_("Using image found at '%s'") % file_path))

        LOG.debug(_("Ensuring image '%s' exists on IVM") % file_path)
        remote_path = CONF.powervm_img_remote_path
        remote_file_name, size = self._copy_image_file(file_path, remote_path)

        # calculate root device size in bytes
        # we respect the minimum root device size in constants
        size_gb = max(instance['instance_type']['root_gb'],
                      constants.POWERVM_MIN_ROOT_GB)
        size = size_gb * 1024 * 1024 * 1024

        try:
            LOG.debug(_("Creating logical volume of size %s bytes") % size)
            disk_name = self._create_logical_volume(size)

            LOG.debug(_("Copying image to the device '%s'") % disk_name)
            self._copy_file_to_device(remote_file_name, disk_name)
        except Exception:
            LOG.error(_("Error while creating logical volume from image. "
                        "Will attempt cleanup."))
            # attempt cleanup of logical volume before re-raising exception
            with excutils.save_and_reraise_exception():
                try:
                    self.delete_volume(disk_name)
                except Exception:
                    msg = _('Error while attempting cleanup of failed '
                            'deploy to logical volume.')
                    LOG.exception(msg)

        return {'device_name': disk_name}
Beispiel #14
0
def fetch_image(context,
                target,
                image_id,
                user_id,
                project_id,
                max_size=0,
                backend=None):
    """Grab image."""
    images.fetch_to_raw(context,
                        image_id,
                        target,
                        user_id,
                        project_id,
                        max_size=max_size,
                        backend=backend)
Beispiel #15
0
def fetch_image(context, instance, image_meta, container_image):
    """Fetch the image from a glance image server."""
    LOG.debug("Downloading image from glance")

    base_dir = os.path.join(CONF.instances_path,
                            CONF.image_cache_subdirectory_name)
    if not os.path.exists(base_dir):
        fileutils.ensure_tree(base_dir)
    base = os.path.join(base_dir, container_image)
    if not os.path.exists(base):
        images.fetch_to_raw(context, instance['image_ref'], base,
                            instance['user_id'], instance['project_id'])
    if not tarfile.is_tarfile(base):
        os.unlink(base)
        raise exception.InvalidDiskFormat(
            disk_format=container_utils.get_disk_format(image_meta))
Beispiel #16
0
    def test_fetch_image(self):
        self.mox.StubOutWithMock(images, 'fetch_to_raw')

        context = 'opaque context'
        target = '/tmp/targetfile'
        image_id = '4'
        user_id = 'fake'
        project_id = 'fake'
        images.fetch_to_raw(context,
                            image_id,
                            target,
                            user_id,
                            project_id,
                            max_size=0)

        self.mox.ReplayAll()
        libvirt_utils.fetch_image(context, target, image_id, user_id,
                                  project_id)
Beispiel #17
0
def _fetch_image(context, instance, image_meta, container_image, idmap,
                 flavor):
    """Fetch the image from a glance image server."""
    LOG.debug("Downloading image from glance")

    base_dir = os.path.join(CONF.instances_path,
                            CONF.image_cache_subdirectory_name)
    image_dir = os.path.join(base_dir, instance['image_ref'])
    if not os.path.exists(base_dir):
        fileutils.ensure_tree(base_dir)
    base = os.path.join(base_dir, container_image)
    if not os.path.exists(base):
        images.fetch_to_raw(context, instance['image_ref'], base,
                            instance['user_id'], instance['project_id'])
        if not tarfile.is_tarfile(base):
            os.unlink(base)
            raise exeception.InvalidDiskFormat(
                disk_format=container_utils.get_disk_format(image_meta))

    if not os.path.exists(image_dir):
        (user, group) = idmap.get_user()
        utils.execute('btrfs', 'sub', 'create', image_dir)

        utils.execute('chown',
                      '%s:%s' % (user, group),
                      image_dir,
                      run_as_root=True)

        tar = [
            'tar', '--directory', image_dir, '--anchored', '--numeric-owner',
            '-xpzf', base
        ]
        nsexec = (['lxc-usernsexec'] +
                  idmap.usernsexec_margs(with_read="user") + ['--'])

        args = tuple(nsexec + tar)
        utils.execute(*args, check_exit_code=[0, 2])
        utils.execute(*tuple(nsexec + ['chown', '0:0', image_dir]))
Beispiel #18
0
def _fetch_image(
        context, instance, image_meta, container_image, idmap, flavor):
    """Fetch the image from a glance image server."""
    LOG.debug("Downloading image from glance")

    base_dir = os.path.join(CONF.instances_path,
                            CONF.image_cache_subdirectory_name)
    image_dir = os.path.join(base_dir, instance['image_ref'])
    if not os.path.exists(base_dir):
        fileutils.ensure_tree(base_dir)
    base = os.path.join(base_dir, container_image)
    if not os.path.exists(base):
        images.fetch_to_raw(context, instance['image_ref'], base,
                            instance['user_id'], instance['project_id'])
        if not tarfile.is_tarfile(base):
            os.unlink(base)
            raise exception.InvalidDiskFormat(
                disk_format=container_utils.get_disk_format(image_meta))

    if not os.path.exists(image_dir):
        (user, group) = idmap.get_user()
        utils.execute('btrfs', 'sub', 'create', image_dir)

        utils.execute(
            'chown', '%s:%s' %
            (user, group), image_dir, run_as_root=True)

        tar = ['tar', '--directory', image_dir,
               '--anchored', '--numeric-owner', '-xpzf', base]
        nsexec = (['lxc-usernsexec'] +
                  idmap.usernsexec_margs(with_read="user") +
                  ['--'])

        args = tuple(nsexec + tar)
        utils.execute(*args, check_exit_code=[0, 2])
        utils.execute(*tuple(nsexec + ['chown', '0:0', image_dir]))
Beispiel #19
0
def fetch_image(context, target, image_id, user_id, project_id):
    """Grab image"""
    images.fetch_to_raw(context, image_id, target, user_id, project_id)
Beispiel #20
0
def fetch_image(context, target, image_id, user_id, project_id,
                max_size=0, imagehandler_args=None):
    """Grab image."""
    images.fetch_to_raw(context, image_id, target, user_id, project_id,
                        max_size=max_size, imagehandler_args=imagehandler_args)
Beispiel #21
0
def fetch_image(context, target, image_id, user_id, project_id, max_size=0,
                backend=None):
    """Grab image."""
    images.fetch_to_raw(context, image_id, target, user_id, project_id,
                        max_size=max_size, backend=backend)
Beispiel #22
0
def fetch_image(context, target, image_id, user_id, project_id):
    """Grab image"""
    images.fetch_to_raw(context, image_id, target, user_id, project_id)
Beispiel #23
0
    def test_fetch_raw_image(self, mock_convert_image, mock_direct_io,
                             mock_disk_op_sema):

        def fake_rename(old, new):
            self.executes.append(('mv', old, new))

        def fake_unlink(path):
            self.executes.append(('rm', path))

        def fake_rm_on_error(path, remove=None):
            self.executes.append(('rm', '-f', path))

        def fake_qemu_img_info(path):
            class FakeImgInfo(object):
                pass

            file_format = path.split('.')[-1]
            if file_format == 'part':
                file_format = path.split('.')[-2]
            elif file_format == 'converted':
                file_format = 'raw'

            if 'backing' in path:
                backing_file = 'backing'
            else:
                backing_file = None

            FakeImgInfo.file_format = file_format
            FakeImgInfo.backing_file = backing_file
            FakeImgInfo.virtual_size = 1

            return FakeImgInfo()

        self.stub_out('os.rename', fake_rename)
        self.stub_out('os.unlink', fake_unlink)
        self.stub_out('nova.virt.images.fetch', lambda *_, **__: None)
        self.stub_out('nova.virt.images.qemu_img_info', fake_qemu_img_info)
        self.stub_out('oslo_utils.fileutils.delete_if_exists',
                      fake_rm_on_error)

        # Since the remove param of fileutils.remove_path_on_error()
        # is initialized at load time, we must provide a wrapper
        # that explicitly resets it to our fake delete_if_exists()
        old_rm_path_on_error = fileutils.remove_path_on_error
        f = functools.partial(old_rm_path_on_error, remove=fake_rm_on_error)
        self.stub_out('oslo_utils.fileutils.remove_path_on_error', f)

        context = 'opaque context'
        image_id = '4'

        target = 't.qcow2'
        self.executes = []
        expected_commands = [('rm', 't.qcow2.part'),
                             ('mv', 't.qcow2.converted', 't.qcow2')]
        images.fetch_to_raw(context, image_id, target)
        self.assertEqual(self.executes, expected_commands)
        mock_disk_op_sema.__enter__.assert_called_once()
        mock_convert_image.assert_called_with(
            't.qcow2.part', 't.qcow2.converted', 'qcow2', 'raw',
            CONF.instances_path)
        mock_convert_image.reset_mock()

        target = 't.raw'
        self.executes = []
        expected_commands = [('mv', 't.raw.part', 't.raw')]
        images.fetch_to_raw(context, image_id, target)
        self.assertEqual(self.executes, expected_commands)
        mock_convert_image.assert_not_called()

        target = 'backing.qcow2'
        self.executes = []
        expected_commands = [('rm', '-f', 'backing.qcow2.part')]
        self.assertRaises(exception.ImageUnacceptable,
                          images.fetch_to_raw, context, image_id, target)
        self.assertEqual(self.executes, expected_commands)
        mock_convert_image.assert_not_called()

        del self.executes
Beispiel #24
0
    def test_fetch_raw_image(self, mock_convert_image, mock_direct_io,
                             mock_disk_op_sema):

        def fake_rename(old, new):
            self.executes.append(('mv', old, new))

        def fake_unlink(path):
            self.executes.append(('rm', path))

        def fake_rm_on_error(path, remove=None):
            self.executes.append(('rm', '-f', path))

        def fake_qemu_img_info(path):
            class FakeImgInfo(object):
                pass

            file_format = path.split('.')[-1]
            if file_format == 'part':
                file_format = path.split('.')[-2]
            elif file_format == 'converted':
                file_format = 'raw'

            if 'backing' in path:
                backing_file = 'backing'
            else:
                backing_file = None

            FakeImgInfo.file_format = file_format
            FakeImgInfo.backing_file = backing_file
            FakeImgInfo.virtual_size = 1

            return FakeImgInfo()

        self.stub_out('os.rename', fake_rename)
        self.stub_out('os.unlink', fake_unlink)
        self.stub_out('nova.virt.images.fetch', lambda *_, **__: None)
        self.stub_out('nova.virt.images.qemu_img_info', fake_qemu_img_info)
        self.stub_out('oslo_utils.fileutils.delete_if_exists',
                      fake_rm_on_error)

        # Since the remove param of fileutils.remove_path_on_error()
        # is initialized at load time, we must provide a wrapper
        # that explicitly resets it to our fake delete_if_exists()
        old_rm_path_on_error = fileutils.remove_path_on_error
        f = functools.partial(old_rm_path_on_error, remove=fake_rm_on_error)
        self.stub_out('oslo_utils.fileutils.remove_path_on_error', f)

        context = 'opaque context'
        image_id = '4'

        target = 't.qcow2'
        self.executes = []
        expected_commands = [('rm', 't.qcow2.part'),
                             ('mv', 't.qcow2.converted', 't.qcow2')]
        images.fetch_to_raw(context, image_id, target)
        self.assertEqual(self.executes, expected_commands)
        mock_disk_op_sema.__enter__.assert_called_once()
        mock_convert_image.assert_called_with(
            't.qcow2.part', 't.qcow2.converted', 'qcow2', 'raw',
            CONF.instances_path, False)
        mock_convert_image.reset_mock()

        target = 't.raw'
        self.executes = []
        expected_commands = [('mv', 't.raw.part', 't.raw')]
        images.fetch_to_raw(context, image_id, target)
        self.assertEqual(self.executes, expected_commands)
        mock_convert_image.assert_not_called()

        target = 'backing.qcow2'
        self.executes = []
        expected_commands = [('rm', '-f', 'backing.qcow2.part')]
        self.assertRaises(exception.ImageUnacceptable,
                          images.fetch_to_raw, context, image_id, target)
        self.assertEqual(self.executes, expected_commands)
        mock_convert_image.assert_not_called()

        del self.executes
Beispiel #25
0
def fetch_image(context, target, image_id):
    """Grab image."""
    images.fetch_to_raw(context, image_id, target)
Beispiel #26
0
    def test_fetch_raw_image(self):
        def fake_execute(*cmd, **kwargs):
            self.executes.append(cmd)
            return None, None

        def fake_rename(old, new):
            self.executes.append(("mv", old, new))

        def fake_unlink(path):
            self.executes.append(("rm", path))

        def fake_rm_on_error(path, remove=None):
            self.executes.append(("rm", "-f", path))

        def fake_qemu_img_info(path):
            class FakeImgInfo(object):
                pass

            file_format = path.split(".")[-1]
            if file_format == "part":
                file_format = path.split(".")[-2]
            elif file_format == "converted":
                file_format = "raw"

            if "backing" in path:
                backing_file = "backing"
            else:
                backing_file = None

            if "big" in path:
                virtual_size = 2
            else:
                virtual_size = 1

            FakeImgInfo.file_format = file_format
            FakeImgInfo.backing_file = backing_file
            FakeImgInfo.virtual_size = virtual_size

            return FakeImgInfo()

        self.stubs.Set(utils, "execute", fake_execute)
        self.stubs.Set(os, "rename", fake_rename)
        self.stubs.Set(os, "unlink", fake_unlink)
        self.stubs.Set(images, "fetch", lambda *_, **__: None)
        self.stubs.Set(images, "qemu_img_info", fake_qemu_img_info)
        self.stubs.Set(fileutils, "delete_if_exists", fake_rm_on_error)

        # Since the remove param of fileutils.remove_path_on_error()
        # is initialized at load time, we must provide a wrapper
        # that explicitly resets it to our fake delete_if_exists()
        old_rm_path_on_error = fileutils.remove_path_on_error
        f = functools.partial(old_rm_path_on_error, remove=fake_rm_on_error)
        self.stubs.Set(fileutils, "remove_path_on_error", f)

        context = "opaque context"
        image_id = "4"
        user_id = "fake"
        project_id = "fake"

        target = "t.qcow2"
        self.executes = []
        expected_commands = [
            ("qemu-img", "convert", "-O", "raw", "t.qcow2.part", "t.qcow2.converted"),
            ("rm", "t.qcow2.part"),
            ("mv", "t.qcow2.converted", "t.qcow2"),
        ]
        images.fetch_to_raw(context, image_id, target, user_id, project_id, max_size=1)
        self.assertEqual(self.executes, expected_commands)

        target = "t.raw"
        self.executes = []
        expected_commands = [("mv", "t.raw.part", "t.raw")]
        images.fetch_to_raw(context, image_id, target, user_id, project_id)
        self.assertEqual(self.executes, expected_commands)

        target = "backing.qcow2"
        self.executes = []
        expected_commands = [("rm", "-f", "backing.qcow2.part")]
        self.assertRaises(
            exception.ImageUnacceptable, images.fetch_to_raw, context, image_id, target, user_id, project_id
        )
        self.assertEqual(self.executes, expected_commands)

        target = "big.qcow2"
        self.executes = []
        expected_commands = [("rm", "-f", "big.qcow2.part")]
        self.assertRaises(
            exception.FlavorDiskTooSmall,
            images.fetch_to_raw,
            context,
            image_id,
            target,
            user_id,
            project_id,
            max_size=1,
        )
        self.assertEqual(self.executes, expected_commands)

        del self.executes
def fetch_image(context, target, image_id, user_id, project_id, max_size=0):
    """Grab image."""
    images.fetch_to_raw(context, image_id, target, user_id, project_id,
                        max_size=max_size)
Beispiel #28
0
def fetch_image(context, target, image_id):
    """Grab image."""
    images.fetch_to_raw(context, image_id, target)
Beispiel #29
0
    def test_fetch_raw_image(self):

        def fake_execute(*cmd, **kwargs):
            self.executes.append(cmd)
            return None, None

        def fake_rename(old, new):
            self.executes.append(('mv', old, new))

        def fake_unlink(path):
            self.executes.append(('rm', path))

        def fake_rm_on_error(path, remove=None):
            self.executes.append(('rm', '-f', path))

        def fake_qemu_img_info(path):
            class FakeImgInfo(object):
                pass

            file_format = path.split('.')[-1]
            if file_format == 'part':
                file_format = path.split('.')[-2]
            elif file_format == 'converted':
                file_format = 'raw'

            if 'backing' in path:
                backing_file = 'backing'
            else:
                backing_file = None

            if 'big' in path:
                virtual_size = 2
            else:
                virtual_size = 1

            FakeImgInfo.file_format = file_format
            FakeImgInfo.backing_file = backing_file
            FakeImgInfo.virtual_size = virtual_size

            return FakeImgInfo()

        self.stubs.Set(utils, 'execute', fake_execute)
        self.stubs.Set(os, 'rename', fake_rename)
        self.stubs.Set(os, 'unlink', fake_unlink)
        self.stubs.Set(images, 'fetch', lambda *_, **__: None)
        self.stubs.Set(images, 'qemu_img_info', fake_qemu_img_info)
        self.stubs.Set(fileutils, 'delete_if_exists', fake_rm_on_error)

        # Since the remove param of fileutils.remove_path_on_error()
        # is initialized at load time, we must provide a wrapper
        # that explicitly resets it to our fake delete_if_exists()
        old_rm_path_on_error = fileutils.remove_path_on_error
        f = functools.partial(old_rm_path_on_error, remove=fake_rm_on_error)
        self.stubs.Set(fileutils, 'remove_path_on_error', f)

        context = 'opaque context'
        image_id = '4'
        user_id = 'fake'
        project_id = 'fake'

        target = 't.qcow2'
        self.executes = []
        expected_commands = [('qemu-img', 'convert', '-O', 'raw',
                              't.qcow2.part', 't.qcow2.converted'),
                             ('rm', 't.qcow2.part'),
                             ('mv', 't.qcow2.converted', 't.qcow2')]
        images.fetch_to_raw(context, image_id, target, user_id, project_id,
                            max_size=1)
        self.assertEqual(self.executes, expected_commands)

        target = 't.raw'
        self.executes = []
        expected_commands = [('mv', 't.raw.part', 't.raw')]
        images.fetch_to_raw(context, image_id, target, user_id, project_id)
        self.assertEqual(self.executes, expected_commands)

        target = 'backing.qcow2'
        self.executes = []
        expected_commands = [('rm', '-f', 'backing.qcow2.part')]
        self.assertRaises(exception.ImageUnacceptable,
                          images.fetch_to_raw,
                          context, image_id, target, user_id, project_id)
        self.assertEqual(self.executes, expected_commands)

        target = 'big.qcow2'
        self.executes = []
        expected_commands = [('rm', '-f', 'big.qcow2.part')]
        self.assertRaises(exception.FlavorDiskTooSmall,
                          images.fetch_to_raw,
                          context, image_id, target, user_id, project_id,
                          max_size=1)
        self.assertEqual(self.executes, expected_commands)

        del self.executes
 def _fetch_image(self, context, target, image_id, user_id, project_id):
     """Grab image and optionally attempt to resize it"""
     images.fetch_to_raw(context, image_id, target, user_id, project_id)