允许对实例进行简单的字符串标记¶
https://blueprints.launchpad.net/nova/+spec/tag-instances
此蓝图旨在为 Nova 域模型中的实例对象添加一个简单的字符串标记机制的支持。
问题描述¶
在大多数流行的 REST API 接口中,领域模型中的对象可以用零个或多个简单的字符串“标记”。然后可以使用这些字符串来对领域模型中的对象进行分组和分类。
为了使 Nova 的 REST API 与互联网上对 资源标记 的常见理解保持一致,我们可以添加一个 API 微版本,允许普通用户为实例添加、删除和列出标签。
用例¶
典型的最终用户希望将一组字符串附加到实例。用户不希望使用键/值对来标记实例中的一些简单字符串。
项目优先级¶
无
提议的变更¶
没有对现有的元数据、system_metadata 或 extra_specs 功能进行任何更改的提议。这专门用于添加一个新的 API,以便普通用户能够用简单的字符串标记他们的实例。
添加一个 API 微版本,允许用户为实例添加、删除和列出标签。
添加一个 API 微版本,以允许基于一个或多个字符串标签搜索实例。
备选方案¶
Nova 通过实例元数据键/值对 API 扩展已经提供了简单字符串标记的替代方案。但使用元数据进行标记并不完全正确。标签经常与元数据混淆。虽然两者之间存在交叉点,但标签的主要功能是将实体集合分类成组,而元数据用于附加有关实体的附加信息。
数据模型影响¶
nova.objects.instance.Instance 对象将拥有一个新的 tags 字段,类型为 nova.objects.fields.ListOfStrings,该字段将按需填充(即延迟加载)。
标签应定义为不超过 60 字节的 Unicode 字节字符串。(此长度完全是任意的,可以根据审查讨论减少或扩展……)
标签是一个不透明的字符串,不打算被 virt 驱动程序解释或甚至读取。在下面的 REST API 更改中,标签中的非 URL 安全字符需要在 URI 中进行 url 编码(例如,执行 DELETE /servers/{server}/tags/{tag} 时,{tag} 需要进行 url 编码)。
注意
Glance 已经具有对象标记功能,并且该项目中的数据库模式对标签值使用 VARCHAR(255) 长度。我更希望保持小于 255 的长度。有许多性能原因(包括 MySQL 在执行聚合和包含 varchar 列的临时表时会将所有 varchar 列转换为固定宽度列)。此外,如果标签是 UTF-8(如上文建议),则 255 的宽度实际上将是 765 字节(这加剧了 MySQL 上的固定宽度问题)。
对于数据库模式,以下表结构就足够了
CREATE TABLE tags (
resource_id CHAR(32) NOT NULL PRIMARY KEY,
tag VARCHAR(60) NOT NULL CHARACTER SET utf8
COLLATION utf8_ci PRIMARY KEY,
CONSTRAINT resource_tag_constraint UNIQUE (resource_id, tag),
deleted_at DATETIME,
deleted INT DEFAULT 0
);
服务器上用户可以使用标签的数量应有一个新的硬编码限制 50。此时无需使其可配置或使用配额系统。
REST API 影响¶
此提议将添加一个 API 微版本,用于检索和设置实例上的标签。此外,它将添加一个 API 微版本,以允许基于一个或多个字符串标签搜索/列出实例。
标签 CRUD 操作 API 微版本如下所示
服务器的标签列表将与服务器详细信息一起返回
GET /servers/{server_id}
响应
{
'id': {server_id},
... other server resource properties ...
'tags': ['foo', 'bar', 'baz']
}
仅获取指定服务器的标签列表
GET /servers/{server_id}/tags
响应
{
'tags': ['foo', 'bar', 'baz']
}
替换服务器上的标签集
PUT /servers/{server_id}/tags
请求负载为
{
'tags': ['foo', 'bar', 'baz']
}
响应
{
'tags': ['foo', 'bar', 'baz']
}
如果标签数量超过服务器上的标签限制,应返回 400 Bad Request
在服务器上添加单个标签
PUT /servers/{server_id}/tags/{tag}
返回 201 Created。
如果标签已存在,则不会引发错误,它只是返回 204 No Content
如果标签数量将超过服务器限制,应返回 400 Bad Request
检查服务器上是否存在标签
GET /servers/{server_id}/tags/{tag}
如果服务器上存在标签,则返回 204 No Content
如果服务器上不存在标签,则返回 404 Not Found
从服务器上删除单个标签
DELETE /servers/{server_id}/tags/{tag}
成功后返回 204 No Content。如果您尝试删除不存在的标签,则返回 404 Not Found。
从服务器上删除所有标签
DELETE /servers/{server_id}/tags
返回 204 No Content。
允许搜索/过滤 GET /servers REST API 调用的 API 微版本将添加以下查询参数
tags
tags-any
not-tags
not-tags-any
要请求具有单个标签的服务器列表,应将 tags 参数设置为所需的标签名称。示例
GET /servers?tags=red
要请求具有两个或多个标签的服务器列表,应将 tags 参数设置为用逗号分隔的标签列表。在这种情况下,要包含在查询结果中,服务器必须同时存在所有给定的标签。一个返回具有“red”和“blue”标签的服务器的示例
GET /servers?tags=red,blue
要请求具有给定标签列表中一个或多个标签的服务器列表,应将 tags-any 参数设置为用逗号分隔的标签列表。在这种情况下,只要存在一个给定的标签,服务器就会包含在查询结果中。一个返回具有“red”或“blue”标签的服务器的示例
GET /servers?tags-any=red,blue
要请求不具有一个或多个标签的服务器列表,应将 not-tags 参数设置为用逗号分隔的标签列表。在这种情况下,只有不具有任何给定标签的服务器才会包含在查询结果中。一个返回不具有“red”或“blue”标签的服务器的示例
GET /servers?not-tags=red,blue
要请求不具有给定标签列表中至少一个标签的服务器列表,应将 not-tags-any 参数设置为用逗号分隔的标签列表。在这种情况下,只有不具有给定标签中至少一个标签的服务器才会包含在查询结果中。一个返回不具有“red”标签或不具有“blue”标签的服务器的示例
GET /servers?not-tags-any=red,blue
可以将 tags、tags-any、not-tags 和 not-tags-any 参数组合起来以构建更复杂的查询。示例
GET /servers?tags=red,blue&tags-any=green,orange
上面的示例返回具有“red”和“blue”标签以及“green”和“orange”标签中的至少一个的任何服务器。
复杂的查询可能具有矛盾的参数。示例
GET /servers?tags=blue¬-tags=blue
在这种情况下,我们应该让 Nova 找到这些服务器。显然没有这样的服务器,Nova 将返回一个空列表。
不需要对 GET /servers/ 调用的 JSON 响应进行任何更改。
安全影响¶
无
通知影响¶
无
其他最终用户影响¶
无
性能影响¶
没有,尽管某些字段上的基于 REGEXP 的查询可能会被修改为使用更快的标签列表过滤查询。
其他部署者影响¶
无
开发人员影响¶
无
实现¶
请参阅下面的 工作项目 部分。
负责人¶
- 主要负责人
snikitin
- 其他贡献者
jaypipes
工作项¶
更改将按顺序进行到
数据库 API 层以添加对实例标签上 CRUD 操作的支持(完成)
数据库 API 层以将标签列表过滤支持添加到 instance_get_all_by_filters
nova.objects 层以添加对 Instance 对象标签字段的支持
添加数据库迁移以更新标签表以使其可软删除
更新 Tag 模型以继承 SoftDeleteMixin
标签 CRUD 操作的 API 微版本
依赖项¶
无。
测试¶
需要新的 Tempest 和单元测试。
文档影响¶
需要新的 API 微版本和用量文档。
参考资料¶
邮件列表讨论
http://lists.openstack.org/pipermail/openstack-dev/2014-April/033222.html http://lists.openstack.org/pipermail/openstack-dev/2014-April/034004.html
标记指南
https://specs.openstack.org/openstack/api-wg/guidelines/tags.html