Apply cookiecutter to newly split project telemetry-tempest-plugin
This tempest plugin is being split out of the main ceilometer project in
accordance with Queens goal "Split Tempest Plugins into Separate
Repos/Projects"[1]. This patch applies the standard boilerplate files
for OpenStack projects so that it can stand on its own.
It contains tempest tests for Aodh, Gnocchi, Ceilometer and Panko projects.
[1] https://governance.openstack.org/tc/goals/queens/split-tempest-plugins.html
diff --git a/telemetry_tempest_plugin/aodh/api/__init__.py b/telemetry_tempest_plugin/aodh/api/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/telemetry_tempest_plugin/aodh/api/__init__.py
diff --git a/telemetry_tempest_plugin/aodh/api/base.py b/telemetry_tempest_plugin/aodh/api/base.py
new file mode 100644
index 0000000..92339b7
--- /dev/null
+++ b/telemetry_tempest_plugin/aodh/api/base.py
@@ -0,0 +1,64 @@
+# 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 tempest import config
+from tempest.lib.common.utils import data_utils
+from tempest.lib import exceptions as lib_exc
+import tempest.test
+
+from telemetry_tempest_plugin.aodh.service import client
+
+CONF = config.CONF
+
+
+class BaseAlarmingTest(tempest.test.BaseTestCase):
+ """Base test case class for all Alarming API tests."""
+
+ credentials = ['primary']
+ client_manager = client.Manager
+
+ @classmethod
+ def skip_checks(cls):
+ super(BaseAlarmingTest, cls).skip_checks()
+ if not CONF.service_available.aodh_plugin:
+ raise cls.skipException("Aodh support is required")
+
+ @classmethod
+ def setup_clients(cls):
+ super(BaseAlarmingTest, cls).setup_clients()
+ cls.alarming_client = cls.os_primary.alarming_client
+
+ @classmethod
+ def resource_setup(cls):
+ super(BaseAlarmingTest, cls).resource_setup()
+ cls.alarm_ids = []
+
+ @classmethod
+ def create_alarm(cls, **kwargs):
+ body = cls.alarming_client.create_alarm(
+ name=data_utils.rand_name('telemetry_alarm'),
+ type='threshold', **kwargs)
+ cls.alarm_ids.append(body['alarm_id'])
+ return body
+
+ @staticmethod
+ def cleanup_resources(method, list_of_ids):
+ for resource_id in list_of_ids:
+ try:
+ method(resource_id)
+ except lib_exc.NotFound:
+ pass
+
+ @classmethod
+ def resource_cleanup(cls):
+ cls.cleanup_resources(cls.alarming_client.delete_alarm, cls.alarm_ids)
+ super(BaseAlarmingTest, cls).resource_cleanup()
diff --git a/telemetry_tempest_plugin/aodh/api/test_alarming_api.py b/telemetry_tempest_plugin/aodh/api/test_alarming_api.py
new file mode 100644
index 0000000..bb486e5
--- /dev/null
+++ b/telemetry_tempest_plugin/aodh/api/test_alarming_api.py
@@ -0,0 +1,94 @@
+# 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 tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
+
+from telemetry_tempest_plugin.aodh.api import base
+
+
+class TelemetryAlarmingAPITest(base.BaseAlarmingTest):
+
+ @classmethod
+ def resource_setup(cls):
+ super(TelemetryAlarmingAPITest, cls).resource_setup()
+ cls.rule = {'meter_name': 'cpu_util',
+ 'comparison_operator': 'gt',
+ 'threshold': 80.0,
+ 'period': 70}
+ for i in range(2):
+ cls.create_alarm(threshold_rule=cls.rule)
+
+ @decorators.idempotent_id('1c918e06-210b-41eb-bd45-14676dd77cd7')
+ def test_alarm_list(self):
+ # List alarms
+ alarm_list = self.alarming_client.list_alarms()
+
+ # Verify created alarm in the list
+ fetched_ids = [a['alarm_id'] for a in alarm_list]
+ missing_alarms = [a for a in self.alarm_ids if a not in fetched_ids]
+ self.assertEqual(0, len(missing_alarms),
+ "Failed to find the following created alarm(s)"
+ " in a fetched list: %s" %
+ ', '.join(str(a) for a in missing_alarms))
+
+ @decorators.idempotent_id('1297b095-39c1-4e74-8a1f-4ae998cedd68')
+ def test_create_update_get_delete_alarm(self):
+ # Create an alarm
+ alarm_name = data_utils.rand_name('telemetry_alarm')
+ body = self.alarming_client.create_alarm(
+ name=alarm_name, type='threshold', threshold_rule=self.rule)
+ self.assertEqual(alarm_name, body['name'])
+ alarm_id = body['alarm_id']
+ self.assertDictContainsSubset(self.rule, body['threshold_rule'])
+ # Update alarm with new rule and new name
+ new_rule = {'meter_name': 'cpu',
+ 'comparison_operator': 'eq',
+ 'threshold': 70.0,
+ 'period': 60}
+ alarm_name_updated = data_utils.rand_name('telemetry-alarm-update')
+ body = self.alarming_client.update_alarm(
+ alarm_id,
+ threshold_rule=new_rule,
+ name=alarm_name_updated,
+ type='threshold')
+ self.assertEqual(alarm_name_updated, body['name'])
+ self.assertDictContainsSubset(new_rule, body['threshold_rule'])
+ # Get and verify details of an alarm after update
+ body = self.alarming_client.show_alarm(alarm_id)
+ self.assertEqual(alarm_name_updated, body['name'])
+ self.assertDictContainsSubset(new_rule, body['threshold_rule'])
+ # Get history for the alarm and verify the same
+ body = self.alarming_client.show_alarm_history(alarm_id)
+ self.assertEqual("rule change", body[0]['type'])
+ self.assertIn(alarm_name_updated, body[0]['detail'])
+ self.assertEqual("creation", body[1]['type'])
+ self.assertIn(alarm_name, body[1]['detail'])
+ # Delete alarm and verify if deleted
+ self.alarming_client.delete_alarm(alarm_id)
+ self.assertRaises(lib_exc.NotFound,
+ self.alarming_client.show_alarm, alarm_id)
+
+ @decorators.idempotent_id('aca49486-70bb-4016-87e0-f6131374f742')
+ def test_set_get_alarm_state(self):
+ alarm_states = ['ok', 'alarm', 'insufficient data']
+ alarm = self.create_alarm(threshold_rule=self.rule)
+ # Set alarm state and verify
+ new_state =\
+ [elem for elem in alarm_states if elem != alarm['state']][0]
+ state = self.alarming_client.alarm_set_state(alarm['alarm_id'],
+ new_state)
+ self.assertEqual(new_state, state.data)
+ # Get alarm state and verify
+ state = self.alarming_client.show_alarm_state(alarm['alarm_id'])
+ self.assertEqual(new_state, state.data)
diff --git a/telemetry_tempest_plugin/aodh/api/test_alarming_api_negative.py b/telemetry_tempest_plugin/aodh/api/test_alarming_api_negative.py
new file mode 100644
index 0000000..0707f67
--- /dev/null
+++ b/telemetry_tempest_plugin/aodh/api/test_alarming_api_negative.py
@@ -0,0 +1,71 @@
+# Copyright 2015 GlobalLogic. All rights reserved.
+#
+# 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 oslo_utils import uuidutils
+from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
+
+from telemetry_tempest_plugin.aodh.api import base
+
+
+class TelemetryAlarmingNegativeTest(base.BaseAlarmingTest):
+ """Negative tests for show_alarm, update_alarm, show_alarm_history tests
+
+ ** show non-existent alarm
+ ** show the deleted alarm
+ ** delete deleted alarm
+ ** update deleted alarm
+ """
+
+ @decorators.attr(type=['negative'])
+ @decorators.idempotent_id('668743d5-08ad-4480-b2b8-15da34f81e7e')
+ def test_get_non_existent_alarm(self):
+ # get the non-existent alarm
+ non_existent_id = uuidutils.generate_uuid()
+ self.assertRaises(lib_exc.NotFound, self.alarming_client.show_alarm,
+ non_existent_id)
+
+ @decorators.attr(type=['negative'])
+ @decorators.idempotent_id('ef45000d-0a72-4781-866d-4cb7bf2582ae')
+ def test_get_update_show_history_delete_deleted_alarm(self):
+ # get, update and delete the deleted alarm
+ alarm_name = data_utils.rand_name('telemetry_alarm')
+ rule = {'meter_name': 'cpu',
+ 'comparison_operator': 'eq',
+ 'threshold': 100.0,
+ 'period': 90}
+ body = self.alarming_client.create_alarm(
+ name=alarm_name,
+ type='threshold',
+ threshold_rule=rule)
+ alarm_id = body['alarm_id']
+ self.alarming_client.delete_alarm(alarm_id)
+ # get the deleted alarm
+ self.assertRaises(lib_exc.NotFound, self.alarming_client.show_alarm,
+ alarm_id)
+
+ # update the deleted alarm
+ updated_alarm_name = data_utils.rand_name('telemetry_alarm_updated')
+ updated_rule = {'meter_name': 'cpu_new',
+ 'comparison_operator': 'eq',
+ 'threshold': 70,
+ 'period': 50}
+ self.assertRaises(lib_exc.NotFound, self.alarming_client.update_alarm,
+ alarm_id, threshold_rule=updated_rule,
+ name=updated_alarm_name,
+ type='threshold')
+ # delete the deleted alarm
+ self.assertRaises(lib_exc.NotFound, self.alarming_client.delete_alarm,
+ alarm_id)