Fixes test_metrics test
Ceilometer API was removed in Queens, meaning that test_metrics has not way to validate the metrics collected by the ceilometer-polling agent. The metrics are instead sent and collected by Gnocchi. This patch adds a Gnocchi client, and updates the test_metrics to use this client properly. Change-Id: Id999d758505de10abb356befb854736e1904f6ee
This commit is contained in:
parent
13506c22a8
commit
dac28d1334
@ -79,7 +79,7 @@ HyperVGroup = [
|
||||
"published by the compute node's ceilometer-polling "
|
||||
"agent. The value must be greater by ~15-20 seconds "
|
||||
"than the agent's publish interval, defined in its "
|
||||
"pipeline.yaml file (typically, the intervals are 600 "
|
||||
"polling.yaml file (typically, the intervals are 600 "
|
||||
"seconds)."),
|
||||
]
|
||||
|
||||
|
@ -51,3 +51,15 @@ class OSWinTempestPlugin(plugins.TempestPlugin):
|
||||
"""
|
||||
return [(group.name, opts)
|
||||
for group, opts in project_config.list_opts()]
|
||||
|
||||
def get_service_clients(self):
|
||||
metric_config = config.service_client_config('metric')
|
||||
metric_v1_params = {
|
||||
'name': 'metric_v1',
|
||||
'service_version': 'metric.v1',
|
||||
'module_path': 'oswin_tempest_plugin.services.gnocchi_client',
|
||||
'client_names': ['GnocchiClient'],
|
||||
}
|
||||
metric_v1_params.update(metric_config)
|
||||
|
||||
return [metric_v1_params]
|
||||
|
0
oswin_tempest_plugin/services/__init__.py
Normal file
0
oswin_tempest_plugin/services/__init__.py
Normal file
50
oswin_tempest_plugin/services/gnocchi_client.py
Normal file
50
oswin_tempest_plugin/services/gnocchi_client.py
Normal file
@ -0,0 +1,50 @@
|
||||
# Copyright 2018 Cloudbase Solutions Srl
|
||||
#
|
||||
# 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 oslo_serialization import jsonutils as json
|
||||
from tempest.lib.common import rest_client
|
||||
|
||||
from oswin_tempest_plugin import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class GnocchiClient(rest_client.RestClient):
|
||||
|
||||
uri_prefix = 'v1'
|
||||
|
||||
def deserialize(self, body):
|
||||
return json.loads(body.replace("\n", ""))
|
||||
|
||||
def _helper_list(self, uri):
|
||||
resp, body = self.get(uri)
|
||||
self.expected_success(200, resp.status)
|
||||
body = self.deserialize(body)
|
||||
return rest_client.ResponseBodyList(resp, body)
|
||||
|
||||
def list_resources(self):
|
||||
uri = '%s/resource/generic' % self.uri_prefix
|
||||
return self._helper_list(uri)
|
||||
|
||||
def list_samples(self, resource_id, meter_name):
|
||||
"""Returns a list of samples for the given resource and meter.
|
||||
|
||||
:returns: list, each item being a list containing the following values
|
||||
in this order: timestamp, granularity, value.
|
||||
"""
|
||||
uri = '%s/resource/generic/%s/metric/%s/measures' % (
|
||||
self.uri_prefix, resource_id, meter_name)
|
||||
return self._helper_list(uri)
|
@ -15,12 +15,6 @@
|
||||
|
||||
import time
|
||||
|
||||
try:
|
||||
# NOTE(claudiub): ceilometer might not be installed, it is not mandatory.
|
||||
from ceilometer.tests.tempest.service import client as telemetry_client
|
||||
except Exception:
|
||||
telemetry_client = None
|
||||
|
||||
from oslo_log import log as logging
|
||||
from tempest import clients
|
||||
|
||||
@ -36,11 +30,10 @@ class ClientManager(clients.Manager):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ClientManager, self).__init__(*args, **kwargs)
|
||||
|
||||
self._set_telemetry_clients()
|
||||
self.set_gnocchi_client()
|
||||
|
||||
def _set_telemetry_clients(self):
|
||||
self.telemetry_client = telemetry_client.TelemetryClient(
|
||||
self.auth_provider, **telemetry_client.Manager.telemetry_params)
|
||||
def set_gnocchi_client(self):
|
||||
self.gnocchi_client = self.metric_v1.GnocchiClient()
|
||||
|
||||
|
||||
class MetricsCollectionTestCase(test_base.TestBase):
|
||||
@ -65,7 +58,7 @@ class MetricsCollectionTestCase(test_base.TestBase):
|
||||
a. Configure tempest's polled_metric_delay, by adding the
|
||||
following line in tempest.conf, in the hyperv section:
|
||||
polled_metrics_delay = <desired value>
|
||||
b. Set the interval value in pipeline.yaml on the compute node to
|
||||
b. Set the interval value in polling.yaml on the compute node to
|
||||
the desired value and restart the ceilometer polling agent. The
|
||||
interval value is set either for the 'meter_source' or for each
|
||||
of the following: 'cpu_source', 'disk_source', 'network_source'.
|
||||
@ -73,7 +66,7 @@ class MetricsCollectionTestCase(test_base.TestBase):
|
||||
Note: If the polled_metrics_delay value is too low, the tests might not
|
||||
find any samples and fail because of this. As a recommandation,
|
||||
polled_metrics_delay's value should be:
|
||||
polled_metric_delay = <pipeline.yaml interval value> + <15-20 seconds>
|
||||
polled_metric_delay = <polling.yaml interval value> + <15-20 seconds>
|
||||
|
||||
tests:
|
||||
1. test_metrics - tests values for the following metrics:
|
||||
@ -84,7 +77,7 @@ class MetricsCollectionTestCase(test_base.TestBase):
|
||||
assumptions:
|
||||
1. Ceilometer agent on the compute node is running.
|
||||
2. Ceilometer agent on the compute node has the polling interval
|
||||
defined in pipeline.yaml lower than the polled_metrics_delay defined
|
||||
defined in polling.yaml lower than the polled_metrics_delay defined
|
||||
in this test suite.
|
||||
3. The compute nodes' nova-compute and neutron-hyperv-agent services
|
||||
have been configured to enable metrics collection.
|
||||
@ -96,9 +89,9 @@ class MetricsCollectionTestCase(test_base.TestBase):
|
||||
def skip_checks(cls):
|
||||
super(MetricsCollectionTestCase, cls).skip_checks()
|
||||
|
||||
if (not CONF.service_available.ceilometer or
|
||||
not CONF.telemetry.deprecated_api_enabled):
|
||||
raise cls.skipException("Ceilometer API support is required.")
|
||||
for service in ['ceilometer', 'gnocchi']:
|
||||
if not getattr(CONF.service_available, service):
|
||||
raise cls.skipException("%s service is required." % service)
|
||||
|
||||
if not CONF.hyperv.collected_metrics:
|
||||
raise cls.skipException("Collected metrics not configured.")
|
||||
@ -108,26 +101,20 @@ class MetricsCollectionTestCase(test_base.TestBase):
|
||||
super(MetricsCollectionTestCase, cls).setup_clients()
|
||||
|
||||
# Telemetry client
|
||||
cls.telemetry_client = cls.os_primary.telemetry_client
|
||||
cls.telemetry_client = cls.os_primary.gnocchi_client
|
||||
|
||||
def _telemetry_check_samples(self, resource_id, meter_name):
|
||||
def _check_samples(self, resource_id, meter_name):
|
||||
LOG.info("Checking %(meter_name)s for resource %(resource_id)s" % {
|
||||
'meter_name': meter_name, 'resource_id': resource_id})
|
||||
|
||||
samples = self.telemetry_client.list_samples(meter_name)
|
||||
self.assertNotEmpty(samples,
|
||||
'Telemetry client returned no samples.')
|
||||
|
||||
resource_samples = [s for s in samples if
|
||||
s['resource_id'] == resource_id]
|
||||
samples = self.telemetry_client.list_samples(resource_id, meter_name)
|
||||
self.assertNotEmpty(
|
||||
resource_samples,
|
||||
'No meter %(meter_name)s samples for resource '
|
||||
'%(resource_id)s found.' % {'meter_name': meter_name,
|
||||
'resource_id': resource_id})
|
||||
samples,
|
||||
'Client returned no samples for the given resource '
|
||||
'"%(resource_id)s" and meter "%(meter_name)s".' % {
|
||||
'resource_id': resource_id, 'meter_name': meter_name})
|
||||
|
||||
non_zero_valued_samples = [s for s in resource_samples if
|
||||
s['counter_volume'] > 0]
|
||||
non_zero_valued_samples = [s for s in samples if s[2] > 0]
|
||||
self.assertNotEmpty(
|
||||
non_zero_valued_samples,
|
||||
'All meter %(meter_name)s samples for resource '
|
||||
@ -145,12 +132,12 @@ class MetricsCollectionTestCase(test_base.TestBase):
|
||||
# %(OS-EXT-SRV-ATTR:instance_name)s-%(instance_id)s-%(port_id)s
|
||||
# the instance returned by self.servers_client does not contain the
|
||||
# OS-EXT-SRV-ATTR:instance_name field. Which means that the resource_id
|
||||
# must be found in ceilometer's resources.
|
||||
# must be found in gnocchi's resources.
|
||||
start_res_id = server['id']
|
||||
resources = self.telemetry_client.list_resources()
|
||||
res_ids = [r['resource_id'] for r in resources
|
||||
if r['resource_id'].startswith('instance-') and
|
||||
start_res_id in r['resource_id']]
|
||||
res_ids = [r['id'] for r in resources
|
||||
if r['original_resource_id'].startswith('instance-') and
|
||||
start_res_id in r['original_resource_id']]
|
||||
|
||||
self.assertEqual(1, len(res_ids))
|
||||
return res_ids[0]
|
||||
@ -162,19 +149,17 @@ class MetricsCollectionTestCase(test_base.TestBase):
|
||||
time.sleep(CONF.hyperv.polled_metrics_delay)
|
||||
|
||||
# TODO(claudiub): Add more metrics.
|
||||
|
||||
if 'cpu' in CONF.hyperv.collected_metrics:
|
||||
cpu_res_id = self._get_instance_cpu_resource_id(server)
|
||||
self._telemetry_check_samples(cpu_res_id, 'cpu')
|
||||
self._check_samples(cpu_res_id, 'cpu')
|
||||
|
||||
if 'network.outgoing.bytes' in CONF.hyperv.collected_metrics:
|
||||
port_res_id = self._get_instance_port_resource_id(server)
|
||||
self._telemetry_check_samples(port_res_id,
|
||||
'network.outgoing.bytes')
|
||||
self._check_samples(port_res_id, 'network.outgoing.bytes')
|
||||
|
||||
if 'disk.read.bytes' in CONF.hyperv.collected_metrics:
|
||||
disk_resource_id = self._get_instance_disk_resource_id(server)
|
||||
self._telemetry_check_samples(disk_resource_id, 'disk.read.bytes')
|
||||
self._check_samples(disk_resource_id, 'disk.read.bytes')
|
||||
|
||||
def test_metrics(self):
|
||||
server_tuple = self._create_server()
|
||||
|
Loading…
Reference in New Issue
Block a user