summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--oswin_tempest_plugin/config.py2
-rw-r--r--oswin_tempest_plugin/plugin.py12
-rw-r--r--oswin_tempest_plugin/services/__init__.py0
-rw-r--r--oswin_tempest_plugin/services/gnocchi_client.py50
-rw-r--r--oswin_tempest_plugin/tests/scenario/test_metrics_collection.py63
5 files changed, 87 insertions, 40 deletions
diff --git a/oswin_tempest_plugin/config.py b/oswin_tempest_plugin/config.py
index 4782a13..e74736d 100644
--- a/oswin_tempest_plugin/config.py
+++ b/oswin_tempest_plugin/config.py
@@ -79,7 +79,7 @@ HyperVGroup = [
79 "published by the compute node's ceilometer-polling " 79 "published by the compute node's ceilometer-polling "
80 "agent. The value must be greater by ~15-20 seconds " 80 "agent. The value must be greater by ~15-20 seconds "
81 "than the agent's publish interval, defined in its " 81 "than the agent's publish interval, defined in its "
82 "pipeline.yaml file (typically, the intervals are 600 " 82 "polling.yaml file (typically, the intervals are 600 "
83 "seconds)."), 83 "seconds)."),
84] 84]
85 85
diff --git a/oswin_tempest_plugin/plugin.py b/oswin_tempest_plugin/plugin.py
index 976c221..de865cd 100644
--- a/oswin_tempest_plugin/plugin.py
+++ b/oswin_tempest_plugin/plugin.py
@@ -51,3 +51,15 @@ class OSWinTempestPlugin(plugins.TempestPlugin):
51 """ 51 """
52 return [(group.name, opts) 52 return [(group.name, opts)
53 for group, opts in project_config.list_opts()] 53 for group, opts in project_config.list_opts()]
54
55 def get_service_clients(self):
56 metric_config = config.service_client_config('metric')
57 metric_v1_params = {
58 'name': 'metric_v1',
59 'service_version': 'metric.v1',
60 'module_path': 'oswin_tempest_plugin.services.gnocchi_client',
61 'client_names': ['GnocchiClient'],
62 }
63 metric_v1_params.update(metric_config)
64
65 return [metric_v1_params]
diff --git a/oswin_tempest_plugin/services/__init__.py b/oswin_tempest_plugin/services/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/oswin_tempest_plugin/services/__init__.py
diff --git a/oswin_tempest_plugin/services/gnocchi_client.py b/oswin_tempest_plugin/services/gnocchi_client.py
new file mode 100644
index 0000000..17f8cf6
--- /dev/null
+++ b/oswin_tempest_plugin/services/gnocchi_client.py
@@ -0,0 +1,50 @@
1# Copyright 2018 Cloudbase Solutions Srl
2#
3# All Rights Reserved.
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
17from oslo_serialization import jsonutils as json
18from tempest.lib.common import rest_client
19
20from oswin_tempest_plugin import config
21
22CONF = config.CONF
23
24
25class GnocchiClient(rest_client.RestClient):
26
27 uri_prefix = 'v1'
28
29 def deserialize(self, body):
30 return json.loads(body.replace("\n", ""))
31
32 def _helper_list(self, uri):
33 resp, body = self.get(uri)
34 self.expected_success(200, resp.status)
35 body = self.deserialize(body)
36 return rest_client.ResponseBodyList(resp, body)
37
38 def list_resources(self):
39 uri = '%s/resource/generic' % self.uri_prefix
40 return self._helper_list(uri)
41
42 def list_samples(self, resource_id, meter_name):
43 """Returns a list of samples for the given resource and meter.
44
45 :returns: list, each item being a list containing the following values
46 in this order: timestamp, granularity, value.
47 """
48 uri = '%s/resource/generic/%s/metric/%s/measures' % (
49 self.uri_prefix, resource_id, meter_name)
50 return self._helper_list(uri)
diff --git a/oswin_tempest_plugin/tests/scenario/test_metrics_collection.py b/oswin_tempest_plugin/tests/scenario/test_metrics_collection.py
index 1375388..7ab6cc9 100644
--- a/oswin_tempest_plugin/tests/scenario/test_metrics_collection.py
+++ b/oswin_tempest_plugin/tests/scenario/test_metrics_collection.py
@@ -15,12 +15,6 @@
15 15
16import time 16import time
17 17
18try:
19 # NOTE(claudiub): ceilometer might not be installed, it is not mandatory.
20 from ceilometer.tests.tempest.service import client as telemetry_client
21except Exception:
22 telemetry_client = None
23
24from oslo_log import log as logging 18from oslo_log import log as logging
25from tempest import clients 19from tempest import clients
26 20
@@ -36,11 +30,10 @@ class ClientManager(clients.Manager):
36 def __init__(self, *args, **kwargs): 30 def __init__(self, *args, **kwargs):
37 super(ClientManager, self).__init__(*args, **kwargs) 31 super(ClientManager, self).__init__(*args, **kwargs)
38 32
39 self._set_telemetry_clients() 33 self.set_gnocchi_client()
40 34
41 def _set_telemetry_clients(self): 35 def set_gnocchi_client(self):
42 self.telemetry_client = telemetry_client.TelemetryClient( 36 self.gnocchi_client = self.metric_v1.GnocchiClient()
43 self.auth_provider, **telemetry_client.Manager.telemetry_params)
44 37
45 38
46class MetricsCollectionTestCase(test_base.TestBase): 39class MetricsCollectionTestCase(test_base.TestBase):
@@ -65,7 +58,7 @@ class MetricsCollectionTestCase(test_base.TestBase):
65 a. Configure tempest's polled_metric_delay, by adding the 58 a. Configure tempest's polled_metric_delay, by adding the
66 following line in tempest.conf, in the hyperv section: 59 following line in tempest.conf, in the hyperv section:
67 polled_metrics_delay = <desired value> 60 polled_metrics_delay = <desired value>
68 b. Set the interval value in pipeline.yaml on the compute node to 61 b. Set the interval value in polling.yaml on the compute node to
69 the desired value and restart the ceilometer polling agent. The 62 the desired value and restart the ceilometer polling agent. The
70 interval value is set either for the 'meter_source' or for each 63 interval value is set either for the 'meter_source' or for each
71 of the following: 'cpu_source', 'disk_source', 'network_source'. 64 of the following: 'cpu_source', 'disk_source', 'network_source'.
@@ -73,7 +66,7 @@ class MetricsCollectionTestCase(test_base.TestBase):
73 Note: If the polled_metrics_delay value is too low, the tests might not 66 Note: If the polled_metrics_delay value is too low, the tests might not
74 find any samples and fail because of this. As a recommandation, 67 find any samples and fail because of this. As a recommandation,
75 polled_metrics_delay's value should be: 68 polled_metrics_delay's value should be:
76 polled_metric_delay = <pipeline.yaml interval value> + <15-20 seconds> 69 polled_metric_delay = <polling.yaml interval value> + <15-20 seconds>
77 70
78 tests: 71 tests:
79 1. test_metrics - tests values for the following metrics: 72 1. test_metrics - tests values for the following metrics:
@@ -84,7 +77,7 @@ class MetricsCollectionTestCase(test_base.TestBase):
84 assumptions: 77 assumptions:
85 1. Ceilometer agent on the compute node is running. 78 1. Ceilometer agent on the compute node is running.
86 2. Ceilometer agent on the compute node has the polling interval 79 2. Ceilometer agent on the compute node has the polling interval
87 defined in pipeline.yaml lower than the polled_metrics_delay defined 80 defined in polling.yaml lower than the polled_metrics_delay defined
88 in this test suite. 81 in this test suite.
89 3. The compute nodes' nova-compute and neutron-hyperv-agent services 82 3. The compute nodes' nova-compute and neutron-hyperv-agent services
90 have been configured to enable metrics collection. 83 have been configured to enable metrics collection.
@@ -96,9 +89,9 @@ class MetricsCollectionTestCase(test_base.TestBase):
96 def skip_checks(cls): 89 def skip_checks(cls):
97 super(MetricsCollectionTestCase, cls).skip_checks() 90 super(MetricsCollectionTestCase, cls).skip_checks()
98 91
99 if (not CONF.service_available.ceilometer or 92 for service in ['ceilometer', 'gnocchi']:
100 not CONF.telemetry.deprecated_api_enabled): 93 if not getattr(CONF.service_available, service):
101 raise cls.skipException("Ceilometer API support is required.") 94 raise cls.skipException("%s service is required." % service)
102 95
103 if not CONF.hyperv.collected_metrics: 96 if not CONF.hyperv.collected_metrics:
104 raise cls.skipException("Collected metrics not configured.") 97 raise cls.skipException("Collected metrics not configured.")
@@ -108,26 +101,20 @@ class MetricsCollectionTestCase(test_base.TestBase):
108 super(MetricsCollectionTestCase, cls).setup_clients() 101 super(MetricsCollectionTestCase, cls).setup_clients()
109 102
110 # Telemetry client 103 # Telemetry client
111 cls.telemetry_client = cls.os_primary.telemetry_client 104 cls.telemetry_client = cls.os_primary.gnocchi_client
112 105
113 def _telemetry_check_samples(self, resource_id, meter_name): 106 def _check_samples(self, resource_id, meter_name):
114 LOG.info("Checking %(meter_name)s for resource %(resource_id)s" % { 107 LOG.info("Checking %(meter_name)s for resource %(resource_id)s" % {
115 'meter_name': meter_name, 'resource_id': resource_id}) 108 'meter_name': meter_name, 'resource_id': resource_id})
116 109
117 samples = self.telemetry_client.list_samples(meter_name) 110 samples = self.telemetry_client.list_samples(resource_id, meter_name)
118 self.assertNotEmpty(samples,
119 'Telemetry client returned no samples.')
120
121 resource_samples = [s for s in samples if
122 s['resource_id'] == resource_id]
123 self.assertNotEmpty( 111 self.assertNotEmpty(
124 resource_samples, 112 samples,
125 'No meter %(meter_name)s samples for resource ' 113 'Client returned no samples for the given resource '
126 '%(resource_id)s found.' % {'meter_name': meter_name, 114 '"%(resource_id)s" and meter "%(meter_name)s".' % {
127 'resource_id': resource_id}) 115 'resource_id': resource_id, 'meter_name': meter_name})
128 116
129 non_zero_valued_samples = [s for s in resource_samples if 117 non_zero_valued_samples = [s for s in samples if s[2] > 0]
130 s['counter_volume'] > 0]
131 self.assertNotEmpty( 118 self.assertNotEmpty(
132 non_zero_valued_samples, 119 non_zero_valued_samples,
133 'All meter %(meter_name)s samples for resource ' 120 'All meter %(meter_name)s samples for resource '
@@ -145,12 +132,12 @@ class MetricsCollectionTestCase(test_base.TestBase):
145 # %(OS-EXT-SRV-ATTR:instance_name)s-%(instance_id)s-%(port_id)s 132 # %(OS-EXT-SRV-ATTR:instance_name)s-%(instance_id)s-%(port_id)s
146 # the instance returned by self.servers_client does not contain the 133 # the instance returned by self.servers_client does not contain the
147 # OS-EXT-SRV-ATTR:instance_name field. Which means that the resource_id 134 # OS-EXT-SRV-ATTR:instance_name field. Which means that the resource_id
148 # must be found in ceilometer's resources. 135 # must be found in gnocchi's resources.
149 start_res_id = server['id'] 136 start_res_id = server['id']
150 resources = self.telemetry_client.list_resources() 137 resources = self.telemetry_client.list_resources()
151 res_ids = [r['resource_id'] for r in resources 138 res_ids = [r['id'] for r in resources
152 if r['resource_id'].startswith('instance-') and 139 if r['original_resource_id'].startswith('instance-') and
153 start_res_id in r['resource_id']] 140 start_res_id in r['original_resource_id']]
154 141
155 self.assertEqual(1, len(res_ids)) 142 self.assertEqual(1, len(res_ids))
156 return res_ids[0] 143 return res_ids[0]
@@ -162,19 +149,17 @@ class MetricsCollectionTestCase(test_base.TestBase):
162 time.sleep(CONF.hyperv.polled_metrics_delay) 149 time.sleep(CONF.hyperv.polled_metrics_delay)
163 150
164 # TODO(claudiub): Add more metrics. 151 # TODO(claudiub): Add more metrics.
165
166 if 'cpu' in CONF.hyperv.collected_metrics: 152 if 'cpu' in CONF.hyperv.collected_metrics:
167 cpu_res_id = self._get_instance_cpu_resource_id(server) 153 cpu_res_id = self._get_instance_cpu_resource_id(server)
168 self._telemetry_check_samples(cpu_res_id, 'cpu') 154 self._check_samples(cpu_res_id, 'cpu')
169 155
170 if 'network.outgoing.bytes' in CONF.hyperv.collected_metrics: 156 if 'network.outgoing.bytes' in CONF.hyperv.collected_metrics:
171 port_res_id = self._get_instance_port_resource_id(server) 157 port_res_id = self._get_instance_port_resource_id(server)
172 self._telemetry_check_samples(port_res_id, 158 self._check_samples(port_res_id, 'network.outgoing.bytes')
173 'network.outgoing.bytes')
174 159
175 if 'disk.read.bytes' in CONF.hyperv.collected_metrics: 160 if 'disk.read.bytes' in CONF.hyperv.collected_metrics:
176 disk_resource_id = self._get_instance_disk_resource_id(server) 161 disk_resource_id = self._get_instance_disk_resource_id(server)
177 self._telemetry_check_samples(disk_resource_id, 'disk.read.bytes') 162 self._check_samples(disk_resource_id, 'disk.read.bytes')
178 163
179 def test_metrics(self): 164 def test_metrics(self):
180 server_tuple = self._create_server() 165 server_tuple = self._create_server()