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()
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()
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)
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
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
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")
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}
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)
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)
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}
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)
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))
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)
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]))
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]))
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)
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)
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
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
def fetch_image(context, target, image_id): """Grab image.""" images.fetch_to_raw(context, image_id, target)
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 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)