Added a Common KafkaConsumer for all of the plugins
- Added the common consumer for all request messages
- Updated the OpenStack plugins to use the common consumer
- Included the access_credentials topic into this consumer
- Added the json schemas for the openstack, vrops and cloudwatch
access credentials
- Updated the Openstack plugins to use access_credentials messages
- Added and updated all necessary tests
- Updated installation documentation
Change-Id: I1486cf7230e351e5dbf18464110e5780d392eeeb
Signed-off-by: Helena McGough <helena.mcgough@intel.com>
diff --git a/test/OpenStack/__init__.py b/test/OpenStack/__init__.py
index d25e458..861627f 100644
--- a/test/OpenStack/__init__.py
+++ b/test/OpenStack/__init__.py
@@ -19,4 +19,13 @@
# For those usages not covered by the Apache License, Version 2.0 please
# contact: helena.mcgough@intel.com or adrian.hoban@intel.com
##
+"""OpenStack plugin tests."""
+import logging
+
+# Initialise a logger for tests
+logging.basicConfig(filename='OpenStack_tests.log',
+ format='%(asctime)s %(message)s',
+ datefmt='%m/%d/%Y %I:%M:%S %p', filemode='a',
+ level=logging.INFO)
+log = logging.getLogger(__name__)
diff --git a/test/OpenStack/test_alarm_req.py b/test/OpenStack/test_alarm_req.py
new file mode 100644
index 0000000..721fae9
--- /dev/null
+++ b/test/OpenStack/test_alarm_req.py
@@ -0,0 +1,129 @@
+# Copyright 2017 iIntel Research and Development Ireland Limited
+# **************************************************************
+
+# This file is part of OSM Monitoring module
+# All Rights Reserved to Intel Corporation
+
+# 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.
+
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: helena.mcgough@intel.com or adrian.hoban@intel.com
+##
+"""Tests for all alarm request message keys."""
+
+import json
+
+import logging
+
+import unittest
+
+import mock
+
+from plugins.OpenStack.Aodh import alarming as alarm_req
+from plugins.OpenStack.common import Common
+
+__author__ = "Helena McGough"
+
+log = logging.getLogger(__name__)
+
+
+class Message(object):
+ """A class to mock a message object value for alarm requests."""
+
+ def __init__(self):
+ """Initialize a mocked message instance."""
+ self.topic = "alarm_request"
+ self.key = None
+ self.value = json.dumps({"mock_value": "mock_details"})
+
+
+class TestAlarmKeys(unittest.TestCase):
+ """Integration test for alarm request keys."""
+
+ def setUp(self):
+ """Setup the tests for alarm request keys."""
+ super(TestAlarmKeys, self).setUp()
+ self.alarming = alarm_req.Alarming()
+ self.alarming.common = Common()
+
+ @mock.patch.object(Common, "_authenticate")
+ def test_alarming_env_authentication(self, auth):
+ """Test getting an auth_token and endpoint for alarm requests."""
+ # if auth_token is None environment variables are used to authenticare
+ message = Message()
+
+ self.alarming.alarming(message, self.alarming.common, None)
+
+ auth.assert_called_with()
+
+ @mock.patch.object(Common, "_authenticate")
+ def test_acccess_cred_auth(self, auth):
+ """Test receiving auth_token from access creds."""
+ message = Message()
+
+ self.alarming.alarming(message, self.alarming.common, "my_auth_token")
+
+ auth.assert_not_called
+ self.assertEqual(self.alarming.auth_token, "my_auth_token")
+
+ @mock.patch.object(alarm_req.Alarming, "delete_alarm")
+ def test_delete_alarm_key(self, del_alarm):
+ """Test the functionality for a create alarm request."""
+ # Mock a message value and key
+ message = Message()
+ message.key = "delete_alarm_request"
+ message.value = json.dumps({"alarm_delete_request":
+ {"alarm_uuid": "my_alarm_id"}})
+
+ # Call the alarming functionality and check delete request
+ self.alarming.alarming(message, self.alarming.common, "my_auth_token")
+
+ del_alarm.assert_called_with(mock.ANY, mock.ANY, "my_alarm_id")
+
+ @mock.patch.object(alarm_req.Alarming, "list_alarms")
+ def test_list_alarm_key(self, list_alarm):
+ """Test the functionality for a list alarm request."""
+ # Mock a message with list alarm key and value
+ message = Message()
+ message.key = "list_alarm_request"
+ message.value = json.dumps({"alarm_list_request": "my_alarm_details"})
+
+ # Call the alarming functionality and check list functionality
+ self.alarming.alarming(message, self.alarming.common, "my_auth_token")
+ list_alarm.assert_called_with(mock.ANY, mock.ANY, "my_alarm_details")
+
+ @mock.patch.object(alarm_req.Alarming, "update_alarm_state")
+ def test_ack_alarm_key(self, ack_alarm):
+ """Test the functionality for an acknowledge alarm request."""
+ # Mock a message with acknowledge alarm key and value
+ message = Message()
+ message.key = "acknowledge_alarm"
+ message.value = json.dumps({"ack_details":
+ {"alarm_uuid": "my_alarm_id"}})
+
+ # Call alarming functionality and check acknowledge functionality
+ self.alarming.alarming(message, self.alarming.common, "my_auth_token")
+ ack_alarm.assert_called_with(mock.ANY, mock.ANY, "my_alarm_id")
+
+ @mock.patch.object(alarm_req.Alarming, "configure_alarm")
+ def test_config_alarm_key(self, config_alarm):
+ """Test the functionality for a create alarm request."""
+ # Mock a message with config alarm key and value
+ message = Message()
+ message.key = "create_alarm_request"
+ message.value = json.dumps({"alarm_create_request": "alarm_details"})
+
+ # Call alarming functionality and check config alarm call
+ config_alarm.return_value = "my_alarm_id", True
+ self.alarming.alarming(message, self.alarming.common, "my_auth_token")
+ config_alarm.assert_called_with(mock.ANY, mock.ANY, "alarm_details")
diff --git a/test/OpenStack/test_alarming.py b/test/OpenStack/test_alarming.py
new file mode 100644
index 0000000..557a93d
--- /dev/null
+++ b/test/OpenStack/test_alarming.py
@@ -0,0 +1,271 @@
+# Copyright 2017 iIntel Research and Development Ireland Limited
+# **************************************************************
+
+# This file is part of OSM Monitoring module
+# All Rights Reserved to Intel Corporation
+
+# 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.
+
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: helena.mcgough@intel.com or adrian.hoban@intel.com
+##
+"""Tests for all alarm request message keys."""
+
+import json
+
+import logging
+
+import unittest
+
+import mock
+
+from plugins.OpenStack.Aodh import alarming as alarm_req
+from plugins.OpenStack.common import Common
+
+__author__ = "Helena McGough"
+
+log = logging.getLogger(__name__)
+
+auth_token = mock.ANY
+endpoint = mock.ANY
+
+
+class Response(object):
+ """Mock a response message class."""
+
+ def __init__(self, result):
+ """Initialise the response text and status code."""
+ self.text = json.dumps(result)
+ self.status_code = "MOCK_STATUS_CODE"
+
+
+class TestAlarming(unittest.TestCase):
+ """Tests for alarming class functions."""
+
+ def setUp(self):
+ """Setup for tests."""
+ super(TestAlarming, self).setUp()
+ self.alarming = alarm_req.Alarming()
+ self.alarming.common = Common()
+
+ @mock.patch.object(alarm_req.Alarming, "check_payload")
+ @mock.patch.object(alarm_req.Alarming, "check_for_metric")
+ @mock.patch.object(Common, "_perform_request")
+ def test_config_invalid_alarm_req(self, perf_req, check_metric, check_pay):
+ """Test configure an invalid alarm request."""
+ # Configuring with invalid alarm name results in failure
+ values = {"alarm_name": "my_alarm",
+ "metric_name": "my_metric",
+ "resource_uuid": "my_r_id"}
+ self.alarming.configure_alarm(endpoint, auth_token, values)
+ perf_req.assert_not_called
+ perf_req.reset_mock()
+
+ # Correct alarm_name will check for metric in Gnocchi
+ # If there isn't one an alarm won;t be created
+ values = {"alarm_name": "disk_write_ops",
+ "metric_name": "disk_write_ops",
+ "resource_uuid": "my_r_id"}
+
+ check_metric.return_value = None
+
+ self.alarming.configure_alarm(endpoint, auth_token, values)
+ perf_req.assert_not_called
+
+ @mock.patch.object(alarm_req.Alarming, "check_payload")
+ @mock.patch.object(alarm_req.Alarming, "check_for_metric")
+ @mock.patch.object(Common, "_perform_request")
+ def test_config_valid_alarm_req(self, perf_req, check_metric, check_pay):
+ """Test config a valid alarm."""
+ # Correct alarm_name will check for metric in Gnocchi
+ # And conform that the payload is configured correctly
+ values = {"alarm_name": "disk_write_ops",
+ "metric_name": "disk_write_ops",
+ "resource_uuid": "my_r_id"}
+
+ check_metric.return_value = "my_metric_id"
+ check_pay.return_value = "my_payload"
+
+ self.alarming.configure_alarm(endpoint, auth_token, values)
+ perf_req.assert_called_with(
+ "<ANY>/v2/alarms/", auth_token,
+ req_type="post", payload="my_payload")
+
+ @mock.patch.object(Common, "_perform_request")
+ def test_delete_alarm_req(self, perf_req):
+ """Test delete alarm request."""
+ self.alarming.delete_alarm(endpoint, auth_token, "my_alarm_id")
+
+ perf_req.assert_called_with(
+ "<ANY>/v2/alarms/my_alarm_id", auth_token, req_type="delete")
+
+ @mock.patch.object(Common, "_perform_request")
+ def test_invalid_list_alarm_req(self, perf_req):
+ """Test invalid list alarm_req."""
+ # Request will not be performed with out a resoure_id
+ list_details = {"mock_details": "invalid_details"}
+ self.alarming.list_alarms(endpoint, auth_token, list_details)
+
+ perf_req.assert_not_called
+
+ @mock.patch.object(Common, "_perform_request")
+ def test_valid_list_alarm_req(self, perf_req):
+ """Test valid list alarm request."""
+ # Minimum requirement for an alarm list is resource_id
+ list_details = {"resource_uuid": "mock_r_id"}
+ self.alarming.list_alarms(endpoint, auth_token, list_details)
+
+ perf_req.assert_called_with(
+ "<ANY>/v2/alarms/", auth_token, req_type="get")
+ perf_req.reset_mock()
+
+ # Check list with alarm_name defined
+ list_details = {"resource_uuid": "mock_r_id",
+ "alarm_name": "my_alarm",
+ "severity": "critical"}
+ self.alarming.list_alarms(endpoint, auth_token, list_details)
+
+ perf_req.assert_called_with(
+ "<ANY>/v2/alarms/", auth_token, req_type="get")
+
+ @mock.patch.object(Common, "_perform_request")
+ def test_ack_alarm_req(self, perf_req):
+ """Test update alarm state for acknowledge alarm request."""
+ self.alarming.update_alarm_state(endpoint, auth_token, "my_alarm_id")
+
+ perf_req.assert_called_with(
+ "<ANY>/v2/alarms/my_alarm_id/state", auth_token, req_type="put",
+ payload=json.dumps("ok"))
+
+ @mock.patch.object(alarm_req.Alarming, "check_payload")
+ @mock.patch.object(Common, "_perform_request")
+ def test_update_alarm_invalid(self, perf_req, check_pay):
+ """Test update alarm with invalid get response."""
+ values = {"alarm_uuid": "my_alarm_id"}
+
+ self.alarming.update_alarm(endpoint, auth_token, values)
+
+ perf_req.assert_called_with(mock.ANY, auth_token, req_type="get")
+ check_pay.assert_not_called
+
+ @mock.patch.object(alarm_req.Alarming, "check_payload")
+ @mock.patch.object(Common, "_perform_request")
+ def test_update_alarm_invalid_payload(self, perf_req, check_pay):
+ """Test update alarm with invalid payload."""
+ resp = Response({"name": "my_alarm",
+ "state": "alarm",
+ "gnocchi_resources_threshold_rule":
+ {"resource_id": "my_resource_id",
+ "metric": "my_metric"}})
+ perf_req.return_value = resp
+ check_pay.return_value = None
+ values = {"alarm_uuid": "my_alarm_id"}
+
+ self.alarming.update_alarm(endpoint, auth_token, values)
+
+ perf_req.assert_called_with(mock.ANY, auth_token, req_type="get")
+ self.assertEqual(perf_req.call_count, 1)
+
+ @mock.patch.object(alarm_req.Alarming, "check_payload")
+ @mock.patch.object(Common, "_perform_request")
+ def test_update_alarm_valid(self, perf_req, check_pay):
+ """Test valid update alarm request."""
+ resp = Response({"name": "my_alarm",
+ "state": "alarm",
+ "gnocchi_resources_threshold_rule":
+ {"resource_id": "my_resource_id",
+ "metric": "my_metric"}})
+ perf_req.return_value = resp
+ values = {"alarm_uuid": "my_alarm_id"}
+
+ self.alarming.update_alarm(endpoint, auth_token, values)
+
+ check_pay.assert_called_with(values, "my_metric", "my_resource_id",
+ "my_alarm", alarm_state="alarm")
+
+ self.assertEqual(perf_req.call_count, 2)
+ # Second call is the update request
+ perf_req.assert_called_with(
+ '<ANY>/v2/alarms/my_alarm_id', auth_token,
+ req_type="put", payload=check_pay.return_value)
+
+ def test_check_valid_payload(self):
+ """Test the check payload function for a valid payload."""
+ values = {"severity": "warning",
+ "statistic": "COUNT",
+ "threshold_value": 12,
+ "operation": "GT"}
+ payload = self.alarming.check_payload(
+ values, "my_metric", "r_id", "alarm_name")
+
+ self.assertEqual(
+ json.loads(payload), {"name": "alarm_name",
+ "gnocchi_resources_threshold_rule":
+ {"resource_id": "r_id",
+ "metric": "my_metric",
+ "comparison_operator": "gt",
+ "aggregation_method": "count",
+ "threshold": 12,
+ "resource_type": "generic"},
+ "severity": "low",
+ "state": "ok",
+ "type": "gnocchi_resources_threshold"})
+
+ def test_check_valid_state_payload(self):
+ """Test the check payload function for a valid payload with state."""
+ values = {"severity": "warning",
+ "statistic": "COUNT",
+ "threshold_value": 12,
+ "operation": "GT"}
+ payload = self.alarming.check_payload(
+ values, "my_metric", "r_id", "alarm_name", alarm_state="alarm")
+
+ self.assertEqual(
+ json.loads(payload), {"name": "alarm_name",
+ "gnocchi_resources_threshold_rule":
+ {"resource_id": "r_id",
+ "metric": "my_metric",
+ "comparison_operator": "gt",
+ "aggregation_method": "count",
+ "threshold": 12,
+ "resource_type": "generic"},
+ "severity": "low",
+ "state": "alarm",
+ "type": "gnocchi_resources_threshold"})
+
+ def test_check_invalid_payload(self):
+ """Test the check payload function for an invalid payload."""
+ values = {"alarm_values": "mock_invalid_details"}
+ payload = self.alarming.check_payload(
+ values, "my_metric", "r_id", "alarm_name")
+
+ self.assertEqual(payload, None)
+
+ @mock.patch.object(Common, "_perform_request")
+ def test_get_alarm_state(self, perf_req):
+ """Test the get alarm state function."""
+ self.alarming.get_alarm_state(endpoint, auth_token, "alarm_id")
+
+ perf_req.assert_called_with(
+ "<ANY>/v2/alarms/alarm_id/state", auth_token, req_type="get")
+
+ @mock.patch.object(Common, "get_endpoint")
+ @mock.patch.object(Common, "_perform_request")
+ def test_check_for_metric(self, perf_req, get_endpoint):
+ """Test the check for metric function."""
+ get_endpoint.return_value = "gnocchi_endpoint"
+
+ self.alarming.check_for_metric(auth_token, "metric_name", "r_id")
+
+ perf_req.assert_called_with(
+ "gnocchi_endpoint/v1/metric/", auth_token, req_type="get")
diff --git a/test/OpenStack/test_common.py b/test/OpenStack/test_common.py
index 29e9558..e725670 100644
--- a/test/OpenStack/test_common.py
+++ b/test/OpenStack/test_common.py
@@ -21,14 +21,40 @@
##
"""Tests for all common OpenStack methods."""
+import json
+
+import logging
+
import unittest
+from keystoneclient.v3 import client
+
import mock
from plugins.OpenStack.common import Common
+from plugins.OpenStack.settings import Config
import requests
+__author__ = "Helena McGough"
+
+log = logging.getLogger(__name__)
+
+
+class Message(object):
+ """Mock a message for an access credentials request."""
+
+ def __init__(self):
+ """Initialise the topic and value of access_cred message."""
+ self.topic = "access_credentials"
+ self.value = json.dumps({"mock_value": "mock_details",
+ "vim_type": "OPENSTACK",
+ "access_config":
+ {"openstack_site": "my_site",
+ "user": "my_user",
+ "password": "my_password",
+ "vim_tenant_name": "my_tenant"}})
+
class TestCommon(unittest.TestCase):
"""Test the common class for OpenStack plugins."""
@@ -38,6 +64,52 @@
super(TestCommon, self).setUp()
self.common = Common()
+ @mock.patch.object(client, "Client")
+ def test_authenticate_exists(self, key_client):
+ """Testing if an authentication token already exists."""
+ # If the auth_token is already generated a new one will not be creates
+ self.common._auth_token = "my_auth_token"
+ token = self.common._authenticate()
+
+ self.assertEqual(token, "my_auth_token")
+
+ @mock.patch.object(Config, "instance")
+ @mock.patch.object(client, "Client")
+ def test_authenticate_none(self, key_client, cfg):
+ """Test generating a new authentication token."""
+ # If auth_token doesn't exist one will try to be created with keystone
+ # With the configuration values from the environment
+ self.common._auth_token = None
+ config = cfg.return_value
+ url = config.OS_AUTH_URL
+ user = config.OS_USERNAME
+ pword = config.OS_PASSWORD
+ tenant = config.OS_TENANT_NAME
+
+ self.common._authenticate()
+
+ key_client.assert_called_with(auth_url=url,
+ username=user,
+ password=pword,
+ tenant_name=tenant)
+ key_client.reset_mock()
+
+ @mock.patch.object(client, "Client")
+ def test_authenticate_access_cred(self, key_client):
+ """Test generating an auth_token using access_credentials from SO."""
+ # Mock valid message from SO
+ self.common._auth_token = None
+ message = Message()
+
+ self.common._authenticate(message=message)
+
+ # The class variables are set for each consifugration
+ self.assertEqual(self.common.openstack_url, "my_site")
+ self.assertEqual(self.common.user, "my_user")
+ self.assertEqual(self.common.password, "my_password")
+ self.assertEqual(self.common.tenant, "my_tenant")
+ key_client.assert_called
+
@mock.patch.object(requests, 'post')
def test_post_req(self, post):
"""Testing a post request."""
diff --git a/test/OpenStack/test_metric_calls.py b/test/OpenStack/test_metric_calls.py
new file mode 100644
index 0000000..f4c7e97
--- /dev/null
+++ b/test/OpenStack/test_metric_calls.py
@@ -0,0 +1,332 @@
+# Copyright 2017 iIntel Research and Development Ireland Limited
+# *************************************************************
+
+# This file is part of OSM Monitoring module
+# All Rights Reserved to Intel Corporation
+
+# 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.
+
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: helena.mcgough@intel.com or adrian.hoban@intel.com
+##
+"""Tests for all metric request message keys."""
+
+import json
+
+import logging
+
+import unittest
+
+import mock
+
+from plugins.OpenStack.Gnocchi import metrics as metric_req
+
+from plugins.OpenStack.common import Common
+
+__author__ = "Helena McGough"
+
+log = logging.getLogger(__name__)
+
+# Mock auth_token and endpoint
+endpoint = mock.ANY
+auth_token = mock.ANY
+
+# Mock a valid metric list for some tests, and a resultant list
+metric_list = [{"name": "disk_write_ops",
+ "id": "metric_id",
+ "unit": "units",
+ "resource_id": "r_id"}]
+result_list = ["metric_id", "r_id", "units", "disk_write_ops"]
+
+
+class Response(object):
+ """Mock a response object for requests."""
+
+ def __init__(self):
+ """Initialise test and status code values."""
+ self.text = json.dumps("mock_response_text")
+ self.status_code = "STATUS_CODE"
+
+
+class TestMetricCalls(unittest.TestCase):
+ """Integration test for metric request keys."""
+
+ def setUp(self):
+ """Setup the tests for metric request keys."""
+ super(TestMetricCalls, self).setUp()
+ self.metrics = metric_req.Metrics()
+ self.metrics._common = Common()
+
+ @mock.patch.object(metric_req.Metrics, "get_metric_name")
+ @mock.patch.object(metric_req.Metrics, "get_metric_id")
+ @mock.patch.object(Common, "_perform_request")
+ def test_invalid_config_metric_req(
+ self, perf_req, get_metric, get_metric_name):
+ """Test the configure metric function, for an invalid metric."""
+ # Test invalid configuration for creating a metric
+ values = {"metric_details": "invalid_metric"}
+
+ m_id, r_id, status = self.metrics.configure_metric(
+ endpoint, auth_token, values)
+
+ perf_req.assert_not_called
+ self.assertEqual(m_id, None)
+ self.assertEqual(r_id, None)
+ self.assertEqual(status, False)
+
+ # Test with an invalid metric name, will not perform request
+ values = {"resource_uuid": "r_id"}
+ get_metric_name.return_value = "metric_name", None
+
+ m_id, r_id, status = self.metrics.configure_metric(
+ endpoint, auth_token, values)
+
+ perf_req.assert_not_called
+ self.assertEqual(m_id, None)
+ self.assertEqual(r_id, "r_id")
+ self.assertEqual(status, False)
+ get_metric_name.reset_mock()
+
+ # If metric exists, it won't be recreated
+ get_metric_name.return_value = "metric_name", "norm_name"
+ get_metric.return_value = "metric_id"
+
+ m_id, r_id, status = self.metrics.configure_metric(
+ endpoint, auth_token, values)
+
+ perf_req.assert_not_called
+ self.assertEqual(m_id, "metric_id")
+ self.assertEqual(r_id, "r_id")
+ self.assertEqual(status, False)
+
+ @mock.patch.object(metric_req.Metrics, "get_metric_name")
+ @mock.patch.object(metric_req.Metrics, "get_metric_id")
+ @mock.patch.object(Common, "_perform_request")
+ def test_valid_config_metric_req(
+ self, perf_req, get_metric, get_metric_name):
+ """Test the configure metric function, for a valid metric."""
+ # Test valid configuration and payload for creating a metric
+ values = {"resource_uuid": "r_id",
+ "metric_unit": "units"}
+ get_metric_name.return_value = "metric_name", "norm_name"
+ get_metric.return_value = None
+ payload = {"id": "r_id",
+ "metrics": {"metric_name":
+ {"archive_policy_name": "high",
+ "name": "metric_name",
+ "unit": "units"}}}
+
+ self.metrics.configure_metric(endpoint, auth_token, values)
+
+ perf_req.assert_called_with(
+ "<ANY>/v1/resource/generic", auth_token, req_type="post",
+ payload=json.dumps(payload))
+
+ @mock.patch.object(Common, "_perform_request")
+ def test_delete_metric_req(self, perf_req):
+ """Test the delete metric function."""
+ self.metrics.delete_metric(endpoint, auth_token, "metric_id")
+
+ perf_req.assert_called_with(
+ "<ANY>/v1/metric/metric_id", auth_token, req_type="delete")
+
+ @mock.patch.object(Common, "_perform_request")
+ def test_delete_metric_invalid_status(self, perf_req):
+ """Test invalid response for delete request."""
+ perf_req.return_value = "404"
+
+ status = self.metrics.delete_metric(endpoint, auth_token, "metric_id")
+
+ self.assertEqual(status, False)
+
+ @mock.patch.object(metric_req.Metrics, "response_list")
+ @mock.patch.object(Common, "_perform_request")
+ def test_complete_list_metric_req(self, perf_req, resp_list):
+ """Test the complete list metric function."""
+ # Test listing metrics without any configuration options
+ values = {}
+ resp = Response()
+ perf_req.return_value = resp
+ self.metrics.list_metrics(endpoint, auth_token, values)
+
+ perf_req.assert_called_with(
+ "<ANY>/v1/metric/", auth_token, req_type="get")
+ resp_list.assert_called_with("mock_response_text")
+
+ @mock.patch.object(metric_req.Metrics, "response_list")
+ @mock.patch.object(Common, "_perform_request")
+ def test_resource_list_metric_req(self, perf_req, resp_list):
+ """Test the resource list metric function."""
+ # Test listing metrics with a resource id specified
+ values = {"resource_uuid": "resource_id"}
+ resp = Response()
+ perf_req.return_value = resp
+ self.metrics.list_metrics(endpoint, auth_token, values)
+
+ perf_req.assert_called_with(
+ "<ANY>/v1/metric/", auth_token, req_type="get")
+ resp_list.assert_called_with(
+ "mock_response_text", resource="resource_id")
+
+ @mock.patch.object(metric_req.Metrics, "response_list")
+ @mock.patch.object(Common, "_perform_request")
+ def test_name_list_metric_req(self, perf_req, resp_list):
+ """Test the metric_name list metric function."""
+ # Test listing metrics with a metric_name specified
+ values = {"metric_name": "disk_write_bytes"}
+ resp = Response()
+ perf_req.return_value = resp
+ self.metrics.list_metrics(endpoint, auth_token, values)
+
+ perf_req.assert_called_with(
+ "<ANY>/v1/metric/", auth_token, req_type="get")
+ resp_list.assert_called_with(
+ "mock_response_text", metric_name="disk_write_bytes")
+
+ @mock.patch.object(metric_req.Metrics, "response_list")
+ @mock.patch.object(Common, "_perform_request")
+ def test_combined_list_metric_req(self, perf_req, resp_list):
+ """Test the combined resource and metric list metric function."""
+ # Test listing metrics with a resource id and metric name specified
+ values = {"resource_uuid": "resource_id",
+ "metric_name": "packets_sent"}
+ resp = Response()
+ perf_req.return_value = resp
+ self.metrics.list_metrics(endpoint, auth_token, values)
+
+ perf_req.assert_called_with(
+ "<ANY>/v1/metric/", auth_token, req_type="get")
+ resp_list.assert_called_with(
+ "mock_response_text", resource="resource_id",
+ metric_name="packets_sent")
+
+ @mock.patch.object(Common, "_perform_request")
+ def test_get_metric_id(self, perf_req):
+ """Test get_metric_id function."""
+ self.metrics.get_metric_id(endpoint, auth_token, "my_metric", "r_id")
+
+ perf_req.assert_called_with(
+ "<ANY>/v1/resource/generic/r_id", auth_token, req_type="get")
+
+ def test_get_metric_name(self):
+ """Test the result from the get_metric_name function."""
+ # test with a valid metric_name
+ values = {"metric_name": "disk_write_ops"}
+
+ metric_name, norm_name = self.metrics.get_metric_name(values)
+
+ self.assertEqual(metric_name, "disk_write_ops")
+ self.assertEqual(norm_name, "disk.disk_ops")
+
+ # test with an invalid metric name
+ values = {"metric_name": "my_invalid_metric"}
+
+ metric_name, norm_name = self.metrics.get_metric_name(values)
+
+ self.assertEqual(metric_name, "my_invalid_metric")
+ self.assertEqual(norm_name, None)
+
+ @mock.patch.object(Common, "_perform_request")
+ def test_valid_read_data_req(self, perf_req):
+ """Test the read metric data function, for a valid call."""
+ values = {"metric_uuid": "metric_id",
+ "collection_unit": "DAY",
+ "collection_period": 1}
+
+ self.metrics.read_metric_data(endpoint, auth_token, values)
+
+ perf_req.assert_called_once
+
+ @mock.patch.object(Common, "_perform_request")
+ def test_invalid_read_data_req(self, perf_req):
+ """Test the read metric data function, for an invalid call."""
+ # Teo empty lists wil be returned because the values are invalid
+ values = {}
+
+ times, data = self.metrics.read_metric_data(
+ endpoint, auth_token, values)
+
+ self.assertEqual(times, [])
+ self.assertEqual(data, [])
+
+ def test_complete_response_list(self):
+ """Test the response list function for formating metric lists."""
+ # Mock a list for testing purposes, with valid OSM metric
+ resp_list = self.metrics.response_list(metric_list)
+
+ # Check for the expected values in the resulting list
+ for l in result_list:
+ self.assertIn(l, resp_list[0])
+
+ def test_name_response_list(self):
+ """Test the response list with metric name configured."""
+ # Mock the metric name to test a metric name list
+ # Test with a name that is not in the list
+ invalid_name = "my_metric"
+ resp_list = self.metrics.response_list(
+ metric_list, metric_name=invalid_name)
+
+ self.assertEqual(resp_list, [])
+
+ # Test with a name on the list
+ valid_name = "disk_write_ops"
+ resp_list = self.metrics.response_list(
+ metric_list, metric_name=valid_name)
+
+ # Check for the expected values in the resulting list
+ for l in result_list:
+ self.assertIn(l, resp_list[0])
+
+ def test_resource_response_list(self):
+ """Test the response list with resource_id configured."""
+ # Mock a resource_id to test a resource list
+ # Test with resource not on the list
+ invalid_id = "mock_resource"
+ resp_list = self.metrics.response_list(metric_list, resource=invalid_id)
+
+ self.assertEqual(resp_list, [])
+
+ # Test with a resource on the list
+ valid_id = "r_id"
+ resp_list = self.metrics.response_list(metric_list, resource=valid_id)
+
+ # Check for the expected values in the resulting list
+ for l in result_list:
+ self.assertIn(l, resp_list[0])
+
+ def test_combined_response_list(self):
+ """Test the response list function with resource_id and metric_name."""
+ # Test for a combined resource and name list
+ # resource and name are on the lisat
+ valid_name = "disk_write_ops"
+ valid_id = "r_id"
+ resp_list = self.metrics.response_list(
+ metric_list, metric_name=valid_name, resource=valid_id)
+
+ # Check for the expected values in the resulting list
+ for l in result_list:
+ self.assertIn(l, resp_list[0])
+
+ # resource not on list
+ invalid_id = "mock_resource"
+ resp_list = self.metrics.response_list(
+ metric_list, metric_name=valid_name, resource=invalid_id)
+
+ self.assertEqual(resp_list, [])
+
+ # metric name not on list
+ invalid_name = "mock_metric"
+ resp_list = self.metrics.response_list(
+ metric_list, metric_name=invalid_name, resource=valid_id)
+
+ self.assertEqual(resp_list, [])
diff --git a/test/OpenStack/test_metric_req.py b/test/OpenStack/test_metric_req.py
new file mode 100644
index 0000000..a3ab3dd
--- /dev/null
+++ b/test/OpenStack/test_metric_req.py
@@ -0,0 +1,151 @@
+# Copyright 2017 iIntel Research and Development Ireland Limited
+# *************************************************************
+
+# This file is part of OSM Monitoring module
+# All Rights Reserved to Intel Corporation
+
+# 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.
+
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: helena.mcgough@intel.com or adrian.hoban@intel.com
+##
+"""Tests for all metric request message keys."""
+
+import json
+
+import logging
+
+import unittest
+
+import mock
+
+from plugins.OpenStack.Gnocchi import metrics as metric_req
+
+from plugins.OpenStack.common import Common
+
+__author__ = "Helena McGough"
+
+log = logging.getLogger(__name__)
+
+
+class Message(object):
+ """A class to mock a message object value for metric requests."""
+
+ def __init__(self):
+ """Initialize a mocked message instance."""
+ self.topic = "metric_request"
+ self.key = None
+ self.value = json.dumps({"mock_message": "message_details"})
+
+
+class TestMetricReq(unittest.TestCase):
+ """Integration test for metric request keys."""
+
+ def setUp(self):
+ """Setup the tests for metric request keys."""
+ super(TestMetricReq, self).setUp()
+ self.common = Common()
+ self.metrics = metric_req.Metrics()
+
+ @mock.patch.object(Common, "_authenticate")
+ def test_access_cred_metric_auth(self, auth):
+ """Test authentication with access credentials."""
+ message = Message()
+
+ self.metrics.metric_calls(message, self.common, "my_auth_token")
+
+ auth.assert_not_called
+ self.assertEqual(self.metrics.auth_token, "my_auth_token")
+
+ @mock.patch.object(Common, "_authenticate")
+ def test_env_metric_auth(self, auth):
+ """Test authentication with environment variables."""
+ message = Message()
+
+ self.metrics.metric_calls(message, self.common, None)
+
+ auth.assert_called_with()
+
+ @mock.patch.object(metric_req.Metrics, "delete_metric")
+ def test_delete_metric_key(self, del_metric):
+ """Test the functionality for a delete metric request."""
+ # Mock a message value and key
+ message = Message()
+ message.key = "delete_metric_request"
+ message.value = json.dumps({"metric_uuid": "my_metric_id"})
+
+ # Call the metric functionality and check delete request
+ self.metrics.metric_calls(message, self.common, "my_auth_token")
+
+ del_metric.assert_called_with(mock.ANY, mock.ANY, "my_metric_id")
+
+ @mock.patch.object(metric_req.Metrics, "list_metrics")
+ def test_list_metric_key(self, list_metrics):
+ """Test the functionality for a list metric request."""
+ # Mock a message with list metric key and value
+ message = Message()
+ message.key = "list_metric_request"
+ message.value = json.dumps({"metrics_list_request": "metric_details"})
+
+ # Call the metric functionality and check list functionality
+ self.metrics.metric_calls(message, self.common, "my_auth_token")
+ list_metrics.assert_called_with(mock.ANY, mock.ANY, "metric_details")
+
+ @mock.patch.object(metric_req.Metrics, "read_metric_data")
+ @mock.patch.object(metric_req.Metrics, "list_metrics")
+ @mock.patch.object(metric_req.Metrics, "delete_metric")
+ @mock.patch.object(metric_req.Metrics, "configure_metric")
+ def test_update_metric_key(self, config_metric, delete_metric, list_metrics,
+ read_data):
+ """Test the functionality for an update metric request."""
+ # Mock a message with update metric key and value
+ message = Message()
+ message.key = "update_metric_request"
+ message.value = json.dumps({"metric_create":
+ {"metric_name": "my_metric",
+ "resource_uuid": "my_r_id"}})
+
+ # Call metric functionality and confirm no function is called
+ # Gnocchi does not support updating a metric configuration
+ self.metrics.metric_calls(message, self.common, "my_auth_token")
+ config_metric.assert_not_called
+ list_metrics.assert_not_called
+ delete_metric.assert_not_called
+ read_data.assert_not_called
+
+ @mock.patch.object(metric_req.Metrics, "configure_metric")
+ def test_config_metric_key(self, config_metric):
+ """Test the functionality for a create metric request."""
+ # Mock a message with create metric key and value
+ message = Message()
+ message.key = "create_metric_request"
+ message.value = json.dumps({"metric_create": "metric_details"})
+
+ # Call metric functionality and check config metric
+ config_metric.return_value = "metric_id", "resource_id", True
+ self.metrics.metric_calls(message, self.common, "my_auth_token")
+ config_metric.assert_called_with(mock.ANY, mock.ANY, "metric_details")
+
+ @mock.patch.object(metric_req.Metrics, "read_metric_data")
+ def test_read_data_key(self, read_data):
+ """Test the functionality for a read metric data request."""
+ # Mock a message with a read data key and value
+ message = Message()
+ message.key = "read_metric_data_request"
+ message.value = json.dumps({"alarm_uuid": "alarm_id"})
+
+ # Call metric functionality and check read data metrics
+ read_data.return_value = "time_stamps", "data_values"
+ self.metrics.metric_calls(message, self.common, "my_auth_token")
+ read_data.assert_called_with(
+ mock.ANY, mock.ANY, json.loads(message.value))
diff --git a/test/OpenStack/test_responses.py b/test/OpenStack/test_responses.py
new file mode 100644
index 0000000..900d8fe
--- /dev/null
+++ b/test/OpenStack/test_responses.py
@@ -0,0 +1,119 @@
+# Copyright 2017 iIntel Research and Development Ireland Limited
+# *************************************************************
+
+# This file is part of OSM Monitoring module
+# All Rights Reserved to Intel Corporation
+
+# 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.
+
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: helena.mcgough@intel.com or adrian.hoban@intel.com
+##
+"""Test that the correct responses are generated for each message."""
+
+import logging
+
+import unittest
+
+import mock
+
+from plugins.OpenStack import response as resp
+
+__author__ = "Helena McGough"
+
+log = logging.getLogger(__name__)
+
+
+class TestOpenStackResponse(unittest.TestCase):
+ """Tests for responses generated by the OpenStack plugins."""
+
+ def setUp(self):
+ """Setup for testing OpenStack plugin responses."""
+ super(TestOpenStackResponse, self).setUp()
+ self.plugin_resp = resp.OpenStack_Response()
+
+ def test_invalid_key(self):
+ """Test if an invalid key is entered for a response."""
+ message = self.plugin_resp.generate_response("mock_invalid_key")
+ self.assertEqual(message, None)
+
+ @mock.patch.object(
+ resp.OpenStack_Response, "alarm_list_response")
+ def test_list_alarm_resp(self, alarm_list_resp):
+ """Test out a function call for a list alarm response."""
+ message = self.plugin_resp.generate_response("list_alarm_response")
+ self.assertEqual(alarm_list_resp.return_value, message)
+
+ @mock.patch.object(
+ resp.OpenStack_Response, "list_metric_response")
+ def test_list_metric_resp(self, metric_list_resp):
+ """Test list metric response function call."""
+ message = self.plugin_resp.generate_response("list_metric_response")
+ self.assertEqual(message, metric_list_resp.return_value)
+
+ @mock.patch.object(
+ resp.OpenStack_Response, "delete_alarm_response")
+ def test_delete_alarm_resp(self, del_alarm_resp):
+ """Test delete alarm response function call."""
+ message = self.plugin_resp.generate_response("delete_alarm_response")
+ self.assertEqual(message, del_alarm_resp.return_value)
+
+ @mock.patch.object(
+ resp.OpenStack_Response, "delete_metric_response")
+ def test_delete_metric_resp(self, del_metric_resp):
+ """Test the response functionality of delete metric response."""
+ message = self.plugin_resp.generate_response("delete_metric_response")
+ self.assertEqual(message, del_metric_resp.return_value)
+
+ @mock.patch.object(
+ resp.OpenStack_Response, "create_alarm_response")
+ def test_create_alarm_resp(self, config_alarm_resp):
+ """Test create alarm response function call."""
+ message = self.plugin_resp.generate_response("create_alarm_response")
+ self.assertEqual(message, config_alarm_resp.return_value)
+
+ @mock.patch.object(
+ resp.OpenStack_Response, "metric_create_response")
+ def test_create_metric_resp(self, config_metric_resp):
+ """Test create metric response function call."""
+ message = self.plugin_resp.generate_response("create_metric_response")
+ self.assertEqual(message, config_metric_resp.return_value)
+
+ @mock.patch.object(
+ resp.OpenStack_Response, "update_alarm_response")
+ def test_update_alarm_resp(self, up_alarm_resp):
+ """Test update alarm response function call."""
+ message = self.plugin_resp.generate_response("update_alarm_response")
+ self.assertEqual(message, up_alarm_resp.return_value)
+
+ @mock.patch.object(
+ resp.OpenStack_Response, "update_metric_response")
+ def test_update_metric_resp(self, up_metric_resp):
+ """Test update metric response function call."""
+ message = self.plugin_resp.generate_response("update_metric_response")
+ self.assertEqual(message, up_metric_resp.return_value)
+
+ @mock.patch.object(
+ resp.OpenStack_Response, "notify_alarm")
+ def test_notify_alarm(self, notify_alarm):
+ """Test notify alarm response function call."""
+ message = self.plugin_resp.generate_response("notify_alarm")
+ self.assertEqual(message, notify_alarm.return_value)
+
+ @mock.patch.object(
+ resp.OpenStack_Response, "read_metric_data_response")
+ def test_read_metric_data_resp(self, read_data_resp):
+ """Test read metric data response function call."""
+ message = self.plugin_resp.generate_response(
+ "read_metric_data_response")
+ self.assertEqual(message, read_data_resp.return_value)
diff --git a/test/OpenStack/test_settings.py b/test/OpenStack/test_settings.py
new file mode 100644
index 0000000..dcc1053
--- /dev/null
+++ b/test/OpenStack/test_settings.py
@@ -0,0 +1,59 @@
+# Copyright 2017 Intel Research and Development Ireland Limited
+# *************************************************************
+
+# This file is part of OSM Monitoring module
+# All Rights Reserved to Intel Corporation
+
+# 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.
+
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: helena.mcgough@intel.com or adrian.hoban@intel.com
+##
+"""Tests for settings for OpenStack plugins configurations."""
+
+import logging
+
+import os
+
+import unittest
+
+import mock
+
+from plugins.OpenStack.settings import Config
+
+__author__ = "Helena McGough"
+
+log = logging.getLogger(__name__)
+
+
+class TestSettings(unittest.TestCase):
+ """Test the settings class for OpenStack plugin configuration."""
+
+ def setUp(self):
+ """Test Setup."""
+ super(TestSettings, self).setUp()
+ self.cfg = Config.instance()
+
+ def test_set_os_username(self):
+ """Test reading the environment for OpenStack plugin configuration."""
+ self.cfg.read_environ("my_service")
+
+ self.assertEqual(self.cfg.OS_USERNAME, "my_service")
+
+ @mock.patch.object(os, "environ")
+ def test_read_environ(self, environ):
+ """Test reading environment variables for configuration."""
+ self.cfg.read_environ("my_service")
+
+ # Called for each key in the configuration dictionary
+ environ.assert_called_once