Remove Ceilometer support
Our current Ceilometer driver relies on old version of ceilometer client, which is in deprecated state and not compatible with the latest Telemetry projects (Panko, Gnocchi). The functionality of the driver is not tested automatically and most probably broken. So it's time to let it go and clean the code. This patch leaves "messaging" driver as default for notification and makes "connection-string" a required parameter in CLI. In the future we may consider to change default notification driver, though it requires proper release note handling in all affected projects. Change-Id: Id8442c4ff13c5cc33fd909b4757757cc5f396f50
This commit is contained in:
parent
599060387e
commit
0bb909c7a0
@ -10,11 +10,11 @@ that control this:
|
||||
|
||||
* ``OSPROFILER_COLLECTOR`` specifies which collector to install in DevStack.
|
||||
By default OSProfiler plugin does not install anything, thus default
|
||||
messaging driver with Ceilometer storage will be used.
|
||||
messaging driver will be used.
|
||||
|
||||
Possible values:
|
||||
|
||||
* ``<empty>`` - default messaging driver with Ceilometer is used
|
||||
* ``<empty>`` - default messaging driver is used
|
||||
* ``redis`` - Redis is installed
|
||||
|
||||
The default value of ``OSPROFILER_CONNECTION_STRING`` is set automatically
|
||||
@ -50,13 +50,6 @@ file and add the following to ``[[local|localrc]]`` section:
|
||||
``OSPROFILER_CONNECTION_STRING`` variable (refer to the next section for
|
||||
details)
|
||||
|
||||
* to use default Ceilometer driver::
|
||||
|
||||
enable_plugin panko https://git.openstack.org/openstack/panko master
|
||||
enable_plugin ceilometer https://git.openstack.org/openstack/ceilometer master
|
||||
enable_plugin osprofiler https://git.openstack.org/openstack/osprofiler master
|
||||
|
||||
Note: the order of enabling plugins matters.
|
||||
|
||||
Run DevStack as normal::
|
||||
|
||||
@ -74,7 +67,7 @@ a comma-separated list of string values::
|
||||
OSPROFILER_HMAC_KEYS=swordfish,foxtrot,charlie
|
||||
|
||||
**OSPROFILER_CONNECTION_STRING** - connection string to identify the driver.
|
||||
Default value is ``messaging://`` refers to Ceilometer driver. For a full
|
||||
Default value is ``messaging://`` refers to messaging driver. For a full
|
||||
list of drivers please refer to
|
||||
``http://git.openstack.org/cgit/openstack/osprofiler/tree/osprofiler/drivers``.
|
||||
Example: enable ElasticSearch driver with the server running on localhost::
|
||||
@ -83,7 +76,7 @@ Example: enable ElasticSearch driver with the server running on localhost::
|
||||
|
||||
**OSPROFILER_COLLECTOR** - controls which collector to install into DevStack.
|
||||
The driver is then chosen automatically based on the collector. Empty value assumes
|
||||
that the default messaging driver with Ceilometer is used.
|
||||
that the default messaging driver is used.
|
||||
Example: enable Redis collector::
|
||||
|
||||
OSPROFILER_COLLECTOR=redis
|
||||
|
@ -36,9 +36,6 @@ for i in $(seq 1 ${NOVA_NUM_CELLS}); do
|
||||
CONF_FILES+=(${conf})
|
||||
done
|
||||
|
||||
# This will update CEILOMETER_NOTIFICATION_TOPICS in ceilometer.conf file
|
||||
export CEILOMETER_NOTIFICATION_TOPICS=notifications,profiler
|
||||
|
||||
|
||||
# Functions
|
||||
# ---------
|
||||
@ -86,11 +83,6 @@ function configure_osprofiler() {
|
||||
VAL=${VAL/catch_errors/catch_errors osprofiler}
|
||||
iniset $Q_API_PASTE_FILE composite:neutronapi_v2_0 keystone "$VAL"
|
||||
fi
|
||||
|
||||
if [ -f $CEILOMETER_CONF ]
|
||||
then
|
||||
iniset $CEILOMETER_CONF event store_raw info
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
@ -232,8 +232,8 @@ Available commands:
|
||||
$ osprofiler trace show <trace_id> --json/--html --out /path/to/file
|
||||
|
||||
* In latest versions of OSProfiler with storage drivers (e.g. MongoDB (URI:
|
||||
``mongodb://``), Messaging (URI: ``messaging://``), and Ceilometer
|
||||
(URI: ``ceilometer://``)) ``--connection-string`` parameter should be set up:
|
||||
``mongodb://``), Messaging (URI: ``messaging://``))
|
||||
``--connection-string`` parameter should be set up:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
|
@ -32,11 +32,10 @@ class TraceCommands(BaseCommand):
|
||||
|
||||
@cliutils.arg("trace", help="File with trace or trace id")
|
||||
@cliutils.arg("--connection-string", dest="conn_str",
|
||||
default=(cliutils.env("OSPROFILER_CONNECTION_STRING") or
|
||||
"ceilometer://"),
|
||||
default=(cliutils.env("OSPROFILER_CONNECTION_STRING")),
|
||||
required=True,
|
||||
help="Storage driver's connection string. Defaults to "
|
||||
"env[OSPROFILER_CONNECTION_STRING] if set, else "
|
||||
"ceilometer://")
|
||||
"env[OSPROFILER_CONNECTION_STRING] if set")
|
||||
@cliutils.arg("--transport-url", dest="transport_url",
|
||||
help="Oslo.messaging transport URL (for messaging:// driver "
|
||||
"only), e.g. rabbit://user:password@host:5672/")
|
||||
@ -74,8 +73,6 @@ class TraceCommands(BaseCommand):
|
||||
"used in the command." % args.trace)
|
||||
raise exc.CommandError(msg)
|
||||
|
||||
# NOTE(ayelistratov): Ceilometer translates datetime objects to
|
||||
# strings, other drivers store this data in ISO Date format.
|
||||
# Since datetime.datetime is not JSON serializable by default,
|
||||
# this method will handle that.
|
||||
def datetime_json_serialize(obj):
|
||||
|
@ -25,7 +25,6 @@ import sys
|
||||
from oslo_config import cfg
|
||||
|
||||
import osprofiler
|
||||
from osprofiler.cmd import cliutils
|
||||
from osprofiler.cmd import commands
|
||||
from osprofiler import exc
|
||||
from osprofiler import opts
|
||||
@ -50,134 +49,10 @@ class OSProfilerShell(object):
|
||||
action="version",
|
||||
version=osprofiler.__version__)
|
||||
|
||||
self._append_ceilometer_args(parser)
|
||||
self._append_identity_args(parser)
|
||||
self._append_subcommands(parser)
|
||||
|
||||
return parser
|
||||
|
||||
def _append_ceilometer_args(self, parent_parser):
|
||||
parser = parent_parser.add_argument_group("ceilometer")
|
||||
parser.add_argument(
|
||||
"--ceilometer-url", default=cliutils.env("CEILOMETER_URL"),
|
||||
help="Defaults to env[CEILOMETER_URL].")
|
||||
parser.add_argument(
|
||||
"--ceilometer-api-version",
|
||||
default=cliutils.env("CEILOMETER_API_VERSION", default="2"),
|
||||
help="Defaults to env[CEILOMETER_API_VERSION] or 2.")
|
||||
|
||||
def _append_identity_args(self, parent_parser):
|
||||
# FIXME(fabgia): identity related parameters should be passed by the
|
||||
# Keystone client itself to avoid constant update in all the services
|
||||
# clients. When this fix is merged this method can be made obsolete.
|
||||
# Bug: https://bugs.launchpad.net/python-keystoneclient/+bug/1332337
|
||||
parser = parent_parser.add_argument_group("identity")
|
||||
parser.add_argument("-k", "--insecure",
|
||||
default=False,
|
||||
action="store_true",
|
||||
help="Explicitly allow osprofiler to "
|
||||
"perform \"insecure\" SSL (https) requests. "
|
||||
"The server's certificate will "
|
||||
"not be verified against any certificate "
|
||||
"authorities. This option should be used with "
|
||||
"caution.")
|
||||
|
||||
# User related options
|
||||
parser.add_argument("--os-username",
|
||||
default=cliutils.env("OS_USERNAME"),
|
||||
help="Defaults to env[OS_USERNAME].")
|
||||
|
||||
parser.add_argument("--os-user-id",
|
||||
default=cliutils.env("OS_USER_ID"),
|
||||
help="Defaults to env[OS_USER_ID].")
|
||||
|
||||
parser.add_argument("--os-password",
|
||||
default=cliutils.env("OS_PASSWORD"),
|
||||
help="Defaults to env[OS_PASSWORD].")
|
||||
|
||||
# Domain related options
|
||||
parser.add_argument("--os-user-domain-id",
|
||||
default=cliutils.env("OS_USER_DOMAIN_ID"),
|
||||
help="Defaults to env[OS_USER_DOMAIN_ID].")
|
||||
|
||||
parser.add_argument("--os-user-domain-name",
|
||||
default=cliutils.env("OS_USER_DOMAIN_NAME"),
|
||||
help="Defaults to env[OS_USER_DOMAIN_NAME].")
|
||||
|
||||
parser.add_argument("--os-project-domain-id",
|
||||
default=cliutils.env("OS_PROJECT_DOMAIN_ID"),
|
||||
help="Defaults to env[OS_PROJECT_DOMAIN_ID].")
|
||||
|
||||
parser.add_argument("--os-project-domain-name",
|
||||
default=cliutils.env("OS_PROJECT_DOMAIN_NAME"),
|
||||
help="Defaults to env[OS_PROJECT_DOMAIN_NAME].")
|
||||
|
||||
# Project V3 or Tenant V2 related options
|
||||
parser.add_argument("--os-project-id",
|
||||
default=cliutils.env("OS_PROJECT_ID"),
|
||||
help="Another way to specify tenant ID. "
|
||||
"This option is mutually exclusive with "
|
||||
" --os-tenant-id. "
|
||||
"Defaults to env[OS_PROJECT_ID].")
|
||||
|
||||
parser.add_argument("--os-project-name",
|
||||
default=cliutils.env("OS_PROJECT_NAME"),
|
||||
help="Another way to specify tenant name. "
|
||||
"This option is mutually exclusive with "
|
||||
" --os-tenant-name. "
|
||||
"Defaults to env[OS_PROJECT_NAME].")
|
||||
|
||||
parser.add_argument("--os-tenant-id",
|
||||
default=cliutils.env("OS_TENANT_ID"),
|
||||
help="This option is mutually exclusive with "
|
||||
" --os-project-id. "
|
||||
"Defaults to env[OS_PROJECT_ID].")
|
||||
|
||||
parser.add_argument("--os-tenant-name",
|
||||
default=cliutils.env("OS_TENANT_NAME"),
|
||||
help="Defaults to env[OS_TENANT_NAME].")
|
||||
|
||||
# Auth related options
|
||||
parser.add_argument("--os-auth-url",
|
||||
default=cliutils.env("OS_AUTH_URL"),
|
||||
help="Defaults to env[OS_AUTH_URL].")
|
||||
|
||||
parser.add_argument("--os-auth-token",
|
||||
default=cliutils.env("OS_AUTH_TOKEN"),
|
||||
help="Defaults to env[OS_AUTH_TOKEN].")
|
||||
|
||||
parser.add_argument("--os-cacert",
|
||||
metavar="<ca-certificate-file>",
|
||||
dest="os_cacert",
|
||||
default=cliutils.env("OS_CACERT"),
|
||||
help="Path of CA TLS certificate(s) used to verify"
|
||||
" the remote server\"s certificate. Without this "
|
||||
"option ceilometer looks for the default system CA"
|
||||
" certificates.")
|
||||
|
||||
parser.add_argument("--os-cert",
|
||||
help="Path of certificate file to use in SSL "
|
||||
"connection. This file can optionally be "
|
||||
"prepended with the private key.")
|
||||
|
||||
parser.add_argument("--os-key",
|
||||
help="Path of client key to use in SSL "
|
||||
"connection. This option is not necessary "
|
||||
"if your key is prepended to your cert file.")
|
||||
|
||||
# Service Catalog related options
|
||||
parser.add_argument("--os-service-type",
|
||||
default=cliutils.env("OS_SERVICE_TYPE"),
|
||||
help="Defaults to env[OS_SERVICE_TYPE].")
|
||||
|
||||
parser.add_argument("--os-endpoint-type",
|
||||
default=cliutils.env("OS_ENDPOINT_TYPE"),
|
||||
help="Defaults to env[OS_ENDPOINT_TYPE].")
|
||||
|
||||
parser.add_argument("--os-region-name",
|
||||
default=cliutils.env("OS_REGION_NAME"),
|
||||
help="Defaults to env[OS_REGION_NAME].")
|
||||
|
||||
def _append_subcommands(self, parent_parser):
|
||||
subcommands = parent_parser.add_subparsers(help="<subcommands>")
|
||||
for group_cls in commands.BaseCommand.__subclasses__():
|
||||
|
@ -1,5 +1,4 @@
|
||||
from osprofiler.drivers import base # noqa
|
||||
from osprofiler.drivers import ceilometer # noqa
|
||||
from osprofiler.drivers import elasticsearch_driver # noqa
|
||||
from osprofiler.drivers import loginsight # noqa
|
||||
from osprofiler.drivers import messaging # noqa
|
||||
|
@ -1,79 +0,0 @@
|
||||
# Copyright 2016 Mirantis Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 osprofiler.drivers import base
|
||||
from osprofiler import exc
|
||||
|
||||
|
||||
class Ceilometer(base.Driver):
|
||||
def __init__(self, connection_str, **kwargs):
|
||||
"""Driver receiving profiled information from ceilometer."""
|
||||
super(Ceilometer, self).__init__(connection_str)
|
||||
try:
|
||||
import ceilometerclient.client
|
||||
except ImportError:
|
||||
raise exc.CommandError(
|
||||
"To use this command, you should install "
|
||||
"'ceilometerclient' manually. Use command:\n "
|
||||
"'pip install python-ceilometerclient'.")
|
||||
|
||||
try:
|
||||
self.client = ceilometerclient.client.get_client(
|
||||
kwargs["ceilometer_api_version"], **kwargs)
|
||||
except Exception as e:
|
||||
if hasattr(e, "http_status") and e.http_status == 401:
|
||||
msg = "Invalid OpenStack Identity credentials."
|
||||
else:
|
||||
msg = "Error occurred while connecting to Ceilometer: %s." % e
|
||||
raise exc.CommandError(msg)
|
||||
|
||||
@classmethod
|
||||
def get_name(cls):
|
||||
return "ceilometer"
|
||||
|
||||
def get_report(self, base_id):
|
||||
"""Retrieves and parses notification from ceilometer.
|
||||
|
||||
:param base_id: Base id of trace elements.
|
||||
"""
|
||||
|
||||
_filter = [{"field": "base_id", "op": "eq", "value": base_id}]
|
||||
|
||||
# limit is hardcoded in this code state. Later that will be changed via
|
||||
# connection string usage
|
||||
notifications = [n.to_dict()
|
||||
for n in self.client.events.list(_filter,
|
||||
limit=100000)]
|
||||
|
||||
for n in notifications:
|
||||
traits = n["traits"]
|
||||
|
||||
def find_field(f_name):
|
||||
return [t["value"] for t in traits if t["name"] == f_name][0]
|
||||
|
||||
trace_id = find_field("trace_id")
|
||||
parent_id = find_field("parent_id")
|
||||
name = find_field("name")
|
||||
project = find_field("project")
|
||||
service = find_field("service")
|
||||
host = find_field("host")
|
||||
timestamp = find_field("timestamp")
|
||||
|
||||
payload = n.get("raw", {}).get("payload", {})
|
||||
|
||||
self._append_results(trace_id, parent_id, name, project, service,
|
||||
host, timestamp, payload)
|
||||
|
||||
return self._parse_results()
|
@ -83,9 +83,7 @@ class Messaging(base.Driver):
|
||||
:param info: Contains information about trace element.
|
||||
In payload dict there are always 3 ids:
|
||||
"base_id" - uuid that is common for all notifications
|
||||
related to one trace. Used to simplify
|
||||
retrieving of all trace elements from
|
||||
Ceilometer.
|
||||
related to one trace.
|
||||
"parent_id" - uuid of parent element in trace
|
||||
"trace_id" - uuid of current element in trace
|
||||
|
||||
|
@ -378,7 +378,7 @@ class _Profiler(object):
|
||||
"""Start new event.
|
||||
|
||||
Adds new trace_id to trace stack and sends notification
|
||||
to collector (may be ceilometer). With "info" and 3 ids:
|
||||
to collector. With "info" and 3 ids:
|
||||
base_id - to be able to retrieve all trace elements by one query
|
||||
parent_id - to build tree of events (not just a list)
|
||||
trace_id - current event id.
|
||||
|
@ -34,42 +34,13 @@ class ShellTestCase(test.TestCase):
|
||||
def setUp(self):
|
||||
super(ShellTestCase, self).setUp()
|
||||
self.old_environment = os.environ.copy()
|
||||
os.environ = {
|
||||
"OS_USERNAME": "username",
|
||||
"OS_USER_ID": "user_id",
|
||||
"OS_PASSWORD": "password",
|
||||
"OS_USER_DOMAIN_ID": "user_domain_id",
|
||||
"OS_USER_DOMAIN_NAME": "user_domain_name",
|
||||
"OS_PROJECT_DOMAIN_ID": "project_domain_id",
|
||||
"OS_PROJECT_DOMAIN_NAME": "project_domain_name",
|
||||
"OS_PROJECT_ID": "project_id",
|
||||
"OS_PROJECT_NAME": "project_name",
|
||||
"OS_TENANT_ID": "tenant_id",
|
||||
"OS_TENANT_NAME": "tenant_name",
|
||||
"OS_AUTH_URL": "http://127.0.0.1:5000/v3/",
|
||||
"OS_AUTH_TOKEN": "pass",
|
||||
"OS_CACERT": "/path/to/cacert",
|
||||
"OS_SERVICE_TYPE": "service_type",
|
||||
"OS_ENDPOINT_TYPE": "public",
|
||||
"OS_REGION_NAME": "test"
|
||||
}
|
||||
|
||||
self.ceiloclient = mock.MagicMock()
|
||||
sys.modules["ceilometerclient"] = self.ceiloclient
|
||||
self.addCleanup(sys.modules.pop, "ceilometerclient", None)
|
||||
ceilo_modules = ["client", "shell"]
|
||||
for module in ceilo_modules:
|
||||
sys.modules["ceilometerclient.%s" % module] = getattr(
|
||||
self.ceiloclient, module)
|
||||
self.addCleanup(
|
||||
sys.modules.pop, "ceilometerclient.%s" % module, None)
|
||||
|
||||
def tearDown(self):
|
||||
super(ShellTestCase, self).tearDown()
|
||||
os.environ = self.old_environment
|
||||
|
||||
def _trace_show_cmd(self, format_=None):
|
||||
cmd = "trace show %s" % self.TRACE_ID
|
||||
cmd = "trace show --connection-string redis:// %s" % self.TRACE_ID
|
||||
return cmd if format_ is None else "%s --%s" % (cmd, format_)
|
||||
|
||||
@mock.patch("sys.stdout", six.StringIO())
|
||||
@ -92,38 +63,14 @@ class ShellTestCase(test.TestCase):
|
||||
"Expected: `osprofiler.exc.CommandError` is raised with "
|
||||
"message: '%s'." % expected_message)
|
||||
|
||||
def test_trace_show_ceilometerclient_is_missed(self):
|
||||
sys.modules["ceilometerclient"] = None
|
||||
sys.modules["ceilometerclient.client"] = None
|
||||
sys.modules["ceilometerclient.shell"] = None
|
||||
|
||||
msg = ("To use this command, you should install "
|
||||
"'ceilometerclient' manually. Use command:\n "
|
||||
"'pip install python-ceilometerclient'.")
|
||||
self._test_with_command_error(self._trace_show_cmd(), msg)
|
||||
|
||||
def test_trace_show_unauthorized(self):
|
||||
class FakeHTTPUnauthorized(Exception):
|
||||
http_status = 401
|
||||
|
||||
self.ceiloclient.client.get_client.side_effect = FakeHTTPUnauthorized
|
||||
|
||||
msg = "Invalid OpenStack Identity credentials."
|
||||
self._test_with_command_error(self._trace_show_cmd(), msg)
|
||||
|
||||
def test_trace_show_unknown_error(self):
|
||||
self.ceiloclient.client.get_client.side_effect = Exception("test")
|
||||
msg = "Error occurred while connecting to Ceilometer: test."
|
||||
self._test_with_command_error(self._trace_show_cmd(), msg)
|
||||
|
||||
@mock.patch("osprofiler.drivers.ceilometer.Ceilometer.get_report")
|
||||
@mock.patch("osprofiler.drivers.redis_driver.Redis.get_report")
|
||||
def test_trace_show_no_selected_format(self, mock_get):
|
||||
mock_get.return_value = self._create_mock_notifications()
|
||||
msg = ("You should choose one of the following output formats: "
|
||||
"json, html or dot.")
|
||||
self._test_with_command_error(self._trace_show_cmd(), msg)
|
||||
|
||||
@mock.patch("osprofiler.drivers.ceilometer.Ceilometer.get_report")
|
||||
@mock.patch("osprofiler.drivers.redis_driver.Redis.get_report")
|
||||
@ddt.data(None, {"info": {"started": 0, "finished": 1, "name": "total"},
|
||||
"children": []})
|
||||
def test_trace_show_trace_id_not_found(self, notifications, mock_get):
|
||||
@ -153,7 +100,7 @@ class ShellTestCase(test.TestCase):
|
||||
return notifications
|
||||
|
||||
@mock.patch("sys.stdout", six.StringIO())
|
||||
@mock.patch("osprofiler.drivers.ceilometer.Ceilometer.get_report")
|
||||
@mock.patch("osprofiler.drivers.redis_driver.Redis.get_report")
|
||||
def test_trace_show_in_json(self, mock_get):
|
||||
notifications = self._create_mock_notifications()
|
||||
mock_get.return_value = notifications
|
||||
@ -164,7 +111,7 @@ class ShellTestCase(test.TestCase):
|
||||
sys.stdout.getvalue())
|
||||
|
||||
@mock.patch("sys.stdout", six.StringIO())
|
||||
@mock.patch("osprofiler.drivers.ceilometer.Ceilometer.get_report")
|
||||
@mock.patch("osprofiler.drivers.redis_driver.Redis.get_report")
|
||||
def test_trace_show_in_html(self, mock_get):
|
||||
notifications = self._create_mock_notifications()
|
||||
mock_get.return_value = notifications
|
||||
@ -193,7 +140,7 @@ class ShellTestCase(test.TestCase):
|
||||
sys.stdout.getvalue())
|
||||
|
||||
@mock.patch("sys.stdout", six.StringIO())
|
||||
@mock.patch("osprofiler.drivers.ceilometer.Ceilometer.get_report")
|
||||
@mock.patch("osprofiler.drivers.redis_driver.Redis.get_report")
|
||||
def test_trace_show_write_to_file(self, mock_get):
|
||||
notifications = self._create_mock_notifications()
|
||||
mock_get.return_value = notifications
|
||||
|
@ -1,423 +0,0 @@
|
||||
# Copyright 2016 Mirantis Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 mock
|
||||
|
||||
from osprofiler.drivers.ceilometer import Ceilometer
|
||||
from osprofiler.tests import test
|
||||
|
||||
|
||||
class CeilometerParserTestCase(test.TestCase):
|
||||
def setUp(self):
|
||||
super(CeilometerParserTestCase, self).setUp()
|
||||
self.ceilometer = Ceilometer("ceilometer://",
|
||||
ceilometer_api_version="2")
|
||||
|
||||
def test_build_empty_tree(self):
|
||||
self.assertEqual([], self.ceilometer._build_tree({}))
|
||||
|
||||
def test_build_complex_tree(self):
|
||||
test_input = {
|
||||
"2": {"parent_id": "0", "trace_id": "2", "info": {"started": 1}},
|
||||
"1": {"parent_id": "0", "trace_id": "1", "info": {"started": 0}},
|
||||
"21": {"parent_id": "2", "trace_id": "21", "info": {"started": 6}},
|
||||
"22": {"parent_id": "2", "trace_id": "22", "info": {"started": 7}},
|
||||
"11": {"parent_id": "1", "trace_id": "11", "info": {"started": 1}},
|
||||
"113": {"parent_id": "11", "trace_id": "113",
|
||||
"info": {"started": 3}},
|
||||
"112": {"parent_id": "11", "trace_id": "112",
|
||||
"info": {"started": 2}},
|
||||
"114": {"parent_id": "11", "trace_id": "114",
|
||||
"info": {"started": 5}}
|
||||
}
|
||||
|
||||
expected_output = [
|
||||
{
|
||||
"parent_id": "0",
|
||||
"trace_id": "1",
|
||||
"info": {"started": 0},
|
||||
"children": [
|
||||
{
|
||||
"parent_id": "1",
|
||||
"trace_id": "11",
|
||||
"info": {"started": 1},
|
||||
"children": [
|
||||
{"parent_id": "11", "trace_id": "112",
|
||||
"info": {"started": 2}, "children": []},
|
||||
{"parent_id": "11", "trace_id": "113",
|
||||
"info": {"started": 3}, "children": []},
|
||||
{"parent_id": "11", "trace_id": "114",
|
||||
"info": {"started": 5}, "children": []}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"parent_id": "0",
|
||||
"trace_id": "2",
|
||||
"info": {"started": 1},
|
||||
"children": [
|
||||
{"parent_id": "2", "trace_id": "21",
|
||||
"info": {"started": 6}, "children": []},
|
||||
{"parent_id": "2", "trace_id": "22",
|
||||
"info": {"started": 7}, "children": []}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
result = self.ceilometer._build_tree(test_input)
|
||||
self.assertEqual(expected_output, result)
|
||||
|
||||
def test_get_report_empty(self):
|
||||
self.ceilometer.client = mock.MagicMock()
|
||||
self.ceilometer.client.events.list.return_value = []
|
||||
|
||||
expected = {
|
||||
"info": {
|
||||
"name": "total",
|
||||
"started": 0,
|
||||
"finished": None,
|
||||
"last_trace_started": None
|
||||
},
|
||||
"children": [],
|
||||
"stats": {},
|
||||
}
|
||||
|
||||
base_id = "10"
|
||||
self.assertEqual(expected, self.ceilometer.get_report(base_id))
|
||||
|
||||
def test_get_report(self):
|
||||
self.ceilometer.client = mock.MagicMock()
|
||||
results = [mock.MagicMock(), mock.MagicMock(), mock.MagicMock(),
|
||||
mock.MagicMock(), mock.MagicMock()]
|
||||
|
||||
self.ceilometer.client.events.list.return_value = results
|
||||
results[0].to_dict.return_value = {
|
||||
"traits": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "base_id",
|
||||
"value": "7253ca8c-33b3-4f84-b4f1-f5a4311ddfa4"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "host",
|
||||
"value": "ubuntu"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "method",
|
||||
"value": "POST"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "name",
|
||||
"value": "wsgi-start"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "parent_id",
|
||||
"value": "7253ca8c-33b3-4f84-b4f1-f5a4311ddfa4"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "project",
|
||||
"value": "keystone"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "service",
|
||||
"value": "main"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "timestamp",
|
||||
"value": "2015-12-23T14:02:22.338776"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "trace_id",
|
||||
"value": "06320327-2c2c-45ae-923a-515de890276a"
|
||||
}
|
||||
],
|
||||
"raw": {},
|
||||
"generated": "2015-12-23T10:41:38.415793",
|
||||
"event_type": "profiler.main",
|
||||
"message_id": "65fc1553-3082-4a6f-9d1e-0e3183f57a47"}
|
||||
|
||||
results[1].to_dict.return_value = {
|
||||
"traits":
|
||||
[
|
||||
{
|
||||
"type": "string",
|
||||
"name": "base_id",
|
||||
"value": "7253ca8c-33b3-4f84-b4f1-f5a4311ddfa4"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "host",
|
||||
"value": "ubuntu"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "name",
|
||||
"value": "wsgi-stop"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "parent_id",
|
||||
"value": "7253ca8c-33b3-4f84-b4f1-f5a4311ddfa4"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "project",
|
||||
"value": "keystone"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "service",
|
||||
"value": "main"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "timestamp",
|
||||
"value": "2015-12-23T14:02:22.380405"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "trace_id",
|
||||
"value": "016c97fd-87f3-40b2-9b55-e431156b694b"
|
||||
}
|
||||
],
|
||||
"raw": {},
|
||||
"generated": "2015-12-23T10:41:38.406052",
|
||||
"event_type": "profiler.main",
|
||||
"message_id": "3256d9f1-48ba-4ac5-a50b-64fa42c6e264"}
|
||||
|
||||
results[2].to_dict.return_value = {
|
||||
"traits":
|
||||
[
|
||||
{
|
||||
"type": "string",
|
||||
"name": "base_id",
|
||||
"value": "7253ca8c-33b3-4f84-b4f1-f5a4311ddfa4"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "db.params",
|
||||
"value": "[]"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "db.statement",
|
||||
"value": "SELECT 1"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "host",
|
||||
"value": "ubuntu"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "name",
|
||||
"value": "db-start"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "parent_id",
|
||||
"value": "06320327-2c2c-45ae-923a-515de890276a"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "project",
|
||||
"value": "keystone"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "service",
|
||||
"value": "main"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "timestamp",
|
||||
"value": "2015-12-23T14:02:22.395365"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "trace_id",
|
||||
"value": "1baf1d24-9ca9-4f4c-bd3f-01b7e0c0735a"
|
||||
}
|
||||
],
|
||||
"raw": {},
|
||||
"generated": "2015-12-23T10:41:38.984161",
|
||||
"event_type": "profiler.main",
|
||||
"message_id": "60368aa4-16f0-4f37-a8fb-89e92fdf36ff"}
|
||||
|
||||
results[3].to_dict.return_value = {
|
||||
"traits":
|
||||
[
|
||||
{
|
||||
"type": "string",
|
||||
"name": "base_id",
|
||||
"value": "7253ca8c-33b3-4f84-b4f1-f5a4311ddfa4"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "host",
|
||||
"value": "ubuntu"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "name",
|
||||
"value": "db-stop"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "parent_id",
|
||||
"value": "06320327-2c2c-45ae-923a-515de890276a"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "project",
|
||||
"value": "keystone"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "service",
|
||||
"value": "main"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "timestamp",
|
||||
"value": "2015-12-23T14:02:22.415486"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "trace_id",
|
||||
"value": "1baf1d24-9ca9-4f4c-bd3f-01b7e0c0735a"
|
||||
}
|
||||
],
|
||||
"raw": {},
|
||||
"generated": "2015-12-23T10:41:39.019378",
|
||||
"event_type": "profiler.main",
|
||||
"message_id": "3fbeb339-55c5-4f28-88e4-15bee251dd3d"}
|
||||
|
||||
results[4].to_dict.return_value = {
|
||||
"traits":
|
||||
[
|
||||
{
|
||||
"type": "string",
|
||||
"name": "base_id",
|
||||
"value": "7253ca8c-33b3-4f84-b4f1-f5a4311ddfa4"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "host",
|
||||
"value": "ubuntu"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "method",
|
||||
"value": "GET"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "name",
|
||||
"value": "wsgi-start"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "parent_id",
|
||||
"value": "7253ca8c-33b3-4f84-b4f1-f5a4311ddfa4"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "project",
|
||||
"value": "keystone"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "service",
|
||||
"value": "main"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "timestamp",
|
||||
"value": "2015-12-23T14:02:22.427444"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "trace_id",
|
||||
"value": "016c97fd-87f3-40b2-9b55-e431156b694b"
|
||||
}
|
||||
],
|
||||
"raw": {},
|
||||
"generated": "2015-12-23T10:41:38.360409",
|
||||
"event_type": "profiler.main",
|
||||
"message_id": "57b971a9-572f-4f29-9838-3ed2564c6b5b"}
|
||||
|
||||
expected = {"children": [
|
||||
{"children": [{"children": [],
|
||||
"info": {"finished": 76,
|
||||
"host": "ubuntu",
|
||||
"meta.raw_payload.db-start": {},
|
||||
"meta.raw_payload.db-stop": {},
|
||||
"name": "db",
|
||||
"project": "keystone",
|
||||
"service": "main",
|
||||
"started": 56,
|
||||
"exception": "None"},
|
||||
"parent_id": "06320327-2c2c-45ae-923a-515de890276a",
|
||||
"trace_id": "1baf1d24-9ca9-4f4c-bd3f-01b7e0c0735a"}
|
||||
],
|
||||
"info": {"finished": 0,
|
||||
"host": "ubuntu",
|
||||
"meta.raw_payload.wsgi-start": {},
|
||||
"name": "wsgi",
|
||||
"project": "keystone",
|
||||
"service": "main",
|
||||
"started": 0},
|
||||
"parent_id": "7253ca8c-33b3-4f84-b4f1-f5a4311ddfa4",
|
||||
"trace_id": "06320327-2c2c-45ae-923a-515de890276a"},
|
||||
{"children": [],
|
||||
"info": {"finished": 41,
|
||||
"host": "ubuntu",
|
||||
"meta.raw_payload.wsgi-start": {},
|
||||
"meta.raw_payload.wsgi-stop": {},
|
||||
"name": "wsgi",
|
||||
"project": "keystone",
|
||||
"service": "main",
|
||||
"started": 88,
|
||||
"exception": "None"},
|
||||
"parent_id": "7253ca8c-33b3-4f84-b4f1-f5a4311ddfa4",
|
||||
"trace_id": "016c97fd-87f3-40b2-9b55-e431156b694b"}],
|
||||
"info": {
|
||||
"finished": 88,
|
||||
"name": "total",
|
||||
"started": 0,
|
||||
"last_trace_started": 88
|
||||
},
|
||||
"stats": {"db": {"count": 1, "duration": 20},
|
||||
"wsgi": {"count": 2, "duration": -47}},
|
||||
}
|
||||
|
||||
base_id = "10"
|
||||
|
||||
result = self.ceilometer.get_report(base_id)
|
||||
|
||||
expected_filter = [{"field": "base_id", "op": "eq", "value": base_id}]
|
||||
self.ceilometer.client.events.list.assert_called_once_with(
|
||||
expected_filter, limit=100000)
|
||||
self.assertEqual(expected, result)
|
@ -12,7 +12,6 @@ sphinx>=1.6.2 # BSD
|
||||
# Bandit security code scanner
|
||||
bandit>=1.1.0 # Apache-2.0
|
||||
|
||||
python-ceilometerclient>=2.5.0 # Apache-2.0
|
||||
pymongo>=3.0.2,!=3.1 # Apache-2.0
|
||||
|
||||
# Elasticsearch python client
|
||||
|
Loading…
Reference in New Issue
Block a user