Files
watcher/watcher/tests/decision_engine/datasources/test_grafana_helper.py
sue c28756c48b use HTTPStatus instead of direct code
Python introduced http.HTTPStatus since version 3.5,
and Wallaby has targeted a minimum version of python 3.6.

Change-Id: I45f732f0f59b8fae831bb6c07f4fdd98cdd7409a
2021-07-09 11:02:36 +02:00

303 lines
12 KiB
Python

# -*- encoding: utf-8 -*-
# Copyright (c) 2019 European Organization for Nuclear Research (CERN)
#
# Authors: Corne Lukken <info@dantalion.nl>
#
# 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 unittest import mock
from oslo_config import cfg
from oslo_log import log
from watcher.common import clients
from watcher.common import exception
from watcher.decision_engine.datasources import grafana
from watcher.tests import base
from http import HTTPStatus
import requests
CONF = cfg.CONF
LOG = log.getLogger(__name__)
@mock.patch.object(clients.OpenStackClients, 'nova', mock.Mock())
class TestGrafana(base.BaseTestCase):
"""Test the GrafanaHelper datasource
Objects under test are preceded with t_ and mocked objects are preceded
with m_ , additionally, patched objects are preceded with p_ no object
under test should be created in setUp this can influence the results.
"""
def setUp(self):
super(TestGrafana, self).setUp()
self.p_conf = mock.patch.object(
grafana, 'CONF',
new_callable=mock.PropertyMock)
self.m_conf = self.p_conf.start()
self.addCleanup(self.p_conf.stop)
self.m_conf.grafana_client.token = \
"eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk=="
self.m_conf.grafana_client.base_url = "https://grafana.proxy/api/"
self.m_conf.grafana_client.project_id_map = {'host_cpu_usage': 7221}
self.m_conf.grafana_client.database_map = \
{'host_cpu_usage': 'mock_db'}
self.m_conf.grafana_client.attribute_map = \
{'host_cpu_usage': 'hostname'}
self.m_conf.grafana_client.translator_map = \
{'host_cpu_usage': 'influxdb'}
self.m_conf.grafana_client.query_map = \
{'host_cpu_usage': 'SELECT 100-{0}("{0}_value") FROM {3}.'
'cpu_percent WHERE ("host" =~ /^{1}$/ AND '
'"type_instance" =~/^idle$/ AND time > '
'(now()-{2}m)'}
self.m_grafana = grafana.GrafanaHelper(osc=mock.Mock())
stat_agg_patcher = mock.patch.object(
self.m_grafana, 'statistic_aggregation',
spec=grafana.GrafanaHelper.statistic_aggregation)
self.mock_aggregation = stat_agg_patcher.start()
self.addCleanup(stat_agg_patcher.stop)
self.m_compute_node = mock.Mock(
id='16a86790-327a-45f9-bc82-45839f062fdc',
hostname='example.hostname.ch'
)
self.m_instance = mock.Mock(
id='73b1ff78-aca7-404f-ac43-3ed16c1fa555',
human_id='example.hostname'
)
def test_configured(self):
"""Initialize GrafanaHelper and check if configured is true"""
t_grafana = grafana.GrafanaHelper(osc=mock.Mock())
self.assertTrue(t_grafana.configured)
def test_configured_error(self):
"""Butcher the required configuration and test if configured is false
"""
self.m_conf.grafana_client.base_url = ""
t_grafana = grafana.GrafanaHelper(osc=mock.Mock())
self.assertFalse(t_grafana.configured)
def test_configured_raise_error(self):
"""Test raising error when using improperly configured GrafanHelper
Assure that the _get_metric method raises errors if the metric is
missing from the map
"""
# Clear the METRIC_MAP of Grafana since it is a static variable that
# other tests might have set before this test runs.
grafana.GrafanaHelper.METRIC_MAP = {}
self.m_conf.grafana_client.base_url = ""
t_grafana = grafana.GrafanaHelper(osc=mock.Mock())
self.assertFalse(t_grafana.configured)
self.assertEqual({}, t_grafana.METRIC_MAP)
self.assertRaises(
exception.MetricNotAvailable,
t_grafana.get_host_cpu_usage,
self.m_compute_node
)
@mock.patch.object(requests, 'get')
def test_request_raise_error(self, m_request):
"""Test raising error when status code of request indicates problem
Assure that the _request method raises errors if the response indicates
problems.
"""
m_request.return_value = mock.Mock(status_code=HTTPStatus.NOT_FOUND)
t_grafana = grafana.GrafanaHelper(osc=mock.Mock())
self.assertIsNone(t_grafana.get_host_cpu_usage(self.m_compute_node))
def test_no_metric_raise_error(self):
"""Test raising error when specified meter does not exist"""
t_grafana = grafana.GrafanaHelper(osc=mock.Mock())
self.assertRaises(exception.MetricNotAvailable,
t_grafana.statistic_aggregation,
self.m_compute_node,
'none existing meter', 60)
@mock.patch.object(grafana.GrafanaHelper, '_request')
def test_get_metric_raise_error(self, m_request):
"""Test raising error when endpoint unable to deliver data for metric
"""
m_request.return_value.content = "{}"
t_grafana = grafana.GrafanaHelper(osc=mock.Mock())
self.assertRaises(exception.NoSuchMetricForHost,
t_grafana.get_host_cpu_usage,
self.m_compute_node, 60)
def test_metric_builder(self):
"""Creates valid and invalid sets of configuration for metrics
Ensures that a valid metric entry can be configured even if multiple
invalid configurations exist for other metrics.
"""
self.m_conf.grafana_client.project_id_map = {
'host_cpu_usage': 7221,
'host_ram_usage': 7221,
'instance_ram_allocated': 7221,
}
self.m_conf.grafana_client.database_map = {
'host_cpu_usage': 'mock_db',
'instance_cpu_usage': 'mock_db',
'instance_ram_allocated': 'mock_db',
}
self.m_conf.grafana_client.attribute_map = {
'host_cpu_usage': 'hostname',
'host_power': 'hostname',
'instance_ram_allocated': 'human_id',
}
self.m_conf.grafana_client.translator_map = {
'host_cpu_usage': 'influxdb',
'host_inlet_temp': 'influxdb',
# validate that invalid entries don't get added
'instance_ram_usage': 'dummy',
'instance_ram_allocated': 'influxdb',
}
self.m_conf.grafana_client.query_map = {
'host_cpu_usage': 'SHOW SERIES',
'instance_ram_usage': 'SHOW SERIES',
'instance_ram_allocated': 'SHOW SERIES',
}
expected_result = {
'host_cpu_usage': {
'db': 'mock_db',
'project': 7221,
'attribute': 'hostname',
'translator': 'influxdb',
'query': 'SHOW SERIES'},
'instance_ram_allocated': {
'db': 'mock_db',
'project': 7221,
'attribute': 'human_id',
'translator': 'influxdb',
'query': 'SHOW SERIES'},
}
t_grafana = grafana.GrafanaHelper(osc=mock.Mock())
self.assertEqual(t_grafana.METRIC_MAP, expected_result)
@mock.patch.object(grafana.GrafanaHelper, '_request')
def test_statistic_aggregation(self, m_request):
m_request.return_value.content = "{ \"results\": [{ \"series\": [{ " \
"\"columns\": [\"time\",\"mean\"]," \
"\"values\": [[1552500855000, " \
"67.3550078657577]]}]}]}"
t_grafana = grafana.GrafanaHelper(osc=mock.Mock())
result = t_grafana.statistic_aggregation(
self.m_compute_node, 'compute_node', 'host_cpu_usage', 60)
self.assertEqual(result, 67.3550078657577)
def test_get_host_cpu_usage(self):
self.m_grafana.get_host_cpu_usage(self.m_compute_node, 60, 'min', 15)
self.mock_aggregation.assert_called_once_with(
self.m_compute_node, 'compute_node', 'host_cpu_usage', 60, 'min',
15)
def test_get_host_ram_usage(self):
self.m_grafana.get_host_ram_usage(self.m_compute_node, 60,
'min', 15)
self.mock_aggregation.assert_called_once_with(
self.m_compute_node, 'compute_node', 'host_ram_usage', 60, 'min',
15)
def test_get_host_outlet_temperature(self):
self.m_grafana.get_host_outlet_temp(self.m_compute_node, 60,
'min', 15)
self.mock_aggregation.assert_called_once_with(
self.m_compute_node, 'compute_node', 'host_outlet_temp', 60, 'min',
15)
def test_get_host_inlet_temperature(self):
self.m_grafana.get_host_inlet_temp(self.m_compute_node, 60,
'min', 15)
self.mock_aggregation.assert_called_once_with(
self.m_compute_node, 'compute_node', 'host_inlet_temp', 60, 'min',
15)
def test_get_host_airflow(self):
self.m_grafana.get_host_airflow(self.m_compute_node, 60,
'min', 15)
self.mock_aggregation.assert_called_once_with(
self.m_compute_node, 'compute_node', 'host_airflow', 60, 'min',
15)
def test_get_host_power(self):
self.m_grafana.get_host_power(self.m_compute_node, 60,
'min', 15)
self.mock_aggregation.assert_called_once_with(
self.m_compute_node, 'compute_node', 'host_power', 60, 'min',
15)
def test_get_instance_cpu_usage(self):
self.m_grafana.get_instance_cpu_usage(self.m_compute_node, 60,
'min', 15)
self.mock_aggregation.assert_called_once_with(
self.m_compute_node, 'instance', 'instance_cpu_usage', 60,
'min', 15)
def test_get_instance_ram_usage(self):
self.m_grafana.get_instance_ram_usage(self.m_compute_node, 60,
'min', 15)
self.mock_aggregation.assert_called_once_with(
self.m_compute_node, 'instance', 'instance_ram_usage', 60,
'min', 15)
def test_get_instance_ram_allocated(self):
self.m_grafana.get_instance_ram_allocated(self.m_compute_node, 60,
'min', 15)
self.mock_aggregation.assert_called_once_with(
self.m_compute_node, 'instance', 'instance_ram_allocated', 60,
'min', 15)
def test_get_instance_l3_cache_usage(self):
self.m_grafana.get_instance_l3_cache_usage(self.m_compute_node, 60,
'min', 15)
self.mock_aggregation.assert_called_once_with(
self.m_compute_node, 'instance', 'instance_l3_cache_usage', 60,
'min', 15)
def test_get_instance_root_disk_allocated(self):
self.m_grafana.get_instance_root_disk_size(self.m_compute_node, 60,
'min', 15)
self.mock_aggregation.assert_called_once_with(
self.m_compute_node, 'instance', 'instance_root_disk_size', 60,
'min', 15)