在经过路由、参数解析及访问控制后,我们现在就正式进入 Nova compute 的虚拟机创建 API,即从 nova.api.openstack.compute.servers::ServersController::create() 函数进入到 nova.compute.api::API::create() 函数。
注:本文都是大图长图…
nova.compute.api::API::create()
nova.compute.api::API::create() 函数详细执行过程如下图(图有点大,可右键下载查看):
从上图,我们接下来会分虚拟机调度(schedule instance)及构建和运行虚拟机(build and run instance)两个部分。
虚拟机调度
虚拟机的调度本质上是选出最合适运行该虚拟机的计算节点。调度过程分为两个部分:
- filtering:过滤出符合条件的计算节点
- weighting:在过滤出来的节点中选出最合适的一个
可用图表示如下:
图片来源:OpenStack 官方文档 Compute schedulers
具体的函数执行详细如下(图有点大,可右键下载查看):
虚拟机构建与运行概览
调度完虚拟机后,就要构建与运行(Build and rund)该虚拟机,过程概览图如下:
调用 Libvirt Driver
创建虚拟机的最后一步就是调用 Libvirt Driver 来真正创建虚拟机。具体的执行函数是 nova.virt.libvirt.driver::LibvirtDriver::spawn()。对于这个函数,我们就不一步步分析了,而是采用 Rafi Khardalian 在 OpenStack Summit 演讲中提到的比较清晰的步骤(视频、PPT),摘录如下:
Create disk files (assuming default configuration):
- Download image from Glance into instance_dir/_base and convert it to RAW (unless it already exists)
- Create instance_dir/uuid/{disk, disk.local, disk.swap}
- Create QCOW2 “disk” file, with backing file from the _base image
- Virtual size set in the QCOW2 image if disk size > 0**
- Create QCOW2 “disk.local” and “disk.swap” (use of swap makes me sad)
- Really, don’t use swap in VMs. I’m serious.·
Generate the libvirt XML and write a copy to the instance_dir
- instance_dir/libvirt.xml is never used by Nova
Establish volume connections (for boot-from-volume)
- Operations executed depend on volume driver (examples):
- iSCSI: Connections made via tgt or iscsiadm
- RBD: Generates XML for Libvirt; rest handled within QEMU
Build the supporting network stack for the instance
- Again, specific operations are driver dependent (assume nova-network here)
- Bring up any necessary bridges/VLANs
- Create the security groups (iptables) for the instance
Define the domain with Libvirt, using the XML generated earlier in this process (from memory, not disk)
- Equivalent of ‘virsh define instance_dir/
/libvirt.xml’ Now, actually start the instance
- Equivilent of ‘virsh start
’ or ‘virsh start
另外值得参考的资料: