Add an option for the metric project to the Monasca collector

In case metrics are not available from within the project cloudkitty is
identified in, the project to fetch a specific metric can now be
specified in the metric's extra_args.

Change-Id: I722377a0df5586977184518733fe1cff341ad68f
This commit is contained in:
Luka Peschke
2019-06-18 11:33:38 +02:00
parent f02196f8a6
commit b88c937891
6 changed files with 130 additions and 2 deletions

View File

@@ -67,6 +67,9 @@ MONASCA_EXTRA_SCHEMA = {
All(str, Length(min=1)),
Required('aggregation_method', default='max'):
In(['max', 'mean', 'min']),
# In case the metrics in Monasca do not belong to the project
# cloudkitty is identified in
Required('forced_project_id', default=''): str,
},
}
@@ -177,6 +180,10 @@ class MonascaCollector(collector.BaseCollector):
period = end - start
extra_args = self.conf[metric_name]['extra_args']
kwargs = {}
if extra_args['forced_project_id']:
kwargs['tenant_id'] = extra_args['forced_project_id']
return self._conn.metrics.list_statistics(
name=metric_name,
merge_metrics=True,
@@ -185,7 +192,8 @@ class MonascaCollector(collector.BaseCollector):
end_time=ck_utils.ts2dt(end),
period=period,
statistics=extra_args['aggregation_method'],
group_by=group_by)
group_by=group_by,
**kwargs)
def _fetch_metrics(self, metric_name, start, end,
project_id=None, q_filter=None):

View File

@@ -17,6 +17,7 @@
#
import decimal
from keystoneauth1 import session as ks_sess
import mock
from oslo_config import fixture as config_fixture
from oslotest import base
@@ -82,7 +83,7 @@ class TestCase(testscenarios.TestWithScenarios, base.BaseTestCase):
self.auth = auth
session = mock.patch(
'keystoneauth1.loading.load_session_from_conf_options',
return_value=dict())
return_value=ks_sess.Session())
session.start()
self.session = session

View File

@@ -0,0 +1,100 @@
# Copyright 2019 Objectif Libre
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
import datetime
import mock
from cloudkitty.collector import monasca as mon_collector
from cloudkitty import tests
from cloudkitty import transformer
from cloudkitty import utils
class MonascaCollectorTest(tests.TestCase):
def setUp(self):
super(MonascaCollectorTest, self).setUp()
self.conf.set_override('collector', 'monasca', 'collect')
conf = {
'metrics': {
'metric_one': {
'unit': 'GiB',
'groupby': ['project_id'],
'extra_args': {
'aggregation_method': 'max',
},
},
'metric_two': {
'unit': 'MiB',
'groupby': ['project_id'],
'extra_args': {
'aggregation_method': 'max',
'forced_project_id': 'project_x'
},
},
}
}
with mock.patch(
'cloudkitty.collector.monasca.'
'MonascaCollector._get_monasca_endpoint',
return_value='http://noop'):
self.collector = mon_collector.MonascaCollector(
transformer.get_transformers(),
period=3600,
conf=conf,
)
def test_fetch_measures_kwargs_no_forced_project(self):
with mock.patch.object(self.collector._conn.metrics,
'list_statistics') as m:
start = datetime.datetime(2019, 1, 1)
end = datetime.datetime(2019, 1, 1, 1)
self.collector._fetch_measures(
'metric_one',
utils.dt2ts(start),
utils.dt2ts(end),
)
m.assert_called_once_with(
name='metric_one',
merge_metrics=True,
dimensions={},
start_time=start,
end_time=end,
period=3600,
statistics='max',
group_by=['project_id', 'resource_id'],
)
def test_fetch_measures_kwargs_with_forced_project(self):
with mock.patch.object(self.collector._conn.metrics,
'list_statistics') as m:
start = datetime.datetime(2019, 1, 1)
end = datetime.datetime(2019, 1, 1, 1)
self.collector._fetch_measures(
'metric_two',
utils.dt2ts(start),
utils.dt2ts(end),
)
m.assert_called_once_with(
name='metric_two',
merge_metrics=True,
dimensions={},
start_time=start,
end_time=end,
period=3600,
statistics='max',
group_by=['project_id', 'resource_id'],
tenant_id='project_x',
)

View File

@@ -97,6 +97,7 @@ class MetricConfigValidationTest(tests.TestCase):
expected_output['metric_one']['extra_args'] = {
'aggregation_method': 'max',
'resource_key': 'resource_id',
'forced_project_id': '',
}
self.assertEqual(

View File

@@ -64,6 +64,13 @@ Section: ``collector_monasca``.
* ``monasca_service_name``: Defaults to ``monasca``. Name of the Monasca
service in Keystone.
.. note:: By default, cloudkitty retrieves all metrics from Monasca in the
project it is identified in. However, some metrics may need to be
fetched from another tenant (for example if ceilometer is publishing
metrics to monasca in the ``service`` tenant but monasca-agent is
publishing metrics to the ``admin`` tenant). See the monasca-specific
section in "Metric collection" below for details on how to configure
this.
Prometheus
----------
@@ -259,6 +266,12 @@ Monasca
when retrieving measures from monasca. Must be one of ``min``, ``max``,
``mean``.
* ``forced_project_id``: Defaults to None. Force the given metric to be
fetched from a specific tenant instead of the one cloudkitty is identified
in. For example, if cloudkitty is identified in the ``service`` project, but
needs to fetch a metric from the ``admin`` project, its ID should be
specified through this option.
Prometheus
~~~~~~~~~~

View File

@@ -0,0 +1,5 @@
---
features:
- |
It is now possible to force a project_id to retrieve a specific metric
from it with the monasca collector.