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:
@@ -67,6 +67,9 @@ MONASCA_EXTRA_SCHEMA = {
|
|||||||
All(str, Length(min=1)),
|
All(str, Length(min=1)),
|
||||||
Required('aggregation_method', default='max'):
|
Required('aggregation_method', default='max'):
|
||||||
In(['max', 'mean', 'min']),
|
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
|
period = end - start
|
||||||
|
|
||||||
extra_args = self.conf[metric_name]['extra_args']
|
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(
|
return self._conn.metrics.list_statistics(
|
||||||
name=metric_name,
|
name=metric_name,
|
||||||
merge_metrics=True,
|
merge_metrics=True,
|
||||||
@@ -185,7 +192,8 @@ class MonascaCollector(collector.BaseCollector):
|
|||||||
end_time=ck_utils.ts2dt(end),
|
end_time=ck_utils.ts2dt(end),
|
||||||
period=period,
|
period=period,
|
||||||
statistics=extra_args['aggregation_method'],
|
statistics=extra_args['aggregation_method'],
|
||||||
group_by=group_by)
|
group_by=group_by,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
def _fetch_metrics(self, metric_name, start, end,
|
def _fetch_metrics(self, metric_name, start, end,
|
||||||
project_id=None, q_filter=None):
|
project_id=None, q_filter=None):
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#
|
#
|
||||||
import decimal
|
import decimal
|
||||||
|
|
||||||
|
from keystoneauth1 import session as ks_sess
|
||||||
import mock
|
import mock
|
||||||
from oslo_config import fixture as config_fixture
|
from oslo_config import fixture as config_fixture
|
||||||
from oslotest import base
|
from oslotest import base
|
||||||
@@ -82,7 +83,7 @@ class TestCase(testscenarios.TestWithScenarios, base.BaseTestCase):
|
|||||||
self.auth = auth
|
self.auth = auth
|
||||||
session = mock.patch(
|
session = mock.patch(
|
||||||
'keystoneauth1.loading.load_session_from_conf_options',
|
'keystoneauth1.loading.load_session_from_conf_options',
|
||||||
return_value=dict())
|
return_value=ks_sess.Session())
|
||||||
session.start()
|
session.start()
|
||||||
self.session = session
|
self.session = session
|
||||||
|
|
||||||
|
|||||||
100
cloudkitty/tests/collectors/test_monasca.py
Normal file
100
cloudkitty/tests/collectors/test_monasca.py
Normal 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',
|
||||||
|
)
|
||||||
@@ -97,6 +97,7 @@ class MetricConfigValidationTest(tests.TestCase):
|
|||||||
expected_output['metric_one']['extra_args'] = {
|
expected_output['metric_one']['extra_args'] = {
|
||||||
'aggregation_method': 'max',
|
'aggregation_method': 'max',
|
||||||
'resource_key': 'resource_id',
|
'resource_key': 'resource_id',
|
||||||
|
'forced_project_id': '',
|
||||||
}
|
}
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
|
|||||||
@@ -64,6 +64,13 @@ Section: ``collector_monasca``.
|
|||||||
* ``monasca_service_name``: Defaults to ``monasca``. Name of the Monasca
|
* ``monasca_service_name``: Defaults to ``monasca``. Name of the Monasca
|
||||||
service in Keystone.
|
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
|
Prometheus
|
||||||
----------
|
----------
|
||||||
@@ -259,6 +266,12 @@ Monasca
|
|||||||
when retrieving measures from monasca. Must be one of ``min``, ``max``,
|
when retrieving measures from monasca. Must be one of ``min``, ``max``,
|
||||||
``mean``.
|
``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
|
Prometheus
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
Reference in New Issue
Block a user