虚拟机的镜像文件主要是指磁盘镜像文件,当然有的还包括ramdisk和kernel镜像来配合磁盘镜像文件使用,这篇文章我们来重点分析一下创建虚拟机磁盘镜像的整个过程。
虚拟机磁盘镜像是虚拟机正常运行不可缺少的镜像文件,它是虚拟机的主磁盘。先来概述一下创建虚拟机磁盘镜像的整个流程:
1. LibvirtDriver类中的_create_img方法,完成虚拟机镜像文件的创建工作的准备工作后,调用Qcow2类的cache方法。
2. Qcow2类的cache方法调用create_image方法,首先检查本地计算节点上是否缓存了虚拟机所需的磁盘镜像文件。如果不存在缓存文件,则调用libvirt_utils包的fetch_image方法从Glance服务器下载。然后,Qcow2类的create_image方法调用copy_qcow2_img方法创建qcow2格式的虚拟机磁盘镜像文件。
3. libvirt_utils包的fetch_image方法调用fetch_to_raw方法。fetch_to_raw方法首先调用fetch方法从Glance服务器上下载镜像文件,然后检查下载的镜像文件格式是否正确,如果下载的不是raw格式,则将其转化为raw格式。
4. Qcow2类的copy_qcow2_img方法通过执行qemu-img命令完成虚拟机磁盘镜像文件的创建,创建的虚拟机磁盘镜像文件会把换成的镜像文件作为baking file。
接着上一篇文章,来分析创建虚拟机镜像文件的代码
class LibvirtDriver(driver.ComputeDriver):
def _create_image(self, context, instance,
disk_mapping, suffix='',
disk_images=None, network_info=None,
block_device_info=None, files=None, admin_pass=None):
#默认的磁盘镜像文件后缀为空
if not suffix:
suffix = ''
...
#创建保存虚拟机磁盘镜像的目录
fileutils.ensure_tree(basepath(suffix='')
...
if not booted_from_volume:
#获取磁盘镜像在本地的文件名
root_fname = imagecache.get_cache_fname(disk_images, 'image_id')
#获取磁盘镜像的大小
size = instance['root_gb'] * 1024 * 1024 * 1024
if size == 0 or suffix == '.rescue':
size = None
#将磁盘镜像保存在本地
image('disk').cache(fetch_func=libvirt_utils.fetch_image,
context=context,
filename=root_fname,
size=size,
image_id=disk_images['image_id'],
user_id=instance['user_id'],
project_id=instance['project_id'])
...
为了便于理解,我们先看一下传入的“instance”变量中保存的是什么?
{'vm_state': 'building', 'availability_zone': None, 'terminated_at': None, 'ephemeral_gb': 0,
'instance_type_id': 4, 'user_data': 'IyEvYmluL2Jhc2gKdXNlcmFkZCAtbSByb290CnBhc3N3ZCByb290IDw8IEVPRgpyb29vdApyb29vdApFT0YKcGFzc3dkIHJvb3QgPDwgRU9GCnJvb290CnJvb290CkVPRgo=',
'vm_mode': None, 'deleted_at': None, 'reservation_id': 'r-ze5a808m', 'id': 70,
'security_groups': [{'project_id': 'e2c96ea3efe0418cb86fef29aabc2725',