Add possibility to get metrics for all projects
This is to enable ceilometer to get all the metrics from all projects the functionality is by default guarded by policy, which allows only admins to access. This policy is simlar for example to nova's policy for listing all servers. Change-Id: I5894328c816b5803a69e9786d33b81566612df40
This commit is contained in:
parent
c373d73290
commit
e5c561a4c4
@ -80,8 +80,8 @@ class MetricsController(rest.RestController):
|
||||
result[c.project_id][c.alarm_id][c.state] = c.value
|
||||
return result
|
||||
|
||||
@wsme_pecan.wsexpose(MetricsOutput)
|
||||
def get_all(self):
|
||||
@wsme_pecan.wsexpose(MetricsOutput, bool)
|
||||
def get_all(self, all_projects=False):
|
||||
"""Return all metrics"""
|
||||
if not pecan.request.cfg.enable_evaluation_results_metrics:
|
||||
raise base.ClientSideError(_(
|
||||
@ -91,16 +91,23 @@ class MetricsController(rest.RestController):
|
||||
project_id = pecan.request.headers.get('X-Project-Id')
|
||||
target = {"project_id": project_id}
|
||||
|
||||
rbac.enforce('get_metrics', pecan.request.headers,
|
||||
pecan.request.enforcer, target)
|
||||
counters = []
|
||||
LOG.debug('Getting evaluation result counters from database')
|
||||
if all_projects is True:
|
||||
rbac.enforce('get_metrics:all_projects', pecan.request.headers,
|
||||
pecan.request.enforcer, target)
|
||||
counters = pecan.request.storage.get_alarm_counters()
|
||||
else:
|
||||
rbac.enforce('get_metrics', pecan.request.headers,
|
||||
pecan.request.enforcer, target)
|
||||
counters = pecan.request.storage.get_alarm_counters(
|
||||
project_id=project_id
|
||||
)
|
||||
|
||||
content = MetricsOutput()
|
||||
alarm_states = [evaluator.UNKNOWN, evaluator.OK, evaluator.ALARM]
|
||||
|
||||
LOG.debug('Getting evaluation result counters from database')
|
||||
grouped_counters = self.group_counters(
|
||||
pecan.request.storage.get_alarm_counters(project_id=project_id)
|
||||
)
|
||||
grouped_counters = self.group_counters(counters)
|
||||
evaluation_results = []
|
||||
for project, alarms in grouped_counters.items():
|
||||
for alarm, states in alarms.items():
|
||||
|
@ -342,6 +342,18 @@ rules = [
|
||||
}
|
||||
]
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name="telemetry:get_metrics:all_projects",
|
||||
check_str=PROJECT_ADMIN,
|
||||
scope_types=['project'],
|
||||
description='Get all metrics from all projects.',
|
||||
operations=[
|
||||
{
|
||||
'path': '/v2/metrics',
|
||||
'method': 'GET'
|
||||
}
|
||||
]
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
import os
|
||||
import webtest
|
||||
|
||||
@ -58,7 +59,9 @@ class TestMetrics(v2.FunctionalTest):
|
||||
def setUp(self):
|
||||
super(TestMetrics, self).setUp()
|
||||
self.project_id = "some_project_id"
|
||||
self.project_id2 = "some_project_id2"
|
||||
self.alarm_id = "some_alarm_id"
|
||||
self.alarm_id2 = "some_alarm_id2"
|
||||
self.user_id = "some_user_id"
|
||||
self.role = "reader"
|
||||
self.auth_headers = {'X-User-Id': self.user_id,
|
||||
@ -69,6 +72,11 @@ class TestMetrics(v2.FunctionalTest):
|
||||
self.project_id,
|
||||
self.user_id)
|
||||
)
|
||||
self.alarm_conn.create_alarm(getTestAlarm(
|
||||
self.alarm_id2,
|
||||
self.project_id2,
|
||||
self.user_id)
|
||||
)
|
||||
self.alarm_conn.increment_alarm_counter(
|
||||
self.alarm_id,
|
||||
self.project_id,
|
||||
@ -84,6 +92,11 @@ class TestMetrics(v2.FunctionalTest):
|
||||
self.project_id,
|
||||
"insufficient_data"
|
||||
)
|
||||
self.alarm_conn.increment_alarm_counter(
|
||||
self.alarm_id2,
|
||||
self.project_id2,
|
||||
"alarm"
|
||||
)
|
||||
|
||||
def test_get_all_metrics_inside_project(self):
|
||||
expected = {
|
||||
@ -118,3 +131,46 @@ class TestMetrics(v2.FunctionalTest):
|
||||
self.assertEqual(403, response.status_code)
|
||||
self.assertEqual(faultstring,
|
||||
response.json['error_message']['faultstring'])
|
||||
|
||||
def test_get_all_metrics_all_projects(self):
|
||||
auth_headers = copy.copy(self.auth_headers)
|
||||
auth_headers['X-Roles'] = 'admin'
|
||||
expected = {
|
||||
"evaluation_results": [{
|
||||
"alarm_id": self.alarm_id,
|
||||
"project_id": self.project_id,
|
||||
"state_counters": {
|
||||
"ok": 1,
|
||||
"insufficient data": 2,
|
||||
"alarm": 0
|
||||
}
|
||||
}, {
|
||||
"alarm_id": self.alarm_id2,
|
||||
"project_id": self.project_id2,
|
||||
"state_counters": {
|
||||
"ok": 0,
|
||||
"insufficient data": 0,
|
||||
"alarm": 1
|
||||
}
|
||||
}]
|
||||
}
|
||||
metrics = self.get_json(
|
||||
'/metrics?all_projects=true',
|
||||
headers=auth_headers,
|
||||
)
|
||||
self.assertEqual(expected, metrics)
|
||||
|
||||
def test_get_all_metrics_all_projects_forbidden(self):
|
||||
pf = os.path.abspath('aodh/tests/functional/api/v2/policy.yaml-test')
|
||||
self.CONF.set_override('policy_file', pf, group='oslo_policy')
|
||||
self.CONF.set_override('auth_mode', None, group='api')
|
||||
self.app = webtest.TestApp(app.load_app(self.CONF))
|
||||
|
||||
response = self.get_json('/metrics?all_projects=true',
|
||||
expect_errors=True,
|
||||
status=403,
|
||||
headers=self.auth_headers)
|
||||
faultstring = 'RBAC Authorization Failed'
|
||||
self.assertEqual(403, response.status_code)
|
||||
self.assertEqual(faultstring,
|
||||
response.json['error_message']['faultstring'])
|
||||
|
Loading…
x
Reference in New Issue
Block a user