nova源码分析--rpc(1)

本文主要分析了nova中虚拟机调度的RPC实现,从schedule_and_build_instances函数开始,逐步探讨了ComputeTaskAPI类、RPCClient的创建、CallContext的准备工作以及最后通过Transport发送请求的过程,揭示了nova如何利用RPC进行通信。
摘要由CSDN通过智能技术生成

nova中的虚拟机调度采用RPC机制,现在分析一下这部分代码的实现。

self.compute_task_api.schedule_and_build_instances函数的定义在nova/conductor/api.py中的类ComputeTaskAPI中,代码如下:

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

直接调用self.conductor_compute_rpcapi.schedule_and_build_instances函数,该函数在文件nova/conductor/rpcapi.py中的ComputeTaskAPI类中定义,代码如下: 

    def schedule_and_build_instances(self, context, build_requests,
                                     request_specs,
                                     image, admin_password, injected_files,
                                     requested_networks,
                                     block_device_mapping,
                                     tags=None):
        version = '1.17'
        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,
              'tags': tags}

        if not self.client.can_send_version(version):
            version = '1.16'
            del kw['tags']

        cctxt = self.client.prepare(version=version)
        cctxt.cast(context, 'schedule_and_build_instances', **kw)

       在创建ComputeTaskAPI类对象的时候,会执行以下代码:

    def __init__(self):
        super(ComputeTaskAPI, self).__init__()
        target = messaging.Target(topic=CONF.conductor.topic,
                                  namespace='compute_task',
                                  version='1.0')
        serializer = objects_base.NovaObjectSerializer()
        self.client = rpc.get_client(target, serializer=serializer)

类Target在文件./oslo_messaging/target.py中定义,包含的数据项如下所示,通过topic,namespace,version,server等确定了一对通信的客户端和服务端。

        self.exchange = exchange
        self.topic = topic
        self.namespace = namespace
        self.version = version
        self.server = server
        self.fanout = fanout
        self.accepted_namespaces = [namespace] + (legacy_namespaces or [])

rpc.get_client()的定义在./nova/rpc.py文件中,代码如下,通过调用./oslo_messaging/rpc/client.py文件中类RPCClient中的构造函数,获取一个RPCClient类的对象。

def get_client(target, version_cap=None, serializer=None):
    assert TRANSPORT is not None

    if profiler:
        serializer = ProfilerRequestContextSerializer(serializer)
    else:
        serializer = RequestContextSerializer(serializer)

    return messaging.RPCClient(TRANSPORT,
                               target,
                               version_cap=version_cap,
                               serializer=serializer)

    cctxt = self.client.prepare(version=version)函数最终调用./oslo_messaging/rpc/client.py文件中类_CallContext中的_prepare()函数,做准备工作,cctxt.cast(context, 'schedule_and_build_instances', **kw)函数最终调用./oslo_messaging/rpc/client.py文件中类_BaseCallContext中的cast()函数,代码如下:

    def cast(self, ctxt, method, **kwargs):
        """Invoke a method and return immediately. See RPCClient.cast()."""
        msg = self._make_message(ctxt, method, kwargs)
        msg_ctxt = self.serializer.serialize_context(ctxt)

        self._check_version_cap(msg.get('version'))

        try:
            self.transport._send(self.target, msg_ctxt, msg, retry=self.retry)
        except driver_base.TransportDriverError as ex:
            raise ClientSendError(self.target, ex)

      调用self.transport._send()函数将调用的函数名和参数发送给服务端。transport为在文件./nova/rpc.py中定义的变量TRANSPORT,类Transport的定义在./oslo_messaging/transport.py文件中,包含conf和_driver两个变量,配置文件默认定义的dirriver为rabbit,self.transport._send()函数调用rabbit的_send()函数发送请求。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值