Merge "Fix scenario test fails when port_vnic_type is set"
diff --git a/HACKING.rst b/HACKING.rst
index c776c49..45c35df 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -314,6 +314,39 @@
          * Check written content in the instance booted from snapshot
         """
 
+Test Identification with Idempotent ID
+--------------------------------------
+
+Every function that provides a test must have an ``idempotent_id`` decorator
+that is a unique ``uuid-4`` instance. This ID is used to complement the fully
+qualified test name and track test funcionality through refactoring. The
+format of the metadata looks like::
+
+    @test.idempotent_id('585e934c-448e-43c4-acbf-d06a9b899997')
+    def test_list_servers_with_detail(self):
+        # The created server should be in the detailed list of all servers
+        ...
+
+Tempest includes a ``check_uuid.py`` tool that will test for the existence
+and uniqueness of idempotent_id metadata for every test. By default the
+tool runs against the Tempest package by calling::
+
+    python check_uuid.py
+
+It can be invoked against any test suite by passing a package name::
+
+    python check_uuid.py --package <package_name>
+
+Tests without an ``idempotent_id`` can be automatically fixed by running
+the command with the ``--fix`` flag, which will modify the source package
+by inserting randomly generated uuids for every test that does not have
+one::
+
+    python check_uuid.py --fix
+
+The ``check_uuid.py`` tool is used as part of the tempest gate job
+to ensure that all tests have an ``idempotent_id`` decorator.
+
 Branchless Tempest Considerations
 ---------------------------------
 
diff --git a/README.rst b/README.rst
index af24569..d7063ba 100644
--- a/README.rst
+++ b/README.rst
@@ -107,7 +107,7 @@
 ----------
 
 Tempest also has a set of unit tests which test the Tempest code itself. These
-tests can be run by specifing the test discovery path::
+tests can be run by specifying the test discovery path::
 
     $> OS_TEST_PATH=./tempest/tests testr run --parallel
 
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index 0805544..3e6013d 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -142,7 +142,7 @@
  #. alt_password
  #. alt_tenant_name
 
-And in the auth secion:
+And in the auth section:
 
  #. allow_tenant_isolation = False
  #. comment out 'test_accounts_file' or keep it as empty
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 27d65e6..c97eb97 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -5,12 +5,14 @@
 #
 
 # Print debugging output (set logging level to DEBUG instead of
-# default WARNING level). (boolean value)
+# default INFO level). (boolean value)
 #debug = false
 
-# Print more verbose output (set logging level to INFO instead of
-# default WARNING level). (boolean value)
-#verbose = false
+# If set to false, will disable INFO logging level, making WARNING the
+# default. (boolean value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+#verbose = true
 
 # The name of a logging configuration file. This file is appended to
 # any existing logging configuration files. For details about logging
@@ -72,7 +74,7 @@
 #logging_exception_prefix = %(asctime)s.%(msecs)03d %(process)d ERROR %(name)s %(instance)s
 
 # List of logger=LEVEL pairs. (list value)
-#default_log_levels = amqp=WARN,amqplib=WARN,boto=WARN,qpid=WARN,sqlalchemy=WARN,suds=INFO,oslo.messaging=INFO,iso8601=WARN,requests.packages.urllib3.connectionpool=WARN,urllib3.connectionpool=WARN,websocket=WARN,requests.packages.urllib3.util.retry=WARN,urllib3.util.retry=WARN,keystonemiddleware=WARN,routes.middleware=WARN,stevedore=WARN
+#default_log_levels = amqp=WARN,amqplib=WARN,boto=WARN,qpid=WARN,sqlalchemy=WARN,suds=INFO,oslo.messaging=INFO,iso8601=WARN,requests.packages.urllib3.connectionpool=WARN,urllib3.connectionpool=WARN,websocket=WARN,requests.packages.urllib3.util.retry=WARN,urllib3.util.retry=WARN,keystonemiddleware=WARN,routes.middleware=WARN,stevedore=WARN,taskflow=WARN
 
 # Enables or disables publication of error events. (boolean value)
 #publish_errors = false
@@ -123,10 +125,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
@@ -376,6 +378,10 @@
 # value)
 #live_migration = true
 
+# Does the test environment support metadata service? Ignored unless
+# validation.run_validation=true. (boolean value)
+#metadata_service = true
+
 # Does the test environment use block devices for live migration
 # (boolean value)
 #block_migration_for_live_migration = false
@@ -498,18 +504,29 @@
 # From tempest.config
 #
 
-# A regex to determine which requests should be traced.  This is a
-# regex to match the caller for rest client requests to be able to
+# A regex to determine which requests should be traced.
+#
+# This is a regex to match the caller for rest client requests to be
+# able to
 # selectively trace calls out of specific classes and methods. It
-# largely exists for test development, and is not expected to be used
-# in a real deploy of tempest. This will be matched against the
-# discovered ClassName:method in the test environment.  Expected
-# values for this field are:   * ClassName:test_method_name - traces
-# one test_method  * ClassName:setUp(Class) - traces specific setup
-# functions  * ClassName:tearDown(Class) - traces specific teardown
-# functions  * ClassName:_run_cleanups - traces the cleanup functions
+# largely
+# exists for test development, and is not expected to be used in a
+# real deploy
+# of tempest. This will be matched against the discovered
+# ClassName:method
+# in the test environment.
+#
+# Expected values for this field are:
+#
+#  * ClassName:test_method_name - traces one test_method
+#  * ClassName:setUp(Class) - traces specific setup functions
+#  * ClassName:tearDown(Class) - traces specific teardown functions
+#  * ClassName:_run_cleanups - traces the cleanup functions
+#
 # If nothing is specified, this feature is not enabled. To trace
-# everything specify .* as the regex.  (string value)
+# everything
+# specify .* as the regex.
+#  (string value)
 #trace_requests =
 
 
@@ -1098,6 +1115,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/requirements.txt b/requirements.txt
index d0419f7..415eaa5 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -12,7 +12,7 @@
 netaddr>=0.7.12
 testrepository>=0.0.18
 pyOpenSSL>=0.14
-oslo.concurrency>=2.1.0 # Apache-2.0
+oslo.concurrency>=2.3.0 # Apache-2.0
 oslo.config>=1.11.0 # Apache-2.0
 oslo.i18n>=1.5.0 # Apache-2.0
 oslo.log>=1.6.0 # Apache-2.0
diff --git a/setup.cfg b/setup.cfg
index 5c78632..ab40f12 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -18,6 +18,12 @@
     Programming Language :: Python :: 3
     Programming Language :: Python :: 3.4
 
+[files]
+packages =
+    tempest
+data_files =
+    etc/tempest = etc/*
+
 [entry_points]
 console_scripts =
     verify-tempest-config = tempest.cmd.verify_tempest_config:main
@@ -26,7 +32,8 @@
     tempest-cleanup = tempest.cmd.cleanup:main
     tempest-account-generator = tempest.cmd.account_generator:main
     tempest = tempest.cmd.main:main
-
+tempest.cm =
+    init = tempest.cmd.init:TempestInit
 oslo.config.opts =
     tempest.config = tempest.config:list_opts
 
diff --git a/tempest/api/compute/admin/test_fixed_ips.py b/tempest/api/compute/admin/test_fixed_ips.py
index dc9a7ef..3e20b46 100644
--- a/tempest/api/compute/admin/test_fixed_ips.py
+++ b/tempest/api/compute/admin/test_fixed_ips.py
@@ -56,11 +56,9 @@
     @test.idempotent_id('5485077b-7e46-4cec-b402-91dc3173433b')
     @test.services('network')
     def test_set_reserve(self):
-        body = {"reserve": "None"}
-        self.client.reserve_fixed_ip(self.ip, body)
+        self.client.reserve_fixed_ip(self.ip, reserve="None")
 
     @test.idempotent_id('7476e322-b9ff-4710-bf82-49d51bac6e2e')
     @test.services('network')
     def test_set_unreserve(self):
-        body = {"unreserve": "None"}
-        self.client.reserve_fixed_ip(self.ip, body)
+        self.client.reserve_fixed_ip(self.ip, unreserve="None")
diff --git a/tempest/api/compute/admin/test_fixed_ips_negative.py b/tempest/api/compute/admin/test_fixed_ips_negative.py
index 6698638..e67936c 100644
--- a/tempest/api/compute/admin/test_fixed_ips_negative.py
+++ b/tempest/api/compute/admin/test_fixed_ips_negative.py
@@ -60,19 +60,17 @@
     @test.idempotent_id('ce60042c-fa60-4836-8d43-1c8e3359dc47')
     @test.services('network')
     def test_set_reserve_with_non_admin_user(self):
-        body = {"reserve": "None"}
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.reserve_fixed_ip,
-                          self.ip, body)
+                          self.ip, reserve="None")
 
     @test.attr(type=['negative'])
     @test.idempotent_id('f1f7a35b-0390-48c5-9803-5f27461439db')
     @test.services('network')
     def test_set_unreserve_with_non_admin_user(self):
-        body = {"unreserve": "None"}
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.reserve_fixed_ip,
-                          self.ip, body)
+                          self.ip, unreserve="None")
 
     @test.attr(type=['negative'])
     @test.idempotent_id('f51cf464-7fc5-4352-bc3e-e75cfa2cb717')
@@ -80,19 +78,17 @@
     def test_set_reserve_with_invalid_ip(self):
         # NOTE(maurosr): since this exercises the same code snippet, we do it
         # only for reserve action
-        body = {"reserve": "None"}
         # NOTE(eliqiao): in Juno, the exception is NotFound, but in master, we
         # change the error code to BadRequest, both exceptions should be
         # accepted by tempest
         self.assertRaises((lib_exc.NotFound, lib_exc.BadRequest),
                           self.client.reserve_fixed_ip,
-                          "my.invalid.ip", body)
+                          "my.invalid.ip", reserve="None")
 
     @test.attr(type=['negative'])
     @test.idempotent_id('fd26ef50-f135-4232-9d32-281aab3f9176')
     @test.services('network')
     def test_fixed_ip_with_invalid_action(self):
-        body = {"invalid_action": "None"}
         self.assertRaises(lib_exc.BadRequest,
                           self.client.reserve_fixed_ip,
-                          self.ip, body)
+                          self.ip, invalid_action="None")
diff --git a/tempest/api/compute/admin/test_flavors.py b/tempest/api/compute/admin/test_flavors.py
index 364d080..a3c25a2 100644
--- a/tempest/api/compute/admin/test_flavors.py
+++ b/tempest/api/compute/admin/test_flavors.py
@@ -63,13 +63,13 @@
         flavor_name = data_utils.rand_name(self.flavor_name_prefix)
 
         # Create the flavor
-        flavor = self.client.create_flavor(flavor_name,
-                                           self.ram, self.vcpus,
-                                           self.disk,
-                                           flavor_id,
+        flavor = self.client.create_flavor(name=flavor_name,
+                                           ram=self.ram, vcpus=self.vcpus,
+                                           disk=self.disk,
+                                           id=flavor_id,
                                            ephemeral=self.ephemeral,
                                            swap=self.swap,
-                                           rxtx=self.rxtx)
+                                           rxtx_factor=self.rxtx)
         self.addCleanup(self.flavor_clean_up, flavor['id'])
         self.assertEqual(flavor['name'], flavor_name)
         self.assertEqual(flavor['vcpus'], self.vcpus)
@@ -115,13 +115,13 @@
         new_flavor_id = data_utils.rand_int_id(start=1000)
 
         # Create the flavor
-        flavor = self.client.create_flavor(flavor_name,
-                                           self.ram, self.vcpus,
-                                           self.disk,
-                                           new_flavor_id,
+        flavor = self.client.create_flavor(name=flavor_name,
+                                           ram=self.ram, vcpus=self.vcpus,
+                                           disk=self.disk,
+                                           id=new_flavor_id,
                                            ephemeral=self.ephemeral,
                                            swap=self.swap,
-                                           rxtx=self.rxtx)
+                                           rxtx_factor=self.rxtx)
         self.addCleanup(self.flavor_clean_up, flavor['id'])
         flag = False
         # Verify flavor is retrieved
@@ -147,10 +147,10 @@
         new_flavor_id = data_utils.rand_int_id(start=1000)
 
         # Create the flavor
-        flavor = self.client.create_flavor(flavor_name,
-                                           self.ram, self.vcpus,
-                                           self.disk,
-                                           new_flavor_id)
+        flavor = self.client.create_flavor(name=flavor_name,
+                                           ram=self.ram, vcpus=self.vcpus,
+                                           disk=self.disk,
+                                           id=new_flavor_id)
         self.addCleanup(self.flavor_clean_up, flavor['id'])
         self.assertEqual(flavor['name'], flavor_name)
         self.assertEqual(flavor['ram'], self.ram)
@@ -182,10 +182,10 @@
         new_flavor_id = data_utils.rand_int_id(start=1000)
 
         # Create the flavor
-        flavor = self.client.create_flavor(flavor_name,
-                                           self.ram, self.vcpus,
-                                           self.disk,
-                                           new_flavor_id,
+        flavor = self.client.create_flavor(name=flavor_name,
+                                           ram=self.ram, vcpus=self.vcpus,
+                                           disk=self.disk,
+                                           id=new_flavor_id,
                                            is_public="False")
         self.addCleanup(self.flavor_clean_up, flavor['id'])
         # Verify flavor is retrieved
@@ -211,10 +211,10 @@
         new_flavor_id = data_utils.rand_int_id(start=1000)
 
         # Create the flavor
-        flavor = self.client.create_flavor(flavor_name,
-                                           self.ram, self.vcpus,
-                                           self.disk,
-                                           new_flavor_id,
+        flavor = self.client.create_flavor(name=flavor_name,
+                                           ram=self.ram, vcpus=self.vcpus,
+                                           disk=self.disk,
+                                           id=new_flavor_id,
                                            is_public="False")
         self.addCleanup(self.flavor_clean_up, flavor['id'])
 
@@ -231,10 +231,10 @@
         new_flavor_id = data_utils.rand_int_id(start=1000)
 
         # Create the flavor
-        flavor = self.client.create_flavor(flavor_name,
-                                           self.ram, self.vcpus,
-                                           self.disk,
-                                           new_flavor_id,
+        flavor = self.client.create_flavor(name=flavor_name,
+                                           ram=self.ram, vcpus=self.vcpus,
+                                           disk=self.disk,
+                                           id=new_flavor_id,
                                            is_public="True")
         self.addCleanup(self.flavor_clean_up, flavor['id'])
         flag = False
@@ -254,18 +254,18 @@
         flavor_name_public = data_utils.rand_name(self.flavor_name_prefix)
 
         # Create a non public flavor
-        flavor = self.client.create_flavor(flavor_name_not_public,
-                                           self.ram, self.vcpus,
-                                           self.disk,
-                                           flavor_id_not_public,
+        flavor = self.client.create_flavor(name=flavor_name_not_public,
+                                           ram=self.ram, vcpus=self.vcpus,
+                                           disk=self.disk,
+                                           id=flavor_id_not_public,
                                            is_public="False")
         self.addCleanup(self.flavor_clean_up, flavor['id'])
 
         # Create a public flavor
-        flavor = self.client.create_flavor(flavor_name_public,
-                                           self.ram, self.vcpus,
-                                           self.disk,
-                                           flavor_id_public,
+        flavor = self.client.create_flavor(name=flavor_name_public,
+                                           ram=self.ram, vcpus=self.vcpus,
+                                           disk=self.disk,
+                                           id=flavor_id_public,
                                            is_public="True")
         self.addCleanup(self.flavor_clean_up, flavor['id'])
 
@@ -294,10 +294,10 @@
         new_flavor_id = data_utils.rand_int_id(start=1000)
 
         ram = "1024"
-        flavor = self.client.create_flavor(flavor_name,
-                                           ram, self.vcpus,
-                                           self.disk,
-                                           new_flavor_id)
+        flavor = self.client.create_flavor(name=flavor_name,
+                                           ram=ram, vcpus=self.vcpus,
+                                           disk=self.disk,
+                                           id=new_flavor_id)
         self.addCleanup(self.flavor_clean_up, flavor['id'])
         self.assertEqual(flavor['name'], flavor_name)
         self.assertEqual(flavor['vcpus'], self.vcpus)
diff --git a/tempest/api/compute/admin/test_flavors_access.py b/tempest/api/compute/admin/test_flavors_access.py
index 2baa53e..ccfe20b 100644
--- a/tempest/api/compute/admin/test_flavors_access.py
+++ b/tempest/api/compute/admin/test_flavors_access.py
@@ -56,10 +56,10 @@
         # private flavor will return an empty access list
         flavor_name = data_utils.rand_name(self.flavor_name_prefix)
         new_flavor_id = data_utils.rand_int_id(start=1000)
-        new_flavor = self.client.create_flavor(flavor_name,
-                                               self.ram, self.vcpus,
-                                               self.disk,
-                                               new_flavor_id,
+        new_flavor = self.client.create_flavor(name=flavor_name,
+                                               ram=self.ram, vcpus=self.vcpus,
+                                               disk=self.disk,
+                                               id=new_flavor_id,
                                                is_public='False')
         self.addCleanup(self.client.delete_flavor, new_flavor['id'])
         flavor_access = self.client.list_flavor_access(new_flavor_id)
@@ -70,10 +70,10 @@
         # Test to add and remove flavor access to a given tenant.
         flavor_name = data_utils.rand_name(self.flavor_name_prefix)
         new_flavor_id = data_utils.rand_int_id(start=1000)
-        new_flavor = self.client.create_flavor(flavor_name,
-                                               self.ram, self.vcpus,
-                                               self.disk,
-                                               new_flavor_id,
+        new_flavor = self.client.create_flavor(name=flavor_name,
+                                               ram=self.ram, vcpus=self.vcpus,
+                                               disk=self.disk,
+                                               id=new_flavor_id,
                                                is_public='False')
         self.addCleanup(self.client.delete_flavor, new_flavor['id'])
         # Add flavor access to a tenant.
diff --git a/tempest/api/compute/admin/test_flavors_access_negative.py b/tempest/api/compute/admin/test_flavors_access_negative.py
index e5ae23b..03898c2 100644
--- a/tempest/api/compute/admin/test_flavors_access_negative.py
+++ b/tempest/api/compute/admin/test_flavors_access_negative.py
@@ -57,10 +57,10 @@
         # Test to list flavor access with exceptions by querying public flavor
         flavor_name = data_utils.rand_name(self.flavor_name_prefix)
         new_flavor_id = data_utils.rand_int_id(start=1000)
-        new_flavor = self.client.create_flavor(flavor_name,
-                                               self.ram, self.vcpus,
-                                               self.disk,
-                                               new_flavor_id,
+        new_flavor = self.client.create_flavor(name=flavor_name,
+                                               ram=self.ram, vcpus=self.vcpus,
+                                               disk=self.disk,
+                                               id=new_flavor_id,
                                                is_public='True')
         self.addCleanup(self.client.delete_flavor, new_flavor['id'])
         self.assertRaises(lib_exc.NotFound,
@@ -73,10 +73,10 @@
         # Test to add flavor access as a user without admin privileges.
         flavor_name = data_utils.rand_name(self.flavor_name_prefix)
         new_flavor_id = data_utils.rand_int_id(start=1000)
-        new_flavor = self.client.create_flavor(flavor_name,
-                                               self.ram, self.vcpus,
-                                               self.disk,
-                                               new_flavor_id,
+        new_flavor = self.client.create_flavor(name=flavor_name,
+                                               ram=self.ram, vcpus=self.vcpus,
+                                               disk=self.disk,
+                                               id=new_flavor_id,
                                                is_public='False')
         self.addCleanup(self.client.delete_flavor, new_flavor['id'])
         self.assertRaises(lib_exc.Forbidden,
@@ -90,10 +90,10 @@
         # Test to remove flavor access as a user without admin privileges.
         flavor_name = data_utils.rand_name(self.flavor_name_prefix)
         new_flavor_id = data_utils.rand_int_id(start=1000)
-        new_flavor = self.client.create_flavor(flavor_name,
-                                               self.ram, self.vcpus,
-                                               self.disk,
-                                               new_flavor_id,
+        new_flavor = self.client.create_flavor(name=flavor_name,
+                                               ram=self.ram, vcpus=self.vcpus,
+                                               disk=self.disk,
+                                               id=new_flavor_id,
                                                is_public='False')
         self.addCleanup(self.client.delete_flavor, new_flavor['id'])
         # Add flavor access to a tenant.
@@ -111,10 +111,10 @@
         # Create a new flavor.
         flavor_name = data_utils.rand_name(self.flavor_name_prefix)
         new_flavor_id = data_utils.rand_int_id(start=1000)
-        new_flavor = self.client.create_flavor(flavor_name,
-                                               self.ram, self.vcpus,
-                                               self.disk,
-                                               new_flavor_id,
+        new_flavor = self.client.create_flavor(name=flavor_name,
+                                               ram=self.ram, vcpus=self.vcpus,
+                                               disk=self.disk,
+                                               id=new_flavor_id,
                                                is_public='False')
         self.addCleanup(self.client.delete_flavor, new_flavor['id'])
 
@@ -136,10 +136,10 @@
         # Create a new flavor.
         flavor_name = data_utils.rand_name(self.flavor_name_prefix)
         new_flavor_id = data_utils.rand_int_id(start=1000)
-        new_flavor = self.client.create_flavor(flavor_name,
-                                               self.ram, self.vcpus,
-                                               self.disk,
-                                               new_flavor_id,
+        new_flavor = self.client.create_flavor(name=flavor_name,
+                                               ram=self.ram, vcpus=self.vcpus,
+                                               disk=self.disk,
+                                               id=new_flavor_id,
                                                is_public='False')
         self.addCleanup(self.client.delete_flavor, new_flavor['id'])
 
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs.py b/tempest/api/compute/admin/test_flavors_extra_specs.py
index 6866c1a..6039cb2 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs.py
@@ -50,12 +50,12 @@
         swap = 1024
         rxtx = 1
         # Create a flavor so as to set/get/unset extra specs
-        cls.flavor = cls.client.create_flavor(flavor_name,
-                                              ram, vcpus,
-                                              disk,
-                                              cls.new_flavor_id,
+        cls.flavor = cls.client.create_flavor(name=flavor_name,
+                                              ram=ram, vcpus=vcpus,
+                                              disk=disk,
+                                              id=cls.new_flavor_id,
                                               ephemeral=ephemeral,
-                                              swap=swap, rxtx=rxtx)
+                                              swap=swap, rxtx_factor=rxtx)
 
     @classmethod
     def resource_cleanup(cls):
@@ -71,7 +71,7 @@
         specs = {"key1": "value1", "key2": "value2"}
         # SET extra specs to the flavor created in setUp
         set_body = \
-            self.client.set_flavor_extra_spec(self.flavor['id'], specs)
+            self.client.set_flavor_extra_spec(self.flavor['id'], **specs)
         self.assertEqual(set_body, specs)
         # GET extra specs and verify
         get_body = self.client.list_flavor_extra_specs(self.flavor['id'])
@@ -96,7 +96,7 @@
     @test.idempotent_id('a99dad88-ae1c-4fba-aeb4-32f898218bd0')
     def test_flavor_non_admin_get_all_keys(self):
         specs = {"key1": "value1", "key2": "value2"}
-        self.client.set_flavor_extra_spec(self.flavor['id'], specs)
+        self.client.set_flavor_extra_spec(self.flavor['id'], **specs)
         body = self.flavors_client.list_flavor_extra_specs(self.flavor['id'])
 
         for key in specs:
@@ -104,8 +104,8 @@
 
     @test.idempotent_id('12805a7f-39a3-4042-b989-701d5cad9c90')
     def test_flavor_non_admin_get_specific_key(self):
-        specs = {"key1": "value1", "key2": "value2"}
-        body = self.client.set_flavor_extra_spec(self.flavor['id'], specs)
+        body = self.client.set_flavor_extra_spec(self.flavor['id'],
+                                                 key1="value1", key2="value2")
         self.assertEqual(body['key1'], 'value1')
         self.assertIn('key2', body)
         body = self.flavors_client.show_flavor_extra_spec(
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
index 8c5a103..f1e11f4 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
@@ -53,12 +53,12 @@
         swap = 1024
         rxtx = 1
         # Create a flavor
-        cls.flavor = cls.client.create_flavor(flavor_name,
-                                              ram, vcpus,
-                                              disk,
-                                              cls.new_flavor_id,
+        cls.flavor = cls.client.create_flavor(name=flavor_name,
+                                              ram=ram, vcpus=vcpus,
+                                              disk=disk,
+                                              id=cls.new_flavor_id,
                                               ephemeral=ephemeral,
-                                              swap=swap, rxtx=rxtx)
+                                              swap=swap, rxtx_factor=rxtx)
 
     @classmethod
     def resource_cleanup(cls):
@@ -70,19 +70,17 @@
     @test.idempotent_id('a00a3b81-5641-45a8-ab2b-4a8ec41e1d7d')
     def test_flavor_non_admin_set_keys(self):
         # Test to SET flavor extra spec as a user without admin privileges.
-        specs = {"key1": "value1", "key2": "value2"}
         self.assertRaises(lib_exc.Forbidden,
                           self.flavors_client.set_flavor_extra_spec,
                           self.flavor['id'],
-                          specs)
+                          key1="value1", key2="value2")
 
     @test.attr(type=['negative'])
     @test.idempotent_id('1ebf4ef8-759e-48fe-a801-d451d80476fb')
     def test_flavor_non_admin_update_specific_key(self):
         # non admin user is not allowed to update flavor extra spec
-        specs = {"key1": "value1", "key2": "value2"}
         body = self.client.set_flavor_extra_spec(
-            self.flavor['id'], specs)
+            self.flavor['id'], key1="value1", key2="value2")
         self.assertEqual(body['key1'], 'value1')
         self.assertRaises(lib_exc.Forbidden,
                           self.flavors_client.
@@ -94,8 +92,8 @@
     @test.attr(type=['negative'])
     @test.idempotent_id('28f12249-27c7-44c1-8810-1f382f316b11')
     def test_flavor_non_admin_unset_keys(self):
-        specs = {"key1": "value1", "key2": "value2"}
-        self.client.set_flavor_extra_spec(self.flavor['id'], specs)
+        self.client.set_flavor_extra_spec(self.flavor['id'],
+                                          key1="value1", key2="value2")
 
         self.assertRaises(lib_exc.Forbidden,
                           self.flavors_client.unset_flavor_extra_spec,
diff --git a/tempest/api/compute/admin/test_quotas_negative.py b/tempest/api/compute/admin/test_quotas_negative.py
index 798bd30..9acf23b 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):
@@ -128,7 +129,7 @@
         # will be raised when out of quota
         self.assertRaises((lib_exc.Forbidden, lib_exc.OverLimit),
                           self.sg_client.create_security_group,
-                          "sg-overlimit", "sg-desc")
+                          name="sg-overlimit", description="sg-desc")
 
     @decorators.skip_because(bug="1186354",
                              condition=CONF.service_available.neutron)
@@ -156,7 +157,8 @@
         s_name = data_utils.rand_name('securitygroup')
         s_description = data_utils.rand_name('description')
         securitygroup =\
-            self.sg_client.create_security_group(s_name, s_description)
+            self.sg_client.create_security_group(name=s_name,
+                                                 description=s_description)
         self.addCleanup(self.sg_client.delete_security_group,
                         securitygroup['id'])
 
@@ -167,5 +169,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/admin/test_security_group_default_rules.py b/tempest/api/compute/admin/test_security_group_default_rules.py
index 13d6cc0..5ae6553 100644
--- a/tempest/api/compute/admin/test_security_group_default_rules.py
+++ b/tempest/api/compute/admin/test_security_group_default_rules.py
@@ -45,9 +45,9 @@
                                              cidr='10.10.0.0/24'):
         # Create Security Group default rule
         rule = self.adm_client.create_security_default_group_rule(
-            ip_protocol,
-            from_port,
-            to_port,
+            ip_protocol=ip_protocol,
+            from_port=from_port,
+            to_port=to_port,
             cidr=cidr)
         self.assertEqual(ip_protocol, rule['ip_protocol'])
         self.assertEqual(from_port, rule['from_port'])
@@ -73,9 +73,9 @@
         from_port = 80
         to_port = 80
         rule = self.adm_client.create_security_default_group_rule(
-            ip_protocol,
-            from_port,
-            to_port)
+            ip_protocol=ip_protocol,
+            from_port=from_port,
+            to_port=to_port)
         self.addCleanup(self.adm_client.delete_security_group_default_rule,
                         rule['id'])
         self.assertNotEqual(0, rule['id'])
@@ -88,9 +88,9 @@
         to_port = 10
         cidr = ''
         rule = self.adm_client.create_security_default_group_rule(
-            ip_protocol,
-            from_port,
-            to_port,
+            ip_protocol=ip_protocol,
+            from_port=from_port,
+            to_port=to_port,
             cidr=cidr)
         self.addCleanup(self.adm_client.delete_security_group_default_rule,
                         rule['id'])
diff --git a/tempest/api/compute/admin/test_security_groups.py b/tempest/api/compute/admin/test_security_groups.py
index ff87a4f..b2a1b98 100644
--- a/tempest/api/compute/admin/test_security_groups.py
+++ b/tempest/api/compute/admin/test_security_groups.py
@@ -51,7 +51,8 @@
             name = data_utils.rand_name('securitygroup')
             description = data_utils.rand_name('description')
             securitygroup = (self.client
-                             .create_security_group(name, description))
+                             .create_security_group(name=name,
+                                                    description=description))
             self.addCleanup(self._delete_security_group,
                             securitygroup['id'], admin=False)
             security_group_list.append(securitygroup)
@@ -61,9 +62,8 @@
         for i in range(2):
             name = data_utils.rand_name('securitygroup')
             description = data_utils.rand_name('description')
-            adm_securitygroup = (self.adm_client
-                                 .create_security_group(name,
-                                                        description))
+            adm_securitygroup = self.adm_client.create_security_group(
+                name=name, description=description)
             self.addCleanup(self._delete_security_group,
                             adm_securitygroup['id'])
             security_group_list.append(adm_securitygroup)
diff --git a/tempest/api/compute/admin/test_servers_negative.py b/tempest/api/compute/admin/test_servers_negative.py
index b93aaca..0241e70 100644
--- a/tempest/api/compute/admin/test_servers_negative.py
+++ b/tempest/api/compute/admin/test_servers_negative.py
@@ -73,9 +73,9 @@
         ram = int(quota_set['ram']) + 1
         vcpus = 8
         disk = 10
-        flavor_ref = self.flavors_client.create_flavor(flavor_name,
-                                                       ram, vcpus, disk,
-                                                       flavor_id)
+        flavor_ref = self.flavors_client.create_flavor(name=flavor_name,
+                                                       ram=ram, vcpus=vcpus,
+                                                       disk=disk, id=flavor_id)
         self.addCleanup(self.flavors_client.delete_flavor, flavor_id)
         self.assertRaises((lib_exc.Forbidden, lib_exc.OverLimit),
                           self.client.resize,
@@ -95,9 +95,9 @@
         quota_set = self.quotas_client.show_default_quota_set(self.tenant_id)
         vcpus = int(quota_set['cores']) + 1
         disk = 10
-        flavor_ref = self.flavors_client.create_flavor(flavor_name,
-                                                       ram, vcpus, disk,
-                                                       flavor_id)
+        flavor_ref = self.flavors_client.create_flavor(name=flavor_name,
+                                                       ram=ram, vcpus=vcpus,
+                                                       disk=disk, id=flavor_id)
         self.addCleanup(self.flavors_client.delete_flavor, flavor_id)
         self.assertRaises((lib_exc.Forbidden, lib_exc.OverLimit),
                           self.client.resize,
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 759bb8c..2126787 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
@@ -221,8 +222,8 @@
         if description is None:
             description = data_utils.rand_name('description')
         body = \
-            cls.security_groups_client.create_security_group(name,
-                                                             description)
+            cls.security_groups_client.create_security_group(
+                name=name, description=description)
         cls.security_groups.append(body)
 
         return body
diff --git a/tempest/api/compute/keypairs/test_keypairs.py b/tempest/api/compute/keypairs/test_keypairs.py
index 45eaa97..9243fdf 100644
--- a/tempest/api/compute/keypairs/test_keypairs.py
+++ b/tempest/api/compute/keypairs/test_keypairs.py
@@ -31,7 +31,10 @@
         self.client.delete_keypair(keypair_name)
 
     def _create_keypair(self, keypair_name, pub_key=None):
-        body = self.client.create_keypair(keypair_name, pub_key)
+        kwargs = {'name': keypair_name}
+        if pub_key:
+            kwargs.update({'public_key': pub_key})
+        body = self.client.create_keypair(**kwargs)
         self.addCleanup(self._delete_keypair, keypair_name)
         return body
 
diff --git a/tempest/api/compute/keypairs/test_keypairs_negative.py b/tempest/api/compute/keypairs/test_keypairs_negative.py
index 54b07f0..3e6d400 100644
--- a/tempest/api/compute/keypairs/test_keypairs_negative.py
+++ b/tempest/api/compute/keypairs/test_keypairs_negative.py
@@ -29,7 +29,10 @@
         cls.client = cls.keypairs_client
 
     def _create_keypair(self, keypair_name, pub_key=None):
-        self.client.create_keypair(keypair_name, pub_key)
+        kwargs = {'name': keypair_name}
+        if pub_key:
+            kwargs.update({'public_key': pub_key})
+        self.client.create_keypair(**kwargs)
         self.addCleanup(self.client.delete_keypair, keypair_name)
 
     @test.attr(type=['negative'])
@@ -72,7 +75,7 @@
     def test_create_keypair_with_duplicate_name(self):
         # Keypairs with duplicate names should not be created
         k_name = data_utils.rand_name('keypair')
-        self.client.create_keypair(k_name)
+        self.client.create_keypair(name=k_name)
         # Now try the same keyname to create another key
         self.assertRaises(lib_exc.Conflict, self._create_keypair,
                           k_name)
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/security_groups/test_security_groups_negative.py b/tempest/api/compute/security_groups/test_security_groups_negative.py
index d8cbe3d..642aca1 100644
--- a/tempest/api/compute/security_groups/test_security_groups_negative.py
+++ b/tempest/api/compute/security_groups/test_security_groups_negative.py
@@ -72,16 +72,17 @@
         s_description = data_utils.rand_name('description')
         # Create Security Group with empty string as group name
         self.assertRaises(lib_exc.BadRequest,
-                          self.client.create_security_group, "", s_description)
+                          self.client.create_security_group,
+                          name="", description=s_description)
         # Create Security Group with white space in group name
         self.assertRaises(lib_exc.BadRequest,
-                          self.client.create_security_group, " ",
-                          s_description)
+                          self.client.create_security_group,
+                          name=" ", description=s_description)
         # Create Security Group with group name longer than 255 chars
         s_name = 'securitygroup-'.ljust(260, '0')
         self.assertRaises(lib_exc.BadRequest,
-                          self.client.create_security_group, s_name,
-                          s_description)
+                          self.client.create_security_group,
+                          name=s_name, description=s_description)
 
     @decorators.skip_because(bug="1161411",
                              condition=CONF.service_available.neutron)
@@ -96,8 +97,8 @@
         # Create Security Group with group description longer than 255 chars
         s_description = 'description-'.ljust(260, '0')
         self.assertRaises(lib_exc.BadRequest,
-                          self.client.create_security_group, s_name,
-                          s_description)
+                          self.client.create_security_group,
+                          name=s_name, description=s_description)
 
     @test.idempotent_id('9fdb4abc-6b66-4b27-b89c-eb215a956168')
     @testtools.skipIf(CONF.service_available.neutron,
@@ -109,11 +110,11 @@
         # be created
         s_name = data_utils.rand_name('securitygroup')
         s_description = data_utils.rand_name('description')
-        self.create_security_group(s_name, s_description)
+        self.create_security_group(name=s_name, description=s_description)
         # Now try the Security Group with the same 'Name'
         self.assertRaises(lib_exc.BadRequest,
-                          self.client.create_security_group, s_name,
-                          s_description)
+                          self.client.create_security_group,
+                          name=s_name, description=s_description)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('36a1629f-c6da-4a26-b8b8-55e7e5d5cd58')
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index 396327b..9e27f33 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -98,7 +98,7 @@
     def _test_create_interface_by_network_id(self, server, ifs):
         network_id = ifs[0]['net_id']
         iface = self.client.create_interface(server['id'],
-                                             network_id=network_id)
+                                             net_id=network_id)
         iface = self.wait_for_interface_status(
             server['id'], iface['port_id'], 'ACTIVE')
         self._check_interface(iface, network_id=network_id)
@@ -179,7 +179,7 @@
         self.assertTrue(interface_count > 0)
         self._check_interface(ifs[0])
         network_id = ifs[0]['net_id']
-        self.client.add_fixed_ip(server['id'], network_id)
+        self.client.add_fixed_ip(server['id'], networkId=network_id)
         # Remove the fixed IP from server.
         server_detail = self.os.servers_client.show_server(
             server['id'])
@@ -192,4 +192,4 @@
                     break
             if fixed_ip is not None:
                 break
-        self.client.remove_fixed_ip(server['id'], fixed_ip)
+        self.client.remove_fixed_ip(server['id'], address=fixed_ip)
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index 23a9cb3..e62a52b 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -269,9 +269,9 @@
 
             # Create a flavor with extra specs
             flavor = (self.flavor_client.
-                      create_flavor(flavor_with_eph_disk_name,
-                                    ram, vcpus, disk,
-                                    flavor_with_eph_disk_id,
+                      create_flavor(name=flavor_with_eph_disk_name,
+                                    ram=ram, vcpus=vcpus, disk=disk,
+                                    id=flavor_with_eph_disk_id,
                                     ephemeral=1))
             self.addCleanup(flavor_clean_up, flavor['id'])
 
@@ -287,9 +287,9 @@
 
             # Create a flavor without extra specs
             flavor = (self.flavor_client.
-                      create_flavor(flavor_no_eph_disk_name,
-                                    ram, vcpus, disk,
-                                    flavor_no_eph_disk_id))
+                      create_flavor(name=flavor_no_eph_disk_name,
+                                    ram=ram, vcpus=vcpus, disk=disk,
+                                    id=flavor_no_eph_disk_id))
             self.addCleanup(flavor_clean_up, flavor['id'])
 
             return flavor['id']
diff --git a/tempest/api/compute/servers/test_server_rescue.py b/tempest/api/compute/servers/test_server_rescue.py
index 98a2f9d..7e09096 100644
--- a/tempest/api/compute/servers/test_server_rescue.py
+++ b/tempest/api/compute/servers/test_server_rescue.py
@@ -48,9 +48,8 @@
         # Security group creation
         cls.sg_name = data_utils.rand_name('sg')
         cls.sg_desc = data_utils.rand_name('sg-desc')
-        cls.sg = \
-            cls.security_groups_client.create_security_group(cls.sg_name,
-                                                             cls.sg_desc)
+        cls.sg = cls.security_groups_client.create_security_group(
+            name=cls.sg_name, description=cls.sg_desc)
         cls.sg_id = cls.sg['id']
 
         # Server for positive tests
diff --git a/tempest/api/compute/servers/test_servers.py b/tempest/api/compute/servers/test_servers.py
index 2c1e69c..c243adf 100644
--- a/tempest/api/compute/servers/test_servers.py
+++ b/tempest/api/compute/servers/test_servers.py
@@ -63,7 +63,7 @@
         # Specify a keypair while creating a server
 
         key_name = data_utils.rand_name('key')
-        self.keypairs_client.create_keypair(key_name)
+        self.keypairs_client.create_keypair(name=key_name)
         self.addCleanup(self.keypairs_client.delete_keypair, key_name)
         self.keypairs_client.list_keypairs()
         server = self.create_test_server(key_name=key_name)
diff --git a/tempest/api/compute/test_authorization.py b/tempest/api/compute/test_authorization.py
index 58c2206..1d7f7fa 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):
@@ -76,18 +78,18 @@
         cls.image = cls.images_client.show_image(image_id)
 
         cls.keypairname = data_utils.rand_name('keypair')
-        cls.keypairs_client.create_keypair(cls.keypairname)
+        cls.keypairs_client.create_keypair(name=cls.keypairname)
 
         name = data_utils.rand_name('security')
         description = data_utils.rand_name('description')
         cls.security_group = cls.security_client.create_security_group(
-            name, description)
+            name=name, description=description)
 
         parent_group_id = cls.security_group['id']
         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
@@ -207,7 +209,8 @@
             resp = {}
             resp['status'] = None
             self.assertRaises(lib_exc.BadRequest,
-                              self.alt_keypairs_client.create_keypair, k_name)
+                              self.alt_keypairs_client.create_keypair,
+                              name=k_name)
         finally:
             # Next request the base_url is back to normal
             if (resp['status'] is not None):
@@ -259,7 +262,7 @@
             resp['status'] = None
             self.assertRaises(lib_exc.BadRequest,
                               self.alt_security_client.create_security_group,
-                              s_name, s_description)
+                              name=s_name, description=s_description)
         finally:
             # Next request the base_url is back to normal
             if resp['status'] is not None:
@@ -292,21 +295,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 +319,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/orchestration/base.py b/tempest/api/orchestration/base.py
index 266f726..6578680 100644
--- a/tempest/api/orchestration/base.py
+++ b/tempest/api/orchestration/base.py
@@ -96,7 +96,7 @@
     @classmethod
     def _create_keypair(cls, name_start='keypair-heat-'):
         kp_name = data_utils.rand_name(name_start)
-        body = cls.keypairs_client.create_keypair(kp_name)
+        body = cls.keypairs_client.create_keypair(name=kp_name)
         cls.keypairs.append(kp_name)
         return body
 
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..71a00c9 100644
--- a/tempest/api/telemetry/test_telemetry_notification_api.py
+++ b/tempest/api/telemetry/test_telemetry_notification_api.py
@@ -10,6 +10,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib import decorators
 import testtools
 
 from tempest.api.telemetry import base
@@ -29,8 +30,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 +71,28 @@
 
         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')
+    @decorators.skip_because(bug='1480490')
+    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/api/volume/base.py b/tempest/api/volume/base.py
index f8ae5eb..b67a6d2 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -62,6 +62,7 @@
         super(BaseVolumeTest, cls).setup_clients()
         cls.servers_client = cls.os.servers_client
         cls.networks_client = cls.os.networks_client
+        cls.images_client = cls.os.images_client
 
         if cls._api_version == 1:
             cls.snapshots_client = cls.os.snapshots_client
diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py
index 29c21ed..a90f9ca 100644
--- a/tempest/api/volume/test_volumes_get.py
+++ b/tempest/api/volume/test_volumes_get.py
@@ -131,7 +131,11 @@
     @test.idempotent_id('54a01030-c7fc-447c-86ee-c1182beae638')
     @test.services('image')
     def test_volume_create_get_update_delete_from_image(self):
-        self._volume_create_get_update_delete(imageRef=CONF.compute.image_ref)
+        image = self.images_client.show_image(CONF.compute.image_ref)
+        min_disk = image.get('minDisk')
+        disk_size = max(min_disk, CONF.volume.volume_size)
+        self._volume_create_get_update_delete(
+            imageRef=CONF.compute.image_ref, size=disk_size)
 
     @test.idempotent_id('3f591b4a-7dc6-444c-bd51-77469506b3a1')
     def test_volume_create_get_update_delete_as_clone(self):
diff --git a/tempest/clients.py b/tempest/clients.py
index 6a2c601..e32d401 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -42,9 +42,9 @@
 from tempest.services.compute.json.fixed_ips_client import FixedIPsClient
 from tempest.services.compute.json.flavors_client import FlavorsClient
 from tempest.services.compute.json.floating_ip_pools_client import \
-    FloatingIpPoolsClient
+    FloatingIPPoolsClient
 from tempest.services.compute.json.floating_ips_bulk_client import \
-    FloatingIpsBulkClient
+    FloatingIPsBulkClient
 from tempest.services.compute.json.floating_ips_client import \
     FloatingIPsClient
 from tempest.services.compute.json.hosts_client import HostsClient
@@ -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 \
@@ -280,12 +282,14 @@
         self.flavors_client = FlavorsClient(self.auth_provider, **params)
         self.extensions_client = ExtensionsClient(self.auth_provider,
                                                   **params)
-        self.floating_ip_pools_client = FloatingIpPoolsClient(
+        self.floating_ip_pools_client = FloatingIPPoolsClient(
             self.auth_provider, **params)
-        self.floating_ips_bulk_client = FloatingIpsBulkClient(
+        self.floating_ips_bulk_client = FloatingIPsBulkClient(
             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 1de20d6..2e96c81 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -1,12 +1,12 @@
 #!/usr/bin/env python
 
-# Copyright 2014 Dell Inc.
+# Copyright 2015 Dell Inc.
 #
 #    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
+#        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
@@ -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
@@ -153,9 +157,8 @@
         for snap in snaps:
             try:
                 client.delete_snapshot(snap['id'])
-            except Exception as e:
-                LOG.exception("Delete Snapshot exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Snapshot exception.")
 
     def dry_run(self):
         snaps = self.list()
@@ -180,9 +183,8 @@
         for server in servers:
             try:
                 client.delete_server(server['id'])
-            except Exception as e:
-                LOG.exception("Delete Server exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Server exception.")
 
     def dry_run(self):
         servers = self.list()
@@ -203,9 +205,8 @@
         for sg in sgs:
             try:
                 client.delete_server_group(sg['id'])
-            except Exception as e:
-                LOG.exception("Delete Server Group exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Server Group exception.")
 
     def dry_run(self):
         sgs = self.list()
@@ -229,9 +230,8 @@
         for stack in stacks:
             try:
                 client.delete_stack(stack['id'])
-            except Exception as e:
-                LOG.exception("Delete Stack exception: %s " % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Stack exception.")
 
     def dry_run(self):
         stacks = self.list()
@@ -256,9 +256,8 @@
             try:
                 name = k['keypair']['name']
                 client.delete_keypair(name)
-            except Exception as e:
-                LOG.exception("Delete Keypairs exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Keypairs exception.")
 
     def dry_run(self):
         keypairs = self.list()
@@ -283,8 +282,8 @@
         for g in secgrp_del:
             try:
                 client.delete_security_group(g['id'])
-            except Exception as e:
-                LOG.exception("Delete Security Groups exception: %s" % e)
+            except Exception:
+                LOG.exception("Delete Security Groups exception.")
 
     def dry_run(self):
         secgrp_del = self.list()
@@ -308,9 +307,8 @@
         for f in floating_ips:
             try:
                 client.delete_floating_ip(f['id'])
-            except Exception as e:
-                LOG.exception("Delete Floating IPs exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Floating IPs exception.")
 
     def dry_run(self):
         floating_ips = self.list()
@@ -334,9 +332,8 @@
         for v in vols:
             try:
                 client.delete_volume(v['id'])
-            except Exception as e:
-                LOG.exception("Delete Volume exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Volume exception.")
 
     def dry_run(self):
         vols = self.list()
@@ -352,9 +349,8 @@
         client = self.client
         try:
             client.delete_quota_set(self.tenant_id)
-        except Exception as e:
-            LOG.exception("Delete Volume Quotas exception: %s" % e)
-            pass
+        except Exception:
+            LOG.exception("Delete Volume Quotas exception.")
 
     def dry_run(self):
         quotas = self.client.show_quota_usage(self.tenant_id)
@@ -371,9 +367,8 @@
         client = self.client
         try:
             client.delete_quota_set(self.tenant_id)
-        except Exception as e:
-            LOG.exception("Delete Quotas exception: %s" % e)
-            pass
+        except Exception:
+            LOG.exception("Delete Quotas exception.")
 
     def dry_run(self):
         client = self.limits_client
@@ -396,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
@@ -411,9 +406,8 @@
         for n in networks:
             try:
                 client.delete_network(n['id'])
-            except Exception as e:
-                LOG.exception("Delete Network exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Network exception.")
 
     def dry_run(self):
         networks = self.list()
@@ -424,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
 
@@ -436,9 +429,8 @@
         for flip in flips:
             try:
                 client.delete_floatingip(flip['id'])
-            except Exception as e:
-                LOG.exception("Delete Network Floating IP exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Network Floating IP exception.")
 
     def dry_run(self):
         flips = self.list()
@@ -449,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]
@@ -465,15 +456,15 @@
         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 as e:
-                LOG.exception("Delete Router exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Router exception.")
 
     def dry_run(self):
         routers = self.list()
@@ -496,9 +487,8 @@
         for hm in hms:
             try:
                 client.delete_health_monitor(hm['id'])
-            except Exception as e:
-                LOG.exception("Delete Health Monitor exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Health Monitor exception.")
 
     def dry_run(self):
         hms = self.list()
@@ -521,9 +511,8 @@
         for member in members:
             try:
                 client.delete_member(member['id'])
-            except Exception as e:
-                LOG.exception("Delete Member exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Member exception.")
 
     def dry_run(self):
         members = self.list()
@@ -546,9 +535,8 @@
         for vip in vips:
             try:
                 client.delete_vip(vip['id'])
-            except Exception as e:
-                LOG.exception("Delete VIP exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete VIP exception.")
 
     def dry_run(self):
         vips = self.list()
@@ -571,9 +559,8 @@
         for pool in pools:
             try:
                 client.delete_pool(pool['id'])
-            except Exception as e:
-                LOG.exception("Delete Pool exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Pool exception.")
 
     def dry_run(self):
         pools = self.list()
@@ -596,9 +583,8 @@
         for rule in rules:
             try:
                 client.delete_metering_label_rule(rule['id'])
-            except Exception as e:
-                LOG.exception("Delete Metering Label Rule exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Metering Label Rule exception.")
 
     def dry_run(self):
         rules = self.list()
@@ -621,9 +607,8 @@
         for label in labels:
             try:
                 client.delete_metering_label(label['id'])
-            except Exception as e:
-                LOG.exception("Delete Metering Label exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Metering Label exception.")
 
     def dry_run(self):
         labels = self.list()
@@ -634,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
 
@@ -648,22 +636,48 @@
         for port in ports:
             try:
                 client.delete_port(port['id'])
-            except Exception as e:
-                LOG.exception("Delete Port exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Port exception.")
 
     def dry_run(self):
         ports = self.list()
         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))
@@ -675,9 +689,8 @@
         for subnet in subnets:
             try:
                 client.delete_subnet(subnet['id'])
-            except Exception as e:
-                LOG.exception("Delete Subnet exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Subnet exception.")
 
     def dry_run(self):
         subnets = self.list()
@@ -702,9 +715,8 @@
         for alarm in alarms:
             try:
                 client.delete_alarm(alarm['id'])
-            except Exception as e:
-                LOG.exception("Delete Alarms exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Alarms exception.")
 
     def dry_run(self):
         alarms = self.list()
@@ -737,9 +749,8 @@
         for flavor in flavors:
             try:
                 client.delete_flavor(flavor['id'])
-            except Exception as e:
-                LOG.exception("Delete Flavor exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Flavor exception.")
 
     def dry_run(self):
         flavors = self.list()
@@ -775,17 +786,16 @@
         for image in images:
             try:
                 client.delete_image(image['id'])
-            except Exception as e:
-                LOG.exception("Delete Image exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Image exception.")
 
     def dry_run(self):
         images = self.list()
         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']
 
@@ -823,9 +833,8 @@
         for user in users:
             try:
                 client.delete_user(user['id'])
-            except Exception as e:
-                LOG.exception("Delete User exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete User exception.")
 
     def dry_run(self):
         users = self.list()
@@ -852,8 +861,8 @@
                           and role['name'] != CONF.identity.admin_role)]
                 LOG.debug("List count, %s Roles after reconcile" % len(roles))
             return roles
-        except Exception as ex:
-            LOG.exception("Cannot retrieve Roles, exception: %s" % ex)
+        except Exception:
+            LOG.exception("Cannot retrieve Roles.")
             return []
 
     def delete(self):
@@ -862,9 +871,8 @@
         for role in roles:
             try:
                 client.delete_role(role['id'])
-            except Exception as e:
-                LOG.exception("Delete Role exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Role exception.")
 
     def dry_run(self):
         roles = self.list()
@@ -900,9 +908,8 @@
         for tenant in tenants:
             try:
                 client.delete_tenant(tenant['id'])
-            except Exception as e:
-                LOG.exception("Delete Tenant exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Tenant exception.")
 
     def dry_run(self):
         tenants = self.list()
@@ -938,9 +945,8 @@
             try:
                 client.update_domain(domain['id'], enabled=False)
                 client.delete_domain(domain['id'])
-            except Exception as e:
-                LOG.exception("Delete Domain exception: %s" % e)
-                pass
+            except Exception:
+                LOG.exception("Delete Domain exception.")
 
     def dry_run(self):
         domains = self.list()
@@ -955,7 +961,6 @@
 
 def get_tenant_cleanup_services():
     tenant_services = []
-
     if IS_CEILOMETER:
         tenant_services.append(TelemetryAlarmService)
     if IS_NOVA:
@@ -969,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/init.py b/tempest/cmd/init.py
new file mode 100644
index 0000000..c13fbe5
--- /dev/null
+++ b/tempest/cmd/init.py
@@ -0,0 +1,99 @@
+# Copyright 2015 Hewlett-Packard Development Company, L.P.
+#
+# 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 os
+import shutil
+import subprocess
+
+from cliff import command
+from oslo_log import log as logging
+from six import moves
+
+LOG = logging.getLogger(__name__)
+
+TESTR_CONF = """[DEFAULT]
+test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \\
+    OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \\
+    OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-500} \\
+    ${PYTHON:-python} -m subunit.run discover -t %s %s $LISTOPT $IDOPTION
+test_id_option=--load-list $IDFILE
+test_list_option=--list
+group_regex=([^\.]*\.)*
+"""
+
+
+class TempestInit(command.Command):
+    """Setup a local working environment for running tempest"""
+
+    def get_parser(self, prog_name):
+        parser = super(TempestInit, self).get_parser(prog_name)
+        parser.add_argument('dir', nargs='?', default=os.getcwd())
+        parser.add_argument('--config-dir', '-c', default='/etc/tempest')
+        return parser
+
+    def generate_testr_conf(self, local_path):
+        testr_conf_path = os.path.join(local_path, '.testr.conf')
+        top_level_path = os.path.dirname(os.path.dirname(__file__))
+        discover_path = os.path.join(top_level_path, 'test_discover')
+        testr_conf = TESTR_CONF % (top_level_path, discover_path)
+        with open(testr_conf_path, 'w+') as testr_conf_file:
+            testr_conf_file.write(testr_conf)
+
+    def update_local_conf(self, conf_path, lock_dir, log_dir):
+        config_parse = moves.configparser.SafeConfigParser()
+        config_parse.optionxform = str
+        with open(conf_path, 'w+') as conf_file:
+            config_parse.readfp(conf_file)
+            # Set local lock_dir in tempest conf
+            if not config_parse.has_section('oslo_concurrency'):
+                config_parse.add_section('oslo_concurrency')
+            config_parse.set('oslo_concurrency', 'lock_path', lock_dir)
+            # Set local log_dir in tempest conf
+            config_parse.set('DEFAULT', 'log_dir', log_dir)
+            # Set default log filename to tempest.log
+            config_parse.set('DEFAULT', 'log_file', 'tempest.log')
+
+    def copy_config(self, etc_dir, config_dir):
+        shutil.copytree(config_dir, etc_dir)
+
+    def create_working_dir(self, local_dir, config_dir):
+        # Create local dir if missing
+        if not os.path.isdir(local_dir):
+            LOG.debug('Creating local working dir: %s' % local_dir)
+            os.mkdir(local_dir)
+        lock_dir = os.path.join(local_dir, 'tempest_lock')
+        etc_dir = os.path.join(local_dir, 'etc')
+        config_path = os.path.join(etc_dir, 'tempest.conf')
+        log_dir = os.path.join(local_dir, 'logs')
+        testr_dir = os.path.join(local_dir, '.testrepository')
+        # Create lock dir
+        if not os.path.isdir(lock_dir):
+            LOG.debug('Creating lock dir: %s' % lock_dir)
+            os.mkdir(lock_dir)
+        # Create log dir
+        if not os.path.isdir(log_dir):
+            LOG.debug('Creating log dir: %s' % log_dir)
+            os.mkdir(log_dir)
+        # Create and copy local etc dir
+        self.copy_config(etc_dir, config_dir)
+        # Update local confs to reflect local paths
+        self.update_local_conf(config_path, lock_dir, log_dir)
+        # Generate a testr conf file
+        self.generate_testr_conf(local_dir)
+        # setup local testr working dir
+        if not os.path.isdir(testr_dir):
+            subprocess.call(['testr', 'init'], cwd=local_dir)
+
+    def take_action(self, parsed_args):
+        self.create_working_dir(parsed_args.dir, parsed_args.config_dir)
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index f091cd3..9402154 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(
@@ -912,12 +915,12 @@
             continue
 
         body = client.secgroups.create_security_group(
-            secgroup['name'], secgroup['description'])
+            name=secgroup['name'], description=secgroup['description'])
         secgroup_id = body['id']
         # 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/common/validation_resources.py b/tempest/common/validation_resources.py
index 18f0b1d..15c452f 100644
--- a/tempest/common/validation_resources.py
+++ b/tempest/common/validation_resources.py
@@ -27,7 +27,8 @@
     sg_name = data_utils.rand_name('securitygroup-')
     sg_description = data_utils.rand_name('description-')
     security_group = \
-        security_group_client.create_security_group(sg_name, sg_description)
+        security_group_client.create_security_group(name=sg_name,
+                                                    description=sg_description)
     if add_rule:
         security_group_client.create_security_group_rule(security_group['id'],
                                                          'tcp', 22, 22)
@@ -46,7 +47,7 @@
         if validation_resources['keypair']:
             keypair_name = data_utils.rand_name('keypair')
             validation_data['keypair'] = \
-                os.keypairs_client.create_keypair(keypair_name)
+                os.keypairs_client.create_keypair(name=keypair_name)
             LOG.debug("Validation resource key %s created" % keypair_name)
         add_rule = False
         if validation_resources['security_group']:
diff --git a/tempest/config.py b/tempest/config.py
index a9f1e01..ab503e3 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -22,6 +22,8 @@
 
 from oslo_log import log as logging
 
+from tempest.test_discover import plugins
+
 
 # TODO(marun) Replace use of oslo_config's global ConfigOpts
 # (cfg.CONF) instance with a local instance (cfg.ConfigOpts()) once
@@ -65,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 "
@@ -328,6 +331,10 @@
                 default=True,
                 help="Does the test environment support live migration "
                      "available?"),
+    cfg.BoolOpt('metadata_service',
+                default=True,
+                help="Does the test environment support metadata service? "
+                     "Ignored unless validation.run_validation=true."),
     cfg.BoolOpt('block_migration_for_live_migration',
                 default=False,
                 help="Does the test environment use block devices for live "
@@ -836,6 +843,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")
 
@@ -1176,6 +1193,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),
@@ -1192,8 +1210,12 @@
 
 
 def register_opts():
+    ext_plugins = plugins.TempestTestPluginManager()
+    # Register in-tree tempest config options
     for g, o in _opts:
         register_opt_group(_CONF, g, o)
+    # Call external plugin config option registration
+    ext_plugins.register_plugin_opts(_CONF)
 
 
 def list_opts():
@@ -1239,6 +1261,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[
@@ -1251,9 +1274,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 fefd9c5..bb0ccdd 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
@@ -138,7 +140,7 @@
             client = self.keypairs_client
         name = data_utils.rand_name(self.__class__.__name__)
         # We don't need to create a keypair by pubkey in scenario
-        body = client.create_keypair(name)
+        body = client.create_keypair(name=name)
         self.addCleanup(client.delete_keypair, name)
         return body
 
@@ -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
@@ -258,7 +261,7 @@
         sg_name = data_utils.rand_name(self.__class__.__name__)
         sg_desc = sg_name + " description"
         secgroup = self.security_groups_client.create_security_group(
-            sg_name, sg_desc)
+            name=sg_name, description=sg_desc)
         self.assertEqual(secgroup['name'], sg_name)
         self.assertEqual(secgroup['description'], sg_desc)
         self.addCleanup(self.delete_wrapper,
diff --git a/tempest/scenario/test_large_ops.py b/tempest/scenario/test_large_ops.py
index fa70d3f..c44557e 100644
--- a/tempest/scenario/test_large_ops.py
+++ b/tempest/scenario/test_large_ops.py
@@ -87,7 +87,7 @@
         # Since no traffic is tested, we don't need to actually add rules to
         # secgroup
         secgroup = self.security_groups_client.create_security_group(
-            'secgroup-%s' % name, 'secgroup-desc-%s' % name)
+            name='secgroup-%s' % name, description='secgroup-desc-%s' % name)
         self.addCleanupClass(self.security_groups_client.delete_security_group,
                              secgroup['id'])
         create_kwargs = {
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index d643485..b31ba69 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -247,7 +247,7 @@
         old_port = port_list[0]
         interface = self.interface_client.create_interface(
             server_id=server['id'],
-            network_id=self.new_net.id)
+            net_id=self.new_net.id)
         self.addCleanup(self.network_client.wait_for_resource_deletion,
                         'port',
                         interface['port_id'])
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index d9918f3..f61b151 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -37,6 +37,7 @@
      * Add simple permissive rules to the security group
      * Launch an instance
      * Perform ssh to instance
+     * Verify metadata service
      * Terminate the instance
     """
 
@@ -81,19 +82,26 @@
     def verify_ssh(self):
         if self.run_ssh:
             # Obtain a floating IP
-            floating_ip = self.floating_ips_client.create_floating_ip()
+            self.floating_ip = self.floating_ips_client.create_floating_ip()
             self.addCleanup(self.delete_wrapper,
                             self.floating_ips_client.delete_floating_ip,
-                            floating_ip['id'])
+                            self.floating_ip['id'])
             # Attach a floating IP
             self.floating_ips_client.associate_floating_ip_to_server(
-                floating_ip['ip'], self.instance['id'])
+                self.floating_ip['ip'], self.instance['id'])
             # Check ssh
-            self.get_remote_client(
-                server_or_ip=floating_ip['ip'],
+            self.ssh_client = self.get_remote_client(
+                server_or_ip=self.floating_ip['ip'],
                 username=self.image_utils.ssh_user(self.image_ref),
                 private_key=self.keypair['private_key'])
 
+    def verify_metadata(self):
+        if self.run_ssh and CONF.compute_feature_enabled.metadata_service:
+            # Verify metadata service
+            result = self.ssh_client.exec_command(
+                "curl http://169.254.169.254/latest/meta-data/public-ipv4")
+            self.assertEqual(self.floating_ip['ip'], result)
+
     @test.idempotent_id('7fff3fb3-91d8-4fd0-bd7d-0204f1f180ba')
     @test.attr(type='smoke')
     @test.services('compute', 'network')
@@ -102,4 +110,5 @@
         self.security_group = self._create_security_group()
         self.boot_instance()
         self.verify_ssh()
+        self.verify_metadata()
         self.servers_client.delete_server(self.instance['id'])
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/fixed_ips_client.py b/tempest/services/compute/json/fixed_ips_client.py
index 69de79f..d0d9ca1 100644
--- a/tempest/services/compute/json/fixed_ips_client.py
+++ b/tempest/services/compute/json/fixed_ips_client.py
@@ -28,9 +28,9 @@
         self.validate_response(schema.get_fixed_ip, resp, body)
         return service_client.ResponseBody(resp, body['fixed_ip'])
 
-    def reserve_fixed_ip(self, fixed_ip, body):
+    def reserve_fixed_ip(self, fixed_ip, **kwargs):
         """This reserves and unreserves fixed ips."""
         url = "os-fixed-ips/%s/action" % fixed_ip
-        resp, body = self.post(url, json.dumps(body))
+        resp, body = self.post(url, json.dumps(kwargs))
         self.validate_response(schema.reserve_fixed_ip, resp, body)
         return service_client.ResponseBody(resp)
diff --git a/tempest/services/compute/json/flavors_client.py b/tempest/services/compute/json/flavors_client.py
index b928f9f..1422944 100644
--- a/tempest/services/compute/json/flavors_client.py
+++ b/tempest/services/compute/json/flavors_client.py
@@ -47,24 +47,19 @@
         self.validate_response(schema.create_get_flavor_details, resp, body)
         return service_client.ResponseBody(resp, body['flavor'])
 
-    def create_flavor(self, name, ram, vcpus, disk, flavor_id, **kwargs):
-        """Creates a new flavor or instance type."""
-        post_body = {
-            'name': name,
-            'ram': ram,
-            'vcpus': vcpus,
-            'disk': disk,
-            'id': flavor_id,
-        }
+    def create_flavor(self, **kwargs):
+        """Creates a new flavor or instance type.
+        Most parameters except the following are passed to the API without
+        any changes.
+        :param ephemeral: The name is changed to OS-FLV-EXT-DATA:ephemeral
+        :param is_public: The name is changed to os-flavor-access:is_public
+        """
         if kwargs.get('ephemeral'):
-            post_body['OS-FLV-EXT-DATA:ephemeral'] = kwargs.get('ephemeral')
-        if kwargs.get('swap'):
-            post_body['swap'] = kwargs.get('swap')
-        if kwargs.get('rxtx'):
-            post_body['rxtx_factor'] = kwargs.get('rxtx')
+            kwargs['OS-FLV-EXT-DATA:ephemeral'] = kwargs.pop('ephemeral')
         if kwargs.get('is_public'):
-            post_body['os-flavor-access:is_public'] = kwargs.get('is_public')
-        post_body = json.dumps({'flavor': post_body})
+            kwargs['os-flavor-access:is_public'] = kwargs.pop('is_public')
+
+        post_body = json.dumps({'flavor': kwargs})
         resp, body = self.post('flavors', post_body)
 
         body = json.loads(body)
@@ -92,9 +87,9 @@
         """Returns the primary type of resource this client works with."""
         return 'flavor'
 
-    def set_flavor_extra_spec(self, flavor_id, specs):
+    def set_flavor_extra_spec(self, flavor_id, **kwargs):
         """Sets extra Specs to the mentioned flavor."""
-        post_body = json.dumps({'extra_specs': specs})
+        post_body = json.dumps({'extra_specs': kwargs})
         resp, body = self.post('flavors/%s/os-extra_specs' % flavor_id,
                                post_body)
         body = json.loads(body)
diff --git a/tempest/services/compute/json/floating_ip_pools_client.py b/tempest/services/compute/json/floating_ip_pools_client.py
index 1cc411b..1e2133b 100644
--- a/tempest/services/compute/json/floating_ip_pools_client.py
+++ b/tempest/services/compute/json/floating_ip_pools_client.py
@@ -21,7 +21,7 @@
 from tempest.common import service_client
 
 
-class FloatingIpPoolsClient(service_client.ServiceClient):
+class FloatingIPPoolsClient(service_client.ServiceClient):
 
     def list_floating_ip_pools(self, params=None):
         """Returns a list of all floating IP Pools."""
diff --git a/tempest/services/compute/json/floating_ips_bulk_client.py b/tempest/services/compute/json/floating_ips_bulk_client.py
index c8e7350..8b1c5a9 100644
--- a/tempest/services/compute/json/floating_ips_bulk_client.py
+++ b/tempest/services/compute/json/floating_ips_bulk_client.py
@@ -19,7 +19,7 @@
 from tempest.common import service_client
 
 
-class FloatingIpsBulkClient(service_client.ServiceClient):
+class FloatingIPsBulkClient(service_client.ServiceClient):
 
     def create_floating_ips_bulk(self, ip_range, pool, interface):
         """Allocate floating IPs in bulk."""
diff --git a/tempest/services/compute/json/interfaces_client.py b/tempest/services/compute/json/interfaces_client.py
index e8b2b64..c437c08 100644
--- a/tempest/services/compute/json/interfaces_client.py
+++ b/tempest/services/compute/json/interfaces_client.py
@@ -29,16 +29,8 @@
         return service_client.ResponseBodyList(resp,
                                                body['interfaceAttachments'])
 
-    def create_interface(self, server_id, port_id=None, network_id=None,
-                         fixed_ip=None):
-        post_body = dict(interfaceAttachment=dict())
-        if port_id:
-            post_body['interfaceAttachment']['port_id'] = port_id
-        if network_id:
-            post_body['interfaceAttachment']['net_id'] = network_id
-        if fixed_ip:
-            fip = dict(ip_address=fixed_ip)
-            post_body['interfaceAttachment']['fixed_ips'] = [fip]
+    def create_interface(self, server_id, **kwargs):
+        post_body = {'interfaceAttachment': kwargs}
         post_body = json.dumps(post_body)
         resp, body = self.post('servers/%s/os-interface' % server_id,
                                body=post_body)
@@ -59,26 +51,18 @@
         self.validate_response(schema.delete_interface, resp, body)
         return service_client.ResponseBody(resp, body)
 
-    def add_fixed_ip(self, server_id, network_id):
+    def add_fixed_ip(self, server_id, **kwargs):
         """Add a fixed IP to input server instance."""
-        post_body = json.dumps({
-            'addFixedIp': {
-                'networkId': network_id
-            }
-        })
+        post_body = json.dumps({'addFixedIp': kwargs})
         resp, body = self.post('servers/%s/action' % server_id,
                                post_body)
         self.validate_response(servers_schema.server_actions_common_schema,
                                resp, body)
         return service_client.ResponseBody(resp, body)
 
-    def remove_fixed_ip(self, server_id, ip_address):
+    def remove_fixed_ip(self, server_id, **kwargs):
         """Remove input fixed IP from input server instance."""
-        post_body = json.dumps({
-            'removeFixedIp': {
-                'address': ip_address
-            }
-        })
+        post_body = json.dumps({'removeFixedIp': kwargs})
         resp, body = self.post('servers/%s/action' % server_id,
                                post_body)
         self.validate_response(servers_schema.server_actions_common_schema,
diff --git a/tempest/services/compute/json/keypairs_client.py b/tempest/services/compute/json/keypairs_client.py
index 6f819ae..e51671f 100644
--- a/tempest/services/compute/json/keypairs_client.py
+++ b/tempest/services/compute/json/keypairs_client.py
@@ -38,11 +38,8 @@
         self.validate_response(schema.get_keypair, resp, body)
         return service_client.ResponseBody(resp, body['keypair'])
 
-    def create_keypair(self, name, pub_key=None):
-        post_body = {'keypair': {'name': name}}
-        if pub_key:
-            post_body['keypair']['public_key'] = pub_key
-        post_body = json.dumps(post_body)
+    def create_keypair(self, **kwargs):
+        post_body = json.dumps({'keypair': kwargs})
         resp, body = self.post("os-keypairs", body=post_body)
         body = json.loads(body)
         self.validate_response(schema.create_keypair, resp, body)
diff --git a/tempest/services/compute/json/quotas_client.py b/tempest/services/compute/json/quotas_client.py
index 4ea47ed..88d0567 100644
--- a/tempest/services/compute/json/quotas_client.py
+++ b/tempest/services/compute/json/quotas_client.py
@@ -41,59 +41,11 @@
         self.validate_response(schema.get_quota_set, resp, body)
         return service_client.ResponseBody(resp, body['quota_set'])
 
-    def update_quota_set(self, tenant_id, user_id=None,
-                         force=None, injected_file_content_bytes=None,
-                         metadata_items=None, ram=None, floating_ips=None,
-                         fixed_ips=None, key_pairs=None, instances=None,
-                         security_group_rules=None, injected_files=None,
-                         cores=None, injected_file_path_bytes=None,
-                         security_groups=None):
+    def update_quota_set(self, tenant_id, user_id=None, **kwargs):
         """
         Updates the tenant's quota limits for one or more resources
         """
-        post_body = {}
-
-        if force is not None:
-            post_body['force'] = force
-
-        if injected_file_content_bytes is not None:
-            post_body['injected_file_content_bytes'] = \
-                injected_file_content_bytes
-
-        if metadata_items is not None:
-            post_body['metadata_items'] = metadata_items
-
-        if ram is not None:
-            post_body['ram'] = ram
-
-        if floating_ips is not None:
-            post_body['floating_ips'] = floating_ips
-
-        if fixed_ips is not None:
-            post_body['fixed_ips'] = fixed_ips
-
-        if key_pairs is not None:
-            post_body['key_pairs'] = key_pairs
-
-        if instances is not None:
-            post_body['instances'] = instances
-
-        if security_group_rules is not None:
-            post_body['security_group_rules'] = security_group_rules
-
-        if injected_files is not None:
-            post_body['injected_files'] = injected_files
-
-        if cores is not None:
-            post_body['cores'] = cores
-
-        if injected_file_path_bytes is not None:
-            post_body['injected_file_path_bytes'] = injected_file_path_bytes
-
-        if security_groups is not None:
-            post_body['security_groups'] = security_groups
-
-        post_body = json.dumps({'quota_set': post_body})
+        post_body = json.dumps({'quota_set': kwargs})
 
         if user_id:
             resp, body = self.put('os-quota-sets/%s?user_id=%s' %
diff --git a/tempest/services/compute/json/security_group_default_rules_client.py b/tempest/services/compute/json/security_group_default_rules_client.py
index fcc715a..658b89a 100644
--- a/tempest/services/compute/json/security_group_default_rules_client.py
+++ b/tempest/services/compute/json/security_group_default_rules_client.py
@@ -22,8 +22,7 @@
 
 class SecurityGroupDefaultRulesClient(service_client.ServiceClient):
 
-    def create_security_default_group_rule(self, ip_protocol, from_port,
-                                           to_port, **kwargs):
+    def create_security_default_group_rule(self, **kwargs):
         """
         Creating security group default rules.
         ip_protocol : ip_protocol (icmp, tcp, udp).
@@ -31,13 +30,7 @@
         to_port  : Port at end of range.
         cidr     : CIDR for address range.
         """
-        post_body = {
-            'ip_protocol': ip_protocol,
-            'from_port': from_port,
-            'to_port': to_port,
-            'cidr': kwargs.get('cidr'),
-        }
-        post_body = json.dumps({'security_group_default_rule': post_body})
+        post_body = json.dumps({'security_group_default_rule': kwargs})
         url = 'os-security-group-default-rules'
         resp, body = self.post(url, post_body)
         body = json.loads(body)
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..c0b667b 100644
--- a/tempest/services/compute/json/security_groups_client.py
+++ b/tempest/services/compute/json/security_groups_client.py
@@ -43,36 +43,26 @@
         self.validate_response(schema.get_security_group, resp, body)
         return service_client.ResponseBody(resp, body['security_group'])
 
-    def create_security_group(self, name, description):
+    def create_security_group(self, **kwargs):
         """
         Creates a new security group.
         name (Required): Name of security group.
         description (Required): Description of security group.
         """
-        post_body = {
-            'name': name,
-            'description': description,
-        }
-        post_body = json.dumps({'security_group': post_body})
+        post_body = json.dumps({'security_group': kwargs})
         resp, body = self.post('os-security-groups', post_body)
         body = json.loads(body)
         self.validate_response(schema.get_security_group, resp, body)
         return service_client.ResponseBody(resp, body['security_group'])
 
-    def update_security_group(self, security_group_id, name=None,
-                              description=None):
+    def update_security_group(self, security_group_id, **kwargs):
         """
         Update a security group.
         security_group_id: a security_group to update
         name: new name of security group
         description: new description of security group
         """
-        post_body = {}
-        if name:
-            post_body['name'] = name
-        if description:
-            post_body['description'] = description
-        post_body = json.dumps({'security_group': post_body})
+        post_body = json.dumps({'security_group': kwargs})
         resp, body = self.put('os-security-groups/%s' % security_group_id,
                               post_body)
         body = json.loads(body)
@@ -86,50 +76,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/stress/actions/ssh_floating.py b/tempest/stress/actions/ssh_floating.py
index 4a27466..03a2d27 100644
--- a/tempest/stress/actions/ssh_floating.py
+++ b/tempest/stress/actions/ssh_floating.py
@@ -93,8 +93,8 @@
         sec_grp_cli = self.manager.security_groups_client
         s_name = data_utils.rand_name('sec_grp')
         s_description = data_utils.rand_name('desc')
-        self.sec_grp = sec_grp_cli.create_security_group(s_name,
-                                                         s_description)
+        self.sec_grp = sec_grp_cli.create_security_group(
+            name=s_name, description=s_description)
         create_rule = sec_grp_cli.create_security_group_rule
         create_rule(self.sec_grp['id'], 'tcp', 22, 22)
         create_rule(self.sec_grp['id'], 'icmp', -1, -1)
diff --git a/tempest/stress/actions/volume_attach_verify.py b/tempest/stress/actions/volume_attach_verify.py
index 3ba2a91..93a443e 100644
--- a/tempest/stress/actions/volume_attach_verify.py
+++ b/tempest/stress/actions/volume_attach_verify.py
@@ -26,7 +26,7 @@
 
     def _create_keypair(self):
         keyname = data_utils.rand_name("key")
-        self.key = self.manager.keypairs_client.create_keypair(keyname)
+        self.key = self.manager.keypairs_client.create_keypair(name=keyname)
 
     def _delete_keypair(self):
         self.manager.keypairs_client.delete_keypair(self.key['name'])
@@ -55,8 +55,8 @@
         sec_grp_cli = self.manager.security_groups_client
         s_name = data_utils.rand_name('sec_grp')
         s_description = data_utils.rand_name('desc')
-        self.sec_grp = sec_grp_cli.create_security_group(s_name,
-                                                         s_description)
+        self.sec_grp = sec_grp_cli.create_security_group(
+            name=s_name, description=s_description)
         create_rule = sec_grp_cli.create_security_group_rule
         create_rule(self.sec_grp['id'], 'tcp', 22, 22)
         create_rule(self.sec_grp['id'], 'icmp', -1, -1)
diff --git a/tempest/test_discover/plugins.py b/tempest/test_discover/plugins.py
index 2701f02..45cd609 100644
--- a/tempest/test_discover/plugins.py
+++ b/tempest/test_discover/plugins.py
@@ -40,6 +40,17 @@
         """
         return
 
+    @abc.abstractmethod
+    def register_opts(self, conf):
+        """Method to add additional configuration options to tempest. This
+        method will be run for the plugin during the register_opts() function
+        in tempest.config
+
+        :param ConfigOpts conf: The conf object that can be used to register
+            additional options on.
+        """
+        return
+
 
 @misc.singleton
 class TempestTestPluginManager(object):
@@ -64,3 +75,7 @@
         for plug in self.ext_plugins:
             load_tests_dict[plug.name] = plug.obj.load_tests()
         return load_tests_dict
+
+    def register_plugin_opts(self, conf):
+        for plug in self.ext_plugins:
+            plug.obj.register_opts(conf)
diff --git a/tempest/tests/cmd/test_javelin.py b/tempest/tests/cmd/test_javelin.py
index f0921d5..3a3e46e 100644
--- a/tempest/tests/cmd/test_javelin.py
+++ b/tempest/tests/cmd/test_javelin.py
@@ -278,8 +278,8 @@
 
         mocked_function = self.fake_client.secgroups.create_security_group
         mocked_function.assert_called_once_with(
-            self.fake_object['name'],
-            self.fake_object['description'])
+            name=self.fake_object['name'],
+            description=self.fake_object['description'])
 
 
 class TestDestroyResources(JavelinUnitTest):
diff --git a/tempest/tests/cmd/test_tempest_init.py b/tempest/tests/cmd/test_tempest_init.py
new file mode 100644
index 0000000..6b5af7e
--- /dev/null
+++ b/tempest/tests/cmd/test_tempest_init.py
@@ -0,0 +1,66 @@
+# Copyright 2015 Hewlett-Packard Development Company, L.P.
+#
+# 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 os
+
+import fixtures
+
+from tempest.cmd import init
+from tempest.tests import base
+
+
+class TestTempestInit(base.TestCase):
+
+    def test_generate_testr_conf(self):
+        # Create fake conf dir
+        conf_dir = self.useFixture(fixtures.TempDir())
+
+        init_cmd = init.TempestInit(None, None)
+        init_cmd.generate_testr_conf(conf_dir.path)
+
+        # Generate expected file contents
+        top_level_path = os.path.dirname(os.path.dirname(init.__file__))
+        discover_path = os.path.join(top_level_path, 'test_discover')
+        testr_conf_file = init.TESTR_CONF % (top_level_path, discover_path)
+
+        conf_path = conf_dir.join('.testr.conf')
+        conf_file = open(conf_path, 'r')
+        self.addCleanup(conf_file.close)
+        self.assertEqual(conf_file.read(), testr_conf_file)
+
+    def test_create_working_dir(self):
+        fake_local_dir = self.useFixture(fixtures.TempDir())
+        fake_local_conf_dir = self.useFixture(fixtures.TempDir())
+        # Create a fake conf file
+        fake_file = fake_local_conf_dir.join('conf_file.conf')
+        open(fake_file, 'w').close()
+        init_cmd = init.TempestInit(None, None)
+        init_cmd.create_working_dir(fake_local_dir.path,
+                                    fake_local_conf_dir.path)
+        # Assert directories are created
+        lock_path = os.path.join(fake_local_dir.path, 'tempest_lock')
+        etc_dir = os.path.join(fake_local_dir.path, 'etc')
+        log_dir = os.path.join(fake_local_dir.path, 'logs')
+        testr_dir = os.path.join(fake_local_dir.path, '.testrepository')
+        self.assertTrue(os.path.isdir(lock_path))
+        self.assertTrue(os.path.isdir(etc_dir))
+        self.assertTrue(os.path.isdir(log_dir))
+        self.assertTrue(os.path.isdir(testr_dir))
+        # Assert file creation
+        fake_file_moved = os.path.join(etc_dir, 'conf_file.conf')
+        local_conf_file = os.path.join(etc_dir, 'tempest.conf')
+        local_testr_conf = os.path.join(fake_local_dir.path, '.testr.conf')
+        self.assertTrue(os.path.isfile(fake_file_moved))
+        self.assertTrue(os.path.isfile(local_conf_file))
+        self.assertTrue(os.path.isfile(local_testr_conf))
diff --git a/tempest/tests/common/test_service_clients.py b/tempest/tests/common/test_service_clients.py
index 695d4a4..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
@@ -115,8 +116,8 @@
             extensions_client.ExtensionsClient,
             fixed_ips_client.FixedIPsClient,
             flavors_client.FlavorsClient,
-            floating_ip_pools_client.FloatingIpPoolsClient,
-            floating_ips_bulk_client.FloatingIpsBulkClient,
+            floating_ip_pools_client.FloatingIPPoolsClient,
+            floating_ips_bulk_client.FloatingIPsBulkClient,
             floating_ips_client.FloatingIPsClient,
             hosts_client.HostsClient,
             hypervisor_client.HypervisorClient,
@@ -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)
diff --git a/tempest/tests/services/compute/test_aggregates_client.py b/tempest/tests/services/compute/test_aggregates_client.py
new file mode 100644
index 0000000..9fe4544
--- /dev/null
+++ b/tempest/tests/services/compute/test_aggregates_client.py
@@ -0,0 +1,47 @@
+# Copyright 2015 NEC Corporation.  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 httplib2
+
+from oslotest import mockpatch
+
+from tempest.services.compute.json import aggregates_client
+from tempest.tests import base
+from tempest.tests import fake_auth_provider
+
+
+class TestAggregatesClient(base.TestCase):
+
+    def setUp(self):
+        super(TestAggregatesClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = aggregates_client.AggregatesClient(
+            fake_auth, 'compute', 'regionOne')
+
+    def _test_list_aggregates(self, bytes_body=False):
+        body = '{"aggregates": []}'
+        if bytes_body:
+            body = body.encode('utf-8')
+        expected = []
+        response = (httplib2.Response({'status': 200}), body)
+        self.useFixture(mockpatch.Patch(
+            'tempest.common.service_client.ServiceClient.get',
+            return_value=response))
+        self.assertEqual(expected, self.client.list_aggregates())
+
+    def test_list_aggregates_with_str_body(self):
+        self._test_list_aggregates()
+
+    def test_list_aggregates_with_bytes_body(self):
+        self._test_list_aggregates(bytes_body=True)
diff --git a/tempest/tests/services/compute/test_keypairs_client.py b/tempest/tests/services/compute/test_keypairs_client.py
new file mode 100644
index 0000000..e79e411
--- /dev/null
+++ b/tempest/tests/services/compute/test_keypairs_client.py
@@ -0,0 +1,47 @@
+# Copyright 2015 NEC Corporation.  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 httplib2
+
+from oslotest import mockpatch
+
+from tempest.services.compute.json import keypairs_client
+from tempest.tests import base
+from tempest.tests import fake_auth_provider
+
+
+class TestKeyPairsClient(base.TestCase):
+
+    def setUp(self):
+        super(TestKeyPairsClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = keypairs_client.KeyPairsClient(
+            fake_auth, 'compute', 'regionOne')
+
+    def _test_list_keypairs(self, bytes_body=False):
+        body = '{"keypairs": []}'
+        if bytes_body:
+            body = body.encode('utf-8')
+        expected = []
+        response = (httplib2.Response({'status': 200}), body)
+        self.useFixture(mockpatch.Patch(
+            'tempest.common.service_client.ServiceClient.get',
+            return_value=response))
+        self.assertEqual(expected, self.client.list_keypairs())
+
+    def test_list_keypairs_with_str_body(self):
+        self._test_list_keypairs()
+
+    def test_list_keypairs_with_bytes_body(self):
+        self._test_list_keypairs(bytes_body=True)
diff --git a/test-requirements.txt b/test-requirements.txt
index 8fcf071..2ea30ec 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -7,7 +7,6 @@
 python-subunit>=0.0.18
 oslosphinx>=2.5.0 # Apache-2.0
 mox>=0.5.3
-mock>=1.1;python_version!='2.6'
-mock==1.0.1;python_version=='2.6'
+mock>=1.2
 coverage>=3.6
-oslotest>=1.7.0 # Apache-2.0
+oslotest>=1.9.0 # Apache-2.0
diff --git a/tox.ini b/tox.ini
index cf7013d..389fee2 100644
--- a/tox.ini
+++ b/tox.ini
@@ -40,6 +40,16 @@
   find . -type f -name "*.pyc" -delete
   bash tools/pretty_tox.sh '{posargs}'
 
+[testenv:all-plugin]
+sitepackages = True
+# 'all' includes slow tests
+setenv = {[tempestenv]setenv}
+         OS_TEST_TIMEOUT=1200
+deps = {[tempestenv]deps}
+commands =
+  find . -type f -name "*.pyc" -delete
+  bash tools/pretty_tox.sh '{posargs}'
+
 [testenv:full]
 sitepackages = {[tempestenv]sitepackages}
 setenv = {[tempestenv]setenv}