1. 下载nova源码
从 github 下载 Victoria 版本的 Nova 源码
git clone https://github.com/openstack/nova.git --branch stable/victoria --single-branch
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/ 文件夹下的 python 文件:
__init__.py
availability_zones.py # 区域设置的工具函数
baserpc.py # 基础 RPC 客户端/服务端实现
block_device.py # 块设备映射
cache_utils.py # oslo_cache 封装
config.py # 解析命令行参数
context.py # 贯穿 Nova 的所有请求的上下文
crypto.py # 包装标准加密数据元素
debugger.py # pydev 调试
exception.py # 基础异常类
exception_wrapper.py # 封装异常类
filters.py # 基础过滤器
i18n.py # 集成 oslo_i18n
loadables.py # 可加载类
manager.py # 基础 Manager 类
middleware.py # 更新 oslo_middleware 的默认配置选项
monkey_patch.py # eventlet 猴子补丁
policy.py # 策略引擎
profiler.py # 调用 OSProfiler
quota.py # 每个项目的资源配额
rpc.py # RPC 操作相关的工具函数
safe_utils.py # 不会导致循环导入的工具函数
service.py # 通用节点基类,用于在主机上运行的所有工作者
service_auth.py # 身份认证插件
test.py # 单元测试基础类
utils.py # 工具函数
version.py # 版本号管理
weights.py # 权重插件
wsgi.py # 管理 WSGI 应用的服务器类
setup.cfg 配置文件,[entry_points] 小节指定了 nova 各个组件入口
console_scripts =
nova-api = nova.cmd.api:main
nova-api-metadata = nova.cmd.api_metadata:main
nova-api-os-compute = nova.cmd.api_os_compute:main
nova-compute = nova.cmd.compute:main
nova-conductor = nova.cmd.conductor:main
nova-manage = nova.cmd.manage:main
nova-novncproxy = nova.cmd.novncproxy:main
nova-policy = nova.cmd.policy:main
nova-rootwrap = oslo_rootwrap.cmd:main
nova-rootwrap-daemon = oslo_rootwrap.cmd:daemon
nova-scheduler = nova.cmd.scheduler:main
nova-serialproxy = nova.cmd.serialproxy:main
nova-spicehtml5proxy = nova.cmd.spicehtml5proxy:main
nova-status = nova.cmd.status:main
wsgi_scripts =
nova-api-wsgi = nova.api.openstack.compute.wsgi:init_application
nova-metadata-wsgi = nova.api.metadata.wsgi:init_application
2. nova-api
nova-api 对外提供 RESTful API,没有对内的 RPC 。
nova/api/ 目录结构
__init__.py
auth.py # 身份认证中间件
compute_req_id.py # x-compute-request-id 中间件(oslo_middleware)
metadata/ # Metadata API
openstack/ # Nova v2.1 API
validation/ # 请求体验证
wsgi.py # WSGI 原语(请求、应用、中间件、路由、加载器)
openstack 目录中包含 WSGI 基础架构的代码,一些 WSGI 中间件,以及如何解析请求与分发请求的核心代码。
nova/api/openstack/compute/ 包含 Controller 实现,Resource 对象将 API 映射到相应的 Controller 方法上。
__init__.py
api_version_request.py # 版本验证
auth.py # noauth 中间件
common.py # 信息查询的工具函数
compute/ # 每个 API 的入口点
identity.py # 验证项目是否存在
requestlog.py # 请求日志中间件
urlmap.py # url 映射
versioned_method.py # 版本信息
wsgi.py # WSGI 相关抽象类
wsgi_app.py # WSGI 应用程序初始化方法
API 请求路由
nova-api 读取 etc/nova/api-paste.ini
并加载 WSGI 程序,最终 API 入口点都位于 nova.api.openstack.compute
中
[composite:osapi_compute]
use = call:nova.api.openstack.urlmap:urlmap_factory
/: oscomputeversions # version API
/v2: oscomputeversion_legacy_v2 # v2 API
/v2.1: oscomputeversion_v2 # v2.1 API
# v21 is an exactly feature match for v2, except it has more stringent
# input validation on the wsgi surface (prevents fuzzing early on the
# API). It also provides new features via API microversions which are
# opt into for clients. Unaware clients will receive the same frozen
# v2 API feature set, but with some relaxed validation
/v2/+: openstack_compute_api_v21_legacy_v2_compatible
/v2.1/+: openstack_compute_api_v21
[composite:openstack_compute_api_v21]
use = call:nova.api.auth:pipeline_factory_v21 # 加载中间件
keystone = cors http_proxy_to_wsgi compute_req_id faultwrap request_log sizelimit osprofiler bees_profiler authtoken keystonecontext osapi_compute_app_v21
# DEPRECATED: The [api]auth_strategy conf option is deprecated and will be
# removed in a subsequent release, whereupon this pipeline will be unreachable.
noauth2 = cors http_proxy_to_wsgi compute_req_id faultwrap request_log sizelimit osprofiler bees_profiler noauth2 osapi_compute_app_v21
[app:osapi_compute_app_v21]
paste.app_factory = nova.api.openstack.compute:APIRouterV21.factory # 入口
nova/api/openstack/compute/routes.py
中的 APIRouterV21 主要用来完成路由规则的创建,其中 ROUTE_LIST 保存了 URL 与 Controller 之间的映射关系。
APIRouterV21 基于 ROUTE_LIST,使用 Routes 模块作为 URL 映射的工具,将各个模块所实现的 API 对应的 URL 注册到 mapper 中,并把每个资源都封装成 nova.api.openstack.wsgi.Resource
对象,当解析 URL 请求时,可以通过 URL 映射找到 API 对应的 Resource 对象。
# Router 类对 WSGI routes 模块进行了简单的封装
class APIRouterV21(base_wsgi.Router):
"""Routes requests on the OpenStack API to the appropriate controller
and method. The URL mapping based on the plain list `ROUTE_LIST` is built
at here.
"""
def __init__(self, custom_routes=None):
""":param custom_routes: the additional routes can be added by this
parameter. This parameter is used to test on some fake routes
primarily.
"""
super(APIRouterV21, self).__init__(nova.api.openstack.ProjectMapper())
if custom_routes is None:
custom_routes = tuple()
for path, methods in ROUTE_LIST + custom_routes:
# NOTE(alex_xu): The variable 'methods' is a dict in normal, since
# the dict includes all the methods supported in the path. But
# if the variable 'method' is a string, it means a redirection.
# For example, the request to the '' will be redirect to the '/' in
# the Nova API. To indicate that, using the target path instead of
# a dict. The route entry just writes as "('', '/)".
if isinstance(methods, six.string_types):
self.map.redirect(path, methods)
continue
for method, controller_info in methods.items():
# TODO(alex_xu): In the end, I want to create single controller
# instance instead of create controller instance for each
# route.
controller = controller_info[0]()
action = controller_info[1]
self.map.create_route(path, method, controller, action)
@classmethod
def factory(cls, global_config, **local_config):
"""Simple paste factory, :class:`nova.wsgi.Router` doesn't have one."""
return cls()
nova/api/wsgi.py
解析 URL 映射,通过 _dispatch