美文网首页
openstack代码层面剖析虚拟机创建完整流程

openstack代码层面剖析虚拟机创建完整流程

作者: lzp1234 | 来源:发表于2019-05-17 15:56 被阅读0次

    前言

    使用python-novaclient创建虚拟机,结合github上python-novaclient、nova源码分析创建虚拟机的整个流程。
    由于代码涉及功能非常多,因此文章着重介绍整个链路,而不会去解释每个节点做了什么。

    环境

    openstack S版本

    正文

    调用novaclient创建虚拟机时,novaclient最后会去请求nova处理任务。因此这里将novaclient和nova分开介绍。

    novaclient 部分:

    python-novaclient代码仓库:
    https://github.com/openstack/python-novaclient

    SDK 创建虚拟机参考:
    https://docs.openstack.org/ocata/user-guide/sdk-compute-apis.html#create-server-api-v2

    image.png

    如图,创建虚拟机调用了 nova_client.servers.create()

    1. 首先寻找nova_client

    from novaclient.client import Client
    通过导包,可以看到 nova_client 是此处的 novaclient.client.Client

    2. 寻找 novaclient.client.Client

    novaclient.client.Client代码位置:
    https://github.com/openstack/python-novaclient/blob/stable/stein/novaclient/client.py

    image.png

    已然找到了Client,在此Client方法中返回了client_class。对client_class定义的代码都在当前页面中,分析后可以发现Client导向 novaclient.v2.client.Client

    3. 寻找 novaclient.v2.client.Client

    novaclient.v2.client.Client代码位置:
    https://github.com/openstack/python-novaclient/blob/stable/stein/novaclient/v2/client.py

    image.png
    如图,第一层nova_client至此结束,实际指向novaclient.v2.client.Client类。
    接下来分析 nova_client.servers.create() 中的servers。
    在当前Client类中 可以发现 servers指向 servers.ServerManager(self),结合导包得出这个servers 实际指向 novaclient.v2.servers.ServerManager
    4. 寻找 novaclient.v2.servers.ServerManager

    novaclient.v2.servers.ServerManager代码位置:
    https://github.com/openstack/python-novaclient/blob/stable/stein/novaclient/v2/servers.py

    image.png
    如图,nova_client.servers.create() 中的servers也已找到。开始分析create()方法。
    1. 当前类的 create() 指向 self._boot()
    2. 当前类的 self._boot() 指向 self._create()
    3. self._create() 并没有在当前类中定义,这里可以通过基类寻找。
    5. 寻找 self._create()
    1. 父类 BootingManagerWithFind 中并没有定义
    2. 再往上,ManagerWithFind 类中也没有定义
    3. 再往上, Manager 类中定义了 _create() 方法

    self._create() 代码位置:
    https://github.com/openstack/python-novaclient/blob/stable/stein/novaclient/base.py

    image.png

    在 _create() 中,可以看到调用了一个post方法。这里就是novaclient sdk的最底层。
    分析可得知,novaclient 向nova 发送http post请求完成创建任务。
    因此nova 势必实现了一个web server,接下来分析nova源码时,可以从此处切入。

    nova 部分

    nova 代码仓库:
    https://github.com/openstack/nova

    1. 寻找webserver的入口

    根据webserver 编程经验,首先寻找路由部分。

    路由代码:
    https://github.com/openstack/nova/blob/stable/stein/nova/api/openstack/compute/routes.py

    image.png
    如图,结合 novalicent的url 以及post方式,可以看出:创建虚拟机通过 server_controller 的create方法实现。
    通过当前页面的代码分析,可以得出 server_controller 指向 ServersController。
    下一步寻找 ServersController
    2. 寻找 ServersController

    ServersController 代码位置:
    https://github.com/openstack/nova/blob/stable/stein/nova/api/openstack/compute/servers.py

    在当前类中,找到了create方法,如下图:


    image.png

    create方法最后调用了 self.compute_api.create()
    在类初始化定义当中 compute_api 指向 compute.API()
    接下来寻找 compute.API()

    3. 寻找 compute.API()

    compute.API() 代码位置:
    https://github.com/openstack/nova/blob/stable/stein/nova/compute/init.py

    image.png

    当前页面分析代码,可得知 API() 指向 nova.compute.api.API

    4. 寻找 nova.compute.api.API

    nova.compute.api.API 代码位置:
    https://github.com/openstack/nova/blob/stable/stein/nova/compute/api.py

    image.png
    self.compute_api.create() 中的compute_api已然找到,现在寻找对应的create()
    1. 当前类中实现了create()create()指向 self._create_instance()
    2. 当前类实现了 self._create_instance(),由于参数的配置不同,本人环境self._create_instance()指向 self.compute_task_api.schedule_and_build_instances()。这里指向的方法虽有不同,但是大体实现原理都是一致的。
    3. self.compute_task_api又指向 conductor.ComputeTaskAPI()
      接下来找到 conductor.ComputeTaskAPI()
    5. 寻找 conductor.ComputeTaskAPI()

    conductor.ComputeTaskAPI() 代码位置:
    https://github.com/openstack/nova/blob/stable/stein/nova/conductor/init.py

    image.png
    如图,根据导包,conductor.ComputeTaskAPI() 又指向 nova.conductor.api.ComputeTaskAPI
    6. 寻找 nova.conductor.api.ComputeTaskAPI

    nova.conductor.api.ComputeTaskAPI 代码位置:
    https://github.com/openstack/nova/blob/stable/stein/nova/conductor/api.py

    image.png

    至此,self.compute_task_api.schedule_and_build_instances()中的 compute_task_api 已然找到。接下来寻找 schedule_and_build_instances()

    1. 当前类实现了 schedule_and_build_instances()
    2. schedule_and_build_instances()又指向 self.conductor_compute_rpcapi.schedule_and_build_instances()
    3. self.conductor_compute_rpcapi指向 rpcapi.ComputeTaskAPI()

    接下来寻找 rpcapi.ComputeTaskAPI()

    7. 寻找 rpcapi.ComputeTaskAPI()

    rpcapi.ComputeTaskAPI() 代码位置:
    https://github.com/openstack/nova/blob/stable/stein/nova/conductor/rpcapi.py

    image.png
    如图 self.conductor_compute_rpcapi.schedule_and_build_instances() 中的 self.conductor_compute_rpcapi 已然找到,接下来就是寻找 schedule_and_build_instances()

    当前类实现了 schedule_and_build_instances(),这个方法调用了 消息队列的 异步方法,代码如下:

    cctxt.cast(context, 'schedule_and_build_instances', **kw)
    

    这里说明,nova哪里还有一个消息的消费者,也就是实现 schedule_and_build_instances的服务端。
    接下来去寻找这个 schedule_and_build_instances

    8. 寻找消息队列的消费者 schedule_and_build_instances

    schedule_and_build_instances 代码位置:
    https://github.com/openstack/nova/blob/stable/stein/nova/conductor/manager.py

    image.png

    通过方法所在类的装饰器可以看出,这是消息队列的消费者。
    当前方法又指向 self.compute_rpcapi.build_and_run_instance()
    self.compute_rpcapi 指向 compute_rpcapi.ComputeAPI()
    结合导包,最终指向为:nova.compute.rpcapi.ComputeAPI()
    现在去寻找 nova.compute.rpcapi.ComputeAPI()

    9. 寻找 nova.compute.rpcapi.ComputeAPI()

    nova.compute.rpcapi.ComputeAPI() 代码位置:
    https://github.com/openstack/nova/blob/stable/stein/nova/compute/rpcapi.py

    image.png
    self.compute_rpcapi.build_and_run_instance() 中的 self.compute_rpcapi已然找到,接下来寻找当前类的 build_and_run_instance()
    当前类实现了build_and_run_instance()
    build_and_run_instance() 调用了消息队列的异步方法,代码如下:
    cctxt.cast(ctxt, 'build_and_run_instance', **kwargs)
    

    接下来,就去寻找这个 build_and_run_instance

    10. 寻找 build_and_run_instance

    build_and_run_instance 代码位置:
    https://github.com/openstack/nova/blob/stable/stein/nova/compute/manager.py

    image.png
    1. 当前方法最后调用了一个协程,指向 _locked_do_build_and_run_instance
    2. 当前方法中定义了_locked_do_build_and_run_instance
    3. _locked_do_build_and_run_instance 指向self._do_build_and_run_instance
    4. 当前类定义了 self._do_build_and_run_instance
    5. self._do_build_and_run_instance 指向 self._build_and_run_instance()
    6. 当前类定义了 self._build_and_run_instance()
    7. self._build_and_run_instance() 数据库更新、调度都在这里有体现。指向 self.driver.spawn()
    8. 结合导包,self.driver 指向 nova.virt.driver.load_compute_driver
    11. 寻找 nova.virt.driver.load_compute_driver

    nova.virt.driver.load_compute_driver 代码位置:
    https://github.com/openstack/nova/blob/stable/stein/nova/virt/driver.py

    image.png
    本环境的 driver是 libvirt.LibvirtDriver
    当前方法返回 nova.virt.libvirt.LibvirtDriver
    接下来寻找 nova.virt.libvirt.LibvirtDriver
    12. 寻找 nova.virt.libvirt.LibvirtDriver

    nova.virt.libvirt.LibvirtDriver 代码位置:
    https://github.com/openstack/nova/blob/stable/stein/nova/virt/libvirt/init.py

    image.png
    这里又指向 nova.virt.libvirt.driver.LibvirtDriver
    接下来寻找 nova.virt.libvirt.driver.LibvirtDriver
    13. 寻找 nova.virt.libvirt.driver.LibvirtDriver

    nova.virt.libvirt.driver.LibvirtDriver 代码位置:
    https://github.com/openstack/nova/blob/stable/stein/nova/virt/libvirt/driver.py

    image.png
    1. self.driver.spawn() 中的driver 已然找到,在当前类中寻找 spawn()
    2. 当前类实现了 spawn()
    3. spawn() 中实现了生成xml等,指向 self._create_domain_and_network()
    4. 当前类实现了 self._create_domain_and_network()
    5. self._create_domain_and_network() 指向 self._create_domain()
    6. 当前类实现了 host.write_instance_config(),这里需要注意传入了一个host参数,host取值于当前类的属性。
    7. 结合导包,self._create_domain() 指向 nova.virt.libvirt.guest.Guest.create()
      接下来寻找 nova.virt.libvirt.guest.Guest.create()
    14. 寻找 nova.virt.libvirt.guest.Guest.create()

    nova.virt.libvirt.guest.Guest.create() 代码位置:https://github.com/openstack/nova/blob/stable/stein/nova/virt/libvirt/guest.py

    image.png
    指向 host.write_instance_config()
    接下来寻找 host.write_instance_config()。这里的host 是步骤【13】里的 host.write_instance_config() 传入的。
    15. 寻找 host.write_instance_config()

    host.write_instance_config() 代码位置:
    https://github.com/openstack/nova/blob/stable/stein/nova/virt/libvirt/host.py

    image.png
    1. 当前方法指向 self.get_connection().defineXML()
    2. self.get_connection() 指向 self._get_connection()
    3. self._get_connection() 指向 self._connect()
    4. self._connect() 指向 tpool.proxy_call(), 大致意思是返回一个libvirt 连接。
    5. defineXML() 就是创建一个虚拟机,但是还未启动。
    6. 回到步骤【13】中的 _create_domain(),这里实现了虚拟机是否开启

    至此,openstack部分已全部走完。

    相关文章

      网友评论

          本文标题:openstack代码层面剖析虚拟机创建完整流程

          本文链接:https://www.haomeiwen.com/subject/seagaqtx.html