When querying data from datasource, it's possible to miss some data.
In this case if we throw an exception, Audit will failed because of
the exception. We should remove the exception and give the decision
to the strategy.
Change-Id: I1b0e6b78b3bba4df9ba16e093b3910aab1de922e
Closes-Bug: #1847434
(cherry picked from commit f685bf62ab)
302 lines
12 KiB
Python
302 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.
|
|
|
|
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
|
|
|
|
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=404)
|
|
|
|
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)
|