nova 创建qcow2的kernel image的过程

来源:互联网 发布:eclipse端口号在哪改 编辑:程序博客网 时间:2024/06/08 17:34
最终调用nova/virt/libvirt/driver.py 中的spawn来创建虚拟机    def spawn(self, context, instance, image_meta, injected_files,              admin_password, network_info=None, block_device_info=None):        disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,                                            instance,                                            image_meta,                                            block_device_info)        gen_confdrive = functools.partial(self._create_configdrive,                                          context, instance,                                          admin_pass=admin_password,                                          files=injected_files,                                          network_info=network_info)这里有调用_create_image        self._create_image(context, instance,                           disk_info['mapping'],                           network_info=network_info,                           block_device_info=block_device_info,                           files=injected_files,                           admin_pass=admin_password)_create_image 源码如下:    def _create_image(self, context, instance,                      disk_mapping, suffix='',                      disk_images=None, network_info=None,                      block_device_info=None, files=None,                      admin_pass=None, inject_files=True,                      fallback_from_host=None):        booted_from_volume = self._is_booted_from_volume(            instance, disk_mapping)        def image(fname, image_type=CONF.libvirt.images_type):            return self.image_backend.image(instance,                                            fname + suffix, image_type)        def raw(fname):            return image(fname, image_type='raw')        # ensure directories exist and are writable        fileutils.ensure_tree(libvirt_utils.get_instance_path(instance))        LOG.info(_LI('Creating image'), instance=instance)        if not disk_images:            disk_images = {'image_id': instance.image_ref,                           'kernel_id': instance.kernel_id,                           'ramdisk_id': instance.ramdisk_id}        if disk_images['kernel_id']:            fname = imagecache.get_cache_fname(disk_images['kernel_id'])            raw('kernel').cache(fetch_func=libvirt_utils.fetch_raw_image,                                context=context,                                filename=fname,                                image_id=disk_images['kernel_id'])可以看到_create_image 中最终调用raw('kernel').cache 来创建kennel镜像,而raw函数调用image。所以最终调用image.cache 来创建kernel镜像,image定义如下:def image(fname, image_type=CONF.libvirt.images_type):            return self.image_backend.image(instance,                                            fname + suffix, image_type)可见最终调用mage_backend.image。其源码路径为nova/virt/libvirt/imagebackend.py   def cache(self, fetch_func, filename, size=None, *args, **kwargs):        """Creates image from template.        Ensures that template and image not already exists.        Ensures that base directory exists.        Synchronizes on template fetching.        :fetch_func: Function that creates the base image                     Should accept `target` argument.        :filename: Name of the file in the image directory        :size: Size of created image in bytes (optional)        """        @utils.synchronized(filename, external=True, lock_path=self.lock_path)        def fetch_func_sync(target, *args, **kwargs):            # The image may have been fetched while a subsequent            # call was waiting to obtain the lock.            if not os.path.exists(target):                fetch_func(target=target, *args, **kwargs)        base_dir = os.path.join(CONF.instances_path,                                CONF.image_cache_subdirectory_name)//获取kernel镜像        if not os.path.exists(base_dir):            fileutils.ensure_tree(base_dir)        base = os.path.join(base_dir, filename)//如果镜像不存在则调用create_image 来创建kernel镜像        if not self.exists() or not os.path.exists(base):            self.create_image(fetch_func_sync, base, size,                              *args, **kwargs)由于建立的kernel镜像为qcow2格式,因此create_image实现在qcow2中class Qcow2(Image):    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.//qcow2镜像的制作必须有个base,如果没有base的话,要通过prepare_template来下载base        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.        libvirt_utils.update_mtime(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.有base后通过copy_qcow2_image创建qcow2镜像         if not os.path.exists(self.path):            with fileutils.remove_path_on_error(self.path):                copy_qcow2_image(base, self.path, size)这里的prepare_template是create_image的第二个参数,往上回溯可以发现这个函数其实为            self.create_image(fetch_func_sync, base, size,                              *args, **kwargs)原来就是fetch_func_sync        def fetch_func_sync(target, *args, **kwargs):            # The image may have been fetched while a subsequent            # call was waiting to obtain the lock.            if not os.path.exists(target):                fetch_func(target=target, *args, **kwargs)这里有调用函数指针fetch_func,继续回溯raw('kernel').cache(fetch_func=libvirt_utils.fetch_raw_image,                                context=context,                                filename=fname,                                image_id=disk_images['kernel_id'])原来最终调用libvirt_utils.fetch_raw_image 来下载base镜像,其源码在libvirt/utils.py def fetch_raw_image(context, target, image_id):    """Grab initrd or kernel image.    This function does not attempt raw conversion, as these images will    already be in raw format.    """    images.fetch(context, image_id, target)原来又是调用image.fetch.其源码在virtt/image.py中def fetch(context, image_href, path):    with fileutils.remove_path_on_error(path):        IMAGE_API.download(context, image_href, dest_path=path)这个download 的函数最终在nova/image/glance.py 中实现。重点是知道这里是通过glance下载的base镜像就行了回到Qcow2类的create_image函数中,下载base镜像后还要通过copy_qcow2_image创建qcow2镜像.其源码在libvirt/utils.py中def create_cow_image(backing_file, path, size=None):    """Create COW image    Creates a COW image with the given backing file构建命令创建qcow2镜像    :param backing_file: Existing image on which to base the COW image    :param path: Desired location of the COW image    """    base_cmd = ['qemu-img', 'create', '-f', 'qcow2']    cow_opts = []    if backing_file:        cow_opts += ['backing_file=%s' % backing_file]        base_details = images.qemu_img_info(backing_file)    else:        base_details = None    # Explicitly inherit the value of 'cluster_size' property of a qcow2    # overlay image from its backing file. This can be useful in cases    # when people create a base image with a non-default 'cluster_size'    # value or cases when images were created with very old QEMU    # versions which had a different default 'cluster_size'.    if base_details and base_details.cluster_size is not None:        cow_opts += ['cluster_size=%s' % base_details.cluster_size]    if size is not None:        cow_opts += ['size=%s' % size]    if cow_opts:        # Format as a comma separated list        csv_opts = ",".join(cow_opts)        cow_opts = ['-o', csv_opts]    cmd = base_cmd + cow_opts + [path]执行命令    execute(*cmd)

原创粉丝点击