Merge "Rename service client classes which include "Ip""
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 724bff4..07ee026 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -123,10 +123,10 @@
 # Roles to assign to all users created by tempest (list value)
 #tempest_roles =
 
-# Only applicable when identity.auth_version is v3.Domain within which
-# isolated credentials are provisioned.The default "None" means that
-# the domain from theadmin user is used instead. (string value)
-#tenant_isolation_domain_name = <None>
+# Default domain used when getting v3 credentials. This is the name
+# keystone uses for v2 compatibility. (string value)
+# Deprecated group/name - [auth]/tenant_isolation_domain_name
+#default_credentials_domain_name = Default
 
 # If allow_tenant_isolation is set to True and Neutron is enabled
 # Tempest will try to create a useable network, subnet, and router
@@ -1098,6 +1098,16 @@
 #too_slow_to_test = true
 
 
+[telemetry-feature-enabled]
+
+#
+# From tempest.config
+#
+
+# Runs Ceilometer event-related tests (boolean value)
+#events = false
+
+
 [validation]
 
 #
diff --git a/tempest/api/compute/admin/test_quotas_negative.py b/tempest/api/compute/admin/test_quotas_negative.py
index 798bd30..33313be 100644
--- a/tempest/api/compute/admin/test_quotas_negative.py
+++ b/tempest/api/compute/admin/test_quotas_negative.py
@@ -32,6 +32,7 @@
         cls.client = cls.os.quotas_client
         cls.adm_client = cls.os_adm.quotas_client
         cls.sg_client = cls.security_groups_client
+        cls.sgr_client = cls.security_group_rules_client
 
     @classmethod
     def resource_setup(cls):
@@ -167,5 +168,5 @@
         # A 403 Forbidden or 413 Overlimit (old behaviour) exception
         # will be raised when out of quota
         self.assertRaises((lib_exc.OverLimit, lib_exc.Forbidden),
-                          self.sg_client.create_security_group_rule,
+                          self.sgr_client.create_security_group_rule,
                           secgroup_id, ip_protocol, 1025, 1025)
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 759bb8c..33442b2 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -64,6 +64,7 @@
         cls.floating_ip_pools_client = cls.os.floating_ip_pools_client
         cls.floating_ips_client = cls.os.floating_ips_client
         cls.keypairs_client = cls.os.keypairs_client
+        cls.security_group_rules_client = cls.os.security_group_rules_client
         cls.security_groups_client = cls.os.security_groups_client
         cls.quotas_client = cls.os.quotas_client
         # NOTE(mriedem): os-quota-class-sets is v2 API only
diff --git a/tempest/api/compute/security_groups/test_security_group_rules.py b/tempest/api/compute/security_groups/test_security_group_rules.py
index ff3f25b..4596e1f 100644
--- a/tempest/api/compute/security_groups/test_security_group_rules.py
+++ b/tempest/api/compute/security_groups/test_security_group_rules.py
@@ -25,7 +25,7 @@
     @classmethod
     def setup_clients(cls):
         super(SecurityGroupRulesTestJSON, cls).setup_clients()
-        cls.client = cls.security_groups_client
+        cls.client = cls.security_group_rules_client
 
     @classmethod
     def resource_setup(cls):
@@ -183,7 +183,7 @@
                                                group_id=sg2_id)
 
         # Delete group2
-        self.client.delete_security_group(sg2_id)
+        self.security_groups_client.delete_security_group(sg2_id)
         # Get rules of the Group1
         rules = \
             self.client.list_security_group_rules(sg1_id)
diff --git a/tempest/api/compute/security_groups/test_security_group_rules_negative.py b/tempest/api/compute/security_groups/test_security_group_rules_negative.py
index 15e79ac..e2a1034 100644
--- a/tempest/api/compute/security_groups/test_security_group_rules_negative.py
+++ b/tempest/api/compute/security_groups/test_security_group_rules_negative.py
@@ -36,6 +36,7 @@
     def setup_clients(cls):
         super(SecurityGroupRulesNegativeTestJSON, cls).setup_clients()
         cls.client = cls.security_groups_client
+        cls.rules_client = cls.security_group_rules_client
 
     @test.attr(type=['negative'])
     @test.idempotent_id('1d507e98-7951-469b-82c3-23f1e6b8c254')
@@ -49,7 +50,7 @@
         from_port = 22
         to_port = 22
         self.assertRaises(lib_exc.NotFound,
-                          self.client.create_security_group_rule,
+                          self.rules_client.create_security_group_rule,
                           parent_group_id, ip_protocol, from_port, to_port)
 
     @test.attr(type=['negative'])
@@ -64,7 +65,7 @@
         from_port = 22
         to_port = 22
         self.assertRaises(lib_exc.BadRequest,
-                          self.client.create_security_group_rule,
+                          self.rules_client.create_security_group_rule,
                           parent_group_id, ip_protocol, from_port, to_port)
 
     @test.attr(type=['negative'])
@@ -81,14 +82,15 @@
         to_port = 22
 
         rule = \
-            self.client.create_security_group_rule(parent_group_id,
-                                                   ip_protocol,
-                                                   from_port,
-                                                   to_port)
-        self.addCleanup(self.client.delete_security_group_rule, rule['id'])
+            self.rules_client.create_security_group_rule(parent_group_id,
+                                                         ip_protocol,
+                                                         from_port,
+                                                         to_port)
+        self.addCleanup(self.rules_client.delete_security_group_rule,
+                        rule['id'])
         # Add the same rule to the group should fail
         self.assertRaises(lib_exc.BadRequest,
-                          self.client.create_security_group_rule,
+                          self.rules_client.create_security_group_rule,
                           parent_group_id, ip_protocol, from_port, to_port)
 
     @test.attr(type=['negative'])
@@ -106,7 +108,7 @@
         to_port = 22
 
         self.assertRaises(lib_exc.BadRequest,
-                          self.client.create_security_group_rule,
+                          self.rules_client.create_security_group_rule,
                           parent_group_id, ip_protocol, from_port, to_port)
 
     @test.attr(type=['negative'])
@@ -123,7 +125,7 @@
         from_port = data_utils.rand_int_id(start=65536)
         to_port = 22
         self.assertRaises(lib_exc.BadRequest,
-                          self.client.create_security_group_rule,
+                          self.rules_client.create_security_group_rule,
                           parent_group_id, ip_protocol, from_port, to_port)
 
     @test.attr(type=['negative'])
@@ -140,7 +142,7 @@
         from_port = 22
         to_port = data_utils.rand_int_id(start=65536)
         self.assertRaises(lib_exc.BadRequest,
-                          self.client.create_security_group_rule,
+                          self.rules_client.create_security_group_rule,
                           parent_group_id, ip_protocol, from_port, to_port)
 
     @test.attr(type=['negative'])
@@ -157,7 +159,7 @@
         from_port = 22
         to_port = 21
         self.assertRaises(lib_exc.BadRequest,
-                          self.client.create_security_group_rule,
+                          self.rules_client.create_security_group_rule,
                           secgroup_id, ip_protocol, from_port, to_port)
 
     @test.attr(type=['negative'])
@@ -168,5 +170,5 @@
         # with non existent id
         non_existent_rule_id = not_existing_id()
         self.assertRaises(lib_exc.NotFound,
-                          self.client.delete_security_group_rule,
+                          self.rules_client.delete_security_group_rule,
                           non_existent_rule_id)
diff --git a/tempest/api/compute/test_authorization.py b/tempest/api/compute/test_authorization.py
index 58c2206..8ee8ad4 100644
--- a/tempest/api/compute/test_authorization.py
+++ b/tempest/api/compute/test_authorization.py
@@ -52,11 +52,13 @@
         cls.glance_client = cls.os.image_client
         cls.keypairs_client = cls.os.keypairs_client
         cls.security_client = cls.os.security_groups_client
+        cls.rule_client = cls.os.security_group_rules_client
 
         cls.alt_client = cls.alt_manager.servers_client
         cls.alt_images_client = cls.alt_manager.images_client
         cls.alt_keypairs_client = cls.alt_manager.keypairs_client
         cls.alt_security_client = cls.alt_manager.security_groups_client
+        cls.alt_rule_client = cls.alt_manager.security_group_rules_client
 
     @classmethod
     def resource_setup(cls):
@@ -87,7 +89,7 @@
         ip_protocol = 'tcp'
         from_port = 22
         to_port = 22
-        cls.rule = cls.security_client.create_security_group_rule(
+        cls.rule = cls.rule_client.create_security_group_rule(
             parent_group_id, ip_protocol, from_port, to_port)
 
     @classmethod
@@ -292,21 +294,21 @@
         to_port = -1
         try:
             # Change the base URL to impersonate another user
-            self.alt_security_client.auth_provider.set_alt_auth_data(
+            self.alt_rule_client.auth_provider.set_alt_auth_data(
                 request_part='url',
-                auth_data=self.security_client.auth_provider.auth_data
+                auth_data=self.rule_client.auth_provider.auth_data
             )
             resp = {}
             resp['status'] = None
             self.assertRaises(lib_exc.BadRequest,
-                              self.alt_security_client.
+                              self.alt_rule_client.
                               create_security_group_rule,
                               parent_group_id, ip_protocol, from_port,
                               to_port)
         finally:
             # Next request the base_url is back to normal
             if resp['status'] is not None:
-                self.alt_security_client.delete_security_group_rule(resp['id'])
+                self.alt_rule_client.delete_security_group_rule(resp['id'])
                 LOG.error("Create security group rule request should not "
                           "happen if the tenant id does not match the"
                           " current user")
@@ -316,7 +318,7 @@
         # A DELETE request for another user's security group rule
         # should fail
         self.assertRaises(lib_exc.NotFound,
-                          self.alt_security_client.delete_security_group_rule,
+                          self.alt_rule_client.delete_security_group_rule,
                           self.rule['id'])
 
     @test.idempotent_id('c5f52351-53d9-4fc9-83e5-917f7f5e3d71')
diff --git a/tempest/api/telemetry/base.py b/tempest/api/telemetry/base.py
index 3be807b..0f9b7dd 100644
--- a/tempest/api/telemetry/base.py
+++ b/tempest/api/telemetry/base.py
@@ -121,3 +121,27 @@
             'Sample for metric:%s with query:%s has not been added to the '
             'database within %d seconds' % (metric, query,
                                             CONF.compute.build_timeout))
+
+
+class BaseTelemetryAdminTest(BaseTelemetryTest):
+    """Base test case class for admin Telemetry API tests."""
+
+    credentials = ['primary', 'admin']
+
+    @classmethod
+    def setup_clients(cls):
+        super(BaseTelemetryAdminTest, cls).setup_clients()
+        cls.telemetry_admin_client = cls.os_adm.telemetry_client
+
+    def await_events(self, query):
+        timeout = CONF.compute.build_timeout
+        start = timeutils.utcnow()
+        while timeutils.delta_seconds(start, timeutils.utcnow()) < timeout:
+            body = self.telemetry_admin_client.list_events(query)
+            if body:
+                return body
+            time.sleep(CONF.compute.build_interval)
+
+        raise exceptions.TimeoutException(
+            'Event with query:%s has not been added to the '
+            'database within %d seconds' % (query, CONF.compute.build_timeout))
diff --git a/tempest/api/telemetry/test_telemetry_notification_api.py b/tempest/api/telemetry/test_telemetry_notification_api.py
index 52793c8..bf1e046 100644
--- a/tempest/api/telemetry/test_telemetry_notification_api.py
+++ b/tempest/api/telemetry/test_telemetry_notification_api.py
@@ -29,8 +29,7 @@
                                     "is disabled")
 
     @test.idempotent_id('d7f8c1c8-d470-4731-8604-315d3956caad')
-    @testtools.skipIf(not CONF.service_available.nova,
-                      "Nova is not available.")
+    @test.services('compute')
     def test_check_nova_notification(self):
 
         body = self.create_server()
@@ -71,3 +70,27 @@
 
         for metric in self.glance_v2_notifications:
             self.await_samples(metric, query)
+
+
+class TelemetryNotificationAdminAPITestJSON(base.BaseTelemetryAdminTest):
+
+    @classmethod
+    def skip_checks(cls):
+        super(TelemetryNotificationAdminAPITestJSON, cls).skip_checks()
+        if CONF.telemetry.too_slow_to_test:
+            raise cls.skipException("Ceilometer feature for fast work mysql "
+                                    "is disabled")
+
+    @test.idempotent_id('29604198-8b45-4fc0-8af8-1cae4f94ebe9')
+    @test.services('compute')
+    def test_check_nova_notification_event_and_meter(self):
+
+        body = self.create_server()
+
+        if CONF.telemetry_feature_enabled.events:
+            query = ('instance_id', 'eq', body['id'])
+            self.await_events(query)
+
+        query = ('resource', 'eq', body['id'])
+        for metric in self.nova_notifications:
+            self.await_samples(metric, query)
diff --git a/tempest/clients.py b/tempest/clients.py
index 55fe72f..e32d401 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -65,6 +65,8 @@
 from tempest.services.compute.json.quotas_client import QuotasClient
 from tempest.services.compute.json.security_group_default_rules_client import \
     SecurityGroupDefaultRulesClient
+from tempest.services.compute.json.security_group_rules_client import \
+    SecurityGroupRulesClient
 from tempest.services.compute.json.security_groups_client import \
     SecurityGroupsClient
 from tempest.services.compute.json.server_groups_client import \
@@ -286,6 +288,8 @@
             self.auth_provider, **params)
         self.floating_ips_client = FloatingIPsClient(self.auth_provider,
                                                      **params)
+        self.security_group_rules_client = SecurityGroupRulesClient(
+            self.auth_provider, **params)
         self.security_groups_client = SecurityGroupsClient(
             self.auth_provider, **params)
         self.interfaces_client = InterfacesClient(self.auth_provider,
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index dcdf7c5..2e96c81 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -76,12 +76,12 @@
                   CONF.identity.alt_username]
 
     if IS_NEUTRON:
-        CONF_PRIV_NETWORK = _get_priv_net_id(CONF.compute.fixed_network_name,
-                                             CONF.identity.tenant_name)
+        CONF_PRIV_NETWORK = _get_network_id(CONF.compute.fixed_network_name,
+                                            CONF.identity.tenant_name)
         CONF_NETWORKS = [CONF_PUB_NETWORK, CONF_PRIV_NETWORK]
 
 
-def _get_priv_net_id(prv_net_name, tenant_name):
+def _get_network_id(net_name, tenant_name):
     am = clients.AdminManager()
     net_cl = am.network_client
     id_cl = am.identity_client
@@ -91,7 +91,7 @@
     t_id = tenant['id']
     n_id = None
     for net in networks['networks']:
-        if (net['tenant_id'] == t_id and net['name'] == prv_net_name):
+        if (net['tenant_id'] == t_id and net['name'] == net_name):
             n_id = net['id']
             break
     return n_id
@@ -103,6 +103,10 @@
         for key, value in kwargs.items():
             setattr(self, key, value)
 
+        self.tenant_filter = {}
+        if hasattr(self, 'tenant_id'):
+            self.tenant_filter['tenant_id'] = self.tenant_id
+
     def _filter_by_tenant_id(self, item_list):
         if (item_list is None
                 or len(item_list) == 0
@@ -387,8 +391,8 @@
 
     def list(self):
         client = self.client
-        networks = client.list_networks()
-        networks = self._filter_by_tenant_id(networks['networks'])
+        networks = client.list_networks(**self.tenant_filter)
+        networks = networks['networks']
         # filter out networks declared in tempest.conf
         if self.is_preserve:
             networks = [network for network in networks
@@ -414,9 +418,8 @@
 
     def list(self):
         client = self.client
-        flips = client.list_floatingips()
+        flips = client.list_floatingips(**self.tenant_filter)
         flips = flips['floatingips']
-        flips = self._filter_by_tenant_id(flips)
         LOG.debug("List count, %s Network Floating IPs" % len(flips))
         return flips
 
@@ -438,9 +441,8 @@
 
     def list(self):
         client = self.client
-        routers = client.list_routers()
+        routers = client.list_routers(**self.tenant_filter)
         routers = routers['routers']
-        routers = self._filter_by_tenant_id(routers)
         if self.is_preserve:
             routers = [router for router in routers
                        if router['id'] != CONF_PUB_ROUTER]
@@ -454,11 +456,12 @@
         for router in routers:
             try:
                 rid = router['id']
-                ports = client.list_router_interfaces(rid)
-                ports = ports['ports']
+                ports = [port for port
+                         in client.list_router_interfaces(rid)['ports']
+                         if port["device_owner"] == "network:router_interface"]
                 for port in ports:
-                    subid = port['fixed_ips'][0]['subnet_id']
-                    client.remove_router_interface_with_subnet_id(rid, subid)
+                    client.remove_router_interface_with_port_id(rid,
+                                                                port['id'])
                 client.delete_router(rid)
             except Exception:
                 LOG.exception("Delete Router exception.")
@@ -616,11 +619,14 @@
 
     def list(self):
         client = self.client
-        ports = client.list_ports()
-        ports = ports['ports']
-        ports = self._filter_by_tenant_id(ports)
+        ports = [port for port in
+                 client.list_ports(**self.tenant_filter)['ports']
+                 if port["device_owner"] == "" or
+                 port["device_owner"].startswith("compute:")]
+
         if self.is_preserve:
             ports = self._filter_by_conf_networks(ports)
+
         LOG.debug("List count, %s Ports" % len(ports))
         return ports
 
@@ -638,13 +644,40 @@
         self.data['ports'] = ports
 
 
+class NetworkSecGroupService(NetworkService):
+    def list(self):
+        client = self.client
+        filter = self.tenant_filter
+        # cannot delete default sec group so never show it.
+        secgroups = [secgroup for secgroup in
+                     client.list_security_groups(**filter)['security_groups']
+                     if secgroup['name'] != 'default']
+
+        if self.is_preserve:
+            secgroups = self._filter_by_conf_networks(secgroups)
+        LOG.debug("List count, %s securtiy_groups" % len(secgroups))
+        return secgroups
+
+    def delete(self):
+        client = self.client
+        secgroups = self.list()
+        for secgroup in secgroups:
+            try:
+                client.delete_secgroup(secgroup['id'])
+            except Exception:
+                LOG.exception("Delete security_group exception.")
+
+    def dry_run(self):
+        secgroups = self.list()
+        self.data['secgroups'] = secgroups
+
+
 class NetworkSubnetService(NetworkService):
 
     def list(self):
         client = self.client
-        subnets = client.list_subnets()
+        subnets = client.list_subnets(**self.tenant_filter)
         subnets = subnets['subnets']
-        subnets = self._filter_by_tenant_id(subnets)
         if self.is_preserve:
             subnets = self._filter_by_conf_networks(subnets)
         LOG.debug("List count, %s Subnets" % len(subnets))
@@ -761,8 +794,8 @@
         self.data['images'] = images
 
     def save_state(self):
-        images = self.list()
         self.data['images'] = {}
+        images = self.list()
         for image in images:
             self.data['images'][image['id']] = image['name']
 
@@ -928,7 +961,6 @@
 
 def get_tenant_cleanup_services():
     tenant_services = []
-
     if IS_CEILOMETER:
         tenant_services.append(TelemetryAlarmService)
     if IS_NOVA:
@@ -942,14 +974,15 @@
     if IS_HEAT:
         tenant_services.append(StackService)
     if IS_NEUTRON:
+        tenant_services.append(NetworkFloatingIpService)
         if test.is_extension_enabled('metering', 'network'):
             tenant_services.append(NetworkMeteringLabelRuleService)
             tenant_services.append(NetworkMeteringLabelService)
         tenant_services.append(NetworkRouterService)
-        tenant_services.append(NetworkFloatingIpService)
         tenant_services.append(NetworkPortService)
         tenant_services.append(NetworkSubnetService)
         tenant_services.append(NetworkService)
+        tenant_services.append(NetworkSecGroupService)
     if IS_CINDER:
         tenant_services.append(SnapshotService)
         tenant_services.append(VolumeService)
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index f091cd3..f35548a 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -122,6 +122,7 @@
 from tempest import config
 from tempest.services.compute.json import flavors_client
 from tempest.services.compute.json import floating_ips_client
+from tempest.services.compute.json import security_group_rules_client
 from tempest.services.compute.json import security_groups_client
 from tempest.services.compute.json import servers_client
 from tempest.services.identity.v2.json import identity_client
@@ -202,6 +203,8 @@
             _auth, **compute_params)
         self.secgroups = security_groups_client.SecurityGroupsClient(
             _auth, **compute_params)
+        self.secrules = security_group_rules_client.SecurityGroupRulesClient(
+            _auth, **compute_params)
         self.objects = object_client.ObjectClient(_auth,
                                                   **object_storage_params)
         self.containers = container_client.ContainerClient(
@@ -917,7 +920,7 @@
         # for each security group, create the rules
         for rule in secgroup['rules']:
             ip_proto, from_port, to_port, cidr = rule.split()
-            client.secgroups.create_security_group_rule(
+            client.secrules.create_security_group_rule(
                 secgroup_id, ip_proto, from_port, to_port, cidr=cidr)
 
 
diff --git a/tempest/common/accounts.py b/tempest/common/accounts.py
index 78e0e72..27b44f6 100644
--- a/tempest/common/accounts.py
+++ b/tempest/common/accounts.py
@@ -216,7 +216,7 @@
             if ('user_domain_name' in init_attributes and 'user_domain_name'
                     not in hash_attributes):
                 # Allow for the case of domain_name populated from config
-                domain_name = CONF.identity.admin_domain_name
+                domain_name = CONF.auth.default_credentials_domain_name
                 hash_attributes['user_domain_name'] = domain_name
             if all([getattr(creds, k) == hash_attributes[k] for
                    k in init_attributes]):
diff --git a/tempest/common/cred_provider.py b/tempest/common/cred_provider.py
index 2b7e0db..783a5fc 100644
--- a/tempest/common/cred_provider.py
+++ b/tempest/common/cred_provider.py
@@ -84,9 +84,9 @@
         domain_fields = set(x for x in auth.KeystoneV3Credentials.ATTRIBUTES
                             if 'domain' in x)
         if not domain_fields.intersection(kwargs.keys()):
-            # TODO(andreaf) It might be better here to use a dedicated config
-            # option such as CONF.auth.tenant_isolation_domain_name
-            params['user_domain_name'] = CONF.identity.admin_domain_name
+            domain_name = CONF.auth.default_credentials_domain_name
+            params['user_domain_name'] = domain_name
+
         auth_url = CONF.identity.uri_v3
     else:
         auth_url = CONF.identity.uri
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index ff4eda9..7888811 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -163,8 +163,8 @@
         self.creds_domain_name = None
         if self.identity_version == 'v3':
             self.creds_domain_name = (
-                CONF.auth.tenant_isolation_domain_name or
-                self.default_admin_creds.project_domain_name)
+                self.default_admin_creds.project_domain_name or
+                CONF.auth.default_credentials_domain_name)
         self.creds_client = get_creds_client(
             self.identity_admin_client, self.creds_domain_name)
 
diff --git a/tempest/config.py b/tempest/config.py
index 5ea4d10..bdfdcdc 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -67,12 +67,13 @@
     cfg.ListOpt('tempest_roles',
                 help="Roles to assign to all users created by tempest",
                 default=[]),
-    cfg.StrOpt('tenant_isolation_domain_name',
-               default=None,
-               help="Only applicable when identity.auth_version is v3."
-                    "Domain within which isolated credentials are provisioned."
-                    "The default \"None\" means that the domain from the"
-                    "admin user is used instead."),
+    cfg.StrOpt('default_credentials_domain_name',
+               default='Default',
+               help="Default domain used when getting v3 credentials. "
+                    "This is the name keystone uses for v2 compatibility.",
+               deprecated_opts=[cfg.DeprecatedOpt(
+                                'tenant_isolation_domain_name',
+                                group='auth')]),
     cfg.BoolOpt('create_isolated_networks',
                 default=True,
                 help="If allow_tenant_isolation is set to True and Neutron is "
@@ -838,6 +839,16 @@
 ]
 
 
+telemetry_feature_group = cfg.OptGroup(name='telemetry-feature-enabled',
+                                       title='Enabled Ceilometer Features')
+
+TelemetryFeaturesGroup = [
+    cfg.BoolOpt('events',
+                default=False,
+                help="Runs Ceilometer event-related tests"),
+]
+
+
 dashboard_group = cfg.OptGroup(name="dashboard",
                                title="Dashboard options")
 
@@ -1178,6 +1189,7 @@
     (database_group, DatabaseGroup),
     (orchestration_group, OrchestrationGroup),
     (telemetry_group, TelemetryGroup),
+    (telemetry_feature_group, TelemetryFeaturesGroup),
     (dashboard_group, DashboardGroup),
     (data_processing_group, DataProcessingGroup),
     (data_processing_feature_group, DataProcessingFeaturesGroup),
@@ -1245,6 +1257,7 @@
         self.orchestration = _CONF.orchestration
         self.messaging = _CONF.messaging
         self.telemetry = _CONF.telemetry
+        self.telemetry_feature_enabled = _CONF['telemetry-feature-enabled']
         self.dashboard = _CONF.dashboard
         self.data_processing = _CONF.data_processing
         self.data_processing_feature_enabled = _CONF[
@@ -1257,9 +1270,11 @@
         self.baremetal = _CONF.baremetal
         self.input_scenario = _CONF['input-scenario']
         self.negative = _CONF.negative
-        _CONF.set_default('domain_name', self.identity.admin_domain_name,
+        _CONF.set_default('domain_name',
+                          self.auth.default_credentials_domain_name,
                           group='identity')
-        _CONF.set_default('alt_domain_name', self.identity.admin_domain_name,
+        _CONF.set_default('alt_domain_name',
+                          self.auth.default_credentials_domain_name,
                           group='identity')
 
     def __init__(self, parse_conf=True, config_path=None):
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 03e572f..e77d07c 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -54,6 +54,8 @@
         cls.keypairs_client = cls.manager.keypairs_client
         # Nova security groups client
         cls.security_groups_client = cls.manager.security_groups_client
+        cls.security_group_rules_client = (
+            cls.manager.security_group_rules_client)
         cls.servers_client = cls.manager.servers_client
         cls.volumes_client = cls.manager.volumes_client
         cls.snapshots_client = cls.manager.snapshots_client
@@ -217,6 +219,7 @@
 
     def _create_loginable_secgroup_rule(self, secgroup_id=None):
         _client = self.security_groups_client
+        _client_rules = self.security_group_rules_client
         if secgroup_id is None:
             sgs = _client.list_security_groups()
             for sg in sgs:
@@ -245,10 +248,10 @@
         ]
         rules = list()
         for ruleset in rulesets:
-            sg_rule = _client.create_security_group_rule(secgroup_id,
-                                                         **ruleset)
+            sg_rule = _client_rules.create_security_group_rule(secgroup_id,
+                                                               **ruleset)
             self.addCleanup(self.delete_wrapper,
-                            _client.delete_security_group_rule,
+                            _client_rules.delete_security_group_rule,
                             sg_rule['id'])
             rules.append(sg_rule)
         return rules
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 45b7b74..3809831 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -106,8 +106,7 @@
                 floating_ip['ip'], server['id'])
             ip = floating_ip['ip']
         else:
-            network_name_for_ssh = CONF.compute.network_for_ssh
-            ip = server.networks[network_name_for_ssh][0]
+            ip = server
 
         return self.get_remote_client(ip, private_key=keypair['private_key'],
                                       log_console_of_servers=[server])
diff --git a/tempest/services/compute/json/agents_client.py b/tempest/services/compute/json/agents_client.py
index 1269991..1a1d832 100644
--- a/tempest/services/compute/json/agents_client.py
+++ b/tempest/services/compute/json/agents_client.py
@@ -52,4 +52,5 @@
         """Update an agent build."""
         put_body = json.dumps({'para': kwargs})
         resp, body = self.put('os-agents/%s' % agent_id, put_body)
-        return service_client.ResponseBody(resp, self._parse_resp(body))
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body['agent'])
diff --git a/tempest/services/compute/json/security_group_rules_client.py b/tempest/services/compute/json/security_group_rules_client.py
new file mode 100644
index 0000000..f570eb7
--- /dev/null
+++ b/tempest/services/compute/json/security_group_rules_client.py
@@ -0,0 +1,68 @@
+# Copyright 2012 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.
+
+import json
+
+from tempest_lib import exceptions as lib_exc
+
+from tempest.api_schema.response.compute.v2_1 import security_groups as schema
+from tempest.common import service_client
+
+
+class SecurityGroupRulesClient(service_client.ServiceClient):
+
+    def create_security_group_rule(self, parent_group_id, ip_proto, from_port,
+                                   to_port, **kwargs):
+        """
+        Creating a new security group rules.
+        parent_group_id :ID of Security group
+        ip_protocol : ip_proto (icmp, tcp, udp).
+        from_port: Port at start of range.
+        to_port  : Port at end of range.
+        Following optional keyword arguments are accepted:
+        cidr     : CIDR for address range.
+        group_id : ID of the Source group
+        """
+        post_body = {
+            'parent_group_id': parent_group_id,
+            'ip_protocol': ip_proto,
+            'from_port': from_port,
+            'to_port': to_port,
+            'cidr': kwargs.get('cidr'),
+            'group_id': kwargs.get('group_id'),
+        }
+        post_body = json.dumps({'security_group_rule': post_body})
+        url = 'os-security-group-rules'
+        resp, body = self.post(url, post_body)
+        body = json.loads(body)
+        self.validate_response(schema.create_security_group_rule, resp, body)
+        return service_client.ResponseBody(resp, body['security_group_rule'])
+
+    def delete_security_group_rule(self, group_rule_id):
+        """Deletes the provided Security Group rule."""
+        resp, body = self.delete('os-security-group-rules/%s' %
+                                 group_rule_id)
+        self.validate_response(schema.delete_security_group_rule, resp, body)
+        return service_client.ResponseBody(resp, body)
+
+    def list_security_group_rules(self, security_group_id):
+        """List all rules for a security group."""
+        resp, body = self.get('os-security-groups')
+        body = json.loads(body)
+        self.validate_response(schema.list_security_groups, resp, body)
+        for sg in body['security_groups']:
+            if sg['id'] == security_group_id:
+                return service_client.ResponseBodyList(resp, sg['rules'])
+        raise lib_exc.NotFound('No such Security Group')
diff --git a/tempest/services/compute/json/security_groups_client.py b/tempest/services/compute/json/security_groups_client.py
index 5a3d771..eec961c 100644
--- a/tempest/services/compute/json/security_groups_client.py
+++ b/tempest/services/compute/json/security_groups_client.py
@@ -86,50 +86,6 @@
         self.validate_response(schema.delete_security_group, resp, body)
         return service_client.ResponseBody(resp, body)
 
-    def create_security_group_rule(self, parent_group_id, ip_proto, from_port,
-                                   to_port, **kwargs):
-        """
-        Creating a new security group rules.
-        parent_group_id :ID of Security group
-        ip_protocol : ip_proto (icmp, tcp, udp).
-        from_port: Port at start of range.
-        to_port  : Port at end of range.
-        Following optional keyword arguments are accepted:
-        cidr     : CIDR for address range.
-        group_id : ID of the Source group
-        """
-        post_body = {
-            'parent_group_id': parent_group_id,
-            'ip_protocol': ip_proto,
-            'from_port': from_port,
-            'to_port': to_port,
-            'cidr': kwargs.get('cidr'),
-            'group_id': kwargs.get('group_id'),
-        }
-        post_body = json.dumps({'security_group_rule': post_body})
-        url = 'os-security-group-rules'
-        resp, body = self.post(url, post_body)
-        body = json.loads(body)
-        self.validate_response(schema.create_security_group_rule, resp, body)
-        return service_client.ResponseBody(resp, body['security_group_rule'])
-
-    def delete_security_group_rule(self, group_rule_id):
-        """Deletes the provided Security Group rule."""
-        resp, body = self.delete('os-security-group-rules/%s' %
-                                 group_rule_id)
-        self.validate_response(schema.delete_security_group_rule, resp, body)
-        return service_client.ResponseBody(resp, body)
-
-    def list_security_group_rules(self, security_group_id):
-        """List all rules for a security group."""
-        resp, body = self.get('os-security-groups')
-        body = json.loads(body)
-        self.validate_response(schema.list_security_groups, resp, body)
-        for sg in body['security_groups']:
-            if sg['id'] == security_group_id:
-                return service_client.ResponseBodyList(resp, sg['rules'])
-        raise lib_exc.NotFound('No such Security Group')
-
     def is_resource_deleted(self, id):
         try:
             self.show_security_group(id)
diff --git a/tempest/services/telemetry/json/telemetry_client.py b/tempest/services/telemetry/json/telemetry_client.py
index 2b1cdc0..1f181e3 100644
--- a/tempest/services/telemetry/json/telemetry_client.py
+++ b/tempest/services/telemetry/json/telemetry_client.py
@@ -84,6 +84,10 @@
         uri = '%s/meters/%s' % (self.uri_prefix, meter_id)
         return self._helper_list(uri, query)
 
+    def list_events(self, query=None):
+        uri = '%s/events' % self.uri_prefix
+        return self._helper_list(uri, query)
+
     def show_resource(self, resource_id):
         uri = '%s/resources/%s' % (self.uri_prefix, resource_id)
         resp, body = self.get(uri)
diff --git a/tempest/tests/common/test_service_clients.py b/tempest/tests/common/test_service_clients.py
index b01b56e..00b8470 100644
--- a/tempest/tests/common/test_service_clients.py
+++ b/tempest/tests/common/test_service_clients.py
@@ -40,6 +40,7 @@
 from tempest.services.compute.json import quotas_client
 from tempest.services.compute.json import security_group_default_rules_client \
     as nova_secgrop_default_client
+from tempest.services.compute.json import security_group_rules_client
 from tempest.services.compute.json import security_groups_client
 from tempest.services.compute.json import server_groups_client
 from tempest.services.compute.json import servers_client
@@ -130,6 +131,7 @@
             quotas_client.QuotasClient,
             quota_classes_client.QuotaClassesClient,
             nova_secgrop_default_client.SecurityGroupDefaultRulesClient,
+            security_group_rules_client.SecurityGroupRulesClient,
             security_groups_client.SecurityGroupsClient,
             server_groups_client.ServerGroupsClient,
             servers_client.ServersClient,
diff --git a/tempest/tests/services/compute/test_agents_client.py b/tempest/tests/services/compute/test_agents_client.py
index d268a18..8316c90 100644
--- a/tempest/tests/services/compute/test_agents_client.py
+++ b/tempest/tests/services/compute/test_agents_client.py
@@ -14,19 +14,18 @@
 
 import httplib2
 
+from oslo_serialization import jsonutils as json
 from oslotest import mockpatch
 
 from tempest.services.compute.json import agents_client
 from tempest.tests import base
 from tempest.tests import fake_auth_provider
-from tempest.tests import fake_config
 
 
 class TestAgentsClient(base.TestCase):
 
     def setUp(self):
         super(TestAgentsClient, self).setUp()
-        self.useFixture(fake_config.ConfigFixture())
         fake_auth = fake_auth_provider.FakeAuthProvider()
         self.client = agents_client.AgentsClient(fake_auth,
                                                  'compute', 'regionOne')
@@ -34,7 +33,7 @@
     def _test_list_agents(self, bytes_body=False):
         body = '{"agents": []}'
         if bytes_body:
-            body = bytes(body.encode('utf-8'))
+            body = body.encode('utf-8')
         expected = []
         response = (httplib2.Response({'status': 200}), body)
         self.useFixture(mockpatch.Patch(
@@ -42,8 +41,64 @@
             return_value=response))
         self.assertEqual(expected, self.client.list_agents())
 
+    def _test_create_agent(self, bytes_body=False):
+        expected = {"url": "http://foo.com", "hypervisor": "kvm",
+                    "md5hash": "md5", "version": "2", "architecture": "x86_64",
+                    "os": "linux", "agent_id": 1}
+        serialized_body = json.dumps({"agent": expected})
+        if bytes_body:
+            serialized_body = serialized_body.encode('utf-8')
+
+        mocked_resp = (httplib2.Response({'status': 200}), serialized_body)
+        self.useFixture(mockpatch.Patch(
+            'tempest.common.service_client.ServiceClient.post',
+            return_value=mocked_resp))
+        resp = self.client.create_agent(
+            url="http://foo.com", hypervisor="kvm", md5hash="md5",
+            version="2", architecture="x86_64", os="linux"
+        )
+        self.assertEqual(expected, resp)
+
+    def _test_delete_agent(self):
+        mocked_resp = (httplib2.Response({'status': 200}), None)
+        self.useFixture(mockpatch.Patch(
+            'tempest.common.service_client.ServiceClient.delete',
+            return_value=mocked_resp))
+        self.client.delete_agent("1")
+
+    def _test_update_agent(self, bytes_body=False):
+        expected = {"url": "http://foo.com", "md5hash": "md5", "version": "2",
+                    "agent_id": 1}
+        serialized_body = json.dumps({"agent": expected})
+        if bytes_body:
+            serialized_body = serialized_body.encode('utf-8')
+
+        mocked_resp = (httplib2.Response({'status': 200}), serialized_body)
+        self.useFixture(mockpatch.Patch(
+            'tempest.common.service_client.ServiceClient.put',
+            return_value=mocked_resp))
+        resp = self.client.update_agent(
+            "1", url="http://foo.com", md5hash="md5", version="2"
+        )
+        self.assertEqual(expected, resp)
+
     def test_list_agents_with_str_body(self):
         self._test_list_agents()
 
     def test_list_agents_with_bytes_body(self):
         self._test_list_agents(bytes_body=True)
+
+    def test_create_agent_with_str_body(self):
+        self._test_create_agent()
+
+    def test_create_agent_with_bytes_body(self):
+        self._test_create_agent(bytes_body=True)
+
+    def test_delete_agent(self):
+        self._test_delete_agent()
+
+    def test_update_agent_with_str_body(self):
+        self._test_update_agent()
+
+    def test_update_agent_with_bytes_body(self):
+        self._test_update_agent(bytes_body=True)