Merge "Add tests for Swift's StaticWeb middelware"
diff --git a/.testr.conf b/.testr.conf
index 510f4c9..05b12c4 100644
--- a/.testr.conf
+++ b/.testr.conf
@@ -1,7 +1,7 @@
 [DEFAULT]
 test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
              OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
-             OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-250} \
+             OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-500} \
              ${PYTHON:-python} -m subunit.run discover -t ./ ./tempest $LISTOPT $IDOPTION
 test_id_option=--load-list $IDFILE
 test_list_option=--list
diff --git a/run_tests.sh b/run_tests.sh
index 856ce54..d672b62 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -124,7 +124,11 @@
 }
 
 function run_pep8 {
-  echo "Running pep8 ..."
+  echo "Running flake8 ..."
+  if [ $never_venv -eq 1 ]; then
+      echo "**WARNING**:" >&2
+      echo "Running flake8 without virtual env may miss OpenStack HACKING detection" >&2
+  fi
   ${wrapper} flake8
 }
 
diff --git a/tempest/api/compute/admin/test_flavors.py b/tempest/api/compute/admin/test_flavors.py
index 5f31084..7efd3c1 100644
--- a/tempest/api/compute/admin/test_flavors.py
+++ b/tempest/api/compute/admin/test_flavors.py
@@ -296,6 +296,24 @@
         _test_string_variations(['t', 'true', 'yes', '1'],
                                 flavor_name_public)
 
+    @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)
+
+        ram = " 1024 "
+        resp, flavor = self.client.create_flavor(flavor_name,
+                                                 ram, self.vcpus,
+                                                 self.disk,
+                                                 new_flavor_id)
+        self.addCleanup(self.flavor_clean_up, flavor['id'])
+        self.assertEqual(200, resp.status)
+        self.assertEqual(flavor['name'], flavor_name)
+        self.assertEqual(flavor['vcpus'], self.vcpus)
+        self.assertEqual(flavor['disk'], self.disk)
+        self.assertEqual(flavor['ram'], int(ram))
+        self.assertEqual(int(flavor['id']), new_flavor_id)
+
     @attr(type=['negative', 'gate'])
     def test_invalid_is_public_string(self):
         self.assertRaises(exceptions.BadRequest,
@@ -319,6 +337,26 @@
                           self.user_client.delete_flavor,
                           self.flavor_ref_alt)
 
+    @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)
+
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_flavor,
+                          flavor_name, -1, self.vcpus,
+                          self.disk, new_flavor_id)
+
+    @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)
+
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_flavor,
+                          flavor_name, self.ram, 0,
+                          self.disk, new_flavor_id)
+
 
 class FlavorsAdminTestXML(FlavorsAdminTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/compute/images/test_images_oneserver.py b/tempest/api/compute/images/test_images_oneserver.py
index 0052a30..06e9ab2 100644
--- a/tempest/api/compute/images/test_images_oneserver.py
+++ b/tempest/api/compute/images/test_images_oneserver.py
@@ -64,7 +64,7 @@
                 cls.alt_manager = clients.AltManager()
             cls.alt_client = cls.alt_manager.images_client
 
-    @testtools.skip("Until Bug #1006725 is fixed")
+    @testtools.skip("Skipped until the Bug #1006725 is resolved.")
     @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
diff --git a/tempest/api/compute/keypairs/test_keypairs.py b/tempest/api/compute/keypairs/test_keypairs.py
index 4848cce..083fbd7 100644
--- a/tempest/api/compute/keypairs/test_keypairs.py
+++ b/tempest/api/compute/keypairs/test_keypairs.py
@@ -84,9 +84,9 @@
         # Keypair should be created, Got details by name and deleted
         k_name = 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)
         self.assertEqual(200, resp.status)
-        self.addCleanup(self.client.delete_keypair, k_name)
         self.assertIn('name', keypair_detail)
         self.assertIn('public_key', keypair_detail)
         self.assertEqual(keypair_detail['name'], k_name,
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index ade7604..8d31598 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -205,7 +205,7 @@
         self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
         self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
 
-    @testtools.skip('Until Bug #1170718 is resolved.')
+    @testtools.skip('Skipped until the Bug #1170718 is resolved.')
     @attr(type='gate')
     def test_list_servers_filtered_by_ip(self):
         # Filter servers by ip
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 25df6e6..76ef461 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -86,7 +86,7 @@
             new_boot_time = linux_client.get_boot_time()
             self.assertGreater(new_boot_time, boot_time)
 
-    @testtools.skip('Until Bug #1014647 is dealt with.')
+    @testtools.skip('Skipped until the Bug #1014647 is resolved.')
     @attr(type='smoke')
     def test_reboot_server_soft(self):
         # The server should be signaled to reboot gracefully
@@ -238,7 +238,7 @@
                           self.servers_client.get_console_output,
                           '!@#$%^&*()', 10)
 
-    @testtools.skip('Until tempest Bug #1014683 is fixed.')
+    @testtools.skip('Skipped until the Bug #1014683 is resolved.')
     @attr(type='gate')
     def test_get_console_output_server_id_in_reboot_status(self):
         # Positive test:Should be able to GET the console output
diff --git a/tempest/api/compute/servers/test_virtual_interfaces.py b/tempest/api/compute/servers/test_virtual_interfaces.py
index e5ea30e..b743a85 100644
--- a/tempest/api/compute/servers/test_virtual_interfaces.py
+++ b/tempest/api/compute/servers/test_virtual_interfaces.py
@@ -37,8 +37,8 @@
         resp, server = cls.create_server(wait_until='ACTIVE')
         cls.server_id = server['id']
 
-    @testtools.skipIf(CONF.service_available.neutron, "This feature is not " +
-                      "implemented by Neutron. See bug: #1183436")
+    @testtools.skipIf(CONF.service_available.neutron, "Not implemented by " +
+                      "Neutron. Skipped until the Bug #1183436 is resolved.")
     @attr(type='gate')
     def test_list_virtual_interfaces(self):
         # Positive test:Should be able to GET the virtual interfaces list
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 7f49452..f3d1485 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -75,7 +75,7 @@
         for n in created_networks:
             self.assertNotIn(n['id'], networks_list)
 
-    @attr(type='gate')
+    @attr(type='smoke')
     def test_create_update_delete_network_subnet(self):
         # Creates a network
         name = rand_name('network-')
@@ -116,7 +116,7 @@
         resp, body = self.client.delete_network(net_id)
         self.assertEqual('204', resp['status'])
 
-    @attr(type='gate')
+    @attr(type='smoke')
     def test_show_network(self):
         # Verifies the details of a network
         resp, body = self.client.show_network(self.network['id'])
@@ -125,7 +125,7 @@
         self.assertEqual(self.network['id'], network['id'])
         self.assertEqual(self.name, network['name'])
 
-    @attr(type='gate')
+    @attr(type='smoke')
     def test_list_networks(self):
         # Verify the network exists in the list of all networks
         resp, body = self.client.list_networks()
@@ -138,7 +138,7 @@
         msg = "Network list doesn't contain created network"
         self.assertIsNotNone(found, msg)
 
-    @attr(type='gate')
+    @attr(type='smoke')
     def test_show_subnet(self):
         # Verifies the details of a subnet
         resp, body = self.client.show_subnet(self.subnet['id'])
@@ -147,7 +147,7 @@
         self.assertEqual(self.subnet['id'], subnet['id'])
         self.assertEqual(self.cidr, subnet['cidr'])
 
-    @attr(type='gate')
+    @attr(type='smoke')
     def test_list_subnets(self):
         # Verify the subnet exists in the list of all subnets
         resp, body = self.client.list_subnets()
@@ -160,7 +160,7 @@
         msg = "Subnet list doesn't contain created subnet"
         self.assertIsNotNone(found, msg)
 
-    @attr(type='gate')
+    @attr(type='smoke')
     def test_create_update_delete_port(self):
         # Verify that successful port creation, update & deletion
         resp, body = self.client.create_port(self.network['id'])
@@ -176,7 +176,7 @@
         resp, body = self.client.delete_port(port['id'])
         self.assertEqual('204', resp['status'])
 
-    @attr(type='gate')
+    @attr(type='smoke')
     def test_show_port(self):
         # Verify the details of port
         resp, body = self.client.show_port(self.port['id'])
@@ -184,7 +184,7 @@
         port = body['port']
         self.assertEqual(self.port['id'], port['id'])
 
-    @attr(type='gate')
+    @attr(type='smoke')
     def test_list_ports(self):
         # Verify the port exists in the list of all ports
         resp, body = self.client.list_ports()
@@ -196,19 +196,19 @@
                 found = n['id']
         self.assertIsNotNone(found, "Port list doesn't contain created port")
 
-    @attr(type=['negative', 'gate'])
+    @attr(type=['negative', 'smoke'])
     def test_show_non_existent_network(self):
         non_exist_id = rand_name('network')
         self.assertRaises(exceptions.NotFound, self.client.show_network,
                           non_exist_id)
 
-    @attr(type=['negative', 'gate'])
+    @attr(type=['negative', 'smoke'])
     def test_show_non_existent_subnet(self):
         non_exist_id = rand_name('subnet')
         self.assertRaises(exceptions.NotFound, self.client.show_subnet,
                           non_exist_id)
 
-    @attr(type='gate')
+    @attr(type='smoke')
     def test_bulk_create_delete_network(self):
         # Creates 2 networks in one request
         network_names = [rand_name('network-'), rand_name('network-')]
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index 4f687b0..9f8c742 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -49,7 +49,7 @@
             router_id, port_id)
         self.assertEqual('200', resp['status'])
 
-    @attr(type='gate')
+    @attr(type='smoke')
     def test_create_show_list_update_delete_router(self):
         # Create a router
         name = rand_name('router-')
@@ -90,7 +90,7 @@
             create_body['router']['id'])
         self.assertEqual(show_body['router']['name'], updated_name)
 
-    @attr(type='gate')
+    @attr(type='smoke')
     def test_add_remove_router_interface_with_subnet_id(self):
         network = self.create_network()
         subnet = self.create_subnet(network)
@@ -111,7 +111,7 @@
         self.assertEqual(show_port_body['port']['device_id'],
                          create_body['router']['id'])
 
-    @attr(type='gate')
+    @attr(type='smoke')
     def test_add_remove_router_interface_with_port_id(self):
         network = self.create_network()
         self.create_subnet(network)
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index d18c2ad..66a74e4 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -52,7 +52,7 @@
             cls.delete_containers(cls.containers, client[0], client[1])
         super(ContainerSyncTest, cls).tearDownClass()
 
-    @testtools.skip('Until Bug #1093743 is resolved.')
+    @testtools.skip('Skipped until the Bug #1093743 is resolved.')
     @attr(type='gate')
     def test_container_synchronization(self):
         # container to container synchronization
diff --git a/tempest/api/object_storage/test_object_expiry.py b/tempest/api/object_storage/test_object_expiry.py
index 8703480..889436d 100644
--- a/tempest/api/object_storage/test_object_expiry.py
+++ b/tempest/api/object_storage/test_object_expiry.py
@@ -43,7 +43,7 @@
         cls.delete_containers([cls.container_name])
         super(ObjectExpiryTest, cls).tearDownClass()
 
-    @testtools.skip('Until Bug #1069849 is resolved.')
+    @testtools.skip('Skipped until the Bug #1069849 is resolved.')
     @attr(type='gate')
     def test_get_object_after_expiry_time(self):
         # TODO(harika-vakadi): similar test case has to be created for
diff --git a/tempest/api/orchestration/base.py b/tempest/api/orchestration/base.py
index 745dd87..2a72c95 100644
--- a/tempest/api/orchestration/base.py
+++ b/tempest/api/orchestration/base.py
@@ -89,8 +89,8 @@
                 pass
 
     @classmethod
-    def _create_keypair(cls, namestart='keypair-heat-'):
-        kp_name = rand_name(namestart)
+    def _create_keypair(cls, name_start='keypair-heat-'):
+        kp_name = 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_neutron_resources.py b/tempest/api/orchestration/stacks/test_neutron_resources.py
new file mode 100644
index 0000000..c934020
--- /dev/null
+++ b/tempest/api/orchestration/stacks/test_neutron_resources.py
@@ -0,0 +1,211 @@
+# 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.
+
+
+import logging
+
+from tempest.api.orchestration import base
+from tempest import clients
+from tempest.common.utils.data_utils import rand_name
+from tempest.test import attr
+
+
+LOG = logging.getLogger(__name__)
+
+
+class NeutronResourcesTestJSON(base.BaseOrchestrationTest):
+    _interface = 'json'
+
+    template = """
+HeatTemplateFormatVersion: '2012-12-12'
+Description: |
+  Template which creates single EC2 instance
+Parameters:
+  KeyName:
+    Type: String
+  InstanceType:
+    Type: String
+  ImageId:
+    Type: String
+  ExternalRouterId:
+    Type: String
+Resources:
+  Network:
+    Type: OS::Quantum::Net
+    Properties: {name: NewNetwork}
+  Subnet:
+    Type: OS::Quantum::Subnet
+    Properties:
+      network_id: {Ref: Network}
+      name: NewSubnet
+      ip_version: 4
+      cidr: 10.0.3.0/24
+      dns_nameservers: ["8.8.8.8"]
+      allocation_pools:
+      - {end: 10.0.3.150, start: 10.0.3.20}
+  RouterInterface:
+    Type: OS::Quantum::RouterInterface
+    Properties:
+      router_id: {Ref: ExternalRouterId}
+      subnet_id: {Ref: Subnet}
+  Server:
+    Type: AWS::EC2::Instance
+    Metadata:
+      Name: SmokeServer
+    Properties:
+      ImageId: {Ref: ImageId}
+      InstanceType: {Ref: InstanceType}
+      KeyName: {Ref: KeyName}
+      SubnetId: {Ref: Subnet}
+      UserData:
+        Fn::Base64:
+          Fn::Join:
+          - ''
+          - - '#!/bin/bash -v
+
+              '
+            - /opt/aws/bin/cfn-signal -e 0 -r "SmokeServer created" '
+            - {Ref: WaitHandle}
+            - '''
+
+              '
+  WaitHandle:
+    Type: AWS::CloudFormation::WaitConditionHandle
+  WaitCondition:
+    Type: AWS::CloudFormation::WaitCondition
+    DependsOn: Server
+    Properties:
+      Handle: {Ref: WaitHandle}
+      Timeout: '600'
+"""
+
+    @classmethod
+    def setUpClass(cls):
+        super(NeutronResourcesTestJSON, cls).setUpClass()
+        if not cls.orchestration_cfg.image_ref:
+            raise cls.skipException("No image available to test")
+        cls.client = cls.orchestration_client
+        os = clients.Manager()
+        cls.network_cfg = os.config.network
+        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.keypair_name = (cls.orchestration_cfg.keypair_name or
+                            cls._create_keypair()['name'])
+        cls.external_router_id = cls._get_external_router_id()
+
+        # create the stack
+        cls.stack_identifier = cls.create_stack(
+            cls.stack_name,
+            cls.template,
+            parameters={
+                'KeyName': cls.keypair_name,
+                'InstanceType': cls.orchestration_cfg.instance_type,
+                'ImageId': cls.orchestration_cfg.image_ref,
+                'ExternalRouterId': cls.external_router_id
+            })
+        cls.stack_id = cls.stack_identifier.split('/')[1]
+        cls.client.wait_for_stack_status(cls.stack_id, 'CREATE_COMPLETE')
+        _, resources = cls.client.list_resources(cls.stack_identifier)
+        cls.test_resources = {}
+        for resource in resources:
+            cls.test_resources[resource['logical_resource_id']] = resource
+
+    @classmethod
+    def _get_external_router_id(cls):
+        resp, body = cls.network_client.list_ports()
+        ports = body['ports']
+        router_ports = filter(lambda port: port['device_owner'] ==
+                              'network:router_interface', ports)
+        return router_ports[0]['device_id']
+
+    @attr(type='slow')
+    def test_created_resources(self):
+        """Verifies created neutron resources."""
+        resources = [('Network', 'OS::Quantum::Net'),
+                     ('Subnet', 'OS::Quantum::Subnet'),
+                     ('RouterInterface', 'OS::Quantum::RouterInterface'),
+                     ('Server', 'AWS::EC2::Instance')]
+        for resource_name, resource_type in resources:
+            resource = self.test_resources.get(resource_name, None)
+            self.assertIsInstance(resource, dict)
+            self.assertEqual(resource_name, resource['logical_resource_id'])
+            self.assertEqual(resource_type, resource['resource_type'])
+            self.assertEqual('CREATE_COMPLETE', resource['resource_status'])
+
+    @attr(type='slow')
+    def test_created_network(self):
+        """Verifies created netowrk."""
+        network_id = self.test_resources.get('Network')['physical_resource_id']
+        resp, body = self.network_client.show_network(network_id)
+        self.assertEqual('200', resp['status'])
+        network = body['network']
+        self.assertIsInstance(network, dict)
+        self.assertEqual(network_id, network['id'])
+        self.assertEqual('NewNetwork', network['name'])
+
+    @attr(type='slow')
+    def test_created_subnet(self):
+        """Verifies created subnet."""
+        subnet_id = self.test_resources.get('Subnet')['physical_resource_id']
+        resp, body = self.network_client.show_subnet(subnet_id)
+        self.assertEqual('200', resp['status'])
+        subnet = body['subnet']
+        network_id = self.test_resources.get('Network')['physical_resource_id']
+        self.assertEqual(subnet_id, subnet['id'])
+        self.assertEqual(network_id, subnet['network_id'])
+        self.assertEqual('NewSubnet', subnet['name'])
+        self.assertEqual('8.8.8.8', subnet['dns_nameservers'][0])
+        self.assertEqual('10.0.3.20', subnet['allocation_pools'][0]['start'])
+        self.assertEqual('10.0.3.150', subnet['allocation_pools'][0]['end'])
+        self.assertEqual(4, subnet['ip_version'])
+        self.assertEqual('10.0.3.0/24', subnet['cidr'])
+
+    @attr(type='slow')
+    def test_created_router_interface(self):
+        """Verifies created router interface."""
+        network_id = self.test_resources.get('Network')['physical_resource_id']
+        subnet_id = self.test_resources.get('Subnet')['physical_resource_id']
+        resp, body = self.network_client.list_ports()
+        self.assertEqual('200', resp['status'])
+        ports = body['ports']
+        router_ports = filter(lambda port: port['device_id'] ==
+                              self.external_router_id, ports)
+        created_network_ports = filter(lambda port: port['network_id'] ==
+                                       network_id, router_ports)
+        self.assertEqual(1, len(created_network_ports))
+        router_interface = created_network_ports[0]
+        fixed_ips = router_interface['fixed_ips']
+        subnet_fixed_ips = filter(lambda port: port['subnet_id'] ==
+                                  subnet_id, fixed_ips)
+        self.assertEqual(1, len(subnet_fixed_ips))
+        router_interface_ip = subnet_fixed_ips[0]['ip_address']
+        self.assertEqual('10.0.3.1', router_interface_ip)
+
+    @attr(type='slow')
+    def test_created_server(self):
+        """Verifies created sever."""
+        server_id = self.test_resources.get('Server')['physical_resource_id']
+        resp, server = self.servers_client.get_server(server_id)
+        self.assertEqual('200', resp['status'])
+        self.assertEqual(self.keypair_name, server['key_name'])
+        self.assertEqual('ACTIVE', server['status'])
+        network = server['addresses']['NewNetwork'][0]
+        self.assertEqual(4, network['version'])
+        ip_addr_prefix = network['addr'][:7]
+        ip_addr_suffix = int(network['addr'].split('.')[3])
+        self.assertEqual('10.0.3.', ip_addr_prefix)
+        self.assertTrue(ip_addr_suffix >= 20)
+        self.assertTrue(ip_addr_suffix <= 150)
diff --git a/tempest/api/orchestration/stacks/test_non_empty_stack.py b/tempest/api/orchestration/stacks/test_non_empty_stack.py
new file mode 100644
index 0000000..defb910
--- /dev/null
+++ b/tempest/api/orchestration/stacks/test_non_empty_stack.py
@@ -0,0 +1,169 @@
+# 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.
+
+import logging
+
+from tempest.api.orchestration import base
+from tempest.common.utils.data_utils import rand_name
+from tempest.test import attr
+
+
+LOG = logging.getLogger(__name__)
+
+
+class StacksTestJSON(base.BaseOrchestrationTest):
+    _interface = 'json'
+
+    template = """
+HeatTemplateFormatVersion: '2012-12-12'
+Description: |
+  Template which creates single EC2 instance
+Parameters:
+  KeyName:
+    Type: String
+  InstanceType:
+    Type: String
+  ImageId:
+    Type: String
+Resources:
+  SmokeServer:
+    Type: AWS::EC2::Instance
+    Metadata:
+      Name: SmokeServer
+    Properties:
+      ImageId: {Ref: ImageId}
+      InstanceType: {Ref: InstanceType}
+      KeyName: {Ref: KeyName}
+      UserData:
+        Fn::Base64:
+          Fn::Join:
+          - ''
+          - - '#!/bin/bash -v
+
+              '
+            - /opt/aws/bin/cfn-signal -e 0 -r "SmokeServer created" '
+            - {Ref: WaitHandle}
+            - '''
+
+              '
+  WaitHandle:
+    Type: AWS::CloudFormation::WaitConditionHandle
+  WaitCondition:
+    Type: AWS::CloudFormation::WaitCondition
+    DependsOn: SmokeServer
+    Properties:
+      Handle: {Ref: WaitHandle}
+      Timeout: '600'
+"""
+
+    @classmethod
+    def setUpClass(cls):
+        super(StacksTestJSON, cls).setUpClass()
+        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')
+        keypair_name = (cls.orchestration_cfg.keypair_name or
+                        cls._create_keypair()['name'])
+
+        # create the stack
+        cls.stack_identifier = cls.create_stack(
+            cls.stack_name,
+            cls.template,
+            parameters={
+                'KeyName': keypair_name,
+                'InstanceType': cls.orchestration_cfg.instance_type,
+                'ImageId': cls.orchestration_cfg.image_ref
+            })
+        cls.stack_id = cls.stack_identifier.split('/')[1]
+        cls.resource_name = 'SmokeServer'
+        cls.resource_type = 'AWS::EC2::Instance'
+        cls.client.wait_for_stack_status(cls.stack_id, 'CREATE_COMPLETE')
+
+    @attr(type='slow')
+    def test_stack_list(self):
+        """Created stack should be on the list of existing stacks."""
+        resp, stacks = self.client.list_stacks()
+        self.assertEqual('200', resp['status'])
+        self.assertIsInstance(stacks, list)
+        stacks_names = map(lambda stack: stack['stack_name'], stacks)
+        self.assertIn(self.stack_name, stacks_names)
+
+    @attr(type='slow')
+    def test_stack_show(self):
+        """Getting details about created stack should be possible."""
+        resp, stack = self.client.get_stack(self.stack_name)
+        self.assertEqual('200', resp['status'])
+        self.assertIsInstance(stack, dict)
+        self.assertEqual(self.stack_name, stack['stack_name'])
+        self.assertEqual(self.stack_id, stack['id'])
+
+    @attr(type='slow')
+    def test_list_resources(self):
+        """Getting list of created resources for the stack should be possible.
+        """
+        resp, resources = self.client.list_resources(self.stack_identifier)
+        self.assertEqual('200', resp['status'])
+        self.assertIsInstance(resources, list)
+        resources_names = map(lambda resource: resource['logical_resource_id'],
+                              resources)
+        self.assertIn(self.resource_name, resources_names)
+        resources_types = map(lambda resource: resource['resource_type'],
+                              resources)
+        self.assertIn(self.resource_type, resources_types)
+
+    @attr(type='slow')
+    def test_show_resource(self):
+        """Getting details about created resource should be possible."""
+        resp, resource = self.client.get_resource(self.stack_identifier,
+                                                  self.resource_name)
+        self.assertIsInstance(resource, dict)
+        self.assertEqual(self.resource_name, resource['logical_resource_id'])
+        self.assertEqual(self.resource_type, resource['resource_type'])
+
+    @attr(type='slow')
+    def test_resource_metadata(self):
+        """Getting metadata for created resource should be possible."""
+        resp, metadata = self.client.show_resource_metadata(
+            self.stack_identifier,
+            self.resource_name)
+        self.assertEqual('200', resp['status'])
+        self.assertIsInstance(metadata, dict)
+        self.assertEqual(self.resource_name, metadata.get('Name', None))
+
+    @attr(type='slow')
+    def test_list_events(self):
+        """Getting list of created events for the stack should be possible."""
+        resp, events = self.client.list_events(self.stack_identifier)
+        self.assertEqual('200', resp['status'])
+        self.assertIsInstance(events, list)
+        resource_statuses = map(lambda event: event['resource_status'], events)
+        self.assertIn('CREATE_IN_PROGRESS', resource_statuses)
+        self.assertIn('CREATE_COMPLETE', resource_statuses)
+
+    @attr(type='slow')
+    def test_show_event(self):
+        """Getting details about existing event should be possible."""
+        resp, events = self.client.list_resource_events(self.stack_identifier,
+                                                        self.resource_name)
+        self.assertNotEqual([], events)
+        events.sort(key=lambda event: event['event_time'])
+        event_id = events[0]['id']
+        resp, event = self.client.show_event(self.stack_identifier,
+                                             self.resource_name, event_id)
+        self.assertEqual('200', resp['status'])
+        self.assertEqual('CREATE_IN_PROGRESS', event['resource_status'])
+        self.assertEqual('state changed', event['resource_status_reason'])
+        self.assertEqual(self.resource_name, event['logical_resource_id'])
+        self.assertIsInstance(event, dict)
diff --git a/tempest/api/orchestration/stacks/test_instance_cfn_init.py b/tempest/api/orchestration/stacks/test_server_cfn_init.py
similarity index 90%
rename from tempest/api/orchestration/stacks/test_instance_cfn_init.py
rename to tempest/api/orchestration/stacks/test_server_cfn_init.py
index fe55ecf..ffe8def 100644
--- a/tempest/api/orchestration/stacks/test_instance_cfn_init.py
+++ b/tempest/api/orchestration/stacks/test_server_cfn_init.py
@@ -26,7 +26,7 @@
 LOG = logging.getLogger(__name__)
 
 
-class InstanceCfnInitTestJSON(base.BaseOrchestrationTest):
+class ServerCfnInitTestJSON(base.BaseOrchestrationTest):
     _interface = 'json'
     existing_keypair = (tempest.config.TempestConfig().
                         orchestration.keypair_name is not None)
@@ -37,11 +37,11 @@
   Template which uses a wait condition to confirm that a minimal
   cfn-init and cfn-signal has worked
 Parameters:
-  KeyName:
+  key_name:
     Type: String
-  InstanceType:
+  flavor:
     Type: String
-  ImageId:
+  image:
     Type: String
 Resources:
   CfnUser:
@@ -58,7 +58,7 @@
     Properties:
       UserName: {Ref: CfnUser}
   SmokeServer:
-    Type: AWS::EC2::Instance
+    Type: OS::Nova::Server
     Metadata:
       AWS::CloudFormation::Init:
         config:
@@ -83,12 +83,12 @@
               owner: root
               group: root
     Properties:
-      ImageId: {Ref: ImageId}
-      InstanceType: {Ref: InstanceType}
-      KeyName: {Ref: KeyName}
-      SecurityGroups:
+      image: {Ref: image}
+      flavor: {Ref: flavor}
+      key_name: {Ref: key_name}
+      security_groups:
       - {Ref: SmokeSecurityGroup}
-      UserData:
+      user_data:
         Fn::Base64:
           Fn::Join:
           - ''
@@ -118,12 +118,12 @@
   SmokeServerIp:
     Description: IP address of server
     Value:
-      Fn::GetAtt: [SmokeServer, PublicIp]
+      Fn::GetAtt: [SmokeServer, first_private_address]
 """
 
     @classmethod
     def setUpClass(cls):
-        super(InstanceCfnInitTestJSON, cls).setUpClass()
+        super(ServerCfnInitTestJSON, cls).setUpClass()
         if not cls.orchestration_cfg.image_ref:
             raise cls.skipException("No image available to test")
         cls.client = cls.orchestration_client
@@ -140,9 +140,9 @@
             stack_name,
             cls.template,
             parameters={
-                'KeyName': keypair_name,
-                'InstanceType': cls.orchestration_cfg.instance_type,
-                'ImageId': cls.orchestration_cfg.image_ref
+                'key_name': keypair_name,
+                'flavor': cls.orchestration_cfg.instance_type,
+                'image': cls.orchestration_cfg.image_ref
             })
 
     @attr(type='slow')
@@ -187,7 +187,7 @@
         # This is an assert of great significance, as it means the following
         # has happened:
         # - cfn-init read the provided metadata and wrote out a file
-        # - a user was created and credentials written to the instance
+        # - a user was created and credentials written to the server
         # - a cfn-signal was built which was signed with provided credentials
         # - the wait condition was fulfilled and the stack has changed state
         wait_status = json.loads(
diff --git a/tempest/api/orchestration/stacks/test_stacks.py b/tempest/api/orchestration/stacks/test_stacks.py
index f1f1f7e..4bda5ab 100644
--- a/tempest/api/orchestration/stacks/test_stacks.py
+++ b/tempest/api/orchestration/stacks/test_stacks.py
@@ -33,8 +33,7 @@
 
     @attr(type='smoke')
     def test_stack_list_responds(self):
-        resp, body = self.client.list_stacks()
-        stacks = body['stacks']
+        resp, stacks = self.client.list_stacks()
         self.assertEqual('200', resp['status'])
         self.assertIsInstance(stacks, list)
 
@@ -42,9 +41,6 @@
     def test_stack_crud_no_resources(self):
         stack_name = rand_name('heat')
 
-        # count how many stacks to start with
-        resp, body = self.client.list_stacks()
-
         # create the stack
         stack_identifier = self.create_stack(
             stack_name, self.empty_template)
@@ -54,21 +50,21 @@
         self.client.wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
 
         # check for stack in list
-        resp, body = self.client.list_stacks()
-        list_ids = list([stack['id'] for stack in body['stacks']])
+        resp, stacks = self.client.list_stacks()
+        list_ids = list([stack['id'] for stack in stacks])
         self.assertIn(stack_id, list_ids)
 
         # fetch the stack
-        resp, body = self.client.get_stack(stack_identifier)
-        self.assertEqual('CREATE_COMPLETE', body['stack_status'])
+        resp, stack = self.client.get_stack(stack_identifier)
+        self.assertEqual('CREATE_COMPLETE', stack['stack_status'])
 
         # fetch the stack by name
-        resp, body = self.client.get_stack(stack_name)
-        self.assertEqual('CREATE_COMPLETE', body['stack_status'])
+        resp, stack = self.client.get_stack(stack_name)
+        self.assertEqual('CREATE_COMPLETE', stack['stack_status'])
 
         # fetch the stack by id
-        resp, body = self.client.get_stack(stack_id)
-        self.assertEqual('CREATE_COMPLETE', body['stack_status'])
+        resp, stack = self.client.get_stack(stack_id)
+        self.assertEqual('CREATE_COMPLETE', stack['stack_status'])
 
         # delete the stack
         resp = self.client.delete_stack(stack_identifier)
diff --git a/tempest/api/orchestration/stacks/test_templates.py b/tempest/api/orchestration/stacks/test_templates.py
new file mode 100644
index 0000000..6a7c541
--- /dev/null
+++ b/tempest/api/orchestration/stacks/test_templates.py
@@ -0,0 +1,86 @@
+# 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.
+
+import logging
+
+from tempest.api.orchestration import base
+from tempest.common.utils.data_utils import rand_name
+from tempest import exceptions
+from tempest.test import attr
+
+
+LOG = logging.getLogger(__name__)
+
+
+class TemplateYAMLTestJSON(base.BaseOrchestrationTest):
+    _interface = 'json'
+
+    template = """
+HeatTemplateFormatVersion: '2012-12-12'
+Description: |
+  Template which creates only a new user
+Resources:
+  CfnUser:
+    Type: AWS::IAM::User
+"""
+
+    invalid_template_url = 'http://www.example.com/template.yaml'
+
+    @classmethod
+    def setUpClass(cls):
+        super(TemplateYAMLTestJSON, cls).setUpClass()
+        cls.client = cls.orchestration_client
+        cls.stack_name = 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')
+        cls.stack_id = cls.stack_identifier.split('/')[1]
+        cls.parameters = {}
+
+    @attr(type='gate')
+    def test_show_template(self):
+        """Getting template used to create the stack."""
+        resp, template = self.client.show_template(self.stack_identifier)
+        self.assertEqual('200', resp['status'])
+
+    @attr(type='gate')
+    def test_validate_template(self):
+        """Validating template passing it content."""
+        resp, parameters = self.client.validate_template(self.template,
+                                                         self.parameters)
+        self.assertEqual('200', resp['status'])
+
+    @attr(type=['gate', 'negative'])
+    def test_validate_template_url(self):
+        """Validating template passing url to it."""
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.validate_template_url,
+                          template_url=self.invalid_template_url,
+                          parameters=self.parameters)
+
+
+class TemplateAWSTestJSON(TemplateYAMLTestJSON):
+    template = """
+{
+  "AWSTemplateFormatVersion" : "2010-09-09",
+  "Description" : "Template which creates only a new user",
+  "Resources" : {
+    "CfnUser" : {
+      "Type" : "AWS::IAM::User"
+    }
+  }
+}
+"""
+
+    invalid_template_url = 'http://www.example.com/template.template'
diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py
index 5d5fd7e..8c39e08 100644
--- a/tempest/api/volume/test_volumes_list.py
+++ b/tempest/api/volume/test_volumes_list.py
@@ -32,6 +32,19 @@
 
     _interface = 'json'
 
+    def assertVolumesIn(self, fetched_list, expected_list):
+        missing_vols = [v for v in expected_list if v not in fetched_list]
+        if len(missing_vols) == 0:
+            return
+
+        def str_vol(vol):
+            return "%s:%s" % (vol['id'], vol['display_name'])
+
+        raw_msg = "Could not find volumes %s in expected list %s; fetched %s"
+        self.fail(raw_msg % ([str_vol(v) for v in missing_vols],
+                             [str_vol(v) for v in expected_list],
+                             [str_vol(v) for v in fetched_list]))
+
     @classmethod
     def setUpClass(cls):
         super(VolumesListTest, cls).setUpClass()
@@ -82,12 +95,7 @@
         # Fetch all volumes
         resp, fetched_list = self.client.list_volumes()
         self.assertEqual(200, resp.status)
-        # Now check if all the volumes created in setup are in fetched list
-        missing_vols = [v for v in self.volume_list if v not in fetched_list]
-        self.assertFalse(missing_vols,
-                         "Failed to find volume %s in fetched list" %
-                         ', '.join(m_vol['display_name']
-                                   for m_vol in missing_vols))
+        self.assertVolumesIn(fetched_list, self.volume_list)
 
     @attr(type='gate')
     def test_volume_list_with_details(self):
@@ -95,12 +103,7 @@
         # Fetch all Volumes
         resp, fetched_list = self.client.list_volumes_with_detail()
         self.assertEqual(200, resp.status)
-        # Verify that all the volumes are returned
-        missing_vols = [v for v in self.volume_list if v not in fetched_list]
-        self.assertFalse(missing_vols,
-                         "Failed to find volume %s in fetched list" %
-                         ', '.join(m_vol['display_name']
-                                   for m_vol in missing_vols))
+        self.assertVolumesIn(fetched_list, self.volume_list)
 
 
 class VolumeListTestXML(VolumesListTest):
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index d744e3d..8dfff6e 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -307,6 +307,12 @@
         self.LOG.info("Response Status: " + status)
         headers = resp.copy()
         del headers['status']
+        if headers.get('x-compute-request-id'):
+            self.LOG.info("Nova request id: %s" %
+                          headers.pop('x-compute-request-id'))
+        elif headers.get('x-openstack-request-id'):
+            self.LOG.info("Glance request id %s" %
+                          headers.pop('x-openstack-request-id'))
         if len(headers):
             self.LOG.debug('Response Headers: ' + str(headers))
         if resp_body:
diff --git a/tempest/common/ssh.py b/tempest/common/ssh.py
index be350c8..2ed1057 100644
--- a/tempest/common/ssh.py
+++ b/tempest/common/ssh.py
@@ -114,9 +114,13 @@
         err_data = []
         poll = select.poll()
         poll.register(channel, select.POLLIN)
+        start_time = time.time()
+
         while True:
             ready = poll.poll(self.channel_timeout)
             if not any(ready):
+                if not self._is_timed_out(self.timeout, start_time):
+                    continue
                 raise exceptions.TimeoutException(
                     "Command: '{0}' executed on host '{1}'.".format(
                         cmd, self.host))
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 1703248..7681f04 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -371,6 +371,24 @@
         LOG.debug("Created volume: %s", volume)
         return volume
 
+    def create_server_snapshot(self, server, compute_client=None,
+                               image_client=None, name=None):
+        if compute_client is None:
+            compute_client = self.compute_client
+        if image_client is None:
+            image_client = self.image_client
+        if name is None:
+            name = 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)
+        self.status_timeout(image_client.images, image_id, 'active')
+        snapshot_image = image_client.images.get(image_id)
+        self.assertEquals(name, snapshot_image.name)
+        LOG.debug("Created snapshot image %s for server %s",
+                  snapshot_image.name, server.name)
+        return snapshot_image
+
     def create_keypair(self, client=None, name=None):
         if client is None:
             client = self.compute_client
diff --git a/tempest/scenario/orchestration/test_autoscaling.py b/tempest/scenario/orchestration/test_autoscaling.py
index 17870a1..78025ee 100644
--- a/tempest/scenario/orchestration/test_autoscaling.py
+++ b/tempest/scenario/orchestration/test_autoscaling.py
@@ -12,16 +12,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.openstack.common import log as logging
 from tempest.scenario import manager
 from tempest.test import attr
 from tempest.test import call_until_true
 import time
 
 
-LOG = logging.getLogger(__name__)
-
-
 class AutoScalingTest(manager.OrchestrationScenarioTest):
 
     def setUp(self):
diff --git a/tempest/scenario/test_snapshot_pattern.py b/tempest/scenario/test_snapshot_pattern.py
index c55e2a3..003c264 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -15,14 +15,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.common.utils.data_utils import rand_name
-from tempest.openstack.common import log as logging
 from tempest.scenario import manager
 
 
-LOG = logging.getLogger(__name__)
-
-
 class TestSnapshotPattern(manager.OfficialClientTest):
     """
     This test is for snapshotting an instance and booting with it.
@@ -34,14 +29,6 @@
 
     """
 
-    def _wait_for_server_status(self, server, status):
-        self.status_timeout(self.compute_client.servers,
-                            server.id,
-                            status)
-
-    def _wait_for_image_status(self, image_id, status):
-        self.status_timeout(self.image_client.images, image_id, status)
-
     def _boot_image(self, image_id):
         create_kwargs = {
             'key_name': self.keypair.name
@@ -61,17 +48,6 @@
         ssh_client.exec_command('date > /tmp/timestamp; sync')
         self.timestamp = ssh_client.exec_command('cat /tmp/timestamp')
 
-    def _create_image(self, server):
-        snapshot_name = rand_name('scenario-snapshot-')
-        create_image_client = self.compute_client.servers.create_image
-        image_id = create_image_client(server, snapshot_name)
-        self.addCleanup(self.image_client.images.delete, image_id)
-        self._wait_for_server_status(server, 'ACTIVE')
-        self._wait_for_image_status(image_id, 'active')
-        snapshot_image = self.image_client.images.get(image_id)
-        self.assertEquals(snapshot_name, snapshot_image.name)
-        return image_id
-
     def _check_timestamp(self, server_or_ip):
         ssh_client = self._ssh_to_server(server_or_ip)
         got_timestamp = ssh_client.exec_command('cat /tmp/timestamp')
@@ -100,10 +76,10 @@
             self._write_timestamp(server)
 
         # snapshot the instance
-        snapshot_image_id = self._create_image(server)
+        snapshot_image = self.create_server_snapshot(server=server)
 
         # boot a second instance from the snapshot
-        server_from_snapshot = self._boot_image(snapshot_image_id)
+        server_from_snapshot = self._boot_image(snapshot_image.id)
 
         # check the existence of the timestamp file in the second instance
         if self.config.compute.use_floatingip_for_ssh:
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index c74b88d..5af4bb2 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -50,14 +50,6 @@
     14. Check the existence of a file which created at 6. in volume2
     """
 
-    def _wait_for_server_status(self, server, status):
-        self.status_timeout(self.compute_client.servers,
-                            server.id,
-                            status)
-
-    def _wait_for_image_status(self, image_id, status):
-        self.status_timeout(self.image_client.images, image_id, status)
-
     def _wait_for_volume_snapshot_status(self, volume_snapshot, status):
         self.status_timeout(self.volume_client.volume_snapshots,
                             volume_snapshot.id, status)
@@ -84,17 +76,6 @@
         linux_client = self.get_remote_client(server_or_ip)
         return linux_client.ssh_client
 
-    def _create_image(self, server):
-        snapshot_name = rand_name('scenario-snapshot-')
-        create_image_client = self.compute_client.servers.create_image
-        image_id = create_image_client(server, snapshot_name)
-        self.addCleanup(self.image_client.images.delete, image_id)
-        self._wait_for_server_status(server, 'ACTIVE')
-        self._wait_for_image_status(image_id, 'active')
-        snapshot_image = self.image_client.images.get(image_id)
-        self.assertEquals(snapshot_name, snapshot_image.name)
-        return image_id
-
     def _create_volume_snapshot(self, volume):
         snapshot_name = rand_name('scenario-snapshot-')
         volume_snapshots = self.volume_client.volume_snapshots
@@ -162,7 +143,7 @@
         got_timestamp = ssh_client.exec_command('sudo cat /mnt/timestamp')
         self.assertEqual(self.timestamp, got_timestamp)
 
-    @testtools.skip("Until Bug #1205344 is fixed")
+    @testtools.skip("Skipped until the Bug #1205344 is resolved.")
     def test_stamp_pattern(self):
         # prepare for booting a instance
         self._add_keypair()
@@ -189,14 +170,14 @@
         volume_snapshot = self._create_volume_snapshot(volume)
 
         # snapshot the instance
-        snapshot_image_id = self._create_image(server)
+        snapshot_image = self.create_server_snapshot(server=server)
 
         # create second volume from the snapshot(volume2)
         volume_from_snapshot = self._create_volume(
             snapshot_id=volume_snapshot.id)
 
         # boot second instance from the snapshot(instance2)
-        server_from_snapshot = self._boot_image(snapshot_image_id)
+        server_from_snapshot = self._boot_image(snapshot_image.id)
 
         # create and add floating IP to server_from_snapshot
         if self.config.compute.use_floatingip_for_ssh:
diff --git a/tempest/scenario/test_volume_snapshot_pattern.py b/tempest/scenario/test_volume_snapshot_pattern.py
index 8fa177e..d873d30 100644
--- a/tempest/scenario/test_volume_snapshot_pattern.py
+++ b/tempest/scenario/test_volume_snapshot_pattern.py
@@ -12,13 +12,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.openstack.common import log as logging
-
 from tempest.common.utils.data_utils import rand_name
 from tempest.scenario import manager
 
-LOG = logging.getLogger(__name__)
-
 
 class TestVolumeSnapshotPattern(manager.OfficialClientTest):
 
diff --git a/tempest/services/orchestration/json/orchestration_client.py b/tempest/services/orchestration/json/orchestration_client.py
index ef88eed..e896e0d 100644
--- a/tempest/services/orchestration/json/orchestration_client.py
+++ b/tempest/services/orchestration/json/orchestration_client.py
@@ -42,7 +42,7 @@
 
         resp, body = self.get(uri)
         body = json.loads(body)
-        return resp, body
+        return resp, body['stacks']
 
     def create_stack(self, name, disable_rollback=True, parameters={},
                      timeout_mins=60, template=None, template_url=None):
@@ -176,3 +176,64 @@
                            (stack_name, status, self.build_timeout))
                 raise exceptions.TimeoutException(message)
             time.sleep(self.build_interval)
+
+    def show_resource_metadata(self, stack_identifier, resource_name):
+        """Returns the resource's metadata."""
+        url = ('stacks/{stack_identifier}/resources/{resource_name}'
+               '/metadata'.format(**locals()))
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body['metadata']
+
+    def list_events(self, stack_identifier):
+        """Returns list of all events for a stack."""
+        url = 'stacks/{stack_identifier}/events'.format(**locals())
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body['events']
+
+    def list_resource_events(self, stack_identifier, resource_name):
+        """Returns list of all events for a resource from stack."""
+        url = ('stacks/{stack_identifier}/resources/{resource_name}'
+               '/events'.format(**locals()))
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body['events']
+
+    def show_event(self, stack_identifier, resource_name, event_id):
+        """Returns the details of a single stack's event."""
+        url = ('stacks/{stack_identifier}/resources/{resource_name}/events'
+               '/{event_id}'.format(**locals()))
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body['event']
+
+    def show_template(self, stack_identifier):
+        """Returns the template for the stack."""
+        url = ('stacks/{stack_identifier}/template'.format(**locals()))
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body
+
+    def _validate_template(self, post_body):
+        """Returns the validation request result."""
+        post_body = json.dumps(post_body)
+        resp, body = self.post('validate', post_body, self.headers)
+        body = json.loads(body)
+        return resp, body
+
+    def validate_template(self, template, parameters={}):
+        """Returns the validation result for a template with parameters."""
+        post_body = {
+            'template': template,
+            'parameters': parameters,
+        }
+        return self._validate_template(post_body)
+
+    def validate_template_url(self, template_url, parameters={}):
+        """Returns the validation result for a template with parameters."""
+        post_body = {
+            'template_url': template_url,
+            'parameters': parameters,
+        }
+        return self._validate_template(post_body)
diff --git a/tempest/stress/actions/ssh_floating.py b/tempest/stress/actions/ssh_floating.py
new file mode 100644
index 0000000..36ef023
--- /dev/null
+++ b/tempest/stress/actions/ssh_floating.py
@@ -0,0 +1,189 @@
+# 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.
+
+import socket
+import subprocess
+
+from tempest.common.utils.data_utils import rand_name
+import tempest.stress.stressaction as stressaction
+import tempest.test
+
+
+class FloatingStress(stressaction.StressAction):
+
+    # from the scenario manager
+    def ping_ip_address(self, ip_address):
+        cmd = ['ping', '-c1', '-w1', ip_address]
+
+        proc = subprocess.Popen(cmd,
+                                stdout=subprocess.PIPE,
+                                stderr=subprocess.PIPE)
+        proc.wait()
+        success = proc.returncode == 0
+        self.logger.info("%s(%s): %s", self.server_id, self.floating['ip'],
+                         "pong!" if success else "no pong :(")
+        return success
+
+    def tcp_connect_scan(self, addr, port):
+        # like tcp
+        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        try:
+            s.connect((addr, port))
+        except socket.error as exc:
+            self.logger.info("%s(%s): %s", self.server_id, self.floating['ip'],
+                             str(exc))
+            return False
+        self.logger.info("%s(%s): Connected :)", self.server_id,
+                         self.floating['ip'])
+        s.close()
+        return True
+
+    def check_port_ssh(self):
+        def func():
+            return self.tcp_connect_scan(self.floating['ip'], 22)
+        if not tempest.test.call_until_true(func, self.check_timeout,
+                                            self.check_interval):
+            raise RuntimeError("Cannot connect to the ssh port.")
+
+    def check_icmp_echo(self):
+        def func():
+            return self.ping_ip_address(self.floating['ip'])
+        if not tempest.test.call_until_true(func, self.check_timeout,
+                                            self.check_interval):
+            raise RuntimeError("Cannot ping the machine.")
+
+    def _create_vm(self):
+        self.name = name = rand_name("instance")
+        servers_client = self.manager.servers_client
+        self.logger.info("creating %s" % name)
+        vm_args = self.vm_extra_args.copy()
+        vm_args['security_groups'] = [{'name': self.sec_grp}]
+        resp, server = servers_client.create_server(name, self.image,
+                                                    self.flavor,
+                                                    **vm_args)
+        self.server_id = server['id']
+        assert(resp.status == 202)
+        if self.wait_after_vm_create:
+            self.manager.servers_client.wait_for_server_status(self.server_id,
+                                                               'ACTIVE')
+
+    def _destroy_vm(self):
+        self.logger.info("deleting %s" % self.server_id)
+        resp, _ = self.manager.servers_client.delete_server(self.server_id)
+        assert(resp.status == 204)  # It cannot be 204 if I had to wait..
+        self.manager.servers_client.wait_for_server_termination(self.server_id)
+        self.logger.info("deleted %s" % self.server_id)
+
+    def _create_sec_group(self):
+        sec_grp_cli = self.manager.security_groups_client
+        s_name = rand_name('sec_grp-')
+        s_description = rand_name('desc-')
+        _, _sec_grp = sec_grp_cli.create_security_group(s_name,
+                                                        s_description)
+        self.sec_grp = _sec_grp['id']
+        create_rule = sec_grp_cli.create_security_group_rule
+        create_rule(self.sec_grp, 'tcp', 22, 22)
+        create_rule(self.sec_grp, 'icmp', -1, -1)
+
+    def _destroy_sec_grp(self):
+        sec_grp_cli = self.manager.security_groups_client
+        sec_grp_cli.delete_security_group(self.sec_grp)
+
+    def _create_floating_ip(self):
+        floating_cli = self.manager.floating_ips_client
+        _, self.floating = floating_cli.create_floating_ip(self.floating_pool)
+
+    def _destroy_floating_ip(self):
+        cli = self.manager.floating_ips_client
+        cli.delete_floating_ip(self.floating['id'])
+        cli.wait_for_resource_deletion(self.floating['id'])
+        self.logger.info("Deleted Floating IP %s", str(self.floating['ip']))
+
+    def setUp(self, **kwargs):
+        self.image = self.manager.config.compute.image_ref
+        self.flavor = self.manager.config.compute.flavor_ref
+        self.vm_extra_args = kwargs.get('vm_extra_args', {})
+        self.wait_after_vm_create = kwargs.get('wait_after_vm_create',
+                                               True)
+        self.new_vm = kwargs.get('new_vm', False)
+        self.new_sec_grp = kwargs.get('new_sec_group', False)
+        self.new_floating = kwargs.get('new_floating', False)
+        self.reboot = kwargs.get('reboot', False)
+        self.floating_pool = kwargs.get('floating_pool', None)
+        self.verify = kwargs.get('verify', ('check_port_ssh',
+                                            'check_icmp_echo'))
+        self.check_timeout = kwargs.get('check_timeout', 120)
+        self.check_interval = kwargs.get('check_interval', 1)
+        self.wait_for_disassociate = kwargs.get('wait_for_disassociate',
+                                                True)
+
+        # allocate floating
+        if not self.new_floating:
+            self._create_floating_ip()
+        # add security group
+        if not self.new_sec_grp:
+            self._create_sec_group()
+        # create vm
+        if not self.new_vm:
+            self._create_vm()
+
+    def wait_disassociate(self):
+        cli = self.manager.floating_ips_client
+
+        def func():
+            _, floating = cli.get_floating_ip_details(self.floating['id'])
+            return floating['instance_id'] is None
+
+        if not tempest.test.call_until_true(func, self.check_timeout,
+                                            self.check_interval):
+            raise RuntimeError("IP disassociate timeout!")
+
+    def run_core(self):
+        cli = self.manager.floating_ips_client
+        cli.associate_floating_ip_to_server(self.floating['ip'],
+                                            self.server_id)
+        for method in self.verify:
+            m = getattr(self, method)
+            m()
+        cli.disassociate_floating_ip_from_server(self.floating['ip'],
+                                                 self.server_id)
+        if self.wait_for_disassociate:
+            self.wait_disassociate()
+
+    def run(self):
+        if self.new_sec_grp:
+            self._create_sec_group()
+        if self.new_floating:
+            self._create_floating_ip()
+        if self.new_vm:
+            self._create_vm()
+        if self.reboot:
+            self.manager.servers_client.reboot(self.server_id, 'HARD')
+
+        self.run_core()
+
+        if self.new_vm:
+            self._destroy_vm()
+        if self.new_floating:
+            self._destroy_floating_ip()
+        if self.new_sec_grp:
+            self._destroy_sec_grp()
+
+    def tearDown(self):
+        if not self.new_vm:
+            self._destroy_vm()
+        if not self.new_floating:
+            self._destroy_floating_ip()
+        if not self.new_sec_grp:
+            self._destroy_sec_grp()
diff --git a/tempest/stress/actions/unit_test.py b/tempest/stress/actions/unit_test.py
index 95cc1bc..5ab5573 100644
--- a/tempest/stress/actions/unit_test.py
+++ b/tempest/stress/actions/unit_test.py
@@ -13,6 +13,7 @@
 #    under the License.
 
 from tempest.openstack.common import importutils
+from tempest.openstack.common import log as logging
 import tempest.stress.stressaction as stressaction
 
 
@@ -46,6 +47,7 @@
         method = kwargs['test_method'].split('.')
         self.test_method = method.pop()
         self.klass = importutils.import_class('.'.join(method))
+        self.logger = logging.getLogger('.'.join(method))
         # valid options are 'process', 'application' , 'action'
         self.class_setup_per = kwargs.get('class_setup_per',
                                           SetUpClassRunTime.process)
@@ -55,6 +57,12 @@
             self.klass.setUpClass()
         self.setupclass_called = False
 
+    @property
+    def action(self):
+        if self.test_method:
+            return self.test_method
+        return super(UnitTest, self).action
+
     def run_core(self):
         res = self.klass(self.test_method).run()
         if res.errors:
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index 5171da2..e518d28 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -148,7 +148,7 @@
 
             process = {'process': p,
                        'p_number': p_number,
-                       'action': test['action'],
+                       'action': test_run.action,
                        'statistic': shared_statistic}
 
             processes.append(process)
diff --git a/tempest/stress/etc/ssh_floating.json b/tempest/stress/etc/ssh_floating.json
new file mode 100644
index 0000000..0cb6776
--- /dev/null
+++ b/tempest/stress/etc/ssh_floating.json
@@ -0,0 +1,16 @@
+[{"action": "tempest.stress.actions.ssh_floating.FloatingStress",
+  "threads": 8,
+  "use_admin": false,
+  "use_isolated_tenants": false,
+  "kwargs": {"vm_extra_args": {},
+             "new_vm": true,
+             "new_sec_group": true,
+             "new_floating": true,
+             "verify": ["check_icmp_echo", "check_port_ssh"],
+             "check_timeout": 120,
+             "check_inerval": 1,
+             "wait_after_vm_create": true,
+             "wait_for_disassociate": true,
+             "reboot": false}
+}
+]
diff --git a/tempest/stress/run_stress.py b/tempest/stress/run_stress.py
index aab2afd..886d94b 100755
--- a/tempest/stress/run_stress.py
+++ b/tempest/stress/run_stress.py
@@ -17,16 +17,16 @@
 #    limitations under the License.
 
 import argparse
+import inspect
 import json
 import sys
 from testtools.testsuite import iterate_tests
 from unittest import loader
 
 
-def discover_stress_tests(path="./", filter_attr=None):
+def discover_stress_tests(path="./", filter_attr=None, call_inherited=False):
     """Discovers all tempest tests and create action out of them
     """
-
     tests = []
     testloader = loader.TestLoader()
     list = testloader.discover(path)
@@ -52,6 +52,11 @@
                                  "class_setup_per": class_setup_per
                                  }
                       }
+            if (not call_inherited and
+                getattr(test_func, "st_allow_inheritance") is not True):
+                class_structure = inspect.getmro(test_func.im_class)
+                if test_func.__name__ not in class_structure[0].__dict__:
+                    continue
             tests.append(action)
     return tests
 
@@ -63,7 +68,8 @@
     if not ns.all:
         tests = json.load(open(ns.tests, 'r'))
     else:
-        tests = discover_stress_tests(filter_attr=ns.type)
+        tests = discover_stress_tests(filter_attr=ns.type,
+                                      call_inherited=ns.call_inherited)
 
     if ns.serial:
         for test in tests:
@@ -79,22 +85,25 @@
     return result
 
 
-parser = argparse.ArgumentParser(description='Run stress tests. ')
+parser = argparse.ArgumentParser(description='Run stress tests')
 parser.add_argument('-d', '--duration', default=300, type=int,
-                    help="Duration of test in secs.")
+                    help="Duration of test in secs")
 parser.add_argument('-s', '--serial', action='store_true',
-                    help="Trigger running tests serially.")
+                    help="Trigger running tests serially")
 parser.add_argument('-S', '--stop', action='store_true',
-                    default=False, help="Stop on first error.")
+                    default=False, help="Stop on first error")
 parser.add_argument('-n', '--number', type=int,
-                    help="How often an action is executed for each process.")
+                    help="How often an action is executed for each process")
 group = parser.add_mutually_exclusive_group(required=True)
 group.add_argument('-a', '--all', action='store_true',
                    help="Execute all stress tests")
 parser.add_argument('-T', '--type',
                     help="Filters tests of a certain type (e.g. gate)")
+parser.add_argument('-i', '--call-inherited', action='store_true',
+                    default=False,
+                    help="Call also inherited function with stress attribute")
 group.add_argument('-t', "--tests", nargs='?',
-                   help="Name of the file with test description.")
+                   help="Name of the file with test description")
 
 if __name__ == "__main__":
     sys.exit(main(parser.parse_args()))
diff --git a/tempest/stress/stressaction.py b/tempest/stress/stressaction.py
index 6284cef..28251af 100644
--- a/tempest/stress/stressaction.py
+++ b/tempest/stress/stressaction.py
@@ -33,6 +33,13 @@
         self.tearDown()
         sys.exit(0)
 
+    @property
+    def action(self):
+        """This methods returns the action. Overload this if you
+        create a stress test wrapper.
+        """
+        return self.__class__.__name__
+
     def setUp(self, **kwargs):
         """This method is called before the run method
         to help the test initiatlize any structures.
diff --git a/tempest/test.py b/tempest/test.py
index 8b3cfa6..decae94 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -67,12 +67,17 @@
            ``application``: once in the stress job lifetime
            ``process``: once in the worker process lifetime
            ``action``: on each action
+    @param allow_inheritance: allows inheritance of this attribute
     """
     def decorator(f):
         if 'class_setup_per' in kwargs:
             setattr(f, "st_class_setup_per", kwargs['class_setup_per'])
         else:
             setattr(f, "st_class_setup_per", 'process')
+        if 'allow_inheritance' in kwargs:
+            setattr(f, "st_allow_inheritance", kwargs['allow_inheritance'])
+        else:
+            setattr(f, "st_allow_inheritance", False)
         attr(type='stress')(f)
         return f
     return decorator
@@ -141,7 +146,7 @@
 
     @classmethod
     def tearDownClass(cls):
-        at_exit_set.remove(cls)
+        at_exit_set.discard(cls)
         if hasattr(super(BaseTestCase, cls), 'tearDownClass'):
             super(BaseTestCase, cls).tearDownClass()
 
@@ -168,6 +173,11 @@
                 os.environ.get('OS_STDERR_CAPTURE') == '1'):
             stderr = self.useFixture(fixtures.StringStream('stderr')).stream
             self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
+        if (os.environ.get('OS_LOG_CAPTURE') != 'False' and
+            os.environ.get('OS_LOG_CAPTURE') != '0'):
+            log_format = '%(asctime)-15s %(message)s'
+            self.useFixture(fixtures.LoggerFixture(nuke_handlers=False,
+                                                   format=log_format))
 
     @classmethod
     def _get_identity_admin_client(cls):
diff --git a/tempest/thirdparty/boto/test_ec2_instance_run.py b/tempest/thirdparty/boto/test_ec2_instance_run.py
index 5007503..a848fc9 100644
--- a/tempest/thirdparty/boto/test_ec2_instance_run.py
+++ b/tempest/thirdparty/boto/test_ec2_instance_run.py
@@ -233,7 +233,7 @@
 
     # NOTE(afazekas): doctored test case,
     # with normal validation it would fail
-    @testtools.skip("Until Bug #1182679 is fixed")
+    @testtools.skip("Skipped until the Bug #1182679 is resolved.")
     @attr(type='smoke')
     def test_integration_1(self):
         # EC2 1. integration test (not strict)