match archive policy rule based on longest match

currently, we use the first archive policy rule that we match based
on querying the existing rules. this list of rules is unordered.
this patch explicitly orders rules by metric_pattern so match against
the longest match first.

Change-Id: I4cc99ccbf98c1920d46ae259c81275953e9bfb03
Co-Authored-By: Alejandro Comisario <alejandro@nubeliu.com>
Closes-bug: #1501344
This commit is contained in:
gordon chung
2015-09-30 16:09:34 -04:00
parent c2d7e06fe5
commit 5eb9baca68
5 changed files with 107 additions and 12 deletions

View File

@@ -152,13 +152,16 @@ match metric names.
An archive policy rule for example could be a mapping to default a medium archive
policy for any volume metric with a pattern matching `volume.*`. When a sample metric
is posted with a name of `volume.size`, that would match the pattern and the
rule applies and sets the archive policy to medium.
rule applies and sets the archive policy to medium. If multiple rules match,
the longest matching rule is taken. For example, if two rules exists which
match `*` and `disk.*`, a `disk.io.rate` metric would match the `disk.*` rule
rather than `*` rule.
To create a rule, the following API request should be used:
{{ scenarios['create-archive-policy-rule']['doc'] }}
The metric_pattern is used to pattern match so as some examples,
The `metric_pattern` is used to pattern match so as some examples,
- `*` matches anything
- `disk.*` matches disk.io
@@ -168,7 +171,8 @@ Once created, you can retrieve the rule information:
{{ scenarios['get-archive-policy-rule']['doc'] }}
It is also possible to list archive policy rules:
It is also possible to list archive policy rules. The result set is ordered by
the `metric_pattern`, in reverse alphabetical order:
{{ scenarios['list-archive-policy-rule']['doc'] }}

View File

@@ -165,7 +165,8 @@ class SQLAlchemyIndexer(indexer.IndexerDriver):
def list_archive_policy_rules(self):
session = self.engine_facade.get_session()
aps = session.query(ArchivePolicyRule).all()
aps = session.query(ArchivePolicyRule).order_by(
ArchivePolicyRule.metric_pattern.desc()).all()
session.expunge_all()
return aps

View File

@@ -25,21 +25,54 @@ tests:
# Attempt to create an archive policy rule
- name: create archive policy rule
- name: create archive policy rule1
url: /v1/archive_policy_rule
method: POST
request_headers:
content-type: application/json
x-roles: admin
data:
name: test_rule
name: test_rule1
metric_pattern: "*"
archive_policy_name: low
status: 201
response_json_paths:
$.metric_pattern: "*"
$.archive_policy_name: low
$.name: test_rule1
- name: create archive policy rule 2
url: /v1/archive_policy_rule
method: POST
request_headers:
content-type: application/json
x-roles: admin
data:
name: test_rule2
metric_pattern: "disk.foo.*"
archive_policy_name: low
status: 201
response_json_paths:
$.metric_pattern: disk.foo.*
$.archive_policy_name: low
$.name: test_rule
$.name: test_rule2
- name: create archive policy rule 3
url: /v1/archive_policy_rule
method: POST
request_headers:
content-type: application/json
x-roles: admin
data:
name: test_rule3
metric_pattern: "disk.*"
archive_policy_name: low
status: 201
response_json_paths:
$.metric_pattern: disk.*
$.archive_policy_name: low
$.name: test_rule3
# Attempt to create an invalid policy rule
@@ -115,6 +148,10 @@ tests:
- name: get archive policy rule
url: /v1/archive_policy_rule
status: 200
response_json_paths:
$.[0].metric_pattern: disk.foo.*
$.[1].metric_pattern: disk.*
$.[2].metric_pattern: "*"
- name: get unknown archive policy rule
url: /v1/archive_policy_rule/foo
@@ -123,14 +160,29 @@ tests:
# delete rule as non admin
- name: delete archive policy rule non admin
url: /v1/archive_policy_rule/test_rule
url: /v1/archive_policy_rule/test_rule1
method: DELETE
status: 403
# delete rule
- name: delete archive policy rule
url: /v1/archive_policy_rule/test_rule
- name: delete archive policy rule1
url: /v1/archive_policy_rule/test_rule1
method: DELETE
request_headers:
x-roles: admin
status: 204
- name: delete archive policy rule2
url: /v1/archive_policy_rule/test_rule2
method: DELETE
request_headers:
x-roles: admin
status: 204
- name: delete archive policy rule3
url: /v1/archive_policy_rule/test_rule3
method: DELETE
request_headers:
x-roles: admin
@@ -139,7 +191,7 @@ tests:
# delete again
- name: confirm delete archive policy rule
url: /v1/archive_policy_rule/test_rule
url: /v1/archive_policy_rule/test_rule1
method: DELETE
request_headers:
x-roles: admin

View File

@@ -32,6 +32,31 @@ tests:
archive_policy_name: cookies
status: 201
- name: create alt archive policy
url: /v1/archive_policy
method: POST
request_headers:
content-type: application/json
x-roles: admin
data:
name: cream
definition:
- granularity: 5 second
status: 201
- name: create alt archive policy rule
desc: extra rule that won't be matched
url: /v1/archive_policy_rule
method: POST
request_headers:
content-type: application/json
x-roles: admin
data:
name: test_ignore_rule
metric_pattern: "disk.*"
archive_policy_name: cream
status: 201
- name: get metric empty
url: /v1/metric
status: 200
@@ -176,4 +201,4 @@ tests:
- name: delete non existent metric
url: /v1/metric/foo
method: DELETE
status: 404
status: 404

View File

@@ -69,6 +69,19 @@ class TestIndexerDriver(tests_base.TestCase):
"low")
self.index.delete_metric(metric_id)
def test_list_ap_rules_ordered(self):
name = str(uuid.uuid4())
self.index.create_archive_policy(
archive_policy.ArchivePolicy(name, 0, {}))
self.index.create_archive_policy_rule('rule1', 'abc.*', name)
self.index.create_archive_policy_rule('rule2', 'abc.xyz.*', name)
self.index.create_archive_policy_rule('rule3', 'abc.xyz', name)
rules = self.index.list_archive_policy_rules()
self.assertEqual(3, len(rules))
self.assertEqual('abc.xyz.*', rules[0]['metric_pattern'])
self.assertEqual('abc.xyz', rules[1]['metric_pattern'])
self.assertEqual('abc.*', rules[2]['metric_pattern'])
def test_create_metric(self):
r1 = uuid.uuid4()
user = uuid.uuid4()