1. 虚拟机镜像的创建和resize流程

nova创建虚拟机涉及的组件比较多,调用比较复杂,这里只列出跟虚拟机镜像创建相关的流程,方便理清虚拟机状态变化的整个流程。

nova-api

nova.api.openstack.compute.servers.ServersController.create() # 接受创建请求,解析出image_uuid
nova.compute.api.API.create ()
nova.compute.api.API._create_instance() # 调用glance api获取image对象
nova.conductor.api.LocalComputeTaskAPI.build_instances()
nova.conductor.manager.ConductorManager.build_instances() # 此处虽然接收block_device_mapping参数,但是是为了兼容旧版,没有使用。实际通过nova.objects.BlockDeviceMappingList.get_by_instance_uuid()获取
nova.compute.rpcapi.ComputeAPI.build_and_run_instance() # 使用cast方法调用nova-compute的build_and_run_instance方法。

nova-compute

nova.compute.manager.ComputeManager.build_and_run_instance()
nova.compute.manager.ComputeManager._do_build_and_run_instance()
nova.compute.manager.ComputeManager._build_and_run_instance() nova.compute.manager.ComputeManager._build_resources()
nova.compute.manager.ComputeManager._prep_block_device()
nova.virt.block_device.attach_block_devices()
nova.virt.block_device.DriverImageBlockDevice.attach()
nova.volume.cinder.API.create() nova.virt.libvirt.driver.LibvirtDriver.spwan()
nova.virt.libvirt.driver.LibvirtDriver._create_image() # 此处会判断如果不是从volume启动,则调用imagebackend去创建虚拟机镜像
nova.virt.libvirt.driver.LibvirtDriver._try_fetch_image_cache()
nova.virt.libvirt.imagebackend.Image.cache() nova.virt.libvirt.imagebackend.Rbd.create_image()
nova.virt.libvirt.imagebackend.Rbd.clone()
nova.virt.libvirt.storage.rbd_utils.RBDDriver.clone() # 创建虚拟机镜像,此处如果所使用的image后端不支持clone,或者镜像不可clone(比如rbd中不是raw格式的镜像),会触发异常,create_image调用下面的fetch_image函数 nova.virt.libvirt.utils.fetch_image()
nova.virt.images.fetch_to_raw()
nova.virt.images.fetch()
nova.image.API.download()
nova.virt.images.convert_image()
nova.virt.images._convert_image() # 将镜像拷贝到本地的/var/lib/instances/_base/目录下,文件名为md5(image).part,然后用qemu-img convert转换为raw格式,名为md5(image).converted,最后重命名为md5(image)
nova.virt.libvirt.storage.rbd_utils.RBDDriver.import_image() # 这一步是在clone失败,执行fetch_image的情况下,判断虚拟机镜像不存在,执行import_image将fetch的镜像导入到RBD后端作为虚拟机镜像。 nova.virt.libvirt.storage.rbd_utils.RBDDriver.resize() # 调整虚拟机镜像大小 nova.virt.libvirt.imagebackend.Rbd.resize_image() # 调整虚拟机镜像大小,RBD后端实际上在create_image时已经resize了,不会执行这一步,这里应该是为了确保其他后端能够正确设置虚拟机镜像的大小

为了便于分析,用graphviz画了在nova-compute的调用关系图:

注:存储后端用的是Ceph,所以调用的后端代码是nova.virt.libvirt.imagebackend.Rbd,如果nova使用了不同的后端,比如本地的qcow2镜像、raw镜像、lvm等,只需要对照nova.virt.libvirt.imagebackend中提供的对应实现,出入不会太大,因为它们都继承nova.virt.libvirt.imagebackend.Image,有相同的接口。

至此,虚拟机的镜像已经创建完毕,并且resize为flavor所设置的大小。后面是虚拟机启动后,resize分区和文件系统的过程。

一般虚拟机镜像中会安装cloud-init或者配置启动脚本来对虚拟机做初始化配置。在cloud-init或启动脚本中调用growpart和resizefs来完成分区和文件系统的扩容。

2. 分区的resize

cloud-init支持使用growpart和gpart对分区进行扩容,时配置的mode而定,默认会按顺序检测系统中是否安装了这两个工具,使用第一个找到的。

growpart是AWS的扩展分区工具,它分别使用sfdisk和sgdisk对MBR和GPT分区表操作,先将分区表导出,然后改写分区的其实扇区位置,最后将改写后的分区表导入,完成分区的扩容。

# growpart [diskdev] [partnum]

gpart是FreeBSD推出的磁盘管理工具,GPT分区表将metadata的主本保存在硬盘的开始,将副本保存在硬盘的末尾,所以当虚拟机镜像被扩容,相当于硬盘的容量变大,在GPT看来末尾的metadata副本丢失了,需要先执行recover命令恢复,然后再进行扩容。

# gpart recover [diskdev]
# gpart resize -i [partnum] [diskdev]

3. 文件系统的resize

cloud-init通过依次尝试解析/proc/$$/mountinfo、/etc/mtab和mount命令的输出,来获取根目录所挂载的分区和文件系统格式。

针对不通的文件系统,使用不同的命令扩容:

# resize2fs [devpth]    # ext文件系统
# xfs_growfs [devpth] # xfs文件系统
# growfs [devpth] # ufs文件系统
# btrfs filesystem resize max [mount_point] # btrfs文件系统

nova虚拟机镜像从创建到文件系统resize完整流程的更多相关文章

  1. 在 Windows Azure 上部署并定制化 FreeBSD 虚拟机镜像

     发布于 2014-12-11 作者 陈阳 FreeBSD 基础镜像现已登陆中国的 VM Depot! 对于青睐 BSD 而非 Linux 的开源爱好者来说,这无疑是个好消息.同时,随着该基础镜像 ...

  2. 如何快捷地修改虚拟机镜像——libguestfs-tools工具集介绍

    前言 在使用云服务器产品时,由于问题修复.功能添加.软件更新等原因,往往需要对已有系统镜像进行二次修改. 这种情况下,最为简单的做法是:使用原镜像创建实例,在实例中进行修改,修改完毕后再转镜像.这种做 ...

  3. 修改kvm虚拟机镜像大小

    修改虚拟机镜像大小(qcow2/raw resize) 创建一个镜像文件,大小1G taw muxueqz@muxueqz /tmp $ qemu-img create -f raw t.raw 1G ...

  4. (转)使用qemu-img管理虚拟机磁盘镜像(创建虚拟机,虚拟机快照)

    转自:http://blog.csdn.net/bravezhe/article/details/8461386 一台虚拟机的核心就是一个磁盘镜像,这个镜像可以理解成虚拟机的磁盘,里面有虚拟机的操作系 ...

  5. Jexus Web Server 完全傻瓜化图文配置教程(基于Ubuntu 12.04.3 64位)[内含Hyper-v 2012虚拟机镜像下载地址]

    1. 前言 近日有感许多新朋友想尝试使用Jexus,不过绝大多数都困惑徘徊在Linux如何安装啊,如何编译Mono啊,如何配置Jexus啊...等等基础问题,于是昨日向宇内流云兄提议,不如搞几个配置好 ...

  6. 世纪互联运营的Microsoft Azure正式支持FreeBSD虚拟机镜像

    自2012年开始,微软云计算与企业事业部和Citrix思杰,NetApp达成合作,共同开发出第一版针对Hyper-V虚拟设备驱动以及相关的用户态程序,并将此称之为集成服务(Integration Se ...

  7. 教程:在 VM Depot 中查找 Azure 可用的虚拟机镜像

     发布于 2014-07-08 作者 陈 忠岳 对于 Azure 的社区管理虚拟机资源库--VM Depot--的用户来说,网站的搜索功能已得到极大的改善.这一搜索能力的增强,可以帮助用户更容易地 ...

  8. docker镜像的创建commit及dockerfile

    在docker 1.3版本以前使用attach进入容器会经常出现卡死的情况,之后官方退出了exec命令,从宿主机进入,但是从其他远程主机进入使用ssh服务来维护是用户熟悉的方法.所以这里来创建一个带有 ...

  9. 宿主机mount虚拟机镜像文件

    转载 mount挂载虚拟机镜像文件 使用mount挂载ubuntu虚拟机所在的img文件的时候,执行: “sudo mount -o loop xxx.img /mnt/xxx”, 系统提示: “mo ...

随机推荐

  1. oracle查询语句大全 oracle 基本命令大全

    oracle查询语句大全 oracle 基本命令大全 来源于:http://download.csdn.net/download/jia584643753/5875619 1.create user ...

  2. 牛客网Java刷题知识点之什么是代码块、普通代码块、静态代码块、同步代码块、构造代码块以及执行顺序

    不多说,直接上干货! 这种形式的程序段我们将其称之为代码块,所谓代码块就是用大括号({})将多行代码封装在一起,形成一个独立的数据体,用于实现特定的算法.一般来说代码块是不能单独运行的,它必须要有运行 ...

  3. nginx的配置文件server_name的意义 location意义

    配置不同的域名      不同域名都可以有首地址 location   同一域名下   分发到不同的路径   或者项目

  4. Nuxt使用记录

    代码及插件需要根据环境引入 (服务端没有window,document,浏览器端没有global) const myPlugins = { install(Vue, options) { Vue.pr ...

  5. 重写FileUpload控件让它可以显示上传后的文件名

    我在以前的开发中经常遇到这样的场景:文件上传之后需要显示文件名,但是asp.net自带的fileupload是不能付给上传后的文件名值的. 以前都是做一个label显示的,今天想起来了,写个控件封装一 ...

  6. webpack.config.js====webpack-dev-server开发服务器配置

    1. 安装webpack-dev-server(在指定目录下),一定要先安装完毕webpack webpack-cli之后在安装webpack-dev-server 一个基于expressjs的开发服 ...

  7. keil下JLINK在线调试仿真设置,SWD连接

    keil下JLINK在线调试仿真设置,以下三个步骤搞定: 有时我们编译时会遇到空间不足的情况,首先我们应该把 flash和RAM的size 设置为当前所用芯片的大小,如下我使用了一个片上flash 2 ...

  8. Ubuntu 自动获取ip地址

    $ sudo dhclient -r               //release ip 释放IP$ sudo dhclient                  //获取IP手動使用 DHCP 自 ...

  9. 在SharePoint Online或SharePoint本地列表中缺少功能区

    您可能会遇到在SharePoint Online或SharePoint内部部署列表中看不到功能区的情况.功能区可以轻松访问SharePoint列表中的常见任务.它还提供了有用的工具,例如连接到Outl ...

  10. Windows UEFI 安装策略的一个细节

    在计算机已连接任何带Windows Boot Manager的硬盘的时候,系统自己不会创建EFI分区,而是用之前的