发现系统能力的新核心 API¶
https://blueprints.launchpad.net/cinder/+spec/discovering-system-capabilities
需要一种方法让 Horizon 发现远程块存储部署的能力,以便它可以启用/禁用使用这些能力的 UI 小部件。 考虑卷备份功能, cinder 部署可能支持或不支持该功能。 如果 Horizon 可以以编程方式检测到此功能的存在,它可以启用 UI 中的卷备份操作。 这将消除操作员手动设置 Horizon 配置中相应字段以指示此功能可用性的需要,而目前的情况就是如此。 我们建议添加一组 API,这些 API 将返回当前用户可用的“能力”。 这些可以被 Horizon 和其他客户端用来配置自身,而无需手动保持同步的配置文件。
此蓝图源于 [1] 和 [2] 中 jgriffith 提交的 bug #1334856 [3] 的设计讨论。
问题描述¶
Horizon 允许用户通过 UI 创建卷备份,前提是底层的 cinder 部署支持相同的功能。 并非所有 cinder 部署都支持此功能,因此 Horizon 需要一种知道何时支持该功能的方法,以便它可以显示备份的 UI 元素。
目前,Horizon 使用 [5] 一个名为“enable_backup”的配置设置来控制 UI 中卷备份操作的启用状态。 这需要操作员根据 cinder-backup 服务的状态手动设置/取消设置。 这不仅繁琐而且容易出错。
卷备份 API 在服务器端由 cinder-backup 服务实现。 当 cinder 部署不支持卷备份时,此服务不存在。 例如,在默认配置的 devstack 中就是这种情况。
“os-services” API 扩展显示所有后端服务的状态。 这表明 Horizon 可以了解 cinder-backup 服务是否存在的一种方式。 但是,这有两个问题。 首先,os-services API 仅供管理员使用,而备份操作即使对于非管理员用户也可用。 第二个更重要的问题是,并非所有功能都有相应的服务或扩展 API,这些服务或扩展 API 可用于以类似的方式计算对该功能的支持。
这个问题在非 UI 领域也出现了。 考虑 OpenStack Heat 项目。 Heat 模板允许在模板中删除相应卷资源时备份卷的选项。 但是,由于无法知道 Cinder 部署是否支持备份功能,这可能会导致卷删除期间出现延迟故障。 这最终会阻止编排模板在云之间的互操作性。
很容易看出,上述问题不仅仅限于备份功能,而是更加普遍。 Horizon 需要一种以编程方式知道远程块存储服务支持哪些能力的方法,以便它可以仅启用处理这些能力的 UI 小部件并禁用其他小部件。
用例¶
此规范中提出的解决方案允许构建动态的、自配置的 Horizon UI。 这减轻了操作员手动配置 Horizon 并不断使其与 Cinder 部署的能力保持同步的负担。
此解决方案可以立即应用于解决 Horizon 中卷备份启用状态的问题。 操作员不再需要在 Horizon 配置中设置“enable_backup”; Horizon 将使用建议的 API 以编程方式获取状态。
复制功能也可以类似地受益,该功能仅受某些卷类型(实际上是“卷后端”,但通常卷后端或多或少与卷类型相关联)的支持。 请注意,该功能将由与列出备份功能的 API 不同的能力 API 列出。 详情如下。
建议的 API 集合也可以用于自定义 UI 或用户脚本,原因与我们设想 Horizon 使用它的原因相同。
提议的变更¶
一个新的、公共的块存储微版本 API,用于返回特定用户和资源的全部能力集合。 请注意,该服务(或部署本身)被视为一种资源(根资源)。
可以在多个级别定义系统的能力。 顶级能力(例如备份能力)在服务级别(或根资源级别)定义。 因此,“此 cinder 服务实例是否具有备份能力?”这个问题本身就有意义。 较低级别的能力在特定的(REST)资源上定义。 例如,复制功能在卷类型上定义。 因此,询问“此 cinder 服务实例是否具有复制能力?”是没有意义的; 相反,我们需要询问“卷类型 xyz 是否具有复制能力?”
虽然我们可以为每个资源定义一个能力 API,但在实践中,只有少数资源需要它。 对于 Cinder API,今天仅需要服务和卷类型资源。
不可能避免多个级别的能力 API。 较低级别的能力 API 需要输入(资源类型),这在顶级级别不可用。
不同级别的能力 API 也与任何 UI(例如 Horizon)的自然组织相一致。 在主页上,UI 仅显示与顶级能力对应的小部件。 可以通过选择主页上的小部件来导航到更深层次。 例如,选择特定的卷类型可以进入一个显示与该特定卷类型的功能对应的小部件的页面。 通过调用适当级别的能力 API,Horizon 可以在每个级别以编程方式配置自身。
请注意,cinder 实例可能实现特定功能,但可能不允许特定用户访问该功能。 因此,能力 API 不仅应考虑服务是否实现特定功能,还应考虑当前用户是否有权访问该功能。 “权限”信息已在 policy.json [4] 文件中可用,该文件将不同的操作映射到可以访问这些操作的用户。 因此,任何能力 API 实现都必须使用此文件。
检测特定部署/资源是否实现特定能力因能力本身而异。 对于备份能力,它可能是 cinder-backup 服务的存在。 对于复制功能,它可能是在创建卷类型时静态设置的,或者可以从驱动程序中获取。
不可能仅基于 policy.json [4] 文件中的信息来实现能力 API,因为策略文件不允许为每个资源定义规则。 例如,我们可以允许所有用户进行复制操作,但我们不能将其限制为特定的卷类型(这至关重要,因为并非所有卷类型都支持复制)。
很容易看出,所有能力 API 都应该是公共的,即任何用户都可以访问。
此 BP 的关键贡献是识别并提出一个 API 模式,即“每个资源一个能力 API”(当然,如果某些资源不需要它,我们就不需要为其定义能力 API)。 这个想法很简单但功能强大,并且可以在所有 OpenStack 项目中重用。
虽然此 BP 提出了一种 API 模式,但我们将仅实现顶级能力 API。 这将仅返回“volume-backup”,但可以随着 Cinder 在服务级别添加新的能力而进行扩展。 目前,备份能力检测将类似于 os-services 扩展。 它将通过检查 cinder 数据库中的服务表来检查 cinder-backup 服务是否启用,如果是,则在响应中返回“volume-backup”。
关于 Cinder 今天存在的类似能力 API 的简要说明:有一个“卷能力”扩展 API [6],但它是在服务级别定义的(/v2/{tenant_id}/capabilities/{hostname}),而不是在卷类型级别定义的。 “显示卷类型详细信息” API [8] 将能力塞入一个通用的“extra_specs”属性中。 如果此 BP 获得批准,我们需要将这些现有的 API 与将要定义的新的能力 API 进行协调。 这不在本次规范的范围内。
备选方案¶
使现有的 os-services 扩展公开:这将向租户公开私有云的内部信息。 这是一个安全漏洞,因此使这种替代方案不可行。 此外,能力和服务之间可能没有一一对应关系。
将现有的 os-services 扩展 API 分成公共和私有两部分,公共部分公开有限的信息。
我们可以修改 services:index 操作以采用 details=true/false 参数:http://{cinder-endpoint}/v2/{tenant-id}/os-services?details=false
并为 detail=true(admin_api)和 detail=false(“”即无限制)定义不同的策略。
“volume_extension:services:index_with_details”: “rule:admin_api”
“volume_extension:services:index_without_details”: “”
不清楚这是否可以以向后兼容的方式实现,以及是否是否有先例根据参数拆分单个 API 调用的策略。 此外,如上所述,能力和服务之间可能没有一一对应关系。
重用现有的“列出扩展”公共 API [7]。 这是 dulek 在 [2] 中提出的。 首先,能力和扩展之间可能没有一一对应关系(尽管对于卷备份情况而言确实如此)。 即使总是如此,操作员也需要修剪 cinder.conf(手动!),以便仅列出实际支持的扩展。 正如 [2] 中解释的那样,没有简单的方法可以做到这一点。 此外,正如 duncant 指出的那样,这会破坏现有的语义 - 许多部署启用了 API 扩展(默认情况下),但服务实际上并未运行。 因此,检查返回值在不同的系统上意味着不同的事情。
数据模型影响¶
没有。 正如解释的那样,我们使用现有的服务表进行卷备份能力检测。 未来的能力添加可能会使用不同的资源和算法。
REST API 影响¶
我们给出了三种资源“能力 API 模式”的实例,包括服务本身。
GET /v3.x/{tenant id}/capabilities返回底层块存储部署在服务级别的一组能力。
正常的 http 响应代码:200
响应是能力列表。 每个能力都是一个简单的名词或连字符连接的名词。 例如
{
"capabilities": [
{
"name": "volume-backup",
"description": "Allows creating backups of volumes."
},
{
"name": "other-capability",
"description": "Other capability description."
},
]
}
GET /v3.x/{tenant_id}/types/{volume_type_id}/capabilities返回特定卷类型的一组能力。
正常的 http 响应代码:200
响应是能力列表。 例如
{
"capabilities": [
{
"name": "replication",
"description": "Allows replication of volumes."
},
{
"name": "other-capability",
"description": "Other capability description."
},
]
}
通用示例
GET /v3.x/{tenant_id}/<some-resource-collection>/{some-resource-instance}/capabilities返回 some-resource-instance 的一组能力。
安全影响¶
没有。 公开一组抽象的系统能力应该是安全的。 无论如何,这些能力都可以从 UI 中的可用操作中获取(例如,备份 UI 小部件可见意味着存在卷备份能力)。
通知影响¶
无
其他最终用户影响¶
此更改对用户是透明的,尽管用户可以使用此 API 以类似于 Horizon 的方式进行自定义 UI 或管理脚本。
性能影响¶
这些是新的 API,不应影响任何现有的 API 或代码路径。
其他部署者影响¶
操作员不再需要在 Horizon 配置设置文件中手动设置“enable_backup”。 此 Horizon 配置更改的向后兼容性故事不在本次规范的范围内。
开发人员影响¶
开发人员需要了解能力 API 模式,并评估计划添加到 Cinder 服务或较低级别资源(例如卷类型)的任何新的可选功能是否可以通过此 API 公开受益。 开发人员可能首先需要为该资源定义一个能力 API。
实现¶
负责人¶
- 主要负责人
dramakri
工作项¶
在服务级别实现建议的公共微版本能力 API
至少实现备份能力检测
添加测试用例
更新 API 文档
依赖项¶
无
测试¶
需要添加单元和功能测试用例来验证此新的 API。
文档影响¶
Cinder 中的新 API 和客户端调用需要记录。
需要记录对 Horizon 配置的更改。