Use ‘LIKE’ operator to filter resource

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

This blueprint proposes changing some filter behaviour to use ‘LIKE’ expression on some columns(name, description, etc).

Problem description

Currently, we could only filter cinder resource by exact match, and this is not flexible enough when user would like to retrieve some resource whose name or attribute is partly alike, especially for the users who have lots of volumes. As it’s already introduced in many other projects, we can take advantage of those some existing mechanism, nova and ironic.

Use Cases

Possible use case is to support client bulk operation, collect the desired resources with single command.

Proposed change

Although we can provide filtering resource based on regex filter, but there is a possibility that we could have ReDos attack. Considering the ‘LIKE’ operator is flexible and safe enough for this case. We could only introduce ‘LIKE’ operator (‘NOT LIKE’ is another useful operator, but it’s not as common as ‘LIKE’). And we can easily apply this filter at the existing common filtering function individually with a decorator:

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

This spec intends to support ‘LIKE’ based filter on some specified resources and columns, as we would have the generalized resource filtering feature, this one will take advantage of that spec in order to make it configurable for administrators, so this is what we would finally have in our filters’ configuration file

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

‘~’ here means the attribute ‘name’ supports query with like operator (not indicating the regex operator), once this is configured, the input key-value pair name~=value from API will finally be translated into this sql statement:

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

so with that switch on, end user could filter volume with these inputs below:

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

assuming we have two volumes in the name of ‘volume_preserved_01’, ‘volume_preserved_02’, so with first command we will get none of them while last command would have both of them.

Alternatives

There is an option that we can deploy searchlight which mainly focus on various cloud resource querying, and that’s a more widely topic. But we should also consider the cloud environment that doesn’t have a searchlight.

Also, there is another option that user can gather all the raw data and do the filtering on their own, but it’s obviously that that is what we try to avoid, cause it costs a lot of unnecessary resource expense.

Data model impact

None

REST API impact

Microversion bump is required for this change.

Cinder-client impact

Help text will be updated to advertise this change.

Security impact

None

Notifications impact

None

Other end user impact

None

Performance Impact

None

Other deployer impact

None

Developer impact

None

Implementation

Assignee(s)

Primary assignee:

tommylikehu(tommylikehu@gmail.com)

Work Items

  • Update the generalized resource filtering logic to accept new symbol ‘~’ in config file.

  • Update target object’s common filter method.

  • Add related unit testcases

  • Update cinder-client and OSC.

Dependencies

Depended on generalized resource filtering

Testing

  • Add unit tests to cover filter process change.

Documentation Impact

Update API documentation.

References

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

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

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

resource filtering: https://review.openstack.org/#/c/441516/