Merge "Change tests to adapt alarm spliting"
diff --git a/tempest/api/telemetry/base.py b/tempest/api/telemetry/base.py
index 81f00ec..bbd01f0 100644
--- a/tempest/api/telemetry/base.py
+++ b/tempest/api/telemetry/base.py
@@ -61,18 +61,9 @@
         cls.glance_v2_notifications = ['image.download', 'image.serve']
 
         cls.server_ids = []
-        cls.alarm_ids = []
         cls.image_ids = []
 
     @classmethod
-    def create_alarm(cls, **kwargs):
-        body = cls.telemetry_client.create_alarm(
-            name=data_utils.rand_name('telemetry_alarm'),
-            type='threshold', **kwargs)
-        cls.alarm_ids.append(body['alarm_id'])
-        return body
-
-    @classmethod
     def create_server(cls):
         tenant_network = cls.get_tenant_network()
         body, server = compute.create_test_server(
@@ -106,7 +97,6 @@
 
     @classmethod
     def resource_cleanup(cls):
-        cls.cleanup_resources(cls.telemetry_client.delete_alarm, cls.alarm_ids)
         cls.cleanup_resources(cls.servers_client.delete_server, cls.server_ids)
         cls.cleanup_resources(cls.image_client.delete_image, cls.image_ids)
         super(BaseTelemetryTest, cls).resource_cleanup()
@@ -153,3 +143,46 @@
         raise exceptions.TimeoutException(
             'Event with query:%s has not been added to the '
             'database within %d seconds' % (query, CONF.compute.build_timeout))
+
+
+class BaseAlarmingTest(tempest.test.BaseTestCase):
+    """Base test case class for all Alarming API tests."""
+
+    credentials = ['primary']
+
+    @classmethod
+    def skip_checks(cls):
+        super(BaseAlarmingTest, cls).skip_checks()
+        if not CONF.service_available.aodh:
+            raise cls.skipException("Aodh support is required")
+
+    @classmethod
+    def setup_clients(cls):
+        super(BaseAlarmingTest, cls).setup_clients()
+        cls.alarming_client = cls.os.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/tempest/api/telemetry/test_telemetry_alarming_api.py b/tempest/api/telemetry/test_alarming_api.py
similarity index 80%
rename from tempest/api/telemetry/test_telemetry_alarming_api.py
rename to tempest/api/telemetry/test_alarming_api.py
index 6c84b98..daa0939 100644
--- a/tempest/api/telemetry/test_telemetry_alarming_api.py
+++ b/tempest/api/telemetry/test_alarming_api.py
@@ -17,7 +17,7 @@
 from tempest import test
 
 
-class TelemetryAlarmingAPITestJSON(base.BaseTelemetryTest):
+class TelemetryAlarmingAPITestJSON(base.BaseAlarmingTest):
 
     @classmethod
     def resource_setup(cls):
@@ -32,7 +32,7 @@
     @test.idempotent_id('1c918e06-210b-41eb-bd45-14676dd77cd6')
     def test_alarm_list(self):
         # List alarms
-        alarm_list = self.telemetry_client.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]
@@ -46,7 +46,7 @@
     def test_create_update_get_delete_alarm(self):
         # Create an alarm
         alarm_name = data_utils.rand_name('telemetry_alarm')
-        body = self.telemetry_client.create_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']
@@ -57,7 +57,7 @@
                     'threshold': 70.0,
                     'period': 60}
         alarm_name_updated = data_utils.rand_name('telemetry-alarm-update')
-        body = self.telemetry_client.update_alarm(
+        body = self.alarming_client.update_alarm(
             alarm_id,
             threshold_rule=new_rule,
             name=alarm_name_updated,
@@ -65,19 +65,19 @@
         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.telemetry_client.show_alarm(alarm_id)
+        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.telemetry_client.show_alarm_history(alarm_id)
+        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.telemetry_client.delete_alarm(alarm_id)
+        self.alarming_client.delete_alarm(alarm_id)
         self.assertRaises(lib_exc.NotFound,
-                          self.telemetry_client.show_alarm, alarm_id)
+                          self.alarming_client.show_alarm, alarm_id)
 
     @test.idempotent_id('aca49486-70bb-4016-87e0-f6131374f741')
     def test_set_get_alarm_state(self):
@@ -86,11 +86,11 @@
         # Set alarm state and verify
         new_state =\
             [elem for elem in alarm_states if elem != alarm['state']][0]
-        state = self.telemetry_client.alarm_set_state(alarm['alarm_id'],
-                                                      new_state)
+        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.telemetry_client.show_alarm_state(alarm['alarm_id'])
+        state = self.alarming_client.show_alarm_state(alarm['alarm_id'])
         self.assertEqual(new_state, state.data)
 
     @test.idempotent_id('08d7e45a-1344-4e5c-ba6f-f6cbb77f55b9')
@@ -99,13 +99,13 @@
                 "operator": "or"}
         # Verifies alarm create
         alarm_name = data_utils.rand_name('combination_alarm')
-        body = self.telemetry_client.create_alarm(name=alarm_name,
-                                                  combination_rule=rule,
-                                                  type='combination')
+        body = self.alarming_client.create_alarm(name=alarm_name,
+                                                 combination_rule=rule,
+                                                 type='combination')
         self.assertEqual(alarm_name, body['name'])
         alarm_id = body['alarm_id']
         self.assertDictContainsSubset(rule, body['combination_rule'])
         # Verify alarm delete
-        self.telemetry_client.delete_alarm(alarm_id)
+        self.alarming_client.delete_alarm(alarm_id)
         self.assertRaises(lib_exc.NotFound,
-                          self.telemetry_client.show_alarm, alarm_id)
+                          self.alarming_client.show_alarm, alarm_id)
diff --git a/tempest/api/telemetry/test_alarming_api_negative.py b/tempest/api/telemetry/test_alarming_api_negative.py
index 06753b0..e945556 100644
--- a/tempest/api/telemetry/test_alarming_api_negative.py
+++ b/tempest/api/telemetry/test_alarming_api_negative.py
@@ -20,7 +20,7 @@
 import uuid
 
 
-class TelemetryAlarmingNegativeTest(base.BaseTelemetryTest):
+class TelemetryAlarmingNegativeTest(base.BaseAlarmingTest):
     """Negative tests for show_alarm, update_alarm, show_alarm_history tests
 
         ** show non-existent alarm
@@ -34,7 +34,7 @@
     def test_get_non_existent_alarm(self):
         # get the non-existent alarm
         non_existent_id = str(uuid.uuid4())
-        self.assertRaises(lib_exc.NotFound, self.telemetry_client.show_alarm,
+        self.assertRaises(lib_exc.NotFound, self.alarming_client.show_alarm,
                           non_existent_id)
 
     @test.attr(type=['negative'])
@@ -46,14 +46,14 @@
                 'comparison_operator': 'eq',
                 'threshold': 100.0,
                 'period': 90}
-        body = self.telemetry_client.create_alarm(
+        body = self.alarming_client.create_alarm(
             name=alarm_name,
             type='threshold',
             threshold_rule=rule)
         alarm_id = body['alarm_id']
-        self.telemetry_client.delete_alarm(alarm_id)
+        self.alarming_client.delete_alarm(alarm_id)
         # get the deleted alarm
-        self.assertRaises(lib_exc.NotFound, self.telemetry_client.show_alarm,
+        self.assertRaises(lib_exc.NotFound, self.alarming_client.show_alarm,
                           alarm_id)
 
         # update the deleted alarm
@@ -62,10 +62,10 @@
                         'comparison_operator': 'eq',
                         'threshold': 70,
                         'period': 50}
-        self.assertRaises(lib_exc.NotFound, self.telemetry_client.update_alarm,
+        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.telemetry_client.delete_alarm,
+        self.assertRaises(lib_exc.NotFound, self.alarming_client.delete_alarm,
                           alarm_id)
diff --git a/tempest/clients.py b/tempest/clients.py
index 48366a5..314ee92 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -115,6 +115,7 @@
 from tempest.services.object_storage.object_client import ObjectClient
 from tempest.services.orchestration.json.orchestration_client import \
     OrchestrationClient
+from tempest.services.telemetry.json.alarming_client import AlarmingClient
 from tempest.services.telemetry.json.telemetry_client import \
     TelemetryClient
 from tempest.services.volume.json.admin.volume_hosts_client import \
@@ -240,6 +241,13 @@
                 CONF.identity.region,
                 endpoint_type=CONF.telemetry.endpoint_type,
                 **self.default_params_with_timeout_values)
+        if CONF.service_available.aodh:
+            self.alarming_client = AlarmingClient(
+                self.auth_provider,
+                CONF.alarming.catalog_type,
+                CONF.identity.region,
+                endpoint_type=CONF.alarming.endpoint_type,
+                **self.default_params_with_timeout_values)
         if CONF.service_available.glance:
             self.image_client = ImageClient(
                 self.auth_provider,
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index cbaf756..3df19fc 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -133,6 +133,7 @@
 from tempest.services.network.json import subnets_client
 from tempest.services.object_storage import container_client
 from tempest.services.object_storage import object_client
+from tempest.services.telemetry.json import alarming_client
 from tempest.services.telemetry.json import telemetry_client
 from tempest.services.volume.json import volumes_client
 
@@ -226,6 +227,12 @@
             CONF.identity.region,
             endpoint_type=CONF.telemetry.endpoint_type,
             **default_params_with_timeout_values)
+        self.alarming = alarming_client.AlarmingClient(
+            _auth,
+            CONF.alarm.catalog_type,
+            CONF.identity.region,
+            endpoint_type=CONF.alarm.endpoint_type,
+            **default_params_with_timeout_values)
         self.volumes = volumes_client.VolumesClient(
             _auth,
             CONF.volume.catalog_type,
diff --git a/tempest/config.py b/tempest/config.py
index 695c15a..c9fe38d 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -917,6 +917,20 @@
                      "notification tests")
 ]
 
+alarming_group = cfg.OptGroup(name='alarming',
+                              title='Alarming Service Options')
+
+AlarmingGroup = [
+    cfg.StrOpt('catalog_type',
+               default='alarming',
+               help="Catalog type of the Alarming service."),
+    cfg.StrOpt('endpoint_type',
+               default='publicURL',
+               choices=['public', 'admin', 'internal',
+                        'publicURL', 'adminURL', 'internalURL'],
+               help="The endpoint type to use for the alarming service."),
+]
+
 
 telemetry_feature_group = cfg.OptGroup(name='telemetry-feature-enabled',
                                        title='Enabled Ceilometer Features')
@@ -1127,6 +1141,9 @@
     cfg.BoolOpt('ceilometer',
                 default=True,
                 help="Whether or not Ceilometer is expected to be available"),
+    cfg.BoolOpt('aodh',
+                default=False,
+                help="Whether or not Aodh is expected to be available"),
     cfg.BoolOpt('horizon',
                 default=True,
                 help="Whether or not Horizon is expected to be available"),
@@ -1273,6 +1290,7 @@
     (orchestration_group, OrchestrationGroup),
     (telemetry_group, TelemetryGroup),
     (telemetry_feature_group, TelemetryFeaturesGroup),
+    (alarming_group, AlarmingGroup),
     (dashboard_group, DashboardGroup),
     (data_processing_group, DataProcessingGroup),
     (data_processing_feature_group, DataProcessingFeaturesGroup),
diff --git a/tempest/hacking/ignored_list_T110.txt b/tempest/hacking/ignored_list_T110.txt
index ee27800..f522865 100644
--- a/tempest/hacking/ignored_list_T110.txt
+++ b/tempest/hacking/ignored_list_T110.txt
@@ -6,6 +6,7 @@
 ./tempest/services/identity/v3/json/region_client.py
 ./tempest/services/messaging/json/messaging_client.py
 ./tempest/services/object_storage/object_client.py
+./tempest/services/telemetry/json/alarming_client.py
 ./tempest/services/telemetry/json/telemetry_client.py
 ./tempest/services/volume/json/qos_client.py
 ./tempest/services/volume/json/backups_client.py
diff --git a/tempest/services/telemetry/json/alarming_client.py b/tempest/services/telemetry/json/alarming_client.py
new file mode 100644
index 0000000..ce14211
--- /dev/null
+++ b/tempest/services/telemetry/json/alarming_client.py
@@ -0,0 +1,98 @@
+# Copyright 2014 OpenStack Foundation
+# 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_serialization import jsonutils as json
+from six.moves.urllib import parse as urllib
+
+from tempest.common import service_client
+
+
+class AlarmingClient(service_client.ServiceClient):
+
+    version = '2'
+    uri_prefix = "v2"
+
+    def deserialize(self, body):
+        return json.loads(body.replace("\n", ""))
+
+    def serialize(self, body):
+        return json.dumps(body)
+
+    def list_alarms(self, query=None):
+        uri = '%s/alarms' % self.uri_prefix
+        uri_dict = {}
+        if query:
+            uri_dict = {'q.field': query[0],
+                        'q.op': query[1],
+                        'q.value': query[2]}
+        if uri_dict:
+            uri += "?%s" % urllib.urlencode(uri_dict)
+        resp, body = self.get(uri)
+        self.expected_success(200, resp.status)
+        body = self.deserialize(body)
+        return service_client.ResponseBodyList(resp, body)
+
+    def show_alarm(self, alarm_id):
+        uri = '%s/alarms/%s' % (self.uri_prefix, alarm_id)
+        resp, body = self.get(uri)
+        self.expected_success(200, resp.status)
+        body = self.deserialize(body)
+        return service_client.ResponseBody(resp, body)
+
+    def show_alarm_history(self, alarm_id):
+        uri = "%s/alarms/%s/history" % (self.uri_prefix, alarm_id)
+        resp, body = self.get(uri)
+        self.expected_success(200, resp.status)
+        body = self.deserialize(body)
+        return service_client.ResponseBodyList(resp, body)
+
+    def delete_alarm(self, alarm_id):
+        uri = "%s/alarms/%s" % (self.uri_prefix, alarm_id)
+        resp, body = self.delete(uri)
+        self.expected_success(204, resp.status)
+        if body:
+            body = self.deserialize(body)
+        return service_client.ResponseBody(resp, body)
+
+    def create_alarm(self, **kwargs):
+        uri = "%s/alarms" % self.uri_prefix
+        body = self.serialize(kwargs)
+        resp, body = self.post(uri, body)
+        self.expected_success(201, resp.status)
+        body = self.deserialize(body)
+        return service_client.ResponseBody(resp, body)
+
+    def update_alarm(self, alarm_id, **kwargs):
+        uri = "%s/alarms/%s" % (self.uri_prefix, alarm_id)
+        body = self.serialize(kwargs)
+        resp, body = self.put(uri, body)
+        self.expected_success(200, resp.status)
+        body = self.deserialize(body)
+        return service_client.ResponseBody(resp, body)
+
+    def show_alarm_state(self, alarm_id):
+        uri = "%s/alarms/%s/state" % (self.uri_prefix, alarm_id)
+        resp, body = self.get(uri)
+        self.expected_success(200, resp.status)
+        body = self.deserialize(body)
+        return service_client.ResponseBodyData(resp, body)
+
+    def alarm_set_state(self, alarm_id, state):
+        uri = "%s/alarms/%s/state" % (self.uri_prefix, alarm_id)
+        body = self.serialize(state)
+        resp, body = self.put(uri, body)
+        self.expected_success(200, resp.status)
+        body = self.deserialize(body)
+        return service_client.ResponseBodyData(resp, body)
diff --git a/tempest/services/telemetry/json/telemetry_client.py b/tempest/services/telemetry/json/telemetry_client.py
index fc8951e..05530b1 100644
--- a/tempest/services/telemetry/json/telemetry_client.py
+++ b/tempest/services/telemetry/json/telemetry_client.py
@@ -72,10 +72,6 @@
         uri = '%s/meters' % self.uri_prefix
         return self._helper_list(uri, query)
 
-    def list_alarms(self, query=None):
-        uri = '%s/alarms' % self.uri_prefix
-        return self._helper_list(uri, query)
-
     def list_statistics(self, meter, period=None, query=None):
         uri = "%s/meters/%s/statistics" % (self.uri_prefix, meter)
         return self._helper_list(uri, query, period)
@@ -94,56 +90,3 @@
         self.expected_success(200, resp.status)
         body = self.deserialize(body)
         return service_client.ResponseBody(resp, body)
-
-    def show_alarm(self, alarm_id):
-        uri = '%s/alarms/%s' % (self.uri_prefix, alarm_id)
-        resp, body = self.get(uri)
-        self.expected_success(200, resp.status)
-        body = self.deserialize(body)
-        return service_client.ResponseBody(resp, body)
-
-    def delete_alarm(self, alarm_id):
-        uri = "%s/alarms/%s" % (self.uri_prefix, alarm_id)
-        resp, body = self.delete(uri)
-        self.expected_success(204, resp.status)
-        if body:
-            body = self.deserialize(body)
-        return service_client.ResponseBody(resp, body)
-
-    def create_alarm(self, **kwargs):
-        uri = "%s/alarms" % self.uri_prefix
-        body = self.serialize(kwargs)
-        resp, body = self.post(uri, body)
-        self.expected_success(201, resp.status)
-        body = self.deserialize(body)
-        return service_client.ResponseBody(resp, body)
-
-    def update_alarm(self, alarm_id, **kwargs):
-        uri = "%s/alarms/%s" % (self.uri_prefix, alarm_id)
-        body = self.serialize(kwargs)
-        resp, body = self.put(uri, body)
-        self.expected_success(200, resp.status)
-        body = self.deserialize(body)
-        return service_client.ResponseBody(resp, body)
-
-    def show_alarm_state(self, alarm_id):
-        uri = "%s/alarms/%s/state" % (self.uri_prefix, alarm_id)
-        resp, body = self.get(uri)
-        self.expected_success(200, resp.status)
-        body = self.deserialize(body)
-        return service_client.ResponseBodyData(resp, body)
-
-    def alarm_set_state(self, alarm_id, state):
-        uri = "%s/alarms/%s/state" % (self.uri_prefix, alarm_id)
-        body = self.serialize(state)
-        resp, body = self.put(uri, body)
-        self.expected_success(200, resp.status)
-        body = self.deserialize(body)
-        return service_client.ResponseBodyData(resp, body)
-
-    def show_alarm_history(self, alarm_id):
-        uri = "%s/alarms/%s/history" % (self.uri_prefix, alarm_id)
-        resp, body = self.get(uri)
-        self.expected_success(200, resp.status)
-        body = self.deserialize(body)
-        return service_client.ResponseBodyList(resp, body)
diff --git a/tempest/tests/common/test_service_clients.py b/tempest/tests/common/test_service_clients.py
index 4225da8..b26ba7d 100644
--- a/tempest/tests/common/test_service_clients.py
+++ b/tempest/tests/common/test_service_clients.py
@@ -46,6 +46,7 @@
 from tempest.services.object_storage import container_client
 from tempest.services.object_storage import object_client
 from tempest.services.orchestration.json import orchestration_client
+from tempest.services.telemetry.json import alarming_client
 from tempest.services.telemetry.json import telemetry_client
 from tempest.services.volume.json.admin import volume_hosts_client
 from tempest.services.volume.json.admin import volume_quotas_client
@@ -105,6 +106,7 @@
             object_client.ObjectClient,
             orchestration_client.OrchestrationClient,
             telemetry_client.TelemetryClient,
+            alarming_client.AlarmingClient,
             qos_client.QosSpecsClient,
             volume_hosts_client.VolumeHostsClient,
             volume_quotas_client.VolumeQuotasClient,