17
zaza/openstack/charm_tests/ceilometer_agent/__init__.py
Normal file
17
zaza/openstack/charm_tests/ceilometer_agent/__init__.py
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright 2021 Canonical Ltd.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Collection of code for setting up and testing ceilometer-agent."""
|
||||
225
zaza/openstack/charm_tests/ceilometer_agent/tests.py
Normal file
225
zaza/openstack/charm_tests/ceilometer_agent/tests.py
Normal file
@@ -0,0 +1,225 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright 2021 Canonical Ltd.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Encapsulate ceilometer-agent testing."""
|
||||
|
||||
import logging
|
||||
import time
|
||||
from gnocchiclient.v1 import client as gnocchi_client
|
||||
|
||||
import zaza.openstack.charm_tests.glance.setup as glance_setup
|
||||
import zaza.openstack.charm_tests.test_utils as test_utils
|
||||
import zaza.openstack.utilities.openstack as openstack_utils
|
||||
|
||||
|
||||
class CeilometerAgentTest(test_utils.OpenStackBaseTest):
|
||||
"""Encapsulate ceilometer-agent tests."""
|
||||
|
||||
def tearDown(self):
|
||||
"""Cleanup of VM guests."""
|
||||
self.resource_cleanup()
|
||||
|
||||
def test_400_gnocchi_metrics(self):
|
||||
"""Verify that ceilometer-agent publishes metrics to gnocchi."""
|
||||
current_os_release = openstack_utils.get_os_release()
|
||||
openstack_pike_or_older = (
|
||||
current_os_release <=
|
||||
openstack_utils.get_os_release('xenial_pike'))
|
||||
if openstack_pike_or_older:
|
||||
# Both the charm and Ceilometer itself had different behaviors in
|
||||
# terms of which metrics were published and how fast, which would
|
||||
# lead to a combinatorial explosion if we had to maintain test
|
||||
# expectations for these old releases.
|
||||
logging.info(
|
||||
'OpenStack Pike or older, skipping')
|
||||
return
|
||||
|
||||
# ceilometer-agent-compute reports metrics for each existing VM, so at
|
||||
# least one VM is needed:
|
||||
self.RESOURCE_PREFIX = 'zaza-ceilometer-agent'
|
||||
self.launch_guest(
|
||||
'ubuntu', instance_key=glance_setup.LTS_IMAGE_NAME)
|
||||
|
||||
logging.info('Instantiating gnocchi client...')
|
||||
overcloud_auth = openstack_utils.get_overcloud_auth()
|
||||
keystone = openstack_utils.get_keystone_client(overcloud_auth)
|
||||
gnocchi_ep = keystone.service_catalog.url_for(
|
||||
service_type='metric',
|
||||
interface='publicURL'
|
||||
)
|
||||
gnocchi = gnocchi_client.Client(
|
||||
session=openstack_utils.get_overcloud_keystone_session(),
|
||||
adapter_options={
|
||||
'endpoint_override': gnocchi_ep,
|
||||
}
|
||||
)
|
||||
|
||||
expected_metric_names = self.__get_expected_metric_names(
|
||||
current_os_release)
|
||||
|
||||
min_timeout_seconds = 500
|
||||
polling_interval_seconds = (
|
||||
openstack_utils.get_application_config_option(
|
||||
self.application_name, 'polling-interval'))
|
||||
timeout_seconds = max(10 * polling_interval_seconds,
|
||||
min_timeout_seconds)
|
||||
logging.info('Giving ceilometer-agent {}s to publish all metrics to '
|
||||
'gnocchi...'.format(timeout_seconds))
|
||||
|
||||
max_time = time.time() + timeout_seconds
|
||||
while time.time() < max_time:
|
||||
found_metric_names = {metric['name']
|
||||
for metric in gnocchi.metric.list()}
|
||||
missing_metric_names = expected_metric_names - found_metric_names
|
||||
if len(missing_metric_names) == 0:
|
||||
logging.info('All expected metrics found.')
|
||||
break
|
||||
time.sleep(polling_interval_seconds)
|
||||
|
||||
unexpected_found_metric_names = (
|
||||
found_metric_names - expected_metric_names)
|
||||
if len(unexpected_found_metric_names) > 0:
|
||||
self.fail(
|
||||
'Unexpected metrics '
|
||||
'published: ' + ', '.join(unexpected_found_metric_names))
|
||||
|
||||
if len(missing_metric_names) > 0:
|
||||
self.fail('These metrics should have been published but '
|
||||
"weren't: " + ', '.join(missing_metric_names))
|
||||
|
||||
def __get_expected_metric_names(self, current_os_release):
|
||||
expected_metric_names = {
|
||||
'compute.instance.booting.time',
|
||||
'disk.ephemeral.size',
|
||||
'disk.root.size',
|
||||
'image.download',
|
||||
'image.serve',
|
||||
'image.size',
|
||||
'memory',
|
||||
'vcpus',
|
||||
}
|
||||
|
||||
all_polsters_are_enabled = (
|
||||
openstack_utils.get_application_config_option(
|
||||
self.application_name, 'enable-all-pollsters'))
|
||||
|
||||
if all_polsters_are_enabled:
|
||||
expected_metric_names |= {
|
||||
'disk.device.allocation',
|
||||
'disk.device.capacity',
|
||||
'disk.device.read.latency',
|
||||
'disk.device.usage',
|
||||
'disk.device.write.latency',
|
||||
'memory.resident',
|
||||
'memory.swap.in',
|
||||
'memory.swap.out',
|
||||
'network.incoming.packets.drop',
|
||||
'network.incoming.packets.error',
|
||||
'network.outgoing.packets.drop',
|
||||
'network.outgoing.packets.error',
|
||||
}
|
||||
|
||||
openstack_queens_or_older = (
|
||||
current_os_release <=
|
||||
openstack_utils.get_os_release('bionic_queens'))
|
||||
openstack_rocky_or_older = (
|
||||
current_os_release <=
|
||||
openstack_utils.get_os_release('bionic_rocky'))
|
||||
openstack_victoria_or_older = (
|
||||
current_os_release <=
|
||||
openstack_utils.get_os_release('groovy_victoria'))
|
||||
|
||||
if openstack_victoria_or_older:
|
||||
expected_metric_names |= {
|
||||
'cpu',
|
||||
'disk.device.read.bytes',
|
||||
'disk.device.read.requests',
|
||||
'disk.device.write.bytes',
|
||||
'disk.device.write.requests',
|
||||
'memory.usage',
|
||||
'network.incoming.bytes',
|
||||
'network.incoming.packets',
|
||||
'network.outgoing.bytes',
|
||||
'network.outgoing.packets',
|
||||
}
|
||||
|
||||
if openstack_rocky_or_older:
|
||||
expected_metric_names |= {
|
||||
'cpu.delta',
|
||||
'cpu_util',
|
||||
'disk.device.read.bytes.rate',
|
||||
'disk.device.read.requests.rate',
|
||||
'disk.device.write.bytes.rate',
|
||||
'disk.device.write.requests.rate',
|
||||
'network.incoming.bytes.rate',
|
||||
'network.incoming.packets.rate',
|
||||
'network.outgoing.bytes.rate',
|
||||
'network.outgoing.packets.rate',
|
||||
}
|
||||
if all_polsters_are_enabled:
|
||||
expected_metric_names |= {
|
||||
'disk.allocation',
|
||||
'disk.capacity',
|
||||
'disk.read.bytes',
|
||||
'disk.read.bytes.rate',
|
||||
'disk.read.requests',
|
||||
'disk.read.requests.rate',
|
||||
'disk.usage',
|
||||
'disk.write.bytes',
|
||||
'disk.write.bytes.rate',
|
||||
'disk.write.requests',
|
||||
'disk.write.requests.rate',
|
||||
}
|
||||
|
||||
if openstack_queens_or_older:
|
||||
expected_metric_names |= {
|
||||
'cpu_l3_cache',
|
||||
'disk.allocation',
|
||||
'disk.capacity',
|
||||
'disk.device.allocation',
|
||||
'disk.device.capacity',
|
||||
'disk.device.iops',
|
||||
'disk.device.latency',
|
||||
'disk.device.read.latency',
|
||||
'disk.device.usage',
|
||||
'disk.device.write.latency',
|
||||
'disk.iops',
|
||||
'disk.latency',
|
||||
'disk.read.bytes',
|
||||
'disk.read.bytes.rate',
|
||||
'disk.read.requests',
|
||||
'disk.read.requests.rate',
|
||||
'disk.usage',
|
||||
'disk.write.bytes',
|
||||
'disk.write.bytes.rate',
|
||||
'disk.write.requests',
|
||||
'disk.write.requests.rate',
|
||||
'memory.bandwidth.local',
|
||||
'memory.bandwidth.total',
|
||||
'memory.resident',
|
||||
'memory.swap.in',
|
||||
'memory.swap.out',
|
||||
'network.incoming.packets.drop',
|
||||
'network.incoming.packets.error',
|
||||
'network.outgoing.packets.drop',
|
||||
'network.outgoing.packets.error',
|
||||
'perf.cache.misses',
|
||||
'perf.cache.references',
|
||||
'perf.cpu.cycles',
|
||||
'perf.instructions',
|
||||
}
|
||||
|
||||
return expected_metric_names
|
||||
@@ -82,7 +82,7 @@ def basic_overcloud_network(limit_gws=None):
|
||||
# Get keystone session
|
||||
keystone_session = openstack_utils.get_overcloud_keystone_session()
|
||||
|
||||
# Get optional use_juju_wait for netw ork option
|
||||
# Get optional use_juju_wait for network option
|
||||
options = (lifecycle_utils
|
||||
.get_charm_config(fatal=False)
|
||||
.get('configure_options', {}))
|
||||
|
||||
@@ -635,7 +635,7 @@ class OpenStackBaseTest(BaseCharmTest):
|
||||
|
||||
def launch_guest(self, guest_name, userdata=None, use_boot_volume=False,
|
||||
instance_key=None):
|
||||
"""Launch two guests to use in tests.
|
||||
"""Launch one guest to use in tests.
|
||||
|
||||
Note that it is up to the caller to have set the RESOURCE_PREFIX class
|
||||
variable prior to calling this method.
|
||||
|
||||
Reference in New Issue
Block a user