Openstack虚拟机创建中的RPC调用

openstack开发实践(五):RPC远程调用解析 RPC服务实现分析 openstack的项目(如nova,cinder,glance以及neutron等)中,各个组件之间主要是通过REST API接口进行通信,而同一个组件内部(比如nova中的nova-scheduler与nova-compute通信)都采用基于AMQP通信模型的RPC通信。AMQP是一种提供统一消息服务的应用层标准协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于... 阅读详情

参考《Openstack设计与实现》
https://blog.apporc.org/2016/04/nova-%E5%88%9B%E5%BB%BA%E8%99%9A%E6%8B%9F%E6%9C%BA%E6%B5%81%E7%A8%8B/
https://github.com/Moonlight-shadow/openstack-workflow

虚拟机创建过程如图1-1


图1-1

如上图,nova-api在收到客户端创建虚拟机的HTTP请求后,通过RPC调用nova.conductor.manager.ComputeTaskManager中的build_instances()方法。nova-conductor会在build_instance()生成request_spec字典,其中包括了详细的虚拟机信息,nova-scheduler会根据这些信息为虚拟机选择一个最佳的主机,然后nova-conductor再通过RPC调用nova-compute创建虚拟机。虚拟机的创建过程即nova中各组件的RPC调用过程。

代码分析

nova-api接收到创建虚拟机的http请求之后,通过nova-api调用compute.API的create方法来创建虚拟机

#nova/api/openstack/compute/servers.py
from nova import compute

class ServersController(wsgi.Controller):
  def __init__(self, **kwargs):
    ...
    super(ServersController, self).__init__(**kwargs)
    self.compute_api = compute.API(skip_policy_check=True)
    #调用compute.API

  def create(self, req, body):  
    #为特定用户创建虚拟机
    context = req.environ['nova.context']
    server_dict = body['server']
    password = self._get_server_admin_password(server_dict)
    name = common.normalize_name(server_dict['name'])
    #要创建实例的各项参数
    create_kwargs = {}

    try:
      inst_type = flavors.get_flavor_by_flavor_id(
                flavor_id, ctxt=context, read_deleted="no")
      #调用compute.API的create方法进行虚拟机创建
      (instances, resv_id) = self.compute_api.create(context,
                inst_type,
                image_uuid,
                display_name=name,
                display_description=name,
                metadata=server_dict.get('metadata', {}),
                admin_password=password,
                requested_networks=requested_networks,
                check_server_group_quota=True,
                **create_kwargs)
      ...

API的create方法返回值调用APi的_creat_instance()

class API(base.Base):

  def compute_task_api(self):
    if self._compute_task_api is None:
        # TODO(alaski): Remove calls into here from conductor manager so
        # that this isn't necessary. #1180540

        #调用conductor的ComputeTaskAPI类
        from nova import conductor
        self._compute_task_api = conductor.ComputeTaskAPI()
    return self._compute_task_api

  def _create_instance(self, context, instance_type,
               image_href, kernel_id, ramdisk_id,
               min_count, max_count,
               display_name, display_description,
               key_name, key_data, security_groups,
               availability_zone, user_data, metadata,
               injected_files, admin_password,
               access_ip_v4, access_ip_v6,
               requested_networks, config_drive,
               block_device_mapping, auto_disk_config,
               reservation_id=None, scheduler_hints=None,
               legacy_bdm=True, shutdown_terminate=False,
               check_server_group_quota=False):

         # self._compute_task_api = conductor.ComputeTaskAPI() 调用调用conductor的ComputeTaskAPI类的build_instances方法
         self.compute_task_api.build_instances(context,
                  instances=instances, image=boot_meta,
                  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,
                  legacy_bdm=False)

          return (instances, reservation_id)

ComputeTaskAPI中build_instances方法的实现

#/nova/compute/api.py
class ComputeTaskAPI(object):
    """ComputeTask API that queues up compute tasks for nova-conductor."""

    def __init__(self):
        self.conductor_compute_rpcapi = rpcapi.ComputeTaskAPI()

    #云主机调整大小
    def resize_instance(self, context, instance, extra_instance_updates,
                        scheduler_hint, flavor, reservations,
                        clean_shutdown=True):
        # NOTE(comstud): 'extra_instance_updates' is not used here but is
        # needed for compatibility with the cells_rpcapi version of this
        # method.
        self.conductor_compute_rpcapi.migrate_server(
            context, instance, scheduler_hint, live=False, rebuild=False,
            flavor=flavor, block_migration=None, disk_over_commit=None,
            reservations=reservations, clean_shutdown=clean_shutdown)

    #rpc调用
    def live_migrate_instance(self, context, instance, host_name,
                              block_migration, disk_over_commit):
        scheduler_hint = {'host': host_name}
        self.conductor_compute_rpcapi.migrate_server(
            context, instance, scheduler_hint, True, False, None,
            block_migration, disk_over_commit, None)

    #创建云主机,调用rpcapi.ComputeTaskAPI()的build_instances方法
    def build_instances(self, context, instances, image, filter_properties,
            admin_password, injected_files, requested_networks,
            security_groups, block_device_mapping, legacy_bdm=True):
        self.conductor_compute_rpcapi.build_instances(context,
                instances=instances, image=image,
                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,
                legacy_bdm=legacy_bdm)


    def unshelve_instance(self, context, instance):
        self.conductor_compute_rpcapi.unshelve_instance(context,
                instance=instance)

    #重建云主机  
    def rebuild_instance(self, context, instance, orig_image_ref, image_ref,
                         injected_files, new_pass, orig_sys_metadata,
                         bdms, recreate=False, on_shared_storage=False,
                         preserve_ephemeral=False, host=None, kwargs=None):
        # kwargs unused but required for cell compatibility
        self.conductor_compute_rpcapi.rebuild_instance(context,
                instance=instance,
                new_pass=new_pass,
                injected_files=injected_files,
                image_ref=image_ref,
                orig_image_ref=orig_image_ref,
                orig_sys_metadata=orig_sys_metadata,
                bdms=bdms,
                recreate=recreate,
                on_shared_storage=on_shared_storage,
                preserve_ephemeral=preserve_ephemeral,
                host=host)

到了conductor.rpcapi

# nova/conductor/rpcapi.py
class ComputeTaskAPI(object):
    """Client side of the conductor 'compute' namespaced RPC API"""

    def build_instances(self, context, instances, image, filter_properties,
        admin_password, injected_files, requested_networks,
        security_groups, block_device_mapping, legacy_bdm=True):
    image_p = jsonutils.to_primitive(image)
    version = '1.10'
    if not self.client.can_send_version(version):
        version = '1.9'
        if 'instance_type' in filter_properties:
            flavor = filter_properties['instance_type']
            flavor_p = objects_base.obj_to_primitive(flavor)
            filter_properties = dict(filter_properties,
                                     instance_type=flavor_p)
    kw = {'instances': instances, 'image': image_p,
           'filter_properties': filter_properties,
           'admin_password': admin_password,
           'injected_files': injected_files,
           'requested_networks': requested_networks,
           'security_groups': security_groups}
    if not self.client.can_send_version(version):
        version = '1.8'
        kw['requested_networks'] = kw['requested_networks'].as_tuples()
    if not self.client.can_send_version('1.7'):
        version = '1.5'
        bdm_p = objects_base.obj_to_primitive(block_device_mapping)
        kw.update({'block_device_mapping': bdm_p,
                   'legacy_bdm': legacy_bdm})

    cctxt = self.client.prepare(version=version)
    #RPC主要用于异步形式,比如下面就用于双肩虚拟机,在创建过程,可能需要比较长的时间
    #如果使用RPC call显然对性能有很大影响。cast()的第二个参数是RPC调用的函数名,后面的参数
    #将作为参数传递给函数。
    #关于同步异步阻塞非阻塞请看 http://blog.youkuaiyun.com/moolight_shadow/article/details/70212874
    # 这儿就调用上面的build_instances方法进行RPC通信。把创建请求扔到消息队列中
    cctxt.cast(context, 'build_instances', **kw)

cast() 方法发送出去的 rpc 请求是没有回复的。所以创建虚拟机的请求在_create_instance()一步直接返回了,此时虚拟机并没有创建完毕,但是创建的请求已成功发往了 nova-conductor。后续虚拟机的创建情况通过虚拟机的状态反映。
nova-conductor 提供了 build_instances() 这个 rpc 方法,所以它一直在紧切注视着 rabbitmq 消息队列。当看到有一个请求指向自己时,它就捡起了这个请求,准备进行 build_instances() 操作。进入 nova/conductor/manager.py 这里,做的事情非常明显,发送一个请求到 nova-scheduler,得到一个选好的运行 nova-compute的主机,然后将请求发给 nova-compute。

在nova-conductor进程中进行处理

class ComputeTaskManager(base.Base):
  def build_instances(self, context, instances, image, filter_properties,
        admin_password, injected_files, requested_networks,
        security_groups, block_device_mapping=None, legacy_bdm=True):
    # TODO(ndipanov): Remove block_device_mapping and legacy_bdm in version
    #                 2.0 of the RPC API.
    request_spec = scheduler_utils.build_request_spec(context, image,
                                                      instances)


    for (instance, host) in itertools.izip(instances, hosts):
        try:
            instance.refresh()
        except (exception.InstanceNotFound,
                exception.InstanceInfoCacheNotFound):
            LOG.debug('Instance deleted during build', instance=instance)
            continue
        local_filter_props = copy.deepcopy(filter_properties)
        scheduler_utils.populate_filter_properties(local_filter_props,
            host)
        # The block_device_mapping passed from the api doesn't contain
        # instance specific information
        bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
                context, instance.uuid)

        self.compute_rpcapi.build_and_run_instance(context,
                instance=instance, host=host['host'], image=image,
                request_spec=request_spec,
                filter_properties=local_filter_props,
                admin_password=admin_password,
                injected_files=injected_files,
                requested_networks=requested_networks,
                security_groups=security_groups,
                block_device_mapping=bdms, node=host['nodename'],
                limits=host['limits'])
OpenStack之RPC调用(一) 众所周知,OpenStack的通信方式有两种,一种是基于HTTP协议的RESTFul API方式,另一种则是RPC调用。两种通信方式的应用场景有所不同,在OpenStack中,前者主要用于各组件之间的通信(如nova与glance的通信),而后者则用于同一组件中各个不同模块之间的通信(如nova组件中nova-compute与nova-scheduler的通信)。 关于OpenStack 阅读详情

相关推荐

OpenStack源码阅读-创建虚拟机(三)

本文为扶艾原创文章,版权所有,禁止转载! 请大家静下心来看源码分析的文章,看完后相信你会有收获的! 本文来自于微信公众号“扶艾”,欢迎大家关注获取更多精彩内容! 上一篇文章我们分析了nova api是如何接收请求的,这篇文章我们将分析接收到请求之后创建虚拟机的流程。 nova api请求接收到请求之后,是执行的路径1的create方法。这个整合了创建虚拟机的用到的参数,并作了简单的合法性检...

塔尖草的博客 1525

openstack中的RPC请求分析

概述在openstack各个项目中,我们通常会用到如下几种RPC请求: RPC.call:发送请求到消息队列,等待返回最终结果。 RPC.cast:发送请求到消息队列,不需要等待最终返回的结果。 RPC.Notifier:发送各类操作消息到队列,不需要等待最终的返回结果。 RPC.call、RPC.cast一般用于同一个项目下的服务之间进行的“内部“请求;RPC.Notifier发送的操作消息,目前

hhp_hhp的专栏 4292

Mitaka版Openstack虚拟机启动流程

最近工作的主要内容是在dashboard中启动虚拟机的时候加一个cache静态划分的功能,是在隔离区还是在共享区,这就需要对整个虚拟机的启动流程代码非常熟悉,并且还要适当的改前端。但是在看源码包括实践的过程发现了一件很神奇的时候,网上的教程大多是IceHose版本的,其启动虚拟机走的是正常的workflow中的handle函数,但是也不知道是我们装的Mitaka版本OpenStack有问题还是怎么样

在努力! 3218

Openstack_通用技术_RPC 远程异步调用

目录 目录 RPC 一个通过 HTTP Request 调用操作函数的 RPC 实现样例 环境 接收 HTTP Request RPC 调用具体的操作函数 测试 RPC RPC: 同一个项目内的不同服务进程之间的交互方式。为不同的进程服务提供了 call()(同步) 和 cast()(异步) 两种调用方式。 ...

weixin_33953249的博客 272

OpenStack之Nova分析——创建虚拟机(五)

上篇两篇文章分析了Nova Scheduler服务,这篇文章我们继续来分析创建虚拟机的过程。先来回顾一下。 class FilterScheduler(driver.Scheduler): def scheduler_run_instance(self, context, request_spec, admin_passwor

仇晗的专栏 1963

结合云技术的虚拟桌面的实现原理

为保护某企业的知识产权,减少由于图纸资料等的泄漏给企业带来的损失,需要在以下方面进行重点保护与防范: 在不影响研发性能与效率的前提下,集中管理研发人员所用的桌面系统,使研发环境与图纸资料等均保留在企业数据中心,通过策略控制相关人员对文件的打印、复制操作,保护研发成果,避免泄漏与丢失; 对办公人员的邮件系统进行统一监管,记录其相关操作,避免通过邮件泄露企业的研发成果或商业机密。

openstack学习之RPC

什么是RPC RPC即Remote Procedure Call(远程方法调用),是Openstack中一种用来实现跨进程(或者跨机器)的通信机制。Openstack中同项目内(如nova, neutron, cinder...)各服务(service)及通过RPC实现彼此间通信。Openstack中还有另外两种跨进程的通信方式:数据库和Rest API。 Openstack中

zhengleiguo的专栏 4996

使用python创建OpenStack虚拟机

手把手教您如何使用python语言,创建OpenStack虚拟机。

Openstack创建虚拟机 Restful api和RPC调用

Horizon前台界面用于接受用户的输入或动作(action),然后将这些参数构造成RESTful API(https://developer.openstack.org/api-ref/compute/#create-server),并通过novaclient发出。Nova-API负责接受该RESTFul API请求,通过RPC调用将消息发送到RabbitMQ,Nova-Compute订阅了该消...

weixin_30443075的博客 633

中山大学_数据科学与计算机_预推免

前言 2019 年 9 月中旬是中山大学预推免时间,本人没能进到夏令营,但是最后在预推免上岸也算不幸中的万幸。 记忆不一定准确,但希望能帮到他人。 想看 流程 的可以直接看总结,正文部分有本人心路历程。 预推免 中山大学的预推免大致可以分为 报道,机试,面试 三大部分,而且尤其是面试,所有人加起来总时长 3 天,幸运的是,本人被安排在第一天的下午第一场,上午就是机试,报道,机试,面试,无缝衔接。 ...

一把健 5208

浅析ArcGis中的软件——ArcMap、ArcScene、 ArcGlobe、ArcCatalog

ArcMap:是集空间数据显示、矢量数据编辑、冲突数据检查(拓扑检查)、查询检索(地理编码)、统计(字段属性表)、报表生成、空间分析(ArcGIS Spatial Analyst)和高级制图(制图表达)等众多功能干一体的桌面应用平台软件。而且提供所见即所得的符号编辑器,令用户可以随心所欲地生成任意复杂的点、线、面符号。所支持的空间数据格式包括Arclnfo coverages、ESRI shapefiles、ArcSDE lavers、DXF、DWG、DGN、常见的图像格式、GRIDs、TINs等。

lxlmycsdnfree的博客 6565

openstack-nova源码之阅读流程

以创建虚拟机为例 1.项目入口setup.cfg文件 2.根据nova-compute = nova.cmd.compute:main找到功能入口 3.nova/api/openstack/compute/servers.py中create(self, req, body)中进行rpc调用 4.进去nova/compute/api.py中cre...

weixin_30417487的博客 642

别再手动调时间了!用Windows自带的tzutil命令,1分钟搞定时区错误

本文介绍了如何使用Windows自带的tzutil命令快速解决时区错误问题。通过简单的命令行操作,用户可以一键切换时区、查看全球时区代码库,并实现自动化时区同步。相比传统GUI设置,tzutil更可靠且高效,特别适合企业环境批量部署。

weixin_42531494的博客 315

模仿OpenStack写自己的RPC

nova各个服务启动时就是开启了一个RPC的服务端,在调用其他服务时会创建一个客户端,通过客户端调用到相应的服务。以nova创建虚拟机为例,在上图的第三步中,nova-scheduler选择好计算节点,将创建虚拟机的信息通过RPC发送给计算节点。代码经过RPC客户端的封装和调用,本文的重点就是如何调用RPC客户端。 从rpc.py中可知,客户端来自messaging,其实就是oslo_messag...

topxjking的专栏 238

Xilinx System Generator多速率系统(Multi-Rate Systems)的使用

在本实验练习中,您将学习在System Generator中如何使用多个时钟域有效地实现具有多个数据速率的设计。

白码王子小张的博客 1093

stm32f407等芯片(HAL库)时钟频率修改(乱码)

其他片子及库文件未知、未验证,只是在使用stm32f407ZG配置串口打印的时候,出现乱码,就从以下几方面定位问题: 1. 确认串口GPIO相关配置; 2. 确认波特率等参数; 3. 确认时钟频率; 结果这次使用YH的串口打印程序在ZDYZ的开发板调试项目工程(有点另类...),做功能验证,就出现了以上问题,出于好奇开始调试,最终发现是时钟频率问题。 看到下图这个配置,因为ZDYZ开发板使用的是8MHz外部晶振(好像默认的是25MHz,如图2),所以他这里PLL_M是25,不是推荐值,感...

bulefire2009的博客 5516

Openstack之Nova创建虚机流程分析

前言 Openstack作为一个虚拟机管理平台,核心功能自然是虚拟机的生命周期的管理,而负责虚机管理的模块就是Nova。 本文就是openstack中Nova模块的分析,所以本文重点是以下三点: 先了解Openstack的整体架构,搞清楚为什么要用这样的架构; 然后再了解架构中的各个组件,组件提供的主要功能与各个组件之间的交互; 了解虚机的启动过程,能在遇到问题时发现...

Allison_ywt的博客 888

同花顺Supermind量化交易 技术面分析专题(一)-- 相似k线的形态验证与选股

W底”,“多头上涨”,“趋势回踩”,”上涨中继“这些都是常见的K线形态,以”上涨中继“为例,当股价快速上涨后,出现盘整形态而非顶部形态,预示股价还会进一步上涨,那么本节主要讲述”上涨中继”形态是否能够预测未来股价上涨,以及如何应用“上涨中继”形态,来快速选股。"相似K线"技术相比于传统的K线组合而言更具技术性,其还有较多的运用空间,比如:运用顶部形态来监控个股潜在的下跌风险,运用相似度来监控个股是否脱离大盘走势,研究各类形态的上涨预测能力,并应用于选股等等。第一步:选取一段标准的“上涨中继”形态K线图。

qq_22808537的博客 4549

openstack代码分析

以下已创建虚拟机为题目对openstack进行通透性代码分析,写得简陋望各位手下留情   1.发起ec2命令(nova/api/ec2/__init__.py)     2.执行方法__call__解析URL发送参数     3.执行/nova/api/ec2/apirequest.py:apirequest.invoke,这里有一个ec2动作解析,如RunInsta

4203

计算机毕设:线性回归 Xgboost LSTM 预测黄金价格实战 完整代码数据视频讲解 可直接运行

线性回归 Xgboost LSTM 预测黄金价格实战 完整代码数据视频讲解 可直接运行

1761

Ansible 面板工具之AWK ( Anssible Tower )界面介绍

整理这部分笔记博文内容为AWX和UI 界面的简单介绍理解不足小伙伴帮忙指正傍晚时分,你坐在屋檐下,看着天慢慢地黑下去,心里寂寞而凄凉,感到自己的生命被剥夺了。当时我是个年轻人,但我害怕这样生活下去,衰老下去。在我看来,这是比死亡更可怕的事。--------王小波这里AWX使用的是最新的版本AWX 21.7.0目前最新版是3.8.6,博客中的版本为3.5.0对于Redhat的,官网上看到在 2022 年 11 月之后不在维护了,改版之后现在叫,感兴趣小伙伴可以了解下虽然有AWX是。

山河已无恙 1303

from nova to ironic(5)

前面说到rest进来如何route,创建server的rest: /v2/{tenant_id}/server, POST 方法, 来看看对应在nova.api.openstack.compute.servers.py中的create方法: 1. parse传进来的数据,数据是否合法,是否包含name,server_admin的password是否传入,没有就生成一个, 查看是否有ima

dingdingwolf的专栏 507

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

OpenStack NOVA创建虚拟详细流程

摘要:OpenStack虚拟机创建流程通过多组件协作完成。首先通过Keystone进行身份认证获取token,Nova-api验证token有效性后调度资源。Nova-scheduler选择合适主机,Nova-compute获取镜像、网络和存储信息后,最终调用虚拟化驱动创建实例。整个过程涉及Keystone认证、Nova组件间消息队列通信,以及Glance、Neutron、Cinder等服务的协同工作,确保虚拟机创建的安全性和资源分配的合理性。(149字)

u010575833的博客 473

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

深挖Openstack Nova - 实例创建(5)

--------------- 紧接上篇 nova实例创建(4) --------------------继续深入_provision_instances方法:3》在循环中,实例创建时需发送状态更新通知# 为实例的初始化建立发送一个状态更新通知,表示实例状态从不存在到建立 # send_update_with_states: # 在一个实例中,发送compute.instance.update来通...

熊孩子会撒野 599

nova创建虚机的关键函数调用结构梳理

本文尝试把nova boot后的实现按调用关键函数的顺序进行一个梳理。

klyhuntermax的博客 565

nova-conductor与AMQP(一)

源码版本:H版 一、AMQP基础 1、 什么是AMQP 可以参考如下文章: http://blog.youkuaiyun.com/linvo/article/details/5750987 http://blog.youkuaiyun.com/gaoxingnengjisuan/article/details/11468061 2、 nova中的AMQP 可以参考如下文章: http://docs.op...

weixin_30359021的博客 164
上一篇: Nova中的RPC
下一篇: KVM虚拟机操作手册(部分)
gfengwong
博客等级 码龄12年 103粉丝 67原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值