Monasca Ceilometer in sync with Ceilometer master
Following changes are necessary to keep monasca-ceilometer in sync with Ceilometer upstream * Remove api/health.py (since ceilometer v2 api was removed) * Remove storage/impl_monasca.py (since ceilometer storage drivers were removed) * Updated opts.py and service.py (to keep in sync with ceilometer master) * removed api, storage driver tests * updated /etc/ceilometer/ceilometer.conf with new [monasca] options Change-Id: I044f3e512db52a128bac8d5c5dcac76549a3b1c2
This commit is contained in:
parent
e81be04ef7
commit
4a2c73685f
|
@ -1,81 +0,0 @@
|
|||
#
|
||||
# (c) Copyright 2018 SUSE LLC
|
||||
#
|
||||
# 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.
|
||||
|
||||
from oslo_log import log
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
def filter_factory(global_config, **local_conf):
|
||||
"""Returns a WSGI Filter."""
|
||||
conf = global_config.copy()
|
||||
conf.update(local_conf)
|
||||
LOG.debug('Filter Factory')
|
||||
|
||||
def health_filter(app):
|
||||
return HealthFilterApi(app, conf)
|
||||
return health_filter
|
||||
|
||||
|
||||
class HealthFilterApi(object):
|
||||
|
||||
def __init__(self, app, conf):
|
||||
self.conf = conf
|
||||
self.app = app
|
||||
self.db = None
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
"""Handle the incoming request and filters it.
|
||||
|
||||
Interjects the request and acts on it only if
|
||||
it is related to the filter functionality, otherwise
|
||||
it just let the request pass through to the app.
|
||||
|
||||
"""
|
||||
|
||||
LOG.debug('Health Check Filter')
|
||||
|
||||
if environ['PATH_INFO'].startswith('/v2/health'):
|
||||
response_code = '204 No Content'
|
||||
if environ['REQUEST_METHOD'] != 'HEAD':
|
||||
response_code = '200 OK'
|
||||
# Commenting out healthcheck behavior when request method
|
||||
# is not of type HEAD.# As it creates load on monasca vertica
|
||||
# FIXME: fix this when monasca creates get versions api in
|
||||
# in Monascaclient. USe that instead
|
||||
# try:
|
||||
# if not self.db:
|
||||
# self.db = storage.get_connection_from_config(cfg.CONF)
|
||||
# meters = self.db.get_meters(unique=True, limit=1)
|
||||
# if not meters:
|
||||
# response_code = '503 Backend Unavailable'
|
||||
# except Exception as e:
|
||||
# response_code = '503 Backend Unavailable'
|
||||
# LOG.warning('DB health check connection failed: %s', e)
|
||||
# self.db = None
|
||||
resp = MiniResp(response_code, environ)
|
||||
start_response(response_code, resp.headers)
|
||||
return resp.body
|
||||
else:
|
||||
return self.app(environ, start_response)
|
||||
|
||||
|
||||
class MiniResp(object):
|
||||
|
||||
def __init__(self, message, env, headers=[]):
|
||||
if env['REQUEST_METHOD'] == 'HEAD':
|
||||
self.body = ['']
|
||||
else:
|
||||
self.body = [message]
|
||||
self.headers = list(headers)
|
|
@ -104,11 +104,17 @@ OPTS = [
|
|||
'Monasca. These include metrics that failed to '
|
||||
'publish on first attempt and failed metrics that'
|
||||
' maxed out their retries.'),
|
||||
|
||||
# from impl_monasca
|
||||
cfg.IntOpt('default_stats_period',
|
||||
default=300,
|
||||
help='Default period (in seconds) to use for querying stats '
|
||||
'in case no period specified in the stats API call.'),
|
||||
cfg.IntOpt('database_max_retries',
|
||||
default=3,
|
||||
help='Maximum number of retry attempts of connecting to '
|
||||
'database failure.'),
|
||||
cfg.IntOpt('database_retry_interval',
|
||||
default=60,
|
||||
help='Frequency of attempting a retry connecting to database'),
|
||||
|
||||
]
|
||||
|
|
|
@ -54,8 +54,8 @@ class Client(object):
|
|||
|
||||
def __init__(self, conf, parsed_url):
|
||||
self.conf = conf
|
||||
self._retry_interval = self.conf.database.retry_interval
|
||||
self._max_retries = self.conf.database.max_retries or 1
|
||||
self._retry_interval = self.conf.monasca.database_retry_interval
|
||||
self._max_retries = self.conf.monasca.database_max_retries or 1
|
||||
# enable monasca api pagination
|
||||
self._enable_api_pagination = self.conf.monasca.enable_api_pagination
|
||||
# NOTE(zqfan): There are many concurrency requests while using
|
||||
|
|
|
@ -18,25 +18,15 @@ import socket
|
|||
from keystoneauth1 import loading
|
||||
from oslo_config import cfg
|
||||
|
||||
import ceilometer.agent.manager
|
||||
import ceilometer.api.app
|
||||
import ceilometer.api.controllers.v2.root
|
||||
import ceilometer.collector
|
||||
import ceilometer.compute.discovery
|
||||
import ceilometer.compute.virt.inspector
|
||||
import ceilometer.compute.virt.libvirt.utils
|
||||
import ceilometer.compute.virt.vmware.inspector
|
||||
import ceilometer.compute.virt.xenapi.inspector
|
||||
import ceilometer.dispatcher
|
||||
import ceilometer.dispatcher.file
|
||||
import ceilometer.dispatcher.gnocchi_opts
|
||||
import ceilometer.dispatcher.http
|
||||
import ceilometer.event.converter
|
||||
import ceilometer.exchange_control
|
||||
import ceilometer.hardware.discovery
|
||||
import ceilometer.hardware.pollsters.generic
|
||||
import ceilometer.image.discovery
|
||||
import ceilometer.ipmi.notifications.ironic
|
||||
import ceilometer.ipmi.platform.intel_node_manager
|
||||
import ceilometer.ipmi.pollsters
|
||||
import ceilometer.keystone_client
|
||||
|
@ -48,11 +38,11 @@ import ceilometer.notification
|
|||
import ceilometer.nova_client
|
||||
import ceilometer.objectstore.rgw
|
||||
import ceilometer.objectstore.swift
|
||||
import ceilometer.pipeline
|
||||
import ceilometer.pipeline.base
|
||||
import ceilometer.polling.manager
|
||||
import ceilometer.publisher.messaging
|
||||
import ceilometer.publisher.utils
|
||||
import ceilometer.sample
|
||||
import ceilometer.storage
|
||||
import ceilometer.utils
|
||||
import ceilometer.volume.discovery
|
||||
|
||||
|
@ -82,22 +72,14 @@ def list_opts():
|
|||
# This have been removed due to a recursive import issue
|
||||
return [
|
||||
('DEFAULT',
|
||||
itertools.chain(ceilometer.agent.manager.OPTS,
|
||||
ceilometer.api.app.OPTS,
|
||||
itertools.chain(ceilometer.polling.manager.OPTS,
|
||||
ceilometer.compute.virt.inspector.OPTS,
|
||||
ceilometer.compute.virt.libvirt.utils.OPTS,
|
||||
ceilometer.dispatcher.OPTS,
|
||||
ceilometer.ipmi.notifications.ironic.OPTS,
|
||||
ceilometer.nova_client.OPTS,
|
||||
ceilometer.objectstore.swift.OPTS,
|
||||
ceilometer.pipeline.OPTS,
|
||||
ceilometer.pipeline.base.OPTS,
|
||||
ceilometer.sample.OPTS,
|
||||
ceilometer.utils.OPTS,
|
||||
ceilometer.exchange_control.EXCHANGE_OPTS,
|
||||
OPTS)),
|
||||
('api', itertools.chain(ceilometer.api.app.API_OPTS,
|
||||
ceilometer.api.controllers.v2.root.API_OPTS)),
|
||||
('collector', ceilometer.collector.OPTS),
|
||||
('compute', ceilometer.compute.discovery.OPTS),
|
||||
('coordination', [
|
||||
cfg.StrOpt(
|
||||
|
@ -113,11 +95,28 @@ def list_opts():
|
|||
help='Number of seconds between checks to see if group '
|
||||
'membership has changed'),
|
||||
]),
|
||||
('database', ceilometer.storage.OPTS),
|
||||
('dispatcher_file', ceilometer.dispatcher.file.OPTS),
|
||||
('dispatcher_http', ceilometer.dispatcher.http.http_dispatcher_opts),
|
||||
('dispatcher_gnocchi',
|
||||
ceilometer.dispatcher.gnocchi_opts.dispatcher_opts),
|
||||
('dispatcher_gnocchi', (
|
||||
cfg.StrOpt(
|
||||
'filter_project',
|
||||
deprecated_for_removal=True,
|
||||
default='gnocchi',
|
||||
help='Gnocchi project used to filter out samples '
|
||||
'generated by Gnocchi service activity'),
|
||||
cfg.StrOpt(
|
||||
'archive_policy',
|
||||
deprecated_for_removal=True,
|
||||
help='The archive policy to use when the dispatcher '
|
||||
'create a new metric.'),
|
||||
cfg.StrOpt(
|
||||
'resources_definition_file',
|
||||
deprecated_for_removal=True,
|
||||
default='gnocchi_resources.yaml',
|
||||
help=('The Yaml file that defines mapping between samples '
|
||||
'and gnocchi resources/metrics')),
|
||||
cfg.FloatOpt(
|
||||
'request_timeout', default=6.05, min=0.0,
|
||||
deprecated_for_removal=True,
|
||||
help='Number of seconds before request to gnocchi times out'))),
|
||||
('event', ceilometer.event.converter.OPTS),
|
||||
('hardware', itertools.chain(
|
||||
ceilometer.hardware.discovery.OPTS,
|
||||
|
@ -130,7 +129,7 @@ def list_opts():
|
|||
('notification',
|
||||
itertools.chain(ceilometer.notification.OPTS,
|
||||
ceilometer.notification.EXCHANGES_OPTS)),
|
||||
('polling', ceilometer.agent.manager.POLLING_OPTS),
|
||||
('polling', ceilometer.polling.manager.POLLING_OPTS),
|
||||
('publisher', ceilometer.publisher.utils.OPTS),
|
||||
('publisher_notifier', ceilometer.publisher.messaging.NOTIFIER_OPTS),
|
||||
('rgw_admin_credentials', ceilometer.objectstore.rgw.CREDENTIAL_OPTS),
|
||||
|
|
|
@ -16,13 +16,10 @@
|
|||
import sys
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_db import options as db_options
|
||||
import oslo_i18n
|
||||
from oslo_log import log
|
||||
from oslo_policy import opts as policy_opts
|
||||
# from oslo_reports import guru_meditation_report as gmr
|
||||
|
||||
from ceilometer.conf import defaults
|
||||
from ceilometer import keystone_client
|
||||
from ceilometer import messaging
|
||||
from ceilometer import opts
|
||||
|
@ -48,9 +45,6 @@ def prepare_service(argv=None, config_files=None, conf=None):
|
|||
['futurist=INFO', 'neutronclient=INFO',
|
||||
'keystoneclient=INFO'])
|
||||
log.set_defaults(default_log_levels=log_levels)
|
||||
defaults.set_cors_middleware_defaults()
|
||||
policy_opts.set_defaults(conf)
|
||||
db_options.set_defaults(conf)
|
||||
|
||||
conf(argv[1:], project='ceilometer', validate_default_values=True,
|
||||
version=version.version_info.version_string(),
|
||||
|
@ -62,11 +56,6 @@ def prepare_service(argv=None, config_files=None, conf=None):
|
|||
utils.setup_root_helper(conf)
|
||||
sample.setup(conf)
|
||||
|
||||
# NOTE(liusheng): guru cannot run with service under apache daemon, so when
|
||||
# ceilometer-api running with mod_wsgi, the argv is [], we don't start
|
||||
# guru.
|
||||
if argv:
|
||||
# gmr.TextGuruMeditation.setup_autorun(version)
|
||||
pass
|
||||
# gmr.TextGuruMeditation.setup_autorun(version)
|
||||
messaging.setup()
|
||||
return conf
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,185 +0,0 @@
|
|||
#
|
||||
# Copyright 2012 New Dream Network, LLC (DreamHost)
|
||||
# (c) Copyright 2018 SUSE LLC
|
||||
#
|
||||
# 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.
|
||||
"""Base classes for API tests.
|
||||
"""
|
||||
from oslo_policy import opts
|
||||
import pecan
|
||||
import pecan.testing
|
||||
|
||||
from ceilometer.api import rbac
|
||||
from ceilometer import monasca_ceilometer_opts
|
||||
from ceilometer import service
|
||||
from ceilometer.tests import db as db_test_base
|
||||
|
||||
|
||||
class FunctionalTest(db_test_base.TestBase):
|
||||
"""Used for functional tests of Pecan controllers.
|
||||
|
||||
Used in case when you need to test your literal application and its
|
||||
integration with the framework.
|
||||
"""
|
||||
|
||||
PATH_PREFIX = ''
|
||||
|
||||
def setUp(self):
|
||||
super(FunctionalTest, self).setUp()
|
||||
self.CONF = service.prepare_service([], [])
|
||||
self.CONF.register_opts(list(monasca_ceilometer_opts.OPTS),
|
||||
'monasca')
|
||||
self.setup_messaging(self.CONF)
|
||||
opts.set_defaults(self.CONF)
|
||||
|
||||
self.CONF.set_override("policy_file",
|
||||
self.path_get('etc/ceilometer/policy.json'),
|
||||
group='oslo_policy')
|
||||
|
||||
self.CONF.set_override('gnocchi_is_enabled', False, group='api')
|
||||
self.CONF.set_override('aodh_is_enabled', False, group='api')
|
||||
self.CONF.set_override('panko_is_enabled', False, group='api')
|
||||
|
||||
self.app = self._make_app()
|
||||
|
||||
def _make_app(self, enable_acl=False):
|
||||
self.config = {
|
||||
'app': {
|
||||
'root': 'ceilometer.api.controllers.root.RootController',
|
||||
'modules': ['ceilometer.api'],
|
||||
'enable_acl': enable_acl,
|
||||
},
|
||||
'wsme': {
|
||||
'debug': True,
|
||||
},
|
||||
}
|
||||
|
||||
return pecan.testing.load_test_app(self.config,
|
||||
conf=self.CONF)
|
||||
|
||||
def tearDown(self):
|
||||
super(FunctionalTest, self).tearDown()
|
||||
rbac.reset()
|
||||
pecan.set_config({}, overwrite=True)
|
||||
|
||||
def put_json(self, path, params, expect_errors=False, headers=None,
|
||||
extra_environ=None, status=None):
|
||||
"""Sends simulated HTTP PUT request to Pecan test app.
|
||||
|
||||
:param path: url path of target service
|
||||
:param params: content for wsgi.input of request
|
||||
:param expect_errors: boolean value whether an error is expected based
|
||||
on request
|
||||
:param headers: A dictionary of headers to send along with the request
|
||||
:param extra_environ: A dictionary of environ variables to send along
|
||||
with the request
|
||||
:param status: Expected status code of response
|
||||
"""
|
||||
return self.post_json(path=path, params=params,
|
||||
expect_errors=expect_errors,
|
||||
headers=headers, extra_environ=extra_environ,
|
||||
status=status, method="put")
|
||||
|
||||
def post_json(self, path, params, expect_errors=False, headers=None,
|
||||
method="post", extra_environ=None, status=None):
|
||||
"""Sends simulated HTTP POST request to Pecan test app.
|
||||
|
||||
:param path: url path of target service
|
||||
:param params: content for wsgi.input of request
|
||||
:param expect_errors: boolean value whether an error is expected based
|
||||
on request
|
||||
:param headers: A dictionary of headers to send along with the request
|
||||
:param method: Request method type. Appropriate method function call
|
||||
should be used rather than passing attribute in.
|
||||
:param extra_environ: A dictionary of environ variables to send along
|
||||
with the request
|
||||
:param status: Expected status code of response
|
||||
"""
|
||||
full_path = self.PATH_PREFIX + path
|
||||
response = getattr(self.app, "%s_json" % method)(
|
||||
str(full_path),
|
||||
params=params,
|
||||
headers=headers,
|
||||
status=status,
|
||||
extra_environ=extra_environ,
|
||||
expect_errors=expect_errors
|
||||
)
|
||||
return response
|
||||
|
||||
def delete(self, path, expect_errors=False, headers=None,
|
||||
extra_environ=None, status=None):
|
||||
"""Sends simulated HTTP DELETE request to Pecan test app.
|
||||
|
||||
:param path: url path of target service
|
||||
:param expect_errors: boolean value whether an error is expected based
|
||||
on request
|
||||
:param headers: A dictionary of headers to send along with the request
|
||||
:param extra_environ: A dictionary of environ variables to send along
|
||||
with the request
|
||||
:param status: Expected status code of response
|
||||
"""
|
||||
full_path = self.PATH_PREFIX + path
|
||||
response = self.app.delete(str(full_path),
|
||||
headers=headers,
|
||||
status=status,
|
||||
extra_environ=extra_environ,
|
||||
expect_errors=expect_errors)
|
||||
return response
|
||||
|
||||
def get_json(self, path, expect_errors=False, headers=None,
|
||||
extra_environ=None, q=None, groupby=None, status=None,
|
||||
override_params=None, **params):
|
||||
"""Sends simulated HTTP GET request to Pecan test app.
|
||||
|
||||
:param path: url path of target service
|
||||
:param expect_errors: boolean value whether an error is expected based
|
||||
on request
|
||||
:param headers: A dictionary of headers to send along with the request
|
||||
:param extra_environ: A dictionary of environ variables to send along
|
||||
with the request
|
||||
:param q: list of queries consisting of: field, value, op, and type
|
||||
keys
|
||||
:param groupby: list of fields to group by
|
||||
:param status: Expected status code of response
|
||||
:param override_params: literally encoded query param string
|
||||
:param params: content for wsgi.input of request
|
||||
"""
|
||||
q = q or []
|
||||
groupby = groupby or []
|
||||
full_path = self.PATH_PREFIX + path
|
||||
if override_params:
|
||||
all_params = override_params
|
||||
else:
|
||||
query_params = {'q.field': [],
|
||||
'q.value': [],
|
||||
'q.op': [],
|
||||
'q.type': [],
|
||||
}
|
||||
for query in q:
|
||||
for name in ['field', 'op', 'value', 'type']:
|
||||
query_params['q.%s' % name].append(query.get(name, ''))
|
||||
all_params = {}
|
||||
all_params.update(params)
|
||||
if q:
|
||||
all_params.update(query_params)
|
||||
if groupby:
|
||||
all_params.update({'groupby': groupby})
|
||||
response = self.app.get(full_path,
|
||||
params=all_params,
|
||||
headers=headers,
|
||||
extra_environ=extra_environ,
|
||||
expect_errors=expect_errors,
|
||||
status=status)
|
||||
if not expect_errors:
|
||||
response = response.json
|
||||
return response
|
|
@ -1,20 +0,0 @@
|
|||
#
|
||||
# Copyright 2012 New Dream Network, LLC (DreamHost)
|
||||
#
|
||||
# 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.
|
||||
|
||||
from ceilometer.tests.functional import api
|
||||
|
||||
|
||||
class FunctionalTest(api.FunctionalTest):
|
||||
PATH_PREFIX = '/v2'
|
|
@ -1,270 +0,0 @@
|
|||
#
|
||||
# Copyright 2015 Hewlett Packard
|
||||
# (c) Copyright 2018 SUSE LLC
|
||||
#
|
||||
# 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.
|
||||
"""Test api with Monasca driver
|
||||
"""
|
||||
|
||||
import fixtures
|
||||
import mock
|
||||
import pkg_resources
|
||||
|
||||
from oslo_config import cfg
|
||||
from stevedore import driver
|
||||
from stevedore import extension
|
||||
|
||||
from ceilometer import monasca_ceilometer_opts
|
||||
from ceilometer import service
|
||||
from ceilometer import storage
|
||||
from ceilometer.tests import base as test_base
|
||||
from oslo_policy import opts
|
||||
|
||||
import pecan
|
||||
import pecan.testing
|
||||
|
||||
OPT_GROUP_NAME = 'keystone_authtoken'
|
||||
cfg.CONF.import_group(OPT_GROUP_NAME, "keystonemiddleware.auth_token")
|
||||
|
||||
|
||||
class TestApi(test_base.BaseTestCase):
|
||||
|
||||
# TODO(Unresolved comment from git review: Can we include CM-api test
|
||||
# cases for get_samples in
|
||||
# ceilometer/tests/api/v2/test_api_with_monasca_driver.py?)
|
||||
|
||||
def _get_driver_from_entry_point(self, entry_point, namespace):
|
||||
ep = pkg_resources.EntryPoint.parse(entry_point)
|
||||
a_driver = extension.Extension('con_driver', ep,
|
||||
ep.load(require=False), None)
|
||||
|
||||
mgr = driver.DriverManager.make_test_instance(
|
||||
a_driver, namespace=namespace
|
||||
)
|
||||
mgr._init_plugins([a_driver])
|
||||
return mgr
|
||||
|
||||
def get_connection_with_mock_driver_manager(self, conf, url, namespace):
|
||||
mgr = self._get_driver_from_entry_point(
|
||||
entry_point='monasca = ceilometer.storage.impl_monasca:Connection',
|
||||
namespace='ceilometer.metering.storage')
|
||||
return mgr.driver(conf, url)
|
||||
|
||||
def get_publisher_with_mock_driver_manager(self, conf, url, namespace):
|
||||
mgr = self._get_driver_from_entry_point(
|
||||
entry_point='monasca = ceilometer.publisher.monclient:'
|
||||
'MonascaPublisher',
|
||||
namespace='ceilometer.sample.publisher')
|
||||
return mgr.driver(conf, url)
|
||||
|
||||
def setUp(self):
|
||||
super(TestApi, self).setUp()
|
||||
self.PATH_PREFIX = '/v2'
|
||||
|
||||
self.CONF = service.prepare_service([], [])
|
||||
self.CONF.register_opts(list(monasca_ceilometer_opts.OPTS),
|
||||
'monasca')
|
||||
self.setup_messaging(self.CONF)
|
||||
opts.set_defaults(self.CONF)
|
||||
self.CONF.set_override("policy_file",
|
||||
self.path_get('etc/ceilometer/policy.json'),
|
||||
group='oslo_policy')
|
||||
|
||||
self.CONF.import_opt('pipeline_cfg_file', 'ceilometer.pipeline')
|
||||
self.CONF.set_override(
|
||||
'pipeline_cfg_file',
|
||||
self.path_get('etc/ceilometer/monasca_pipeline.yaml')
|
||||
)
|
||||
|
||||
self.CONF.import_opt('monasca_mappings',
|
||||
'ceilometer.publisher.monasca_data_filter',
|
||||
group='monasca')
|
||||
|
||||
self.CONF.set_override(
|
||||
'monasca_mappings',
|
||||
self.path_get('etc/ceilometer/monasca_field_definitions.yaml'),
|
||||
group='monasca'
|
||||
)
|
||||
|
||||
with mock.patch("ceilometer.monasca_client.Client") as mock_client,\
|
||||
mock.patch('ceilometer.storage.get_connection') as \
|
||||
get_storage_conn, \
|
||||
mock.patch('ceilometer.publisher.get_publisher') as get_pub:
|
||||
|
||||
get_storage_conn.side_effect = (
|
||||
self.get_connection_with_mock_driver_manager)
|
||||
get_pub.side_effect = self.get_publisher_with_mock_driver_manager
|
||||
self.mock_mon_client = mock_client
|
||||
self.conn = storage.get_connection(
|
||||
self.CONF,
|
||||
'monasca://127.0.0.1:8080',
|
||||
'ceilometer.metering.storage')
|
||||
|
||||
self.useFixture(fixtures.MockPatch(
|
||||
'ceilometer.storage.get_connection',
|
||||
return_value=self.conn))
|
||||
|
||||
self.app = self._make_app()
|
||||
|
||||
def _make_app(self, enable_acl=False):
|
||||
self.config = {
|
||||
'app': {
|
||||
'root': 'ceilometer.api.controllers.root.RootController',
|
||||
'modules': ['ceilometer.api'],
|
||||
'enable_acl': enable_acl,
|
||||
},
|
||||
'wsme': {
|
||||
'debug': True,
|
||||
},
|
||||
}
|
||||
|
||||
return pecan.testing.load_test_app(self.config,
|
||||
conf=self.CONF)
|
||||
|
||||
def get_json(self, path, expect_errors=False, headers=None,
|
||||
extra_environ=None, q=None, groupby=None, status=None,
|
||||
override_params=None, **params):
|
||||
"""Sends simulated HTTP GET request to Pecan test app.
|
||||
|
||||
:param path: url path of target service
|
||||
:param expect_errors: boolean value whether an error is expected based
|
||||
on request
|
||||
:param headers: A dictionary of headers to send along with the request
|
||||
:param extra_environ: A dictionary of environ variables to send along
|
||||
with the request
|
||||
:param q: list of queries consisting of: field, value, op, and type
|
||||
keys
|
||||
:param groupby: list of fields to group by
|
||||
:param status: Expected status code of response
|
||||
:param override_params: literally encoded query param string
|
||||
:param params: content for wsgi.input of request
|
||||
"""
|
||||
|
||||
q = q or []
|
||||
groupby = groupby or []
|
||||
full_path = self.PATH_PREFIX + path
|
||||
if override_params:
|
||||
all_params = override_params
|
||||
else:
|
||||
query_params = {'q.field': [],
|
||||
'q.value': [],
|
||||
'q.op': [],
|
||||
'q.type': [],
|
||||
}
|
||||
for query in q:
|
||||
for name in ['field', 'op', 'value', 'type']:
|
||||
query_params['q.%s' % name].append(query.get(name, ''))
|
||||
all_params = {}
|
||||
all_params.update(params)
|
||||
if q:
|
||||
all_params.update(query_params)
|
||||
if groupby:
|
||||
all_params.update({'groupby': groupby})
|
||||
response = self.app.get(full_path,
|
||||
params=all_params,
|
||||
headers=headers,
|
||||
extra_environ=extra_environ,
|
||||
expect_errors=expect_errors,
|
||||
status=status)
|
||||
if not expect_errors:
|
||||
response = response.json
|
||||
return response
|
||||
|
||||
|
||||
class TestListMeters(TestApi):
|
||||
|
||||
def setUp(self):
|
||||
super(TestListMeters, self).setUp()
|
||||
|
||||
self.meter_payload = [{'name': 'm1',
|
||||
'dimensions': {
|
||||
'type': 'gauge',
|
||||
'unit': 'any',
|
||||
'resource_id': 'resource-1',
|
||||
'project_id': 'project-1',
|
||||
'user_id': 'user-1',
|
||||
'source': 'source'}},
|
||||
{'name': 'm2',
|
||||
'dimensions': {
|
||||
'type': 'delta',
|
||||
'unit': 'any',
|
||||
'resource_id': 'resource-1',
|
||||
'project_id': 'project-1',
|
||||
'user_id': 'user-1',
|
||||
'source': 'source'}}]
|
||||
|
||||
def test_empty(self):
|
||||
data = self.get_json('/meters')
|
||||
self.assertEqual([], data)
|
||||
|
||||
def test_get_meters(self):
|
||||
|
||||
mnl_mock = self.mock_mon_client().metrics_list
|
||||
mnl_mock.return_value = self.meter_payload
|
||||
|
||||
data = self.get_json('/meters')
|
||||
self.assertEqual(True, mnl_mock.called)
|
||||
self.assertEqual(2, mnl_mock.call_count,
|
||||
"impl_monasca.py calls the metrics_list api twice.")
|
||||
self.assertEqual(2, len(data))
|
||||
|
||||
(self.assertIn(meter['name'],
|
||||
[payload.get('name') for payload in
|
||||
self.meter_payload]) for meter in data)
|
||||
|
||||
def test_get_meters_query_with_project_resource(self):
|
||||
"""Test meter name conversion for project-id and resource-id.
|
||||
|
||||
Previous versions of the monasca client did not do this conversion.
|
||||
|
||||
Pre-Newton expected:
|
||||
'dimensions': {'project_id': u'project-1','resource_id': u'resource-1'}
|
||||
|
||||
Newton expected:
|
||||
'dimensions': {'hostname': u'resource-1','project_id': u'project-1'}
|
||||
"""
|
||||
|
||||
mnl_mock = self.mock_mon_client().metrics_list
|
||||
mnl_mock.return_value = self.meter_payload
|
||||
|
||||
self.get_json('/meters',
|
||||
q=[{'field': 'resource_id',
|
||||
'value': 'resource-1'},
|
||||
{'field': 'project_id',
|
||||
'value': 'project-1'}])
|
||||
self.assertEqual(True, mnl_mock.called)
|
||||
self.assertEqual(4, mnl_mock.call_count,
|
||||
"impl_monasca.py expected to make 4 calls to mock.")
|
||||
# Note - previous versions of the api included a limit value
|
||||
self.assertEqual(dict(dimensions=dict(hostname=u'resource-1',
|
||||
project_id=u'project-1')),
|
||||
mnl_mock.call_args[1])
|
||||
|
||||
def test_get_meters_query_with_user(self):
|
||||
mnl_mock = self.mock_mon_client().metrics_list
|
||||
mnl_mock.return_value = self.meter_payload
|
||||
|
||||
self.get_json('/meters',
|
||||
q=[{'field': 'user_id',
|
||||
'value': 'user-1'}])
|
||||
self.assertEqual(True, mnl_mock.called)
|
||||
self.assertEqual(2, mnl_mock.call_count,
|
||||
"impl_monasca.py calls the metrics_list api twice.")
|
||||
# Note - previous versions of the api included a limit value
|
||||
self.assertEqual(dict(dimensions=dict(user_id=u'user-1')),
|
||||
mnl_mock.call_args[1])
|
||||
|
||||
# TODO(joadavis) Test a bad query parameter
|
||||
# Like using 'hostname' instead of 'resource_id'
|
||||
# Expected result with bad parameter:
|
||||
# webtest.app.AppError: Bad response: 400 Bad Request
|
|
@ -1,601 +0,0 @@
|
|||
#
|
||||
# Copyright 2016 Hewlett Packard
|
||||
# (c) Copyright 2018 SUSE LLC
|
||||
#
|
||||
# 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 collections
|
||||
import os
|
||||
|
||||
import fixtures
|
||||
import mock
|
||||
from oslo_utils import fileutils
|
||||
from oslo_utils import timeutils
|
||||
from oslotest import base
|
||||
import six
|
||||
import yaml
|
||||
|
||||
from ceilometer.ceilosca_mapping import ceilosca_mapping
|
||||
from ceilometer.ceilosca_mapping.ceilosca_mapping import (
|
||||
CeiloscaMappingDefinition)
|
||||
from ceilometer.ceilosca_mapping.ceilosca_mapping import (
|
||||
CeiloscaMappingDefinitionException)
|
||||
from ceilometer.ceilosca_mapping.ceilosca_mapping import PipelineReader
|
||||
from ceilometer import monasca_ceilometer_opts
|
||||
from ceilometer import service
|
||||
from ceilometer import storage
|
||||
from ceilometer.storage import impl_monasca
|
||||
from ceilometer.storage import models as storage_models
|
||||
|
||||
MONASCA_MEASUREMENT = {
|
||||
"id": "fef26f9d27f8027ea44b940cf3626fc398f7edfb",
|
||||
"name": "fake_metric",
|
||||
"dimensions": {
|
||||
"resource_id": "2fe6e3a9-9bdf-4c98-882c-a826cf0107a1",
|
||||
"cloud_name": "helion-poc-hlm-003",
|
||||
"component": "vm",
|
||||
"control_plane": "control-plane-1",
|
||||
"service": "compute",
|
||||
"device": "tap3356676e-a5",
|
||||
"tenant_id": "50ce24dd577c43879cede72b77224e2f",
|
||||
"hostname": "hlm003-cp1-comp0003-mgmt",
|
||||
"cluster": "compute",
|
||||
"zone": "nova"
|
||||
},
|
||||
"columns": ["timestamp", "value", "value_meta"],
|
||||
"measurements": [["2016-05-23T22:22:42.000Z", 54.0, {
|
||||
"audit_period_ending": "None",
|
||||
"audit_period_beginning": "None",
|
||||
"host": "network.hlm003-cp1-c1-m2-mgmt",
|
||||
"availability_zone": "None",
|
||||
"event_type": "subnet.create.end",
|
||||
"enable_dhcp": "true",
|
||||
"gateway_ip": "10.43.0.1",
|
||||
"ip_version": "4",
|
||||
"cidr": "10.43.0.0/28"}]]
|
||||
}
|
||||
|
||||
MONASCA_VALUE_META = {
|
||||
'audit_period_beginning': 'None',
|
||||
'audit_period_ending': 'None',
|
||||
'availability_zone': 'None',
|
||||
'cidr': '10.43.0.0/28',
|
||||
'enable_dhcp': 'true',
|
||||
'event_type': 'subnet.create.end',
|
||||
'gateway_ip': '10.43.0.1',
|
||||
'host': 'network.hlm003-cp1-c1-m2-mgmt',
|
||||
'ip_version': '4'
|
||||
}
|
||||
|
||||
|
||||
class TestCeiloscaMapping(base.BaseTestCase):
|
||||
pipeline_data = yaml.dump({
|
||||
'sources': [{
|
||||
'name': 'test_pipeline',
|
||||
'interval': 1,
|
||||
'meters': ['testbatch', 'testbatch2'],
|
||||
'resources': ['alpha', 'beta', 'gamma', 'delta'],
|
||||
'sinks': ['test_sink']}],
|
||||
'sinks': [{
|
||||
'name': 'test_sink',
|
||||
'transformers': [],
|
||||
'publishers': ["test"]}]
|
||||
})
|
||||
|
||||
cfg = yaml.dump({
|
||||
'meter_metric_map': [{
|
||||
'user_id': '$.dimensions.user_id',
|
||||
'name': 'fake_meter',
|
||||
'resource_id': '$.dimensions.resource_id',
|
||||
'region': 'NA',
|
||||
'monasca_metric_name': 'fake_metric',
|
||||
'source': 'NA',
|
||||
'project_id': '$.dimensions.tenant_id',
|
||||
'type': 'gauge',
|
||||
'resource_metadata': '$.measurements[0][2]',
|
||||
'unit': 'B/s'
|
||||
}, {
|
||||
'user_id': '$.dimensions.user_id',
|
||||
'name': 'fake_meter2',
|
||||
'resource_id': '$.dimensions.resource_id',
|
||||
'region': 'NA',
|
||||
'monasca_metric_name': 'fake_metric2',
|
||||
'source': 'NA',
|
||||
'project_id': '$.dimensions.project_id',
|
||||
'type': 'delta',
|
||||
'resource_metadata': '$.measurements[0][2]',
|
||||
'unit': 'B/s'
|
||||
}, {
|
||||
'user_id': '$.dimensions.user_id',
|
||||
'name': 'fake_meter3',
|
||||
'resource_id': '$.dimensions.hostname',
|
||||
'region': 'NA',
|
||||
'monasca_metric_name': 'fake_metric3',
|
||||
'source': 'NA',
|
||||
'project_id': '$.dimensions.project_id',
|
||||
'type': 'delta',
|
||||
'resource_metadata': '$.measurements[0][2]',
|
||||
'unit': 'B/s'
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
def setup_pipeline_file(self, pipeline_data):
|
||||
if six.PY3:
|
||||
pipeline_data = pipeline_data.encode('utf-8')
|
||||
pipeline_cfg_file = fileutils.write_to_tempfile(content=pipeline_data,
|
||||
prefix="pipeline",
|
||||
suffix="yaml")
|
||||
self.addCleanup(os.remove, pipeline_cfg_file)
|
||||
return pipeline_cfg_file
|
||||
|
||||
def setup_ceilosca_mapping_def_file(self, cfg):
|
||||
if six.PY3:
|
||||
cfg = cfg.encode('utf-8')
|
||||
ceilosca_mapping_file = fileutils.write_to_tempfile(
|
||||
content=cfg, prefix='ceilosca_mapping', suffix='yaml')
|
||||
self.addCleanup(os.remove, ceilosca_mapping_file)
|
||||
return ceilosca_mapping_file
|
||||
|
||||
|
||||
class TestGetPipelineReader(TestCeiloscaMapping):
|
||||
|
||||
def setUp(self):
|
||||
super(TestGetPipelineReader, self).setUp()
|
||||
self.CONF = service.prepare_service([], [])
|
||||
self.CONF.register_opts(list(monasca_ceilometer_opts.OPTS),
|
||||
'monasca')
|
||||
|
||||
def test_pipeline_reader(self):
|
||||
pipeline_cfg_file = self.setup_pipeline_file(
|
||||
self.pipeline_data)
|
||||
self.CONF.set_override("pipeline_cfg_file", pipeline_cfg_file)
|
||||
|
||||
test_pipeline_reader = PipelineReader(self.CONF)
|
||||
|
||||
self.assertEqual(set(['testbatch', 'testbatch2']),
|
||||
test_pipeline_reader.get_pipeline_meters()
|
||||
)
|
||||
|
||||
|
||||
class TestMappingDefinition(base.BaseTestCase):
|
||||
|
||||
def test_mapping_definition(self):
|
||||
cfg = dict(name="network.outgoing.rate",
|
||||
monasca_metric_name="vm.net.out_bytes_sec",
|
||||
resource_id="$.dimensions.resource_id",
|
||||
project_id="$.dimensions.tenant_id",
|
||||
user_id="$.dimensions.user_id",
|
||||
region="NA",
|
||||
type="gauge",
|
||||
unit="B/s",
|
||||
source="NA",
|
||||
resource_metadata="$.measurements[0][2]")
|
||||
handler = CeiloscaMappingDefinition(cfg)
|
||||
self.assertIsNone(handler.parse_fields("user_id", MONASCA_MEASUREMENT))
|
||||
self.assertEqual("2fe6e3a9-9bdf-4c98-882c-a826cf0107a1",
|
||||
handler.parse_fields("resource_id",
|
||||
MONASCA_MEASUREMENT))
|
||||
self.assertEqual("50ce24dd577c43879cede72b77224e2f",
|
||||
handler.parse_fields("project_id",
|
||||
MONASCA_MEASUREMENT))
|
||||
self.assertEqual(MONASCA_VALUE_META,
|
||||
handler.parse_fields("resource_metadata",
|
||||
MONASCA_MEASUREMENT))
|
||||
self.assertEqual("$.dimensions.tenant_id", handler.cfg["project_id"])
|
||||
|
||||
def test_config_required_missing_fields(self):
|
||||
cfg = dict()
|
||||
try:
|
||||
CeiloscaMappingDefinition(cfg)
|
||||
except CeiloscaMappingDefinitionException as e:
|
||||
self.assertEqual("Required fields ["
|
||||
"'name', 'monasca_metric_name', 'type', 'unit', "
|
||||
"'source', 'resource_metadata', 'resource_id', "
|
||||
"'project_id', 'user_id', 'region'] "
|
||||
"not specified", e.message)
|
||||
|
||||
def test_bad_type_cfg_definition(self):
|
||||
cfg = dict(name="fake_meter",
|
||||
monasca_metric_name="fake_metric",
|
||||
resource_id="$.dimensions.resource_id",
|
||||
project_id="$.dimensions.tenant_id",
|
||||
user_id="$.dimensions.user_id",
|
||||
region="NA",
|
||||
type="foo",
|
||||
unit="B/s",
|
||||
source="NA",
|
||||
resource_metadata="$.measurements[0][2]")
|
||||
try:
|
||||
CeiloscaMappingDefinition(cfg)
|
||||
except CeiloscaMappingDefinitionException as e:
|
||||
self.assertEqual("Invalid type foo specified", e.message)
|
||||
|
||||
|
||||
class TestMappedCeiloscaMetricProcessing(TestCeiloscaMapping):
|
||||
|
||||
def setUp(self):
|
||||
super(TestMappedCeiloscaMetricProcessing, self).setUp()
|
||||
|
||||
self.CONF = service.prepare_service([], [])
|
||||
self.CONF.register_opts(list(monasca_ceilometer_opts.OPTS),
|
||||
'monasca')
|
||||
|
||||
def test_fallback_mapping_file_path(self):
|
||||
self.useFixture(fixtures.MockPatchObject(self.CONF,
|
||||
'find_file',
|
||||
return_value=None))
|
||||
fall_bak_path = ceilosca_mapping.get_config_file(self.CONF)
|
||||
self.assertIn("ceilosca_mapping/data/ceilosca_mapping.yaml",
|
||||
fall_bak_path)
|
||||
|
||||
@mock.patch('ceilometer.ceilosca_mapping.ceilosca_mapping.LOG')
|
||||
def test_bad_meter_definition_skip(self, LOG):
|
||||
cfg = yaml.dump({
|
||||
'meter_metric_map': [{
|
||||
'user_id': '$.dimensions.user_id',
|
||||
'name': 'fake_meter',
|
||||
'resource_id': '$.dimensions.resource_id',
|
||||
'region': 'NA',
|
||||
'monasca_metric_name': 'fake_metric',
|
||||
'source': 'NA',
|
||||
'project_id': '$.dimensions.tenant_id',
|
||||
'type': 'gauge',
|
||||
'resource_metadata': '$.measurements[0][2]',
|
||||
'unit': 'B/s'
|
||||
}, {
|
||||
'user_id': '$.dimensions.user_id',
|
||||
'name': 'fake_meter',
|
||||
'resource_id': '$.dimensions.resource_id',
|
||||
'region': 'NA',
|
||||
'monasca_metric_name': 'fake_metric',
|
||||
'source': 'NA',
|
||||
'project_id': '$.dimensions.tenant_id',
|
||||
'type': 'foo',
|
||||
'resource_metadata': '$.measurements[0][2]',
|
||||
'unit': 'B/s'
|
||||
}]
|
||||
})
|
||||
ceilosca_mapping_file = self.setup_ceilosca_mapping_def_file(cfg)
|
||||
self.CONF.set_override('ceilometer_monasca_metrics_mapping',
|
||||
ceilosca_mapping_file, group='monasca')
|
||||
data = ceilosca_mapping.setup_ceilosca_mapping_config(self.CONF)
|
||||
meter_loaded = ceilosca_mapping.load_definitions(data)
|
||||
self.assertEqual(1, len(meter_loaded))
|
||||
LOG.error.assert_called_with(
|
||||
"Error loading Ceilometer Monasca Mapping Definition : "
|
||||
"Invalid type foo specified")
|
||||
|
||||
def test_list_of_meters_returned(self):
|
||||
ceilosca_mapping_file = self.setup_ceilosca_mapping_def_file(self.cfg)
|
||||
self.CONF.set_override('ceilometer_monasca_metrics_mapping',
|
||||
ceilosca_mapping_file, group='monasca')
|
||||
ceilosca_mapper = ceilosca_mapping\
|
||||
.ProcessMappedCeiloscaMetric(self.CONF)
|
||||
ceilosca_mapper.reinitialize(self.CONF)
|
||||
self.assertItemsEqual(['fake_metric', 'fake_metric2', 'fake_metric3'],
|
||||
ceilosca_mapper.get_list_monasca_metrics().keys()
|
||||
)
|
||||
|
||||
def test_monasca_metric_name_map_ceilometer_meter(self):
|
||||
cfg = yaml.dump({
|
||||
'meter_metric_map': [{
|
||||
'user_id': '$.dimensions.user_id',
|
||||
'name': 'fake_meter',
|
||||
'resource_id': '$.dimensions.resource_id',
|
||||
'region': 'NA',
|
||||
'monasca_metric_name': 'fake_metric',
|
||||
'source': 'NA',
|
||||
'project_id': '$.dimensions.tenant_id',
|
||||
'type': 'gauge',
|
||||
'resource_metadata': '$.measurements[0][2]',
|
||||
'unit': 'B/s'
|
||||
}]
|
||||
})
|
||||
ceilosca_mapping_file = self.setup_ceilosca_mapping_def_file(cfg)
|
||||
self.CONF.set_override('ceilometer_monasca_metrics_mapping',
|
||||
ceilosca_mapping_file, group='monasca')
|
||||
ceilosca_mapper = ceilosca_mapping\
|
||||
.ProcessMappedCeiloscaMetric(self.CONF)
|
||||
ceilosca_mapper.reinitialize(self.CONF)
|
||||
self.assertEqual('fake_metric',
|
||||
ceilosca_mapper.get_monasca_metric_name('fake_meter')
|
||||
)
|
||||
self.assertEqual('$.dimensions.tenant_id',
|
||||
ceilosca_mapper.
|
||||
get_ceilosca_mapped_definition_key_val('fake_metric',
|
||||
'project_id'))
|
||||
|
||||
|
||||
# This Class will only test the driver for the mapped meteric
|
||||
# Impl_Monasca Tests will be doing exhaustive tests for non mapped metrics
|
||||
@mock.patch("ceilometer.storage.impl_monasca.MonascaDataFilter")
|
||||
class TestMoanscaDriverForMappedMetrics(TestCeiloscaMapping):
|
||||
Aggregate = collections.namedtuple("Aggregate", ['func', 'param'])
|
||||
|
||||
def setUp(self):
|
||||
|
||||
super(TestMoanscaDriverForMappedMetrics, self).setUp()
|
||||
|
||||
self.CONF = service.prepare_service([], [])
|
||||
self.CONF.register_opts(list(monasca_ceilometer_opts.OPTS),
|
||||
'monasca')
|
||||
|
||||
pipeline_cfg_file = self.setup_pipeline_file(self.pipeline_data)
|
||||
self.CONF.set_override("pipeline_cfg_file", pipeline_cfg_file)
|
||||
|
||||
ceilosca_mapping_file = self.setup_ceilosca_mapping_def_file(self.cfg)
|
||||
self.CONF.set_override('ceilometer_monasca_metrics_mapping',
|
||||
ceilosca_mapping_file, group='monasca')
|
||||
|
||||
ceilosca_mapper = ceilosca_mapping\
|
||||
.ProcessMappedCeiloscaMetric(self.CONF)
|
||||
ceilosca_mapper.reinitialize(self.CONF)
|
||||
|
||||
def test_get_samples_for_mapped_meters(self, mdf_mock):
|
||||
with mock.patch("ceilometer.monasca_client.Client") as mock_client:
|
||||
conn = impl_monasca.Connection(self.CONF, "127.0.0.1:8080")
|
||||
ml_mock = mock_client().measurements_list
|
||||
# TODO(this test case needs more work)
|
||||
ml_mock.return_value = ([MONASCA_MEASUREMENT])
|
||||
|
||||
sample_filter = storage.SampleFilter(
|
||||
meter='fake_meter',
|
||||
start_timestamp='2015-03-20T00:00:00Z')
|
||||
results = list(conn.get_samples(sample_filter))
|
||||
self.assertEqual(True, ml_mock.called)
|
||||
self.assertEqual('fake_meter', results[0].counter_name)
|
||||
self.assertEqual(54.0, results[0].counter_volume)
|
||||
self.assertEqual('gauge', results[0].counter_type)
|
||||
self.assertEqual('2fe6e3a9-9bdf-4c98-882c-a826cf0107a1',
|
||||
results[0].resource_id
|
||||
)
|
||||
self.assertEqual(MONASCA_VALUE_META, results[0].resource_metadata)
|
||||
self.assertEqual('50ce24dd577c43879cede72b77224e2f',
|
||||
results[0].project_id,
|
||||
)
|
||||
self.assertEqual('B/s', results[0].counter_unit)
|
||||
self.assertIsNone(results[0].user_id)
|
||||
|
||||
def test_get_meter_for_mapped_meters_non_uniq(self, mdf_mock):
|
||||
data1 = (
|
||||
[{u'dimensions': {u'datasource': u'ceilometer'},
|
||||
u'id': u'2015-04-14T18:42:31Z',
|
||||
u'name': u'meter-1'},
|
||||
{u'dimensions': {u'datasource': u'ceilometer'},
|
||||
u'id': u'2015-04-15T18:42:31Z',
|
||||
u'name': u'meter-1'}])
|
||||
data2 = (
|
||||
[{u'dimensions': {u'datasource': u'ceilometer'},
|
||||
u'id': u'2015-04-14T18:42:31Z',
|
||||
u'name': u'meter-1'},
|
||||
{u'dimensions': {u'datasource': u'ceilometer'},
|
||||
u'id': u'2015-04-15T18:42:31Z',
|
||||
u'name': u'meter-1'},
|
||||
{u'id': u'fef26f9d27f8027ea44b940cf3626fc398f7edfb',
|
||||
u'name': u'fake_metric',
|
||||
u'dimensions': {
|
||||
u'resource_id': u'2fe6e3a9-9bdf-4c98-882c-a826cf0107a1',
|
||||
u'cloud_name': u'helion-poc-hlm-003',
|
||||
u'component': u'vm',
|
||||
u'control_plane': u'control-plane-1',
|
||||
u'service': u'compute',
|
||||
u'device': u'tap3356676e-a5',
|
||||
u'tenant_id': u'50ce24dd577c43879cede72b77224e2f',
|
||||
u'hostname': u'hlm003-cp1-comp0003-mgmt',
|
||||
u'cluster': u'compute',
|
||||
u'zone': u'nova'}
|
||||
},
|
||||
{u'dimensions': {},
|
||||
u'id': u'2015-04-16T18:42:31Z',
|
||||
u'name': u'testbatch'}])
|
||||
with mock.patch("ceilometer.monasca_client.Client") as mock_client:
|
||||
conn = impl_monasca.Connection(self.CONF, "127.0.0.1:8080")
|
||||
metrics_list_mock = mock_client().metrics_list
|
||||
metrics_list_mock.side_effect = [data1, data2]
|
||||
kwargs = dict(limit=4)
|
||||
|
||||
results = list(conn.get_meters(**kwargs))
|
||||
# result contains 2 records from data 1 since datasource
|
||||
# = ceilometer, 2 records from data 2, 1 for pipeline
|
||||
# meter but no datasource set to ceilometer and one for
|
||||
# mapped meter
|
||||
self.assertEqual(4, len(results))
|
||||
self.assertEqual(True, metrics_list_mock.called)
|
||||
self.assertEqual(2, metrics_list_mock.call_count)
|
||||
|
||||
def test_get_meter_for_mapped_meters_uniq(self, mdf_mock):
|
||||
dummy_metric_names_mocked_return_value = (
|
||||
[{"id": "015c995b1a770147f4ef18f5841ef566ab33521d",
|
||||
"name": "network.delete"},
|
||||
{"id": "335b5d569ad29dc61b3dc24609fad3619e947944",
|
||||
"name": "subnet.update"}])
|
||||
with mock.patch("ceilometer.monasca_client.Client") as mock_client:
|
||||
conn = impl_monasca.Connection(self.CONF, "127.0.0.1:8080")
|
||||
metric_names_list_mock = mock_client().metric_names_list
|
||||
metric_names_list_mock.return_value = (
|
||||
dummy_metric_names_mocked_return_value)
|
||||
kwargs = dict(limit=4, unique=True)
|
||||
results = list(conn.get_meters(**kwargs))
|
||||
self.assertEqual(2, len(results))
|
||||
self.assertEqual(True, metric_names_list_mock.called)
|
||||
self.assertEqual(1, metric_names_list_mock.call_count)
|
||||
|
||||
def test_stats_list_mapped_meters(self, mock_mdf):
|
||||
with mock.patch("ceilometer.monasca_client.Client") as mock_client:
|
||||
conn = impl_monasca.Connection(self.CONF, "127.0.0.1:8080")
|
||||
sl_mock = mock_client().statistics_list
|
||||
sl_mock.return_value = [
|
||||
{
|
||||
'statistics':
|
||||
[
|
||||
['2014-10-24T12:12:12Z', 0.008],
|
||||
['2014-10-24T12:52:12Z', 0.018]
|
||||
],
|
||||
'dimensions': {'unit': 'gb'},
|
||||
'columns': ['timestamp', 'min']
|
||||
}
|
||||
]
|
||||
|
||||
sf = storage.SampleFilter()
|
||||
sf.meter = "fake_meter"
|
||||
aggregate = self.Aggregate(func="min", param=None)
|
||||
sf.start_timestamp = timeutils.parse_isotime(
|
||||
'2014-10-24T12:12:42').replace(tzinfo=None)
|
||||
stats = list(conn.get_meter_statistics(sf, aggregate=[aggregate],
|
||||
period=30))
|
||||
self.assertEqual(2, len(stats))
|
||||
self.assertEqual('B/s', stats[0].unit)
|
||||
self.assertEqual('B/s', stats[1].unit)
|
||||
self.assertEqual(0.008, stats[0].min)
|
||||
self.assertEqual(0.018, stats[1].min)
|
||||
self.assertEqual(30, stats[0].period)
|
||||
self.assertEqual('2014-10-24T12:12:42',
|
||||
stats[0].period_end.isoformat())
|
||||
self.assertEqual('2014-10-24T12:52:42',
|
||||
stats[1].period_end.isoformat())
|
||||
self.assertIsNotNone(stats[0].as_dict().get('aggregate'))
|
||||
self.assertEqual({u'min': 0.008}, stats[0].as_dict()['aggregate'])
|
||||
|
||||
def test_get_resources_for_mapped_meters(self, mock_mdf):
|
||||
with mock.patch("ceilometer.monasca_client.Client") as mock_client:
|
||||
conn = impl_monasca.Connection(self.CONF, "127.0.0.1:8080")
|
||||
dummy_metric_names_mocked_return_value = (
|
||||
[{"id": "015c995b1a770147f4ef18f5841ef566ab33521d",
|
||||
"name": "fake_metric"},
|
||||
{"id": "335b5d569ad29dc61b3dc24609fad3619e947944",
|
||||
"name": "metric1"}])
|
||||
mnl_mock = mock_client().metric_names_list
|
||||
mnl_mock.return_value = (
|
||||
dummy_metric_names_mocked_return_value)
|
||||
|
||||
dummy_get_resources_mocked_return_value = (
|
||||
[{u'dimensions': {u'resource_id': u'abcd'},
|
||||
u'measurements': [[u'2015-04-14T17:52:31Z', 1.0, {}],
|
||||
[u'2015-04-15T17:52:31Z', 2.0, {}],
|
||||
[u'2015-04-16T17:52:31Z', 3.0, {}]],
|
||||
u'id': u'2015-04-14T18:42:31Z',
|
||||
u'columns': [u'timestamp', u'value', u'value_meta'],
|
||||
u'name': u'fake_metric'}])
|
||||
|
||||
ml_mock = mock_client().measurements_list
|
||||
ml_mock.return_value = (
|
||||
dummy_get_resources_mocked_return_value)
|
||||
|
||||
sample_filter = storage.SampleFilter(
|
||||
meter='fake_meter', end_timestamp='2015-04-20T00:00:00Z')
|
||||
resources = list(conn.get_resources(sample_filter, limit=2))
|
||||
self.assertEqual(2, len(resources))
|
||||
self.assertEqual(True, ml_mock.called)
|
||||
self.assertEqual(1, ml_mock.call_count)
|
||||
resources_without_limit = list(conn.get_resources(sample_filter))
|
||||
self.assertEqual(3, len(resources_without_limit))
|
||||
|
||||
def test_stats_list_with_groupby_for_mapped_meters(self, mock_mdf):
|
||||
with mock.patch("ceilometer.monasca_client.Client") as mock_client:
|
||||
conn = impl_monasca.Connection(self.CONF, "127.0.0.1:8080")
|
||||
sl_mock = mock_client().statistics_list
|
||||
sl_mock.return_value = [
|
||||
{
|
||||
'statistics':
|
||||
[
|
||||
['2014-10-24T12:12:12Z', 0.008, 1.3, 3, 0.34],
|
||||
['2014-10-24T12:20:12Z', 0.078, 1.25, 2, 0.21],
|
||||
['2014-10-24T12:52:12Z', 0.018, 0.9, 4, 0.14]
|
||||
],
|
||||
'dimensions': {'hostname': '1234', 'unit': 'gb'},
|
||||
'columns': ['timestamp', 'min', 'max', 'count', 'avg']
|
||||
},
|
||||
{
|
||||
'statistics':
|
||||
[
|
||||
['2014-10-24T12:14:12Z', 0.45, 2.5, 2, 2.1],
|
||||
['2014-10-24T12:20:12Z', 0.58, 3.2, 3, 3.4],
|
||||
['2014-10-24T13:52:42Z', 1.67, 3.5, 1, 5.3]
|
||||
],
|
||||
'dimensions': {'hostname': '5678', 'unit': 'gb'},
|
||||
'columns': ['timestamp', 'min', 'max', 'count', 'avg']
|
||||
}]
|
||||
|
||||
sf = storage.SampleFilter()
|
||||
sf.meter = "fake_meter3"
|
||||
sf.start_timestamp = timeutils.parse_isotime(
|
||||
'2014-10-24T12:12:42').replace(tzinfo=None)
|
||||
groupby = ['resource_id']
|
||||
stats = list(conn.get_meter_statistics(sf, period=30,
|
||||
groupby=groupby))
|
||||
|
||||
self.assertEqual(2, len(stats))
|
||||
|
||||
for stat in stats:
|
||||
self.assertIsNotNone(stat.groupby)
|
||||
resource_id = stat.groupby.get('resource_id')
|
||||
self.assertIn(resource_id, ['1234', '5678'])
|
||||
if resource_id == '1234':
|
||||
self.assertEqual(0.008, stat.min)
|
||||
self.assertEqual(1.3, stat.max)
|
||||
self.assertEqual(0.23, stat.avg)
|
||||
self.assertEqual(9, stat.count)
|
||||
self.assertEqual(30, stat.period)
|
||||
self.assertEqual('2014-10-24T12:12:12',
|
||||
stat.period_start.isoformat())
|
||||
if resource_id == '5678':
|
||||
self.assertEqual(0.45, stat.min)
|
||||
self.assertEqual(3.5, stat.max)
|
||||
self.assertEqual(3.6, stat.avg)
|
||||
self.assertEqual(6, stat.count)
|
||||
self.assertEqual(30, stat.period)
|
||||
self.assertEqual('2014-10-24T13:52:42',
|
||||
stat.period_end.isoformat())
|
||||
|
||||
def test_query_samples_for_mapped_meter(self, mock_mdf):
|
||||
SAMPLES = [[
|
||||
storage_models.Sample(
|
||||
counter_name="fake_meter",
|
||||
counter_type="gauge",
|
||||
counter_unit="instance",
|
||||
counter_volume=1,
|
||||
project_id="123",
|
||||
user_id="456",
|
||||
resource_id="789",
|
||||
resource_metadata={},
|
||||
source="openstack",
|
||||
recorded_at=timeutils.utcnow(),
|
||||
timestamp=timeutils.utcnow(),
|
||||
message_id="0",
|
||||
message_signature='', )
|
||||
]] * 2
|
||||
samples = SAMPLES[:]
|
||||
|
||||
def _get_samples(*args, **kwargs):
|
||||
return samples.pop()
|
||||
|
||||
with mock.patch("ceilometer.monasca_client.Client"):
|
||||
conn = impl_monasca.Connection(self.CONF, "127.0.0.1:8080")
|
||||
with mock.patch.object(conn, 'get_samples') as gsm:
|
||||
gsm.side_effect = _get_samples
|
||||
|
||||
query = {'and': [{'=': {'counter_name': 'fake_meter'}},
|
||||
{'or': [{'=': {"project_id": "123"}},
|
||||
{'=': {"user_id": "456"}}]}]}
|
||||
samples = conn.query_samples(query, None, 100)
|
||||
self.assertEqual(2, len(samples))
|
||||
self.assertEqual(2, gsm.call_count)
|
||||
|
||||
samples = SAMPLES[:]
|
||||
query = {'and': [{'=': {'counter_name': 'fake_meter'}},
|
||||
{'or': [{'=': {"project_id": "123"}},
|
||||
{'>': {"counter_volume": 2}}]}]}
|
||||
samples = conn.query_samples(query, None, 100)
|
||||
self.assertEqual(1, len(samples))
|
||||
self.assertEqual(4, gsm.call_count)
|
|
@ -1,286 +0,0 @@
|
|||
#
|
||||
# Copyright 2016 Hewlett Packard
|
||||
# (c) Copyright 2018 SUSE LLC
|
||||
#
|
||||
# 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 os
|
||||
|
||||
import fixtures
|
||||
import mock
|
||||
# from oslo_config import fixture as fixture_config
|
||||
from oslo_utils import fileutils
|
||||
from oslotest import base
|
||||
import six
|
||||
import yaml
|
||||
|
||||
from ceilometer.ceilosca_mapping import ceilometer_static_info_mapping
|
||||
from ceilometer.ceilosca_mapping.ceilometer_static_info_mapping import (
|
||||
CeilometerStaticMappingDefinition)
|
||||
from ceilometer.ceilosca_mapping.ceilometer_static_info_mapping import (
|
||||
CeilometerStaticMappingDefinitionException)
|
||||
from ceilometer import monasca_ceilometer_opts
|
||||
from ceilometer import service
|
||||
from ceilometer.storage import impl_monasca
|
||||
|
||||
|
||||
class TestStaticInfoBase(base.BaseTestCase):
|
||||
pipeline_data = yaml.dump({
|
||||
'sources': [{
|
||||
'name': 'test_pipeline',
|
||||
'interval': 1,
|
||||
'meters': ['testbatch', 'testbatch2'],
|
||||
'resources': ['alpha', 'beta', 'gamma', 'delta'],
|
||||
'sinks': ['test_sink']}],
|
||||
'sinks': [{
|
||||
'name': 'test_sink',
|
||||
'transformers': [],
|
||||
'publishers': ["test"]}]
|
||||
})
|
||||
|
||||
cfg = yaml.dump({
|
||||
'meter_info_static_map': [{
|
||||
'name': "disk.ephemeral.size",
|
||||
'type': "gauge",
|
||||
'unit': "GB"
|
||||
}, {
|
||||
'name': "image.delete",
|
||||
'type': "delta",
|
||||
'unit': "image"
|
||||
}, {
|
||||
'name': "image",
|
||||
'type': "gauge",
|
||||
'unit': "image"
|
||||
}, {
|
||||
'name': "disk.root.size",
|
||||
'type': "gauge",
|
||||
'unit': "GB"
|
||||
}
|
||||
]
|
||||
})
|
||||
ceilosca_cfg = yaml.dump({
|
||||
'meter_metric_map': [{
|
||||
'user_id': '$.dimensions.user_id',
|
||||
'name': 'fake_meter',
|
||||
'resource_id': '$.dimensions.resource_id',
|
||||
'region': 'NA',
|
||||
'monasca_metric_name': 'fake_metric',
|
||||
'source': 'NA',
|
||||
'project_id': '$.dimensions.tenant_id',
|
||||
'type': 'gauge',
|
||||
'resource_metadata': '$.measurements[0][2]',
|
||||
'unit': 'B/s'
|
||||
}, {
|
||||
'user_id': '$.dimensions.user_id',
|
||||
'name': 'fake_meter2',
|
||||
'resource_id': '$.dimensions.resource_id',
|
||||
'region': 'NA',
|
||||
'monasca_metric_name': 'fake_metric2',
|
||||
'source': 'NA',
|
||||
'project_id': '$.dimensions.project_id',
|
||||
'type': 'delta',
|
||||
'resource_metadata': '$.measurements[0][2]',
|
||||
'unit': 'B/s'
|
||||
}]
|
||||
})
|
||||
|
||||
def setup_static_mapping_def_file(self, cfg):
|
||||
if six.PY3:
|
||||
cfg = cfg.encode('utf-8')
|
||||
ceilometer_static_info_mapping = fileutils.write_to_tempfile(
|
||||
content=cfg, prefix='ceilometer_static_info_mapping', suffix='yaml'
|
||||
)
|
||||
self.addCleanup(os.remove, ceilometer_static_info_mapping)
|
||||
return ceilometer_static_info_mapping
|
||||
|
||||
def setup_ceilosca_mapping_def_file(self, ceilosca_cfg):
|
||||
if six.PY3:
|
||||
ceilosca_cfg = ceilosca_cfg.encode('utf-8')
|
||||
ceilosca_mapping_file = fileutils.write_to_tempfile(
|
||||
content=ceilosca_cfg, prefix='ceilosca_mapping', suffix='yaml')
|
||||
self.addCleanup(os.remove, ceilosca_mapping_file)
|
||||
return ceilosca_mapping_file
|
||||
|
||||
def setup_pipeline_file(self, pipeline_data):
|
||||
if six.PY3:
|
||||
pipeline_data = pipeline_data.encode('utf-8')
|
||||
pipeline_cfg_file = fileutils.write_to_tempfile(content=pipeline_data,
|
||||
prefix="pipeline",
|
||||
suffix="yaml")
|
||||
self.addCleanup(os.remove, pipeline_cfg_file)
|
||||
return pipeline_cfg_file
|
||||
|
||||
|
||||
class TestStaticInfoDefinition(base.BaseTestCase):
|
||||
|
||||
def test_static_info_definition(self):
|
||||
cfg = dict(name="image.delete",
|
||||
type="delta",
|
||||
unit="image")
|
||||
handler = CeilometerStaticMappingDefinition(cfg)
|
||||
self.assertEqual("delta", handler.cfg['type'])
|
||||
self.assertEqual("image.delete", handler.cfg['name'])
|
||||
self.assertEqual("image", handler.cfg['unit'])
|
||||
|
||||
def test_config_required_missing_fields(self):
|
||||
cfg = dict()
|
||||
try:
|
||||
CeilometerStaticMappingDefinition(cfg)
|
||||
except CeilometerStaticMappingDefinitionException as e:
|
||||
self.assertEqual("Required fields ["
|
||||
"'name', 'type', 'unit'] "
|
||||
"not specified", e.message)
|
||||
|
||||
def test_bad_type_cfg_definition(self):
|
||||
cfg = dict(name="fake_meter",
|
||||
type="foo",
|
||||
unit="B/s")
|
||||
try:
|
||||
CeilometerStaticMappingDefinition(cfg)
|
||||
except CeilometerStaticMappingDefinitionException as e:
|
||||
self.assertEqual("Invalid type foo specified", e.message)
|
||||
|
||||
|
||||
class TestMappedCeilometerStaticInfoProcessing(TestStaticInfoBase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestMappedCeilometerStaticInfoProcessing, self).setUp()
|
||||
# self.CONF = self.useFixture(fixture_config.Config()).conf
|
||||
self.CONF = service.prepare_service([], [])
|
||||
self.CONF.register_opts(list(monasca_ceilometer_opts.OPTS),
|
||||
'monasca')
|
||||
static_info_mapping_file = self.setup_static_mapping_def_file(self.cfg)
|
||||
self.CONF.set_override('ceilometer_static_info_mapping',
|
||||
static_info_mapping_file, group='monasca')
|
||||
self.static_info_mapper = ceilometer_static_info_mapping\
|
||||
.ProcessMappedCeilometerStaticInfo(self.CONF)
|
||||
# self.CONF([], project='ceilometer', validate_default_values=True)
|
||||
|
||||
def test_fallback_mapping_file_path(self):
|
||||
self.useFixture(fixtures.MockPatchObject(self.CONF,
|
||||
'find_file',
|
||||
return_value=None))
|
||||
self.CONF.set_override('ceilometer_static_info_mapping',
|
||||
' ', group='monasca')
|
||||
self.static_info_mapper.reinitialize(self.CONF)
|
||||
fall_bak_path = ceilometer_static_info_mapping.get_config_file(
|
||||
self.CONF)
|
||||
self.assertIn(
|
||||
"ceilosca_mapping/data/ceilometer_static_info_mapping.yaml",
|
||||
fall_bak_path)
|
||||
|
||||
@mock.patch(
|
||||
'ceilometer.ceilosca_mapping.ceilometer_static_info_mapping.LOG')
|
||||
def test_bad_mapping_definition_skip(self, LOG):
|
||||
cfg = yaml.dump({
|
||||
'meter_info_static_map': [{
|
||||
'name': "disk.ephemeral.size",
|
||||
'type': "gauge",
|
||||
'unit': "GB"
|
||||
}, {
|
||||
'name': "image.delete",
|
||||
'type': "delta",
|
||||
'unit': "image"
|
||||
}, {
|
||||
'name': "image",
|
||||
'type': "gauge",
|
||||
'unit': "image"
|
||||
}, {
|
||||
'name': "disk.root.size",
|
||||
'type': "foo",
|
||||
'unit': "GB"
|
||||
}]
|
||||
})
|
||||
static_info_mapping_file = self.setup_static_mapping_def_file(cfg)
|
||||
self.CONF.set_override('ceilometer_static_info_mapping',
|
||||
static_info_mapping_file, group='monasca')
|
||||
data = ceilometer_static_info_mapping.\
|
||||
setup_ceilometer_static_mapping_config(self.CONF)
|
||||
meter_loaded = ceilometer_static_info_mapping.load_definitions(data)
|
||||
self.assertEqual(3, len(meter_loaded))
|
||||
LOG.error.assert_called_with(
|
||||
"Error loading Ceilometer Static Mapping Definition : "
|
||||
"Invalid type foo specified")
|
||||
|
||||
def test_list_of_meters_returned(self):
|
||||
self.static_info_mapper.reinitialize(self.CONF)
|
||||
self.assertItemsEqual(['disk.ephemeral.size', 'disk.root.size',
|
||||
'image', 'image.delete'],
|
||||
self.static_info_mapper.
|
||||
get_list_supported_meters().
|
||||
keys()
|
||||
)
|
||||
|
||||
def test_static_info_of_ceilometer_meter(self):
|
||||
cfg = yaml.dump({
|
||||
'meter_info_static_map': [{
|
||||
'name': "disk.ephemeral.size",
|
||||
'type': "gauge",
|
||||
'unit': "GB"
|
||||
}]
|
||||
})
|
||||
static_info_mapping_file = self.setup_static_mapping_def_file(cfg)
|
||||
self.CONF.set_override('ceilometer_static_info_mapping',
|
||||
static_info_mapping_file, group='monasca')
|
||||
self.static_info_mapper.reinitialize(self.CONF)
|
||||
self.assertEqual('gauge',
|
||||
self.static_info_mapper.get_meter_static_info_key_val(
|
||||
'disk.ephemeral.size', 'type')
|
||||
)
|
||||
|
||||
|
||||
# This Class will only test the driver for the mapped static info
|
||||
# Impl_Monasca Tests will be doing exhaustive tests for other test cases
|
||||
@mock.patch("ceilometer.storage.impl_monasca.MonascaDataFilter")
|
||||
class TestMoanscaDriverForMappedStaticInfo(TestStaticInfoBase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestMoanscaDriverForMappedStaticInfo, self).setUp()
|
||||
# self.CONF = self.useFixture(fixture_config.Config()).conf
|
||||
# self.CONF([], project='ceilometer', validate_default_values=True)
|
||||
self.CONF = service.prepare_service([], [])
|
||||
self.CONF.register_opts(list(monasca_ceilometer_opts.OPTS),
|
||||
'monasca')
|
||||
pipeline_cfg_file = self.setup_pipeline_file(self.pipeline_data)
|
||||
self.CONF.set_override("pipeline_cfg_file", pipeline_cfg_file)
|
||||
static_info_mapping_file = self.setup_static_mapping_def_file(self.cfg)
|
||||
self.CONF.set_override('ceilometer_static_info_mapping',
|
||||
static_info_mapping_file, group='monasca')
|
||||
ceilosca_mapping_file = self.setup_ceilosca_mapping_def_file(
|
||||
self.ceilosca_cfg)
|
||||
self.CONF.set_override('ceilometer_monasca_metrics_mapping',
|
||||
ceilosca_mapping_file, group='monasca')
|
||||
self.static_info_mapper = ceilometer_static_info_mapping\
|
||||
.ProcessMappedCeilometerStaticInfo(self.CONF)
|
||||
self.static_info_mapper.reinitialize(self.CONF)
|
||||
|
||||
def test_get_statc_info_for_mapped_meters_uniq(self, mdf_mock):
|
||||
dummy_metric_names_mocked_return_value = (
|
||||
[{"id": "015c995b1a770147f4ef18f5841ef566ab33521d",
|
||||
"name": "image"},
|
||||
{"id": "335b5d569ad29dc61b3dc24609fad3619e947944",
|
||||
"name": "fake_metric"}])
|
||||
|
||||
with mock.patch('ceilometer.monasca_client.Client') as mock_client:
|
||||
conn = impl_monasca.Connection(self.CONF, '127.0.0.1:8080')
|
||||
metric_names_list_mock = mock_client().metric_names_list
|
||||
metric_names_list_mock.return_value = (
|
||||
dummy_metric_names_mocked_return_value
|
||||
)
|
||||
|
||||
kwargs = dict(limit=4,
|
||||
unique=True)
|
||||
results = list(conn.get_meters(**kwargs))
|
||||
self.assertEqual(2, len(results))
|
||||
self.assertEqual(True, metric_names_list_mock.called)
|
||||
self.assertEqual(1, metric_names_list_mock.call_count)
|
File diff suppressed because it is too large
Load Diff
|
@ -38,7 +38,7 @@ class TestMonascaClient(base.BaseTestCase):
|
|||
'http://localhost:5000/v2.0',
|
||||
'monasca')
|
||||
|
||||
self.CONF.set_override('max_retries', 0, 'database')
|
||||
self.CONF.set_override('database_max_retries', 0, 'monasca')
|
||||
self.mc = self._get_client()
|
||||
|
||||
def tearDown(self):
|
||||
|
@ -111,8 +111,8 @@ class TestMonascaClient(base.BaseTestCase):
|
|||
self.assertIsNotNone(True, conf.service_username)
|
||||
|
||||
def test_retry_on_key_error(self):
|
||||
self.CONF.set_override('max_retries', 2, 'database')
|
||||
self.CONF.set_override('retry_interval', 1, 'database')
|
||||
self.CONF.set_override('database_max_retries', 2, 'monasca')
|
||||
self.CONF.set_override('database_retry_interval', 1, 'monasca')
|
||||
self.mc = self._get_client()
|
||||
with mock.patch.object(
|
||||
self.mc._mon_client.metrics, 'list',
|
||||
|
@ -121,8 +121,8 @@ class TestMonascaClient(base.BaseTestCase):
|
|||
self.assertEqual(2, mocked_metrics_list.call_count)
|
||||
|
||||
def test_no_retry_on_invalid_parameter(self):
|
||||
self.CONF.set_override('max_retries', 2, 'database')
|
||||
self.CONF.set_override('retry_interval', 1, 'database')
|
||||
self.CONF.set_override('database_max_retries', 2, 'monasca')
|
||||
self.CONF.set_override('database_retry_interval', 1, 'monasca')
|
||||
self.mc = self._get_client()
|
||||
|
||||
def _check(exception):
|
||||
|
@ -139,7 +139,8 @@ class TestMonascaClient(base.BaseTestCase):
|
|||
|
||||
def test_max_retris_not_too_much(self):
|
||||
def _check(configured, expected):
|
||||
self.CONF.set_override('max_retries', configured, 'database')
|
||||
self.CONF.set_override('database_max_retries', configured,
|
||||
'monasca')
|
||||
self.mc = self._get_client()
|
||||
self.assertEqual(expected, self.mc._max_retries)
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ rabbit_password = password
|
|||
rabbit_hosts = 16.78.179.83
|
||||
|
||||
[service_credentials]
|
||||
auth_url = http://192.168.10.6:5000
|
||||
auth_url = http://192.168.10.6:5000/v3
|
||||
region_name = RegionOne
|
||||
password = secretservice
|
||||
username = ceilometer
|
||||
|
@ -22,18 +22,22 @@ project_name = service
|
|||
project_domain_id = default
|
||||
user_domain_id = default
|
||||
auth_type = password
|
||||
interface = internalURL
|
||||
|
||||
[keystone_authtoken]
|
||||
signing_dir = /var/cache/ceilometer
|
||||
auth_type = v3password
|
||||
cafile = /opt/stack/data/ca-bundle.pem
|
||||
auth_uri = http://16.78.179.83:5000
|
||||
project_domain_id = default
|
||||
project_name = service
|
||||
user_domain_id = default
|
||||
project_domain_name = Default
|
||||
user_domain_name = Default
|
||||
password = password
|
||||
username = ceilometer
|
||||
auth_url = http://16.78.179.83:35357
|
||||
auth_plugin = password
|
||||
region_name = RegionOne
|
||||
|
||||
[notification]
|
||||
store_events = True
|
||||
|
@ -43,4 +47,18 @@ disable_non_metric_meters = False
|
|||
#metering_connection = mysql://root:password@127.0.0.1/ceilometer?charset=utf8
|
||||
event_connection = mysql://root:password@127.0.0.1/ceilometer?charset=utf8
|
||||
alarm_connection = mysql://root:password@127.0.0.1/ceilometer?charset=utf8
|
||||
metering_connection = monasca://http://127.0.0.1:8070/v2.0
|
||||
connection = monasca://http://127.0.0.1:8070/v2.0
|
||||
|
||||
[monasca]
|
||||
enable_api_pagination = True
|
||||
database_retry_interval = 5
|
||||
database_max_retries = 5
|
||||
service_auth_url = http://192.168.10.6:5000/v3
|
||||
service_password = secretservice
|
||||
service_username = ceilometer
|
||||
service_interface = internalURL
|
||||
service_auth_type = password
|
||||
service_domain_name = Default
|
||||
service_verify = /opt/stack/data/ca-bundle.pem
|
||||
service_region_name = RegionOne
|
||||
monasca_mappings = /etc/ceilometer/monasca_field_definitions.yaml
|
||||
|
|
|
@ -25,8 +25,7 @@ ceilosca_files = {
|
|||
'monasca_client.py',
|
||||
'monasca_ceilometer_opts.py',
|
||||
'publisher/monasca_data_filter.py',
|
||||
'publisher/monclient.py',
|
||||
'storage/impl_monasca.py'
|
||||
'publisher/monclient.py'
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
git+https://github.com/openstack/ceilometer.git@stable/pike#egg=ceilometer
|
||||
git+https://github.com/openstack/ceilometer.git@master#egg=ceilometer
|
||||
mock>=1.2
|
||||
testrepository>=0.0.18
|
||||
testscenarios>=0.4
|
||||
|
|
Loading…
Reference in New Issue