在 V3 API 代码库上实现 v2.1 API¶
https://blueprints.launchpad.net/nova/+spec/v2-on-v3-api
基于 v3 API 基础设施实现与 v2 兼容的 API。
问题描述¶
在 v3 API 开发过程中,我们改进了 API 基础设施,例如 API 插件加载、输入验证、策略检查等。此外,为了修复 v2 API 不一致的接口,我们对 Nova API 进行了大量的向后不兼容的更改(更改成功状态码、API 属性名称和 API URL)。这里有关于 v2 API 对用户、运营商和开发人员问题的全面描述:http://ozlabs.org/~cyeoh/V3_API.html
然而,关于 Nova 的未来以及同时支持 v2 和 v3 两个 API 所带来的维护开销,进行了大量的讨论。
用例¶
这项工作主要是 API 基础设施的清理工作,最终将允许我们开发者移除脆弱且不支持 V3 API 框架功能的旧 V2 API 代码库。它也是支持未来微版本化的必要工作。对用户和部署者的影响在以下部分中描述。
项目优先级¶
Kilo 优先级列表当前未定义。但是,在目前拟议的优先级列表中,它将属于“用户体验”类别,因为它为微版本化和改进 Nova API 的能力铺平了道路。
提议的变更¶
经过大量的讨论,我们理解了 v3 API 基础设施的优势(API 插件加载、输入验证、策略检查等)。然而,它们向后不兼容的接口现在看起来有些过早,因为我们现在不确定当前的 v3 API 是否是最好的。这意味着,即使切换到当前的 v3 API,我们也无法确定不再需要任何向后不兼容的更改。
本规范建议从 v3 代码中移除向后不兼容的更改。这意味着当前的 v3 一致接口将回归到 v2 不一致的接口,例如
--- a/nova/api/openstack/compute/plugins/v3/servers.py
+++ b/nova/api/openstack/compute/plugins/v3/servers.py
@@ -752,7 +752,7 @@ class ServersController(wsgi.Controller):
The field image_ref is mandatory when no block devices have been
defined and must be a proper uuid when present.
"""
- image_href = server_dict.get('image_ref')
+ image_href = server_dict.get('imageRef')
这个提议对 v3 API 开发者来说很痛苦,因为他们努力了一年多时间来创建一致的接口,而且 v3 接口实际上比 v2 接口更好。然而,通过讨论,我们了解到向后不兼容的更改对用户来说非常痛苦,我们必须关注这些更改。
在本规范中,我们将提供与 v3 的优势兼容的 v2 API 作为第一步。在此规范之后,我们将通过逐步定义 API 规则来提供一致的接口。这些规则将防止相同的向后不兼容的更改,并保持一致的接口,即使在未来添加大量新的 API。
备选方案¶
通过这些讨论,我们意识到可以在 v3 API 代码库之上同时支持 v2 API 和 v3 API。在这种想法下,nova 将 v2 请求转换为 v3 请求并将其传递给 v3 API 方法。在 v3 API 方法操作之后,nova 再次将 v3 响应转换为 v2 响应并将其返回给客户端。然而,对于这个想法也进行了大量的讨论,因为在长期内,当存在大量的向后不兼容的更改时,许多转换会使 API 问题的调试变得困难。
数据模型影响¶
无
REST API 影响¶
呈现的 V2.1 REST API 将与 V2 API 相同,除非另有说明。
但是,请注意,V2.1 不支持 V2 API 的 XML 版本,仅支持 JSON 版本。然而,V2 API 的 XML 版本目前已被标记为已弃用。
另一个影响是 JSON-Schema 的严格输入验证。JSON-Schema 包含“additionalProperties”功能,可以拒绝输入请求中未定义的属性。V2 API 只是忽略请求中包含的未定义属性,但 V2.1 API 会拒绝该请求并向客户端返回 BadRequest 响应。
在 V2.1 开发期间,我们发现 Tempest 也将未定义的属性传递给 Nova API,而 Nova V2 API 只是忽略了它们,然后测试成功。然而,Nova V2.1 API 拒绝了这些请求,测试失败。所以这是 Tempest 的错误,但我们想象这种问题可能会发生在其他 SDK 上。在修复此 Tempest 错误之前,我们调查了主要的 SDK(fog、jclouds)的代码,并确认这些 SDK 发送有效的请求,不包含未定义的属性,并且不包含此类问题。
我们无法检查世界上所有的 SDK/客户端,也无法确认此问题永远不会发生在 V2.1 API 上。这种问题一定是由客户端代码引起的,客户端的用户将能够知道这些现有的代码传递了无意义的属性。这意味着这种严格的验证将是一个提高客户端代码质量的机会。然而,这个问题对于公共云环境来说是一个巨大的担忧,也是 V2.1 采用的一个大问题。我们需要一些采用方式,例如未来进行验证放松或其他方式。
安全影响¶
更早期的输入验证将减少恶意用户输入利用安全漏洞的能力。
通知影响¶
无
其他最终用户影响¶
潜在地,如果 python novaclient 可以与 /v2.1 通信而不是 /v2,这可能是有利的,但更改代码可能不需要更改此设置。通过 keystone 配置来完成可能更简单。API 本身保持不变。
性能影响¶
更严格的输入验证也意味着需要在 API 层完成更多的工作,但总体而言这是一件好事。
其他部署者影响¶
如果部署者想要将 API 作为 /v2 而不是 /v2.1 导出,他们需要修改 api-paste.ini 文件(几行更改以禁用原始 V2 API 并将 APIRouterV21 作为 /v2 API 使用)。
长远目标是在部署者和用户对 v2.1 满足他们的要求感到满意时,弃用并最终移除原始 V2 API 代码。
我们将使用的流程是
V2.1 完全实现 Tempest 验证(包括正在添加的响应数据方面的额外验证)
来自多个来源(云提供商、用户等)的验证,V2.1 与 V2 兼容
这可以通过多种方式完成
Keystone 更改,以便 /v2.1 代替 /v2 进行广告宣传
将 V2.1 作为 /v2 导出
结合将 V2.1 输入验证放入日志而不是拒绝模式的可能性。
V2.1 在 OpenStack 发布中存在 N 个版本
在广泛确认 V2.1 API 兼容后,V2 将被标记为已弃用
开发人员影响¶
开发者长远优势是
所有 API 实现都在新的 API 框架上
减少支持两个主要 API 版本的维护开销
拥有更好的框架来处理未来的向后不兼容的更改。
在短期内,虽然旧的 V2 API 代码存在,仍然会存在双重维护开销。
实现¶
负责人¶
- 主要负责人
cyeoh-0
- 其他贡献者
oomichi Alex Xu
工作项¶
将 v3 成功状态码更改为 v2 的状态码。
将 v3 API 路由更改为 v2 的路由。
处理包含项目 ID 的 API URL。
更改 API 资源路径。(例如:/keypairs(v3) -> /os-keypairs(v2))
更改操作名称。(例如:migrate_live(v3) -> os-migrateLive(v2))
将 v3 API 属性名称更改为 v2 的名称。
更改 v3 代码的 API 解析器。
更改输入验证的 API 模式。
将 v3 API 行为更改为 v2 的行为。在某些 API 上,存在不同的行为。例如,v3 “创建私有风味”API 会自动为其自身项目添加风味访问权限,但 v2 不会。
以下工作项不是强制性的,它是一个愿望清单。
更改 v3 插件代码路径。例如
nova/api/openstack/compute/plugins/v3/servers.py -> nova/api/openstack/compute/plugins/servers.py
依赖项¶
无
测试¶
Tempest 已经包含大量的 v2 API 测试,现在这是一个很好的测试覆盖率。对于这个 v2.1 API,我们需要并行运行 v2 API 测试,用于当前的 v2 和 v2.1。作为一个想法,我们将通过从现有的 v2 API 测试类继承并针对 /v2.1 执行它们来添加 v2.1 API 测试。已经提出了一个关于这个想法的规范
文档影响¶
由于 API 除了输入验证方面的改进之外不会发生变化,因此 v2 API 的文档基本上与以前相同。在可能的错误状态码方面需要进行一些更新。
从长远来看,改进的输入验证基础设施以及响应验证的 JSON 模式的开发将使自动生成 v2 的文档更容易,而不是依赖于当前主要手动流程。
参考资料¶
Juno Mid-Cycle meetup https://etherpad.openstack.org/p/juno-nova-mid-cycle-meetup
Juno 设计峰会讨论 https://etherpad.openstack.org/p/juno-nova-v2-on-v3-api-poc
关于 Nova V3 API 和维护开销的邮件列表讨论
Etherpad 页面,讨论 V2 on V3 概念验证并跟踪正在进行的工作。
关于 V2 API 问题的文档
描述 V2 和 V3 API 之间当前差异的文档