def create_image(self, prepare_template, base, size, *args, **kwargs): filename = self._get_lock_name(base) @utils.synchronized(filename, external=True, lock_path=self.lock_path) def copy_raw_image(base, target, size): libvirt_utils.copy_image(base, target) if size: image = imgmodel.LocalFileImage(target, self.driver_format) disk.extend(image, size) generating = 'image_id' not in kwargs if generating: if not self.exists(): # Generating image in place prepare_template(target=self.path, *args, **kwargs) else: if not os.path.exists(base): prepare_template(target=base, *args, **kwargs) # NOTE(mikal): Update the mtime of the base file so the image # cache manager knows it is in use. dac_admin.utime(base) self.verify_base_size(base, size) if not os.path.exists(self.path): with fileutils.remove_path_on_error(self.path): copy_raw_image(base, self.path, size) self.correct_format()
def create_image(self, prepare_template, base, size, *args, **kwargs): filename = os.path.basename(base) # Copy main file of ploop disk, restore DiskDescriptor.xml for it # and resize if necessary @utils.synchronized(filename, external=True, lock_path=self.lock_path) def _copy_ploop_image(base, target, size): # Ploop disk is a directory with data file(root.hds) and # DiskDescriptor.xml, so create this dir fileutils.ensure_tree(target) image_path = os.path.join(target, "root.hds") libvirt_utils.copy_image(base, image_path) utils.execute('ploop', 'restore-descriptor', '-f', self.pcs_format, target, image_path) if size: self.resize_image(size) # Generating means that we create empty ploop disk generating = 'image_id' not in kwargs remove_func = functools.partial(fileutils.delete_if_exists, remove=shutil.rmtree) if generating: if os.path.exists(self.path): return with fileutils.remove_path_on_error(self.path, remove=remove_func): prepare_template(target=self.path, *args, **kwargs) else: # Create ploop disk from glance image if not os.path.exists(base): prepare_template(target=base, *args, **kwargs) else: # Disk already exists in cache, just update time dac_admin.utime(base) self.verify_base_size(base, size) if os.path.exists(self.path): return # Get format for ploop disk if CONF.force_raw_images: self.pcs_format = "raw" else: image_meta = IMAGE_API.get(kwargs["context"], kwargs["image_id"]) format = image_meta.get("disk_format") if format == "ploop": self.pcs_format = "expanded" elif format == "raw": self.pcs_format = "raw" else: reason = _("Ploop image backend doesn't support images in" " %s format. You should either set" " force_raw_images=True in config or upload an" " image in ploop or raw format.") % format raise exception.ImageUnacceptable( image_id=kwargs["image_id"], reason=reason) with fileutils.remove_path_on_error(self.path, remove=remove_func): _copy_ploop_image(base, self.path, size)
def create_image(self, prepare_template, base, size, *args, **kwargs): filename = self._get_lock_name(base) @utils.synchronized(filename, external=True, lock_path=self.lock_path) def copy_qcow2_image(base, target, size): # TODO(pbrady): Consider copying the cow image here # with preallocation=metadata set for performance reasons. # This would be keyed on a 'preallocate_images' setting. libvirt_utils.create_cow_image(base, target) if size: image = imgmodel.LocalFileImage(target, imgmodel.FORMAT_QCOW2) disk.extend(image, size) # Download the unmodified base image unless we already have a copy. if not os.path.exists(base): prepare_template(target=base, *args, **kwargs) # NOTE(ankit): Update the mtime of the base file so the image # cache manager knows it is in use. dac_admin.utime(base) self.verify_base_size(base, size) legacy_backing_size = None legacy_base = base # Determine whether an existing qcow2 disk uses a legacy backing by # actually looking at the image itself and parsing the output of the # backing file it expects to be using. if os.path.exists(self.path): backing_path = libvirt_utils.get_disk_backing_file(self.path) if backing_path is not None: backing_file = os.path.basename(backing_path) backing_parts = backing_file.rpartition('_') if backing_file != backing_parts[-1] and \ backing_parts[-1].isdigit(): legacy_backing_size = int(backing_parts[-1]) legacy_base += '_%d' % legacy_backing_size legacy_backing_size *= units.Gi # Create the legacy backing file if necessary. if legacy_backing_size: if not os.path.exists(legacy_base): with fileutils.remove_path_on_error(legacy_base): libvirt_utils.copy_image(base, legacy_base) image = imgmodel.LocalFileImage(legacy_base, imgmodel.FORMAT_QCOW2) disk.extend(image, legacy_backing_size) if not os.path.exists(self.path): with fileutils.remove_path_on_error(self.path): copy_qcow2_image(base, self.path, size)
def _age_and_verify_swap_images(self, context, base_dir): LOG.debug('Verify swap images') for ent in self.back_swap_images: base_file = os.path.join(base_dir, ent) if ent in self.used_swap_images and os.path.exists(base_file): dac_admin.utime(base_file) elif self.remove_unused_base_images: self._remove_swap_file(base_file) error_images = self.used_swap_images - self.back_swap_images for error_image in error_images: LOG.warning( '%s swap image was used by instance' ' but no back files existing!', error_image)
def _mark_in_use(self, img_id, base_file): """Mark a single base image as in use.""" LOG.info('image %(id)s at (%(base_file)s): checking', { 'id': img_id, 'base_file': base_file }) if base_file in self.unexplained_images: self.unexplained_images.remove(base_file) self.active_base_files.append(base_file) LOG.debug('image %(id)s at (%(base_file)s): image is in use', { 'id': img_id, 'base_file': base_file }) dac_admin.utime(base_file)