共计 2520 个字符,预计需要花费 7 分钟才能阅读完成。
1 Nova-compute服务源码解析
nova-compute创建虚拟机时,其主要任务就是通过用户准备的各种参数,最终生成创建虚拟机的XML文件以供Hypervisor使用,主要步骤如下:
- 准备虚拟机所需要的资源(CPU资源,RAM资源以及镜像资源等),网络资源也会在这个阶段一同分配
- 创建虚拟机的镜像文件,nova-compute会调用glanceclient拉取镜像,以该镜像为基础创建镜像文件。
- 生成创建虚拟机的XML文件
- 创建网络并启动虚拟机
以上过程中生成的XML或者暂存在计算节点的镜像都会存放在计算节点的/var/lib/nova/instances文件夹下以该虚拟机的UUID命名的子目录中。
1.1 Nova-compute启动流程
nova-compute服务的入口位于nova/cmd/compute.py,如下图所示:
其中第45行会读取配置文件进行一些初始化的工作,第59行代码用于创建RPC Service,并将此RPC Service的topic设置为CONF.compute_topic,类Service的定义位于nova/service.py,其中第116行为实例化一个ComputeManager(nova/compute/manager.py)类,里面定义了接受并处理各种RPC请求的方法。
最后在nova/cmd/compute.py的第61行service.serve(server)用于启动RPC Service(),service.serve()的实现方法(nova/service.py)如下所示,通过oslo_service/service.py中的launch方法,启动相应数量的RPC Service进程,至此nova-compute服务启动。
1.2 Nova-compute创建虚拟机流程
在OpenStack nova创建虚拟机过程中,nova-api收到虚拟机创建请求,然后nova-scheduler完成选择合适计算节点的任务,nova-conductor则开始调用build_instance()来创建虚机。
在conductor.manager.ComputeTaskManager.build_instance()中,通过rpc调用:self.compute_rpcapi.build_and_run_instance(),该方法的代码如下所示(nova/compute/rpcapi.py)该方法通过RPC调用nova/compute/manager.py:ComputeManager中的build_and_run_instance()方法。而build_and_run_instance()方法就完成VM在计算节点上的创建和启动任务。
nova/compute/rpcapi.py:
nova/compute/manager.py:
里面定义了一个_locked_do_build_and_run_instance()方法,这里真正实现instance的创建和启动的,还有一个spawn方法调用,这是因为nova compute创建VM的时间会比较长,因为其中包括了下载VM镜像、创建和配置VM网卡信息、文件注入等任务,因此调用utils.spawn_n()方法返回RPC线程而不会造成阻塞。
在locked_do_build_and_run_instance()方法直接调用self.do_build_and_run_instance()。
self._do_build_and_run_instance()方法主要做了一下几件事:
1、 设置虚拟机状态为BUILDING instance.vm_state = vm_states.BUILDING, task_state为None,然后调用instance.save()将状态存入数据库中。
2、 如果起虚机时有文件注入,将会调用nova.compute.manager.ComputeManager.decode_files()完成文件注入处理。decoded_files = self.decode_files(injected_files)
3、 接下来就是调用self._build_and_run_instance方法进行虚拟机创建。
self._build_and_run_instance:
该方法包含如下几个部分:
1、 通知部分,通知其他组件实例的创建状态:
2、 检查设备和证书:
3、 provider_mapping = self._get_request_group_mapping(request_spec) 要在服务器调度期间支持 QoS 最小带宽策略,Neutron 需要知道哪个资源提供程序为服务器创建请求中的每个端口提供带宽资源。在处理 VGPU 和加速器设备时会出现类似的需求。返回一个字典,如果该字典不为空,那么就需要更新pci_request_spec。
4、 获取该用户的分配情况:
5、 get_scheduler_hints获取调度程序提示,self.rt.instance_claim获取实例资源分配声明,可用于发生异常后恢复资源,self.validate_instance_group_policy验证是否符合调度程序设置的策略:
6、 接下来就是调用self._build_resources申请各种资源,成功后,更新数据库中的状态:vm_state为building, task_state为spawning,
7、 最后调用driver.spawn方法完成VM孵化,OpenStack底层调用的是libvirt,因此这里的driver就是libvirt提供的接口。在配置文件/etc/nova/nova.conf中设置了Driver= LibvirtDriver。
查看具体如何申请各种资源的:
self._build_resources()方法:
1、如果accel_uuids不为空,执行get_bound_arq_resources和split_network_arqs。
2、为实例构建网络:_build_networks_for_instance
3、分配块设备