Merge "Neutron: Remove get_namespace from API extensions"
diff --git a/doc/source/account_generator.rst b/doc/source/account_generator.rst
new file mode 100644
index 0000000..1c30473
--- /dev/null
+++ b/doc/source/account_generator.rst
@@ -0,0 +1,5 @@
+--------------------------------
+Tempest Test-Account Generator Utility
+--------------------------------
+
+.. automodule:: tempest.cmd.account_generator
\ No newline at end of file
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index eab7487..0805544 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -112,7 +112,7 @@
     available in the file. (if running serially the worker count is 1)
 
     You can check the sample file packaged in tempest for the yaml format
- #. Provide tempest with the location of you accounts.yaml file with the
+ #. Provide tempest with the location of your accounts.yaml file with the
     test_accounts_file option in the auth section
 
  #. Set allow_tenant_isolation = False in the auth group
diff --git a/doc/source/index.rst b/doc/source/index.rst
index cb1c504..f925018 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -45,6 +45,7 @@
 .. toctree::
    :maxdepth: 1
 
+   account_generator
    cleanup
    javelin
 
diff --git a/etc/javelin-resources.yaml.sample b/etc/javelin-resources.yaml.sample
new file mode 100644
index 0000000..fb270a4
--- /dev/null
+++ b/etc/javelin-resources.yaml.sample
@@ -0,0 +1,65 @@
+tenants:
+  - javelin
+  - discuss
+
+users:
+  - name: javelin
+    pass: gungnir
+    tenant: javelin
+  - name: javelin2
+    pass: gungnir2
+    tenant: discuss
+
+secgroups:
+  - name: secgroup1
+    owner: javelin
+    description: SecurityGroup1
+    rules:
+      - 'icmp -1 -1 0.0.0.0/0'
+      - 'tcp 22 22 0.0.0.0/0'
+  - name: secgroup2
+    owner: javelin2
+    description: SecurityGroup2
+    rules:
+      - 'tcp 80 80 0.0.0.0/0'
+
+images:
+  - name: cirros1
+    owner: javelin
+    imgdir: images
+    file: cirros.img
+    container_format: bare
+    disk_format: qcow2
+  - name: cirros2
+    owner: javelin2
+    imgdir: files/images/cirros-0.3.2-x86_64-uec
+    file: cirros-0.3.2-x86_64-blank.img
+    container_format: ami
+    disk_format: ami
+    aki: cirros-0.3.2-x86_64-vmlinuz
+    ari: cirros-0.3.2-x86_64-initrd
+
+networks:
+  - name: network1
+    owner: javelin
+  - name: network2
+    owner: javelin2
+
+subnets:
+  - name: net1-subnet1
+    range: 10.1.0.0/24
+    network: network1
+    owner: javelin
+  - name: net2-subnet2
+    range: 192.168.1.0/24
+    network: network2
+    owner: javelin2
+
+objects:
+  - container: container1
+    name: object1
+    owner: javelin
+    file: /etc/hosts
+    swift_role: Member
+
+telemetry: true
\ No newline at end of file
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index b3aca42..6424f55 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -161,8 +161,9 @@
 # Timeout for Ironic power transitions. (integer value)
 #power_timeout = 60
 
-# Timeout for unprovisioning an Ironic node. (integer value)
-#unprovision_timeout = 60
+# Timeout for unprovisioning an Ironic node. Takes longer since Kilo
+# as Ironic performs an extra step in Node cleaning. (integer value)
+#unprovision_timeout = 300
 
 
 [boto]
@@ -647,6 +648,10 @@
 # Is the v1 image API enabled (boolean value)
 #api_v1 = true
 
+# Is the deactivate-image feature enabled. The feature has been
+# integrated since Kilo. (boolean value)
+#deactivate_image = false
+
 
 [input-scenario]
 
diff --git a/requirements.txt b/requirements.txt
index 7fe8858..cb0031d 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,17 +4,17 @@
 pbr>=0.11,<2.0
 anyjson>=0.3.3
 httplib2>=0.7.5
-jsonschema>=2.0.0,<3.0.0
+jsonschema>=2.0.0,<3.0.0,!=2.5.0
 testtools>=0.9.36,!=1.2.0
 boto>=2.32.1
 paramiko>=1.13.0
 netaddr>=0.7.12
 testrepository>=0.0.18
 pyOpenSSL>=0.11
-oslo.concurrency>=1.8.0         # Apache-2.0
+oslo.concurrency>=2.0.0         # Apache-2.0
 oslo.config>=1.11.0  # Apache-2.0
 oslo.i18n>=1.5.0  # Apache-2.0
-oslo.log>=1.0.0  # Apache-2.0
+oslo.log>=1.2.0  # Apache-2.0
 oslo.serialization>=1.4.0               # Apache-2.0
 oslo.utils>=1.4.0                       # Apache-2.0
 six>=1.9.0
diff --git a/tempest/api/compute/admin/test_fixed_ips.py b/tempest/api/compute/admin/test_fixed_ips.py
index eec4688..a65fda6 100644
--- a/tempest/api/compute/admin/test_fixed_ips.py
+++ b/tempest/api/compute/admin/test_fixed_ips.py
@@ -50,7 +50,7 @@
     @test.idempotent_id('16b7d848-2f7c-4709-85a3-2dfb4576cc52')
     @test.services('network')
     def test_list_fixed_ip_details(self):
-        fixed_ip = self.client.get_fixed_ip_details(self.ip)
+        fixed_ip = self.client.show_fixed_ip(self.ip)
         self.assertEqual(fixed_ip['address'], self.ip)
 
     @test.idempotent_id('5485077b-7e46-4cec-b402-91dc3173433b')
diff --git a/tempest/api/compute/admin/test_fixed_ips_negative.py b/tempest/api/compute/admin/test_fixed_ips_negative.py
index ac8a60d..35c719d 100644
--- a/tempest/api/compute/admin/test_fixed_ips_negative.py
+++ b/tempest/api/compute/admin/test_fixed_ips_negative.py
@@ -54,7 +54,7 @@
     @test.services('network')
     def test_list_fixed_ip_details_with_non_admin_user(self):
         self.assertRaises(lib_exc.Forbidden,
-                          self.non_admin_client.get_fixed_ip_details, self.ip)
+                          self.non_admin_client.show_fixed_ip, self.ip)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('ce60042c-fa60-4836-8d43-1c8e3359dc47')
diff --git a/tempest/api/compute/admin/test_flavors.py b/tempest/api/compute/admin/test_flavors.py
index 8aab8da..f12784e 100644
--- a/tempest/api/compute/admin/test_flavors.py
+++ b/tempest/api/compute/admin/test_flavors.py
@@ -82,7 +82,7 @@
         self.assertEqual(flavor['os-flavor-access:is_public'], True)
 
         # Verify flavor is retrieved
-        flavor = self.client.get_flavor_details(flavor['id'])
+        flavor = self.client.show_flavor(flavor['id'])
         self.assertEqual(flavor['name'], flavor_name)
 
         return flavor['id']
@@ -160,7 +160,7 @@
         verify_flavor_response_extension(flavor)
 
         # Verify flavor is retrieved
-        flavor = self.client.get_flavor_details(new_flavor_id)
+        flavor = self.client.show_flavor(new_flavor_id)
         self.assertEqual(flavor['name'], flavor_name)
         verify_flavor_response_extension(flavor)
 
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs.py b/tempest/api/compute/admin/test_flavors_extra_specs.py
index 2ed1e35..a14a61f 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs.py
@@ -75,7 +75,7 @@
             self.client.set_flavor_extra_spec(self.flavor['id'], specs)
         self.assertEqual(set_body, specs)
         # GET extra specs and verify
-        get_body = self.client.get_flavor_extra_spec(self.flavor['id'])
+        get_body = self.client.list_flavor_extra_specs(self.flavor['id'])
         self.assertEqual(get_body, specs)
 
         # UPDATE the value of the extra specs key1
@@ -87,7 +87,7 @@
 
         # GET extra specs and verify the value of the key2
         # is the same as before
-        get_body = self.client.get_flavor_extra_spec(self.flavor['id'])
+        get_body = self.client.list_flavor_extra_specs(self.flavor['id'])
         self.assertEqual(get_body, {"key1": "value", "key2": "value2"})
 
         # UNSET extra specs that were set in this test
@@ -98,7 +98,7 @@
     def test_flavor_non_admin_get_all_keys(self):
         specs = {"key1": "value1", "key2": "value2"}
         self.client.set_flavor_extra_spec(self.flavor['id'], specs)
-        body = self.flavors_client.get_flavor_extra_spec(self.flavor['id'])
+        body = self.flavors_client.list_flavor_extra_specs(self.flavor['id'])
 
         for key in specs:
             self.assertEqual(body[key], specs[key])
@@ -109,7 +109,7 @@
         body = self.client.set_flavor_extra_spec(self.flavor['id'], specs)
         self.assertEqual(body['key1'], 'value1')
         self.assertIn('key2', body)
-        body = self.flavors_client.get_flavor_extra_spec_with_key(
+        body = self.flavors_client.show_flavor_extra_spec(
             self.flavor['id'], 'key1')
         self.assertEqual(body['key1'], 'value1')
         self.assertNotIn('key2', body)
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 df592dd..ba05c7f 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
@@ -115,7 +115,7 @@
     @test.idempotent_id('329a7be3-54b2-48be-8052-bf2ce4afd898')
     def test_flavor_get_nonexistent_key(self):
         self.assertRaises(lib_exc.NotFound,
-                          self.flavors_client.get_flavor_extra_spec_with_key,
+                          self.flavors_client.show_flavor_extra_spec,
                           self.flavor['id'],
                           "nonexistent_key")
 
diff --git a/tempest/api/compute/admin/test_live_migration.py b/tempest/api/compute/admin/test_live_migration.py
index d3b1f5e..a03439a 100644
--- a/tempest/api/compute/admin/test_live_migration.py
+++ b/tempest/api/compute/admin/test_live_migration.py
@@ -78,7 +78,7 @@
             return server_id
 
     def _volume_clean_up(self, server_id, volume_id):
-        body = self.volumes_client.get_volume(volume_id)
+        body = self.volumes_client.show_volume(volume_id)
         if body['status'] == 'in-use':
             self.servers_client.detach_volume(server_id, volume_id)
             self.volumes_client.wait_for_volume_status(volume_id, 'available')
diff --git a/tempest/api/compute/admin/test_servers_negative.py b/tempest/api/compute/admin/test_servers_negative.py
index 7f78ce8..d325bd7 100644
--- a/tempest/api/compute/admin/test_servers_negative.py
+++ b/tempest/api/compute/admin/test_servers_negative.py
@@ -53,7 +53,7 @@
         flavor_id = data_utils.rand_int_id(start=1000)
         while True:
             try:
-                self.flavors_client.get_flavor_details(flavor_id)
+                self.flavors_client.show_flavor(flavor_id)
             except lib_exc.NotFound:
                 break
             flavor_id = data_utils.rand_int_id(start=1000)
diff --git a/tempest/api/compute/flavors/test_flavors.py b/tempest/api/compute/flavors/test_flavors.py
index c1c87f9..251f4ec 100644
--- a/tempest/api/compute/flavors/test_flavors.py
+++ b/tempest/api/compute/flavors/test_flavors.py
@@ -33,7 +33,7 @@
     def test_list_flavors(self):
         # List of all flavors should contain the expected flavor
         flavors = self.client.list_flavors()
-        flavor = self.client.get_flavor_details(self.flavor_ref)
+        flavor = self.client.show_flavor(self.flavor_ref)
         flavor_min_detail = {'id': flavor['id'], 'links': flavor['links'],
                              'name': flavor['name']}
         self.assertIn(flavor_min_detail, flavors)
@@ -42,14 +42,14 @@
     def test_list_flavors_with_detail(self):
         # Detailed list of all flavors should contain the expected flavor
         flavors = self.client.list_flavors_with_detail()
-        flavor = self.client.get_flavor_details(self.flavor_ref)
+        flavor = self.client.show_flavor(self.flavor_ref)
         self.assertIn(flavor, flavors)
 
     @test.attr(type='smoke')
     @test.idempotent_id('1f12046b-753d-40d2-abb6-d8eb8b30cb2f')
     def test_get_flavor(self):
         # The expected flavor details should be returned
-        flavor = self.client.get_flavor_details(self.flavor_ref)
+        flavor = self.client.show_flavor(self.flavor_ref)
         self.assertEqual(self.flavor_ref, flavor['id'])
 
     @test.idempotent_id('8d7691b3-6ed4-411a-abc9-2839a765adab')
@@ -69,7 +69,7 @@
     @test.idempotent_id('e800f879-9828-4bd0-8eae-4f17189951fb')
     def test_list_flavors_using_marker(self):
         # The list of flavors should start from the provided marker
-        flavor = self.client.get_flavor_details(self.flavor_ref)
+        flavor = self.client.show_flavor(self.flavor_ref)
         flavor_id = flavor['id']
 
         params = {'marker': flavor_id}
@@ -80,7 +80,7 @@
     @test.idempotent_id('6db2f0c0-ddee-4162-9c84-0703d3dd1107')
     def test_list_flavors_detailed_using_marker(self):
         # The list of flavors should start from the provided marker
-        flavor = self.client.get_flavor_details(self.flavor_ref)
+        flavor = self.client.show_flavor(self.flavor_ref)
         flavor_id = flavor['id']
 
         params = {'marker': flavor_id}
@@ -91,7 +91,7 @@
     @test.idempotent_id('3df2743e-3034-4e57-a4cb-b6527f6eac79')
     def test_list_flavors_detailed_filter_by_min_disk(self):
         # The detailed list of flavors should be filtered by disk space
-        flavor = self.client.get_flavor_details(self.flavor_ref)
+        flavor = self.client.show_flavor(self.flavor_ref)
         flavor_id = flavor['id']
 
         params = {self._min_disk: flavor['disk'] + 1}
@@ -101,7 +101,7 @@
     @test.idempotent_id('09fe7509-b4ee-4b34-bf8b-39532dc47292')
     def test_list_flavors_detailed_filter_by_min_ram(self):
         # The detailed list of flavors should be filtered by RAM
-        flavor = self.client.get_flavor_details(self.flavor_ref)
+        flavor = self.client.show_flavor(self.flavor_ref)
         flavor_id = flavor['id']
 
         params = {self._min_ram: flavor['ram'] + 1}
@@ -111,7 +111,7 @@
     @test.idempotent_id('10645a4d-96f5-443f-831b-730711e11dd4')
     def test_list_flavors_filter_by_min_disk(self):
         # The list of flavors should be filtered by disk space
-        flavor = self.client.get_flavor_details(self.flavor_ref)
+        flavor = self.client.show_flavor(self.flavor_ref)
         flavor_id = flavor['id']
 
         params = {self._min_disk: flavor['disk'] + 1}
@@ -121,7 +121,7 @@
     @test.idempotent_id('935cf550-e7c8-4da6-8002-00f92d5edfaa')
     def test_list_flavors_filter_by_min_ram(self):
         # The list of flavors should be filtered by RAM
-        flavor = self.client.get_flavor_details(self.flavor_ref)
+        flavor = self.client.show_flavor(self.flavor_ref)
         flavor_id = flavor['id']
 
         params = {self._min_ram: flavor['ram'] + 1}
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions.py b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
index 5f438fb..093f16b 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
@@ -67,7 +67,7 @@
         self.addCleanup(self.client.delete_floating_ip,
                         floating_ip_id_allocated)
         floating_ip_details = \
-            self.client.get_floating_ip_details(floating_ip_id_allocated)
+            self.client.show_floating_ip(floating_ip_id_allocated)
         # Checking if the details of allocated IP is in list of floating IP
         body = self.client.list_floating_ips()
         self.assertIn(floating_ip_details, body)
@@ -97,7 +97,7 @@
             self.server_id)
 
         # Check instance_id in the floating_ip body
-        body = self.client.get_floating_ip_details(self.floating_ip_id)
+        body = self.client.show_floating_ip(self.floating_ip_id)
         self.assertEqual(self.server_id, body['instance_id'])
 
         # Disassociation of floating IP that was associated in this method
diff --git a/tempest/api/compute/floating_ips/test_list_floating_ips.py b/tempest/api/compute/floating_ips/test_list_floating_ips.py
index 62bc92c..ad52b8c 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips.py
@@ -63,7 +63,7 @@
         floating_ip_instance_id = body['instance_id']
         floating_ip_ip = body['ip']
         floating_ip_fixed_ip = body['fixed_ip']
-        body = self.client.get_floating_ip_details(floating_ip_id)
+        body = self.client.show_floating_ip(floating_ip_id)
         # Comparing the details of floating IP
         self.assertEqual(floating_ip_instance_id,
                          body['instance_id'])
diff --git a/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py b/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
index e1e30a4..05d3d05 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
@@ -44,4 +44,4 @@
         else:
             non_exist_id = data_utils.rand_int_id(start=999)
         self.assertRaises(lib_exc.NotFound,
-                          self.client.get_floating_ip_details, non_exist_id)
+                          self.client.show_floating_ip, non_exist_id)
diff --git a/tempest/api/compute/images/test_images_oneserver.py b/tempest/api/compute/images/test_images_oneserver.py
index 3771a43..1fd165b 100644
--- a/tempest/api/compute/images/test_images_oneserver.py
+++ b/tempest/api/compute/images/test_images_oneserver.py
@@ -70,7 +70,7 @@
         cls.server_id = server['id']
 
     def _get_default_flavor_disk_size(self, flavor_id):
-        flavor = self.flavors_client.get_flavor_details(flavor_id)
+        flavor = self.flavors_client.show_flavor(flavor_id)
         return flavor['disk']
 
     @test.idempotent_id('3731d080-d4c5-4872-b41a-64d0d0021314')
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 2cf2e28..06e073d 100644
--- a/tempest/api/compute/security_groups/test_security_groups_negative.py
+++ b/tempest/api/compute/security_groups/test_security_groups_negative.py
@@ -89,15 +89,10 @@
     @test.idempotent_id('777b6f14-aca9-4758-9e84-38783cfa58bc')
     @test.services('network')
     def test_security_group_create_with_invalid_group_description(self):
-        # Negative test:Security Group should not be created with description
-        # as an empty string/with white spaces/chars more than 255
+        # Negative test: Security Group should not be created with description
+        # longer than 255 chars. Empty description is allowed by the API
+        # reference, however.
         s_name = data_utils.rand_name('securitygroup')
-        # Create Security Group with empty string as description
-        self.assertRaises(lib_exc.BadRequest,
-                          self.client.create_security_group, s_name, "")
-        # Create Security Group with white space in description
-        self.assertRaises(lib_exc.BadRequest,
-                          self.client.create_security_group, s_name, " ")
         # Create Security Group with group description longer than 255 chars
         s_description = 'description-'.ljust(260, '0')
         self.assertRaises(lib_exc.BadRequest,
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index 9012d3d..16b1597 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -100,7 +100,7 @@
     def test_verify_created_server_vcpus(self):
         # Verify that the number of vcpus reported by the instance matches
         # the amount stated by the flavor
-        flavor = self.flavors_client.get_flavor_details(self.flavor_ref)
+        flavor = self.flavors_client.show_flavor(self.flavor_ref)
         linux_client = remote_client.RemoteClient(self.server, self.ssh_user,
                                                   self.password)
         self.assertEqual(flavor['vcpus'], linux_client.get_number_of_vcpus())
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index d7607ab..7a91cab 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -14,7 +14,6 @@
 #    under the License.
 
 from tempest_lib.common.utils import data_utils
-from tempest_lib import decorators
 from tempest_lib import exceptions as lib_exc
 
 from tempest.api.compute import base
@@ -290,8 +289,6 @@
         self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
         self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
 
-    @decorators.skip_because(bug="1182883",
-                             condition=CONF.service_available.neutron)
     @test.idempotent_id('a905e287-c35e-42f2-b132-d02b09f3654a')
     def test_list_servers_filtered_by_ip_regex(self):
         # Filter servers by regex ip
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index c2ed0ce..10b08a1 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -42,6 +42,10 @@
         # Check if the server is in a clean state after test
         try:
             self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+        except lib_exc.NotFound:
+            # The server was deleted by previous test, create a new one
+            server = self.create_test_server(wait_until='ACTIVE')
+            self.__class__.server_id = server['id']
         except Exception:
             # Rebuild server if something happened to it during a test
             self.__class__.server_id = self.rebuild_server(self.server_id)
@@ -287,8 +291,9 @@
             'backup_type': "daily",
             'instance_uuid': self.server_id,
         }
-        image_list = self.os.image_client.image_list_detail(
-            properties,
+        image_list = self.os.image_client.list_images(
+            detail=True,
+            properties=properties,
             status='active',
             sort_key='created_at',
             sort_dir='asc')
@@ -310,8 +315,9 @@
         self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
         self.os.image_client.wait_for_resource_deletion(image1_id)
         oldest_backup_exist = False
-        image_list = self.os.image_client.image_list_detail(
-            properties,
+        image_list = self.os.image_client.list_images(
+            detail=True,
+            properties=properties,
             status='active',
             sort_key='created_at',
             sort_dir='asc')
diff --git a/tempest/api/identity/admin/v2/test_users.py b/tempest/api/identity/admin/v2/test_users.py
index bcac853..8eac80c 100644
--- a/tempest/api/identity/admin/v2/test_users.py
+++ b/tempest/api/identity/admin/v2/test_users.py
@@ -50,7 +50,7 @@
                                        self.alt_email, enabled=False)
         self.data.users.append(user)
         self.assertEqual(name, user['name'])
-        self.assertEqual('false', str(user['enabled']).lower())
+        self.assertEqual(False, user['enabled'])
         self.assertEqual(self.alt_email, user['email'])
 
     @test.idempotent_id('39d05857-e8a5-4ed4-ba83-0b52d3ab97ee')
@@ -71,13 +71,13 @@
                                               enabled=False)
         self.assertEqual(u_name2, update_user['name'])
         self.assertEqual(u_email2, update_user['email'])
-        self.assertEqual('false', str(update_user['enabled']).lower())
+        self.assertEqual(False, update_user['enabled'])
         # GET by id after updating
         updated_user = self.client.get_user(user['id'])
         # Assert response body of GET after updating
         self.assertEqual(u_name2, updated_user['name'])
         self.assertEqual(u_email2, updated_user['email'])
-        self.assertEqual('false', str(updated_user['enabled']).lower())
+        self.assertEqual(False, update_user['enabled'])
 
     @test.idempotent_id('29ed26f4-a74e-4425-9a85-fdb49fa269d2')
     def test_delete_user(self):
diff --git a/tempest/api/identity/admin/v3/test_domains.py b/tempest/api/identity/admin/v3/test_domains.py
index b775e91..b1a9d3b 100644
--- a/tempest/api/identity/admin/v3/test_domains.py
+++ b/tempest/api/identity/admin/v3/test_domains.py
@@ -79,12 +79,12 @@
         self.assertIsNotNone(updated_domain['id'])
         self.assertEqual(new_name, updated_domain['name'])
         self.assertEqual(new_desc, updated_domain['description'])
-        self.assertEqual('true', str(updated_domain['enabled']).lower())
+        self.assertEqual(True, updated_domain['enabled'])
 
         fetched_domain = self.client.get_domain(domain['id'])
         self.assertEqual(new_name, fetched_domain['name'])
         self.assertEqual(new_desc, fetched_domain['description'])
-        self.assertEqual('true', str(fetched_domain['enabled']).lower())
+        self.assertEqual(True, fetched_domain['enabled'])
 
     @test.idempotent_id('036df86e-bb5d-42c0-a7c2-66b9db3a6046')
     def test_create_domain_with_disabled_status(self):
diff --git a/tempest/api/identity/admin/v3/test_endpoints.py b/tempest/api/identity/admin/v3/test_endpoints.py
index 1672d47..9ca10a4 100644
--- a/tempest/api/identity/admin/v3/test_endpoints.py
+++ b/tempest/api/identity/admin/v3/test_endpoints.py
@@ -126,4 +126,4 @@
         self.assertEqual(interface2, endpoint['interface'])
         self.assertEqual(url2, endpoint['url'])
         self.assertEqual(region2, endpoint['region'])
-        self.assertEqual('false', str(endpoint['enabled']).lower())
+        self.assertEqual(False, endpoint['enabled'])
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index 7fe369e..c2456c4 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -53,7 +53,7 @@
         self.assertEqual(project['id'],
                          update_user['project_id'])
         self.assertEqual(u_email2, update_user['email'])
-        self.assertEqual('false', str(update_user['enabled']).lower())
+        self.assertEqual(False, update_user['enabled'])
         # GET by id after updation
         new_user_get = self.client.get_user(user['id'])
         # Assert response body of GET after updation
@@ -62,7 +62,7 @@
         self.assertEqual(project['id'],
                          new_user_get['project_id'])
         self.assertEqual(u_email2, new_user_get['email'])
-        self.assertEqual('false', str(new_user_get['enabled']).lower())
+        self.assertEqual(False, new_user_get['enabled'])
 
     @test.idempotent_id('2d223a0e-e457-4a70-9fb1-febe027a0ff9')
     def test_update_user_password(self):
diff --git a/tempest/api/identity/v2/test_api_discovery.py b/tempest/api/identity/v2/test_api_discovery.py
new file mode 100644
index 0000000..8132ee1
--- /dev/null
+++ b/tempest/api/identity/v2/test_api_discovery.py
@@ -0,0 +1,57 @@
+# Copyright 2015 OpenStack Foundation.
+# Copyright 2015, Red Hat, 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
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.identity import base
+from tempest import test
+
+
+class TestApiDiscovery(base.BaseIdentityV2Test):
+    """Tests for API discovery features."""
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('ea889a68-a15f-4166-bfb1-c12456eae853')
+    def test_api_version_resources(self):
+        descr = self.non_admin_client.get_api_description()
+        expected_resources = ('id', 'links', 'media-types', 'status',
+                              'updated')
+
+        keys = descr.keys()
+        for res in expected_resources:
+            self.assertIn(res, keys)
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('007a0be0-78fe-4fdb-bbee-e9216cc17bb2')
+    def test_api_media_types(self):
+        descr = self.non_admin_client.get_api_description()
+        # Get MIME type bases and descriptions
+        media_types = [(media_type['base'], media_type['type']) for
+                       media_type in descr['media-types']]
+        # These are supported for API version 2
+        supported_types = [('application/json',
+                            'application/vnd.openstack.identity-v2.0+json')]
+
+        # Check if supported types exist in response body
+        for s_type in supported_types:
+            self.assertIn(s_type, media_types)
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('77fd6be0-8801-48e6-b9bf-38cdd2f253ec')
+    def test_api_version_statuses(self):
+        descr = self.non_admin_client.get_api_description()
+        status = descr['status'].lower()
+        supported_statuses = ['current', 'stable', 'experimental',
+                              'supported', 'deprecated']
+
+        self.assertIn(status, supported_statuses)
diff --git a/tempest/api/identity/v3/test_api_discovery.py b/tempest/api/identity/v3/test_api_discovery.py
new file mode 100644
index 0000000..2ec8ad8
--- /dev/null
+++ b/tempest/api/identity/v3/test_api_discovery.py
@@ -0,0 +1,57 @@
+# Copyright 2015 OpenStack Foundation.
+# Copyright 2015, Red Hat, 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
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.identity import base
+from tempest import test
+
+
+class TestApiDiscovery(base.BaseIdentityV3Test):
+    """Tests for API discovery features."""
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('b9232f5e-d9e5-4d97-b96c-28d3db4de1bd')
+    def test_api_version_resources(self):
+        descr = self.non_admin_client.get_api_description()
+        expected_resources = ('id', 'links', 'media-types', 'status',
+                              'updated')
+
+        keys = descr.keys()
+        for res in expected_resources:
+            self.assertIn(res, keys)
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('657c1970-4722-4189-8831-7325f3bc4265')
+    def test_api_media_types(self):
+        descr = self.non_admin_client.get_api_description()
+        # Get MIME type bases and descriptions
+        media_types = [(media_type['base'], media_type['type']) for
+                       media_type in descr['media-types']]
+        # These are supported for API version 2
+        supported_types = [('application/json',
+                            'application/vnd.openstack.identity-v3+json')]
+
+        # Check if supported types exist in response body
+        for s_type in supported_types:
+            self.assertIn(s_type, media_types)
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('8879a470-abfb-47bb-bb8d-5a7fd279ad1e')
+    def test_api_version_statuses(self):
+        descr = self.non_admin_client.get_api_description()
+        status = descr['status'].lower()
+        supported_statuses = ['current', 'stable', 'experimental',
+                              'supported', 'deprecated']
+
+        self.assertIn(status, supported_statuses)
diff --git a/tempest/api/image/admin/__init__.py b/tempest/api/image/admin/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api/image/admin/__init__.py
diff --git a/tempest/api/image/admin/v2/__init__.py b/tempest/api/image/admin/v2/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api/image/admin/v2/__init__.py
diff --git a/tempest/api/image/admin/v2/test_images.py b/tempest/api/image/admin/v2/test_images.py
new file mode 100644
index 0000000..83efc7d
--- /dev/null
+++ b/tempest/api/image/admin/v2/test_images.py
@@ -0,0 +1,55 @@
+# Copyright 2015 Red Hat, Inc.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from six import moves
+from tempest_lib.common.utils import data_utils
+import testtools
+
+from tempest.api.image import base
+from tempest import config
+from tempest import test
+
+
+CONF = config.CONF
+
+
+class BasicAdminOperationsImagesTest(base.BaseV2ImageAdminTest):
+
+    """
+    Here we test admin operations of images
+    """
+    @testtools.skipUnless(CONF.image_feature_enabled.deactivate_image,
+                          'deactivate-image is not available.')
+    @test.idempotent_id('951ebe01-969f-4ea9-9898-8a3f1f442ab0')
+    def test_admin_deactivate_reactivate_image(self):
+        # Create image by non-admin tenant
+        image_name = data_utils.rand_name('image')
+        body = self.client.create_image(name=image_name,
+                                        container_format='bare',
+                                        disk_format='raw',
+                                        visibility='private')
+        image_id = body['id']
+        self.addCleanup(self.client.delete_image, image_id)
+        # upload an image file
+        image_file = moves.cStringIO(data_utils.random_bytes())
+        self.client.store_image(image_id, image_file)
+        # deactivate image
+        self.admin_client.deactivate_image(image_id)
+        body = self.client.show_image(image_id)
+        self.assertEqual("deactivated", body['status'])
+        # reactivate image
+        self.admin_client.reactivate_image(image_id)
+        body = self.client.show_image(image_id)
+        self.assertEqual("active", body['status'])
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index 00959d9..dc38cab 100644
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -158,3 +158,23 @@
         image_id = image['id']
         self.addCleanup(self.os_img_client.delete_image, image_id)
         return image_id
+
+
+class BaseV1ImageAdminTest(BaseImageTest):
+    credentials = ['admin', 'primary']
+
+    @classmethod
+    def setup_clients(cls):
+        super(BaseV1ImageAdminTest, cls).setup_clients()
+        cls.client = cls.os.image_client
+        cls.admin_client = cls.os_adm.image_client
+
+
+class BaseV2ImageAdminTest(BaseImageTest):
+    credentials = ['admin', 'primary']
+
+    @classmethod
+    def setup_clients(cls):
+        super(BaseV2ImageAdminTest, cls).setup_clients()
+        cls.client = cls.os.image_client_v2
+        cls.admin_client = cls.os_adm.image_client_v2
diff --git a/tempest/api/image/v1/test_image_members.py b/tempest/api/image/v1/test_image_members.py
index 4969858..eb6969b 100644
--- a/tempest/api/image/v1/test_image_members.py
+++ b/tempest/api/image/v1/test_image_members.py
@@ -36,7 +36,7 @@
         self.client.add_member(self.alt_tenant_id, image)
         share_image = self._create_image()
         self.client.add_member(self.alt_tenant_id, share_image)
-        body = self.client.get_shared_images(self.alt_tenant_id)
+        body = self.client.list_shared_images(self.alt_tenant_id)
         images = body['shared_images']
         images = map(lambda x: x['image_id'], images)
         self.assertIn(share_image, images)
diff --git a/tempest/api/image/v1/test_images.py b/tempest/api/image/v1/test_images.py
index 6c25c93..3f71fcb 100644
--- a/tempest/api/image/v1/test_images.py
+++ b/tempest/api/image/v1/test_images.py
@@ -211,9 +211,10 @@
 
     @test.idempotent_id('e5dc26d9-9aa2-48dd-bda5-748e1445da98')
     def test_index_status_active_detail(self):
-        images_list = self.client.image_list_detail(status='active',
-                                                    sort_key='size',
-                                                    sort_dir='desc')
+        images_list = self.client.list_images(detail=True,
+                                              status='active',
+                                              sort_key='size',
+                                              sort_dir='desc')
         top_size = images_list[0]['size']  # We have non-zero sized images
         for image in images_list:
             size = image['size']
@@ -223,7 +224,8 @@
 
     @test.idempotent_id('097af10a-bae8-4342-bff4-edf89969ed2a')
     def test_index_name(self):
-        images_list = self.client.image_list_detail(
+        images_list = self.client.list_images(
+            detail=True,
             name='New Remote Image dup')
         result_set = set(map(lambda x: x['id'], images_list))
         for image in images_list:
diff --git a/tempest/api/image/v2/test_images_member.py b/tempest/api/image/v2/test_images_member.py
index 07c2073..eb6ffeb 100644
--- a/tempest/api/image/v2/test_images_member.py
+++ b/tempest/api/image/v2/test_images_member.py
@@ -19,15 +19,15 @@
     @test.idempotent_id('5934c6ea-27dc-4d6e-9421-eeb5e045494a')
     def test_image_share_accept(self):
         image_id = self._create_image()
-        member = self.os_img_client.add_member(image_id,
-                                               self.alt_tenant_id)
+        member = self.os_img_client.add_image_member(image_id,
+                                                     self.alt_tenant_id)
         self.assertEqual(member['member_id'], self.alt_tenant_id)
         self.assertEqual(member['image_id'], image_id)
         self.assertEqual(member['status'], 'pending')
         self.assertNotIn(image_id, self._list_image_ids_as_alt())
-        self.alt_img_client.update_member_status(image_id,
-                                                 self.alt_tenant_id,
-                                                 'accepted')
+        self.alt_img_client.update_image_member(image_id,
+                                                self.alt_tenant_id,
+                                                {'status': 'accepted'})
         self.assertIn(image_id, self._list_image_ids_as_alt())
         body = self.os_img_client.list_image_members(image_id)
         members = body['members']
@@ -40,29 +40,29 @@
     @test.idempotent_id('d9e83e5f-3524-4b38-a900-22abcb26e90e')
     def test_image_share_reject(self):
         image_id = self._create_image()
-        member = self.os_img_client.add_member(image_id,
-                                               self.alt_tenant_id)
+        member = self.os_img_client.add_image_member(image_id,
+                                                     self.alt_tenant_id)
         self.assertEqual(member['member_id'], self.alt_tenant_id)
         self.assertEqual(member['image_id'], image_id)
         self.assertEqual(member['status'], 'pending')
         self.assertNotIn(image_id, self._list_image_ids_as_alt())
-        self.alt_img_client.update_member_status(image_id,
-                                                 self.alt_tenant_id,
-                                                 'rejected')
+        self.alt_img_client.update_image_member(image_id,
+                                                self.alt_tenant_id,
+                                                {'status': 'rejected'})
         self.assertNotIn(image_id, self._list_image_ids_as_alt())
 
     @test.idempotent_id('a6ee18b9-4378-465e-9ad9-9a6de58a3287')
     def test_get_image_member(self):
         image_id = self._create_image()
-        self.os_img_client.add_member(image_id,
-                                      self.alt_tenant_id)
-        self.alt_img_client.update_member_status(image_id,
-                                                 self.alt_tenant_id,
-                                                 'accepted')
+        self.os_img_client.add_image_member(image_id,
+                                            self.alt_tenant_id)
+        self.alt_img_client.update_image_member(image_id,
+                                                self.alt_tenant_id,
+                                                {'status': 'accepted'})
 
         self.assertIn(image_id, self._list_image_ids_as_alt())
-        member = self.os_img_client.get_member(image_id,
-                                               self.alt_tenant_id)
+        member = self.os_img_client.show_image_member(image_id,
+                                                      self.alt_tenant_id)
         self.assertEqual(self.alt_tenant_id, member['member_id'])
         self.assertEqual(image_id, member['image_id'])
         self.assertEqual('accepted', member['status'])
@@ -70,14 +70,14 @@
     @test.idempotent_id('72989bc7-2268-48ed-af22-8821e835c914')
     def test_remove_image_member(self):
         image_id = self._create_image()
-        self.os_img_client.add_member(image_id,
-                                      self.alt_tenant_id)
-        self.alt_img_client.update_member_status(image_id,
-                                                 self.alt_tenant_id,
-                                                 'accepted')
+        self.os_img_client.add_image_member(image_id,
+                                            self.alt_tenant_id)
+        self.alt_img_client.update_image_member(image_id,
+                                                self.alt_tenant_id,
+                                                {'status': 'accepted'})
 
         self.assertIn(image_id, self._list_image_ids_as_alt())
-        self.os_img_client.remove_member(image_id, self.alt_tenant_id)
+        self.os_img_client.remove_image_member(image_id, self.alt_tenant_id)
         self.assertNotIn(image_id, self._list_image_ids_as_alt())
 
     @test.idempotent_id('634dcc3f-f6e2-4409-b8fd-354a0bb25d83')
diff --git a/tempest/api/image/v2/test_images_member_negative.py b/tempest/api/image/v2/test_images_member_negative.py
index d95e5c1..ae8913c 100644
--- a/tempest/api/image/v2/test_images_member_negative.py
+++ b/tempest/api/image/v2/test_images_member_negative.py
@@ -22,22 +22,23 @@
     @test.idempotent_id('b79efb37-820d-4cf0-b54c-308b00cf842c')
     def test_image_share_invalid_status(self):
         image_id = self._create_image()
-        member = self.os_img_client.add_member(image_id,
-                                               self.alt_tenant_id)
+        member = self.os_img_client.add_image_member(image_id,
+                                                     self.alt_tenant_id)
         self.assertEqual(member['status'], 'pending')
         self.assertRaises(lib_exc.BadRequest,
-                          self.alt_img_client.update_member_status,
-                          image_id, self.alt_tenant_id, 'notavalidstatus')
+                          self.alt_img_client.update_image_member,
+                          image_id, self.alt_tenant_id,
+                          {'status': 'notavalidstatus'})
 
     @test.attr(type=['negative'])
     @test.idempotent_id('27002f74-109e-4a37-acd0-f91cd4597967')
     def test_image_share_owner_cannot_accept(self):
         image_id = self._create_image()
-        member = self.os_img_client.add_member(image_id,
-                                               self.alt_tenant_id)
+        member = self.os_img_client.add_image_member(image_id,
+                                                     self.alt_tenant_id)
         self.assertEqual(member['status'], 'pending')
         self.assertNotIn(image_id, self._list_image_ids_as_alt())
         self.assertRaises(lib_exc.Forbidden,
-                          self.os_img_client.update_member_status,
-                          image_id, self.alt_tenant_id, 'accepted')
+                          self.os_img_client.update_image_member,
+                          image_id, self.alt_tenant_id, {'status': 'accepted'})
         self.assertNotIn(image_id, self._list_image_ids_as_alt())
diff --git a/tempest/api/network/admin/test_l3_agent_scheduler.py b/tempest/api/network/admin/test_l3_agent_scheduler.py
index 160cc06..2ff8897 100644
--- a/tempest/api/network/admin/test_l3_agent_scheduler.py
+++ b/tempest/api/network/admin/test_l3_agent_scheduler.py
@@ -72,15 +72,22 @@
         # query and setup steps are only required if the extension is available
         # and only if the router's default type is distributed.
         if test.is_extension_enabled('dvr', 'network'):
-            is_dvr_router = cls.admin_client.show_router(
+            cls.is_dvr_router = cls.admin_client.show_router(
                 cls.router['id'])['router'].get('distributed', False)
-            if is_dvr_router:
+            if cls.is_dvr_router:
                 cls.network = cls.create_network()
-                cls.create_subnet(cls.network)
+                cls.subnet = cls.create_subnet(cls.network)
                 cls.port = cls.create_port(cls.network)
                 cls.client.add_router_interface_with_port_id(
                     cls.router['id'], cls.port['id'])
 
+    @classmethod
+    def resource_cleanup(cls):
+        if cls.is_dvr_router:
+            cls.client.remove_router_interface_with_port_id(
+                cls.router['id'], cls.port['id'])
+        super(L3AgentSchedulerTestJSON, cls).resource_cleanup()
+
     @test.idempotent_id('b7ce6e89-e837-4ded-9b78-9ed3c9c6a45a')
     def test_list_routers_on_l3_agent(self):
         self.admin_client.list_routers_on_l3_agent(self.agent['id'])
diff --git a/tempest/api/network/test_dhcp_ipv6.py b/tempest/api/network/test_dhcp_ipv6.py
index ca08fbd..5d798e3 100644
--- a/tempest/api/network/test_dhcp_ipv6.py
+++ b/tempest/api/network/test_dhcp_ipv6.py
@@ -193,13 +193,10 @@
                         self.network, **kwargs_dhcp)
                     subnet_slaac = self.create_subnet(self.network, **kwargs)
                 port_mac = data_utils.rand_mac_address()
-                dhcp_ip = subnet_dhcp["allocation_pools"][0]["start"]
                 eui_ip = data_utils.get_ipv6_addr_by_EUI64(
                     subnet_slaac['cidr'],
                     port_mac
                 ).format()
-                # TODO(sergsh): remove this when 1219795 is fixed
-                dhcp_ip = [dhcp_ip, (netaddr.IPAddress(dhcp_ip) + 1).format()]
                 port = self.create_port(self.network, mac_address=port_mac)
                 real_ips = dict([(k['subnet_id'], k['ip_address'])
                                  for k in port['fixed_ips']])
@@ -217,11 +214,10 @@
                                  'Real IP is {0}, but shall be {1}'.format(
                                      real_eui_ip,
                                      eui_ip))
-                self.assertIn(
-                    real_dhcp_ip, dhcp_ip,
-                    'Real IP is {0}, but shall be one from {1}'.format(
-                        real_dhcp_ip,
-                        str(dhcp_ip)))
+                msg = ('Real IP address is {0} and it is NOT on '
+                       'subnet {1}'.format(real_dhcp_ip, subnet_dhcp['cidr']))
+                self.assertIn(netaddr.IPAddress(real_dhcp_ip),
+                              netaddr.IPNetwork(subnet_dhcp['cidr']), msg)
 
     @test.idempotent_id('4256c61d-c538-41ea-9147-3c450c36669e')
     def test_dhcpv6_64_subnets(self):
@@ -246,13 +242,10 @@
                         self.network, ip_version=4)
                     subnet_slaac = self.create_subnet(self.network, **kwargs)
                 port_mac = data_utils.rand_mac_address()
-                dhcp_ip = subnet_dhcp["allocation_pools"][0]["start"]
                 eui_ip = data_utils.get_ipv6_addr_by_EUI64(
                     subnet_slaac['cidr'],
                     port_mac
                 ).format()
-                # TODO(sergsh): remove this when 1219795 is fixed
-                dhcp_ip = [dhcp_ip, (netaddr.IPAddress(dhcp_ip) + 1).format()]
                 port = self.create_port(self.network, mac_address=port_mac)
                 real_ips = dict([(k['subnet_id'], k['ip_address'])
                                  for k in port['fixed_ips']])
@@ -260,23 +253,20 @@
                                              for sub in [subnet_dhcp,
                                              subnet_slaac]]
                 self._clean_network()
-                self.assertTrue({real_eui_ip,
-                                 real_dhcp_ip}.issubset([eui_ip] + dhcp_ip))
                 self.assertEqual(real_eui_ip,
                                  eui_ip,
                                  'Real IP is {0}, but shall be {1}'.format(
                                      real_eui_ip,
                                      eui_ip))
-                self.assertIn(
-                    real_dhcp_ip, dhcp_ip,
-                    'Real IP is {0}, but shall be one from {1}'.format(
-                        real_dhcp_ip,
-                        str(dhcp_ip)))
+                msg = ('Real IP address is {0} and it is NOT on '
+                       'subnet {1}'.format(real_dhcp_ip, subnet_dhcp['cidr']))
+                self.assertIn(netaddr.IPAddress(real_dhcp_ip),
+                              netaddr.IPNetwork(subnet_dhcp['cidr']), msg)
 
     @test.idempotent_id('4ab211a0-276f-4552-9070-51e27f58fecf')
     def test_dhcp_stateful(self):
-        """With all options below, DHCPv6 shall allocate first
-        address from subnet pool to port.
+        """With all options below, DHCPv6 shall allocate address
+        from subnet pool to port.
         """
         for ra_mode, add_mode in (
                 ('dhcpv6-stateful', 'dhcpv6-stateful'),
@@ -289,15 +279,11 @@
             subnet = self.create_subnet(self.network, **kwargs)
             port = self.create_port(self.network)
             port_ip = next(iter(port['fixed_ips']), None)['ip_address']
-            dhcp_ip = subnet["allocation_pools"][0]["start"]
-            # TODO(sergsh): remove this when 1219795 is fixed
-            dhcp_ip = [dhcp_ip, (netaddr.IPAddress(dhcp_ip) + 1).format()]
             self._clean_network()
-            self.assertIn(
-                port_ip, dhcp_ip,
-                'Real IP is {0}, but shall be one from {1}'.format(
-                    port_ip,
-                    str(dhcp_ip)))
+            msg = ('Real IP address is {0} and it is NOT on '
+                   'subnet {1}'.format(port_ip, subnet['cidr']))
+            self.assertIn(netaddr.IPAddress(port_ip),
+                          netaddr.IPNetwork(subnet['cidr']), msg)
 
     @test.idempotent_id('51a5e97f-f02e-4e4e-9a17-a69811d300e3')
     def test_dhcp_stateful_fixedips(self):
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
index 7b6b25b..29600c5 100644
--- a/tempest/api/network/test_ports.py
+++ b/tempest/api/network/test_ports.py
@@ -150,6 +150,34 @@
                  if port['id'] == self.port['id']]
         self.assertNotEmpty(ports, "Created port not found in the list")
 
+    @test.idempotent_id('e7fe260b-1e79-4dd3-86d9-bec6a7959fc5')
+    def test_port_list_filter_by_ip(self):
+        # Create network and subnet
+        network = self.create_network()
+        subnet = self.create_subnet(network)
+        self.addCleanup(self.client.delete_subnet, subnet['id'])
+        # Create two ports specifying a fixed_ips
+        address = self._get_ipaddress_from_tempest_conf()
+        _fixed_ip_1 = str(address + 3)
+        _fixed_ip_2 = str(address + 4)
+        fixed_ips_1 = [{'ip_address': _fixed_ip_1}]
+        port_1 = self.client.create_port(network_id=network['id'],
+                                         fixed_ips=fixed_ips_1)
+        self.addCleanup(self.client.delete_port, port_1['port']['id'])
+        fixed_ips_2 = [{'ip_address': _fixed_ip_2}]
+        port_2 = self.client.create_port(network_id=network['id'],
+                                         fixed_ips=fixed_ips_2)
+        self.addCleanup(self.client.delete_port, port_2['port']['id'])
+        # List ports filtered by fixed_ips
+        fixed_ips = 'ip_address=' + _fixed_ip_1
+        port_list = self.client.list_ports(fixed_ips=fixed_ips)
+        ports = port_list['ports']
+        self.assertEqual(len(ports), 1)
+        self.assertEqual(ports[0]['id'], port_1['port']['id'])
+        self.assertEqual(ports[0]['fixed_ips'][0]['ip_address'],
+                         _fixed_ip_1)
+        self.assertEqual(ports[0]['network_id'], network['id'])
+
     @test.idempotent_id('5ad01ed0-0e6e-4c5d-8194-232801b15c72')
     def test_port_list_filter_by_router_id(self):
         # Create a router
diff --git a/tempest/api/object_storage/test_object_slo.py b/tempest/api/object_storage/test_object_slo.py
index 7df0dde..6fc7821 100644
--- a/tempest/api/object_storage/test_object_slo.py
+++ b/tempest/api/object_storage/test_object_slo.py
@@ -110,6 +110,7 @@
         self.assertHeaders(resp, 'Object', method)
 
     @test.idempotent_id('2c3f24a6-36e8-4711-9aa2-800ee1fc7b5b')
+    @test.requires_ext(extension='slo', service='object')
     def test_upload_manifest(self):
         # create static large object from multipart manifest
         manifest = self._create_manifest()
@@ -124,6 +125,7 @@
         self._assertHeadersSLO(resp, 'PUT')
 
     @test.idempotent_id('e69ad766-e1aa-44a2-bdd2-bf62c09c1456')
+    @test.requires_ext(extension='slo', service='object')
     def test_list_large_object_metadata(self):
         # list static large object metadata using multipart manifest
         object_name = self._create_large_object()
@@ -135,6 +137,7 @@
         self._assertHeadersSLO(resp, 'HEAD')
 
     @test.idempotent_id('49bc49bc-dd1b-4c0f-904e-d9f10b830ee8')
+    @test.requires_ext(extension='slo', service='object')
     def test_retrieve_large_object(self):
         # list static large object using multipart manifest
         object_name = self._create_large_object()
@@ -149,6 +152,7 @@
         self.assertEqual(body, sum_data)
 
     @test.idempotent_id('87b6dfa1-abe9-404d-8bf0-6c3751e6aa77')
+    @test.requires_ext(extension='slo', service='object')
     def test_delete_large_object(self):
         # delete static large object using multipart manifest
         object_name = self._create_large_object()
diff --git a/tempest/cmd/account_generator.py b/tempest/cmd/account_generator.py
index 0a48b8d..892e051 100755
--- a/tempest/cmd/account_generator.py
+++ b/tempest/cmd/account_generator.py
@@ -14,7 +14,76 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+"""
+Utility for creating **accounts.yaml** file for concurrent test runs.
+Creates one primary user, one alt user, one swift admin, one stack owner
+and one admin (optionally) for each concurrent thread. The utility creates
+user for each tenant. The **accounts.yaml** file will be valid and contain
+credentials for created users, so each user will be in separate tenant and
+have the username, tenant_name, password and roles.
+
+**Usage:** ``tempest-account-generator [-h] [OPTIONS] accounts_file.yaml``.
+
+Positional Arguments
+-----------------
+**accounts_file.yaml** (Required) Provide an output accounts yaml file. Utility
+creates a .yaml file in the directory where the command is ran. The appropriate
+name for the file is *accounts.yaml* and it should be placed in *tempest/etc*
+directory.
+
+Authentication
+--------------
+
+Account generator creates users and tenants so it needs the admin credentials
+of your cloud to operate properly. The corresponding info can be given either
+through CLI options or environment variables.
+
+You're probably familiar with these, but just to remind::
+
+    +----------+------------------+----------------------+
+    | Param    | CLI              | Environment Variable |
+    +----------+------------------+----------------------+
+    | Username | --os-username    | OS_USERNAME          |
+    | Password | --os-password    | OS_PASSWORD          |
+    | Tenant   | --os-tenant-name | OS_TENANT_NAME       |
+    +----------+------------------+----------------------+
+
+Optional Arguments
+-----------------
+**-h**, **--help** (Optional) Shows help message with the description of
+utility and its arguments, and exits.
+
+**c /etc/tempest.conf**, **--config-file /etc/tempest.conf** (Optional) Path to
+tempest config file.
+
+**--os-username <auth-user-name>** (Optional) Name used for authentication with
+the OpenStack Identity service. Defaults to env[OS_USERNAME]. Note: User should
+have permissions to create new user accounts and tenants.
+
+**--os-password <auth-password>** (Optional) Password used for authentication
+with the OpenStack Identity service. Defaults to env[OS_PASSWORD].
+
+**--os-tenant-name <auth-tenant-name>** (Optional) Tenant to request
+authorization on. Defaults to env[OS_TENANT_NAME].
+
+**--tag TAG** (Optional) Resources tag. Each created resource (user, project)
+will have the prefix with the given TAG in its name. Using tag is recommended
+for the further using, cleaning resources.
+
+**-r CONCURRENCY**, **--concurrency CONCURRENCY** (Required) Concurrency count
+(default: 1). The number of accounts required can be estimated as
+CONCURRENCY x 2. Each user provided in *accounts.yaml* file will be in
+a different tenant. This is required to provide isolation between test for
+running in parallel.
+
+**--with-admin** (Optional) Creates admin for each concurrent group
+(default: False).
+
+To see help on specific argument, please do: ``tempest-account-generator
+[OPTIONS] <accounts_file.yaml> -h``.
+"""
 import argparse
+import netaddr
 import os
 
 from oslo_log import log as logging
@@ -23,6 +92,7 @@
 from tempest import config
 from tempest import exceptions
 from tempest.services.identity.v2.json import identity_client
+from tempest.services.network.json import network_client
 import tempest_lib.auth
 from tempest_lib.common.utils import data_utils
 import tempest_lib.exceptions
@@ -37,7 +107,7 @@
     LOG = logging.getLogger(__name__)
 
 
-def keystone_admin(opts):
+def get_admin_clients(opts):
     _creds = tempest_lib.auth.KeystoneV2Credentials(
         username=opts.os_username,
         password=opts.os_password,
@@ -58,18 +128,28 @@
         'build_interval': CONF.compute.build_interval,
         'build_timeout': CONF.compute.build_timeout
     }
-    return identity_client.IdentityClientJSON(
+    identity_admin = identity_client.IdentityClientJSON(
         _auth,
         CONF.identity.catalog_type,
         CONF.identity.region,
         endpoint_type='adminURL',
         **params
     )
+    network_admin = None
+    if (CONF.service_available.neutron and
+        CONF.auth.create_isolated_networks):
+        network_admin = network_client.NetworkClientJSON(
+            _auth,
+            CONF.network.catalog_type,
+            CONF.network.region or CONF.identity.region,
+            endpoint_type='adminURL',
+            **params)
+    return identity_admin, network_admin
 
 
 def create_resources(opts, resources):
-    admin = keystone_admin(opts)
-    roles = admin.list_roles()
+    identity_admin, network_admin = get_admin_clients(opts)
+    roles = identity_admin.list_roles()
     for u in resources['users']:
         u['role_ids'] = []
         for r in u.get('roles', ()):
@@ -80,24 +160,24 @@
                 raise exceptions.TempestException(
                     "Role: %s - doesn't exist" % r
                 )
-    existing = [x['name'] for x in admin.list_tenants()]
+    existing = [x['name'] for x in identity_admin.list_tenants()]
     for tenant in resources['tenants']:
         if tenant not in existing:
-            admin.create_tenant(tenant)
+            identity_admin.create_tenant(tenant)
         else:
             LOG.warn("Tenant '%s' already exists in this environment" % tenant)
     LOG.info('Tenants created')
     for u in resources['users']:
         try:
-            tenant = admin.get_tenant_by_name(u['tenant'])
+            tenant = identity_admin.get_tenant_by_name(u['tenant'])
         except tempest_lib.exceptions.NotFound:
             LOG.error("Tenant: %s - not found" % u['tenant'])
             continue
         while True:
             try:
-                admin.get_user_by_username(tenant['id'], u['name'])
+                identity_admin.get_user_by_username(tenant['id'], u['name'])
             except tempest_lib.exceptions.NotFound:
-                admin.create_user(
+                identity_admin.create_user(
                     u['name'], u['pass'], tenant['id'],
                     "%s@%s" % (u['name'], tenant['id']),
                     enabled=True)
@@ -108,21 +188,29 @@
                 u['name'] = random_user_name(opts.tag, u['prefix'])
 
     LOG.info('Users created')
+    if network_admin:
+        for u in resources['users']:
+            tenant = identity_admin.get_tenant_by_name(u['tenant'])
+            network_name = create_network_resources(network_admin,
+                                                    tenant['id'],
+                                                    u['name'])
+            u['network'] = network_name
+        LOG.info('Networks created')
     for u in resources['users']:
         try:
-            tenant = admin.get_tenant_by_name(u['tenant'])
+            tenant = identity_admin.get_tenant_by_name(u['tenant'])
         except tempest_lib.exceptions.NotFound:
             LOG.error("Tenant: %s - not found" % u['tenant'])
             continue
         try:
-            user = admin.get_user_by_username(tenant['id'],
-                                              u['name'])
+            user = identity_admin.get_user_by_username(tenant['id'],
+                                                       u['name'])
         except tempest_lib.exceptions.NotFound:
             LOG.error("User: %s - not found" % u['user'])
             continue
         for r in u['role_ids']:
             try:
-                admin.assign_user_role(tenant['id'], user['id'], r)
+                identity_admin.assign_user_role(tenant['id'], user['id'], r)
             except tempest_lib.exceptions.Conflict:
                 # don't care if it's already assigned
                 pass
@@ -130,6 +218,57 @@
     LOG.info('Resources deployed successfully!')
 
 
+def create_network_resources(network_admin_client, tenant_id, name):
+
+    def _create_network(name):
+        resp_body = network_admin_client.create_network(
+            name=name, tenant_id=tenant_id)
+        return resp_body['network']
+
+    def _create_subnet(subnet_name, network_id):
+        base_cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr)
+        mask_bits = CONF.network.tenant_network_mask_bits
+        for subnet_cidr in base_cidr.subnet(mask_bits):
+            try:
+                resp_body = network_admin_client.\
+                    create_subnet(
+                        network_id=network_id, cidr=str(subnet_cidr),
+                        name=subnet_name,
+                        tenant_id=tenant_id,
+                        enable_dhcp=True,
+                        ip_version=4)
+                break
+            except tempest_lib.exceptions.BadRequest as e:
+                if 'overlaps with another subnet' not in str(e):
+                    raise
+        else:
+            message = 'Available CIDR for subnet creation could not be found'
+            raise Exception(message)
+        return resp_body['subnet']
+
+    def _create_router(router_name):
+        external_net_id = dict(
+            network_id=CONF.network.public_network_id)
+        resp_body = network_admin_client.create_router(
+            router_name,
+            external_gateway_info=external_net_id,
+            tenant_id=tenant_id)
+        return resp_body['router']
+
+    def _add_router_interface(router_id, subnet_id):
+        network_admin_client.add_router_interface_with_subnet_id(
+            router_id, subnet_id)
+
+    network_name = name + "-network"
+    network = _create_network(network_name)
+    subnet_name = name + "-subnet"
+    subnet = _create_subnet(subnet_name, network['id'])
+    router_name = name + "-router"
+    router = _create_router(router_name)
+    _add_router_interface(router['id'], subnet['id'])
+    return network_name
+
+
 def random_user_name(tag, prefix):
     if tag:
         return data_utils.rand_name('-'.join((tag, prefix)))
@@ -185,12 +324,15 @@
 def dump_accounts(opts, resources):
     accounts = []
     for user in resources['users']:
-        accounts.append({
+        account = {
             'username': user['name'],
             'tenant_name': user['tenant'],
             'password': user['pass'],
             'roles': user['roles']
-        })
+        }
+        if 'network' in user:
+            account['resources'] = {'network': user['network']}
+        accounts.append(account)
     if os.path.exists(opts.accounts):
         os.rename(opts.accounts, '.'.join((opts.accounts, 'bak')))
     with open(opts.accounts, 'w') as f:
@@ -199,9 +341,9 @@
 
 
 def get_options():
-    usage_string = ('account_generator [-h] <ARG> ...\n\n'
+    usage_string = ('tempest-account-generator [-h] <ARG> ...\n\n'
                     'To see help on specific argument, do:\n'
-                    'account_generator <ARG> -h')
+                    'tempest-account-generator <ARG> -h')
     parser = argparse.ArgumentParser(
         description='Create accounts.yaml file for concurrent test runs. '
                     'One primary user, one alt user, '
@@ -218,7 +360,7 @@
     parser.add_argument('--os-username',
                         metavar='<auth-user-name>',
                         default=os.environ.get('OS_USERNAME'),
-                        help='User should have permitions '
+                        help='User should have permissions '
                              'to create new user accounts and '
                              'tenants. Defaults to env[OS_USERNAME].')
     parser.add_argument('--os-password',
@@ -243,7 +385,7 @@
     parser.add_argument('--with-admin',
                         action='store_true',
                         dest='admin',
-                        help='Create admin in every tenant')
+                        help='Creates admin for each concurrent group')
     parser.add_argument('accounts',
                         metavar='accounts_file.yaml',
                         help='Output accounts yaml file')
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index f51d9aa..2269d41 100755
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -57,14 +57,17 @@
         change_option(option, group, value)
 
 
+def contains_version(prefix, versions):
+    return any([x for x in versions if x.startswith(prefix)])
+
+
 def verify_glance_api_versions(os, update):
     # Check glance api versions
-    versions = os.image_client.get_versions()
-    if CONF.image_feature_enabled.api_v1 != ('v1.1' in versions or 'v1.0' in
-                                             versions):
+    _, versions = os.image_client.get_versions()
+    if CONF.image_feature_enabled.api_v1 != contains_version('v1.', versions):
         print_and_or_update('api_v1', 'image_feature_enabled',
                             not CONF.image_feature_enabled.api_v1, update)
-    if CONF.image_feature_enabled.api_v2 != ('v2.0' in versions):
+    if CONF.image_feature_enabled.api_v2 != contains_version('v2.', versions):
         print_and_or_update('api_v2', 'image_feature_enabled',
                             not CONF.image_feature_enabled.api_v2, update)
 
@@ -100,10 +103,12 @@
 def verify_keystone_api_versions(os, update):
     # Check keystone api versions
     versions = _get_api_versions(os, 'keystone')
-    if CONF.identity_feature_enabled.api_v2 != ('v2.0' in versions):
+    if (CONF.identity_feature_enabled.api_v2 !=
+            contains_version('v2.', versions)):
         print_and_or_update('api_v2', 'identity_feature_enabled',
                             not CONF.identity_feature_enabled.api_v2, update)
-    if CONF.identity_feature_enabled.api_v3 != ('v3.0' in versions):
+    if (CONF.identity_feature_enabled.api_v3 !=
+            contains_version('v3.', versions)):
         print_and_or_update('api_v3', 'identity_feature_enabled',
                             not CONF.identity_feature_enabled.api_v3, update)
 
@@ -111,10 +116,12 @@
 def verify_cinder_api_versions(os, update):
     # Check cinder api versions
     versions = _get_api_versions(os, 'cinder')
-    if CONF.volume_feature_enabled.api_v1 != ('v1.0' in versions):
+    if (CONF.volume_feature_enabled.api_v1 !=
+            contains_version('v1.', versions)):
         print_and_or_update('api_v1', 'volume_feature_enabled',
                             not CONF.volume_feature_enabled.api_v1, update)
-    if CONF.volume_feature_enabled.api_v2 != ('v2.0' in versions):
+    if (CONF.volume_feature_enabled.api_v2 !=
+            contains_version('v2.', versions)):
         print_and_or_update('api_v2', 'volume_feature_enabled',
                             not CONF.volume_feature_enabled.api_v2, update)
 
diff --git a/tempest/config.py b/tempest/config.py
index 603ccd2..0fa5bf5 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -433,6 +433,10 @@
     cfg.BoolOpt('api_v1',
                 default=True,
                 help="Is the v1 image API enabled"),
+    cfg.BoolOpt('deactivate_image',
+                default=False,
+                help="Is the deactivate-image feature enabled."
+                     " The feature has been integrated since Kilo."),
 ]
 
 network_group = cfg.OptGroup(name='network',
@@ -1114,8 +1118,10 @@
                default=60,
                help="Timeout for Ironic power transitions."),
     cfg.IntOpt('unprovision_timeout',
-               default=60,
-               help="Timeout for unprovisioning an Ironic node.")
+               default=300,
+               help="Timeout for unprovisioning an Ironic node. "
+                    "Takes longer since Kilo as Ironic performs an extra "
+                    "step in Node cleaning.")
 ]
 
 negative_group = cfg.OptGroup(name='negative', title="Negative Test Options")
diff --git a/tempest/scenario/test_baremetal_basic_ops.py b/tempest/scenario/test_baremetal_basic_ops.py
index e54c25a..9fdba39 100644
--- a/tempest/scenario/test_baremetal_basic_ops.py
+++ b/tempest/scenario/test_baremetal_basic_ops.py
@@ -98,7 +98,7 @@
     def get_flavor_ephemeral_size(self):
         """Returns size of the ephemeral partition in GiB."""
         f_id = self.instance['flavor']['id']
-        flavor = self.flavors_client.get_flavor_details(f_id)
+        flavor = self.flavors_client.show_flavor(f_id)
         ephemeral = flavor.get('OS-FLV-EXT-DATA:ephemeral')
         if not ephemeral or ephemeral == 'N/A':
             return None
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index 6e67c4b..fba839a 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -13,7 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 import functools
-import netaddr
 
 from oslo_log import log as logging
 import six
@@ -28,12 +27,13 @@
 
 
 class TestGettingAddress(manager.NetworkScenarioTest):
-    """Create network with 2 subnets: IPv4 and IPv6 in a given address mode
+    """Create network with subnets: one IPv4 and
+    one or few IPv6 in a given address mode
     Boot 2 VMs on this network
     Allocate and assign 2 FIP4
-    Check that vNIC of server matches port data from OpenStack DB
-    Ping4 tenant IPv4 of one VM from another one
-    Will do the same with ping6 when available in VM
+    Check that vNICs of all VMs gets all addresses actually assigned
+    Ping4 to one VM from another one
+    If ping6 available in VM, do ping6 to all v6 addresses
     """
 
     @classmethod
@@ -65,41 +65,41 @@
             'key_name': self.keypair['name'],
             'security_groups': [{'name': self.sec_grp['name']}]}
 
-    def prepare_network(self, address6_mode):
+    def prepare_network(self, address6_mode, n_subnets6=1):
         """Creates network with
-         one IPv6 subnet in the given mode and
+         given number of IPv6 subnets in the given mode and
          one IPv4 subnet
-         Creates router with ports on both subnets
+         Creates router with ports on all subnets
         """
         self.network = self._create_network(tenant_id=self.tenant_id)
         sub4 = self._create_subnet(network=self.network,
                                    namestart='sub4',
                                    ip_version=4,)
-        # since https://bugs.launchpad.net/neutron/+bug/1394112 we need
-        # to specify gateway_ip manually
-        net_range = netaddr.IPNetwork(CONF.network.tenant_network_v6_cidr)
-        gateway_ip = (netaddr.IPAddress(net_range) + 1).format()
-        sub6 = self._create_subnet(network=self.network,
-                                   namestart='sub6',
-                                   ip_version=6,
-                                   gateway_ip=gateway_ip,
-                                   ipv6_ra_mode=address6_mode,
-                                   ipv6_address_mode=address6_mode)
 
         router = self._get_router(tenant_id=self.tenant_id)
         sub4.add_to_router(router_id=router['id'])
-        sub6.add_to_router(router_id=router['id'])
         self.addCleanup(sub4.delete)
-        self.addCleanup(sub6.delete)
+
+        for _ in range(n_subnets6):
+            sub6 = self._create_subnet(network=self.network,
+                                       namestart='sub6',
+                                       ip_version=6,
+                                       ipv6_ra_mode=address6_mode,
+                                       ipv6_address_mode=address6_mode)
+
+            sub6.add_to_router(router_id=router['id'])
+            self.addCleanup(sub6.delete)
 
     @staticmethod
     def define_server_ips(srv):
+        ips = {'4': None, '6': []}
         for net_name, nics in six.iteritems(srv['addresses']):
             for nic in nics:
                 if nic['version'] == 6:
-                    srv['accessIPv6'] = nic['addr']
+                    ips['6'].append(nic['addr'])
                 else:
-                    srv['accessIPv4'] = nic['addr']
+                    ips['4'] = nic['addr']
+        return ips
 
     def prepare_server(self):
         username = CONF.compute.image_ssh_user
@@ -109,53 +109,56 @@
 
         srv = self.create_server(create_kwargs=create_kwargs)
         fip = self.create_floating_ip(thing=srv)
-        self.define_server_ips(srv=srv)
+        ips = self.define_server_ips(srv=srv)
         ssh = self.get_remote_client(
             server_or_ip=fip.floating_ip_address,
             username=username)
-        return ssh, srv
+        return ssh, ips
 
-    def _prepare_and_test(self, address6_mode):
-        self.prepare_network(address6_mode=address6_mode)
+    def _prepare_and_test(self, address6_mode, n_subnets6=1):
+        self.prepare_network(address6_mode=address6_mode,
+                             n_subnets6=n_subnets6)
 
-        ssh1, srv1 = self.prepare_server()
-        ssh2, srv2 = self.prepare_server()
+        sshv4_1, ips_from_api_1 = self.prepare_server()
+        sshv4_2, ips_from_api_2 = self.prepare_server()
 
         def guest_has_address(ssh, addr):
             return addr in ssh.get_ip_list()
 
-        srv1_v6_addr_assigned = functools.partial(
-            guest_has_address, ssh1, srv1['accessIPv6'])
-        srv2_v6_addr_assigned = functools.partial(
-            guest_has_address, ssh2, srv2['accessIPv6'])
+        # get addresses assigned to vNIC as reported by 'ip address' utility
+        ips_from_ip_1 = sshv4_1.get_ip_list()
+        ips_from_ip_2 = sshv4_2.get_ip_list()
+        self.assertIn(ips_from_api_1['4'], ips_from_ip_1)
+        self.assertIn(ips_from_api_2['4'], ips_from_ip_2)
+        for i in range(n_subnets6):
+            # v6 should be configured since the image supports it
+            # It can take time for ipv6 automatic address to get assigned
+            srv1_v6_addr_assigned = functools.partial(
+                guest_has_address, sshv4_1, ips_from_api_1['6'][i])
 
-        result = ssh1.get_ip_list()
-        self.assertIn(srv1['accessIPv4'], result)
-        # v6 should be configured since the image supports it
-        # It can take time for ipv6 automatic address to get assigned
-        self.assertTrue(
-            test.call_until_true(srv1_v6_addr_assigned,
-                                 CONF.compute.ping_timeout, 1))
-        result = ssh2.get_ip_list()
-        self.assertIn(srv2['accessIPv4'], result)
-        # v6 should be configured since the image supports it
-        # It can take time for ipv6 automatic address to get assigned
-        self.assertTrue(
-            test.call_until_true(srv2_v6_addr_assigned,
-                                 CONF.compute.ping_timeout, 1))
-        result = ssh1.ping_host(srv2['accessIPv4'])
+            srv2_v6_addr_assigned = functools.partial(
+                guest_has_address, sshv4_2, ips_from_api_2['6'][i])
+
+            self.assertTrue(test.call_until_true(srv1_v6_addr_assigned,
+                                                 CONF.compute.ping_timeout, 1))
+
+            self.assertTrue(test.call_until_true(srv2_v6_addr_assigned,
+                                                 CONF.compute.ping_timeout, 1))
+
+        result = sshv4_1.ping_host(ips_from_api_2['4'])
         self.assertIn('0% packet loss', result)
-        result = ssh2.ping_host(srv1['accessIPv4'])
+        result = sshv4_2.ping_host(ips_from_api_1['4'])
         self.assertIn('0% packet loss', result)
 
         # Some VM (like cirros) may not have ping6 utility
-        result = ssh1.exec_command('whereis ping6')
+        result = sshv4_1.exec_command('whereis ping6')
         is_ping6 = False if result == 'ping6:\n' else True
         if is_ping6:
-            result = ssh1.ping_host(srv2['accessIPv6'])
-            self.assertIn('0% packet loss', result)
-            result = ssh2.ping_host(srv1['accessIPv6'])
-            self.assertIn('0% packet loss', result)
+            for i in range(n_subnets6):
+                result = sshv4_1.ping_host(ips_from_api_2['6'][i])
+                self.assertIn('0% packet loss', result)
+                result = sshv4_2.ping_host(ips_from_api_1['6'][i])
+                self.assertIn('0% packet loss', result)
         else:
             LOG.warning('Ping6 is not available, skipping')
 
@@ -168,3 +171,13 @@
     @test.services('compute', 'network')
     def test_dhcp6_stateless_from_os(self):
         self._prepare_and_test(address6_mode='dhcpv6-stateless')
+
+    @test.idempotent_id('7ab23f41-833b-4a16-a7c9-5b42fe6d4123')
+    @test.services('compute', 'network')
+    def test_multi_prefix_dhcpv6_stateless(self):
+        self._prepare_and_test(address6_mode='dhcpv6-stateless', n_subnets6=2)
+
+    @test.idempotent_id('dec222b1-180c-4098-b8c5-cc1b8342d611')
+    @test.services('compute', 'network')
+    def test_multi_prefix_slaac(self):
+        self._prepare_and_test(address6_mode='slaac', n_subnets6=2)
diff --git a/tempest/scenario/utils.py b/tempest/scenario/utils.py
index f8d9dd4..cd9d925 100644
--- a/tempest/scenario/utils.py
+++ b/tempest/scenario/utils.py
@@ -65,7 +65,7 @@
 
     def is_flavor_enough(self, flavor_id, image_id):
         _image = self.images_client.show_image(image_id)
-        _flavor = self.flavors_client.get_flavor_details(flavor_id)
+        _flavor = self.flavors_client.show_flavor(flavor_id)
         return self._is_flavor_enough(_flavor, _image)
 
 
diff --git a/tempest/services/compute/json/fixed_ips_client.py b/tempest/services/compute/json/fixed_ips_client.py
index 7ba424f..769bfdc 100644
--- a/tempest/services/compute/json/fixed_ips_client.py
+++ b/tempest/services/compute/json/fixed_ips_client.py
@@ -21,7 +21,7 @@
 
 class FixedIPsClientJSON(service_client.ServiceClient):
 
-    def get_fixed_ip_details(self, fixed_ip):
+    def show_fixed_ip(self, fixed_ip):
         url = "os-fixed-ips/%s" % (fixed_ip)
         resp, body = self.get(url)
         body = json.loads(body)
diff --git a/tempest/services/compute/json/flavors_client.py b/tempest/services/compute/json/flavors_client.py
index 7938d8e..dee56ac 100644
--- a/tempest/services/compute/json/flavors_client.py
+++ b/tempest/services/compute/json/flavors_client.py
@@ -47,7 +47,7 @@
         self.validate_response(schema.list_flavors_details, resp, body)
         return service_client.ResponseBodyList(resp, body['flavors'])
 
-    def get_flavor_details(self, flavor_id):
+    def show_flavor(self, flavor_id):
         resp, body = self.get("flavors/%s" % str(flavor_id))
         body = json.loads(body)
         self.validate_response(schema.create_get_flavor_details, resp, body)
@@ -84,7 +84,7 @@
         return service_client.ResponseBody(resp, body)
 
     def is_resource_deleted(self, id):
-        # Did not use get_flavor_details(id) for verification as it gives
+        # Did not use show_flavor(id) for verification as it gives
         # 200 ok even for deleted id. LP #981263
         # we can remove the loop here and use get by ID when bug gets sortedout
         flavors = self.list_flavors_with_detail()
@@ -108,7 +108,7 @@
                                resp, body)
         return service_client.ResponseBody(resp, body['extra_specs'])
 
-    def get_flavor_extra_spec(self, flavor_id):
+    def list_flavor_extra_specs(self, flavor_id):
         """Gets extra Specs details of the mentioned flavor."""
         resp, body = self.get('flavors/%s/os-extra_specs' % flavor_id)
         body = json.loads(body)
@@ -116,7 +116,7 @@
                                resp, body)
         return service_client.ResponseBody(resp, body['extra_specs'])
 
-    def get_flavor_extra_spec_with_key(self, flavor_id, key):
+    def show_flavor_extra_spec(self, flavor_id, key):
         """Gets extra Specs key-value of the mentioned flavor and key."""
         resp, body = self.get('flavors/%s/os-extra_specs/%s' % (str(flavor_id),
                               key))
diff --git a/tempest/services/compute/json/floating_ips_client.py b/tempest/services/compute/json/floating_ips_client.py
index f30bfdb..6095dc0 100644
--- a/tempest/services/compute/json/floating_ips_client.py
+++ b/tempest/services/compute/json/floating_ips_client.py
@@ -35,7 +35,7 @@
         self.validate_response(schema.list_floating_ips, resp, body)
         return service_client.ResponseBodyList(resp, body['floating_ips'])
 
-    def get_floating_ip_details(self, floating_ip_id):
+    def show_floating_ip(self, floating_ip_id):
         """Get the details of a floating IP."""
         url = "os-floating-ips/%s" % str(floating_ip_id)
         resp, body = self.get(url)
@@ -90,7 +90,7 @@
 
     def is_resource_deleted(self, id):
         try:
-            self.get_floating_ip_details(id)
+            self.show_floating_ip(id)
         except lib_exc.NotFound:
             return True
         return False
diff --git a/tempest/services/identity/v2/json/identity_client.py b/tempest/services/identity/v2/json/identity_client.py
index 039f9bb..c5f7338 100644
--- a/tempest/services/identity/v2/json/identity_client.py
+++ b/tempest/services/identity/v2/json/identity_client.py
@@ -18,6 +18,13 @@
 
 class IdentityClientJSON(service_client.ServiceClient):
 
+    def get_api_description(self):
+        """Retrieves info about the v2.0 Identity API"""
+        url = ''
+        resp, body = self.get(url)
+        self.expected_success([200, 203], resp.status)
+        return service_client.ResponseBody(resp, self._parse_resp(body))
+
     def has_admin_extensions(self):
         """
         Returns True if the KSADM Admin Extensions are supported
diff --git a/tempest/services/identity/v3/json/identity_client.py b/tempest/services/identity/v3/json/identity_client.py
index f3d02a8..30fb3e1 100644
--- a/tempest/services/identity/v3/json/identity_client.py
+++ b/tempest/services/identity/v3/json/identity_client.py
@@ -23,6 +23,13 @@
 class IdentityV3ClientJSON(service_client.ServiceClient):
     api_version = "v3"
 
+    def get_api_description(self):
+        """Retrieves info about the v3 Identity API"""
+        url = ''
+        resp, body = self.get(url)
+        self.expected_success(200, resp.status)
+        return service_client.ResponseBody(resp, self._parse_resp(body))
+
     def create_user(self, user_name, password=None, project_id=None,
                     email=None, domain_id='default', **kwargs):
         """Creates a user."""
diff --git a/tempest/services/image/v1/json/image_client.py b/tempest/services/image/v1/json/image_client.py
index 7c58f01..add26a9 100644
--- a/tempest/services/image/v1/json/image_client.py
+++ b/tempest/services/image/v1/json/image_client.py
@@ -201,20 +201,12 @@
         self.expected_success(200, resp.status)
         return service_client.ResponseBody(resp, body)
 
-    def list_images(self, **kwargs):
+    def list_images(self, detail=False, properties=dict(),
+                    changes_since=None, **kwargs):
         url = 'v1/images'
 
-        if len(kwargs) > 0:
-            url += '?%s' % urllib.urlencode(kwargs)
-
-        resp, body = self.get(url)
-        self.expected_success(200, resp.status)
-        body = json.loads(body)
-        return service_client.ResponseBodyList(resp, body['images'])
-
-    def image_list_detail(self, properties=dict(), changes_since=None,
-                          **kwargs):
-        url = 'v1/images/detail'
+        if detail:
+            url += '/detail'
 
         params = {}
         for key, value in properties.items():
@@ -265,8 +257,9 @@
         body = json.loads(body)
         return service_client.ResponseBody(resp, body)
 
-    def get_shared_images(self, member_id):
-        url = 'v1/shared-images/%s' % member_id
+    def list_shared_images(self, tenant_id):
+        """List shared images with the specified tenant"""
+        url = 'v1/shared-images/%s' % tenant_id
         resp, body = self.get(url)
         self.expected_success(200, resp.status)
         body = json.loads(body)
diff --git a/tempest/services/image/v2/json/image_client.py b/tempest/services/image/v2/json/image_client.py
index a4cb48c..9e37f6e 100644
--- a/tempest/services/image/v2/json/image_client.py
+++ b/tempest/services/image/v2/json/image_client.py
@@ -96,6 +96,18 @@
         body = json.loads(body)
         return service_client.ResponseBody(resp, body)
 
+    def deactivate_image(self, image_id):
+        url = 'v2/images/%s/actions/deactivate' % image_id
+        resp, body = self.post(url, None)
+        self.expected_success(204, resp.status)
+        return service_client.ResponseBody(resp, body)
+
+    def reactivate_image(self, image_id):
+        url = 'v2/images/%s/actions/reactivate' % image_id
+        resp, body = self.post(url, None)
+        self.expected_success(204, resp.status)
+        return service_client.ResponseBody(resp, body)
+
     def delete_image(self, image_id):
         url = 'v2/images/%s' % image_id
         resp, _ = self.delete(url)
@@ -166,7 +178,7 @@
         body = json.loads(body)
         return service_client.ResponseBody(resp, body)
 
-    def add_member(self, image_id, member_id):
+    def add_image_member(self, image_id, member_id):
         url = 'v2/images/%s/members' % image_id
         data = json.dumps({'member': member_id})
         resp, body = self.post(url, data)
@@ -174,22 +186,21 @@
         body = json.loads(body)
         return service_client.ResponseBody(resp, body)
 
-    def update_member_status(self, image_id, member_id, status):
-        """Valid status are: ``pending``, ``accepted``,  ``rejected``."""
+    def update_image_member(self, image_id, member_id, body):
         url = 'v2/images/%s/members/%s' % (image_id, member_id)
-        data = json.dumps({'status': status})
+        data = json.dumps(body)
         resp, body = self.put(url, data)
         self.expected_success(200, resp.status)
         body = json.loads(body)
         return service_client.ResponseBody(resp, body)
 
-    def get_member(self, image_id, member_id):
+    def show_image_member(self, image_id, member_id):
         url = 'v2/images/%s/members/%s' % (image_id, member_id)
         resp, body = self.get(url)
         self.expected_success(200, resp.status)
         return service_client.ResponseBody(resp, json.loads(body))
 
-    def remove_member(self, image_id, member_id):
+    def remove_image_member(self, image_id, member_id):
         url = 'v2/images/%s/members/%s' % (image_id, member_id)
         resp, _ = self.delete(url)
         self.expected_success(204, resp.status)
diff --git a/tempest/stress/actions/ssh_floating.py b/tempest/stress/actions/ssh_floating.py
index 0df2eb1..9fdb394 100644
--- a/tempest/stress/actions/ssh_floating.py
+++ b/tempest/stress/actions/ssh_floating.py
@@ -145,7 +145,7 @@
         cli = self.manager.floating_ips_client
 
         def func():
-            floating = cli.get_floating_ip_details(self.floating['id'])
+            floating = cli.show_floating_ip(self.floating['id'])
             return floating['instance_id'] is None
 
         if not tempest.test.call_until_true(func, self.check_timeout,
diff --git a/tempest/stress/actions/volume_attach_verify.py b/tempest/stress/actions/volume_attach_verify.py
index c8d9f06..ea53481 100644
--- a/tempest/stress/actions/volume_attach_verify.py
+++ b/tempest/stress/actions/volume_attach_verify.py
@@ -96,7 +96,7 @@
         cli = self.manager.floating_ips_client
 
         def func():
-            floating = cli.get_floating_ip_details(self.floating['id'])
+            floating = cli.show_floating_ip(self.floating['id'])
             return floating['instance_id'] is None
 
         if not tempest.test.call_until_true(func, CONF.compute.build_timeout,
diff --git a/tempest/tests/cmd/test_javelin.py b/tempest/tests/cmd/test_javelin.py
index 860599b..f98f8ba 100644
--- a/tempest/tests/cmd/test_javelin.py
+++ b/tempest/tests/cmd/test_javelin.py
@@ -28,6 +28,39 @@
         self.fake_client = mock.MagicMock()
         self.fake_object = mock.MagicMock()
 
+    def test_load_resources(self):
+        with mock.patch('six.moves.builtins.open', mock.mock_open(),
+                        create=True) as open_mock:
+            with mock.patch('yaml.load', mock.MagicMock(),
+                            create=True) as load_mock:
+                javelin.load_resources(self.fake_object)
+                load_mock.assert_called_once_with(open_mock(self.fake_object))
+
+    def test_keystone_admin(self):
+        self.useFixture(mockpatch.PatchObject(javelin, "OSClient"))
+        javelin.OPTS = self.fake_object
+        javelin.keystone_admin()
+        javelin.OSClient.assert_called_once_with(
+            self.fake_object.os_username,
+            self.fake_object.os_password,
+            self.fake_object.os_tenant_name)
+
+    def test_client_for_user(self):
+        fake_user = mock.MagicMock()
+        javelin.USERS = {fake_user['name']: fake_user}
+        self.useFixture(mockpatch.PatchObject(javelin, "OSClient"))
+        javelin.client_for_user(fake_user['name'])
+        javelin.OSClient.assert_called_once_with(
+            fake_user['name'], fake_user['pass'], fake_user['tenant'])
+
+    def test_client_for_non_existing_user(self):
+        fake_non_existing_user = self.fake_object
+        fake_user = mock.MagicMock()
+        javelin.USERS = {fake_user['name']: fake_user}
+        self.useFixture(mockpatch.PatchObject(javelin, "OSClient"))
+        javelin.client_for_user(fake_non_existing_user['name'])
+        self.assertFalse(javelin.OSClient.called)
+
 
 class TestCreateResources(JavelinUnitTest):
     def test_create_tenants(self):
diff --git a/tempest/tests/cmd/test_verify_tempest_config.py b/tempest/tests/cmd/test_verify_tempest_config.py
index b9afd5e..7286d76 100644
--- a/tempest/tests/cmd/test_verify_tempest_config.py
+++ b/tempest/tests/cmd/test_verify_tempest_config.py
@@ -164,7 +164,7 @@
 
     def test_verify_glance_version_no_v2_with_v1_1(self):
         def fake_get_versions():
-            return (['v1.1'])
+            return (None, ['v1.1'])
         fake_os = mock.MagicMock()
         fake_os.image_client.get_versions = fake_get_versions
         with mock.patch.object(verify_tempest_config,
@@ -175,7 +175,7 @@
 
     def test_verify_glance_version_no_v2_with_v1_0(self):
         def fake_get_versions():
-            return (['v1.0'])
+            return (None, ['v1.0'])
         fake_os = mock.MagicMock()
         fake_os.image_client.get_versions = fake_get_versions
         with mock.patch.object(verify_tempest_config,
@@ -186,7 +186,7 @@
 
     def test_verify_glance_version_no_v1(self):
         def fake_get_versions():
-            return (['v2.0'])
+            return (None, ['v2.0'])
         fake_os = mock.MagicMock()
         fake_os.image_client.get_versions = fake_get_versions
         with mock.patch.object(verify_tempest_config,
diff --git a/test-requirements.txt b/test-requirements.txt
index 32f33bc..7169610 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -10,4 +10,4 @@
 mock>=1.0
 coverage>=3.6
 oslotest>=1.5.1  # Apache-2.0
-stevedore>=1.3.0  # Apache-2.0
+stevedore>=1.5.0  # Apache-2.0