Merge "Add a control point for floating IP assignment"
diff --git a/HACKING.rst b/HACKING.rst
index 7d995c3..a74ff73 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -163,3 +163,32 @@
 - If the execution of a set of tests is required to be serialized then locking
   can be used to perform this. See AggregatesAdminTest in
   tempest.api.compute.admin for an example of using locking.
+
+Stress Tests in Tempest
+-----------------------
+Any tempest test case can be flagged as a stress test. With this flag it will
+be automatically discovery and used in the stress test runs. The stress test
+framework itself is a facility to spawn and control worker processes in order
+to find race conditions (see ``tempest/stress/`` for more information). Please
+note that these stress tests can't be used for benchmarking purposes since they
+don't measure any performance characteristics.
+
+Example::
+
+  @stresstest(class_setup_per='process')
+  def test_this_and_that(self):
+    ...
+
+This will flag the test ``test_this_and_that`` as a stress test. The parameter
+``class_setup_per`` gives control when the setUpClass function should be called.
+
+Good candidates for stress tests are:
+
+- Scenario tests
+- API tests that have a wide focus
+
+Sample Configuration File
+-------------------------
+The sample config file is autogenerated using a script. If any changes are made
+to the config variables in tempest then the sample config file must be
+regenerated. This can be done running the script: tools/generate_sample.sh
diff --git a/README.rst b/README.rst
index 0996022..96f6e4c 100644
--- a/README.rst
+++ b/README.rst
@@ -79,6 +79,9 @@
 document. The etc/tempest.conf.sample attempts to be a self
 documenting version of the configuration.
 
+The sample config file is auto generated using the script:
+tools/generate_sample.sh
+
 The most important pieces that are needed are the user ids, openstack
 endpoints, and basic flavors and images needed to run tests.
 
diff --git a/etc/README.txt b/etc/README.txt
deleted file mode 100644
index c7e5e6e..0000000
--- a/etc/README.txt
+++ /dev/null
@@ -1 +0,0 @@
-Copy config.ini.sample to config.ini, and update it to reflect your environment.
diff --git a/etc/TEMPEST_README.txt b/etc/TEMPEST_README.txt
deleted file mode 100644
index 50fa688..0000000
--- a/etc/TEMPEST_README.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-To run:
--rename the /etc/tempest.conf.sample file to tempest.conf
--Set the fields in the file to values relevant to your system
--Set the "authentication" value (basic or keystone_v2 currently supported)
--From the root directory of the project, run "./run_tests.sh" this will
-create the venv to install the project dependencies and run nosetests tempest
-to run all the tests
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 87bf758..1080ddf 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -1,448 +1,753 @@
 [DEFAULT]
-#log_config = /opt/stack/tempest/etc/logging.conf.sample
 
-# disable logging to the stderr
-use_stderr = false
+#
+# Options defined in tempest.openstack.common.lockutils
+#
 
-# log file
-log_file = tempest.log
+# Whether to disable inter-process locks (boolean value)
+#disable_process_locking=false
 
-# lock/semaphore base directory
-lock_path=/tmp
+# Directory to use for lock files. (string value)
+#lock_path=<None>
 
-default_log_levels=tempest.stress=INFO,amqplib=WARN,sqlalchemy=WARN,boto=WARN,suds=INFO,keystone=INFO,eventlet.wsgi.server=WARN
+
+#
+# Options defined in tempest.openstack.common.log
+#
+
+# Print debugging output (set logging level to DEBUG instead
+# of default WARNING level). (boolean value)
+#debug=false
+
+# Print more verbose output (set logging level to INFO instead
+# of default WARNING level). (boolean value)
+#verbose=false
+
+# Log output to standard error (boolean value)
+#use_stderr=true
+
+# format string to use for log messages with context (string
+# value)
+#logging_context_format_string=%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [%(request_id)s %(user)s %(tenant)s] %(instance)s%(message)s
+
+# format string to use for log messages without context
+# (string value)
+#logging_default_format_string=%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [-] %(instance)s%(message)s
+
+# data to append to log format when level is DEBUG (string
+# value)
+#logging_debug_format_suffix=%(funcName)s %(pathname)s:%(lineno)d
+
+# prefix each line of exception output with this format
+# (string value)
+#logging_exception_prefix=%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s %(instance)s
+
+# list of logger=LEVEL pairs (list value)
+#default_log_levels=amqplib=WARN,sqlalchemy=WARN,boto=WARN,suds=INFO,keystone=INFO,paramiko=INFO
+
+# publish error events (boolean value)
+#publish_errors=false
+
+# make deprecations fatal (boolean value)
+#fatal_deprecations=false
+
+# If an instance is passed with the log message, format it
+# like this (string value)
+#instance_format="[instance: %(uuid)s] "
+
+# If an instance UUID is passed with the log message, format
+# it like this (string value)
+#instance_uuid_format="[instance: %(uuid)s] "
+
+# If this option is specified, the logging configuration file
+# specified is used and overrides any other logging options
+# specified. Please see the Python logging module
+# documentation for details on logging configuration files.
+# (string value)
+#log_config=<None>
+
+# DEPRECATED. A logging.Formatter log message format string
+# which may use any of the available logging.LogRecord
+# attributes. This option is deprecated.  Please use
+# logging_context_format_string and
+# logging_default_format_string instead. (string value)
+#log_format=<None>
+
+# Format string for %%(asctime)s in log records. Default:
+# %(default)s (string value)
+#log_date_format=%Y-%m-%d %H:%M:%S
+
+# (Optional) Name of log file to output to. If no default is
+# set, logging will go to stdout. (string value)
+# Deprecated group/name - [DEFAULT]/logfile
+#log_file=<None>
+
+# (Optional) The base directory used for relative --log-file
+# paths (string value)
+# Deprecated group/name - [DEFAULT]/logdir
+#log_dir=<None>
+
+# Use syslog for logging. (boolean value)
+#use_syslog=false
+
+# syslog facility to receive log lines (string value)
+#syslog_log_facility=LOG_USER
+
 
 [identity]
-# This section contains configuration options that a variety of Tempest
-# test clients use when authenticating with different user/tenant
-# combinations
 
-# The type of endpoint for a Identity service. Unless you have a
-# custom Keystone service catalog implementation, you probably want to leave
-# this value as "identity"
-catalog_type = identity
-# Ignore SSL certificate validation failures? Use when in testing
-# environments that have self-signed SSL certs.
-disable_ssl_certificate_validation = false
-# URL for where to find the OpenStack Identity API endpoint (Keystone)
-uri = http://127.0.0.1:5000/v2.0/
-# URL for where to find the OpenStack V3 Identity API endpoint (Keystone)
-uri_v3 = http://127.0.0.1:5000/v3/
-# The identity region. Also used as the other services' region name unless
-# they are set explicitly.
-region = RegionOne
+#
+# Options defined in tempest.config
+#
 
-# This should be the username of a user WITHOUT administrative privileges
-username = demo
-# The above non-administrative user's password
-password = secret
-# The above non-administrative user's tenant name
-tenant_name = demo
+# Catalog type of the Identity service. (string value)
+#catalog_type=identity
 
-# This should be the username of an alternate user WITHOUT
-# administrative privileges
-alt_username = alt_demo
-# The above non-administrative user's password
-alt_password = secret
-# The above non-administrative user's tenant name
-alt_tenant_name = alt_demo
+# Set to True if using self-signed SSL certificates. (boolean
+# value)
+#disable_ssl_certificate_validation=false
 
-# This should be the username of a user WITH administrative privileges
-admin_username = admin
-# The above administrative user's password
-admin_password = secret
-# The above administrative user's tenant name
-admin_tenant_name = admin
+# Full URI of the OpenStack Identity API (Keystone), v2
+# (string value)
+#uri=<None>
 
-# The role that is required to administrate keystone.
-admin_role = admin
+# Full URI of the OpenStack Identity API (Keystone), v3
+# (string value)
+#uri_v3=<None>
 
-[compute]
-# This section contains configuration options used when executing tests
-# against the OpenStack Compute API.
+# The identity region name to use. Also used as the other
+# services' region name unless they are set explicitly. If no
+# such region is found in the service catalog, the first found
+# one is used. (string value)
+#region=RegionOne
 
-# Allows test cases to create/destroy tenants and users. This option
-# enables isolated test cases and better parallel execution,
-# but also requires that OpenStack Identity API admin credentials
-# are known.
-allow_tenant_isolation = true
+# Username to use for Nova API requests. (string value)
+#username=demo
 
-# Allows test cases to create/destroy tenants and users. This option
-# enables isolated test cases and better parallel execution,
-# but also requires that OpenStack Identity API admin credentials
-# are known.
-allow_tenant_reuse = true
+# Tenant name to use for Nova API requests. (string value)
+#tenant_name=demo
 
-# Reference data for tests. The ref and ref_alt should be
-# distinct images/flavors.
-image_ref = {$IMAGE_ID}
-image_ref_alt = {$IMAGE_ID_ALT}
-flavor_ref = 1
-flavor_ref_alt = 2
+# Role required to administrate keystone. (string value)
+#admin_role=admin
 
-# User name used to authenticate to an instance
-image_ssh_user = root
+# API key to use when authenticating. (string value)
+#password=pass
 
-# Password used to authenticate to an instance
-image_ssh_password = password
+# Username of alternate user to use for Nova API requests.
+# (string value)
+#alt_username=<None>
 
-# User name used to authenticate to an instance using the alternate image
-image_alt_ssh_user = root
+# Alternate user's Tenant name to use for Nova API requests.
+# (string value)
+#alt_tenant_name=<None>
 
-# Password used to authenticate to an instance using the alternate image
-image_alt_ssh_password = password
+# API key to use when authenticating as alternate user.
+# (string value)
+#alt_password=<None>
 
-# Number of seconds to wait while looping to check the status of an
-# instance that is building.
-build_interval = 10
+# Administrative Username to use forKeystone API requests.
+# (string value)
+#admin_username=admin
 
-# Number of seconds to time out on waiting for an instance
-# to build or reach an expected status
-build_timeout = 600
+# Administrative Tenant name to use for Keystone API requests.
+# (string value)
+#admin_tenant_name=admin
 
-# Run additional tests that use SSH for instance validation?
-# This requires the instances be routable from the host
-#  executing the tests
-run_ssh = false
+# API key to use when authenticating as admin. (string value)
+#admin_password=pass
 
-# Name of a user used to authenticate to an instance.
-ssh_user = cirros
 
-# Visible fixed network name
-fixed_network_name = private
+[stress]
 
-# Network id used for SSH (public, private, etc)
-network_for_ssh = public
+#
+# Options defined in tempest.config
+#
 
-# IP version of the address used for SSH
-ip_version_for_ssh = 4
+# Directory containing log files on the compute nodes (string
+# value)
+#nova_logdir=<None>
 
-# Number of seconds to wait to ping to an instance
-ping_timeout = 60
+# Maximum number of instances to create during test. (integer
+# value)
+#max_instances=16
 
-# Number of seconds to wait to authenticate to an instance
-ssh_timeout = 300
+# Controller host. (string value)
+#controller=<None>
 
-# Additinal wait time for clean state, when there is
-# no OS-EXT-STS extension availiable
-ready_wait = 0
+# Controller host. (string value)
+#target_controller=<None>
 
-# Number of seconds to wait for output from ssh channel
-ssh_channel_timeout = 60
+# ssh user. (string value)
+#target_ssh_user=<None>
 
-# Dose the SSH uses Floating IP?
-use_floatingip_for_ssh = true
+# Path to private key. (string value)
+#target_private_key_path=<None>
 
-# The type of endpoint for a Compute API service. Unless you have a
-# custom Keystone service catalog implementation, you probably want to leave
-# this value as "compute"
-catalog_type = compute
+# regexp for list of log files. (string value)
+#target_logfiles=<None>
 
-# The name of a region for compute. If empty or commented-out, the value of
-# identity.region is used instead. If no such region is found in the service
-# catalog, the first found one is used.
-#region = RegionOne
+# time (in seconds) between log file error checks. (integer
+# value)
+#log_check_interval=60
 
-# Expected first device name when a volume is attached to an instance
-volume_device_name = vdb
+# The number of threads created while stress test. (integer
+# value)
+#default_thread_number_per_action=4
 
-[compute-feature-enabled]
-# Does the Compute API support creation of images?
-create_image = true
-
-# For resize to work with libvirt/kvm, one of the following must be true:
-# Single node: allow_resize_to_same_host=true must be set in nova.conf
-# Cluster: the 'nova' user must have scp access between cluster nodes
-resize = true
-
-# Does the compute API support changing the admin password?
-change_password = false
-
-# Run live migration tests (requires 2 hosts)
-live_migration = false
-
-# Use block live migration (Otherwise, non-block migration will be
-# performed, which requires XenServer pools in case of using XS)
-block_migration_for_live_migration = false
-
-# Supports iSCSI block migration - depends on a XAPI supporting
-# relax-xsm-sr-check
-block_migrate_cinder_iscsi = false
-
-# When set to false, disk config tests are forced to skip
-disk_config = true
-
-# When set to false, flavor extra data tests are forced to skip
-flavor_extra = true
-
-[compute-admin]
-# This should be the username of a user WITH administrative privileges
-# If not defined the admin user from the identity section will be used
-username =
-# The above administrative user's password
-password =
-# The above administrative user's tenant name
-tenant_name =
-
-[image]
-# This section contains configuration options used when executing tests
-# against the OpenStack Images API
-
-# The type of endpoint for an Image API service. Unless you have a
-# custom Keystone service catalog implementation, you probably want to leave
-# this value as "image"
-catalog_type = image
-
-# The name of a region for image. If empty or commented-out, the value of
-# identity.region is used instead. If no such region is found in the service
-# catalog, the first found one is used.
-#region = RegionOne
-
-# HTTP image to use for glance http image testing
-http_image = http://download.cirros-cloud.net/0.3.1/cirros-0.3.1-x86_64-uec.tar.gz
 
 [image-feature-enabled]
-# Is the image api_v1 enabled
-api_v1 = True
-# Is the image api_v2 enabled
-api_v2 = True
+
+#
+# Options defined in tempest.config
+#
+
+# Is the v2 image API enabled (boolean value)
+#api_v2=true
+
+# Is the v1 image API enabled (boolean value)
+#api_v1=true
+
+
+[compute]
+
+#
+# Options defined in tempest.config
+#
+
+# Allows test cases to create/destroy tenants and users. This
+# option enables isolated test cases and better parallel
+# execution, but also requires that OpenStack Identity API
+# admin credentials are known. (boolean value)
+#allow_tenant_isolation=false
+
+# Valid secondary image reference to be used in tests. (string
+# value)
+#image_ref={$IMAGE_ID}
+
+# Valid secondary image reference to be used in tests. (string
+# value)
+#image_ref_alt={$IMAGE_ID_ALT}
+
+# Valid primary flavor to use in tests. (string value)
+#flavor_ref=1
+
+# Valid secondary flavor to be used in tests. (string value)
+#flavor_ref_alt=2
+
+# User name used to authenticate to an instance. (string
+# value)
+#image_ssh_user=root
+
+# Password used to authenticate to an instance. (string value)
+#image_ssh_password=password
+
+# User name used to authenticate to an instance using the
+# alternate image. (string value)
+#image_alt_ssh_user=root
+
+# Password used to authenticate to an instance using the
+# alternate image. (string value)
+#image_alt_ssh_password=password
+
+# Time in seconds between build status checks. (integer value)
+#build_interval=10
+
+# Timeout in seconds to wait for an instance to build.
+# (integer value)
+#build_timeout=300
+
+# Does the test environment support snapshots? (boolean value)
+#run_ssh=false
+
+# User name used to authenticate to an instance. (string
+# value)
+#ssh_user=root
+
+# Timeout in seconds to wait for ping to succeed. (integer
+# value)
+#ping_timeout=60
+
+# Timeout in seconds to wait for authentication to succeed.
+# (integer value)
+#ssh_timeout=300
+
+# Additional wait time for clean state, when there is no OS-
+# EXT-STS extension available (integer value)
+#ready_wait=0
+
+# Timeout in seconds to wait for output from ssh channel.
+# (integer value)
+#ssh_channel_timeout=60
+
+# Visible fixed network name  (string value)
+#fixed_network_name=private
+
+# Network used for SSH connections. (string value)
+#network_for_ssh=public
+
+# IP version used for SSH connections. (integer value)
+#ip_version_for_ssh=4
+
+# Dose the SSH uses Floating IP? (boolean value)
+#use_floatingip_for_ssh=true
+
+# Catalog type of the Compute service. (string value)
+#catalog_type=compute
+
+# The compute region name to use. If empty, the value of
+# identity.region is used instead. If no such region is found
+# in the service catalog, the first found one is used. (string
+# value)
+#region=
+
+# Catalog type of the Compute v3 service. (string value)
+#catalog_v3_type=computev3
+
+# Path to a private key file for SSH access to remote hosts
+# (string value)
+#path_to_private_key=<None>
+
+# Expected device name when a volume is attached to an
+# instance (string value)
+#volume_device_name=vdb
+
+# Time in seconds before a shelved instance is eligible for
+# removing from a host.  -1 never offload, 0 offload when
+# shelved. This time should be the same as the time of
+# nova.conf, and some tests will run for as long as the time.
+# (integer value)
+#shelved_offload_time=0
+
 
 [network]
-# This section contains configuration options used when executing tests
-# against the OpenStack Network API.
 
-# Version of the Neutron API
-api_version = v1.1
-# Catalog type of the Neutron Service
-catalog_type = network
+#
+# Options defined in tempest.config
+#
 
-# The name of a region for network. If empty or commented-out, the value of
-# identity.region is used instead. If no such region is found in the service
-# catalog, the first found one is used.
-#region = RegionOne
+# Catalog type of the Neutron service. (string value)
+#catalog_type=network
 
-# A large private cidr block from which to allocate smaller blocks for
-# tenant networks.
-tenant_network_cidr = 10.100.0.0/16
+# The network region name to use. If empty, the value of
+# identity.region is used instead. If no such region is found
+# in the service catalog, the first found one is used. (string
+# value)
+#region=
 
-# The mask bits used to partition the tenant block.
-tenant_network_mask_bits = 24
+# The cidr block to allocate tenant networks from (string
+# value)
+#tenant_network_cidr=10.100.0.0/16
 
-# If tenant networks are reachable, connectivity checks will be
-# performed directly against addresses on those networks.
-tenant_networks_reachable = false
+# The mask bits for tenant networks (integer value)
+#tenant_network_mask_bits=28
 
-# Id of the public network that provides external connectivity.
-public_network_id = {$PUBLIC_NETWORK_ID}
+# Whether tenant network connectivity should be evaluated
+# directly (boolean value)
+#tenant_networks_reachable=false
 
-# Id of a shared public router that provides external connectivity.
-# A shared public router would commonly be used where IP namespaces
-# were disabled.  If namespaces are enabled, it would be preferable
-# for each tenant to have their own router.
-public_router_id = {$PUBLIC_ROUTER_ID}
+# Id of the public network that provides external connectivity
+# (string value)
+#public_network_id=
+
+# Id of the public router that provides external connectivity
+# (string value)
+#public_router_id=
+
+
+[boto]
+
+#
+# Options defined in tempest.config
+#
+
+# EC2 URL (string value)
+#ec2_url=http://localhost:8773/services/Cloud
+
+# S3 URL (string value)
+#s3_url=http://localhost:8080
+
+# AWS Secret Key (string value)
+#aws_secret=<None>
+
+# AWS Access Key (string value)
+#aws_access=<None>
+
+# S3 Materials Path (string value)
+#s3_materials_path=/opt/stack/devstack/files/images/s3-materials/cirros-0.3.0
+
+# ARI Ramdisk Image manifest (string value)
+#ari_manifest=cirros-0.3.0-x86_64-initrd.manifest.xml
+
+# AMI Machine Image manifest (string value)
+#ami_manifest=cirros-0.3.0-x86_64-blank.img.manifest.xml
+
+# AKI Kernel Image manifest (string value)
+#aki_manifest=cirros-0.3.0-x86_64-vmlinuz.manifest.xml
+
+# Instance type (string value)
+#instance_type=m1.tiny
+
+# boto Http socket timeout (integer value)
+#http_socket_timeout=3
+
+# boto num_retries on error (integer value)
+#num_retries=1
+
+# Status Change Timeout (integer value)
+#build_timeout=60
+
+# Status Change Test Interval (integer value)
+#build_interval=1
+
+
+[scenario]
+
+#
+# Options defined in tempest.config
+#
+
+# Directory containing image files (string value)
+#img_dir=/opt/stack/new/devstack/files/images/cirros-0.3.1-x86_64-uec
+
+# AMI image file name (string value)
+#ami_img_file=cirros-0.3.1-x86_64-blank.img
+
+# ARI image file name (string value)
+#ari_img_file=cirros-0.3.1-x86_64-initrd
+
+# AKI image file name (string value)
+#aki_img_file=cirros-0.3.1-x86_64-vmlinuz
+
+# ssh username for the image file (string value)
+#ssh_user=cirros
+
+# specifies how many resources to request at once. Used for
+# large operations testing. (integer value)
+#large_ops_number=0
+
+
+[image]
+
+#
+# Options defined in tempest.config
+#
+
+# Catalog type of the Image service. (string value)
+#catalog_type=image
+
+# The image region name to use. If empty, the value of
+# identity.region is used instead. If no such region is found
+# in the service catalog, the first found one is used. (string
+# value)
+#region=
+
+# http accessible image (string value)
+#http_image=http://download.cirros-cloud.net/0.3.1/cirros-0.3.1-x86_64-uec.tar.gz
+
+
+[compute-admin]
+
+#
+# Options defined in tempest.config
+#
+
+# Administrative Username to use for Nova API requests.
+# (string value)
+#username=admin
+
+# Administrative Tenant name to use for Nova API requests.
+# (string value)
+#tenant_name=admin
+
+# API key to use when authenticating as admin. (string value)
+#password=pass
+
+
+[cli]
+
+#
+# Options defined in tempest.cli
+#
+
+# enable cli tests (boolean value)
+#enabled=true
+
+# directory where python client binaries are located (string
+# value)
+#cli_dir=/usr/local/bin
+
+# Number of seconds to wait on a CLI timeout (integer value)
+#timeout=15
 
 
 [volume]
-# This section contains the configuration options used when executing tests
-# against the OpenStack Block Storage API service
 
-# The type of endpoint for a Cinder or Block Storage API service.
-# Unless you have a custom Keystone service catalog implementation, you
-# probably want to leave this value as "volume"
-catalog_type = volume
-# The name of a region for volume. If empty or commented-out, the value of
-# identity.region is used instead. If no such region is found in the service
-# catalog, the first found one is used.
-#region = RegionOne
-# The disk format to use when copying a volume to image
-disk_format = raw
-# Number of seconds to wait while looping to check the status of a
-# volume that is being made available
-build_interval = 10
-# Number of seconds to time out on waiting for a volume
-# to be available or reach an expected status
-build_timeout = 300
-# If multi_backend is enabled there must be 2 volume_backend_names (
-# backend1_name and backend2_name) which have to be different)
-backend1_name = BACKEND_1
-backend2_name = BACKEND_2
-# Protocol and vendor of volume backend to target when testing volume-types.
-# You should update to reflect those exported by configured backend driver.
-storage_protocol = iSCSI
-vendor_name = Open Source
+#
+# Options defined in tempest.config
+#
 
-[volume-feature-enabled]
-#Runs Cinder multi-backend tests (requires 2 backends declared in cinder.conf)
-multi_backend = false
+# Time in seconds between volume availability checks. (integer
+# value)
+#build_interval=10
 
-[object-storage]
-# This section contains configuration options used when executing tests
-# against the OpenStack Object Storage API.
+# Timeout in seconds to wait for a volume to becomeavailable.
+# (integer value)
+#build_timeout=300
 
-# You can configure the credentials in the compute section
+# Catalog type of the Volume Service (string value)
+#catalog_type=volume
 
-# The type of endpoint for an Object Storage API service. Unless you have a
-# custom Keystone service catalog implementation, you probably want to leave
-# this value as "object-store"
-catalog_type = object-store
+# The volume region name to use. If empty, the value of
+# identity.region is used instead. If no such region is found
+# in the service catalog, the first found one is used. (string
+# value)
+#region=
 
-# The name of a region for object storage. If empty or commented-out, the
-# value of identity.region is used instead. If no such region is found in
-# the service catalog, the first found one is used.
-#region = RegionOne
+# Name of the backend1 (must be declared in cinder.conf)
+# (string value)
+#backend1_name=BACKEND_1
 
-# Number of seconds to time on waiting for a container to container
-# synchronization complete
-container_sync_timeout = 120
-# Number of seconds to wait while looping to check the status of a
-# container to container synchronization
-container_sync_interval = 5
+# Name of the backend2 (must be declared in cinder.conf)
+# (string value)
+#backend2_name=BACKEND_2
 
-# Set operator role for tests that require creating a container
-operator_role = Member
+# Backend protocol to target when creating volume types
+# (string value)
+#storage_protocol=iSCSI
 
-[object-feature-enabled]
-# Set to True if the Account Quota middleware is enabled
-accounts_quotas = True
-# Set to True if the Container Quota middleware is enabled
-container_quotas = True
+# Backend vendor to target when creating volume types (string
+# value)
+#vendor_name=Open Source
 
-[boto]
-# This section contains configuration options used when executing tests
-# with boto.
+# Disk format to use when copying a volume to image (string
+# value)
+#disk_format=raw
 
-# EC2 URL
-ec2_url = http://localhost:8773/services/Cloud
-# S3 URL
-s3_url = http://localhost:3333
-
-# Use keystone ec2-* command to get those values for your test user and tenant
-aws_access =
-aws_secret =
-
-# Image materials for S3 upload
-# ALL content of the specified directory will be uploaded to S3
-s3_materials_path = /opt/stack/devstack/files/images/s3-materials/cirros-0.3.1
-
-# The manifest.xml files, must be in the s3_materials_path directory
-# Subdirectories not allowed!
-# The filenames will be used as a Keys in the S3 Buckets
-
-# ARI Ramdisk manifest. Must be in the above s3_materials_path
-ari_manifest = cirros-0.3.1-x86_64-initrd.manifest.xml
-
-# AMI Machine Image manifest. Must be in the above s3_materials_path
-ami_manifest = cirros-0.3.1-x86_64-blank.img.manifest.xml
-
-# AKI Kernel Image manifest, Must be in the above s3_materials_path
-aki_manifest = cirros-0.3.1-x86_64-vmlinuz.manifest.xml
-
-# Instance type
-instance_type = m1.tiny
-
-# TCP/IP connection timeout
-http_socket_timeout = 5
-
-# Number of retries actions on connection or 5xx error
-num_retries = 1
-
-# Status change wait timout
-build_timeout = 120
-
-# Status change wait interval
-build_interval = 1
-
-[orchestration]
-# The type of endpoint for an Orchestration API service. Unless you have a
-# custom Keystone service catalog implementation, you probably want to leave
-# this value as "orchestration"
-catalog_type = orchestration
-
-# The name of a region for orchestration. If empty or commented-out, the value
-# of identity.region is used instead. If no such region is found in the service
-# catalog, the first found one is used.
-#region = RegionOne
-
-# Status change wait interval
-build_interval = 1
-
-# Status change wait timout. This may vary across environments as some some
-# tests spawn full VMs, which could be slow if the test is already in a VM.
-build_timeout = 300
-
-# Instance type for tests. Needs to be big enough for a
-# full OS plus the test workload
-instance_type = m1.micro
-
-# Name of heat-cfntools enabled image to use when launching test instances
-# If not specified, tests that spawn instances will not run
-#image_ref = ubuntu-vm-heat-cfntools
-
-# Name of existing keypair to launch servers with. The default is not to specify
-# any key, which will generate a keypair for each test class
-#keypair_name = heat_key
-
-[dashboard]
-# URL where to find the dashboard home page
-dashboard_url = 'http://localhost/'
-
-# URL where to submit the login form
-login_url = 'http://localhost/auth/login/'
-
-[scenario]
-# Directory containing image files
-img_dir = /opt/stack/new/devstack/files/images/cirros-0.3.1-x86_64-uec
-
-# AMI image file name
-ami_img_file = cirros-0.3.1-x86_64-blank.img
-
-# ARI image file name
-ari_img_file = cirros-0.3.1-x86_64-initrd
-
-# AKI image file name
-aki_img_file = cirros-0.3.1-x86_64-vmlinuz
-
-# ssh username for the image file
-ssh_user = cirros
-
-# specifies how many resources to request at once. Used for large operations
-# testing."
-large_ops_number = 0
-
-[cli]
-# Enable cli tests
-enabled = true
-# directory where python client binaries are located
-cli_dir = /usr/local/bin
-# Number of seconds to wait on a CLI timeout
-timeout = 15
-
-[service_available]
-# Whether or not cinder is expected to be available
-cinder = true
-# Whether or not neutron is expected to be available
-neutron = false
-# Whether or not glance is expected to be available
-glance = true
-# Whether or not swift is expected to be available
-swift = true
-# Whether or not nova is expected to be available
-nova = true
-# Whether or not Heat is expected to be available
-heat = false
-# Whether or not Ceilometer is expected to be available
-ceilometer = True
-# Whether or not horizon is expected to be available
-horizon = true
-
-[stress]
-# Maximum number of instances to create during test
-max_instances = 32
-# Time (in seconds) between log file error checks
-log_check_interval = 60
-# The default number of threads created while stress test
-default_thread_number_per_action = 4
 
 [debug]
-# Enable diagnostic commands
-enable = true
+
+#
+# Options defined in tempest.config
+#
+
+# Enable diagnostic commands (boolean value)
+#enable=true
+
+
+[dashboard]
+
+#
+# Options defined in tempest.config
+#
+
+# Where the dashboard can be found (string value)
+#dashboard_url=http://localhost/
+
+# Login page for the dashboard (string value)
+#login_url=http://localhost/auth/login/
+
+
+[orchestration]
+
+#
+# Options defined in tempest.config
+#
+
+# Catalog type of the Orchestration service. (string value)
+#catalog_type=orchestration
+
+# The orchestration region name to use. If empty, the value of
+# identity.region is used instead. If no such region is found
+# in the service catalog, the first found one is used. (string
+# value)
+#region=
+
+# Allows test cases to create/destroy tenants and users. This
+# option enables isolated test cases and better parallel
+# execution, but also requires that OpenStack Identity API
+# admin credentials are known. (boolean value)
+#allow_tenant_isolation=false
+
+# Time in seconds between build status checks. (integer value)
+#build_interval=1
+
+# Timeout in seconds to wait for a stack to build. (integer
+# value)
+#build_timeout=300
+
+# Instance type for tests. Needs to be big enough for a full
+# OS plus the test workload (string value)
+#instance_type=m1.micro
+
+# Name of heat-cfntools enabled image to use when launching
+# test instances. (string value)
+#image_ref=<None>
+
+# Name of existing keypair to launch servers with. (string
+# value)
+#keypair_name=<None>
+
+# Value must match heat configuration of the same name.
+# (integer value)
+#max_template_size=524288
+
+
+[object-storage]
+
+#
+# Options defined in tempest.config
+#
+
+# Catalog type of the Object-Storage service. (string value)
+#catalog_type=object-store
+
+# The object-storage region name to use. If empty, the value
+# of identity.region is used instead. If no such region is
+# found in the service catalog, the first found one is used.
+# (string value)
+#region=
+
+# Number of seconds to time on waiting for a containerto
+# container synchronization complete. (integer value)
+#container_sync_timeout=120
+
+# Number of seconds to wait while looping to check thestatus
+# of a container to container synchronization (integer value)
+#container_sync_interval=5
+
+# Role to add to users created for swift tests to enable
+# creating containers (string value)
+#operator_role=Member
+
+
+[network-feature-enabled]
+
+#
+# Options defined in tempest.config
+#
+
+# A list of enabled extensions with a special entry all which
+# indicates every extension is enabled (list value)
+#api_extensions=all
+
+
+[service_available]
+
+#
+# Options defined in tempest.config
+#
+
+# Whether or not cinder is expected to be available (boolean
+# value)
+#cinder=true
+
+# Whether or not neutron is expected to be available (boolean
+# value)
+#neutron=false
+
+# Whether or not glance is expected to be available (boolean
+# value)
+#glance=true
+
+# Whether or not swift is expected to be available (boolean
+# value)
+#swift=true
+
+# Whether or not nova is expected to be available (boolean
+# value)
+#nova=true
+
+# Whether or not Heat is expected to be available (boolean
+# value)
+#heat=false
+
+# Whether or not Ceilometer is expected to be available
+# (boolean value)
+#ceilometer=true
+
+# Whether or not Horizon is expected to be available (boolean
+# value)
+#horizon=true
+
+
+[compute-feature-enabled]
+
+#
+# Options defined in tempest.config
+#
+
+# If false, skip all nova v3 tests. (boolean value)
+#api_v3=true
+
+# If false, skip disk config tests (boolean value)
+#disk_config=true
+
+# A list of enabled extensions with a special entry all which
+# indicates every extension is enabled (list value)
+#api_extensions=all
+
+# A list of enabled v3 extensions with a special entry all
+# which indicates every extension is enabled (list value)
+#api_v3_extensions=all
+
+# Does the test environment support changing the admin
+# password? (boolean value)
+#change_password=false
+
+# Does the test environment support snapshots? (boolean value)
+#create_image=false
+
+# Does the test environment support resizing? (boolean value)
+#resize=false
+
+# Does the test environment support live migration available?
+# (boolean value)
+#live_migration=false
+
+# Does the test environment use block devices for live
+# migration (boolean value)
+#block_migration_for_live_migration=false
+
+# Does the test environment block migration support cinder
+# iSCSI volumes (boolean value)
+#block_migrate_cinder_iscsi=false
+
+
+[object-storage-feature-enabled]
+
+#
+# Options defined in tempest.config
+#
+
+# Set to True if the Container Quota middleware is enabled
+# (boolean value)
+#container_quotas=true
+
+# Set to True if the Account Quota middleware is enabled
+# (boolean value)
+#accounts_quotas=true
+
+# Set to True if the Crossdomain middleware is enabled
+# (boolean value)
+#crossdomain=true
+
+# Set to True if the TempURL middleware is enabled (boolean
+# value)
+#tempurl=true
+
+
+[volume-feature-enabled]
+
+#
+# Options defined in tempest.config
+#
+
+# Runs Cinder multi-backend test (requires 2 backends)
+# (boolean value)
+#multi_backend=false
+
+# A list of enabled extensions with a special entry all which
+# indicates every extension is enabled (list value)
+#api_extensions=all
+
+
diff --git a/etc/whitelist.yaml b/etc/whitelist.yaml
index e6d28f5..a8c5276 100644
--- a/etc/whitelist.yaml
+++ b/etc/whitelist.yaml
@@ -31,6 +31,14 @@
       message: "Getting disk size of instance"
     - module: "nova.virt.libvirt.driver"
       message: "No such file or directory: '/opt/stack/data/nova/instances"
+    - module: "nova.virt.libvirt.driver"
+      message: "Nova requires libvirt version 0\\.9\\.11 or greater"
+    - module: "nova.compute.manager"
+      message: "error during stop\\(\\) in sync_power_state"
+    - module: "nova.compute.manager"
+      message: "Instance failed network setup after 1 attempt"
+    - module: "nova.compute.manager"
+      message: "Periodic sync_power_state task had an error"
 
 g-api:
     - module: "glance.store.sheepdog"
@@ -38,18 +46,42 @@
         running command"
     - module: "swiftclient"
       message: "Container HEAD failed: .*404 Not Found"
+    - module: "glance.api.middleware.cache"
+      message: "however the registry did not contain metadata for that image"
+    - module: "oslo.messaging.notify._impl_messaging"
+      message: ".*"
 
 ceilometer-acompute:
     - module: "ceilometer.compute.pollsters.disk"
+      message: "Unable to read from monitor: Connection reset by peer"
+    - module: "ceilometer.compute.pollsters.disk"
+      message: "Requested operation is not valid: domain is not running"
+    - module: "ceilometer.compute.pollsters.net"
       message: "Requested operation is not valid: domain is not running"
     - module: "ceilometer.compute.pollsters.disk"
       message: "Domain not found: no domain with matching uuid"
     - module: "ceilometer.compute.pollsters.net"
+      message: "Domain not found: no domain with matching uuid"
+    - module: "ceilometer.compute.pollsters.net"
       message: "No module named libvirt"
+    - module: "ceilometer.compute.pollsters.net"
+      message: "Unable to write to monitor: Broken pipe"
+    - module: "ceilometer.compute.pollsters.cpu"
+      message: "Domain not found: no domain with matching uuid"
+    - module: "ceilometer.compute.pollsters.net"
+      message: ".*"
+    - module: "ceilometer.compute.pollsters.disk"
+      message: ".*"
 
 ceilometer-alarm-evaluator:
     - module: "ceilometer.alarm.service"
       message: "alarm evaluation cycle failed"
+    - module: "ceilometer.alarm.evaluator.threshold"
+      message: ".*"
+
+ceilometer-api:
+    - module: "wsme.api"
+      message: ".*"
 
 h-api:
     - module: "root"
@@ -81,37 +113,53 @@
       message: "\\{u'kernel_id'.*u'ramdisk_id':"
     - module: "nova.api.openstack.wsgi"
       message: "takes exactly 4 arguments"
+    - module: "nova.api.openstack"
+      message: "Caught error: Instance .* could not be found"
+    - module: "nova.api.metadata.handler"
+      message: "Failed to get metadata for instance id:"
 
 n-cond:
     - module: "nova.notifications"
       message: "Failed to send state update notification"
+    - module: "nova.openstack.common.rpc.amqp"
+      message: "Exception during message handling"
+    - module: "nova.openstack.common.rpc.common"
+      message: "but the actual state is deleting to caller"
+    - module: "nova.openstack.common.rpc.common"
+      message: "Traceback \\(most recent call last"
 
 n-sch:
     - module: "nova.scheduler.filter_scheduler"
       message: "Error from last host: "
 
+n-net:
+    - module: "nova.openstack.common.rpc.amqp"
+      message: "Exception during message handling"
+    - module: "nova.openstack.common.rpc.common"
+      message: "'NoneType' object has no attribute '__getitem__'"
+    - module: "nova.openstack.common.rpc.common"
+      message: "Instance .* could not be found"
+
 c-api:
     - module: "cinder.api.middleware.fault"
       message: "Caught error: Volume .* could not be found"
     - module: "cinder.api.middleware.fault"
       message: "Caught error: Snapshot .* could not be found"
+    - module: "cinder.api.openstack.wsgi"
+      message: "argument must be a string or a number, not 'NoneType'"
+    - module: "cinder.volume.api"
+      message: "Volume status must be available to reserve"
 
 c-vol:
     - module: "cinder.brick.iscsi.iscsi"
       message: "Failed to create iscsi target for volume id"
     - module: "cinder.brick.local_dev.lvm"
-      message: "/dev/dm-1: stat failed: No such file or directory"
+      message: "stat failed: No such file or directory"
+    - module: "cinder.brick.local_dev.lvm"
+      message: "LV stack-volumes.*in use: not deactivating"
     - module: "cinder.brick.local_dev.lvm"
       message: "Can't remove open logical volume"
 
-q-dhpc:
-    - module: "neutron.common.legacy"
-      message: "Skipping unknown group key: firewall_driver"
-    - module: "neutron.agent.dhcp_agent"
-      message: "Unable to enable dhcp"
-    - module: "neutron.agent.dhcp_agent"
-      message: " Network .* RPC info call failed"
-
 ceilometer-collector:
     - module: "stevedore.extension"
       message: ".*"
@@ -119,6 +167,14 @@
       message: "duplicate key value violates unique constraint"
     - module: "ceilometer.collector.dispatcher.database"
       message: "Failed to record metering data: QueuePool limit"
+    - module: "ceilometer.dispatcher.database"
+      message: "\\(DataError\\) integer out of range"
+    - module: "ceilometer.collector.dispatcher.database"
+      message: "Failed to record metering data: .* integer out of range"
+    - module: "ceilometer.collector.dispatcher.database"
+      message: "Failed to record metering data: .* integer out of range"
+    - module: "ceilometer.openstack.common.db.sqlalchemy.session"
+      message: "DB exception wrapped"
 
 q-agt:
     - module: "neutron.agent.linux.ovs_lib"
@@ -159,4 +215,9 @@
       message: "(Network|Pool|Subnet|Agent|Port) .* could not be found"
     - module: "neutron.api.v2.resource"
       message: ".* failed"
+    - module: ".*"
+      message: ".*"
 
+s-proxy:
+    - module: "proxy-server"
+      message: "Timeout talking to memcached"
diff --git a/include/sample_vm/README.txt b/include/sample_vm/README.txt
deleted file mode 100644
index 51b609d..0000000
--- a/include/sample_vm/README.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-You will need to download an image into this directory..
-Will also need to update the tests to reference this new image.
-
-You could use e.g. the Ubuntu Natty cloud images (this matches the sample configuration):
-$ wget http://cloud-images.ubuntu.com/releases/natty/release/ubuntu-11.04-server-cloudimg-amd64.tar.gz
-$ tar xvzf ubuntu-11.04-server-cloudimg-amd64.tar.gz
diff --git a/include/swift_objects/README.txt b/include/swift_objects/README.txt
deleted file mode 100644
index 3857524..0000000
--- a/include/swift_objects/README.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-## For the swift tests you will need three objects to upload for the test
-## examples below are a 512K object, a 500M object, and 1G object
-dd if=/dev/zero of=swift_small bs=512 count=1024
-dd if=/dev/zero of=swift_medium bs=512 count=1024000
-dd if=/dev/zero of=swift_large bs=1024 count=1024000
diff --git a/openstack-common.conf b/openstack-common.conf
index dabf5a0..38d58ee 100644
--- a/openstack-common.conf
+++ b/openstack-common.conf
@@ -1,6 +1,7 @@
 [DEFAULT]
 
 # The list of modules to copy from openstack-common
+module=config
 module=install_venv_common
 module=lockutils
 module=log
diff --git a/requirements.txt b/requirements.txt
index 4f6a1d3..cd11aa7 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,9 +5,9 @@
 jsonschema>=1.3.0,!=1.4.0
 testtools>=0.9.32
 lxml>=2.3
-boto>=2.4.0,!=2.13.0
+boto>=2.12.0,!=2.13.0
 paramiko>=1.8.0
-netaddr
+netaddr>=0.7.6
 python-glanceclient>=0.9.0
 python-keystoneclient>=0.4.1
 python-novaclient>=2.15.0
@@ -20,5 +20,5 @@
 oslo.config>=1.2.0
 eventlet>=0.13.0
 six>=1.4.1
-iso8601>=0.1.4
+iso8601>=0.1.8
 fixtures>=0.3.14
diff --git a/run_tests.sh b/run_tests.sh
index 5c8ce7d..3c9c051 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -11,7 +11,6 @@
   echo "  -u, --update             Update the virtual environment with any newer package versions"
   echo "  -s, --smoke              Only run smoke tests"
   echo "  -t, --serial             Run testr serially"
-  echo "  -c, --nova-coverage      Enable Nova coverage collection"
   echo "  -C, --config             Config file location"
   echo "  -p, --pep8               Just run pep8"
   echo "  -h, --help               Print this usage message"
@@ -31,13 +30,12 @@
 no_site_packages=0
 force=0
 wrapper=""
-nova_coverage=0
 config_file=""
 update=0
 logging=0
 logging_config=etc/logging.conf
 
-if ! options=$(getopt -o VNnfustcphdC:lL: -l virtual-env,no-virtual-env,no-site-packages,force,update,smoke,serial,nova-coverage,pep8,help,debug,config:,logging,logging-config: -- "$@")
+if ! options=$(getopt -o VNnfustphdC:lL: -l virtual-env,no-virtual-env,no-site-packages,force,update,smoke,serial,pep8,help,debug,config:,logging,logging-config: -- "$@")
 then
     # parse error
     usage
@@ -55,7 +53,6 @@
     -f|--force) force=1;;
     -u|--update) update=1;;
     -d|--debug) set -o xtrace;;
-    -c|--nova-coverage) let nova_coverage=1;;
     -C|--config) config_file=$2; shift;;
     -p|--pep8) let just_pep8=1;;
     -s|--smoke) testrargs+="smoke"; noseargs+="--attr=type=smoke";;
@@ -131,16 +128,6 @@
   ${wrapper} flake8
 }
 
-function run_coverage_start {
-  echo "Starting nova-coverage"
-  ${wrapper} python tools/tempest_coverage.py -c start
-}
-
-function run_coverage_report {
-  echo "Generating nova-coverage report"
-  ${wrapper} python tools/tempest_coverage.py -c report
-}
-
 if [ $never_venv -eq 0 ]
 then
   # Remove the virtual environment if --force used
@@ -176,11 +163,6 @@
     exit
 fi
 
-if [ $nova_coverage -eq 1 ]; then
-    run_coverage_start
-fi
-
-
 py_version=`${wrapper} python --version 2>&1`
 if [[ $py_version =~ "2.6" ]] ; then
     run_tests_nose
@@ -189,10 +171,6 @@
 fi
 retval=$?
 
-if [ $nova_coverage -eq 1 ]; then
-    run_coverage_report
-fi
-
 if [ -z "$testrargs" ]; then
     run_pep8
 fi
diff --git a/tempest/api/compute/__init__.py b/tempest/api/compute/__init__.py
index a528754..d20068e 100644
--- a/tempest/api/compute/__init__.py
+++ b/tempest/api/compute/__init__.py
@@ -16,7 +16,6 @@
 #    under the License.
 
 from tempest import config
-from tempest.exceptions import InvalidConfiguration
 from tempest.openstack.common import log as logging
 
 LOG = logging.getLogger(__name__)
@@ -26,30 +25,3 @@
 RESIZE_AVAILABLE = CONFIG.compute_feature_enabled.resize
 CHANGE_PASSWORD_AVAILABLE = CONFIG.compute_feature_enabled.change_password
 DISK_CONFIG_ENABLED = CONFIG.compute_feature_enabled.disk_config
-FLAVOR_EXTRA_DATA_ENABLED = CONFIG.compute_feature_enabled.flavor_extra
-MULTI_USER = True
-
-
-# All compute tests -- single setup function
-def generic_setup_package():
-    LOG.debug("Entering tempest.api.compute.setup_package")
-
-    global MULTI_USER
-
-    # Determine if there are two regular users that can be
-    # used in testing. If the test cases are allowed to create
-    # users (config.compute.allow_tenant_isolation is true,
-    # then we allow multi-user.
-    if not CONFIG.compute.allow_tenant_isolation:
-        user1 = CONFIG.identity.username
-        user2 = CONFIG.identity.alt_username
-        if not user2 or user1 == user2:
-            MULTI_USER = False
-        else:
-            user2_password = CONFIG.identity.alt_password
-            user2_tenant_name = CONFIG.identity.alt_tenant_name
-            if not user2_password or not user2_tenant_name:
-                msg = ("Alternate user specified but not alternate "
-                       "tenant or password: alt_tenant_name=%s alt_password=%s"
-                       % (user2_tenant_name, user2_password))
-                raise InvalidConfiguration(msg)
diff --git a/tempest/api/compute/admin/test_aggregates.py b/tempest/api/compute/admin/test_aggregates.py
index 4ff6b07..467a6f9 100644
--- a/tempest/api/compute/admin/test_aggregates.py
+++ b/tempest/api/compute/admin/test_aggregates.py
@@ -17,7 +17,7 @@
 
 from tempest.api.compute import base
 from tempest.common import tempest_fixtures as fixtures
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.test import attr
 
@@ -47,7 +47,7 @@
     @attr(type='gate')
     def test_aggregate_create_delete(self):
         # Create and delete an aggregate.
-        aggregate_name = rand_name(self.aggregate_name_prefix)
+        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
         resp, aggregate = self.client.create_aggregate(aggregate_name)
         self.assertEqual(200, resp.status)
         self.assertEqual(aggregate_name, aggregate['name'])
@@ -60,8 +60,8 @@
     @attr(type='gate')
     def test_aggregate_create_delete_with_az(self):
         # Create and delete an aggregate.
-        aggregate_name = rand_name(self.aggregate_name_prefix)
-        az_name = rand_name(self.az_name_prefix)
+        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
+        az_name = data_utils.rand_name(self.az_name_prefix)
         resp, aggregate = self.client.create_aggregate(aggregate_name, az_name)
         self.assertEqual(200, resp.status)
         self.assertEqual(aggregate_name, aggregate['name'])
@@ -74,7 +74,7 @@
     @attr(type='gate')
     def test_aggregate_create_verify_entry_in_list(self):
         # Create an aggregate and ensure it is listed.
-        aggregate_name = rand_name(self.aggregate_name_prefix)
+        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
         resp, aggregate = self.client.create_aggregate(aggregate_name)
         self.addCleanup(self.client.delete_aggregate, aggregate['id'])
 
@@ -87,7 +87,7 @@
     @attr(type='gate')
     def test_aggregate_create_update_metadata_get_details(self):
         # Create an aggregate and ensure its details are returned.
-        aggregate_name = rand_name(self.aggregate_name_prefix)
+        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
         resp, aggregate = self.client.create_aggregate(aggregate_name)
         self.addCleanup(self.client.delete_aggregate, aggregate['id'])
 
@@ -113,8 +113,8 @@
     def test_aggregate_create_update_with_az(self):
         # Update an aggregate and ensure properties are updated correctly
         self.useFixture(fixtures.LockFixture('availability_zone'))
-        aggregate_name = rand_name(self.aggregate_name_prefix)
-        az_name = rand_name(self.az_name_prefix)
+        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
+        az_name = data_utils.rand_name(self.az_name_prefix)
         resp, aggregate = self.client.create_aggregate(aggregate_name, az_name)
         self.addCleanup(self.client.delete_aggregate, aggregate['id'])
 
@@ -144,7 +144,7 @@
     @attr(type=['negative', 'gate'])
     def test_aggregate_create_as_user(self):
         # Regular user is not allowed to create an aggregate.
-        aggregate_name = rand_name(self.aggregate_name_prefix)
+        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
         self.assertRaises(exceptions.Unauthorized,
                           self.user_client.create_aggregate,
                           aggregate_name)
@@ -152,7 +152,7 @@
     @attr(type=['negative', 'gate'])
     def test_aggregate_delete_as_user(self):
         # Regular user is not allowed to delete an aggregate.
-        aggregate_name = rand_name(self.aggregate_name_prefix)
+        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
         resp, aggregate = self.client.create_aggregate(aggregate_name)
         self.addCleanup(self.client.delete_aggregate, aggregate['id'])
 
@@ -169,7 +169,7 @@
     @attr(type=['negative', 'gate'])
     def test_aggregate_get_details_as_user(self):
         # Regular user is not allowed to get aggregate details.
-        aggregate_name = rand_name(self.aggregate_name_prefix)
+        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
         resp, aggregate = self.client.create_aggregate(aggregate_name)
         self.addCleanup(self.client.delete_aggregate, aggregate['id'])
 
@@ -193,7 +193,7 @@
     def test_aggregate_add_remove_host(self):
         # Add an host to the given aggregate and remove.
         self.useFixture(fixtures.LockFixture('availability_zone'))
-        aggregate_name = rand_name(self.aggregate_name_prefix)
+        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
         resp, aggregate = self.client.create_aggregate(aggregate_name)
         self.addCleanup(self.client.delete_aggregate, aggregate['id'])
 
@@ -215,7 +215,7 @@
     def test_aggregate_add_host_list(self):
         # Add an host to the given aggregate and list.
         self.useFixture(fixtures.LockFixture('availability_zone'))
-        aggregate_name = rand_name(self.aggregate_name_prefix)
+        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
         resp, aggregate = self.client.create_aggregate(aggregate_name)
         self.addCleanup(self.client.delete_aggregate, aggregate['id'])
         self.client.add_host(aggregate['id'], self.host)
@@ -233,7 +233,7 @@
     def test_aggregate_add_host_get_details(self):
         # Add an host to the given aggregate and get details.
         self.useFixture(fixtures.LockFixture('availability_zone'))
-        aggregate_name = rand_name(self.aggregate_name_prefix)
+        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
         resp, aggregate = self.client.create_aggregate(aggregate_name)
         self.addCleanup(self.client.delete_aggregate, aggregate['id'])
         self.client.add_host(aggregate['id'], self.host)
@@ -248,18 +248,17 @@
     def test_aggregate_add_host_create_server_with_az(self):
         # Add an host to the given aggregate and create a server.
         self.useFixture(fixtures.LockFixture('availability_zone'))
-        aggregate_name = rand_name(self.aggregate_name_prefix)
-        az_name = rand_name(self.az_name_prefix)
+        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
+        az_name = data_utils.rand_name(self.az_name_prefix)
         resp, aggregate = self.client.create_aggregate(aggregate_name, az_name)
         self.addCleanup(self.client.delete_aggregate, aggregate['id'])
         self.client.add_host(aggregate['id'], self.host)
         self.addCleanup(self.client.remove_host, aggregate['id'], self.host)
-        server_name = rand_name('test_server_')
-        servers_client = self.servers_client
+        server_name = data_utils.rand_name('test_server_')
         admin_servers_client = self.os_adm.servers_client
-        resp, server = self.create_server(name=server_name,
-                                          availability_zone=az_name)
-        servers_client.wait_for_server_status(server['id'], 'ACTIVE')
+        resp, server = self.create_test_server(name=server_name,
+                                               availability_zone=az_name,
+                                               wait_until='ACTIVE')
         resp, body = admin_servers_client.get_server(server['id'])
         self.assertEqual(self.host, body[self._host_key])
 
@@ -269,11 +268,11 @@
         resp, hosts_all = self.os_adm.hosts_client.list_hosts()
         hosts = map(lambda x: x['host_name'], hosts_all)
         while True:
-            non_exist_host = rand_name('nonexist_host_')
+            non_exist_host = data_utils.rand_name('nonexist_host_')
             if non_exist_host not in hosts:
                 break
 
-        aggregate_name = rand_name(self.aggregate_name_prefix)
+        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
         resp, aggregate = self.client.create_aggregate(aggregate_name)
         self.addCleanup(self.client.delete_aggregate, aggregate['id'])
 
@@ -283,7 +282,7 @@
     @attr(type=['negative', 'gate'])
     def test_aggregate_add_host_as_user(self):
         # Regular user is not allowed to add a host to an aggregate.
-        aggregate_name = rand_name(self.aggregate_name_prefix)
+        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
         resp, aggregate = self.client.create_aggregate(aggregate_name)
         self.addCleanup(self.client.delete_aggregate, aggregate['id'])
 
@@ -295,7 +294,7 @@
     def test_aggregate_remove_host_as_user(self):
         # Regular user is not allowed to remove a host from an aggregate.
         self.useFixture(fixtures.LockFixture('availability_zone'))
-        aggregate_name = rand_name(self.aggregate_name_prefix)
+        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
         resp, aggregate = self.client.create_aggregate(aggregate_name)
         self.addCleanup(self.client.delete_aggregate, aggregate['id'])
         self.client.add_host(aggregate['id'], self.host)
diff --git a/tempest/api/compute/admin/test_fixed_ips.py b/tempest/api/compute/admin/test_fixed_ips.py
index 766589e..427f728 100644
--- a/tempest/api/compute/admin/test_fixed_ips.py
+++ b/tempest/api/compute/admin/test_fixed_ips.py
@@ -31,7 +31,7 @@
             raise cls.skipException(msg)
         cls.client = cls.os_adm.fixed_ips_client
         cls.non_admin_client = cls.fixed_ips_client
-        resp, server = cls.create_server(wait_until='ACTIVE')
+        resp, server = cls.create_test_server(wait_until='ACTIVE')
         resp, server = cls.servers_client.get_server(server['id'])
         for ip_set in server['addresses']:
             for ip in server['addresses'][ip_set]:
diff --git a/tempest/api/compute/admin/test_flavors.py b/tempest/api/compute/admin/test_flavors.py
index 05bb457..cf72e49 100644
--- a/tempest/api/compute/admin/test_flavors.py
+++ b/tempest/api/compute/admin/test_flavors.py
@@ -15,13 +15,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.api import compute
+import uuid
+
 from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_int_id
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
-from tempest.test import attr
-from tempest.test import skip_because
+from tempest import test
 
 
 class FlavorsAdminTestJSON(base.BaseV2ComputeAdminTest):
@@ -35,7 +34,7 @@
     @classmethod
     def setUpClass(cls):
         super(FlavorsAdminTestJSON, cls).setUpClass()
-        if not compute.FLAVOR_EXTRA_DATA_ENABLED:
+        if not test.is_extension_enabled('FlavorExtraData', 'compute'):
             msg = "FlavorExtraData extension not enabled."
             raise cls.skipException(msg)
 
@@ -54,18 +53,16 @@
         self.assertEqual(resp.status, 202)
         self.client.wait_for_resource_deletion(flavor_id)
 
-    @attr(type='gate')
-    def test_create_flavor(self):
+    def _create_flavor(self, flavor_id):
         # Create a flavor and ensure it is listed
         # This operation requires the user to have 'admin' role
-        flavor_name = rand_name(self.flavor_name_prefix)
-        new_flavor_id = rand_int_id(start=1000)
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
 
         # Create the flavor
         resp, flavor = self.client.create_flavor(flavor_name,
                                                  self.ram, self.vcpus,
                                                  self.disk,
-                                                 new_flavor_id,
+                                                 flavor_id,
                                                  ephemeral=self.ephemeral,
                                                  swap=self.swap,
                                                  rxtx=self.rxtx)
@@ -75,7 +72,6 @@
         self.assertEqual(flavor['vcpus'], self.vcpus)
         self.assertEqual(flavor['disk'], self.disk)
         self.assertEqual(flavor['ram'], self.ram)
-        self.assertEqual(int(flavor['id']), new_flavor_id)
         self.assertEqual(flavor['swap'], self.swap)
         self.assertEqual(flavor['rxtx_factor'], self.rxtx)
         self.assertEqual(flavor['OS-FLV-EXT-DATA:ephemeral'],
@@ -83,16 +79,38 @@
         self.assertEqual(flavor['os-flavor-access:is_public'], True)
 
         # Verify flavor is retrieved
-        resp, flavor = self.client.get_flavor_details(new_flavor_id)
+        resp, flavor = self.client.get_flavor_details(flavor['id'])
         self.assertEqual(resp.status, 200)
         self.assertEqual(flavor['name'], flavor_name)
 
-    @attr(type='gate')
+        return flavor['id']
+
+    @test.attr(type='gate')
+    def test_create_flavor_with_int_id(self):
+        flavor_id = data_utils.rand_int_id(start=1000)
+        new_flavor_id = self._create_flavor(flavor_id)
+        self.assertEqual(new_flavor_id, str(flavor_id))
+
+    @test.attr(type='gate')
+    def test_create_flavor_with_uuid_id(self):
+        flavor_id = str(uuid.uuid4())
+        new_flavor_id = self._create_flavor(flavor_id)
+        self.assertEqual(new_flavor_id, flavor_id)
+
+    @test.attr(type='gate')
+    def test_create_flavor_with_none_id(self):
+        # If nova receives a request with None as flavor_id,
+        # nova generates flavor_id of uuid.
+        flavor_id = None
+        new_flavor_id = self._create_flavor(flavor_id)
+        self.assertEqual(new_flavor_id, str(uuid.UUID(new_flavor_id)))
+
+    @test.attr(type='gate')
     def test_create_flavor_verify_entry_in_list_details(self):
         # Create a flavor and ensure it's details are listed
         # This operation requires the user to have 'admin' role
-        flavor_name = rand_name(self.flavor_name_prefix)
-        new_flavor_id = rand_int_id(start=1000)
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
 
         # Create the flavor
         resp, flavor = self.client.create_flavor(flavor_name,
@@ -112,12 +130,12 @@
                 flag = True
         self.assertTrue(flag)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_get_flavor_details_for_deleted_flavor(self):
         # Delete a flavor and ensure it is not listed
         # Create a test flavor
-        flavor_name = rand_name(self.flavor_name_prefix)
-        new_flavor_id = rand_int_id(start=1000)
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
 
         resp, flavor = self.client.create_flavor(flavor_name,
                                                  self.ram,
@@ -146,7 +164,7 @@
                 flag = False
         self.assertTrue(flag)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_create_list_flavor_without_extra_data(self):
         # Create a flavor and ensure it is listed
         # This operation requires the user to have 'admin' role
@@ -158,8 +176,8 @@
             self.assertEqual(int(flavor['OS-FLV-EXT-DATA:ephemeral']), 0)
             self.assertEqual(flavor['os-flavor-access:is_public'], True)
 
-        flavor_name = rand_name(self.flavor_name_prefix)
-        new_flavor_id = rand_int_id(start=1000)
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
 
         # Create the flavor
         resp, flavor = self.client.create_flavor(flavor_name,
@@ -190,14 +208,14 @@
                 flag = True
         self.assertTrue(flag)
 
-    @skip_because(bug="1209101")
-    @attr(type='gate')
+    @test.skip_because(bug="1209101")
+    @test.attr(type='gate')
     def test_list_non_public_flavor(self):
         # Create a flavor with os-flavor-access:is_public false should
         # be present in list_details.
         # This operation requires the user to have 'admin' role
-        flavor_name = rand_name(self.flavor_name_prefix)
-        new_flavor_id = rand_int_id(start=1000)
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
 
         # Create the flavor
         resp, flavor = self.client.create_flavor(flavor_name,
@@ -224,11 +242,11 @@
                 flag = True
         self.assertFalse(flag)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_create_server_with_non_public_flavor(self):
         # Create a flavor with os-flavor-access:is_public false
-        flavor_name = rand_name(self.flavor_name_prefix)
-        new_flavor_id = rand_int_id(start=1000)
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
 
         # Create the flavor
         resp, flavor = self.client.create_flavor(flavor_name,
@@ -244,12 +262,12 @@
                           self.os.servers_client.create_server,
                           'test', self.image_ref, flavor['id'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_public_flavor_with_other_user(self):
         # Create a Flavor with public access.
         # Try to List/Get flavor with another user
-        flavor_name = rand_name(self.flavor_name_prefix)
-        new_flavor_id = rand_int_id(start=1000)
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
 
             # Create the flavor
         resp, flavor = self.client.create_flavor(flavor_name,
@@ -268,12 +286,12 @@
                 flag = True
         self.assertTrue(flag)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_is_public_string_variations(self):
-        flavor_id_not_public = rand_int_id(start=1000)
-        flavor_name_not_public = rand_name(self.flavor_name_prefix)
-        flavor_id_public = rand_int_id(start=1000)
-        flavor_name_public = rand_name(self.flavor_name_prefix)
+        flavor_id_not_public = data_utils.rand_int_id(start=1000)
+        flavor_name_not_public = data_utils.rand_name(self.flavor_name_prefix)
+        flavor_id_public = data_utils.rand_int_id(start=1000)
+        flavor_name_public = data_utils.rand_name(self.flavor_name_prefix)
 
         # Create a non public flavor
         resp, flavor = self.client.create_flavor(flavor_name_not_public,
@@ -311,10 +329,10 @@
         _test_string_variations(['t', 'true', 'yes', '1'],
                                 flavor_name_public)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_create_flavor_using_string_ram(self):
-        flavor_name = rand_name(self.flavor_name_prefix)
-        new_flavor_id = rand_int_id(start=1000)
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
 
         ram = " 1024 "
         resp, flavor = self.client.create_flavor(flavor_name,
@@ -329,16 +347,16 @@
         self.assertEqual(flavor['ram'], int(ram))
         self.assertEqual(int(flavor['id']), new_flavor_id)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_invalid_is_public_string(self):
         self.assertRaises(exceptions.BadRequest,
                           self.client.list_flavors_with_detail,
                           {'is_public': 'invalid'})
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_create_flavor_as_user(self):
-        flavor_name = rand_name(self.flavor_name_prefix)
-        new_flavor_id = rand_int_id(start=1000)
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
 
         self.assertRaises(exceptions.Unauthorized,
                           self.user_client.create_flavor,
@@ -346,26 +364,26 @@
                           new_flavor_id, ephemeral=self.ephemeral,
                           swap=self.swap, rxtx=self.rxtx)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_delete_flavor_as_user(self):
         self.assertRaises(exceptions.Unauthorized,
                           self.user_client.delete_flavor,
                           self.flavor_ref_alt)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_create_flavor_using_invalid_ram(self):
-        flavor_name = rand_name(self.flavor_name_prefix)
-        new_flavor_id = rand_int_id(start=1000)
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
 
         self.assertRaises(exceptions.BadRequest,
                           self.client.create_flavor,
                           flavor_name, -1, self.vcpus,
                           self.disk, new_flavor_id)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_create_flavor_using_invalid_vcpus(self):
-        flavor_name = rand_name(self.flavor_name_prefix)
-        new_flavor_id = rand_int_id(start=1000)
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
 
         self.assertRaises(exceptions.BadRequest,
                           self.client.create_flavor,
diff --git a/tempest/api/compute/admin/test_flavors_access.py b/tempest/api/compute/admin/test_flavors_access.py
index e8ae3b4..048312b 100644
--- a/tempest/api/compute/admin/test_flavors_access.py
+++ b/tempest/api/compute/admin/test_flavors_access.py
@@ -15,14 +15,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import uuid
-
-from tempest.api import compute
 from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_int_id
-from tempest.common.utils.data_utils import rand_name
-from tempest import exceptions
-from tempest.test import attr
+from tempest.common.utils import data_utils
+from tempest import test
 
 
 class FlavorsAccessTestJSON(base.BaseV2ComputeAdminTest):
@@ -37,26 +32,48 @@
     @classmethod
     def setUpClass(cls):
         super(FlavorsAccessTestJSON, cls).setUpClass()
-        if not compute.FLAVOR_EXTRA_DATA_ENABLED:
+        if not test.is_extension_enabled('FlavorExtraData', 'compute'):
             msg = "FlavorExtraData extension not enabled."
             raise cls.skipException(msg)
 
         cls.client = cls.os_adm.flavors_client
         admin_client = cls._get_identity_admin_client()
-        resp, tenants = admin_client.list_tenants()
-        cls.tenant_id = [tnt['id'] for tnt in tenants if tnt['name'] ==
-                         cls.flavors_client.tenant_name][0]
-
+        cls.tenant = admin_client.get_tenant_by_name(cls.flavors_client.
+                                                     tenant_name)
+        cls.tenant_id = cls.tenant['id']
+        cls.adm_tenant = admin_client.get_tenant_by_name(cls.os_adm.
+                                                         flavors_client.
+                                                         tenant_name)
+        cls.adm_tenant_id = cls.adm_tenant['id']
         cls.flavor_name_prefix = 'test_flavor_access_'
         cls.ram = 512
         cls.vcpus = 1
         cls.disk = 10
 
-    @attr(type='gate')
+    @test.attr(type='gate')
+    def test_flavor_access_list_with_private_flavor(self):
+        # Test to list flavor access successfully by querying private flavor
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
+        resp, new_flavor = self.client.create_flavor(flavor_name,
+                                                     self.ram, self.vcpus,
+                                                     self.disk,
+                                                     new_flavor_id,
+                                                     is_public='False')
+        self.addCleanup(self.client.delete_flavor, new_flavor['id'])
+        self.assertEqual(resp.status, 200)
+        resp, flavor_access = self.client.list_flavor_access(new_flavor_id)
+        self.assertEqual(resp.status, 200)
+        self.assertEqual(len(flavor_access), 1, str(flavor_access))
+        first_flavor = flavor_access[0]
+        self.assertEqual(str(new_flavor_id), str(first_flavor['flavor_id']))
+        self.assertEqual(self.adm_tenant_id, first_flavor['tenant_id'])
+
+    @test.attr(type='gate')
     def test_flavor_access_add_remove(self):
         # Test to add and remove flavor access to a given tenant.
-        flavor_name = rand_name(self.flavor_name_prefix)
-        new_flavor_id = rand_int_id(start=1000)
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
         resp, new_flavor = self.client.create_flavor(flavor_name,
                                                      self.ram, self.vcpus,
                                                      self.disk,
@@ -89,84 +106,6 @@
         self.assertEqual(resp.status, 200)
         self.assertNotIn(new_flavor['id'], map(lambda x: x['id'], flavors))
 
-    @attr(type=['negative', 'gate'])
-    def test_flavor_non_admin_add(self):
-        # Test to add flavor access as a user without admin privileges.
-        flavor_name = rand_name(self.flavor_name_prefix)
-        new_flavor_id = rand_int_id(start=1000)
-        resp, new_flavor = self.client.create_flavor(flavor_name,
-                                                     self.ram, self.vcpus,
-                                                     self.disk,
-                                                     new_flavor_id,
-                                                     is_public='False')
-        self.addCleanup(self.client.delete_flavor, new_flavor['id'])
-        self.assertRaises(exceptions.Unauthorized,
-                          self.flavors_client.add_flavor_access,
-                          new_flavor['id'],
-                          self.tenant_id)
-
-    @attr(type=['negative', 'gate'])
-    def test_flavor_non_admin_remove(self):
-        # Test to remove flavor access as a user without admin privileges.
-        flavor_name = rand_name(self.flavor_name_prefix)
-        new_flavor_id = rand_int_id(start=1000)
-        resp, new_flavor = self.client.create_flavor(flavor_name,
-                                                     self.ram, self.vcpus,
-                                                     self.disk,
-                                                     new_flavor_id,
-                                                     is_public='False')
-        self.addCleanup(self.client.delete_flavor, new_flavor['id'])
-        # Add flavor access to a tenant.
-        self.client.add_flavor_access(new_flavor['id'], self.tenant_id)
-        self.addCleanup(self.client.remove_flavor_access,
-                        new_flavor['id'], self.tenant_id)
-        self.assertRaises(exceptions.Unauthorized,
-                          self.flavors_client.remove_flavor_access,
-                          new_flavor['id'],
-                          self.tenant_id)
-
-    @attr(type=['negative', 'gate'])
-    def test_add_flavor_access_duplicate(self):
-        # Create a new flavor.
-        flavor_name = rand_name(self.flavor_name_prefix)
-        new_flavor_id = rand_int_id(start=1000)
-        resp, new_flavor = self.client.create_flavor(flavor_name,
-                                                     self.ram, self.vcpus,
-                                                     self.disk,
-                                                     new_flavor_id,
-                                                     is_public='False')
-        self.addCleanup(self.client.delete_flavor, new_flavor['id'])
-
-        # Add flavor access to a tenant.
-        self.client.add_flavor_access(new_flavor['id'], self.tenant_id)
-        self.addCleanup(self.client.remove_flavor_access,
-                        new_flavor['id'], self.tenant_id)
-
-        # An exception should be raised when adding flavor access to the same
-        # tenant
-        self.assertRaises(exceptions.Conflict,
-                          self.client.add_flavor_access,
-                          new_flavor['id'],
-                          self.tenant_id)
-
-    @attr(type=['negative', 'gate'])
-    def test_remove_flavor_access_not_found(self):
-        # Create a new flavor.
-        flavor_name = rand_name(self.flavor_name_prefix)
-        new_flavor_id = rand_int_id(start=1000)
-        resp, new_flavor = self.client.create_flavor(flavor_name,
-                                                     self.ram, self.vcpus,
-                                                     self.disk,
-                                                     new_flavor_id,
-                                                     is_public='False')
-        self.addCleanup(self.client.delete_flavor, new_flavor['id'])
-
-        # An exception should be raised when flavor access is not found
-        self.assertRaises(exceptions.NotFound,
-                          self.client.remove_flavor_access,
-                          new_flavor['id'],
-                          str(uuid.uuid4()))
-
 
 class FlavorsAdminTestXML(FlavorsAccessTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/compute/admin/test_flavors_access_negative.py b/tempest/api/compute/admin/test_flavors_access_negative.py
new file mode 100644
index 0000000..976124e
--- /dev/null
+++ b/tempest/api/compute/admin/test_flavors_access_negative.py
@@ -0,0 +1,152 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM 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 uuid
+
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest import test
+
+
+class FlavorsAccessNegativeTestJSON(base.BaseV2ComputeAdminTest):
+
+    """
+    Tests Flavor Access API extension.
+    Add and remove Flavor Access require admin privileges.
+    """
+
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(FlavorsAccessNegativeTestJSON, cls).setUpClass()
+        if not test.is_extension_enabled('FlavorExtraData', 'compute'):
+            msg = "FlavorExtraData extension not enabled."
+            raise cls.skipException(msg)
+
+        cls.client = cls.os_adm.flavors_client
+        admin_client = cls._get_identity_admin_client()
+        cls.tenant = admin_client.get_tenant_by_name(cls.flavors_client.
+                                                     tenant_name)
+        cls.tenant_id = cls.tenant['id']
+        cls.adm_tenant = admin_client.get_tenant_by_name(cls.os_adm.
+                                                         flavors_client.
+                                                         tenant_name)
+        cls.adm_tenant_id = cls.adm_tenant['id']
+        cls.flavor_name_prefix = 'test_flavor_access_'
+        cls.ram = 512
+        cls.vcpus = 1
+        cls.disk = 10
+
+    @test.attr(type=['negative', 'gate'])
+    def test_flavor_access_list_with_public_flavor(self):
+        # Test to list flavor access with exceptions by querying public flavor
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
+        resp, new_flavor = self.client.create_flavor(flavor_name,
+                                                     self.ram, self.vcpus,
+                                                     self.disk,
+                                                     new_flavor_id,
+                                                     is_public='True')
+        self.addCleanup(self.client.delete_flavor, new_flavor['id'])
+        self.assertEqual(resp.status, 200)
+        self.assertRaises(exceptions.NotFound,
+                          self.client.list_flavor_access,
+                          new_flavor_id)
+
+    @test.attr(type=['negative', 'gate'])
+    def test_flavor_non_admin_add(self):
+        # Test to add flavor access as a user without admin privileges.
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
+        resp, new_flavor = self.client.create_flavor(flavor_name,
+                                                     self.ram, self.vcpus,
+                                                     self.disk,
+                                                     new_flavor_id,
+                                                     is_public='False')
+        self.addCleanup(self.client.delete_flavor, new_flavor['id'])
+        self.assertRaises(exceptions.Unauthorized,
+                          self.flavors_client.add_flavor_access,
+                          new_flavor['id'],
+                          self.tenant_id)
+
+    @test.attr(type=['negative', 'gate'])
+    def test_flavor_non_admin_remove(self):
+        # Test to remove flavor access as a user without admin privileges.
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
+        resp, new_flavor = self.client.create_flavor(flavor_name,
+                                                     self.ram, self.vcpus,
+                                                     self.disk,
+                                                     new_flavor_id,
+                                                     is_public='False')
+        self.addCleanup(self.client.delete_flavor, new_flavor['id'])
+        # Add flavor access to a tenant.
+        self.client.add_flavor_access(new_flavor['id'], self.tenant_id)
+        self.addCleanup(self.client.remove_flavor_access,
+                        new_flavor['id'], self.tenant_id)
+        self.assertRaises(exceptions.Unauthorized,
+                          self.flavors_client.remove_flavor_access,
+                          new_flavor['id'],
+                          self.tenant_id)
+
+    @test.attr(type=['negative', 'gate'])
+    def test_add_flavor_access_duplicate(self):
+        # Create a new flavor.
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
+        resp, new_flavor = self.client.create_flavor(flavor_name,
+                                                     self.ram, self.vcpus,
+                                                     self.disk,
+                                                     new_flavor_id,
+                                                     is_public='False')
+        self.addCleanup(self.client.delete_flavor, new_flavor['id'])
+
+        # Add flavor access to a tenant.
+        self.client.add_flavor_access(new_flavor['id'], self.tenant_id)
+        self.addCleanup(self.client.remove_flavor_access,
+                        new_flavor['id'], self.tenant_id)
+
+        # An exception should be raised when adding flavor access to the same
+        # tenant
+        self.assertRaises(exceptions.Conflict,
+                          self.client.add_flavor_access,
+                          new_flavor['id'],
+                          self.tenant_id)
+
+    @test.attr(type=['negative', 'gate'])
+    def test_remove_flavor_access_not_found(self):
+        # Create a new flavor.
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
+        resp, new_flavor = self.client.create_flavor(flavor_name,
+                                                     self.ram, self.vcpus,
+                                                     self.disk,
+                                                     new_flavor_id,
+                                                     is_public='False')
+        self.addCleanup(self.client.delete_flavor, new_flavor['id'])
+
+        # An exception should be raised when flavor access is not found
+        self.assertRaises(exceptions.NotFound,
+                          self.client.remove_flavor_access,
+                          new_flavor['id'],
+                          str(uuid.uuid4()))
+
+
+class FlavorsAdminNegativeTestXML(FlavorsAccessNegativeTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs.py b/tempest/api/compute/admin/test_flavors_extra_specs.py
index 403a946..875f742 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs.py
@@ -15,18 +15,16 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.api import compute
 from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_int_id
-from tempest.common.utils.data_utils import rand_name
-from tempest.test import attr
+from tempest.common.utils import data_utils
+from tempest import test
 
 
 class FlavorsExtraSpecsTestJSON(base.BaseV2ComputeAdminTest):
 
     """
     Tests Flavor Extra Spec API extension.
-    SET, UNSET Flavor Extra specs require admin privileges.
+    SET, UNSET, UPDATE Flavor Extra specs require admin privileges.
     GET Flavor Extra specs can be performed even by without admin privileges.
     """
 
@@ -35,17 +33,17 @@
     @classmethod
     def setUpClass(cls):
         super(FlavorsExtraSpecsTestJSON, cls).setUpClass()
-        if not compute.FLAVOR_EXTRA_DATA_ENABLED:
+        if not test.is_extension_enabled('FlavorExtraData', 'compute'):
             msg = "FlavorExtraData extension not enabled."
             raise cls.skipException(msg)
 
         cls.client = cls.os_adm.flavors_client
-        flavor_name = rand_name('test_flavor')
+        flavor_name = data_utils.rand_name('test_flavor')
         ram = 512
         vcpus = 1
         disk = 10
         ephemeral = 10
-        cls.new_flavor_id = rand_int_id(start=1000)
+        cls.new_flavor_id = data_utils.rand_int_id(start=1000)
         swap = 1024
         rxtx = 1
         # Create a flavor so as to set/get/unset extra specs
@@ -62,7 +60,7 @@
         cls.client.wait_for_resource_deletion(cls.flavor['id'])
         super(FlavorsExtraSpecsTestJSON, cls).tearDownClass()
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_flavor_set_get_update_show_unset_keys(self):
         # Test to SET, GET, UPDATE, SHOW, UNSET flavor extra
         # spec as a user with admin privileges.
@@ -87,13 +85,6 @@
         self.assertEqual(update_resp.status, 200)
         self.assertEqual({"key1": "value"}, update_body)
 
-        # GET a key value and verify
-        show_resp, get_body = \
-            self.client.get_flavor_extra_spec_with_key(self.flavor['id'],
-                                                       "key1")
-        self.assertEqual(show_resp.status, 200)
-        self.assertEqual(get_body, 'value')
-
         # GET extra specs and verify the value of the key2
         # is the same as before
         get_resp, get_body = \
@@ -109,8 +100,8 @@
             self.client.unset_flavor_extra_spec(self.flavor['id'], "key2")
         self.assertEqual(unset_resp.status, 200)
 
-    @attr(type='gate')
-    def test_flavor_non_admin_get_all_keys_and_specified_key(self):
+    @test.attr(type='gate')
+    def test_flavor_non_admin_get_all_keys(self):
         specs = {"key1": "value1", "key2": "value2"}
         set_resp, set_body = self.client.set_flavor_extra_spec(
             self.flavor['id'], specs)
@@ -121,12 +112,19 @@
         for key in specs:
             self.assertEqual(body[key], specs[key])
 
-        get_resp, get_body = \
-            self.flavors_client.get_flavor_extra_spec_with_key(
-                self.flavor['id'],
-                "key1")
-        self.assertEqual(get_resp.status, 200)
-        self.assertEqual("value1", get_body)
+    @test.attr(type='gate')
+    def test_flavor_non_admin_get_specific_key(self):
+        specs = {"key1": "value1", "key2": "value2"}
+        resp, body = self.client.set_flavor_extra_spec(
+            self.flavor['id'], specs)
+        self.assertEqual(resp.status, 200)
+        self.assertEqual(body['key1'], 'value1')
+        self.assertIn('key2', body)
+        resp, body = self.flavors_client.get_flavor_extra_spec_with_key(
+            self.flavor['id'], 'key1')
+        self.assertEqual(resp.status, 200)
+        self.assertEqual(body['key1'], 'value1')
+        self.assertNotIn('key2', body)
 
 
 class FlavorsExtraSpecsTestXML(FlavorsExtraSpecsTestJSON):
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 8d62a2a..fb09a63 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
@@ -16,33 +16,35 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.api import compute
 from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_int_id
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
-from tempest.test import attr
+from tempest import test
 
 
 class FlavorsExtraSpecsNegativeTestJSON(base.BaseV2ComputeAdminTest):
-    """the Negative tests for FlavorsExtraSpecs."""
+
+    """
+    Negative Tests Flavor Extra Spec API extension.
+    SET, UNSET, UPDATE Flavor Extra specs require admin privileges.
+    """
 
     _interface = 'json'
 
     @classmethod
     def setUpClass(cls):
         super(FlavorsExtraSpecsNegativeTestJSON, cls).setUpClass()
-        if not compute.FLAVOR_EXTRA_DATA_ENABLED:
+        if not test.is_extension_enabled('FlavorExtraData', 'compute'):
             msg = "FlavorExtraData extension not enabled."
             raise cls.skipException(msg)
 
         cls.client = cls.os_adm.flavors_client
-        flavor_name = rand_name('test_flavor')
+        flavor_name = data_utils.rand_name('test_flavor')
         ram = 512
         vcpus = 1
         disk = 10
         ephemeral = 10
-        cls.new_flavor_id = rand_int_id(start=1000)
+        cls.new_flavor_id = data_utils.rand_int_id(start=1000)
         swap = 1024
         rxtx = 1
         # Create a flavor
@@ -59,7 +61,7 @@
         cls.client.wait_for_resource_deletion(cls.flavor['id'])
         super(FlavorsExtraSpecsNegativeTestJSON, cls).tearDownClass()
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_flavor_non_admin_set_keys(self):
         # Test to SET flavor extra spec as a user without admin privileges.
         specs = {"key1": "value1", "key2": "value2"}
@@ -68,7 +70,22 @@
                           self.flavor['id'],
                           specs)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
+    def test_flavor_non_admin_update_specific_key(self):
+        # non admin user is not allowed to update flavor extra spec
+        specs = {"key1": "value1", "key2": "value2"}
+        resp, body = self.client.set_flavor_extra_spec(
+            self.flavor['id'], specs)
+        self.assertEqual(resp.status, 200)
+        self.assertEqual(body['key1'], 'value1')
+        self.assertRaises(exceptions.Unauthorized,
+                          self.flavors_client.
+                          update_flavor_extra_spec,
+                          self.flavor['id'],
+                          'key1',
+                          key1='value1_new')
+
+    @test.attr(type=['negative', 'gate'])
     def test_flavor_non_admin_unset_keys(self):
         specs = {"key1": "value1", "key2": "value2"}
         set_resp, set_body = self.client.set_flavor_extra_spec(
@@ -79,22 +96,22 @@
                           self.flavor['id'],
                           'key1')
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_flavor_unset_nonexistent_key(self):
-        nonexistent_key = rand_name('flavor_key')
+        nonexistent_key = data_utils.rand_name('flavor_key')
         self.assertRaises(exceptions.NotFound,
                           self.client.unset_flavor_extra_spec,
                           self.flavor['id'],
                           nonexistent_key)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_flavor_get_nonexistent_key(self):
         self.assertRaises(exceptions.NotFound,
                           self.flavors_client.get_flavor_extra_spec_with_key,
                           self.flavor['id'],
                           "nonexistent_key")
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_flavor_update_mismatch_key(self):
         # the key will be updated should be match the key in the body
         self.assertRaises(exceptions.BadRequest,
@@ -103,7 +120,7 @@
                           "key2",
                           key1="value")
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_flavor_update_more_key(self):
         # there should be just one item in the request body
         self.assertRaises(exceptions.BadRequest,
diff --git a/tempest/api/compute/admin/test_hosts.py b/tempest/api/compute/admin/test_hosts.py
index 8e451a0..22e6cf1 100644
--- a/tempest/api/compute/admin/test_hosts.py
+++ b/tempest/api/compute/admin/test_hosts.py
@@ -32,18 +32,11 @@
         super(HostsAdminTestJSON, cls).setUpClass()
         cls.client = cls.os_adm.hosts_client
 
-    def _get_host_name(self):
-        resp, hosts = self.client.list_hosts()
-        self.assertEqual(200, resp.status)
-        self.assertTrue(len(hosts) >= 1)
-        hostname = hosts[0]['host_name']
-        return hostname
-
     @attr(type='gate')
     def test_list_hosts(self):
         resp, hosts = self.client.list_hosts()
         self.assertEqual(200, resp.status)
-        self.assertTrue(len(hosts) >= 2)
+        self.assertTrue(len(hosts) >= 2, str(hosts))
 
     @attr(type='gate')
     def test_list_hosts_with_zone(self):
@@ -77,18 +70,24 @@
 
     @attr(type='gate')
     def test_show_host_detail(self):
-        hostname = self._get_host_name()
-
-        resp, resources = self.client.show_host_detail(hostname)
+        resp, hosts = self.client.list_hosts()
         self.assertEqual(200, resp.status)
-        self.assertTrue(len(resources) >= 1)
-        host_resource = resources[0]['resource']
-        self.assertIsNotNone(host_resource)
-        self.assertIsNotNone(host_resource['cpu'])
-        self.assertIsNotNone(host_resource['disk_gb'])
-        self.assertIsNotNone(host_resource['memory_mb'])
-        self.assertIsNotNone(host_resource['project'])
-        self.assertEqual(hostname, host_resource['host'])
+
+        hosts = [host for host in hosts if host['service'] == 'compute']
+        self.assertTrue(len(hosts) >= 1)
+
+        for host in hosts:
+            hostname = host['host_name']
+            resp, resources = self.client.show_host_detail(hostname)
+            self.assertEqual(200, resp.status)
+            self.assertTrue(len(resources) >= 1)
+            host_resource = resources[0]['resource']
+            self.assertIsNotNone(host_resource)
+            self.assertIsNotNone(host_resource['cpu'])
+            self.assertIsNotNone(host_resource['disk_gb'])
+            self.assertIsNotNone(host_resource['memory_mb'])
+            self.assertIsNotNone(host_resource['project'])
+            self.assertEqual(hostname, host_resource['host'])
 
 
 class HostsAdminTestXML(HostsAdminTestJSON):
diff --git a/tempest/api/compute/admin/test_instance_usage_audit_log.py b/tempest/api/compute/admin/test_instance_usage_audit_log.py
new file mode 100644
index 0000000..cea6e92
--- /dev/null
+++ b/tempest/api/compute/admin/test_instance_usage_audit_log.py
@@ -0,0 +1,64 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM 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 datetime
+
+from tempest.api.compute import base
+from tempest.test import attr
+import urllib
+
+
+class InstanceUsageAuditLogTestJSON(base.BaseV2ComputeAdminTest):
+
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(InstanceUsageAuditLogTestJSON, cls).setUpClass()
+        cls.adm_client = cls.os_adm.instance_usages_audit_log_client
+
+    @attr(type='gate')
+    def test_list_instance_usage_audit_logs(self):
+        # list instance usage audit logs
+        resp, body = self.adm_client.list_instance_usage_audit_logs()
+        self.assertEqual(200, resp.status)
+        expected_items = ['total_errors', 'total_instances', 'log',
+                          'num_hosts_running', 'num_hosts_done',
+                          'num_hosts', 'hosts_not_run', 'overall_status',
+                          'period_ending', 'period_beginning',
+                          'num_hosts_not_run']
+        for item in expected_items:
+            self.assertIn(item, body)
+
+    @attr(type='gate')
+    def test_get_instance_usage_audit_log(self):
+        # Get instance usage audit log before specified time
+        now = datetime.datetime.now()
+        resp, body = self.adm_client.get_instance_usage_audit_log(
+            urllib.quote(now.strftime("%Y-%m-%d %H:%M:%S")))
+
+        self.assertEqual(200, resp.status)
+        expected_items = ['total_errors', 'total_instances', 'log',
+                          'num_hosts_running', 'num_hosts_done', 'num_hosts',
+                          'hosts_not_run', 'overall_status', 'period_ending',
+                          'period_beginning', 'num_hosts_not_run']
+        for item in expected_items:
+            self.assertIn(item, body)
+
+
+class InstanceUsageAuditLogTestXML(InstanceUsageAuditLogTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py b/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
new file mode 100644
index 0000000..dcf41c5
--- /dev/null
+++ b/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
@@ -0,0 +1,56 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM 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 datetime
+
+from tempest.api.compute import base
+from tempest import exceptions
+from tempest.test import attr
+import urllib
+
+
+class InstanceUsageAuditLogNegativeTestJSON(base.BaseV2ComputeAdminTest):
+
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(InstanceUsageAuditLogNegativeTestJSON, cls).setUpClass()
+        cls.adm_client = cls.os_adm.instance_usages_audit_log_client
+
+    @attr(type=['negative', 'gate'])
+    def test_instance_usage_audit_logs_with_nonadmin_user(self):
+        # the instance_usage_audit_logs API just can be accessed by admin user
+        self.assertRaises(exceptions.Unauthorized,
+                          self.instance_usages_audit_log_client.
+                          list_instance_usage_audit_logs)
+        now = datetime.datetime.now()
+        self.assertRaises(exceptions.Unauthorized,
+                          self.instance_usages_audit_log_client.
+                          get_instance_usage_audit_log,
+                          urllib.quote(now.strftime("%Y-%m-%d %H:%M:%S")))
+
+    @attr(type=['negative', 'gate'])
+    def test_get_instance_usage_audit_logs_with_invalid_time(self):
+        self.assertRaises(exceptions.BadRequest,
+                          self.adm_client.get_instance_usage_audit_log,
+                          "invalid_time")
+
+
+class InstanceUsageAuditLogNegativeTestXML(
+    InstanceUsageAuditLogNegativeTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/admin/test_quotas.py b/tempest/api/compute/admin/test_quotas.py
index 6c4d350..f49aae4 100644
--- a/tempest/api/compute/admin/test_quotas.py
+++ b/tempest/api/compute/admin/test_quotas.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import config
 from tempest import exceptions
 from tempest.test import attr
@@ -36,8 +36,6 @@
         cls.identity_admin_client = cls._get_identity_admin_client()
         cls.sg_client = cls.security_groups_client
 
-        resp, tenants = cls.identity_admin_client.list_tenants()
-
         # NOTE(afazekas): these test cases should always create and use a new
         # tenant most of them should be skipped if we can't do that
         cls.demo_tenant_id = cls.isolated_creds.get_primary_user().get(
@@ -89,7 +87,7 @@
     @attr(type='gate')
     def test_get_updated_quotas(self):
         # Verify that GET shows the updated quota set
-        tenant_name = rand_name('cpu_quota_tenant_')
+        tenant_name = data_utils.rand_name('cpu_quota_tenant_')
         tenant_desc = tenant_name + '-desc'
         identity_client = self.os_adm.identity_client
         _, tenant = identity_client.create_tenant(name=tenant_name,
@@ -119,7 +117,7 @@
 
         self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
                         cores=default_vcpu_quota)
-        self.assertRaises(exceptions.OverLimit, self.create_server)
+        self.assertRaises(exceptions.OverLimit, self.create_test_server)
 
     @attr(type='gate')
     def test_create_server_when_memory_quota_is_full(self):
@@ -134,7 +132,7 @@
 
         self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
                         ram=default_mem_quota)
-        self.assertRaises(exceptions.OverLimit, self.create_server)
+        self.assertRaises(exceptions.OverLimit, self.create_test_server)
 
     @attr(type='gate')
     def test_update_quota_normal_user(self):
@@ -155,7 +153,7 @@
                                          instances=instances_quota)
         self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
                         instances=default_instances_quota)
-        self.assertRaises(exceptions.OverLimit, self.create_server)
+        self.assertRaises(exceptions.OverLimit, self.create_test_server)
 
     @skip_because(bug="1186354",
                   condition=config.TempestConfig().service_available.neutron)
@@ -202,8 +200,8 @@
                         self.demo_tenant_id,
                         security_group_rules=default_sg_rules_quota)
 
-        s_name = rand_name('securitygroup-')
-        s_description = rand_name('description-')
+        s_name = data_utils.rand_name('securitygroup-')
+        s_description = data_utils.rand_name('description-')
         resp, securitygroup =\
             self.sg_client.create_security_group(s_name, s_description)
         self.addCleanup(self.sg_client.delete_security_group,
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index ebc661c..6fe3186 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -15,8 +15,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_int_id
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.test import attr
 from tempest.test import skip_because
@@ -34,30 +33,26 @@
     def setUpClass(cls):
         super(ServersAdminTestJSON, cls).setUpClass()
         cls.client = cls.os_adm.servers_client
-        cls.non_adm_client = cls.servers_client
+        cls.non_admin_client = cls.servers_client
         cls.flavors_client = cls.os_adm.flavors_client
-        cls.identity_client = cls._get_identity_admin_client()
-        tenant = cls.identity_client.get_tenant_by_name(
-            cls.client.tenant_name)
-        cls.tenant_id = tenant['id']
 
-        cls.s1_name = rand_name('server')
-        resp, server = cls.create_server(name=cls.s1_name,
-                                         wait_until='ACTIVE')
+        cls.s1_name = data_utils.rand_name('server')
+        resp, server = cls.create_test_server(name=cls.s1_name,
+                                              wait_until='ACTIVE')
         cls.s1_id = server['id']
 
-        cls.s2_name = rand_name('server')
-        resp, server = cls.create_server(name=cls.s2_name,
-                                         wait_until='ACTIVE')
+        cls.s2_name = data_utils.rand_name('server')
+        resp, server = cls.create_test_server(name=cls.s2_name,
+                                              wait_until='ACTIVE')
 
     def _get_unused_flavor_id(self):
-        flavor_id = rand_int_id(start=1000)
+        flavor_id = data_utils.rand_int_id(start=1000)
         while True:
             try:
                 resp, body = self.flavors_client.get_flavor_details(flavor_id)
             except exceptions.NotFound:
                 break
-            flavor_id = rand_int_id(start=1000)
+            flavor_id = data_utils.rand_int_id(start=1000)
         return flavor_id
 
     @attr(type='gate')
@@ -83,47 +78,11 @@
     @attr(type='gate')
     def test_admin_delete_servers_of_others(self):
         # Administrator can delete servers of others
-        _, server = self.create_server()
+        _, server = self.create_test_server()
         resp, _ = self.client.delete_server(server['id'])
         self.assertEqual('204', resp['status'])
         self.servers_client.wait_for_server_termination(server['id'])
 
-    @attr(type=['negative', 'gate'])
-    def test_resize_server_using_overlimit_ram(self):
-        flavor_name = rand_name("flavor-")
-        flavor_id = self._get_unused_flavor_id()
-        resp, quota_set = self.quotas_client.get_default_quota_set(
-            self.tenant_id)
-        ram = int(quota_set['ram']) + 1
-        vcpus = 8
-        disk = 10
-        resp, flavor_ref = self.flavors_client.create_flavor(flavor_name,
-                                                             ram, vcpus, disk,
-                                                             flavor_id)
-        self.addCleanup(self.flavors_client.delete_flavor, flavor_id)
-        self.assertRaises(exceptions.OverLimit,
-                          self.client.resize,
-                          self.servers[0]['id'],
-                          flavor_ref['id'])
-
-    @attr(type=['negative', 'gate'])
-    def test_resize_server_using_overlimit_vcpus(self):
-        flavor_name = rand_name("flavor-")
-        flavor_id = self._get_unused_flavor_id()
-        ram = 512
-        resp, quota_set = self.quotas_client.get_default_quota_set(
-            self.tenant_id)
-        vcpus = int(quota_set['cores']) + 1
-        disk = 10
-        resp, flavor_ref = self.flavors_client.create_flavor(flavor_name,
-                                                             ram, vcpus, disk,
-                                                             flavor_id)
-        self.addCleanup(self.flavors_client.delete_flavor, flavor_id)
-        self.assertRaises(exceptions.OverLimit,
-                          self.client.resize,
-                          self.servers[0]['id'],
-                          flavor_ref['id'])
-
     @attr(type='gate')
     def test_reset_state_server(self):
         # Reset server's state to 'error'
@@ -142,23 +101,6 @@
         resp, server = self.client.get_server(self.s1_id)
         self.assertEqual(server['status'], 'ACTIVE')
 
-    @attr(type=['negative', 'gate'])
-    def test_reset_state_server_invalid_state(self):
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.reset_state, self.s1_id,
-                          state='invalid')
-
-    @attr(type=['negative', 'gate'])
-    def test_reset_state_server_invalid_type(self):
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.reset_state, self.s1_id,
-                          state=1)
-
-    @attr(type=['negative', 'gate'])
-    def test_reset_state_server_nonexistent_server(self):
-        self.assertRaises(exceptions.NotFound,
-                          self.client.reset_state, '999')
-
     @attr(type='gate')
     @skip_because(bug="1240043")
     def test_get_server_diagnostics_by_admin(self):
@@ -171,12 +113,33 @@
         for key in basic_attrs:
             self.assertIn(key, str(diagnostic.keys()))
 
-    @attr(type=['negative', 'gate'])
-    def test_get_server_diagnostics_by_non_admin(self):
-        # Non-admin user can not view server diagnostics according to policy
-        self.assertRaises(exceptions.Unauthorized,
-                          self.non_adm_client.get_server_diagnostics,
-                          self.s1_id)
+    @attr(type='gate')
+    def test_rebuild_server_in_error_state(self):
+        # The server in error state should be rebuilt using the provided
+        # image and changed to ACTIVE state
+
+        # resetting vm state require admin priviledge
+        resp, server = self.client.reset_state(self.s1_id, state='error')
+        self.assertEqual(202, resp.status)
+        resp, rebuilt_server = self.non_admin_client.rebuild(
+            self.s1_id, self.image_ref_alt)
+        self.addCleanup(self.non_admin_client.wait_for_server_status,
+                        self.s1_id, 'ACTIVE')
+        self.addCleanup(self.non_admin_client.rebuild, self.s1_id,
+                        self.image_ref)
+
+        # Verify the properties in the initial response are correct
+        self.assertEqual(self.s1_id, rebuilt_server['id'])
+        rebuilt_image_id = rebuilt_server['image']['id']
+        self.assertEqual(self.image_ref_alt, rebuilt_image_id)
+        self.assertEqual(self.flavor_ref, rebuilt_server['flavor']['id'])
+        self.non_admin_client.wait_for_server_status(rebuilt_server['id'],
+                                                     'ACTIVE',
+                                                     raise_on_error=False)
+        # Verify the server properties after rebuilding
+        resp, server = self.non_admin_client.get_server(rebuilt_server['id'])
+        rebuilt_image_id = server['image']['id']
+        self.assertEqual(self.image_ref_alt, rebuilt_image_id)
 
 
 class ServersAdminTestXML(ServersAdminTestJSON):
diff --git a/tempest/api/compute/admin/test_servers_negative.py b/tempest/api/compute/admin/test_servers_negative.py
new file mode 100644
index 0000000..77d873b
--- /dev/null
+++ b/tempest/api/compute/admin/test_servers_negative.py
@@ -0,0 +1,143 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 Huawei Technologies Co.,LTD.
+#
+#    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 uuid
+
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest.test import attr
+
+
+class ServersAdminNegativeTestJSON(base.BaseV2ComputeAdminTest):
+
+    """
+    Tests Servers API using admin privileges
+    """
+
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(ServersAdminNegativeTestJSON, cls).setUpClass()
+        cls.client = cls.os_adm.servers_client
+        cls.non_adm_client = cls.servers_client
+        cls.flavors_client = cls.os_adm.flavors_client
+        cls.identity_client = cls._get_identity_admin_client()
+        tenant = cls.identity_client.get_tenant_by_name(
+            cls.client.tenant_name)
+        cls.tenant_id = tenant['id']
+
+        cls.s1_name = data_utils.rand_name('server')
+        resp, server = cls.create_test_server(name=cls.s1_name,
+                                              wait_until='ACTIVE')
+        cls.s1_id = server['id']
+
+    def _get_unused_flavor_id(self):
+        flavor_id = data_utils.rand_int_id(start=1000)
+        while True:
+            try:
+                resp, body = self.flavors_client.get_flavor_details(flavor_id)
+            except exceptions.NotFound:
+                break
+            flavor_id = data_utils.rand_int_id(start=1000)
+        return flavor_id
+
+    @attr(type=['negative', 'gate'])
+    def test_resize_server_using_overlimit_ram(self):
+        flavor_name = data_utils.rand_name("flavor-")
+        flavor_id = self._get_unused_flavor_id()
+        resp, quota_set = self.quotas_client.get_default_quota_set(
+            self.tenant_id)
+        ram = int(quota_set['ram']) + 1
+        vcpus = 8
+        disk = 10
+        resp, flavor_ref = self.flavors_client.create_flavor(flavor_name,
+                                                             ram, vcpus, disk,
+                                                             flavor_id)
+        self.addCleanup(self.flavors_client.delete_flavor, flavor_id)
+        self.assertRaises(exceptions.OverLimit,
+                          self.client.resize,
+                          self.servers[0]['id'],
+                          flavor_ref['id'])
+
+    @attr(type=['negative', 'gate'])
+    def test_resize_server_using_overlimit_vcpus(self):
+        flavor_name = data_utils.rand_name("flavor-")
+        flavor_id = self._get_unused_flavor_id()
+        ram = 512
+        resp, quota_set = self.quotas_client.get_default_quota_set(
+            self.tenant_id)
+        vcpus = int(quota_set['cores']) + 1
+        disk = 10
+        resp, flavor_ref = self.flavors_client.create_flavor(flavor_name,
+                                                             ram, vcpus, disk,
+                                                             flavor_id)
+        self.addCleanup(self.flavors_client.delete_flavor, flavor_id)
+        self.assertRaises(exceptions.OverLimit,
+                          self.client.resize,
+                          self.servers[0]['id'],
+                          flavor_ref['id'])
+
+    @attr(type=['negative', 'gate'])
+    def test_reset_state_server_invalid_state(self):
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.reset_state, self.s1_id,
+                          state='invalid')
+
+    @attr(type=['negative', 'gate'])
+    def test_reset_state_server_invalid_type(self):
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.reset_state, self.s1_id,
+                          state=1)
+
+    @attr(type=['negative', 'gate'])
+    def test_reset_state_server_nonexistent_server(self):
+        self.assertRaises(exceptions.NotFound,
+                          self.client.reset_state, '999')
+
+    @attr(type=['negative', 'gate'])
+    def test_get_server_diagnostics_by_non_admin(self):
+        # Non-admin user can not view server diagnostics according to policy
+        self.assertRaises(exceptions.Unauthorized,
+                          self.non_adm_client.get_server_diagnostics,
+                          self.s1_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_migrate_non_existent_server(self):
+        # migrate a non existent server
+        self.assertRaises(exceptions.NotFound,
+                          self.client.migrate_server,
+                          str(uuid.uuid4()))
+
+    @attr(type=['negative', 'gate'])
+    def test_migrate_server_invalid_state(self):
+        # create server.
+        resp, server = self.create_test_server(wait_until='ACTIVE')
+        self.assertEqual(202, resp.status)
+        server_id = server['id']
+        # suspend the server.
+        resp, _ = self.client.suspend_server(server_id)
+        self.assertEqual(202, resp.status)
+        self.client.wait_for_server_status(server_id, 'SUSPENDED')
+        # migrate an suspended server should fail
+        self.assertRaises(exceptions.Conflict,
+                          self.client.migrate_server,
+                          server_id)
+
+
+class ServersAdminNegativeTestXML(ServersAdminNegativeTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/admin/test_services.py b/tempest/api/compute/admin/test_services.py
index 327d8b8..6122758 100644
--- a/tempest/api/compute/admin/test_services.py
+++ b/tempest/api/compute/admin/test_services.py
@@ -17,7 +17,6 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest import exceptions
 from tempest.test import attr
 
 
@@ -41,11 +40,6 @@
         self.assertEqual(200, resp.status)
         self.assertNotEqual(0, len(services))
 
-    @attr(type=['negative', 'gate'])
-    def test_list_services_with_non_admin_user(self):
-        self.assertRaises(exceptions.Unauthorized,
-                          self.non_admin_client.list_services)
-
     @attr(type='gate')
     def test_get_service_by_service_binary_name(self):
         binary_name = 'nova-compute'
@@ -74,15 +68,6 @@
         # on order.
         self.assertEqual(sorted(s1), sorted(s2))
 
-    @attr(type=['negative', 'gate'])
-    def test_get_service_by_invalid_params(self):
-        # return all services if send the request with invalid parameter
-        resp, services = self.client.list_services()
-        params = {'xxx': 'nova-compute'}
-        resp, services_xxx = self.client.list_services(params)
-        self.assertEqual(200, resp.status)
-        self.assertEqual(len(services), len(services_xxx))
-
     @attr(type='gate')
     def test_get_service_by_service_and_host_name(self):
         resp, services = self.client.list_services()
@@ -95,41 +80,6 @@
         self.assertEqual(host_name, services[0]['host'])
         self.assertEqual(binary_name, services[0]['binary'])
 
-    @attr(type=['negative', 'gate'])
-    def test_get_service_by_invalid_service_and_valid_host(self):
-        resp, services = self.client.list_services()
-        host_name = services[0]['host']
-        params = {'host': host_name, 'binary': 'xxx'}
-        resp, services = self.client.list_services(params)
-        self.assertEqual(200, resp.status)
-        self.assertEqual(0, len(services))
-
-    @attr(type=['negative', 'gate'])
-    def test_get_service_with_valid_service_and_invalid_host(self):
-        resp, services = self.client.list_services()
-        binary_name = services[0]['binary']
-        params = {'host': 'xxx', 'binary': binary_name}
-        resp, services = self.client.list_services(params)
-        self.assertEqual(200, resp.status)
-        self.assertEqual(0, len(services))
-
-    @attr(type='gate')
-    def test_service_enable_disable(self):
-        resp, services = self.client.list_services()
-        host_name = services[0]['host']
-        binary_name = services[0]['binary']
-
-        resp, service = self.client.disable_service(host_name, binary_name)
-        self.assertEqual(200, resp.status)
-        params = {'host': host_name, 'binary': binary_name}
-        resp, services = self.client.list_services(params)
-        self.assertEqual('disabled', services[0]['status'])
-
-        resp, service = self.client.enable_service(host_name, binary_name)
-        self.assertEqual(200, resp.status)
-        resp, services = self.client.list_services(params)
-        self.assertEqual('enabled', services[0]['status'])
-
 
 class ServicesAdminTestXML(ServicesAdminTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/compute/admin/test_services_negative.py b/tempest/api/compute/admin/test_services_negative.py
new file mode 100644
index 0000000..da1482e
--- /dev/null
+++ b/tempest/api/compute/admin/test_services_negative.py
@@ -0,0 +1,70 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+# Copyright 2013 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.
+
+from tempest.api.compute import base
+from tempest import exceptions
+from tempest.test import attr
+
+
+class ServicesAdminNegativeTestJSON(base.BaseV2ComputeAdminTest):
+
+    """
+    Tests Services API. List and Enable/Disable require admin privileges.
+    """
+
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(ServicesAdminNegativeTestJSON, cls).setUpClass()
+        cls.client = cls.os_adm.services_client
+        cls.non_admin_client = cls.services_client
+
+    @attr(type=['negative', 'gate'])
+    def test_list_services_with_non_admin_user(self):
+        self.assertRaises(exceptions.Unauthorized,
+                          self.non_admin_client.list_services)
+
+    @attr(type=['negative', 'gate'])
+    def test_get_service_by_invalid_params(self):
+        # return all services if send the request with invalid parameter
+        resp, services = self.client.list_services()
+        params = {'xxx': 'nova-compute'}
+        resp, services_xxx = self.client.list_services(params)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(len(services), len(services_xxx))
+
+    @attr(type=['negative', 'gate'])
+    def test_get_service_by_invalid_service_and_valid_host(self):
+        resp, services = self.client.list_services()
+        host_name = services[0]['host']
+        params = {'host': host_name, 'binary': 'xxx'}
+        resp, services = self.client.list_services(params)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(0, len(services))
+
+    @attr(type=['negative', 'gate'])
+    def test_get_service_with_valid_service_and_invalid_host(self):
+        resp, services = self.client.list_services()
+        binary_name = services[0]['binary']
+        params = {'host': 'xxx', 'binary': binary_name}
+        resp, services = self.client.list_services(params)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(0, len(services))
+
+
+class ServicesAdminNegativeTestXML(ServicesAdminNegativeTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/admin/test_simple_tenant_usage.py b/tempest/api/compute/admin/test_simple_tenant_usage.py
index 3178ead..a599f06 100644
--- a/tempest/api/compute/admin/test_simple_tenant_usage.py
+++ b/tempest/api/compute/admin/test_simple_tenant_usage.py
@@ -39,7 +39,7 @@
                          cls.client.tenant_name][0]
 
         # Create a server in the demo tenant
-        resp, server = cls.create_server(wait_until='ACTIVE')
+        resp, server = cls.create_test_server(wait_until='ACTIVE')
         time.sleep(2)
 
         now = datetime.datetime.now()
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 5679a45..d18b749 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -17,10 +17,8 @@
 
 import time
 
-from tempest.api import compute
 from tempest import clients
-from tempest.common.utils.data_utils import parse_image_id
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.openstack.common import log as logging
 import tempest.test
@@ -32,7 +30,6 @@
 class BaseComputeTest(tempest.test.BaseTestCase):
     """Base test case class for all Compute API tests."""
 
-    conclusion = compute.generic_setup_package()
     force_tenant_isolation = False
 
     @classmethod
@@ -56,6 +53,30 @@
         cls.image_ssh_password = cls.config.compute.image_ssh_password
         cls.servers = []
         cls.images = []
+        cls.multi_user = cls.get_multi_user()
+
+    @classmethod
+    def get_multi_user(cls):
+        multi_user = True
+        # Determine if there are two regular users that can be
+        # used in testing. If the test cases are allowed to create
+        # users (config.compute.allow_tenant_isolation is true,
+        # then we allow multi-user.
+        if not cls.config.compute.allow_tenant_isolation:
+            user1 = cls.config.identity.username
+            user2 = cls.config.identity.alt_username
+            if not user2 or user1 == user2:
+                multi_user = False
+            else:
+                user2_password = cls.config.identity.alt_password
+                user2_tenant_name = cls.config.identity.alt_tenant_name
+                if not user2_password or not user2_tenant_name:
+                    msg = ("Alternate user specified but not alternate "
+                           "tenant or password: alt_tenant_name=%s "
+                           "alt_password=%s"
+                           % (user2_tenant_name, user2_password))
+                    raise exceptions.InvalidConfiguration(msg)
+        return multi_user
 
     @classmethod
     def clear_servers(cls):
@@ -72,19 +93,6 @@
                 pass
 
     @classmethod
-    def rebuild_server(cls, **kwargs):
-        # Destroy an existing server and creates a new one
-        try:
-            cls.servers_client.delete_server(cls.server_id)
-            cls.servers_client.wait_for_server_termination(cls.server_id)
-        except Exception as exc:
-            LOG.exception(exc)
-            pass
-        resp, server = cls.create_server(wait_until='ACTIVE', **kwargs)
-        cls.server_id = server['id']
-        cls.password = server['adminPass']
-
-    @classmethod
     def clear_images(cls):
         for image_id in cls.images:
             try:
@@ -105,9 +113,9 @@
         super(BaseComputeTest, cls).tearDownClass()
 
     @classmethod
-    def create_server(cls, **kwargs):
+    def create_test_server(cls, **kwargs):
         """Wrapper utility that returns a test server."""
-        name = rand_name(cls.__name__ + "-instance")
+        name = data_utils.rand_name(cls.__name__ + "-instance")
         if 'name' in kwargs:
             name = kwargs.pop('name')
         flavor = kwargs.get('flavor', cls.flavor_ref)
@@ -132,25 +140,6 @@
 
         return resp, body
 
-    @classmethod
-    def create_image_from_server(cls, server_id, **kwargs):
-        """Wrapper utility that returns an image created from the server."""
-        name = rand_name(cls.__name__ + "-image")
-        if 'name' in kwargs:
-            name = kwargs.pop('name')
-
-        resp, image = cls.images_client.create_image(
-            server_id, name)
-        image_id = parse_image_id(resp['location'])
-        cls.images.append(image_id)
-
-        if 'wait_until' in kwargs:
-            cls.images_client.wait_for_image_status(image_id,
-                                                    kwargs['wait_until'])
-            resp, image = cls.images_client.get_image(image_id)
-
-        return resp, image
-
     def wait_for(self, condition):
         """Repeatedly calls condition() until a timeout."""
         start_time = int(time.time())
@@ -188,8 +177,49 @@
         cls.availability_zone_client = cls.os.availability_zone_client
         cls.aggregates_client = cls.os.aggregates_client
         cls.services_client = cls.os.services_client
+        cls.instance_usages_audit_log_client = \
+            cls.os.instance_usages_audit_log_client
         cls.hypervisor_client = cls.os.hypervisor_client
         cls.servers_client_v3_auth = cls.os.servers_client_v3_auth
+        cls.certificates_client = cls.os.certificates_client
+
+    @classmethod
+    def create_image_from_server(cls, server_id, **kwargs):
+        """Wrapper utility that returns an image created from the server."""
+        name = data_utils.rand_name(cls.__name__ + "-image")
+        if 'name' in kwargs:
+            name = kwargs.pop('name')
+
+        resp, image = cls.images_client.create_image(
+            server_id, name)
+        image_id = data_utils.parse_image_id(resp['location'])
+        cls.images.append(image_id)
+
+        if 'wait_until' in kwargs:
+            cls.images_client.wait_for_image_status(image_id,
+                                                    kwargs['wait_until'])
+            resp, image = cls.images_client.get_image(image_id)
+
+            if kwargs['wait_until'] == 'ACTIVE':
+                if kwargs.get('wait_for_server', True):
+                    cls.servers_client.wait_for_server_status(server_id,
+                                                              'ACTIVE')
+
+        return resp, image
+
+    @classmethod
+    def rebuild_server(cls, server_id, **kwargs):
+        # Destroy an existing server and creates a new one
+        if server_id:
+            try:
+                cls.servers_client.delete_server(server_id)
+                cls.servers_client.wait_for_server_termination(server_id)
+            except Exception as exc:
+                LOG.exception(exc)
+                pass
+        resp, server = cls.create_test_server(wait_until='ACTIVE', **kwargs)
+        cls.password = server['adminPass']
+        return server['id']
 
 
 class BaseV2ComputeAdminTest(BaseV2ComputeTest):
@@ -215,3 +245,89 @@
                                          interface=cls._interface)
         else:
             cls.os_adm = clients.ComputeAdminManager(interface=cls._interface)
+
+
+class BaseV3ComputeTest(BaseComputeTest):
+
+    @classmethod
+    def setUpClass(cls):
+        super(BaseV3ComputeTest, cls).setUpClass()
+        if not cls.config.compute_feature_enabled.api_v3:
+            cls.tearDownClass()
+            skip_msg = ("%s skipped as nova v3 api is not available" %
+                        cls.__name__)
+            raise cls.skipException(skip_msg)
+
+        cls.servers_client = cls.os.servers_v3_client
+        cls.images_client = cls.os.image_client
+        cls.services_client = cls.os.services_v3_client
+        cls.extensions_client = cls.os.extensions_v3_client
+        cls.availability_zone_client = cls.os.availability_zone_v3_client
+        cls.interfaces_client = cls.os.interfaces_v3_client
+        cls.hypervisor_client = cls.os.hypervisor_v3_client
+        cls.tenant_usages_client = cls.os.tenant_usages_v3_client
+        cls.volumes_client = cls.os.volumes_client
+
+    @classmethod
+    def create_image_from_server(cls, server_id, **kwargs):
+        """Wrapper utility that returns an image created from the server."""
+        name = data_utils.rand_name(cls.__name__ + "-image")
+        if 'name' in kwargs:
+            name = kwargs.pop('name')
+
+        resp, image = cls.servers_client.create_image(
+            server_id, name)
+        image_id = data_utils.parse_image_id(resp['location'])
+        cls.images.append(image_id)
+
+        if 'wait_until' in kwargs:
+            cls.images_client.wait_for_image_status(image_id,
+                                                    kwargs['wait_until'])
+            resp, image = cls.images_client.get_image_meta(image_id)
+
+        return resp, image
+
+    @classmethod
+    def rebuild_server(cls, server_id, **kwargs):
+        # Destroy an existing server and creates a new one
+        try:
+            cls.servers_client.delete_server(server_id)
+            cls.servers_client.wait_for_server_termination(server_id)
+        except Exception as exc:
+            LOG.exception(exc)
+            pass
+        resp, server = cls.create_test_server(wait_until='ACTIVE', **kwargs)
+        cls.password = server['admin_password']
+        return server['id']
+
+
+class BaseV3ComputeAdminTest(BaseV3ComputeTest):
+    """Base test case class for all Compute Admin API V3 tests."""
+
+    @classmethod
+    def setUpClass(cls):
+        super(BaseV3ComputeAdminTest, cls).setUpClass()
+        admin_username = cls.config.compute_admin.username
+        admin_password = cls.config.compute_admin.password
+        admin_tenant = cls.config.compute_admin.tenant_name
+        if not (admin_username and admin_password and admin_tenant):
+            msg = ("Missing Compute Admin API credentials "
+                   "in configuration.")
+            raise cls.skipException(msg)
+        if cls.config.compute.allow_tenant_isolation:
+            creds = cls.isolated_creds.get_admin_creds()
+            admin_username, admin_tenant_name, admin_password = creds
+            os_adm = clients.Manager(username=admin_username,
+                                     password=admin_password,
+                                     tenant_name=admin_tenant_name,
+                                     interface=cls._interface)
+        else:
+            os_adm = clients.ComputeAdminManager(interface=cls._interface)
+
+        cls.os_adm = os_adm
+        cls.severs_admin_client = cls.os_adm.servers_v3_client
+        cls.services_admin_client = cls.os_adm.services_v3_client
+        cls.availability_zone_admin_client = \
+            cls.os_adm.availability_zone_v3_client
+        cls.hypervisor_admin_client = cls.os_adm.hypervisor_v3_client
+        cls.tenant_usages_admin_client = cls.os_adm.tenant_usages_v3_client
diff --git a/tempest/api/compute/certificates/__init__.py b/tempest/api/compute/certificates/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api/compute/certificates/__init__.py
diff --git a/tempest/api/compute/certificates/test_certificates.py b/tempest/api/compute/certificates/test_certificates.py
new file mode 100644
index 0000000..4be1cff
--- /dev/null
+++ b/tempest/api/compute/certificates/test_certificates.py
@@ -0,0 +1,40 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.compute import base
+from tempest.test import attr
+
+
+class CertificatesTestJSON(base.BaseV2ComputeTest):
+    _interface = 'json'
+
+    @attr(type='gate')
+    def test_create_and_get_root_certificate(self):
+        # create certificates
+        resp, create_body = self.certificates_client.create_certificate()
+        self.assertEqual(200, resp.status)
+        self.assertIn('data', create_body)
+        self.assertIn('private_key', create_body)
+        # get the root certificate
+        resp, body = self.certificates_client.get_certificate('root')
+        self.assertEqual(200, resp.status)
+        self.assertIn('data', body)
+        self.assertIn('private_key', body)
+
+
+class CertificatesTestXML(CertificatesTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/flavors/test_flavors.py b/tempest/api/compute/flavors/test_flavors.py
index eac98ea..092fd65 100644
--- a/tempest/api/compute/flavors/test_flavors.py
+++ b/tempest/api/compute/flavors/test_flavors.py
@@ -16,7 +16,6 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest import exceptions
 from tempest.test import attr
 
 
@@ -48,13 +47,7 @@
     def test_get_flavor(self):
         # The expected flavor details should be returned
         resp, flavor = self.client.get_flavor_details(self.flavor_ref)
-        self.assertEqual(self.flavor_ref, int(flavor['id']))
-
-    @attr(type=['negative', 'gate'])
-    def test_get_non_existant_flavor(self):
-        # flavor details are not returned for non-existent flavors
-        self.assertRaises(exceptions.NotFound, self.client.get_flavor_details,
-                          999)
+        self.assertEqual(self.flavor_ref, flavor['id'])
 
     @attr(type='gate')
     def test_list_flavors_limit_results(self):
@@ -136,24 +129,6 @@
         resp, flavors = self.client.list_flavors(params)
         self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]))
 
-    @attr(type=['negative', 'gate'])
-    def test_invalid_minRam_filter(self):
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.list_flavors_with_detail,
-                          {'minRam': 'invalid'})
-
-    @attr(type=['negative', 'gate'])
-    def test_invalid_minDisk_filter(self):
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.list_flavors_with_detail,
-                          {'minDisk': 'invalid'})
-
-    @attr(type=['negative', 'gate'])
-    def test_get_flavor_details_for_invalid_flavor_id(self):
-        # Ensure 404 returned for non-existent flavor ID
-        self.assertRaises(exceptions.NotFound, self.client.get_flavor_details,
-                          9999)
-
 
 class FlavorsTestXML(FlavorsTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/compute/flavors/test_flavors_negative.py b/tempest/api/compute/flavors/test_flavors_negative.py
new file mode 100644
index 0000000..81e4f87
--- /dev/null
+++ b/tempest/api/compute/flavors/test_flavors_negative.py
@@ -0,0 +1,69 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import uuid
+
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest.test import attr
+
+
+class FlavorsNegativeTestJSON(base.BaseV2ComputeTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(FlavorsNegativeTestJSON, cls).setUpClass()
+        cls.client = cls.flavors_client
+
+        # Generating a nonexistent flavor id
+        resp, flavors = cls.client.list_flavors()
+        flavor_ids = [flavor['id'] for flavor in flavors]
+        while True:
+            cls.nonexistent_flavor_id = data_utils.rand_int_id(start=999)
+            if cls.nonexistent_flavor_id not in flavor_ids:
+                break
+
+    @attr(type=['negative', 'gate'])
+    def test_invalid_minRam_filter(self):
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.list_flavors_with_detail,
+                          {'minRam': 'invalid'})
+
+    @attr(type=['negative', 'gate'])
+    def test_invalid_minDisk_filter(self):
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.list_flavors_with_detail,
+                          {'minDisk': 'invalid'})
+
+    @attr(type=['negative', 'gate'])
+    def test_get_flavor_details_for_invalid_flavor_id(self):
+        # Ensure 404 returned for invalid flavor ID
+        invalid_flavor_id = str(uuid.uuid4())
+        self.assertRaises(exceptions.NotFound, self.client.get_flavor_details,
+                          invalid_flavor_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_non_existent_flavor_id(self):
+        # flavor details are not returned for non-existent flavors
+        self.assertRaises(exceptions.NotFound, self.client.get_flavor_details,
+                          self.nonexistent_flavor_id)
+
+
+class FlavorsNegativeTestXML(FlavorsNegativeTestJSON):
+    _interface = 'xml'
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 ff7188b..f4ad449 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
@@ -15,10 +15,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import uuid
-
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
+from tempest.common.utils.data_utils import rand_name
 from tempest import exceptions
 from tempest.test import attr
 
@@ -32,27 +30,15 @@
     def setUpClass(cls):
         super(FloatingIPsTestJSON, cls).setUpClass()
         cls.client = cls.floating_ips_client
-        cls.servers_client = cls.servers_client
+        #cls.servers_client = cls.servers_client
 
         # Server creation
-        resp, server = cls.create_server(wait_until='ACTIVE')
+        resp, server = cls.create_test_server(wait_until='ACTIVE')
         cls.server_id = server['id']
-        resp, body = cls.servers_client.get_server(server['id'])
         # Floating IP creation
         resp, body = cls.client.create_floating_ip()
         cls.floating_ip_id = body['id']
         cls.floating_ip = body['ip']
-        # Generating a nonexistent floatingIP id
-        cls.floating_ip_ids = []
-        resp, body = cls.client.list_floating_ips()
-        for i in range(len(body)):
-            cls.floating_ip_ids.append(body[i]['id'])
-        while True:
-            cls.non_exist_id = data_utils.rand_int_id(start=999)
-            if cls.config.service_available.neutron:
-                cls.non_exist_id = str(uuid.uuid4())
-            if cls.non_exist_id not in cls.floating_ip_ids:
-                break
 
     @classmethod
     def tearDownClass(cls):
@@ -64,10 +50,10 @@
     def test_allocate_floating_ip(self):
         # Positive test:Allocation of a new floating IP to a project
         # should be successful
+        resp, body = self.client.create_floating_ip()
+        self.assertEqual(200, resp.status)
+        floating_ip_id_allocated = body['id']
         try:
-            resp, body = self.client.create_floating_ip()
-            self.assertEqual(200, resp.status)
-            floating_ip_id_allocated = body['id']
             resp, floating_ip_details = \
                 self.client.get_floating_ip_details(floating_ip_id_allocated)
             # Checking if the details of allocated IP is in list of floating IP
@@ -77,14 +63,6 @@
             # Deleting the floating IP which is created in this method
             self.client.delete_floating_ip(floating_ip_id_allocated)
 
-    @attr(type=['negative', 'gate'])
-    def test_allocate_floating_ip_from_nonexistent_pool(self):
-        # Positive test:Allocation of a new floating IP from a nonexistent_pool
-        # to a project should fail
-        self.assertRaises(exceptions.NotFound,
-                          self.client.create_floating_ip,
-                          "non_exist_pool")
-
     @attr(type='gate')
     def test_delete_floating_ip(self):
         # Positive test:Deletion of valid floating IP from project
@@ -116,38 +94,13 @@
             self.server_id)
         self.assertEqual(202, resp.status)
 
-    @attr(type=['negative', 'gate'])
-    def test_delete_nonexistant_floating_ip(self):
-        # Negative test:Deletion of a nonexistent floating IP
-        # from project should fail
-
-        # Deleting the non existent floating IP
-        self.assertRaises(exceptions.NotFound, self.client.delete_floating_ip,
-                          self.non_exist_id)
-
-    @attr(type=['negative', 'gate'])
-    def test_associate_nonexistant_floating_ip(self):
-        # Negative test:Association of a non existent floating IP
-        # to specific server should fail
-        # Associating non existent floating IP
-        self.assertRaises(exceptions.NotFound,
-                          self.client.associate_floating_ip_to_server,
-                          "0.0.0.0", self.server_id)
-
-    @attr(type=['negative', 'gate'])
-    def test_dissociate_nonexistant_floating_ip(self):
-        # Negative test:Dissociation of a non existent floating IP should fail
-        # Dissociating non existent floating IP
-        self.assertRaises(exceptions.NotFound,
-                          self.client.disassociate_floating_ip_from_server,
-                          "0.0.0.0", self.server_id)
-
     @attr(type='gate')
     def test_associate_already_associated_floating_ip(self):
         # positive test:Association of an already associated floating IP
         # to specific server should change the association of the Floating IP
         # Create server so as to use for Multiple association
-        resp, body = self.servers_client.create_server('floating-server2',
+        new_name = rand_name('floating_server')
+        resp, body = self.servers_client.create_server(new_name,
                                                        self.image_ref,
                                                        self.flavor_ref)
         self.servers_client.wait_for_server_status(body['id'], 'ACTIVE')
@@ -174,14 +127,6 @@
                           self.client.disassociate_floating_ip_from_server,
                           self.floating_ip, self.server_id)
 
-    @attr(type=['negative', 'gate'])
-    def test_associate_ip_to_server_without_passing_floating_ip(self):
-        # Negative test:Association of empty floating IP to specific server
-        # should raise NotFound exception
-        self.assertRaises(exceptions.NotFound,
-                          self.client.associate_floating_ip_to_server,
-                          '', self.server_id)
-
 
 class FloatingIPsTestXML(FloatingIPsTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
new file mode 100644
index 0000000..89315bb
--- /dev/null
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
@@ -0,0 +1,94 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import uuid
+
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest.test import attr
+
+
+class FloatingIPsNegativeTestJSON(base.BaseV2ComputeTest):
+    _interface = 'json'
+    server_id = None
+
+    @classmethod
+    def setUpClass(cls):
+        super(FloatingIPsNegativeTestJSON, cls).setUpClass()
+        cls.client = cls.floating_ips_client
+
+        # Server creation
+        resp, server = cls.create_test_server(wait_until='ACTIVE')
+        cls.server_id = server['id']
+        # Generating a nonexistent floatingIP id
+        cls.floating_ip_ids = []
+        resp, body = cls.client.list_floating_ips()
+        for i in range(len(body)):
+            cls.floating_ip_ids.append(body[i]['id'])
+        while True:
+            cls.non_exist_id = data_utils.rand_int_id(start=999)
+            if cls.config.service_available.neutron:
+                cls.non_exist_id = str(uuid.uuid4())
+            if cls.non_exist_id not in cls.floating_ip_ids:
+                break
+
+    @attr(type=['negative', 'gate'])
+    def test_allocate_floating_ip_from_nonexistent_pool(self):
+        # Negative test:Allocation of a new floating IP from a nonexistent_pool
+        # to a project should fail
+        self.assertRaises(exceptions.NotFound,
+                          self.client.create_floating_ip,
+                          "non_exist_pool")
+
+    @attr(type=['negative', 'gate'])
+    def test_delete_nonexistent_floating_ip(self):
+        # Negative test:Deletion of a nonexistent floating IP
+        # from project should fail
+
+        # Deleting the non existent floating IP
+        self.assertRaises(exceptions.NotFound, self.client.delete_floating_ip,
+                          self.non_exist_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_associate_nonexistent_floating_ip(self):
+        # Negative test:Association of a non existent floating IP
+        # to specific server should fail
+        # Associating non existent floating IP
+        self.assertRaises(exceptions.NotFound,
+                          self.client.associate_floating_ip_to_server,
+                          "0.0.0.0", self.server_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_dissociate_nonexistent_floating_ip(self):
+        # Negative test:Dissociation of a non existent floating IP should fail
+        # Dissociating non existent floating IP
+        self.assertRaises(exceptions.NotFound,
+                          self.client.disassociate_floating_ip_from_server,
+                          "0.0.0.0", self.server_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_associate_ip_to_server_without_passing_floating_ip(self):
+        # Negative test:Association of empty floating IP to specific server
+        # should raise NotFound exception
+        self.assertRaises(exceptions.NotFound,
+                          self.client.associate_floating_ip_to_server,
+                          '', self.server_id)
+
+
+class FloatingIPsNegativeTestXML(FloatingIPsNegativeTestJSON):
+    _interface = 'xml'
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 7fec2d1..6387f4e 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips.py
@@ -32,7 +32,6 @@
         cls.client = cls.floating_ips_client
         cls.floating_ip = []
         cls.floating_ip_id = []
-        cls.random_number = 0
         for i in range(3):
             resp, body = cls.client.create_floating_ip()
             cls.floating_ip.append(body)
diff --git a/tempest/api/compute/images/test_image_metadata.py b/tempest/api/compute/images/test_image_metadata.py
index df857bf..618abe2 100644
--- a/tempest/api/compute/images/test_image_metadata.py
+++ b/tempest/api/compute/images/test_image_metadata.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.test import attr
 
@@ -34,11 +34,11 @@
         cls.servers_client = cls.servers_client
         cls.client = cls.images_client
 
-        resp, server = cls.create_server(wait_until='ACTIVE')
+        resp, server = cls.create_test_server(wait_until='ACTIVE')
         cls.server_id = server['id']
 
         # Snapshot the server once to save time
-        name = rand_name('image')
+        name = data_utils.rand_name('image')
         resp, _ = cls.client.create_image(cls.server_id, name, {})
         cls.image_id = resp['location'].rsplit('/', 1)[1]
 
diff --git a/tempest/api/compute/images/test_images.py b/tempest/api/compute/images/test_images.py
index 383ea1d..f7db89b 100644
--- a/tempest/api/compute/images/test_images.py
+++ b/tempest/api/compute/images/test_images.py
@@ -14,11 +14,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.api import compute
 from tempest.api.compute import base
 from tempest import clients
-from tempest.common.utils.data_utils import parse_image_id
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.test import attr
 
@@ -37,7 +35,7 @@
 
         cls.image_ids = []
 
-        if compute.MULTI_USER:
+        if cls.multi_user:
             if cls.config.compute.allow_tenant_isolation:
                 creds = cls.isolated_creds.get_alt_creds()
                 username, tenant_name, password = creds
@@ -58,7 +56,7 @@
 
     def __create_image__(self, server_id, name, meta=None):
         resp, body = self.client.create_image(server_id, name, meta)
-        image_id = parse_image_id(resp['location'])
+        image_id = data_utils.parse_image_id(resp['location'])
         self.client.wait_for_image_status(image_id, 'ACTIVE')
         self.image_ids.append(image_id)
         return resp, body
@@ -66,13 +64,13 @@
     @attr(type=['negative', 'gate'])
     def test_create_image_from_deleted_server(self):
         # An image should not be created if the server instance is removed
-        resp, server = self.create_server(wait_until='ACTIVE')
+        resp, server = self.create_test_server(wait_until='ACTIVE')
 
         # Delete server before trying to create server
         self.servers_client.delete_server(server['id'])
         self.servers_client.wait_for_server_termination(server['id'])
         # Create a new image after server is deleted
-        name = rand_name('image')
+        name = data_utils.rand_name('image')
         meta = {'image_type': 'test'}
         self.assertRaises(exceptions.NotFound,
                           self.__create_image__,
@@ -82,7 +80,7 @@
     def test_create_image_from_invalid_server(self):
         # An image should not be created with invalid server id
         # Create a new image with invalid server id
-        name = rand_name('image')
+        name = data_utils.rand_name('image')
         meta = {'image_type': 'test'}
         resp = {}
         resp['status'] = None
@@ -91,22 +89,23 @@
 
     @attr(type=['negative', 'gate'])
     def test_create_image_from_stopped_server(self):
-        resp, server = self.create_server(wait_until='ACTIVE')
+        resp, server = self.create_test_server(wait_until='ACTIVE')
         self.servers_client.stop(server['id'])
         self.servers_client.wait_for_server_status(server['id'],
                                                    'SHUTOFF')
         self.addCleanup(self.servers_client.delete_server, server['id'])
-        snapshot_name = rand_name('test-snap-')
+        snapshot_name = data_utils.rand_name('test-snap-')
         resp, image = self.create_image_from_server(server['id'],
                                                     name=snapshot_name,
-                                                    wait_until='ACTIVE')
+                                                    wait_until='ACTIVE',
+                                                    wait_for_server=False)
         self.addCleanup(self.client.delete_image, image['id'])
         self.assertEqual(snapshot_name, image['name'])
 
     @attr(type='gate')
     def test_delete_saving_image(self):
-        snapshot_name = rand_name('test-snap-')
-        resp, server = self.create_server(wait_until='ACTIVE')
+        snapshot_name = data_utils.rand_name('test-snap-')
+        resp, server = self.create_test_server(wait_until='ACTIVE')
         self.addCleanup(self.servers_client.delete_server, server['id'])
         resp, image = self.create_image_from_server(server['id'],
                                                     name=snapshot_name,
@@ -117,7 +116,7 @@
     @attr(type=['negative', 'gate'])
     def test_create_image_specify_uuid_35_characters_or_less(self):
         # Return an error if Image ID passed is 35 characters or less
-        snapshot_name = rand_name('test-snap-')
+        snapshot_name = data_utils.rand_name('test-snap-')
         test_uuid = ('a' * 35)
         self.assertRaises(exceptions.NotFound, self.client.create_image,
                           test_uuid, snapshot_name)
@@ -125,7 +124,7 @@
     @attr(type=['negative', 'gate'])
     def test_create_image_specify_uuid_37_characters_or_more(self):
         # Return an error if Image ID passed is 37 characters or more
-        snapshot_name = rand_name('test-snap-')
+        snapshot_name = data_utils.rand_name('test-snap-')
         test_uuid = ('a' * 37)
         self.assertRaises(exceptions.NotFound, self.client.create_image,
                           test_uuid, snapshot_name)
diff --git a/tempest/api/compute/images/test_images_oneserver.py b/tempest/api/compute/images/test_images_oneserver.py
index bec5ea4..b0ff7ab 100644
--- a/tempest/api/compute/images/test_images_oneserver.py
+++ b/tempest/api/compute/images/test_images_oneserver.py
@@ -20,12 +20,9 @@
 from tempest.api import compute
 from tempest.api.compute import base
 from tempest import clients
-from tempest.common.utils.data_utils import parse_image_id
-from tempest.common.utils.data_utils import rand_name
-from tempest import exceptions
+from tempest.common.utils import data_utils
 from tempest.openstack.common import log as logging
 from tempest.test import attr
-from tempest.test import skip_because
 
 LOG = logging.getLogger(__name__)
 
@@ -52,7 +49,7 @@
             LOG.exception(exc)
             # Rebuild server if cannot reach the ACTIVE state
             # Usually it means the server had a serius accident
-            self.rebuild_server()
+            self.__class__.server_id = self.rebuild_server(self.server_id)
 
     @classmethod
     def setUpClass(cls):
@@ -63,7 +60,7 @@
             raise cls.skipException(skip_msg)
 
         try:
-            resp, server = cls.create_server(wait_until='ACTIVE')
+            resp, server = cls.create_test_server(wait_until='ACTIVE')
             cls.server_id = server['id']
         except Exception:
             cls.tearDownClass()
@@ -71,7 +68,7 @@
 
         cls.image_ids = []
 
-        if compute.MULTI_USER:
+        if cls.multi_user:
             if cls.config.compute.allow_tenant_isolation:
                 creds = cls.isolated_creds.get_alt_creds()
                 username, tenant_name, password = creds
@@ -83,31 +80,6 @@
                 cls.alt_manager = clients.AltManager()
             cls.alt_client = cls.alt_manager.images_client
 
-    @skip_because(bug="1006725")
-    @attr(type=['negative', 'gate'])
-    def test_create_image_specify_multibyte_character_image_name(self):
-        # Return an error if the image name has multi-byte characters
-        snapshot_name = rand_name('\xef\xbb\xbf')
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.create_image, self.server_id,
-                          snapshot_name)
-
-    @attr(type=['negative', 'gate'])
-    def test_create_image_specify_invalid_metadata(self):
-        # Return an error when creating image with invalid metadata
-        snapshot_name = rand_name('test-snap-')
-        meta = {'': ''}
-        self.assertRaises(exceptions.BadRequest, self.client.create_image,
-                          self.server_id, snapshot_name, meta)
-
-    @attr(type=['negative', 'gate'])
-    def test_create_image_specify_metadata_over_limits(self):
-        # Return an error when creating image with meta data over 256 chars
-        snapshot_name = rand_name('test-snap-')
-        meta = {'a' * 260: 'b' * 260}
-        self.assertRaises(exceptions.BadRequest, self.client.create_image,
-                          self.server_id, snapshot_name, meta)
-
     def _get_default_flavor_disk_size(self, flavor_id):
         resp, flavor = self.flavors_client.get_flavor_details(flavor_id)
         return flavor['disk']
@@ -118,11 +90,11 @@
     def test_create_delete_image(self):
 
         # Create a new image
-        name = rand_name('image')
+        name = data_utils.rand_name('image')
         meta = {'image_type': 'test'}
         resp, body = self.client.create_image(self.server_id, name, meta)
         self.assertEqual(202, resp.status)
-        image_id = parse_image_id(resp['location'])
+        image_id = data_utils.parse_image_id(resp['location'])
         self.client.wait_for_image_status(image_id, 'ACTIVE')
 
         # Verify the image was created correctly
@@ -145,49 +117,6 @@
         self.assertEqual('204', resp['status'])
         self.client.wait_for_resource_deletion(image_id)
 
-    @attr(type=['negative', 'gate'])
-    def test_create_second_image_when_first_image_is_being_saved(self):
-        # Disallow creating another image when first image is being saved
-
-        # Create first snapshot
-        snapshot_name = rand_name('test-snap-')
-        resp, body = self.client.create_image(self.server_id,
-                                              snapshot_name)
-        self.assertEqual(202, resp.status)
-        image_id = parse_image_id(resp['location'])
-        self.image_ids.append(image_id)
-
-        # Create second snapshot
-        alt_snapshot_name = rand_name('test-snap-')
-        self.assertRaises(exceptions.Conflict, self.client.create_image,
-                          self.server_id, alt_snapshot_name)
-        self.client.wait_for_image_status(image_id, 'ACTIVE')
-
-    @attr(type=['negative', 'gate'])
-    def test_create_image_specify_name_over_256_chars(self):
-        # Return an error if snapshot name over 256 characters is passed
-
-        snapshot_name = rand_name('a' * 260)
-        self.assertRaises(exceptions.BadRequest, self.client.create_image,
-                          self.server_id, snapshot_name)
-
-    @attr(type=['negative', 'gate'])
-    def test_delete_image_that_is_not_yet_active(self):
-        # Return an error while trying to delete an image what is creating
-
-        snapshot_name = rand_name('test-snap-')
-        resp, body = self.client.create_image(self.server_id, snapshot_name)
-        self.assertEqual(202, resp.status)
-        image_id = parse_image_id(resp['location'])
-        self.image_ids.append(image_id)
-
-        # Do not wait, attempt to delete the image, ensure it's successful
-        resp, body = self.client.delete_image(image_id)
-        self.assertEqual('204', resp['status'])
-        self.image_ids.remove(image_id)
-
-        self.assertRaises(exceptions.NotFound, self.client.get_image, image_id)
-
 
 class ImagesOneServerTestXML(ImagesOneServerTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/compute/images/test_images_oneserver_negative.py b/tempest/api/compute/images/test_images_oneserver_negative.py
new file mode 100644
index 0000000..864f445
--- /dev/null
+++ b/tempest/api/compute/images/test_images_oneserver_negative.py
@@ -0,0 +1,152 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# Copyright 2013 IBM Corp.
+# 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 tempest.api.compute import base
+from tempest import clients
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest.openstack.common import log as logging
+from tempest.test import attr
+from tempest.test import skip_because
+
+LOG = logging.getLogger(__name__)
+
+
+class ImagesOneServerNegativeTestJSON(base.BaseV2ComputeTest):
+    _interface = 'json'
+
+    def tearDown(self):
+        """Terminate test instances created after a test is executed."""
+        for image_id in self.image_ids:
+            self.client.delete_image(image_id)
+            self.image_ids.remove(image_id)
+        super(ImagesOneServerNegativeTestJSON, self).tearDown()
+
+    def setUp(self):
+        # NOTE(afazekas): Normally we use the same server with all test cases,
+        # but if it has an issue, we build a new one
+        super(ImagesOneServerNegativeTestJSON, self).setUp()
+        # Check if the server is in a clean state after test
+        try:
+            self.servers_client.wait_for_server_status(self.server_id,
+                                                       'ACTIVE')
+        except Exception as exc:
+            LOG.exception(exc)
+            # Rebuild server if cannot reach the ACTIVE state
+            # Usually it means the server had a serius accident
+            self.__class__.server_id = self.rebuild_server(self.server_id)
+
+    @classmethod
+    def setUpClass(cls):
+        super(ImagesOneServerNegativeTestJSON, cls).setUpClass()
+        cls.client = cls.images_client
+        if not cls.config.service_available.glance:
+            skip_msg = ("%s skipped as glance is not available" % cls.__name__)
+            raise cls.skipException(skip_msg)
+
+        try:
+            resp, server = cls.create_test_server(wait_until='ACTIVE')
+            cls.server_id = server['id']
+        except Exception:
+            cls.tearDownClass()
+            raise
+
+        cls.image_ids = []
+
+        if cls.multi_user:
+            if cls.config.compute.allow_tenant_isolation:
+                creds = cls.isolated_creds.get_alt_creds()
+                username, tenant_name, password = creds
+                cls.alt_manager = clients.Manager(username=username,
+                                                  password=password,
+                                                  tenant_name=tenant_name)
+            else:
+                # Use the alt_XXX credentials in the config file
+                cls.alt_manager = clients.AltManager()
+            cls.alt_client = cls.alt_manager.images_client
+
+    @skip_because(bug="1006725")
+    @attr(type=['negative', 'gate'])
+    def test_create_image_specify_multibyte_character_image_name(self):
+        # Return an error if the image name has multi-byte characters
+        snapshot_name = data_utils.rand_name('\xef\xbb\xbf')
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_image, self.server_id,
+                          snapshot_name)
+
+    @attr(type=['negative', 'gate'])
+    def test_create_image_specify_invalid_metadata(self):
+        # Return an error when creating image with invalid metadata
+        snapshot_name = data_utils.rand_name('test-snap-')
+        meta = {'': ''}
+        self.assertRaises(exceptions.BadRequest, self.client.create_image,
+                          self.server_id, snapshot_name, meta)
+
+    @attr(type=['negative', 'gate'])
+    def test_create_image_specify_metadata_over_limits(self):
+        # Return an error when creating image with meta data over 256 chars
+        snapshot_name = data_utils.rand_name('test-snap-')
+        meta = {'a' * 260: 'b' * 260}
+        self.assertRaises(exceptions.BadRequest, self.client.create_image,
+                          self.server_id, snapshot_name, meta)
+
+    @attr(type=['negative', 'gate'])
+    def test_create_second_image_when_first_image_is_being_saved(self):
+        # Disallow creating another image when first image is being saved
+
+        # Create first snapshot
+        snapshot_name = data_utils.rand_name('test-snap-')
+        resp, body = self.client.create_image(self.server_id,
+                                              snapshot_name)
+        self.assertEqual(202, resp.status)
+        image_id = data_utils.parse_image_id(resp['location'])
+        self.image_ids.append(image_id)
+
+        # Create second snapshot
+        alt_snapshot_name = data_utils.rand_name('test-snap-')
+        self.assertRaises(exceptions.Conflict, self.client.create_image,
+                          self.server_id, alt_snapshot_name)
+
+    @attr(type=['negative', 'gate'])
+    def test_create_image_specify_name_over_256_chars(self):
+        # Return an error if snapshot name over 256 characters is passed
+
+        snapshot_name = data_utils.rand_name('a' * 260)
+        self.assertRaises(exceptions.BadRequest, self.client.create_image,
+                          self.server_id, snapshot_name)
+
+    @attr(type=['negative', 'gate'])
+    def test_delete_image_that_is_not_yet_active(self):
+        # Return an error while trying to delete an image what is creating
+
+        snapshot_name = data_utils.rand_name('test-snap-')
+        resp, body = self.client.create_image(self.server_id, snapshot_name)
+        self.assertEqual(202, resp.status)
+        image_id = data_utils.parse_image_id(resp['location'])
+        self.image_ids.append(image_id)
+
+        # Do not wait, attempt to delete the image, ensure it's successful
+        resp, body = self.client.delete_image(image_id)
+        self.assertEqual('204', resp['status'])
+        self.image_ids.remove(image_id)
+
+        self.assertRaises(exceptions.NotFound, self.client.get_image, image_id)
+
+
+class ImagesOneServerNegativeTestXML(ImagesOneServerNegativeTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/images/test_list_image_filters.py b/tempest/api/compute/images/test_list_image_filters.py
index 8d4e47b..ac2ecba 100644
--- a/tempest/api/compute/images/test_list_image_filters.py
+++ b/tempest/api/compute/images/test_list_image_filters.py
@@ -16,7 +16,6 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils.data_utils import parse_image_id
 from tempest import exceptions
 from tempest.openstack.common import log as logging
 from tempest.test import attr
@@ -38,31 +37,28 @@
         cls.image_ids = []
 
         try:
-            resp, cls.server1 = cls.create_server()
-            resp, cls.server2 = cls.create_server(wait_until='ACTIVE')
+            resp, cls.server1 = cls.create_test_server()
+            resp, cls.server2 = cls.create_test_server(wait_until='ACTIVE')
             # NOTE(sdague) this is faster than doing the sync wait_util on both
             cls.servers_client.wait_for_server_status(cls.server1['id'],
                                                       'ACTIVE')
 
             # Create images to be used in the filter tests
-            resp, body = cls.create_image_from_server(cls.server1['id'])
-            cls.image1_id = parse_image_id(resp['location'])
-            cls.client.wait_for_image_status(cls.image1_id, 'ACTIVE')
-            resp, cls.image1 = cls.client.get_image(cls.image1_id)
+            resp, cls.image1 = cls.create_image_from_server(
+                cls.server1['id'], wait_until='ACTIVE')
+            cls.image1_id = cls.image1['id']
 
             # Servers have a hidden property for when they are being imaged
             # Performing back-to-back create image calls on a single
             # server will sometimes cause failures
-            resp, body = cls.create_image_from_server(cls.server2['id'])
-            cls.image3_id = parse_image_id(resp['location'])
-            cls.client.wait_for_image_status(cls.image3_id, 'ACTIVE')
-            resp, cls.image3 = cls.client.get_image(cls.image3_id)
+            resp, cls.image3 = cls.create_image_from_server(
+                cls.server2['id'], wait_until='ACTIVE')
+            cls.image3_id = cls.image3['id']
 
-            resp, body = cls.create_image_from_server(cls.server1['id'])
-            cls.image2_id = parse_image_id(resp['location'])
-
-            cls.client.wait_for_image_status(cls.image2_id, 'ACTIVE')
-            resp, cls.image2 = cls.client.get_image(cls.image2_id)
+            # Wait for the server to be active after the image upload
+            resp, cls.image2 = cls.create_image_from_server(
+                cls.server1['id'], wait_until='ACTIVE')
+            cls.image2_id = cls.image2['id']
         except Exception as exc:
             LOG.exception(exc)
             cls.tearDownClass()
diff --git a/tempest/api/compute/keypairs/test_keypairs.py b/tempest/api/compute/keypairs/test_keypairs.py
index d059994..50b6c77 100644
--- a/tempest/api/compute/keypairs/test_keypairs.py
+++ b/tempest/api/compute/keypairs/test_keypairs.py
@@ -16,8 +16,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
-from tempest import exceptions
+from tempest.common.utils import data_utils
 from tempest.test import attr
 
 
@@ -35,7 +34,7 @@
         # Create 3 keypairs
         key_list = list()
         for i in range(3):
-            k_name = rand_name('keypair-')
+            k_name = data_utils.rand_name('keypair-')
             resp, keypair = self.client.create_keypair(k_name)
             # Need to pop these keys so that our compare doesn't fail later,
             # as the keypair dicts from list API doesn't have them.
@@ -66,7 +65,7 @@
     @attr(type='gate')
     def test_keypair_create_delete(self):
         # Keypair should be created, verified and deleted
-        k_name = rand_name('keypair-')
+        k_name = data_utils.rand_name('keypair-')
         resp, keypair = self.client.create_keypair(k_name)
         self.assertEqual(200, resp.status)
         private_key = keypair['private_key']
@@ -82,7 +81,7 @@
     @attr(type='gate')
     def test_get_keypair_detail(self):
         # Keypair should be created, Got details by name and deleted
-        k_name = rand_name('keypair-')
+        k_name = data_utils.rand_name('keypair-')
         resp, keypair = self.client.create_keypair(k_name)
         self.addCleanup(self.client.delete_keypair, k_name)
         resp, keypair_detail = self.client.get_keypair(k_name)
@@ -99,7 +98,7 @@
     @attr(type='gate')
     def test_keypair_create_with_pub_key(self):
         # Keypair should be created with a given public key
-        k_name = rand_name('keypair-')
+        k_name = data_utils.rand_name('keypair-')
         pub_key = ("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCs"
                    "Ne3/1ILNCqFyfYWDeTKLD6jEXC2OQHLmietMWW+/vd"
                    "aZq7KZEwO0jhglaFjU1mpqq4Gz5RX156sCTNM9vRbw"
@@ -120,69 +119,6 @@
         resp, _ = self.client.delete_keypair(k_name)
         self.assertEqual(202, resp.status)
 
-    @attr(type=['negative', 'gate'])
-    def test_keypair_create_with_invalid_pub_key(self):
-        # Keypair should not be created with a non RSA public key
-        k_name = rand_name('keypair-')
-        pub_key = "ssh-rsa JUNK nova@ubuntu"
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.create_keypair, k_name, pub_key)
-
-    @attr(type=['negative', 'gate'])
-    def test_keypair_delete_nonexistant_key(self):
-        # Non-existant key deletion should throw a proper error
-        k_name = rand_name("keypair-non-existant-")
-        self.assertRaises(exceptions.NotFound, self.client.delete_keypair,
-                          k_name)
-
-    @attr(type=['negative', 'gate'])
-    def test_create_keypair_with_empty_public_key(self):
-        # Keypair should not be created with an empty public key
-        k_name = rand_name("keypair-")
-        pub_key = ' '
-        self.assertRaises(exceptions.BadRequest, self.client.create_keypair,
-                          k_name, pub_key)
-
-    @attr(type=['negative', 'gate'])
-    def test_create_keypair_when_public_key_bits_exceeds_maximum(self):
-        # Keypair should not be created when public key bits are too long
-        k_name = rand_name("keypair-")
-        pub_key = 'ssh-rsa ' + 'A' * 2048 + ' openstack@ubuntu'
-        self.assertRaises(exceptions.BadRequest, self.client.create_keypair,
-                          k_name, pub_key)
-
-    @attr(type=['negative', 'gate'])
-    def test_create_keypair_with_duplicate_name(self):
-        # Keypairs with duplicate names should not be created
-        k_name = rand_name('keypair-')
-        resp, _ = self.client.create_keypair(k_name)
-        self.assertEqual(200, resp.status)
-        # Now try the same keyname to create another key
-        self.assertRaises(exceptions.Conflict, self.client.create_keypair,
-                          k_name)
-        resp, _ = self.client.delete_keypair(k_name)
-        self.assertEqual(202, resp.status)
-
-    @attr(type=['negative', 'gate'])
-    def test_create_keypair_with_empty_name_string(self):
-        # Keypairs with name being an empty string should not be created
-        self.assertRaises(exceptions.BadRequest, self.client.create_keypair,
-                          '')
-
-    @attr(type=['negative', 'gate'])
-    def test_create_keypair_with_long_keynames(self):
-        # Keypairs with name longer than 255 chars should not be created
-        k_name = 'keypair-'.ljust(260, '0')
-        self.assertRaises(exceptions.BadRequest, self.client.create_keypair,
-                          k_name)
-
-    @attr(type=['negative', 'gate'])
-    def test_create_keypair_invalid_name(self):
-        # Keypairs with name being an invalid name should not be created
-        k_name = 'key_/.\@:'
-        self.assertRaises(exceptions.BadRequest, self.client.create_keypair,
-                          k_name)
-
 
 class KeyPairsTestXML(KeyPairsTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/compute/keypairs/test_keypairs_negative.py b/tempest/api/compute/keypairs/test_keypairs_negative.py
new file mode 100644
index 0000000..fad985e
--- /dev/null
+++ b/tempest/api/compute/keypairs/test_keypairs_negative.py
@@ -0,0 +1,98 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# Copyright 2013 IBM Corp
+# 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 tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest.test import attr
+
+
+class KeyPairsNegativeTestJSON(base.BaseV2ComputeTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(KeyPairsNegativeTestJSON, cls).setUpClass()
+        cls.client = cls.keypairs_client
+
+    @attr(type=['negative', 'gate'])
+    def test_keypair_create_with_invalid_pub_key(self):
+        # Keypair should not be created with a non RSA public key
+        k_name = data_utils.rand_name('keypair-')
+        pub_key = "ssh-rsa JUNK nova@ubuntu"
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_keypair, k_name, pub_key)
+
+    @attr(type=['negative', 'gate'])
+    def test_keypair_delete_nonexistant_key(self):
+        # Non-existant key deletion should throw a proper error
+        k_name = data_utils.rand_name("keypair-non-existant-")
+        self.assertRaises(exceptions.NotFound, self.client.delete_keypair,
+                          k_name)
+
+    @attr(type=['negative', 'gate'])
+    def test_create_keypair_with_empty_public_key(self):
+        # Keypair should not be created with an empty public key
+        k_name = data_utils.rand_name("keypair-")
+        pub_key = ' '
+        self.assertRaises(exceptions.BadRequest, self.client.create_keypair,
+                          k_name, pub_key)
+
+    @attr(type=['negative', 'gate'])
+    def test_create_keypair_when_public_key_bits_exceeds_maximum(self):
+        # Keypair should not be created when public key bits are too long
+        k_name = data_utils.rand_name("keypair-")
+        pub_key = 'ssh-rsa ' + 'A' * 2048 + ' openstack@ubuntu'
+        self.assertRaises(exceptions.BadRequest, self.client.create_keypair,
+                          k_name, pub_key)
+
+    @attr(type=['negative', 'gate'])
+    def test_create_keypair_with_duplicate_name(self):
+        # Keypairs with duplicate names should not be created
+        k_name = data_utils.rand_name('keypair-')
+        resp, _ = self.client.create_keypair(k_name)
+        self.assertEqual(200, resp.status)
+        # Now try the same keyname to create another key
+        self.assertRaises(exceptions.Conflict, self.client.create_keypair,
+                          k_name)
+        resp, _ = self.client.delete_keypair(k_name)
+        self.assertEqual(202, resp.status)
+
+    @attr(type=['negative', 'gate'])
+    def test_create_keypair_with_empty_name_string(self):
+        # Keypairs with name being an empty string should not be created
+        self.assertRaises(exceptions.BadRequest, self.client.create_keypair,
+                          '')
+
+    @attr(type=['negative', 'gate'])
+    def test_create_keypair_with_long_keynames(self):
+        # Keypairs with name longer than 255 chars should not be created
+        k_name = 'keypair-'.ljust(260, '0')
+        self.assertRaises(exceptions.BadRequest, self.client.create_keypair,
+                          k_name)
+
+    @attr(type=['negative', 'gate'])
+    def test_create_keypair_invalid_name(self):
+        # Keypairs with name being an invalid name should not be created
+        k_name = 'key_/.\@:'
+        self.assertRaises(exceptions.BadRequest, self.client.create_keypair,
+                          k_name)
+
+
+class KeyPairsNegativeTestXML(KeyPairsNegativeTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/security_groups/test_security_group_rules.py b/tempest/api/compute/security_groups/test_security_group_rules.py
index 9dc164d..2ccc3a8 100644
--- a/tempest/api/compute/security_groups/test_security_group_rules.py
+++ b/tempest/api/compute/security_groups/test_security_group_rules.py
@@ -17,10 +17,7 @@
 
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
-from tempest import config
-from tempest import exceptions
 from tempest.test import attr
-from tempest.test import skip_because
 
 
 class SecurityGroupRulesTestJSON(base.BaseV2ComputeTest):
@@ -30,8 +27,9 @@
     def setUpClass(cls):
         super(SecurityGroupRulesTestJSON, cls).setUpClass()
         cls.client = cls.security_groups_client
+        cls.neutron_available = cls.config.service_available.neutron
 
-    @attr(type='gate')
+    @attr(type='smoke')
     def test_security_group_rules_create(self):
         # Positive test: Creation of Security Group rule
         # should be successful
@@ -54,7 +52,7 @@
         self.addCleanup(self.client.delete_security_group_rule, rule['id'])
         self.assertEqual(200, resp.status)
 
-    @attr(type='gate')
+    @attr(type='smoke')
     def test_security_group_rules_create_with_optional_arguments(self):
         # Positive test: Creation of Security Group rule
         # with optional arguments
@@ -93,109 +91,7 @@
         self.addCleanup(self.client.delete_security_group_rule, rule['id'])
         self.assertEqual(200, resp.status)
 
-    @skip_because(bug="1182384",
-                  condition=config.TempestConfig().service_available.neutron)
-    @attr(type=['negative', 'gate'])
-    def test_security_group_rules_create_with_invalid_id(self):
-        # Negative test: Creation of Security Group rule should FAIL
-        # with invalid Parent group id
-        # Adding rules to the invalid Security Group id
-        parent_group_id = data_utils.rand_int_id(start=999)
-        ip_protocol = 'tcp'
-        from_port = 22
-        to_port = 22
-        self.assertRaises(exceptions.NotFound,
-                          self.client.create_security_group_rule,
-                          parent_group_id, ip_protocol, from_port, to_port)
-
-    @attr(type=['negative', 'gate'])
-    def test_security_group_rules_create_with_invalid_ip_protocol(self):
-        # Negative test: Creation of Security Group rule should FAIL
-        # with invalid ip_protocol
-        # Creating a Security Group to add rule to it
-        s_name = data_utils.rand_name('securitygroup-')
-        s_description = data_utils.rand_name('description-')
-        resp, securitygroup = self.client.create_security_group(s_name,
-                                                                s_description)
-        # Adding rules to the created Security Group
-        parent_group_id = securitygroup['id']
-        ip_protocol = data_utils.rand_name('999')
-        from_port = 22
-        to_port = 22
-
-        self.addCleanup(self.client.delete_security_group, securitygroup['id'])
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.create_security_group_rule,
-                          parent_group_id, ip_protocol, from_port, to_port)
-
-    @attr(type=['negative', 'gate'])
-    def test_security_group_rules_create_with_invalid_from_port(self):
-        # Negative test: Creation of Security Group rule should FAIL
-        # with invalid from_port
-        # Creating a Security Group to add rule to it
-        s_name = data_utils.rand_name('securitygroup-')
-        s_description = data_utils.rand_name('description-')
-        resp, securitygroup = self.client.create_security_group(s_name,
-                                                                s_description)
-        # Adding rules to the created Security Group
-        parent_group_id = securitygroup['id']
-        ip_protocol = 'tcp'
-        from_port = data_utils.rand_int_id(start=999, end=65535)
-        to_port = 22
-        self.addCleanup(self.client.delete_security_group, securitygroup['id'])
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.create_security_group_rule,
-                          parent_group_id, ip_protocol, from_port, to_port)
-
-    @attr(type=['negative', 'gate'])
-    def test_security_group_rules_create_with_invalid_to_port(self):
-        # Negative test: Creation of Security Group rule should FAIL
-        # with invalid to_port
-        # Creating a Security Group to add rule to it
-        s_name = data_utils.rand_name('securitygroup-')
-        s_description = data_utils.rand_name('description-')
-        resp, securitygroup = self.client.create_security_group(s_name,
-                                                                s_description)
-        # Adding rules to the created Security Group
-        parent_group_id = securitygroup['id']
-        ip_protocol = 'tcp'
-        from_port = 22
-        to_port = data_utils.rand_int_id(start=65536)
-        self.addCleanup(self.client.delete_security_group, securitygroup['id'])
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.create_security_group_rule,
-                          parent_group_id, ip_protocol, from_port, to_port)
-
-    @attr(type=['negative', 'gate'])
-    def test_security_group_rules_create_with_invalid_port_range(self):
-        # Negative test: Creation of Security Group rule should FAIL
-        # with invalid port range.
-        # Creating a Security Group to add rule to it.
-        s_name = data_utils.rand_name('securitygroup-')
-        s_description = data_utils.rand_name('description-')
-        resp, securitygroup = self.client.create_security_group(s_name,
-                                                                s_description)
-        # Adding a rule to the created Security Group
-        secgroup_id = securitygroup['id']
-        ip_protocol = 'tcp'
-        from_port = 22
-        to_port = 21
-        self.addCleanup(self.client.delete_security_group, securitygroup['id'])
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.create_security_group_rule,
-                          secgroup_id, ip_protocol, from_port, to_port)
-
-    @skip_because(bug="1182384",
-                  condition=config.TempestConfig().service_available.neutron)
-    @attr(type=['negative', 'gate'])
-    def test_security_group_rules_delete_with_invalid_id(self):
-        # Negative test: Deletion of Security Group rule should be FAIL
-        # with invalid rule id
-        self.assertRaises(exceptions.NotFound,
-                          self.client.delete_security_group_rule,
-                          data_utils.rand_int_id(start=999))
-
-    @attr(type='gate')
+    @attr(type='smoke')
     def test_security_group_rules_list(self):
         # Positive test: Created Security Group rules should be
         # in the list of all rules
@@ -238,6 +134,44 @@
         self.assertTrue(any([i for i in rules if i['id'] == rule1_id]))
         self.assertTrue(any([i for i in rules if i['id'] == rule2_id]))
 
+    @attr(type='smoke')
+    def test_security_group_rules_delete_when_peer_group_deleted(self):
+        # Positive test:rule will delete when peer group deleting
+        # Creating a Security Group to add rules to it
+        s1_name = data_utils.rand_name('securitygroup1-')
+        s1_description = data_utils.rand_name('description1-')
+        resp, sg1 = \
+            self.client.create_security_group(s1_name, s1_description)
+        self.addCleanup(self.client.delete_security_group, sg1['id'])
+        self.assertEqual(200, resp.status)
+        # Creating other Security Group to access to group1
+        s2_name = data_utils.rand_name('securitygroup2-')
+        s2_description = data_utils.rand_name('description2-')
+        resp, sg2 = \
+            self.client.create_security_group(s2_name, s2_description)
+        self.assertEqual(200, resp.status)
+        sg2_id = sg2['id']
+        # Adding rules to the Group1
+        ip_protocol = 'tcp'
+        from_port = 22
+        to_port = 22
+        resp, rule = \
+            self.client.create_security_group_rule(sg1['id'],
+                                                   ip_protocol,
+                                                   from_port,
+                                                   to_port,
+                                                   group_id=sg2_id)
+
+        self.assertEqual(200, resp.status)
+        # Delete group2
+        resp, body = self.client.delete_security_group(sg2_id)
+        self.assertEqual(202, resp.status)
+        # Get rules of the Group1
+        resp, rules = \
+            self.client.list_security_group_rules(sg1['id'])
+        # The group1 has no rules because group2 has deleted
+        self.assertEqual(0, len(rules))
+
 
 class SecurityGroupRulesTestXML(SecurityGroupRulesTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/compute/security_groups/test_security_group_rules_negative.py b/tempest/api/compute/security_groups/test_security_group_rules_negative.py
new file mode 100644
index 0000000..1c38268
--- /dev/null
+++ b/tempest/api/compute/security_groups/test_security_group_rules_negative.py
@@ -0,0 +1,183 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 Huawei Technologies Co.,LTD.
+# 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 testtools
+
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import config
+from tempest import exceptions
+from tempest.test import attr
+from tempest.test import skip_because
+
+
+class SecurityGroupRulesNegativeTestJSON(base.BaseV2ComputeTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(SecurityGroupRulesNegativeTestJSON, cls).setUpClass()
+        cls.client = cls.security_groups_client
+
+    @skip_because(bug="1182384",
+                  condition=config.TempestConfig().service_available.neutron)
+    @attr(type=['negative', 'smoke'])
+    def test_create_security_group_rule_with_non_existent_id(self):
+        # Negative test: Creation of Security Group rule should FAIL
+        # with non existent Parent group id
+        # Adding rules to the non existent Security Group id
+        parent_group_id = data_utils.rand_int_id(start=999)
+        ip_protocol = 'tcp'
+        from_port = 22
+        to_port = 22
+        self.assertRaises(exceptions.NotFound,
+                          self.client.create_security_group_rule,
+                          parent_group_id, ip_protocol, from_port, to_port)
+
+    @testtools.skipIf(config.TempestConfig().service_available.neutron,
+                      "Neutron not check the security_group_id")
+    @attr(type=['negative', 'smoke'])
+    def test_create_security_group_rule_with_invalid_id(self):
+        # Negative test: Creation of Security Group rule should FAIL
+        # with Parent group id which is not integer
+        # Adding rules to the non int Security Group id
+        parent_group_id = data_utils.rand_name('non_int_id')
+        ip_protocol = 'tcp'
+        from_port = 22
+        to_port = 22
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_security_group_rule,
+                          parent_group_id, ip_protocol, from_port, to_port)
+
+    @attr(type=['negative', 'smoke'])
+    def test_create_security_group_rule_duplicate(self):
+        # Negative test: Create Security Group rule duplicate should fail
+        # Creating a Security Group to add rule to it
+        s_name = data_utils.rand_name('securitygroup-')
+        s_description = data_utils.rand_name('description-')
+        resp, sg = self.client.create_security_group(s_name, s_description)
+        self.assertEqual(200, resp.status)
+        # Adding rules to the created Security Group
+        parent_group_id = sg['id']
+        ip_protocol = 'tcp'
+        from_port = 22
+        to_port = 22
+
+        self.addCleanup(self.client.delete_security_group, sg['id'])
+        resp, rule = \
+            self.client.create_security_group_rule(parent_group_id,
+                                                   ip_protocol,
+                                                   from_port,
+                                                   to_port)
+        self.addCleanup(self.client.delete_security_group_rule, rule['id'])
+        self.assertEqual(200, resp.status)
+        # Add the same rule to the group should fail
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_security_group_rule,
+                          parent_group_id, ip_protocol, from_port, to_port)
+
+    @attr(type=['negative', 'smoke'])
+    def test_create_security_group_rule_with_invalid_ip_protocol(self):
+        # Negative test: Creation of Security Group rule should FAIL
+        # with invalid ip_protocol
+        # Creating a Security Group to add rule to it
+        s_name = data_utils.rand_name('securitygroup-')
+        s_description = data_utils.rand_name('description-')
+        resp, securitygroup = self.client.create_security_group(s_name,
+                                                                s_description)
+        # Adding rules to the created Security Group
+        parent_group_id = securitygroup['id']
+        ip_protocol = data_utils.rand_name('999')
+        from_port = 22
+        to_port = 22
+
+        self.addCleanup(self.client.delete_security_group, securitygroup['id'])
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_security_group_rule,
+                          parent_group_id, ip_protocol, from_port, to_port)
+
+    @attr(type=['negative', 'smoke'])
+    def test_create_security_group_rule_with_invalid_from_port(self):
+        # Negative test: Creation of Security Group rule should FAIL
+        # with invalid from_port
+        # Creating a Security Group to add rule to it
+        s_name = data_utils.rand_name('securitygroup-')
+        s_description = data_utils.rand_name('description-')
+        resp, securitygroup = self.client.create_security_group(s_name,
+                                                                s_description)
+        # Adding rules to the created Security Group
+        parent_group_id = securitygroup['id']
+        ip_protocol = 'tcp'
+        from_port = data_utils.rand_int_id(start=65536)
+        to_port = 22
+        self.addCleanup(self.client.delete_security_group, securitygroup['id'])
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_security_group_rule,
+                          parent_group_id, ip_protocol, from_port, to_port)
+
+    @attr(type=['negative', 'smoke'])
+    def test_create_security_group_rule_with_invalid_to_port(self):
+        # Negative test: Creation of Security Group rule should FAIL
+        # with invalid to_port
+        # Creating a Security Group to add rule to it
+        s_name = data_utils.rand_name('securitygroup-')
+        s_description = data_utils.rand_name('description-')
+        resp, securitygroup = self.client.create_security_group(s_name,
+                                                                s_description)
+        # Adding rules to the created Security Group
+        parent_group_id = securitygroup['id']
+        ip_protocol = 'tcp'
+        from_port = 22
+        to_port = data_utils.rand_int_id(start=65536)
+        self.addCleanup(self.client.delete_security_group, securitygroup['id'])
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_security_group_rule,
+                          parent_group_id, ip_protocol, from_port, to_port)
+
+    @attr(type=['negative', 'smoke'])
+    def test_create_security_group_rule_with_invalid_port_range(self):
+        # Negative test: Creation of Security Group rule should FAIL
+        # with invalid port range.
+        # Creating a Security Group to add rule to it.
+        s_name = data_utils.rand_name('securitygroup-')
+        s_description = data_utils.rand_name('description-')
+        resp, securitygroup = self.client.create_security_group(s_name,
+                                                                s_description)
+        # Adding a rule to the created Security Group
+        secgroup_id = securitygroup['id']
+        ip_protocol = 'tcp'
+        from_port = 22
+        to_port = 21
+        self.addCleanup(self.client.delete_security_group, securitygroup['id'])
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_security_group_rule,
+                          secgroup_id, ip_protocol, from_port, to_port)
+
+    @skip_because(bug="1182384",
+                  condition=config.TempestConfig().service_available.neutron)
+    @attr(type=['negative', 'smoke'])
+    def test_delete_security_group_rule_with_non_existent_id(self):
+        # Negative test: Deletion of Security Group rule should be FAIL
+        # with non existent id
+        non_existent_rule_id = data_utils.rand_int_id(start=999)
+        self.assertRaises(exceptions.NotFound,
+                          self.client.delete_security_group_rule,
+                          non_existent_rule_id)
+
+
+class SecurityGroupRulesNegativeTestXML(SecurityGroupRulesNegativeTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/security_groups/test_security_groups.py b/tempest/api/compute/security_groups/test_security_groups.py
index 6e08700..7cb96af 100644
--- a/tempest/api/compute/security_groups/test_security_groups.py
+++ b/tempest/api/compute/security_groups/test_security_groups.py
@@ -16,6 +16,7 @@
 #    under the License.
 
 import testtools
+import uuid
 
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
@@ -32,6 +33,7 @@
     def setUpClass(cls):
         super(SecurityGroupsTestJSON, cls).setUpClass()
         cls.client = cls.security_groups_client
+        cls.neutron_available = cls.config.service_available.neutron
 
     def _delete_security_group(self, securitygroup_id):
         resp, _ = self.client.delete_security_group(securitygroup_id)
@@ -108,9 +110,7 @@
                          "The fetched Security Group is different "
                          "from the created Group")
 
-    @skip_because(bug="1182384",
-                  condition=config.TempestConfig().service_available.neutron)
-    @attr(type=['negative', 'gate'])
+    @attr(type=['negative', 'smoke'])
     def test_security_group_get_nonexistant_group(self):
         # Negative test:Should not be able to GET the details
         # of non-existent Security Group
@@ -121,6 +121,8 @@
         # Creating a non-existent Security Group id
         while True:
             non_exist_id = data_utils.rand_int_id(start=999)
+            if self.neutron_available:
+                non_exist_id = str(uuid.uuid4())
             if non_exist_id not in security_group_id:
                 break
         self.assertRaises(exceptions.NotFound, self.client.get_security_group,
@@ -198,9 +200,7 @@
                           self.client.delete_security_group,
                           default_security_group_id)
 
-    @skip_because(bug="1182384",
-                  condition=config.TempestConfig().service_available.neutron)
-    @attr(type=['negative', 'gate'])
+    @attr(type=['negative', 'smoke'])
     def test_delete_nonexistant_security_group(self):
         # Negative test:Deletion of a non-existent Security Group should Fail
         security_group_id = []
@@ -210,6 +210,8 @@
         # Creating non-existent Security Group
         while True:
             non_exist_id = data_utils.rand_int_id(start=999)
+            if self.neutron_available:
+                non_exist_id = str(uuid.uuid4())
             if non_exist_id not in security_group_id:
                 break
         self.assertRaises(exceptions.NotFound,
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index c554dc2..a177cea 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -40,8 +40,7 @@
             self.assertEqual(iface['fixed_ips'][0]['ip_address'], fixed_ip)
 
     def _create_server_get_interfaces(self):
-        resp, server = self.create_server()
-        self.os.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
+        resp, server = self.create_test_server(wait_until='ACTIVE')
         resp, ifs = self.client.list_interfaces(server['id'])
         resp, body = self.client.wait_for_interface_status(
             server['id'], ifs[0]['port_id'], 'ACTIVE')
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index adbc048..24ade96 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -22,7 +22,7 @@
 
 from tempest.api import compute
 from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.common.utils.linux.remote_client import RemoteClient
 import tempest.config
 from tempest.test import attr
@@ -39,17 +39,17 @@
         cls.meta = {'hello': 'world'}
         cls.accessIPv4 = '1.1.1.1'
         cls.accessIPv6 = '0000:0000:0000:0000:0000:babe:220.12.22.2'
-        cls.name = rand_name('server')
+        cls.name = data_utils.rand_name('server')
         file_contents = 'This is a test file.'
         personality = [{'path': '/test.txt',
                        'contents': base64.b64encode(file_contents)}]
         cls.client = cls.servers_client
-        cli_resp = cls.create_server(name=cls.name,
-                                     meta=cls.meta,
-                                     accessIPv4=cls.accessIPv4,
-                                     accessIPv6=cls.accessIPv6,
-                                     personality=personality,
-                                     disk_config=cls.disk_config)
+        cli_resp = cls.create_test_server(name=cls.name,
+                                          meta=cls.meta,
+                                          accessIPv4=cls.accessIPv4,
+                                          accessIPv6=cls.accessIPv6,
+                                          personality=personality,
+                                          disk_config=cls.disk_config)
         cls.resp, cls.server_initial = cli_resp
         cls.password = cls.server_initial['adminPass']
         cls.client.wait_for_server_status(cls.server_initial['id'], 'ACTIVE')
@@ -72,7 +72,7 @@
                          str(netaddr.IPAddress(self.accessIPv6)))
         self.assertEqual(self.name, self.server['name'])
         self.assertEqual(self.image_ref, self.server['image']['id'])
-        self.assertEqual(str(self.flavor_ref), self.server['flavor']['id'])
+        self.assertEqual(self.flavor_ref, self.server['flavor']['id'])
         self.assertEqual(self.meta, self.server['metadata'])
 
     @attr(type='smoke')
diff --git a/tempest/api/compute/servers/test_disk_config.py b/tempest/api/compute/servers/test_disk_config.py
index 76a7117..0121c42 100644
--- a/tempest/api/compute/servers/test_disk_config.py
+++ b/tempest/api/compute/servers/test_disk_config.py
@@ -32,19 +32,25 @@
             raise cls.skipException(msg)
         super(ServerDiskConfigTestJSON, cls).setUpClass()
         cls.client = cls.os.servers_client
+        resp, server = cls.create_test_server(wait_until='ACTIVE')
+        cls.server_id = server['id']
+
+    def _update_server_with_disk_config(self, disk_config):
+        resp, server = self.client.get_server(self.server_id)
+        if disk_config != server['OS-DCF:diskConfig']:
+            resp, server = self.client.update_server(self.server_id,
+                                                     disk_config=disk_config)
+            self.assertEqual(200, resp.status)
+            self.client.wait_for_server_status(server['id'], 'ACTIVE')
+            resp, server = self.client.get_server(server['id'])
+            self.assertEqual(disk_config, server['OS-DCF:diskConfig'])
 
     @attr(type='gate')
     def test_rebuild_server_with_manual_disk_config(self):
         # A server should be rebuilt using the manual disk config option
-        resp, server = self.create_server(disk_config='AUTO',
-                                          wait_until='ACTIVE')
-        self.addCleanup(self.client.delete_server, server['id'])
+        self._update_server_with_disk_config(disk_config='AUTO')
 
-        # Verify the specified attributes are set correctly
-        resp, server = self.client.get_server(server['id'])
-        self.assertEqual('AUTO', server['OS-DCF:diskConfig'])
-
-        resp, server = self.client.rebuild(server['id'],
+        resp, server = self.client.rebuild(self.server_id,
                                            self.image_ref_alt,
                                            disk_config='MANUAL')
 
@@ -58,15 +64,9 @@
     @attr(type='gate')
     def test_rebuild_server_with_auto_disk_config(self):
         # A server should be rebuilt using the auto disk config option
-        resp, server = self.create_server(disk_config='MANUAL',
-                                          wait_until='ACTIVE')
-        self.addCleanup(self.client.delete_server, server['id'])
+        self._update_server_with_disk_config(disk_config='MANUAL')
 
-        # Verify the specified attributes are set correctly
-        resp, server = self.client.get_server(server['id'])
-        self.assertEqual('MANUAL', server['OS-DCF:diskConfig'])
-
-        resp, server = self.client.rebuild(server['id'],
+        resp, server = self.client.rebuild(self.server_id,
                                            self.image_ref_alt,
                                            disk_config='AUTO')
 
@@ -77,54 +77,53 @@
         resp, server = self.client.get_server(server['id'])
         self.assertEqual('AUTO', server['OS-DCF:diskConfig'])
 
+    def _get_alternative_flavor(self):
+        resp, server = self.client.get_server(self.server_id)
+
+        if server['flavor']['id'] == self.flavor_ref:
+            return self.flavor_ref_alt
+        else:
+            return self.flavor_ref
+
     @testtools.skipUnless(compute.RESIZE_AVAILABLE, 'Resize not available.')
     @attr(type='gate')
     def test_resize_server_from_manual_to_auto(self):
         # A server should be resized from manual to auto disk config
-        resp, server = self.create_server(disk_config='MANUAL',
-                                          wait_until='ACTIVE')
-        self.addCleanup(self.client.delete_server, server['id'])
-        # Resize with auto option
-        self.client.resize(server['id'], self.flavor_ref_alt,
-                           disk_config='AUTO')
-        self.client.wait_for_server_status(server['id'], 'VERIFY_RESIZE')
-        self.client.confirm_resize(server['id'])
-        self.client.wait_for_server_status(server['id'], 'ACTIVE')
+        self._update_server_with_disk_config(disk_config='MANUAL')
 
-        resp, server = self.client.get_server(server['id'])
+        # Resize with auto option
+        flavor_id = self._get_alternative_flavor()
+        self.client.resize(self.server_id, flavor_id, disk_config='AUTO')
+        self.client.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
+        self.client.confirm_resize(self.server_id)
+        self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+
+        resp, server = self.client.get_server(self.server_id)
         self.assertEqual('AUTO', server['OS-DCF:diskConfig'])
 
     @testtools.skipUnless(compute.RESIZE_AVAILABLE, 'Resize not available.')
     @attr(type='gate')
     def test_resize_server_from_auto_to_manual(self):
         # A server should be resized from auto to manual disk config
-        resp, server = self.create_server(disk_config='AUTO',
-                                          wait_until='ACTIVE')
-        self.addCleanup(self.client.delete_server, server['id'])
+        self._update_server_with_disk_config(disk_config='AUTO')
 
         # Resize with manual option
-        self.client.resize(server['id'], self.flavor_ref_alt,
-                           disk_config='MANUAL')
-        self.client.wait_for_server_status(server['id'], 'VERIFY_RESIZE')
-        self.client.confirm_resize(server['id'])
-        self.client.wait_for_server_status(server['id'], 'ACTIVE')
+        flavor_id = self._get_alternative_flavor()
+        self.client.resize(self.server_id, flavor_id, disk_config='MANUAL')
+        self.client.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
+        self.client.confirm_resize(self.server_id)
+        self.client.wait_for_server_status(self.server_id, 'ACTIVE')
 
-        resp, server = self.client.get_server(server['id'])
+        resp, server = self.client.get_server(self.server_id)
         self.assertEqual('MANUAL', server['OS-DCF:diskConfig'])
 
     @attr(type='gate')
     def test_update_server_from_auto_to_manual(self):
         # A server should be updated from auto to manual disk config
-        resp, server = self.create_server(disk_config='AUTO',
-                                          wait_until='ACTIVE')
-        self.addCleanup(self.client.delete_server, server['id'])
-
-        # Verify the disk_config attribute is set correctly
-        resp, server = self.client.get_server(server['id'])
-        self.assertEqual('AUTO', server['OS-DCF:diskConfig'])
+        self._update_server_with_disk_config(disk_config='AUTO')
 
         # Update the disk_config attribute to manual
-        resp, server = self.client.update_server(server['id'],
+        resp, server = self.client.update_server(self.server_id,
                                                  disk_config='MANUAL')
         self.assertEqual(200, resp.status)
         self.client.wait_for_server_status(server['id'], 'ACTIVE')
diff --git a/tempest/api/compute/servers/test_instance_actions.py b/tempest/api/compute/servers/test_instance_actions.py
index 61be50a..5019003 100644
--- a/tempest/api/compute/servers/test_instance_actions.py
+++ b/tempest/api/compute/servers/test_instance_actions.py
@@ -27,7 +27,7 @@
     def setUpClass(cls):
         super(InstanceActionsTestJSON, cls).setUpClass()
         cls.client = cls.servers_client
-        resp, server = cls.create_server(wait_until='ACTIVE')
+        resp, server = cls.create_test_server(wait_until='ACTIVE')
         cls.request_id = resp['x-compute-request-id']
         cls.server_id = server['id']
 
@@ -39,7 +39,7 @@
 
         resp, body = self.client.list_instance_actions(self.server_id)
         self.assertEqual(200, resp.status)
-        self.assertTrue(len(body) == 2)
+        self.assertTrue(len(body) == 2, str(body))
         self.assertTrue(any([i for i in body if i['action'] == 'create']))
         self.assertTrue(any([i for i in body if i['action'] == 'reboot']))
 
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index 778b8ec..4cbf94d 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -17,7 +17,7 @@
 
 from tempest.api.compute import base
 from tempest.api import utils
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import config
 from tempest import exceptions
 from tempest.test import attr
@@ -57,23 +57,19 @@
             raise RuntimeError("Image %s (image_ref_alt) was not found!" %
                                cls.image_ref_alt)
 
-        cls.s1_name = rand_name(cls.__name__ + '-instance')
-        resp, cls.s1 = cls.create_server(name=cls.s1_name,
-                                         image_id=cls.image_ref,
-                                         flavor=cls.flavor_ref,
-                                         wait_until='ACTIVE')
+        cls.s1_name = data_utils.rand_name(cls.__name__ + '-instance')
+        resp, cls.s1 = cls.create_test_server(name=cls.s1_name,
+                                              wait_until='ACTIVE')
 
-        cls.s2_name = rand_name(cls.__name__ + '-instance')
-        resp, cls.s2 = cls.create_server(name=cls.s2_name,
-                                         image_id=cls.image_ref_alt,
-                                         flavor=cls.flavor_ref,
-                                         wait_until='ACTIVE')
+        cls.s2_name = data_utils.rand_name(cls.__name__ + '-instance')
+        resp, cls.s2 = cls.create_test_server(name=cls.s2_name,
+                                              image_id=cls.image_ref_alt,
+                                              wait_until='ACTIVE')
 
-        cls.s3_name = rand_name(cls.__name__ + '-instance')
-        resp, cls.s3 = cls.create_server(name=cls.s3_name,
-                                         image_id=cls.image_ref,
-                                         flavor=cls.flavor_ref_alt,
-                                         wait_until='ACTIVE')
+        cls.s3_name = data_utils.rand_name(cls.__name__ + '-instance')
+        resp, cls.s3 = cls.create_test_server(name=cls.s3_name,
+                                              flavor=cls.flavor_ref_alt,
+                                              wait_until='ACTIVE')
 
         cls.fixed_network_name = cls.config.compute.fixed_network_name
 
diff --git a/tempest/api/compute/servers/test_list_servers_negative.py b/tempest/api/compute/servers/test_list_servers_negative.py
index 088d3ae..521a480 100644
--- a/tempest/api/compute/servers/test_list_servers_negative.py
+++ b/tempest/api/compute/servers/test_list_servers_negative.py
@@ -17,71 +17,19 @@
 
 import datetime
 
-from tempest.api import compute
 from tempest.api.compute import base
-from tempest import clients
 from tempest import exceptions
 from tempest.test import attr
 
 
 class ListServersNegativeTestJSON(base.BaseV2ComputeTest):
     _interface = 'json'
-
-    @classmethod
-    def _ensure_no_servers(cls, servers, username, tenant_name):
-        """
-        If there are servers and there is tenant isolation then a
-        skipException is raised to skip the test since it requires no servers
-        to already exist for the given user/tenant.
-        If there are servers and there is not tenant isolation then the test
-        blocks while the servers are being deleted.
-        """
-        if len(servers):
-            if not cls.config.compute.allow_tenant_isolation:
-                for srv in servers:
-                    cls.client.wait_for_server_termination(srv['id'],
-                                                           ignore_error=True)
-            else:
-                msg = ("User/tenant %(u)s/%(t)s already have "
-                       "existing server instances. Skipping test." %
-                       {'u': username, 't': tenant_name})
-                raise cls.skipException(msg)
+    force_tenant_isolation = True
 
     @classmethod
     def setUpClass(cls):
         super(ListServersNegativeTestJSON, cls).setUpClass()
         cls.client = cls.servers_client
-        cls.servers = []
-
-        if compute.MULTI_USER:
-            if cls.config.compute.allow_tenant_isolation:
-                creds = cls.isolated_creds.get_alt_creds()
-                username, tenant_name, password = creds
-                cls.alt_manager = clients.Manager(username=username,
-                                                  password=password,
-                                                  tenant_name=tenant_name)
-            else:
-                # Use the alt_XXX credentials in the config file
-                cls.alt_manager = clients.AltManager()
-            cls.alt_client = cls.alt_manager.servers_client
-
-        # Under circumstances when there is not a tenant/user
-        # created for the test case, the test case checks
-        # to see if there are existing servers for the
-        # either the normal user/tenant or the alt user/tenant
-        # and if so, the whole test is skipped. We do this
-        # because we assume a baseline of no servers at the
-        # start of the test instead of destroying any existing
-        # servers.
-        resp, body = cls.client.list_servers()
-        cls._ensure_no_servers(body['servers'],
-                               cls.os.username,
-                               cls.os.tenant_name)
-
-        resp, body = cls.alt_client.list_servers()
-        cls._ensure_no_servers(body['servers'],
-                               cls.alt_manager.username,
-                               cls.alt_manager.tenant_name)
 
         # The following servers are created for use
         # by the test methods in this class. These
@@ -91,10 +39,10 @@
         cls.deleted_fixtures = []
         cls.start_time = datetime.datetime.utcnow()
         for x in xrange(2):
-            resp, srv = cls.create_server()
+            resp, srv = cls.create_test_server()
             cls.existing_fixtures.append(srv)
 
-        resp, srv = cls.create_server()
+        resp, srv = cls.create_test_server()
         cls.client.delete_server(srv['id'])
         # We ignore errors on termination because the server may
         # be put into ERROR status on a quick spawn, then delete,
diff --git a/tempest/api/compute/servers/test_multiple_create.py b/tempest/api/compute/servers/test_multiple_create.py
index d582894..080bd1a 100644
--- a/tempest/api/compute/servers/test_multiple_create.py
+++ b/tempest/api/compute/servers/test_multiple_create.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.test import attr
 
@@ -26,7 +26,7 @@
     _name = 'multiple-create-test'
 
     def _generate_name(self):
-        return rand_name(self._name)
+        return data_utils.rand_name(self._name)
 
     def _create_multiple_servers(self, name=None, wait_until=None, **kwargs):
         """
@@ -34,7 +34,7 @@
         created servers into the servers list to be cleaned up after all.
         """
         kwargs['name'] = kwargs.get('name', self._generate_name())
-        resp, body = self.create_server(**kwargs)
+        resp, body = self.create_test_server(**kwargs)
 
         return resp, body
 
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 961737a..5552d0b 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -22,7 +22,7 @@
 
 from tempest.api import compute
 from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.common.utils.linux.remote_client import RemoteClient
 import tempest.config
 from tempest import exceptions
@@ -45,13 +45,13 @@
             self.client.wait_for_server_status(self.server_id, 'ACTIVE')
         except Exception:
             # Rebuild server if something happened to it during a test
-            self.rebuild_server()
+            self.__class__.server_id = self.rebuild_server(self.server_id)
 
     @classmethod
     def setUpClass(cls):
         super(ServerActionsTestJSON, cls).setUpClass()
         cls.client = cls.servers_client
-        cls.rebuild_server()
+        cls.server_id = cls.rebuild_server(None)
 
     @testtools.skipUnless(compute.CHANGE_PASSWORD_AVAILABLE,
                           'Change password not available.')
@@ -112,7 +112,7 @@
     def test_rebuild_server(self):
         # The server should be rebuilt using the provided image and data
         meta = {'rebuild': 'server'}
-        new_name = rand_name('server')
+        new_name = data_utils.rand_name('server')
         file_contents = 'Test server rebuild.'
         personality = [{'path': 'rebuild.txt',
                        'contents': base64.b64encode(file_contents)}]
@@ -123,32 +123,62 @@
                                                    metadata=meta,
                                                    personality=personality,
                                                    adminPass=password)
+        self.addCleanup(self.client.rebuild, self.server_id, self.image_ref)
 
         # Verify the properties in the initial response are correct
         self.assertEqual(self.server_id, rebuilt_server['id'])
         rebuilt_image_id = rebuilt_server['image']['id']
         self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
-        self.assertEqual(self.flavor_ref, int(rebuilt_server['flavor']['id']))
+        self.assertEqual(self.flavor_ref, rebuilt_server['flavor']['id'])
 
         # Verify the server properties after the rebuild completes
         self.client.wait_for_server_status(rebuilt_server['id'], 'ACTIVE')
         resp, server = self.client.get_server(rebuilt_server['id'])
-        rebuilt_image_id = rebuilt_server['image']['id']
+        rebuilt_image_id = server['image']['id']
         self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
-        self.assertEqual(new_name, rebuilt_server['name'])
+        self.assertEqual(new_name, server['name'])
 
         if self.run_ssh:
             # Verify that the user can authenticate with the provided password
             linux_client = RemoteClient(server, self.ssh_user, password)
             self.assertTrue(linux_client.can_authenticate())
 
+    @attr(type='gate')
+    def test_rebuild_server_in_stop_state(self):
+        # The server in stop state  should be rebuilt using the provided
+        # image and remain in SHUTOFF state
+        resp, server = self.client.get_server(self.server_id)
+        old_image = server['image']['id']
+        new_image = self.image_ref_alt \
+            if old_image == self.image_ref else self.image_ref
+        resp, server = self.client.stop(self.server_id)
+        self.assertEqual(202, resp.status)
+        self.client.wait_for_server_status(self.server_id, 'SHUTOFF')
+        self.addCleanup(self.client.start, self.server_id)
+        resp, rebuilt_server = self.client.rebuild(self.server_id, new_image)
+        self.addCleanup(self.client.wait_for_server_status, self.server_id,
+                        'SHUTOFF')
+        self.addCleanup(self.client.rebuild, self.server_id, old_image)
+
+        # Verify the properties in the initial response are correct
+        self.assertEqual(self.server_id, rebuilt_server['id'])
+        rebuilt_image_id = rebuilt_server['image']['id']
+        self.assertEqual(new_image, rebuilt_image_id)
+        self.assertEqual(self.flavor_ref, rebuilt_server['flavor']['id'])
+
+        # Verify the server properties after the rebuild completes
+        self.client.wait_for_server_status(rebuilt_server['id'], 'SHUTOFF')
+        resp, server = self.client.get_server(rebuilt_server['id'])
+        rebuilt_image_id = server['image']['id']
+        self.assertEqual(new_image, rebuilt_image_id)
+
     def _detect_server_image_flavor(self, server_id):
         # Detects the current server image flavor ref.
         resp, server = self.client.get_server(self.server_id)
         current_flavor = server['flavor']['id']
         new_flavor_ref = self.flavor_ref_alt \
-            if int(current_flavor) == self.flavor_ref else self.flavor_ref
-        return int(current_flavor), int(new_flavor_ref)
+            if current_flavor == self.flavor_ref else self.flavor_ref
+        return current_flavor, new_flavor_ref
 
     @testtools.skipIf(not resize_available, 'Resize not available.')
     @attr(type='smoke')
@@ -167,7 +197,7 @@
         self.client.wait_for_server_status(self.server_id, 'ACTIVE')
 
         resp, server = self.client.get_server(self.server_id)
-        self.assertEqual(new_flavor_ref, int(server['flavor']['id']))
+        self.assertEqual(new_flavor_ref, server['flavor']['id'])
 
     @testtools.skipIf(not resize_available, 'Resize not available.')
     @attr(type='gate')
@@ -189,7 +219,7 @@
         resp, server = self.client.get_server(self.server_id)
         start = int(time.time())
 
-        while int(server['flavor']['id']) != previous_flavor_ref:
+        while server['flavor']['id'] != previous_flavor_ref:
             time.sleep(self.build_interval)
             resp, server = self.client.get_server(self.server_id)
 
@@ -199,32 +229,115 @@
                 raise exceptions.TimeoutException(message)
 
     @attr(type='gate')
+    def test_create_backup(self):
+        # Positive test:create backup successfully and rotate backups correctly
+        # create the first and the second backup
+        backup1 = data_utils.rand_name('backup')
+        resp, _ = self.servers_client.create_backup(self.server_id,
+                                                    'daily',
+                                                    2,
+                                                    backup1)
+        oldest_backup_exist = True
+
+        # the oldest one should be deleted automatically in this test
+        def _clean_oldest_backup(oldest_backup):
+            if oldest_backup_exist:
+                self.os.image_client.delete_image(oldest_backup)
+
+        image1_id = data_utils.parse_image_id(resp['location'])
+        self.addCleanup(_clean_oldest_backup, image1_id)
+        self.assertEqual(202, resp.status)
+        self.os.image_client.wait_for_image_status(image1_id, 'active')
+
+        backup2 = data_utils.rand_name('backup')
+        self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
+        resp, _ = self.servers_client.create_backup(self.server_id,
+                                                    'daily',
+                                                    2,
+                                                    backup2)
+        image2_id = data_utils.parse_image_id(resp['location'])
+        self.addCleanup(self.os.image_client.delete_image, image2_id)
+        self.assertEqual(202, resp.status)
+        self.os.image_client.wait_for_image_status(image2_id, 'active')
+
+        # verify they have been created
+        properties = {
+            'image_type': 'backup',
+            'backup_type': "daily",
+            'instance_uuid': self.server_id,
+        }
+        resp, image_list = self.os.image_client.image_list_detail(
+            properties,
+            sort_key='created_at',
+            sort_dir='asc')
+        self.assertEqual(200, resp.status)
+        self.assertEqual(2, len(image_list))
+        self.assertEqual((backup1, backup2),
+                         (image_list[0]['name'], image_list[1]['name']))
+
+        # create the third one, due to the rotation is 2,
+        # the first one will be deleted
+        backup3 = data_utils.rand_name('backup')
+        self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
+        resp, _ = self.servers_client.create_backup(self.server_id,
+                                                    'daily',
+                                                    2,
+                                                    backup3)
+        image3_id = data_utils.parse_image_id(resp['location'])
+        self.addCleanup(self.os.image_client.delete_image, image3_id)
+        self.assertEqual(202, resp.status)
+        # the first back up should be deleted
+        self.os.image_client.wait_for_resource_deletion(image1_id)
+        oldest_backup_exist = False
+        resp, image_list = self.os.image_client.image_list_detail(
+            properties,
+            sort_key='created_at',
+            sort_dir='asc')
+        self.assertEqual(200, resp.status)
+        self.assertEqual(2, len(image_list))
+        self.assertEqual((backup2, backup3),
+                         (image_list[0]['name'], image_list[1]['name']))
+
+    def _get_output(self):
+        resp, output = self.servers_client.get_console_output(
+            self.server_id, 10)
+        self.assertEqual(200, resp.status)
+        self.assertTrue(output, "Console output was empty.")
+        lines = len(output.split('\n'))
+        self.assertEqual(lines, 10)
+
+    @attr(type='gate')
     def test_get_console_output(self):
         # Positive test:Should be able to GET the console output
         # for a given server_id and number of lines
-        def get_output():
-            resp, output = self.servers_client.get_console_output(
-                self.server_id, 10)
-            self.assertEqual(200, resp.status)
-            self.assertTrue(output, "Console output was empty.")
-            lines = len(output.split('\n'))
-            self.assertEqual(lines, 10)
-        self.wait_for(get_output)
 
-    @skip_because(bug="1014683")
+        # This reboot is necessary for outputting some console log after
+        # creating a instance backup. If a instance backup, the console
+        # log file is truncated and we cannot get any console log through
+        # "console-log" API.
+        # The detail is https://bugs.launchpad.net/nova/+bug/1251920
+        resp, body = self.servers_client.reboot(self.server_id, 'HARD')
+        self.assertEqual(202, resp.status)
+        self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
+
+        self.wait_for(self._get_output)
+
     @attr(type='gate')
-    def test_get_console_output_server_id_in_reboot_status(self):
+    def test_get_console_output_server_id_in_shutoff_status(self):
         # Positive test:Should be able to GET the console output
-        # for a given server_id in reboot status
-        resp, output = self.servers_client.reboot(self.server_id, 'SOFT')
-        self.servers_client.wait_for_server_status(self.server_id,
-                                                   'REBOOT')
-        resp, output = self.servers_client.get_console_output(self.server_id,
-                                                              10)
-        self.assertEqual(200, resp.status)
-        self.assertIsNotNone(output)
-        lines = len(output.split('\n'))
-        self.assertEqual(lines, 10)
+        # for a given server_id in SHUTOFF status
+
+        # NOTE: SHUTOFF is irregular status. To avoid test instability,
+        #       one server is created only for this test without using
+        #       the server that was created in setupClass.
+        resp, server = self.create_test_server(wait_until='ACTIVE')
+        temp_server_id = server['id']
+
+        resp, server = self.servers_client.stop(temp_server_id)
+        self.assertEqual(202, resp.status)
+        self.servers_client.wait_for_server_status(temp_server_id, 'SHUTOFF')
+
+        self.wait_for(self._get_output)
 
     @attr(type='gate')
     def test_pause_unpause_server(self):
@@ -245,6 +358,31 @@
         self.client.wait_for_server_status(self.server_id, 'ACTIVE')
 
     @attr(type='gate')
+    def test_shelve_unshelve_server(self):
+        resp, server = self.client.shelve_server(self.server_id)
+        self.assertEqual(202, resp.status)
+
+        offload_time = self.config.compute.shelved_offload_time
+        if offload_time >= 0:
+            self.client.wait_for_server_status(self.server_id,
+                                               'SHELVED_OFFLOADED',
+                                               extra_timeout=offload_time)
+        else:
+            self.client.wait_for_server_status(self.server_id,
+                                               'SHELVED')
+
+        resp, server = self.client.get_server(self.server_id)
+        image_name = server['name'] + '-shelved'
+        params = {'name': image_name}
+        resp, images = self.images_client.list_images(params)
+        self.assertEqual(1, len(images))
+        self.assertEqual(image_name, images[0]['name'])
+
+        resp, server = self.client.unshelve_server(self.server_id)
+        self.assertEqual(202, resp.status)
+        self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+
+    @attr(type='gate')
     def test_stop_start_server(self):
         resp, server = self.servers_client.stop(self.server_id)
         self.assertEqual(202, resp.status)
diff --git a/tempest/api/compute/servers/test_server_addresses.py b/tempest/api/compute/servers/test_server_addresses.py
index a594f6c..7ca8a52 100644
--- a/tempest/api/compute/servers/test_server_addresses.py
+++ b/tempest/api/compute/servers/test_server_addresses.py
@@ -28,7 +28,7 @@
         super(ServerAddressesTest, cls).setUpClass()
         cls.client = cls.servers_client
 
-        resp, cls.server = cls.create_server(wait_until='ACTIVE')
+        resp, cls.server = cls.create_test_server(wait_until='ACTIVE')
 
     @attr(type=['negative', 'gate'])
     def test_list_server_addresses_invalid_server_id(self):
diff --git a/tempest/api/compute/servers/test_server_metadata.py b/tempest/api/compute/servers/test_server_metadata.py
index 4e45e4b..ee0f4a9 100644
--- a/tempest/api/compute/servers/test_server_metadata.py
+++ b/tempest/api/compute/servers/test_server_metadata.py
@@ -32,7 +32,7 @@
         resp, tenants = cls.admin_client.list_tenants()
         cls.tenant_id = [tnt['id'] for tnt in tenants if tnt['name'] ==
                          cls.client.tenant_name][0]
-        resp, server = cls.create_server(meta={}, wait_until='ACTIVE')
+        resp, server = cls.create_test_server(meta={}, wait_until='ACTIVE')
 
         cls.server_id = server['id']
 
@@ -76,7 +76,7 @@
             key = "k" * sz
             meta = {key: 'data1'}
             self.assertRaises(exceptions.OverLimit,
-                              self.create_server,
+                              self.create_test_server,
                               meta=meta)
 
         # no teardown - all creates should fail
@@ -143,7 +143,7 @@
         # Blank key should trigger an error.
         meta = {'': 'data1'}
         self.assertRaises(exceptions.BadRequest,
-                          self.create_server,
+                          self.create_test_server,
                           meta=meta)
 
         # GET on a non-existent server should not succeed
diff --git a/tempest/api/compute/servers/test_server_password.py b/tempest/api/compute/servers/test_server_password.py
new file mode 100644
index 0000000..93c6e44
--- /dev/null
+++ b/tempest/api/compute/servers/test_server_password.py
@@ -0,0 +1,44 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM 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.
+
+
+from tempest.api.compute import base
+from tempest.test import attr
+
+
+class ServerPasswordTestJSON(base.BaseV2ComputeTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(ServerPasswordTestJSON, cls).setUpClass()
+        cls.client = cls.servers_client
+        resp, cls.server = cls.create_test_server(wait_until="ACTIVE")
+
+    @attr(type='gate')
+    def test_get_server_password(self):
+        resp, body = self.client.get_password(self.server['id'])
+        self.assertEqual(200, resp.status)
+
+    @attr(type='gate')
+    def test_delete_server_password(self):
+        resp, body = self.client.delete_password(self.server['id'])
+        self.assertEqual(204, resp.status)
+
+
+class ServerPasswordTestXML(ServerPasswordTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/servers/test_server_personality.py b/tempest/api/compute/servers/test_server_personality.py
index ba5c0df..c6d2e44 100644
--- a/tempest/api/compute/servers/test_server_personality.py
+++ b/tempest/api/compute/servers/test_server_personality.py
@@ -43,7 +43,7 @@
             path = 'etc/test' + str(i) + '.txt'
             personality.append({'path': path,
                                 'contents': base64.b64encode(file_contents)})
-        self.assertRaises(exceptions.OverLimit, self.create_server,
+        self.assertRaises(exceptions.OverLimit, self.create_test_server,
                           personality=personality)
 
     @attr(type='gate')
@@ -60,8 +60,7 @@
                 'path': path,
                 'contents': base64.b64encode(file_contents),
             })
-        resp, server = self.create_server(personality=person)
-        self.addCleanup(self.client.delete_server, server['id'])
+        resp, server = self.create_test_server(personality=person)
         self.assertEqual('202', resp['status'])
 
 
diff --git a/tempest/api/compute/servers/test_server_rescue.py b/tempest/api/compute/servers/test_server_rescue.py
index f72d36e..1008670 100644
--- a/tempest/api/compute/servers/test_server_rescue.py
+++ b/tempest/api/compute/servers/test_server_rescue.py
@@ -16,8 +16,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
-import tempest.config
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.test import attr
 
@@ -25,8 +24,6 @@
 class ServerRescueTestJSON(base.BaseV2ComputeTest):
     _interface = 'json'
 
-    run_ssh = tempest.config.TempestConfig().compute.run_ssh
-
     @classmethod
     def setUpClass(cls):
         super(ServerRescueTestJSON, cls).setUpClass()
@@ -38,8 +35,8 @@
         cls.floating_ip = str(body['ip']).strip()
 
         # Security group creation
-        cls.sg_name = rand_name('sg')
-        cls.sg_desc = rand_name('sg-desc')
+        cls.sg_name = data_utils.rand_name('sg')
+        cls.sg_desc = data_utils.rand_name('sg-desc')
         resp, cls.sg = \
             cls.security_groups_client.create_security_group(cls.sg_name,
                                                              cls.sg_desc)
@@ -62,12 +59,8 @@
             cls.volume_to_detach['id'], 'available')
 
         # Server for positive tests
-        resp, server = cls.create_server(image_id=cls.image_ref,
-                                         flavor=cls.flavor_ref,
-                                         wait_until='BUILD')
-        resp, resc_server = cls.create_server(image_id=cls.image_ref,
-                                              flavor=cls.flavor_ref,
-                                              wait_until='ACTIVE')
+        resp, server = cls.create_test_server(wait_until='BUILD')
+        resp, resc_server = cls.create_test_server(wait_until='ACTIVE')
         cls.server_id = server['id']
         cls.password = server['adminPass']
         cls.servers_client.wait_for_server_status(cls.server_id, 'ACTIVE')
diff --git a/tempest/api/compute/servers/test_servers.py b/tempest/api/compute/servers/test_servers.py
index 5f68201..d72476d 100644
--- a/tempest/api/compute/servers/test_servers.py
+++ b/tempest/api/compute/servers/test_servers.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 
 
@@ -36,7 +36,7 @@
     def test_create_server_with_admin_password(self):
         # If an admin password is provided on server creation, the server's
         # root password should be set to that password.
-        resp, server = self.create_server(adminPass='testpassword')
+        resp, server = self.create_test_server(adminPass='testpassword')
 
         # Verify the password is set correctly in the response
         self.assertEqual('testpassword', server['adminPass'])
@@ -46,12 +46,12 @@
         # Creating a server with a name that already exists is allowed
 
         # TODO(sdague): clear out try, we do cleanup one layer up
-        server_name = rand_name('server')
-        resp, server = self.create_server(name=server_name,
-                                          wait_until='ACTIVE')
+        server_name = data_utils.rand_name('server')
+        resp, server = self.create_test_server(name=server_name,
+                                               wait_until='ACTIVE')
         id1 = server['id']
-        resp, server = self.create_server(name=server_name,
-                                          wait_until='ACTIVE')
+        resp, server = self.create_test_server(name=server_name,
+                                               wait_until='ACTIVE')
         id2 = server['id']
         self.assertNotEqual(id1, id2, "Did not create a new server")
         resp, server = self.client.get_server(id1)
@@ -64,10 +64,10 @@
     def test_create_specify_keypair(self):
         # Specify a keypair while creating a server
 
-        key_name = rand_name('key')
+        key_name = data_utils.rand_name('key')
         resp, keypair = self.keypairs_client.create_keypair(key_name)
         resp, body = self.keypairs_client.list_keypairs()
-        resp, server = self.create_server(key_name=key_name)
+        resp, server = self.create_test_server(key_name=key_name)
         self.assertEqual('202', resp['status'])
         self.client.wait_for_server_status(server['id'], 'ACTIVE')
         resp, server = self.client.get_server(server['id'])
@@ -76,7 +76,7 @@
     @attr(type='gate')
     def test_update_server_name(self):
         # The server name should be changed to the the provided value
-        resp, server = self.create_server(wait_until='ACTIVE')
+        resp, server = self.create_test_server(wait_until='ACTIVE')
 
         # Update the server with a new name
         resp, server = self.client.update_server(server['id'],
@@ -91,7 +91,7 @@
     @attr(type='gate')
     def test_update_access_server_address(self):
         # The server's access addresses should reflect the provided values
-        resp, server = self.create_server(wait_until='ACTIVE')
+        resp, server = self.create_test_server(wait_until='ACTIVE')
 
         # Update the IPv4 and IPv6 access addresses
         resp, body = self.client.update_server(server['id'],
@@ -108,21 +108,21 @@
     @attr(type='gate')
     def test_delete_server_while_in_building_state(self):
         # Delete a server while it's VM state is Building
-        resp, server = self.create_server(wait_until='BUILD')
+        resp, server = self.create_test_server(wait_until='BUILD')
         resp, _ = self.client.delete_server(server['id'])
         self.assertEqual('204', resp['status'])
 
     @attr(type='gate')
     def test_delete_active_server(self):
         # Delete a server while it's VM state is Active
-        resp, server = self.create_server(wait_until='ACTIVE')
+        resp, server = self.create_test_server(wait_until='ACTIVE')
         resp, _ = self.client.delete_server(server['id'])
         self.assertEqual('204', resp['status'])
 
     @attr(type='gate')
     def test_create_server_with_ipv6_addr_only(self):
         # Create a server without an IPv4 address(only IPv6 address).
-        resp, server = self.create_server(accessIPv6='2001:2001::3')
+        resp, server = self.create_test_server(accessIPv6='2001:2001::3')
         self.assertEqual('202', resp['status'])
         self.client.wait_for_server_status(server['id'], 'ACTIVE')
         resp, server = self.client.get_server(server['id'])
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index 0f753a0..8142250 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -21,7 +21,7 @@
 
 from tempest.api.compute import base
 from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.test import attr
 
@@ -34,7 +34,7 @@
         try:
             self.client.wait_for_server_status(self.server_id, 'ACTIVE')
         except Exception:
-            self.rebuild_server()
+            self.__class__.server_id = self.rebuild_server(self.server_id)
 
     @classmethod
     def setUpClass(cls):
@@ -43,7 +43,7 @@
         cls.img_client = cls.images_client
         cls.alt_os = clients.AltManager()
         cls.alt_client = cls.alt_os.servers_client
-        resp, server = cls.create_server(wait_until='ACTIVE')
+        resp, server = cls.create_test_server(wait_until='ACTIVE')
         cls.server_id = server['id']
 
     @attr(type=['negative', 'gate'])
@@ -51,7 +51,7 @@
         # Create a server with name parameter empty
 
         self.assertRaises(exceptions.BadRequest,
-                          self.create_server,
+                          self.create_test_server,
                           name='')
 
     @attr(type=['negative', 'gate'])
@@ -63,7 +63,7 @@
                    'contents': file_contents}]
 
         self.assertRaises(exceptions.BadRequest,
-                          self.create_server,
+                          self.create_test_server,
                           personality=person)
 
     @attr(type=['negative', 'gate'])
@@ -71,7 +71,7 @@
         # Create a server with an unknown image
 
         self.assertRaises(exceptions.BadRequest,
-                          self.create_server,
+                          self.create_test_server,
                           image_id=-1)
 
     @attr(type=['negative', 'gate'])
@@ -79,7 +79,7 @@
         # Create a server with an unknown flavor
 
         self.assertRaises(exceptions.BadRequest,
-                          self.create_server,
+                          self.create_test_server,
                           flavor=-1,)
 
     @attr(type=['negative', 'gate'])
@@ -88,7 +88,7 @@
 
         IPv4 = '1.1.1.1.1.1'
         self.assertRaises(exceptions.BadRequest,
-                          self.create_server, accessIPv4=IPv4)
+                          self.create_test_server, accessIPv4=IPv4)
 
     @attr(type=['negative', 'gate'])
     def test_invalid_ip_v6_address(self):
@@ -97,7 +97,14 @@
         IPv6 = 'notvalid'
 
         self.assertRaises(exceptions.BadRequest,
-                          self.create_server, accessIPv6=IPv6)
+                          self.create_test_server, accessIPv6=IPv6)
+
+    @attr(type=['negative', 'gate'])
+    def test_resize_nonexistent_server(self):
+        nonexistent_server = str(uuid.uuid4())
+        self.assertRaises(exceptions.NotFound,
+                          self.client.resize,
+                          nonexistent_server, self.flavor_ref)
 
     @attr(type=['negative', 'gate'])
     def test_resize_server_with_non_existent_flavor(self):
@@ -133,7 +140,7 @@
     @attr(type=['negative', 'gate'])
     def test_rebuild_reboot_deleted_server(self):
         # Rebuild and Reboot a deleted server
-        _, server = self.create_server()
+        _, server = self.create_test_server()
         self.client.delete_server(server['id'])
         self.client.wait_for_server_termination(server['id'])
 
@@ -148,7 +155,7 @@
         # Rebuild a non existent server
         nonexistent_server = str(uuid.uuid4())
         meta = {'rebuild': 'server'}
-        new_name = rand_name('server')
+        new_name = data_utils.rand_name('server')
         file_contents = 'Test server rebuild.'
         personality = [{'path': '/etc/rebuild.txt',
                         'contents': base64.b64encode(file_contents)}]
@@ -168,7 +175,7 @@
 
         server_name = 12345
         self.assertRaises(exceptions.BadRequest,
-                          self.create_server,
+                          self.create_test_server,
                           name=server_name)
 
     @attr(type=['negative', 'gate'])
@@ -177,7 +184,7 @@
 
         server_name = 'a' * 256
         self.assertRaises(exceptions.BadRequest,
-                          self.create_server,
+                          self.create_test_server,
                           name=server_name)
 
     @attr(type=['negative', 'gate'])
@@ -187,16 +194,16 @@
         networks = [{'fixed_ip': '10.0.1.1', 'uuid': 'a-b-c-d-e-f-g-h-i-j'}]
 
         self.assertRaises(exceptions.BadRequest,
-                          self.create_server,
+                          self.create_test_server,
                           networks=networks)
 
     @attr(type=['negative', 'gate'])
     def test_create_with_non_existant_keypair(self):
         # Pass a non-existent keypair while creating a server
 
-        key_name = rand_name('key')
+        key_name = data_utils.rand_name('key')
         self.assertRaises(exceptions.BadRequest,
-                          self.create_server,
+                          self.create_test_server,
                           key_name=key_name)
 
     @attr(type=['negative', 'gate'])
@@ -205,15 +212,15 @@
 
         metadata = {'a': 'b' * 260}
         self.assertRaises(exceptions.OverLimit,
-                          self.create_server,
+                          self.create_test_server,
                           meta=metadata)
 
     @attr(type=['negative', 'gate'])
     def test_update_name_of_non_existent_server(self):
         # Update name of a non-existent server
 
-        server_name = rand_name('server')
-        new_name = rand_name('server') + '_updated'
+        server_name = data_utils.rand_name('server')
+        new_name = data_utils.rand_name('server') + '_updated'
 
         self.assertRaises(exceptions.NotFound, self.client.update_server,
                           server_name, name=new_name)
@@ -222,7 +229,7 @@
     def test_update_server_set_empty_name(self):
         # Update name of the server to an empty string
 
-        server_name = rand_name('server')
+        server_name = data_utils.rand_name('server')
         new_name = ''
 
         self.assertRaises(exceptions.BadRequest, self.client.update_server,
@@ -280,7 +287,7 @@
 
         security_groups = [{'name': 'does_not_exist'}]
         self.assertRaises(exceptions.BadRequest,
-                          self.create_server,
+                          self.create_test_server,
                           security_groups=security_groups)
 
     @attr(type=['negative', 'gate'])
@@ -359,6 +366,84 @@
                           self.client.get_console_output,
                           nonexistent_server, 10)
 
+    @attr(type=['negative', 'gate'])
+    def test_force_delete_nonexistent_server_id(self):
+        non_existent_server_id = str(uuid.uuid4())
+
+        self.assertRaises(exceptions.NotFound,
+                          self.client.force_delete_server,
+                          non_existent_server_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_force_delete_server_invalid_state(self):
+        # we can only force-delete a server in 'soft-delete' state
+        self.assertRaises(exceptions.Conflict,
+                          self.client.force_delete_server,
+                          self.server_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_restore_nonexistent_server_id(self):
+        non_existent_server_id = str(uuid.uuid4())
+
+        self.assertRaises(exceptions.NotFound,
+                          self.client.restore_soft_deleted_server,
+                          non_existent_server_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_restore_server_invalid_state(self):
+        # we can only restore-delete a server in 'soft-delete' state
+        self.assertRaises(exceptions.Conflict,
+                          self.client.restore_soft_deleted_server,
+                          self.server_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_shelve_non_existent_server(self):
+        # shelve a non existent server
+        nonexistent_server = str(uuid.uuid4())
+        self.assertRaises(exceptions.NotFound, self.client.shelve_server,
+                          nonexistent_server)
+
+    @attr(type=['negative', 'gate'])
+    def test_shelve_shelved_server(self):
+        # shelve a shelved server.
+        resp, server = self.client.shelve_server(self.server_id)
+        self.assertEqual(202, resp.status)
+        self.addCleanup(self.client.unshelve_server, self.server_id)
+
+        offload_time = self.config.compute.shelved_offload_time
+        if offload_time >= 0:
+            self.client.wait_for_server_status(self.server_id,
+                                               'SHELVED_OFFLOADED',
+                                               extra_timeout=offload_time)
+        else:
+            self.client.wait_for_server_status(self.server_id,
+                                               'SHELVED')
+
+        resp, server = self.client.get_server(self.server_id)
+        image_name = server['name'] + '-shelved'
+        params = {'name': image_name}
+        resp, images = self.images_client.list_images(params)
+        self.assertEqual(1, len(images))
+        self.assertEqual(image_name, images[0]['name'])
+
+        self.assertRaises(exceptions.Conflict,
+                          self.client.shelve_server,
+                          self.server_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_unshelve_non_existent_server(self):
+        # unshelve a non existent server
+        nonexistent_server = str(uuid.uuid4())
+        self.assertRaises(exceptions.NotFound, self.client.unshelve_server,
+                          nonexistent_server)
+
+    @attr(type=['negative', 'gate'])
+    def test_unshelve_server_invalid_state(self):
+        # unshelve an active server.
+        self.assertRaises(exceptions.Conflict,
+                          self.client.unshelve_server,
+                          self.server_id)
+
 
 class ServersNegativeTestXML(ServersNegativeTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/compute/servers/test_virtual_interfaces.py b/tempest/api/compute/servers/test_virtual_interfaces.py
index a00e8ed..77ada0b 100644
--- a/tempest/api/compute/servers/test_virtual_interfaces.py
+++ b/tempest/api/compute/servers/test_virtual_interfaces.py
@@ -18,7 +18,7 @@
 import netaddr
 
 from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import config
 from tempest import exceptions
 from tempest.test import attr
@@ -34,7 +34,7 @@
     def setUpClass(cls):
         super(VirtualInterfacesTestJSON, cls).setUpClass()
         cls.client = cls.servers_client
-        resp, server = cls.create_server(wait_until='ACTIVE')
+        resp, server = cls.create_test_server(wait_until='ACTIVE')
         cls.server_id = server['id']
 
     @skip_because(bug="1183436",
@@ -58,7 +58,7 @@
     def test_list_virtual_interfaces_invalid_server_id(self):
         # Negative test: Should not be able to GET virtual interfaces
         # for an invalid server_id
-        invalid_server_id = rand_name('!@#$%^&*()')
+        invalid_server_id = data_utils.rand_name('!@#$%^&*()')
         self.assertRaises(exceptions.NotFound,
                           self.client.list_virtual_interfaces,
                           invalid_server_id)
diff --git a/tempest/api/compute/test_authorization.py b/tempest/api/compute/test_authorization.py
index a7d9310..327c7d1 100644
--- a/tempest/api/compute/test_authorization.py
+++ b/tempest/api/compute/test_authorization.py
@@ -15,11 +15,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.api import compute
 from tempest.api.compute import base
 from tempest import clients
-from tempest.common.utils.data_utils import parse_image_id
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.openstack.common import log as logging
 from tempest.test import attr
@@ -32,12 +30,10 @@
 
     @classmethod
     def setUpClass(cls):
-        if not compute.MULTI_USER:
+        super(AuthorizationTestJSON, cls).setUpClass()
+        if not cls.multi_user:
             msg = "Need >1 user"
             raise cls.skipException(msg)
-
-        super(AuthorizationTestJSON, cls).setUpClass()
-
         cls.client = cls.os.servers_client
         cls.images_client = cls.os.images_client
         cls.keypairs_client = cls.os.keypairs_client
@@ -59,21 +55,21 @@
         cls.alt_security_client = cls.alt_manager.security_groups_client
 
         cls.alt_security_client._set_auth()
-        resp, server = cls.create_server(wait_until='ACTIVE')
+        resp, server = cls.create_test_server(wait_until='ACTIVE')
         resp, cls.server = cls.client.get_server(server['id'])
 
-        name = rand_name('image')
+        name = data_utils.rand_name('image')
         resp, body = cls.client.create_image(server['id'], name)
-        image_id = parse_image_id(resp['location'])
+        image_id = data_utils.parse_image_id(resp['location'])
         cls.images_client.wait_for_image_status(image_id, 'ACTIVE')
         resp, cls.image = cls.images_client.get_image(image_id)
 
-        cls.keypairname = rand_name('keypair')
+        cls.keypairname = data_utils.rand_name('keypair')
         resp, keypair = \
             cls.keypairs_client.create_keypair(cls.keypairname)
 
-        name = rand_name('security')
-        description = rand_name('description')
+        name = data_utils.rand_name('security')
+        description = data_utils.rand_name('description')
         resp, cls.security_group = cls.security_client.create_security_group(
             name, description)
 
@@ -86,7 +82,7 @@
 
     @classmethod
     def tearDownClass(cls):
-        if compute.MULTI_USER:
+        if cls.multi_user:
             cls.images_client.delete_image(cls.image['id'])
             cls.keypairs_client.delete_keypair(cls.keypairname)
             cls.security_client.delete_security_group(cls.security_group['id'])
@@ -191,7 +187,7 @@
         # A create keypair request should fail if the tenant id does not match
         # the current user
         # POST keypair with other user tenant
-        k_name = rand_name('keypair-')
+        k_name = data_utils.rand_name('keypair-')
         self.alt_keypairs_client._set_auth()
         self.saved_base_url = self.alt_keypairs_client.base_url
         try:
@@ -241,8 +237,8 @@
         # A create security group request should fail if the tenant id does not
         # match the current user
         # POST security group with other user tenant
-        s_name = rand_name('security-')
-        s_description = rand_name('security')
+        s_name = data_utils.rand_name('security-')
+        s_description = data_utils.rand_name('security')
         self.saved_base_url = self.alt_security_client.base_url
         try:
             # Change the base URL to impersonate another user
diff --git a/tempest/api/compute/test_live_block_migration.py b/tempest/api/compute/test_live_block_migration.py
index 7f68ab5..a7b6cd2 100644
--- a/tempest/api/compute/test_live_block_migration.py
+++ b/tempest/api/compute/test_live_block_migration.py
@@ -84,7 +84,7 @@
             if 'ACTIVE' == self._get_server_status(server_id):
                 return server_id
         else:
-            _, server = self.create_server(wait_until="ACTIVE")
+            _, server = self.create_test_server(wait_until="ACTIVE")
             server_id = server['id']
             self.password = server['adminPass']
             self.password = 'password'
diff --git a/tempest/api/compute/v3/__init__.py b/tempest/api/compute/v3/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api/compute/v3/__init__.py
diff --git a/tempest/api/compute/v3/admin/__init__.py b/tempest/api/compute/v3/admin/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api/compute/v3/admin/__init__.py
diff --git a/tempest/api/compute/v3/admin/test_availability_zone.py b/tempest/api/compute/v3/admin/test_availability_zone.py
new file mode 100644
index 0000000..ff2765c
--- /dev/null
+++ b/tempest/api/compute/v3/admin/test_availability_zone.py
@@ -0,0 +1,70 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 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.
+
+from tempest.api.compute import base
+from tempest import exceptions
+from tempest.test import attr
+
+
+class AvailabilityZoneAdminV3TestJSON(base.BaseV3ComputeAdminTest):
+
+    """
+    Tests Availability Zone API List that require admin privileges
+    """
+
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(AvailabilityZoneAdminV3TestJSON, cls).setUpClass()
+        cls.client = cls.availability_zone_admin_client
+        cls.non_adm_client = cls.availability_zone_client
+
+    @attr(type='gate')
+    def test_get_availability_zone_list(self):
+        # List of availability zone
+        resp, availability_zone = self.client.get_availability_zone_list()
+        self.assertEqual(200, resp.status)
+        self.assertTrue(len(availability_zone) > 0)
+
+    @attr(type='gate')
+    def test_get_availability_zone_list_detail(self):
+        # List of availability zones and available services
+        resp, availability_zone = \
+            self.client.get_availability_zone_list_detail()
+        self.assertEqual(200, resp.status)
+        self.assertTrue(len(availability_zone) > 0)
+
+    @attr(type='gate')
+    def test_get_availability_zone_list_with_non_admin_user(self):
+        # List of availability zone with non-administrator user
+        resp, availability_zone = \
+            self.non_adm_client.get_availability_zone_list()
+        self.assertEqual(200, resp.status)
+        self.assertTrue(len(availability_zone) > 0)
+
+    @attr(type=['negative', 'gate'])
+    def test_get_availability_zone_list_detail_with_non_admin_user(self):
+        # List of availability zones and available services with
+        # non-administrator user
+        self.assertRaises(
+            exceptions.Unauthorized,
+            self.non_adm_client.get_availability_zone_list_detail)
+
+
+class AvailabilityZoneAdminV3TestXML(AvailabilityZoneAdminV3TestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/admin/test_flavors_access.py b/tempest/api/compute/v3/admin/test_flavors_access.py
new file mode 100644
index 0000000..048312b
--- /dev/null
+++ b/tempest/api/compute/v3/admin/test_flavors_access.py
@@ -0,0 +1,111 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 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.
+
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import test
+
+
+class FlavorsAccessTestJSON(base.BaseV2ComputeAdminTest):
+
+    """
+    Tests Flavor Access API extension.
+    Add and remove Flavor Access require admin privileges.
+    """
+
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(FlavorsAccessTestJSON, cls).setUpClass()
+        if not test.is_extension_enabled('FlavorExtraData', 'compute'):
+            msg = "FlavorExtraData extension not enabled."
+            raise cls.skipException(msg)
+
+        cls.client = cls.os_adm.flavors_client
+        admin_client = cls._get_identity_admin_client()
+        cls.tenant = admin_client.get_tenant_by_name(cls.flavors_client.
+                                                     tenant_name)
+        cls.tenant_id = cls.tenant['id']
+        cls.adm_tenant = admin_client.get_tenant_by_name(cls.os_adm.
+                                                         flavors_client.
+                                                         tenant_name)
+        cls.adm_tenant_id = cls.adm_tenant['id']
+        cls.flavor_name_prefix = 'test_flavor_access_'
+        cls.ram = 512
+        cls.vcpus = 1
+        cls.disk = 10
+
+    @test.attr(type='gate')
+    def test_flavor_access_list_with_private_flavor(self):
+        # Test to list flavor access successfully by querying private flavor
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
+        resp, new_flavor = self.client.create_flavor(flavor_name,
+                                                     self.ram, self.vcpus,
+                                                     self.disk,
+                                                     new_flavor_id,
+                                                     is_public='False')
+        self.addCleanup(self.client.delete_flavor, new_flavor['id'])
+        self.assertEqual(resp.status, 200)
+        resp, flavor_access = self.client.list_flavor_access(new_flavor_id)
+        self.assertEqual(resp.status, 200)
+        self.assertEqual(len(flavor_access), 1, str(flavor_access))
+        first_flavor = flavor_access[0]
+        self.assertEqual(str(new_flavor_id), str(first_flavor['flavor_id']))
+        self.assertEqual(self.adm_tenant_id, first_flavor['tenant_id'])
+
+    @test.attr(type='gate')
+    def test_flavor_access_add_remove(self):
+        # Test to add and remove flavor access to a given tenant.
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
+        resp, new_flavor = self.client.create_flavor(flavor_name,
+                                                     self.ram, self.vcpus,
+                                                     self.disk,
+                                                     new_flavor_id,
+                                                     is_public='False')
+        self.addCleanup(self.client.delete_flavor, new_flavor['id'])
+        # Add flavor access to a tenant.
+        resp_body = {
+            "tenant_id": str(self.tenant_id),
+            "flavor_id": str(new_flavor['id']),
+        }
+        add_resp, add_body = \
+            self.client.add_flavor_access(new_flavor['id'], self.tenant_id)
+        self.assertEqual(add_resp.status, 200)
+        self.assertIn(resp_body, add_body)
+
+        # The flavor is present in list.
+        resp, flavors = self.flavors_client.list_flavors_with_detail()
+        self.assertEqual(resp.status, 200)
+        self.assertIn(new_flavor['id'], map(lambda x: x['id'], flavors))
+
+        # Remove flavor access from a tenant.
+        remove_resp, remove_body = \
+            self.client.remove_flavor_access(new_flavor['id'], self.tenant_id)
+        self.assertEqual(remove_resp.status, 200)
+        self.assertNotIn(resp_body, remove_body)
+
+        # The flavor is not present in list.
+        resp, flavors = self.flavors_client.list_flavors_with_detail()
+        self.assertEqual(resp.status, 200)
+        self.assertNotIn(new_flavor['id'], map(lambda x: x['id'], flavors))
+
+
+class FlavorsAdminTestXML(FlavorsAccessTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/admin/test_flavors_access_negative.py b/tempest/api/compute/v3/admin/test_flavors_access_negative.py
new file mode 100644
index 0000000..976124e
--- /dev/null
+++ b/tempest/api/compute/v3/admin/test_flavors_access_negative.py
@@ -0,0 +1,152 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM 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 uuid
+
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest import test
+
+
+class FlavorsAccessNegativeTestJSON(base.BaseV2ComputeAdminTest):
+
+    """
+    Tests Flavor Access API extension.
+    Add and remove Flavor Access require admin privileges.
+    """
+
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(FlavorsAccessNegativeTestJSON, cls).setUpClass()
+        if not test.is_extension_enabled('FlavorExtraData', 'compute'):
+            msg = "FlavorExtraData extension not enabled."
+            raise cls.skipException(msg)
+
+        cls.client = cls.os_adm.flavors_client
+        admin_client = cls._get_identity_admin_client()
+        cls.tenant = admin_client.get_tenant_by_name(cls.flavors_client.
+                                                     tenant_name)
+        cls.tenant_id = cls.tenant['id']
+        cls.adm_tenant = admin_client.get_tenant_by_name(cls.os_adm.
+                                                         flavors_client.
+                                                         tenant_name)
+        cls.adm_tenant_id = cls.adm_tenant['id']
+        cls.flavor_name_prefix = 'test_flavor_access_'
+        cls.ram = 512
+        cls.vcpus = 1
+        cls.disk = 10
+
+    @test.attr(type=['negative', 'gate'])
+    def test_flavor_access_list_with_public_flavor(self):
+        # Test to list flavor access with exceptions by querying public flavor
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
+        resp, new_flavor = self.client.create_flavor(flavor_name,
+                                                     self.ram, self.vcpus,
+                                                     self.disk,
+                                                     new_flavor_id,
+                                                     is_public='True')
+        self.addCleanup(self.client.delete_flavor, new_flavor['id'])
+        self.assertEqual(resp.status, 200)
+        self.assertRaises(exceptions.NotFound,
+                          self.client.list_flavor_access,
+                          new_flavor_id)
+
+    @test.attr(type=['negative', 'gate'])
+    def test_flavor_non_admin_add(self):
+        # Test to add flavor access as a user without admin privileges.
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
+        resp, new_flavor = self.client.create_flavor(flavor_name,
+                                                     self.ram, self.vcpus,
+                                                     self.disk,
+                                                     new_flavor_id,
+                                                     is_public='False')
+        self.addCleanup(self.client.delete_flavor, new_flavor['id'])
+        self.assertRaises(exceptions.Unauthorized,
+                          self.flavors_client.add_flavor_access,
+                          new_flavor['id'],
+                          self.tenant_id)
+
+    @test.attr(type=['negative', 'gate'])
+    def test_flavor_non_admin_remove(self):
+        # Test to remove flavor access as a user without admin privileges.
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
+        resp, new_flavor = self.client.create_flavor(flavor_name,
+                                                     self.ram, self.vcpus,
+                                                     self.disk,
+                                                     new_flavor_id,
+                                                     is_public='False')
+        self.addCleanup(self.client.delete_flavor, new_flavor['id'])
+        # Add flavor access to a tenant.
+        self.client.add_flavor_access(new_flavor['id'], self.tenant_id)
+        self.addCleanup(self.client.remove_flavor_access,
+                        new_flavor['id'], self.tenant_id)
+        self.assertRaises(exceptions.Unauthorized,
+                          self.flavors_client.remove_flavor_access,
+                          new_flavor['id'],
+                          self.tenant_id)
+
+    @test.attr(type=['negative', 'gate'])
+    def test_add_flavor_access_duplicate(self):
+        # Create a new flavor.
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
+        resp, new_flavor = self.client.create_flavor(flavor_name,
+                                                     self.ram, self.vcpus,
+                                                     self.disk,
+                                                     new_flavor_id,
+                                                     is_public='False')
+        self.addCleanup(self.client.delete_flavor, new_flavor['id'])
+
+        # Add flavor access to a tenant.
+        self.client.add_flavor_access(new_flavor['id'], self.tenant_id)
+        self.addCleanup(self.client.remove_flavor_access,
+                        new_flavor['id'], self.tenant_id)
+
+        # An exception should be raised when adding flavor access to the same
+        # tenant
+        self.assertRaises(exceptions.Conflict,
+                          self.client.add_flavor_access,
+                          new_flavor['id'],
+                          self.tenant_id)
+
+    @test.attr(type=['negative', 'gate'])
+    def test_remove_flavor_access_not_found(self):
+        # Create a new flavor.
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = data_utils.rand_int_id(start=1000)
+        resp, new_flavor = self.client.create_flavor(flavor_name,
+                                                     self.ram, self.vcpus,
+                                                     self.disk,
+                                                     new_flavor_id,
+                                                     is_public='False')
+        self.addCleanup(self.client.delete_flavor, new_flavor['id'])
+
+        # An exception should be raised when flavor access is not found
+        self.assertRaises(exceptions.NotFound,
+                          self.client.remove_flavor_access,
+                          new_flavor['id'],
+                          str(uuid.uuid4()))
+
+
+class FlavorsAdminNegativeTestXML(FlavorsAccessNegativeTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/admin/test_flavors_extra_specs.py b/tempest/api/compute/v3/admin/test_flavors_extra_specs.py
new file mode 100644
index 0000000..875f742
--- /dev/null
+++ b/tempest/api/compute/v3/admin/test_flavors_extra_specs.py
@@ -0,0 +1,131 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import test
+
+
+class FlavorsExtraSpecsTestJSON(base.BaseV2ComputeAdminTest):
+
+    """
+    Tests Flavor Extra Spec API extension.
+    SET, UNSET, UPDATE Flavor Extra specs require admin privileges.
+    GET Flavor Extra specs can be performed even by without admin privileges.
+    """
+
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(FlavorsExtraSpecsTestJSON, cls).setUpClass()
+        if not test.is_extension_enabled('FlavorExtraData', 'compute'):
+            msg = "FlavorExtraData extension not enabled."
+            raise cls.skipException(msg)
+
+        cls.client = cls.os_adm.flavors_client
+        flavor_name = data_utils.rand_name('test_flavor')
+        ram = 512
+        vcpus = 1
+        disk = 10
+        ephemeral = 10
+        cls.new_flavor_id = data_utils.rand_int_id(start=1000)
+        swap = 1024
+        rxtx = 1
+        # Create a flavor so as to set/get/unset extra specs
+        resp, cls.flavor = cls.client.create_flavor(flavor_name,
+                                                    ram, vcpus,
+                                                    disk,
+                                                    cls.new_flavor_id,
+                                                    ephemeral=ephemeral,
+                                                    swap=swap, rxtx=rxtx)
+
+    @classmethod
+    def tearDownClass(cls):
+        resp, body = cls.client.delete_flavor(cls.flavor['id'])
+        cls.client.wait_for_resource_deletion(cls.flavor['id'])
+        super(FlavorsExtraSpecsTestJSON, cls).tearDownClass()
+
+    @test.attr(type='gate')
+    def test_flavor_set_get_update_show_unset_keys(self):
+        # Test to SET, GET, UPDATE, SHOW, UNSET flavor extra
+        # spec as a user with admin privileges.
+        # Assigning extra specs values that are to be set
+        specs = {"key1": "value1", "key2": "value2"}
+        # SET extra specs to the flavor created in setUp
+        set_resp, set_body = \
+            self.client.set_flavor_extra_spec(self.flavor['id'], specs)
+        self.assertEqual(set_resp.status, 200)
+        self.assertEqual(set_body, specs)
+        # GET extra specs and verify
+        get_resp, get_body = \
+            self.client.get_flavor_extra_spec(self.flavor['id'])
+        self.assertEqual(get_resp.status, 200)
+        self.assertEqual(get_body, specs)
+
+        # UPDATE the value of the extra specs key1
+        update_resp, update_body = \
+            self.client.update_flavor_extra_spec(self.flavor['id'],
+                                                 "key1",
+                                                 key1="value")
+        self.assertEqual(update_resp.status, 200)
+        self.assertEqual({"key1": "value"}, update_body)
+
+        # GET extra specs and verify the value of the key2
+        # is the same as before
+        get_resp, get_body = \
+            self.client.get_flavor_extra_spec(self.flavor['id'])
+        self.assertEqual(get_resp.status, 200)
+        self.assertEqual(get_body, {"key1": "value", "key2": "value2"})
+
+        # UNSET extra specs that were set in this test
+        unset_resp, _ = \
+            self.client.unset_flavor_extra_spec(self.flavor['id'], "key1")
+        self.assertEqual(unset_resp.status, 200)
+        unset_resp, _ = \
+            self.client.unset_flavor_extra_spec(self.flavor['id'], "key2")
+        self.assertEqual(unset_resp.status, 200)
+
+    @test.attr(type='gate')
+    def test_flavor_non_admin_get_all_keys(self):
+        specs = {"key1": "value1", "key2": "value2"}
+        set_resp, set_body = self.client.set_flavor_extra_spec(
+            self.flavor['id'], specs)
+        resp, body = self.flavors_client.get_flavor_extra_spec(
+            self.flavor['id'])
+        self.assertEqual(resp.status, 200)
+
+        for key in specs:
+            self.assertEqual(body[key], specs[key])
+
+    @test.attr(type='gate')
+    def test_flavor_non_admin_get_specific_key(self):
+        specs = {"key1": "value1", "key2": "value2"}
+        resp, body = self.client.set_flavor_extra_spec(
+            self.flavor['id'], specs)
+        self.assertEqual(resp.status, 200)
+        self.assertEqual(body['key1'], 'value1')
+        self.assertIn('key2', body)
+        resp, body = self.flavors_client.get_flavor_extra_spec_with_key(
+            self.flavor['id'], 'key1')
+        self.assertEqual(resp.status, 200)
+        self.assertEqual(body['key1'], 'value1')
+        self.assertNotIn('key2', body)
+
+
+class FlavorsExtraSpecsTestXML(FlavorsExtraSpecsTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/admin/test_flavors_extra_specs_negative.py b/tempest/api/compute/v3/admin/test_flavors_extra_specs_negative.py
new file mode 100644
index 0000000..fb09a63
--- /dev/null
+++ b/tempest/api/compute/v3/admin/test_flavors_extra_specs_negative.py
@@ -0,0 +1,135 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+# Copyright 2013 IBM Corp.
+#
+#    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.compute import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest import test
+
+
+class FlavorsExtraSpecsNegativeTestJSON(base.BaseV2ComputeAdminTest):
+
+    """
+    Negative Tests Flavor Extra Spec API extension.
+    SET, UNSET, UPDATE Flavor Extra specs require admin privileges.
+    """
+
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(FlavorsExtraSpecsNegativeTestJSON, cls).setUpClass()
+        if not test.is_extension_enabled('FlavorExtraData', 'compute'):
+            msg = "FlavorExtraData extension not enabled."
+            raise cls.skipException(msg)
+
+        cls.client = cls.os_adm.flavors_client
+        flavor_name = data_utils.rand_name('test_flavor')
+        ram = 512
+        vcpus = 1
+        disk = 10
+        ephemeral = 10
+        cls.new_flavor_id = data_utils.rand_int_id(start=1000)
+        swap = 1024
+        rxtx = 1
+        # Create a flavor
+        resp, cls.flavor = cls.client.create_flavor(flavor_name,
+                                                    ram, vcpus,
+                                                    disk,
+                                                    cls.new_flavor_id,
+                                                    ephemeral=ephemeral,
+                                                    swap=swap, rxtx=rxtx)
+
+    @classmethod
+    def tearDownClass(cls):
+        resp, body = cls.client.delete_flavor(cls.flavor['id'])
+        cls.client.wait_for_resource_deletion(cls.flavor['id'])
+        super(FlavorsExtraSpecsNegativeTestJSON, cls).tearDownClass()
+
+    @test.attr(type=['negative', 'gate'])
+    def test_flavor_non_admin_set_keys(self):
+        # Test to SET flavor extra spec as a user without admin privileges.
+        specs = {"key1": "value1", "key2": "value2"}
+        self.assertRaises(exceptions.Unauthorized,
+                          self.flavors_client.set_flavor_extra_spec,
+                          self.flavor['id'],
+                          specs)
+
+    @test.attr(type=['negative', 'gate'])
+    def test_flavor_non_admin_update_specific_key(self):
+        # non admin user is not allowed to update flavor extra spec
+        specs = {"key1": "value1", "key2": "value2"}
+        resp, body = self.client.set_flavor_extra_spec(
+            self.flavor['id'], specs)
+        self.assertEqual(resp.status, 200)
+        self.assertEqual(body['key1'], 'value1')
+        self.assertRaises(exceptions.Unauthorized,
+                          self.flavors_client.
+                          update_flavor_extra_spec,
+                          self.flavor['id'],
+                          'key1',
+                          key1='value1_new')
+
+    @test.attr(type=['negative', 'gate'])
+    def test_flavor_non_admin_unset_keys(self):
+        specs = {"key1": "value1", "key2": "value2"}
+        set_resp, set_body = self.client.set_flavor_extra_spec(
+            self.flavor['id'], specs)
+
+        self.assertRaises(exceptions.Unauthorized,
+                          self.flavors_client.unset_flavor_extra_spec,
+                          self.flavor['id'],
+                          'key1')
+
+    @test.attr(type=['negative', 'gate'])
+    def test_flavor_unset_nonexistent_key(self):
+        nonexistent_key = data_utils.rand_name('flavor_key')
+        self.assertRaises(exceptions.NotFound,
+                          self.client.unset_flavor_extra_spec,
+                          self.flavor['id'],
+                          nonexistent_key)
+
+    @test.attr(type=['negative', 'gate'])
+    def test_flavor_get_nonexistent_key(self):
+        self.assertRaises(exceptions.NotFound,
+                          self.flavors_client.get_flavor_extra_spec_with_key,
+                          self.flavor['id'],
+                          "nonexistent_key")
+
+    @test.attr(type=['negative', 'gate'])
+    def test_flavor_update_mismatch_key(self):
+        # the key will be updated should be match the key in the body
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.update_flavor_extra_spec,
+                          self.flavor['id'],
+                          "key2",
+                          key1="value")
+
+    @test.attr(type=['negative', 'gate'])
+    def test_flavor_update_more_key(self):
+        # there should be just one item in the request body
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.update_flavor_extra_spec,
+                          self.flavor['id'],
+                          "key1",
+                          key1="value",
+                          key2="value")
+
+
+class FlavorsExtraSpecsNegativeTestXML(FlavorsExtraSpecsNegativeTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/admin/test_hypervisor.py b/tempest/api/compute/v3/admin/test_hypervisor.py
new file mode 100644
index 0000000..3da3369
--- /dev/null
+++ b/tempest/api/compute/v3/admin/test_hypervisor.py
@@ -0,0 +1,105 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM 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.
+
+from tempest.api.compute import base
+from tempest.test import attr
+
+
+class HypervisorAdminV3TestJSON(base.BaseV3ComputeAdminTest):
+
+    """
+    Tests Hypervisors API that require admin privileges
+    """
+
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(HypervisorAdminV3TestJSON, cls).setUpClass()
+        cls.client = cls.hypervisor_admin_client
+
+    def _list_hypervisors(self):
+        # List of hypervisors
+        resp, hypers = self.client.get_hypervisor_list()
+        self.assertEqual(200, resp.status)
+        return hypers
+
+    @attr(type='gate')
+    def test_get_hypervisor_list(self):
+        # List of hypervisor and available hypervisors hostname
+        hypers = self._list_hypervisors()
+        self.assertTrue(len(hypers) > 0)
+
+    @attr(type='gate')
+    def test_get_hypervisor_list_details(self):
+        # Display the details of the all hypervisor
+        resp, hypers = self.client.get_hypervisor_list_details()
+        self.assertEqual(200, resp.status)
+        self.assertTrue(len(hypers) > 0)
+
+    @attr(type='gate')
+    def test_get_hypervisor_show_details(self):
+        # Display the details of the specified hypervisor
+        hypers = self._list_hypervisors()
+        self.assertTrue(len(hypers) > 0)
+
+        resp, details = (self.client.
+                         get_hypervisor_show_details(hypers[0]['id']))
+        self.assertEqual(200, resp.status)
+        self.assertTrue(len(details) > 0)
+        self.assertEqual(details['hypervisor_hostname'],
+                         hypers[0]['hypervisor_hostname'])
+
+    @attr(type='gate')
+    def test_get_hypervisor_show_servers(self):
+        # Show instances about the specific hypervisors
+        hypers = self._list_hypervisors()
+        self.assertTrue(len(hypers) > 0)
+
+        hypervisor_id = hypers[0]['id']
+        resp, hypervisors = self.client.get_hypervisor_servers(hypervisor_id)
+        self.assertEqual(200, resp.status)
+        self.assertTrue(len(hypervisors) > 0)
+
+    @attr(type='gate')
+    def test_get_hypervisor_stats(self):
+        # Verify the stats of the all hypervisor
+        resp, stats = self.client.get_hypervisor_stats()
+        self.assertEqual(200, resp.status)
+        self.assertTrue(len(stats) > 0)
+
+    @attr(type='gate')
+    def test_get_hypervisor_uptime(self):
+        # Verify that GET shows the specified hypervisor uptime
+        hypers = self._list_hypervisors()
+
+        resp, uptime = self.client.get_hypervisor_uptime(hypers[0]['id'])
+        self.assertEqual(200, resp.status)
+        self.assertTrue(len(uptime) > 0)
+
+    @attr(type='gate')
+    def test_search_hypervisor(self):
+        hypers = self._list_hypervisors()
+        self.assertTrue(len(hypers) > 0)
+        resp, hypers = self.client.search_hypervisor(
+            hypers[0]['hypervisor_hostname'])
+        self.assertEqual(200, resp.status)
+        self.assertTrue(len(hypers) > 0)
+
+
+class HypervisorAdminV3TestXML(HypervisorAdminV3TestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/admin/test_hypervisor_negative.py b/tempest/api/compute/v3/admin/test_hypervisor_negative.py
new file mode 100644
index 0000000..847679e
--- /dev/null
+++ b/tempest/api/compute/v3/admin/test_hypervisor_negative.py
@@ -0,0 +1,144 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 Huawei Technologies Co.,LTD.
+# 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 uuid
+
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest.test import attr
+
+
+class HypervisorAdminNegativeV3TestJSON(base.BaseV3ComputeAdminTest):
+
+    """
+    Tests Hypervisors API that require admin privileges
+    """
+
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(HypervisorAdminNegativeV3TestJSON, cls).setUpClass()
+        cls.client = cls.hypervisor_admin_client
+        cls.non_adm_client = cls.hypervisor_client
+
+    def _list_hypervisors(self):
+        # List of hypervisors
+        resp, hypers = self.client.get_hypervisor_list()
+        self.assertEqual(200, resp.status)
+        return hypers
+
+    @attr(type=['negative', 'gate'])
+    def test_show_nonexistent_hypervisor(self):
+        nonexistent_hypervisor_id = str(uuid.uuid4())
+
+        self.assertRaises(
+            exceptions.NotFound,
+            self.client.get_hypervisor_show_details,
+            nonexistent_hypervisor_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_show_hypervisor_with_non_admin_user(self):
+        hypers = self._list_hypervisors()
+        self.assertTrue(len(hypers) > 0)
+
+        self.assertRaises(
+            exceptions.Unauthorized,
+            self.non_adm_client.get_hypervisor_show_details,
+            hypers[0]['id'])
+
+    @attr(type=['negative', 'gate'])
+    def test_show_servers_with_non_admin_user(self):
+        hypers = self._list_hypervisors()
+        self.assertTrue(len(hypers) > 0)
+
+        self.assertRaises(
+            exceptions.Unauthorized,
+            self.non_adm_client.get_hypervisor_servers,
+            hypers[0]['id'])
+
+    @attr(type=['negative', 'gate'])
+    def test_show_servers_with_nonexistent_hypervisor(self):
+        nonexistent_hypervisor_id = str(uuid.uuid4())
+
+        self.assertRaises(
+            exceptions.NotFound,
+            self.client.get_hypervisor_servers,
+            nonexistent_hypervisor_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_get_hypervisor_stats_with_non_admin_user(self):
+        self.assertRaises(
+            exceptions.Unauthorized,
+            self.non_adm_client.get_hypervisor_stats)
+
+    @attr(type=['negative', 'gate'])
+    def test_get_nonexistent_hypervisor_uptime(self):
+        nonexistent_hypervisor_id = str(uuid.uuid4())
+
+        self.assertRaises(
+            exceptions.NotFound,
+            self.client.get_hypervisor_uptime,
+            nonexistent_hypervisor_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_get_hypervisor_uptime_with_non_admin_user(self):
+        hypers = self._list_hypervisors()
+        self.assertTrue(len(hypers) > 0)
+
+        self.assertRaises(
+            exceptions.Unauthorized,
+            self.non_adm_client.get_hypervisor_uptime,
+            hypers[0]['id'])
+
+    @attr(type=['negative', 'gate'])
+    def test_get_hypervisor_list_with_non_admin_user(self):
+        # List of hypervisor and available services with non admin user
+        self.assertRaises(
+            exceptions.Unauthorized,
+            self.non_adm_client.get_hypervisor_list)
+
+    @attr(type=['negative', 'gate'])
+    def test_get_hypervisor_list_details_with_non_admin_user(self):
+        # List of hypervisor details and available services with non admin user
+        self.assertRaises(
+            exceptions.Unauthorized,
+            self.non_adm_client.get_hypervisor_list_details)
+
+    @attr(type=['negative', 'gate'])
+    def test_search_nonexistent_hypervisor(self):
+        nonexistent_hypervisor_name = data_utils.rand_name('test_hypervisor')
+
+        resp, hypers = self.client.search_hypervisor(
+            nonexistent_hypervisor_name)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(0, len(hypers))
+
+    @attr(type=['negative', 'gate'])
+    def test_search_hypervisor_with_non_admin_user(self):
+        hypers = self._list_hypervisors()
+        self.assertTrue(len(hypers) > 0)
+
+        self.assertRaises(
+            exceptions.Unauthorized,
+            self.non_adm_client.search_hypervisor,
+            hypers[0]['hypervisor_hostname'])
+
+
+class HypervisorAdminNegativeV3TestXML(HypervisorAdminNegativeV3TestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/admin/test_quotas.py b/tempest/api/compute/v3/admin/test_quotas.py
new file mode 100644
index 0000000..f49aae4
--- /dev/null
+++ b/tempest/api/compute/v3/admin/test_quotas.py
@@ -0,0 +1,220 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import config
+from tempest import exceptions
+from tempest.test import attr
+from tempest.test import skip_because
+
+
+class QuotasAdminTestJSON(base.BaseV2ComputeAdminTest):
+    _interface = 'json'
+    force_tenant_isolation = True
+
+    @classmethod
+    def setUpClass(cls):
+        super(QuotasAdminTestJSON, cls).setUpClass()
+        cls.auth_url = cls.config.identity.uri
+        cls.client = cls.os.quotas_client
+        cls.adm_client = cls.os_adm.quotas_client
+        cls.identity_admin_client = cls._get_identity_admin_client()
+        cls.sg_client = cls.security_groups_client
+
+        # NOTE(afazekas): these test cases should always create and use a new
+        # tenant most of them should be skipped if we can't do that
+        cls.demo_tenant_id = cls.isolated_creds.get_primary_user().get(
+            'tenantId')
+
+        cls.default_quota_set = set(('injected_file_content_bytes',
+                                     'metadata_items', 'injected_files',
+                                     'ram', 'floating_ips',
+                                     'fixed_ips', 'key_pairs',
+                                     'injected_file_path_bytes',
+                                     'instances', 'security_group_rules',
+                                     'cores', 'security_groups'))
+
+    @attr(type='smoke')
+    def test_get_default_quotas(self):
+        # Admin can get the default resource quota set for a tenant
+        expected_quota_set = self.default_quota_set | set(['id'])
+        resp, quota_set = self.client.get_default_quota_set(
+            self.demo_tenant_id)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(sorted(expected_quota_set),
+                         sorted(quota_set.keys()))
+        self.assertEqual(quota_set['id'], self.demo_tenant_id)
+
+    @attr(type='gate')
+    def test_update_all_quota_resources_for_tenant(self):
+        # Admin can update all the resource quota limits for a tenant
+        resp, default_quota_set = self.client.get_default_quota_set(
+            self.demo_tenant_id)
+        new_quota_set = {'injected_file_content_bytes': 20480,
+                         'metadata_items': 256, 'injected_files': 10,
+                         'ram': 10240, 'floating_ips': 20, 'fixed_ips': 10,
+                         'key_pairs': 200, 'injected_file_path_bytes': 512,
+                         'instances': 20, 'security_group_rules': 20,
+                         'cores': 2, 'security_groups': 20}
+        # Update limits for all quota resources
+        resp, quota_set = self.adm_client.update_quota_set(
+            self.demo_tenant_id,
+            force=True,
+            **new_quota_set)
+
+        default_quota_set.pop('id')
+        self.addCleanup(self.adm_client.update_quota_set,
+                        self.demo_tenant_id, **default_quota_set)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(new_quota_set, quota_set)
+
+    # TODO(afazekas): merge these test cases
+    @attr(type='gate')
+    def test_get_updated_quotas(self):
+        # Verify that GET shows the updated quota set
+        tenant_name = data_utils.rand_name('cpu_quota_tenant_')
+        tenant_desc = tenant_name + '-desc'
+        identity_client = self.os_adm.identity_client
+        _, tenant = identity_client.create_tenant(name=tenant_name,
+                                                  description=tenant_desc)
+        tenant_id = tenant['id']
+        self.addCleanup(identity_client.delete_tenant,
+                        tenant_id)
+
+        self.adm_client.update_quota_set(tenant_id,
+                                         ram='5120')
+        resp, quota_set = self.adm_client.get_quota_set(tenant_id)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(quota_set['ram'], 5120)
+
+    # TODO(afazekas): Add dedicated tenant to the skiped quota tests
+    # it can be moved into the setUpClass as well
+    @attr(type='gate')
+    def test_create_server_when_cpu_quota_is_full(self):
+        # Disallow server creation when tenant's vcpu quota is full
+        resp, quota_set = self.client.get_quota_set(self.demo_tenant_id)
+        default_vcpu_quota = quota_set['cores']
+        vcpu_quota = 0  # Set the quota to zero to conserve resources
+
+        resp, quota_set = self.adm_client.update_quota_set(self.demo_tenant_id,
+                                                           force=True,
+                                                           cores=vcpu_quota)
+
+        self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
+                        cores=default_vcpu_quota)
+        self.assertRaises(exceptions.OverLimit, self.create_test_server)
+
+    @attr(type='gate')
+    def test_create_server_when_memory_quota_is_full(self):
+        # Disallow server creation when tenant's memory quota is full
+        resp, quota_set = self.client.get_quota_set(self.demo_tenant_id)
+        default_mem_quota = quota_set['ram']
+        mem_quota = 0  # Set the quota to zero to conserve resources
+
+        self.adm_client.update_quota_set(self.demo_tenant_id,
+                                         force=True,
+                                         ram=mem_quota)
+
+        self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
+                        ram=default_mem_quota)
+        self.assertRaises(exceptions.OverLimit, self.create_test_server)
+
+    @attr(type='gate')
+    def test_update_quota_normal_user(self):
+        self.assertRaises(exceptions.Unauthorized,
+                          self.client.update_quota_set,
+                          self.demo_tenant_id,
+                          ram=0)
+
+    @attr(type=['negative', 'gate'])
+    def test_create_server_when_instances_quota_is_full(self):
+        # Once instances quota limit is reached, disallow server creation
+        resp, quota_set = self.client.get_quota_set(self.demo_tenant_id)
+        default_instances_quota = quota_set['instances']
+        instances_quota = 0  # Set quota to zero to disallow server creation
+
+        self.adm_client.update_quota_set(self.demo_tenant_id,
+                                         force=True,
+                                         instances=instances_quota)
+        self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
+                        instances=default_instances_quota)
+        self.assertRaises(exceptions.OverLimit, self.create_test_server)
+
+    @skip_because(bug="1186354",
+                  condition=config.TempestConfig().service_available.neutron)
+    @attr(type=['negative', 'gate'])
+    def test_security_groups_exceed_limit(self):
+        # Negative test: Creation Security Groups over limit should FAIL
+
+        resp, quota_set = self.client.get_quota_set(self.demo_tenant_id)
+        default_sg_quota = quota_set['security_groups']
+        sg_quota = 0  # Set the quota to zero to conserve resources
+
+        resp, quota_set =\
+            self.adm_client.update_quota_set(self.demo_tenant_id,
+                                             force=True,
+                                             security_groups=sg_quota)
+
+        self.addCleanup(self.adm_client.update_quota_set,
+                        self.demo_tenant_id,
+                        security_groups=default_sg_quota)
+
+        # Check we cannot create anymore
+        self.assertRaises(exceptions.OverLimit,
+                          self.sg_client.create_security_group,
+                          "sg-overlimit", "sg-desc")
+
+    @skip_because(bug="1186354",
+                  condition=config.TempestConfig().service_available.neutron)
+    @attr(type=['negative', 'gate'])
+    def test_security_groups_rules_exceed_limit(self):
+        # Negative test: Creation of Security Group Rules should FAIL
+        # when we reach limit maxSecurityGroupRules
+
+        resp, quota_set = self.client.get_quota_set(self.demo_tenant_id)
+        default_sg_rules_quota = quota_set['security_group_rules']
+        sg_rules_quota = 0  # Set the quota to zero to conserve resources
+
+        resp, quota_set =\
+            self.adm_client.update_quota_set(
+                self.demo_tenant_id,
+                force=True,
+                security_group_rules=sg_rules_quota)
+
+        self.addCleanup(self.adm_client.update_quota_set,
+                        self.demo_tenant_id,
+                        security_group_rules=default_sg_rules_quota)
+
+        s_name = data_utils.rand_name('securitygroup-')
+        s_description = data_utils.rand_name('description-')
+        resp, securitygroup =\
+            self.sg_client.create_security_group(s_name, s_description)
+        self.addCleanup(self.sg_client.delete_security_group,
+                        securitygroup['id'])
+
+        secgroup_id = securitygroup['id']
+        ip_protocol = 'tcp'
+
+        # Check we cannot create SG rule anymore
+        self.assertRaises(exceptions.OverLimit,
+                          self.sg_client.create_security_group_rule,
+                          secgroup_id, ip_protocol, 1025, 1025)
+
+
+class QuotasAdminTestXML(QuotasAdminTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/admin/test_services.py b/tempest/api/compute/v3/admin/test_services.py
new file mode 100644
index 0000000..64135ed
--- /dev/null
+++ b/tempest/api/compute/v3/admin/test_services.py
@@ -0,0 +1,118 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 NEC Corporation
+# Copyright 2013 IBM Corp.
+# 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 tempest.api.compute import base
+from tempest import exceptions
+from tempest.test import attr
+
+
+class ServicesAdminV3TestJSON(base.BaseV3ComputeAdminTest):
+
+    """
+    Tests Services API. List and Enable/Disable require admin privileges.
+    """
+
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(ServicesAdminV3TestJSON, cls).setUpClass()
+        cls.client = cls.services_admin_client
+        cls.non_admin_client = cls.services_client
+
+    @attr(type='gate')
+    def test_list_services(self):
+        resp, services = self.client.list_services()
+        self.assertEqual(200, resp.status)
+        self.assertNotEqual(0, len(services))
+
+    @attr(type=['negative', 'gate'])
+    def test_list_services_with_non_admin_user(self):
+        self.assertRaises(exceptions.Unauthorized,
+                          self.non_admin_client.list_services)
+
+    @attr(type='gate')
+    def test_get_service_by_service_binary_name(self):
+        binary_name = 'nova-compute'
+        params = {'binary': binary_name}
+        resp, services = self.client.list_services(params)
+        self.assertEqual(200, resp.status)
+        self.assertNotEqual(0, len(services))
+        for service in services:
+            self.assertEqual(binary_name, service['binary'])
+
+    @attr(type='gate')
+    def test_get_service_by_host_name(self):
+        resp, services = self.client.list_services()
+        host_name = services[0]['host']
+        services_on_host = [service for service in services if
+                            service['host'] == host_name]
+        params = {'host': host_name}
+        resp, services = self.client.list_services(params)
+
+        # we could have a periodic job checkin between the 2 service
+        # lookups, so only compare binary lists.
+        s1 = map(lambda x: x['binary'], services)
+        s2 = map(lambda x: x['binary'], services_on_host)
+
+        # sort the lists before comparing, to take out dependency
+        # on order.
+        self.assertEqual(sorted(s1), sorted(s2))
+
+    @attr(type=['negative', 'gate'])
+    def test_get_service_by_invalid_params(self):
+        # return all services if send the request with invalid parameter
+        resp, services = self.client.list_services()
+        params = {'xxx': 'nova-compute'}
+        resp, services_xxx = self.client.list_services(params)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(len(services), len(services_xxx))
+
+    @attr(type='gate')
+    def test_get_service_by_service_and_host_name(self):
+        resp, services = self.client.list_services()
+        host_name = services[0]['host']
+        binary_name = services[0]['binary']
+        params = {'host': host_name, 'binary': binary_name}
+        resp, services = self.client.list_services(params)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(1, len(services))
+        self.assertEqual(host_name, services[0]['host'])
+        self.assertEqual(binary_name, services[0]['binary'])
+
+    @attr(type=['negative', 'gate'])
+    def test_get_service_by_invalid_service_and_valid_host(self):
+        resp, services = self.client.list_services()
+        host_name = services[0]['host']
+        params = {'host': host_name, 'binary': 'xxx'}
+        resp, services = self.client.list_services(params)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(0, len(services))
+
+    @attr(type=['negative', 'gate'])
+    def test_get_service_with_valid_service_and_invalid_host(self):
+        resp, services = self.client.list_services()
+        binary_name = services[0]['binary']
+        params = {'host': 'xxx', 'binary': binary_name}
+        resp, services = self.client.list_services(params)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(0, len(services))
+
+
+class ServicesAdminV3TestXML(ServicesAdminV3TestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/admin/test_simple_tenant_usage.py b/tempest/api/compute/v3/admin/test_simple_tenant_usage.py
new file mode 100644
index 0000000..3fc58eb
--- /dev/null
+++ b/tempest/api/compute/v3/admin/test_simple_tenant_usage.py
@@ -0,0 +1,115 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 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 datetime
+
+from tempest.api.compute import base
+from tempest import exceptions
+from tempest.test import attr
+import time
+
+
+class TenantUsagesV3TestJSON(base.BaseV3ComputeAdminTest):
+
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(TenantUsagesV3TestJSON, cls).setUpClass()
+        cls.adm_client = cls.tenant_usages_admin_client
+        cls.client = cls.tenant_usages_client
+        cls.identity_client = cls._get_identity_admin_client()
+
+        resp, tenants = cls.identity_client.list_tenants()
+        cls.tenant_id = [tnt['id'] for tnt in tenants if tnt['name'] ==
+                         cls.client.tenant_name][0]
+
+        # Create a server in the demo tenant
+        resp, server = cls.create_test_server(wait_until='ACTIVE')
+        time.sleep(2)
+
+        now = datetime.datetime.now()
+        cls.start = cls._parse_strtime(now - datetime.timedelta(days=1))
+        cls.end = cls._parse_strtime(now + datetime.timedelta(days=1))
+
+    @classmethod
+    def _parse_strtime(cls, at):
+        # Returns formatted datetime
+        return at.strftime('%Y-%m-%dT%H:%M:%S.%f')
+
+    @attr(type='gate')
+    def test_list_usage_all_tenants(self):
+        # Get usage for all tenants
+        params = {'start': self.start,
+                  'end': self.end,
+                  'detailed': int(bool(True))}
+        resp, tenant_usage = self.adm_client.list_tenant_usages(params)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(len(tenant_usage), 8)
+
+    @attr(type='gate')
+    def test_get_usage_tenant(self):
+        # Get usage for a specific tenant
+        params = {'start': self.start,
+                  'end': self.end}
+        resp, tenant_usage = self.adm_client.get_tenant_usage(
+            self.tenant_id, params)
+
+        self.assertEqual(200, resp.status)
+        self.assertEqual(len(tenant_usage), 8)
+
+    @attr(type='gate')
+    def test_get_usage_tenant_with_non_admin_user(self):
+        # Get usage for a specific tenant with non admin user
+        params = {'start': self.start,
+                  'end': self.end}
+        resp, tenant_usage = self.client.get_tenant_usage(
+            self.tenant_id, params)
+
+        self.assertEqual(200, resp.status)
+        self.assertEqual(len(tenant_usage), 8)
+
+    @attr(type=['negative', 'gate'])
+    def test_get_usage_tenant_with_empty_tenant_id(self):
+        # Get usage for a specific tenant empty
+        params = {'start': self.start,
+                  'end': self.end}
+        self.assertRaises(exceptions.NotFound,
+                          self.adm_client.get_tenant_usage,
+                          '', params)
+
+    @attr(type=['negative', 'gate'])
+    def test_get_usage_tenant_with_invalid_date(self):
+        # Get usage for tenant with invalid date
+        params = {'start': self.end,
+                  'end': self.start}
+        self.assertRaises(exceptions.BadRequest,
+                          self.adm_client.get_tenant_usage,
+                          self.tenant_id, params)
+
+    @attr(type=['negative', 'gate'])
+    def test_list_usage_all_tenants_with_non_admin_user(self):
+        # Get usage for all tenants with non admin user
+        params = {'start': self.start,
+                  'end': self.end,
+                  'detailed': int(bool(True))}
+        self.assertRaises(exceptions.Unauthorized,
+                          self.client.list_tenant_usages, params)
+
+
+class TenantUsagesV3TestXML(TenantUsagesV3TestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/images/__init__.py b/tempest/api/compute/v3/images/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api/compute/v3/images/__init__.py
diff --git a/tempest/api/compute/v3/images/test_images.py b/tempest/api/compute/v3/images/test_images.py
new file mode 100644
index 0000000..a179d65
--- /dev/null
+++ b/tempest/api/compute/v3/images/test_images.py
@@ -0,0 +1,126 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+#
+#    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.compute import base
+from tempest import clients
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest.test import attr
+
+
+class ImagesV3TestJSON(base.BaseV3ComputeTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(ImagesV3TestJSON, cls).setUpClass()
+        if not cls.config.service_available.glance:
+            skip_msg = ("%s skipped as glance is not available" % cls.__name__)
+            raise cls.skipException(skip_msg)
+        cls.client = cls.images_client
+        cls.servers_client = cls.servers_client
+
+        if cls.multi_user:
+            if cls.config.compute.allow_tenant_isolation:
+                creds = cls.isolated_creds.get_alt_creds()
+                username, tenant_name, password = creds
+                cls.alt_manager = clients.Manager(username=username,
+                                                  password=password,
+                                                  tenant_name=tenant_name)
+            else:
+                # Use the alt_XXX credentials in the config file
+                cls.alt_manager = clients.AltManager()
+            cls.alt_client = cls.alt_manager.images_client
+
+    def __create_image__(self, server_id, name, meta=None):
+        resp, body = self.servers_client.create_image(server_id, name, meta)
+        image_id = data_utils.parse_image_id(resp['location'])
+        self.addCleanup(self.client.delete_image, image_id)
+        self.client.wait_for_image_status(image_id, 'ACTIVE')
+        return resp, body
+
+    @attr(type=['negative', 'gate'])
+    def test_create_image_from_deleted_server(self):
+        # An image should not be created if the server instance is removed
+        resp, server = self.create_test_server(wait_until='ACTIVE')
+
+        # Delete server before trying to create server
+        self.servers_client.delete_server(server['id'])
+        self.servers_client.wait_for_server_termination(server['id'])
+        # Create a new image after server is deleted
+        name = data_utils.rand_name('image')
+        meta = {'image_type': 'test'}
+        self.assertRaises(exceptions.NotFound,
+                          self.__create_image__,
+                          server['id'], name, meta)
+
+    @attr(type=['negative', 'gate'])
+    def test_create_image_from_invalid_server(self):
+        # An image should not be created with invalid server id
+        # Create a new image with invalid server id
+        name = data_utils.rand_name('image')
+        meta = {'image_type': 'test'}
+        resp = {}
+        resp['status'] = None
+        self.assertRaises(exceptions.NotFound, self.__create_image__,
+                          '!@#$%^&*()', name, meta)
+
+    @attr(type=['negative', 'gate'])
+    def test_create_image_from_stopped_server(self):
+        resp, server = self.create_test_server(wait_until='ACTIVE')
+        self.servers_client.stop(server['id'])
+        self.servers_client.wait_for_server_status(server['id'],
+                                                   'SHUTOFF')
+        self.addCleanup(self.servers_client.delete_server, server['id'])
+        snapshot_name = data_utils.rand_name('test-snap-')
+        resp, image = self.create_image_from_server(server['id'],
+                                                    name=snapshot_name,
+                                                    wait_until='active')
+        self.addCleanup(self.client.delete_image, image['id'])
+        self.assertEqual(snapshot_name, image['name'])
+
+    @attr(type='gate')
+    def test_delete_queued_image(self):
+        snapshot_name = data_utils.rand_name('test-snap-')
+        resp, server = self.create_test_server(wait_until='ACTIVE')
+        self.addCleanup(self.servers_client.delete_server, server['id'])
+        resp, image = self.create_image_from_server(server['id'],
+                                                    name=snapshot_name,
+                                                    wait_until='queued')
+        resp, body = self.client.delete_image(image['id'])
+        self.assertEqual('200', resp['status'])
+
+    @attr(type=['negative', 'gate'])
+    def test_create_image_specify_uuid_35_characters_or_less(self):
+        # Return an error if Image ID passed is 35 characters or less
+        snapshot_name = data_utils.rand_name('test-snap-')
+        test_uuid = ('a' * 35)
+        self.assertRaises(exceptions.NotFound,
+                          self.servers_client.create_image,
+                          test_uuid, snapshot_name)
+
+    @attr(type=['negative', 'gate'])
+    def test_create_image_specify_uuid_37_characters_or_more(self):
+        # Return an error if Image ID passed is 37 characters or more
+        snapshot_name = data_utils.rand_name('test-snap-')
+        test_uuid = ('a' * 37)
+        self.assertRaises(exceptions.NotFound,
+                          self.servers_client.create_image,
+                          test_uuid, snapshot_name)
+
+
+class ImagesV3TestXML(ImagesV3TestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/servers/__init__.py b/tempest/api/compute/v3/servers/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api/compute/v3/servers/__init__.py
diff --git a/tempest/api/compute/v3/servers/test_attach_interfaces.py b/tempest/api/compute/v3/servers/test_attach_interfaces.py
new file mode 100644
index 0000000..f208a4b
--- /dev/null
+++ b/tempest/api/compute/v3/servers/test_attach_interfaces.py
@@ -0,0 +1,118 @@
+# Copyright 2013 IBM Corp.
+# 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 tempest.api.compute import base
+from tempest.test import attr
+
+import time
+
+
+class AttachInterfacesV3TestJSON(base.BaseV3ComputeTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        if not cls.config.service_available.neutron:
+            raise cls.skipException("Neutron is required")
+        super(AttachInterfacesV3TestJSON, cls).setUpClass()
+        cls.client = cls.interfaces_client
+
+    def _check_interface(self, iface, port_id=None, network_id=None,
+                         fixed_ip=None):
+        self.assertIn('port_state', iface)
+        if port_id:
+            self.assertEqual(iface['port_id'], port_id)
+        if network_id:
+            self.assertEqual(iface['net_id'], network_id)
+        if fixed_ip:
+            self.assertEqual(iface['fixed_ips'][0]['ip_address'], fixed_ip)
+
+    def _create_server_get_interfaces(self):
+        resp, server = self.create_test_server(wait_until='ACTIVE')
+        resp, ifs = self.client.list_interfaces(server['id'])
+        resp, body = self.client.wait_for_interface_status(
+            server['id'], ifs[0]['port_id'], 'ACTIVE')
+        ifs[0]['port_state'] = body['port_state']
+        return server, ifs
+
+    def _test_create_interface(self, server):
+        resp, iface = self.client.create_interface(server['id'])
+        resp, iface = self.client.wait_for_interface_status(
+            server['id'], iface['port_id'], 'ACTIVE')
+        self._check_interface(iface)
+        return iface
+
+    def _test_create_interface_by_network_id(self, server, ifs):
+        network_id = ifs[0]['net_id']
+        resp, iface = self.client.create_interface(server['id'],
+                                                   network_id=network_id)
+        resp, iface = self.client.wait_for_interface_status(
+            server['id'], iface['port_id'], 'ACTIVE')
+        self._check_interface(iface, network_id=network_id)
+        return iface
+
+    def _test_show_interface(self, server, ifs):
+        iface = ifs[0]
+        resp, _iface = self.client.show_interface(server['id'],
+                                                  iface['port_id'])
+        self.assertEqual(iface, _iface)
+
+    def _test_delete_interface(self, server, ifs):
+        # NOTE(danms): delete not the first or last, but one in the middle
+        iface = ifs[1]
+        self.client.delete_interface(server['id'], iface['port_id'])
+        for i in range(0, 5):
+            _r, _ifs = self.client.list_interfaces(server['id'])
+            if len(ifs) != len(_ifs):
+                break
+            time.sleep(1)
+
+        self.assertEqual(len(_ifs), len(ifs) - 1)
+        for _iface in _ifs:
+            self.assertNotEqual(iface['port_id'], _iface['port_id'])
+        return _ifs
+
+    def _compare_iface_list(self, list1, list2):
+        # NOTE(danms): port_state will likely have changed, so just
+        # confirm the port_ids are the same at least
+        list1 = [x['port_id'] for x in list1]
+        list2 = [x['port_id'] for x in list2]
+
+        self.assertEqual(sorted(list1), sorted(list2))
+
+    @attr(type='gate')
+    def test_create_list_show_delete_interfaces(self):
+        server, ifs = self._create_server_get_interfaces()
+        interface_count = len(ifs)
+        self.assertTrue(interface_count > 0)
+        self._check_interface(ifs[0])
+
+        iface = self._test_create_interface(server)
+        ifs.append(iface)
+
+        iface = self._test_create_interface_by_network_id(server, ifs)
+        ifs.append(iface)
+
+        resp, _ifs = self.client.list_interfaces(server['id'])
+        self._compare_iface_list(ifs, _ifs)
+
+        self._test_show_interface(server, ifs)
+
+        _ifs = self._test_delete_interface(server, ifs)
+        self.assertEqual(len(ifs) - 1, len(_ifs))
+
+
+class AttachInterfacesV3TestXML(AttachInterfacesV3TestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/servers/test_create_server.py b/tempest/api/compute/v3/servers/test_create_server.py
new file mode 100644
index 0000000..24ade96
--- /dev/null
+++ b/tempest/api/compute/v3/servers/test_create_server.py
@@ -0,0 +1,130 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import base64
+
+import netaddr
+import testtools
+
+from tempest.api import compute
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest.common.utils.linux.remote_client import RemoteClient
+import tempest.config
+from tempest.test import attr
+
+
+class ServersTestJSON(base.BaseV2ComputeTest):
+    _interface = 'json'
+    run_ssh = tempest.config.TempestConfig().compute.run_ssh
+    disk_config = 'AUTO'
+
+    @classmethod
+    def setUpClass(cls):
+        super(ServersTestJSON, cls).setUpClass()
+        cls.meta = {'hello': 'world'}
+        cls.accessIPv4 = '1.1.1.1'
+        cls.accessIPv6 = '0000:0000:0000:0000:0000:babe:220.12.22.2'
+        cls.name = data_utils.rand_name('server')
+        file_contents = 'This is a test file.'
+        personality = [{'path': '/test.txt',
+                       'contents': base64.b64encode(file_contents)}]
+        cls.client = cls.servers_client
+        cli_resp = cls.create_test_server(name=cls.name,
+                                          meta=cls.meta,
+                                          accessIPv4=cls.accessIPv4,
+                                          accessIPv6=cls.accessIPv6,
+                                          personality=personality,
+                                          disk_config=cls.disk_config)
+        cls.resp, cls.server_initial = cli_resp
+        cls.password = cls.server_initial['adminPass']
+        cls.client.wait_for_server_status(cls.server_initial['id'], 'ACTIVE')
+        resp, cls.server = cls.client.get_server(cls.server_initial['id'])
+
+    @attr(type='smoke')
+    def test_create_server_response(self):
+        # Check that the required fields are returned with values
+        self.assertEqual(202, self.resp.status)
+        self.assertTrue(self.server_initial['id'] is not None)
+        self.assertTrue(self.server_initial['adminPass'] is not None)
+
+    @attr(type='smoke')
+    def test_verify_server_details(self):
+        # Verify the specified server attributes are set correctly
+        self.assertEqual(self.accessIPv4, self.server['accessIPv4'])
+        # NOTE(maurosr): See http://tools.ietf.org/html/rfc5952 (section 4)
+        # Here we compare directly with the canonicalized format.
+        self.assertEqual(self.server['accessIPv6'],
+                         str(netaddr.IPAddress(self.accessIPv6)))
+        self.assertEqual(self.name, self.server['name'])
+        self.assertEqual(self.image_ref, self.server['image']['id'])
+        self.assertEqual(self.flavor_ref, self.server['flavor']['id'])
+        self.assertEqual(self.meta, self.server['metadata'])
+
+    @attr(type='smoke')
+    def test_list_servers(self):
+        # The created server should be in the list of all servers
+        resp, body = self.client.list_servers()
+        servers = body['servers']
+        found = any([i for i in servers if i['id'] == self.server['id']])
+        self.assertTrue(found)
+
+    @attr(type='smoke')
+    def test_list_servers_with_detail(self):
+        # The created server should be in the detailed list of all servers
+        resp, body = self.client.list_servers_with_detail()
+        servers = body['servers']
+        found = any([i for i in servers if i['id'] == self.server['id']])
+        self.assertTrue(found)
+
+    @testtools.skipIf(not run_ssh, 'Instance validation tests are disabled.')
+    @attr(type='gate')
+    def test_can_log_into_created_server(self):
+        # Check that the user can authenticate with the generated password
+        linux_client = RemoteClient(self.server, self.ssh_user, self.password)
+        self.assertTrue(linux_client.can_authenticate())
+
+    @testtools.skipIf(not run_ssh, 'Instance validation tests are disabled.')
+    @attr(type='gate')
+    def test_verify_created_server_vcpus(self):
+        # Verify that the number of vcpus reported by the instance matches
+        # the amount stated by the flavor
+        resp, flavor = self.flavors_client.get_flavor_details(self.flavor_ref)
+        linux_client = RemoteClient(self.server, self.ssh_user, self.password)
+        self.assertEqual(flavor['vcpus'], linux_client.get_number_of_vcpus())
+
+    @testtools.skipIf(not run_ssh, 'Instance validation tests are disabled.')
+    @attr(type='gate')
+    def test_host_name_is_same_as_server_name(self):
+        # Verify the instance host name is the same as the server name
+        linux_client = RemoteClient(self.server, self.ssh_user, self.password)
+        self.assertTrue(linux_client.hostname_equals_servername(self.name))
+
+
+class ServersTestManualDisk(ServersTestJSON):
+    disk_config = 'MANUAL'
+
+    @classmethod
+    def setUpClass(cls):
+        if not compute.DISK_CONFIG_ENABLED:
+            msg = "DiskConfig extension not enabled."
+            raise cls.skipException(msg)
+        super(ServersTestManualDisk, cls).setUpClass()
+
+
+class ServersTestXML(ServersTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/servers/test_instance_actions.py b/tempest/api/compute/v3/servers/test_instance_actions.py
new file mode 100644
index 0000000..ea92c9f
--- /dev/null
+++ b/tempest/api/compute/v3/servers/test_instance_actions.py
@@ -0,0 +1,69 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 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.
+
+from tempest.api.compute import base
+from tempest import exceptions
+from tempest.test import attr
+
+
+class InstanceActionsV3TestJSON(base.BaseV3ComputeTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(InstanceActionsV3TestJSON, cls).setUpClass()
+        cls.client = cls.servers_client
+        resp, server = cls.create_test_server(wait_until='ACTIVE')
+        cls.request_id = resp['x-compute-request-id']
+        cls.server_id = server['id']
+
+    @attr(type='gate')
+    def test_list_instance_actions(self):
+        # List actions of the provided server
+        resp, body = self.client.reboot(self.server_id, 'HARD')
+        self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+
+        resp, body = self.client.list_instance_actions(self.server_id)
+        self.assertEqual(200, resp.status)
+        self.assertTrue(len(body) == 2, str(body))
+        self.assertTrue(any([i for i in body if i['action'] == 'create']))
+        self.assertTrue(any([i for i in body if i['action'] == 'reboot']))
+
+    @attr(type='gate')
+    def test_get_instance_action(self):
+        # Get the action details of the provided server
+        resp, body = self.client.get_instance_action(self.server_id,
+                                                     self.request_id)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(self.server_id, body['instance_uuid'])
+        self.assertEqual('create', body['action'])
+
+    @attr(type=['negative', 'gate'])
+    def test_list_instance_actions_invalid_server(self):
+        # List actions of the invalid server id
+        self.assertRaises(exceptions.NotFound,
+                          self.client.list_instance_actions, 'server-999')
+
+    @attr(type=['negative', 'gate'])
+    def test_get_instance_action_invalid_request(self):
+        # Get the action details of the provided server with invalid request
+        self.assertRaises(exceptions.NotFound, self.client.get_instance_action,
+                          self.server_id, '999')
+
+
+class InstanceActionsV3TestXML(InstanceActionsV3TestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/servers/test_list_server_filters.py b/tempest/api/compute/v3/servers/test_list_server_filters.py
new file mode 100644
index 0000000..d333a1d
--- /dev/null
+++ b/tempest/api/compute/v3/servers/test_list_server_filters.py
@@ -0,0 +1,239 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.compute import base
+from tempest.api import utils
+from tempest.common.utils import data_utils
+from tempest import config
+from tempest import exceptions
+from tempest.test import attr
+from tempest.test import skip_because
+
+
+class ListServerFiltersV3TestJSON(base.BaseV3ComputeTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(ListServerFiltersV3TestJSON, cls).setUpClass()
+        cls.client = cls.servers_client
+
+        # Check to see if the alternate image ref actually exists...
+        images_client = cls.images_client
+        resp, images = images_client.image_list()
+
+        if cls.image_ref != cls.image_ref_alt and \
+            any([image for image in images
+                 if image['id'] == cls.image_ref_alt]):
+            cls.multiple_images = True
+        else:
+            cls.image_ref_alt = cls.image_ref
+
+        # Do some sanity checks here. If one of the images does
+        # not exist, fail early since the tests won't work...
+        try:
+            cls.images_client.get_image_meta(cls.image_ref)
+        except exceptions.NotFound:
+            raise RuntimeError("Image %s (image_ref) was not found!" %
+                               cls.image_ref)
+
+        try:
+            cls.images_client.get_image_meta(cls.image_ref_alt)
+        except exceptions.NotFound:
+            raise RuntimeError("Image %s (image_ref_alt) was not found!" %
+                               cls.image_ref_alt)
+
+        cls.s1_name = data_utils.rand_name(cls.__name__ + '-instance')
+        resp, cls.s1 = cls.create_test_server(name=cls.s1_name,
+                                              wait_until='ACTIVE')
+
+        cls.s2_name = data_utils.rand_name(cls.__name__ + '-instance')
+        resp, cls.s2 = cls.create_test_server(name=cls.s2_name,
+                                              image_id=cls.image_ref_alt,
+                                              wait_until='ACTIVE')
+
+        cls.s3_name = data_utils.rand_name(cls.__name__ + '-instance')
+        resp, cls.s3 = cls.create_test_server(name=cls.s3_name,
+                                              flavor=cls.flavor_ref_alt,
+                                              wait_until='ACTIVE')
+
+        cls.fixed_network_name = cls.config.compute.fixed_network_name
+
+    @utils.skip_unless_attr('multiple_images', 'Only one image found')
+    @attr(type='gate')
+    def test_list_servers_filter_by_image(self):
+        # Filter the list of servers by image
+        params = {'image': self.image_ref}
+        resp, body = self.client.list_servers(params)
+        servers = body['servers']
+
+        self.assertIn(self.s1['id'], map(lambda x: x['id'], servers))
+        self.assertNotIn(self.s2['id'], map(lambda x: x['id'], servers))
+        self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
+
+    @attr(type='gate')
+    def test_list_servers_filter_by_flavor(self):
+        # Filter the list of servers by flavor
+        params = {'flavor': self.flavor_ref_alt}
+        resp, body = self.client.list_servers(params)
+        servers = body['servers']
+
+        self.assertNotIn(self.s1['id'], map(lambda x: x['id'], servers))
+        self.assertNotIn(self.s2['id'], map(lambda x: x['id'], servers))
+        self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
+
+    @attr(type='gate')
+    def test_list_servers_filter_by_server_name(self):
+        # Filter the list of servers by server name
+        params = {'name': self.s1_name}
+        resp, body = self.client.list_servers(params)
+        servers = body['servers']
+
+        self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
+        self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
+        self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
+
+    @attr(type='gate')
+    def test_list_servers_filter_by_server_status(self):
+        # Filter the list of servers by server status
+        params = {'status': 'active'}
+        resp, body = self.client.list_servers(params)
+        servers = body['servers']
+
+        self.assertIn(self.s1['id'], map(lambda x: x['id'], servers))
+        self.assertIn(self.s2['id'], map(lambda x: x['id'], servers))
+        self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
+
+    @attr(type='gate')
+    def test_list_servers_filter_by_limit(self):
+        # Verify only the expected number of servers are returned
+        params = {'limit': 1}
+        resp, servers = self.client.list_servers(params)
+        # when _interface='xml', one element for servers_links in servers
+        self.assertEqual(1, len([x for x in servers['servers'] if 'id' in x]))
+
+    @utils.skip_unless_attr('multiple_images', 'Only one image found')
+    @attr(type='gate')
+    def test_list_servers_detailed_filter_by_image(self):
+        # Filter the detailed list of servers by image
+        params = {'image': self.image_ref}
+        resp, body = self.client.list_servers_with_detail(params)
+        servers = body['servers']
+
+        self.assertIn(self.s1['id'], map(lambda x: x['id'], servers))
+        self.assertNotIn(self.s2['id'], map(lambda x: x['id'], servers))
+        self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
+
+    @attr(type='gate')
+    def test_list_servers_detailed_filter_by_flavor(self):
+        # Filter the detailed list of servers by flavor
+        params = {'flavor': self.flavor_ref_alt}
+        resp, body = self.client.list_servers_with_detail(params)
+        servers = body['servers']
+
+        self.assertNotIn(self.s1['id'], map(lambda x: x['id'], servers))
+        self.assertNotIn(self.s2['id'], map(lambda x: x['id'], servers))
+        self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
+
+    @attr(type='gate')
+    def test_list_servers_detailed_filter_by_server_name(self):
+        # Filter the detailed list of servers by server name
+        params = {'name': self.s1_name}
+        resp, body = self.client.list_servers_with_detail(params)
+        servers = body['servers']
+
+        self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
+        self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
+        self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
+
+    @attr(type='gate')
+    def test_list_servers_detailed_filter_by_server_status(self):
+        # Filter the detailed list of servers by server status
+        params = {'status': 'active'}
+        resp, body = self.client.list_servers_with_detail(params)
+        expected_servers = (self.s1['id'], self.s2['id'], self.s3['id'])
+        servers = [x for x in body['servers'] if x['id'] in expected_servers]
+
+        self.assertIn(self.s1['id'], map(lambda x: x['id'], servers))
+        self.assertIn(self.s2['id'], map(lambda x: x['id'], servers))
+        self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
+        self.assertEqual(['ACTIVE'] * 3, [x['status'] for x in servers])
+
+    @attr(type='gate')
+    def test_list_servers_filtered_by_name_wildcard(self):
+        # List all servers that contains '-instance' in name
+        params = {'name': '-instance'}
+        resp, body = self.client.list_servers(params)
+        servers = body['servers']
+
+        self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
+        self.assertIn(self.s2_name, map(lambda x: x['name'], servers))
+        self.assertIn(self.s3_name, map(lambda x: x['name'], servers))
+
+        # Let's take random part of name and try to search it
+        part_name = self.s1_name[6:-1]
+
+        params = {'name': part_name}
+        resp, body = self.client.list_servers(params)
+        servers = body['servers']
+
+        self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
+        self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
+        self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
+
+    @skip_because(bug="1170718")
+    @attr(type='gate')
+    def test_list_servers_filtered_by_ip(self):
+        # Filter servers by ip
+        # Here should be listed 1 server
+        resp, self.s1 = self.client.get_server(self.s1['id'])
+        ip = self.s1['addresses'][self.fixed_network_name][0]['addr']
+        params = {'ip': ip}
+        resp, body = self.client.list_servers(params)
+        servers = body['servers']
+
+        self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
+        self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
+        self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
+
+    @skip_because(bug="1182883",
+                  condition=config.TempestConfig().service_available.neutron)
+    @attr(type='gate')
+    def test_list_servers_filtered_by_ip_regex(self):
+        # Filter servers by regex ip
+        # List all servers filtered by part of ip address.
+        # Here should be listed all servers
+        resp, self.s1 = self.client.get_server(self.s1['id'])
+        ip = self.s1['addresses'][self.fixed_network_name][0]['addr'][0:-3]
+        params = {'ip': ip}
+        resp, body = self.client.list_servers(params)
+        servers = body['servers']
+
+        self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
+        self.assertIn(self.s2_name, map(lambda x: x['name'], servers))
+        self.assertIn(self.s3_name, map(lambda x: x['name'], servers))
+
+    @attr(type='gate')
+    def test_list_servers_detailed_limit_results(self):
+        # Verify only the expected number of detailed results are returned
+        params = {'limit': 1}
+        resp, servers = self.client.list_servers_with_detail(params)
+        self.assertEqual(1, len(servers['servers']))
+
+
+class ListServerFiltersV3TestXML(ListServerFiltersV3TestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/servers/test_list_servers_negative.py b/tempest/api/compute/v3/servers/test_list_servers_negative.py
new file mode 100644
index 0000000..3f7f885
--- /dev/null
+++ b/tempest/api/compute/v3/servers/test_list_servers_negative.py
@@ -0,0 +1,221 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import datetime
+
+from tempest.api.compute import base
+from tempest import clients
+from tempest import exceptions
+from tempest.test import attr
+
+
+class ListServersNegativeV3TestJSON(base.BaseV3ComputeTest):
+    _interface = 'json'
+
+    @classmethod
+    def _ensure_no_servers(cls, servers, username, tenant_name):
+        """
+        If there are servers and there is tenant isolation then a
+        skipException is raised to skip the test since it requires no servers
+        to already exist for the given user/tenant.
+        If there are servers and there is not tenant isolation then the test
+        blocks while the servers are being deleted.
+        """
+        if len(servers):
+            if not cls.config.compute.allow_tenant_isolation:
+                for srv in servers:
+                    cls.client.wait_for_server_termination(srv['id'],
+                                                           ignore_error=True)
+            else:
+                msg = ("User/tenant %(u)s/%(t)s already have "
+                       "existing server instances. Skipping test." %
+                       {'u': username, 't': tenant_name})
+                raise cls.skipException(msg)
+
+    @classmethod
+    def setUpClass(cls):
+        super(ListServersNegativeV3TestJSON, cls).setUpClass()
+        cls.client = cls.servers_client
+        cls.servers = []
+
+        if cls.multi_user:
+            if cls.config.compute.allow_tenant_isolation:
+                creds = cls.isolated_creds.get_alt_creds()
+                username, tenant_name, password = creds
+                cls.alt_manager = clients.Manager(username=username,
+                                                  password=password,
+                                                  tenant_name=tenant_name)
+            else:
+                # Use the alt_XXX credentials in the config file
+                cls.alt_manager = clients.AltManager()
+            cls.alt_client = cls.alt_manager.servers_client
+
+        # Under circumstances when there is not a tenant/user
+        # created for the test case, the test case checks
+        # to see if there are existing servers for the
+        # either the normal user/tenant or the alt user/tenant
+        # and if so, the whole test is skipped. We do this
+        # because we assume a baseline of no servers at the
+        # start of the test instead of destroying any existing
+        # servers.
+        resp, body = cls.client.list_servers()
+        cls._ensure_no_servers(body['servers'],
+                               cls.os.username,
+                               cls.os.tenant_name)
+
+        resp, body = cls.alt_client.list_servers()
+        cls._ensure_no_servers(body['servers'],
+                               cls.alt_manager.username,
+                               cls.alt_manager.tenant_name)
+
+        # The following servers are created for use
+        # by the test methods in this class. These
+        # servers are cleaned up automatically in the
+        # tearDownClass method of the super-class.
+        cls.existing_fixtures = []
+        cls.deleted_fixtures = []
+        cls.start_time = datetime.datetime.utcnow()
+        for x in xrange(2):
+            resp, srv = cls.create_test_server()
+            cls.existing_fixtures.append(srv)
+
+        resp, srv = cls.create_test_server()
+        cls.client.delete_server(srv['id'])
+        # We ignore errors on termination because the server may
+        # be put into ERROR status on a quick spawn, then delete,
+        # as the compute node expects the instance local status
+        # to be spawning, not deleted. See LP Bug#1061167
+        cls.client.wait_for_server_termination(srv['id'],
+                                               ignore_error=True)
+        cls.deleted_fixtures.append(srv)
+
+    @attr(type=['negative', 'gate'])
+    def test_list_servers_with_a_deleted_server(self):
+        # Verify deleted servers do not show by default in list servers
+        # List servers and verify server not returned
+        resp, body = self.client.list_servers()
+        servers = body['servers']
+        deleted_ids = [s['id'] for s in self.deleted_fixtures]
+        actual = [srv for srv in servers
+                  if srv['id'] in deleted_ids]
+        self.assertEqual('200', resp['status'])
+        self.assertEqual([], actual)
+
+    @attr(type=['negative', 'gate'])
+    def test_list_servers_by_non_existing_image(self):
+        # Listing servers for a non existing image returns empty list
+        non_existing_image = '1234abcd-zzz0-aaa9-ppp3-0987654abcde'
+        resp, body = self.client.list_servers(dict(image=non_existing_image))
+        servers = body['servers']
+        self.assertEqual('200', resp['status'])
+        self.assertEqual([], servers)
+
+    @attr(type=['negative', 'gate'])
+    def test_list_servers_by_non_existing_flavor(self):
+        # Listing servers by non existing flavor returns empty list
+        non_existing_flavor = 1234
+        resp, body = self.client.list_servers(dict(flavor=non_existing_flavor))
+        servers = body['servers']
+        self.assertEqual('200', resp['status'])
+        self.assertEqual([], servers)
+
+    @attr(type=['negative', 'gate'])
+    def test_list_servers_by_non_existing_server_name(self):
+        # Listing servers for a non existent server name returns empty list
+        non_existing_name = 'junk_server_1234'
+        resp, body = self.client.list_servers(dict(name=non_existing_name))
+        servers = body['servers']
+        self.assertEqual('200', resp['status'])
+        self.assertEqual([], servers)
+
+    @attr(type=['negative', 'gate'])
+    def test_list_servers_status_non_existing(self):
+        # Return an empty list when invalid status is specified
+        non_existing_status = 'BALONEY'
+        resp, body = self.client.list_servers(dict(status=non_existing_status))
+        servers = body['servers']
+        self.assertEqual('200', resp['status'])
+        self.assertEqual([], servers)
+
+    @attr(type='gate')
+    def test_list_servers_by_limits(self):
+        # List servers by specifying limits
+        resp, body = self.client.list_servers({'limit': 1})
+        self.assertEqual('200', resp['status'])
+        # when _interface='xml', one element for servers_links in servers
+        self.assertEqual(1, len([x for x in body['servers'] if 'id' in x]))
+
+    @attr(type=['negative', 'gate'])
+    def test_list_servers_by_limits_greater_than_actual_count(self):
+        # List servers by specifying a greater value for limit
+        resp, body = self.client.list_servers({'limit': 100})
+        self.assertEqual('200', resp['status'])
+        self.assertEqual(len(self.existing_fixtures), len(body['servers']))
+
+    @attr(type=['negative', 'gate'])
+    def test_list_servers_by_limits_pass_string(self):
+        # Return an error if a string value is passed for limit
+        self.assertRaises(exceptions.BadRequest, self.client.list_servers,
+                          {'limit': 'testing'})
+
+    @attr(type=['negative', 'gate'])
+    def test_list_servers_by_limits_pass_negative_value(self):
+        # Return an error if a negative value for limit is passed
+        self.assertRaises(exceptions.BadRequest, self.client.list_servers,
+                          {'limit': -1})
+
+    @attr(type='gate')
+    def test_list_servers_by_changes_since(self):
+        # Servers are listed by specifying changes-since date
+        changes_since = {'changes_since': self.start_time.isoformat()}
+        resp, body = self.client.list_servers(changes_since)
+        self.assertEqual('200', resp['status'])
+        # changes-since returns all instances, including deleted.
+        num_expected = (len(self.existing_fixtures) +
+                        len(self.deleted_fixtures))
+        self.assertEqual(num_expected, len(body['servers']),
+                         "Number of servers %d is wrong in %s" %
+                         (num_expected, body['servers']))
+
+    @attr(type=['negative', 'gate'])
+    def test_list_servers_by_changes_since_invalid_date(self):
+        # Return an error when invalid date format is passed
+        self.assertRaises(exceptions.BadRequest, self.client.list_servers,
+                          {'changes_since': '2011/01/01'})
+
+    @attr(type=['negative', 'gate'])
+    def test_list_servers_by_changes_since_future_date(self):
+        # Return an empty list when a date in the future is passed
+        changes_since = {'changes_since': '2051-01-01T12:34:00Z'}
+        resp, body = self.client.list_servers(changes_since)
+        self.assertEqual('200', resp['status'])
+        self.assertEqual(0, len(body['servers']))
+
+    @attr(type=['negative', 'gate'])
+    def test_list_servers_detail_server_is_deleted(self):
+        # Server details are not listed for a deleted server
+        deleted_ids = [s['id'] for s in self.deleted_fixtures]
+        resp, body = self.client.list_servers_with_detail()
+        servers = body['servers']
+        actual = [srv for srv in servers
+                  if srv['id'] in deleted_ids]
+        self.assertEqual('200', resp['status'])
+        self.assertEqual([], actual)
+
+
+class ListServersNegativeV3TestXML(ListServersNegativeV3TestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/servers/test_multiple_create.py b/tempest/api/compute/v3/servers/test_multiple_create.py
new file mode 100644
index 0000000..080bd1a
--- /dev/null
+++ b/tempest/api/compute/v3/servers/test_multiple_create.py
@@ -0,0 +1,95 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM Corp
+# 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 tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest.test import attr
+
+
+class MultipleCreateTestJSON(base.BaseV2ComputeTest):
+    _interface = 'json'
+    _name = 'multiple-create-test'
+
+    def _generate_name(self):
+        return data_utils.rand_name(self._name)
+
+    def _create_multiple_servers(self, name=None, wait_until=None, **kwargs):
+        """
+        This is the right way to create_multiple servers and manage to get the
+        created servers into the servers list to be cleaned up after all.
+        """
+        kwargs['name'] = kwargs.get('name', self._generate_name())
+        resp, body = self.create_test_server(**kwargs)
+
+        return resp, body
+
+    @attr(type='gate')
+    def test_multiple_create(self):
+        resp, body = self._create_multiple_servers(wait_until='ACTIVE',
+                                                   min_count=1,
+                                                   max_count=2)
+        # NOTE(maurosr): do status response check and also make sure that
+        # reservation_id is not in the response body when the request send
+        # contains return_reservation_id=False
+        self.assertEqual('202', resp['status'])
+        self.assertNotIn('reservation_id', body)
+
+    @attr(type=['negative', 'gate'])
+    def test_min_count_less_than_one(self):
+        invalid_min_count = 0
+        self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
+                          min_count=invalid_min_count)
+
+    @attr(type=['negative', 'gate'])
+    def test_min_count_non_integer(self):
+        invalid_min_count = 2.5
+        self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
+                          min_count=invalid_min_count)
+
+    @attr(type=['negative', 'gate'])
+    def test_max_count_less_than_one(self):
+        invalid_max_count = 0
+        self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
+                          max_count=invalid_max_count)
+
+    @attr(type=['negative', 'gate'])
+    def test_max_count_non_integer(self):
+        invalid_max_count = 2.5
+        self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
+                          max_count=invalid_max_count)
+
+    @attr(type=['negative', 'gate'])
+    def test_max_count_less_than_min_count(self):
+        min_count = 3
+        max_count = 2
+        self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
+                          min_count=min_count,
+                          max_count=max_count)
+
+    @attr(type='gate')
+    def test_multiple_create_with_reservation_return(self):
+        resp, body = self._create_multiple_servers(wait_until='ACTIVE',
+                                                   min_count=1,
+                                                   max_count=2,
+                                                   return_reservation_id=True)
+        self.assertEqual(resp['status'], '202')
+        self.assertIn('reservation_id', body)
+
+
+class MultipleCreateTestXML(MultipleCreateTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/servers/test_server_actions.py b/tempest/api/compute/v3/servers/test_server_actions.py
new file mode 100644
index 0000000..090f4dd
--- /dev/null
+++ b/tempest/api/compute/v3/servers/test_server_actions.py
@@ -0,0 +1,278 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import base64
+import time
+
+import testtools
+
+from tempest.api import compute
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest.common.utils.linux.remote_client import RemoteClient
+import tempest.config
+from tempest import exceptions
+from tempest.test import attr
+from tempest.test import skip_because
+
+
+class ServerActionsV3TestJSON(base.BaseV3ComputeTest):
+    _interface = 'json'
+    resize_available = tempest.config.TempestConfig().\
+        compute_feature_enabled.resize
+    run_ssh = tempest.config.TempestConfig().compute.run_ssh
+
+    def setUp(self):
+        # NOTE(afazekas): Normally we use the same server with all test cases,
+        # but if it has an issue, we build a new one
+        super(ServerActionsV3TestJSON, self).setUp()
+        # Check if the server is in a clean state after test
+        try:
+            self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+        except Exception:
+            # Rebuild server if something happened to it during a test
+            self.__class__.server_id = self.rebuild_server(self.server_id)
+
+    @classmethod
+    def setUpClass(cls):
+        super(ServerActionsV3TestJSON, cls).setUpClass()
+        cls.client = cls.servers_client
+        cls.server_id = cls.rebuild_server(None)
+
+    @testtools.skipUnless(compute.CHANGE_PASSWORD_AVAILABLE,
+                          'Change password not available.')
+    @attr(type='gate')
+    def test_change_server_password(self):
+        # The server's password should be set to the provided password
+        new_password = 'Newpass1234'
+        resp, body = self.client.change_password(self.server_id, new_password)
+        self.assertEqual(202, resp.status)
+        self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+
+        if self.run_ssh:
+            # Verify that the user can authenticate with the new password
+            resp, server = self.client.get_server(self.server_id)
+            linux_client = RemoteClient(server, self.ssh_user, new_password)
+            self.assertTrue(linux_client.can_authenticate())
+
+    @attr(type='smoke')
+    def test_reboot_server_hard(self):
+        # The server should be power cycled
+        if self.run_ssh:
+            # Get the time the server was last rebooted,
+            resp, server = self.client.get_server(self.server_id)
+            linux_client = RemoteClient(server, self.ssh_user, self.password)
+            boot_time = linux_client.get_boot_time()
+
+        resp, body = self.client.reboot(self.server_id, 'HARD')
+        self.assertEqual(202, resp.status)
+        self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+
+        if self.run_ssh:
+            # Log in and verify the boot time has changed
+            linux_client = RemoteClient(server, self.ssh_user, self.password)
+            new_boot_time = linux_client.get_boot_time()
+            self.assertGreater(new_boot_time, boot_time)
+
+    @skip_because(bug="1014647")
+    @attr(type='smoke')
+    def test_reboot_server_soft(self):
+        # The server should be signaled to reboot gracefully
+        if self.run_ssh:
+            # Get the time the server was last rebooted,
+            resp, server = self.client.get_server(self.server_id)
+            linux_client = RemoteClient(server, self.ssh_user, self.password)
+            boot_time = linux_client.get_boot_time()
+
+        resp, body = self.client.reboot(self.server_id, 'SOFT')
+        self.assertEqual(202, resp.status)
+        self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+
+        if self.run_ssh:
+            # Log in and verify the boot time has changed
+            linux_client = RemoteClient(server, self.ssh_user, self.password)
+            new_boot_time = linux_client.get_boot_time()
+            self.assertGreater(new_boot_time, boot_time)
+
+    @attr(type='smoke')
+    def test_rebuild_server(self):
+        # The server should be rebuilt using the provided image and data
+        meta = {'rebuild': 'server'}
+        new_name = data_utils.rand_name('server')
+        file_contents = 'Test server rebuild.'
+        personality = [{'path': 'rebuild.txt',
+                       'contents': base64.b64encode(file_contents)}]
+        password = 'rebuildPassw0rd'
+        resp, rebuilt_server = self.client.rebuild(self.server_id,
+                                                   self.image_ref_alt,
+                                                   name=new_name,
+                                                   metadata=meta,
+                                                   personality=personality,
+                                                   admin_password=password)
+
+        # Verify the properties in the initial response are correct
+        self.assertEqual(self.server_id, rebuilt_server['id'])
+        rebuilt_image_id = rebuilt_server['image']['id']
+        self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
+        self.assertEqual(self.flavor_ref, rebuilt_server['flavor']['id'])
+
+        # Verify the server properties after the rebuild completes
+        self.client.wait_for_server_status(rebuilt_server['id'], 'ACTIVE')
+        resp, server = self.client.get_server(rebuilt_server['id'])
+        rebuilt_image_id = rebuilt_server['image']['id']
+        self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
+        self.assertEqual(new_name, rebuilt_server['name'])
+
+        if self.run_ssh:
+            # Verify that the user can authenticate with the provided password
+            linux_client = RemoteClient(server, self.ssh_user, password)
+            self.assertTrue(linux_client.can_authenticate())
+
+    def _detect_server_image_flavor(self, server_id):
+        # Detects the current server image flavor ref.
+        resp, server = self.client.get_server(self.server_id)
+        current_flavor = server['flavor']['id']
+        new_flavor_ref = self.flavor_ref_alt \
+            if current_flavor == self.flavor_ref else self.flavor_ref
+        return current_flavor, new_flavor_ref
+
+    @testtools.skipIf(not resize_available, 'Resize not available.')
+    @attr(type='smoke')
+    def test_resize_server_confirm(self):
+        # The server's RAM and disk space should be modified to that of
+        # the provided flavor
+
+        previous_flavor_ref, new_flavor_ref = \
+            self._detect_server_image_flavor(self.server_id)
+
+        resp, server = self.client.resize(self.server_id, new_flavor_ref)
+        self.assertEqual(202, resp.status)
+        self.client.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
+
+        self.client.confirm_resize(self.server_id)
+        self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+
+        resp, server = self.client.get_server(self.server_id)
+        self.assertEqual(new_flavor_ref, server['flavor']['id'])
+
+    @testtools.skipIf(not resize_available, 'Resize not available.')
+    @attr(type='gate')
+    def test_resize_server_revert(self):
+        # The server's RAM and disk space should return to its original
+        # values after a resize is reverted
+
+        previous_flavor_ref, new_flavor_ref = \
+            self._detect_server_image_flavor(self.server_id)
+
+        resp, server = self.client.resize(self.server_id, new_flavor_ref)
+        self.assertEqual(202, resp.status)
+        self.client.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
+
+        self.client.revert_resize(self.server_id)
+        self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+
+        # Need to poll for the id change until lp#924371 is fixed
+        resp, server = self.client.get_server(self.server_id)
+        start = int(time.time())
+
+        while server['flavor']['id'] != previous_flavor_ref:
+            time.sleep(self.build_interval)
+            resp, server = self.client.get_server(self.server_id)
+
+            if int(time.time()) - start >= self.build_timeout:
+                message = 'Server %s failed to revert resize within the \
+                required time (%s s).' % (self.server_id, self.build_timeout)
+                raise exceptions.TimeoutException(message)
+
+    @attr(type='gate')
+    def test_get_console_output(self):
+        # Positive test:Should be able to GET the console output
+        # for a given server_id and number of lines
+        def get_output():
+            resp, output = self.servers_client.get_console_output(
+                self.server_id, 10)
+            self.assertEqual(200, resp.status)
+            self.assertTrue(output, "Console output was empty.")
+            lines = len(output.split('\n'))
+            self.assertEqual(lines, 10)
+        self.wait_for(get_output)
+
+    @skip_because(bug="1014683")
+    @attr(type='gate')
+    def test_get_console_output_server_id_in_reboot_status(self):
+        # Positive test:Should be able to GET the console output
+        # for a given server_id in reboot status
+        resp, output = self.servers_client.reboot(self.server_id, 'SOFT')
+        self.servers_client.wait_for_server_status(self.server_id,
+                                                   'REBOOT')
+        resp, output = self.servers_client.get_console_output(self.server_id,
+                                                              10)
+        self.assertEqual(200, resp.status)
+        self.assertIsNotNone(output)
+        lines = len(output.split('\n'))
+        self.assertEqual(lines, 10)
+
+    @attr(type='gate')
+    def test_pause_unpause_server(self):
+        resp, server = self.client.pause_server(self.server_id)
+        self.assertEqual(202, resp.status)
+        self.client.wait_for_server_status(self.server_id, 'PAUSED')
+        resp, server = self.client.unpause_server(self.server_id)
+        self.assertEqual(202, resp.status)
+        self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+
+    @attr(type='gate')
+    def test_suspend_resume_server(self):
+        resp, server = self.client.suspend_server(self.server_id)
+        self.assertEqual(202, resp.status)
+        self.client.wait_for_server_status(self.server_id, 'SUSPENDED')
+        resp, server = self.client.resume_server(self.server_id)
+        self.assertEqual(202, resp.status)
+        self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+
+    @attr(type='gate')
+    def test_stop_start_server(self):
+        resp, server = self.servers_client.stop(self.server_id)
+        self.assertEqual(202, resp.status)
+        self.servers_client.wait_for_server_status(self.server_id, 'SHUTOFF')
+        resp, server = self.servers_client.start(self.server_id)
+        self.assertEqual(202, resp.status)
+        self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
+
+    @attr(type='gate')
+    def test_lock_unlock_server(self):
+        # Lock the server,try server stop(exceptions throw),unlock it and retry
+        resp, server = self.servers_client.lock_server(self.server_id)
+        self.assertEqual(202, resp.status)
+        resp, server = self.servers_client.get_server(self.server_id)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(server['status'], 'ACTIVE')
+        # Locked server is not allowed to be stopped by non-admin user
+        self.assertRaises(exceptions.Conflict,
+                          self.servers_client.stop, self.server_id)
+        resp, server = self.servers_client.unlock_server(self.server_id)
+        self.assertEqual(202, resp.status)
+        resp, server = self.servers_client.stop(self.server_id)
+        self.assertEqual(202, resp.status)
+        self.servers_client.wait_for_server_status(self.server_id, 'SHUTOFF')
+        resp, server = self.servers_client.start(self.server_id)
+        self.assertEqual(202, resp.status)
+        self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
+
+
+class ServerActionsV3TestXML(ServerActionsV3TestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/servers/test_server_addresses.py b/tempest/api/compute/v3/servers/test_server_addresses.py
new file mode 100644
index 0000000..82588b6
--- /dev/null
+++ b/tempest/api/compute/v3/servers/test_server_addresses.py
@@ -0,0 +1,84 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.compute import base
+from tempest import exceptions
+from tempest.test import attr
+
+
+class ServerAddressesV3Test(base.BaseV3ComputeTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(ServerAddressesV3Test, cls).setUpClass()
+        cls.client = cls.servers_client
+
+        resp, cls.server = cls.create_test_server(wait_until='ACTIVE')
+
+    @attr(type=['negative', 'gate'])
+    def test_list_server_addresses_invalid_server_id(self):
+        # List addresses request should fail if server id not in system
+        self.assertRaises(exceptions.NotFound, self.client.list_addresses,
+                          '999')
+
+    @attr(type=['negative', 'gate'])
+    def test_list_server_addresses_by_network_neg(self):
+        # List addresses by network should fail if network name not valid
+        self.assertRaises(exceptions.NotFound,
+                          self.client.list_addresses_by_network,
+                          self.server['id'], 'invalid')
+
+    @attr(type='smoke')
+    def test_list_server_addresses(self):
+        # All public and private addresses for
+        # a server should be returned
+
+        resp, addresses = self.client.list_addresses(self.server['id'])
+        self.assertEqual('200', resp['status'])
+
+        # We do not know the exact network configuration, but an instance
+        # should at least have a single public or private address
+        self.assertTrue(len(addresses) >= 1)
+        for network_name, network_addresses in addresses.iteritems():
+            self.assertTrue(len(network_addresses) >= 1)
+            for address in network_addresses:
+                self.assertTrue(address['addr'])
+                self.assertTrue(address['version'])
+
+    @attr(type='smoke')
+    def test_list_server_addresses_by_network(self):
+        # Providing a network type should filter
+        # the addresses return by that type
+
+        resp, addresses = self.client.list_addresses(self.server['id'])
+
+        # Once again we don't know the environment's exact network config,
+        # but the response for each individual network should be the same
+        # as the partial result of the full address list
+        id = self.server['id']
+        for addr_type in addresses:
+            resp, addr = self.client.list_addresses_by_network(id, addr_type)
+            self.assertEqual('200', resp['status'])
+
+            addr = addr[addr_type]
+            for address in addresses[addr_type]:
+                self.assertTrue(any([a for a in addr if a == address]))
+
+
+class ServerAddressesV3TestXML(ServerAddressesV3Test):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/servers/test_server_metadata.py b/tempest/api/compute/v3/servers/test_server_metadata.py
new file mode 100644
index 0000000..ee0f4a9
--- /dev/null
+++ b/tempest/api/compute/v3/servers/test_server_metadata.py
@@ -0,0 +1,217 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.compute import base
+from tempest import exceptions
+from tempest.test import attr
+
+
+class ServerMetadataTestJSON(base.BaseV2ComputeTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(ServerMetadataTestJSON, cls).setUpClass()
+        cls.client = cls.servers_client
+        cls.quotas = cls.quotas_client
+        cls.admin_client = cls._get_identity_admin_client()
+        resp, tenants = cls.admin_client.list_tenants()
+        cls.tenant_id = [tnt['id'] for tnt in tenants if tnt['name'] ==
+                         cls.client.tenant_name][0]
+        resp, server = cls.create_test_server(meta={}, wait_until='ACTIVE')
+
+        cls.server_id = server['id']
+
+    def setUp(self):
+        super(ServerMetadataTestJSON, self).setUp()
+        meta = {'key1': 'value1', 'key2': 'value2'}
+        resp, _ = self.client.set_server_metadata(self.server_id, meta)
+        self.assertEqual(resp.status, 200)
+
+    @attr(type='gate')
+    def test_list_server_metadata(self):
+        # All metadata key/value pairs for a server should be returned
+        resp, resp_metadata = self.client.list_server_metadata(self.server_id)
+
+        # Verify the expected metadata items are in the list
+        self.assertEqual(200, resp.status)
+        expected = {'key1': 'value1', 'key2': 'value2'}
+        self.assertEqual(expected, resp_metadata)
+
+    @attr(type='gate')
+    def test_set_server_metadata(self):
+        # The server's metadata should be replaced with the provided values
+        # Create a new set of metadata for the server
+        req_metadata = {'meta2': 'data2', 'meta3': 'data3'}
+        resp, metadata = self.client.set_server_metadata(self.server_id,
+                                                         req_metadata)
+        self.assertEqual(200, resp.status)
+
+        # Verify the expected values are correct, and that the
+        # previous values have been removed
+        resp, resp_metadata = self.client.list_server_metadata(self.server_id)
+        self.assertEqual(resp_metadata, req_metadata)
+
+    @attr(type='gate')
+    def test_server_create_metadata_key_too_long(self):
+        # Attempt to start a server with a meta-data key that is > 255
+        # characters
+
+        # Try a few values
+        for sz in [256, 257, 511, 1023]:
+            key = "k" * sz
+            meta = {key: 'data1'}
+            self.assertRaises(exceptions.OverLimit,
+                              self.create_test_server,
+                              meta=meta)
+
+        # no teardown - all creates should fail
+
+    @attr(type='gate')
+    def test_update_server_metadata(self):
+        # The server's metadata values should be updated to the
+        # provided values
+        meta = {'key1': 'alt1', 'key3': 'value3'}
+        resp, metadata = self.client.update_server_metadata(self.server_id,
+                                                            meta)
+        self.assertEqual(200, resp.status)
+
+        # Verify the values have been updated to the proper values
+        resp, resp_metadata = self.client.list_server_metadata(self.server_id)
+        expected = {'key1': 'alt1', 'key2': 'value2', 'key3': 'value3'}
+        self.assertEqual(expected, resp_metadata)
+
+    @attr(type='gate')
+    def test_update_metadata_empty_body(self):
+        # The original metadata should not be lost if empty metadata body is
+        # passed
+        meta = {}
+        _, metadata = self.client.update_server_metadata(self.server_id, meta)
+        resp, resp_metadata = self.client.list_server_metadata(self.server_id)
+        expected = {'key1': 'value1', 'key2': 'value2'}
+        self.assertEqual(expected, resp_metadata)
+
+    @attr(type='gate')
+    def test_get_server_metadata_item(self):
+        # The value for a specific metadata key should be returned
+        resp, meta = self.client.get_server_metadata_item(self.server_id,
+                                                          'key2')
+        self.assertEqual('value2', meta['key2'])
+
+    @attr(type='gate')
+    def test_set_server_metadata_item(self):
+        # The item's value should be updated to the provided value
+        # Update the metadata value
+        meta = {'nova': 'alt'}
+        resp, body = self.client.set_server_metadata_item(self.server_id,
+                                                          'nova', meta)
+        self.assertEqual(200, resp.status)
+
+        # Verify the meta item's value has been updated
+        resp, resp_metadata = self.client.list_server_metadata(self.server_id)
+        expected = {'key1': 'value1', 'key2': 'value2', 'nova': 'alt'}
+        self.assertEqual(expected, resp_metadata)
+
+    @attr(type='gate')
+    def test_delete_server_metadata_item(self):
+        # The metadata value/key pair should be deleted from the server
+        resp, meta = self.client.delete_server_metadata_item(self.server_id,
+                                                             'key1')
+        self.assertEqual(204, resp.status)
+
+        # Verify the metadata item has been removed
+        resp, resp_metadata = self.client.list_server_metadata(self.server_id)
+        expected = {'key2': 'value2'}
+        self.assertEqual(expected, resp_metadata)
+
+    @attr(type=['negative', 'gate'])
+    def test_server_metadata_negative(self):
+        # Blank key should trigger an error.
+        meta = {'': 'data1'}
+        self.assertRaises(exceptions.BadRequest,
+                          self.create_test_server,
+                          meta=meta)
+
+        # GET on a non-existent server should not succeed
+        self.assertRaises(exceptions.NotFound,
+                          self.client.get_server_metadata_item, 999, 'test2')
+
+        # List metadata on a non-existent server should not succeed
+        self.assertRaises(exceptions.NotFound,
+                          self.client.list_server_metadata, 999)
+
+        # Raise BadRequest if key in uri does not match
+        # the key passed in body.
+        meta = {'testkey': 'testvalue'}
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.set_server_metadata_item,
+                          self.server_id, 'key', meta)
+
+        # Set metadata on a non-existent server should not succeed
+        meta = {'meta1': 'data1'}
+        self.assertRaises(exceptions.NotFound,
+                          self.client.set_server_metadata, 999, meta)
+
+        # An update should not happen for a non-existent image
+        meta = {'key1': 'value1', 'key2': 'value2'}
+        self.assertRaises(exceptions.NotFound,
+                          self.client.update_server_metadata, 999, meta)
+
+        # Blank key should trigger an error
+        meta = {'': 'data1'}
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.update_server_metadata,
+                          self.server_id, meta=meta)
+
+        # Should not be able to delete metadata item from a non-existent server
+        self.assertRaises(exceptions.NotFound,
+                          self.client.delete_server_metadata_item, 999, 'd')
+
+        # Raise a 413 OverLimit exception while exceeding metadata items limit
+        # for tenant.
+        _, quota_set = self.quotas.get_quota_set(self.tenant_id)
+        quota_metadata = quota_set['metadata_items']
+        req_metadata = {}
+        for num in range(1, quota_metadata + 2):
+            req_metadata['key' + str(num)] = 'val' + str(num)
+        self.assertRaises(exceptions.OverLimit,
+                          self.client.set_server_metadata,
+                          self.server_id, req_metadata)
+
+        # Raise a 413 OverLimit exception while exceeding metadata items limit
+        # for tenant (update).
+        self.assertRaises(exceptions.OverLimit,
+                          self.client.update_server_metadata,
+                          self.server_id, req_metadata)
+
+        # Raise a bad request error for blank key.
+        # set_server_metadata will replace all metadata with new value
+        meta = {'': 'data1'}
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.set_server_metadata,
+                          self.server_id, meta=meta)
+
+        # Raise a bad request error for a missing metadata field
+        # set_server_metadata will replace all metadata with new value
+        meta = {'meta1': 'data1'}
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.set_server_metadata,
+                          self.server_id, meta=meta, no_metadata_field=True)
+
+
+class ServerMetadataTestXML(ServerMetadataTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/servers/test_server_personality.py b/tempest/api/compute/v3/servers/test_server_personality.py
new file mode 100644
index 0000000..c6d2e44
--- /dev/null
+++ b/tempest/api/compute/v3/servers/test_server_personality.py
@@ -0,0 +1,68 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import base64
+
+from tempest.api.compute import base
+from tempest import exceptions
+from tempest.test import attr
+
+
+class ServerPersonalityTestJSON(base.BaseV2ComputeTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(ServerPersonalityTestJSON, cls).setUpClass()
+        cls.client = cls.servers_client
+        cls.user_client = cls.limits_client
+
+    @attr(type='gate')
+    def test_personality_files_exceed_limit(self):
+        # Server creation should fail if greater than the maximum allowed
+        # number of files are injected into the server.
+        file_contents = 'This is a test file.'
+        personality = []
+        max_file_limit = \
+            self.user_client.get_specific_absolute_limit("maxPersonality")
+        for i in range(0, int(max_file_limit) + 1):
+            path = 'etc/test' + str(i) + '.txt'
+            personality.append({'path': path,
+                                'contents': base64.b64encode(file_contents)})
+        self.assertRaises(exceptions.OverLimit, self.create_test_server,
+                          personality=personality)
+
+    @attr(type='gate')
+    def test_can_create_server_with_max_number_personality_files(self):
+        # Server should be created successfully if maximum allowed number of
+        # files is injected into the server during creation.
+        file_contents = 'This is a test file.'
+        max_file_limit = \
+            self.user_client.get_specific_absolute_limit("maxPersonality")
+        person = []
+        for i in range(0, int(max_file_limit)):
+            path = 'etc/test' + str(i) + '.txt'
+            person.append({
+                'path': path,
+                'contents': base64.b64encode(file_contents),
+            })
+        resp, server = self.create_test_server(personality=person)
+        self.assertEqual('202', resp['status'])
+
+
+class ServerPersonalityTestXML(ServerPersonalityTestJSON):
+    _interface = "xml"
diff --git a/tempest/api/compute/v3/servers/test_server_rescue.py b/tempest/api/compute/v3/servers/test_server_rescue.py
new file mode 100644
index 0000000..eebd4d8
--- /dev/null
+++ b/tempest/api/compute/v3/servers/test_server_rescue.py
@@ -0,0 +1,173 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 Hewlett-Packard Development Company, L.P.
+# 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 tempest.api.compute import base
+from tempest import exceptions
+from tempest.test import attr
+
+
+class ServerRescueV3TestJSON(base.BaseV3ComputeTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(ServerRescueV3TestJSON, cls).setUpClass()
+        cls.device = 'vdf'
+
+        # Create a volume and wait for it to become ready for attach
+        resp, cls.volume_to_attach = \
+            cls.volumes_client.create_volume(1,
+                                             display_name=
+                                             'test_attach')
+        cls.volumes_client.wait_for_volume_status(
+            cls.volume_to_attach['id'], 'available')
+
+        # Create a volume and wait for it to become ready for attach
+        resp, cls.volume_to_detach = \
+            cls.volumes_client.create_volume(1,
+                                             display_name=
+                                             'test_detach')
+        cls.volumes_client.wait_for_volume_status(
+            cls.volume_to_detach['id'], 'available')
+
+        # Server for positive tests
+        resp, server = cls.create_test_server(wait_until='BUILD')
+        resp, resc_server = cls.create_test_server(wait_until='ACTIVE')
+        cls.server_id = server['id']
+        cls.password = server['admin_password']
+        cls.servers_client.wait_for_server_status(cls.server_id, 'ACTIVE')
+
+        # Server for negative tests
+        cls.rescue_id = resc_server['id']
+        cls.rescue_password = resc_server['admin_password']
+
+        cls.servers_client.rescue_server(
+            cls.rescue_id, cls.rescue_password)
+        cls.servers_client.wait_for_server_status(cls.rescue_id, 'RESCUE')
+
+    def setUp(self):
+        super(ServerRescueV3TestJSON, self).setUp()
+
+    @classmethod
+    def tearDownClass(cls):
+        client = cls.volumes_client
+        client.delete_volume(str(cls.volume_to_attach['id']).strip())
+        client.delete_volume(str(cls.volume_to_detach['id']).strip())
+        super(ServerRescueV3TestJSON, cls).tearDownClass()
+
+    def tearDown(self):
+        super(ServerRescueV3TestJSON, self).tearDown()
+
+    def _detach(self, server_id, volume_id):
+        self.servers_client.detach_volume(server_id, volume_id)
+        self.volumes_client.wait_for_volume_status(volume_id,
+                                                   'available')
+
+    def _delete(self, volume_id):
+        self.volumes_client.delete_volume(volume_id)
+
+    def _unrescue(self, server_id):
+        resp, body = self.servers_client.unrescue_server(server_id)
+        self.assertEqual(202, resp.status)
+        self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
+
+    def _unpause(self, server_id):
+        resp, body = self.servers_client.unpause_server(server_id)
+        self.assertEqual(202, resp.status)
+        self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
+
+    @attr(type='smoke')
+    def test_rescue_unrescue_instance(self):
+        resp, body = self.servers_client.rescue_server(
+            self.server_id, self.password)
+        self.assertEqual(202, resp.status)
+        self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
+        resp, body = self.servers_client.unrescue_server(self.server_id)
+        self.assertEqual(202, resp.status)
+        self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
+
+    @attr(type=['negative', 'gate'])
+    def test_rescue_paused_instance(self):
+        # Rescue a paused server
+        resp, body = self.servers_client.pause_server(
+            self.server_id)
+        self.addCleanup(self._unpause, self.server_id)
+        self.assertEqual(202, resp.status)
+        self.servers_client.wait_for_server_status(self.server_id, 'PAUSED')
+        self.assertRaises(exceptions.Conflict,
+                          self.servers_client.rescue_server,
+                          self.server_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_rescued_vm_reboot(self):
+        self.assertRaises(exceptions.Conflict, self.servers_client.reboot,
+                          self.rescue_id, 'HARD')
+
+    @attr(type=['negative', 'gate'])
+    def test_rescue_non_existent_server(self):
+        # Rescue a non-existing server
+        self.assertRaises(exceptions.NotFound,
+                          self.servers_client.rescue_server,
+                          '999erra43')
+
+    @attr(type=['negative', 'gate'])
+    def test_rescued_vm_rebuild(self):
+        self.assertRaises(exceptions.Conflict,
+                          self.servers_client.rebuild,
+                          self.rescue_id,
+                          self.image_ref_alt)
+
+    @attr(type=['negative', 'gate'])
+    def test_rescued_vm_attach_volume(self):
+        # Rescue the server
+        self.servers_client.rescue_server(self.server_id, self.password)
+        self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
+        self.addCleanup(self._unrescue, self.server_id)
+
+        # Attach the volume to the server
+        self.assertRaises(exceptions.Conflict,
+                          self.servers_client.attach_volume,
+                          self.server_id,
+                          self.volume_to_attach['id'],
+                          device='/dev/%s' % self.device)
+
+    @attr(type=['negative', 'gate'])
+    def test_rescued_vm_detach_volume(self):
+        # Attach the volume to the server
+        self.servers_client.attach_volume(self.server_id,
+                                          self.volume_to_detach['id'],
+                                          device='/dev/%s' % self.device)
+        self.volumes_client.wait_for_volume_status(
+            self.volume_to_detach['id'], 'in-use')
+
+        # Rescue the server
+        self.servers_client.rescue_server(self.server_id, self.password)
+        self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
+        # addCleanup is a LIFO queue
+        self.addCleanup(self._detach, self.server_id,
+                        self.volume_to_detach['id'])
+        self.addCleanup(self._unrescue, self.server_id)
+
+        # Detach the volume from the server expecting failure
+        self.assertRaises(exceptions.Conflict,
+                          self.servers_client.detach_volume,
+                          self.server_id,
+                          self.volume_to_detach['id'])
+
+
+class ServerRescueV3TestXML(ServerRescueV3TestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/servers/test_servers.py b/tempest/api/compute/v3/servers/test_servers.py
new file mode 100644
index 0000000..d72476d
--- /dev/null
+++ b/tempest/api/compute/v3/servers/test_servers.py
@@ -0,0 +1,133 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest.test import attr
+
+
+class ServersTestJSON(base.BaseV2ComputeTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(ServersTestJSON, cls).setUpClass()
+        cls.client = cls.servers_client
+
+    def tearDown(self):
+        self.clear_servers()
+        super(ServersTestJSON, self).tearDown()
+
+    @attr(type='gate')
+    def test_create_server_with_admin_password(self):
+        # If an admin password is provided on server creation, the server's
+        # root password should be set to that password.
+        resp, server = self.create_test_server(adminPass='testpassword')
+
+        # Verify the password is set correctly in the response
+        self.assertEqual('testpassword', server['adminPass'])
+
+    @attr(type='gate')
+    def test_create_with_existing_server_name(self):
+        # Creating a server with a name that already exists is allowed
+
+        # TODO(sdague): clear out try, we do cleanup one layer up
+        server_name = data_utils.rand_name('server')
+        resp, server = self.create_test_server(name=server_name,
+                                               wait_until='ACTIVE')
+        id1 = server['id']
+        resp, server = self.create_test_server(name=server_name,
+                                               wait_until='ACTIVE')
+        id2 = server['id']
+        self.assertNotEqual(id1, id2, "Did not create a new server")
+        resp, server = self.client.get_server(id1)
+        name1 = server['name']
+        resp, server = self.client.get_server(id2)
+        name2 = server['name']
+        self.assertEqual(name1, name2)
+
+    @attr(type='gate')
+    def test_create_specify_keypair(self):
+        # Specify a keypair while creating a server
+
+        key_name = data_utils.rand_name('key')
+        resp, keypair = self.keypairs_client.create_keypair(key_name)
+        resp, body = self.keypairs_client.list_keypairs()
+        resp, server = self.create_test_server(key_name=key_name)
+        self.assertEqual('202', resp['status'])
+        self.client.wait_for_server_status(server['id'], 'ACTIVE')
+        resp, server = self.client.get_server(server['id'])
+        self.assertEqual(key_name, server['key_name'])
+
+    @attr(type='gate')
+    def test_update_server_name(self):
+        # The server name should be changed to the the provided value
+        resp, server = self.create_test_server(wait_until='ACTIVE')
+
+        # Update the server with a new name
+        resp, server = self.client.update_server(server['id'],
+                                                 name='newname')
+        self.assertEqual(200, resp.status)
+        self.client.wait_for_server_status(server['id'], 'ACTIVE')
+
+        # Verify the name of the server has changed
+        resp, server = self.client.get_server(server['id'])
+        self.assertEqual('newname', server['name'])
+
+    @attr(type='gate')
+    def test_update_access_server_address(self):
+        # The server's access addresses should reflect the provided values
+        resp, server = self.create_test_server(wait_until='ACTIVE')
+
+        # Update the IPv4 and IPv6 access addresses
+        resp, body = self.client.update_server(server['id'],
+                                               accessIPv4='1.1.1.1',
+                                               accessIPv6='::babe:202:202')
+        self.assertEqual(200, resp.status)
+        self.client.wait_for_server_status(server['id'], 'ACTIVE')
+
+        # Verify the access addresses have been updated
+        resp, server = self.client.get_server(server['id'])
+        self.assertEqual('1.1.1.1', server['accessIPv4'])
+        self.assertEqual('::babe:202:202', server['accessIPv6'])
+
+    @attr(type='gate')
+    def test_delete_server_while_in_building_state(self):
+        # Delete a server while it's VM state is Building
+        resp, server = self.create_test_server(wait_until='BUILD')
+        resp, _ = self.client.delete_server(server['id'])
+        self.assertEqual('204', resp['status'])
+
+    @attr(type='gate')
+    def test_delete_active_server(self):
+        # Delete a server while it's VM state is Active
+        resp, server = self.create_test_server(wait_until='ACTIVE')
+        resp, _ = self.client.delete_server(server['id'])
+        self.assertEqual('204', resp['status'])
+
+    @attr(type='gate')
+    def test_create_server_with_ipv6_addr_only(self):
+        # Create a server without an IPv4 address(only IPv6 address).
+        resp, server = self.create_test_server(accessIPv6='2001:2001::3')
+        self.assertEqual('202', resp['status'])
+        self.client.wait_for_server_status(server['id'], 'ACTIVE')
+        resp, server = self.client.get_server(server['id'])
+        self.assertEqual('2001:2001::3', server['accessIPv6'])
+
+
+class ServersTestXML(ServersTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/servers/test_servers_negative.py b/tempest/api/compute/v3/servers/test_servers_negative.py
new file mode 100644
index 0000000..8142250
--- /dev/null
+++ b/tempest/api/compute/v3/servers/test_servers_negative.py
@@ -0,0 +1,449 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import base64
+import sys
+import uuid
+
+from tempest.api.compute import base
+from tempest import clients
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest.test import attr
+
+
+class ServersNegativeTestJSON(base.BaseV2ComputeTest):
+    _interface = 'json'
+
+    def setUp(self):
+        super(ServersNegativeTestJSON, self).setUp()
+        try:
+            self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+        except Exception:
+            self.__class__.server_id = self.rebuild_server(self.server_id)
+
+    @classmethod
+    def setUpClass(cls):
+        super(ServersNegativeTestJSON, cls).setUpClass()
+        cls.client = cls.servers_client
+        cls.img_client = cls.images_client
+        cls.alt_os = clients.AltManager()
+        cls.alt_client = cls.alt_os.servers_client
+        resp, server = cls.create_test_server(wait_until='ACTIVE')
+        cls.server_id = server['id']
+
+    @attr(type=['negative', 'gate'])
+    def test_server_name_blank(self):
+        # Create a server with name parameter empty
+
+        self.assertRaises(exceptions.BadRequest,
+                          self.create_test_server,
+                          name='')
+
+    @attr(type=['negative', 'gate'])
+    def test_personality_file_contents_not_encoded(self):
+        # Use an unencoded file when creating a server with personality
+
+        file_contents = 'This is a test file.'
+        person = [{'path': '/etc/testfile.txt',
+                   'contents': file_contents}]
+
+        self.assertRaises(exceptions.BadRequest,
+                          self.create_test_server,
+                          personality=person)
+
+    @attr(type=['negative', 'gate'])
+    def test_create_with_invalid_image(self):
+        # Create a server with an unknown image
+
+        self.assertRaises(exceptions.BadRequest,
+                          self.create_test_server,
+                          image_id=-1)
+
+    @attr(type=['negative', 'gate'])
+    def test_create_with_invalid_flavor(self):
+        # Create a server with an unknown flavor
+
+        self.assertRaises(exceptions.BadRequest,
+                          self.create_test_server,
+                          flavor=-1,)
+
+    @attr(type=['negative', 'gate'])
+    def test_invalid_access_ip_v4_address(self):
+        # An access IPv4 address must match a valid address pattern
+
+        IPv4 = '1.1.1.1.1.1'
+        self.assertRaises(exceptions.BadRequest,
+                          self.create_test_server, accessIPv4=IPv4)
+
+    @attr(type=['negative', 'gate'])
+    def test_invalid_ip_v6_address(self):
+        # An access IPv6 address must match a valid address pattern
+
+        IPv6 = 'notvalid'
+
+        self.assertRaises(exceptions.BadRequest,
+                          self.create_test_server, accessIPv6=IPv6)
+
+    @attr(type=['negative', 'gate'])
+    def test_resize_nonexistent_server(self):
+        nonexistent_server = str(uuid.uuid4())
+        self.assertRaises(exceptions.NotFound,
+                          self.client.resize,
+                          nonexistent_server, self.flavor_ref)
+
+    @attr(type=['negative', 'gate'])
+    def test_resize_server_with_non_existent_flavor(self):
+        # Resize a server with non-existent flavor
+        nonexistent_flavor = str(uuid.uuid4())
+        self.assertRaises(exceptions.BadRequest, self.client.resize,
+                          self.server_id, flavor_ref=nonexistent_flavor)
+
+    @attr(type=['negative', 'gate'])
+    def test_resize_server_with_null_flavor(self):
+        # Resize a server with null flavor
+        self.assertRaises(exceptions.BadRequest, self.client.resize,
+                          self.server_id, flavor_ref="")
+
+    @attr(type=['negative', 'gate'])
+    def test_reboot_non_existent_server(self):
+        # Reboot a non existent server
+        nonexistent_server = str(uuid.uuid4())
+        self.assertRaises(exceptions.NotFound, self.client.reboot,
+                          nonexistent_server, 'SOFT')
+
+    @attr(type=['negative', 'gate'])
+    def test_pause_paused_server(self):
+        # Pause a paused server.
+        self.client.pause_server(self.server_id)
+        self.addCleanup(self.client.unpause_server,
+                        self.server_id)
+        self.client.wait_for_server_status(self.server_id, 'PAUSED')
+        self.assertRaises(exceptions.Conflict,
+                          self.client.pause_server,
+                          self.server_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_rebuild_reboot_deleted_server(self):
+        # Rebuild and Reboot a deleted server
+        _, server = self.create_test_server()
+        self.client.delete_server(server['id'])
+        self.client.wait_for_server_termination(server['id'])
+
+        self.assertRaises(exceptions.NotFound,
+                          self.client.rebuild,
+                          server['id'], self.image_ref_alt)
+        self.assertRaises(exceptions.NotFound, self.client.reboot,
+                          server['id'], 'SOFT')
+
+    @attr(type=['negative', 'gate'])
+    def test_rebuild_non_existent_server(self):
+        # Rebuild a non existent server
+        nonexistent_server = str(uuid.uuid4())
+        meta = {'rebuild': 'server'}
+        new_name = data_utils.rand_name('server')
+        file_contents = 'Test server rebuild.'
+        personality = [{'path': '/etc/rebuild.txt',
+                        'contents': base64.b64encode(file_contents)}]
+        self.assertRaises(exceptions.NotFound,
+                          self.client.rebuild,
+                          nonexistent_server,
+                          self.image_ref_alt,
+                          name=new_name, meta=meta,
+                          personality=personality,
+                          adminPass='rebuild')
+
+    @attr(type=['negative', 'gate'])
+    def test_create_numeric_server_name(self):
+        # Create a server with a numeric name
+        if self.__class__._interface == "xml":
+            raise self.skipException("Not testable in XML")
+
+        server_name = 12345
+        self.assertRaises(exceptions.BadRequest,
+                          self.create_test_server,
+                          name=server_name)
+
+    @attr(type=['negative', 'gate'])
+    def test_create_server_name_length_exceeds_256(self):
+        # Create a server with name length exceeding 256 characters
+
+        server_name = 'a' * 256
+        self.assertRaises(exceptions.BadRequest,
+                          self.create_test_server,
+                          name=server_name)
+
+    @attr(type=['negative', 'gate'])
+    def test_create_with_invalid_network_uuid(self):
+        # Pass invalid network uuid while creating a server
+
+        networks = [{'fixed_ip': '10.0.1.1', 'uuid': 'a-b-c-d-e-f-g-h-i-j'}]
+
+        self.assertRaises(exceptions.BadRequest,
+                          self.create_test_server,
+                          networks=networks)
+
+    @attr(type=['negative', 'gate'])
+    def test_create_with_non_existant_keypair(self):
+        # Pass a non-existent keypair while creating a server
+
+        key_name = data_utils.rand_name('key')
+        self.assertRaises(exceptions.BadRequest,
+                          self.create_test_server,
+                          key_name=key_name)
+
+    @attr(type=['negative', 'gate'])
+    def test_create_server_metadata_exceeds_length_limit(self):
+        # Pass really long metadata while creating a server
+
+        metadata = {'a': 'b' * 260}
+        self.assertRaises(exceptions.OverLimit,
+                          self.create_test_server,
+                          meta=metadata)
+
+    @attr(type=['negative', 'gate'])
+    def test_update_name_of_non_existent_server(self):
+        # Update name of a non-existent server
+
+        server_name = data_utils.rand_name('server')
+        new_name = data_utils.rand_name('server') + '_updated'
+
+        self.assertRaises(exceptions.NotFound, self.client.update_server,
+                          server_name, name=new_name)
+
+    @attr(type=['negative', 'gate'])
+    def test_update_server_set_empty_name(self):
+        # Update name of the server to an empty string
+
+        server_name = data_utils.rand_name('server')
+        new_name = ''
+
+        self.assertRaises(exceptions.BadRequest, self.client.update_server,
+                          server_name, name=new_name)
+
+    @attr(type=['negative', 'gate'])
+    def test_update_server_of_another_tenant(self):
+        # Update name of a server that belongs to another tenant
+
+        new_name = self.server_id + '_new'
+        self.assertRaises(exceptions.NotFound,
+                          self.alt_client.update_server, self.server_id,
+                          name=new_name)
+
+    @attr(type=['negative', 'gate'])
+    def test_update_server_name_length_exceeds_256(self):
+        # Update name of server exceed the name length limit
+
+        new_name = 'a' * 256
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.update_server,
+                          self.server_id,
+                          name=new_name)
+
+    @attr(type=['negative', 'gate'])
+    def test_delete_non_existent_server(self):
+        # Delete a non existent server
+
+        self.assertRaises(exceptions.NotFound, self.client.delete_server,
+                          '999erra43')
+
+    @attr(type=['negative', 'gate'])
+    def test_delete_a_server_of_another_tenant(self):
+        # Delete a server that belongs to another tenant
+        self.assertRaises(exceptions.NotFound,
+                          self.alt_client.delete_server,
+                          self.server_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_delete_server_pass_negative_id(self):
+        # Pass an invalid string parameter to delete server
+
+        self.assertRaises(exceptions.NotFound, self.client.delete_server, -1)
+
+    @attr(type=['negative', 'gate'])
+    def test_delete_server_pass_id_exceeding_length_limit(self):
+        # Pass a server ID that exceeds length limit to delete server
+
+        self.assertRaises(exceptions.NotFound, self.client.delete_server,
+                          sys.maxint + 1)
+
+    @attr(type=['negative', 'gate'])
+    def test_create_with_nonexistent_security_group(self):
+        # Create a server with a nonexistent security group
+
+        security_groups = [{'name': 'does_not_exist'}]
+        self.assertRaises(exceptions.BadRequest,
+                          self.create_test_server,
+                          security_groups=security_groups)
+
+    @attr(type=['negative', 'gate'])
+    def test_get_non_existent_server(self):
+        # Get a non existent server details
+
+        self.assertRaises(exceptions.NotFound, self.client.get_server,
+                          '999erra43')
+
+    @attr(type=['negative', 'gate'])
+    def test_stop_non_existent_server(self):
+        # Stop a non existent server
+        nonexistent_server = str(uuid.uuid4())
+        self.assertRaises(exceptions.NotFound, self.servers_client.stop,
+                          nonexistent_server)
+
+    @attr(type=['negative', 'gate'])
+    def test_pause_non_existent_server(self):
+        # pause a non existent server
+        nonexistent_server = str(uuid.uuid4())
+        self.assertRaises(exceptions.NotFound, self.client.pause_server,
+                          nonexistent_server)
+
+    @attr(type=['negative', 'gate'])
+    def test_unpause_non_existent_server(self):
+        # unpause a non existent server
+        nonexistent_server = str(uuid.uuid4())
+        self.assertRaises(exceptions.NotFound, self.client.unpause_server,
+                          nonexistent_server)
+
+    @attr(type=['negative', 'gate'])
+    def test_unpause_server_invalid_state(self):
+        # unpause an active server.
+        self.assertRaises(exceptions.Conflict,
+                          self.client.unpause_server,
+                          self.server_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_suspend_non_existent_server(self):
+        # suspend a non existent server
+        nonexistent_server = str(uuid.uuid4())
+        self.assertRaises(exceptions.NotFound, self.client.suspend_server,
+                          nonexistent_server)
+
+    @attr(type=['negative', 'gate'])
+    def test_suspend_server_invalid_state(self):
+        # suspend a suspended server.
+        resp, _ = self.client.suspend_server(self.server_id)
+        self.addCleanup(self.client.resume_server,
+                        self.server_id)
+        self.assertEqual(202, resp.status)
+        self.client.wait_for_server_status(self.server_id, 'SUSPENDED')
+        self.assertRaises(exceptions.Conflict,
+                          self.client.suspend_server,
+                          self.server_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_resume_non_existent_server(self):
+        # resume a non existent server
+        nonexistent_server = str(uuid.uuid4())
+        self.assertRaises(exceptions.NotFound, self.client.resume_server,
+                          nonexistent_server)
+
+    @attr(type=['negative', 'gate'])
+    def test_resume_server_invalid_state(self):
+        # resume an active server.
+        self.assertRaises(exceptions.Conflict,
+                          self.client.resume_server,
+                          self.server_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_get_console_output_of_non_existent_server(self):
+        # get the console output for a non existent server
+        nonexistent_server = str(uuid.uuid4())
+        self.assertRaises(exceptions.NotFound,
+                          self.client.get_console_output,
+                          nonexistent_server, 10)
+
+    @attr(type=['negative', 'gate'])
+    def test_force_delete_nonexistent_server_id(self):
+        non_existent_server_id = str(uuid.uuid4())
+
+        self.assertRaises(exceptions.NotFound,
+                          self.client.force_delete_server,
+                          non_existent_server_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_force_delete_server_invalid_state(self):
+        # we can only force-delete a server in 'soft-delete' state
+        self.assertRaises(exceptions.Conflict,
+                          self.client.force_delete_server,
+                          self.server_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_restore_nonexistent_server_id(self):
+        non_existent_server_id = str(uuid.uuid4())
+
+        self.assertRaises(exceptions.NotFound,
+                          self.client.restore_soft_deleted_server,
+                          non_existent_server_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_restore_server_invalid_state(self):
+        # we can only restore-delete a server in 'soft-delete' state
+        self.assertRaises(exceptions.Conflict,
+                          self.client.restore_soft_deleted_server,
+                          self.server_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_shelve_non_existent_server(self):
+        # shelve a non existent server
+        nonexistent_server = str(uuid.uuid4())
+        self.assertRaises(exceptions.NotFound, self.client.shelve_server,
+                          nonexistent_server)
+
+    @attr(type=['negative', 'gate'])
+    def test_shelve_shelved_server(self):
+        # shelve a shelved server.
+        resp, server = self.client.shelve_server(self.server_id)
+        self.assertEqual(202, resp.status)
+        self.addCleanup(self.client.unshelve_server, self.server_id)
+
+        offload_time = self.config.compute.shelved_offload_time
+        if offload_time >= 0:
+            self.client.wait_for_server_status(self.server_id,
+                                               'SHELVED_OFFLOADED',
+                                               extra_timeout=offload_time)
+        else:
+            self.client.wait_for_server_status(self.server_id,
+                                               'SHELVED')
+
+        resp, server = self.client.get_server(self.server_id)
+        image_name = server['name'] + '-shelved'
+        params = {'name': image_name}
+        resp, images = self.images_client.list_images(params)
+        self.assertEqual(1, len(images))
+        self.assertEqual(image_name, images[0]['name'])
+
+        self.assertRaises(exceptions.Conflict,
+                          self.client.shelve_server,
+                          self.server_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_unshelve_non_existent_server(self):
+        # unshelve a non existent server
+        nonexistent_server = str(uuid.uuid4())
+        self.assertRaises(exceptions.NotFound, self.client.unshelve_server,
+                          nonexistent_server)
+
+    @attr(type=['negative', 'gate'])
+    def test_unshelve_server_invalid_state(self):
+        # unshelve an active server.
+        self.assertRaises(exceptions.Conflict,
+                          self.client.unshelve_server,
+                          self.server_id)
+
+
+class ServersNegativeTestXML(ServersNegativeTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/test_extensions.py b/tempest/api/compute/v3/test_extensions.py
new file mode 100644
index 0000000..d7269d1
--- /dev/null
+++ b/tempest/api/compute/v3/test_extensions.py
@@ -0,0 +1,35 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+
+from tempest.api.compute import base
+from tempest.test import attr
+
+
+class ExtensionsV3TestJSON(base.BaseV3ComputeTest):
+    _interface = 'json'
+
+    @attr(type='gate')
+    def test_list_extensions(self):
+        # List of all extensions
+        resp, extensions = self.extensions_client.list_extensions()
+        self.assertIn("extensions", extensions)
+        self.assertEqual(200, resp.status)
+
+
+class ExtensionsV3TestXML(ExtensionsV3TestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/v3/test_quotas.py b/tempest/api/compute/v3/test_quotas.py
new file mode 100644
index 0000000..475d055
--- /dev/null
+++ b/tempest/api/compute/v3/test_quotas.py
@@ -0,0 +1,73 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.compute import base
+from tempest.test import attr
+
+
+class QuotasTestJSON(base.BaseV2ComputeTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(QuotasTestJSON, cls).setUpClass()
+        cls.client = cls.quotas_client
+        cls.admin_client = cls._get_identity_admin_client()
+        resp, tenants = cls.admin_client.list_tenants()
+        cls.tenant_id = [tnt['id'] for tnt in tenants if tnt['name'] ==
+                         cls.client.tenant_name][0]
+        cls.default_quota_set = set(('injected_file_content_bytes',
+                                     'metadata_items', 'injected_files',
+                                     'ram', 'floating_ips',
+                                     'fixed_ips', 'key_pairs',
+                                     'injected_file_path_bytes',
+                                     'instances', 'security_group_rules',
+                                     'cores', 'security_groups'))
+
+    @attr(type='smoke')
+    def test_get_quotas(self):
+        # User can get the quota set for it's tenant
+        expected_quota_set = self.default_quota_set | set(['id'])
+        resp, quota_set = self.client.get_quota_set(self.tenant_id)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(sorted(expected_quota_set),
+                         sorted(quota_set.keys()))
+        self.assertEqual(quota_set['id'], self.tenant_id)
+
+    @attr(type='smoke')
+    def test_get_default_quotas(self):
+        # User can get the default quota set for it's tenant
+        expected_quota_set = self.default_quota_set | set(['id'])
+        resp, quota_set = self.client.get_default_quota_set(self.tenant_id)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(sorted(expected_quota_set),
+                         sorted(quota_set.keys()))
+        self.assertEqual(quota_set['id'], self.tenant_id)
+
+    @attr(type='smoke')
+    def test_compare_tenant_quotas_with_default_quotas(self):
+        # Tenants are created with the default quota values
+        resp, defualt_quota_set = \
+            self.client.get_default_quota_set(self.tenant_id)
+        self.assertEqual(200, resp.status)
+        resp, tenant_quota_set = self.client.get_quota_set(self.tenant_id)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(defualt_quota_set, tenant_quota_set)
+
+
+class QuotasTestXML(QuotasTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index a993077..660de95 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -53,8 +53,9 @@
 
     def _create_and_attach(self):
         # Start a server and wait for it to become ready
-        resp, server = self.create_server(wait_until='ACTIVE',
-                                          adminPass=self.image_ssh_password)
+        admin_pass = self.image_ssh_password
+        resp, server = self.create_test_server(wait_until='ACTIVE',
+                                               adminPass=admin_pass)
         self.server = server
 
         # Record addresses so that we can ssh later
diff --git a/tempest/api/compute/volumes/test_volumes_get.py b/tempest/api/compute/volumes/test_volumes_get.py
index 192d81e..ae6996d 100644
--- a/tempest/api/compute/volumes/test_volumes_get.py
+++ b/tempest/api/compute/volumes/test_volumes_get.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 
 
@@ -36,7 +36,7 @@
     def test_volume_create_get_delete(self):
         # CREATE, GET, DELETE Volume
         volume = None
-        v_name = rand_name('Volume-%s-') % self._interface
+        v_name = data_utils.rand_name('Volume-%s-') % self._interface
         metadata = {'Type': 'work'}
         # Create volume
         resp, volume = self.client.create_volume(size=1,
@@ -73,7 +73,7 @@
     @attr(type='gate')
     def test_volume_get_metadata_none(self):
         # CREATE, GET empty metadata dict
-        v_name = rand_name('Volume-')
+        v_name = data_utils.rand_name('Volume-')
         # Create volume
         resp, volume = self.client.create_volume(size=1,
                                                  display_name=v_name,
diff --git a/tempest/api/compute/volumes/test_volumes_list.py b/tempest/api/compute/volumes/test_volumes_list.py
index b4e00f9..f54e9b3 100644
--- a/tempest/api/compute/volumes/test_volumes_list.py
+++ b/tempest/api/compute/volumes/test_volumes_list.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 
 
@@ -43,9 +43,8 @@
         cls.volume_list = []
         cls.volume_id_list = []
         for i in range(3):
-            v_name = rand_name('volume-%s')
+            v_name = data_utils.rand_name('volume-%s' % cls._interface)
             metadata = {'Type': 'work'}
-            v_name += cls._interface
             try:
                 resp, volume = cls.client.create_volume(size=1,
                                                         display_name=v_name,
diff --git a/tempest/api/identity/admin/test_roles.py b/tempest/api/identity/admin/test_roles.py
index 543cd91..8205d15 100644
--- a/tempest/api/identity/admin/test_roles.py
+++ b/tempest/api/identity/admin/test_roles.py
@@ -16,8 +16,7 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
-from tempest import exceptions
+from tempest.common.utils import data_utils
 from tempest.test import attr
 
 
@@ -28,7 +27,8 @@
     def setUpClass(cls):
         super(RolesTestJSON, cls).setUpClass()
         for _ in xrange(5):
-            resp, role = cls.client.create_role(rand_name('role-'))
+            role_name = data_utils.rand_name(name='role-')
+            resp, role = cls.client.create_role(role_name)
             cls.data.roles.append(role)
 
     def _get_role_params(self):
@@ -55,23 +55,9 @@
         self.assertEqual(len(found), len(self.data.roles))
 
     @attr(type='gate')
-    def test_list_roles_by_unauthorized_user(self):
-        # Non-administrator user should not be able to list roles
-        self.assertRaises(exceptions.Unauthorized,
-                          self.non_admin_client.list_roles)
-
-    @attr(type='gate')
-    def test_list_roles_request_without_token(self):
-        # Request to list roles without a valid token should fail
-        token = self.client.get_auth()
-        self.client.delete_token(token)
-        self.assertRaises(exceptions.Unauthorized, self.client.list_roles)
-        self.client.clear_auth()
-
-    @attr(type='gate')
     def test_role_create_delete(self):
         # Role should be created, verified, and deleted
-        role_name = rand_name('role-test-')
+        role_name = data_utils.rand_name(name='role-test-')
         resp, body = self.client.create_role(role_name)
         self.assertIn('status', resp)
         self.assertTrue(resp['status'].startswith('2'))
@@ -90,23 +76,6 @@
         self.assertFalse(any(found))
 
     @attr(type='gate')
-    def test_role_create_blank_name(self):
-        # Should not be able to create a role with a blank name
-        self.assertRaises(exceptions.BadRequest, self.client.create_role, '')
-
-    @attr(type='gate')
-    def test_role_create_duplicate(self):
-        # Role names should be unique
-        role_name = rand_name('role-dup-')
-        resp, body = self.client.create_role(role_name)
-        role1_id = body.get('id')
-        self.assertIn('status', resp)
-        self.assertTrue(resp['status'].startswith('2'))
-        self.addCleanup(self.client.delete_role, role1_id)
-        self.assertRaises(exceptions.Conflict, self.client.create_role,
-                          role_name)
-
-    @attr(type='gate')
     def test_assign_user_role(self):
         # Assign a role to a user on a tenant
         (user, tenant, role) = self._get_role_params()
@@ -115,55 +84,6 @@
         self.assert_role_in_role_list(role, roles)
 
     @attr(type='gate')
-    def test_assign_user_role_by_unauthorized_user(self):
-        # Non-administrator user should not be authorized to
-        # assign a role to user
-        (user, tenant, role) = self._get_role_params()
-        self.assertRaises(exceptions.Unauthorized,
-                          self.non_admin_client.assign_user_role,
-                          tenant['id'], user['id'], role['id'])
-
-    @attr(type='gate')
-    def test_assign_user_role_request_without_token(self):
-        # Request to assign a role to a user without a valid token
-        (user, tenant, role) = self._get_role_params()
-        token = self.client.get_auth()
-        self.client.delete_token(token)
-        self.assertRaises(exceptions.Unauthorized,
-                          self.client.assign_user_role, tenant['id'],
-                          user['id'], role['id'])
-        self.client.clear_auth()
-
-    @attr(type='gate')
-    def test_assign_user_role_for_non_existent_user(self):
-        # Attempt to assign a role to a non existent user should fail
-        (user, tenant, role) = self._get_role_params()
-        self.assertRaises(exceptions.NotFound, self.client.assign_user_role,
-                          tenant['id'], 'junk-user-id-999', role['id'])
-
-    @attr(type='gate')
-    def test_assign_user_role_for_non_existent_role(self):
-        # Attempt to assign a non existent role to user should fail
-        (user, tenant, role) = self._get_role_params()
-        self.assertRaises(exceptions.NotFound, self.client.assign_user_role,
-                          tenant['id'], user['id'], 'junk-role-id-12345')
-
-    @attr(type='gate')
-    def test_assign_user_role_for_non_existent_tenant(self):
-        # Attempt to assign a role on a non existent tenant should fail
-        (user, tenant, role) = self._get_role_params()
-        self.assertRaises(exceptions.NotFound, self.client.assign_user_role,
-                          'junk-tenant-1234', user['id'], role['id'])
-
-    @attr(type='gate')
-    def test_assign_duplicate_user_role(self):
-        # Duplicate user role should not get assigned
-        (user, tenant, role) = self._get_role_params()
-        self.client.assign_user_role(tenant['id'], user['id'], role['id'])
-        self.assertRaises(exceptions.Conflict, self.client.assign_user_role,
-                          tenant['id'], user['id'], role['id'])
-
-    @attr(type='gate')
     def test_remove_user_role(self):
         # Remove a role assigned to a user on a tenant
         (user, tenant, role) = self._get_role_params()
@@ -174,62 +94,6 @@
         self.assertEqual(resp['status'], '204')
 
     @attr(type='gate')
-    def test_remove_user_role_by_unauthorized_user(self):
-        # Non-administrator user should not be authorized to
-        # remove a user's role
-        (user, tenant, role) = self._get_role_params()
-        resp, user_role = self.client.assign_user_role(tenant['id'],
-                                                       user['id'],
-                                                       role['id'])
-        self.assertRaises(exceptions.Unauthorized,
-                          self.non_admin_client.remove_user_role,
-                          tenant['id'], user['id'], role['id'])
-
-    @attr(type='gate')
-    def test_remove_user_role_request_without_token(self):
-        # Request to remove a user's role without a valid token
-        (user, tenant, role) = self._get_role_params()
-        resp, user_role = self.client.assign_user_role(tenant['id'],
-                                                       user['id'],
-                                                       role['id'])
-        token = self.client.get_auth()
-        self.client.delete_token(token)
-        self.assertRaises(exceptions.Unauthorized,
-                          self.client.remove_user_role, tenant['id'],
-                          user['id'], role['id'])
-        self.client.clear_auth()
-
-    @attr(type='gate')
-    def test_remove_user_role_non_existant_user(self):
-        # Attempt to remove a role from a non existent user should fail
-        (user, tenant, role) = self._get_role_params()
-        resp, user_role = self.client.assign_user_role(tenant['id'],
-                                                       user['id'],
-                                                       role['id'])
-        self.assertRaises(exceptions.NotFound, self.client.remove_user_role,
-                          tenant['id'], 'junk-user-id-123', role['id'])
-
-    @attr(type='gate')
-    def test_remove_user_role_non_existant_role(self):
-        # Attempt to delete a non existent role from a user should fail
-        (user, tenant, role) = self._get_role_params()
-        resp, user_role = self.client.assign_user_role(tenant['id'],
-                                                       user['id'],
-                                                       role['id'])
-        self.assertRaises(exceptions.NotFound, self.client.remove_user_role,
-                          tenant['id'], user['id'], 'junk-user-role-123')
-
-    @attr(type='gate')
-    def test_remove_user_role_non_existant_tenant(self):
-        # Attempt to remove a role from a non existent tenant should fail
-        (user, tenant, role) = self._get_role_params()
-        resp, user_role = self.client.assign_user_role(tenant['id'],
-                                                       user['id'],
-                                                       role['id'])
-        self.assertRaises(exceptions.NotFound, self.client.remove_user_role,
-                          'junk-tenant-id-123', user['id'], role['id'])
-
-    @attr(type='gate')
     def test_list_user_roles(self):
         # List roles assigned to a user on tenant
         (user, tenant, role) = self._get_role_params()
@@ -237,36 +101,6 @@
         resp, roles = self.client.list_user_roles(tenant['id'], user['id'])
         self.assert_role_in_role_list(role, roles)
 
-    @attr(type='gate')
-    def test_list_user_roles_by_unauthorized_user(self):
-        # Non-administrator user should not be authorized to list
-        # a user's roles
-        (user, tenant, role) = self._get_role_params()
-        self.client.assign_user_role(tenant['id'], user['id'], role['id'])
-        self.assertRaises(exceptions.Unauthorized,
-                          self.non_admin_client.list_user_roles, tenant['id'],
-                          user['id'])
-
-    @attr(type='gate')
-    def test_list_user_roles_request_without_token(self):
-        # Request to list user's roles without a valid token should fail
-        (user, tenant, role) = self._get_role_params()
-        token = self.client.get_auth()
-        self.client.delete_token(token)
-        try:
-            self.assertRaises(exceptions.Unauthorized,
-                              self.client.list_user_roles, tenant['id'],
-                              user['id'])
-        finally:
-            self.client.clear_auth()
-
-    @attr(type='gate')
-    def test_list_user_roles_for_non_existent_user(self):
-        # Attempt to list roles of a non existent user should fail
-        (user, tenant, role) = self._get_role_params()
-        self.assertRaises(exceptions.NotFound, self.client.list_user_roles,
-                          tenant['id'], 'junk-role-aabbcc11')
-
 
 class RolesTestXML(RolesTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/identity/admin/test_roles_negative.py b/tempest/api/identity/admin/test_roles_negative.py
new file mode 100644
index 0000000..83d1d4d
--- /dev/null
+++ b/tempest/api/identity/admin/test_roles_negative.py
@@ -0,0 +1,262 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 Huawei Technologies Co.,LTD.
+# 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 uuid
+
+from tempest.api.identity import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest.test import attr
+
+
+class RolesNegativeTestJSON(base.BaseIdentityAdminTest):
+    _interface = 'json'
+
+    def _get_role_params(self):
+        self.data.setup_test_user()
+        self.data.setup_test_role()
+        user = self.get_user_by_name(self.data.test_user)
+        tenant = self.get_tenant_by_name(self.data.test_tenant)
+        role = self.get_role_by_name(self.data.test_role)
+        return (user, tenant, role)
+
+    @attr(type=['negative', 'gate'])
+    def test_list_roles_by_unauthorized_user(self):
+        # Non-administrator user should not be able to list roles
+        self.assertRaises(exceptions.Unauthorized,
+                          self.non_admin_client.list_roles)
+
+    @attr(type=['negative', 'gate'])
+    def test_list_roles_request_without_token(self):
+        # Request to list roles without a valid token should fail
+        token = self.client.get_auth()
+        self.client.delete_token(token)
+        self.assertRaises(exceptions.Unauthorized, self.client.list_roles)
+        self.client.clear_auth()
+
+    @attr(type=['negative', 'gate'])
+    def test_role_create_blank_name(self):
+        # Should not be able to create a role with a blank name
+        self.assertRaises(exceptions.BadRequest, self.client.create_role, '')
+
+    @attr(type=['negative', 'gate'])
+    def test_create_role_by_unauthorized_user(self):
+        # Non-administrator user should not be able to create role
+        role_name = data_utils.rand_name(name='role-')
+        self.assertRaises(exceptions.Unauthorized,
+                          self.non_admin_client.create_role, role_name)
+
+    @attr(type=['negative', 'gate'])
+    def test_create_role_request_without_token(self):
+        # Request to create role without a valid token should fail
+        token = self.client.get_auth()
+        self.client.delete_token(token)
+        role_name = data_utils.rand_name(name='role-')
+        self.assertRaises(exceptions.Unauthorized,
+                          self.client.create_role, role_name)
+        self.client.clear_auth()
+
+    @attr(type=['negative', 'gate'])
+    def test_role_create_duplicate(self):
+        # Role names should be unique
+        role_name = data_utils.rand_name(name='role-dup-')
+        resp, body = self.client.create_role(role_name)
+        role1_id = body.get('id')
+        self.assertIn('status', resp)
+        self.assertTrue(resp['status'].startswith('2'))
+        self.addCleanup(self.client.delete_role, role1_id)
+        self.assertRaises(exceptions.Conflict, self.client.create_role,
+                          role_name)
+
+    @attr(type=['negative', 'gate'])
+    def test_delete_role_by_unauthorized_user(self):
+        # Non-administrator user should not be able to delete role
+        role_name = data_utils.rand_name(name='role-')
+        resp, body = self.client.create_role(role_name)
+        self.assertEqual(200, resp.status)
+        self.data.roles.append(body)
+        role_id = body.get('id')
+        self.assertRaises(exceptions.Unauthorized,
+                          self.non_admin_client.delete_role, role_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_delete_role_request_without_token(self):
+        # Request to delete role without a valid token should fail
+        role_name = data_utils.rand_name(name='role-')
+        resp, body = self.client.create_role(role_name)
+        self.assertEqual(200, resp.status)
+        self.data.roles.append(body)
+        role_id = body.get('id')
+        token = self.client.get_auth()
+        self.client.delete_token(token)
+        self.assertRaises(exceptions.Unauthorized,
+                          self.client.delete_role,
+                          role_id)
+        self.client.clear_auth()
+
+    @attr(type=['negative', 'gate'])
+    def test_delete_role_non_existent(self):
+        # Attempt to delete a non existent role should fail
+        non_existent_role = str(uuid.uuid4().hex)
+        self.assertRaises(exceptions.NotFound, self.client.delete_role,
+                          non_existent_role)
+
+    @attr(type=['negative', 'gate'])
+    def test_assign_user_role_by_unauthorized_user(self):
+        # Non-administrator user should not be authorized to
+        # assign a role to user
+        (user, tenant, role) = self._get_role_params()
+        self.assertRaises(exceptions.Unauthorized,
+                          self.non_admin_client.assign_user_role,
+                          tenant['id'], user['id'], role['id'])
+
+    @attr(type=['negative', 'gate'])
+    def test_assign_user_role_request_without_token(self):
+        # Request to assign a role to a user without a valid token
+        (user, tenant, role) = self._get_role_params()
+        token = self.client.get_auth()
+        self.client.delete_token(token)
+        self.assertRaises(exceptions.Unauthorized,
+                          self.client.assign_user_role, tenant['id'],
+                          user['id'], role['id'])
+        self.client.clear_auth()
+
+    @attr(type=['negative', 'gate'])
+    def test_assign_user_role_for_non_existent_user(self):
+        # Attempt to assign a role to a non existent user should fail
+        (user, tenant, role) = self._get_role_params()
+        non_existent_user = str(uuid.uuid4().hex)
+        self.assertRaises(exceptions.NotFound, self.client.assign_user_role,
+                          tenant['id'], non_existent_user, role['id'])
+
+    @attr(type=['negative', 'gate'])
+    def test_assign_user_role_for_non_existent_role(self):
+        # Attempt to assign a non existent role to user should fail
+        (user, tenant, role) = self._get_role_params()
+        non_existent_role = str(uuid.uuid4().hex)
+        self.assertRaises(exceptions.NotFound, self.client.assign_user_role,
+                          tenant['id'], user['id'], non_existent_role)
+
+    @attr(type=['negative', 'gate'])
+    def test_assign_user_role_for_non_existent_tenant(self):
+        # Attempt to assign a role on a non existent tenant should fail
+        (user, tenant, role) = self._get_role_params()
+        non_existent_tenant = str(uuid.uuid4().hex)
+        self.assertRaises(exceptions.NotFound, self.client.assign_user_role,
+                          non_existent_tenant, user['id'], role['id'])
+
+    @attr(type=['negative', 'gate'])
+    def test_assign_duplicate_user_role(self):
+        # Duplicate user role should not get assigned
+        (user, tenant, role) = self._get_role_params()
+        self.client.assign_user_role(tenant['id'], user['id'], role['id'])
+        self.assertRaises(exceptions.Conflict, self.client.assign_user_role,
+                          tenant['id'], user['id'], role['id'])
+
+    @attr(type=['negative', 'gate'])
+    def test_remove_user_role_by_unauthorized_user(self):
+        # Non-administrator user should not be authorized to
+        # remove a user's role
+        (user, tenant, role) = self._get_role_params()
+        resp, user_role = self.client.assign_user_role(tenant['id'],
+                                                       user['id'],
+                                                       role['id'])
+        self.assertRaises(exceptions.Unauthorized,
+                          self.non_admin_client.remove_user_role,
+                          tenant['id'], user['id'], role['id'])
+
+    @attr(type=['negative', 'gate'])
+    def test_remove_user_role_request_without_token(self):
+        # Request to remove a user's role without a valid token
+        (user, tenant, role) = self._get_role_params()
+        resp, user_role = self.client.assign_user_role(tenant['id'],
+                                                       user['id'],
+                                                       role['id'])
+        token = self.client.get_auth()
+        self.client.delete_token(token)
+        self.assertRaises(exceptions.Unauthorized,
+                          self.client.remove_user_role, tenant['id'],
+                          user['id'], role['id'])
+        self.client.clear_auth()
+
+    @attr(type=['negative', 'gate'])
+    def test_remove_user_role_non_existant_user(self):
+        # Attempt to remove a role from a non existent user should fail
+        (user, tenant, role) = self._get_role_params()
+        resp, user_role = self.client.assign_user_role(tenant['id'],
+                                                       user['id'],
+                                                       role['id'])
+        non_existant_user = str(uuid.uuid4().hex)
+        self.assertRaises(exceptions.NotFound, self.client.remove_user_role,
+                          tenant['id'], non_existant_user, role['id'])
+
+    @attr(type=['negative', 'gate'])
+    def test_remove_user_role_non_existant_role(self):
+        # Attempt to delete a non existent role from a user should fail
+        (user, tenant, role) = self._get_role_params()
+        resp, user_role = self.client.assign_user_role(tenant['id'],
+                                                       user['id'],
+                                                       role['id'])
+        non_existant_role = str(uuid.uuid4().hex)
+        self.assertRaises(exceptions.NotFound, self.client.remove_user_role,
+                          tenant['id'], user['id'], non_existant_role)
+
+    @attr(type=['negative', 'gate'])
+    def test_remove_user_role_non_existant_tenant(self):
+        # Attempt to remove a role from a non existent tenant should fail
+        (user, tenant, role) = self._get_role_params()
+        resp, user_role = self.client.assign_user_role(tenant['id'],
+                                                       user['id'],
+                                                       role['id'])
+        non_existant_tenant = str(uuid.uuid4().hex)
+        self.assertRaises(exceptions.NotFound, self.client.remove_user_role,
+                          non_existant_tenant, user['id'], role['id'])
+
+    @attr(type=['negative', 'gate'])
+    def test_list_user_roles_by_unauthorized_user(self):
+        # Non-administrator user should not be authorized to list
+        # a user's roles
+        (user, tenant, role) = self._get_role_params()
+        self.client.assign_user_role(tenant['id'], user['id'], role['id'])
+        self.assertRaises(exceptions.Unauthorized,
+                          self.non_admin_client.list_user_roles, tenant['id'],
+                          user['id'])
+
+    @attr(type=['negative', 'gate'])
+    def test_list_user_roles_request_without_token(self):
+        # Request to list user's roles without a valid token should fail
+        (user, tenant, role) = self._get_role_params()
+        token = self.client.get_auth()
+        self.client.delete_token(token)
+        try:
+            self.assertRaises(exceptions.Unauthorized,
+                              self.client.list_user_roles, tenant['id'],
+                              user['id'])
+        finally:
+            self.client.clear_auth()
+
+    @attr(type=['negative', 'gate'])
+    def test_list_user_roles_for_non_existent_user(self):
+        # Attempt to list roles of a non existent user should fail
+        (user, tenant, role) = self._get_role_params()
+        non_existent_user = str(uuid.uuid4().hex)
+        self.assertRaises(exceptions.NotFound, self.client.list_user_roles,
+                          tenant['id'], non_existent_user)
+
+
+class RolesTestXML(RolesNegativeTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/identity/admin/test_services.py b/tempest/api/identity/admin/test_services.py
index df6c317..7fe5171 100644
--- a/tempest/api/identity/admin/test_services.py
+++ b/tempest/api/identity/admin/test_services.py
@@ -17,7 +17,7 @@
 
 
 from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.test import attr
 
@@ -30,9 +30,9 @@
         # GET Service
         try:
             # Creating a Service
-            name = rand_name('service-')
-            type = rand_name('type--')
-            description = rand_name('description-')
+            name = data_utils.rand_name('service-')
+            type = data_utils.rand_name('type--')
+            description = data_utils.rand_name('description-')
             resp, service_data = self.client.create_service(
                 name, type, description=description)
             self.assertTrue(resp['status'].startswith('2'))
@@ -72,9 +72,9 @@
         # Create, List, Verify and Delete Services
         services = []
         for _ in xrange(3):
-            name = rand_name('service-')
-            type = rand_name('type--')
-            description = rand_name('description-')
+            name = data_utils.rand_name('service-')
+            type = data_utils.rand_name('type--')
+            description = data_utils.rand_name('description-')
             resp, service = self.client.create_service(
                 name, type, description=description)
             services.append(service)
diff --git a/tempest/api/identity/admin/test_users.py b/tempest/api/identity/admin/test_users.py
index 906fad3..5d5a814 100644
--- a/tempest/api/identity/admin/test_users.py
+++ b/tempest/api/identity/admin/test_users.py
@@ -31,8 +31,6 @@
         cls.alt_user = data_utils.rand_name('test_user_')
         cls.alt_password = data_utils.rand_name('pass_')
         cls.alt_email = cls.alt_user + '@testmail.tm'
-        cls.alt_tenant = data_utils.rand_name('test_tenant_')
-        cls.alt_description = data_utils.rand_name('desc_')
 
     @attr(type='smoke')
     def test_create_user(self):
diff --git a/tempest/api/identity/admin/test_users_negative.py b/tempest/api/identity/admin/test_users_negative.py
index b29d155..3163c16 100644
--- a/tempest/api/identity/admin/test_users_negative.py
+++ b/tempest/api/identity/admin/test_users_negative.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.test import attr
 import uuid
@@ -28,11 +28,9 @@
     @classmethod
     def setUpClass(cls):
         super(UsersNegativeTestJSON, cls).setUpClass()
-        cls.alt_user = rand_name('test_user_')
-        cls.alt_password = rand_name('pass_')
+        cls.alt_user = data_utils.rand_name('test_user_')
+        cls.alt_password = data_utils.rand_name('pass_')
         cls.alt_email = cls.alt_user + '@testmail.tm'
-        cls.alt_tenant = rand_name('test_tenant_')
-        cls.alt_description = rand_name('desc_')
 
     @attr(type=['negative', 'gate'])
     def test_create_user_by_unauthorized_user(self):
@@ -93,7 +91,7 @@
     def test_create_user_with_enabled_non_bool(self):
         # Attempt to create a user with valid enabled para should fail
         self.data.setup_test_tenant()
-        name = rand_name('test_user_')
+        name = data_utils.rand_name('test_user_')
         self.assertRaises(exceptions.BadRequest, self.client.create_user,
                           name, self.alt_password,
                           self.data.tenant['id'],
@@ -102,7 +100,7 @@
     @attr(type=['negative', 'gate'])
     def test_update_user_for_non_existant_user(self):
         # Attempt to update a user non-existent user should fail
-        user_name = rand_name('user-')
+        user_name = data_utils.rand_name('user-')
         non_existent_id = str(uuid.uuid4())
         self.assertRaises(exceptions.NotFound, self.client.update_user,
                           non_existent_id, name=user_name)
@@ -222,9 +220,9 @@
         # users for a non-existent tenant
         # Assign invalid tenant ids
         invalid_id = list()
-        invalid_id.append(rand_name('999'))
+        invalid_id.append(data_utils.rand_name('999'))
         invalid_id.append('alpha')
-        invalid_id.append(rand_name("dddd@#%%^$"))
+        invalid_id.append(data_utils.rand_name("dddd@#%%^$"))
         invalid_id.append('!@#()$%^&*?<>{}[]')
         # List the users with invalid tenant id
         for invalid in invalid_id:
diff --git a/tempest/api/identity/admin/v3/test_credentials.py b/tempest/api/identity/admin/v3/test_credentials.py
index cda5863..0b494f3 100644
--- a/tempest/api/identity/admin/v3/test_credentials.py
+++ b/tempest/api/identity/admin/v3/test_credentials.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 
 
@@ -29,13 +29,14 @@
         cls.projects = list()
         cls.creds_list = [['project_id', 'user_id', 'id'],
                           ['access', 'secret']]
-        u_name = rand_name('user-')
+        u_name = data_utils.rand_name('user-')
         u_desc = '%s description' % u_name
         u_email = '%s@testmail.tm' % u_name
-        u_password = rand_name('pass-')
+        u_password = data_utils.rand_name('pass-')
         for i in range(2):
             resp, cls.project = cls.v3_client.create_project(
-                rand_name('project-'), description=rand_name('project-desc-'))
+                data_utils.rand_name('project-'),
+                description=data_utils.rand_name('project-desc-'))
             assert resp['status'] == '201', "Expected %s" % resp['status']
             cls.projects.append(cls.project['id'])
 
@@ -59,7 +60,8 @@
 
     @attr(type='smoke')
     def test_credentials_create_get_update_delete(self):
-        keys = [rand_name('Access-'), rand_name('Secret-')]
+        keys = [data_utils.rand_name('Access-'),
+                data_utils.rand_name('Secret-')]
         resp, cred = self.creds_client.create_credential(
             keys[0], keys[1], self.user_body['id'],
             self.projects[0])
@@ -70,7 +72,8 @@
         for value2 in self.creds_list[1]:
             self.assertIn(value2, cred['blob'])
 
-        new_keys = [rand_name('NewAccess-'), rand_name('NewSecret-')]
+        new_keys = [data_utils.rand_name('NewAccess-'),
+                    data_utils.rand_name('NewSecret-')]
         resp, update_body = self.creds_client.update_credential(
             cred['id'], access_key=new_keys[0], secret_key=new_keys[1],
             project_id=self.projects[1])
@@ -97,7 +100,8 @@
 
         for i in range(2):
             resp, cred = self.creds_client.create_credential(
-                rand_name('Access-'), rand_name('Secret-'),
+                data_utils.rand_name('Access-'),
+                data_utils.rand_name('Secret-'),
                 self.user_body['id'], self.projects[0])
             self.assertEqual(resp['status'], '201')
             created_cred_ids.append(cred['id'])
diff --git a/tempest/api/identity/admin/v3/test_domains.py b/tempest/api/identity/admin/v3/test_domains.py
index 2fbef77..ed776cd 100644
--- a/tempest/api/identity/admin/v3/test_domains.py
+++ b/tempest/api/identity/admin/v3/test_domains.py
@@ -17,7 +17,7 @@
 
 
 from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 
 
@@ -38,7 +38,8 @@
         fetched_ids = list()
         for _ in range(3):
             _, domain = self.v3_client.create_domain(
-                rand_name('domain-'), description=rand_name('domain-desc-'))
+                data_utils.rand_name('domain-'),
+                description=data_utils.rand_name('domain-desc-'))
             # Delete the domain at the end of this method
             self.addCleanup(self._delete_domain, domain['id'])
             domain_ids.append(domain['id'])
@@ -52,8 +53,8 @@
 
     @attr(type='smoke')
     def test_create_update_delete_domain(self):
-        d_name = rand_name('domain-')
-        d_desc = rand_name('domain-desc-')
+        d_name = data_utils.rand_name('domain-')
+        d_desc = data_utils.rand_name('domain-desc-')
         resp_1, domain = self.v3_client.create_domain(
             d_name, description=d_desc)
         self.assertEqual(resp_1['status'], '201')
@@ -70,8 +71,8 @@
             self.assertEqual(True, domain['enabled'])
         else:
             self.assertEqual('true', str(domain['enabled']).lower())
-        new_desc = rand_name('new-desc-')
-        new_name = rand_name('new-name-')
+        new_desc = data_utils.rand_name('new-desc-')
+        new_name = data_utils.rand_name('new-name-')
 
         resp_2, updated_domain = self.v3_client.update_domain(
             domain['id'], name=new_name, description=new_desc)
diff --git a/tempest/api/identity/admin/v3/test_endpoints.py b/tempest/api/identity/admin/v3/test_endpoints.py
index 02a6f5b..d4d2109 100644
--- a/tempest/api/identity/admin/v3/test_endpoints.py
+++ b/tempest/api/identity/admin/v3/test_endpoints.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 
 
@@ -29,9 +29,9 @@
         cls.identity_client = cls.client
         cls.client = cls.endpoints_client
         cls.service_ids = list()
-        s_name = rand_name('service-')
-        s_type = rand_name('type--')
-        s_description = rand_name('description-')
+        s_name = data_utils.rand_name('service-')
+        s_type = data_utils.rand_name('type--')
+        s_description = data_utils.rand_name('description-')
         resp, cls.service_data =\
             cls.identity_client.create_service(s_name, s_type,
                                                description=s_description)
@@ -40,8 +40,8 @@
         # Create endpoints so as to use for LIST and GET test cases
         cls.setup_endpoints = list()
         for i in range(2):
-            region = rand_name('region')
-            url = rand_name('url')
+            region = data_utils.rand_name('region')
+            url = data_utils.rand_name('url')
             interface = 'public'
             resp, endpoint = cls.client.create_endpoint(
                 cls.service_id, interface, url, region=region, enabled=True)
@@ -69,8 +69,8 @@
 
     @attr(type='gate')
     def test_create_list_delete_endpoint(self):
-        region = rand_name('region')
-        url = rand_name('url')
+        region = data_utils.rand_name('region')
+        url = data_utils.rand_name('url')
         interface = 'public'
         resp, endpoint =\
             self.client.create_endpoint(self.service_id, interface, url,
@@ -97,24 +97,24 @@
     def test_update_endpoint(self):
         # Creating an endpoint so as to check update endpoint
         # with new values
-        region1 = rand_name('region')
-        url1 = rand_name('url')
+        region1 = data_utils.rand_name('region')
+        url1 = data_utils.rand_name('url')
         interface1 = 'public'
         resp, endpoint_for_update =\
             self.client.create_endpoint(self.service_id, interface1,
                                         url1, region=region1,
                                         enabled=True)
         # Creating service so as update endpoint with new service ID
-        s_name = rand_name('service-')
-        s_type = rand_name('type--')
-        s_description = rand_name('description-')
+        s_name = data_utils.rand_name('service-')
+        s_type = data_utils.rand_name('type--')
+        s_description = data_utils.rand_name('description-')
         resp, self.service2 =\
             self.identity_client.create_service(s_name, s_type,
                                                 description=s_description)
         self.service_ids.append(self.service2['id'])
         # Updating endpoint with new values
-        region2 = rand_name('region')
-        url2 = rand_name('url')
+        region2 = data_utils.rand_name('region')
+        url2 = data_utils.rand_name('url')
         interface2 = 'internal'
         resp, endpoint = \
             self.client.update_endpoint(endpoint_for_update['id'],
diff --git a/tempest/api/identity/admin/v3/test_policies.py b/tempest/api/identity/admin/v3/test_policies.py
index 737a0e0..48f8fcd 100644
--- a/tempest/api/identity/admin/v3/test_policies.py
+++ b/tempest/api/identity/admin/v3/test_policies.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 
 
@@ -33,8 +33,8 @@
         policy_ids = list()
         fetched_ids = list()
         for _ in range(3):
-            blob = rand_name('BlobName-')
-            policy_type = rand_name('PolicyType-')
+            blob = data_utils.rand_name('BlobName-')
+            policy_type = data_utils.rand_name('PolicyType-')
             resp, policy = self.policy_client.create_policy(blob,
                                                             policy_type)
             # Delete the Policy at the end of this method
@@ -51,8 +51,8 @@
     @attr(type='smoke')
     def test_create_update_delete_policy(self):
         # Test to update policy
-        blob = rand_name('BlobName-')
-        policy_type = rand_name('PolicyType-')
+        blob = data_utils.rand_name('BlobName-')
+        policy_type = data_utils.rand_name('PolicyType-')
         resp, policy = self.policy_client.create_policy(blob, policy_type)
         self.addCleanup(self._delete_policy, policy['id'])
         self.assertIn('id', policy)
@@ -64,7 +64,7 @@
         resp, fetched_policy = self.policy_client.get_policy(policy['id'])
         self.assertEqual(resp['status'], '200')
         # Update policy
-        update_type = rand_name('UpdatedPolicyType-')
+        update_type = data_utils.rand_name('UpdatedPolicyType-')
         resp, data = self.policy_client.update_policy(
             policy['id'], type=update_type)
         self.assertIn('type', data)
diff --git a/tempest/api/identity/admin/v3/test_projects.py b/tempest/api/identity/admin/v3/test_projects.py
index ef9814a..cbfcd04 100644
--- a/tempest/api/identity/admin/v3/test_projects.py
+++ b/tempest/api/identity/admin/v3/test_projects.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.test import attr
 
@@ -35,7 +35,7 @@
         # Create several projects and delete them
         for _ in xrange(3):
             resp, project = self.v3_client.create_project(
-                rand_name('project-new'))
+                data_utils.rand_name('project-new'))
             self.addCleanup(self._delete_project, project['id'])
 
         resp, list_projects = self.v3_client.list_projects()
@@ -47,8 +47,8 @@
     @attr(type='gate')
     def test_project_create_with_description(self):
         # Create project with a description
-        project_name = rand_name('project-')
-        project_desc = rand_name('desc-')
+        project_name = data_utils.rand_name('project-')
+        project_desc = data_utils.rand_name('desc-')
         resp, project = self.v3_client.create_project(
             project_name, description=project_desc)
         self.v3data.projects.append(project)
@@ -66,7 +66,7 @@
     @attr(type='gate')
     def test_project_create_enabled(self):
         # Create a project that is enabled
-        project_name = rand_name('project-')
+        project_name = data_utils.rand_name('project-')
         resp, project = self.v3_client.create_project(
             project_name, enabled=True)
         self.v3data.projects.append(project)
@@ -82,7 +82,7 @@
     @attr(type='gate')
     def test_project_create_not_enabled(self):
         # Create a project that is not enabled
-        project_name = rand_name('project-')
+        project_name = data_utils.rand_name('project-')
         resp, project = self.v3_client.create_project(
             project_name, enabled=False)
         self.v3data.projects.append(project)
@@ -99,13 +99,13 @@
     @attr(type='gate')
     def test_project_update_name(self):
         # Update name attribute of a project
-        p_name1 = rand_name('project-')
+        p_name1 = data_utils.rand_name('project-')
         resp, project = self.v3_client.create_project(p_name1)
         self.v3data.projects.append(project)
 
         resp1_name = project['name']
 
-        p_name2 = rand_name('project2-')
+        p_name2 = data_utils.rand_name('project2-')
         resp, body = self.v3_client.update_project(project['id'], name=p_name2)
         st2 = resp['status']
         resp2_name = body['name']
@@ -122,14 +122,14 @@
     @attr(type='gate')
     def test_project_update_desc(self):
         # Update description attribute of a project
-        p_name = rand_name('project-')
-        p_desc = rand_name('desc-')
+        p_name = data_utils.rand_name('project-')
+        p_desc = data_utils.rand_name('desc-')
         resp, project = self.v3_client.create_project(
             p_name, description=p_desc)
         self.v3data.projects.append(project)
         resp1_desc = project['description']
 
-        p_desc2 = rand_name('desc2-')
+        p_desc2 = data_utils.rand_name('desc2-')
         resp, body = self.v3_client.update_project(
             project['id'], description=p_desc2)
         st2 = resp['status']
@@ -147,7 +147,7 @@
     @attr(type='gate')
     def test_project_update_enable(self):
         # Update the enabled attribute of a project
-        p_name = rand_name('project-')
+        p_name = data_utils.rand_name('project-')
         p_en = False
         resp, project = self.v3_client.create_project(p_name, enabled=p_en)
         self.v3data.projects.append(project)
@@ -173,15 +173,15 @@
     def test_associate_user_to_project(self):
         #Associate a user to a project
         #Create a Project
-        p_name = rand_name('project-')
+        p_name = data_utils.rand_name('project-')
         resp, project = self.v3_client.create_project(p_name)
         self.v3data.projects.append(project)
 
         #Create a User
-        u_name = rand_name('user-')
+        u_name = data_utils.rand_name('user-')
         u_desc = u_name + 'description'
         u_email = u_name + '@testmail.tm'
-        u_password = rand_name('pass-')
+        u_password = data_utils.rand_name('pass-')
         resp, user = self.v3_client.create_user(
             u_name, description=u_desc, password=u_password,
             email=u_email, project_id=project['id'])
@@ -207,7 +207,7 @@
     @attr(type=['negative', 'gate'])
     def test_project_create_duplicate(self):
         # Project names should be unique
-        project_name = rand_name('project-dup-')
+        project_name = data_utils.rand_name('project-dup-')
         resp, project = self.v3_client.create_project(project_name)
         self.v3data.projects.append(project)
 
@@ -217,7 +217,7 @@
     @attr(type=['negative', 'gate'])
     def test_create_project_by_unauthorized_user(self):
         # Non-admin user should not be authorized to create a project
-        project_name = rand_name('project-')
+        project_name = data_utils.rand_name('project-')
         self.assertRaises(
             exceptions.Unauthorized, self.v3_non_admin_client.create_project,
             project_name)
@@ -238,7 +238,7 @@
     @attr(type=['negative', 'gate'])
     def test_project_delete_by_unauthorized_user(self):
         # Non-admin user should not be able to delete a project
-        project_name = rand_name('project-')
+        project_name = data_utils.rand_name('project-')
         resp, project = self.v3_client.create_project(project_name)
         self.v3data.projects.append(project)
         self.assertRaises(
diff --git a/tempest/api/identity/admin/v3/test_roles.py b/tempest/api/identity/admin/v3/test_roles.py
index a238c46..a6a2bd7 100644
--- a/tempest/api/identity/admin/v3/test_roles.py
+++ b/tempest/api/identity/admin/v3/test_roles.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 
 
@@ -27,23 +27,26 @@
     def setUpClass(cls):
         super(RolesV3TestJSON, cls).setUpClass()
         cls.fetched_role_ids = list()
-        u_name = rand_name('user-')
+        u_name = data_utils.rand_name('user-')
         u_desc = '%s description' % u_name
         u_email = '%s@testmail.tm' % u_name
-        u_password = rand_name('pass-')
+        u_password = data_utils.rand_name('pass-')
         resp = [None] * 5
         resp[0], cls.project = cls.v3_client.create_project(
-            rand_name('project-'), description=rand_name('project-desc-'))
+            data_utils.rand_name('project-'),
+            description=data_utils.rand_name('project-desc-'))
         resp[1], cls.domain = cls.v3_client.create_domain(
-            rand_name('domain-'), description=rand_name('domain-desc-'))
+            data_utils.rand_name('domain-'),
+            description=data_utils.rand_name('domain-desc-'))
         resp[2], cls.group_body = cls.v3_client.create_group(
-            rand_name('Group-'), project_id=cls.project['id'],
+            data_utils.rand_name('Group-'), project_id=cls.project['id'],
             domain_id=cls.domain['id'])
         resp[3], cls.user_body = cls.v3_client.create_user(
             u_name, description=u_desc, password=u_password,
             email=u_email, project_id=cls.project['id'],
             domain_id=cls.domain['id'])
-        resp[4], cls.role = cls.v3_client.create_role(rand_name('Role-'))
+        resp[4], cls.role = cls.v3_client.create_role(
+            data_utils.rand_name('Role-'))
         for r in resp:
             assert r['status'] == '201', "Expected: %s" % r['status']
 
@@ -69,14 +72,14 @@
 
     @attr(type='smoke')
     def test_role_create_update_get(self):
-        r_name = rand_name('Role-')
+        r_name = data_utils.rand_name('Role-')
         resp, role = self.v3_client.create_role(r_name)
         self.addCleanup(self.v3_client.delete_role, role['id'])
         self.assertEqual(resp['status'], '201')
         self.assertIn('name', role)
         self.assertEqual(role['name'], r_name)
 
-        new_name = rand_name('NewRole-')
+        new_name = data_utils.rand_name('NewRole-')
         resp, updated_role = self.v3_client.update_role(new_name, role['id'])
         self.assertEqual(resp['status'], '200')
         self.assertIn('name', updated_role)
diff --git a/tempest/api/identity/admin/v3/test_services.py b/tempest/api/identity/admin/v3/test_services.py
index bfa0d84..1751638 100644
--- a/tempest/api/identity/admin/v3/test_services.py
+++ b/tempest/api/identity/admin/v3/test_services.py
@@ -17,7 +17,7 @@
 
 
 from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 
 
@@ -27,9 +27,9 @@
     @attr(type='gate')
     def test_update_service(self):
         # Update description attribute of service
-        name = rand_name('service-')
-        type = rand_name('type--')
-        description = rand_name('description-')
+        name = data_utils.rand_name('service-')
+        type = data_utils.rand_name('type--')
+        description = data_utils.rand_name('description-')
         resp, body = self.client.create_service(
             name, type, description=description)
         self.assertEqual('200', resp['status'])
@@ -39,7 +39,7 @@
         s_id = body['id']
         resp1_desc = body['description']
 
-        s_desc2 = rand_name('desc2-')
+        s_desc2 = data_utils.rand_name('desc2-')
         resp, body = self.service_client.update_service(
             s_id, description=s_desc2)
         resp2_desc = body['description']
diff --git a/tempest/api/identity/admin/v3/test_tokens.py b/tempest/api/identity/admin/v3/test_tokens.py
index f8a62a6..2541e25 100644
--- a/tempest/api/identity/admin/v3/test_tokens.py
+++ b/tempest/api/identity/admin/v3/test_tokens.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.test import attr
 
@@ -28,10 +28,10 @@
     def test_tokens(self):
         # Valid user's token is authenticated
         # Create a User
-        u_name = rand_name('user-')
+        u_name = data_utils.rand_name('user-')
         u_desc = '%s-description' % u_name
         u_email = '%s@testmail.tm' % u_name
-        u_password = rand_name('pass-')
+        u_password = data_utils.rand_name('pass-')
         resp, user = self.v3_client.create_user(
             u_name, description=u_desc, password=u_password,
             email=u_email)
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index 50e9702..b1c4d82 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 
 
@@ -27,10 +27,10 @@
     def test_user_update(self):
         # Test case to check if updating of user attributes is successful.
         # Creating first user
-        u_name = rand_name('user-')
+        u_name = data_utils.rand_name('user-')
         u_desc = u_name + 'description'
         u_email = u_name + '@testmail.tm'
-        u_password = rand_name('pass-')
+        u_password = data_utils.rand_name('pass-')
         resp, user = self.v3_client.create_user(
             u_name, description=u_desc, password=u_password,
             email=u_email, enabled=False)
@@ -38,11 +38,12 @@
         self.addCleanup(self.v3_client.delete_user, user['id'])
         # Creating second project for updation
         resp, project = self.v3_client.create_project(
-            rand_name('project-'), description=rand_name('project-desc-'))
+            data_utils.rand_name('project-'),
+            description=data_utils.rand_name('project-desc-'))
         # Delete the Project at the end of this method
         self.addCleanup(self.v3_client.delete_project, project['id'])
         # Updating user details with new values
-        u_name2 = rand_name('user2-')
+        u_name2 = data_utils.rand_name('user2-')
         u_email2 = u_name2 + '@testmail.tm'
         u_description2 = u_name2 + ' description'
         resp, update_user = self.v3_client.update_user(
@@ -73,21 +74,23 @@
         assigned_project_ids = list()
         fetched_project_ids = list()
         _, u_project = self.v3_client.create_project(
-            rand_name('project-'), description=rand_name('project-desc-'))
+            data_utils.rand_name('project-'),
+            description=data_utils.rand_name('project-desc-'))
         # Delete the Project at the end of this method
         self.addCleanup(self.v3_client.delete_project, u_project['id'])
         # Create a user.
-        u_name = rand_name('user-')
+        u_name = data_utils.rand_name('user-')
         u_desc = u_name + 'description'
         u_email = u_name + '@testmail.tm'
-        u_password = rand_name('pass-')
+        u_password = data_utils.rand_name('pass-')
         _, user_body = self.v3_client.create_user(
             u_name, description=u_desc, password=u_password,
             email=u_email, enabled=False, project_id=u_project['id'])
         # Delete the User at the end of this method
         self.addCleanup(self.v3_client.delete_user, user_body['id'])
         # Creating Role
-        _, role_body = self.v3_client.create_role(rand_name('role-'))
+        _, role_body = self.v3_client.create_role(
+            data_utils.rand_name('role-'))
         # Delete the Role at the end of this method
         self.addCleanup(self.v3_client.delete_role, role_body['id'])
 
@@ -96,7 +99,8 @@
         for i in range(2):
             # Creating project so as to assign role
             _, project_body = self.v3_client.create_project(
-                rand_name('project-'), description=rand_name('project-desc-'))
+                data_utils.rand_name('project-'),
+                description=data_utils.rand_name('project-desc-'))
             _, project = self.v3_client.get_project(project_body['id'])
             # Delete the Project at the end of this method
             self.addCleanup(self.v3_client.delete_project, project_body['id'])
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index ab89af4..876edfd 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -17,7 +17,7 @@
 
 
 from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 import tempest.test
 
 
@@ -94,8 +94,8 @@
         def setup_test_user(self):
             """Set up a test user."""
             self.setup_test_tenant()
-            self.test_user = rand_name('test_user_')
-            self.test_password = rand_name('pass_')
+            self.test_user = data_utils.rand_name('test_user_')
+            self.test_password = data_utils.rand_name('pass_')
             self.test_email = self.test_user + '@testmail.tm'
             resp, self.user = self.client.create_user(self.test_user,
                                                       self.test_password,
@@ -105,8 +105,8 @@
 
         def setup_test_tenant(self):
             """Set up a test tenant."""
-            self.test_tenant = rand_name('test_tenant_')
-            self.test_description = rand_name('desc_')
+            self.test_tenant = data_utils.rand_name('test_tenant_')
+            self.test_description = data_utils.rand_name('desc_')
             resp, self.tenant = self.client.create_tenant(
                 name=self.test_tenant,
                 description=self.test_description)
@@ -114,15 +114,15 @@
 
         def setup_test_role(self):
             """Set up a test role."""
-            self.test_role = rand_name('role')
+            self.test_role = data_utils.rand_name('role')
             resp, self.role = self.client.create_role(self.test_role)
             self.roles.append(self.role)
 
         def setup_test_v3_user(self):
             """Set up a test v3 user."""
             self.setup_test_project()
-            self.test_user = rand_name('test_user_')
-            self.test_password = rand_name('pass_')
+            self.test_user = data_utils.rand_name('test_user_')
+            self.test_password = data_utils.rand_name('pass_')
             self.test_email = self.test_user + '@testmail.tm'
             resp, self.v3_user = self.client.create_user(self.test_user,
                                                          self.test_password,
@@ -132,8 +132,8 @@
 
         def setup_test_project(self):
             """Set up a test project."""
-            self.test_project = rand_name('test_project_')
-            self.test_description = rand_name('desc_')
+            self.test_project = data_utils.rand_name('test_project_')
+            self.test_description = data_utils.rand_name('desc_')
             resp, self.project = self.client.create_project(
                 name=self.test_project,
                 description=self.test_description)
@@ -141,7 +141,7 @@
 
         def setup_test_v3_role(self):
             """Set up a test v3 role."""
-            self.test_role = rand_name('role')
+            self.test_role = data_utils.rand_name('role')
             resp, self.v3_role = self.client.create_role(self.test_role)
             self.v3_roles.append(self.v3_role)
 
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index ab0cb00..28ed5b6 100644
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -14,9 +14,11 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import cStringIO as StringIO
+
 from tempest import clients
 from tempest.common import isolated_creds
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.openstack.common import log as logging
 import tempest.test
@@ -61,7 +63,7 @@
     @classmethod
     def create_image(cls, **kwargs):
         """Wrapper that returns a test image."""
-        name = rand_name(cls.__name__ + "-instance")
+        name = data_utils.rand_name(cls.__name__ + "-instance")
 
         if 'name' in kwargs:
             name = kwargs.pop('name')
@@ -86,6 +88,36 @@
             raise cls.skipException(msg)
 
 
+class BaseV1ImageMembersTest(BaseV1ImageTest):
+    @classmethod
+    def setUpClass(cls):
+        super(BaseV1ImageMembersTest, cls).setUpClass()
+        if cls.config.compute.allow_tenant_isolation:
+            creds = cls.isolated_creds.get_alt_creds()
+            username, tenant_name, password = creds
+            cls.os_alt = clients.Manager(username=username,
+                                         password=password,
+                                         tenant_name=tenant_name)
+            cls.alt_tenant_id = cls.isolated_creds.get_alt_tenant()['id']
+        else:
+            cls.os_alt = clients.AltManager()
+            identity_client = cls._get_identity_admin_client()
+            cls.alt_tenant_id = identity_client.get_tenant_by_name(
+                cls.os_alt.tenant_name)['id']
+
+        cls.alt_img_cli = cls.os_alt.image_client
+
+    def _create_image(self):
+        image_file = StringIO.StringIO('*' * 1024)
+        resp, image = self.create_image(container_format='bare',
+                                        disk_format='raw',
+                                        is_public=False,
+                                        data=image_file)
+        self.assertEqual(201, resp.status)
+        image_id = image['id']
+        return image_id
+
+
 class BaseV2ImageTest(BaseImageTest):
 
     @classmethod
@@ -95,3 +127,40 @@
         if not cls.config.image_feature_enabled.api_v2:
             msg = "Glance API v2 not supported"
             raise cls.skipException(msg)
+
+
+class BaseV2MemeberImageTest(BaseImageTest):
+
+    @classmethod
+    def setUpClass(cls):
+        super(BaseV2MemeberImageTest, cls).setUpClass()
+        if cls.config.compute.allow_tenant_isolation:
+            creds = cls.isolated_creds.get_alt_creds()
+            username, tenant_name, password = creds
+            cls.os_alt = clients.Manager(username=username,
+                                         password=password,
+                                         tenant_name=tenant_name,
+                                         interface=cls._interface)
+            cls.alt_tenant_id = cls.isolated_creds.get_alt_tenant()['id']
+        else:
+            cls.os_alt = clients.AltManager()
+            alt_tenant_name = cls.os_alt.tenant_name
+            identity_client = cls._get_identity_admin_client()
+            cls.alt_tenant_id = identity_client.get_tenant_by_name(
+                alt_tenant_name)['id']
+        cls.os_img_client = cls.os.image_client_v2
+        cls.alt_img_client = cls.os_alt.image_client_v2
+
+    def _list_image_ids_as_alt(self):
+        _, image_list = self.alt_img_client.image_list()
+        image_ids = map(lambda x: x['id'], image_list)
+        return image_ids
+
+    def _create_image(self):
+        name = data_utils.rand_name('image')
+        resp, image = self.os_img_client.create_image(name,
+                                                      container_format='bare',
+                                                      disk_format='raw')
+        image_id = image['id']
+        self.addCleanup(self.os_img_client.delete_image, image_id)
+        return image_id
diff --git a/tempest/api/image/v1/test_image_members.py b/tempest/api/image/v1/test_image_members.py
index 9ea9a3d..437527d 100644
--- a/tempest/api/image/v1/test_image_members.py
+++ b/tempest/api/image/v1/test_image_members.py
@@ -14,44 +14,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import cStringIO as StringIO
 
 from tempest.api.image import base
-from tempest import clients
-from tempest.common.utils.data_utils import rand_name
-from tempest import exceptions
 from tempest.test import attr
 
 
-class ImageMembersTests(base.BaseV1ImageTest):
-
-    @classmethod
-    def setUpClass(cls):
-        super(ImageMembersTests, cls).setUpClass()
-        if cls.config.compute.allow_tenant_isolation:
-            creds = cls.isolated_creds.get_alt_creds()
-            username, tenant_name, password = creds
-            cls.os_alt = clients.Manager(username=username,
-                                         password=password,
-                                         tenant_name=tenant_name)
-        else:
-            cls.os_alt = clients.AltManager()
-
-        alt_tenant_name = cls.os_alt.tenant_name
-        identity_client = cls._get_identity_admin_client()
-        _, tenants = identity_client.list_tenants()
-        cls.alt_tenant_id = [tnt['id'] for tnt in tenants if tnt['name'] ==
-                             alt_tenant_name][0]
-
-    def _create_image(self):
-        image_file = StringIO.StringIO('*' * 1024)
-        resp, image = self.create_image(container_format='bare',
-                                        disk_format='raw',
-                                        is_public=False,
-                                        data=image_file)
-        self.assertEqual(201, resp.status)
-        image_id = image['id']
-        return image_id
+class ImageMembersTest(base.BaseV1ImageMembersTest):
 
     @attr(type='gate')
     def test_add_image_member(self):
@@ -63,6 +31,9 @@
         members = body['members']
         members = map(lambda x: x['member_id'], members)
         self.assertIn(self.alt_tenant_id, members)
+        # get image as alt user
+        resp, body = self.alt_img_cli.get_image(image)
+        self.assertEqual(200, resp.status)
 
     @attr(type='gate')
     def test_get_shared_images(self):
@@ -90,25 +61,3 @@
         self.assertEqual(200, resp.status)
         members = body['members']
         self.assertEqual(0, len(members), str(members))
-
-    @attr(type=['negative', 'gate'])
-    def test_add_member_with_non_existing_image(self):
-        # Add member with non existing image.
-        non_exist_image = rand_name('image_')
-        self.assertRaises(exceptions.NotFound, self.client.add_member,
-                          self.alt_tenant_id, non_exist_image)
-
-    @attr(type=['negative', 'gate'])
-    def test_delete_member_with_non_existing_image(self):
-        # Delete member with non existing image.
-        non_exist_image = rand_name('image_')
-        self.assertRaises(exceptions.NotFound, self.client.delete_member,
-                          self.alt_tenant_id, non_exist_image)
-
-    @attr(type=['negative', 'gate'])
-    def test_delete_member_with_non_existing_tenant(self):
-        # Delete member with non existing tenant.
-        image_id = self._create_image()
-        non_exist_tenant = rand_name('tenant_')
-        self.assertRaises(exceptions.NotFound, self.client.delete_member,
-                          non_exist_tenant, image_id)
diff --git a/tempest/api/image/v1/test_image_members_negative.py b/tempest/api/image/v1/test_image_members_negative.py
new file mode 100644
index 0000000..83f7a0f
--- /dev/null
+++ b/tempest/api/image/v1/test_image_members_negative.py
@@ -0,0 +1,54 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM Corp.
+#
+#    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.image import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest.test import attr
+
+
+class ImageMembersNegativeTest(base.BaseV1ImageMembersTest):
+
+    @attr(type=['negative', 'gate'])
+    def test_add_member_with_non_existing_image(self):
+        # Add member with non existing image.
+        non_exist_image = data_utils.rand_uuid()
+        self.assertRaises(exceptions.NotFound, self.client.add_member,
+                          self.alt_tenant_id, non_exist_image)
+
+    @attr(type=['negative', 'gate'])
+    def test_delete_member_with_non_existing_image(self):
+        # Delete member with non existing image.
+        non_exist_image = data_utils.rand_uuid()
+        self.assertRaises(exceptions.NotFound, self.client.delete_member,
+                          self.alt_tenant_id, non_exist_image)
+
+    @attr(type=['negative', 'gate'])
+    def test_delete_member_with_non_existing_tenant(self):
+        # Delete member with non existing tenant.
+        image_id = self._create_image()
+        non_exist_tenant = data_utils.rand_uuid_hex()
+        self.assertRaises(exceptions.NotFound, self.client.delete_member,
+                          non_exist_tenant, image_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_get_image_without_membership(self):
+        # Image is hidden from another tenants.
+        image_id = self._create_image()
+        self.assertRaises(exceptions.NotFound,
+                          self.alt_img_cli.get_image,
+                          image_id)
diff --git a/tempest/api/image/v1/test_images.py b/tempest/api/image/v1/test_images.py
index 90ffeae..558e2ec 100644
--- a/tempest/api/image/v1/test_images.py
+++ b/tempest/api/image/v1/test_images.py
@@ -18,7 +18,6 @@
 import cStringIO as StringIO
 
 from tempest.api.image import base
-from tempest import exceptions
 from tempest.test import attr
 
 
@@ -26,17 +25,6 @@
     """Here we test the registration and creation of images."""
 
     @attr(type='gate')
-    def test_register_with_invalid_container_format(self):
-        # Negative tests for invalid data supplied to POST /images
-        self.assertRaises(exceptions.BadRequest, self.client.create_image,
-                          'test', 'wrong', 'vhd')
-
-    @attr(type='gate')
-    def test_register_with_invalid_disk_format(self):
-        self.assertRaises(exceptions.BadRequest, self.client.create_image,
-                          'test', 'bare', 'wrong')
-
-    @attr(type='gate')
     def test_register_then_upload(self):
         # Register, then upload an image
         properties = {'prop1': 'val1'}
@@ -108,6 +96,8 @@
         self.assertEqual(40, body.get('min_ram'))
         for key, val in properties.items():
             self.assertEqual(val, body.get('properties')[key])
+        resp, body = self.client.delete_image(body['id'])
+        self.assertEqual('200', resp['status'])
 
 
 class ListImagesTest(base.BaseV1ImageTest):
diff --git a/tempest/api/image/v1/test_images_negative.py b/tempest/api/image/v1/test_images_negative.py
new file mode 100644
index 0000000..1bcf120
--- /dev/null
+++ b/tempest/api/image/v1/test_images_negative.py
@@ -0,0 +1,72 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM Corp.
+# 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 tempest.api.image import base
+from tempest import exceptions
+from tempest.test import attr
+
+
+class CreateDeleteImagesNegativeTest(base.BaseV1ImageTest):
+    """Here are negative tests for the deletion and creation of images."""
+
+    @attr(type=['negative', 'gate'])
+    def test_register_with_invalid_container_format(self):
+        # Negative tests for invalid data supplied to POST /images
+        self.assertRaises(exceptions.BadRequest, self.client.create_image,
+                          'test', 'wrong', 'vhd')
+
+    @attr(type=['negative', 'gate'])
+    def test_register_with_invalid_disk_format(self):
+        self.assertRaises(exceptions.BadRequest, self.client.create_image,
+                          'test', 'bare', 'wrong')
+
+    @attr(type=['negative', 'gate'])
+    def test_delete_image_with_invalid_image_id(self):
+        # An image should not be deleted with invalid image id
+        self.assertRaises(exceptions.NotFound, self.client.delete_image,
+                          '!@$%^&*()')
+
+    @attr(type=['negative', 'gate'])
+    def test_delete_non_existent_image(self):
+        # Return an error while trying to delete a non-existent image
+
+        non_existent_image_id = '11a22b9-12a9-5555-cc11-00ab112223fa'
+        self.assertRaises(exceptions.NotFound, self.client.delete_image,
+                          non_existent_image_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_delete_image_blank_id(self):
+        # Return an error while trying to delete an image with blank Id
+        self.assertRaises(exceptions.NotFound, self.client.delete_image, '')
+
+    @attr(type=['negative', 'gate'])
+    def test_delete_image_non_hex_string_id(self):
+        # Return an error while trying to delete an image with non hex id
+        image_id = '11a22b9-120q-5555-cc11-00ab112223gj'
+        self.assertRaises(exceptions.NotFound, self.client.delete_image,
+                          image_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_delete_image_negative_image_id(self):
+        # Return an error while trying to delete an image with negative id
+        self.assertRaises(exceptions.NotFound, self.client.delete_image, -1)
+
+    @attr(type=['negative', 'gate'])
+    def test_delete_image_id_is_over_35_character_limit(self):
+        # Return an error while trying to delete image with id over limit
+        self.assertRaises(exceptions.NotFound, self.client.delete_image,
+                          '11a22b9-12a9-5555-cc11-00ab112223fa-3fac')
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index ee6d656..6408c15 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -1,8 +1,8 @@
 # vim: tabstop=4 shiftwidth=4 softtabstop=4
 
 # Copyright 2013 OpenStack Foundation
+# Copyright 2013 IBM Corp
 # All Rights Reserved.
-# Copyright 2013 IBM Corp.
 #
 #    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
@@ -21,28 +21,16 @@
 
 from tempest.api.image import base
 from tempest.common.utils import data_utils
-from tempest import exceptions
 from tempest.test import attr
 
 
-class CreateRegisterImagesTest(base.BaseV2ImageTest):
+class BasicOperationsImagesTest(base.BaseV2ImageTest):
 
     """
-    Here we test the registration and creation of images
+    Here we test the basic operations of images
     """
 
     @attr(type='gate')
-    def test_register_with_invalid_container_format(self):
-        # Negative tests for invalid data supplied to POST /images
-        self.assertRaises(exceptions.BadRequest, self.client.create_image,
-                          'test', 'wrong', 'vhd')
-
-    @attr(type='gate')
-    def test_register_with_invalid_disk_format(self):
-        self.assertRaises(exceptions.BadRequest, self.client.create_image,
-                          'test', 'bare', 'wrong')
-
-    @attr(type='gate')
     def test_register_upload_get_image_file(self):
 
         """
@@ -83,6 +71,28 @@
         self.assertEqual(200, resp.status)
         self.assertEqual(file_content, body)
 
+    @attr(type='gate')
+    def test_delete_image(self):
+        # Deletes a image by image_id
+
+        # Create image
+        image_name = data_utils.rand_name('image')
+        resp, body = self.client.create_image(name=image_name,
+                                              container_format='bare',
+                                              disk_format='raw',
+                                              visibility='public')
+        self.assertEqual(201, resp.status)
+        image_id = body['id']
+
+        # Delete Image
+        self.client.delete_image(image_id)
+        self.client.wait_for_resource_deletion(image_id)
+
+        # Verifying deletion
+        resp, images = self.client.image_list()
+        self.assertEqual(resp.status, 200)
+        self.assertNotIn(image_id, images)
+
 
 class ListImagesTest(base.BaseV2ImageTest):
 
@@ -123,8 +133,3 @@
         image_list = map(lambda x: x['id'], images_list)
         for image in self.created_images:
             self.assertIn(image, image_list)
-
-    @attr(type=['negative', 'gate'])
-    def test_get_image_by_null_id(self):
-        self.assertRaises(exceptions.NotFound,
-                          self.client.get_image, '')
diff --git a/tempest/api/image/v2/test_images_member.py b/tempest/api/image/v2/test_images_member.py
new file mode 100644
index 0000000..954c79d
--- /dev/null
+++ b/tempest/api/image/v2/test_images_member.py
@@ -0,0 +1,55 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+#    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.image import base
+from tempest.test import attr
+
+
+class ImagesMemberTest(base.BaseV2MemeberImageTest):
+    _interface = 'json'
+
+    @attr(type='gate')
+    def test_image_share_accept(self):
+        image_id = self._create_image()
+        resp, member = self.os_img_client.add_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.assertIn(image_id, self._list_image_ids_as_alt())
+        _, body = self.os_img_client.get_image_membership(image_id)
+        members = body['members']
+        member = members[0]
+        self.assertEqual(len(members), 1, str(members))
+        self.assertEqual(member['member_id'], self.alt_tenant_id)
+        self.assertEqual(member['image_id'], image_id)
+        self.assertEqual(member['status'], 'accepted')
+
+    @attr(type='gate')
+    def test_image_share_reject(self):
+        image_id = self._create_image()
+        resp, member = self.os_img_client.add_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.assertNotIn(image_id, self._list_image_ids_as_alt())
diff --git a/tempest/api/image/v2/test_images_member_negative.py b/tempest/api/image/v2/test_images_member_negative.py
new file mode 100644
index 0000000..3c17959
--- /dev/null
+++ b/tempest/api/image/v2/test_images_member_negative.py
@@ -0,0 +1,43 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+#    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.image import base
+from tempest import exceptions
+from tempest.test import attr
+
+
+class ImagesMemberNegativeTest(base.BaseV2MemeberImageTest):
+    _interface = 'json'
+
+    @attr(type=['negative', 'gate'])
+    def test_image_share_invalid_status(self):
+        image_id = self._create_image()
+        resp, member = self.os_img_client.add_member(image_id,
+                                                     self.alt_tenant_id)
+        self.assertEqual(member['status'], 'pending')
+        self.assertRaises(exceptions.BadRequest,
+                          self.alt_img_client.update_member_status,
+                          image_id, self.alt_tenant_id, 'notavalidstatus')
+
+    @attr(type=['negative', 'gate'])
+    def test_image_share_owner_cannot_accept(self):
+        image_id = self._create_image()
+        resp, member = self.os_img_client.add_member(image_id,
+                                                     self.alt_tenant_id)
+        self.assertEqual(member['status'], 'pending')
+        self.assertNotIn(image_id, self._list_image_ids_as_alt())
+        self.assertRaises(exceptions.Unauthorized,
+                          self.os_img_client.update_member_status,
+                          image_id, self.alt_tenant_id, 'accepted')
+        self.assertNotIn(image_id, self._list_image_ids_as_alt())
diff --git a/tempest/api/image/v2/test_images_negative.py b/tempest/api/image/v2/test_images_negative.py
new file mode 100644
index 0000000..1cd6f29
--- /dev/null
+++ b/tempest/api/image/v2/test_images_negative.py
@@ -0,0 +1,95 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack Foundation
+# All Rights Reserved.
+# Copyright 2013 IBM Corp.
+#
+#    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 uuid
+
+from tempest.api.image import base
+from tempest import exceptions
+from tempest.test import attr
+
+
+class ImagesNegativeTest(base.BaseV2ImageTest):
+
+    """
+    here we have -ve tests for get_image and delete_image api
+
+    Tests
+        ** get non-existent image
+        ** get image with image_id=NULL
+        ** get the deleted image
+        ** delete non-existent image
+        ** delete rimage with  image_id=NULL
+        ** delete the deleted image
+     """
+
+    @attr(type=['negative', 'gate'])
+    def test_get_non_existent_image(self):
+        # get the non-existent image
+        non_existent_id = str(uuid.uuid4())
+        self.assertRaises(exceptions.NotFound, self.client.get_image,
+                          non_existent_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_get_image_null_id(self):
+        # get image with image_id = NULL
+        image_id = ""
+        self.assertRaises(exceptions.NotFound, self.client.get_image, image_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_get_delete_deleted_image(self):
+        # get and delete the deleted image
+        # create and delete image
+        resp, body = self.client.create_image(name='test',
+                                              container_format='bare',
+                                              disk_format='raw')
+        image_id = body['id']
+        self.assertEqual(201, resp.status)
+        self.client.delete_image(image_id)
+        self.client.wait_for_resource_deletion(image_id)
+
+        # get the deleted image
+        self.assertRaises(exceptions.NotFound, self.client.get_image, image_id)
+
+        # delete the deleted image
+        self.assertRaises(exceptions.NotFound, self.client.delete_image,
+                          image_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_delete_non_existing_image(self):
+        # delete non-existent image
+        non_existent_image_id = str(uuid.uuid4())
+        self.assertRaises(exceptions.NotFound, self.client.delete_image,
+                          non_existent_image_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_delete_image_null_id(self):
+        # delete image with image_id=NULL
+        image_id = ""
+        self.assertRaises(exceptions.NotFound, self.client.delete_image,
+                          image_id)
+
+    @attr(type=['negative', 'gate'])
+    def test_register_with_invalid_container_format(self):
+        # Negative tests for invalid data supplied to POST /images
+        self.assertRaises(exceptions.BadRequest, self.client.create_image,
+                          'test', 'wrong', 'vhd')
+
+    @attr(type=['negative', 'gate'])
+    def test_register_with_invalid_disk_format(self):
+        self.assertRaises(exceptions.BadRequest, self.client.create_image,
+                          'test', 'bare', 'wrong')
diff --git a/tempest/api/network/admin/__init__.py b/tempest/api/network/admin/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api/network/admin/__init__.py
diff --git a/tempest/api/network/admin/test_dhcp_agent_scheduler.py b/tempest/api/network/admin/test_dhcp_agent_scheduler.py
new file mode 100644
index 0000000..ac10e68
--- /dev/null
+++ b/tempest/api/network/admin/test_dhcp_agent_scheduler.py
@@ -0,0 +1,78 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM Corp.
+#
+#    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.network import base
+from tempest.test import attr
+
+
+class DHCPAgentSchedulersTestJSON(base.BaseAdminNetworkTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(DHCPAgentSchedulersTestJSON, cls).setUpClass()
+        # Create a network and make sure it will be hosted by a
+        # dhcp agent.
+        cls.network = cls.create_network()
+        cls.subnet = cls.create_subnet(cls.network)
+        cls.cidr = cls.subnet['cidr']
+        cls.port = cls.create_port(cls.network)
+
+    @attr(type='smoke')
+    def test_list_dhcp_agent_hosting_network(self):
+        resp, body = self.admin_client.list_dhcp_agent_hosting_network(
+            self.network['id'])
+        self.assertEqual(resp['status'], '200')
+
+    @attr(type='smoke')
+    def test_list_networks_hosted_by_one_dhcp(self):
+        resp, body = self.admin_client.list_dhcp_agent_hosting_network(
+            self.network['id'])
+        agents = body['agents']
+        self.assertIsNotNone(agents)
+        agent = agents[0]
+        self.assertTrue(self._check_network_in_dhcp_agent(
+            self.network['id'], agent))
+
+    def _check_network_in_dhcp_agent(self, network_id, agent):
+        network_ids = []
+        resp, body = self.admin_client.list_networks_hosted_by_one_dhcp_agent(
+            agent['id'])
+        self.assertEqual(resp['status'], '200')
+        networks = body['networks']
+        for network in networks:
+            network_ids.append(network['id'])
+        return network_id in network_ids
+
+    @attr(type='smoke')
+    def test_remove_network_from_dhcp_agent(self):
+        resp, body = self.admin_client.list_dhcp_agent_hosting_network(
+            self.network['id'])
+        agents = body['agents']
+        self.assertIsNotNone(agents)
+        # Get an agent.
+        agent = agents[0]
+        network_id = self.network['id']
+        resp, body = self.admin_client.remove_network_from_dhcp_agent(
+            agent_id=agent['id'],
+            network_id=network_id)
+        self.assertEqual(resp['status'], '204')
+        self.assertFalse(self._check_network_in_dhcp_agent(
+            network_id, agent))
+
+
+class DHCPAgentSchedulersTestXML(DHCPAgentSchedulersTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/network/admin/test_l3_agent_scheduler.py b/tempest/api/network/admin/test_l3_agent_scheduler.py
new file mode 100644
index 0000000..9c187fd
--- /dev/null
+++ b/tempest/api/network/admin/test_l3_agent_scheduler.py
@@ -0,0 +1,64 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM Corp.
+#
+#    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.network import base
+from tempest.common.utils import data_utils
+from tempest.test import attr
+
+
+class L3AgentSchedulerJSON(base.BaseAdminNetworkTest):
+    _interface = 'json'
+
+    """
+    Tests the following operations in the Neutron API using the REST client for
+    Neutron:
+
+        List routers that the given L3 agent is hosting.
+        List L3 agents hosting the given router.
+
+    v2.0 of the Neutron API is assumed. It is also assumed that the following
+    options are defined in the [network] section of etc/tempest.conf:
+    """
+
+    @classmethod
+    def setUpClass(cls):
+        super(L3AgentSchedulerJSON, cls).setUpClass()
+
+    @attr(type='smoke')
+    def test_list_routers_on_l3_agent(self):
+        resp, body = self.admin_client.list_agents()
+        agents = body['agents']
+        for a in agents:
+            if a['agent_type'] == 'L3 agent':
+                agent = a
+        resp, body = self.admin_client.list_routers_on_l3_agent(
+            agent['id'])
+        self.assertEqual('200', resp['status'])
+
+    @attr(type='smoke')
+    def test_list_l3_agents_hosting_router(self):
+        name = data_utils.rand_name('router-')
+        resp, router = self.client.create_router(name)
+        self.assertEqual('201', resp['status'])
+        resp, body = self.admin_client.list_l3_agents_hosting_router(
+            router['router']['id'])
+        self.assertEqual('200', resp['status'])
+        resp, _ = self.client.delete_router(router['router']['id'])
+        self.assertEqual(204, resp.status)
+
+
+class L3AgentSchedulerXML(L3AgentSchedulerJSON):
+    _interface = 'xml'
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index ed915c1..61af91f 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -18,7 +18,7 @@
 import netaddr
 
 from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.openstack.common import log as logging
 import tempest.test
@@ -65,9 +65,13 @@
         cls.members = []
         cls.health_monitors = []
         cls.vpnservices = []
+        cls.ikepolicies = []
 
     @classmethod
     def tearDownClass(cls):
+        # Clean up ike policies
+        for ikepolicy in cls.ikepolicies:
+            cls.client.delete_ike_policy(ikepolicy['id'])
         # Clean up vpn services
         for vpnservice in cls.vpnservices:
             cls.client.delete_vpn_service(vpnservice['id'])
@@ -105,7 +109,7 @@
     @classmethod
     def create_network(cls, network_name=None):
         """Wrapper utility that returns a test network."""
-        network_name = network_name or rand_name('test-network-')
+        network_name = network_name or data_utils.rand_name('test-network-')
 
         resp, body = cls.client.create_network(network_name)
         network = body['network']
@@ -211,11 +215,19 @@
         """Wrapper utility that returns a test vpn service."""
         resp, body = cls.client.create_vpn_service(
             subnet_id, router_id, admin_state_up=True,
-            name=rand_name("vpnservice-"))
+            name=data_utils.rand_name("vpnservice-"))
         vpnservice = body['vpnservice']
         cls.vpnservices.append(vpnservice)
         return vpnservice
 
+    @classmethod
+    def create_ike_policy(cls, name):
+        """Wrapper utility that returns a test ike policy."""
+        resp, body = cls.client.create_ike_policy(name)
+        ikepolicy = body['ikepolicy']
+        cls.ikepolicies.append(ikepolicy)
+        return ikepolicy
+
 
 class BaseAdminNetworkTest(BaseNetworkTest):
 
diff --git a/tempest/api/network/common.py b/tempest/api/network/common.py
index 43e7f68..ab19fa8 100644
--- a/tempest/api/network/common.py
+++ b/tempest/api/network/common.py
@@ -94,3 +94,18 @@
 
     def delete(self):
         self.client.delete_port(self.id)
+
+
+class DeletableSecurityGroup(DeletableResource):
+
+    def delete(self):
+        self.client.delete_security_group(self.id)
+
+
+class DeletableSecurityGroupRule(DeletableResource):
+
+    def __repr__(self):
+        return '<%s id="%s">' % (self.__class__.__name__, self.id)
+
+    def delete(self):
+        self.client.delete_security_group_rule(self.id)
diff --git a/tempest/api/network/test_floating_ips.py b/tempest/api/network/test_floating_ips.py
index 9acb6c5..35d4fa8 100644
--- a/tempest/api/network/test_floating_ips.py
+++ b/tempest/api/network/test_floating_ips.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.network import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 
 
@@ -48,7 +48,7 @@
         cls.network = cls.create_network()
         cls.subnet = cls.create_subnet(cls.network)
         cls.router = cls.create_router(
-            rand_name('router-'),
+            data_utils.rand_name('router-'),
             external_network_id=cls.network_cfg.public_network_id)
         resp, _ = cls.client.add_router_interface_with_subnet_id(
             cls.router['id'], cls.subnet['id'])
diff --git a/tempest/api/network/test_load_balancer.py b/tempest/api/network/test_load_balancer.py
index e3bf4e8..7e4ec37 100644
--- a/tempest/api/network/test_load_balancer.py
+++ b/tempest/api/network/test_load_balancer.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.network import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 
 
@@ -45,8 +45,8 @@
         cls.network = cls.create_network()
         cls.name = cls.network['name']
         cls.subnet = cls.create_subnet(cls.network)
-        pool_name = rand_name('pool-')
-        vip_name = rand_name('vip-')
+        pool_name = data_utils.rand_name('pool-')
+        vip_name = data_utils.rand_name('vip-')
         cls.pool = cls.create_pool(pool_name, "ROUND_ROBIN",
                                    "HTTP", cls.subnet)
         cls.vip = cls.create_vip(vip_name, "HTTP", 80, cls.subnet, cls.pool)
@@ -68,8 +68,8 @@
 
     def test_create_update_delete_pool_vip(self):
         # Creates a vip
-        name = rand_name('vip-')
-        resp, body = self.client.create_pool(rand_name("pool-"),
+        name = data_utils.rand_name('vip-')
+        resp, body = self.client.create_pool(data_utils.rand_name("pool-"),
                                              "ROUND_ROBIN", "HTTP",
                                              self.subnet['id'])
         pool = body['pool']
@@ -134,7 +134,7 @@
     @attr(type='smoke')
     def test_create_update_delete_member(self):
         # Creates a member
-        resp, body = self.client.create_member("10.0.9.46", 80,
+        resp, body = self.client.create_member("10.0.9.47", 80,
                                                self.pool['id'])
         self.assertEqual('201', resp['status'])
         member = body['member']
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index f2df1ee..14c8500 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -18,7 +18,7 @@
 import netaddr
 
 from tempest.api.network import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.test import attr
 
@@ -66,7 +66,7 @@
     @attr(type='smoke')
     def test_create_update_delete_network_subnet(self):
         # Creates a network
-        name = rand_name('network-')
+        name = data_utils.rand_name('network-')
         resp, body = self.client.create_network(name)
         self.assertEqual('201', resp['status'])
         network = body['network']
@@ -186,19 +186,19 @@
 
     @attr(type=['negative', 'smoke'])
     def test_show_non_existent_network(self):
-        non_exist_id = rand_name('network')
+        non_exist_id = data_utils.rand_name('network')
         self.assertRaises(exceptions.NotFound, self.client.show_network,
                           non_exist_id)
 
     @attr(type=['negative', 'smoke'])
     def test_show_non_existent_subnet(self):
-        non_exist_id = rand_name('subnet')
+        non_exist_id = data_utils.rand_name('subnet')
         self.assertRaises(exceptions.NotFound, self.client.show_subnet,
                           non_exist_id)
 
     @attr(type=['negative', 'smoke'])
     def test_show_non_existent_port(self):
-        non_exist_id = rand_name('port')
+        non_exist_id = data_utils.rand_name('port')
         self.assertRaises(exceptions.NotFound, self.client.show_port,
                           non_exist_id)
 
@@ -274,7 +274,8 @@
     @attr(type='smoke')
     def test_bulk_create_delete_network(self):
         # Creates 2 networks in one request
-        network_names = [rand_name('network-'), rand_name('network-')]
+        network_names = [data_utils.rand_name('network-'),
+                         data_utils.rand_name('network-')]
         resp, body = self.client.create_bulk_network(2, network_names)
         created_networks = body['networks']
         self.assertEqual('201', resp['status'])
@@ -299,7 +300,7 @@
         names = []
         networks = [self.network1['id'], self.network2['id']]
         for i in range(len(networks)):
-            names.append(rand_name('subnet-'))
+            names.append(data_utils.rand_name('subnet-'))
         subnet_list = []
         # TODO(raies): "for IPv6, version list [4, 6] will be used.
         # and cidr for IPv6 will be of IPv6"
@@ -332,7 +333,7 @@
         names = []
         networks = [self.network1['id'], self.network2['id']]
         for i in range(len(networks)):
-            names.append(rand_name('port-'))
+            names.append(data_utils.rand_name('port-'))
         port_list = []
         state = [True, False]
         for i in range(len(names)):
diff --git a/tempest/api/network/test_quotas.py b/tempest/api/network/test_quotas.py
index 51395ea..f7ba3cb 100644
--- a/tempest/api/network/test_quotas.py
+++ b/tempest/api/network/test_quotas.py
@@ -18,7 +18,7 @@
 
 from tempest.api.network import base
 from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 
 
@@ -55,8 +55,8 @@
     @attr(type='gate')
     def test_quotas(self):
         # Add a tenant to conduct the test
-        test_tenant = rand_name('test_tenant_')
-        test_description = rand_name('desc_')
+        test_tenant = data_utils.rand_name('test_tenant_')
+        test_description = data_utils.rand_name('desc_')
         _, tenant = self.identity_admin_client.create_tenant(
             name=test_tenant,
             description=test_description)
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index 512d065..3cbe23f 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.network import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 
 
@@ -57,7 +57,7 @@
         # Create a router
         # NOTE(salv-orlando): Do not invoke self.create_router
         # as we need to check the response code
-        name = rand_name('router-')
+        name = data_utils.rand_name('router-')
         resp, create_body = self.client.create_router(
             name, external_gateway_info={
                 "network_id": self.network_cfg.public_network_id},
@@ -99,15 +99,15 @@
     def test_add_remove_router_interface_with_subnet_id(self):
         network = self.create_network()
         subnet = self.create_subnet(network)
-        router = self.create_router(rand_name('router-'))
+        router = self.create_router(data_utils.rand_name('router-'))
         # Add router interface with subnet id
         resp, interface = self.client.add_router_interface_with_subnet_id(
             router['id'], subnet['id'])
         self.assertEqual('200', resp['status'])
         self.addCleanup(self._remove_router_interface_with_subnet_id,
                         router['id'], subnet['id'])
-        self.assertTrue('subnet_id' in interface.keys())
-        self.assertTrue('port_id' in interface.keys())
+        self.assertIn('subnet_id', interface.keys())
+        self.assertIn('port_id', interface.keys())
         # Verify router id is equal to device id in port details
         resp, show_port_body = self.client.show_port(
             interface['port_id'])
@@ -118,7 +118,7 @@
     def test_add_remove_router_interface_with_port_id(self):
         network = self.create_network()
         self.create_subnet(network)
-        router = self.create_router(rand_name('router-'))
+        router = self.create_router(data_utils.rand_name('router-'))
         resp, port_body = self.client.create_port(network['id'])
         # add router interface to port created above
         resp, interface = self.client.add_router_interface_with_port_id(
@@ -126,8 +126,8 @@
         self.assertEqual('200', resp['status'])
         self.addCleanup(self._remove_router_interface_with_port_id,
                         router['id'], port_body['port']['id'])
-        self.assertTrue('subnet_id' in interface.keys())
-        self.assertTrue('port_id' in interface.keys())
+        self.assertIn('subnet_id', interface.keys())
+        self.assertIn('port_id', interface.keys())
         # Verify router id is equal to device id in port details
         resp, show_port_body = self.client.show_port(
             interface['port_id'])
@@ -160,7 +160,7 @@
 
     @attr(type='smoke')
     def test_update_router_set_gateway(self):
-        router = self.create_router(rand_name('router-'))
+        router = self.create_router(data_utils.rand_name('router-'))
         self.client.update_router(
             router['id'],
             external_gateway_info={
@@ -175,7 +175,7 @@
 
     @attr(type='smoke')
     def test_update_router_set_gateway_with_snat_explicit(self):
-        router = self.create_router(rand_name('router-'))
+        router = self.create_router(data_utils.rand_name('router-'))
         self.admin_client.update_router_with_snat_gw_info(
             router['id'],
             external_gateway_info={
@@ -189,7 +189,7 @@
 
     @attr(type='smoke')
     def test_update_router_set_gateway_without_snat(self):
-        router = self.create_router(rand_name('router-'))
+        router = self.create_router(data_utils.rand_name('router-'))
         self.admin_client.update_router_with_snat_gw_info(
             router['id'],
             external_gateway_info={
@@ -204,7 +204,7 @@
     @attr(type='smoke')
     def test_update_router_unset_gateway(self):
         router = self.create_router(
-            rand_name('router-'),
+            data_utils.rand_name('router-'),
             external_network_id=self.network_cfg.public_network_id)
         self.client.update_router(router['id'], external_gateway_info={})
         self._verify_router_gateway(router['id'])
@@ -217,7 +217,7 @@
     @attr(type='smoke')
     def test_update_router_reset_gateway_without_snat(self):
         router = self.create_router(
-            rand_name('router-'),
+            data_utils.rand_name('router-'),
             external_network_id=self.network_cfg.public_network_id)
         self.admin_client.update_router_with_snat_gw_info(
             router['id'],
diff --git a/tempest/api/network/test_security_groups_negative.py b/tempest/api/network/test_security_groups_negative.py
index cb0c247..32f4c95 100644
--- a/tempest/api/network/test_security_groups_negative.py
+++ b/tempest/api/network/test_security_groups_negative.py
@@ -15,10 +15,11 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import uuid
+
 from tempest.api.network import base_security_groups as base
 from tempest import exceptions
 from tempest.test import attr
-import uuid
 
 
 class NegativeSecGroupTest(base.BaseSecGroupTest):
@@ -74,6 +75,22 @@
                                    port_range_max=pmax)
             self.assertIn(msg, str(ex))
 
+    @attr(type=['negative', 'smoke'])
+    def test_create_additional_default_security_group_fails(self):
+        # Create security group named 'default', it should be failed.
+        name = 'default'
+        self.assertRaises(exceptions.Conflict,
+                          self.client.create_security_group,
+                          name)
+
+    @attr(type=['negative', 'smoke'])
+    def test_create_security_group_rule_with_non_existent_security_group(self):
+        # Create security group rules with not existing security group.
+        non_existent_sg = str(uuid.uuid4())
+        self.assertRaises(exceptions.NotFound,
+                          self.client.create_security_group_rule,
+                          non_existent_sg)
+
 
 class NegativeSecGroupTestXML(NegativeSecGroupTest):
     _interface = 'xml'
diff --git a/tempest/api/network/test_service_type_management.py b/tempest/api/network/test_service_type_management.py
new file mode 100644
index 0000000..ae03e96
--- /dev/null
+++ b/tempest/api/network/test_service_type_management.py
@@ -0,0 +1,30 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+#    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.network import base
+from tempest.test import attr
+
+
+class ServiceTypeManagementTestJSON(base.BaseNetworkTest):
+    _interface = 'json'
+
+    @attr(type='smoke')
+    def test_service_provider_list(self):
+        resp, body = self.client.list_service_providers()
+        self.assertEqual(resp['status'], '200')
+        self.assertIsInstance(body['service_providers'], list)
+
+
+class ServiceTypeManagementTestXML(ServiceTypeManagementTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/network/test_vpnaas_extensions.py b/tempest/api/network/test_vpnaas_extensions.py
index 7a8128b..63a8e24 100644
--- a/tempest/api/network/test_vpnaas_extensions.py
+++ b/tempest/api/network/test_vpnaas_extensions.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.network import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 
 
@@ -32,6 +32,7 @@
         Create VPN Services
         Update VPN Services
         Delete VPN Services
+        List, Show, Create, Delete, and Update IKE policy
     """
 
     @classmethod
@@ -39,10 +40,30 @@
         super(VPNaaSJSON, cls).setUpClass()
         cls.network = cls.create_network()
         cls.subnet = cls.create_subnet(cls.network)
-        cls.router = cls.create_router(rand_name("router-"))
+        cls.router = cls.create_router(
+            data_utils.rand_name("router-"),
+            external_network_id=cls.network_cfg.public_network_id)
         cls.create_router_interface(cls.router['id'], cls.subnet['id'])
         cls.vpnservice = cls.create_vpnservice(cls.subnet['id'],
                                                cls.router['id'])
+        cls.ikepolicy = cls.create_ike_policy(data_utils.rand_name(
+                                              "ike-policy-"))
+
+    def _delete_ike_policy(self, ike_policy_id):
+        # Deletes a ike policy and verifies if it is deleted or not
+        ike_list = list()
+        resp, all_ike = self.client.list_ike_policies()
+        for ike in all_ike['ikepolicies']:
+            ike_list.append(ike['id'])
+        if ike_policy_id in ike_list:
+            resp, _ = self.client.delete_ike_policy(ike_policy_id)
+            self.assertEqual(204, resp.status)
+            # Asserting that the policy is not found in list after deletion
+            resp, ikepolicies = self.client.list_ike_policies()
+            ike_id_list = list()
+            for i in ikepolicies['ikepolicies']:
+                ike_id_list.append(i['id'])
+            self.assertNotIn(ike_policy_id, ike_id_list)
 
     @attr(type='smoke')
     def test_list_vpn_services(self):
@@ -55,7 +76,7 @@
     @attr(type='smoke')
     def test_create_update_delete_vpn_service(self):
         # Creates a VPN service
-        name = rand_name('vpn-service-')
+        name = data_utils.rand_name('vpn-service-')
         resp, body = self.client.create_vpn_service(self.subnet['id'],
                                                     self.router['id'],
                                                     name=name,
@@ -94,3 +115,59 @@
         self.assertEqual(self.vpnservice['router_id'], vpnservice['router_id'])
         self.assertEqual(self.vpnservice['subnet_id'], vpnservice['subnet_id'])
         self.assertEqual(self.vpnservice['tenant_id'], vpnservice['tenant_id'])
+
+    @attr(type='smoke')
+    def test_list_ike_policies(self):
+        # Verify the ike policy exists in the list of all IKE policies
+        resp, body = self.client.list_ike_policies()
+        self.assertEqual('200', resp['status'])
+        ikepolicies = body['ikepolicies']
+        self.assertIn(self.ikepolicy['id'], [i['id'] for i in ikepolicies])
+
+    @attr(type='smoke')
+    def test_create_update_delete_ike_policy(self):
+        # Creates a IKE policy
+        name = data_utils.rand_name('ike-policy-')
+        resp, body = (self.client.create_ike_policy(
+                      name,
+                      ike_version="v1",
+                      encryption_algorithm="aes-128",
+                      auth_algorithm="sha1"))
+        self.assertEqual('201', resp['status'])
+        ikepolicy = body['ikepolicy']
+        self.addCleanup(self._delete_ike_policy, ikepolicy['id'])
+        # Verification of ike policy update
+        description = "Updated ike policy"
+        new_ike = {'description': description, 'pfs': 'group5',
+                   'name': data_utils.rand_name("New-IKE-")}
+        resp, body = self.client.update_ike_policy(ikepolicy['id'],
+                                                   **new_ike)
+        self.assertEqual('200', resp['status'])
+        updated_ike_policy = body['ikepolicy']
+        self.assertEqual(updated_ike_policy['description'], description)
+        # Verification of ike policy delete
+        resp, body = self.client.delete_ike_policy(ikepolicy['id'])
+        self.assertEqual('204', resp['status'])
+
+    @attr(type='smoke')
+    def test_show_ike_policy(self):
+        # Verifies the details of a ike policy
+        resp, body = self.client.show_ike_policy(self.ikepolicy['id'])
+        self.assertEqual('200', resp['status'])
+        ikepolicy = body['ikepolicy']
+        self.assertEqual(self.ikepolicy['id'], ikepolicy['id'])
+        self.assertEqual(self.ikepolicy['name'], ikepolicy['name'])
+        self.assertEqual(self.ikepolicy['description'],
+                         ikepolicy['description'])
+        self.assertEqual(self.ikepolicy['encryption_algorithm'],
+                         ikepolicy['encryption_algorithm'])
+        self.assertEqual(self.ikepolicy['auth_algorithm'],
+                         ikepolicy['auth_algorithm'])
+        self.assertEqual(self.ikepolicy['tenant_id'],
+                         ikepolicy['tenant_id'])
+        self.assertEqual(self.ikepolicy['pfs'],
+                         ikepolicy['pfs'])
+        self.assertEqual(self.ikepolicy['phase1_negotiation_mode'],
+                         ikepolicy['phase1_negotiation_mode'])
+        self.assertEqual(self.ikepolicy['ike_version'],
+                         ikepolicy['ike_version'])
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index c6639c2..e7cb806 100644
--- a/tempest/api/object_storage/base.py
+++ b/tempest/api/object_storage/base.py
@@ -18,6 +18,7 @@
 
 from tempest.api.identity.base import DataGenerator
 from tempest import clients
+from tempest.common import custom_matchers
 from tempest.common import isolated_creds
 from tempest import exceptions
 import tempest.test
@@ -120,3 +121,12 @@
                 container_client.delete_container(cont)
             except exceptions.NotFound:
                 pass
+
+    def assertHeaders(self, resp, target, method):
+        """
+        Common method to check the existence and the format of common response
+        headers
+        """
+        self.assertThat(resp, custom_matchers.ExistsAllResponseHeaders(
+                        target, method))
+        self.assertThat(resp, custom_matchers.AreAllWellFormatted())
diff --git a/tempest/api/object_storage/test_account_quotas.py b/tempest/api/object_storage/test_account_quotas.py
index a90d3f4..c1b3391 100644
--- a/tempest/api/object_storage/test_account_quotas.py
+++ b/tempest/api/object_storage/test_account_quotas.py
@@ -18,8 +18,7 @@
 
 from tempest.api.object_storage import base
 from tempest import clients
-from tempest.common.utils.data_utils import arbitrary_string
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import config
 from tempest import exceptions
 from tempest.test import attr
@@ -32,7 +31,7 @@
     @classmethod
     def setUpClass(cls):
         super(AccountQuotasTest, cls).setUpClass()
-        cls.container_name = rand_name(name="TestContainer")
+        cls.container_name = data_utils.rand_name(name="TestContainer")
         cls.container_client.create_container(cls.container_name)
 
         cls.data.setup_test_user()
@@ -102,19 +101,20 @@
                       "Account Quotas middleware not available")
     @attr(type="smoke")
     def test_upload_valid_object(self):
-        object_name = rand_name(name="TestObject")
-        data = arbitrary_string()
+        object_name = data_utils.rand_name(name="TestObject")
+        data = data_utils.arbitrary_string()
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, data)
 
         self.assertEqual(resp["status"], "201")
+        self.assertHeaders(resp, 'Object', 'PUT')
 
     @testtools.skipIf(not accounts_quotas_available,
                       "Account Quotas middleware not available")
     @attr(type=["negative", "smoke"])
     def test_upload_large_object(self):
-        object_name = rand_name(name="TestObject")
-        data = arbitrary_string(30)
+        object_name = data_utils.rand_name(name="TestObject")
+        data = data_utils.arbitrary_string(30)
         self.assertRaises(exceptions.OverLimit,
                           self.object_client.create_object,
                           self.container_name, object_name, data)
@@ -142,6 +142,7 @@
                                                             headers, "")
 
             self.assertEqual(resp["status"], "204")
+            self.assertHeaders(resp, 'Account', 'POST')
 
     @testtools.skipIf(not accounts_quotas_available,
                       "Account Quotas middleware not available")
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index 90b0914..12c823b 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -18,7 +18,7 @@
 import random
 
 from tempest.api.object_storage import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.test import attr
 from tempest.test import HTTP_SUCCESS
@@ -30,7 +30,7 @@
         super(AccountTest, cls).setUpClass()
         cls.containers = []
         for i in xrange(ord('a'), ord('f') + 1):
-            name = rand_name(name='%s-' % chr(i))
+            name = data_utils.rand_name(name='%s-' % chr(i))
             cls.container_client.create_container(name)
             cls.containers.append(name)
         cls.containers_count = len(cls.containers)
@@ -46,6 +46,7 @@
         params = {'format': 'json'}
         resp, container_list = \
             self.account_client.list_account_containers(params=params)
+        self.assertHeaders(resp, 'Account', 'GET')
 
         self.assertIsNotNone(container_list)
         container_names = [c['name'] for c in container_list]
@@ -59,6 +60,8 @@
             params = {'limit': limit}
             resp, container_list = \
                 self.account_client.list_account_containers(params=params)
+            self.assertHeaders(resp, 'Account', 'GET')
+
             self.assertEqual(len(container_list), limit)
 
     @attr(type='smoke')
@@ -70,10 +73,15 @@
         params = {'marker': self.containers[-1]}
         resp, container_list = \
             self.account_client.list_account_containers(params=params)
+        self.assertHeaders(resp, 'Account', 'GET')
+
         self.assertEqual(len(container_list), 0)
+
         params = {'marker': self.containers[self.containers_count / 2]}
         resp, container_list = \
             self.account_client.list_account_containers(params=params)
+        self.assertHeaders(resp, 'Account', 'GET')
+
         self.assertEqual(len(container_list), self.containers_count / 2 - 1)
 
     @attr(type='smoke')
@@ -85,10 +93,13 @@
         params = {'end_marker': self.containers[0]}
         resp, container_list = \
             self.account_client.list_account_containers(params=params)
+        self.assertHeaders(resp, 'Account', 'GET')
         self.assertEqual(len(container_list), 0)
+
         params = {'end_marker': self.containers[self.containers_count / 2]}
         resp, container_list = \
             self.account_client.list_account_containers(params=params)
+        self.assertHeaders(resp, 'Account', 'GET')
         self.assertEqual(len(container_list), self.containers_count / 2)
 
     @attr(type='smoke')
@@ -101,6 +112,8 @@
                       'limit': limit}
             resp, container_list = \
                 self.account_client.list_account_containers(params=params)
+            self.assertHeaders(resp, 'Account', 'GET')
+
             self.assertTrue(len(container_list) <= limit, str(container_list))
 
     @attr(type='smoke')
@@ -108,9 +121,7 @@
         # list all account metadata
         resp, metadata = self.account_client.list_account_metadata()
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
-        self.assertIn('x-account-object-count', resp)
-        self.assertIn('x-account-container-count', resp)
-        self.assertIn('x-account-bytes-used', resp)
+        self.assertHeaders(resp, 'Account', 'HEAD')
 
     @attr(type='smoke')
     def test_create_and_delete_account_metadata(self):
@@ -120,8 +131,11 @@
         resp, _ = self.account_client.create_account_metadata(
             metadata={header: data})
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Account', 'POST')
 
         resp, _ = self.account_client.list_account_metadata()
+        self.assertHeaders(resp, 'Account', 'HEAD')
+
         self.assertIn('x-account-meta-' + header, resp)
         self.assertEqual(resp['x-account-meta-' + header], data)
 
@@ -129,8 +143,10 @@
         resp, _ = \
             self.account_client.delete_account_metadata(metadata=[header])
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Account', 'POST')
 
         resp, _ = self.account_client.list_account_metadata()
+        self.assertHeaders(resp, 'Account', 'HEAD')
         self.assertNotIn('x-account-meta-' + header, resp)
 
     @attr(type=['negative', 'gate'])
diff --git a/tempest/api/object_storage/test_container_acl.py b/tempest/api/object_storage/test_container_acl.py
index de5307a..b2dc20f 100644
--- a/tempest/api/object_storage/test_container_acl.py
+++ b/tempest/api/object_storage/test_container_acl.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.object_storage import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.test import attr
 from tempest.test import HTTP_SUCCESS
@@ -39,7 +39,7 @@
 
     def setUp(self):
         super(ObjectTestACLs, self).setUp()
-        self.container_name = rand_name(name='TestContainer')
+        self.container_name = data_utils.rand_name(name='TestContainer')
         self.container_client.create_container(self.container_name)
 
     def tearDown(self):
@@ -50,7 +50,7 @@
     def test_write_object_without_using_creds(self):
         # trying to create object with empty headers
         # X-Auth-Token is not provided
-        object_name = rand_name(name='Object')
+        object_name = data_utils.rand_name(name='Object')
         self.assertRaises(exceptions.Unauthorized,
                           self.custom_object_client.create_object,
                           self.container_name, object_name, 'data')
@@ -58,7 +58,7 @@
     @attr(type=['negative', 'gate'])
     def test_delete_object_without_using_creds(self):
         # create object
-        object_name = rand_name(name='Object')
+        object_name = data_utils.rand_name(name='Object')
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, 'data')
         # trying to delete object with empty headers
@@ -71,7 +71,7 @@
     def test_write_object_with_non_authorized_user(self):
         # attempt to upload another file using non-authorized user
         # User provided token is forbidden. ACL are not set
-        object_name = rand_name(name='Object')
+        object_name = data_utils.rand_name(name='Object')
         # trying to create object with non-authorized user
         self.assertRaises(exceptions.Unauthorized,
                           self.custom_object_client.create_object,
@@ -82,10 +82,11 @@
     def test_read_object_with_non_authorized_user(self):
         # attempt to read object using non-authorized user
         # User provided token is forbidden. ACL are not set
-        object_name = rand_name(name='Object')
+        object_name = data_utils.rand_name(name='Object')
         resp, _ = self.object_client.create_object(
             self.container_name, object_name, 'data')
         self.assertEqual(resp['status'], '201')
+        self.assertHeaders(resp, 'Object', 'PUT')
         # trying to get object with non authorized user token
         self.assertRaises(exceptions.Unauthorized,
                           self.custom_object_client.get_object,
@@ -96,10 +97,11 @@
     def test_delete_object_with_non_authorized_user(self):
         # attempt to delete object using non-authorized user
         # User provided token is forbidden. ACL are not set
-        object_name = rand_name(name='Object')
+        object_name = data_utils.rand_name(name='Object')
         resp, _ = self.object_client.create_object(
             self.container_name, object_name, 'data')
         self.assertEqual(resp['status'], '201')
+        self.assertHeaders(resp, 'Object', 'PUT')
         # trying to delete object with non-authorized user token
         self.assertRaises(exceptions.Unauthorized,
                           self.custom_object_client.delete_object,
@@ -115,11 +117,13 @@
             self.container_name, metadata=cont_headers,
             metadata_prefix='')
         self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp_meta, 'Container', 'POST')
         # create object
-        object_name = rand_name(name='Object')
+        object_name = data_utils.rand_name(name='Object')
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, 'data')
         self.assertEqual(resp['status'], '201')
+        self.assertHeaders(resp, 'Object', 'PUT')
         # Trying to read the object without rights
         self.assertRaises(exceptions.Unauthorized,
                           self.custom_object_client.get_object,
@@ -135,8 +139,9 @@
             self.container_name, metadata=cont_headers,
             metadata_prefix='')
         self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp_meta, 'Container', 'POST')
         # Trying to write the object without rights
-        object_name = rand_name(name='Object')
+        object_name = data_utils.rand_name(name='Object')
         self.assertRaises(exceptions.Unauthorized,
                           self.custom_object_client.create_object,
                           self.container_name,
@@ -153,16 +158,19 @@
             self.container_name, metadata=cont_headers,
             metadata_prefix='')
         self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp_meta, 'Container', 'POST')
         # create object
-        object_name = rand_name(name='Object')
+        object_name = data_utils.rand_name(name='Object')
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, 'data')
         self.assertEqual(resp['status'], '201')
+        self.assertHeaders(resp, 'Object', 'PUT')
         # Trying to read the object with rights
         resp, _ = self.custom_object_client.get_object(
             self.container_name, object_name,
             metadata=self.custom_headers)
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Object', 'GET')
 
     @attr(type='smoke')
     def test_write_object_with_rights(self):
@@ -174,13 +182,15 @@
             self.container_name, metadata=cont_headers,
             metadata_prefix='')
         self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp_meta, 'Container', 'POST')
         # Trying to write the object with rights
-        object_name = rand_name(name='Object')
+        object_name = data_utils.rand_name(name='Object')
         resp, _ = self.custom_object_client.create_object(
             self.container_name,
             object_name, 'data',
             metadata=self.custom_headers)
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Object', 'PUT')
 
     @attr(type=['negative', 'smoke'])
     def test_write_object_without_write_rights(self):
@@ -193,8 +203,9 @@
             self.container_name, metadata=cont_headers,
             metadata_prefix='')
         self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp_meta, 'Container', 'POST')
         # Trying to write the object without write rights
-        object_name = rand_name(name='Object')
+        object_name = data_utils.rand_name(name='Object')
         self.assertRaises(exceptions.Unauthorized,
                           self.custom_object_client.create_object,
                           self.container_name,
@@ -212,11 +223,13 @@
             self.container_name, metadata=cont_headers,
             metadata_prefix='')
         self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp_meta, 'Container', 'POST')
         # create object
-        object_name = rand_name(name='Object')
+        object_name = data_utils.rand_name(name='Object')
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, 'data')
         self.assertEqual(resp['status'], '201')
+        self.assertHeaders(resp, 'Object', 'PUT')
         # Trying to delete the object without write rights
         self.assertRaises(exceptions.Unauthorized,
                           self.custom_object_client.delete_object,
diff --git a/tempest/api/object_storage/test_container_quotas.py b/tempest/api/object_storage/test_container_quotas.py
index 2e0d76a..c7b5e28 100644
--- a/tempest/api/object_storage/test_container_quotas.py
+++ b/tempest/api/object_storage/test_container_quotas.py
@@ -18,8 +18,7 @@
 import testtools
 
 from tempest.api.object_storage import base
-from tempest.common.utils.data_utils import arbitrary_string
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import config
 from tempest import exceptions
 from tempest.test import attr
@@ -46,7 +45,7 @@
                      Maximum object count of the container.
         """
         super(ContainerQuotasTest, self).setUp()
-        self.container_name = rand_name(name="TestContainer")
+        self.container_name = data_utils.rand_name(name="TestContainer")
         self.container_client.create_container(self.container_name)
         metadata = {"quota-bytes": str(QUOTA_BYTES),
                     "quota-count": str(QUOTA_COUNT), }
@@ -62,14 +61,15 @@
     @attr(type="smoke")
     def test_upload_valid_object(self):
         """Attempts to uploads an object smaller than the bytes quota."""
-        object_name = rand_name(name="TestObject")
-        data = arbitrary_string(QUOTA_BYTES)
+        object_name = data_utils.rand_name(name="TestObject")
+        data = data_utils.arbitrary_string(QUOTA_BYTES)
 
         nbefore = self._get_bytes_used()
 
         resp, _ = self.object_client.create_object(
             self.container_name, object_name, data)
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Object', 'PUT')
 
         nafter = self._get_bytes_used()
         self.assertEqual(nbefore + len(data), nafter)
@@ -78,8 +78,8 @@
     @attr(type="smoke")
     def test_upload_large_object(self):
         """Attempts to upload an object lagger than the bytes quota."""
-        object_name = rand_name(name="TestObject")
-        data = arbitrary_string(QUOTA_BYTES + 1)
+        object_name = data_utils.rand_name(name="TestObject")
+        data = data_utils.arbitrary_string(QUOTA_BYTES + 1)
 
         nbefore = self._get_bytes_used()
 
@@ -95,7 +95,7 @@
     def test_upload_too_many_objects(self):
         """Attempts to upload many objects that exceeds the count limit."""
         for _ in range(QUOTA_COUNT):
-            name = rand_name(name="TestObject")
+            name = data_utils.rand_name(name="TestObject")
             self.object_client.create_object(self.container_name, name, "")
 
         nbefore = self._get_object_count()
diff --git a/tempest/api/object_storage/test_container_services.py b/tempest/api/object_storage/test_container_services.py
index 4b49d73..04de072 100644
--- a/tempest/api/object_storage/test_container_services.py
+++ b/tempest/api/object_storage/test_container_services.py
@@ -16,8 +16,7 @@
 #    under the License.
 
 from tempest.api.object_storage import base
-from tempest.common.utils.data_utils import arbitrary_string
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 from tempest.test import HTTP_SUCCESS
 
@@ -35,20 +34,23 @@
 
     @attr(type='smoke')
     def test_create_container(self):
-        container_name = rand_name(name='TestContainer')
+        container_name = data_utils.rand_name(name='TestContainer')
         resp, body = self.container_client.create_container(container_name)
         self.containers.append(container_name)
         self.assertIn(resp['status'], ('202', '201'))
+        self.assertHeaders(resp, 'Container', 'PUT')
 
     @attr(type='smoke')
     def test_delete_container(self):
         # create a container
-        container_name = rand_name(name='TestContainer')
+        container_name = data_utils.rand_name(name='TestContainer')
         resp, _ = self.container_client.create_container(container_name)
         self.containers.append(container_name)
         # delete container
         resp, _ = self.container_client.delete_container(container_name)
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Container', 'DELETE')
+
         self.containers.remove(container_name)
 
     @attr(type='smoke')
@@ -56,17 +58,17 @@
         # add metadata to an object
 
         # create a container
-        container_name = rand_name(name='TestContainer')
+        container_name = data_utils.rand_name(name='TestContainer')
         resp, _ = self.container_client.create_container(container_name)
         self.containers.append(container_name)
         # create object
-        object_name = rand_name(name='TestObject')
-        data = arbitrary_string()
+        object_name = data_utils.rand_name(name='TestObject')
+        data = data_utils.arbitrary_string()
         resp, _ = self.object_client.create_object(container_name,
                                                    object_name, data)
         # set object metadata
-        meta_key = rand_name(name='Meta-Test-')
-        meta_value = rand_name(name='MetaValue-')
+        meta_key = data_utils.rand_name(name='Meta-Test-')
+        meta_value = data_utils.rand_name(name='MetaValue-')
         orig_metadata = {meta_key: meta_value}
         resp, _ = self.object_client.update_object_metadata(container_name,
                                                             object_name,
@@ -77,6 +79,8 @@
             self.container_client.\
             list_container_contents(container_name, params=params)
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Container', 'GET')
+
         self.assertIsNotNone(object_list)
 
         object_names = [obj['name'] for obj in object_list]
@@ -87,7 +91,7 @@
         # update/retrieve/delete container metadata
 
         # create a container
-        container_name = rand_name(name='TestContainer')
+        container_name = data_utils.rand_name(name='TestContainer')
         resp, _ = self.container_client.create_container(container_name)
         self.containers.append(container_name)
         # update container metadata
@@ -98,11 +102,14 @@
             self.container_client.update_container_metadata(container_name,
                                                             metadata=metadata)
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Container', 'POST')
 
         # list container metadata
         resp, _ = self.container_client.list_container_metadata(
             container_name)
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Container', 'HEAD')
+
         self.assertIn('x-container-meta-name', resp)
         self.assertIn('x-container-meta-description', resp)
         self.assertEqual(resp['x-container-meta-name'], 'Pictures')
@@ -113,9 +120,12 @@
             container_name,
             metadata=metadata.keys())
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Container', 'POST')
 
         # check if the metadata are no longer there
         resp, _ = self.container_client.list_container_metadata(container_name)
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Container', 'HEAD')
+
         self.assertNotIn('x-container-meta-name', resp)
         self.assertNotIn('x-container-meta-description', resp)
diff --git a/tempest/api/object_storage/test_container_staticweb.py b/tempest/api/object_storage/test_container_staticweb.py
index d07697a..9f9abd8 100644
--- a/tempest/api/object_storage/test_container_staticweb.py
+++ b/tempest/api/object_storage/test_container_staticweb.py
@@ -15,9 +15,9 @@
 # under the License.
 
 from tempest.api.object_storage import base
-from tempest.common.utils.data_utils import arbitrary_string
-from tempest.common.utils.data_utils import rand_name
-from tempest.test import attr
+from tempest.common import custom_matchers
+from tempest.common.utils import data_utils
+from tempest import test
 
 
 class StaticWebTest(base.BaseObjectTest):
@@ -25,15 +25,15 @@
     @classmethod
     def setUpClass(cls):
         super(StaticWebTest, cls).setUpClass()
-        cls.container_name = rand_name(name="TestContainer")
+        cls.container_name = data_utils.rand_name(name="TestContainer")
 
         # This header should be posted on the container before every test
         cls.headers_public_read_acl = {'Read': '.r:*'}
 
         # Create test container and create one object in it
         cls.container_client.create_container(cls.container_name)
-        cls.object_name = rand_name(name="TestObject")
-        cls.object_data = arbitrary_string()
+        cls.object_name = data_utils.rand_name(name="TestObject")
+        cls.object_data = data_utils.arbitrary_string()
         cls.object_client.create_object(cls.container_name,
                                         cls.object_name,
                                         cls.object_data)
@@ -49,7 +49,7 @@
         cls.data.teardown_all()
         super(StaticWebTest, cls).tearDownClass()
 
-    @attr('gate')
+    @test.attr('gate')
     def test_web_index(self):
         headers = {'web-index': self.object_name}
 
@@ -60,7 +60,9 @@
         # we should retrieve the self.object_name file
         resp, body = self.custom_account_client.request("GET",
                                                         self.container_name)
-        self.assertEqual(resp['status'], '200')
+        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
+        # This request is equivalent to GET object
+        self.assertHeaders(resp, 'Object', 'GET')
         self.assertEqual(body, self.object_data)
 
         # clean up before exiting
@@ -71,7 +73,7 @@
             self.container_name)
         self.assertNotIn('x-container-meta-web-index', body)
 
-    @attr('gate')
+    @test.attr('gate')
     def test_web_listing(self):
         headers = {'web-listings': 'true'}
 
@@ -82,7 +84,16 @@
         # we should retrieve a listing of objects
         resp, body = self.custom_account_client.request("GET",
                                                         self.container_name)
-        self.assertEqual(resp['status'], '200')
+        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
+        # The target of the request is not any Swift resource. Therefore, the
+        # existence of response header is checked without a custom matcher.
+        self.assertIn('content-length', resp)
+        self.assertIn('content-type', resp)
+        self.assertIn('x-trans-id', resp)
+        self.assertIn('date', resp)
+        # Check only the format of common headers with custom matcher
+        self.assertThat(resp, custom_matchers.AreAllWellFormatted())
+
         self.assertIn(self.object_name, body)
 
         # clean up before exiting
@@ -92,3 +103,41 @@
         _, body = self.container_client.list_container_metadata(
             self.container_name)
         self.assertNotIn('x-container-meta-web-listings', body)
+
+    @test.attr('gate')
+    def test_web_listing_css(self):
+        headers = {'web-listings': 'true',
+                   'web-listings-css': 'listings.css'}
+
+        self.container_client.update_container_metadata(
+            self.container_name, metadata=headers)
+
+        # test GET on http://account_url/container_name
+        # we should retrieve a listing of objects
+        resp, body = self.custom_account_client.request("GET",
+                                                        self.container_name)
+        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
+        self.assertIn(self.object_name, body)
+        css = '<link rel="stylesheet" type="text/css" href="listings.css" />'
+        self.assertIn(css, body)
+
+    @test.attr('gate')
+    def test_web_error(self):
+        headers = {'web-listings': 'true',
+                   'web-error': self.object_name}
+
+        self.container_client.update_container_metadata(
+            self.container_name, metadata=headers)
+
+        # Create object to return when requested object not found
+        object_name_404 = "404" + self.object_name
+        object_data_404 = data_utils.arbitrary_string()
+        self.object_client.create_object(self.container_name,
+                                         object_name_404,
+                                         object_data_404)
+
+        # Request non-existing object
+        resp, body = self.custom_object_client.get_object(self.container_name,
+                                                          "notexisting")
+        self.assertEqual(resp['status'], '404')
+        self.assertEqual(body, object_data_404)
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index ff9f7bf..dcfe219 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -18,7 +18,7 @@
 import time
 
 from tempest.api.object_storage import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 from tempest.test import skip_because
 
@@ -37,9 +37,9 @@
             int(container_sync_timeout / cls.container_sync_interval)
         # define container and object clients
         cls.clients = {}
-        cls.clients[rand_name(name='TestContainerSync')] = \
+        cls.clients[data_utils.rand_name(name='TestContainerSync')] = \
             (cls.container_client, cls.object_client)
-        cls.clients[rand_name(name='TestContainerSync')] = \
+        cls.clients[data_utils.rand_name(name='TestContainerSync')] = \
             (cls.container_client_alt, cls.object_client_alt)
         for cont_name, client in cls.clients.items():
             client[0].create_container(cont_name)
@@ -71,8 +71,8 @@
                           'Error installing X-Container-Sync-To '
                           'for the container "%s"' % (cont[0]))
             # create object in container
-            object_name = rand_name(name='TestSyncObject')
-            data = object_name[::-1]  # arbitrary_string()
+            object_name = data_utils.rand_name(name='TestSyncObject')
+            data = object_name[::-1]  # data_utils.arbitrary_string()
             resp, _ = obj_client[0].create_object(cont[0], object_name, data)
             self.assertEqual(resp['status'], '201',
                              'Error creating the object "%s" in'
diff --git a/tempest/api/object_storage/test_crossdomain.py b/tempest/api/object_storage/test_crossdomain.py
new file mode 100644
index 0000000..51ecd16
--- /dev/null
+++ b/tempest/api/object_storage/test_crossdomain.py
@@ -0,0 +1,92 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
+#
+# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
+#
+# 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.object_storage import base
+from tempest import clients
+from tempest.common import custom_matchers
+from tempest import config
+from tempest.test import attr
+from tempest.test import HTTP_SUCCESS
+
+
+class CrossdomainTest(base.BaseObjectTest):
+    crossdomain_available = \
+        config.TempestConfig().object_storage_feature_enabled.crossdomain
+
+    @classmethod
+    def setUpClass(cls):
+        super(CrossdomainTest, cls).setUpClass()
+
+        # skip this test if CORS isn't enabled in the conf file.
+        if not cls.crossdomain_available:
+            skip_msg = ("%s skipped as Crossdomain middleware not available"
+                        % cls.__name__)
+            raise cls.skipException(skip_msg)
+
+        # creates a test user. The test user will set its base_url to the Swift
+        # endpoint and test the healthcheck feature.
+        cls.data.setup_test_user()
+
+        cls.os_test_user = clients.Manager(
+            cls.data.test_user,
+            cls.data.test_password,
+            cls.data.test_tenant)
+
+        cls.xml_start = '<?xml version="1.0"?>\n' \
+                        '<!DOCTYPE cross-domain-policy SYSTEM ' \
+                        '"http://www.adobe.com/xml/dtds/cross-domain-policy.' \
+                        'dtd" >\n<cross-domain-policy>\n'
+
+        cls.xml_end = "</cross-domain-policy>"
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.data.teardown_all()
+        super(CrossdomainTest, cls).tearDownClass()
+
+    def setUp(self):
+        super(CrossdomainTest, self).setUp()
+
+        client = self.os_test_user.account_client
+        client._set_auth()
+        # Turning http://.../v1/foobar into http://.../
+        client.base_url = "/".join(client.base_url.split("/")[:-2])
+
+    def tearDown(self):
+        # clear the base_url for subsequent requests
+        self.os_test_user.account_client.base_url = None
+
+        super(CrossdomainTest, self).tearDown()
+
+    @attr('gate')
+    def test_get_crossdomain_policy(self):
+        resp, body = self.os_test_user.account_client.get("crossdomain.xml",
+                                                          {})
+
+        self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertTrue(body.startswith(self.xml_start) and
+                        body.endswith(self.xml_end))
+
+        # The target of the request is not any Swift resource. Therefore, the
+        # existence of response header is checked without a custom matcher.
+        self.assertIn('content-length', resp)
+        self.assertIn('content-type', resp)
+        self.assertIn('x-trans-id', resp)
+        self.assertIn('date', resp)
+        # Check only the format of common headers with custom matcher
+        self.assertThat(resp, custom_matchers.AreAllWellFormatted())
diff --git a/tempest/api/object_storage/test_healthcheck.py b/tempest/api/object_storage/test_healthcheck.py
index 798ea4f..7bbdd1e 100644
--- a/tempest/api/object_storage/test_healthcheck.py
+++ b/tempest/api/object_storage/test_healthcheck.py
@@ -19,6 +19,7 @@
 
 from tempest.api.object_storage import base
 from tempest import clients
+from tempest.common import custom_matchers
 from tempest.test import attr
 from tempest.test import HTTP_SUCCESS
 
@@ -63,3 +64,12 @@
 
         # The status is expected to be 200
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+
+        # The target of the request is not any Swift resource. Therefore, the
+        # existence of response header is checked without a custom matcher.
+        self.assertIn('content-length', resp)
+        self.assertIn('content-type', resp)
+        self.assertIn('x-trans-id', resp)
+        self.assertIn('date', resp)
+        # Check only the format of common headers with custom matcher
+        self.assertThat(resp, custom_matchers.AreAllWellFormatted())
diff --git a/tempest/api/object_storage/test_object_expiry.py b/tempest/api/object_storage/test_object_expiry.py
index cb52d88..4958f70 100644
--- a/tempest/api/object_storage/test_object_expiry.py
+++ b/tempest/api/object_storage/test_object_expiry.py
@@ -18,8 +18,7 @@
 import time
 
 from tempest.api.object_storage import base
-from tempest.common.utils.data_utils import arbitrary_string
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.test import attr
 from tempest.test import skip_because
@@ -29,7 +28,7 @@
     @classmethod
     def setUpClass(cls):
         super(ObjectExpiryTest, cls).setUpClass()
-        cls.container_name = rand_name(name='TestContainer')
+        cls.container_name = data_utils.rand_name(name='TestContainer')
         cls.container_client.create_container(cls.container_name)
 
     @classmethod
@@ -49,8 +48,8 @@
         # "X-Delete-At", after this test case works.
 
         # create object
-        object_name = rand_name(name='TestObject')
-        data = arbitrary_string()
+        object_name = data_utils.rand_name(name='TestObject')
+        data = data_utils.arbitrary_string()
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, data)
         # update object metadata with expiry time of 3 seconds
@@ -63,10 +62,13 @@
             self.object_client.list_object_metadata(self.container_name,
                                                     object_name)
         self.assertEqual(resp['status'], '200')
+        self.assertHeaders(resp, 'Object', 'HEAD')
         self.assertIn('x-delete-at', resp)
         resp, body = self.object_client.get_object(self.container_name,
                                                    object_name)
         self.assertEqual(resp['status'], '200')
+        self.assertHeaders(resp, 'Object', 'GET')
+        self.assertIn('x-delete-at', resp)
         # check data
         self.assertEqual(body, data)
         # sleep for over 5 seconds, so that object expires
diff --git a/tempest/api/object_storage/test_object_formpost.py b/tempest/api/object_storage/test_object_formpost.py
new file mode 100644
index 0000000..817c892
--- /dev/null
+++ b/tempest/api/object_storage/test_object_formpost.py
@@ -0,0 +1,137 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
+#
+# Author: Christian Schwede <christian.schwede@enovance.com>
+#
+# 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 hashlib
+import hmac
+import time
+import urlparse
+
+from tempest.api.object_storage import base
+from tempest.common.utils import data_utils
+from tempest.test import attr
+from tempest.test import HTTP_SUCCESS
+
+
+class ObjectFormPostTest(base.BaseObjectTest):
+
+    @classmethod
+    def setUpClass(cls):
+        super(ObjectFormPostTest, cls).setUpClass()
+        cls.container_name = data_utils.rand_name(name='TestContainer')
+        cls.object_name = data_utils.rand_name(name='ObjectTemp')
+
+        cls.container_client.create_container(cls.container_name)
+        cls.containers = [cls.container_name]
+
+        cls.key = 'Meta'
+        cls.metadata = {'Temp-URL-Key': cls.key}
+        cls.account_client.create_account_metadata(metadata=cls.metadata)
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.account_client.delete_account_metadata(metadata=cls.metadata)
+        cls.delete_containers(cls.containers)
+        cls.data.teardown_all()
+        super(ObjectFormPostTest, cls).tearDownClass()
+
+    def get_multipart_form(self, expires=600):
+        path = "%s/%s/%s" % (
+            urlparse.urlparse(self.container_client.base_url).path,
+            self.container_name,
+            self.object_name)
+
+        redirect = ''
+        max_file_size = 104857600
+        max_file_count = 10
+        expires += int(time.time())
+        hmac_body = '%s\n%s\n%s\n%s\n%s' % (path,
+                                            redirect,
+                                            max_file_size,
+                                            max_file_count,
+                                            expires)
+
+        signature = hmac.new(self.key, hmac_body, hashlib.sha1).hexdigest()
+
+        fields = {'redirect': redirect,
+                  'max_file_size': str(max_file_size),
+                  'max_file_count': str(max_file_count),
+                  'expires': str(expires),
+                  'signature': signature}
+
+        boundary = '--boundary--'
+        data = []
+        for (key, value) in fields.items():
+            data.append('--' + boundary)
+            data.append('Content-Disposition: form-data; name="%s"' % key)
+            data.append('')
+            data.append(value)
+
+        data.append('--' + boundary)
+        data.append('Content-Disposition: form-data; '
+                    'name="file1"; filename="testfile"')
+        data.append('Content-Type: application/octet-stream')
+        data.append('')
+        data.append('hello world')
+
+        data.append('--' + boundary + '--')
+        data.append('')
+
+        body = '\r\n'.join(data)
+        content_type = 'multipart/form-data; boundary=%s' % boundary
+        return body, content_type
+
+    @attr(type='gate')
+    def test_post_object_using_form(self):
+        body, content_type = self.get_multipart_form()
+
+        headers = {'Content-Type': content_type,
+                   'Content-Length': str(len(body))}
+
+        url = "%s/%s/%s" % (self.container_client.base_url,
+                            self.container_name,
+                            self.object_name)
+
+        # Use a raw request, otherwise authentication headers are used
+        resp, body = self.object_client.http_obj.request(url, "POST",
+                                                         body, headers=headers)
+        self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, "Object", "POST")
+
+        # Ensure object is available
+        resp, body = self.object_client.get("%s/%s%s" % (
+            self.container_name, self.object_name, "testfile"))
+        self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, "Object", "GET")
+        self.assertEqual(body, "hello world")
+
+    @attr(type=['gate', 'negative'])
+    def test_post_object_using_form_expired(self):
+        body, content_type = self.get_multipart_form(expires=1)
+        time.sleep(2)
+
+        headers = {'Content-Type': content_type,
+                   'Content-Length': str(len(body))}
+
+        url = "%s/%s/%s" % (self.container_client.base_url,
+                            self.container_name,
+                            self.object_name)
+
+        # Use a raw request, otherwise authentication headers are used
+        resp, body = self.object_client.http_obj.request(url, "POST",
+                                                         body, headers=headers)
+        self.assertEqual(int(resp['status']), 401)
+        self.assertIn('FormPost: Form Expired', body)
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index 407c3ec..c7fdd0e 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -16,10 +16,11 @@
 #    under the License.
 
 import hashlib
+import re
 
 from tempest.api.object_storage import base
-from tempest.common.utils.data_utils import arbitrary_string
-from tempest.common.utils.data_utils import rand_name
+from tempest.common import custom_matchers
+from tempest.common.utils import data_utils
 from tempest.test import attr
 from tempest.test import HTTP_SUCCESS
 
@@ -28,7 +29,7 @@
     @classmethod
     def setUpClass(cls):
         super(ObjectTest, cls).setUpClass()
-        cls.container_name = rand_name(name='TestContainer')
+        cls.container_name = data_utils.rand_name(name='TestContainer')
         cls.container_client.create_container(cls.container_name)
         cls.containers = [cls.container_name]
 
@@ -51,52 +52,57 @@
     @attr(type='smoke')
     def test_create_object(self):
         # create object
-        object_name = rand_name(name='TestObject')
-        data = arbitrary_string()
+        object_name = data_utils.rand_name(name='TestObject')
+        data = data_utils.arbitrary_string()
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, data)
         # create another object
-        object_name = rand_name(name='TestObject')
-        data = arbitrary_string()
+        object_name = data_utils.rand_name(name='TestObject')
+        data = data_utils.arbitrary_string()
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, data)
         self.assertEqual(resp['status'], '201')
+        self.assertHeaders(resp, 'Object', 'PUT')
 
     @attr(type='smoke')
     def test_delete_object(self):
         # create object
-        object_name = rand_name(name='TestObject')
-        data = arbitrary_string()
+        object_name = data_utils.rand_name(name='TestObject')
+        data = data_utils.arbitrary_string()
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, data)
         # delete object
         resp, _ = self.object_client.delete_object(self.container_name,
                                                    object_name)
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Object', 'DELETE')
 
     @attr(type='smoke')
     def test_object_metadata(self):
         # add metadata to storage object, test if metadata is retrievable
 
         # create Object
-        object_name = rand_name(name='TestObject')
-        data = arbitrary_string()
+        object_name = data_utils.rand_name(name='TestObject')
+        data = data_utils.arbitrary_string()
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, data)
         # set object metadata
-        meta_key = rand_name(name='test-')
-        meta_value = rand_name(name='MetaValue-')
+        meta_key = data_utils.rand_name(name='test-')
+        meta_value = data_utils.rand_name(name='MetaValue-')
         orig_metadata = {meta_key: meta_value}
         resp, _ = self.object_client.update_object_metadata(
             self.container_name, object_name, orig_metadata)
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Object', 'POST')
 
         # get object metadata
         resp, resp_metadata = self.object_client.list_object_metadata(
             self.container_name, object_name)
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Object', 'HEAD')
+
         actual_meta_key = 'x-object-meta-' + meta_key
-        self.assertTrue(actual_meta_key in resp)
+        self.assertIn(actual_meta_key, resp)
         self.assertEqual(resp[actual_meta_key], meta_value)
 
     @attr(type='smoke')
@@ -104,29 +110,31 @@
         # retrieve object's data (in response body)
 
         # create object
-        object_name = rand_name(name='TestObject')
-        data = arbitrary_string()
+        object_name = data_utils.rand_name(name='TestObject')
+        data = data_utils.arbitrary_string()
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, data)
         # get object
         resp, body = self.object_client.get_object(self.container_name,
                                                    object_name)
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Object', 'GET')
+
         self.assertEqual(body, data)
 
     @attr(type='smoke')
     def test_copy_object_in_same_container(self):
         # create source object
-        src_object_name = rand_name(name='SrcObject')
-        src_data = arbitrary_string(size=len(src_object_name) * 2,
-                                    base_text=src_object_name)
+        src_object_name = data_utils.rand_name(name='SrcObject')
+        src_data = data_utils.arbitrary_string(size=len(src_object_name) * 2,
+                                               base_text=src_object_name)
         resp, _ = self.object_client.create_object(self.container_name,
                                                    src_object_name,
                                                    src_data)
         # create destination object
-        dst_object_name = rand_name(name='DstObject')
-        dst_data = arbitrary_string(size=len(dst_object_name) * 3,
-                                    base_text=dst_object_name)
+        dst_object_name = data_utils.rand_name(name='DstObject')
+        dst_data = data_utils.arbitrary_string(size=len(dst_object_name) * 3,
+                                               base_text=dst_object_name)
         resp, _ = self.object_client.create_object(self.container_name,
                                                    dst_object_name,
                                                    dst_data)
@@ -134,6 +142,8 @@
         resp, _ = self.object_client.copy_object_in_same_container(
             self.container_name, src_object_name, dst_object_name)
         self.assertEqual(resp['status'], '201')
+        self.assertHeaders(resp, 'Object', 'PUT')
+
         # check data
         resp, body = self.object_client.get_object(self.container_name,
                                                    dst_object_name)
@@ -144,8 +154,8 @@
         # change the content type of an existing object
 
         # create object
-        object_name = rand_name(name='TestObject')
-        data = arbitrary_string()
+        object_name = data_utils.rand_name(name='TestObject')
+        data = data_utils.arbitrary_string()
         self.object_client.create_object(self.container_name,
                                          object_name, data)
         # get the old content type
@@ -157,6 +167,8 @@
         resp, _ = self.object_client.copy_object_in_same_container(
             self.container_name, object_name, object_name, metadata)
         self.assertEqual(resp['status'], '201')
+        self.assertHeaders(resp, 'Object', 'PUT')
+
         # check the content type
         resp, _ = self.object_client.list_object_metadata(self.container_name,
                                                           object_name)
@@ -165,15 +177,15 @@
     @attr(type='smoke')
     def test_copy_object_2d_way(self):
         # create source object
-        src_object_name = rand_name(name='SrcObject')
-        src_data = arbitrary_string(size=len(src_object_name) * 2,
-                                    base_text=src_object_name)
+        src_object_name = data_utils.rand_name(name='SrcObject')
+        src_data = data_utils.arbitrary_string(size=len(src_object_name) * 2,
+                                               base_text=src_object_name)
         resp, _ = self.object_client.create_object(self.container_name,
                                                    src_object_name, src_data)
         # create destination object
-        dst_object_name = rand_name(name='DstObject')
-        dst_data = arbitrary_string(size=len(dst_object_name) * 3,
-                                    base_text=dst_object_name)
+        dst_object_name = data_utils.rand_name(name='DstObject')
+        dst_data = data_utils.arbitrary_string(size=len(dst_object_name) * 3,
+                                               base_text=dst_object_name)
         resp, _ = self.object_client.create_object(self.container_name,
                                                    dst_object_name, dst_data)
         # copy source object to destination
@@ -181,6 +193,17 @@
                                                         src_object_name,
                                                         dst_object_name)
         self.assertEqual(resp['status'], '201')
+        self.assertHeaders(resp, 'Object', 'COPY')
+
+        self.assertIn('last-modified', resp)
+        self.assertIn('x-copied-from', resp)
+        self.assertIn('x-copied-from-last-modified', resp)
+        self.assertNotEqual(len(resp['last-modified']), 0)
+        self.assertEqual(
+            resp['x-copied-from'],
+            self.container_name + "/" + src_object_name)
+        self.assertNotEqual(len(resp['x-copied-from-last-modified']), 0)
+
         # check data
         resp, body = self.object_client.get_object(self.container_name,
                                                    dst_object_name)
@@ -189,45 +212,50 @@
     @attr(type='smoke')
     def test_copy_object_across_containers(self):
         # create a container to use as  asource container
-        src_container_name = rand_name(name='TestSourceContainer')
+        src_container_name = data_utils.rand_name(name='TestSourceContainer')
         self.container_client.create_container(src_container_name)
         self.containers.append(src_container_name)
         # create a container to use as a destination container
-        dst_container_name = rand_name(name='TestDestinationContainer')
+        dst_container_name = data_utils.rand_name(
+            name='TestDestinationContainer')
         self.container_client.create_container(dst_container_name)
         self.containers.append(dst_container_name)
         # create object in source container
-        object_name = rand_name(name='Object')
-        data = arbitrary_string(size=len(object_name) * 2,
-                                base_text=object_name)
+        object_name = data_utils.rand_name(name='Object')
+        data = data_utils.arbitrary_string(size=len(object_name) * 2,
+                                           base_text=object_name)
         resp, _ = self.object_client.create_object(src_container_name,
                                                    object_name, data)
         # set object metadata
-        meta_key = rand_name(name='test-')
-        meta_value = rand_name(name='MetaValue-')
+        meta_key = data_utils.rand_name(name='test-')
+        meta_value = data_utils.rand_name(name='MetaValue-')
         orig_metadata = {meta_key: meta_value}
         resp, _ = self.object_client.update_object_metadata(src_container_name,
                                                             object_name,
                                                             orig_metadata)
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Object', 'POST')
+
         # copy object from source container to destination container
         resp, _ = self.object_client.copy_object_across_containers(
             src_container_name, object_name, dst_container_name,
             object_name)
         self.assertEqual(resp['status'], '201')
+        self.assertHeaders(resp, 'Object', 'PUT')
+
         # check if object is present in destination container
         resp, body = self.object_client.get_object(dst_container_name,
                                                    object_name)
         self.assertEqual(body, data)
         actual_meta_key = 'x-object-meta-' + meta_key
-        self.assertTrue(actual_meta_key in resp)
+        self.assertIn(actual_meta_key, resp)
         self.assertEqual(resp[actual_meta_key], meta_value)
 
     @attr(type='gate')
     def test_object_upload_in_segments(self):
         # create object
-        object_name = rand_name(name='LObject')
-        data = arbitrary_string()
+        object_name = data_utils.rand_name(name='LObject')
+        data = data_utils.arbitrary_string()
         segments = 10
         data_segments = [data + str(i) for i in xrange(segments)]
         # uploading segments
@@ -238,13 +266,34 @@
         # creating a manifest file
         metadata = {'X-Object-Manifest': '%s/%s/'
                     % (self.container_name, object_name)}
-        self.object_client.create_object(self.container_name,
-                                         object_name, data='')
+        resp, _ = self.object_client.create_object(self.container_name,
+                                                   object_name, data='')
+        self.assertHeaders(resp, 'Object', 'PUT')
+
         resp, _ = self.object_client.update_object_metadata(
             self.container_name, object_name, metadata, metadata_prefix='')
+        self.assertHeaders(resp, 'Object', 'POST')
+
         resp, _ = self.object_client.list_object_metadata(
             self.container_name, object_name)
+
+        # Check only the existence of common headers with custom matcher
+        self.assertThat(resp, custom_matchers.ExistsAllResponseHeaders(
+                        'Object', 'HEAD'))
         self.assertIn('x-object-manifest', resp)
+
+        # Etag value of a large object is enclosed in double-quotations.
+        # This is a special case, therefore the formats of response headers
+        # are checked without a custom matcher.
+        self.assertTrue(resp['etag'].startswith('\"'))
+        self.assertTrue(resp['etag'].endswith('\"'))
+        self.assertTrue(resp['etag'].strip('\"').isalnum())
+        self.assertTrue(re.match("^\d+\.?\d*\Z", resp['x-timestamp']))
+        self.assertNotEqual(len(resp['content-type']), 0)
+        self.assertTrue(re.match("^tx[0-9a-f]*-[0-9a-f]*$",
+                                 resp['x-trans-id']))
+        self.assertNotEqual(len(resp['date']), 0)
+        self.assertEqual(resp['accept-ranges'], 'bytes')
         self.assertEqual(resp['x-object-manifest'],
                          '%s/%s/' % (self.container_name, object_name))
 
@@ -259,8 +308,8 @@
         # Make a conditional request for an object using the If-None-Match
         # header, it should get downloaded only if the local file is different,
         # otherwise the response code should be 304 Not Modified
-        object_name = rand_name(name='TestObject')
-        data = arbitrary_string()
+        object_name = data_utils.rand_name(name='TestObject')
+        data = data_utils.arbitrary_string()
         self.object_client.create_object(self.container_name,
                                          object_name, data)
         # local copy is identical, no download
@@ -270,18 +319,29 @@
         resp, _ = self.object_client.get(url, headers=headers)
         self.assertEqual(resp['status'], '304')
 
+        # When the file is not downloaded from Swift server, response does
+        # not contain 'X-Timestamp' header. This is the special case, therefore
+        # the existence of response headers is checked without custom matcher.
+        self.assertIn('content-type', resp)
+        self.assertIn('x-trans-id', resp)
+        self.assertIn('date', resp)
+        self.assertIn('accept-ranges', resp)
+        # Check only the format of common headers with custom matcher
+        self.assertThat(resp, custom_matchers.AreAllWellFormatted())
+
         # local copy is different, download
         local_data = "something different"
         md5 = hashlib.md5(local_data).hexdigest()
         headers = {'If-None-Match': md5}
         resp, body = self.object_client.get(url, headers=headers)
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Object', 'GET')
 
 
 class PublicObjectTest(base.BaseObjectTest):
     def setUp(self):
         super(PublicObjectTest, self).setUp()
-        self.container_name = rand_name(name='TestContainer')
+        self.container_name = data_utils.rand_name(name='TestContainer')
         self.container_client.create_container(self.container_name)
 
     def tearDown(self):
@@ -298,24 +358,31 @@
         resp_meta, body = self.container_client.update_container_metadata(
             self.container_name, metadata=cont_headers, metadata_prefix='')
         self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp_meta, 'Container', 'POST')
+
         # create object
-        object_name = rand_name(name='Object')
-        data = arbitrary_string(size=len(object_name),
-                                base_text=object_name)
+        object_name = data_utils.rand_name(name='Object')
+        data = data_utils.arbitrary_string(size=len(object_name),
+                                           base_text=object_name)
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, data)
         self.assertEqual(resp['status'], '201')
+        self.assertHeaders(resp, 'Object', 'PUT')
 
         # list container metadata
         resp_meta, _ = self.container_client.list_container_metadata(
             self.container_name)
-        self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp_meta, 'Container', 'HEAD')
+
         self.assertIn('x-container-read', resp_meta)
         self.assertEqual(resp_meta['x-container-read'], '.r:*,.rlistings')
 
         # trying to get object with empty headers as it is public readable
         resp, body = self.custom_object_client.get_object(
             self.container_name, object_name, metadata={})
+        self.assertHeaders(resp, 'Object', 'GET')
+
         self.assertEqual(body, data)
 
     @attr(type='smoke')
@@ -327,19 +394,23 @@
             self.container_name, metadata=cont_headers,
             metadata_prefix='')
         self.assertIn(int(resp_meta['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp_meta, 'Container', 'POST')
 
         # create object
-        object_name = rand_name(name='Object')
-        data = arbitrary_string(size=len(object_name) * 1,
-                                base_text=object_name)
+        object_name = data_utils.rand_name(name='Object')
+        data = data_utils.arbitrary_string(size=len(object_name) * 1,
+                                           base_text=object_name)
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, data)
         self.assertEqual(resp['status'], '201')
+        self.assertHeaders(resp, 'Object', 'PUT')
 
         # list container metadata
         resp, _ = self.container_client.list_container_metadata(
             self.container_name)
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Container', 'HEAD')
+
         self.assertIn('x-container-read', resp)
         self.assertEqual(resp['x-container-read'], '.r:*,.rlistings')
 
@@ -350,4 +421,6 @@
         resp, body = self.custom_object_client.get_object(
             self.container_name, object_name,
             metadata=headers)
+        self.assertHeaders(resp, 'Object', 'GET')
+
         self.assertEqual(body, data)
diff --git a/tempest/api/object_storage/test_object_slo.py b/tempest/api/object_storage/test_object_slo.py
new file mode 100644
index 0000000..997120a
--- /dev/null
+++ b/tempest/api/object_storage/test_object_slo.py
@@ -0,0 +1,193 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 NTT Corporation
+#
+#    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 hashlib
+import json
+import re
+
+from tempest.api.object_storage import base
+from tempest.common import custom_matchers
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest import test
+
+# Each segment, except for the final one, must be at least 1 megabyte
+MIN_SEGMENT_SIZE = 1024 * 1024
+
+
+class ObjectSloTest(base.BaseObjectTest):
+
+    def setUp(self):
+        super(ObjectSloTest, self).setUp()
+        self.container_name = data_utils.rand_name(name='TestContainer')
+        self.container_client.create_container(self.container_name)
+        self.objects = []
+
+    def tearDown(self):
+        for obj in self.objects:
+            try:
+                self.object_client.delete_object(
+                    self.container_name,
+                    obj)
+            except exceptions.NotFound:
+                pass
+        self.container_client.delete_container(self.container_name)
+        super(ObjectSloTest, self).tearDown()
+
+    def _create_object(self, container_name, object_name, data, params=None):
+        resp, _ = self.object_client.create_object(container_name,
+                                                   object_name,
+                                                   data,
+                                                   params)
+        self.objects.append(object_name)
+
+        return resp
+
+    def _create_manifest(self):
+        # Create a manifest file for SLO uploading
+        object_name = data_utils.rand_name(name='TestObject')
+        object_name_base_1 = object_name + '_01'
+        object_name_base_2 = object_name + '_02'
+        data_size = MIN_SEGMENT_SIZE
+        self.data = data_utils.arbitrary_string(data_size)
+        self._create_object(self.container_name,
+                            object_name_base_1,
+                            self.data)
+        self._create_object(self.container_name,
+                            object_name_base_2,
+                            self.data)
+
+        path_object_1 = '/%s/%s' % (self.container_name,
+                                    object_name_base_1)
+        path_object_2 = '/%s/%s' % (self.container_name,
+                                    object_name_base_2)
+        data_manifest = [{'path': path_object_1,
+                          'etag': hashlib.md5(self.data).hexdigest(),
+                          'size_bytes': data_size},
+                         {'path': path_object_2,
+                          'etag': hashlib.md5(self.data).hexdigest(),
+                          'size_bytes': data_size}]
+
+        return json.dumps(data_manifest)
+
+    def _create_large_object(self):
+        # Create a large object for preparation of testing various SLO
+        # features
+        manifest = self._create_manifest()
+
+        params = {'multipart-manifest': 'put'}
+        object_name = data_utils.rand_name(name='TestObject')
+        self._create_object(self.container_name,
+                            object_name,
+                            manifest,
+                            params)
+        return object_name
+
+    def _assertHeadersSLO(self, resp, method):
+        # Check the existence of common headers with custom matcher
+        self.assertThat(resp, custom_matchers.ExistsAllResponseHeaders(
+                        'Object', method))
+        # When sending GET or HEAD requests to SLO the response contains
+        # 'X-Static-Large-Object' header
+        if method in ('GET', 'HEAD'):
+            self.assertIn('x-static-large-object', resp)
+
+        # Check common headers for all HTTP methods
+        self.assertTrue(re.match("^tx[0-9a-f]*-[0-9a-f]*$",
+                                 resp['x-trans-id']))
+        self.assertTrue(resp['content-length'].isdigit())
+        self.assertNotEqual(len(resp['date']), 0)
+        # Etag value of a large object is enclosed in double-quotations.
+        self.assertTrue(resp['etag'].startswith('\"'))
+        self.assertTrue(resp['etag'].endswith('\"'))
+        self.assertTrue(resp['etag'].strip('\"').isalnum())
+        # Check header formats for a specific method
+        if method in ('GET', 'HEAD'):
+            self.assertTrue(re.match("^\d+\.?\d*\Z", resp['x-timestamp']))
+            self.assertNotEqual(len(resp['content-type']), 0)
+            self.assertEqual(resp['accept-ranges'], 'bytes')
+            self.assertEqual(resp['x-static-large-object'], 'True')
+
+    @test.attr(type='gate')
+    def test_upload_manifest(self):
+        # create static large object from multipart manifest
+        manifest = self._create_manifest()
+
+        params = {'multipart-manifest': 'put'}
+        object_name = data_utils.rand_name(name='TestObject')
+        resp = self._create_object(self.container_name,
+                                   object_name,
+                                   manifest,
+                                   params)
+
+        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
+        self._assertHeadersSLO(resp, 'PUT')
+
+    @test.attr(type='gate')
+    def test_list_large_object_metadata(self):
+        # list static large object metadata using multipart manifest
+        object_name = self._create_large_object()
+
+        resp, body = self.object_client.list_object_metadata(
+            self.container_name,
+            object_name)
+
+        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
+        self._assertHeadersSLO(resp, 'HEAD')
+
+    @test.attr(type='gate')
+    def test_retrieve_large_object(self):
+        # list static large object using multipart manifest
+        object_name = self._create_large_object()
+
+        resp, body = self.object_client.get_object(
+            self.container_name,
+            object_name)
+
+        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
+        self._assertHeadersSLO(resp, 'GET')
+
+        sum_data = self.data + self.data
+        self.assertEqual(body, sum_data)
+
+    @test.attr(type='gate')
+    def test_delete_large_object(self):
+        # delete static large object using multipart manifest
+        object_name = self._create_large_object()
+
+        params_del = {'multipart-manifest': 'delete'}
+        resp, body = self.object_client.delete_object(
+            self.container_name,
+            object_name,
+            params=params_del)
+
+        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
+
+        # When deleting SLO using multipart manifest, the response contains
+        # not 'content-length' but 'transfer-encoding' header. This is the
+        # special case, therefore the existence of response headers is checked
+        # outside of custom matcher.
+        self.assertIn('transfer-encoding', resp)
+        self.assertIn('content-type', resp)
+        self.assertIn('x-trans-id', resp)
+        self.assertIn('date', resp)
+
+        # Check only the format of common headers with custom matcher
+        self.assertThat(resp, custom_matchers.AreAllWellFormatted())
+
+        resp, body = self.container_client.list_container_contents(
+            self.container_name)
+        self.assertEqual(int(resp['x-container-object-count']), 0)
diff --git a/tempest/api/object_storage/test_object_temp_url.py b/tempest/api/object_storage/test_object_temp_url.py
index 0fd5499..bb03932 100644
--- a/tempest/api/object_storage/test_object_temp_url.py
+++ b/tempest/api/object_storage/test_object_temp_url.py
@@ -21,8 +21,8 @@
 import urlparse
 
 from tempest.api.object_storage import base
-from tempest.common.utils.data_utils import arbitrary_string
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
+from tempest import config
 from tempest import exceptions
 from tempest.test import attr
 from tempest.test import HTTP_SUCCESS
@@ -30,10 +30,20 @@
 
 class ObjectTempUrlTest(base.BaseObjectTest):
 
+    tempurl_available = \
+        config.TempestConfig().object_storage_feature_enabled.tempurl
+
     @classmethod
     def setUpClass(cls):
         super(ObjectTempUrlTest, cls).setUpClass()
-        cls.container_name = rand_name(name='TestContainer')
+
+        # skip this test if CORS isn't enabled in the conf file.
+        if not cls.tempurl_available:
+            skip_msg = ("%s skipped as TempUrl middleware not available"
+                        % cls.__name__)
+            raise cls.skipException(skip_msg)
+
+        cls.container_name = data_utils.rand_name(name='TestContainer')
         cls.container_client.create_container(cls.container_name)
         cls.containers = [cls.container_name]
 
@@ -48,9 +58,9 @@
     def tearDownClass(cls):
         resp, _ = cls.account_client.delete_account_metadata(
             metadata=cls.metadata)
-        resp, _ = cls.account_client.list_account_metadata()
 
         cls.delete_containers(cls.containers)
+
         # delete the user setup created
         cls.data.teardown_all()
         super(ObjectTempUrlTest, cls).tearDownClass()
@@ -66,14 +76,17 @@
             self.key)
 
         # create object
-        self.object_name = rand_name(name='ObjectTemp')
-        self.data = arbitrary_string(size=len(self.object_name),
-                                     base_text=self.object_name)
+        self.object_name = data_utils.rand_name(name='ObjectTemp')
+        self.data = data_utils.arbitrary_string(size=len(self.object_name),
+                                                base_text=self.object_name)
         self.object_client.create_object(self.container_name,
                                          self.object_name, self.data)
 
-    def get_temp_url(self, container, object_name, method, expires,
-                     key):
+    def _get_expiry_date(self, expiration_time=1000):
+        return int(time.time() + expiration_time)
+
+    def _get_temp_url(self, container, object_name, method, expires,
+                      key):
         """Create the temporary URL."""
 
         path = "%s/%s/%s" % (
@@ -91,66 +104,86 @@
 
     @attr(type='gate')
     def test_get_object_using_temp_url(self):
-        EXPIRATION_TIME = 10000  # high to ensure the test finishes.
-        expires = int(time.time() + EXPIRATION_TIME)
+        expires = self._get_expiry_date()
 
         # get a temp URL for the created object
-        url = self.get_temp_url(self.container_name,
-                                self.object_name, "GET",
-                                expires, self.key)
+        url = self._get_temp_url(self.container_name,
+                                 self.object_name, "GET",
+                                 expires, self.key)
 
         # trying to get object using temp url within expiry time
-        _, body = self.object_client.get_object_using_temp_url(url)
-
+        resp, body = self.object_client.get_object_using_temp_url(url)
+        self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Object', 'GET')
         self.assertEqual(body, self.data)
 
         # Testing a HEAD on this Temp URL
         resp, body = self.object_client.head(url)
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Object', 'HEAD')
+
+    @attr(type='gate')
+    def test_get_object_using_temp_url_key_2(self):
+        key2 = 'Meta2-'
+        metadata = {'Temp-URL-Key-2': key2}
+        self.account_client.create_account_metadata(metadata=metadata)
+
+        self.account_client_metadata, _ = \
+            self.account_client.list_account_metadata()
+        self.assertIn('x-account-meta-temp-url-key-2',
+                      self.account_client_metadata)
+
+        expires = self._get_expiry_date()
+        url = self._get_temp_url(self.container_name,
+                                 self.object_name, "GET",
+                                 expires, key2)
+        resp, body = self.object_client.get_object_using_temp_url(url)
+        self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertEqual(body, self.data)
 
     @attr(type='gate')
     def test_put_object_using_temp_url(self):
         # make sure the metadata has been set
-        new_data = arbitrary_string(size=len(self.object_name),
-                                    base_text=rand_name(name="random"))
+        new_data = data_utils.arbitrary_string(
+            size=len(self.object_name),
+            base_text=data_utils.rand_name(name="random"))
 
-        EXPIRATION_TIME = 10000  # high to ensure the test finishes.
-        expires = int(time.time() + EXPIRATION_TIME)
-
-        url = self.get_temp_url(self.container_name,
-                                self.object_name, "PUT",
-                                expires, self.key)
+        expires = self._get_expiry_date()
+        url = self._get_temp_url(self.container_name,
+                                 self.object_name, "PUT",
+                                 expires, self.key)
 
         # trying to put random data in the object using temp url
         resp, body = self.object_client.put_object_using_temp_url(
             url, new_data)
 
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Object', 'PUT')
 
         # Testing a HEAD on this Temp URL
         resp, body = self.object_client.head(url)
         self.assertIn(int(resp['status']), HTTP_SUCCESS)
+        self.assertHeaders(resp, 'Object', 'HEAD')
 
         # Validate that the content of the object has been modified
-        url = self.get_temp_url(self.container_name,
-                                self.object_name, "GET",
-                                expires, self.key)
+        url = self._get_temp_url(self.container_name,
+                                 self.object_name, "GET",
+                                 expires, self.key)
 
         _, body = self.object_client.get_object_using_temp_url(url)
         self.assertEqual(body, new_data)
 
     @attr(type=['gate', 'negative'])
     def test_get_object_after_expiration_time(self):
-        EXPIRATION_TIME = 1
-        expires = int(time.time() + EXPIRATION_TIME)
 
+        expires = self._get_expiry_date(1)
         # get a temp URL for the created object
-        url = self.get_temp_url(self.container_name,
-                                self.object_name, "GET",
-                                expires, self.key)
+        url = self._get_temp_url(self.container_name,
+                                 self.object_name, "GET",
+                                 expires, self.key)
 
-        # temp URL is valid for 1 seconds, let's wait 3
-        time.sleep(EXPIRATION_TIME + 2)
+        # temp URL is valid for 1 seconds, let's wait 2
+        time.sleep(2)
 
         self.assertRaises(exceptions.Unauthorized,
                           self.object_client.get_object_using_temp_url,
diff --git a/tempest/api/object_storage/test_object_version.py b/tempest/api/object_storage/test_object_version.py
index 2b75b77..d706eef 100644
--- a/tempest/api/object_storage/test_object_version.py
+++ b/tempest/api/object_storage/test_object_version.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.object_storage import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 
 
@@ -34,6 +34,7 @@
     def assertContainer(self, container, count, byte, versioned):
         resp, _ = self.container_client.list_container_metadata(container)
         self.assertEqual(resp['status'], ('204'))
+        self.assertHeaders(resp, 'Container', 'HEAD')
         header_value = resp.get('x-container-object-count', 'Missing Header')
         self.assertEqual(header_value, count)
         header_value = resp.get('x-container-bytes-used', 'Missing Header')
@@ -44,14 +45,15 @@
     @attr(type='smoke')
     def test_versioned_container(self):
         # create container
-        vers_container_name = rand_name(name='TestVersionContainer')
+        vers_container_name = data_utils.rand_name(name='TestVersionContainer')
         resp, body = self.container_client.create_container(
             vers_container_name)
         self.containers.append(vers_container_name)
         self.assertIn(resp['status'], ('202', '201'))
+        self.assertHeaders(resp, 'Container', 'PUT')
         self.assertContainer(vers_container_name, '0', '0', 'Missing Header')
 
-        base_container_name = rand_name(name='TestBaseContainer')
+        base_container_name = data_utils.rand_name(name='TestBaseContainer')
         headers = {'X-versions-Location': vers_container_name}
         resp, body = self.container_client.create_container(
             base_container_name,
@@ -59,9 +61,10 @@
             metadata_prefix='')
         self.containers.append(base_container_name)
         self.assertIn(resp['status'], ('202', '201'))
+        self.assertHeaders(resp, 'Container', 'PUT')
         self.assertContainer(base_container_name, '0', '0',
                              vers_container_name)
-        object_name = rand_name(name='TestObject')
+        object_name = data_utils.rand_name(name='TestObject')
         # create object
         resp, _ = self.object_client.create_object(base_container_name,
                                                    object_name, '1')
diff --git a/tempest/api/orchestration/base.py b/tempest/api/orchestration/base.py
index 7c72991..f3ef99f 100644
--- a/tempest/api/orchestration/base.py
+++ b/tempest/api/orchestration/base.py
@@ -15,7 +15,7 @@
 import time
 
 from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.openstack.common import log as logging
 import tempest.test
 
@@ -99,7 +99,7 @@
 
     @classmethod
     def _create_keypair(cls, name_start='keypair-heat-'):
-        kp_name = rand_name(name_start)
+        kp_name = data_utils.rand_name(name_start)
         resp, body = cls.keypairs_client.create_keypair(kp_name)
         cls.keypairs.append(kp_name)
         return body
diff --git a/tempest/api/orchestration/stacks/test_limits.py b/tempest/api/orchestration/stacks/test_limits.py
index aa59581..d294c7a 100644
--- a/tempest/api/orchestration/stacks/test_limits.py
+++ b/tempest/api/orchestration/stacks/test_limits.py
@@ -15,7 +15,7 @@
 import logging
 
 from tempest.api.orchestration import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.test import attr
 
@@ -30,7 +30,7 @@
     def setUpClass(cls):
         super(TestServerStackLimits, cls).setUpClass()
         cls.client = cls.orchestration_client
-        cls.stack_name = rand_name('heat')
+        cls.stack_name = data_utils.rand_name('heat')
 
     @attr(type='gate')
     def test_exceed_max_template_size_fails(self):
diff --git a/tempest/api/orchestration/stacks/test_neutron_resources.py b/tempest/api/orchestration/stacks/test_neutron_resources.py
index 174c82a..c86edf0 100644
--- a/tempest/api/orchestration/stacks/test_neutron_resources.py
+++ b/tempest/api/orchestration/stacks/test_neutron_resources.py
@@ -17,7 +17,7 @@
 
 from tempest.api.orchestration import base
 from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 
 
@@ -101,7 +101,7 @@
         if not cls.config.service_available.neutron:
             raise cls.skipException("Neutron support is required")
         cls.network_client = os.network_client
-        cls.stack_name = rand_name('heat')
+        cls.stack_name = data_utils.rand_name('heat')
         cls.keypair_name = (cls.orchestration_cfg.keypair_name or
                             cls._create_keypair()['name'])
         cls.external_router_id = cls._get_external_router_id()
diff --git a/tempest/api/orchestration/stacks/test_non_empty_stack.py b/tempest/api/orchestration/stacks/test_non_empty_stack.py
index 0ecc5ff..35a7326 100644
--- a/tempest/api/orchestration/stacks/test_non_empty_stack.py
+++ b/tempest/api/orchestration/stacks/test_non_empty_stack.py
@@ -15,7 +15,7 @@
 import logging
 
 from tempest.api.orchestration import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 
 
@@ -76,7 +76,7 @@
         if not cls.orchestration_cfg.image_ref:
             raise cls.skipException("No image available to test")
         cls.client = cls.orchestration_client
-        cls.stack_name = rand_name('heat')
+        cls.stack_name = data_utils.rand_name('heat')
         keypair_name = (cls.orchestration_cfg.keypair_name or
                         cls._create_keypair()['name'])
 
diff --git a/tempest/api/orchestration/stacks/test_server_cfn_init.py b/tempest/api/orchestration/stacks/test_server_cfn_init.py
index ea0bff5..3c2a2d2 100644
--- a/tempest/api/orchestration/stacks/test_server_cfn_init.py
+++ b/tempest/api/orchestration/stacks/test_server_cfn_init.py
@@ -16,7 +16,7 @@
 import testtools
 
 from tempest.api.orchestration import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.common.utils.linux.remote_client import RemoteClient
 import tempest.config
 from tempest.openstack.common import log as logging
@@ -132,7 +132,7 @@
             raise cls.skipException("No image available to test")
         cls.client = cls.orchestration_client
 
-        stack_name = rand_name('heat')
+        stack_name = data_utils.rand_name('heat')
         if cls.orchestration_cfg.keypair_name:
             keypair_name = cls.orchestration_cfg.keypair_name
         else:
diff --git a/tempest/api/orchestration/stacks/test_stacks.py b/tempest/api/orchestration/stacks/test_stacks.py
index 4bda5ab..0b7883d 100644
--- a/tempest/api/orchestration/stacks/test_stacks.py
+++ b/tempest/api/orchestration/stacks/test_stacks.py
@@ -13,7 +13,7 @@
 #    under the License.
 
 from tempest.api.orchestration import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.openstack.common import log as logging
 from tempest.test import attr
 
@@ -39,7 +39,7 @@
 
     @attr(type='smoke')
     def test_stack_crud_no_resources(self):
-        stack_name = rand_name('heat')
+        stack_name = data_utils.rand_name('heat')
 
         # create the stack
         stack_identifier = self.create_stack(
diff --git a/tempest/api/orchestration/stacks/test_templates.py b/tempest/api/orchestration/stacks/test_templates.py
index 6a7c541..2589632 100644
--- a/tempest/api/orchestration/stacks/test_templates.py
+++ b/tempest/api/orchestration/stacks/test_templates.py
@@ -15,7 +15,7 @@
 import logging
 
 from tempest.api.orchestration import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.test import attr
 
@@ -41,7 +41,7 @@
     def setUpClass(cls):
         super(TemplateYAMLTestJSON, cls).setUpClass()
         cls.client = cls.orchestration_client
-        cls.stack_name = rand_name('heat')
+        cls.stack_name = data_utils.rand_name('heat')
         cls.stack_identifier = cls.create_stack(cls.stack_name, cls.template)
         cls.client.wait_for_stack_status(cls.stack_identifier,
                                          'CREATE_COMPLETE')
diff --git a/tempest/api/volume/admin/test_multi_backend.py b/tempest/api/volume/admin/test_multi_backend.py
index eada639..03e8469 100644
--- a/tempest/api/volume/admin/test_multi_backend.py
+++ b/tempest/api/volume/admin/test_multi_backend.py
@@ -13,7 +13,7 @@
 #    under the License.
 
 from tempest.api.volume import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.openstack.common import log as logging
 from tempest.services.volume.json.admin import volume_types_client
 from tempest.services.volume.json import volumes_client
@@ -29,6 +29,7 @@
     def setUpClass(cls):
         super(VolumeMultiBackendTest, cls).setUpClass()
         if not cls.config.volume_feature_enabled.multi_backend:
+            cls.tearDownClass()
             raise cls.skipException("Cinder multi-backend feature disabled")
 
         cls.backend1_name = cls.config.volume.backend1_name
@@ -54,8 +55,8 @@
         cls.volume_id_list = []
         try:
             # Volume/Type creation (uses backend1_name)
-            type1_name = rand_name('Type-')
-            vol1_name = rand_name('Volume-')
+            type1_name = data_utils.rand_name('Type-')
+            vol1_name = data_utils.rand_name('Volume-')
             extra_specs1 = {"volume_backend_name": cls.backend1_name}
             resp, cls.type1 = cls.type_client.create_volume_type(
                 type1_name, extra_specs=extra_specs1)
@@ -69,8 +70,8 @@
 
             if cls.backend1_name != cls.backend2_name:
                 # Volume/Type creation (uses backend2_name)
-                type2_name = rand_name('Type-')
-                vol2_name = rand_name('Volume-')
+                type2_name = data_utils.rand_name('Type-')
+                vol2_name = data_utils.rand_name('Volume-')
                 extra_specs2 = {"volume_backend_name": cls.backend2_name}
                 resp, cls.type2 = cls.type_client.create_volume_type(
                     type2_name, extra_specs=extra_specs2)
@@ -89,12 +90,14 @@
     @classmethod
     def tearDownClass(cls):
         # volumes deletion
-        for volume_id in cls.volume_id_list:
+        volume_id_list = getattr(cls, 'volume_id_list', [])
+        for volume_id in volume_id_list:
             cls.volume_client.delete_volume(volume_id)
             cls.volume_client.wait_for_resource_deletion(volume_id)
 
         # volume types deletion
-        for volume_type_id in cls.volume_type_id_list:
+        volume_type_id_list = getattr(cls, 'volume_type_id_list', [])
+        for volume_type_id in volume_type_id_list:
             cls.type_client.delete_volume_type(volume_type_id)
 
         super(VolumeMultiBackendTest, cls).tearDownClass()
diff --git a/tempest/api/volume/admin/test_snapshots_actions.py b/tempest/api/volume/admin/test_snapshots_actions.py
new file mode 100644
index 0000000..5e838e5
--- /dev/null
+++ b/tempest/api/volume/admin/test_snapshots_actions.py
@@ -0,0 +1,110 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 Huawei Technologies Co.,LTD
+# 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 tempest.api.volume.base import BaseVolumeAdminTest
+from tempest.common.utils import data_utils
+from tempest.test import attr
+
+
+class SnapshotsActionsTest(BaseVolumeAdminTest):
+    _interface = "json"
+
+    @classmethod
+    def setUpClass(cls):
+        super(SnapshotsActionsTest, cls).setUpClass()
+        cls.client = cls.snapshots_client
+
+        # Create admin volume client
+        cls.admin_snapshots_client = cls.os_adm.snapshots_client
+
+        # Create a test shared volume for tests
+        vol_name = data_utils.rand_name(cls.__name__ + '-Volume-')
+        resp_vol, cls.volume = \
+            cls.volumes_client.create_volume(size=1, display_name=vol_name)
+        cls.volumes_client.wait_for_volume_status(cls.volume['id'],
+                                                  'available')
+
+        # Create a test shared snapshot for tests
+        snap_name = data_utils.rand_name(cls.__name__ + '-Snapshot-')
+        resp_snap, cls.snapshot = \
+            cls.client.create_snapshot(cls.volume['id'],
+                                       display_name=snap_name)
+        cls.client.wait_for_snapshot_status(cls.snapshot['id'],
+                                            'available')
+
+    @classmethod
+    def tearDownClass(cls):
+        # Delete the test snapshot
+        cls.client.delete_snapshot(cls.snapshot['id'])
+        cls.client.wait_for_resource_deletion(cls.snapshot['id'])
+
+        # Delete the test volume
+        cls.volumes_client.delete_volume(cls.volume['id'])
+        cls.volumes_client.wait_for_resource_deletion(cls.volume['id'])
+
+        super(SnapshotsActionsTest, cls).tearDownClass()
+
+    def tearDown(self):
+        # Set snapshot's status to available after test
+        status = 'available'
+        snapshot_id = self.snapshot['id']
+        self.admin_snapshots_client.reset_snapshot_status(snapshot_id,
+                                                          status)
+        super(SnapshotsActionsTest, self).tearDown()
+
+    def _get_progress_alias(self):
+        return 'os-extended-snapshot-attributes:progress'
+
+    @attr(type='gate')
+    def test_reset_snapshot_status(self):
+        # Reset snapshot status to creating
+        status = 'creating'
+        resp, body = self.admin_snapshots_client.\
+            reset_snapshot_status(self.snapshot['id'], status)
+        self.assertEqual(202, resp.status)
+        resp_get, snapshot_get \
+            = self.admin_snapshots_client.get_snapshot(self.snapshot['id'])
+        self.assertEqual(200, resp_get.status)
+        self.assertEqual(status, snapshot_get['status'])
+
+    @attr(type='gate')
+    def test_update_snapshot_status(self):
+        # Reset snapshot status to creating
+        status = 'creating'
+        self.admin_snapshots_client.\
+            reset_snapshot_status(self.snapshot['id'], status)
+
+        # Update snapshot status to error
+        progress = '80%'
+        status = 'error'
+        progress_alias = self._get_progress_alias()
+        resp, body = self.client.update_snapshot_status(self.snapshot['id'],
+                                                        status, progress)
+        self.assertEqual(202, resp.status)
+        resp_get, snapshot_get \
+            = self.admin_snapshots_client.get_snapshot(self.snapshot['id'])
+        self.assertEqual(200, resp_get.status)
+        self.assertEqual(status, snapshot_get['status'])
+        self.assertEqual(progress, snapshot_get[progress_alias])
+
+
+class SnapshotsActionsTestXML(SnapshotsActionsTest):
+    _interface = "xml"
+
+    def _get_progress_alias(self):
+        return '{http://docs.openstack.org/volume/ext' \
+               '/extended_snapshot_attributes/api/v1}progress'
diff --git a/tempest/api/volume/admin/test_volume_hosts.py b/tempest/api/volume/admin/test_volume_hosts.py
new file mode 100644
index 0000000..e7d8c02
--- /dev/null
+++ b/tempest/api/volume/admin/test_volume_hosts.py
@@ -0,0 +1,34 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.volume import base
+from tempest.test import attr
+
+
+class VolumeHostsAdminTestsJSON(base.BaseVolumeAdminTest):
+    _interface = "json"
+
+    @attr(type='gate')
+    def test_list_hosts(self):
+        resp, hosts = self.hosts_client.list_hosts()
+        self.assertEqual(200, resp.status)
+        self.assertTrue(len(hosts) >= 2, "No. of hosts are < 2,"
+                        "response of list hosts is: % s" % hosts)
+
+
+class VolumeHostsAdminTestsXML(VolumeHostsAdminTestsJSON):
+    _interface = 'xml'
diff --git a/tempest/api/volume/admin/test_volume_types.py b/tempest/api/volume/admin/test_volume_types.py
index c455566..5218f83 100644
--- a/tempest/api/volume/admin/test_volume_types.py
+++ b/tempest/api/volume/admin/test_volume_types.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.volume.base import BaseVolumeTest
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.services.volume.json.admin import volume_types_client
 from tempest.test import attr
 
@@ -58,8 +58,8 @@
     def test_create_get_delete_volume_with_volume_type_and_extra_specs(self):
         # Create/get/delete volume with volume_type and extra spec.
         volume = {}
-        vol_name = rand_name("volume-")
-        vol_type_name = rand_name("volume-type-")
+        vol_name = data_utils.rand_name("volume-")
+        vol_type_name = data_utils.rand_name("volume-type-")
         proto = self.config.volume.storage_protocol
         vendor = self.config.volume.vendor_name
         extra_specs = {"storage_protocol": proto,
@@ -99,31 +99,14 @@
                          'from the created Volume')
 
     @attr(type='smoke')
-    def test_volume_type_create_delete(self):
-        # Create/Delete volume type.
-        name = rand_name("volume-type-")
-        extra_specs = {"storage_protocol": "iSCSI",
-                       "vendor_name": "Open Source"}
-        resp, body = self.client.create_volume_type(
-            name,
-            extra_specs=extra_specs)
-        self.assertEqual(200, resp.status)
-        self.assertIn('id', body)
-        self.addCleanup(self._delete_volume_type, body['id'])
-        self.assertIn('name', body)
-        self.assertEqual(body['name'], name,
-                         "The created volume_type name is not equal "
-                         "to the requested name")
-        self.assertTrue(body['id'] is not None,
-                        "Field volume_type id is empty or not found.")
-
-    @attr(type='smoke')
-    def test_volume_type_create_get(self):
+    def test_volume_type_create_get_delete(self):
         # Create/get volume type.
         body = {}
-        name = rand_name("volume-type-")
-        extra_specs = {"storage_protocol": "iSCSI",
-                       "vendor_name": "Open Source"}
+        name = data_utils.rand_name("volume-type-")
+        proto = self.config.volume.storage_protocol
+        vendor = self.config.volume.vendor_name
+        extra_specs = {"storage_protocol": proto,
+                       "vendor_name": vendor}
         resp, body = self.client.create_volume_type(
             name,
             extra_specs=extra_specs)
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs.py b/tempest/api/volume/admin/test_volume_types_extra_specs.py
index d6dd7db..dbb75af 100644
--- a/tempest/api/volume/admin/test_volume_types_extra_specs.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.volume import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 
 
@@ -26,7 +26,7 @@
     @classmethod
     def setUpClass(cls):
         super(VolumeTypesExtraSpecsTest, cls).setUpClass()
-        vol_type_name = rand_name('Volume-type-')
+        vol_type_name = data_utils.rand_name('Volume-type-')
         resp, cls.volume_type = cls.client.create_volume_type(vol_type_name)
 
     @classmethod
@@ -47,8 +47,7 @@
             self.volume_type['id'])
         self.assertEqual(200, resp.status)
         self.assertIsInstance(body, dict)
-        self.assertTrue('spec1' in body, "Incorrect volume type extra"
-                        " spec returned")
+        self.assertIn('spec1', body)
 
     @attr(type='gate')
     def test_volume_type_extra_specs_update(self):
@@ -66,8 +65,7 @@
             extra_spec.keys()[0],
             extra_spec)
         self.assertEqual(200, resp.status)
-        self.assertTrue('spec2' in body,
-                        "Volume type extra spec incorrectly updated")
+        self.assertIn('spec2', body)
         self.assertEqual(extra_spec['spec2'], body['spec2'],
                          "Volume type extra spec incorrectly updated")
 
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
index e76c0ac..8b5dce2 100644
--- a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
@@ -18,7 +18,7 @@
 import uuid
 
 from tempest.api.volume import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.test import attr
 
@@ -29,7 +29,7 @@
     @classmethod
     def setUpClass(cls):
         super(ExtraSpecsNegativeTest, cls).setUpClass()
-        vol_type_name = rand_name('Volume-type-')
+        vol_type_name = data_utils.rand_name('Volume-type-')
         cls.extra_specs = {"spec1": "val1"}
         resp, cls.volume_type = cls.client.create_volume_type(vol_type_name,
                                                               extra_specs=
diff --git a/tempest/api/volume/admin/test_volumes_actions.py b/tempest/api/volume/admin/test_volumes_actions.py
index 4063eef..cb9ff11 100644
--- a/tempest/api/volume/admin/test_volumes_actions.py
+++ b/tempest/api/volume/admin/test_volumes_actions.py
@@ -47,7 +47,7 @@
         super(VolumesActionsTest, cls).tearDownClass()
 
     def _reset_volume_status(self, volume_id, status):
-        #Reset the volume status
+        # Reset the volume status
         resp, body = self.admin_volume_client.reset_volume_status(volume_id,
                                                                   status)
         return resp, body
@@ -57,6 +57,26 @@
         self._reset_volume_status(self.volume['id'], 'available')
         super(VolumesActionsTest, self).tearDown()
 
+    def _create_temp_volume(self):
+        # Create a temp volume for force delete tests
+        vol_name = utils.rand_name('Volume')
+        resp, temp_volume = self.client.create_volume(size=1,
+                                                      display_name=vol_name)
+        self.client.wait_for_volume_status(temp_volume['id'], 'available')
+
+        return temp_volume
+
+    def _create_reset_and_force_delete_temp_volume(self, status=None):
+        # Create volume, reset volume status, and force delete temp volume
+        temp_volume = self._create_temp_volume()
+        if status:
+            resp, body = self._reset_volume_status(temp_volume['id'], status)
+            self.assertEqual(202, resp.status)
+        resp_delete, volume_delete = self.admin_volume_client.\
+            force_delete_volume(temp_volume['id'])
+        self.assertEqual(202, resp_delete.status)
+        self.client.wait_for_resource_deletion(temp_volume['id'])
+
     @attr(type='gate')
     def test_volume_reset_status(self):
         # test volume reset status : available->error->available
@@ -84,6 +104,19 @@
         resp_get, volume_get = self.client.get_volume(self.volume['id'])
         self.assertEqual('in-use', volume_get['status'])
 
+    def test_volume_force_delete_when_volume_is_creating(self):
+        # test force delete when status of volume is creating
+        self._create_reset_and_force_delete_temp_volume('creating')
+
+    def test_volume_force_delete_when_volume_is_attaching(self):
+        # test force delete when status of volume is attaching
+        self._create_reset_and_force_delete_temp_volume('attaching')
+
+    @attr(type='gate')
+    def test_volume_force_delete_when_volume_is_error(self):
+        # test force delete when status of volume is error
+        self._create_reset_and_force_delete_temp_volume('error')
+
 
 class VolumesActionsTestXML(VolumesActionsTest):
     _interface = "xml"
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index cdf8638..465f570 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -151,3 +151,4 @@
         else:
             cls.os_adm = clients.AdminManager(interface=cls._interface)
         cls.client = cls.os_adm.volume_types_client
+        cls.hosts_client = cls.os_adm.volume_hosts_client
diff --git a/tempest/api/volume/test_volume_transfers.py b/tempest/api/volume/test_volume_transfers.py
new file mode 100644
index 0000000..dacebf1
--- /dev/null
+++ b/tempest/api/volume/test_volume_transfers.py
@@ -0,0 +1,120 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.volume.base import BaseVolumeTest
+from tempest import clients
+from tempest.common.utils.data_utils import rand_name
+from tempest.test import attr
+
+
+class VolumesTransfersTest(BaseVolumeTest):
+    _interface = "json"
+
+    @classmethod
+    def setUpClass(cls):
+        super(VolumesTransfersTest, cls).setUpClass()
+
+        # Add another tenant to test volume-transfer
+        if cls.config.compute.allow_tenant_isolation:
+            creds = cls.isolated_creds.get_alt_creds()
+            username, tenant_name, password = creds
+            cls.os_alt = clients.Manager(username=username,
+                                         password=password,
+                                         tenant_name=tenant_name,
+                                         interface=cls._interface)
+            cls.alt_tenant_id = cls.isolated_creds.get_alt_tenant()['id']
+
+            # Add admin tenant to cleanup resources
+            adm_creds = cls.isolated_creds.get_admin_creds()
+            admin_username, admin_tenant_name, admin_password = adm_creds
+            cls.os_adm = clients.Manager(username=admin_username,
+                                         password=admin_password,
+                                         tenant_name=admin_tenant_name,
+                                         interface=cls._interface)
+        else:
+            cls.os_alt = clients.AltManager()
+            alt_tenant_name = cls.os_alt.tenant_name
+            identity_client = cls._get_identity_admin_client()
+            _, tenants = identity_client.list_tenants()
+            cls.alt_tenant_id = [tnt['id'] for tnt in tenants
+                                 if tnt['name'] == alt_tenant_name][0]
+            cls.os_adm = clients.ComputeAdminManager(interface=cls._interface)
+
+        cls.client = cls.volumes_client
+        cls.alt_client = cls.os_alt.volumes_client
+        cls.adm_client = cls.os_adm.volumes_client
+
+    @attr(type='gate')
+    def test_create_get_list_accept_volume_transfer(self):
+        # Create a volume first
+        vol_name = rand_name('-Volume-')
+        _, volume = self.client.create_volume(size=1, display_name=vol_name)
+        self.addCleanup(self.adm_client.delete_volume, volume['id'])
+        self.client.wait_for_volume_status(volume['id'], 'available')
+
+        # Create a volume transfer
+        resp, transfer = self.client.create_volume_transfer(volume['id'])
+        self.assertEqual(202, resp.status)
+        transfer_id = transfer['id']
+        auth_key = transfer['auth_key']
+        self.client.wait_for_volume_status(volume['id'],
+                                           'awaiting-transfer')
+
+        # Get a volume transfer
+        resp, body = self.client.get_volume_transfer(transfer_id)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(volume['id'], body['volume_id'])
+
+        # List volume transfers, the result should be greater than
+        # or equal to 1
+        resp, body = self.client.list_volume_transfers()
+        self.assertEqual(200, resp.status)
+        self.assertGreaterEqual(len(body), 1)
+
+        # Accept a volume transfer by alt_tenant
+        resp, body = self.alt_client.accept_volume_transfer(transfer_id,
+                                                            auth_key)
+        self.assertEqual(202, resp.status)
+        self.alt_client.wait_for_volume_status(volume['id'], 'available')
+
+    def test_create_list_delete_volume_transfer(self):
+        # Create a volume first
+        vol_name = rand_name('-Volume-')
+        _, volume = self.client.create_volume(size=1, display_name=vol_name)
+        self.addCleanup(self.adm_client.delete_volume, volume['id'])
+        self.client.wait_for_volume_status(volume['id'], 'available')
+
+        # Create a volume transfer
+        resp, body = self.client.create_volume_transfer(volume['id'])
+        self.assertEqual(202, resp.status)
+        transfer_id = body['id']
+        self.client.wait_for_volume_status(volume['id'],
+                                           'awaiting-transfer')
+
+        # List all volume transfers, there's only one in this test
+        resp, body = self.client.list_volume_transfers()
+        self.assertEqual(200, resp.status)
+        self.assertEqual(volume['id'], body[0]['volume_id'])
+
+        # Delete a volume transfer
+        resp, body = self.client.delete_volume_transfer(transfer_id)
+        self.assertEqual(202, resp.status)
+        self.client.wait_for_volume_status(volume['id'], 'available')
+
+
+class VolumesTransfersTestXML(VolumesTransfersTest):
+    _interface = "xml"
diff --git a/tempest/api/volume/test_volumes_actions.py b/tempest/api/volume/test_volumes_actions.py
index f12d4bb..8581d16 100644
--- a/tempest/api/volume/test_volumes_actions.py
+++ b/tempest/api/volume/test_volumes_actions.py
@@ -123,6 +123,52 @@
         self.assertEqual(200, resp.status)
         self.assertEqual(int(volume['size']), extend_size)
 
+    @attr(type='gate')
+    def test_reserve_unreserve_volume(self):
+        # Mark volume as reserved.
+        resp, body = self.client.reserve_volume(self.volume['id'])
+        self.assertEqual(202, resp.status)
+        # To get the volume info
+        resp, body = self.client.get_volume(self.volume['id'])
+        self.assertEqual(200, resp.status)
+        self.assertIn('attaching', body['status'])
+        # Unmark volume as reserved.
+        resp, body = self.client.unreserve_volume(self.volume['id'])
+        self.assertEqual(202, resp.status)
+        # To get the volume info
+        resp, body = self.client.get_volume(self.volume['id'])
+        self.assertEqual(200, resp.status)
+        self.assertIn('available', body['status'])
+
+    def _is_true(self, val):
+        return val in ['true', 'True', True]
+
+    @attr(type='gate')
+    def test_volume_readonly_update(self):
+        # Update volume readonly true
+        readonly = True
+        resp, body = self.client.update_volume_readonly(self.volume['id'],
+                                                        readonly)
+        self.assertEqual(202, resp.status)
+
+        # Get Volume information
+        resp, fetched_volume = self.client.get_volume(self.volume['id'])
+        bool_flag = self._is_true(fetched_volume['metadata']['readonly'])
+        self.assertEqual(200, resp.status)
+        self.assertEqual(True, bool_flag)
+
+        # Update volume readonly false
+        readonly = False
+        resp, body = self.client.update_volume_readonly(self.volume['id'],
+                                                        readonly)
+        self.assertEqual(202, resp.status)
+
+        # Get Volume information
+        resp, fetched_volume = self.client.get_volume(self.volume['id'])
+        bool_flag = self._is_true(fetched_volume['metadata']['readonly'])
+        self.assertEqual(200, resp.status)
+        self.assertEqual(False, bool_flag)
+
 
 class VolumesActionsTestXML(VolumesActionsTest):
     _interface = "xml"
diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py
index f2915f7..14120fe 100644
--- a/tempest/api/volume/test_volumes_get.py
+++ b/tempest/api/volume/test_volumes_get.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest.api.volume import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 from tempest.test import services
 
@@ -46,7 +46,7 @@
     def _volume_create_get_update_delete(self, **kwargs):
         # Create a volume, Get it's details and Delete the volume
         volume = {}
-        v_name = rand_name('Volume')
+        v_name = data_utils.rand_name('Volume')
         metadata = {'Type': 'Test'}
         # Create a volume
         resp, volume = self.client.create_volume(size=1,
@@ -88,7 +88,7 @@
             self.assertEqual(boot_flag, False)
 
         # Update Volume
-        new_v_name = rand_name('new-Volume')
+        new_v_name = data_utils.rand_name('new-Volume')
         new_desc = 'This is the new description of volume'
         resp, update_volume = \
             self.client.update_volume(volume['id'],
@@ -118,7 +118,7 @@
     def test_volume_get_metadata_none(self):
         # Create a volume without passing metadata, get details, and delete
         volume = {}
-        v_name = rand_name('Volume-')
+        v_name = data_utils.rand_name('Volume-')
         # Create a volume without metadata
         resp, volume = self.client.create_volume(size=1,
                                                  display_name=v_name,
diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py
index 2aaa71d..4dbc88a 100644
--- a/tempest/api/volume/test_volumes_list.py
+++ b/tempest/api/volume/test_volumes_list.py
@@ -17,8 +17,7 @@
 #    under the License.
 
 from tempest.api.volume import base
-from tempest.common.utils.data_utils import rand_int_id
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.openstack.common import log as logging
 from tempest.test import attr
 
@@ -59,7 +58,7 @@
         cls.volume_list = []
         cls.volume_id_list = []
         for i in range(3):
-            v_name = rand_name('volume')
+            v_name = data_utils.rand_name('volume')
             metadata = {'Type': 'work'}
             try:
                 resp, volume = cls.client.create_volume(size=1,
@@ -107,7 +106,7 @@
 
     @attr(type='gate')
     def test_volume_list_by_name(self):
-        volume = self.volume_list[rand_int_id(0, 2)]
+        volume = self.volume_list[data_utils.rand_int_id(0, 2)]
         params = {'display_name': volume['display_name']}
         resp, fetched_vol = self.client.list_volumes(params)
         self.assertEqual(200, resp.status)
@@ -117,7 +116,7 @@
 
     @attr(type='gate')
     def test_volume_list_details_by_name(self):
-        volume = self.volume_list[rand_int_id(0, 2)]
+        volume = self.volume_list[data_utils.rand_int_id(0, 2)]
         params = {'display_name': volume['display_name']}
         resp, fetched_vol = self.client.list_volumes_with_detail(params)
         self.assertEqual(200, resp.status)
@@ -145,7 +144,7 @@
 
     @attr(type='gate')
     def test_volumes_list_by_availability_zone(self):
-        volume = self.volume_list[rand_int_id(0, 2)]
+        volume = self.volume_list[data_utils.rand_int_id(0, 2)]
         zone = volume['availability_zone']
         params = {'availability_zone': zone}
         resp, fetched_list = self.client.list_volumes(params)
@@ -156,7 +155,7 @@
 
     @attr(type='gate')
     def test_volumes_list_details_by_availability_zone(self):
-        volume = self.volume_list[rand_int_id(0, 2)]
+        volume = self.volume_list[data_utils.rand_int_id(0, 2)]
         zone = volume['availability_zone']
         params = {'availability_zone': zone}
         resp, fetched_list = self.client.list_volumes_with_detail(params)
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
index 9bab9a0..928bd49 100644
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -18,7 +18,7 @@
 import uuid
 
 from tempest.api.volume import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.test import attr
 
@@ -32,7 +32,7 @@
         cls.client = cls.volumes_client
 
         # Create a test shared instance and volume for attach/detach tests
-        vol_name = rand_name('Volume-')
+        vol_name = data_utils.rand_name('Volume-')
 
         cls.volume = cls.create_volume(size=1, display_name=vol_name)
         cls.client.wait_for_volume_status(cls.volume['id'], 'available')
@@ -54,7 +54,7 @@
     def test_create_volume_with_invalid_size(self):
         # Should not be able to create volume with invalid size
         # in request
-        v_name = rand_name('Volume-')
+        v_name = data_utils.rand_name('Volume-')
         metadata = {'Type': 'work'}
         self.assertRaises(exceptions.BadRequest, self.client.create_volume,
                           size='#$%', display_name=v_name, metadata=metadata)
@@ -63,7 +63,7 @@
     def test_create_volume_with_out_passing_size(self):
         # Should not be able to create volume without passing size
         # in request
-        v_name = rand_name('Volume-')
+        v_name = data_utils.rand_name('Volume-')
         metadata = {'Type': 'work'}
         self.assertRaises(exceptions.BadRequest, self.client.create_volume,
                           size='', display_name=v_name, metadata=metadata)
@@ -71,7 +71,7 @@
     @attr(type=['negative', 'gate'])
     def test_create_volume_with_size_zero(self):
         # Should not be able to create volume with size zero
-        v_name = rand_name('Volume-')
+        v_name = data_utils.rand_name('Volume-')
         metadata = {'Type': 'work'}
         self.assertRaises(exceptions.BadRequest, self.client.create_volume,
                           size='0', display_name=v_name, metadata=metadata)
@@ -79,7 +79,7 @@
     @attr(type=['negative', 'gate'])
     def test_create_volume_with_size_negative(self):
         # Should not be able to create volume with size negative
-        v_name = rand_name('Volume-')
+        v_name = data_utils.rand_name('Volume-')
         metadata = {'Type': 'work'}
         self.assertRaises(exceptions.BadRequest, self.client.create_volume,
                           size='-1', display_name=v_name, metadata=metadata)
@@ -87,7 +87,7 @@
     @attr(type=['negative', 'gate'])
     def test_create_volume_with_nonexistant_volume_type(self):
         # Should not be able to create volume with non-existant volume type
-        v_name = rand_name('Volume-')
+        v_name = data_utils.rand_name('Volume-')
         metadata = {'Type': 'work'}
         self.assertRaises(exceptions.NotFound, self.client.create_volume,
                           size='1', volume_type=str(uuid.uuid4()),
@@ -96,7 +96,7 @@
     @attr(type=['negative', 'gate'])
     def test_create_volume_with_nonexistant_snapshot_id(self):
         # Should not be able to create volume with non-existant snapshot
-        v_name = rand_name('Volume-')
+        v_name = data_utils.rand_name('Volume-')
         metadata = {'Type': 'work'}
         self.assertRaises(exceptions.NotFound, self.client.create_volume,
                           size='1', snapshot_id=str(uuid.uuid4()),
@@ -105,7 +105,7 @@
     @attr(type=['negative', 'gate'])
     def test_create_volume_with_nonexistant_source_volid(self):
         # Should not be able to create volume with non-existant source volume
-        v_name = rand_name('Volume-')
+        v_name = data_utils.rand_name('Volume-')
         metadata = {'Type': 'work'}
         self.assertRaises(exceptions.NotFound, self.client.create_volume,
                           size='1', source_volid=str(uuid.uuid4()),
@@ -113,7 +113,7 @@
 
     @attr(type=['negative', 'gate'])
     def test_update_volume_with_nonexistant_volume_id(self):
-        v_name = rand_name('Volume-')
+        v_name = data_utils.rand_name('Volume-')
         metadata = {'Type': 'work'}
         self.assertRaises(exceptions.NotFound, self.client.update_volume,
                           volume_id=str(uuid.uuid4()), display_name=v_name,
@@ -121,7 +121,7 @@
 
     @attr(type=['negative', 'gate'])
     def test_update_volume_with_invalid_volume_id(self):
-        v_name = rand_name('Volume-')
+        v_name = data_utils.rand_name('Volume-')
         metadata = {'Type': 'work'}
         self.assertRaises(exceptions.NotFound, self.client.update_volume,
                           volume_id='#$%%&^&^', display_name=v_name,
@@ -129,7 +129,7 @@
 
     @attr(type=['negative', 'gate'])
     def test_update_volume_with_empty_volume_id(self):
-        v_name = rand_name('Volume-')
+        v_name = data_utils.rand_name('Volume-')
         metadata = {'Type': 'work'}
         self.assertRaises(exceptions.NotFound, self.client.update_volume,
                           volume_id='', display_name=v_name,
@@ -159,7 +159,7 @@
 
     @attr(type=['negative', 'gate'])
     def test_attach_volumes_with_nonexistent_volume_id(self):
-        srv_name = rand_name('Instance-')
+        srv_name = data_utils.rand_name('Instance-')
         resp, server = self.servers_client.create_server(srv_name,
                                                          self.image_ref,
                                                          self.flavor_ref)
@@ -212,6 +212,61 @@
         self.assertRaises(exceptions.NotFound, self.client.extend_volume,
                           None, extend_size)
 
+    @attr(type=['negative', 'gate'])
+    def test_reserve_volume_with_nonexistent_volume_id(self):
+        self.assertRaises(exceptions.NotFound,
+                          self.client.reserve_volume,
+                          str(uuid.uuid4()))
+
+    @attr(type=['negative', 'gate'])
+    def test_unreserve_volume_with_nonexistent_volume_id(self):
+        self.assertRaises(exceptions.NotFound,
+                          self.client.unreserve_volume,
+                          str(uuid.uuid4()))
+
+    @attr(type=['negative', 'gate'])
+    def test_reserve_volume_with_negative_volume_status(self):
+        # Mark volume as reserved.
+        resp, body = self.client.reserve_volume(self.volume['id'])
+        self.assertEqual(202, resp.status)
+        # Mark volume which is marked as reserved before
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.reserve_volume,
+                          self.volume['id'])
+        # Unmark volume as reserved.
+        resp, body = self.client.unreserve_volume(self.volume['id'])
+        self.assertEqual(202, resp.status)
+
+    @attr(type=['negative', 'gate'])
+    def test_list_volumes_with_nonexistent_name(self):
+        v_name = data_utils.rand_name('Volume-')
+        params = {'display_name': v_name}
+        resp, fetched_volume = self.client.list_volumes(params)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(0, len(fetched_volume))
+
+    @attr(type=['negative', 'gate'])
+    def test_list_volumes_detail_with_nonexistent_name(self):
+        v_name = data_utils.rand_name('Volume-')
+        params = {'display_name': v_name}
+        resp, fetched_volume = self.client.list_volumes_with_detail(params)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(0, len(fetched_volume))
+
+    @attr(type=['negative', 'gate'])
+    def test_list_volumes_with_invalid_status(self):
+        params = {'status': 'null'}
+        resp, fetched_volume = self.client.list_volumes(params)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(0, len(fetched_volume))
+
+    @attr(type=['negative', 'gate'])
+    def test_list_volumes_detail_with_invalid_status(self):
+        params = {'status': 'null'}
+        resp, fetched_volume = self.client.list_volumes_with_detail(params)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(0, len(fetched_volume))
+
 
 class VolumesNegativeTestXML(VolumesNegativeTest):
     _interface = 'xml'
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 6b186e5..99e8de7 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -13,7 +13,7 @@
 #    under the License.
 
 from tempest.api.volume import base
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.openstack.common import log as logging
 from tempest.test import attr
 
@@ -40,7 +40,7 @@
     @attr(type='gate')
     def test_snapshot_create_get_list_update_delete(self):
         # Create a snapshot
-        s_name = rand_name('snap')
+        s_name = data_utils.rand_name('snap')
         snapshot = self.create_snapshot(self.volume_origin['id'],
                                         display_name=s_name)
 
@@ -59,7 +59,7 @@
         self.assertIn(tracking_data, snaps_data)
 
         # Updates snapshot with new values
-        new_s_name = rand_name('new-snap')
+        new_s_name = data_utils.rand_name('new-snap')
         new_desc = 'This is the new description of snapshot.'
         resp, update_snapshot = \
             self.snapshots_client.update_snapshot(snapshot['id'],
diff --git a/tempest/cli/__init__.py b/tempest/cli/__init__.py
index bd1b44f..ec8b3a1 100644
--- a/tempest/cli/__init__.py
+++ b/tempest/cli/__init__.py
@@ -128,7 +128,8 @@
             if not fail_ok and proc.returncode != 0:
                 raise CommandFailed(proc.returncode,
                                     cmd,
-                                    result)
+                                    result,
+                                    stderr=result_err)
         finally:
             LOG.debug('output of %s:\n%s' % (cmd_str, result))
             if not merge_stderr and result_err:
@@ -149,6 +150,7 @@
 
 class CommandFailed(subprocess.CalledProcessError):
     # adds output attribute for python2.6
-    def __init__(self, returncode, cmd, output):
+    def __init__(self, returncode, cmd, output, stderr=""):
         super(CommandFailed, self).__init__(returncode, cmd)
         self.output = output
+        self.stderr = stderr
diff --git a/tempest/cli/simple_read_only/test_neutron.py b/tempest/cli/simple_read_only/test_neutron.py
index 9bd07d0..047b17d 100644
--- a/tempest/cli/simple_read_only/test_neutron.py
+++ b/tempest/cli/simple_read_only/test_neutron.py
@@ -76,6 +76,25 @@
     def test_neutron_meter_label_rule_list(self):
         self.neutron('meter-label-rule-list')
 
+    def _test_neutron_lbaas_command(self, command):
+        try:
+            self.neutron(command)
+        except tempest.cli.CommandFailed as e:
+            if '404 Not Found' not in e.stderr:
+                self.fail('%s: Unexpected failure.' % command)
+
+    def test_neutron_lb_healthmonitor_list(self):
+        self._test_neutron_lbaas_command('lb-healthmonitor-list')
+
+    def test_neutron_lb_member_list(self):
+        self._test_neutron_lbaas_command('lb-member-list')
+
+    def test_neutron_lb_pool_list(self):
+        self._test_neutron_lbaas_command('lb-pool-list')
+
+    def test_neutron_lb_vip_list(self):
+        self._test_neutron_lbaas_command('lb-vip-list')
+
     def test_neutron_net_external_list(self):
         self.neutron('net-external-list')
 
diff --git a/tempest/clients.py b/tempest/clients.py
index dd104a7..ac79ce0 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -23,6 +23,8 @@
     AggregatesClientJSON
 from tempest.services.compute.json.availability_zone_client import \
     AvailabilityZoneClientJSON
+from tempest.services.compute.json.certificates_client import \
+    CertificatesClientJSON
 from tempest.services.compute.json.extensions_client import \
     ExtensionsClientJSON
 from tempest.services.compute.json.fixed_ips_client import FixedIPsClientJSON
@@ -33,6 +35,8 @@
 from tempest.services.compute.json.hypervisor_client import \
     HypervisorClientJSON
 from tempest.services.compute.json.images_client import ImagesClientJSON
+from tempest.services.compute.json.instance_usage_audit_log_client import \
+    InstanceUsagesAuditLogClientJSON
 from tempest.services.compute.json.interfaces_client import \
     InterfacesClientJSON
 from tempest.services.compute.json.keypairs_client import KeyPairsClientJSON
@@ -46,9 +50,38 @@
     TenantUsagesClientJSON
 from tempest.services.compute.json.volumes_extensions_client import \
     VolumesExtensionsClientJSON
+from tempest.services.compute.v3.json.availability_zone_client import \
+    AvailabilityZoneV3ClientJSON
+from tempest.services.compute.v3.json.extensions_client import \
+    ExtensionsV3ClientJSON
+from tempest.services.compute.v3.json.hypervisor_client import \
+    HypervisorV3ClientJSON
+from tempest.services.compute.v3.json.interfaces_client import \
+    InterfacesV3ClientJSON
+from tempest.services.compute.v3.json.servers_client import \
+    ServersV3ClientJSON
+from tempest.services.compute.v3.json.services_client import \
+    ServicesV3ClientJSON
+from tempest.services.compute.v3.json.tenant_usages_client import \
+    TenantUsagesV3ClientJSON
+from tempest.services.compute.v3.xml.availability_zone_client import \
+    AvailabilityZoneV3ClientXML
+from tempest.services.compute.v3.xml.extensions_client import \
+    ExtensionsV3ClientXML
+from tempest.services.compute.v3.xml.hypervisor_client import \
+    HypervisorV3ClientXML
+from tempest.services.compute.v3.xml.interfaces_client import \
+    InterfacesV3ClientXML
+from tempest.services.compute.v3.xml.servers_client import ServersV3ClientXML
+from tempest.services.compute.v3.xml.services_client import \
+    ServicesV3ClientXML
+from tempest.services.compute.v3.xml.tenant_usages_client import \
+    TenantUsagesV3ClientXML
 from tempest.services.compute.xml.aggregates_client import AggregatesClientXML
 from tempest.services.compute.xml.availability_zone_client import \
     AvailabilityZoneClientXML
+from tempest.services.compute.xml.certificates_client import \
+    CertificatesClientXML
 from tempest.services.compute.xml.extensions_client import ExtensionsClientXML
 from tempest.services.compute.xml.fixed_ips_client import FixedIPsClientXML
 from tempest.services.compute.xml.flavors_client import FlavorsClientXML
@@ -56,6 +89,8 @@
     FloatingIPsClientXML
 from tempest.services.compute.xml.hypervisor_client import HypervisorClientXML
 from tempest.services.compute.xml.images_client import ImagesClientXML
+from tempest.services.compute.xml.instance_usage_audit_log_client import \
+    InstanceUsagesAuditLogClientXML
 from tempest.services.compute.xml.interfaces_client import \
     InterfacesClientXML
 from tempest.services.compute.xml.keypairs_client import KeyPairsClientXML
@@ -105,10 +140,14 @@
     ObjectClientCustomizedHeader
 from tempest.services.orchestration.json.orchestration_client import \
     OrchestrationClient
+from tempest.services.volume.json.admin.volume_hosts_client import \
+    VolumeHostsClientJSON
 from tempest.services.volume.json.admin.volume_types_client import \
     VolumeTypesClientJSON
 from tempest.services.volume.json.snapshots_client import SnapshotsClientJSON
 from tempest.services.volume.json.volumes_client import VolumesClientJSON
+from tempest.services.volume.xml.admin.volume_hosts_client import \
+    VolumeHostsClientXML
 from tempest.services.volume.xml.admin.volume_types_client import \
     VolumeTypesClientXML
 from tempest.services.volume.xml.snapshots_client import SnapshotsClientXML
@@ -166,12 +205,15 @@
         self.servers_client_v3_auth = None
 
         if interface == 'xml':
+            self.certificates_client = CertificatesClientXML(*client_args)
             self.servers_client = ServersClientXML(*client_args)
+            self.servers_v3_client = ServersV3ClientXML(*client_args)
             self.limits_client = LimitsClientXML(*client_args)
             self.images_client = ImagesClientXML(*client_args)
             self.keypairs_client = KeyPairsClientXML(*client_args)
             self.quotas_client = QuotasClientXML(*client_args)
             self.flavors_client = FlavorsClientXML(*client_args)
+            self.extensions_v3_client = ExtensionsV3ClientXML(*client_args)
             self.extensions_client = ExtensionsClientXML(*client_args)
             self.volumes_extensions_client = VolumesExtensionsClientXML(
                 *client_args)
@@ -184,32 +226,45 @@
             self.token_client = TokenClientXML(self.config)
             self.security_groups_client = SecurityGroupsClientXML(
                 *client_args)
+            self.interfaces_v3_client = InterfacesV3ClientXML(*client_args)
             self.interfaces_client = InterfacesClientXML(*client_args)
             self.endpoints_client = EndPointClientXML(*client_args)
             self.fixed_ips_client = FixedIPsClientXML(*client_args)
+            self.availability_zone_v3_client = AvailabilityZoneV3ClientXML(
+                *client_args)
             self.availability_zone_client = AvailabilityZoneClientXML(
                 *client_args)
+            self.services_v3_client = ServicesV3ClientXML(*client_args)
             self.service_client = ServiceClientXML(*client_args)
             self.aggregates_client = AggregatesClientXML(*client_args)
             self.services_client = ServicesClientXML(*client_args)
+            self.tenant_usages_v3_client = TenantUsagesV3ClientXML(
+                *client_args)
             self.tenant_usages_client = TenantUsagesClientXML(*client_args)
             self.policy_client = PolicyClientXML(*client_args)
+            self.hypervisor_v3_client = HypervisorV3ClientXML(*client_args)
             self.hypervisor_client = HypervisorClientXML(*client_args)
             self.token_v3_client = V3TokenClientXML(*client_args)
             self.network_client = NetworkClientXML(*client_args)
             self.credentials_client = CredentialsClientXML(*client_args)
+            self.instance_usages_audit_log_client = \
+                InstanceUsagesAuditLogClientXML(*client_args)
+            self.volume_hosts_client = VolumeHostsClientXML(*client_args)
 
             if client_args_v3_auth:
                 self.servers_client_v3_auth = ServersClientXML(
                     *client_args_v3_auth)
 
         elif interface == 'json':
+            self.certificates_client = CertificatesClientJSON(*client_args)
             self.servers_client = ServersClientJSON(*client_args)
+            self.servers_v3_client = ServersV3ClientJSON(*client_args)
             self.limits_client = LimitsClientJSON(*client_args)
             self.images_client = ImagesClientJSON(*client_args)
             self.keypairs_client = KeyPairsClientJSON(*client_args)
             self.quotas_client = QuotasClientJSON(*client_args)
             self.flavors_client = FlavorsClientJSON(*client_args)
+            self.extensions_v3_client = ExtensionsV3ClientJSON(*client_args)
             self.extensions_client = ExtensionsClientJSON(*client_args)
             self.volumes_extensions_client = VolumesExtensionsClientJSON(
                 *client_args)
@@ -222,20 +277,30 @@
             self.token_client = TokenClientJSON(self.config)
             self.security_groups_client = SecurityGroupsClientJSON(
                 *client_args)
+            self.interfaces_v3_client = InterfacesV3ClientJSON(*client_args)
             self.interfaces_client = InterfacesClientJSON(*client_args)
             self.endpoints_client = EndPointClientJSON(*client_args)
             self.fixed_ips_client = FixedIPsClientJSON(*client_args)
+            self.availability_zone_v3_client = AvailabilityZoneV3ClientJSON(
+                *client_args)
             self.availability_zone_client = AvailabilityZoneClientJSON(
                 *client_args)
+            self.services_v3_client = ServicesV3ClientJSON(*client_args)
             self.service_client = ServiceClientJSON(*client_args)
             self.aggregates_client = AggregatesClientJSON(*client_args)
             self.services_client = ServicesClientJSON(*client_args)
+            self.tenant_usages_v3_client = TenantUsagesV3ClientJSON(
+                *client_args)
             self.tenant_usages_client = TenantUsagesClientJSON(*client_args)
             self.policy_client = PolicyClientJSON(*client_args)
+            self.hypervisor_v3_client = HypervisorV3ClientJSON(*client_args)
             self.hypervisor_client = HypervisorClientJSON(*client_args)
             self.token_v3_client = V3TokenClientJSON(*client_args)
             self.network_client = NetworkClientJSON(*client_args)
             self.credentials_client = CredentialsClientJSON(*client_args)
+            self.instance_usages_audit_log_client = \
+                InstanceUsagesAuditLogClientJSON(*client_args)
+            self.volume_hosts_client = VolumeHostsClientJSON(*client_args)
 
             if client_args_v3_auth:
                 self.servers_client_v3_auth = ServersClientJSON(
@@ -267,11 +332,12 @@
     managed client objects
     """
 
-    def __init__(self):
+    def __init__(self, interface='json'):
         conf = config.TempestConfig()
         super(AltManager, self).__init__(conf.identity.alt_username,
                                          conf.identity.alt_password,
-                                         conf.identity.alt_tenant_name)
+                                         conf.identity.alt_tenant_name,
+                                         interface=interface)
 
 
 class AdminManager(Manager):
diff --git a/tempest/common/custom_matchers.py b/tempest/common/custom_matchers.py
new file mode 100644
index 0000000..307d5db
--- /dev/null
+++ b/tempest/common/custom_matchers.py
@@ -0,0 +1,154 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 NTT Corporation
+#
+#    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 re
+
+
+class ExistsAllResponseHeaders(object):
+    """
+    Specific matcher to check the existence of Swift's response headers
+
+    This matcher checks the existence of common headers for each HTTP method
+    or the target, which means account, container or object.
+    When checking the existence of 'specific' headers such as
+    X-Account-Meta-* or X-Object-Manifest for example, those headers must be
+    checked in each test code.
+    """
+
+    def __init__(self, target, method):
+        """
+        param: target Account/Container/Object
+        param: method PUT/GET/HEAD/DELETE/COPY/POST
+        """
+        self.target = target
+        self.method = method
+
+    def match(self, actual):
+        """
+        param: actual HTTP response headers
+        """
+        # Check common headers for all HTTP methods
+        if 'content-length' not in actual:
+            return NonExistentHeader('content-length')
+        if 'content-type' not in actual:
+            return NonExistentHeader('content-type')
+        if 'x-trans-id' not in actual:
+            return NonExistentHeader('x-trans-id')
+        if 'date' not in actual:
+            return NonExistentHeader('date')
+
+        # Check headers for a specific method or target
+        if self.method == 'GET' or self.method == 'HEAD':
+            if 'x-timestamp' not in actual:
+                return NonExistentHeader('x-timestamp')
+            if 'accept-ranges' not in actual:
+                return NonExistentHeader('accept-ranges')
+            if self.target == 'Account':
+                if 'x-account-bytes-used' not in actual:
+                    return NonExistentHeader('x-account-bytes-used')
+                if 'x-account-container-count' not in actual:
+                    return NonExistentHeader('x-account-container-count')
+                if 'x-account-object-count' not in actual:
+                    return NonExistentHeader('x-account-object-count')
+            elif self.target == 'Container':
+                if 'x-container-bytes-used' not in actual:
+                    return NonExistentHeader('x-container-bytes-used')
+                if 'x-container-object-count' not in actual:
+                    return NonExistentHeader('x-container-object-count')
+            elif self.target == 'Object':
+                if 'etag' not in actual:
+                    return NonExistentHeader('etag')
+        elif self.method == 'PUT' or self.method == 'COPY':
+            if self.target == 'Object':
+                if 'etag' not in actual:
+                    return NonExistentHeader('etag')
+
+        return None
+
+
+class NonExistentHeader(object):
+    """
+    Informs an error message for end users in the case of missing a
+    certain header in Swift's responses
+    """
+
+    def __init__(self, header):
+        self.header = header
+
+    def describe(self):
+        return "%s header does not exist" % self.header
+
+    def get_details(self):
+        return {}
+
+
+class AreAllWellFormatted(object):
+    """
+    Specific matcher to check the correctness of formats of values of Swift's
+    response headers
+
+    This matcher checks the format of values of response headers.
+    When checking the format of values of 'specific' headers such as
+    X-Account-Meta-* or X-Object-Manifest for example, those values must be
+    checked in each test code.
+    """
+
+    def match(self, actual):
+        for key, value in actual.iteritems():
+            if key == 'content-length' and not value.isdigit():
+                return InvalidFormat(key, value)
+            elif key == 'x-timestamp' and not re.match("^\d+\.?\d*\Z", value):
+                return InvalidFormat(key, value)
+            elif key == 'x-account-bytes-used' and not value.isdigit():
+                return InvalidFormat(key, value)
+            elif key == 'x-account-container-count' and not value.isdigit():
+                return InvalidFormat(key, value)
+            elif key == 'x-account-object-count' and not value.isdigit():
+                return InvalidFormat(key, value)
+            elif key == 'x-container-bytes-used' and not value.isdigit():
+                return InvalidFormat(key, value)
+            elif key == 'x-container-object-count' and not value.isdigit():
+                return InvalidFormat(key, value)
+            elif key == 'content-type' and not value:
+                return InvalidFormat(key, value)
+            elif key == 'x-trans-id' and \
+                not re.match("^tx[0-9a-f]*-[0-9a-f]*$", value):
+                return InvalidFormat(key, value)
+            elif key == 'date' and not value:
+                return InvalidFormat(key, value)
+            elif key == 'accept-ranges' and not value == 'bytes':
+                return InvalidFormat(key, value)
+            elif key == 'etag' and not value.isalnum():
+                return InvalidFormat(key, value)
+
+        return None
+
+
+class InvalidFormat(object):
+    """
+    Informs an error message for end users if a format of a certain header
+    is invalid
+    """
+
+    def __init__(self, key, value):
+        self.key = key
+        self.value = value
+
+    def describe(self):
+        return "InvalidFormat (%s, %s)" % (self.key, self.value)
+
+    def get_details(self):
+        return {}
diff --git a/tempest/common/generate_sample_tempest.py b/tempest/common/generate_sample_tempest.py
new file mode 100644
index 0000000..545703b
--- /dev/null
+++ b/tempest/common/generate_sample_tempest.py
@@ -0,0 +1,35 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM Corp.
+# 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 sys
+
+from tempest import config
+from tempest.openstack.common.config import generator
+
+# NOTE(mtreinish): This hack is needed because of how oslo config is used in
+# tempest. Tempest is run from inside a test runner and so we can't rely on the
+# global CONF object being fully populated when we run a test. (test runners
+# don't init every file for running a test) So to get around that we manually
+# load the config file in tempest for each test class to ensure that every
+# config option is set. However, the tool expects the CONF object to be fully
+# populated when it inits all the files in the project. This just works around
+# the issue by manually loading the config file (which may or may not exist)
+# which will populate all the options before running the generator.
+
+config.TempestConfig()
+generator.generate(sys.argv[1:])
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index 8c82ec0..5dbb3a7 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -20,7 +20,7 @@
 import neutronclient.v2_0.client as neutronclient
 
 from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import config
 from tempest import exceptions
 from tempest.openstack.common import log as logging
@@ -147,17 +147,17 @@
             self.identity_admin_client.tenants.delete(tenant)
 
     def _create_creds(self, suffix=None, admin=False):
-        rand_name_root = rand_name(self.name)
+        data_utils.rand_name_root = data_utils.rand_name(self.name)
         if suffix:
-            rand_name_root += suffix
-        tenant_name = rand_name_root + "-tenant"
+            data_utils.rand_name_root += suffix
+        tenant_name = data_utils.rand_name_root + "-tenant"
         tenant_desc = tenant_name + "-desc"
         tenant = self._create_tenant(name=tenant_name,
                                      description=tenant_desc)
         if suffix:
-            rand_name_root += suffix
-        username = rand_name_root + "-user"
-        email = rand_name_root + "@example.com"
+            data_utils.rand_name_root += suffix
+        username = data_utils.rand_name_root + "-user"
+        email = data_utils.rand_name_root + "@example.com"
         user = self._create_user(username, self.password,
                                  tenant, email)
         if admin:
@@ -197,13 +197,13 @@
         network = None
         subnet = None
         router = None
-        rand_name_root = rand_name(self.name)
-        network_name = rand_name_root + "-network"
+        data_utils.rand_name_root = data_utils.rand_name(self.name)
+        network_name = data_utils.rand_name_root + "-network"
         network = self._create_network(network_name, tenant_id)
         try:
-            subnet_name = rand_name_root + "-subnet"
+            subnet_name = data_utils.rand_name_root + "-subnet"
             subnet = self._create_subnet(subnet_name, tenant_id, network['id'])
-            router_name = rand_name_root + "-router"
+            router_name = data_utils.rand_name_root + "-router"
             router = self._create_router(router_name, tenant_id)
             self._add_router_interface(router['id'], subnet['id'])
         except Exception:
@@ -412,7 +412,11 @@
                 resp_body = self.network_admin_client.list_ports()
             self.ports = resp_body['ports']
         ports_to_delete = [
-            port for port in self.ports if port['network_id'] == network_id]
+            port
+            for port in self.ports
+            if (port['network_id'] == network_id and
+                port['device_owner'] != 'network:router_interface')
+        ]
         for port in ports_to_delete:
             try:
                 LOG.info('Cleaning up port id %s, name %s' %
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index 9322f1b..9aca2ff 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -506,18 +506,26 @@
         if resp.status in (500, 501):
             message = resp_body
             if parse_resp:
-                resp_body = self._parse_resp(resp_body)
-                # I'm seeing both computeFault and cloudServersFault come back.
-                # Will file a bug to fix, but leave as is for now.
-                if 'cloudServersFault' in resp_body:
-                    message = resp_body['cloudServersFault']['message']
-                elif 'computeFault' in resp_body:
-                    message = resp_body['computeFault']['message']
-                elif 'error' in resp_body:  # Keystone errors
-                    message = resp_body['error']['message']
-                    raise exceptions.IdentityError(message)
-                elif 'message' in resp_body:
-                    message = resp_body['message']
+                try:
+                    resp_body = self._parse_resp(resp_body)
+                except ValueError:
+                    # If response body is a non-json string message.
+                    # Use resp_body as is and raise InvalidResponseBody
+                    # exception.
+                    raise exceptions.InvalidHTTPResponseBody(message)
+                else:
+                    # I'm seeing both computeFault
+                    # and cloudServersFault come back.
+                    # Will file a bug to fix, but leave as is for now.
+                    if 'cloudServersFault' in resp_body:
+                        message = resp_body['cloudServersFault']['message']
+                    elif 'computeFault' in resp_body:
+                        message = resp_body['computeFault']['message']
+                    elif 'error' in resp_body:  # Keystone errors
+                        message = resp_body['error']['message']
+                        raise exceptions.IdentityError(message)
+                    elif 'message' in resp_body:
+                        message = resp_body['message']
 
             raise exceptions.ServerFault(message)
 
diff --git a/tempest/common/ssh.py b/tempest/common/ssh.py
index 3eaa203..c397b7c 100644
--- a/tempest/common/ssh.py
+++ b/tempest/common/ssh.py
@@ -62,11 +62,12 @@
                             password=self.password,
                             look_for_keys=self.look_for_keys,
                             key_filename=self.key_filename,
-                            timeout=self.timeout, pkey=self.pkey)
+                            timeout=self.channel_timeout, pkey=self.pkey)
                 _timeout = False
                 break
             except (socket.error,
-                    paramiko.AuthenticationException):
+                    paramiko.AuthenticationException,
+                    paramiko.SSHException):
                 time.sleep(bsleep)
                 bsleep *= backoff
                 continue
diff --git a/tempest/common/utils/data_utils.py b/tempest/common/utils/data_utils.py
index 3ab8fe0..4f93e1c 100644
--- a/tempest/common/utils/data_utils.py
+++ b/tempest/common/utils/data_utils.py
@@ -19,10 +19,19 @@
 import random
 import re
 import urllib
+import uuid
 
 from tempest import exceptions
 
 
+def rand_uuid():
+    return str(uuid.uuid4())
+
+
+def rand_uuid_hex():
+    return uuid.uuid4().hex
+
+
 def rand_name(name='test'):
     return name + "-tempest-" + str(random.randint(1, 0x7fffffff))
 
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index 15569cd..44198f0 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -24,7 +24,8 @@
 
 
 # NOTE(afazekas): This function needs to know a token and a subject.
-def wait_for_server_status(client, server_id, status, ready_wait=True):
+def wait_for_server_status(client, server_id, status, ready_wait=True,
+                           extra_timeout=0, raise_on_error=True):
     """Waits for a server to reach a given status."""
 
     def _get_task_state(body):
@@ -37,6 +38,7 @@
     old_status = server_status = body['status']
     old_task_state = task_state = _get_task_state(body)
     start_time = int(time.time())
+    timeout = client.build_timeout + extra_timeout
     while True:
         # NOTE(afazekas): Now the BUILD status only reached
         # between the UNKOWN->ACTIVE transition.
@@ -67,16 +69,22 @@
                      '/'.join((old_status, str(old_task_state))),
                      '/'.join((server_status, str(task_state))),
                      time.time() - start_time)
-        if server_status == 'ERROR':
+        if (server_status == 'ERROR') and raise_on_error:
             raise exceptions.BuildErrorException(server_id=server_id)
 
-        timed_out = int(time.time()) - start_time >= client.build_timeout
+        timed_out = int(time.time()) - start_time >= timeout
 
         if timed_out:
-            message = ('Server %s failed to reach %s status within the '
-                       'required time (%s s).' %
-                       (server_id, status, client.build_timeout))
+            expected_task_state = 'None' if ready_wait else 'n/a'
+            message = ('Server %(server_id)s failed to reach %(status)s '
+                       'status and task state "%(expected_task_state)s" '
+                       'within the required time (%(timeout)s s).' %
+                       {'server_id': server_id,
+                        'status': status,
+                        'expected_task_state': expected_task_state,
+                        'timeout': timeout})
             message += ' Current status: %s.' % server_status
+            message += ' Current task state: %s.' % task_state
             raise exceptions.TimeoutException(message)
         old_status = server_status
         old_task_state = task_state
diff --git a/tempest/config.py b/tempest/config.py
index 925c4bd..3d9eba9 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -103,25 +103,17 @@
                      "users. This option enables isolated test cases and "
                      "better parallel execution, but also requires that "
                      "OpenStack Identity API admin credentials are known."),
-    cfg.BoolOpt('allow_tenant_reuse',
-                default=True,
-                help="If allow_tenant_isolation is True and a tenant that "
-                     "would be created for a given test already exists (such "
-                     "as from a previously-failed run), re-use that tenant "
-                     "instead of failing because of the conflict. Note that "
-                     "this would result in the tenant being deleted at the "
-                     "end of a subsequent successful run."),
     cfg.StrOpt('image_ref',
                default="{$IMAGE_ID}",
                help="Valid secondary image reference to be used in tests."),
     cfg.StrOpt('image_ref_alt',
                default="{$IMAGE_ID_ALT}",
                help="Valid secondary image reference to be used in tests."),
-    cfg.IntOpt('flavor_ref',
-               default=1,
+    cfg.StrOpt('flavor_ref',
+               default="1",
                help="Valid primary flavor to use in tests."),
-    cfg.IntOpt('flavor_ref_alt',
-               default=2,
+    cfg.StrOpt('flavor_ref_alt',
+               default="2",
                help='Valid secondary flavor to be used in tests.'),
     cfg.StrOpt('image_ssh_user',
                default="root",
@@ -186,6 +178,9 @@
                     "of identity.region is used instead. If no such region "
                     "is found in the service catalog, the first found one is "
                     "used."),
+    cfg.StrOpt('catalog_v3_type',
+               default='computev3',
+               help="Catalog type of the Compute v3 service."),
     cfg.StrOpt('path_to_private_key',
                default=None,
                help="Path to a private key file for SSH access to remote "
@@ -193,19 +188,34 @@
     cfg.StrOpt('volume_device_name',
                default='vdb',
                help="Expected device name when a volume is attached to "
-                    "an instance")
+                    "an instance"),
+    cfg.IntOpt('shelved_offload_time',
+               default=0,
+               help='Time in seconds before a shelved instance is eligible '
+                    'for removing from a host.  -1 never offload, 0 offload '
+                    'when shelved. This time should be the same as the time '
+                    'of nova.conf, and some tests will run for as long as the '
+                    'time.')
 ]
 
 compute_features_group = cfg.OptGroup(name='compute-feature-enabled',
                                       title="Enabled Compute Service Features")
 
 ComputeFeaturesGroup = [
+    cfg.BoolOpt('api_v3',
+                default=True,
+                help="If false, skip all nova v3 tests."),
     cfg.BoolOpt('disk_config',
                 default=True,
                 help="If false, skip disk config tests"),
-    cfg.BoolOpt('flavor_extra',
-                default=True,
-                help="If false, skip flavor extra data test"),
+    cfg.ListOpt('api_extensions',
+                default=['all'],
+                help='A list of enabled extensions with a special entry all '
+                     'which indicates every extension is enabled'),
+    cfg.ListOpt('api_v3_extensions',
+                default=['all'],
+                help='A list of enabled v3 extensions with a special entry all'
+                     ' which indicates every extension is enabled'),
     cfg.BoolOpt('change_password',
                 default=False,
                 help="Does the test environment support changing the admin "
@@ -312,6 +322,16 @@
                     "connectivity"),
 ]
 
+network_feature_group = cfg.OptGroup(name='network-feature-enabled',
+                                     title='Enabled network service features')
+
+NetworkFeaturesGroup = [
+    cfg.ListOpt('api_extensions',
+                default=['all'],
+                help='A list of enabled extensions with a special entry all '
+                     'which indicates every extension is enabled'),
+]
+
 volume_group = cfg.OptGroup(name='volume',
                             title='Block Storage Options')
 
@@ -355,7 +375,11 @@
 VolumeFeaturesGroup = [
     cfg.BoolOpt('multi_backend',
                 default=False,
-                help="Runs Cinder multi-backend test (requires 2 backends)")
+                help="Runs Cinder multi-backend test (requires 2 backends)"),
+    cfg.ListOpt('api_extensions',
+                default=['all'],
+                help='A list of enabled extensions with a special entry all '
+                     'which indicates every extension is enabled'),
 ]
 
 
@@ -393,11 +417,17 @@
 ObjectStoreFeaturesGroup = [
     cfg.BoolOpt('container_quotas',
                 default=True,
-                help="Set to True if the container quota middleware "
+                help="Set to True if the Container Quota middleware "
                      "is enabled"),
     cfg.BoolOpt('accounts_quotas',
                 default=True,
                 help="Set to True if the Account Quota middleware is enabled"),
+    cfg.BoolOpt('crossdomain',
+                default=True,
+                help="Set to True if the Crossdomain middleware is enabled"),
+    cfg.BoolOpt('tempurl',
+                default=True,
+                help="Set to True if the TempURL middleware is enabled"),
 ]
 
 
@@ -648,6 +678,8 @@
         register_opt_group(cfg.CONF, image_group, ImageGroup)
         register_opt_group(cfg.CONF, image_feature_group, ImageFeaturesGroup)
         register_opt_group(cfg.CONF, network_group, NetworkGroup)
+        register_opt_group(cfg.CONF, network_feature_group,
+                           NetworkFeaturesGroup)
         register_opt_group(cfg.CONF, volume_group, VolumeGroup)
         register_opt_group(cfg.CONF, volume_feature_group,
                            VolumeFeaturesGroup)
@@ -669,6 +701,7 @@
         self.images = cfg.CONF.image
         self.image_feature_enabled = cfg.CONF['image-feature-enabled']
         self.network = cfg.CONF.network
+        self.network_feature_enabled = cfg.CONF['network-feature-enabled']
         self.volume = cfg.CONF.volume
         self.volume_feature_enabled = cfg.CONF['volume-feature-enabled']
         self.object_storage = cfg.CONF['object-storage']
diff --git a/tempest/exceptions.py b/tempest/exceptions.py
index 67406b0..0bab9c7 100644
--- a/tempest/exceptions.py
+++ b/tempest/exceptions.py
@@ -82,7 +82,7 @@
 
 
 class ImageKilledException(TempestException):
-    message = "Image %(image_id)s 'killed' while waiting for %(status)s"
+    message = "Image %(image_id)s 'killed' while waiting for '%(status)s'"
 
 
 class AddImageException(TempestException):
@@ -184,3 +184,7 @@
 class ResponseWithEntity(RFCViolation):
     message = ("RFC Violation! Response with 205 HTTP Status Code "
                "MUST NOT have an entity")
+
+
+class InvalidHTTPResponseBody(RestClientException):
+    message = "HTTP response body is invalid json or xml"
diff --git a/tempest/openstack/common/config/__init__.py b/tempest/openstack/common/config/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/openstack/common/config/__init__.py
diff --git a/tempest/openstack/common/config/generator.py b/tempest/openstack/common/config/generator.py
new file mode 100644
index 0000000..373f9a6
--- /dev/null
+++ b/tempest/openstack/common/config/generator.py
@@ -0,0 +1,268 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 SINA 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.
+#
+
+"""Extracts OpenStack config option info from module(s)."""
+
+from __future__ import print_function
+
+import imp
+import os
+import re
+import socket
+import sys
+import textwrap
+
+from oslo.config import cfg
+
+from tempest.openstack.common import gettextutils
+from tempest.openstack.common import importutils
+
+gettextutils.install('tempest')
+
+STROPT = "StrOpt"
+BOOLOPT = "BoolOpt"
+INTOPT = "IntOpt"
+FLOATOPT = "FloatOpt"
+LISTOPT = "ListOpt"
+MULTISTROPT = "MultiStrOpt"
+
+OPT_TYPES = {
+    STROPT: 'string value',
+    BOOLOPT: 'boolean value',
+    INTOPT: 'integer value',
+    FLOATOPT: 'floating point value',
+    LISTOPT: 'list value',
+    MULTISTROPT: 'multi valued',
+}
+
+OPTION_REGEX = re.compile(r"(%s)" % "|".join([STROPT, BOOLOPT, INTOPT,
+                                              FLOATOPT, LISTOPT,
+                                              MULTISTROPT]))
+
+PY_EXT = ".py"
+BASEDIR = os.path.abspath(os.path.join(os.path.dirname(__file__),
+                                       "../../../../"))
+WORDWRAP_WIDTH = 60
+
+
+def generate(srcfiles):
+    mods_by_pkg = dict()
+    for filepath in srcfiles:
+        pkg_name = filepath.split(os.sep)[1]
+        mod_str = '.'.join(['.'.join(filepath.split(os.sep)[:-1]),
+                            os.path.basename(filepath).split('.')[0]])
+        mods_by_pkg.setdefault(pkg_name, list()).append(mod_str)
+    # NOTE(lzyeval): place top level modules before packages
+    pkg_names = filter(lambda x: x.endswith(PY_EXT), mods_by_pkg.keys())
+    pkg_names.sort()
+    ext_names = filter(lambda x: x not in pkg_names, mods_by_pkg.keys())
+    ext_names.sort()
+    pkg_names.extend(ext_names)
+
+    # opts_by_group is a mapping of group name to an options list
+    # The options list is a list of (module, options) tuples
+    opts_by_group = {'DEFAULT': []}
+
+    for module_name in os.getenv(
+            "OSLO_CONFIG_GENERATOR_EXTRA_MODULES", "").split(','):
+        module = _import_module(module_name)
+        if module:
+            for group, opts in _list_opts(module):
+                opts_by_group.setdefault(group, []).append((module_name, opts))
+
+    for pkg_name in pkg_names:
+        mods = mods_by_pkg.get(pkg_name)
+        mods.sort()
+        for mod_str in mods:
+            if mod_str.endswith('.__init__'):
+                mod_str = mod_str[:mod_str.rfind(".")]
+
+            mod_obj = _import_module(mod_str)
+            if not mod_obj:
+                raise RuntimeError("Unable to import module %s" % mod_str)
+
+            for group, opts in _list_opts(mod_obj):
+                opts_by_group.setdefault(group, []).append((mod_str, opts))
+
+    print_group_opts('DEFAULT', opts_by_group.pop('DEFAULT', []))
+    for group, opts in opts_by_group.items():
+        print_group_opts(group, opts)
+
+
+def _import_module(mod_str):
+    try:
+        if mod_str.startswith('bin.'):
+            imp.load_source(mod_str[4:], os.path.join('bin', mod_str[4:]))
+            return sys.modules[mod_str[4:]]
+        else:
+            return importutils.import_module(mod_str)
+    except ImportError as ie:
+        sys.stderr.write("%s\n" % str(ie))
+        return None
+    except Exception:
+        return None
+
+
+def _is_in_group(opt, group):
+    "Check if opt is in group."
+    for key, value in group._opts.items():
+        if value['opt'] == opt:
+            return True
+    return False
+
+
+def _guess_groups(opt, mod_obj):
+    # is it in the DEFAULT group?
+    if _is_in_group(opt, cfg.CONF):
+        return 'DEFAULT'
+
+    # what other groups is it in?
+    for key, value in cfg.CONF.items():
+        if isinstance(value, cfg.CONF.GroupAttr):
+            if _is_in_group(opt, value._group):
+                return value._group.name
+
+    raise RuntimeError(
+        "Unable to find group for option %s, "
+        "maybe it's defined twice in the same group?"
+        % opt.name
+    )
+
+
+def _list_opts(obj):
+    def is_opt(o):
+        return (isinstance(o, cfg.Opt) and
+                not isinstance(o, cfg.SubCommandOpt))
+
+    opts = list()
+    for attr_str in dir(obj):
+        attr_obj = getattr(obj, attr_str)
+        if is_opt(attr_obj):
+            opts.append(attr_obj)
+        elif (isinstance(attr_obj, list) and
+              all(map(lambda x: is_opt(x), attr_obj))):
+            opts.extend(attr_obj)
+
+    ret = {}
+    for opt in opts:
+        ret.setdefault(_guess_groups(opt, obj), []).append(opt)
+    return ret.items()
+
+
+def print_group_opts(group, opts_by_module):
+    print("[%s]" % group)
+    print('')
+    for mod, opts in opts_by_module:
+        print('#')
+        print('# Options defined in %s' % mod)
+        print('#')
+        print('')
+        for opt in opts:
+            _print_opt(opt)
+        print('')
+
+
+def _get_my_ip():
+    try:
+        csock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+        csock.connect(('8.8.8.8', 80))
+        (addr, port) = csock.getsockname()
+        csock.close()
+        return addr
+    except socket.error:
+        return None
+
+
+def _sanitize_default(name, value):
+    """Set up a reasonably sensible default for pybasedir, my_ip and host."""
+    if value.startswith(sys.prefix):
+        # NOTE(jd) Don't use os.path.join, because it is likely to think the
+        # second part is an absolute pathname and therefore drop the first
+        # part.
+        value = os.path.normpath("/usr/" + value[len(sys.prefix):])
+    elif value.startswith(BASEDIR):
+        return value.replace(BASEDIR, '/usr/lib/python/site-packages')
+    elif BASEDIR in value:
+        return value.replace(BASEDIR, '')
+    elif value == _get_my_ip():
+        return '10.0.0.1'
+    elif value == socket.gethostname() and 'host' in name:
+        return 'tempest'
+    elif value.strip() != value:
+        return '"%s"' % value
+    return value
+
+
+def _print_opt(opt):
+    opt_name, opt_default, opt_help = opt.dest, opt.default, opt.help
+    if not opt_help:
+        sys.stderr.write('WARNING: "%s" is missing help string.\n' % opt_name)
+        opt_help = ""
+    opt_type = None
+    try:
+        opt_type = OPTION_REGEX.search(str(type(opt))).group(0)
+    except (ValueError, AttributeError) as err:
+        sys.stderr.write("%s\n" % str(err))
+        sys.exit(1)
+    opt_help += ' (' + OPT_TYPES[opt_type] + ')'
+    print('#', "\n# ".join(textwrap.wrap(opt_help, WORDWRAP_WIDTH)))
+    if opt.deprecated_opts:
+        for deprecated_opt in opt.deprecated_opts:
+            if deprecated_opt.name:
+                deprecated_group = (deprecated_opt.group if
+                                    deprecated_opt.group else "DEFAULT")
+                print('# Deprecated group/name - [%s]/%s' %
+                      (deprecated_group,
+                       deprecated_opt.name))
+    try:
+        if opt_default is None:
+            print('#%s=<None>' % opt_name)
+        elif opt_type == STROPT:
+            assert(isinstance(opt_default, basestring))
+            print('#%s=%s' % (opt_name, _sanitize_default(opt_name,
+                                                          opt_default)))
+        elif opt_type == BOOLOPT:
+            assert(isinstance(opt_default, bool))
+            print('#%s=%s' % (opt_name, str(opt_default).lower()))
+        elif opt_type == INTOPT:
+            assert(isinstance(opt_default, int) and
+                   not isinstance(opt_default, bool))
+            print('#%s=%s' % (opt_name, opt_default))
+        elif opt_type == FLOATOPT:
+            assert(isinstance(opt_default, float))
+            print('#%s=%s' % (opt_name, opt_default))
+        elif opt_type == LISTOPT:
+            assert(isinstance(opt_default, list))
+            print('#%s=%s' % (opt_name, ','.join(opt_default)))
+        elif opt_type == MULTISTROPT:
+            assert(isinstance(opt_default, list))
+            if not opt_default:
+                opt_default = ['']
+            for default in opt_default:
+                print('#%s=%s' % (opt_name, default))
+        print('')
+    except Exception:
+        sys.stderr.write('Error in option "%s"\n' % opt_name)
+        sys.exit(1)
+
+
+def main():
+    generate(sys.argv[1:])
+
+if __name__ == '__main__':
+    main()
diff --git a/tempest/openstack/common/excutils.py b/tempest/openstack/common/excutils.py
index db37660..c7bce72 100644
--- a/tempest/openstack/common/excutils.py
+++ b/tempest/openstack/common/excutils.py
@@ -79,7 +79,7 @@
             try:
                 return infunc(*args, **kwargs)
             except Exception as exc:
-                this_exc_message = unicode(exc)
+                this_exc_message = six.u(str(exc))
                 if this_exc_message == last_exc_message:
                     exc_count += 1
                 else:
diff --git a/tempest/openstack/common/fileutils.py b/tempest/openstack/common/fileutils.py
index 6cf68ba..15530af 100644
--- a/tempest/openstack/common/fileutils.py
+++ b/tempest/openstack/common/fileutils.py
@@ -19,6 +19,7 @@
 import contextlib
 import errno
 import os
+import tempfile
 
 from tempest.openstack.common import excutils
 from tempest.openstack.common.gettextutils import _  # noqa
@@ -109,3 +110,30 @@
     state at all (for unit tests)
     """
     return file(*args, **kwargs)
+
+
+def write_to_tempfile(content, path=None, suffix='', prefix='tmp'):
+    """Create temporary file or use existing file.
+
+    This util is needed for creating temporary file with
+    specified content, suffix and prefix. If path is not None,
+    it will be used for writing content. If the path doesn't
+    exist it'll be created.
+
+    :param content: content for temporary file.
+    :param path: same as parameter 'dir' for mkstemp
+    :param suffix: same as parameter 'suffix' for mkstemp
+    :param prefix: same as parameter 'prefix' for mkstemp
+
+    For example: it can be used in database tests for creating
+    configuration files.
+    """
+    if path:
+        ensure_tree(path)
+
+    (fd, path) = tempfile.mkstemp(suffix=suffix, dir=path, prefix=prefix)
+    try:
+        os.write(fd, content)
+    finally:
+        os.close(fd)
+    return path
diff --git a/tempest/openstack/common/gettextutils.py b/tempest/openstack/common/gettextutils.py
index cbf570a..2939ed9 100644
--- a/tempest/openstack/common/gettextutils.py
+++ b/tempest/openstack/common/gettextutils.py
@@ -60,6 +60,8 @@
     if USE_LAZY:
         return Message(msg, 'tempest')
     else:
+        if six.PY3:
+            return _t.gettext(msg)
         return _t.ugettext(msg)
 
 
@@ -105,13 +107,17 @@
             """
             return Message(msg, domain)
 
-        import __builtin__
-        __builtin__.__dict__['_'] = _lazy_gettext
+        from six import moves
+        moves.builtins.__dict__['_'] = _lazy_gettext
     else:
         localedir = '%s_LOCALEDIR' % domain.upper()
-        gettext.install(domain,
-                        localedir=os.environ.get(localedir),
-                        unicode=True)
+        if six.PY3:
+            gettext.install(domain,
+                            localedir=os.environ.get(localedir))
+        else:
+            gettext.install(domain,
+                            localedir=os.environ.get(localedir),
+                            unicode=True)
 
 
 class Message(_userString.UserString, object):
@@ -121,8 +127,8 @@
         self._msg = msg
         self._left_extra_msg = ''
         self._right_extra_msg = ''
+        self._locale = None
         self.params = None
-        self.locale = None
         self.domain = domain
 
     @property
@@ -142,8 +148,13 @@
                                        localedir=localedir,
                                        fallback=True)
 
+        if six.PY3:
+            ugettext = lang.gettext
+        else:
+            ugettext = lang.ugettext
+
         full_msg = (self._left_extra_msg +
-                    lang.ugettext(self._msg) +
+                    ugettext(self._msg) +
                     self._right_extra_msg)
 
         if self.params is not None:
@@ -151,6 +162,33 @@
 
         return six.text_type(full_msg)
 
+    @property
+    def locale(self):
+        return self._locale
+
+    @locale.setter
+    def locale(self, value):
+        self._locale = value
+        if not self.params:
+            return
+
+        # This Message object may have been constructed with one or more
+        # Message objects as substitution parameters, given as a single
+        # Message, or a tuple or Map containing some, so when setting the
+        # locale for this Message we need to set it for those Messages too.
+        if isinstance(self.params, Message):
+            self.params.locale = value
+            return
+        if isinstance(self.params, tuple):
+            for param in self.params:
+                if isinstance(param, Message):
+                    param.locale = value
+            return
+        if isinstance(self.params, dict):
+            for param in self.params.values():
+                if isinstance(param, Message):
+                    param.locale = value
+
     def _save_dictionary_parameter(self, dict_param):
         full_msg = self.data
         # look for %(blah) fields in string;
@@ -169,7 +207,7 @@
                     params[key] = copy.deepcopy(dict_param[key])
                 except TypeError:
                     # cast uncopyable thing to unicode string
-                    params[key] = unicode(dict_param[key])
+                    params[key] = six.text_type(dict_param[key])
 
         return params
 
@@ -188,7 +226,7 @@
             try:
                 self.params = copy.deepcopy(other)
             except TypeError:
-                self.params = unicode(other)
+                self.params = six.text_type(other)
 
         return self
 
@@ -197,11 +235,13 @@
         return self.data
 
     def __str__(self):
+        if six.PY3:
+            return self.__unicode__()
         return self.data.encode('utf-8')
 
     def __getstate__(self):
         to_copy = ['_msg', '_right_extra_msg', '_left_extra_msg',
-                   'domain', 'params', 'locale']
+                   'domain', 'params', '_locale']
         new_dict = self.__dict__.fromkeys(to_copy)
         for attr in to_copy:
             new_dict[attr] = copy.deepcopy(self.__dict__[attr])
@@ -289,13 +329,21 @@
 
 
 def get_localized_message(message, user_locale):
-    """Gets a localized version of the given message in the given locale."""
+    """Gets a localized version of the given message in the given locale.
+
+    If the message is not a Message object the message is returned as-is.
+    If the locale is None the message is translated to the default locale.
+
+    :returns: the translated message in unicode, or the original message if
+              it could not be translated
+    """
+    translated = message
     if isinstance(message, Message):
-        if user_locale:
-            message.locale = user_locale
-        return unicode(message)
-    else:
-        return message
+        original_locale = message.locale
+        message.locale = user_locale
+        translated = six.text_type(message)
+        message.locale = original_locale
+    return translated
 
 
 class LocaleHandler(logging.Handler):
diff --git a/tempest/openstack/common/jsonutils.py b/tempest/openstack/common/jsonutils.py
index c568a06..b589545 100644
--- a/tempest/openstack/common/jsonutils.py
+++ b/tempest/openstack/common/jsonutils.py
@@ -46,6 +46,7 @@
 
 import six
 
+from tempest.openstack.common import gettextutils
 from tempest.openstack.common import importutils
 from tempest.openstack.common import timeutils
 
@@ -135,6 +136,8 @@
 
         if convert_datetime and isinstance(value, datetime.datetime):
             return timeutils.strtime(value)
+        elif isinstance(value, gettextutils.Message):
+            return value.data
         elif hasattr(value, 'iteritems'):
             return recursive(dict(value.iteritems()), level=level + 1)
         elif hasattr(value, '__iter__'):
diff --git a/tempest/openstack/common/lockutils.py b/tempest/openstack/common/lockutils.py
index a55fd94..65f3548 100644
--- a/tempest/openstack/common/lockutils.py
+++ b/tempest/openstack/common/lockutils.py
@@ -20,11 +20,14 @@
 import errno
 import functools
 import os
+import shutil
+import subprocess
+import sys
+import tempfile
 import threading
 import time
 import weakref
 
-import fixtures
 from oslo.config import cfg
 
 from tempest.openstack.common import fileutils
@@ -40,6 +43,7 @@
     cfg.BoolOpt('disable_process_locking', default=False,
                 help='Whether to disable inter-process locks'),
     cfg.StrOpt('lock_path',
+               default=os.environ.get("TEMPEST_LOCK_PATH"),
                help=('Directory to use for lock files.'))
 ]
 
@@ -132,6 +136,7 @@
     InterProcessLock = _PosixLock
 
 _semaphores = weakref.WeakValueDictionary()
+_semaphores_lock = threading.Lock()
 
 
 @contextlib.contextmanager
@@ -154,15 +159,12 @@
     special location for external lock files to live. If nothing is set, then
     CONF.lock_path is used as a default.
     """
-    # NOTE(soren): If we ever go natively threaded, this will be racy.
-    #              See http://stackoverflow.com/questions/5390569/dyn
-    #              amically-allocating-and-destroying-mutexes
-    sem = _semaphores.get(name, threading.Semaphore())
-    if name not in _semaphores:
-        # this check is not racy - we're already holding ref locally
-        # so GC won't remove the item and there was no IO switch
-        # (only valid in greenthreads)
-        _semaphores[name] = sem
+    with _semaphores_lock:
+        try:
+            sem = _semaphores[name]
+        except KeyError:
+            sem = threading.Semaphore()
+            _semaphores[name] = sem
 
     with sem:
         LOG.debug(_('Got semaphore "%(lock)s"'), {'lock': name})
@@ -242,13 +244,14 @@
     def wrap(f):
         @functools.wraps(f)
         def inner(*args, **kwargs):
-            with lock(name, lock_file_prefix, external, lock_path):
-                LOG.debug(_('Got semaphore / lock "%(function)s"'),
+            try:
+                with lock(name, lock_file_prefix, external, lock_path):
+                    LOG.debug(_('Got semaphore / lock "%(function)s"'),
+                              {'function': f.__name__})
+                    return f(*args, **kwargs)
+            finally:
+                LOG.debug(_('Semaphore / lock released "%(function)s"'),
                           {'function': f.__name__})
-                return f(*args, **kwargs)
-
-            LOG.debug(_('Semaphore / lock released "%(function)s"'),
-                      {'function': f.__name__})
         return inner
     return wrap
 
@@ -278,34 +281,25 @@
     return functools.partial(synchronized, lock_file_prefix=lock_file_prefix)
 
 
-class LockFixture(fixtures.Fixture):
-    """External locking fixture.
+def main(argv):
+    """Create a dir for locks and pass it to command from arguments
 
-    This fixture is basically an alternative to the synchronized decorator with
-    the external flag so that tearDowns and addCleanups will be included in
-    the lock context for locking between tests. The fixture is recommended to
-    be the first line in a test method, like so::
+    If you run this:
+    python -m openstack.common.lockutils python setup.py testr <etc>
 
-        def test_method(self):
-            self.useFixture(LockFixture)
-                ...
-
-    or the first line in setUp if all the test methods in the class are
-    required to be serialized. Something like::
-
-        class TestCase(testtools.testcase):
-            def setUp(self):
-                self.useFixture(LockFixture)
-                super(TestCase, self).setUp()
-                    ...
-
-    This is because addCleanups are put on a LIFO queue that gets run after the
-    test method exits. (either by completing or raising an exception)
+    a temporary directory will be created for all your locks and passed to all
+    your tests in an environment variable. The temporary dir will be deleted
+    afterwards and the return value will be preserved.
     """
-    def __init__(self, name, lock_file_prefix=None):
-        self.mgr = lock(name, lock_file_prefix, True)
 
-    def setUp(self):
-        super(LockFixture, self).setUp()
-        self.addCleanup(self.mgr.__exit__, None, None, None)
-        self.mgr.__enter__()
+    lock_dir = tempfile.mkdtemp()
+    os.environ["TEMPEST_LOCK_PATH"] = lock_dir
+    try:
+        ret_val = subprocess.call(argv[1:])
+    finally:
+        shutil.rmtree(lock_dir, ignore_errors=True)
+    return ret_val
+
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv))
diff --git a/tempest/openstack/common/log.py b/tempest/openstack/common/log.py
index 4133c30..abb44ef 100644
--- a/tempest/openstack/common/log.py
+++ b/tempest/openstack/common/log.py
@@ -39,6 +39,7 @@
 import traceback
 
 from oslo.config import cfg
+import six
 from six import moves
 
 from tempest.openstack.common.gettextutils import _  # noqa
@@ -131,7 +132,7 @@
                     'boto=WARN',
                     'suds=INFO',
                     'keystone=INFO',
-                    'eventlet.wsgi.server=WARN'
+                    'paramiko=INFO'
                 ],
                 help='list of logger=LEVEL pairs'),
     cfg.BoolOpt('publish_errors',
@@ -207,6 +208,8 @@
         binary = binary or _get_binary_name()
         return '%s.log' % (os.path.join(logdir, binary),)
 
+    return None
+
 
 class BaseLoggerAdapter(logging.LoggerAdapter):
 
@@ -249,6 +252,13 @@
             self.warn(stdmsg, *args, **kwargs)
 
     def process(self, msg, kwargs):
+        # NOTE(mrodden): catch any Message/other object and
+        #                coerce to unicode before they can get
+        #                to the python logging and possibly
+        #                cause string encoding trouble
+        if not isinstance(msg, six.string_types):
+            msg = six.text_type(msg)
+
         if 'extra' not in kwargs:
             kwargs['extra'] = {}
         extra = kwargs['extra']
@@ -260,14 +270,14 @@
             extra.update(_dictify_context(context))
 
         instance = kwargs.pop('instance', None)
+        instance_uuid = (extra.get('instance_uuid', None) or
+                         kwargs.pop('instance_uuid', None))
         instance_extra = ''
         if instance:
             instance_extra = CONF.instance_format % instance
-        else:
-            instance_uuid = kwargs.pop('instance_uuid', None)
-            if instance_uuid:
-                instance_extra = (CONF.instance_uuid_format
-                                  % {'uuid': instance_uuid})
+        elif instance_uuid:
+            instance_extra = (CONF.instance_uuid_format
+                              % {'uuid': instance_uuid})
         extra.update({'instance': instance_extra})
 
         extra.update({"project": self.project})
diff --git a/tempest/openstack/common/timeutils.py b/tempest/openstack/common/timeutils.py
index 60f02bc..98d877d 100644
--- a/tempest/openstack/common/timeutils.py
+++ b/tempest/openstack/common/timeutils.py
@@ -117,12 +117,15 @@
 utcnow.override_time = None
 
 
-def set_time_override(override_time=datetime.datetime.utcnow()):
+def set_time_override(override_time=None):
     """Overrides utils.utcnow.
 
     Make it return a constant time or a list thereof, one at a time.
+
+    :param override_time: datetime instance or list thereof. If not
+                          given, defaults to the current UTC time.
     """
-    utcnow.override_time = override_time
+    utcnow.override_time = override_time or datetime.datetime.utcnow()
 
 
 def advance_time_delta(timedelta):
diff --git a/tempest/scenario/README.rst b/tempest/scenario/README.rst
index ce12a3b..835ba99 100644
--- a/tempest/scenario/README.rst
+++ b/tempest/scenario/README.rst
@@ -10,10 +10,13 @@
 of a previous part. They ideally involve the integration between
 multiple OpenStack services to exercise the touch points between them.
 
-An example would be: start with a blank environment, upload a glance
-image, deploy a vm from it, ssh to the guest, make changes, capture
-that vm's image back into glance as a snapshot, and launch a second vm
-from that snapshot.
+Any scenario test should have a real-life use case. An example would be:
+
+ - "As operator I want to start with a blank environment":
+    1. upload a glance image
+    2. deploy a vm from it
+    3. ssh to the guest
+    4. create a snapshot of the vm
 
 
 Why are these tests in tempest?
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 97e2ae3..fa46cd7 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -34,7 +34,7 @@
 from tempest.api.network import common as net_common
 from tempest.common import isolated_creds
 from tempest.common import ssh
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.common.utils.linux.remote_client import RemoteClient
 from tempest import exceptions
 import tempest.manager
@@ -88,6 +88,7 @@
 
         auth_url = self.config.identity.uri
         dscv = self.config.identity.disable_ssl_certificate_validation
+        region = self.config.identity.region
 
         client_args = (username, password, tenant_name, auth_url)
 
@@ -96,13 +97,16 @@
         return novaclient.client.Client(self.NOVACLIENT_VERSION,
                                         *client_args,
                                         service_type=service_type,
+                                        region_name=region,
                                         no_cache=True,
                                         insecure=dscv,
                                         http_log_debug=True)
 
     def _get_image_client(self):
         token = self.identity_client.auth_token
+        region = self.config.identity.region
         endpoint = self.identity_client.service_catalog.url_for(
+            attr='region', filter_value=region,
             service_type='image', endpoint_type='publicURL')
         dscv = self.config.identity.disable_ssl_certificate_validation
         return glanceclient.Client('1', endpoint=endpoint, token=token,
@@ -110,11 +114,13 @@
 
     def _get_volume_client(self, username, password, tenant_name):
         auth_url = self.config.identity.uri
+        region = self.config.identity.region
         return cinderclient.client.Client(self.CINDERCLIENT_VERSION,
                                           username,
                                           password,
                                           tenant_name,
                                           auth_url,
+                                          region_name=region,
                                           http_log_debug=True)
 
     def _get_orchestration_client(self, username=None, password=None,
@@ -129,9 +135,12 @@
         self._validate_credentials(username, password, tenant_name)
 
         keystone = self._get_identity_client(username, password, tenant_name)
+        region = self.config.identity.region
         token = keystone.auth_token
         try:
             endpoint = keystone.service_catalog.url_for(
+                attr='region',
+                filter_value=region,
                 service_type='orchestration',
                 endpoint_type='publicURL')
         except keystoneclient.exceptions.EndpointNotFound:
@@ -355,7 +364,8 @@
                       to become %s" % (thing_id, log_status)
             raise exceptions.TimeoutException(message)
 
-    def create_loginable_secgroup_rule(self, client=None, secgroup_id=None):
+    def _create_loginable_secgroup_rule_nova(self, client=None,
+                                             secgroup_id=None):
         if client is None:
             client = self.compute_client
         if secgroup_id is None:
@@ -384,17 +394,20 @@
                 'cidr': '0.0.0.0/0',
             }
         ]
+        rules = list()
         for ruleset in rulesets:
             sg_rule = client.security_group_rules.create(secgroup_id,
                                                          **ruleset)
             self.set_resource(sg_rule.id, sg_rule)
+            rules.append(sg_rule)
+        return rules
 
     def create_server(self, client=None, name=None, image=None, flavor=None,
                       create_kwargs={}):
         if client is None:
             client = self.compute_client
         if name is None:
-            name = rand_name('scenario-server-')
+            name = data_utils.rand_name('scenario-server-')
         if image is None:
             image = self.config.compute.image_ref
         if flavor is None:
@@ -418,7 +431,7 @@
         if client is None:
             client = self.volume_client
         if name is None:
-            name = rand_name('scenario-volume-')
+            name = data_utils.rand_name('scenario-volume-')
         LOG.debug("Creating a volume (size: %s, name: %s)", size, name)
         volume = client.volumes.create(size=size, display_name=name,
                                        snapshot_id=snapshot_id,
@@ -436,7 +449,7 @@
         if image_client is None:
             image_client = self.image_client
         if name is None:
-            name = rand_name('scenario-snapshot-')
+            name = data_utils.rand_name('scenario-snapshot-')
         LOG.debug("Creating a snapshot image for server: %s", server.name)
         image_id = compute_client.servers.create_image(server, name)
         self.addCleanup(image_client.images.delete, image_id)
@@ -451,7 +464,7 @@
         if client is None:
             client = self.compute_client
         if name is None:
-            name = rand_name('scenario-keypair-')
+            name = data_utils.rand_name('scenario-keypair-')
         keypair = client.keypairs.create(name)
         self.assertEqual(keypair.name, name)
         self.set_resource(name, keypair)
@@ -501,24 +514,8 @@
                 cls.config.identity.password,
                 cls.config.identity.tenant_name).tenant_id
 
-    def _create_security_group(self, client=None, namestart='secgroup-smoke-'):
-        if client is None:
-            client = self.compute_client
-        # Create security group
-        sg_name = rand_name(namestart)
-        sg_desc = sg_name + " description"
-        secgroup = client.security_groups.create(sg_name, sg_desc)
-        self.assertEqual(secgroup.name, sg_name)
-        self.assertEqual(secgroup.description, sg_desc)
-        self.set_resource(sg_name, secgroup)
-
-        # Add rules to the security group
-        self.create_loginable_secgroup_rule(client, secgroup.id)
-
-        return secgroup
-
     def _create_network(self, tenant_id, namestart='network-smoke-'):
-        name = rand_name(namestart)
+        name = data_utils.rand_name(namestart)
         body = dict(
             network=dict(
                 name=name,
@@ -544,6 +541,27 @@
         routers = self.network_client.list_routers()
         return routers['routers']
 
+    def _list_ports(self):
+        ports = self.network_client.list_ports()
+        return ports['ports']
+
+    def _get_tenant_own_network_num(self, tenant_id):
+        nets = self._list_networks()
+        ownnets = [value for value in nets if tenant_id == value['tenant_id']]
+        return len(ownnets)
+
+    def _get_tenant_own_subnet_num(self, tenant_id):
+        subnets = self._list_subnets()
+        ownsubnets = ([value for value in subnets
+                      if tenant_id == value['tenant_id']])
+        return len(ownsubnets)
+
+    def _get_tenant_own_port_num(self, tenant_id):
+        ports = self._list_ports()
+        ownports = ([value for value in ports
+                    if tenant_id == value['tenant_id']])
+        return len(ownports)
+
     def _create_subnet(self, network, namestart='subnet-smoke-'):
         """
         Create a subnet for the given network within the cidr block
@@ -574,11 +592,11 @@
         subnet = net_common.DeletableSubnet(client=self.network_client,
                                             **result['subnet'])
         self.assertEqual(subnet.cidr, str(subnet_cidr))
-        self.set_resource(rand_name(namestart), subnet)
+        self.set_resource(data_utils.rand_name(namestart), subnet)
         return subnet
 
     def _create_port(self, network, namestart='port-quotatest-'):
-        name = rand_name(namestart)
+        name = data_utils.rand_name(namestart)
         body = dict(
             port=dict(name=name,
                       network_id=network.id,
@@ -607,7 +625,7 @@
         floating_ip = net_common.DeletableFloatingIp(
             client=self.network_client,
             **result['floatingip'])
-        self.set_resource(rand_name('floatingip-'), floating_ip)
+        self.set_resource(data_utils.rand_name('floatingip-'), floating_ip)
         return floating_ip
 
     def _ping_ip_address(self, ip_address):
@@ -643,6 +661,183 @@
             'Auth failure in connecting to %s@%s via ssh' %
             (username, ip_address))
 
+    def _create_security_group_nova(self, client=None,
+                                    namestart='secgroup-smoke-',
+                                    tenant_id=None):
+        if client is None:
+            client = self.compute_client
+        # Create security group
+        sg_name = data_utils.rand_name(namestart)
+        sg_desc = sg_name + " description"
+        secgroup = client.security_groups.create(sg_name, sg_desc)
+        self.assertEqual(secgroup.name, sg_name)
+        self.assertEqual(secgroup.description, sg_desc)
+        self.set_resource(sg_name, secgroup)
+
+        # Add rules to the security group
+        self._create_loginable_secgroup_rule_nova(client, secgroup.id)
+
+        return secgroup
+
+    def _create_security_group_neutron(self, tenant_id, client=None,
+                                       namestart='secgroup-smoke-'):
+        if client is None:
+            client = self.network_client
+        secgroup = self._create_empty_security_group(namestart=namestart,
+                                                     client=client,
+                                                     tenant_id=tenant_id)
+
+        # Add rules to the security group
+        rules = self._create_loginable_secgroup_rule_neutron(secgroup=secgroup)
+        for rule in rules:
+            self.assertEqual(tenant_id, rule.tenant_id)
+            self.assertEqual(secgroup.id, rule.security_group_id)
+        return secgroup
+
+    def _create_empty_security_group(self, tenant_id, client=None,
+                                     namestart='secgroup-smoke-'):
+        """Create a security group without rules.
+
+        Default rules will be created:
+         - IPv4 egress to any
+         - IPv6 egress to any
+
+        :param tenant_id: secgroup will be created in this tenant
+        :returns: DeletableSecurityGroup -- containing the secgroup created
+        """
+        if client is None:
+            client = self.network_client
+        sg_name = data_utils.rand_name(namestart)
+        sg_desc = sg_name + " description"
+        sg_dict = dict(name=sg_name,
+                       description=sg_desc)
+        sg_dict['tenant_id'] = tenant_id
+        body = dict(security_group=sg_dict)
+        result = client.create_security_group(body=body)
+        secgroup = net_common.DeletableSecurityGroup(
+            client=client,
+            **result['security_group']
+        )
+        self.assertEqual(secgroup.name, sg_name)
+        self.assertEqual(tenant_id, secgroup.tenant_id)
+        self.assertEqual(secgroup.description, sg_desc)
+        self.set_resource(sg_name, secgroup)
+        return secgroup
+
+    def _default_security_group(self, tenant_id, client=None):
+        """Get default secgroup for given tenant_id.
+
+        :returns: DeletableSecurityGroup -- default secgroup for given tenant
+        """
+        if client is None:
+            client = self.network_client
+        sgs = [
+            sg for sg in client.list_security_groups().values()[0]
+            if sg['tenant_id'] == tenant_id and sg['name'] == 'default'
+        ]
+        msg = "No default security group for tenant %s." % (tenant_id)
+        self.assertTrue(len(sgs) > 0, msg)
+        if len(sgs) > 1:
+            msg = "Found %d default security groups" % len(sgs)
+            raise exc.NeutronClientNoUniqueMatch(msg=msg)
+        return net_common.DeletableSecurityGroup(client=client,
+                                                 **sgs[0])
+
+    def _create_security_group_rule(self, client=None, secgroup=None,
+                                    tenant_id=None, **kwargs):
+        """Create a rule from a dictionary of rule parameters.
+
+        Create a rule in a secgroup. if secgroup not defined will search for
+        default secgroup in tenant_id.
+
+        :param secgroup: type DeletableSecurityGroup.
+        :param secgroup_id: search for secgroup by id
+            default -- choose default secgroup for given tenant_id
+        :param tenant_id: if secgroup not passed -- the tenant in which to
+            search for default secgroup
+        :param kwargs: a dictionary containing rule parameters:
+            for example, to allow incoming ssh:
+            rule = {
+                    direction: 'ingress'
+                    protocol:'tcp',
+                    port_range_min: 22,
+                    port_range_max: 22
+                    }
+        """
+        if client is None:
+            client = self.network_client
+        if secgroup is None:
+            secgroup = self._default_security_group(tenant_id)
+
+        ruleset = dict(security_group_id=secgroup.id,
+                       tenant_id=secgroup.tenant_id,
+                       )
+        ruleset.update(kwargs)
+
+        body = dict(security_group_rule=dict(ruleset))
+        sg_rule = client.create_security_group_rule(body=body)
+        sg_rule = net_common.DeletableSecurityGroupRule(
+            client=client,
+            **sg_rule['security_group_rule']
+        )
+        self.set_resource(sg_rule.id, sg_rule)
+        self.assertEqual(secgroup.tenant_id, sg_rule.tenant_id)
+        self.assertEqual(secgroup.id, sg_rule.security_group_id)
+
+        return sg_rule
+
+    def _create_loginable_secgroup_rule_neutron(self, client=None,
+                                                secgroup=None):
+        """These rules are intended to permit inbound ssh and icmp
+        traffic from all sources, so no group_id is provided.
+        Setting a group_id would only permit traffic from ports
+        belonging to the same security group.
+        """
+
+        if client is None:
+            client = self.network_client
+        rules = []
+        rulesets = [
+            dict(
+                # ssh
+                protocol='tcp',
+                port_range_min=22,
+                port_range_max=22,
+            ),
+            dict(
+                # ping
+                protocol='icmp',
+            )
+        ]
+        for ruleset in rulesets:
+            for r_direction in ['ingress', 'egress']:
+                ruleset['direction'] = r_direction
+                try:
+                    sg_rule = self._create_security_group_rule(
+                        client=client, secgroup=secgroup, **ruleset)
+                except exc.NeutronClientException as ex:
+                    # if rule already exist - skip rule and continue
+                    if not (ex.status_code is 409 and 'Security group rule'
+                            ' already exists' in ex.message):
+                        raise ex
+                else:
+                    self.assertEqual(r_direction, sg_rule.direction)
+                    rules.append(sg_rule)
+
+        return rules
+
+    def _show_quota_network(self, tenant_id):
+        quota = self.network_client.show_quota(tenant_id)
+        return quota['quota']['network']
+
+    def _show_quota_subnet(self, tenant_id):
+        quota = self.network_client.show_quota(tenant_id)
+        return quota['quota']['subnet']
+
+    def _show_quota_port(self, tenant_id):
+        quota = self.network_client.show_quota(tenant_id)
+        return quota['quota']['port']
+
 
 class OrchestrationScenarioTest(OfficialClientTest):
     """
@@ -670,7 +865,7 @@
 
     @classmethod
     def _stack_rand_name(cls):
-        return rand_name(cls.__name__ + '-')
+        return data_utils.rand_name(cls.__name__ + '-')
 
     @classmethod
     def _get_default_network(cls):
diff --git a/tempest/scenario/orchestration/test_autoscaling.py b/tempest/scenario/orchestration/test_autoscaling.py
index e843793..90ef3a0 100644
--- a/tempest/scenario/orchestration/test_autoscaling.py
+++ b/tempest/scenario/orchestration/test_autoscaling.py
@@ -19,6 +19,7 @@
 from tempest.test import attr
 from tempest.test import call_until_true
 from tempest.test import services
+from tempest.test import skip_because
 
 
 class AutoScalingTest(manager.OrchestrationScenarioTest):
@@ -62,6 +63,7 @@
         if not self.config.orchestration.keypair_name:
             self.set_resource('stack', self.stack)
 
+    @skip_because(bug="1257575")
     @attr(type='slow')
     @services('orchestration', 'compute')
     def test_scale_up_then_down(self):
diff --git a/tempest/scenario/orchestration/test_autoscaling.yaml b/tempest/scenario/orchestration/test_autoscaling.yaml
index 745eb05..4651284 100644
--- a/tempest/scenario/orchestration/test_autoscaling.yaml
+++ b/tempest/scenario/orchestration/test_autoscaling.yaml
@@ -23,11 +23,11 @@
     Default: '420'
   ScaleUpThreshold:
     Description: Memory percentage threshold to scale up on
-    Type: Number
+    Type: String
     Default: '70'
   ScaleDownThreshold:
     Description: Memory percentage threshold to scale down on
-    Type: Number
+    Type: String
     Default: '60'
   ConsumeMemoryLimit:
     Description: Memory percentage threshold to consume
@@ -182,4 +182,4 @@
             # wait ConsumeStartSeconds then ramp up memory consumption
             # until it is over ConsumeMemoryLimit%
             # then exits ConsumeStopSeconds seconds after stack launch
-            /root/consume_memory > /root/consume_memory.log &
\ No newline at end of file
+            /root/consume_memory > /root/consume_memory.log &
diff --git a/tempest/scenario/test_large_ops.py b/tempest/scenario/test_large_ops.py
index 22c543b..7f8d3e4 100644
--- a/tempest/scenario/test_large_ops.py
+++ b/tempest/scenario/test_large_ops.py
@@ -15,7 +15,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.openstack.common import log as logging
 from tempest.scenario import manager
 from tempest.test import services
@@ -47,7 +47,7 @@
             self.volume_client.volumes, volume_id, status)
 
     def _image_create(self, name, fmt, path, properties={}):
-        name = rand_name('%s-' % name)
+        name = data_utils.rand_name('%s-' % name)
         image_file = open(path, 'rb')
         self.addCleanup(image_file.close)
         params = {
@@ -82,10 +82,10 @@
                                         properties=properties)
 
     def nova_boot(self):
-        name = rand_name('scenario-server-')
+        name = data_utils.rand_name('scenario-server-')
         client = self.compute_client
         flavor_id = self.config.compute.flavor_ref
-        secgroup = self._create_security_group()
+        secgroup = self._create_security_group_nova()
         self.servers = client.servers.create(
             name=name, image=self.image,
             flavor=flavor_id,
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index 752ff6f..8a51cd1 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -15,7 +15,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.openstack.common import log as logging
 from tempest.scenario import manager
 from tempest.test import services
@@ -48,7 +48,7 @@
             self.volume_client.volumes, volume_id, status)
 
     def _image_create(self, name, fmt, path, properties={}):
-        name = rand_name('%s-' % name)
+        name = data_utils.rand_name('%s-' % name)
         image_file = open(path, 'rb')
         self.addCleanup(image_file.close)
         params = {
@@ -161,7 +161,7 @@
 
         self.nova_floating_ip_create()
         self.nova_floating_ip_add()
-        self.create_loginable_secgroup_rule()
+        self._create_loginable_secgroup_rule_nova()
         self.ssh_to_server()
         self.check_partitions()
 
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 5bf5900..1418b75 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -18,7 +18,7 @@
 
 from tempest.api.network import common as net_common
 from tempest.common import debug
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import config
 from tempest.openstack.common import jsonutils
 from tempest.openstack.common import log as logging
@@ -191,7 +191,7 @@
                             "'public_network_id' has been defined.")
 
     def _create_router(self, tenant_id, namestart='router-smoke-'):
-        name = rand_name(namestart)
+        name = data_utils.rand_name(namestart)
         body = dict(
             router=dict(
                 name=name,
@@ -208,10 +208,11 @@
 
     def _create_keypairs(self):
         self.keypairs[self.tenant_id] = self.create_keypair(
-            name=rand_name('keypair-smoke-'))
+            name=data_utils.rand_name('keypair-smoke-'))
 
     def _create_security_groups(self):
-        self.security_groups[self.tenant_id] = self._create_security_group()
+        self.security_groups[self.tenant_id] =\
+            self._create_security_group_neutron(tenant_id=self.tenant_id)
 
     def _create_networks(self):
         network = self._create_network(self.tenant_id)
@@ -261,7 +262,7 @@
 
     def _create_servers(self):
         for i, network in enumerate(self.networks):
-            name = rand_name('server-smoke-%d-' % i)
+            name = data_utils.rand_name('server-smoke-%d-' % i)
             server = self._create_server(name, network)
             self.servers.append(server)
 
diff --git a/tempest/scenario/test_network_quotas.py b/tempest/scenario/test_network_quotas.py
index 3268066..cb7aa0b 100644
--- a/tempest/scenario/test_network_quotas.py
+++ b/tempest/scenario/test_network_quotas.py
@@ -20,8 +20,6 @@
 from tempest.scenario.manager import NetworkScenarioTest
 from tempest.test import services
 
-MAX_REASONABLE_ITERATIONS = 51  # more than enough. Default for port is 50.
-
 
 class TestNetworkQuotaBasic(NetworkScenarioTest):
     """
@@ -46,7 +44,9 @@
     @services('network')
     def test_create_network_until_quota_hit(self):
         hit_limit = False
-        for n in xrange(MAX_REASONABLE_ITERATIONS):
+        networknum = self._get_tenant_own_network_num(self.tenant_id)
+        max = self._show_quota_network(self.tenant_id) - networknum
+        for n in xrange(max):
             try:
                 self.networks.append(
                     self._create_network(self.tenant_id,
@@ -56,6 +56,16 @@
                     raise
                 hit_limit = True
                 break
+        self.assertFalse(hit_limit, "Failed: Hit quota limit !")
+
+        try:
+            self.networks.append(
+                self._create_network(self.tenant_id,
+                                     namestart='network-quotatest-'))
+        except exc.NeutronClientException as e:
+            if (e.status_code != 409):
+                raise
+            hit_limit = True
         self.assertTrue(hit_limit, "Failed: Did not hit quota limit !")
 
     @services('network')
@@ -65,7 +75,9 @@
                 self._create_network(self.tenant_id,
                                      namestart='network-quotatest-'))
         hit_limit = False
-        for n in xrange(MAX_REASONABLE_ITERATIONS):
+        subnetnum = self._get_tenant_own_subnet_num(self.tenant_id)
+        max = self._show_quota_subnet(self.tenant_id) - subnetnum
+        for n in xrange(max):
             try:
                 self.subnets.append(
                     self._create_subnet(self.networks[0],
@@ -75,6 +87,16 @@
                     raise
                 hit_limit = True
                 break
+        self.assertFalse(hit_limit, "Failed: Hit quota limit !")
+
+        try:
+            self.subnets.append(
+                self._create_subnet(self.networks[0],
+                                    namestart='subnet-quotatest-'))
+        except exc.NeutronClientException as e:
+            if (e.status_code != 409):
+                raise
+            hit_limit = True
         self.assertTrue(hit_limit, "Failed: Did not hit quota limit !")
 
     @services('network')
@@ -84,7 +106,9 @@
                 self._create_network(self.tenant_id,
                                      namestart='network-quotatest-'))
         hit_limit = False
-        for n in xrange(MAX_REASONABLE_ITERATIONS):
+        portnum = self._get_tenant_own_port_num(self.tenant_id)
+        max = self._show_quota_port(self.tenant_id) - portnum
+        for n in xrange(max):
             try:
                 self.ports.append(
                     self._create_port(self.networks[0],
@@ -94,4 +118,14 @@
                     raise
                 hit_limit = True
                 break
+        self.assertFalse(hit_limit, "Failed: Hit quota limit !")
+
+        try:
+            self.ports.append(
+                self._create_port(self.networks[0],
+                                  namestart='port-quotatest-'))
+        except exc.NeutronClientException as e:
+            if (e.status_code != 409):
+                raise
+            hit_limit = True
         self.assertTrue(hit_limit, "Failed: Did not hit quota limit !")
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index c32d49d..1e1a310 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -15,7 +15,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.openstack.common import log as logging
 from tempest.scenario import manager
 from tempest.test import services
@@ -41,7 +41,7 @@
         self.keypair = self.create_keypair()
 
     def create_security_group(self):
-        sg_name = rand_name('secgroup-smoke')
+        sg_name = data_utils.rand_name('secgroup-smoke')
         sg_desc = sg_name + " description"
         self.secgroup = self.compute_client.security_groups.create(sg_name,
                                                                    sg_desc)
@@ -50,7 +50,7 @@
         self.set_resource('secgroup', self.secgroup)
 
         # Add rules to the security group
-        self.create_loginable_secgroup_rule(secgroup_id=self.secgroup.id)
+        self._create_loginable_secgroup_rule_nova(secgroup_id=self.secgroup.id)
 
     def boot_instance(self):
         create_kwargs = {
diff --git a/tempest/scenario/test_snapshot_pattern.py b/tempest/scenario/test_snapshot_pattern.py
index ba347e0..00139f0 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -65,7 +65,7 @@
     def test_snapshot_pattern(self):
         # prepare for booting a instance
         self._add_keypair()
-        self.create_loginable_secgroup_rule()
+        self._create_loginable_secgroup_rule_nova()
 
         # boot a instance and create a timestamp file in it
         server = self._boot_image(self.config.compute.image_ref)
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 6812d64..5eac55c 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -19,7 +19,7 @@
 
 from cinderclient import exceptions as cinder_exceptions
 
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.openstack.common import log as logging
 from tempest.scenario import manager
@@ -75,7 +75,7 @@
         return linux_client.ssh_client
 
     def _create_volume_snapshot(self, volume):
-        snapshot_name = rand_name('scenario-snapshot-')
+        snapshot_name = data_utils.rand_name('scenario-snapshot-')
         volume_snapshots = self.volume_client.volume_snapshots
         snapshot = volume_snapshots.create(
             volume.id, display_name=snapshot_name)
@@ -146,7 +146,7 @@
     def test_stamp_pattern(self):
         # prepare for booting a instance
         self._add_keypair()
-        self.create_loginable_secgroup_rule()
+        self._create_loginable_secgroup_rule_nova()
 
         # boot an instance and create a timestamp file in it
         volume = self._create_volume()
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index d12cd56..fa9a228 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -12,7 +12,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.scenario import manager
 from tempest.test import services
 
@@ -34,7 +34,7 @@
 
     def _create_volume_from_image(self):
         img_uuid = self.config.compute.image_ref
-        vol_name = rand_name('volume-origin')
+        vol_name = data_utils.rand_name('volume-origin')
         return self.create_volume(name=vol_name, imageRef=img_uuid)
 
     def _boot_instance_from_volume(self, vol_id, keypair):
@@ -53,7 +53,7 @@
 
     def _create_snapshot_from_volume(self, vol_id):
         volume_snapshots = self.volume_client.volume_snapshots
-        snap_name = rand_name('snapshot')
+        snap_name = data_utils.rand_name('snapshot')
         snap = volume_snapshots.create(volume_id=vol_id,
                                        force=True,
                                        display_name=snap_name)
@@ -64,7 +64,7 @@
         return snap
 
     def _create_volume_from_snapshot(self, snap_id):
-        vol_name = rand_name('volume')
+        vol_name = data_utils.rand_name('volume')
         return self.create_volume(name=vol_name, snapshot_id=snap_id)
 
     def _stop_instances(self, instances):
@@ -88,7 +88,7 @@
     def _ssh_to_server(self, server, keypair):
         if self.config.compute.use_floatingip_for_ssh:
             floating_ip = self.compute_client.floating_ips.create()
-            fip_name = rand_name('scenario-fip')
+            fip_name = data_utils.rand_name('scenario-fip')
             self.set_resource(fip_name, floating_ip)
             server.add_floating_ip(floating_ip)
             ip = floating_ip.ip
@@ -104,7 +104,7 @@
         return ssh_client.exec_command('cat /tmp/text')
 
     def _write_text(self, ssh_client):
-        text = rand_name('text-')
+        text = data_utils.rand_name('text-')
         ssh_client.exec_command('echo "%s" > /tmp/text; sync' % (text))
 
         return self._get_content(ssh_client)
@@ -120,7 +120,7 @@
     @services('compute', 'volume', 'image')
     def test_volume_boot_pattern(self):
         keypair = self.create_keypair()
-        self.create_loginable_secgroup_rule()
+        self._create_loginable_secgroup_rule_nova()
 
         # create an instance from volume
         volume_origin = self._create_volume_from_image()
diff --git a/tempest/services/compute/json/certificates_client.py b/tempest/services/compute/json/certificates_client.py
new file mode 100644
index 0000000..9fdce17
--- /dev/null
+++ b/tempest/services/compute/json/certificates_client.py
@@ -0,0 +1,42 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM Corp
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import json
+
+from tempest.common.rest_client import RestClient
+
+
+class CertificatesClientJSON(RestClient):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(CertificatesClientJSON, self).__init__(config, username,
+                                                     password,
+                                                     auth_url, tenant_name)
+        self.service = self.config.compute.catalog_type
+
+    def get_certificate(self, id):
+        url = "os-certificates/%s" % (id)
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body['certificate']
+
+    def create_certificate(self):
+        """create certificates."""
+        url = "os-certificates"
+        resp, body = self.post(url, None, self.headers)
+        body = json.loads(body)
+        return resp, body['certificate']
diff --git a/tempest/services/compute/json/flavors_client.py b/tempest/services/compute/json/flavors_client.py
index 305a77b..00d6f8a 100644
--- a/tempest/services/compute/json/flavors_client.py
+++ b/tempest/services/compute/json/flavors_client.py
@@ -103,14 +103,14 @@
         return resp, body['extra_specs']
 
     def get_flavor_extra_spec_with_key(self, flavor_id, key):
-        """Gets a specified key value for the mentioned flavor."""
+        """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))
         body = json.loads(body)
-        return resp, body[key]
+        return resp, body
 
     def update_flavor_extra_spec(self, flavor_id, key, **kwargs):
-        """Gets specified extra Specs details of the mentioned flavor."""
+        """Update specified extra Specs of the mentioned flavor and key."""
         resp, body = self.put('flavors/%s/os-extra_specs/%s' %
                               (flavor_id, key),
                               json.dumps(kwargs), self.headers)
@@ -122,6 +122,13 @@
         return self.delete('flavors/%s/os-extra_specs/%s' % (str(flavor_id),
                            key))
 
+    def list_flavor_access(self, flavor_id):
+        """Gets flavor access information given the flavor id."""
+        resp, body = self.get('flavors/%s/os-flavor-access' % flavor_id,
+                              self.headers)
+        body = json.loads(body)
+        return resp, body['flavor_access']
+
     def add_flavor_access(self, flavor_id, tenant_id):
         """Add flavor access for the specified tenant."""
         post_body = {
diff --git a/tempest/services/compute/json/instance_usage_audit_log_client.py b/tempest/services/compute/json/instance_usage_audit_log_client.py
new file mode 100644
index 0000000..07ce1bb
--- /dev/null
+++ b/tempest/services/compute/json/instance_usage_audit_log_client.py
@@ -0,0 +1,40 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM 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 json
+
+from tempest.common.rest_client import RestClient
+
+
+class InstanceUsagesAuditLogClientJSON(RestClient):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(InstanceUsagesAuditLogClientJSON, self).__init__(
+            config, username, password, auth_url, tenant_name)
+        self.service = self.config.compute.catalog_type
+
+    def list_instance_usage_audit_logs(self):
+        url = 'os-instance_usage_audit_log'
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body["instance_usage_audit_logs"]
+
+    def get_instance_usage_audit_log(self, time_before):
+        url = 'os-instance_usage_audit_log/%s' % time_before
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body["instance_usage_audit_log"]
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index 07bb6ce..eb1a0c3 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -154,9 +154,12 @@
         body = json.loads(body)
         return resp, body
 
-    def wait_for_server_status(self, server_id, status):
+    def wait_for_server_status(self, server_id, status, extra_timeout=0,
+                               raise_on_error=True):
         """Waits for a server to reach a given status."""
-        return waiters.wait_for_server_status(self, server_id, status)
+        return waiters.wait_for_server_status(self, server_id, status,
+                                              extra_timeout=extra_timeout,
+                                              raise_on_error=raise_on_error)
 
     def wait_for_server_termination(self, server_id, ignore_error=False):
         """Waits for server to reach termination."""
@@ -197,11 +200,33 @@
             body = json.loads(body)[response_key]
         return resp, body
 
+    def create_backup(self, server_id, backup_type, rotation, name):
+        """Backup a server instance."""
+        return self.action(server_id, "createBackup", None,
+                           backup_type=backup_type,
+                           rotation=rotation,
+                           name=name)
+
     def change_password(self, server_id, adminPass):
         """Changes the root password for the server."""
         return self.action(server_id, 'changePassword', None,
                            adminPass=adminPass)
 
+    def get_password(self, server_id):
+        resp, body = self.get("servers/%s/os-server-password" %
+                              str(server_id))
+        body = json.loads(body)
+        return resp, body
+
+    def delete_password(self, server_id):
+        """
+        Removes the encrypted server password from the metadata server
+        Note that this does not actually change the instance server
+        password.
+        """
+        return self.delete("servers/%s/os-server-password" %
+                           str(server_id))
+
     def reboot(self, server_id, reboot_type):
         """Reboots a server."""
         return self.action(server_id, 'reboot', None, type=reboot_type)
@@ -333,25 +358,33 @@
         return self.action(server_id, 'unlock', None, **kwargs)
 
     def suspend_server(self, server_id, **kwargs):
-        """Suspends the provded server."""
+        """Suspends the provided server."""
         return self.action(server_id, 'suspend', None, **kwargs)
 
     def resume_server(self, server_id, **kwargs):
-        """Un-suspends the provded server."""
+        """Un-suspends the provided server."""
         return self.action(server_id, 'resume', None, **kwargs)
 
     def pause_server(self, server_id, **kwargs):
-        """Pauses the provded server."""
+        """Pauses the provided server."""
         return self.action(server_id, 'pause', None, **kwargs)
 
     def unpause_server(self, server_id, **kwargs):
-        """Un-pauses the provded server."""
+        """Un-pauses the provided server."""
         return self.action(server_id, 'unpause', None, **kwargs)
 
     def reset_state(self, server_id, state='error'):
         """Resets the state of a server to active/error."""
         return self.action(server_id, 'os-resetState', None, state=state)
 
+    def shelve_server(self, server_id, **kwargs):
+        """Shelves the provided server."""
+        return self.action(server_id, 'shelve', None, **kwargs)
+
+    def unshelve_server(self, server_id, **kwargs):
+        """Un-shelves the provided server."""
+        return self.action(server_id, 'unshelve', None, **kwargs)
+
     def get_console_output(self, server_id, length):
         return self.action(server_id, 'os-getConsoleOutput', 'output',
                            length=length)
@@ -390,3 +423,11 @@
                               (str(server_id), str(request_id)))
         body = json.loads(body)
         return resp, body['instanceAction']
+
+    def force_delete_server(self, server_id, **kwargs):
+        """Force delete a server."""
+        return self.action(server_id, 'forceDelete', None, **kwargs)
+
+    def restore_soft_deleted_server(self, server_id, **kwargs):
+        """Restore a soft-deleted server."""
+        return self.action(server_id, 'restore', None, **kwargs)
diff --git a/tempest/services/compute/v3/__init__.py b/tempest/services/compute/v3/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/services/compute/v3/__init__.py
diff --git a/tempest/services/compute/v3/json/__init__.py b/tempest/services/compute/v3/json/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/services/compute/v3/json/__init__.py
diff --git a/tempest/services/compute/v3/json/availability_zone_client.py b/tempest/services/compute/v3/json/availability_zone_client.py
new file mode 100644
index 0000000..9a3fe8b
--- /dev/null
+++ b/tempest/services/compute/v3/json/availability_zone_client.py
@@ -0,0 +1,39 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 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 json
+
+from tempest.common.rest_client import RestClient
+
+
+class AvailabilityZoneV3ClientJSON(RestClient):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(AvailabilityZoneV3ClientJSON, self).__init__(config, username,
+                                                           password, auth_url,
+                                                           tenant_name)
+        self.service = self.config.compute.catalog_v3_type
+
+    def get_availability_zone_list(self):
+        resp, body = self.get('os-availability-zone')
+        body = json.loads(body)
+        return resp, body['availability_zone_info']
+
+    def get_availability_zone_list_detail(self):
+        resp, body = self.get('os-availability-zone/detail')
+        body = json.loads(body)
+        return resp, body['availability_zone_info']
diff --git a/tempest/services/compute/v3/json/extensions_client.py b/tempest/services/compute/v3/json/extensions_client.py
new file mode 100644
index 0000000..60c0217
--- /dev/null
+++ b/tempest/services/compute/v3/json/extensions_client.py
@@ -0,0 +1,40 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import json
+
+from tempest.common.rest_client import RestClient
+
+
+class ExtensionsV3ClientJSON(RestClient):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(ExtensionsV3ClientJSON, self).__init__(config, username,
+                                                     password, auth_url,
+                                                     tenant_name)
+        self.service = self.config.compute.catalog_v3_type
+
+    def list_extensions(self):
+        url = 'extensions'
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body
+
+    def is_enabled(self, extension):
+        _, extensions = self.list_extensions()
+        exts = extensions['extensions']
+        return any([e for e in exts if e['name'] == extension])
diff --git a/tempest/services/compute/v3/json/flavors_client.py b/tempest/services/compute/v3/json/flavors_client.py
new file mode 100644
index 0000000..00d6f8a
--- /dev/null
+++ b/tempest/services/compute/v3/json/flavors_client.py
@@ -0,0 +1,156 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import json
+import urllib
+
+from tempest.common.rest_client import RestClient
+
+
+class FlavorsClientJSON(RestClient):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(FlavorsClientJSON, self).__init__(config, username, password,
+                                                auth_url, tenant_name)
+        self.service = self.config.compute.catalog_type
+
+    def list_flavors(self, params=None):
+        url = 'flavors'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body['flavors']
+
+    def list_flavors_with_detail(self, params=None):
+        url = 'flavors/detail'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body['flavors']
+
+    def get_flavor_details(self, flavor_id):
+        resp, body = self.get("flavors/%s" % str(flavor_id))
+        body = json.loads(body)
+        return resp, body['flavor']
+
+    def create_flavor(self, name, ram, vcpus, disk, flavor_id, **kwargs):
+        """Creates a new flavor or instance type."""
+        post_body = {
+            'name': name,
+            'ram': ram,
+            'vcpus': vcpus,
+            'disk': disk,
+            'id': flavor_id,
+        }
+        if kwargs.get('ephemeral'):
+            post_body['OS-FLV-EXT-DATA:ephemeral'] = kwargs.get('ephemeral')
+        if kwargs.get('swap'):
+            post_body['swap'] = kwargs.get('swap')
+        if kwargs.get('rxtx'):
+            post_body['rxtx_factor'] = kwargs.get('rxtx')
+        if kwargs.get('is_public'):
+            post_body['os-flavor-access:is_public'] = kwargs.get('is_public')
+        post_body = json.dumps({'flavor': post_body})
+        resp, body = self.post('flavors', post_body, self.headers)
+
+        body = json.loads(body)
+        return resp, body['flavor']
+
+    def delete_flavor(self, flavor_id):
+        """Deletes the given flavor."""
+        return self.delete("flavors/%s" % str(flavor_id))
+
+    def is_resource_deleted(self, id):
+        # Did not use get_flavor_details(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
+        resp, flavors = self.list_flavors_with_detail()
+        for flavor in flavors:
+            if flavor['id'] == id:
+                return False
+        return True
+
+    def set_flavor_extra_spec(self, flavor_id, specs):
+        """Sets extra Specs to the mentioned flavor."""
+        post_body = json.dumps({'extra_specs': specs})
+        resp, body = self.post('flavors/%s/os-extra_specs' % flavor_id,
+                               post_body, self.headers)
+        body = json.loads(body)
+        return resp, body['extra_specs']
+
+    def get_flavor_extra_spec(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)
+        return resp, body['extra_specs']
+
+    def get_flavor_extra_spec_with_key(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))
+        body = json.loads(body)
+        return resp, body
+
+    def update_flavor_extra_spec(self, flavor_id, key, **kwargs):
+        """Update specified extra Specs of the mentioned flavor and key."""
+        resp, body = self.put('flavors/%s/os-extra_specs/%s' %
+                              (flavor_id, key),
+                              json.dumps(kwargs), self.headers)
+        body = json.loads(body)
+        return resp, body
+
+    def unset_flavor_extra_spec(self, flavor_id, key):
+        """Unsets extra Specs from the mentioned flavor."""
+        return self.delete('flavors/%s/os-extra_specs/%s' % (str(flavor_id),
+                           key))
+
+    def list_flavor_access(self, flavor_id):
+        """Gets flavor access information given the flavor id."""
+        resp, body = self.get('flavors/%s/os-flavor-access' % flavor_id,
+                              self.headers)
+        body = json.loads(body)
+        return resp, body['flavor_access']
+
+    def add_flavor_access(self, flavor_id, tenant_id):
+        """Add flavor access for the specified tenant."""
+        post_body = {
+            'addTenantAccess': {
+                'tenant': tenant_id
+            }
+        }
+        post_body = json.dumps(post_body)
+        resp, body = self.post('flavors/%s/action' % flavor_id,
+                               post_body, self.headers)
+        body = json.loads(body)
+        return resp, body['flavor_access']
+
+    def remove_flavor_access(self, flavor_id, tenant_id):
+        """Remove flavor access from the specified tenant."""
+        post_body = {
+            'removeTenantAccess': {
+                'tenant': tenant_id
+            }
+        }
+        post_body = json.dumps(post_body)
+        resp, body = self.post('flavors/%s/action' % flavor_id,
+                               post_body, self.headers)
+        body = json.loads(body)
+        return resp, body['flavor_access']
diff --git a/tempest/services/compute/v3/json/hypervisor_client.py b/tempest/services/compute/v3/json/hypervisor_client.py
new file mode 100644
index 0000000..fa1255a
--- /dev/null
+++ b/tempest/services/compute/v3/json/hypervisor_client.py
@@ -0,0 +1,71 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM 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 json
+
+from tempest.common.rest_client import RestClient
+
+
+class HypervisorV3ClientJSON(RestClient):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(HypervisorV3ClientJSON, self).__init__(config, username,
+                                                     password, auth_url,
+                                                     tenant_name)
+        self.service = self.config.compute.catalog_v3_type
+
+    def get_hypervisor_list(self):
+        """List hypervisors information."""
+        resp, body = self.get('os-hypervisors')
+        body = json.loads(body)
+        return resp, body['hypervisors']
+
+    def get_hypervisor_list_details(self):
+        """Show detailed hypervisors information."""
+        resp, body = self.get('os-hypervisors/detail')
+        body = json.loads(body)
+        return resp, body['hypervisors']
+
+    def get_hypervisor_show_details(self, hyper_id):
+        """Display the details of the specified hypervisor."""
+        resp, body = self.get('os-hypervisors/%s' % hyper_id)
+        body = json.loads(body)
+        return resp, body['hypervisor']
+
+    def get_hypervisor_servers(self, hyper_name):
+        """List instances belonging to the specified hypervisor."""
+        resp, body = self.get('os-hypervisors/%s/servers' % hyper_name)
+        body = json.loads(body)
+        return resp, body['hypervisor']
+
+    def get_hypervisor_stats(self):
+        """Get hypervisor statistics over all compute nodes."""
+        resp, body = self.get('os-hypervisors/statistics')
+        body = json.loads(body)
+        return resp, body['hypervisor_statistics']
+
+    def get_hypervisor_uptime(self, hyper_id):
+        """Display the uptime of the specified hypervisor."""
+        resp, body = self.get('os-hypervisors/%s/uptime' % hyper_id)
+        body = json.loads(body)
+        return resp, body['hypervisor']
+
+    def search_hypervisor(self, hyper_name):
+        """Search specified hypervisor."""
+        resp, body = self.get('os-hypervisors/search?query=%s' % hyper_name)
+        body = json.loads(body)
+        return resp, body['hypervisors']
diff --git a/tempest/services/compute/v3/json/interfaces_client.py b/tempest/services/compute/v3/json/interfaces_client.py
new file mode 100644
index 0000000..7fb0fa9
--- /dev/null
+++ b/tempest/services/compute/v3/json/interfaces_client.py
@@ -0,0 +1,83 @@
+# Copyright 2013 IBM Corp.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import json
+import time
+
+from tempest.common.rest_client import RestClient
+from tempest import exceptions
+
+
+class InterfacesV3ClientJSON(RestClient):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(InterfacesV3ClientJSON, self).__init__(config, username,
+                                                     password, auth_url,
+                                                     tenant_name)
+        self.service = self.config.compute.catalog_v3_type
+
+    def list_interfaces(self, server):
+        resp, body = self.get('servers/%s/os-attach-interfaces' % server)
+        body = json.loads(body)
+        return resp, body['interface_attachments']
+
+    def create_interface(self, server, port_id=None, network_id=None,
+                         fixed_ip=None):
+        post_body = dict(interface_attachment=dict())
+        if port_id:
+            post_body['port_id'] = port_id
+        if network_id:
+            post_body['net_id'] = network_id
+        if fixed_ip:
+            post_body['fixed_ips'] = [dict(ip_address=fixed_ip)]
+        post_body = json.dumps(post_body)
+        resp, body = self.post('servers/%s/os-attach-interfaces' % server,
+                               headers=self.headers,
+                               body=post_body)
+        body = json.loads(body)
+        return resp, body['interface_attachment']
+
+    def show_interface(self, server, port_id):
+        resp, body =\
+            self.get('servers/%s/os-attach-interfaces/%s' % (server, port_id))
+        body = json.loads(body)
+        return resp, body['interface_attachment']
+
+    def delete_interface(self, server, port_id):
+        resp, body =\
+            self.delete('servers/%s/os-attach-interfaces/%s' % (server,
+                                                                port_id))
+        return resp, body
+
+    def wait_for_interface_status(self, server, port_id, status):
+        """Waits for a interface to reach a given status."""
+        resp, body = self.show_interface(server, port_id)
+        interface_status = body['port_state']
+        start = int(time.time())
+
+        while(interface_status != status):
+            time.sleep(self.build_interval)
+            resp, body = self.show_interface(server, port_id)
+            interface_status = body['port_state']
+
+            timed_out = int(time.time()) - start >= self.build_timeout
+
+            if interface_status != status and timed_out:
+                message = ('Interface %s failed to reach %s status within '
+                           'the required time (%s s).' %
+                           (port_id, status, self.build_timeout))
+                raise exceptions.TimeoutException(message)
+
+        return resp, body
diff --git a/tempest/services/compute/v3/json/limits_client.py b/tempest/services/compute/v3/json/limits_client.py
new file mode 100644
index 0000000..3e53e3e
--- /dev/null
+++ b/tempest/services/compute/v3/json/limits_client.py
@@ -0,0 +1,40 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import json
+from tempest.common.rest_client import RestClient
+
+
+class LimitsClientJSON(RestClient):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(LimitsClientJSON, self).__init__(config, username, password,
+                                               auth_url, tenant_name)
+        self.service = self.config.compute.catalog_type
+
+    def get_absolute_limits(self):
+        resp, body = self.get("limits")
+        body = json.loads(body)
+        return resp, body['limits']['absolute']
+
+    def get_specific_absolute_limit(self, absolute_limit):
+        resp, body = self.get("limits")
+        body = json.loads(body)
+        if absolute_limit not in body['limits']['absolute']:
+            return None
+        else:
+            return body['limits']['absolute'][absolute_limit]
diff --git a/tempest/services/compute/v3/json/quotas_client.py b/tempest/services/compute/v3/json/quotas_client.py
new file mode 100644
index 0000000..a910dec
--- /dev/null
+++ b/tempest/services/compute/v3/json/quotas_client.py
@@ -0,0 +1,103 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+# Copyright 2012 NTT Data
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import json
+
+from tempest.common.rest_client import RestClient
+
+
+class QuotasClientJSON(RestClient):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(QuotasClientJSON, self).__init__(config, username, password,
+                                               auth_url, tenant_name)
+        self.service = self.config.compute.catalog_type
+
+    def get_quota_set(self, tenant_id):
+        """List the quota set for a tenant."""
+
+        url = 'os-quota-sets/%s' % str(tenant_id)
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body['quota_set']
+
+    def get_default_quota_set(self, tenant_id):
+        """List the default quota set for a tenant."""
+
+        url = 'os-quota-sets/%s/defaults' % str(tenant_id)
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body['quota_set']
+
+    def update_quota_set(self, tenant_id, force=None,
+                         injected_file_content_bytes=None,
+                         metadata_items=None, ram=None, floating_ips=None,
+                         fixed_ips=None, key_pairs=None, instances=None,
+                         security_group_rules=None, injected_files=None,
+                         cores=None, injected_file_path_bytes=None,
+                         security_groups=None):
+        """
+        Updates the tenant's quota limits for one or more resources
+        """
+        post_body = {}
+
+        if force is not None:
+            post_body['force'] = force
+
+        if injected_file_content_bytes is not None:
+            post_body['injected_file_content_bytes'] = \
+                injected_file_content_bytes
+
+        if metadata_items is not None:
+            post_body['metadata_items'] = metadata_items
+
+        if ram is not None:
+            post_body['ram'] = ram
+
+        if floating_ips is not None:
+            post_body['floating_ips'] = floating_ips
+
+        if fixed_ips is not None:
+            post_body['fixed_ips'] = fixed_ips
+
+        if key_pairs is not None:
+            post_body['key_pairs'] = key_pairs
+
+        if instances is not None:
+            post_body['instances'] = instances
+
+        if security_group_rules is not None:
+            post_body['security_group_rules'] = security_group_rules
+
+        if injected_files is not None:
+            post_body['injected_files'] = injected_files
+
+        if cores is not None:
+            post_body['cores'] = cores
+
+        if injected_file_path_bytes is not None:
+            post_body['injected_file_path_bytes'] = injected_file_path_bytes
+
+        if security_groups is not None:
+            post_body['security_groups'] = security_groups
+
+        post_body = json.dumps({'quota_set': post_body})
+        resp, body = self.put('os-quota-sets/%s' % str(tenant_id), post_body,
+                              self.headers)
+
+        body = json.loads(body)
+        return resp, body['quota_set']
diff --git a/tempest/services/compute/v3/json/servers_client.py b/tempest/services/compute/v3/json/servers_client.py
new file mode 100644
index 0000000..a7fcc6d
--- /dev/null
+++ b/tempest/services/compute/v3/json/servers_client.py
@@ -0,0 +1,390 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# Copyright 2013 Hewlett-Packard Development Company, L.P.
+# Copyright 2013 IBM Corp
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import json
+import time
+import urllib
+
+from tempest.common.rest_client import RestClient
+from tempest.common import waiters
+from tempest import exceptions
+
+
+class ServersV3ClientJSON(RestClient):
+
+    def __init__(self, config, username, password, auth_url,
+                 tenant_name=None, auth_version='v2'):
+        super(ServersV3ClientJSON, self).__init__(config, username, password,
+                                                  auth_url, tenant_name,
+                                                  auth_version=auth_version)
+        self.service = self.config.compute.catalog_v3_type
+
+    def create_server(self, name, image_ref, flavor_ref, **kwargs):
+        """
+        Creates an instance of a server.
+        name (Required): The name of the server.
+        image_ref (Required): Reference to the image used to build the server.
+        flavor_ref (Required): The flavor used to build the server.
+        Following optional keyword arguments are accepted:
+        admin_password: Sets the initial root password.
+        key_name: Key name of keypair that was created earlier.
+        meta: A dictionary of values to be used as metadata.
+        personality: A list of dictionaries for files to be injected into
+        the server.
+        security_groups: A list of security group dicts.
+        networks: A list of network dicts with UUID and fixed_ip.
+        user_data: User data for instance.
+        availability_zone: Availability zone in which to launch instance.
+        access_ip_v4: The IPv4 access address for the server.
+        access_ip_v6: The IPv6 access address for the server.
+        min_count: Count of minimum number of instances to launch.
+        max_count: Count of maximum number of instances to launch.
+        disk_config: Determines if user or admin controls disk configuration.
+        return_reservation_id: Enable/Disable the return of reservation id
+        """
+        post_body = {
+            'name': name,
+            'image_ref': image_ref,
+            'flavor_ref': flavor_ref
+        }
+
+        for option in ['personality', 'admin_password', 'key_name',
+                       'security_groups', 'networks',
+                       ('os-user-data:user_data', 'user_data'),
+                       ('os-availability-zone:availability_zone',
+                        'availability_zone'),
+                       'access_ip_v4', 'access_ip_v6',
+                       ('os-multiple-create:min_count', 'min_count'),
+                       ('os-multiple-create:max_count', 'max_count'),
+                       ('metadata', 'meta'),
+                       ('os-disk-config:disk_config', 'disk_config'),
+                       ('os-multiple-create:return_reservation_id',
+                       'return_reservation_id')]:
+            if isinstance(option, tuple):
+                post_param = option[0]
+                key = option[1]
+            else:
+                post_param = option
+                key = option
+            value = kwargs.get(key)
+            if value is not None:
+                post_body[post_param] = value
+        post_body = json.dumps({'server': post_body})
+        resp, body = self.post('servers', post_body, self.headers)
+
+        body = json.loads(body)
+        # NOTE(maurosr): this deals with the case of multiple server create
+        # with return reservation id set True
+        if 'reservation_id' in body:
+            return resp, body
+        return resp, body['server']
+
+    def update_server(self, server_id, name=None, meta=None, access_ip_v4=None,
+                      access_ip_v6=None, disk_config=None):
+        """
+        Updates the properties of an existing server.
+        server_id: The id of an existing server.
+        name: The name of the server.
+        personality: A list of files to be injected into the server.
+        access_ip_v4: The IPv4 access address for the server.
+        access_ip_v6: The IPv6 access address for the server.
+        """
+
+        post_body = {}
+
+        if meta is not None:
+            post_body['metadata'] = meta
+
+        if name is not None:
+            post_body['name'] = name
+
+        if access_ip_v4 is not None:
+            post_body['access_ip_v4'] = access_ip_v4
+
+        if access_ip_v6 is not None:
+            post_body['access_ip_v6'] = access_ip_v6
+
+        if disk_config is not None:
+            post_body['os-disk-config:disk_config'] = disk_config
+
+        post_body = json.dumps({'server': post_body})
+        resp, body = self.put("servers/%s" % str(server_id),
+                              post_body, self.headers)
+        body = json.loads(body)
+        return resp, body['server']
+
+    def get_server(self, server_id):
+        """Returns the details of an existing server."""
+        resp, body = self.get("servers/%s" % str(server_id))
+        body = json.loads(body)
+        return resp, body['server']
+
+    def delete_server(self, server_id):
+        """Deletes the given server."""
+        return self.delete("servers/%s" % str(server_id))
+
+    def list_servers(self, params=None):
+        """Lists all servers for a user."""
+
+        url = 'servers'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body
+
+    def list_servers_with_detail(self, params=None):
+        """Lists all servers in detail for a user."""
+
+        url = 'servers/detail'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body
+
+    def wait_for_server_status(self, server_id, status, extra_timeout=0):
+        """Waits for a server to reach a given status."""
+        return waiters.wait_for_server_status(self, server_id, status,
+                                              extra_timeout=extra_timeout)
+
+    def wait_for_server_termination(self, server_id, ignore_error=False):
+        """Waits for server to reach termination."""
+        start_time = int(time.time())
+        while True:
+            try:
+                resp, body = self.get_server(server_id)
+            except exceptions.NotFound:
+                return
+
+            server_status = body['status']
+            if server_status == 'ERROR' and not ignore_error:
+                raise exceptions.BuildErrorException(server_id=server_id)
+
+            if int(time.time()) - start_time >= self.build_timeout:
+                raise exceptions.TimeoutException
+
+            time.sleep(self.build_interval)
+
+    def list_addresses(self, server_id):
+        """Lists all addresses for a server."""
+        resp, body = self.get("servers/%s/ips" % str(server_id))
+        body = json.loads(body)
+        return resp, body['addresses']
+
+    def list_addresses_by_network(self, server_id, network_id):
+        """Lists all addresses of a specific network type for a server."""
+        resp, body = self.get("servers/%s/ips/%s" %
+                              (str(server_id), network_id))
+        body = json.loads(body)
+        return resp, body
+
+    def action(self, server_id, action_name, response_key, **kwargs):
+        post_body = json.dumps({action_name: kwargs})
+        resp, body = self.post('servers/%s/action' % str(server_id),
+                               post_body, self.headers)
+        if response_key is not None:
+            body = json.loads(body)[response_key]
+        return resp, body
+
+    def change_password(self, server_id, admin_password):
+        """Changes the root password for the server."""
+        return self.action(server_id, 'change_password', None,
+                           admin_password=admin_password)
+
+    def reboot(self, server_id, reboot_type):
+        """Reboots a server."""
+        return self.action(server_id, 'reboot', None, type=reboot_type)
+
+    def rebuild(self, server_id, image_ref, **kwargs):
+        """Rebuilds a server with a new image."""
+        kwargs['image_ref'] = image_ref
+        if 'disk_config' in kwargs:
+            kwargs['os-disk-config:disk_config'] = kwargs['disk_config']
+            del kwargs['disk_config']
+        return self.action(server_id, 'rebuild', 'server', **kwargs)
+
+    def resize(self, server_id, flavor_ref, **kwargs):
+        """Changes the flavor of a server."""
+        kwargs['flavor_ref'] = flavor_ref
+        if 'disk_config' in kwargs:
+            kwargs['os-disk-config:disk_config'] = kwargs['disk_config']
+            del kwargs['disk_config']
+        return self.action(server_id, 'resize', None, **kwargs)
+
+    def confirm_resize(self, server_id, **kwargs):
+        """Confirms the flavor change for a server."""
+        return self.action(server_id, 'confirm_resize', None, **kwargs)
+
+    def revert_resize(self, server_id, **kwargs):
+        """Reverts a server back to its original flavor."""
+        return self.action(server_id, 'revert_resize', None, **kwargs)
+
+    def create_image(self, server_id, name, meta=None):
+        """Creates an image of the original server."""
+
+        post_body = {
+            'create_image': {
+                'name': name,
+            }
+        }
+
+        if meta is not None:
+            post_body['create_image']['metadata'] = meta
+
+        post_body = json.dumps(post_body)
+        resp, body = self.post('servers/%s/action' % str(server_id),
+                               post_body, self.headers)
+        return resp, body
+
+    def list_server_metadata(self, server_id):
+        resp, body = self.get("servers/%s/metadata" % str(server_id))
+        body = json.loads(body)
+        return resp, body['metadata']
+
+    def set_server_metadata(self, server_id, meta, no_metadata_field=False):
+        if no_metadata_field:
+            post_body = ""
+        else:
+            post_body = json.dumps({'metadata': meta})
+        resp, body = self.put('servers/%s/metadata' % str(server_id),
+                              post_body, self.headers)
+        body = json.loads(body)
+        return resp, body['metadata']
+
+    def update_server_metadata(self, server_id, meta):
+        post_body = json.dumps({'metadata': meta})
+        resp, body = self.post('servers/%s/metadata' % str(server_id),
+                               post_body, self.headers)
+        body = json.loads(body)
+        return resp, body['metadata']
+
+    def get_server_metadata_item(self, server_id, key):
+        resp, body = self.get("servers/%s/metadata/%s" % (str(server_id), key))
+        body = json.loads(body)
+        return resp, body['metadata']
+
+    def set_server_metadata_item(self, server_id, key, meta):
+        post_body = json.dumps({'metadata': meta})
+        resp, body = self.put('servers/%s/metadata/%s' % (str(server_id), key),
+                              post_body, self.headers)
+        body = json.loads(body)
+        return resp, body['metadata']
+
+    def delete_server_metadata_item(self, server_id, key):
+        resp, body = self.delete("servers/%s/metadata/%s" %
+                                 (str(server_id), key))
+        return resp, body
+
+    def stop(self, server_id, **kwargs):
+        return self.action(server_id, 'stop', None, **kwargs)
+
+    def start(self, server_id, **kwargs):
+        return self.action(server_id, 'start', None, **kwargs)
+
+    def attach_volume(self, server_id, volume_id, device='/dev/vdz'):
+        """Attaches a volume to a server instance."""
+        return self.action(server_id, 'attach', None, volume_id=volume_id,
+                           device=device)
+
+    def detach_volume(self, server_id, volume_id):
+        """Detaches a volume from a server instance."""
+        return self.action(server_id, 'detach', None, volume_id=volume_id)
+
+    def live_migrate_server(self, server_id, dest_host, use_block_migration):
+        """This should be called with administrator privileges ."""
+
+        migrate_params = {
+            "disk_over_commit": False,
+            "block_migration": use_block_migration,
+            "host": dest_host
+        }
+
+        req_body = json.dumps({'migrate_live': migrate_params})
+
+        resp, body = self.post("servers/%s/action" % str(server_id),
+                               req_body, self.headers)
+        return resp, body
+
+    def migrate_server(self, server_id, **kwargs):
+        """Migrates a server to a new host."""
+        return self.action(server_id, 'migrate', None, **kwargs)
+
+    def lock_server(self, server_id, **kwargs):
+        """Locks the given server."""
+        return self.action(server_id, 'lock', None, **kwargs)
+
+    def unlock_server(self, server_id, **kwargs):
+        """UNlocks the given server."""
+        return self.action(server_id, 'unlock', None, **kwargs)
+
+    def suspend_server(self, server_id, **kwargs):
+        """Suspends the provded server."""
+        return self.action(server_id, 'suspend', None, **kwargs)
+
+    def resume_server(self, server_id, **kwargs):
+        """Un-suspends the provded server."""
+        return self.action(server_id, 'resume', None, **kwargs)
+
+    def pause_server(self, server_id, **kwargs):
+        """Pauses the provded server."""
+        return self.action(server_id, 'pause', None, **kwargs)
+
+    def unpause_server(self, server_id, **kwargs):
+        """Un-pauses the provded server."""
+        return self.action(server_id, 'unpause', None, **kwargs)
+
+    def reset_state(self, server_id, state='error'):
+        """Resets the state of a server to active/error."""
+        return self.action(server_id, 'reset_state', None, state=state)
+
+    def get_console_output(self, server_id, length):
+        return self.action(server_id, 'get_console_output', 'output',
+                           length=length)
+
+    def rescue_server(self, server_id, admin_password=None):
+        """Rescue the provided server."""
+        return self.action(server_id, 'rescue', None,
+                           admin_password=admin_password)
+
+    def unrescue_server(self, server_id):
+        """Unrescue the provided server."""
+        return self.action(server_id, 'unrescue', None)
+
+    def get_server_diagnostics(self, server_id):
+        """Get the usage data for a server."""
+        resp, body = self.get("servers/%s/os-server-diagnostics" %
+                              str(server_id))
+        return resp, json.loads(body)
+
+    def list_instance_actions(self, server_id):
+        """List the provided server action."""
+        resp, body = self.get("servers/%s/os-instance-actions" %
+                              str(server_id))
+        body = json.loads(body)
+        return resp, body['instance_actions']
+
+    def get_instance_action(self, server_id, request_id):
+        """Returns the action details of the provided server."""
+        resp, body = self.get("servers/%s/os-instance-actions/%s" %
+                              (str(server_id), str(request_id)))
+        body = json.loads(body)
+        return resp, body['instance_action']
diff --git a/tempest/services/compute/v3/json/services_client.py b/tempest/services/compute/v3/json/services_client.py
new file mode 100644
index 0000000..41564e5
--- /dev/null
+++ b/tempest/services/compute/v3/json/services_client.py
@@ -0,0 +1,71 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 NEC Corporation
+# Copyright 2013 IBM Corp.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import json
+import urllib
+
+from tempest.common.rest_client import RestClient
+
+
+class ServicesV3ClientJSON(RestClient):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(ServicesV3ClientJSON, self).__init__(config, username, password,
+                                                   auth_url, tenant_name)
+        self.service = self.config.compute.catalog_v3_type
+
+    def list_services(self, params=None):
+        url = 'os-services'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body['services']
+
+    def enable_service(self, host_name, binary):
+        """
+        Enable service on a host
+        host_name: Name of host
+        binary: Service binary
+        """
+        post_body = json.dumps({
+            'service': {
+                'binary': binary,
+                'host': host_name
+            }
+        })
+        resp, body = self.put('os-services/enable', post_body, self.headers)
+        body = json.loads(body)
+        return resp, body['service']
+
+    def disable_service(self, host_name, binary):
+        """
+        Disable service on a host
+        host_name: Name of host
+        binary: Service binary
+        """
+        post_body = json.dumps({
+            'service': {
+                'binary': binary,
+                'host': host_name
+            }
+        })
+        resp, body = self.put('os-services/disable', post_body, self.headers)
+        body = json.loads(body)
+        return resp, body['service']
diff --git a/tempest/services/compute/v3/json/tenant_usages_client.py b/tempest/services/compute/v3/json/tenant_usages_client.py
new file mode 100644
index 0000000..298f363
--- /dev/null
+++ b/tempest/services/compute/v3/json/tenant_usages_client.py
@@ -0,0 +1,47 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 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 json
+import urllib
+
+from tempest.common.rest_client import RestClient
+
+
+class TenantUsagesV3ClientJSON(RestClient):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(TenantUsagesV3ClientJSON, self).__init__(
+            config, username, password, auth_url, tenant_name)
+        self.service = self.config.compute.catalog_v3_type
+
+    def list_tenant_usages(self, params=None):
+        url = 'os-simple-tenant-usage'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body['tenant_usages'][0]
+
+    def get_tenant_usage(self, tenant_id, params=None):
+        url = 'os-simple-tenant-usage/%s' % tenant_id
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body['tenant_usage']
diff --git a/tempest/services/compute/v3/xml/__init__.py b/tempest/services/compute/v3/xml/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/services/compute/v3/xml/__init__.py
diff --git a/tempest/services/compute/v3/xml/availability_zone_client.py b/tempest/services/compute/v3/xml/availability_zone_client.py
new file mode 100644
index 0000000..35fb2b1
--- /dev/null
+++ b/tempest/services/compute/v3/xml/availability_zone_client.py
@@ -0,0 +1,43 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 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.
+
+from lxml import etree
+
+from tempest.common.rest_client import RestClientXML
+from tempest.services.compute.xml.common import xml_to_json
+
+
+class AvailabilityZoneV3ClientXML(RestClientXML):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(AvailabilityZoneV3ClientXML, self).__init__(config, username,
+                                                          password, auth_url,
+                                                          tenant_name)
+        self.service = self.config.compute.catalog_v3_type
+
+    def _parse_array(self, node):
+        return [xml_to_json(x) for x in node]
+
+    def get_availability_zone_list(self):
+        resp, body = self.get('os-availability-zone', self.headers)
+        availability_zone = self._parse_array(etree.fromstring(body))
+        return resp, availability_zone
+
+    def get_availability_zone_list_detail(self):
+        resp, body = self.get('os-availability-zone/detail', self.headers)
+        availability_zone = self._parse_array(etree.fromstring(body))
+        return resp, availability_zone
diff --git a/tempest/services/compute/v3/xml/extensions_client.py b/tempest/services/compute/v3/xml/extensions_client.py
new file mode 100644
index 0000000..e03251c
--- /dev/null
+++ b/tempest/services/compute/v3/xml/extensions_client.py
@@ -0,0 +1,45 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from lxml import etree
+from tempest.common.rest_client import RestClientXML
+from tempest.services.compute.xml.common import xml_to_json
+
+
+class ExtensionsV3ClientXML(RestClientXML):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(ExtensionsV3ClientXML, self).__init__(config, username, password,
+                                                    auth_url, tenant_name)
+        self.service = self.config.compute.catalog_v3_type
+
+    def _parse_array(self, node):
+        array = []
+        for child in node:
+            array.append(xml_to_json(child))
+        return array
+
+    def list_extensions(self):
+        url = 'extensions'
+        resp, body = self.get(url, self.headers)
+        body = self._parse_array(etree.fromstring(body))
+        return resp, {'extensions': body}
+
+    def is_enabled(self, extension):
+        _, extensions = self.list_extensions()
+        exts = extensions['extensions']
+        return any([e for e in exts if e['name'] == extension])
diff --git a/tempest/services/compute/v3/xml/flavors_client.py b/tempest/services/compute/v3/xml/flavors_client.py
new file mode 100644
index 0000000..a1c74d9
--- /dev/null
+++ b/tempest/services/compute/v3/xml/flavors_client.py
@@ -0,0 +1,220 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import urllib
+
+from lxml import etree
+
+from tempest.common.rest_client import RestClientXML
+from tempest.services.compute.xml.common import Document
+from tempest.services.compute.xml.common import Element
+from tempest.services.compute.xml.common import Text
+from tempest.services.compute.xml.common import xml_to_json
+from tempest.services.compute.xml.common import XMLNS_11
+
+
+XMLNS_OS_FLV_EXT_DATA = \
+    "http://docs.openstack.org/compute/ext/flavor_extra_data/api/v1.1"
+XMLNS_OS_FLV_ACCESS = \
+    "http://docs.openstack.org/compute/ext/flavor_access/api/v2"
+
+
+class FlavorsClientXML(RestClientXML):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(FlavorsClientXML, self).__init__(config, username, password,
+                                               auth_url, tenant_name)
+        self.service = self.config.compute.catalog_type
+
+    def _format_flavor(self, f):
+        flavor = {'links': []}
+        for k, v in f.items():
+            if k == 'id':
+                flavor['id'] = v
+                continue
+
+            if k == 'link':
+                flavor['links'].append(v)
+                continue
+
+            if k == '{%s}ephemeral' % XMLNS_OS_FLV_EXT_DATA:
+                k = 'OS-FLV-EXT-DATA:ephemeral'
+
+            if k == '{%s}is_public' % XMLNS_OS_FLV_ACCESS:
+                k = 'os-flavor-access:is_public'
+                v = True if v == 'True' else False
+
+            if k == 'extra_specs':
+                k = 'OS-FLV-WITH-EXT-SPECS:extra_specs'
+                flavor[k] = dict(v)
+                continue
+
+            try:
+                v = int(v)
+            except ValueError:
+                try:
+                    v = float(v)
+                except ValueError:
+                    pass
+
+            flavor[k] = v
+
+        return flavor
+
+    def _parse_array(self, node):
+        return [self._format_flavor(xml_to_json(x)) for x in node]
+
+    def _list_flavors(self, url, params):
+        if params:
+            url += "?%s" % urllib.urlencode(params)
+
+        resp, body = self.get(url, self.headers)
+        flavors = self._parse_array(etree.fromstring(body))
+        return resp, flavors
+
+    def list_flavors(self, params=None):
+        url = 'flavors'
+        return self._list_flavors(url, params)
+
+    def list_flavors_with_detail(self, params=None):
+        url = 'flavors/detail'
+        return self._list_flavors(url, params)
+
+    def get_flavor_details(self, flavor_id):
+        resp, body = self.get("flavors/%s" % str(flavor_id), self.headers)
+        body = xml_to_json(etree.fromstring(body))
+        flavor = self._format_flavor(body)
+        return resp, flavor
+
+    def create_flavor(self, name, ram, vcpus, disk, flavor_id, **kwargs):
+        """Creates a new flavor or instance type."""
+        flavor = Element("flavor",
+                         xmlns=XMLNS_11,
+                         ram=ram,
+                         vcpus=vcpus,
+                         disk=disk,
+                         id=flavor_id,
+                         name=name)
+        if kwargs.get('rxtx'):
+            flavor.add_attr('rxtx_factor', kwargs.get('rxtx'))
+        if kwargs.get('swap'):
+            flavor.add_attr('swap', kwargs.get('swap'))
+        if kwargs.get('ephemeral'):
+            flavor.add_attr('OS-FLV-EXT-DATA:ephemeral',
+                            kwargs.get('ephemeral'))
+        if kwargs.get('is_public'):
+            flavor.add_attr('os-flavor-access:is_public',
+                            kwargs.get('is_public'))
+        flavor.add_attr('xmlns:OS-FLV-EXT-DATA', XMLNS_OS_FLV_EXT_DATA)
+        flavor.add_attr('xmlns:os-flavor-access', XMLNS_OS_FLV_ACCESS)
+        resp, body = self.post('flavors', str(Document(flavor)), self.headers)
+        body = xml_to_json(etree.fromstring(body))
+        flavor = self._format_flavor(body)
+        return resp, flavor
+
+    def delete_flavor(self, flavor_id):
+        """Deletes the given flavor."""
+        return self.delete("flavors/%s" % str(flavor_id), self.headers)
+
+    def is_resource_deleted(self, id):
+        # Did not use get_flavor_details(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
+        resp, flavors = self.list_flavors_with_detail()
+        for flavor in flavors:
+            if flavor['id'] == id:
+                return False
+        return True
+
+    def set_flavor_extra_spec(self, flavor_id, specs):
+        """Sets extra Specs to the mentioned flavor."""
+        extra_specs = Element("extra_specs")
+        for key in specs.keys():
+            extra_specs.add_attr(key, specs[key])
+        resp, body = self.post('flavors/%s/os-extra_specs' % flavor_id,
+                               str(Document(extra_specs)), self.headers)
+        body = xml_to_json(etree.fromstring(body))
+        return resp, body
+
+    def get_flavor_extra_spec(self, flavor_id):
+        """Gets extra Specs of the mentioned flavor."""
+        resp, body = self.get('flavors/%s/os-extra_specs' % flavor_id,
+                              self.headers)
+        body = xml_to_json(etree.fromstring(body))
+        return resp, body
+
+    def get_flavor_extra_spec_with_key(self, flavor_id, key):
+        """Gets extra Specs key-value of the mentioned flavor and key."""
+        resp, xml_body = self.get('flavors/%s/os-extra_specs/%s' %
+                                  (str(flavor_id), key), self.headers)
+        body = {}
+        element = etree.fromstring(xml_body)
+        key = element.get('key')
+        body[key] = xml_to_json(element)
+        return resp, body
+
+    def update_flavor_extra_spec(self, flavor_id, key, **kwargs):
+        """Update extra Specs details of the mentioned flavor and key."""
+        doc = Document()
+        for (k, v) in kwargs.items():
+            element = Element(k)
+            doc.append(element)
+            value = Text(v)
+            element.append(value)
+
+        resp, body = self.put('flavors/%s/os-extra_specs/%s' %
+                              (flavor_id, key),
+                              str(doc), self.headers)
+        body = xml_to_json(etree.fromstring(body))
+        return resp, {key: body}
+
+    def unset_flavor_extra_spec(self, flavor_id, key):
+        """Unsets an extra spec based on the mentioned flavor and key."""
+        return self.delete('flavors/%s/os-extra_specs/%s' % (str(flavor_id),
+                           key))
+
+    def _parse_array_access(self, node):
+        return [xml_to_json(x) for x in node]
+
+    def list_flavor_access(self, flavor_id):
+        """Gets flavor access information given the flavor id."""
+        resp, body = self.get('flavors/%s/os-flavor-access' % str(flavor_id),
+                              self.headers)
+        body = self._parse_array(etree.fromstring(body))
+        return resp, body
+
+    def add_flavor_access(self, flavor_id, tenant_id):
+        """Add flavor access for the specified tenant."""
+        doc = Document()
+        server = Element("addTenantAccess")
+        doc.append(server)
+        server.add_attr("tenant", tenant_id)
+        resp, body = self.post('flavors/%s/action' % str(flavor_id),
+                               str(doc), self.headers)
+        body = self._parse_array_access(etree.fromstring(body))
+        return resp, body
+
+    def remove_flavor_access(self, flavor_id, tenant_id):
+        """Remove flavor access from the specified tenant."""
+        doc = Document()
+        server = Element("removeTenantAccess")
+        doc.append(server)
+        server.add_attr("tenant", tenant_id)
+        resp, body = self.post('flavors/%s/action' % str(flavor_id),
+                               str(doc), self.headers)
+        body = self._parse_array_access(etree.fromstring(body))
+        return resp, body
diff --git a/tempest/services/compute/v3/xml/hypervisor_client.py b/tempest/services/compute/v3/xml/hypervisor_client.py
new file mode 100644
index 0000000..ce0207d
--- /dev/null
+++ b/tempest/services/compute/v3/xml/hypervisor_client.py
@@ -0,0 +1,79 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM 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.
+
+from lxml import etree
+
+from tempest.common.rest_client import RestClientXML
+from tempest.services.compute.xml.common import xml_to_json
+
+
+class HypervisorV3ClientXML(RestClientXML):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(HypervisorV3ClientXML, self).__init__(config, username,
+                                                    password, auth_url,
+                                                    tenant_name)
+        self.service = self.config.compute.catalog_v3_type
+
+    def _parse_array(self, node):
+        return [xml_to_json(x) for x in node]
+
+    def get_hypervisor_list(self):
+        """List hypervisors information."""
+        resp, body = self.get('os-hypervisors', self.headers)
+        hypervisors = self._parse_array(etree.fromstring(body))
+        return resp, hypervisors
+
+    def get_hypervisor_list_details(self):
+        """Show detailed hypervisors information."""
+        resp, body = self.get('os-hypervisors/detail', self.headers)
+        hypervisors = self._parse_array(etree.fromstring(body))
+        return resp, hypervisors
+
+    def get_hypervisor_show_details(self, hyper_id):
+        """Display the details of the specified hypervisor."""
+        resp, body = self.get('os-hypervisors/%s' % hyper_id,
+                              self.headers)
+        hypervisor = xml_to_json(etree.fromstring(body))
+        return resp, hypervisor
+
+    def get_hypervisor_servers(self, hyper_name):
+        """List instances belonging to the specified hypervisor."""
+        resp, body = self.get('os-hypervisors/%s/servers' % hyper_name,
+                              self.headers)
+        hypervisors = self._parse_array(etree.fromstring(body))
+        return resp, hypervisors
+
+    def get_hypervisor_stats(self):
+        """Get hypervisor statistics over all compute nodes."""
+        resp, body = self.get('os-hypervisors/statistics', self.headers)
+        stats = xml_to_json(etree.fromstring(body))
+        return resp, stats
+
+    def get_hypervisor_uptime(self, hyper_id):
+        """Display the uptime of the specified hypervisor."""
+        resp, body = self.get('os-hypervisors/%s/uptime' % hyper_id,
+                              self.headers)
+        uptime = xml_to_json(etree.fromstring(body))
+        return resp, uptime
+
+    def search_hypervisor(self, hyper_name):
+        """Search specified hypervisor."""
+        resp, body = self.get('os-hypervisors/search?query=%s' % hyper_name,
+                              self.headers)
+        hypervisors = self._parse_array(etree.fromstring(body))
+        return resp, hypervisors
diff --git a/tempest/services/compute/v3/xml/interfaces_client.py b/tempest/services/compute/v3/xml/interfaces_client.py
new file mode 100644
index 0000000..870c130
--- /dev/null
+++ b/tempest/services/compute/v3/xml/interfaces_client.py
@@ -0,0 +1,108 @@
+# Copyright 2013 IBM Corp.
+# 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 time
+
+from lxml import etree
+
+from tempest.common.rest_client import RestClientXML
+from tempest import exceptions
+from tempest.services.compute.xml.common import Document
+from tempest.services.compute.xml.common import Element
+from tempest.services.compute.xml.common import Text
+from tempest.services.compute.xml.common import xml_to_json
+
+
+class InterfacesV3ClientXML(RestClientXML):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(InterfacesV3ClientXML, self).__init__(config, username, password,
+                                                    auth_url, tenant_name)
+        self.service = self.config.compute.catalog_v3_type
+
+    def _process_xml_interface(self, node):
+        iface = xml_to_json(node)
+        # NOTE(danms): if multiple addresses per interface is ever required,
+        # xml_to_json will need to be fixed or replaced in this case
+        iface['fixed_ips'] = [dict(iface['fixed_ips']['fixed_ip'].items())]
+        return iface
+
+    def list_interfaces(self, server):
+        resp, body = self.get('servers/%s/os-attach-interfaces' % server,
+                              self.headers)
+        node = etree.fromstring(body)
+        interfaces = [self._process_xml_interface(x)
+                      for x in node.getchildren()]
+        return resp, interfaces
+
+    def create_interface(self, server, port_id=None, network_id=None,
+                         fixed_ip=None):
+        doc = Document()
+        iface = Element('interface_attachment')
+        if port_id:
+            _port_id = Element('port_id')
+            _port_id.append(Text(port_id))
+            iface.append(_port_id)
+        if network_id:
+            _network_id = Element('net_id')
+            _network_id.append(Text(network_id))
+            iface.append(_network_id)
+        if fixed_ip:
+            _fixed_ips = Element('fixed_ips')
+            _fixed_ip = Element('fixed_ip')
+            _ip_address = Element('ip_address')
+            _ip_address.append(Text(fixed_ip))
+            _fixed_ip.append(_ip_address)
+            _fixed_ips.append(_fixed_ip)
+            iface.append(_fixed_ips)
+        doc.append(iface)
+        resp, body = self.post('servers/%s/os-attach-interfaces' % server,
+                               headers=self.headers,
+                               body=str(doc))
+        body = self._process_xml_interface(etree.fromstring(body))
+        return resp, body
+
+    def show_interface(self, server, port_id):
+        resp, body =\
+            self.get('servers/%s/os-attach-interfaces/%s' % (server, port_id),
+                     self.headers)
+        body = self._process_xml_interface(etree.fromstring(body))
+        return resp, body
+
+    def delete_interface(self, server, port_id):
+        resp, body =\
+            self.delete('servers/%s/os-attach-interfaces/%s' % (server,
+                                                                port_id))
+        return resp, body
+
+    def wait_for_interface_status(self, server, port_id, status):
+        """Waits for a interface to reach a given status."""
+        resp, body = self.show_interface(server, port_id)
+        interface_status = body['port_state']
+        start = int(time.time())
+
+        while(interface_status != status):
+            time.sleep(self.build_interval)
+            resp, body = self.show_interface(server, port_id)
+            interface_status = body['port_state']
+
+            timed_out = int(time.time()) - start >= self.build_timeout
+
+            if interface_status != status and timed_out:
+                message = ('Interface %s failed to reach %s status within '
+                           'the required time (%s s).' %
+                           (port_id, status, self.build_timeout))
+                raise exceptions.TimeoutException(message)
+        return resp, body
diff --git a/tempest/services/compute/v3/xml/limits_client.py b/tempest/services/compute/v3/xml/limits_client.py
new file mode 100644
index 0000000..704de52
--- /dev/null
+++ b/tempest/services/compute/v3/xml/limits_client.py
@@ -0,0 +1,55 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+# Copyright 2012 IBM Corp.
+# 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 lxml import objectify
+
+from tempest.common.rest_client import RestClientXML
+
+NS = "{http://docs.openstack.org/common/api/v1.0}"
+
+
+class LimitsClientXML(RestClientXML):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(LimitsClientXML, self).__init__(config, username, password,
+                                              auth_url, tenant_name)
+        self.service = self.config.compute.catalog_type
+
+    def get_absolute_limits(self):
+        resp, body = self.get("limits", self.headers)
+        body = objectify.fromstring(body)
+        lim = NS + 'absolute'
+        ret = {}
+
+        for el in body[lim].iterchildren():
+            attributes = el.attrib
+            ret[attributes['name']] = attributes['value']
+        return resp, ret
+
+    def get_specific_absolute_limit(self, absolute_limit):
+        resp, body = self.get("limits", self.headers)
+        body = objectify.fromstring(body)
+        lim = NS + 'absolute'
+        ret = {}
+
+        for el in body[lim].iterchildren():
+            attributes = el.attrib
+            ret[attributes['name']] = attributes['value']
+        if absolute_limit not in ret:
+            return None
+        else:
+            return ret[absolute_limit]
diff --git a/tempest/services/compute/v3/xml/quotas_client.py b/tempest/services/compute/v3/xml/quotas_client.py
new file mode 100644
index 0000000..ef5362c
--- /dev/null
+++ b/tempest/services/compute/v3/xml/quotas_client.py
@@ -0,0 +1,126 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+# Copyright 2012 NTT Data
+# 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 lxml import etree
+
+from tempest.common.rest_client import RestClientXML
+from tempest.services.compute.xml.common import Document
+from tempest.services.compute.xml.common import Element
+from tempest.services.compute.xml.common import xml_to_json
+from tempest.services.compute.xml.common import XMLNS_11
+
+
+class QuotasClientXML(RestClientXML):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(QuotasClientXML, self).__init__(config, username, password,
+                                              auth_url, tenant_name)
+        self.service = self.config.compute.catalog_type
+
+    def _format_quota(self, q):
+        quota = {}
+        for k, v in q.items():
+            try:
+                v = int(v)
+            except ValueError:
+                pass
+
+            quota[k] = v
+
+        return quota
+
+    def _parse_array(self, node):
+        return [self._format_quota(xml_to_json(x)) for x in node]
+
+    def get_quota_set(self, tenant_id):
+        """List the quota set for a tenant."""
+
+        url = 'os-quota-sets/%s' % str(tenant_id)
+        resp, body = self.get(url, self.headers)
+        body = xml_to_json(etree.fromstring(body))
+        body = self._format_quota(body)
+        return resp, body
+
+    def get_default_quota_set(self, tenant_id):
+        """List the default quota set for a tenant."""
+
+        url = 'os-quota-sets/%s/defaults' % str(tenant_id)
+        resp, body = self.get(url, self.headers)
+        body = xml_to_json(etree.fromstring(body))
+        body = self._format_quota(body)
+        return resp, body
+
+    def update_quota_set(self, tenant_id, force=None,
+                         injected_file_content_bytes=None,
+                         metadata_items=None, ram=None, floating_ips=None,
+                         fixed_ips=None, key_pairs=None, instances=None,
+                         security_group_rules=None, injected_files=None,
+                         cores=None, injected_file_path_bytes=None,
+                         security_groups=None):
+        """
+        Updates the tenant's quota limits for one or more resources
+        """
+        post_body = Element("quota_set",
+                            xmlns=XMLNS_11)
+
+        if force is not None:
+            post_body.add_attr('force', force)
+
+        if injected_file_content_bytes is not None:
+            post_body.add_attr('injected_file_content_bytes',
+                               injected_file_content_bytes)
+
+        if metadata_items is not None:
+            post_body.add_attr('metadata_items', metadata_items)
+
+        if ram is not None:
+            post_body.add_attr('ram', ram)
+
+        if floating_ips is not None:
+            post_body.add_attr('floating_ips', floating_ips)
+
+        if fixed_ips is not None:
+            post_body.add_attr('fixed_ips', fixed_ips)
+
+        if key_pairs is not None:
+            post_body.add_attr('key_pairs', key_pairs)
+
+        if instances is not None:
+            post_body.add_attr('instances', instances)
+
+        if security_group_rules is not None:
+            post_body.add_attr('security_group_rules', security_group_rules)
+
+        if injected_files is not None:
+            post_body.add_attr('injected_files', injected_files)
+
+        if cores is not None:
+            post_body.add_attr('cores', cores)
+
+        if injected_file_path_bytes is not None:
+            post_body.add_attr('injected_file_path_bytes',
+                               injected_file_path_bytes)
+
+        if security_groups is not None:
+            post_body.add_attr('security_groups', security_groups)
+
+        resp, body = self.put('os-quota-sets/%s' % str(tenant_id),
+                              str(Document(post_body)),
+                              self.headers)
+        body = xml_to_json(etree.fromstring(body))
+        body = self._format_quota(body)
+        return resp, body
diff --git a/tempest/services/compute/v3/xml/servers_client.py b/tempest/services/compute/v3/xml/servers_client.py
new file mode 100644
index 0000000..7af4161
--- /dev/null
+++ b/tempest/services/compute/v3/xml/servers_client.py
@@ -0,0 +1,623 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+# Copyright 2012 IBM Corp.
+# Copyright 2013 Hewlett-Packard Development Company, L.P.
+# 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 time
+import urllib
+
+from lxml import etree
+
+from tempest.common.rest_client import RestClientXML
+from tempest.common import waiters
+from tempest import exceptions
+from tempest.openstack.common import log as logging
+from tempest.services.compute.xml.common import Document
+from tempest.services.compute.xml.common import Element
+from tempest.services.compute.xml.common import Text
+from tempest.services.compute.xml.common import xml_to_json
+from tempest.services.compute.xml.common import XMLNS_V3
+
+
+LOG = logging.getLogger(__name__)
+
+
+def _translate_ip_xml_json(ip):
+    """
+    Convert the address version to int.
+    """
+    ip = dict(ip)
+    version = ip.get('version')
+    if version:
+        ip['version'] = int(version)
+    if ip.get('type'):
+        ip['type'] = ip.get('type')
+    if ip.get('mac_addr'):
+        ip['mac_addr'] = ip.get('mac_addr')
+    return ip
+
+
+def _translate_network_xml_to_json(network):
+    return [_translate_ip_xml_json(ip.attrib)
+            for ip in network.findall('{%s}ip' % XMLNS_V3)]
+
+
+def _translate_addresses_xml_to_json(xml_addresses):
+    return dict((network.attrib['id'], _translate_network_xml_to_json(network))
+                for network in xml_addresses.findall('{%s}network' % XMLNS_V3))
+
+
+def _translate_server_xml_to_json(xml_dom):
+    """Convert server XML to server JSON.
+
+    The addresses collection does not convert well by the dumb xml_to_json.
+    This method does some pre and post-processing to deal with that.
+
+    Translate XML addresses subtree to JSON.
+
+    Having xml_doc similar to
+    <api:server  xmlns:api="http://docs.openstack.org/compute/api/v3">
+        <api:addresses>
+            <api:network id="foo_novanetwork">
+                <api:ip version="4" addr="192.168.0.4"/>
+            </api:network>
+            <api:network id="bar_novanetwork">
+                <api:ip version="4" addr="10.1.0.4"/>
+                <api:ip version="6" addr="2001:0:0:1:2:3:4:5"/>
+            </api:network>
+        </api:addresses>
+    </api:server>
+
+    the _translate_server_xml_to_json(etree.fromstring(xml_doc)) should produce
+    something like
+
+    {'addresses': {'bar_novanetwork': [{'addr': '10.1.0.4', 'version': 4},
+                                       {'addr': '2001:0:0:1:2:3:4:5',
+                                        'version': 6}],
+                   'foo_novanetwork': [{'addr': '192.168.0.4', 'version': 4}]}}
+    """
+    nsmap = {'api': XMLNS_V3}
+    addresses = xml_dom.xpath('/api:server/api:addresses', namespaces=nsmap)
+    if addresses:
+        if len(addresses) > 1:
+            raise ValueError('Expected only single `addresses` element.')
+        json_addresses = _translate_addresses_xml_to_json(addresses[0])
+        json = xml_to_json(xml_dom)
+        json['addresses'] = json_addresses
+    else:
+        json = xml_to_json(xml_dom)
+    disk_config = ('{http://docs.openstack.org'
+                   '/compute/ext/disk_config/api/v3}disk_config')
+    terminated_at = ('{http://docs.openstack.org/'
+                     'compute/ext/os-server-usage/api/v3}terminated_at')
+    launched_at = ('{http://docs.openstack.org'
+                   '/compute/ext/os-server-usage/api/v3}launched_at')
+    power_state = ('{http://docs.openstack.org'
+                   '/compute/ext/extended_status/api/v3}power_state')
+    availability_zone = ('{http://docs.openstack.org'
+                         '/compute/ext/extended_availability_zone/api/v3}'
+                         'availability_zone')
+    vm_state = ('{http://docs.openstack.org'
+                '/compute/ext/extended_status/api/v3}vm_state')
+    task_state = ('{http://docs.openstack.org'
+                  '/compute/ext/extended_status/api/v3}task_state')
+    if disk_config in json:
+        json['os-disk-config:disk_config'] = json.pop(disk_config)
+    if terminated_at in json:
+        json['os-server-usage:terminated_at'] = json.pop(terminated_at)
+    if launched_at in json:
+        json['os-server-usage:launched_at'] = json.pop(launched_at)
+    if power_state in json:
+        json['os-extended-status:power_state'] = json.pop(power_state)
+    if availability_zone in json:
+        json['os-extended-availability-zone:availability_zone'] = json.pop(
+            availability_zone)
+    if vm_state in json:
+        json['os-extended-status:vm_state'] = json.pop(vm_state)
+    if task_state in json:
+        json['os-extended-status:task_state'] = json.pop(task_state)
+    return json
+
+
+class ServersV3ClientXML(RestClientXML):
+
+    def __init__(self, config, username, password, auth_url,
+                 tenant_name=None, auth_version='v2'):
+        super(ServersV3ClientXML, self).__init__(config, username, password,
+                                                 auth_url, tenant_name,
+                                                 auth_version=auth_version)
+        self.service = self.config.compute.catalog_v3_type
+
+    def _parse_key_value(self, node):
+        """Parse <foo key='key'>value</foo> data into {'key': 'value'}."""
+        data = {}
+        for node in node.getchildren():
+            data[node.get('key')] = node.text
+        return data
+
+    def _parse_links(self, node, json):
+        del json['link']
+        json['links'] = []
+        for linknode in node.findall('{http://www.w3.org/2005/Atom}link'):
+            json['links'].append(xml_to_json(linknode))
+
+    def _parse_server(self, body):
+        json = _translate_server_xml_to_json(body)
+
+        if 'metadata' in json and json['metadata']:
+            # NOTE(danms): if there was metadata, we need to re-parse
+            # that as a special type
+            metadata_tag = body.find('{%s}metadata' % XMLNS_V3)
+            json["metadata"] = self._parse_key_value(metadata_tag)
+        if 'link' in json:
+            self._parse_links(body, json)
+        for sub in ['image', 'flavor']:
+            if sub in json and 'link' in json[sub]:
+                self._parse_links(body, json[sub])
+        return json
+
+    def _parse_xml_virtual_interfaces(self, xml_dom):
+        """
+        Return server's virtual interfaces XML as JSON.
+        """
+        data = {"virtual_interfaces": []}
+        for iface in xml_dom.getchildren():
+            data["virtual_interfaces"].append(
+                {"id": iface.get("id"),
+                 "mac_address": iface.get("mac_address")})
+        return data
+
+    def get_server(self, server_id):
+        """Returns the details of an existing server."""
+        resp, body = self.get("servers/%s" % str(server_id), self.headers)
+        server = self._parse_server(etree.fromstring(body))
+        return resp, server
+
+    def lock_server(self, server_id, **kwargs):
+        """Locks the given server."""
+        return self.action(server_id, 'lock', None, **kwargs)
+
+    def unlock_server(self, server_id, **kwargs):
+        """Unlocks the given server."""
+        return self.action(server_id, 'unlock', None, **kwargs)
+
+    def suspend_server(self, server_id, **kwargs):
+        """Suspends the provided server."""
+        return self.action(server_id, 'suspend', None, **kwargs)
+
+    def resume_server(self, server_id, **kwargs):
+        """Un-suspends the provided server."""
+        return self.action(server_id, 'resume', None, **kwargs)
+
+    def pause_server(self, server_id, **kwargs):
+        """Pauses the provided server."""
+        return self.action(server_id, 'pause', None, **kwargs)
+
+    def unpause_server(self, server_id, **kwargs):
+        """Un-pauses the provided server."""
+        return self.action(server_id, 'unpause', None, **kwargs)
+
+    def reset_state(self, server_id, state='error'):
+        """Resets the state of a server to active/error."""
+        return self.action(server_id, 'reset_state', None, state=state)
+
+    def delete_server(self, server_id):
+        """Deletes the given server."""
+        return self.delete("servers/%s" % str(server_id))
+
+    def _parse_array(self, node):
+        array = []
+        for child in node.getchildren():
+            array.append(xml_to_json(child))
+        return array
+
+    def list_servers(self, params=None):
+        url = 'servers'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+
+        resp, body = self.get(url, self.headers)
+        servers = self._parse_array(etree.fromstring(body))
+        return resp, {"servers": servers}
+
+    def list_servers_with_detail(self, params=None):
+        url = 'servers/detail'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+
+        resp, body = self.get(url, self.headers)
+        servers = self._parse_array(etree.fromstring(body))
+        return resp, {"servers": servers}
+
+    def update_server(self, server_id, name=None, meta=None, access_ip_v4=None,
+                      access_ip_v6=None, disk_config=None):
+        doc = Document()
+        server = Element("server")
+        doc.append(server)
+
+        if name is not None:
+            server.add_attr("name", name)
+        if access_ip_v4 is not None:
+            server.add_attr("access_ip_v4", access_ip_v4)
+        if access_ip_v6 is not None:
+            server.add_attr("access_ip_v6", access_ip_v6)
+        if disk_config is not None:
+            server.add_attr('xmlns:os-disk-config', "http://docs.openstack.org"
+                            "/compute/ext/disk_config/api/v3")
+            server.add_attr("os-disk-config:disk_config", disk_config)
+        if meta is not None:
+            metadata = Element("metadata")
+            server.append(metadata)
+            for k, v in meta:
+                meta = Element("meta", key=k)
+                meta.append(Text(v))
+                metadata.append(meta)
+
+        resp, body = self.put('servers/%s' % str(server_id),
+                              str(doc), self.headers)
+        return resp, xml_to_json(etree.fromstring(body))
+
+    def create_server(self, name, image_ref, flavor_ref, **kwargs):
+        """
+        Creates an instance of a server.
+        name (Required): The name of the server.
+        image_ref (Required): Reference to the image used to build the server.
+        flavor_ref (Required): The flavor used to build the server.
+        Following optional keyword arguments are accepted:
+        admin_password: Sets the initial root password.
+        key_name: Key name of keypair that was created earlier.
+        meta: A dictionary of values to be used as metadata.
+        personality: A list of dictionaries for files to be injected into
+        the server.
+        security_groups: A list of security group dicts.
+        networks: A list of network dicts with UUID and fixed_ip.
+        user_data: User data for instance.
+        availability_zone: Availability zone in which to launch instance.
+        access_ip_v4: The IPv4 access address for the server.
+        access_ip_v6: The IPv6 access address for the server.
+        min_count: Count of minimum number of instances to launch.
+        max_count: Count of maximum number of instances to launch.
+        disk_config: Determines if user or admin controls disk configuration.
+        return_reservation_id: Enable/Disable the return of reservation id.
+        """
+        server = Element("server",
+                         imageRef=image_ref,
+                         xmlns=XMLNS_V3,
+                         flavor_ref=flavor_ref,
+                         image_ref=image_ref,
+                         name=name)
+        attrs = ["admin_password", "access_ip_v4", "access_ip_v6", "key_name",
+                 ("os-user-data:user_data",
+                  'user_data',
+                  'xmlns:os-user-data',
+                  "http://docs.openstack.org/compute/ext/userdata/api/v3"),
+                 ("os-availability-zone:availability_zone",
+                  'availability_zone',
+                  'xmlns:os-availability-zone',
+                  "http://docs.openstack.org/compute/ext/"
+                  "availabilityzone/api/v3"),
+                 ("os-multiple-create:min_count",
+                  'min_count',
+                  'xmlns:os-multiple-create',
+                  "http://docs.openstack.org/compute/ext/"
+                  "multiplecreate/api/v3"),
+                 ("os-multiple-create:max_count",
+                  'max_count',
+                  'xmlns:os-multiple-create',
+                  "http://docs.openstack.org/compute/ext/"
+                  "multiplecreate/api/v3"),
+                 ("os-multiple-create:return_reservation_id",
+                  "return_reservation_id",
+                  'xmlns:os-multiple-create',
+                  "http://docs.openstack.org/compute/ext/"
+                  "multiplecreate/api/v3"),
+                 ("os-disk-config:disk_config",
+                  "disk_config",
+                  "xmlns:os-disk-config",
+                  "http://docs.openstack.org/"
+                  "compute/ext/disk_config/api/v3")]
+
+        for attr in attrs:
+            if isinstance(attr, tuple):
+                post_param = attr[0]
+                key = attr[1]
+                value = kwargs.get(key)
+                if value is not None:
+                    server.add_attr(attr[2], attr[3])
+                    server.add_attr(post_param, value)
+            else:
+                post_param = attr
+                key = attr
+                value = kwargs.get(key)
+                if value is not None:
+                    server.add_attr(post_param, value)
+
+        if 'security_groups' in kwargs:
+            secgroups = Element("security_groups")
+            server.append(secgroups)
+            for secgroup in kwargs['security_groups']:
+                s = Element("security_group", name=secgroup['name'])
+                secgroups.append(s)
+
+        if 'networks' in kwargs:
+            networks = Element("networks")
+            server.append(networks)
+            for network in kwargs['networks']:
+                s = Element("network", uuid=network['uuid'],
+                            fixed_ip=network['fixed_ip'])
+                networks.append(s)
+
+        if 'meta' in kwargs:
+            metadata = Element("metadata")
+            server.append(metadata)
+            for k, v in kwargs['meta'].items():
+                meta = Element("meta", key=k)
+                meta.append(Text(v))
+                metadata.append(meta)
+
+        if 'personality' in kwargs:
+            personality = Element('personality')
+            server.append(personality)
+            for k in kwargs['personality']:
+                temp = Element('file', path=k['path'])
+                temp.append(Text(k['contents']))
+                personality.append(temp)
+
+        resp, body = self.post('servers', str(Document(server)), self.headers)
+        server = self._parse_server(etree.fromstring(body))
+        return resp, server
+
+    def wait_for_server_status(self, server_id, status, extra_timeout=0):
+        """Waits for a server to reach a given status."""
+        return waiters.wait_for_server_status(self, server_id, status,
+                                              extra_timeout=extra_timeout)
+
+    def wait_for_server_termination(self, server_id, ignore_error=False):
+        """Waits for server to reach termination."""
+        start_time = int(time.time())
+        while True:
+            try:
+                resp, body = self.get_server(server_id)
+            except exceptions.NotFound:
+                return
+
+            server_status = body['status']
+            if server_status == 'ERROR' and not ignore_error:
+                raise exceptions.BuildErrorException
+
+            if int(time.time()) - start_time >= self.build_timeout:
+                raise exceptions.TimeoutException
+
+            time.sleep(self.build_interval)
+
+    def _parse_network(self, node):
+        addrs = []
+        for child in node.getchildren():
+            addrs.append({'version': int(child.get('version')),
+                         'addr': child.get('addr')})
+        return {node.get('id'): addrs}
+
+    def list_addresses(self, server_id):
+        """Lists all addresses for a server."""
+        resp, body = self.get("servers/%s/ips" % str(server_id), self.headers)
+
+        networks = {}
+        xml_list = etree.fromstring(body)
+        for child in xml_list.getchildren():
+            network = self._parse_network(child)
+            networks.update(**network)
+
+        return resp, networks
+
+    def list_addresses_by_network(self, server_id, network_id):
+        """Lists all addresses of a specific network type for a server."""
+        resp, body = self.get("servers/%s/ips/%s" % (str(server_id),
+                                                     network_id),
+                              self.headers)
+        network = self._parse_network(etree.fromstring(body))
+
+        return resp, network
+
+    def action(self, server_id, action_name, response_key, **kwargs):
+        if 'xmlns' not in kwargs:
+            kwargs['xmlns'] = XMLNS_V3
+        doc = Document((Element(action_name, **kwargs)))
+        resp, body = self.post("servers/%s/action" % server_id,
+                               str(doc), self.headers)
+        if response_key is not None:
+            body = xml_to_json(etree.fromstring(body))
+        return resp, body
+
+    def change_password(self, server_id, password):
+        return self.action(server_id, "change_password", None,
+                           admin_password=password)
+
+    def reboot(self, server_id, reboot_type):
+        return self.action(server_id, "reboot", None, type=reboot_type)
+
+    def rebuild(self, server_id, image_ref, **kwargs):
+        kwargs['image_ref'] = image_ref
+        if 'disk_config' in kwargs:
+            kwargs['os-disk-config:disk_config'] = kwargs['disk_config']
+            del kwargs['disk_config']
+            kwargs['xmlns:os-disk-config'] = "http://docs.openstack.org/"\
+                                             "compute/ext/disk_config/api/v3"
+            kwargs['xmlns:atom'] = "http://www.w3.org/2005/Atom"
+        if 'xmlns' not in kwargs:
+            kwargs['xmlns'] = XMLNS_V3
+
+        attrs = kwargs.copy()
+        if 'metadata' in attrs:
+            del attrs['metadata']
+        rebuild = Element("rebuild",
+                          **attrs)
+
+        if 'metadata' in kwargs:
+            metadata = Element("metadata")
+            rebuild.append(metadata)
+            for k, v in kwargs['metadata'].items():
+                meta = Element("meta", key=k)
+                meta.append(Text(v))
+                metadata.append(meta)
+
+        resp, body = self.post('servers/%s/action' % server_id,
+                               str(Document(rebuild)), self.headers)
+        server = self._parse_server(etree.fromstring(body))
+        return resp, server
+
+    def resize(self, server_id, flavor_ref, **kwargs):
+        if 'disk_config' in kwargs:
+            kwargs['os-disk-config:disk_config'] = kwargs['disk_config']
+            del kwargs['disk_config']
+            kwargs['xmlns:os-disk-config'] = "http://docs.openstack.org/"\
+                                             "compute/ext/disk_config/api/v3"
+            kwargs['xmlns:atom'] = "http://www.w3.org/2005/Atom"
+        kwargs['flavor_ref'] = flavor_ref
+        return self.action(server_id, 'resize', None, **kwargs)
+
+    def confirm_resize(self, server_id, **kwargs):
+        return self.action(server_id, 'confirm_resize', None, **kwargs)
+
+    def revert_resize(self, server_id, **kwargs):
+        return self.action(server_id, 'revert_resize', None, **kwargs)
+
+    def stop(self, server_id, **kwargs):
+        return self.action(server_id, 'stop', None, **kwargs)
+
+    def start(self, server_id, **kwargs):
+        return self.action(server_id, 'start', None, **kwargs)
+
+    def create_image(self, server_id, name, meta=None):
+        """Creates an image of the original server."""
+        post_body = Element('create_image', name=name)
+
+        if meta:
+            metadata = Element('metadata')
+            post_body.append(metadata)
+            for k, v in meta.items():
+                data = Element('meta', key=k)
+                data.append(Text(v))
+                metadata.append(data)
+        resp, body = self.post('servers/%s/action' % str(server_id),
+                               str(Document(post_body)), self.headers)
+        return resp, body
+
+    def live_migrate_server(self, server_id, dest_host, use_block_migration):
+        """This should be called with administrator privileges ."""
+
+        req_body = Element("migrate_live",
+                           xmlns=XMLNS_V3,
+                           disk_over_commit=False,
+                           block_migration=use_block_migration,
+                           host=dest_host)
+
+        resp, body = self.post("servers/%s/action" % str(server_id),
+                               str(Document(req_body)), self.headers)
+        return resp, body
+
+    def list_server_metadata(self, server_id):
+        resp, body = self.get("servers/%s/metadata" % str(server_id),
+                              self.headers)
+        body = self._parse_key_value(etree.fromstring(body))
+        return resp, body
+
+    def set_server_metadata(self, server_id, meta, no_metadata_field=False):
+        doc = Document()
+        if not no_metadata_field:
+            metadata = Element("metadata")
+            doc.append(metadata)
+            for k, v in meta.items():
+                meta_element = Element("meta", key=k)
+                meta_element.append(Text(v))
+                metadata.append(meta_element)
+        resp, body = self.put('servers/%s/metadata' % str(server_id),
+                              str(doc), self.headers)
+        return resp, xml_to_json(etree.fromstring(body))
+
+    def update_server_metadata(self, server_id, meta):
+        doc = Document()
+        metadata = Element("metadata")
+        doc.append(metadata)
+        for k, v in meta.items():
+            meta_element = Element("meta", key=k)
+            meta_element.append(Text(v))
+            metadata.append(meta_element)
+        resp, body = self.post("/servers/%s/metadata" % str(server_id),
+                               str(doc), headers=self.headers)
+        body = xml_to_json(etree.fromstring(body))
+        return resp, body
+
+    def get_server_metadata_item(self, server_id, key):
+        resp, body = self.get("servers/%s/metadata/%s" % (str(server_id), key),
+                              headers=self.headers)
+        return resp, dict([(etree.fromstring(body).attrib['key'],
+                            xml_to_json(etree.fromstring(body)))])
+
+    def set_server_metadata_item(self, server_id, key, meta):
+        doc = Document()
+        for k, v in meta.items():
+            meta_element = Element("meta", key=k)
+            meta_element.append(Text(v))
+            doc.append(meta_element)
+        resp, body = self.put('servers/%s/metadata/%s' % (str(server_id), key),
+                              str(doc), self.headers)
+        return resp, xml_to_json(etree.fromstring(body))
+
+    def delete_server_metadata_item(self, server_id, key):
+        resp, body = self.delete("servers/%s/metadata/%s" %
+                                 (str(server_id), key))
+        return resp, body
+
+    def get_console_output(self, server_id, length):
+        return self.action(server_id, 'get_console_output', 'output',
+                           length=length)
+
+    def rescue_server(self, server_id, admin_password=None):
+        """Rescue the provided server."""
+        return self.action(server_id, 'rescue', None,
+                           admin_password=admin_password)
+
+    def unrescue_server(self, server_id):
+        """Unrescue the provided server."""
+        return self.action(server_id, 'unrescue', None)
+
+    def attach_volume(self, server_id, volume_id, device='/dev/vdz'):
+        return self.action(server_id, "attach", None, volume_id=volume_id,
+                           device=device)
+
+    def detach_volume(self, server_id, volume_id):
+        return self.action(server_id, "detach", None, volume_id=volume_id)
+
+    def get_server_diagnostics(self, server_id):
+        """Get the usage data for a server."""
+        resp, body = self.get("servers/%s/os-server-diagnostics" % server_id,
+                              self.headers)
+        body = xml_to_json(etree.fromstring(body))
+        return resp, body
+
+    def list_instance_actions(self, server_id):
+        """List the provided server action."""
+        resp, body = self.get("servers/%s/os-instance-actions" % server_id,
+                              self.headers)
+        body = self._parse_array(etree.fromstring(body))
+        return resp, body
+
+    def get_instance_action(self, server_id, request_id):
+        """Returns the action details of the provided server."""
+        resp, body = self.get("servers/%s/os-instance-actions/%s" %
+                              (server_id, request_id), self.headers)
+        body = xml_to_json(etree.fromstring(body))
+        return resp, body
diff --git a/tempest/services/compute/v3/xml/services_client.py b/tempest/services/compute/v3/xml/services_client.py
new file mode 100644
index 0000000..855641b
--- /dev/null
+++ b/tempest/services/compute/v3/xml/services_client.py
@@ -0,0 +1,73 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 NEC Corporation
+# Copyright 2013 IBM Corp.
+# 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 urllib
+
+from lxml import etree
+from tempest.common.rest_client import RestClientXML
+from tempest.services.compute.xml.common import Document
+from tempest.services.compute.xml.common import Element
+from tempest.services.compute.xml.common import xml_to_json
+
+
+class ServicesV3ClientXML(RestClientXML):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(ServicesV3ClientXML, self).__init__(config, username, password,
+                                                  auth_url, tenant_name)
+        self.service = self.config.compute.catalog_v3_type
+
+    def list_services(self, params=None):
+        url = 'os-services'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+
+        resp, body = self.get(url, self.headers)
+        node = etree.fromstring(body)
+        body = [xml_to_json(x) for x in node.getchildren()]
+        return resp, body
+
+    def enable_service(self, host_name, binary):
+        """
+        Enable service on a host
+        host_name: Name of host
+        binary: Service binary
+        """
+        post_body = Element("service")
+        post_body.add_attr('binary', binary)
+        post_body.add_attr('host', host_name)
+
+        resp, body = self.put('os-services/enable', str(Document(post_body)),
+                              self.headers)
+        body = xml_to_json(etree.fromstring(body))
+        return resp, body
+
+    def disable_service(self, host_name, binary):
+        """
+        Disable service on a host
+        host_name: Name of host
+        binary: Service binary
+        """
+        post_body = Element("service")
+        post_body.add_attr('binary', binary)
+        post_body.add_attr('host', host_name)
+
+        resp, body = self.put('os-services/disable', str(Document(post_body)),
+                              self.headers)
+        body = xml_to_json(etree.fromstring(body))
+        return resp, body
diff --git a/tempest/services/compute/v3/xml/tenant_usages_client.py b/tempest/services/compute/v3/xml/tenant_usages_client.py
new file mode 100644
index 0000000..790bd5c
--- /dev/null
+++ b/tempest/services/compute/v3/xml/tenant_usages_client.py
@@ -0,0 +1,54 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 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 urllib
+
+from lxml import etree
+
+from tempest.common.rest_client import RestClientXML
+from tempest.services.compute.xml.common import xml_to_json
+
+
+class TenantUsagesV3ClientXML(RestClientXML):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(TenantUsagesV3ClientXML, self).__init__(config, username,
+                                                      password, auth_url,
+                                                      tenant_name)
+        self.service = self.config.compute.catalog_v3_type
+
+    def _parse_array(self, node):
+        json = xml_to_json(node)
+        return json
+
+    def list_tenant_usages(self, params=None):
+        url = 'os-simple-tenant-usage'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+
+        resp, body = self.get(url, self.headers)
+        tenant_usage = self._parse_array(etree.fromstring(body))
+        return resp, tenant_usage['tenant_usage']
+
+    def get_tenant_usage(self, tenant_id, params=None):
+        url = 'os-simple-tenant-usage/%s' % tenant_id
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+
+        resp, body = self.get(url, self.headers)
+        tenant_usage = self._parse_array(etree.fromstring(body))
+        return resp, tenant_usage
diff --git a/tempest/services/compute/xml/certificates_client.py b/tempest/services/compute/xml/certificates_client.py
new file mode 100644
index 0000000..7523352
--- /dev/null
+++ b/tempest/services/compute/xml/certificates_client.py
@@ -0,0 +1,40 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM Corp
+# 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 tempest.common.rest_client import RestClientXML
+
+
+class CertificatesClientXML(RestClientXML):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(CertificatesClientXML, self).__init__(config, username, password,
+                                                    auth_url, tenant_name)
+        self.service = self.config.compute.catalog_type
+
+    def get_certificate(self, id):
+        url = "os-certificates/%s" % (id)
+        resp, body = self.get(url, self.headers)
+        body = self._parse_resp(body)
+        return resp, body
+
+    def create_certificate(self):
+        """create certificates."""
+        url = "os-certificates"
+        resp, body = self.post(url, None, self.headers)
+        body = self._parse_resp(body)
+        return resp, body
diff --git a/tempest/services/compute/xml/common.py b/tempest/services/compute/xml/common.py
index ad79ed6..860dd5b 100644
--- a/tempest/services/compute/xml/common.py
+++ b/tempest/services/compute/xml/common.py
@@ -18,6 +18,7 @@
 import collections
 
 XMLNS_11 = "http://docs.openstack.org/compute/api/v1.1"
+XMLNS_V3 = "http://docs.openstack.org/compute/api/v1.1"
 
 
 # NOTE(danms): This is just a silly implementation to help make generating
diff --git a/tempest/services/compute/xml/fixed_ips_client.py b/tempest/services/compute/xml/fixed_ips_client.py
index ef023f0..bf2de38 100644
--- a/tempest/services/compute/xml/fixed_ips_client.py
+++ b/tempest/services/compute/xml/fixed_ips_client.py
@@ -15,13 +15,11 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from lxml import etree
 
 from tempest.common.rest_client import RestClientXML
 from tempest.services.compute.xml.common import Document
 from tempest.services.compute.xml.common import Element
 from tempest.services.compute.xml.common import Text
-from tempest.services.compute.xml.common import xml_to_json
 
 
 class FixedIPsClientXML(RestClientXML):
@@ -31,10 +29,6 @@
                                                 auth_url, tenant_name)
         self.service = self.config.compute.catalog_type
 
-    def _parse_fixed_ip_details(self, body):
-        body = xml_to_json(etree.fromstring(body))
-        return body
-
     def get_fixed_ip_details(self, fixed_ip):
         url = "os-fixed-ips/%s" % (fixed_ip)
         resp, body = self.get(url, self.headers)
diff --git a/tempest/services/compute/xml/flavors_client.py b/tempest/services/compute/xml/flavors_client.py
index 12e24d0..a1c74d9 100644
--- a/tempest/services/compute/xml/flavors_client.py
+++ b/tempest/services/compute/xml/flavors_client.py
@@ -43,6 +43,10 @@
     def _format_flavor(self, f):
         flavor = {'links': []}
         for k, v in f.items():
+            if k == 'id':
+                flavor['id'] = v
+                continue
+
             if k == 'link':
                 flavor['links'].append(v)
                 continue
@@ -154,14 +158,17 @@
         return resp, body
 
     def get_flavor_extra_spec_with_key(self, flavor_id, key):
-        """Gets a specified key detail for the mentioned flavor."""
-        resp, body = self.get('flavors/%s/os-extra_specs/%s' % (str(flavor_id),
-                              key), self.headers)
-        body = xml_to_json(etree.fromstring(body))
+        """Gets extra Specs key-value of the mentioned flavor and key."""
+        resp, xml_body = self.get('flavors/%s/os-extra_specs/%s' %
+                                  (str(flavor_id), key), self.headers)
+        body = {}
+        element = etree.fromstring(xml_body)
+        key = element.get('key')
+        body[key] = xml_to_json(element)
         return resp, body
 
     def update_flavor_extra_spec(self, flavor_id, key, **kwargs):
-        """Gets specified extra Specs details of the mentioned flavor."""
+        """Update extra Specs details of the mentioned flavor and key."""
         doc = Document()
         for (k, v) in kwargs.items():
             element = Element(k)
@@ -183,6 +190,13 @@
     def _parse_array_access(self, node):
         return [xml_to_json(x) for x in node]
 
+    def list_flavor_access(self, flavor_id):
+        """Gets flavor access information given the flavor id."""
+        resp, body = self.get('flavors/%s/os-flavor-access' % str(flavor_id),
+                              self.headers)
+        body = self._parse_array(etree.fromstring(body))
+        return resp, body
+
     def add_flavor_access(self, flavor_id, tenant_id):
         """Add flavor access for the specified tenant."""
         doc = Document()
diff --git a/tempest/services/compute/xml/instance_usage_audit_log_client.py b/tempest/services/compute/xml/instance_usage_audit_log_client.py
new file mode 100644
index 0000000..175997b
--- /dev/null
+++ b/tempest/services/compute/xml/instance_usage_audit_log_client.py
@@ -0,0 +1,41 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM 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.
+
+from lxml import etree
+
+from tempest.common.rest_client import RestClientXML
+from tempest.services.compute.xml.common import xml_to_json
+
+
+class InstanceUsagesAuditLogClientXML(RestClientXML):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(InstanceUsagesAuditLogClientXML, self).__init__(
+            config, username, password, auth_url, tenant_name)
+        self.service = self.config.compute.catalog_type
+
+    def list_instance_usage_audit_logs(self):
+        url = 'os-instance_usage_audit_log'
+        resp, body = self.get(url, self.headers)
+        instance_usage_audit_logs = xml_to_json(etree.fromstring(body))
+        return resp, instance_usage_audit_logs
+
+    def get_instance_usage_audit_log(self, time_before):
+        url = 'os-instance_usage_audit_log/%s' % time_before
+        resp, body = self.get(url, self.headers)
+        instance_usage_audit_log = xml_to_json(etree.fromstring(body))
+        return resp, instance_usage_audit_log
diff --git a/tempest/services/compute/xml/servers_client.py b/tempest/services/compute/xml/servers_client.py
index 43de4ef..68f6cf0 100644
--- a/tempest/services/compute/xml/servers_client.py
+++ b/tempest/services/compute/xml/servers_client.py
@@ -193,6 +193,10 @@
         server = self._parse_server(etree.fromstring(body))
         return resp, server
 
+    def migrate_server(self, server_id, **kwargs):
+        """Migrates the given server ."""
+        return self.action(server_id, 'migrate', None, **kwargs)
+
     def lock_server(self, server_id, **kwargs):
         """Locks the given server."""
         return self.action(server_id, 'lock', None, **kwargs)
@@ -217,6 +221,14 @@
         """Un-pauses the provided server."""
         return self.action(server_id, 'unpause', None, **kwargs)
 
+    def shelve_server(self, server_id, **kwargs):
+        """Shelves the provided server."""
+        return self.action(server_id, 'shelve', None, **kwargs)
+
+    def unshelve_server(self, server_id, **kwargs):
+        """Un-shelves the provided server."""
+        return self.action(server_id, 'unshelve', None, **kwargs)
+
     def reset_state(self, server_id, state='error'):
         """Resets the state of a server to active/error."""
         return self.action(server_id, 'os-resetState', None, state=state)
@@ -351,9 +363,12 @@
         server = self._parse_server(etree.fromstring(body))
         return resp, server
 
-    def wait_for_server_status(self, server_id, status):
+    def wait_for_server_status(self, server_id, status, extra_timeout=0,
+                               raise_on_error=True):
         """Waits for a server to reach a given status."""
-        return waiters.wait_for_server_status(self, server_id, status)
+        return waiters.wait_for_server_status(self, server_id, status,
+                                              extra_timeout=extra_timeout,
+                                              raise_on_error=raise_on_error)
 
     def wait_for_server_termination(self, server_id, ignore_error=False):
         """Waits for server to reach termination."""
@@ -411,10 +426,32 @@
             body = xml_to_json(etree.fromstring(body))
         return resp, body
 
+    def create_backup(self, server_id, backup_type, rotation, name):
+        """Backup a server instance."""
+        return self.action(server_id, "createBackup", None,
+                           backup_type=backup_type,
+                           rotation=rotation,
+                           name=name)
+
     def change_password(self, server_id, password):
         return self.action(server_id, "changePassword", None,
                            adminPass=password)
 
+    def get_password(self, server_id):
+        resp, body = self.get("servers/%s/os-server-password" %
+                              str(server_id), self.headers)
+        body = xml_to_json(etree.fromstring(body))
+        return resp, body
+
+    def delete_password(self, server_id):
+        """
+        Removes the encrypted server password from the metadata server
+        Note that this does not actually change the instance server
+        password.
+        """
+        return self.delete("servers/%s/os-server-password" %
+                           str(server_id))
+
     def reboot(self, server_id, reboot_type):
         return self.action(server_id, "reboot", None, type=reboot_type)
 
@@ -600,3 +637,11 @@
                               (server_id, request_id), self.headers)
         body = xml_to_json(etree.fromstring(body))
         return resp, body
+
+    def force_delete_server(self, server_id, **kwargs):
+        """Force delete a server."""
+        return self.action(server_id, 'forceDelete', None, **kwargs)
+
+    def restore_soft_deleted_server(self, server_id, **kwargs):
+        """Restore a soft-deleted server."""
+        return self.action(server_id, 'restore', None, **kwargs)
diff --git a/tempest/services/image/v1/json/image_client.py b/tempest/services/image/v1/json/image_client.py
index 41b9e81..9f5a405 100644
--- a/tempest/services/image/v1/json/image_client.py
+++ b/tempest/services/image/v1/json/image_client.py
@@ -175,7 +175,7 @@
 
     def delete_image(self, image_id):
         url = 'v1/images/%s' % image_id
-        self.delete(url)
+        return self.delete(url)
 
     def image_list(self, **kwargs):
         url = 'v1/images'
@@ -187,9 +187,15 @@
         body = json.loads(body)
         return resp, body['images']
 
-    def image_list_detail(self, **kwargs):
+    def image_list_detail(self, properties=dict(), **kwargs):
         url = 'v1/images/detail'
 
+        params = {}
+        for key, value in properties.items():
+            params['property-%s' % key] = value
+
+        kwargs.update(params)
+
         if len(kwargs) > 0:
             url += '?%s' % urllib.urlencode(kwargs)
 
@@ -270,7 +276,7 @@
 
             if value == 'killed':
                 raise exceptions.ImageKilledException(image_id=image_id,
-                                                      status=value)
+                                                      status=status)
             if dtime > self.build_timeout:
                 message = ('Time Limit Exceeded! (%ds)'
                            'while waiting for %s, '
diff --git a/tempest/services/image/v2/json/image_client.py b/tempest/services/image/v2/json/image_client.py
index 342a09c..3d37267 100644
--- a/tempest/services/image/v2/json/image_client.py
+++ b/tempest/services/image/v2/json/image_client.py
@@ -134,3 +134,27 @@
         url = 'v2/images/%s/tags/%s' % (image_id, tag)
         resp, _ = self.delete(url)
         return resp
+
+    def get_image_membership(self, image_id):
+        url = 'v2/images/%s/members' % image_id
+        resp, body = self.get(url)
+        body = json.loads(body)
+        self.expected_success(200, resp)
+        return resp, body
+
+    def add_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, self.headers)
+        body = json.loads(body)
+        self.expected_success(200, resp)
+        return resp, body
+
+    def update_member_status(self, image_id, member_id, status):
+        """Valid status are: ``pending``, ``accepted``,  ``rejected``."""
+        url = 'v2/images/%s/members/%s' % (image_id, member_id)
+        data = json.dumps({'status': status})
+        resp, body = self.put(url, data, self.headers)
+        body = json.loads(body)
+        self.expected_success(200, resp)
+        return resp, body
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index e7cd33f..c6bd423 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -673,3 +673,84 @@
         resp, body = self.get(uri, self.headers)
         body = json.loads(body)
         return resp, body
+
+    def list_agents(self):
+        uri = '%s/agents' % self.uri_prefix
+        resp, body = self.get(uri, self.headers)
+        body = json.loads(body)
+        return resp, body
+
+    def list_routers_on_l3_agent(self, agent_id):
+        uri = '%s/agents/%s/l3-routers' % (self.uri_prefix, agent_id)
+        resp, body = self.get(uri, self.headers)
+        body = json.loads(body)
+        return resp, body
+
+    def list_l3_agents_hosting_router(self, router_id):
+        uri = '%s/routers/%s/l3-agents' % (self.uri_prefix, router_id)
+        resp, body = self.get(uri, self.headers)
+        body = json.loads(body)
+        return resp, body
+
+    def list_service_providers(self):
+        uri = '%s/service-providers' % self.uri_prefix
+        resp, body = self.get(uri, self.headers)
+        body = json.loads(body)
+        return resp, body
+
+    def list_dhcp_agent_hosting_network(self, network_id):
+        uri = '%s/networks/%s/dhcp-agents' % (self.uri_prefix, network_id)
+        resp, body = self.get(uri, self.headers)
+        body = json.loads(body)
+        return resp, body
+
+    def list_networks_hosted_by_one_dhcp_agent(self, agent_id):
+        uri = '%s/agents/%s/dhcp-networks' % (self.uri_prefix, agent_id)
+        resp, body = self.get(uri, self.headers)
+        body = json.loads(body)
+        return resp, body
+
+    def remove_network_from_dhcp_agent(self, agent_id, network_id):
+        uri = '%s/agents/%s/dhcp-networks/%s' % (self.uri_prefix, agent_id,
+                                                 network_id)
+        resp, body = self.delete(uri, self.headers)
+        return resp, body
+
+    def list_ike_policies(self):
+        uri = '%s/vpn/ikepolicies' % (self.uri_prefix)
+        resp, body = self.get(uri, self.headers)
+        body = json.loads(body)
+        return resp, body
+
+    def create_ike_policy(self, name, **kwargs):
+        post_body = {
+            "ikepolicy": {
+                "name": name,
+            }
+        }
+        for key, val in kwargs.items():
+            post_body['ikepolicy'][key] = val
+        body = json.dumps(post_body)
+        uri = '%s/vpn/ikepolicies' % (self.uri_prefix)
+        resp, body = self.post(uri, headers=self.headers, body=body)
+        body = json.loads(body)
+        return resp, body
+
+    def show_ike_policy(self, uuid):
+        uri = '%s/vpn/ikepolicies/%s' % (self.uri_prefix, uuid)
+        resp, body = self.get(uri, self.headers)
+        body = json.loads(body)
+        return resp, body
+
+    def delete_ike_policy(self, uuid):
+        uri = '%s/vpn/ikepolicies/%s' % (self.uri_prefix, uuid)
+        resp, body = self.delete(uri, self.headers)
+        return resp, body
+
+    def update_ike_policy(self, uuid, **kwargs):
+        put_body = {'ikepolicy': kwargs}
+        body = json.dumps(put_body)
+        uri = '%s/vpn/ikepolicies/%s' % (self.uri_prefix, uuid)
+        resp, body = self.put(uri, body=body, headers=self.headers)
+        body = json.loads(body)
+        return resp, body
diff --git a/tempest/services/network/xml/network_client.py b/tempest/services/network/xml/network_client.py
index 04ad86f..e11d4c1 100755
--- a/tempest/services/network/xml/network_client.py
+++ b/tempest/services/network/xml/network_client.py
@@ -554,6 +554,52 @@
         ports = {"ports": ports}
         return resp, ports
 
+    def list_agents(self):
+        uri = '%s/agents' % self.uri_prefix
+        resp, body = self.get(uri, self.headers)
+        agents = self._parse_array(etree.fromstring(body))
+        agents = {'agents': agents}
+        return resp, agents
+
+    def list_routers_on_l3_agent(self, agent_id):
+        uri = '%s/agents/%s/l3-routers' % (self.uri_prefix, agent_id)
+        resp, body = self.get(uri, self.headers)
+        body = _root_tag_fetcher_and_xml_to_json_parse(body)
+        return resp, body
+
+    def list_l3_agents_hosting_router(self, router_id):
+        uri = '%s/routers/%s/l3-agents' % (self.uri_prefix, router_id)
+        resp, body = self.get(uri, self.headers)
+        body = _root_tag_fetcher_and_xml_to_json_parse(body)
+        return resp, body
+
+    def list_service_providers(self):
+        uri = '%s/service-providers' % self.uri_prefix
+        resp, body = self.get(uri, self.headers)
+        providers = self._parse_array(etree.fromstring(body))
+        body = {'service_providers': providers}
+        return resp, body
+
+    def list_dhcp_agent_hosting_network(self, network_id):
+        uri = '%s/networks/%s/dhcp-agents' % (self.uri_prefix, network_id)
+        resp, body = self.get(uri, self.headers)
+        agents = self._parse_array(etree.fromstring(body))
+        body = {'agents': agents}
+        return resp, body
+
+    def list_networks_hosted_by_one_dhcp_agent(self, agent_id):
+        uri = '%s/agents/%s/dhcp-networks' % (self.uri_prefix, agent_id)
+        resp, body = self.get(uri, self.headers)
+        networks = self._parse_array(etree.fromstring(body))
+        body = {'networks': networks}
+        return resp, body
+
+    def remove_network_from_dhcp_agent(self, agent_id, network_id):
+        uri = '%s/agents/%s/dhcp-networks/%s' % (self.uri_prefix, agent_id,
+                                                 network_id)
+        resp, body = self.delete(uri, self.headers)
+        return resp, body
+
 
 def _root_tag_fetcher_and_xml_to_json_parse(xml_returned_body):
     body = ET.fromstring(xml_returned_body)
diff --git a/tempest/services/object_storage/object_client.py b/tempest/services/object_storage/object_client.py
index 2fee042..9e0adff 100644
--- a/tempest/services/object_storage/object_client.py
+++ b/tempest/services/object_storage/object_client.py
@@ -15,6 +15,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import urllib
+
 from tempest.common import http
 from tempest.common.rest_client import RestClient
 from tempest import exceptions
@@ -27,13 +29,16 @@
 
         self.service = self.config.object_storage.catalog_type
 
-    def create_object(self, container, object_name, data):
+    def create_object(self, container, object_name, data, params=None):
         """Create storage object."""
 
         headers = dict(self.headers)
         if not data:
             headers['content-length'] = '0'
         url = "%s/%s" % (str(container), str(object_name))
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+
         resp, body = self.put(url, data, headers)
         return resp, body
 
@@ -41,9 +46,11 @@
         """Upload data to replace current storage object."""
         return self.create_object(container, object_name, data)
 
-    def delete_object(self, container, object_name):
+    def delete_object(self, container, object_name, params=None):
         """Delete storage object."""
         url = "%s/%s" % (str(container), str(object_name))
+        if params:
+            url += '?%s' % urllib.urlencode(params)
         resp, body = self.delete(url)
         return resp, body
 
diff --git a/tempest/services/volume/json/admin/volume_hosts_client.py b/tempest/services/volume/json/admin/volume_hosts_client.py
new file mode 100644
index 0000000..fc28ada
--- /dev/null
+++ b/tempest/services/volume/json/admin/volume_hosts_client.py
@@ -0,0 +1,46 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import json
+import urllib
+
+from tempest.common.rest_client import RestClient
+
+
+class VolumeHostsClientJSON(RestClient):
+    """
+    Client class to send CRUD Volume Hosts API requests to a Cinder endpoint
+    """
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(VolumeHostsClientJSON, self).__init__(config, username, password,
+                                                    auth_url, tenant_name)
+
+        self.service = self.config.volume.catalog_type
+        self.build_interval = self.config.volume.build_interval
+        self.build_timeout = self.config.volume.build_timeout
+
+    def list_hosts(self, params=None):
+        """Lists all hosts."""
+
+        url = 'os-hosts'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body['hosts']
diff --git a/tempest/services/volume/json/snapshots_client.py b/tempest/services/volume/json/snapshots_client.py
index 10ba3fd..5d980eb 100644
--- a/tempest/services/volume/json/snapshots_client.py
+++ b/tempest/services/volume/json/snapshots_client.py
@@ -131,3 +131,21 @@
         except exceptions.NotFound:
             return True
         return False
+
+    def reset_snapshot_status(self, snapshot_id, status):
+        """Reset the specified snapshot's status."""
+        post_body = json.dumps({'os-reset_status': {"status": status}})
+        resp, body = self.post('snapshots/%s/action' % snapshot_id, post_body,
+                               self.headers)
+        return resp, body
+
+    def update_snapshot_status(self, snapshot_id, status, progress):
+        """Update the specified snapshot's status."""
+        post_body = {
+            'status': status,
+            'progress': progress
+        }
+        post_body = json.dumps({'os-update_snapshot_status': post_body})
+        url = 'snapshots/%s/action' % str(snapshot_id)
+        resp, body = self.post(url, post_body, self.headers)
+        return resp, body
diff --git a/tempest/services/volume/json/volumes_client.py b/tempest/services/volume/json/volumes_client.py
index eb87cbe..967dc09 100644
--- a/tempest/services/volume/json/volumes_client.py
+++ b/tempest/services/volume/json/volumes_client.py
@@ -128,6 +128,22 @@
         resp, body = self.post(url, post_body, self.headers)
         return resp, body
 
+    def reserve_volume(self, volume_id):
+        """Reserves a volume."""
+        post_body = {}
+        post_body = json.dumps({'os-reserve': post_body})
+        url = 'volumes/%s/action' % (volume_id)
+        resp, body = self.post(url, post_body, self.headers)
+        return resp, body
+
+    def unreserve_volume(self, volume_id):
+        """Restore a reserved volume ."""
+        post_body = {}
+        post_body = json.dumps({'os-unreserve': post_body})
+        url = 'volumes/%s/action' % (volume_id)
+        resp, body = self.post(url, post_body, self.headers)
+        return resp, body
+
     def wait_for_volume_status(self, volume_id, status):
         """Waits for a Volume to reach a given status."""
         resp, body = self.get_volume(volume_id)
@@ -185,3 +201,65 @@
         resp, body = self.post('volumes/%s/action' % volume_id, post_body,
                                self.headers)
         return resp, body
+
+    def create_volume_transfer(self, vol_id, display_name=None):
+        """Create a volume transfer."""
+        post_body = {
+            'volume_id': vol_id
+        }
+        if display_name:
+            post_body['name'] = display_name
+        post_body = json.dumps({'transfer': post_body})
+        resp, body = self.post('os-volume-transfer',
+                               post_body,
+                               self.headers)
+        body = json.loads(body)
+        return resp, body['transfer']
+
+    def get_volume_transfer(self, transfer_id):
+        """Returns the details of a volume transfer."""
+        url = "os-volume-transfer/%s" % str(transfer_id)
+        resp, body = self.get(url, self.headers)
+        body = json.loads(body)
+        return resp, body['transfer']
+
+    def list_volume_transfers(self, params=None):
+        """List all the volume transfers created."""
+        url = 'os-volume-transfer'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body['transfers']
+
+    def delete_volume_transfer(self, transfer_id):
+        """Delete a volume transfer."""
+        return self.delete("os-volume-transfer/%s" % str(transfer_id))
+
+    def accept_volume_transfer(self, transfer_id, transfer_auth_key):
+        """Accept a volume transfer."""
+        post_body = {
+            'auth_key': transfer_auth_key,
+        }
+        url = 'os-volume-transfer/%s/accept' % transfer_id
+        post_body = json.dumps({'accept': post_body})
+        resp, body = self.post(url, post_body, self.headers)
+        body = json.loads(body)
+        return resp, body['transfer']
+
+    def update_volume_readonly(self, volume_id, readonly):
+        """Update the Specified Volume readonly."""
+        post_body = {
+            'readonly': readonly
+        }
+        post_body = json.dumps({'os-update_readonly_flag': post_body})
+        url = 'volumes/%s/action' % (volume_id)
+        resp, body = self.post(url, post_body, self.headers)
+        return resp, body
+
+    def force_delete_volume(self, volume_id):
+        """Force Delete Volume."""
+        post_body = json.dumps({'os-force_delete': {}})
+        resp, body = self.post('volumes/%s/action' % volume_id, post_body,
+                               self.headers)
+        return resp, body
diff --git a/tempest/services/volume/xml/admin/volume_hosts_client.py b/tempest/services/volume/xml/admin/volume_hosts_client.py
new file mode 100644
index 0000000..59ce933
--- /dev/null
+++ b/tempest/services/volume/xml/admin/volume_hosts_client.py
@@ -0,0 +1,72 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+# Copyright 2013 Openstack Foundation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import urllib
+
+from lxml import etree
+
+from tempest.common.rest_client import RestClientXML
+from tempest.services.compute.xml.common import xml_to_json
+
+
+class VolumeHostsClientXML(RestClientXML):
+    """
+    Client class to send CRUD Volume Hosts API requests to a Cinder endpoint
+    """
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(VolumeHostsClientXML, self).__init__(config, username, password,
+                                                   auth_url, tenant_name)
+        self.service = self.config.volume.catalog_type
+        self.build_interval = self.config.compute.build_interval
+        self.build_timeout = self.config.compute.build_timeout
+
+    def _parse_array(self, node):
+        """
+        This method is to parse the "list" response body
+        Eg:
+
+        <?xml version='1.0' encoding='UTF-8'?>
+        <hosts>
+        <host service-status="available" service="cinder-scheduler"/>
+        <host service-status="available" service="cinder-volume"/>
+        </hosts>
+
+        This method will append the details of specified tag,
+        here it is "host"
+        Return value would be list of hosts as below
+
+        [{'service-status': 'available', 'service': 'cinder-scheduler'},
+         {'service-status': 'available', 'service': 'cinder-volume'}]
+        """
+        array = []
+        for child in node.getchildren():
+            tag_list = child.tag.split('}', 1)
+            if tag_list[0] == "host":
+                array.append(xml_to_json(child))
+        return array
+
+    def list_hosts(self, params=None):
+        """List all the hosts."""
+        url = 'os-hosts'
+
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+
+        resp, body = self.get(url, self.headers)
+        body = self._parse_array(etree.fromstring(body))
+        return resp, body
diff --git a/tempest/services/volume/xml/snapshots_client.py b/tempest/services/volume/xml/snapshots_client.py
index b7ba56b..5d59b07 100644
--- a/tempest/services/volume/xml/snapshots_client.py
+++ b/tempest/services/volume/xml/snapshots_client.py
@@ -147,3 +147,26 @@
         except exceptions.NotFound:
             return True
         return False
+
+    def reset_snapshot_status(self, snapshot_id, status):
+        """Reset the specified snapshot's status."""
+        post_body = Element("os-reset_status",
+                            status=status
+                            )
+        url = 'snapshots/%s/action' % str(snapshot_id)
+        resp, body = self.post(url, str(Document(post_body)), self.headers)
+        if body:
+            body = xml_to_json(etree.fromstring(body))
+        return resp, body
+
+    def update_snapshot_status(self, snapshot_id, status, progress):
+        """Update the specified snapshot's status."""
+        post_body = Element("os-update_snapshot_status",
+                            status=status,
+                            progress=progress
+                            )
+        url = 'snapshots/%s/action' % str(snapshot_id)
+        resp, body = self.post(url, str(Document(post_body)), self.headers)
+        if body:
+            body = xml_to_json(etree.fromstring(body))
+        return resp, body
diff --git a/tempest/services/volume/xml/volumes_client.py b/tempest/services/volume/xml/volumes_client.py
index be292a2..1fc63e9 100644
--- a/tempest/services/volume/xml/volumes_client.py
+++ b/tempest/services/volume/xml/volumes_client.py
@@ -266,3 +266,93 @@
         if body:
             body = xml_to_json(etree.fromstring(body))
         return resp, body
+
+    def reserve_volume(self, volume_id):
+        """Reserves a volume."""
+        post_body = Element("os-reserve")
+        url = 'volumes/%s/action' % str(volume_id)
+        resp, body = self.post(url, str(Document(post_body)), self.headers)
+        if body:
+            body = xml_to_json(etree.fromstring(body))
+        return resp, body
+
+    def unreserve_volume(self, volume_id):
+        """Restore a reserved volume ."""
+        post_body = Element("os-unreserve")
+        url = 'volumes/%s/action' % str(volume_id)
+        resp, body = self.post(url, str(Document(post_body)), self.headers)
+        if body:
+            body = xml_to_json(etree.fromstring(body))
+        return resp, body
+
+    def create_volume_transfer(self, vol_id, display_name=None):
+        """Create a volume transfer."""
+        post_body = Element("transfer",
+                            volume_id=vol_id)
+        if display_name:
+            post_body.add_attr('name', display_name)
+        resp, body = self.post('os-volume-transfer',
+                               str(Document(post_body)),
+                               self.headers)
+        volume = xml_to_json(etree.fromstring(body))
+        return resp, volume
+
+    def get_volume_transfer(self, transfer_id):
+        """Returns the details of a volume transfer."""
+        url = "os-volume-transfer/%s" % str(transfer_id)
+        resp, body = self.get(url, self.headers)
+        volume = xml_to_json(etree.fromstring(body))
+        return resp, volume
+
+    def list_volume_transfers(self, params=None):
+        """List all the volume transfers created."""
+        url = 'os-volume-transfer'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+
+        resp, body = self.get(url, self.headers)
+        body = etree.fromstring(body)
+        volumes = []
+        if body is not None:
+            volumes += [self._parse_volume_transfer(vol) for vol in list(body)]
+        return resp, volumes
+
+    def _parse_volume_transfer(self, body):
+        vol = dict((attr, body.get(attr)) for attr in body.keys())
+        for child in body.getchildren():
+            tag = child.tag
+            if tag.startswith("{"):
+                tag = tag.split("}", 1)
+            vol[tag] = xml_to_json(child)
+        return vol
+
+    def delete_volume_transfer(self, transfer_id):
+        """Delete a volume transfer."""
+        return self.delete("os-volume-transfer/%s" % str(transfer_id))
+
+    def accept_volume_transfer(self, transfer_id, transfer_auth_key):
+        """Accept a volume transfer."""
+        post_body = Element("accept", auth_key=transfer_auth_key)
+        url = 'os-volume-transfer/%s/accept' % transfer_id
+        resp, body = self.post(url, str(Document(post_body)), self.headers)
+        volume = xml_to_json(etree.fromstring(body))
+        return resp, volume
+
+    def update_volume_readonly(self, volume_id, readonly):
+        """Update the Specified Volume readonly."""
+        post_body = Element("os-update_readonly_flag",
+                            readonly=readonly)
+        url = 'volumes/%s/action' % str(volume_id)
+        resp, body = self.post(url, str(Document(post_body)), self.headers)
+        if body:
+            body = xml_to_json(etree.fromstring(body))
+        return resp, body
+
+    def force_delete_volume(self, volume_id):
+        """Force Delete Volume."""
+        post_body = Element("os-force_delete")
+        url = 'volumes/%s/action' % str(volume_id)
+        resp, body = self.post(url, str(Document(post_body)), self.headers)
+        if body:
+            body = xml_to_json(etree.fromstring(body))
+        return resp, body
diff --git a/tempest/stress/README.rst b/tempest/stress/README.rst
index ae86f6e..20e58d4 100644
--- a/tempest/stress/README.rst
+++ b/tempest/stress/README.rst
@@ -26,6 +26,16 @@
 To activate logging on your console please make sure that you activate `use_stderr`
 in tempest.conf or use the default `logging.conf.sample` file.
 
+Running default stress test set
+-------------------------------
+
+The stress test framework can automatically discover test inside the tempest
+test suite. All test flag with the `@stresstest` decorator will be executed.
+In order to use this discovery you have to be in the tempest root directory
+and execute the following:
+
+	tempest/stress/run_stress.py -a -d 30
+
 Running the sample test
 -----------------------
 
diff --git a/tempest/stress/actions/server_create_destroy.py b/tempest/stress/actions/server_create_destroy.py
index 1a1e30b..84c7cf5 100644
--- a/tempest/stress/actions/server_create_destroy.py
+++ b/tempest/stress/actions/server_create_destroy.py
@@ -12,7 +12,7 @@
 #    See the License for the specific language governing permissions and
 #    limitations under the License.
 
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 import tempest.stress.stressaction as stressaction
 
 
@@ -23,7 +23,7 @@
         self.flavor = self.manager.config.compute.flavor_ref
 
     def run(self):
-        name = rand_name("instance")
+        name = data_utils.rand_name("instance")
         self.logger.info("creating %s" % name)
         resp, server = self.manager.servers_client.create_server(
             name, self.image, self.flavor)
diff --git a/tempest/stress/actions/ssh_floating.py b/tempest/stress/actions/ssh_floating.py
index 36ef023..74a9739 100644
--- a/tempest/stress/actions/ssh_floating.py
+++ b/tempest/stress/actions/ssh_floating.py
@@ -15,7 +15,7 @@
 import socket
 import subprocess
 
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 import tempest.stress.stressaction as stressaction
 import tempest.test
 
@@ -64,7 +64,7 @@
             raise RuntimeError("Cannot ping the machine.")
 
     def _create_vm(self):
-        self.name = name = rand_name("instance")
+        self.name = name = data_utils.rand_name("instance")
         servers_client = self.manager.servers_client
         self.logger.info("creating %s" % name)
         vm_args = self.vm_extra_args.copy()
@@ -87,8 +87,8 @@
 
     def _create_sec_group(self):
         sec_grp_cli = self.manager.security_groups_client
-        s_name = rand_name('sec_grp-')
-        s_description = rand_name('desc-')
+        s_name = data_utils.rand_name('sec_grp-')
+        s_description = data_utils.rand_name('desc-')
         _, _sec_grp = sec_grp_cli.create_security_group(s_name,
                                                         s_description)
         self.sec_grp = _sec_grp['id']
diff --git a/tempest/stress/actions/volume_attach_delete.py b/tempest/stress/actions/volume_attach_delete.py
index a7b872f..e6fcb81 100644
--- a/tempest/stress/actions/volume_attach_delete.py
+++ b/tempest/stress/actions/volume_attach_delete.py
@@ -11,7 +11,7 @@
 #    See the License for the specific language governing permissions and
 #    limitations under the License.
 
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 import tempest.stress.stressaction as stressaction
 
 
@@ -23,7 +23,7 @@
 
     def run(self):
         # Step 1: create volume
-        name = rand_name("volume")
+        name = data_utils.rand_name("volume")
         self.logger.info("creating volume: %s" % name)
         resp, volume = self.manager.volumes_client.create_volume(size=1,
                                                                  display_name=
@@ -34,7 +34,7 @@
         self.logger.info("created volume: %s" % volume['id'])
 
         # Step 2: create vm instance
-        vm_name = rand_name("instance")
+        vm_name = data_utils.rand_name("instance")
         self.logger.info("creating vm: %s" % vm_name)
         resp, server = self.manager.servers_client.create_server(
             vm_name, self.image, self.flavor)
diff --git a/tempest/stress/actions/volume_create_delete.py b/tempest/stress/actions/volume_create_delete.py
index e29d9c4..4e75be0 100644
--- a/tempest/stress/actions/volume_create_delete.py
+++ b/tempest/stress/actions/volume_create_delete.py
@@ -10,14 +10,14 @@
 #    See the License for the specific language governing permissions and
 #    limitations under the License.
 
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 import tempest.stress.stressaction as stressaction
 
 
 class VolumeCreateDeleteTest(stressaction.StressAction):
 
     def run(self):
-        name = rand_name("volume")
+        name = data_utils.rand_name("volume")
         self.logger.info("creating %s" % name)
         volumes_client = self.manager.volumes_client
         resp, volume = volumes_client.create_volume(size=1,
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index b5cab68..d37ab6d 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -19,25 +19,18 @@
 
 from tempest import clients
 from tempest.common import ssh
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.openstack.common import importutils
 from tempest.openstack.common import log as logging
 from tempest.stress import cleanup
 
-admin_manager = clients.AdminManager()
-
 LOG = logging.getLogger(__name__)
 processes = []
 
 
-def do_ssh(command, host):
-    username = admin_manager.config.stress.target_ssh_user
-    key_filename = admin_manager.config.stress.target_private_key_path
-    if not (username and key_filename):
-        LOG.error('username and key_filename should not be empty')
-        return None
-    ssh_client = ssh.Client(host, username, key_filename=key_filename)
+def do_ssh(command, host, ssh_user, ssh_key=None):
+    ssh_client = ssh.Client(host, ssh_user, key_filename=ssh_key)
     try:
         return ssh_client.exec_command(command)
     except exceptions.SSHExecCommandFailed:
@@ -46,14 +39,14 @@
         return None
 
 
-def _get_compute_nodes(controller):
+def _get_compute_nodes(controller, ssh_user, ssh_key=None):
     """
     Returns a list of active compute nodes. List is generated by running
     nova-manage on the controller.
     """
     nodes = []
     cmd = "nova-manage service list | grep ^nova-compute"
-    output = do_ssh(cmd, controller)
+    output = do_ssh(cmd, controller, ssh_user, ssh_key)
     if not output:
         return nodes
     # For example: nova-compute xg11eth0 nova enabled :-) 2011-10-31 18:57:46
@@ -65,14 +58,15 @@
     return nodes
 
 
-def _has_error_in_logs(logfiles, nodes, stop_on_error=False):
+def _has_error_in_logs(logfiles, nodes, ssh_user, ssh_key=None,
+                       stop_on_error=False):
     """
     Detect errors in the nova log files on the controller and compute nodes.
     """
     grep = 'egrep "ERROR|TRACE" %s' % logfiles
     ret = False
     for node in nodes:
-        errors = do_ssh(grep, node)
+        errors = do_ssh(grep, node, ssh_user, ssh_key)
         if len(errors) > 0:
             LOG.error('%s: %s' % (node, errors))
             ret = True
@@ -88,18 +82,17 @@
     terminate_all_processes()
 
 
-def terminate_all_processes():
+def terminate_all_processes(check_interval=20):
     """
     Goes through the process list and terminates all child processes.
     """
-    log_check_interval = int(admin_manager.config.stress.log_check_interval)
     for process in processes:
         if process['process'].is_alive():
             try:
                 process['process'].terminate()
             except Exception:
                 pass
-    time.sleep(log_check_interval)
+    time.sleep(check_interval)
     for process in processes:
         if process['process'].is_alive():
             try:
@@ -115,15 +108,19 @@
     """
     Workload driver. Executes an action function against a nova-cluster.
     """
+    admin_manager = clients.AdminManager()
+
+    ssh_user = admin_manager.config.stress.target_ssh_user
+    ssh_key = admin_manager.config.stress.target_private_key_path
     logfiles = admin_manager.config.stress.target_logfiles
     log_check_interval = int(admin_manager.config.stress.log_check_interval)
     default_thread_num = int(admin_manager.config.stress.
                              default_thread_number_per_action)
     if logfiles:
         controller = admin_manager.config.stress.target_controller
-        computes = _get_compute_nodes(controller)
+        computes = _get_compute_nodes(controller, ssh_user, ssh_key)
         for node in computes:
-            do_ssh("rm -f %s" % logfiles, node)
+            do_ssh("rm -f %s" % logfiles, node, ssh_user, ssh_key)
     for test in tests:
         if test.get('use_admin', False):
             manager = admin_manager
@@ -131,8 +128,8 @@
             manager = clients.Manager()
         for p_number in xrange(test.get('threads', default_thread_num)):
             if test.get('use_isolated_tenants', False):
-                username = rand_name("stress_user")
-                tenant_name = rand_name("stress_tenant")
+                username = data_utils.rand_name("stress_user")
+                tenant_name = data_utils.rand_name("stress_tenant")
                 password = "pass"
                 identity_client = admin_manager.identity_client
                 _, tenant = identity_client.create_tenant(name=tenant_name)
@@ -196,7 +193,8 @@
 
         if not logfiles:
             continue
-        if _has_error_in_logs(logfiles, computes, stop_on_error):
+        if _has_error_in_logs(logfiles, computes, ssh_user, ssh_key,
+                              stop_on_error):
             had_errors = True
             break
 
diff --git a/tempest/stress/run_stress.py b/tempest/stress/run_stress.py
index e5cc281..067b994 100755
--- a/tempest/stress/run_stress.py
+++ b/tempest/stress/run_stress.py
@@ -24,6 +24,7 @@
 from unittest import loader
 
 from tempest.openstack.common import log as logging
+from tempest.stress import driver
 
 LOG = logging.getLogger(__name__)
 
@@ -68,8 +69,6 @@
 
 
 def main(ns):
-    # NOTE(mkoderer): moved import to make "-h" possible without OpenStack
-    from tempest.stress import driver
     result = 0
     if not ns.all:
         tests = json.load(open(ns.tests, 'r'))
diff --git a/tempest/test.py b/tempest/test.py
index 6ae7925..ceb2c80 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -123,6 +123,42 @@
     return decorator
 
 
+def requires_ext(*args, **kwargs):
+    """A decorator to skip tests if an extension is not enabled
+
+    @param extension
+    @param service
+    """
+    def decorator(func):
+        @functools.wraps(func)
+        def wrapper(*func_args, **func_kwargs):
+            if not is_extension_enabled(kwargs['extension'],
+                                        kwargs['service']):
+                msg = "Skipped because %s extension: %s is not enabled" % (
+                    kwargs['service'], kwargs['extension'])
+                raise testtools.TestCase.skipException(msg)
+            return func(*func_args, **func_kwargs)
+        return wrapper
+    return decorator
+
+
+def is_extension_enabled(extension_name, service):
+    """A function that will check the list of enabled extensions from config
+
+    """
+    configs = config.TempestConfig()
+    config_dict = {
+        'compute': configs.compute_feature_enabled.api_extensions,
+        'compute_v3': configs.compute_feature_enabled.api_v3_extensions,
+        'volume': configs.volume_feature_enabled.api_extensions,
+        'network': configs.network_feature_enabled.api_extensions,
+    }
+    if config_dict[service][0] == 'all':
+        return True
+    if extension_name in config_dict[service]:
+        return True
+    return False
+
 # there is a mis-match between nose and testtools for older pythons.
 # testtools will set skipException to be either
 # unittest.case.SkipTest, unittest2.case.SkipTest or an internal skip
diff --git a/tempest/tests/base.py b/tempest/tests/base.py
index 12c1c25..ba83cf4 100644
--- a/tempest/tests/base.py
+++ b/tempest/tests/base.py
@@ -17,24 +17,9 @@
 import os
 
 import fixtures
-import mox
-import stubout
 import testtools
 
-
-class MoxStubout(fixtures.Fixture):
-    """Deal with code around mox and stubout as a fixture."""
-
-    def setUp(self):
-        super(MoxStubout, self).setUp()
-        # emulate some of the mox stuff, we can't use the metaclass
-        # because it screws with our generators
-        self.mox = mox.Mox()
-        self.stubs = stubout.StubOutForTesting()
-        self.addCleanup(self.stubs.UnsetAll)
-        self.addCleanup(self.stubs.SmartUnsetAll)
-        self.addCleanup(self.mox.UnsetStubs)
-        self.addCleanup(self.mox.VerifyAll)
+from tempest.openstack.common.fixture import moxstubout
 
 
 class TestCase(testtools.TestCase):
@@ -50,6 +35,6 @@
             stderr = self.useFixture(fixtures.StringStream('stderr')).stream
             self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
 
-        mox_fixture = self.useFixture(MoxStubout())
+        mox_fixture = self.useFixture(moxstubout.MoxStubout())
         self.mox = mox_fixture.mox
         self.stubs = mox_fixture.stubs
diff --git a/tempest/tests/stress/__init__.py b/tempest/tests/stress/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/tests/stress/__init__.py
diff --git a/tempest/tests/stress/test_stress.py b/tempest/tests/stress/test_stress.py
new file mode 100644
index 0000000..4d7de9d
--- /dev/null
+++ b/tempest/tests/stress/test_stress.py
@@ -0,0 +1,57 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 Deutsche Telekom AG
+# 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 shlex
+import subprocess
+
+import tempest.cli as cli
+from tempest.openstack.common import log as logging
+import tempest.test
+
+LOG = logging.getLogger(__name__)
+
+
+class StressFrameworkTest(tempest.test.BaseTestCase):
+    """Basic test for the stress test framework.
+    """
+
+    def _cmd(self, cmd, param):
+        """Executes specified command."""
+        cmd = ' '.join([cmd, param])
+        LOG.info("running: '%s'" % cmd)
+        cmd_str = cmd
+        cmd = shlex.split(cmd)
+        result = ''
+        result_err = ''
+        try:
+            stdout = subprocess.PIPE
+            stderr = subprocess.PIPE
+            proc = subprocess.Popen(
+                cmd, stdout=stdout, stderr=stderr)
+            result, result_err = proc.communicate()
+            if proc.returncode != 0:
+                LOG.debug('error of %s:\n%s' % (cmd_str, result_err))
+                raise cli.CommandFailed(proc.returncode,
+                                        cmd,
+                                        result)
+        finally:
+            LOG.debug('output of %s:\n%s' % (cmd_str, result))
+        return proc.returncode
+
+    def test_help_function(self):
+        result = self._cmd("python", "-m tempest.stress.run_stress -h")
+        self.assertEqual(0, result)
diff --git a/tempest/tests/stress/test_stressaction.py b/tempest/tests/stress/test_stressaction.py
new file mode 100644
index 0000000..3d2901e
--- /dev/null
+++ b/tempest/tests/stress/test_stressaction.py
@@ -0,0 +1,65 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 Deutsche Telekom AG
+# 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 tempest.stress.stressaction as stressaction
+import tempest.test
+
+
+class FakeStressAction(stressaction.StressAction):
+    def __init__(self, manager, max_runs=None, stop_on_error=False):
+        super(self.__class__, self).__init__(manager, max_runs, stop_on_error)
+        self._run_called = False
+
+    def run(self):
+        self._run_called = True
+
+    @property
+    def run_called(self):
+        return self._run_called
+
+
+class FakeStressActionFailing(stressaction.StressAction):
+    def run(self):
+        raise Exception('FakeStressActionFailing raise exception')
+
+
+class TestStressAction(tempest.test.BaseTestCase):
+    def _bulid_stats_dict(self, runs=0, fails=0):
+        return {'runs': runs, 'fails': fails}
+
+    def testStressTestRun(self):
+        stressAction = FakeStressAction(manager=None, max_runs=1)
+        stats = self._bulid_stats_dict()
+        stressAction.execute(stats)
+        self.assertTrue(stressAction.run_called)
+        self.assertEqual(stats['runs'], 1)
+        self.assertEqual(stats['fails'], 0)
+
+    def testStressMaxTestRuns(self):
+        stressAction = FakeStressAction(manager=None, max_runs=500)
+        stats = self._bulid_stats_dict(runs=499)
+        stressAction.execute(stats)
+        self.assertTrue(stressAction.run_called)
+        self.assertEqual(stats['runs'], 500)
+        self.assertEqual(stats['fails'], 0)
+
+    def testStressTestRunWithException(self):
+        stressAction = FakeStressActionFailing(manager=None, max_runs=1)
+        stats = self._bulid_stats_dict()
+        stressAction.execute(stats)
+        self.assertEqual(stats['runs'], 1)
+        self.assertEqual(stats['fails'], 1)
diff --git a/tempest/tests/test_wrappers.py b/tempest/tests/test_wrappers.py
index dbf1809..88bef9b 100644
--- a/tempest/tests/test_wrappers.py
+++ b/tempest/tests/test_wrappers.py
@@ -56,7 +56,7 @@
         # version or an sdist to work. so make the test directory a git repo
         # too.
         subprocess.call(['git', 'init'])
-        exit_code = subprocess.call('sh pretty_tox.sh tests.passing',
+        exit_code = subprocess.call('bash pretty_tox.sh tests.passing',
                                     shell=True, stdout=DEVNULL, stderr=DEVNULL)
         self.assertEqual(exit_code, 0)
 
@@ -71,7 +71,7 @@
         # version or an sdist to work. so make the test directory a git repo
         # too.
         subprocess.call(['git', 'init'])
-        exit_code = subprocess.call('sh pretty_tox.sh', shell=True,
+        exit_code = subprocess.call('bash pretty_tox.sh', shell=True,
                                     stdout=DEVNULL, stderr=DEVNULL)
         self.assertEqual(exit_code, 1)
 
@@ -82,7 +82,7 @@
         # Change directory, run wrapper and check result
         self.addCleanup(os.chdir, os.path.abspath(os.curdir))
         os.chdir(self.directory)
-        exit_code = subprocess.call('sh pretty_tox_serial.sh tests.passing',
+        exit_code = subprocess.call('bash pretty_tox_serial.sh tests.passing',
                                     shell=True, stdout=DEVNULL, stderr=DEVNULL)
         self.assertEqual(exit_code, 0)
 
@@ -93,6 +93,6 @@
         # Change directory, run wrapper and check result
         self.addCleanup(os.chdir, os.path.abspath(os.curdir))
         os.chdir(self.directory)
-        exit_code = subprocess.call('sh pretty_tox_serial.sh', shell=True,
+        exit_code = subprocess.call('bash pretty_tox_serial.sh', shell=True,
                                     stdout=DEVNULL, stderr=DEVNULL)
         self.assertEqual(exit_code, 1)
diff --git a/tempest/thirdparty/boto/test_ec2_instance_run.py b/tempest/thirdparty/boto/test_ec2_instance_run.py
index 0f455e1..9ded9da 100644
--- a/tempest/thirdparty/boto/test_ec2_instance_run.py
+++ b/tempest/thirdparty/boto/test_ec2_instance_run.py
@@ -18,7 +18,7 @@
 from boto import exception
 
 from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.common.utils.linux.remote_client import RemoteClient
 from tempest import exceptions
 from tempest.openstack.common import log as logging
@@ -50,8 +50,8 @@
         aki_manifest = config.boto.aki_manifest
         ari_manifest = config.boto.ari_manifest
         cls.instance_type = config.boto.instance_type
-        cls.bucket_name = rand_name("s3bucket-")
-        cls.keypair_name = rand_name("keypair-")
+        cls.bucket_name = data_utils.rand_name("s3bucket-")
+        cls.keypair_name = data_utils.rand_name("keypair-")
         cls.keypair = cls.ec2_client.create_key_pair(cls.keypair_name)
         cls.addResourceCleanUp(cls.ec2_client.delete_key_pair,
                                cls.keypair_name)
@@ -61,13 +61,13 @@
                                cls.bucket_name)
         s3_upload_dir(bucket, cls.materials_path)
         cls.images = {"ami":
-                      {"name": rand_name("ami-name-"),
+                      {"name": data_utils.rand_name("ami-name-"),
                        "location": cls.bucket_name + "/" + ami_manifest},
                       "aki":
-                      {"name": rand_name("aki-name-"),
+                      {"name": data_utils.rand_name("aki-name-"),
                        "location": cls.bucket_name + "/" + aki_manifest},
                       "ari":
-                      {"name": rand_name("ari-name-"),
+                      {"name": data_utils.rand_name("ari-name-"),
                        "location": cls.bucket_name + "/" + ari_manifest}}
         for image in cls.images.itervalues():
             image["image_id"] = cls.ec2_client.register_image(
@@ -238,7 +238,7 @@
     def test_integration_1(self):
         # EC2 1. integration test (not strict)
         image_ami = self.ec2_client.get_image(self.images["ami"]["image_id"])
-        sec_group_name = rand_name("securitygroup-")
+        sec_group_name = data_utils.rand_name("securitygroup-")
         group_desc = sec_group_name + " security group description "
         security_group = self.ec2_client.create_security_group(sec_group_name,
                                                                group_desc)
@@ -285,7 +285,7 @@
         ssh = RemoteClient(address.public_ip,
                            self.os.config.compute.ssh_user,
                            pkey=self.keypair.material)
-        text = rand_name("Pattern text for console output -")
+        text = data_utils.rand_name("Pattern text for console output -")
         resp = ssh.write_to_console(text)
         self.assertFalse(resp)
 
diff --git a/tempest/thirdparty/boto/test_ec2_keys.py b/tempest/thirdparty/boto/test_ec2_keys.py
index 5592d8c..41db709 100644
--- a/tempest/thirdparty/boto/test_ec2_keys.py
+++ b/tempest/thirdparty/boto/test_ec2_keys.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 from tempest.test import skip_because
 from tempest.thirdparty.boto.test import BotoTestCase
@@ -40,7 +40,7 @@
     @attr(type='smoke')
     def test_create_ec2_keypair(self):
         # EC2 create KeyPair
-        key_name = rand_name("keypair-")
+        key_name = data_utils.rand_name("keypair-")
         self.addResourceCleanUp(self.client.delete_key_pair, key_name)
         keypair = self.client.create_key_pair(key_name)
         self.assertTrue(compare_key_pairs(keypair,
@@ -50,7 +50,7 @@
     @attr(type='smoke')
     def test_delete_ec2_keypair(self):
         # EC2 delete KeyPair
-        key_name = rand_name("keypair-")
+        key_name = data_utils.rand_name("keypair-")
         self.client.create_key_pair(key_name)
         self.client.delete_key_pair(key_name)
         self.assertEqual(None, self.client.get_key_pair(key_name))
@@ -58,7 +58,7 @@
     @attr(type='smoke')
     def test_get_ec2_keypair(self):
         # EC2 get KeyPair
-        key_name = rand_name("keypair-")
+        key_name = data_utils.rand_name("keypair-")
         self.addResourceCleanUp(self.client.delete_key_pair, key_name)
         keypair = self.client.create_key_pair(key_name)
         self.assertTrue(compare_key_pairs(keypair,
@@ -67,7 +67,7 @@
     @attr(type='smoke')
     def test_duplicate_ec2_keypair(self):
         # EC2 duplicate KeyPair
-        key_name = rand_name("keypair-")
+        key_name = data_utils.rand_name("keypair-")
         self.addResourceCleanUp(self.client.delete_key_pair, key_name)
         keypair = self.client.create_key_pair(key_name)
         self.assertBotoError(self.ec.client.InvalidKeyPair.Duplicate,
diff --git a/tempest/thirdparty/boto/test_ec2_security_groups.py b/tempest/thirdparty/boto/test_ec2_security_groups.py
index 3b10cfa..e8c6466 100644
--- a/tempest/thirdparty/boto/test_ec2_security_groups.py
+++ b/tempest/thirdparty/boto/test_ec2_security_groups.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 from tempest.thirdparty.boto.test import BotoTestCase
 
@@ -32,7 +32,7 @@
     @attr(type='smoke')
     def test_create_authorize_security_group(self):
         # EC2 Create, authorize/revoke security group
-        group_name = rand_name("securty_group-")
+        group_name = data_utils.rand_name("securty_group-")
         group_description = group_name + " security group description "
         group = self.client.create_security_group(group_name,
                                                   group_description)
diff --git a/tempest/thirdparty/boto/test_s3_buckets.py b/tempest/thirdparty/boto/test_s3_buckets.py
index 1a8fbe0..56ee9e3 100644
--- a/tempest/thirdparty/boto/test_s3_buckets.py
+++ b/tempest/thirdparty/boto/test_s3_buckets.py
@@ -16,7 +16,7 @@
 #    under the License.
 
 from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 from tempest.test import skip_because
 from tempest.thirdparty.boto.test import BotoTestCase
@@ -34,7 +34,7 @@
     @attr(type='smoke')
     def test_create_and_get_delete_bucket(self):
         # S3 Create, get and delete bucket
-        bucket_name = rand_name("s3bucket-")
+        bucket_name = data_utils.rand_name("s3bucket-")
         cleanup_key = self.addResourceCleanUp(self.client.delete_bucket,
                                               bucket_name)
         bucket = self.client.create_bucket(bucket_name)
diff --git a/tempest/thirdparty/boto/test_s3_ec2_images.py b/tempest/thirdparty/boto/test_s3_ec2_images.py
index aaf2569..2e7525a 100644
--- a/tempest/thirdparty/boto/test_s3_ec2_images.py
+++ b/tempest/thirdparty/boto/test_s3_ec2_images.py
@@ -18,7 +18,7 @@
 import os
 
 from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 from tempest.thirdparty.boto.test import BotoTestCase
 from tempest.thirdparty.boto.utils.s3 import s3_upload_dir
@@ -43,7 +43,7 @@
         cls.ami_path = cls.materials_path + os.sep + cls.ami_manifest
         cls.aki_path = cls.materials_path + os.sep + cls.aki_manifest
         cls.ari_path = cls.materials_path + os.sep + cls.ari_manifest
-        cls.bucket_name = rand_name("bucket-")
+        cls.bucket_name = data_utils.rand_name("bucket-")
         bucket = cls.s3_client.create_bucket(cls.bucket_name)
         cls.addResourceCleanUp(cls.destroy_bucket,
                                cls.s3_client.connection_data,
@@ -53,7 +53,7 @@
     @attr(type='smoke')
     def test_register_get_deregister_ami_image(self):
         # Register and deregister ami image
-        image = {"name": rand_name("ami-name-"),
+        image = {"name": data_utils.rand_name("ami-name-"),
                  "location": self.bucket_name + "/" + self.ami_manifest,
                  "type": "ami"}
         image["image_id"] = self.images_client.register_image(
@@ -76,7 +76,7 @@
 
     def test_register_get_deregister_aki_image(self):
         # Register and deregister aki image
-        image = {"name": rand_name("aki-name-"),
+        image = {"name": data_utils.rand_name("aki-name-"),
                  "location": self.bucket_name + "/" + self.aki_manifest,
                  "type": "aki"}
         image["image_id"] = self.images_client.register_image(
@@ -99,7 +99,7 @@
 
     def test_register_get_deregister_ari_image(self):
         # Register and deregister ari image
-        image = {"name": rand_name("ari-name-"),
+        image = {"name": data_utils.rand_name("ari-name-"),
                  "location": "/" + self.bucket_name + "/" + self.ari_manifest,
                  "type": "ari"}
         image["image_id"] = self.images_client.register_image(
diff --git a/tempest/thirdparty/boto/test_s3_objects.py b/tempest/thirdparty/boto/test_s3_objects.py
index 188d1db..57ec34a 100644
--- a/tempest/thirdparty/boto/test_s3_objects.py
+++ b/tempest/thirdparty/boto/test_s3_objects.py
@@ -20,7 +20,7 @@
 import boto.s3.key
 
 from tempest import clients
-from tempest.common.utils.data_utils import rand_name
+from tempest.common.utils import data_utils
 from tempest.test import attr
 from tempest.thirdparty.boto.test import BotoTestCase
 
@@ -36,8 +36,8 @@
     @attr(type='smoke')
     def test_create_get_delete_object(self):
         # S3 Create, get and delete object
-        bucket_name = rand_name("s3bucket-")
-        object_name = rand_name("s3object-")
+        bucket_name = data_utils.rand_name("s3bucket-")
+        object_name = data_utils.rand_name("s3object-")
         content = 'x' * 42
         bucket = self.client.create_bucket(bucket_name)
         self.addResourceCleanUp(self.destroy_bucket,
diff --git a/test-requirements.txt b/test-requirements.txt
index fbe7e43..9486244 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -1,7 +1,8 @@
-hacking>=0.5.6,<0.8
+hacking>=0.8.0,<0.9
 # needed for doc build
 docutils==0.9.1
-sphinx>=1.1.2
+sphinx>=1.1.2,<1.2
 python-subunit
 oslo.sphinx
 mox>=0.5.3
+mock>=1.0
diff --git a/tools/check_logs.py b/tools/check_logs.py
index 2ad4f70..0c8fd21 100755
--- a/tools/check_logs.py
+++ b/tools/check_logs.py
@@ -26,6 +26,12 @@
 import yaml
 
 
+is_neutron = os.environ.get('DEVSTACK_GATE_NEUTRON', "0") == "1"
+is_grenade = (os.environ.get('DEVSTACK_GATE_GRENADE', "0") == "1" or
+              os.environ.get('DEVSTACK_GATE_GRENADE_FORWARD', "0") == "1")
+dump_all_errors = is_neutron
+
+
 def process_files(file_specs, url_specs, whitelists):
     regexp = re.compile(r"^.*(ERROR|CRITICAL).*\[.*\-.*\]")
     had_errors = False
@@ -48,6 +54,7 @@
 
 def scan_content(name, content, regexp, whitelist):
     had_errors = False
+    print_log_name = True
     for line in content:
         if not line.startswith("Stderr:") and regexp.match(line):
             whitelisted = False
@@ -57,10 +64,12 @@
                 if re.match(pat, line):
                     whitelisted = True
                     break
-            if not whitelisted:
-                if not had_errors:
+            if not whitelisted or dump_all_errors:
+                if print_log_name:
                     print("Log File: %s" % name)
-                had_errors = True
+                    print_log_name = False
+                if not whitelisted:
+                    had_errors = True
                 print(line)
     return had_errors
 
@@ -115,8 +124,14 @@
             whitelists = loaded
     if process_files(files_to_process, urls_to_process, whitelists):
         print("Logs have errors")
-        # Return non-zero to start failing builds
-        return 0
+        if is_neutron:
+            print("Currently not failing neutron builds with errors")
+            return 0
+        if is_grenade:
+            print("Currently not failing grenade runs with errors")
+            return 0
+        print("FAILED")
+        return 1
     else:
         print("ok")
         return 0
diff --git a/tools/config/check_uptodate.sh b/tools/config/check_uptodate.sh
new file mode 100755
index 0000000..45c8629
--- /dev/null
+++ b/tools/config/check_uptodate.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+TEMPDIR=`mktemp -d`
+CFGFILE=tempest.conf.sample
+tools/config/generate_sample.sh -b ./ -p tempest -o $TEMPDIR
+if ! diff $TEMPDIR/$CFGFILE etc/$CFGFILE
+then
+    echo "E: tempest.conf.sample is not up to date, please run:"
+    echo "tools/generate_sample.sh"
+    exit 42
+fi
diff --git a/tools/config/generate_sample.sh b/tools/config/generate_sample.sh
new file mode 100755
index 0000000..b86e0c2
--- /dev/null
+++ b/tools/config/generate_sample.sh
@@ -0,0 +1,93 @@
+#!/usr/bin/env bash
+
+print_hint() {
+    echo "Try \`${0##*/} --help' for more information." >&2
+}
+
+PARSED_OPTIONS=$(getopt -n "${0##*/}" -o hb:p:o: \
+                 --long help,base-dir:,package-name:,output-dir: -- "$@")
+
+if [ $? != 0 ] ; then print_hint ; exit 1 ; fi
+
+eval set -- "$PARSED_OPTIONS"
+
+while true; do
+    case "$1" in
+        -h|--help)
+            echo "${0##*/} [options]"
+            echo ""
+            echo "options:"
+            echo "-h, --help                show brief help"
+            echo "-b, --base-dir=DIR        project base directory"
+            echo "-p, --package-name=NAME   project package name"
+            echo "-o, --output-dir=DIR      file output directory"
+            exit 0
+            ;;
+        -b|--base-dir)
+            shift
+            BASEDIR=`echo $1 | sed -e 's/\/*$//g'`
+            shift
+            ;;
+        -p|--package-name)
+            shift
+            PACKAGENAME=`echo $1`
+            shift
+            ;;
+        -o|--output-dir)
+            shift
+            OUTPUTDIR=`echo $1 | sed -e 's/\/*$//g'`
+            shift
+            ;;
+        --)
+            break
+            ;;
+    esac
+done
+
+BASEDIR=${BASEDIR:-`pwd`}
+if ! [ -d $BASEDIR ]
+then
+    echo "${0##*/}: missing project base directory" >&2 ; print_hint ; exit 1
+elif [[ $BASEDIR != /* ]]
+then
+    BASEDIR=$(cd "$BASEDIR" && pwd)
+fi
+
+PACKAGENAME=${PACKAGENAME:-${BASEDIR##*/}}
+TARGETDIR=$BASEDIR/$PACKAGENAME
+if ! [ -d $TARGETDIR ]
+then
+    echo "${0##*/}: invalid project package name" >&2 ; print_hint ; exit 1
+fi
+
+OUTPUTDIR=${OUTPUTDIR:-$BASEDIR/etc}
+# NOTE(bnemec): Some projects put their sample config in etc/,
+#               some in etc/$PACKAGENAME/
+if [ -d $OUTPUTDIR/$PACKAGENAME ]
+then
+    OUTPUTDIR=$OUTPUTDIR/$PACKAGENAME
+elif ! [ -d $OUTPUTDIR ]
+then
+    echo "${0##*/}: cannot access \`$OUTPUTDIR': No such file or directory" >&2
+    exit 1
+fi
+
+BASEDIRESC=`echo $BASEDIR | sed -e 's/\//\\\\\//g'`
+find $TARGETDIR -type f -name "*.pyc" -delete
+FILES=$(find $TARGETDIR -type f -name "*.py" ! -path "*/tests/*" \
+        -exec grep -l "Opt(" {} + | sed -e "s/^$BASEDIRESC\///g" | sort -u)
+
+EXTRA_MODULES_FILE="`dirname $0`/oslo.config.generator.rc"
+if test -r "$EXTRA_MODULES_FILE"
+then
+    source "$EXTRA_MODULES_FILE"
+fi
+
+export EVENTLET_NO_GREENDNS=yes
+
+OS_VARS=$(set | sed -n '/^OS_/s/=[^=]*$//gp' | xargs)
+[ "$OS_VARS" ] && eval "unset \$OS_VARS"
+DEFAULT_MODULEPATH=tempest.openstack.common.config.generator
+MODULEPATH=${MODULEPATH:-$DEFAULT_MODULEPATH}
+OUTPUTFILE=$OUTPUTDIR/$PACKAGENAME.conf.sample
+python -m $MODULEPATH $FILES > $OUTPUTFILE
diff --git a/tools/generate_sample.sh b/tools/generate_sample.sh
new file mode 100755
index 0000000..9b312c9
--- /dev/null
+++ b/tools/generate_sample.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+MODULEPATH=tempest.common.generate_sample_tempest tools/config/generate_sample.sh $@
diff --git a/tools/install_venv_common.py b/tools/install_venv_common.py
index 92d66ae..1bab88a 100644
--- a/tools/install_venv_common.py
+++ b/tools/install_venv_common.py
@@ -121,9 +121,6 @@
 
         self.pip_install('-r', self.requirements, '-r', self.test_requirements)
 
-    def post_process(self):
-        self.get_distro().post_process()
-
     def parse_args(self, argv):
         """Parses command-line arguments."""
         parser = optparse.OptionParser()
@@ -156,14 +153,6 @@
                  ' requires virtualenv, please install it using your'
                  ' favorite package management tool' % self.project)
 
-    def post_process(self):
-        """Any distribution-specific post-processing gets done here.
-
-        In particular, this is useful for applying patches to code inside
-        the venv.
-        """
-        pass
-
 
 class Fedora(Distro):
     """This covers all Fedora-based distributions.
@@ -175,10 +164,6 @@
         return self.run_command_with_code(['rpm', '-q', pkg],
                                           check_exit_code=False)[1] == 0
 
-    def apply_patch(self, originalfile, patchfile):
-        self.run_command(['patch', '-N', originalfile, patchfile],
-                         check_exit_code=False)
-
     def install_virtualenv(self):
         if self.check_cmd('virtualenv'):
             return
@@ -187,27 +172,3 @@
             self.die("Please install 'python-virtualenv'.")
 
         super(Fedora, self).install_virtualenv()
-
-    def post_process(self):
-        """Workaround for a bug in eventlet.
-
-        This currently affects RHEL6.1, but the fix can safely be
-        applied to all RHEL and Fedora distributions.
-
-        This can be removed when the fix is applied upstream.
-
-        Nova: https://bugs.launchpad.net/nova/+bug/884915
-        Upstream: https://bitbucket.org/eventlet/eventlet/issue/89
-        RHEL: https://bugzilla.redhat.com/958868
-        """
-
-        if os.path.exists('contrib/redhat-eventlet.patch'):
-            # Install "patch" program if it's not there
-            if not self.check_pkg('patch'):
-                self.die("Please install 'patch'.")
-
-            # Apply the eventlet patch
-            self.apply_patch(os.path.join(self.venv, 'lib', self.py_version,
-                                          'site-packages',
-                                          'eventlet/green/subprocess.py'),
-                             'contrib/redhat-eventlet.patch')
diff --git a/tools/pretty_tox.sh b/tools/pretty_tox.sh
index a5a6076..07c35a0 100755
--- a/tools/pretty_tox.sh
+++ b/tools/pretty_tox.sh
@@ -1,4 +1,6 @@
-#!/bin/sh
+#!/usr/bin/env bash
+
+set -o pipefail
 
 TESTRARGS=$1
 python setup.py testr --slowest --testr-args="--subunit $TESTRARGS" | subunit2pyunit
diff --git a/tools/pretty_tox_serial.sh b/tools/pretty_tox_serial.sh
index 45f05bd..42ce760 100755
--- a/tools/pretty_tox_serial.sh
+++ b/tools/pretty_tox_serial.sh
@@ -1,4 +1,6 @@
-#!/bin/sh
+#!/usr/bin/env bash
+
+set -o pipefail
 
 TESTRARGS=$@
 
diff --git a/tools/tempest_auto_config.py b/tools/tempest_auto_config.py
index aef6a1f..fe9f5af 100644
--- a/tools/tempest_auto_config.py
+++ b/tools/tempest_auto_config.py
@@ -14,38 +14,50 @@
 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 #    License for the specific language governing permissions and limitations
 #    under the License.
+#
+# This script aims to configure an initial Openstack environment with all the
+# necessary configurations for tempest's run using nothing but Openstack's
+# native API.
+# That includes, creating users, tenants, registering images (cirros),
+# configuring neutron and so on.
+#
+# ASSUMPTION: this script is run by an admin user as it is meant to configure
+# the Openstack environment prior to actual use.
 
 # Config
 import ConfigParser
 import os
+import tarfile
+import urllib2
 
 # Default client libs
+import glanceclient as glance_client
 import keystoneclient.v2_0.client as keystone_client
 
 # Import Openstack exceptions
+import glanceclient.exc as glance_exception
 import keystoneclient.exceptions as keystone_exception
 
 
-DEFAULT_CONFIG_DIR = "%s/etc" % os.path.abspath(os.path.pardir)
-DEFAULT_CONFIG_FILE = "tempest.conf"
-DEFAULT_CONFIG_SAMPLE = "tempest.conf.sample"
+TEMPEST_TEMP_DIR = os.getenv("TEMPEST_TEMP_DIR", "/tmp").rstrip('/')
+TEMPEST_ROOT_DIR = os.getenv("TEMPEST_ROOT_DIR", os.getenv("HOME")).rstrip('/')
 
 # Environment variables override defaults
-TEMPEST_CONFIG_DIR = os.environ.get('TEMPEST_CONFIG_DIR') or DEFAULT_CONFIG_DIR
-TEMPEST_CONFIG = os.environ.get('TEMPEST_CONFIG') or "%s/%s" % \
-    (TEMPEST_CONFIG_DIR, DEFAULT_CONFIG_FILE)
-TEMPEST_CONFIG_SAMPLE = os.environ.get('TEMPEST_CONFIG_SAMPLE') or "%s/%s" % \
-    (TEMPEST_CONFIG_DIR, DEFAULT_CONFIG_SAMPLE)
-
-# Admin credentials
-OS_USERNAME = os.environ.get('OS_USERNAME')
-OS_PASSWORD = os.environ.get('OS_PASSWORD')
-OS_TENANT_NAME = os.environ.get('OS_TENANT_NAME')
-OS_AUTH_URL = os.environ.get('OS_AUTH_URL')
-
+TEMPEST_CONFIG_DIR = os.getenv("TEMPEST_CONFIG_DIR",
+                               "%s%s" % (TEMPEST_ROOT_DIR, "/etc")).rstrip('/')
+TEMPEST_CONFIG_FILE = os.getenv("TEMPEST_CONFIG_FILE",
+                                "%s%s" % (TEMPEST_CONFIG_DIR, "/tempest.conf"))
+TEMPEST_CONFIG_SAMPLE = os.getenv("TEMPEST_CONFIG_SAMPLE",
+                                  "%s%s" % (TEMPEST_CONFIG_DIR,
+                                            "/tempest.conf.sample"))
 # Image references
-IMAGE_ID = os.environ.get('IMAGE_ID')
-IMAGE_ID_ALT = os.environ.get('IMAGE_ID_ALT')
+IMAGE_DOWNLOAD_CHUNK_SIZE = 8 * 1024
+IMAGE_UEC_SOURCE_URL = os.getenv("IMAGE_UEC_SOURCE_URL",
+                                 "http://download.cirros-cloud.net/0.3.1/"
+                                 "cirros-0.3.1-x86_64-uec.tar.gz")
+TEMPEST_IMAGE_ID = os.getenv('IMAGE_ID')
+TEMPEST_IMAGE_ID_ALT = os.getenv('IMAGE_ID_ALT')
+IMAGE_STATUS_ACTIVE = 'active'
 
 
 class ClientManager(object):
@@ -76,26 +88,52 @@
 
         return self.identity_client
 
+    def get_image_client(self, version="1", *args, **kwargs):
+        """
+        This method returns Openstack glance python client
+        :param version: a string representing the version of the glance client
+        to use.
+        :param string endpoint: A user-supplied endpoint URL for the glance
+                            service.
+        :param string token: Token for authentication.
+        :param integer timeout: Allows customization of the timeout for client
+                                http requests. (optional)
+        :return: a Client object representing the glance client
+        """
+        if not self.image_client:
+            self.image_client = glance_client.Client(version, *args, **kwargs)
 
-def getTempestConfigSample():
+        return self.image_client
+
+
+def get_tempest_config(path_to_config):
     """
     Gets the tempest configuration file as a ConfigParser object
-    :return: the tempest configuration file
+    :param path_to_config: path to the config file
+    :return: a ConfigParser object representing the tempest configuration file
     """
     # get the sample config file from the sample
-    config_sample = ConfigParser.ConfigParser()
-    config_sample.readfp(open(TEMPEST_CONFIG_SAMPLE))
+    config = ConfigParser.ConfigParser()
+    config.readfp(open(path_to_config))
 
-    return config_sample
+    return config
 
 
 def update_config_admin_credentials(config, config_section):
     """
     Updates the tempest config with the admin credentials
-    :param config: an object representing the tempest config file
+    :param config: a ConfigParser object representing the tempest config file
     :param config_section: the section name where the admin credentials are
     """
-    # Check if credentials are present
+    # Check if credentials are present, default uses the config credentials
+    OS_USERNAME = os.getenv('OS_USERNAME',
+                            config.get(config_section, "admin_username"))
+    OS_PASSWORD = os.getenv('OS_PASSWORD',
+                            config.get(config_section, "admin_password"))
+    OS_TENANT_NAME = os.getenv('OS_TENANT_NAME',
+                               config.get(config_section, "admin_tenant_name"))
+    OS_AUTH_URL = os.getenv('OS_AUTH_URL', config.get(config_section, "uri"))
+
     if not (OS_AUTH_URL and
             OS_USERNAME and
             OS_PASSWORD and
@@ -113,31 +151,31 @@
                                       config_identity_params)
 
 
-def update_config_section_with_params(config, section, params):
+def update_config_section_with_params(config, config_section, params):
     """
     Updates a given config object with given params
-    :param config: the object representing the config file of tempest
-    :param section: the section we would like to update
+    :param config: a ConfigParser object representing the tempest config file
+    :param config_section: the section we would like to update
     :param params: the parameters we wish to update for that section
     """
     for option, value in params.items():
-        config.set(section, option, value)
+        config.set(config_section, option, value)
 
 
-def get_identity_client_kwargs(config, section_name):
+def get_identity_client_kwargs(config, config_section):
     """
     Get the required arguments for the identity python client
-    :param config: the tempest configuration file
-    :param section_name: the section name in the configuration where the
+    :param config: a ConfigParser object representing the tempest config file
+    :param config_section: the section name in the configuration where the
     arguments can be found
     :return: a dictionary representing the needed arguments for the identity
     client
     """
-    username = config.get(section_name, 'admin_username')
-    password = config.get(section_name, 'admin_password')
-    tenant_name = config.get(section_name, 'admin_tenant_name')
-    auth_url = config.get(section_name, 'uri')
-    dscv = config.get(section_name, 'disable_ssl_certificate_validation')
+    username = config.get(config_section, 'admin_username')
+    password = config.get(config_section, 'admin_password')
+    tenant_name = config.get(config_section, 'admin_tenant_name')
+    auth_url = config.get(config_section, 'uri')
+    dscv = config.get(config_section, 'disable_ssl_certificate_validation')
     kwargs = {'username': username,
               'password': password,
               'tenant_name': tenant_name,
@@ -185,21 +223,21 @@
 
 def create_users_and_tenants(identity_client,
                              config,
-                             identity_section):
+                             config_section):
     """
     Creates the two non admin users and tenants for tempest
     :param identity_client: openstack identity python client
-    :param config: tempest configuration file
-    :param identity_section: the section name of identity in the config
+    :param config: a ConfigParser object representing the tempest config file
+    :param config_section: the section name of identity in the config
     """
     # Get the necessary params from the config file
-    tenant_name = config.get(identity_section, 'tenant_name')
-    username = config.get(identity_section, 'username')
-    password = config.get(identity_section, 'password')
+    tenant_name = config.get(config_section, 'tenant_name')
+    username = config.get(config_section, 'username')
+    password = config.get(config_section, 'password')
 
-    alt_tenant_name = config.get(identity_section, 'alt_tenant_name')
-    alt_username = config.get(identity_section, 'alt_username')
-    alt_password = config.get(identity_section, 'alt_password')
+    alt_tenant_name = config.get(config_section, 'alt_tenant_name')
+    alt_username = config.get(config_section, 'alt_username')
+    alt_password = config.get(config_section, 'alt_password')
 
     # Create the necessary users for the test runs
     create_user_with_tenant(identity_client, username, password, tenant_name)
@@ -207,28 +245,153 @@
                             alt_tenant_name)
 
 
+def get_image_client_kwargs(identity_client, config, config_section):
+    """
+    Get the required arguments for the image python client
+    :param identity_client: openstack identity python client
+    :param config: a ConfigParser object representing the tempest config file
+    :param config_section: the section name of identity in the config
+    :return: a dictionary representing the needed arguments for the image
+    client
+    """
+
+    token = identity_client.auth_token
+    endpoint = identity_client.\
+        service_catalog.url_for(service_type='image', endpoint_type='publicURL'
+                                )
+    dscv = config.get(config_section, 'disable_ssl_certificate_validation')
+    kwargs = {'endpoint': endpoint,
+              'token': token,
+              'insecure': dscv}
+
+    return kwargs
+
+
+def images_exist(image_client):
+    """
+    Checks whether the images ID's located in the environment variable are
+    indeed registered
+    :param image_client: the openstack python client representing the image
+    client
+    """
+    exist = True
+    if not TEMPEST_IMAGE_ID or not TEMPEST_IMAGE_ID_ALT:
+        exist = False
+    else:
+        try:
+            image_client.images.get(TEMPEST_IMAGE_ID)
+            image_client.images.get(TEMPEST_IMAGE_ID_ALT)
+        except glance_exception.HTTPNotFound:
+            exist = False
+
+    return exist
+
+
+def download_and_register_uec_images(image_client, download_url,
+                                     download_folder):
+    """
+    Downloads and registered the UEC AKI/AMI/ARI images
+    :param image_client:
+    :param download_url: the url of the uec tar file
+    :param download_folder: the destination folder we wish to save the file to
+    """
+    basename = os.path.basename(download_url)
+    path = os.path.join(download_folder, basename)
+
+    request = urllib2.urlopen(download_url)
+
+    # First, download the file
+    with open(path, "wb") as fp:
+        while True:
+            chunk = request.read(IMAGE_DOWNLOAD_CHUNK_SIZE)
+            if not chunk:
+                break
+
+            fp.write(chunk)
+
+    # Then extract and register images
+    tar = tarfile.open(path, "r")
+    for name in tar.getnames():
+        file_obj = tar.extractfile(name)
+        format = "aki"
+
+        if file_obj.name.endswith(".img"):
+            format = "ami"
+
+        if file_obj.name.endswith("initrd"):
+            format = "ari"
+
+        # Register images in image client
+        image_client.images.create(name=file_obj.name, disk_format=format,
+                                   container_format=format, data=file_obj,
+                                   is_public="true")
+
+    tar.close()
+
+
+def create_images(image_client, config, config_section,
+                  download_url=IMAGE_UEC_SOURCE_URL,
+                  download_folder=TEMPEST_TEMP_DIR):
+    """
+    Creates images for tempest's use and registers the environment variables
+    IMAGE_ID and IMAGE_ID_ALT with registered images
+    :param image_client: Openstack python image client
+    :param config: a ConfigParser object representing the tempest config file
+    :param config_section: the section name where the IMAGE ids are set
+    :param download_url: the URL from which we should download the UEC tar
+    :param download_folder: the place where we want to save the download file
+    """
+    if not images_exist(image_client):
+        # Falls down to the default uec images
+        download_and_register_uec_images(image_client, download_url,
+                                         download_folder)
+        image_ids = []
+        for image in image_client.images.list():
+            image_ids.append(image.id)
+
+        os.environ["IMAGE_ID"] = image_ids[0]
+        os.environ["IMAGE_ID_ALT"] = image_ids[1]
+
+    params = {'image_ref': os.getenv("IMAGE_ID"),
+              'image_ref_alt': os.getenv("IMAGE_ID_ALT")}
+
+    update_config_section_with_params(config, config_section, params)
+
+
 def main():
     """
     Main module to control the script
     """
-    # TODO(tkammer): add support for existing config file
-    config_sample = getTempestConfigSample()
-    update_config_admin_credentials(config_sample, 'identity')
+    # Check if config file exists or fall to the default sample otherwise
+    path_to_config = TEMPEST_CONFIG_SAMPLE
+
+    if os.path.isfile(TEMPEST_CONFIG_FILE):
+        path_to_config = TEMPEST_CONFIG_FILE
+
+    config = get_tempest_config(path_to_config)
+    update_config_admin_credentials(config, 'identity')
 
     client_manager = ClientManager()
 
     # Set the identity related info for tempest
-    identity_client_kwargs = get_identity_client_kwargs(config_sample,
+    identity_client_kwargs = get_identity_client_kwargs(config,
                                                         'identity')
     identity_client = client_manager.get_identity_client(
         **identity_client_kwargs)
 
     # Create the necessary users and tenants for tempest run
-    create_users_and_tenants(identity_client,
-                             config_sample,
-                             'identity')
+    create_users_and_tenants(identity_client, config, 'identity')
 
-    # TODO(tkammer): add image implementation
+    # Set the image related info for tempest
+    image_client_kwargs = get_image_client_kwargs(identity_client,
+                                                  config,
+                                                  'identity')
+    image_client = client_manager.get_image_client(**image_client_kwargs)
+
+    # Create the necessary users and tenants for tempest run
+    create_images(image_client, config, 'compute')
+
+    # TODO(tkammer): add network implementation
 
 if __name__ == "__main__":
     main()
diff --git a/tools/tempest_coverage.py b/tools/tempest_coverage.py
deleted file mode 100755
index ef2eacd..0000000
--- a/tools/tempest_coverage.py
+++ /dev/null
@@ -1,193 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2012 IBM Corp.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-import json
-import os
-import shutil
-import sys
-
-from oslo.config import cfg
-
-from tempest.common.rest_client import RestClient
-from tempest import config
-
-CONF = config.TempestConfig()
-
-
-class CoverageClientJSON(RestClient):
-
-    def __init__(self, config, username, password, auth_url, tenant_name=None):
-        super(CoverageClientJSON, self).__init__(config, username, password,
-                                                 auth_url, tenant_name)
-        self.service = self.config.compute.catalog_type
-
-    def start_coverage(self):
-        post_body = {
-            'start': {},
-        }
-        post_body = json.dumps(post_body)
-        return self.post('os-coverage/action', post_body, self.headers)
-
-    def start_coverage_combine(self):
-        post_body = {
-            'start': {
-                'combine': True,
-            },
-        }
-        post_body = json.dumps(post_body)
-        return self.post('os-coverage/action', post_body, self.headers)
-
-    def stop_coverage(self):
-        post_body = {
-            'stop': {},
-        }
-        post_body = json.dumps(post_body)
-        resp, body = self.post('os-coverage/action', post_body, self.headers)
-        body = json.loads(body)
-        return resp, body
-
-    def report_coverage_xml(self, file=None):
-        post_body = {
-            'report': {
-                'file': 'coverage.report',
-                'xml': True,
-            },
-        }
-        if file:
-            post_body['report']['file'] = file
-        post_body = json.dumps(post_body)
-        resp, body = self.post('os-coverage/action', post_body, self.headers)
-        body = json.loads(body)
-        return resp, body
-
-    def report_coverage(self, file=None):
-        post_body = {
-            'report': {
-                'file': 'coverage.report',
-            },
-        }
-        if file:
-            post_body['report']['file'] = file
-        post_body = json.dumps(post_body)
-        resp, body = self.post('os-coverage/action', post_body, self.headers)
-        body = json.loads(body)
-        return resp, body
-
-    def report_coverage_html(self, file=None):
-        post_body = {
-            'report': {
-                'file': 'coverage.report',
-                'html': True,
-            },
-        }
-        if file:
-            post_body['report']['file'] = file
-        post_body = json.dumps(post_body)
-        resp, body = self.post('os-coverage/action', post_body, self.headers)
-        body = json.loads(body)
-        return resp, body
-
-
-def parse_opts(argv):
-    cli_opts = [
-        cfg.StrOpt('command',
-                   short='c',
-                   default='',
-                   help="This required argument is used to specify the "
-                        "coverage command to run. Only 'start', "
-                        "'stop', or 'report' are valid fields."),
-        cfg.StrOpt('filename',
-                   default='tempest-coverage',
-                   help="Specify a filename to be used for generated report "
-                        "files"),
-        cfg.BoolOpt('xml',
-                    default=False,
-                    help='Generate XML reports instead of text'),
-        cfg.BoolOpt('html',
-                    default=False,
-                    help='Generate HTML reports instead of text'),
-        cfg.BoolOpt('combine',
-                    default=False,
-                    help='Generate a single report for all services'),
-        cfg.StrOpt('output',
-                   short='o',
-                   default=None,
-                   help='Optional directory to copy generated coverage data or'
-                        ' reports into. This directory must not already exist '
-                        'it will be created')
-    ]
-    CLI = cfg.ConfigOpts()
-    CLI.register_cli_opts(cli_opts)
-    CLI(argv[1:])
-    return CLI
-
-
-def main(argv):
-    CLI = parse_opts(argv)
-    client_args = (CONF, CONF.identity.admin_username,
-                   CONF.identity.admin_password, CONF.identity.uri,
-                   CONF.identity.admin_tenant_name)
-    coverage_client = CoverageClientJSON(*client_args)
-
-    if CLI.command == 'start':
-        if CLI.combine:
-            coverage_client.start_coverage_combine()
-        else:
-            coverage_client.start_coverage()
-
-    elif CLI.command == 'stop':
-        resp, body = coverage_client.stop_coverage()
-        if not resp['status'] == '200':
-            print('coverage stop failed with: %s:' % (resp['status'] + ': '
-                                                      + body))
-            exit(int(resp['status']))
-        path = body['path']
-        if CLI.output:
-            shutil.copytree(path, CLI.output)
-        else:
-            print("Data files located at: %s" % path)
-
-    elif CLI.command == 'report':
-        if CLI.xml:
-            resp, body = coverage_client.report_coverage_xml(file=CLI.filename)
-        elif CLI.html:
-            resp, body = coverage_client.report_coverage_html(
-                file=CLI.filename)
-        else:
-            resp, body = coverage_client.report_coverage(file=CLI.filename)
-        if not resp['status'] == '200':
-            print('coverage report failed with: %s:' % (resp['status'] + ': '
-                                                        + body))
-            exit(int(resp['status']))
-        path = body['path']
-        if CLI.output:
-            if CLI.html:
-                shutil.copytree(path, CLI.output)
-            else:
-                path = os.path.dirname(path)
-                shutil.copytree(path, CLI.output)
-        else:
-            if not CLI.html:
-                path = os.path.dirname(path)
-            print('Report files located at: %s' % path)
-
-    else:
-        print('Invalid command')
-        exit(1)
-
-
-if __name__ == "__main__":
-    main(sys.argv)
diff --git a/tools/verify_tempest_config.py b/tools/verify_tempest_config.py
index 1b5fe68..347659d 100755
--- a/tools/verify_tempest_config.py
+++ b/tools/verify_tempest_config.py
@@ -36,11 +36,11 @@
     __, versions = os.image_client.get_versions()
     if CONF.image_feature_enabled.api_v1 != ('v1.1' in versions or 'v1.0' in
                                              versions):
-        print 'Config option image api_v1 should be change to: %s' % (
-            not CONF.image_feature_enabled.api_v1)
+        print('Config option image api_v1 should be change to: %s' % (
+            not CONF.image_feature_enabled.api_v1))
     if CONF.image_feature_enabled.api_v2 != ('v2.0' in versions):
-        print 'Config option image api_v2 should be change to: %s' % (
-            not CONF.image_feature_enabled.api_v2)
+        print('Config option image api_v2 should be change to: %s' % (
+            not CONF.image_feature_enabled.api_v2))
 
 
 def verify_extensions(os):
@@ -62,8 +62,8 @@
     for option in NOVA_EXTENSIONS.keys():
         config_value = getattr(CONF.compute_feature_enabled, option)
         if config_value != results['nova_features'][option]:
-            print "Config option: %s should be changed to: %s" % (
-                option, not config_value)
+            print("Config option: %s should be changed to: %s" % (
+                option, not config_value))
 
 
 def main(argv):
diff --git a/tox.ini b/tox.ini
index a3c781b..1d7e1b7 100644
--- a/tox.ini
+++ b/tox.ini
@@ -9,6 +9,7 @@
          LANGUAGE=en_US:en
          LC_ALL=C
 usedevelop = True
+install_command = pip install -U {opts} {packages}
 
 [testenv:py26]
 commands = python setup.py test --slowest --testr-arg='tempest\.tests {posargs}'
@@ -30,19 +31,19 @@
 # The regex below is used to select which tests to run and exclude the slow tag:
 # See the testrepostiory bug: https://bugs.launchpad.net/testrepository/+bug/1208610
 commands =
-  sh tools/pretty_tox.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty|cli)) {posargs}'
+  bash tools/pretty_tox.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty|cli)) {posargs}'
 
 [testenv:testr-full]
 sitepackages = True
 commands =
-  sh tools/pretty_tox.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty|cli)) {posargs}'
+  bash tools/pretty_tox.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty|cli)) {posargs}'
 
 [testenv:heat-slow]
 sitepackages = True
 setenv = OS_TEST_TIMEOUT=1200
 # The regex below is used to select heat api/scenario tests tagged as slow.
 commands =
-  sh tools/pretty_tox_serial.sh '(?=.*\[.*\bslow\b.*\])(^tempest\.(api|scenario)\.orchestration) {posargs}'
+  bash tools/pretty_tox_serial.sh '(?=.*\[.*\bslow\b.*\])(^tempest\.(api|scenario)\.orchestration) {posargs}'
 
 [testenv:large-ops]
 sitepackages = True
@@ -77,18 +78,16 @@
 
 [testenv:smoke]
 sitepackages = True
+commands =
+   bash tools/pretty_tox.sh '(?!.*\[.*\bslow\b.*\])((smoke)|(^tempest\.scenario)) {posargs}'
+
+[testenv:smoke-serial]
+sitepackages = True
 # This is still serial because neutron doesn't work with parallel. See:
 # https://bugs.launchpad.net/tempest/+bug/1216076 so the neutron smoke
 # job would fail if we moved it to parallel.
 commands =
-   sh tools/pretty_tox_serial.sh '(?!.*\[.*\bslow\b.*\])((smoke)|(^tempest\.scenario)) {posargs}'
-
-[testenv:coverage]
-sitepackages = True
-commands =
-   python -m tools/tempest_coverage -c start --combine
-   sh tools/pretty_tox.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty|cli))'
-   python -m tools/tempest_coverage -c report --html {posargs}
+   bash tools/pretty_tox_serial.sh '(?!.*\[.*\bslow\b.*\])((smoke)|(^tempest\.scenario)) {posargs}'
 
 [testenv:stress]
 sitepackages = True
@@ -101,7 +100,11 @@
        -r{toxinidir}/test-requirements.txt
 
 [testenv:pep8]
-commands = flake8
+setenv = MODULEPATH=tempest.common.generate_sample_tempest
+commands =
+   flake8 {posargs}
+   {toxinidir}/tools/config/check_uptodate.sh
+
 deps = -r{toxinidir}/requirements.txt
        -r{toxinidir}/test-requirements.txt