openstack 源码阅读技巧2021(持续更新中……)

不要问楼主为什么同样的一篇博客不选更新选重发,问就是CSDN不支持老博客从富文本编辑转到markdown,害!

写在开始之前

共性问题:
怎么读openstack代码这件事,是个持续性问题,毕竟官方半年就出一个新版本。有一些共性的小技巧放在前面说一说

  • 1.从一个特性入手是比较合适的看代码的方式
  • 2.日志可以佐证代码跟踪路线
  • 3.看别人的帖子的时候注意代码版本(版本不同有些地方就不一样)
  • 4.多节点环境看日志vip飘来飘去的,需要注意日志产生的地方,建议在单节点环境学习看日志

针对人群:

本文是为新手准备的,大佬请直接跳过,很多大佬觉得默认知道的事情,实际上对于新手来说比较致命,因为就卡在那些大佬认为简单不愿意写但是很容易混淆或者跟丢的地方

代码结构

nova代码结构:nova_queens/nova路径展开(nova_queens是指我下载下来的queens版的nova代码)

accelerator/    # Cyborg 加速器
api/            # Nova API 服务
cmd/            # 各个 Nova 服务的入口程序
compute/        # Nova Compute 服务
conductor/      # Nova Conductor 服务
conf/           # 所有的配置选项
console/        # nova-console 服务
db/             # 封装数据库操作
hacking/        # 编码规范检查
image/          # 封装镜像操作,Glance 接口抽象
keymgr/         # 密钥管理器实现
locale/         # 国际化相关文件
network/        # nova-network 服务
notifications/  # 通知相关功能
objects/        # 封装实体对象的 CURD 操作
pci/            # PCI/SR-IOV 支持
policies/       # 所有 Policy 的默认规则
privsep/        # oslo_privsep 相关
scheduler/      # Nova Scheduler 服务
servicegroup/   # 成员服务(membership),服务组
storage/        # Ceph 存储支持
tests/          # 单元测试
virt/           # 支持的 hypervisor 驱动
volume/         # 封装卷访问接口,Cinder 接口抽象

举一个例子

比如简单的虚拟机开机操作,会以这个操作为例,简述从命令行如何跟踪到代码

主要流程

请添加图片描述

代码跟踪

# 启动指定虚拟机,并输出日志
nova --debug start 【uuid】

日志输出

...
# 发出post请求调用后端接口函数 
DEBUG (session:372) REQ: curl -g -i -X POST http://controller:8774/v2.1/servers/0a5d7618-9217-4da3-bcbc-808ab6576aeb/action -H "Accept: application/json" -H "User-Agent: python-novaclient" -H "OpenStack-API-Version: compute 2.60" -H "X-OpenStack-Nova-API-Version: 2.60" -H "X-Auth-Token: {SHA1}4ccf2aa10756927beef200e497262ccc3c3daa13" -H "Content-Type: application/json" -d '{"os-start": null}'
...
# 成功启动虚拟机
DEBUG (session:722) POST call to compute for http://controller:8774/v2.1/servers/0a5d7618-9217-4da3-bcbc-808ab6576aeb/action used request id req-d4558f93-2156-4fcd-a1c6-998e279ac648
Request to start server 0a5d7618-9217-4da3-bcbc-808ab6576aeb has been accepted.

注意找到日志中的-d '{"os-start": null}',找到-d后面的key(这里就是os-start),然后去nova_queens/nova/api/openstack/compute/servers.py中找到带os-start装饰器的action函数

    @wsgi.response(202)
    @wsgi.expected_errors((404, 409))
    @wsgi.action('os-start')
    def _start_server(self, req, id, body):
        """Start an instance."""
        ...
        context.can(server_policies.SERVERS % 'start', instance)
        try:
            # 调用 compute API 中的 start 函数
            self.compute_api.start(context, instance)
        ...

其他命令也一样,找到找到-d后面的key,根据这个key去servers.py找带着个key名字的装饰器的action函数

这里为什么这样找,需要去Restful、WSGI,在本篇不作详细说明了,新手先知道可以这么找,能够看openstack代码,后面再慢慢了解也不迟,当然二次开发加代码之前,还是得了解了再加

/nova_queens/nova/api/openstack/compute/servers.py文件的init中,已经初始化导入了computeAPI

    def __init__(self, **kwargs):

        super(ServersController, self).__init__(**kwargs)
        self.compute_api = compute.API()

所以可以直接用self.compute_api.start(context, instance)去调用 compute API 中的 start 函数,去/nova_queens/nova/compute/api.py下找到 calss API()中的start函数

@profiler.trace_cls("compute_api")
class API(base.Base):
    """API for interacting with the compute manager."""

    @check_instance_lock
    @check_instance_host
    @check_instance_cell
    @check_instance_state(vm_state=[vm_states.STOPPED])
    def start(self, context, instance):
        """Start an instance."""
        ...
        instance.task_state = task_states.POWERING_ON
        instance.save(expected_task_state=[None])
        ...
        # rpc远程调用 start_instance启动虚拟机
        self.compute_rpcapi.start_instance(context, instance)

转入/nova_queens/nova/compute/rpcapi.py查看rpc调用函数,rpc调用不明白的参考 openstack中的rpc远程调用

    def start_instance(self, ctxt, instance):
        version = self._ver(ctxt, '4.0')
        cctxt = self.router.client(ctxt).prepare(
                server=_compute_host(None, instance), version=version)
        # cast表示异步调用,第二个参数是进行实际实现的函数名,去manager.py下找到start_instance函数
        cctxt.cast(ctxt, 'start_instance', instance=instance)

转入/nova_queens/nova/compute/manager.py查看实际实现的函数start_instance

    @wrap_exception()
    @reverts_task_state
    @wrap_instance_event(prefix='compute')
    @wrap_instance_fault
    def start_instance(self, context, instance):
        """Starting an instance on this host."""
        ...
        self._power_on(context, instance)
        # 获取虚拟机电源状态
        instance.power_state = self._get_power_state(context, instance)
        # 更改虚拟机状态为active
        instance.vm_state = vm_states.ACTIVE
        # 置空虚拟机任务状态
        instance.task_state = None
        ...
        instance.save(expected_task_state=task_states.POWERING_ON)
        ...

底层实现不再一一赘述

如何查看日志

为了便于了解过程,这里举的例子非常简单日志很少,所以我们可以在命令下发时直接 --debug 输出到当前窗口,如果是复杂的特性,就不能这样了,关于萌新怎么查看openstack在这里 openstack怎么查看日志(小白适用实操版2019)

参考文献

https://github.com/openstack/nova/blob/master/setup.cfg
https://jckling.github.io/2021/05/23/OpenStack/OpenStack%20Nova/
https://blog.csdn.net/qq_33909098/article/details/118576253
https://blog.csdn.net/qq_33909098/article/details/103458081

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值