使用 ‘LIKE’ 操作符过滤资源

https://blueprints.launchpad.net/cinder/+spec/support-regexp-based-query

此蓝图建议修改某些过滤行为,在某些列(名称、描述等)上使用 ‘LIKE’ 表达式。

问题描述

目前,我们只能通过精确匹配来过滤 cinder 资源,当用户希望检索名称或属性部分相似的资源时,这不够灵活,特别是对于拥有大量卷的用户而言。正如在许多其他项目中已经介绍的那样,我们可以利用一些现有的机制,例如 novaironic

用例

可能的用例是支持客户端批量操作,通过单个命令收集所需的资源。

提议的变更

虽然我们可以提供基于正则表达式过滤资源的功能,但我们可能会遇到 ReDos 攻击的风险。考虑到 ‘LIKE’ 操作符对于这种情况来说既灵活又安全。我们只能引入 ‘LIKE’ 操作符(‘NOT LIKE’ 是另一个有用的操作符,但它不如 ‘LIKE’ 常用)。我们可以很容易地将此过滤器单独应用于现有的通用过滤函数,使用装饰器

@apply_like_filters(model=models.Volume)
def _process_volume_filters(query, filters):
    pass

此规范旨在支持在某些指定资源和列上基于 ‘LIKE’ 的过滤,由于我们将拥有通用的 资源过滤 功能,因此将利用该规范使其可配置,以便管理员进行配置,这是我们最终在过滤配置文件中将拥有的内容

{
    "volume_filters": ["availability_zone", "status", "name~"]
}

这里的 ‘~’ 表示属性 ‘name’ 支持使用 like 操作符进行查询(不表示正则表达式操作符),一旦配置,API 中的键值对 name~=value 将最终被翻译成此 sql 语句

# '%' is automatically appended at both sides
SELECT * FROM volumes
WHERE name LIKE '%value%'

因此,在启用该开关后,最终用户可以使用以下输入过滤卷

cinder list --filters name=volume_preserved   #exact matches
cinder list --filters name~=volume_preserved  #inexact matches

假设我们有两个名称为 ‘volume_preserved_01’、‘volume_preserved_02’ 的卷,那么使用第一个命令我们将无法获得任何一个,而最后一个命令将获得两者。

备选方案

我们还可以部署 searchlight,它主要关注各种云资源查询,这是一个更广泛的话题。但我们也应该考虑没有 searchlight 的云环境。

此外,用户还可以收集所有原始数据并自行进行过滤,但显然我们试图避免这种情况,因为它会造成大量的资源浪费。

数据模型影响

REST API 影响

此更改需要 microversion 升级。

Cinder 客户端影响

将更新帮助文本以宣传此更改。

安全影响

通知影响

其他最终用户影响

性能影响

其他部署者影响

开发人员影响

实现

负责人

主要负责人

tommylikehu(tommylikehu@gmail.com)

工作项

  • 更新通用的资源过滤逻辑,以接受配置文件中的新符号 ‘~’。

  • 更新目标对象的通用过滤方法。

  • 添加相关的单元测试用例

  • 更新 cinder-client 和 OSC。

依赖项

依赖于通用的 资源过滤

测试

  • 添加单元测试以覆盖过滤过程的更改。

文档影响

更新 API 文档。

参考资料

nova: https://review.openstack.org/#/c/45026/

ironic: https://review.openstack.org/#/c/266688/

reDos: https://en.wikipedia.org/wiki/ReDoS

资源过滤: https://review.openstack.org/#/c/441516/