openstack (nova) metadata 分析

8 阅读3分钟

docs.openstack.org/nova/2025.2… api 对应 nova/api/metadata/

结论:Metadata API 服务完全维护在当前 Nova 项目中。

Metadata API 代码目录

核心代码位于 nova/api/metadata/,文件结构如下:

  ┌─────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────┐
  │                  文件                   │                                    作用                                     │
  ├─────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────┤
  │ nova/api/metadata/handler.py            │ 请求处理器 — MetadataRequestHandler 类,处理 169.254.169.254 上的 HTTP 请求 │
  ├─────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────┤
  │ nova/api/metadata/base.py               │ 核心逻辑 — 元数据的组装和渲染(EC2 格式、OpenStack 格式)                   │
  ├─────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────┤
  │ nova/api/metadata/password.py           │ 实例密码相关元数据                                                          │
  ├─────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────┤
  │ nova/api/metadata/vendordata.py         │ 静态 vendor data                                                            │
  ├─────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────┤
  │ nova/api/metadata/vendordata_dynamic.py │ 动态 vendor data                                                            │
  ├─────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────┤
  │ nova/api/metadata/vendordata_json.py    │ JSON 格式的 vendor data                                                     │
  └─────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────┘

  WSGI 入口点:

  ┌───────────────────────┬────────────────────────────────────────────────┐
  │         文件          │                      作用                      │
  ├───────────────────────┼────────────────────────────────────────────────┤
  │ nova/wsgi/metadata.py │ WSGI 应用入口,对应 nova-api-metadata 服务进程 │
  └───────────────────────┴────────────────────────────────────────────────┘

说明

  1. 独立服务进程:metadata API 作为 nova-api-metadata 独立进程运行(见 nova/wsgi/metadata.py:23 中 PROG = "nova-api-metadata"),与 nova-api(计算 API)是分开的。
  2. 完全在 Nova 内:从请求处理(handler)、数据组装(base)、到 WSGI 入口,全部代码都在当前 Nova 仓库中,没有依赖其他 OpenStack 项目的 metadata 实现。
  3. Neutron 的角色:Neutron 只负责 metadata proxy(将虚拟机发往 169.254.169.254 的请求转发到 Nova),实际的元数据生成和返回逻辑完全由 Nova 负责。

❯ 分析当前的 nova/api/metadata/ 和 文档中的 uri 链接是否完全对的上


文档 vs 代码对比分析

一、OpenStack 版本列表 — 文档缺失 2 个版本


  ┌─────────────────────────┬──────────────────────┬─────────────────────────────┬──────────┐
  │          版本           │ 代码 (base.py:76-87) │ 文档 (metadata.rst:104-112) │   状态   │
  ├─────────────────────────┼──────────────────────┼─────────────────────────────┼──────────┤
  │ 2012-08-10 (FOLSOM)     │          ✅          │             ✅              │ 一致     │
  ├─────────────────────────┼──────────────────────┼─────────────────────────────┼──────────┤
  │ 2013-04-04 (GRIZZLY)    │          ✅          │             ✅              │ 一致     │
  ├─────────────────────────┼──────────────────────┼─────────────────────────────┼──────────┤
  │ 2013-10-17 (HAVANA)     │          ✅          │             ✅              │ 一致     │
  ├─────────────────────────┼──────────────────────┼─────────────────────────────┼──────────┤
  │ 2015-10-15 (LIBERTY)    │          ✅          │             ✅              │ 一致     │
  ├─────────────────────────┼──────────────────────┼─────────────────────────────┼──────────┤
  │ 2016-06-30 (NEWTON_ONE) │          ✅          │             ✅              │ 一致     │
  ├─────────────────────────┼──────────────────────┼─────────────────────────────┼──────────┤
  │ 2016-10-06 (NEWTON_TWO) │          ✅          │             ✅              │ 一致     │
  ├─────────────────────────┼──────────────────────┼─────────────────────────────┼──────────┤
  │ 2017-02-22 (OCATA)      │          ✅          │             ✅              │ 一致     │
  ├─────────────────────────┼──────────────────────┼─────────────────────────────┼──────────┤
  │ 2018-08-27 (ROCKY)      │          ✅          │             ✅              │ 一致     │
  ├─────────────────────────┼──────────────────────┼─────────────────────────────┼──────────┤
  │ 2020-10-14 (VICTORIA)   │          ✅          │             ❌              │ 文档缺失 │
  ├─────────────────────────┼──────────────────────┼─────────────────────────────┼──────────┤
  │ 2025-04-04 (EPOXY)      │          ✅          │             ❌              │ 文档缺失 │
  └─────────────────────────┴──────────────────────┴─────────────────────────────┴──────────┘

代码中的隐藏逻辑(base.py:569-570)仅隐藏未来日期版本,当前日期 2026-03-10,这两个版本都已过期,用户实际能看到它们。

二、EC2 版本列表 — 完全一致 ✅

文档和代码都列出了相同的 9 个版本 + latest。

三、Config Drive 目录 — 文档缺失多个版本

EC2 部分:文档只列出 ec2/2009-04-04 和 ec2/latest。代码默认跳过旧版本(config_drive_skip_versions 默认值 = 跳过 1.0 ~ 2008-09-01),所以文档与默认行为一致 ✅

OpenStack 部分(metadata.rst:217-225):


  ┌─────────────────────────┬────────────────────┬───────────────────┬──────────┐
            版本            代码 (base.py:611)  文档 config drive    状态   
  ├─────────────────────────┼────────────────────┼───────────────────┼──────────┤
   2012-08-10 ~ 2017-02-22                                     一致     
  ├─────────────────────────┼────────────────────┼───────────────────┼──────────┤
   2018-08-27 (ROCKY)                                          文档缺失 
  ├─────────────────────────┼────────────────────┼───────────────────┼──────────┤
   2020-10-14 (VICTORIA)                                       文档缺失 
  ├─────────────────────────┼────────────────────┼───────────────────┼──────────┤
   2025-04-04 (EPOXY)                                          文档缺失 
  └─────────────────────────┴────────────────────┴───────────────────┴──────────┘

四、meta_data.json 字段 — 文档缺失新增字段

  ┌───────────────────────────────────────────────────────┬─────────────┬────────────────────────┬────────────────────────┬────────────┐
  │                         字段                          │  引入版本   │ 代码 (base.py:317-369) │ 文档示例 (rst:275-313) │    状态    │
  ├───────────────────────────────────────────────────────┼─────────────┼────────────────────────┼────────────────────────┼────────────┤
  │ uuid                                                  │ 始终        │           ✅           │           ❌           │ 文档缺失   │
  ├───────────────────────────────────────────────────────┼─────────────┼────────────────────────┼────────────────────────┼────────────┤
  │ meta, hostname, name, launch_index, availability_zone │ 始终        │           ✅           │           ✅           │ 一致       │
  ├───────────────────────────────────────────────────────┼─────────────┼────────────────────────┼────────────────────────┼────────────┤
  │ public_keys, keys                                     │ 始终        │           ✅           │           ✅           │ 一致       │
  ├───────────────────────────────────────────────────────┼─────────────┼────────────────────────┼────────────────────────┼────────────┤
  │ random_seed                                           │ GRIZZLY+    │           ✅           │           ✅           │ 一致       │
  ├───────────────────────────────────────────────────────┼─────────────┼────────────────────────┼────────────────────────┼────────────┤
  │ project_id                                            │ LIBERTY+    │           ✅           │           ✅           │ 一致       │
  ├───────────────────────────────────────────────────────┼─────────────┼────────────────────────┼────────────────────────┼────────────┤
  │ devices                                               │ NEWTON_ONE+ │           ✅           │           ✅           │ 一致       │
  ├───────────────────────────────────────────────────────┼─────────────┼────────────────────────┼────────────────────────┼────────────┤
  │ dedicated_cpus                                        │ VICTORIA+   │           ✅           │           ❌           │ 文档缺失   │
  ├───────────────────────────────────────────────────────┼─────────────┼────────────────────────┼────────────────────────┼────────────┤
  │ files                                                 │ 始终(有时)  │           ✅           │           ❌           │ 文档未展示 │
  ├───────────────────────────────────────────────────────┼─────────────┼────────────────────────┼────────────────────────┼────────────┤
  │ network_config                                        │ 始终(有时)  │           ✅           │           ❌           │ 文档未展示 │
  └───────────────────────────────────────────────────────┴─────────────┴────────────────────────┴────────────────────────┴────────────┘

五、设备元数据 (devices) — 文档缺失 share 类型

  ┌───────────────────────────┬───────────────────────────────┬────────────────────────┬──────┬──────────┐
  │         设备类型          │           引入版本            │ 代码 (base.py:409-441) │ 文档 │   状态   │
  ├───────────────────────────┼───────────────────────────────┼────────────────────────┼──────┼──────────┤
  │ nic (含 vlan, vf_trusted) │ NEWTON_ONE+ / OCATA+ / ROCKY+ │           ✅           │  ✅  │ 一致     │
  ├───────────────────────────┼───────────────────────────────┼────────────────────────┼──────┼──────────┤
  │ disk                      │ NEWTON_ONE+                   │           ✅           │  ✅  │ 一致     │
  ├───────────────────────────┼───────────────────────────────┼────────────────────────┼──────┼──────────┤
  │ share                     │ EPOXY+                        │           ✅           │  ❌  │ 文档缺失 │
  └───────────────────────────┴───────────────────────────────┴────────────────────────┴──────┴──────────┘

六、OpenStack endpoint 文件列表 — 文档缺失 password

代码 _handle_version(base.py:467-481)暴露的文件:

  ┌───────────────────┬─────────────┬──────┬──────┬──────────┐
  │       文件        │  引入版本   │ 代码 │ 文档 │   状态   │
  ├───────────────────┼─────────────┼──────┼──────┼──────────┤
  │ meta_data.json    │ 始终        │  ✅  │  ✅  │ 一致     │
  ├───────────────────┼─────────────┼──────┼──────┼──────────┤
  │ user_data         │ 始终(有时)  │  ✅  │  ✅  │ 一致     │
  ├───────────────────┼─────────────┼──────┼──────┼──────────┤
  │ password          │ GRIZZLY+    │  ✅  │  ❌  │ 文档缺失 │
  ├───────────────────┼─────────────┼──────┼──────┼──────────┤
  │ vendor_data.json  │ HAVANA+     │  ✅  │  ✅  │ 一致     │
  ├───────────────────┼─────────────┼──────┼──────┼──────────┤
  │ network_data.json │ LIBERTY+    │  ✅  │  ✅  │ 一致     │
  ├───────────────────┼─────────────┼──────┼──────┼──────────┤
  │ vendor_data2.json │ NEWTON_TWO+ │  ✅  │  ✅  │ 一致     │
  └───────────────────┴─────────────┴──────┴──────┴──────────┘

七、总结

文档落后代码主要涉及 VICTORIA (2020-10-14) 和 EPOXY (2025-04-04) 两个版本的新增内容:

  1. 版本列表:OpenStack 版本列表和 config drive 目录缺少 VICTORIA、EPOXY(config drive 还额外缺少 ROCKY)
  2. dedicated_cpus:VICTORIA 新增的字段,文档未记录
  3. share 设备类型:EPOXY 新增,文档未记录
  4. password endpoint:GRIZZLY 就有,但文档从未记录(历史遗留)
  5. uuid 字段:一直存在于 meta_data.json,文档示例从未展示