zoukankan      html  css  js  c++  java
  • OpenStack创建虚拟机流程

    云主机创建流程图:

    dashboard发创建云主机的请求是先到novaclient,再由novaclienthttp的形式发送到nova-api端,我们这里直接从nova端讲起,通过wsgi映射匹配,API映射匹配可以看我的另一篇博客:OpenStack Restful API框架介绍

    创建云主机会首先调用到nova/api/openstack/compute/servers.py文件中的create()函数:

    @wsgi.response(202)
    @extensions.expected_errors((400, 403, 409))
    @validation.schema(schema_server_create_v20, '2.0', '2.0')
    @validation.schema(schema_server_create, '2.1', '2.18')
    @validation.schema(schema_server_create_v219, '2.19', '2.31')
    @validation.schema(schema_server_create_v232, '2.32', '2.36')
    @validation.schema(schema_server_create_v237, '2.37', '2.41')
    @validation.schema(schema_server_create_v242, '2.42')
    def create(self, req, body):
        """Creates a new server for a given user."""
        ......
        # 前面的代码主要是做了传进参数的检查、转换和操作的权限检查,同时获取镜像
        # id和flavor对象,这些处理完后会调用:
        (instances, resv_id) = self.compute_api.create(context,
                                    inst_type,
                                    image_uuid,
                                    display_name=name,
                                    display_description=description,
                                    availability_zone=availability_zone,
                                    forced_host=host, forced_node=node,
                                    metadata=server_dict.get('metadata', {}),
                                    admin_password=password,
                                    requested_networks=requested_networks,
                                    check_server_group_quota=True,
                                    group_id=server_dict.get('group_id', None),
                                    os_type=server_dict.get('os_type', None),
                                    boot_type='legacy',
                                    store_id=server_dict.get('store_id', None),
                                    enable_ha=server_dict.get('enable_ha', None),
                                    thinputer_extra=server_dict.get('thinputer_extra', None),
                                    **create_kwargs)

     

    这里是调用到了nova/compute/api.py文件中的create函数

    该函数进行网络是否有不合规操作,比如多个云主机却只指定了一个ip,检查可用域,生成过滤字典,然后调用_create_instance方法

    主要是初始化一些参数,检查和检验参数和配额方面的检查,生成instancesrequest_specsbuild_requests对象,request_specsbuild_requests对象用以调度选择,instances用以返回给客户端,值可看注解,接着函数调用:

    self.compute_task_api.schedule_and_build_instances(
                    context,
                    build_requests=build_requests,
                    request_spec=request_specs,
                    image=boot_meta,
                    admin_password=admin_password,
                    injected_files=injected_files,
                    requested_networks=requested_networks,
                    block_device_mapping=block_device_mapping)

     

    实现文件是在nova/conductor/api.py,该api.py其实是对同级下的rpcapi.py做了层封装,真正实现在rpcapi.py文件。

    api.py中的:

    def schedule_and_build_instances(self, context, build_requests,
                                         request_spec, image,
                                         admin_password, injected_files,
                                         requested_networks, block_device_mapping):
            self.conductor_compute_rpcapi.schedule_and_build_instances(
                context, build_requests, request_spec, image,
                admin_password, injected_files, requested_networks,
                block_device_mapping)

     

    这里调用了rpcapi.py中的schedule_and_build_instances方法:

    def schedule_and_build_instances(self, context, build_requests,
                                          request_specs,
                                          image, admin_password, injected_files,
                                          requested_networks,
                                          block_device_mapping):
            version = '1.16'
            kw = {'build_requests': build_requests,
                  'request_specs': request_specs,
                  'image': jsonutils.to_primitive(image),
                  'admin_password': admin_password,
                  'injected_files': injected_files,
                  'requested_networks': requested_networks,
                  'block_device_mapping': block_device_mapping}
    
            cctxt = self.client.prepare(version=version)
            cctxt.cast(context, 'schedule_and_build_instances', **kw)

     

    这里是远程调用到了nova/conductor/manager.py中的schedule_and_build_instances函数:

    def schedule_and_build_instances(self, context, build_requests,
                                         request_specs, image,
                                         admin_password, injected_files,
                                         requested_networks, block_device_mapping):
            legacy_spec = request_specs[0].to_legacy_request_spec_dict()
            try:
                hosts = self._schedule_instances(context, legacy_spec,
                            request_specs[0].to_legacy_filter_properties_dict())
                ..........

     

    这个函数主要前面部分主要是先通过scheduler选择合适的host,然后是将要创建的虚拟机的信息写入到数据库中,最后是调用build_and_run_instance函数,该函数实现是在nova/compute_rpcapi.py

    def build_and_run_instance(self, ctxt, instance, host, image, request_spec,
                filter_properties, admin_password=None, injected_files=None,
                requested_networks=None, security_groups=None,
                block_device_mapping=None, node=None, limits=None):
    
            version = '4.0'
            cctxt = self.router.by_host(ctxt, host).prepare(
                    server=host, version=version)
            cctxt.cast(ctxt, 'build_and_run_instance', instance=instance,
                    image=image, request_spec=request_spec,
                    filter_properties=filter_properties,
                    admin_password=admin_password,
                    injected_files=injected_files,
                    requested_networks=requested_networks,
                    security_groups=security_groups,
                    block_device_mapping=block_device_mapping, node=node,
                    limits=limits)

     

    通过host参数远程调用指定宿主机的build_and_run_instance方法,实现文件在nova/compute/manage.py

    @wrap_exception()
    @reverts_task_state
    @wrap_instance_fault
    def build_and_run_instance(self, context, instance, image, request_spec,
                     filter_properties, admin_password=None,
                     injected_files=None, requested_networks=None,
                     security_groups=None, block_device_mapping=None,
                     node=None, limits=None):
    
        @utils.synchronized(instance.uuid)
        def _locked_do_build_and_run_instance(*args, **kwargs):
            # NOTE(danms): We grab the semaphore with the instance uuid
            # locked because we could wait in line to build this instance
            # for a while and we want to make sure that nothing else tries
            # to do anything with this instance while we wait.
            with self._build_semaphore:
                self._do_build_and_run_instance(*args, **kwargs)
    
        # NOTE(danms): We spawn here to return the RPC worker thread back to
        # the pool. Since what follows could take a really long time, we don't
        # want to tie up RPC workers.
        utils.spawn_n(_locked_do_build_and_run_instance,
                      context, instance, image, request_spec,
                      filter_properties, admin_password, injected_files,
                      requested_networks, security_groups,
                      block_device_mapping, node, limits)

    这里的关键点是调用到了_do_build_and_run_instance函数,该函数的关键代码是调用了_build_and_run_instance函数来创建:

    def _build_and_run_instance(self, context, instance, image, injected_files,
                admin_password, requested_networks, security_groups,
                block_device_mapping, node, limits, filter_properties):
        ..........
    
        # 这个函数的主要功能有进行事件通知、获取所需资源、创建好网络设备和磁盘设备,最
        # 后是通过配置文件的driver选定以哪种虚拟化方式实现虚拟机的生成,这里调用的函数是:
        self.driver.spawn(context, instance, image_meta,
                                                  injected_files, admin_password,
                                                  network_info=network_info,
                                                  block_device_info=block_device_info)

     

    对应的函数实现在nova/virt/libvirt/driver.py

    def spawn(self, context, instance, image_meta, injected_files,
                  admin_password, network_info=None, block_device_info=None):
            disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
                                                instance,
                                                image_meta,
                                                block_device_info)
            injection_info = InjectionInfo(network_info=network_info,
                                           files=injected_files,
                                           admin_pass=admin_password)
            gen_confdrive = functools.partial(self._create_configdrive,
                                              context, instance,
                                              injection_info)
            self._create_image(context, instance, disk_info['mapping'],
                               injection_info=injection_info,
                               block_device_info=block_device_info)
    
            # Required by Quobyte CI
            self._ensure_console_log_for_instance(instance)
    
            # 生成libvirt所需的xml文件
            xml = self._get_guest_xml(context, instance, network_info,
                                      disk_info, image_meta,
                                      block_device_info=block_device_info)
            self._create_domain_and_network(
                context, xml, instance, network_info, disk_info,
                block_device_info=block_device_info,
                post_xml_callback=gen_confdrive,
                destroy_disks_on_failure=True,
                power_on=False)
            LOG.debug("Instance is running", instance=instance)

     

    在该函数中主要的功能是生成镜像、生成xml信息,最后调用_create_domain_and_network函数进行挂载上磁盘、网络初始化和虚拟机域生成。

    虚拟机域生成通过调用了_create_domain函数来实现

     

    总结下,虚拟机的创建流程如下:
    (1)用户首先通过Restful Api向keystone组件获取认证信息
    (2)然后向nova-api进程发送一个创建虚拟机的请求,并携带获取的认证信息和创建虚拟机的参数
    (3)nova-api将认证信息发送到keystone里认证是否是有效的认证信息
    (4)通过认证后且nova-api检查权限通过后向数据库写入新建虚拟机的数据库记录
    (5)nova-api通过发消息到消息队列让nova-conductor去创建虚拟机
    (6)nova-conductor通过发消息到消息队列让nova-scheduler筛选和选择可创建虚拟机的节点
    (7)nova-scheduler返回经过筛选的可用宿主机给nova-conductor
    (8)nova-conductor通过发消息到消息队列请求让目标节点nova-compute服务创建虚拟机
    (9)nova-compute服务发消息到消息队列让控制节点上的nova-conductor服务获取要新建的虚拟机的元数据信息,比如内存、cpu等信息
    (10)nova-compute获取到新建虚拟机的元数据信息后,为虚拟机分配资源,比如cpu、内存资源
    (11)请求镜像服务获取新建虚拟机的镜像信息和创建镜像文件
    (12)如果有网卡和数据盘创建请求,则会分别向neutron和cinder服务请求创建对应的资源
    (13)虚拟机域的生成,如果是libvirt的driver,定义好虚拟机的XML信息
    (14)初始化虚拟网络设备并启动虚拟机
     
  • 相关阅读:
    关于正则表达式的递归匹配问题
    给程序添加启动画面
    C#中的ICollection接口
    C#基本线程同步
    C# 图片裁剪代码
    .NET程序性能的基本要领
    C# 6与VB 12即将加入模式匹配
    Python实例---利用正则实现计算器[FTL版]
    Python实例---利用正则实现计算器[参考版]
    Python学习---重点模块之subprocess
  • 原文地址:https://www.cnblogs.com/luohaixian/p/12368164.html
Copyright © 2011-2022 走看看