Merge "Switch all uses of StringIO to use it from six"
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index 4fe2e9f..e21deea 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -40,6 +40,24 @@
 Eventually the config options for providing credentials to tempest will be
 deprecated and removed in favor of the accounts.yaml file.
 
+Keystone Connection Info
+^^^^^^^^^^^^^^^^^^^^^^^^
+In order for tempest to be able to talk to your OpenStack deployment you need
+to provide it with information about how it communicates with keystone.
+This involves configuring the following options in the identity section:
+
+ #. auth_version
+ #. uri
+ #. uri_v3
+
+The *auth_version* option is used to tell tempest whether it should be using
+keystone's v2 or v3 api for communicating with keystone. (except for the
+identity api tests which will test a specific version) The 2 uri options are
+used to tell tempest the url of the keystone endpoint. The *uri* option is used
+for keystone v2 request and *uri_v3* is used for keystone v3. You want to ensure
+that which ever version you set for *auth_version* has its uri option defined.
+
+
 Credential Provider Mechanisms
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
@@ -123,3 +141,233 @@
 is that if a test requires specific roles on accounts these tests can not be
 run. This is because the config options do not give sufficient flexibility to
 describe the roles assigned to a user for running the tests.
+
+Compute
+-------
+
+Flavors
+^^^^^^^
+For tempest to be able to create servers you need to specify flavors that it
+can use to boot the servers with. There are 2 options in the tempest config
+for doing this:
+
+ #. flavor_ref
+ #. flavor_ref_alt
+
+Both of these options are in the compute section of the config file and take
+in the flavor id (not the name) from nova. The *flavor_ref* option is what will
+be used for booting almost all of the guests, *flavor_ref_alt* is only used in
+tests where 2 different sized servers are required. (for example a resize test)
+
+Using a smaller flavor is generally recommended, when larger flavors are used
+the extra time required to bring up servers will likely affect total run time
+and probably require tweaking timeout values to ensure tests have ample time to
+finish.
+
+Images
+^^^^^^
+Just like with flavors, tempest needs to know which images to use for booting
+servers. There are 2 options in the compute section just like with flavors:
+
+ #. image_ref
+ #. image_ref_alt
+
+Both options are expecting an image id (not name) from nova. The *image_ref*
+option is what what will be used for booting the majority of servers in tempest.
+*image_ref_alt* is used for tests that require 2 images such as rebuild. If 2
+images are not available you can set both options to the same image_ref and
+those tests will be skipped.
+
+There are also options in the scenario section for images:
+
+ #. img_file
+ #. img_dir
+ #. aki_img_file
+ #. ari_img_file
+ #. ami_img_file
+ #. img_container_format
+ #. img_disk_format
+
+however unlike the other image options these are used for a very small subset
+of scenario tests which are uploading an image. These options are used to tell
+tempest where an image file is located and describe it's metadata for when it's
+uploaded.
+
+The behavior of these options is a bit convoluted (which will likely be fixed
+in future versions). You first need to specify *img_dir*, which is the directory
+tempest will look for the image files in. First it will check if the filename
+set for *img_file* could be found in *img_dir*. If it is found then the
+*img_container_format* and *img_disk_format* options are used to upload that
+image to glance. However if it's not found tempest will look for the 3 uec image
+file name options as a fallback. If neither is found the tests requiring an
+image to upload will fail.
+
+It is worth pointing out that using `cirros`_ is a very good choice for running
+tempest. It's what is used for upstream testing, they boot quickly and have a
+small footprint.
+
+.. _cirros: https://launchpad.net/cirros
+
+Networking
+----------
+OpenStack has a myriad of different networking configurations possible and
+depending on which of the 2 network backends, nova-network or neutron, you are
+using things can vary drastically. Due to this complexity Tempest has to provide
+a certain level of flexibility in it's configuration to ensure it will work
+against any cloud. This ends up causing a large number of permutations in
+Tempest's config around network configuration.
+
+
+Enabling Remote Access to Created Servers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+When Tempest creates servers for testing, some tests require being able to
+connect those servers. Depending on the configuration of the cloud, the methods
+for doing this can be different. In certain configurations it is required to
+specify a single network with server create calls. Accordingly, Tempest provides
+a few different methods for providing this information in configuration to try
+and ensure that regardless of the clouds configuration it'll still be able to
+run. This section covers the different methods of configuring Tempest to provide
+a network when creating servers.
+
+Fixed Network Name
+""""""""""""""""""
+This is the simplest method of specifying how networks should be used. You can
+just specify a single network name/label to use for all server creations. The
+limitation with this is that all tenants/projects and users must be able to see
+that network name/label if they were to perform a network list and be able to
+use it.
+
+If no network name is assigned in the config file and none of the below
+alternatives are used, then Tempest will not specify a network on server
+creations, which depending on the cloud configuration might prevent them from
+booting.
+
+To set a fixed network name simply do:
+
+ #. Set the fixed_network_name option in the compute group
+
+In the case that the configured fixed network name can not be found by a user
+network list call, it will be treated like one was not provided except that a
+warning will be logged stating that it couldn't be found.
+
+
+Accounts File
+"""""""""""""
+If you are using an accounts file to provide credentials for running Tempest
+then you can leverage it to also specify which network should be used with
+server creations on a per tenant/project and user pair basis. This provides
+the necessary flexibility to work with more intricate networking configurations
+by enabling the user to specify exactly which network to use for which
+tenants/projects. You can refer to the accounts.yaml sample file included in
+the tempest repo for the syntax around specifying networks in the file.
+
+However, specifying a network is not required when using an accounts file. If
+one is not specified you can use a fixed network name to specify the network to
+use when creating servers just as without an accounts file. However, any network
+specified in the accounts file will take precedence over the fixed network name
+provided. If no network is provided in the accounts file and a fixed network
+name is not set then no network will be included in create server requests.
+
+If a fixed network is provided and the accounts.yaml file also contains networks
+this has the benefit of enabling a couple more tests which require a static
+network to perform operations like server lists with a network filter. If a
+fixed network name is not provided these tests are skipped. Additionally, if a
+fixed network name is provided it will serve as a fallback in case of a
+misconfiguration or a missing network in the accounts file.
+
+
+With Tenant Isolation
+"""""""""""""""""""""
+With tenant isolation enabled and using nova-network then nothing changes. Your
+only option for configuration is to either set a fixed network name or not.
+However, in most cases it shouldn't matter because nova-network should have no
+problem booting a server with multiple networks. If this is not the case for
+your cloud then using an accounts file is recommended because it provides the
+necessary flexibility to describe your configuration. Tenant isolation is not
+able to dynamically allocate things as necessary if neutron is not enabled.
+
+With neutron and tenant isolation enabled there should not be any additional
+configuration necessary to enable Tempest to create servers with working
+networking, assuming you have properly configured the network section to work
+for your cloud. Tempest will dynamically create the neutron resources necessary
+to enable using servers with that network. Also, just as with the accounts
+file, if you specify a fixed network name while using neutron and tenant
+isolation it will enable running tests which require a static network and it
+will additionally be used as a fallback for server creation. However, unlike
+accounts.yaml this should never be triggered.
+
+Configuring Available Services
+------------------------------
+OpenStack is really a constellation of several different projects which
+are running together to create a cloud. However which projects you're running
+is not set in stone, and which services are running is up to the deployer.
+Tempest however needs to know which services are available so it can figure
+out which tests it is able to run and certain setup steps which differ based
+on the available services.
+
+The *service_available* section of the config file is used to set which
+services are available. It contains a boolean option for each service (except
+for keystone which is a hard requirement) set it to True if the service is
+available or False if it is not.
+
+Service Catalog
+^^^^^^^^^^^^^^^
+Each project which has its own REST API contains an entry in the service
+catalog. Like most things in OpenStack this is also completely configurable.
+However, for tempest to be able to figure out the endpoints to send REST API
+calls for each service to it needs to know how that project is defined in the
+service catalog. There are 3 options for each service section to accomplish
+this:
+
+ #. catalog_type
+ #. endpoint_type
+ #. region
+
+Setting *catalog_type* and *endpoint_type* should normally give Tempest enough
+information to determine which endpoint it should pull from the service
+catalog to use for talking to that particular service. However, if you're cloud
+has multiple regions available and you need to specify a particular one to use
+a service you can set the *region* option in that service's section.
+
+It should also be noted that the default values for these options are set
+to what devstack uses. (which is a de facto standard for service catalog
+entries) So often nothing actually needs to be set on these options to enable
+communication to a particular service. It is only if you are either not using
+the same *catalog_type* as devstack or you want Tempest to talk to a different
+endpoint type instead of publicURL for a service that these need to be changed.
+
+
+Service feature configuration
+-----------------------------
+
+OpenStack provides its deployers a myriad of different configuration options
+to enable anyone deploying it to create a cloud tailor-made for any individual
+use case. It provides options for several different backend type, databases,
+message queues, etc. However, the downside to this configurability is that
+certain operations and features aren't supported depending on the configuration.
+These features may or may not be discoverable from the API so the burden is
+often on the user to figure out what the cloud they're talking to supports.
+Besides the obvious interoperability issues with this it also leaves Tempest
+in an interesting situation trying to figure out which tests are expected to
+work. However, Tempest tests do not rely on dynamic api discovery for a feature
+(assuming one exists). Instead Tempest has to be explicitly configured as to
+which optional features are enabled. This is in order to prevent bugs in the
+discovery mechanisms from masking failures.
+
+The service feature-enabled config sections are how Tempest addresses the
+optional feature question. Each service that has tests for optional features
+contains one of these sections. The only options in it are boolean options
+with the name of a feature which is used. If it is set to false any test which
+depends on that functionality will be skipped. For a complete list of all these
+options refer to the sample config file.
+
+
+API Extensions
+^^^^^^^^^^^^^^
+The service feature-enabled sections often contain an *api-extensions* option
+(or in the case of swift a *discoverable_apis* option) this is used to tell
+tempest which api extensions (or configurable middleware) is used in your
+deployment. It has 2 valid config states, either it contains a single value
+"all" (which is the default) which means that every api extension is assumed
+to be enabled, or it is set to a list of each individual extension that is
+enabled for that service.
diff --git a/tempest/api/compute/admin/test_aggregates.py b/tempest/api/compute/admin/test_aggregates.py
index 3a34a2e..c4cb11a 100644
--- a/tempest/api/compute/admin/test_aggregates.py
+++ b/tempest/api/compute/admin/test_aggregates.py
@@ -102,7 +102,7 @@
         aggregate = self.client.create_aggregate(name=aggregate_name)
         self.addCleanup(self.client.delete_aggregate, aggregate['id'])
 
-        body = self.client.get_aggregate(aggregate['id'])
+        body = self.client.show_aggregate(aggregate['id'])
         self.assertEqual(aggregate['name'], body['name'])
         self.assertEqual(aggregate['availability_zone'],
                          body['availability_zone'])
@@ -114,7 +114,7 @@
         self.assertEqual(meta, body["metadata"])
 
         # verify the metadata has been set
-        body = self.client.get_aggregate(aggregate['id'])
+        body = self.client.show_aggregate(aggregate['id'])
         self.assertEqual(meta, body["metadata"])
 
     @test.attr(type='gate')
@@ -198,7 +198,7 @@
         self.client.add_host(aggregate['id'], self.host)
         self.addCleanup(self.client.remove_host, aggregate['id'], self.host)
 
-        body = self.client.get_aggregate(aggregate['id'])
+        body = self.client.show_aggregate(aggregate['id'])
         self.assertEqual(aggregate_name, body['name'])
         self.assertIsNone(body['availability_zone'])
         self.assertIn(self.host, body['hosts'])
diff --git a/tempest/api/compute/admin/test_aggregates_negative.py b/tempest/api/compute/admin/test_aggregates_negative.py
index f6d6ad3..882986c 100644
--- a/tempest/api/compute/admin/test_aggregates_negative.py
+++ b/tempest/api/compute/admin/test_aggregates_negative.py
@@ -110,7 +110,7 @@
         self.addCleanup(self.client.delete_aggregate, aggregate['id'])
 
         self.assertRaises(lib_exc.Forbidden,
-                          self.user_client.get_aggregate,
+                          self.user_client.show_aggregate,
                           aggregate['id'])
 
     @test.attr(type=['negative', 'gate'])
@@ -125,7 +125,7 @@
     def test_aggregate_get_details_with_invalid_id(self):
         # Get aggregate details with invalid id should raise exceptions.
         self.assertRaises(lib_exc.NotFound,
-                          self.client.get_aggregate, -1)
+                          self.client.show_aggregate, -1)
 
     @test.attr(type=['negative', 'gate'])
     @test.idempotent_id('0ef07828-12b4-45ba-87cc-41425faf5711')
diff --git a/tempest/api/compute/admin/test_availability_zone.py b/tempest/api/compute/admin/test_availability_zone.py
index eadc15a..1ec171b 100644
--- a/tempest/api/compute/admin/test_availability_zone.py
+++ b/tempest/api/compute/admin/test_availability_zone.py
@@ -32,12 +32,12 @@
     @test.idempotent_id('d3431479-8a09-4f76-aa2d-26dc580cb27c')
     def test_get_availability_zone_list(self):
         # List of availability zone
-        availability_zone = self.client.get_availability_zone_list()
+        availability_zone = self.client.list_availability_zones()
         self.assertTrue(len(availability_zone) > 0)
 
     @test.attr(type='gate')
     @test.idempotent_id('ef726c58-530f-44c2-968c-c7bed22d5b8c')
     def test_get_availability_zone_list_detail(self):
         # List of availability zones and available services
-        availability_zone = self.client.get_availability_zone_list_detail()
+        availability_zone = self.client.list_availability_zones(detail=True)
         self.assertTrue(len(availability_zone) > 0)
diff --git a/tempest/api/compute/admin/test_availability_zone_negative.py b/tempest/api/compute/admin/test_availability_zone_negative.py
index d6e577e..e9de628 100644
--- a/tempest/api/compute/admin/test_availability_zone_negative.py
+++ b/tempest/api/compute/admin/test_availability_zone_negative.py
@@ -36,4 +36,4 @@
         # non-administrator user
         self.assertRaises(
             lib_exc.Forbidden,
-            self.non_adm_client.get_availability_zone_list_detail)
+            self.non_adm_client.list_availability_zones, detail=True)
diff --git a/tempest/api/compute/admin/test_baremetal_nodes.py b/tempest/api/compute/admin/test_baremetal_nodes.py
index 64099c3..9b88938 100644
--- a/tempest/api/compute/admin/test_baremetal_nodes.py
+++ b/tempest/api/compute/admin/test_baremetal_nodes.py
@@ -52,5 +52,5 @@
 
         # Test getting each individually
         for node in test_nodes:
-            baremetal_node = self.client.get_baremetal_node(node['uuid'])
+            baremetal_node = self.client.show_baremetal_node(node['uuid'])
             self.assertEqual(node['uuid'], baremetal_node['id'])
diff --git a/tempest/api/compute/certificates/test_certificates.py b/tempest/api/compute/certificates/test_certificates.py
index 2be201a..4fe87ad 100644
--- a/tempest/api/compute/certificates/test_certificates.py
+++ b/tempest/api/compute/certificates/test_certificates.py
@@ -33,6 +33,6 @@
     @test.idempotent_id('3ac273d0-92d2-4632-bdfc-afbc21d4606c')
     def test_get_root_certificate(self):
         # get the root certificate
-        body = self.certificates_client.get_certificate('root')
+        body = self.certificates_client.show_certificate('root')
         self.assertIn('data', body)
         self.assertIn('private_key', body)
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 e069f6e..3a6b42d 100644
--- a/tempest/api/compute/security_groups/test_security_groups_negative.py
+++ b/tempest/api/compute/security_groups/test_security_groups_negative.py
@@ -156,7 +156,7 @@
 
     @test.idempotent_id('00579617-fe04-4e1c-9d08-ca7467d2e34b')
     @testtools.skipIf(CONF.service_available.neutron,
-                      "Neutron not check the security_group_id")
+                      "Neutron does not check the security group ID")
     @test.attr(type=['negative', 'smoke'])
     @test.services('network')
     def test_update_security_group_with_invalid_sg_id(self):
@@ -171,7 +171,7 @@
 
     @test.idempotent_id('cda8d8b4-59f8-4087-821d-20cf5a03b3b1')
     @testtools.skipIf(CONF.service_available.neutron,
-                      "Neutron not check the security_group_name")
+                      "Neutron does not check the security group name")
     @test.attr(type=['negative', 'smoke'])
     @test.services('network')
     def test_update_security_group_with_invalid_sg_name(self):
@@ -187,7 +187,7 @@
 
     @test.idempotent_id('97d12b1c-a610-4194-93f1-ba859e718b45')
     @testtools.skipIf(CONF.service_available.neutron,
-                      "Neutron not check the security_group_description")
+                      "Neutron does not check the security group description")
     @test.attr(type=['negative', 'smoke'])
     @test.services('network')
     def test_update_security_group_with_invalid_sg_des(self):
diff --git a/tempest/api/compute/servers/test_availability_zone.py b/tempest/api/compute/servers/test_availability_zone.py
index f3650ac..8d3f31c 100644
--- a/tempest/api/compute/servers/test_availability_zone.py
+++ b/tempest/api/compute/servers/test_availability_zone.py
@@ -32,5 +32,5 @@
     @test.idempotent_id('a8333aa2-205c-449f-a828-d38c2489bf25')
     def test_get_availability_zone_list_with_non_admin_user(self):
         # List of availability zone with non-administrator user
-        availability_zone = self.client.get_availability_zone_list()
+        availability_zone = self.client.list_availability_zones()
         self.assertTrue(len(availability_zone) > 0)
diff --git a/tempest/api/compute/test_extensions.py b/tempest/api/compute/test_extensions.py
index 5b14071..09927fc 100644
--- a/tempest/api/compute/test_extensions.py
+++ b/tempest/api/compute/test_extensions.py
@@ -50,5 +50,5 @@
     @test.attr(type='gate')
     def test_get_extension(self):
         # get the specified extensions
-        extension = self.extensions_client.get_extension('os-consoles')
+        extension = self.extensions_client.show_extension('os-consoles')
         self.assertEqual('os-consoles', extension['alias'])
diff --git a/tempest/api/data_processing/base.py b/tempest/api/data_processing/base.py
index d91fbaa..5a903b7 100644
--- a/tempest/api/data_processing/base.py
+++ b/tempest/api/data_processing/base.py
@@ -12,14 +12,216 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from collections import OrderedDict
+
+import six
 from tempest_lib import exceptions as lib_exc
 
 from tempest import config
+from tempest import exceptions
 import tempest.test
 
 
 CONF = config.CONF
 
+"""Default templates.
+There should always be at least a master1 and a worker1 node
+group template."""
+DEFAULT_TEMPLATES = {
+    'vanilla': OrderedDict([
+        ('2.6.0', {
+            'NODES': {
+                'master1': {
+                    'count': 1,
+                    'node_processes': ['namenode', 'resourcemanager',
+                                       'hiveserver']
+                },
+                'master2': {
+                    'count': 1,
+                    'node_processes': ['oozie', 'historyserver',
+                                       'secondarynamenode']
+                },
+                'worker1': {
+                    'count': 1,
+                    'node_processes': ['datanode', 'nodemanager'],
+                    'node_configs': {
+                        'MapReduce': {
+                            'yarn.app.mapreduce.am.resource.mb': 256,
+                            'yarn.app.mapreduce.am.command-opts': '-Xmx256m'
+                        },
+                        'YARN': {
+                            'yarn.scheduler.minimum-allocation-mb': 256,
+                            'yarn.scheduler.maximum-allocation-mb': 1024,
+                            'yarn.nodemanager.vmem-check-enabled': False
+                        }
+                    }
+                }
+            },
+            'cluster_configs': {
+                'HDFS': {
+                    'dfs.replication': 1
+                }
+            }
+        }),
+        ('1.2.1', {
+            'NODES': {
+                'master1': {
+                    'count': 1,
+                    'node_processes': ['namenode', 'jobtracker']
+                },
+                'worker1': {
+                    'count': 1,
+                    'node_processes': ['datanode', 'tasktracker'],
+                    'node_configs': {
+                        'HDFS': {
+                            'Data Node Heap Size': 1024
+                        },
+                        'MapReduce': {
+                            'Task Tracker Heap Size': 1024
+                        }
+                    }
+                }
+            },
+            'cluster_configs': {
+                'HDFS': {
+                    'dfs.replication': 1
+                },
+                'MapReduce': {
+                    'mapred.map.tasks.speculative.execution': False,
+                    'mapred.child.java.opts': '-Xmx500m'
+                },
+                'general': {
+                    'Enable Swift': False
+                }
+            }
+        })
+    ]),
+    'hdp': OrderedDict([
+        ('2.0.6', {
+            'NODES': {
+                'master1': {
+                    'count': 1,
+                    'node_processes': ['NAMENODE', 'SECONDARY_NAMENODE',
+                                       'ZOOKEEPER_SERVER', 'AMBARI_SERVER',
+                                       'HISTORYSERVER', 'RESOURCEMANAGER',
+                                       'GANGLIA_SERVER', 'NAGIOS_SERVER',
+                                       'OOZIE_SERVER']
+                },
+                'worker1': {
+                    'count': 1,
+                    'node_processes': ['HDFS_CLIENT', 'DATANODE',
+                                       'YARN_CLIENT', 'ZOOKEEPER_CLIENT',
+                                       'MAPREDUCE2_CLIENT', 'NODEMANAGER',
+                                       'PIG', 'OOZIE_CLIENT']
+                }
+            },
+            'cluster_configs': {
+                'HDFS': {
+                    'dfs.replication': 1
+                }
+            }
+        })
+    ]),
+    'spark': OrderedDict([
+        ('1.0.0', {
+            'NODES': {
+                'master1': {
+                    'count': 1,
+                    'node_processes': ['namenode', 'master']
+                },
+                'worker1': {
+                    'count': 1,
+                    'node_processes': ['datanode', 'slave']
+                }
+            },
+            'cluster_configs': {
+                'HDFS': {
+                    'dfs.replication': 1
+                }
+            }
+        })
+    ]),
+    'cdh': OrderedDict([
+        ('5.3.0', {
+            'NODES': {
+                'master1': {
+                    'count': 1,
+                    'node_processes': ['CLOUDERA_MANAGER']
+                },
+                'master2': {
+                    'count': 1,
+                    'node_processes': ['HDFS_NAMENODE',
+                                       'YARN_RESOURCEMANAGER']
+                },
+                'master3': {
+                    'count': 1,
+                    'node_processes': ['OOZIE_SERVER', 'YARN_JOBHISTORY',
+                                       'HDFS_SECONDARYNAMENODE',
+                                       'HIVE_METASTORE', 'HIVE_SERVER2']
+                },
+                'worker1': {
+                    'count': 1,
+                    'node_processes': ['YARN_NODEMANAGER', 'HDFS_DATANODE']
+                }
+            },
+            'cluster_configs': {
+                'HDFS': {
+                    'dfs_replication': 1
+                }
+            }
+        }),
+        ('5', {
+            'NODES': {
+                'master1': {
+                    'count': 1,
+                    'node_processes': ['CLOUDERA_MANAGER']
+                },
+                'master2': {
+                    'count': 1,
+                    'node_processes': ['HDFS_NAMENODE',
+                                       'YARN_RESOURCEMANAGER']
+                },
+                'master3': {
+                    'count': 1,
+                    'node_processes': ['OOZIE_SERVER', 'YARN_JOBHISTORY',
+                                       'HDFS_SECONDARYNAMENODE',
+                                       'HIVE_METASTORE', 'HIVE_SERVER2']
+                },
+                'worker1': {
+                    'count': 1,
+                    'node_processes': ['YARN_NODEMANAGER', 'HDFS_DATANODE']
+                }
+            },
+            'cluster_configs': {
+                'HDFS': {
+                    'dfs_replication': 1
+                }
+            }
+        })
+    ]),
+    'mapr': OrderedDict([
+        ('4.0.1.mrv2', {
+            'NODES': {
+                'master1': {
+                    'count': 1,
+                    'node_processes': ['CLDB', 'FileServer', 'ZooKeeper',
+                                       'NodeManager', 'ResourceManager',
+                                       'HistoryServer', 'Oozie']
+                },
+                'worker1': {
+                    'count': 1,
+                    'node_processes': ['FileServer', 'NodeManager', 'Pig']
+                }
+            },
+            'cluster_configs': {
+                'Hive': {
+                    'Hive Version': '0.13',
+                }
+            }
+        })
+    ]),
+}
+
 
 class BaseDataProcessingTest(tempest.test.BaseTestCase):
 
@@ -28,6 +230,7 @@
         super(BaseDataProcessingTest, cls).skip_checks()
         if not CONF.service_available.sahara:
             raise cls.skipException('Sahara support is required')
+        cls.default_plugin = cls._get_default_plugin()
 
     @classmethod
     def setup_credentials(cls):
@@ -43,6 +246,10 @@
     def resource_setup(cls):
         super(BaseDataProcessingTest, cls).resource_setup()
 
+        cls.default_version = cls._get_default_version()
+        if cls.default_plugin is not None and cls.default_version is None:
+            raise exceptions.InvalidConfiguration(
+                message="No known Sahara plugin version was found")
         cls.flavor_ref = CONF.compute.flavor_ref
 
         # add lists for watched resources
@@ -172,3 +379,100 @@
         cls._jobs.append(resp_body['id'])
 
         return resp_body
+
+    @classmethod
+    def _get_default_plugin(cls):
+        """Returns the default plugin used for testing."""
+        if len(CONF.data_processing_feature_enabled.plugins) == 0:
+            return None
+
+        for plugin in CONF.data_processing_feature_enabled.plugins:
+            if plugin in DEFAULT_TEMPLATES.keys():
+                break
+        else:
+            plugin = ''
+        return plugin
+
+    @classmethod
+    def _get_default_version(cls):
+        """Returns the default plugin version used for testing.
+        This is gathered separately from the plugin to allow
+        the usage of plugin name in skip_checks. This method is
+        rather invoked into resource_setup, which allows API calls
+        and exceptions.
+        """
+        if not cls.default_plugin:
+            return None
+        plugin = cls.client.get_plugin(cls.default_plugin)
+
+        for version in DEFAULT_TEMPLATES[cls.default_plugin].keys():
+            if version in plugin['versions']:
+                break
+        else:
+            version = None
+
+        return version
+
+    @classmethod
+    def get_node_group_template(cls, nodegroup='worker1'):
+        """Returns a node group template for the default plugin."""
+        try:
+            plugin_data = (
+                DEFAULT_TEMPLATES[cls.default_plugin][cls.default_version]
+            )
+            nodegroup_data = plugin_data['NODES'][nodegroup]
+            node_group_template = {
+                'description': 'Test node group template',
+                'plugin_name': cls.default_plugin,
+                'hadoop_version': cls.default_version,
+                'node_processes': nodegroup_data['node_processes'],
+                'flavor_id': cls.flavor_ref,
+                'node_configs': nodegroup_data.get('node_configs', {}),
+            }
+            return node_group_template
+        except (IndexError, KeyError):
+            return None
+
+    @classmethod
+    def get_cluster_template(cls, node_group_template_ids=None):
+        """Returns a cluster template for the default plugin.
+        node_group_template_defined contains the type and ID of pre-defined
+        node group templates that have to be used in the cluster template
+        (instead of dynamically defining them with 'node_processes').
+        """
+        if node_group_template_ids is None:
+            node_group_template_ids = {}
+        try:
+            plugin_data = (
+                DEFAULT_TEMPLATES[cls.default_plugin][cls.default_version]
+            )
+
+            all_node_groups = []
+            for ng_name, ng_data in six.iteritems(plugin_data['NODES']):
+                node_group = {
+                    'name': '%s-node' % (ng_name),
+                    'flavor_id': cls.flavor_ref,
+                    'count': ng_data['count']
+                }
+                if ng_name in node_group_template_ids.keys():
+                    # node group already defined, use it
+                    node_group['node_group_template_id'] = (
+                        node_group_template_ids[ng_name]
+                    )
+                else:
+                    # node_processes list defined on-the-fly
+                    node_group['node_processes'] = ng_data['node_processes']
+                if 'node_configs' in ng_data:
+                    node_group['node_configs'] = ng_data['node_configs']
+                all_node_groups.append(node_group)
+
+            cluster_template = {
+                'description': 'Test cluster template',
+                'plugin_name': cls.default_plugin,
+                'hadoop_version': cls.default_version,
+                'cluster_configs': plugin_data.get('cluster_configs', {}),
+                'node_groups': all_node_groups,
+            }
+            return cluster_template
+        except (IndexError, KeyError):
+            return None
diff --git a/tempest/api/data_processing/test_cluster_templates.py b/tempest/api/data_processing/test_cluster_templates.py
index 8a63c3f..cebf493 100644
--- a/tempest/api/data_processing/test_cluster_templates.py
+++ b/tempest/api/data_processing/test_cluster_templates.py
@@ -15,6 +15,7 @@
 from tempest_lib.common.utils import data_utils
 
 from tempest.api.data_processing import base as dp_base
+from tempest import exceptions
 from tempest import test
 
 
@@ -23,55 +24,30 @@
     sahara/restapi/rest_api_v1.0.html#cluster-templates
     """
     @classmethod
+    def skip_checks(cls):
+        super(ClusterTemplateTest, cls).skip_checks()
+        if cls.default_plugin is None:
+            raise cls.skipException("No Sahara plugins configured")
+
+    @classmethod
     def resource_setup(cls):
         super(ClusterTemplateTest, cls).resource_setup()
-        # create node group template
-        node_group_template = {
-            'name': data_utils.rand_name('sahara-ng-template'),
-            'description': 'Test node group template',
-            'plugin_name': 'vanilla',
-            'hadoop_version': '1.2.1',
-            'node_processes': ['datanode'],
-            'flavor_id': cls.flavor_ref,
-            'node_configs': {
-                'HDFS': {
-                    'Data Node Heap Size': 1024
-                }
-            }
-        }
-        resp_body = cls.create_node_group_template(**node_group_template)
-        node_group_template_id = resp_body['id']
 
-        cls.full_cluster_template = {
-            'description': 'Test cluster template',
-            'plugin_name': 'vanilla',
-            'hadoop_version': '1.2.1',
-            'cluster_configs': {
-                'HDFS': {
-                    'dfs.replication': 2
-                },
-                'MapReduce': {
-                    'mapred.map.tasks.speculative.execution': False,
-                    'mapred.child.java.opts': '-Xmx500m'
-                },
-                'general': {
-                    'Enable Swift': False
-                }
-            },
-            'node_groups': [
-                {
-                    'name': 'master-node',
-                    'flavor_id': cls.flavor_ref,
-                    'node_processes': ['namenode'],
-                    'count': 1
-                },
-                {
-                    'name': 'worker-node',
-                    'node_group_template_id': node_group_template_id,
-                    'count': 3
-                }
-            ]
-        }
+        # pre-define a node group templates
+        node_group_template_w = cls.get_node_group_template('worker1')
+        if node_group_template_w is None:
+            raise exceptions.InvalidConfiguration(
+                message="No known Sahara plugin was found")
+
+        node_group_template_w['name'] = data_utils.rand_name(
+            'sahara-ng-template')
+        resp_body = cls.create_node_group_template(**node_group_template_w)
+        node_group_template_id = resp_body['id']
+        configured_node_group_templates = {'worker1': node_group_template_id}
+
+        cls.full_cluster_template = cls.get_cluster_template(
+            configured_node_group_templates)
+
         # create cls.cluster_template variable to use for comparison to cluster
         # template response body. The 'node_groups' field in the response body
         # has some extra info that post body does not have. The 'node_groups'
diff --git a/tempest/api/data_processing/test_node_group_templates.py b/tempest/api/data_processing/test_node_group_templates.py
index d7381f4..4068027 100644
--- a/tempest/api/data_processing/test_node_group_templates.py
+++ b/tempest/api/data_processing/test_node_group_templates.py
@@ -19,27 +19,16 @@
 
 
 class NodeGroupTemplateTest(dp_base.BaseDataProcessingTest):
+
+    @classmethod
+    def skip_checks(cls):
+        super(NodeGroupTemplateTest, cls).skip_checks()
+        if cls.default_plugin is None:
+            raise cls.skipException("No Sahara plugins configured")
+
     @classmethod
     def resource_setup(cls):
         super(NodeGroupTemplateTest, cls).resource_setup()
-        cls.node_group_template = {
-            'description': 'Test node group template',
-            'plugin_name': 'vanilla',
-            'hadoop_version': '1.2.1',
-            'node_processes': [
-                'datanode',
-                'tasktracker'
-            ],
-            'flavor_id': cls.flavor_ref,
-            'node_configs': {
-                'HDFS': {
-                    'Data Node Heap Size': 1024
-                },
-                'MapReduce': {
-                    'Task Tracker Heap Size': 1024
-                }
-            }
-        }
 
     def _create_node_group_template(self, template_name=None):
         """Creates Node Group Template with optional name specified.
@@ -47,6 +36,10 @@
         It creates template, ensures template name and response body.
         Returns id and name of created template.
         """
+        self.node_group_template = self.get_node_group_template()
+        self.assertIsNotNone(self.node_group_template,
+                             "No known Sahara plugin was found")
+
         if not template_name:
             # generate random name if it's not specified
             template_name = data_utils.rand_name('sahara-ng-template')
diff --git a/tempest/api/telemetry/test_telemetry_alarming_api.py b/tempest/api/telemetry/test_telemetry_alarming_api.py
index 8bc97e8..d106b28 100644
--- a/tempest/api/telemetry/test_telemetry_alarming_api.py
+++ b/tempest/api/telemetry/test_telemetry_alarming_api.py
@@ -67,13 +67,13 @@
         self.assertEqual(alarm_name, body['name'])
         self.assertDictContainsSubset(new_rule, body['threshold_rule'])
         # Get and verify details of an alarm after update
-        body = self.telemetry_client.get_alarm(alarm_id)
+        body = self.telemetry_client.show_alarm(alarm_id)
         self.assertEqual(alarm_name, body['name'])
         self.assertDictContainsSubset(new_rule, body['threshold_rule'])
         # Delete alarm and verify if deleted
         self.telemetry_client.delete_alarm(alarm_id)
         self.assertRaises(lib_exc.NotFound,
-                          self.telemetry_client.get_alarm, alarm_id)
+                          self.telemetry_client.show_alarm, alarm_id)
 
     @test.attr(type="gate")
     @test.idempotent_id('aca49486-70bb-4016-87e0-f6131374f741')
@@ -87,7 +87,7 @@
                                                       new_state)
         self.assertEqual(new_state, state.data)
         # Get alarm state and verify
-        state = self.telemetry_client.alarm_get_state(alarm['alarm_id'])
+        state = self.telemetry_client.show_alarm_state(alarm['alarm_id'])
         self.assertEqual(new_state, state.data)
 
     @test.attr(type="gate")
@@ -106,4 +106,4 @@
         # Verify alarm delete
         self.telemetry_client.delete_alarm(alarm_id)
         self.assertRaises(lib_exc.NotFound,
-                          self.telemetry_client.get_alarm, alarm_id)
+                          self.telemetry_client.show_alarm, alarm_id)
diff --git a/tempest/api_schema/response/compute/servers.py b/tempest/api_schema/response/compute/servers.py
deleted file mode 100644
index 3950173..0000000
--- a/tempest/api_schema/response/compute/servers.py
+++ /dev/null
@@ -1,238 +0,0 @@
-# Copyright 2014 NEC Corporation.  All rights reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-import copy
-
-from tempest.api_schema.response.compute import parameter_types
-
-get_password = {
-    'status_code': [200],
-    'response_body': {
-        'type': 'object',
-        'properties': {
-            'password': {'type': 'string'}
-        },
-        'required': ['password']
-    }
-}
-
-get_vnc_console = {
-    'status_code': [200],
-    'response_body': {
-        'type': 'object',
-        'properties': {
-            'console': {
-                'type': 'object',
-                'properties': {
-                    'type': {'type': 'string'},
-                    'url': {
-                        'type': 'string',
-                        'format': 'uri'
-                    }
-                },
-                'required': ['type', 'url']
-            }
-        },
-        'required': ['console']
-    }
-}
-
-common_show_server = {
-    'type': 'object',
-    'properties': {
-        'id': {'type': 'string'},
-        'name': {'type': 'string'},
-        'status': {'type': 'string'},
-        'image': {'oneOf': [
-            {'type': 'object',
-                'properties': {
-                    'id': {'type': 'string'},
-                    'links': parameter_types.links
-                },
-                'required': ['id', 'links']},
-            {'type': ['string', 'null']}
-        ]},
-        'flavor': {
-            'type': 'object',
-            'properties': {
-                'id': {'type': 'string'},
-                'links': parameter_types.links
-            },
-            'required': ['id', 'links']
-        },
-        'fault': {
-            'type': 'object',
-            'properties': {
-                'code': {'type': 'integer'},
-                'created': {'type': 'string'},
-                'message': {'type': 'string'},
-                'details': {'type': 'string'},
-            },
-            # NOTE(gmann): 'details' is not necessary to be present
-            #  in the 'fault'. So it is not defined as 'required'.
-            'required': ['code', 'created', 'message']
-        },
-        'user_id': {'type': 'string'},
-        'tenant_id': {'type': 'string'},
-        'created': {'type': 'string'},
-        'updated': {'type': 'string'},
-        'progress': {'type': 'integer'},
-        'metadata': {'type': 'object'},
-        'links': parameter_types.links,
-        'addresses': parameter_types.addresses,
-    },
-    # NOTE(GMann): 'progress' attribute is present in the response
-    # only when server's status is one of the progress statuses
-    # ("ACTIVE","BUILD", "REBUILD", "RESIZE","VERIFY_RESIZE")
-    # 'fault' attribute is present in the response
-    # only when server's status is one of the  "ERROR", "DELETED".
-    # So they are not defined as 'required'.
-    'required': ['id', 'name', 'status', 'image', 'flavor',
-                 'user_id', 'tenant_id', 'created', 'updated',
-                 'metadata', 'links', 'addresses']
-}
-
-base_update_get_server = {
-    'status_code': [200],
-    'response_body': {
-        'type': 'object',
-        'properties': {
-            'server': common_show_server
-        },
-        'required': ['server']
-    }
-}
-
-delete_server = {
-    'status_code': [204],
-}
-
-set_server_metadata = {
-    'status_code': [200],
-    'response_body': {
-        'type': 'object',
-        'properties': {
-            'metadata': {
-                'type': 'object',
-                'patternProperties': {
-                    '^.+$': {'type': 'string'}
-                }
-            }
-        },
-        'required': ['metadata']
-    }
-}
-
-list_server_metadata = copy.deepcopy(set_server_metadata)
-
-update_server_metadata = copy.deepcopy(set_server_metadata)
-
-delete_server_metadata_item = {
-    'status_code': [204]
-}
-
-list_servers = {
-    'status_code': [200],
-    'response_body': {
-        'type': 'object',
-        'properties': {
-            'servers': {
-                'type': 'array',
-                'items': {
-                    'type': 'object',
-                    'properties': {
-                        'id': {'type': 'string'},
-                        'links': parameter_types.links,
-                        'name': {'type': 'string'}
-                    },
-                    'required': ['id', 'links', 'name']
-                }
-            },
-            'servers_links': parameter_types.links
-        },
-        # NOTE(gmann): servers_links attribute is not necessary to be
-        # present always So it is not 'required'.
-        'required': ['servers']
-    }
-}
-
-server_actions_common_schema = {
-    'status_code': [202]
-}
-
-server_actions_delete_password = {
-    'status_code': [204]
-}
-
-get_console_output = {
-    'status_code': [200],
-    'response_body': {
-        'type': 'object',
-        'properties': {
-            'output': {'type': 'string'}
-        },
-        'required': ['output']
-    }
-}
-
-common_instance_actions = {
-    'type': 'object',
-    'properties': {
-        'action': {'type': 'string'},
-        'request_id': {'type': 'string'},
-        'user_id': {'type': 'string'},
-        'project_id': {'type': 'string'},
-        'start_time': {'type': 'string'},
-        'message': {'type': ['string', 'null']}
-    },
-    'required': ['action', 'request_id', 'user_id', 'project_id',
-                 'start_time', 'message']
-}
-
-instance_action_events = {
-    'type': 'array',
-    'items': {
-        'type': 'object',
-        'properties': {
-            'event': {'type': 'string'},
-            'start_time': {'type': 'string'},
-            'finish_time': {'type': 'string'},
-            'result': {'type': 'string'},
-            'traceback': {'type': ['string', 'null']}
-        },
-        'required': ['event', 'start_time', 'finish_time', 'result',
-                     'traceback']
-    }
-}
-
-common_get_instance_action = copy.deepcopy(common_instance_actions)
-
-common_get_instance_action['properties'].update({
-    'events': instance_action_events})
-# 'events' does not come in response body always so it is not
-# defined as 'required'
-
-base_list_servers_detail = {
-    'status_code': [200],
-    'response_body': {
-        'type': 'object',
-        'properties': {
-            'servers': {
-                'type': 'array',
-                'items': common_show_server
-            }
-        },
-        'required': ['servers']
-    }
-}
diff --git a/tempest/api_schema/response/compute/v2_1/servers.py b/tempest/api_schema/response/compute/v2_1/servers.py
index ebee697..726f9b1 100644
--- a/tempest/api_schema/response/compute/v2_1/servers.py
+++ b/tempest/api_schema/response/compute/v2_1/servers.py
@@ -15,7 +15,6 @@
 import copy
 
 from tempest.api_schema.response.compute import parameter_types
-from tempest.api_schema.response.compute import servers
 
 create_server = {
     'status_code': [202],
@@ -46,24 +45,110 @@
 create_server_with_admin_pass['response_body']['properties']['server'][
     'required'].append('adminPass')
 
-update_server = copy.deepcopy(servers.base_update_get_server)
-update_server['response_body']['properties']['server']['properties'].update({
-    'hostId': {'type': 'string'},
-    'OS-DCF:diskConfig': {'type': 'string'},
-    'accessIPv4': parameter_types.access_ip_v4,
-    'accessIPv6': parameter_types.access_ip_v6
-})
-update_server['response_body']['properties']['server']['required'].append(
-    # NOTE: OS-DCF:diskConfig and accessIPv4/v6 are API
-    # extensions, and some environments return a response
-    # without these attributes. So they are not 'required'.
-    'hostId'
-)
+list_servers = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'servers': {
+                'type': 'array',
+                'items': {
+                    'type': 'object',
+                    'properties': {
+                        'id': {'type': 'string'},
+                        'links': parameter_types.links,
+                        'name': {'type': 'string'}
+                    },
+                    'required': ['id', 'links', 'name']
+                }
+            },
+            'servers_links': parameter_types.links
+        },
+        # NOTE(gmann): servers_links attribute is not necessary to be
+        # present always So it is not 'required'.
+        'required': ['servers']
+    }
+}
 
-get_server = copy.deepcopy(servers.base_update_get_server)
-get_server['response_body']['properties']['server']['properties'].update({
+delete_server = {
+    'status_code': [204],
+}
+
+common_show_server = {
+    'type': 'object',
+    'properties': {
+        'id': {'type': 'string'},
+        'name': {'type': 'string'},
+        'status': {'type': 'string'},
+        'image': {'oneOf': [
+            {'type': 'object',
+                'properties': {
+                    'id': {'type': 'string'},
+                    'links': parameter_types.links
+                },
+                'required': ['id', 'links']},
+            {'type': ['string', 'null']}
+        ]},
+        'flavor': {
+            'type': 'object',
+            'properties': {
+                'id': {'type': 'string'},
+                'links': parameter_types.links
+            },
+            'required': ['id', 'links']
+        },
+        'fault': {
+            'type': 'object',
+            'properties': {
+                'code': {'type': 'integer'},
+                'created': {'type': 'string'},
+                'message': {'type': 'string'},
+                'details': {'type': 'string'},
+            },
+            # NOTE(gmann): 'details' is not necessary to be present
+            #  in the 'fault'. So it is not defined as 'required'.
+            'required': ['code', 'created', 'message']
+        },
+        'user_id': {'type': 'string'},
+        'tenant_id': {'type': 'string'},
+        'created': {'type': 'string'},
+        'updated': {'type': 'string'},
+        'progress': {'type': 'integer'},
+        'metadata': {'type': 'object'},
+        'links': parameter_types.links,
+        'addresses': parameter_types.addresses,
+        'hostId': {'type': 'string'},
+        'OS-DCF:diskConfig': {'type': 'string'},
+        'accessIPv4': parameter_types.access_ip_v4,
+        'accessIPv6': parameter_types.access_ip_v6
+    },
+    # NOTE(GMann): 'progress' attribute is present in the response
+    # only when server's status is one of the progress statuses
+    # ("ACTIVE","BUILD", "REBUILD", "RESIZE","VERIFY_RESIZE")
+    # 'fault' attribute is present in the response
+    # only when server's status is one of the  "ERROR", "DELETED".
+    # OS-DCF:diskConfig and accessIPv4/v6 are API
+    # extensions, and some environments return a response
+    # without these attributes.So these are not defined as 'required'.
+    'required': ['id', 'name', 'status', 'image', 'flavor',
+                 'user_id', 'tenant_id', 'created', 'updated',
+                 'metadata', 'links', 'addresses', 'hostId']
+}
+
+update_server = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'server': common_show_server
+        },
+        'required': ['server']
+    }
+}
+
+server_detail = copy.deepcopy(common_show_server)
+server_detail['properties'].update({
     'key_name': {'type': ['string', 'null']},
-    'hostId': {'type': 'string'},
     'security_groups': {'type': 'array'},
 
     # NOTE: Non-admin users also can see "OS-SRV-USG" and "OS-EXT-AZ"
@@ -81,27 +166,64 @@
     'OS-EXT-SRV-ATTR:instance_name': {'type': 'string'},
     'OS-EXT-SRV-ATTR:hypervisor_hostname': {'type': ['string', 'null']},
     'os-extended-volumes:volumes_attached': {'type': 'array'},
-    'OS-DCF:diskConfig': {'type': 'string'},
-    'accessIPv4': parameter_types.access_ip_v4,
-    'accessIPv6': parameter_types.access_ip_v6,
     'config_drive': {'type': 'string'}
 })
-get_server['response_body']['properties']['server']['required'].append(
-    # NOTE: OS-SRV-USG, OS-EXT-AZ, OS-EXT-STS, OS-EXT-SRV-ATTR,
-    # os-extended-volumes, OS-DCF and accessIPv4/v6 are API
-    # extension, and some environments return a response without
-    # these attributes. So they are not 'required'.
-    'hostId'
-)
+server_detail['properties']['addresses']['patternProperties'][
+    '^[a-zA-Z0-9-_.]+$']['items']['properties'].update({
+        'OS-EXT-IPS:type': {'type': 'string'},
+        'OS-EXT-IPS-MAC:mac_addr': parameter_types.mac_address})
 # NOTE(gmann): Update OS-EXT-IPS:type and OS-EXT-IPS-MAC:mac_addr
 # attributes in server address. Those are API extension,
 # and some environments return a response without
 # these attributes. So they are not 'required'.
-get_server['response_body']['properties']['server']['properties'][
-    'addresses']['patternProperties']['^[a-zA-Z0-9-_.]+$']['items'][
-    'properties'].update({
-        'OS-EXT-IPS:type': {'type': 'string'},
-        'OS-EXT-IPS-MAC:mac_addr': parameter_types.mac_address})
+
+get_server = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'server': server_detail
+        },
+        'required': ['server']
+    }
+}
+
+list_servers_detail = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'servers': {
+                'type': 'array',
+                'items': server_detail
+            },
+            'servers_links': parameter_types.links
+        },
+        # NOTE(gmann): servers_links attribute is not necessary to be
+        # present always So it is not 'required'.
+        'required': ['servers']
+    }
+}
+
+rebuild_server = copy.deepcopy(update_server)
+rebuild_server['status_code'] = [202]
+
+rebuild_server_with_admin_pass = copy.deepcopy(rebuild_server)
+rebuild_server_with_admin_pass['response_body']['properties']['server'][
+    'properties'].update({'adminPass': {'type': 'string'}})
+rebuild_server_with_admin_pass['response_body']['properties']['server'][
+    'required'].append('adminPass')
+
+rescue_server = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'adminPass': {'type': 'string'}
+        },
+        'required': ['adminPass']
+    }
+}
 
 list_virtual_interfaces = {
     'status_code': [200],
@@ -174,30 +296,11 @@
     'volumeAttachments']['items']['properties'].update(
     {'serverId': {'type': 'string'}})
 
-set_get_server_metadata_item = {
-    'status_code': [200],
-    'response_body': {
-        'type': 'object',
-        'properties': {
-            'meta': {
-                'type': 'object',
-                'patternProperties': {
-                    '^.+$': {'type': 'string'}
-                }
-            }
-        },
-        'required': ['meta']
-    }
-}
-
 list_addresses_by_network = {
     'status_code': [200],
     'response_body': parameter_types.addresses
 }
 
-server_actions_confirm_resize = copy.deepcopy(
-    servers.server_actions_delete_password)
-
 list_addresses = {
     'status_code': [200],
     'response_body': {
@@ -258,10 +361,36 @@
     }
 }
 
-instance_actions_object = copy.deepcopy(servers.common_instance_actions)
-instance_actions_object[
-    'properties'].update({'instance_uuid': {'type': 'string'}})
-instance_actions_object['required'].extend(['instance_uuid'])
+instance_actions = {
+    'type': 'object',
+    'properties': {
+        'action': {'type': 'string'},
+        'request_id': {'type': 'string'},
+        'user_id': {'type': 'string'},
+        'project_id': {'type': 'string'},
+        'start_time': {'type': 'string'},
+        'message': {'type': ['string', 'null']},
+        'instance_uuid': {'type': 'string'}
+    },
+    'required': ['action', 'request_id', 'user_id', 'project_id',
+                 'start_time', 'message', 'instance_uuid']
+}
+
+instance_action_events = {
+    'type': 'array',
+    'items': {
+        'type': 'object',
+        'properties': {
+            'event': {'type': 'string'},
+            'start_time': {'type': 'string'},
+            'finish_time': {'type': 'string'},
+            'result': {'type': 'string'},
+            'traceback': {'type': ['string', 'null']}
+        },
+        'required': ['event', 'start_time', 'finish_time', 'result',
+                     'traceback']
+    }
+}
 
 list_instance_actions = {
     'status_code': [200],
@@ -270,93 +399,120 @@
         'properties': {
             'instanceActions': {
                 'type': 'array',
-                'items': instance_actions_object
+                'items': instance_actions
             }
         },
         'required': ['instanceActions']
     }
 }
 
-get_instance_actions_object = copy.deepcopy(servers.common_get_instance_action)
-get_instance_actions_object[
-    'properties'].update({'instance_uuid': {'type': 'string'}})
-get_instance_actions_object['required'].extend(['instance_uuid'])
+instance_actions_with_events = copy.deepcopy(instance_actions)
+instance_actions_with_events['properties'].update({
+    'events': instance_action_events})
+# 'events' does not come in response body always so it is not
+# defined as 'required'
 
 get_instance_action = {
     'status_code': [200],
     'response_body': {
         'type': 'object',
         'properties': {
-            'instanceAction': get_instance_actions_object
+            'instanceAction': instance_actions_with_events
         },
         'required': ['instanceAction']
     }
 }
 
-list_servers_detail = copy.deepcopy(servers.base_list_servers_detail)
-list_servers_detail['response_body']['properties']['servers']['items'][
-    'properties'].update({
-        'key_name': {'type': ['string', 'null']},
-        'hostId': {'type': 'string'},
-        'OS-DCF:diskConfig': {'type': 'string'},
-        'security_groups': {'type': 'array'},
-
-        # NOTE: Non-admin users also can see "OS-SRV-USG" and "OS-EXT-AZ"
-        # attributes.
-        'OS-SRV-USG:launched_at': {'type': ['string', 'null']},
-        'OS-SRV-USG:terminated_at': {'type': ['string', 'null']},
-        'OS-EXT-AZ:availability_zone': {'type': 'string'},
-
-        # NOTE: Admin users only can see "OS-EXT-STS" and "OS-EXT-SRV-ATTR"
-        # attributes.
-        'OS-EXT-STS:task_state': {'type': ['string', 'null']},
-        'OS-EXT-STS:vm_state': {'type': 'string'},
-        'OS-EXT-STS:power_state': {'type': 'integer'},
-        'OS-EXT-SRV-ATTR:host': {'type': ['string', 'null']},
-        'OS-EXT-SRV-ATTR:instance_name': {'type': 'string'},
-        'OS-EXT-SRV-ATTR:hypervisor_hostname': {'type': ['string', 'null']},
-        'os-extended-volumes:volumes_attached': {'type': 'array'},
-        'accessIPv4': parameter_types.access_ip_v4,
-        'accessIPv6': parameter_types.access_ip_v6,
-        'config_drive': {'type': 'string'}
-    })
-# NOTE(GMann): OS-SRV-USG, OS-EXT-AZ, OS-EXT-STS, OS-EXT-SRV-ATTR,
-# os-extended-volumes, OS-DCF and accessIPv4/v6 are API
-# extensions, and some environments return a response without
-# these attributes. So they are not 'required'.
-list_servers_detail['response_body']['properties']['servers']['items'][
-    'required'].append('hostId')
-# NOTE(gmann): Update OS-EXT-IPS:type and OS-EXT-IPS-MAC:mac_addr
-# attributes in server address. Those are API extension,
-# and some environments return a response without
-# these attributes. So they are not 'required'.
-list_servers_detail['response_body']['properties']['servers']['items'][
-    'properties']['addresses']['patternProperties']['^[a-zA-Z0-9-_.]+$'][
-    'items']['properties'].update({
-        'OS-EXT-IPS:type': {'type': 'string'},
-        'OS-EXT-IPS-MAC:mac_addr': parameter_types.mac_address})
-# Defining 'servers_links' attributes for V2 server schema
-list_servers_detail['response_body'][
-    'properties'].update({'servers_links': parameter_types.links})
-# NOTE(gmann): servers_links attribute is not necessary to be
-# present always So it is not 'required'.
-
-rebuild_server = copy.deepcopy(update_server)
-rebuild_server['status_code'] = [202]
-
-rebuild_server_with_admin_pass = copy.deepcopy(rebuild_server)
-rebuild_server_with_admin_pass['response_body']['properties']['server'][
-    'properties'].update({'adminPass': {'type': 'string'}})
-rebuild_server_with_admin_pass['response_body']['properties']['server'][
-    'required'].append('adminPass')
-
-rescue_server = {
+get_password = {
     'status_code': [200],
     'response_body': {
         'type': 'object',
         'properties': {
-            'adminPass': {'type': 'string'}
+            'password': {'type': 'string'}
         },
-        'required': ['adminPass']
+        'required': ['password']
     }
 }
+
+get_vnc_console = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'console': {
+                'type': 'object',
+                'properties': {
+                    'type': {'type': 'string'},
+                    'url': {
+                        'type': 'string',
+                        'format': 'uri'
+                    }
+                },
+                'required': ['type', 'url']
+            }
+        },
+        'required': ['console']
+    }
+}
+
+get_console_output = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'output': {'type': 'string'}
+        },
+        'required': ['output']
+    }
+}
+
+set_server_metadata = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'metadata': {
+                'type': 'object',
+                'patternProperties': {
+                    '^.+$': {'type': 'string'}
+                }
+            }
+        },
+        'required': ['metadata']
+    }
+}
+
+list_server_metadata = copy.deepcopy(set_server_metadata)
+
+update_server_metadata = copy.deepcopy(set_server_metadata)
+
+delete_server_metadata_item = {
+    'status_code': [204]
+}
+
+set_get_server_metadata_item = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'meta': {
+                'type': 'object',
+                'patternProperties': {
+                    '^.+$': {'type': 'string'}
+                }
+            }
+        },
+        'required': ['meta']
+    }
+}
+
+server_actions_common_schema = {
+    'status_code': [202]
+}
+
+server_actions_delete_password = {
+    'status_code': [204]
+}
+
+server_actions_confirm_resize = copy.deepcopy(
+    server_actions_delete_password)
diff --git a/tempest/api_schema/response/compute/version.py b/tempest/api_schema/response/compute/version.py
index 32c6d96..6579c63 100644
--- a/tempest/api_schema/response/compute/version.py
+++ b/tempest/api_schema/response/compute/version.py
@@ -45,8 +45,12 @@
                         }
                     },
                     'status': {'type': 'string'},
-                    'updated': {'type': 'string', 'format': 'date-time'}
+                    'updated': {'type': 'string', 'format': 'date-time'},
+                    'version': {'type': 'string'},
+                    'min_version': {'type': 'string'}
                 },
+                # NOTE: version and min_version have been added since Kilo,
+                # so they should not be required.
                 'required': ['id', 'links', 'media-types', 'status', 'updated']
             }
         },
diff --git a/tempest/common/accounts.py b/tempest/common/accounts.py
index acf6d4f..93c8bcf 100644
--- a/tempest/common/accounts.py
+++ b/tempest/common/accounts.py
@@ -180,12 +180,20 @@
             useable_hashes = hashes
         return useable_hashes
 
+    def _sanitize_creds(self, creds):
+        temp_creds = creds.copy()
+        temp_creds.pop('password')
+        return temp_creds
+
     def _get_creds(self, roles=None):
         if self.use_default_creds:
             raise exceptions.InvalidConfiguration(
                 "Account file %s doesn't exist" % CONF.auth.test_accounts_file)
         useable_hashes = self._get_match_hash_list(roles)
         free_hash = self._get_free_hash(useable_hashes)
+        clean_creds = self._sanitize_creds(
+            self.hash_dict['creds'][free_hash])
+        LOG.info('%s allocated creds:\n%s' % (self.name, clean_creds))
         return self._wrap_creds_with_network(free_hash)
 
     @lockutils.synchronized('test_accounts_io', external=True)
@@ -216,7 +224,9 @@
 
     def remove_credentials(self, creds):
         _hash = self.get_hash(creds)
+        clean_creds = self._sanitize_creds(self.hash_dict['creds'][_hash])
         self.remove_hash(_hash)
+        LOG.info("%s returned allocated creds:\n%s" % (self.name, clean_creds))
 
     def get_primary_creds(self):
         if self.isolated_creds.get('primary'):
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index d2c41f0..cc152d2 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -319,10 +319,18 @@
 
         if username is None:
             username = CONF.scenario.ssh_user
-        if private_key is None:
-            private_key = self.keypair['private_key']
+        # Set this with 'keypair' or others to log in with keypair or
+        # username/password.
+        if CONF.compute.ssh_auth_method == 'keypair':
+            password = None
+            if private_key is None:
+                private_key = self.keypair['private_key']
+        else:
+            password = CONF.compute.image_ssh_password
+            private_key = None
         linux_client = remote_client.RemoteClient(ip, username,
-                                                  pkey=private_key)
+                                                  pkey=private_key,
+                                                  password=password)
         try:
             linux_client.validate_authentication()
         except Exception:
diff --git a/tempest/scenario/test_aggregates_basic_ops.py b/tempest/scenario/test_aggregates_basic_ops.py
index c5e8012..b1d3418 100644
--- a/tempest/scenario/test_aggregates_basic_ops.py
+++ b/tempest/scenario/test_aggregates_basic_ops.py
@@ -80,7 +80,7 @@
 
     def _check_aggregate_details(self, aggregate, aggregate_name, azone,
                                  hosts, metadata):
-        aggregate = self.aggregates_client.get_aggregate(aggregate['id'])
+        aggregate = self.aggregates_client.show_aggregate(aggregate['id'])
         self.assertEqual(aggregate_name, aggregate['name'])
         self.assertEqual(azone, aggregate['availability_zone'])
         self.assertEqual(hosts, aggregate['hosts'])
diff --git a/tempest/services/compute/json/aggregates_client.py b/tempest/services/compute/json/aggregates_client.py
index 36a347b..6c02b63 100644
--- a/tempest/services/compute/json/aggregates_client.py
+++ b/tempest/services/compute/json/aggregates_client.py
@@ -30,7 +30,7 @@
         self.validate_response(schema.list_aggregates, resp, body)
         return service_client.ResponseBodyList(resp, body['aggregates'])
 
-    def get_aggregate(self, aggregate_id):
+    def show_aggregate(self, aggregate_id):
         """Get details of the given aggregate."""
         resp, body = self.get("os-aggregates/%s" % str(aggregate_id))
         body = json.loads(body)
@@ -67,7 +67,7 @@
 
     def is_resource_deleted(self, id):
         try:
-            self.get_aggregate(id)
+            self.show_aggregate(id)
         except lib_exc.NotFound:
             return True
         return False
diff --git a/tempest/services/compute/json/availability_zone_client.py b/tempest/services/compute/json/availability_zone_client.py
index 6c50398..925d79f 100644
--- a/tempest/services/compute/json/availability_zone_client.py
+++ b/tempest/services/compute/json/availability_zone_client.py
@@ -22,17 +22,15 @@
 
 class AvailabilityZoneClientJSON(service_client.ServiceClient):
 
-    def get_availability_zone_list(self):
-        resp, body = self.get('os-availability-zone')
-        body = json.loads(body)
-        self.validate_response(schema.list_availability_zone_list, resp, body)
-        return service_client.ResponseBodyList(resp,
-                                               body['availabilityZoneInfo'])
+    def list_availability_zones(self, detail=False):
+        url = 'os-availability-zone'
+        schema_list = schema.list_availability_zone_list
+        if detail:
+            url += '/detail'
+            schema_list = schema.list_availability_zone_list_detail
 
-    def get_availability_zone_list_detail(self):
-        resp, body = self.get('os-availability-zone/detail')
+        resp, body = self.get(url)
         body = json.loads(body)
-        self.validate_response(schema.list_availability_zone_list_detail, resp,
-                               body)
+        self.validate_response(schema_list, resp, body)
         return service_client.ResponseBodyList(resp,
                                                body['availabilityZoneInfo'])
diff --git a/tempest/services/compute/json/baremetal_nodes_client.py b/tempest/services/compute/json/baremetal_nodes_client.py
index d8bbadd..e4a4e88 100644
--- a/tempest/services/compute/json/baremetal_nodes_client.py
+++ b/tempest/services/compute/json/baremetal_nodes_client.py
@@ -34,7 +34,7 @@
         self.validate_response(schema.list_baremetal_nodes, resp, body)
         return service_client.ResponseBodyList(resp, body['nodes'])
 
-    def get_baremetal_node(self, baremetal_node_id):
+    def show_baremetal_node(self, baremetal_node_id):
         """Returns the details of a single baremetal node."""
         url = 'os-baremetal-nodes/%s' % baremetal_node_id
         resp, body = self.get(url)
diff --git a/tempest/services/compute/json/certificates_client.py b/tempest/services/compute/json/certificates_client.py
index e6b72bb..752a48e 100644
--- a/tempest/services/compute/json/certificates_client.py
+++ b/tempest/services/compute/json/certificates_client.py
@@ -21,7 +21,7 @@
 
 class CertificatesClientJSON(service_client.ServiceClient):
 
-    def get_certificate(self, id):
+    def show_certificate(self, id):
         url = "os-certificates/%s" % (id)
         resp, body = self.get(url)
         body = json.loads(body)
diff --git a/tempest/services/compute/json/extensions_client.py b/tempest/services/compute/json/extensions_client.py
index 5c69085..265b381 100644
--- a/tempest/services/compute/json/extensions_client.py
+++ b/tempest/services/compute/json/extensions_client.py
@@ -33,7 +33,7 @@
         exts = extensions['extensions']
         return any([e for e in exts if e['name'] == extension])
 
-    def get_extension(self, extension_alias):
+    def show_extension(self, extension_alias):
         resp, body = self.get('extensions/%s' % extension_alias)
         body = json.loads(body)
         return service_client.ResponseBody(resp, body['extension'])
diff --git a/tempest/services/compute/json/interfaces_client.py b/tempest/services/compute/json/interfaces_client.py
index c3bfa99..223e90b 100644
--- a/tempest/services/compute/json/interfaces_client.py
+++ b/tempest/services/compute/json/interfaces_client.py
@@ -16,8 +16,8 @@
 import json
 import time
 
-from tempest.api_schema.response.compute import servers as servers_schema
 from tempest.api_schema.response.compute.v2_1 import interfaces as schema
+from tempest.api_schema.response.compute.v2_1 import servers as servers_schema
 from tempest.common import service_client
 from tempest import exceptions
 
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index bd27668..c9ba2c3 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -20,7 +20,6 @@
 
 from tempest_lib import exceptions as lib_exc
 
-from tempest.api_schema.response.compute import servers as common_schema
 from tempest.api_schema.response.compute.v2_1 import servers as schema
 from tempest.common import service_client
 from tempest.common import waiters
@@ -147,7 +146,7 @@
     def delete_server(self, server_id):
         """Deletes the given server."""
         resp, body = self.delete("servers/%s" % str(server_id))
-        self.validate_response(common_schema.delete_server, resp, body)
+        self.validate_response(schema.delete_server, resp, body)
         return service_client.ResponseBody(resp, body)
 
     def list_servers(self, params=None):
@@ -159,7 +158,7 @@
 
         resp, body = self.get(url)
         body = json.loads(body)
-        self.validate_response(common_schema.list_servers, resp, body)
+        self.validate_response(schema.list_servers, resp, body)
         return service_client.ResponseBody(resp, body)
 
     def list_servers_with_detail(self, params=None):
@@ -216,7 +215,7 @@
         return service_client.ResponseBody(resp, body)
 
     def action(self, server_id, action_name, response_key,
-               schema=common_schema.server_actions_common_schema,
+               schema=schema.server_actions_common_schema,
                response_class=service_client.ResponseBody, **kwargs):
         post_body = json.dumps({action_name: kwargs})
         resp, body = self.post('servers/%s/action' % str(server_id),
@@ -253,7 +252,7 @@
         resp, body = self.get("servers/%s/os-server-password" %
                               str(server_id))
         body = json.loads(body)
-        self.validate_response(common_schema.get_password, resp, body)
+        self.validate_response(schema.get_password, resp, body)
         return service_client.ResponseBody(resp, body)
 
     def delete_password(self, server_id):
@@ -264,7 +263,7 @@
         """
         resp, body = self.delete("servers/%s/os-server-password" %
                                  str(server_id))
-        self.validate_response(common_schema.server_actions_delete_password,
+        self.validate_response(schema.server_actions_delete_password,
                                resp, body)
         return service_client.ResponseBody(resp, body)
 
@@ -306,7 +305,7 @@
     def list_server_metadata(self, server_id):
         resp, body = self.get("servers/%s/metadata" % str(server_id))
         body = json.loads(body)
-        self.validate_response(common_schema.list_server_metadata, resp, body)
+        self.validate_response(schema.list_server_metadata, resp, body)
         return service_client.ResponseBody(resp, body['metadata'])
 
     def set_server_metadata(self, server_id, meta, no_metadata_field=False):
@@ -317,7 +316,7 @@
         resp, body = self.put('servers/%s/metadata' % str(server_id),
                               post_body)
         body = json.loads(body)
-        self.validate_response(common_schema.set_server_metadata, resp, body)
+        self.validate_response(schema.set_server_metadata, resp, body)
         return service_client.ResponseBody(resp, body['metadata'])
 
     def update_server_metadata(self, server_id, meta):
@@ -325,7 +324,7 @@
         resp, body = self.post('servers/%s/metadata' % str(server_id),
                                post_body)
         body = json.loads(body)
-        self.validate_response(common_schema.update_server_metadata,
+        self.validate_response(schema.update_server_metadata,
                                resp, body)
         return service_client.ResponseBody(resp, body['metadata'])
 
@@ -348,7 +347,7 @@
     def delete_server_metadata_item(self, server_id, key):
         resp, body = self.delete("servers/%s/metadata/%s" %
                                  (str(server_id), key))
-        self.validate_response(common_schema.delete_server_metadata_item,
+        self.validate_response(schema.delete_server_metadata_item,
                                resp, body)
         return service_client.ResponseBody(resp, body)
 
@@ -415,7 +414,7 @@
         req_body = json.dumps({'os-migrateLive': migrate_params})
 
         resp, body = self.post("servers/%s/action" % str(server_id), req_body)
-        self.validate_response(common_schema.server_actions_common_schema,
+        self.validate_response(schema.server_actions_common_schema,
                                resp, body)
         return service_client.ResponseBody(resp, body)
 
@@ -466,7 +465,7 @@
     def get_console_output(self, server_id, length):
         kwargs = {'length': length} if length else {}
         return self.action(server_id, 'os-getConsoleOutput', 'output',
-                           common_schema.get_console_output,
+                           schema.get_console_output,
                            response_class=service_client.ResponseBodyData,
                            **kwargs)
 
@@ -531,7 +530,7 @@
     def get_vnc_console(self, server_id, console_type):
         """Get URL of VNC console."""
         return self.action(server_id, "os-getVNCConsole",
-                           "console", common_schema.get_vnc_console,
+                           "console", schema.get_vnc_console,
                            type=console_type)
 
     def create_server_group(self, name, policies):
diff --git a/tempest/services/telemetry/json/telemetry_client.py b/tempest/services/telemetry/json/telemetry_client.py
index 36c123b..0c01908 100644
--- a/tempest/services/telemetry/json/telemetry_client.py
+++ b/tempest/services/telemetry/json/telemetry_client.py
@@ -50,7 +50,7 @@
         body = self.deserialize(body)
         return service_client.ResponseBody(resp, body)
 
-    def helper_list(self, uri, query=None, period=None):
+    def _helper_list(self, uri, query=None, period=None):
         uri_dict = {}
         if query:
             uri_dict = {'q.field': query[0],
@@ -67,32 +67,32 @@
 
     def list_resources(self, query=None):
         uri = '%s/resources' % self.uri_prefix
-        return self.helper_list(uri, query)
+        return self._helper_list(uri, query)
 
     def list_meters(self, query=None):
         uri = '%s/meters' % self.uri_prefix
-        return self.helper_list(uri, query)
+        return self._helper_list(uri, query)
 
     def list_alarms(self, query=None):
         uri = '%s/alarms' % self.uri_prefix
-        return self.helper_list(uri, query)
+        return self._helper_list(uri, query)
 
     def list_statistics(self, meter, period=None, query=None):
         uri = "%s/meters/%s/statistics" % (self.uri_prefix, meter)
-        return self.helper_list(uri, query, period)
+        return self._helper_list(uri, query, period)
 
     def list_samples(self, meter_id, query=None):
         uri = '%s/meters/%s' % (self.uri_prefix, meter_id)
-        return self.helper_list(uri, query)
+        return self._helper_list(uri, query)
 
-    def get_resource(self, resource_id):
+    def show_resource(self, resource_id):
         uri = '%s/resources/%s' % (self.uri_prefix, resource_id)
         resp, body = self.get(uri)
         self.expected_success(200, resp.status)
         body = self.deserialize(body)
         return service_client.ResponseBody(resp, body)
 
-    def get_alarm(self, alarm_id):
+    def show_alarm(self, alarm_id):
         uri = '%s/alarms/%s' % (self.uri_prefix, alarm_id)
         resp, body = self.get(uri)
         self.expected_success(200, resp.status)
@@ -123,7 +123,7 @@
         body = self.deserialize(body)
         return service_client.ResponseBody(resp, body)
 
-    def alarm_get_state(self, alarm_id):
+    def show_alarm_state(self, alarm_id):
         uri = "%s/alarms/%s/state" % (self.uri_prefix, alarm_id)
         resp, body = self.get(uri)
         self.expected_success(200, resp.status)