Merge "Enable some volumes v2 tests by sharing codes part2"
diff --git a/tempest/api/compute/admin/test_security_group_default_rules.py b/tempest/api/compute/admin/test_security_group_default_rules.py
new file mode 100644
index 0000000..07408a8
--- /dev/null
+++ b/tempest/api/compute/admin/test_security_group_default_rules.py
@@ -0,0 +1,127 @@
+# Copyright 2014 NEC Corporation.  All rights reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import testtools
+
+from tempest.api.compute import base
+from tempest import config
+from tempest import exceptions
+from tempest import test
+
+CONF = config.CONF
+
+
+class SecurityGroupDefaultRulesTest(base.BaseV2ComputeAdminTest):
+
+    @classmethod
+    # TODO(GMann): Once Bug# 1311500 is fixed, these test can run
+    # for Neutron also.
+    @testtools.skipIf(CONF.service_available.neutron,
+                      "Skip as this functionality is not yet "
+                      "implemented in Neutron. Related Bug#1311500")
+    @test.safe_setup
+    def setUpClass(cls):
+        # A network and a subnet will be created for these tests
+        cls.set_network_resources(network=True, subnet=True)
+        super(SecurityGroupDefaultRulesTest, cls).setUpClass()
+        cls.adm_client = cls.os_adm.security_group_default_rules_client
+
+    def _create_security_group_default_rules(self, ip_protocol='tcp',
+                                             from_port=22, to_port=22,
+                                             cidr='10.10.0.0/24'):
+        # Create Security Group default rule
+        _, rule = self.adm_client.create_security_default_group_rule(
+            ip_protocol,
+            from_port,
+            to_port,
+            cidr=cidr)
+        self.assertEqual(ip_protocol, rule['ip_protocol'])
+        self.assertEqual(from_port, rule['from_port'])
+        self.assertEqual(to_port, rule['to_port'])
+        self.assertEqual(cidr, rule['ip_range']['cidr'])
+        return rule
+
+    @test.attr(type='smoke')
+    def test_create_delete_security_group_default_rules(self):
+        # Create and delete Security Group default rule
+        ip_protocols = {'tcp', 'udp', 'icmp'}
+        for ip_protocol in ip_protocols:
+            rule = self._create_security_group_default_rules(ip_protocol)
+            # Delete Security Group default rule
+            self.adm_client.delete_security_group_default_rule(rule['id'])
+            self.assertRaises(exceptions.NotFound,
+                              self.adm_client.get_security_group_default_rule,
+                              rule['id'])
+
+    @test.attr(type='smoke')
+    def test_create_security_group_default_rule_without_cidr(self):
+        ip_protocol = 'udp'
+        from_port = 80
+        to_port = 80
+        _, rule = self.adm_client.create_security_default_group_rule(
+            ip_protocol,
+            from_port,
+            to_port)
+        self.addCleanup(self.adm_client.delete_security_group_default_rule,
+                        rule['id'])
+        self.assertNotEqual(0, rule['id'])
+        self.assertEqual('0.0.0.0/0', rule['ip_range']['cidr'])
+
+    @test.attr(type='smoke')
+    def test_create_security_group_default_rule_with_blank_cidr(self):
+        ip_protocol = 'icmp'
+        from_port = 10
+        to_port = 10
+        cidr = ''
+        _, rule = self.adm_client.create_security_default_group_rule(
+            ip_protocol,
+            from_port,
+            to_port,
+            cidr=cidr)
+        self.addCleanup(self.adm_client.delete_security_group_default_rule,
+                        rule['id'])
+        self.assertNotEqual(0, rule['id'])
+        self.assertEqual('0.0.0.0/0', rule['ip_range']['cidr'])
+
+    @test.attr(type='smoke')
+    def test_security_group_default_rules_list(self):
+        ip_protocol = 'tcp'
+        from_port = 22
+        to_port = 22
+        cidr = '10.10.0.0/24'
+        rule = self._create_security_group_default_rules(ip_protocol,
+                                                         from_port,
+                                                         to_port,
+                                                         cidr)
+        self.addCleanup(self.adm_client.delete_security_group_default_rule,
+                        rule['id'])
+        _, rules = self.adm_client.list_security_group_default_rules()
+        self.assertNotEqual(0, len(rules))
+        self.assertIn(rule, rules)
+
+    @test.attr(type='smoke')
+    def test_default_security_group_default_rule_show(self):
+        ip_protocol = 'tcp'
+        from_port = 22
+        to_port = 22
+        cidr = '10.10.0.0/24'
+        rule = self._create_security_group_default_rules(ip_protocol,
+                                                         from_port,
+                                                         to_port,
+                                                         cidr)
+        self.addCleanup(self.adm_client.delete_security_group_default_rule,
+                        rule['id'])
+        _, fetched_rule = self.adm_client.get_security_group_default_rule(
+            rule['id'])
+        self.assertEqual(rule, fetched_rule)
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 70a9604..a3295eb 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -83,6 +83,8 @@
             cls.hypervisor_client = cls.os.hypervisor_client
             cls.certificates_client = cls.os.certificates_client
             cls.migrations_client = cls.os.migrations_client
+            cls.security_group_default_rules_client = (
+                cls.os.security_group_default_rules_client)
 
         elif cls._api_version == 3:
             if not CONF.compute_feature_enabled.api_v3:
diff --git a/tempest/api/identity/admin/v3/test_list_projects.py b/tempest/api/identity/admin/v3/test_list_projects.py
new file mode 100644
index 0000000..a3944e2
--- /dev/null
+++ b/tempest/api/identity/admin/v3/test_list_projects.py
@@ -0,0 +1,73 @@
+# Copyright 2014 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.identity import base
+from tempest.common.utils import data_utils
+from tempest import test
+
+
+class ListProjectsTestJSON(base.BaseIdentityV3AdminTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(ListProjectsTestJSON, cls).setUpClass()
+        cls.project_ids = list()
+        cls.data.setup_test_domain()
+        # Create project with domain
+        cls.p1_name = data_utils.rand_name('project')
+        _, cls.p1 = cls.client.create_project(
+            cls.p1_name, enabled=False, domain_id=cls.data.domain['id'])
+        cls.data.projects.append(cls.p1)
+        cls.project_ids.append(cls.p1['id'])
+        # Create default project
+        p2_name = data_utils.rand_name('project')
+        _, cls.p2 = cls.client.create_project(p2_name)
+        cls.data.projects.append(cls.p2)
+        cls.project_ids.append(cls.p2['id'])
+
+    @test.attr(type='gate')
+    def test_projects_list(self):
+        # List projects
+        resp, list_projects = self.client.list_projects()
+
+        for p in self.project_ids:
+            _, get_project = self.client.get_project(p)
+            self.assertIn(get_project, list_projects)
+
+    @test.attr(type='gate')
+    def test_list_projects_with_domains(self):
+        # List projects with domain
+        self._list_projects_with_params(
+            {'domain_id': self.data.domain['id']}, 'domain_id')
+
+    @test.attr(type='gate')
+    def test_list_projects_with_enabled(self):
+        # List the projects with enabled
+        self._list_projects_with_params({'enabled': False}, 'enabled')
+
+    @test.attr(type='gate')
+    def test_list_projects_with_name(self):
+        # List projects with name
+        self._list_projects_with_params({'name': self.p1_name}, 'name')
+
+    def _list_projects_with_params(self, params, key):
+        resp, body = self.client.list_projects(params)
+        self.assertIn(self.p1[key], map(lambda x: x[key], body))
+        self.assertNotIn(self.p2[key], map(lambda x: x[key], body))
+
+
+class ListProjectsTestXML(ListProjectsTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/identity/admin/v3/test_projects.py b/tempest/api/identity/admin/v3/test_projects.py
index 77acd57..5890eab 100644
--- a/tempest/api/identity/admin/v3/test_projects.py
+++ b/tempest/api/identity/admin/v3/test_projects.py
@@ -13,35 +13,14 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from six import moves
-
 from tempest.api.identity import base
 from tempest.common.utils import data_utils
-from tempest import exceptions
 from tempest import test
 
 
 class ProjectsTestJSON(base.BaseIdentityV3AdminTest):
     _interface = 'json'
 
-    def _delete_project(self, project_id):
-        self.client.delete_project(project_id)
-        self.assertRaises(
-            exceptions.NotFound, self.client.get_project, project_id)
-
-    @test.attr(type='gate')
-    def test_project_list_delete(self):
-        # Create several projects and delete them
-        for _ in moves.xrange(3):
-            _, project = self.client.create_project(
-                data_utils.rand_name('project-new'))
-            self.addCleanup(self._delete_project, project['id'])
-
-        _, list_projects = self.client.list_projects()
-
-        _, get_project = self.client.get_project(project['id'])
-        self.assertIn(get_project, list_projects)
-
     @test.attr(type='gate')
     def test_project_create_with_description(self):
         # Create project with a description
@@ -60,6 +39,21 @@
                          'to be set')
 
     @test.attr(type='gate')
+    def test_project_create_with_domain(self):
+        # Create project with a domain
+        self.data.setup_test_domain()
+        project_name = data_utils.rand_name('project')
+        resp, project = self.client.create_project(
+            project_name, domain_id=self.data.domain['id'])
+        self.data.projects.append(project)
+        project_id = project['id']
+        self.assertEqual(project_name, project['name'])
+        self.assertEqual(self.data.domain['id'], project['domain_id'])
+        _, body = self.client.get_project(project_id)
+        self.assertEqual(project_name, body['name'])
+        self.assertEqual(self.data.domain['id'], body['domain_id'])
+
+    @test.attr(type='gate')
     def test_project_create_enabled(self):
         # Create a project that is enabled
         project_name = data_utils.rand_name('project-')
diff --git a/tempest/api/identity/admin/v3/test_tokens.py b/tempest/api/identity/admin/v3/test_tokens.py
index e61b738..bd08614 100644
--- a/tempest/api/identity/admin/v3/test_tokens.py
+++ b/tempest/api/identity/admin/v3/test_tokens.py
@@ -48,6 +48,7 @@
         self.assertRaises(exceptions.NotFound, self.client.get_token,
                           subject_token)
 
+    @test.skip_because(bug="1351026")
     @test.attr(type='gate')
     def test_rescope_token(self):
         """Rescope a token.
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index 02d391b..c875b2f 100644
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -100,7 +100,7 @@
         cls.alt_tenant_id = cls.alt_img_cli.tenant_id
 
     def _create_image(self):
-        image_file = StringIO.StringIO('*' * 1024)
+        image_file = StringIO.StringIO(data_utils.random_bytes())
         resp, image = self.create_image(container_format='bare',
                                         disk_format='raw',
                                         is_public=False,
diff --git a/tempest/api/image/v1/test_images.py b/tempest/api/image/v1/test_images.py
index 8528e42..bf55b89 100644
--- a/tempest/api/image/v1/test_images.py
+++ b/tempest/api/image/v1/test_images.py
@@ -44,7 +44,7 @@
             self.assertEqual(val, body.get('properties')[key])
 
         # Now try uploading an image file
-        image_file = StringIO.StringIO(('*' * 1024))
+        image_file = StringIO.StringIO(data_utils.random_bytes())
         _, body = self.client.update_image(image_id, data=image_file)
         self.assertIn('size', body)
         self.assertEqual(1024, body.get('size'))
@@ -157,7 +157,7 @@
         image. Note that the size of the new image is a random number between
         1024 and 4096
         """
-        image_file = StringIO.StringIO('*' * size)
+        image_file = StringIO.StringIO(data_utils.random_bytes(size))
         name = 'New Standard Image %s' % name
         _, image = cls.create_image(name=name,
                                     container_format=container_format,
@@ -338,10 +338,9 @@
                                disk_format, size):
         """
         Create a new standard image and return the ID of the newly-registered
-        image. Note that the size of the new image is a random number between
-        1024 and 4096
+        image.
         """
-        image_file = StringIO.StringIO('*' * size)
+        image_file = StringIO.StringIO(data_utils.random_bytes(size))
         name = 'New Standard Image %s' % name
         _, image = cls.create_image(name=name,
                                     container_format=container_format,
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index 4226815..a974ebb 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -52,7 +52,7 @@
         self.assertEqual('queued', body['status'])
 
         # Now try uploading an image file
-        file_content = '*' * 1024
+        file_content = data_utils.random_bytes()
         image_file = StringIO.StringIO(file_content)
         self.client.store_image(image_id, image_file)
 
@@ -104,8 +104,7 @@
         image_id = body['id']
 
         # Now try uploading an image file
-        file_content = '*' * 1024
-        image_file = StringIO.StringIO(file_content)
+        image_file = StringIO.StringIO(data_utils.random_bytes())
         self.client.store_image(image_id, image_file)
 
         # Update Image
@@ -146,7 +145,8 @@
         image. Note that the size of the new image is a random number between
         1024 and 4096
         """
-        image_file = StringIO.StringIO('*' * random.randint(1024, 4096))
+        size = random.randint(1024, 4096)
+        image_file = StringIO.StringIO(data_utils.random_bytes(size))
         name = data_utils.rand_name('image-')
         _, body = cls.create_image(name=name,
                                    container_format=container_format,
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index 087b87a..d75339c 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -85,57 +85,58 @@
 
     @classmethod
     def tearDownClass(cls):
-        # Clean up ipsec policies
-        for ipsecpolicy in cls.ipsecpolicies:
-            cls.client.delete_ipsecpolicy(ipsecpolicy['id'])
-        # Clean up firewall policies
-        for fw_policy in cls.fw_policies:
-            cls.client.delete_firewall_policy(fw_policy['id'])
-        # Clean up firewall rules
-        for fw_rule in cls.fw_rules:
-            cls.client.delete_firewall_rule(fw_rule['id'])
-        # Clean up ike policies
-        for ikepolicy in cls.ikepolicies:
-            cls.client.delete_ikepolicy(ikepolicy['id'])
-        # Clean up vpn services
-        for vpnservice in cls.vpnservices:
-            cls.client.delete_vpnservice(vpnservice['id'])
-        # Clean up floating IPs
-        for floating_ip in cls.floating_ips:
-            cls.client.delete_floatingip(floating_ip['id'])
-        # Clean up routers
-        for router in cls.routers:
-            cls.delete_router(router)
+        if CONF.service_available.neutron:
+            # Clean up ipsec policies
+            for ipsecpolicy in cls.ipsecpolicies:
+                cls.client.delete_ipsecpolicy(ipsecpolicy['id'])
+            # Clean up firewall policies
+            for fw_policy in cls.fw_policies:
+                cls.client.delete_firewall_policy(fw_policy['id'])
+            # Clean up firewall rules
+            for fw_rule in cls.fw_rules:
+                cls.client.delete_firewall_rule(fw_rule['id'])
+            # Clean up ike policies
+            for ikepolicy in cls.ikepolicies:
+                cls.client.delete_ikepolicy(ikepolicy['id'])
+            # Clean up vpn services
+            for vpnservice in cls.vpnservices:
+                cls.client.delete_vpnservice(vpnservice['id'])
+            # Clean up floating IPs
+            for floating_ip in cls.floating_ips:
+                cls.client.delete_floatingip(floating_ip['id'])
+            # Clean up routers
+            for router in cls.routers:
+                cls.delete_router(router)
 
-        # Clean up health monitors
-        for health_monitor in cls.health_monitors:
-            cls.client.delete_health_monitor(health_monitor['id'])
-        # Clean up members
-        for member in cls.members:
-            cls.client.delete_member(member['id'])
-        # Clean up vips
-        for vip in cls.vips:
-            cls.client.delete_vip(vip['id'])
-        # Clean up pools
-        for pool in cls.pools:
-            cls.client.delete_pool(pool['id'])
-        # Clean up metering label rules
-        for metering_label_rule in cls.metering_label_rules:
-            cls.admin_client.delete_metering_label_rule(
-                metering_label_rule['id'])
-        # Clean up metering labels
-        for metering_label in cls.metering_labels:
-            cls.admin_client.delete_metering_label(metering_label['id'])
-        # Clean up ports
-        for port in cls.ports:
-            cls.client.delete_port(port['id'])
-        # Clean up subnets
-        for subnet in cls.subnets:
-            cls.client.delete_subnet(subnet['id'])
-        # Clean up networks
-        for network in cls.networks:
-            cls.client.delete_network(network['id'])
-        cls.clear_isolated_creds()
+            # Clean up health monitors
+            for health_monitor in cls.health_monitors:
+                cls.client.delete_health_monitor(health_monitor['id'])
+            # Clean up members
+            for member in cls.members:
+                cls.client.delete_member(member['id'])
+            # Clean up vips
+            for vip in cls.vips:
+                cls.client.delete_vip(vip['id'])
+            # Clean up pools
+            for pool in cls.pools:
+                cls.client.delete_pool(pool['id'])
+            # Clean up metering label rules
+            for metering_label_rule in cls.metering_label_rules:
+                cls.admin_client.delete_metering_label_rule(
+                    metering_label_rule['id'])
+            # Clean up metering labels
+            for metering_label in cls.metering_labels:
+                cls.admin_client.delete_metering_label(metering_label['id'])
+            # Clean up ports
+            for port in cls.ports:
+                cls.client.delete_port(port['id'])
+            # Clean up subnets
+            for subnet in cls.subnets:
+                cls.client.delete_subnet(subnet['id'])
+            # Clean up networks
+            for network in cls.networks:
+                cls.client.delete_network(network['id'])
+            cls.clear_isolated_creds()
         super(BaseNetworkTest, cls).tearDownClass()
 
     @classmethod
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index 1ef9aa1..b21aa44 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -17,7 +17,7 @@
 import hashlib
 import random
 import re
-from six import moves
+import six
 import time
 import zlib
 
@@ -54,15 +54,36 @@
         object_name = data_utils.rand_name(name='LObject')
         data = data_utils.arbitrary_string()
         segments = 10
-        data_segments = [data + str(i) for i in moves.xrange(segments)]
+        data_segments = [data + str(i) for i in six.moves.xrange(segments)]
         # uploading segments
-        for i in moves.xrange(segments):
+        for i in six.moves.xrange(segments):
             resp, _ = self.object_client.create_object_segments(
                 self.container_name, object_name, i, data_segments[i])
             self.assertEqual(resp['status'], '201')
 
         return object_name, data_segments
 
+    def _copy_object_2d(self, src_object_name, metadata=None):
+        dst_object_name = data_utils.rand_name(name='TestObject')
+        resp, _ = self.object_client.copy_object_2d_way(self.container_name,
+                                                        src_object_name,
+                                                        dst_object_name,
+                                                        metadata=metadata)
+        return dst_object_name, resp
+
+    def _check_copied_obj(self, dst_object_name, src_body,
+                          in_meta=None, not_in_meta=None):
+        resp, dest_body = self.object_client.get_object(self.container_name,
+                                                        dst_object_name)
+
+        self.assertEqual(src_body, dest_body)
+        if in_meta:
+            for meta_key in in_meta:
+                self.assertIn('x-object-meta-' + meta_key, resp)
+        if not_in_meta:
+            for meta_key in not_in_meta:
+                self.assertNotIn('x-object-meta-' + meta_key, resp)
+
     @test.attr(type='gate')
     def test_create_object(self):
         # create object
@@ -765,10 +786,7 @@
         # change the content type of an existing object
 
         # create object
-        object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string()
-        self.object_client.create_object(self.container_name,
-                                         object_name, data)
+        object_name, data = self._create_object()
         # get the old content type
         resp_tmp, _ = self.object_client.list_object_metadata(
             self.container_name, object_name)
@@ -805,20 +823,12 @@
                                                         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)
-        self.assertEqual(body, src_data)
+        self._check_copied_obj(dst_object_name, src_data)
 
     @test.attr(type='smoke')
     def test_copy_object_across_containers(self):
@@ -862,15 +872,82 @@
         self.assertIn(actual_meta_key, resp)
         self.assertEqual(resp[actual_meta_key], meta_value)
 
+    @test.attr(type='smoke')
+    def test_copy_object_with_x_fresh_metadata(self):
+        # create source object
+        metadata = {'x-object-meta-src': 'src_value'}
+        src_object_name, data = self._create_object(metadata)
+
+        # copy source object with x_fresh_metadata header
+        metadata = {'X-Fresh-Metadata': 'true'}
+        dst_object_name, resp = self._copy_object_2d(src_object_name,
+                                                     metadata)
+
+        self.assertEqual(resp['status'], '201')
+        self.assertHeaders(resp, 'Object', 'COPY')
+
+        self.assertNotIn('x-object-meta-src', resp)
+        self.assertEqual(resp['x-copied-from'],
+                         self.container_name + "/" + src_object_name)
+
+        # check that destination object does NOT have any object-meta
+        self._check_copied_obj(dst_object_name, data, not_in_meta=["src"])
+
+    @test.attr(type='smoke')
+    def test_copy_object_with_x_object_metakey(self):
+        # create source object
+        metadata = {'x-object-meta-src': 'src_value'}
+        src_obj_name, data = self._create_object(metadata)
+
+        # copy source object to destination with x-object-meta-key
+        metadata = {'x-object-meta-test': ''}
+        dst_obj_name, resp = self._copy_object_2d(src_obj_name, metadata)
+
+        self.assertEqual(resp['status'], '201')
+        self.assertHeaders(resp, 'Object', 'COPY')
+
+        expected = {'x-object-meta-test': '',
+                    'x-object-meta-src': 'src_value',
+                    'x-copied-from': self.container_name + "/" + src_obj_name}
+        for key, value in six.iteritems(expected):
+            self.assertIn(key, resp)
+            self.assertEqual(value, resp[key])
+
+        # check destination object
+        self._check_copied_obj(dst_obj_name, data, in_meta=["test", "src"])
+
+    @test.attr(type='smoke')
+    def test_copy_object_with_x_object_meta(self):
+        # create source object
+        metadata = {'x-object-meta-src': 'src_value'}
+        src_obj_name, data = self._create_object(metadata)
+
+        # copy source object to destination with object metadata
+        metadata = {'x-object-meta-test': 'value'}
+        dst_obj_name, resp = self._copy_object_2d(src_obj_name, metadata)
+
+        self.assertEqual(resp['status'], '201')
+        self.assertHeaders(resp, 'Object', 'COPY')
+
+        expected = {'x-object-meta-test': 'value',
+                    'x-object-meta-src': 'src_value',
+                    'x-copied-from': self.container_name + "/" + src_obj_name}
+        for key, value in six.iteritems(expected):
+            self.assertIn(key, resp)
+            self.assertEqual(value, resp[key])
+
+        # check destination object
+        self._check_copied_obj(dst_obj_name, data, in_meta=["test", "src"])
+
     @test.attr(type='gate')
     def test_object_upload_in_segments(self):
         # create object
         object_name = data_utils.rand_name(name='LObject')
         data = data_utils.arbitrary_string()
         segments = 10
-        data_segments = [data + str(i) for i in moves.xrange(segments)]
+        data_segments = [data + str(i) for i in six.moves.xrange(segments)]
         # uploading segments
-        for i in moves.xrange(segments):
+        for i in six.moves.xrange(segments):
             resp, _ = self.object_client.create_object_segments(
                 self.container_name, object_name, i, data_segments[i])
             self.assertEqual(resp['status'], '201')
diff --git a/tempest/api/orchestration/stacks/test_nova_keypair_resources.py b/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
index e22a08b..e3ffdaf 100644
--- a/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
+++ b/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
@@ -48,7 +48,7 @@
         for resource in resources:
             cls.test_resources[resource['logical_resource_id']] = resource
 
-    @test.attr(type='slow')
+    @test.attr(type='gate')
     def test_created_resources(self):
         """Verifies created keypair resource."""
 
@@ -68,7 +68,7 @@
             self.assertEqual(resource_type, resource['resource_type'])
             self.assertEqual('CREATE_COMPLETE', resource['resource_status'])
 
-    @test.attr(type='slow')
+    @test.attr(type='gate')
     def test_stack_keypairs_output(self):
         resp, stack = self.client.get_stack(self.stack_name)
         self.assertEqual('200', resp['status'])
diff --git a/tempest/api_schema/compute/v2/servers.py b/tempest/api_schema/compute/v2/servers.py
index 551924a..4abadf4 100644
--- a/tempest/api_schema/compute/v2/servers.py
+++ b/tempest/api_schema/compute/v2/servers.py
@@ -28,14 +28,11 @@
                     'id': {'type': 'string'},
                     'security_groups': {'type': 'array'},
                     'links': parameter_types.links,
-                    'adminPass': {'type': 'string'},
                     'OS-DCF:diskConfig': {'type': 'string'}
                 },
                 # NOTE: OS-DCF:diskConfig is API extension, and some
                 # environments return a response without the attribute.
                 # So it is not 'required'.
-                # NOTE: adminPass is not required because it can be deactivated
-                # with nova API flag enable_instance_password=False
                 'required': ['id', 'security_groups', 'links']
             }
         },
@@ -43,6 +40,12 @@
     }
 }
 
+create_server_with_admin_pass = copy.deepcopy(create_server)
+create_server_with_admin_pass['response_body']['properties']['server'][
+    'properties'].update({'adminPass': {'type': 'string'}})
+create_server_with_admin_pass['response_body']['properties']['server'][
+    'required'].append('adminPass')
+
 update_server = copy.deepcopy(servers.base_update_get_server)
 update_server['response_body']['properties']['server']['properties'].update({
     'hostId': {'type': 'string'},
@@ -281,3 +284,14 @@
     'properties'].update({'adminPass': {'type': 'string'}})
 rebuild_server_with_admin_pass['response_body']['properties']['server'][
     'required'].append('adminPass')
+
+rescue_server = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'adminPass': {'type': 'string'}
+        },
+        'required': ['adminPass']
+    }
+}
diff --git a/tempest/api_schema/compute/v3/servers.py b/tempest/api_schema/compute/v3/servers.py
index cebb2d7..a84ac3c 100644
--- a/tempest/api_schema/compute/v3/servers.py
+++ b/tempest/api_schema/compute/v3/servers.py
@@ -28,7 +28,6 @@
                     'id': {'type': 'string'},
                     'os-security-groups:security_groups': {'type': 'array'},
                     'links': parameter_types.links,
-                    'admin_password': {'type': 'string'},
                     'os-access-ips:access_ip_v4': parameter_types.access_ip_v4,
                     'os-access-ips:access_ip_v6': parameter_types.access_ip_v6
                 },
@@ -36,13 +35,19 @@
                 # and some environments return a response without these
                 # attributes. So they are not 'required'.
                 'required': ['id', 'os-security-groups:security_groups',
-                             'links', 'admin_password']
+                             'links']
             }
         },
         'required': ['server']
     }
 }
 
+create_server_with_admin_pass = copy.deepcopy(create_server)
+create_server_with_admin_pass['response_body']['properties']['server'][
+    'properties'].update({'admin_password': {'type': 'string'}})
+create_server_with_admin_pass['response_body']['properties']['server'][
+    'required'].append('admin_password')
+
 addresses_v3 = copy.deepcopy(parameter_types.addresses)
 addresses_v3['patternProperties']['^[a-zA-Z0-9-_.]+$']['items'][
     'properties'].update({
@@ -190,3 +195,18 @@
     'properties'].update({'admin_password': {'type': 'string'}})
 rebuild_server_with_admin_pass['response_body']['properties']['server'][
     'required'].append('admin_password')
+
+rescue_server_with_admin_pass = {
+    'status_code': [202],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'admin_password': {'type': 'string'}
+        },
+        'required': ['admin_password']
+    }
+}
+
+rescue_server = copy.deepcopy(rescue_server_with_admin_pass)
+del rescue_server['response_body']['properties']
+del rescue_server['response_body']['required']
diff --git a/tempest/auth.py b/tempest/auth.py
index 830dca9..5df6224 100644
--- a/tempest/auth.py
+++ b/tempest/auth.py
@@ -13,10 +13,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import abc
 import copy
 import datetime
 import exceptions
 import re
+import six
 import urlparse
 
 from tempest import config
@@ -31,6 +33,7 @@
 LOG = logging.getLogger(__name__)
 
 
+@six.add_metaclass(abc.ABCMeta)
 class AuthProvider(object):
     """
     Provide authentication
@@ -70,18 +73,21 @@
                    interface=self.interface, cache=self.cache
                )
 
+    @abc.abstractmethod
     def _decorate_request(self, filters, method, url, headers=None, body=None,
                           auth_data=None):
         """
         Decorate request with authentication data
         """
-        raise NotImplementedError
+        return
 
+    @abc.abstractmethod
     def _get_auth(self):
-        raise NotImplementedError
+        return
 
+    @abc.abstractmethod
     def _fill_credentials(self, auth_data_body):
-        raise NotImplementedError
+        return
 
     def fill_credentials(self):
         """
@@ -130,8 +136,9 @@
         self.cache = None
         self.credentials.reset()
 
+    @abc.abstractmethod
     def is_expired(self, auth_data):
-        raise NotImplementedError
+        return
 
     def auth_request(self, method, url, headers=None, body=None, filters=None):
         """
@@ -188,11 +195,12 @@
         self.alt_part = request_part
         self.alt_auth_data = auth_data
 
+    @abc.abstractmethod
     def base_url(self, filters, auth_data=None):
         """
         Extracts the base_url based on provided filters
         """
-        raise NotImplementedError
+        return
 
 
 class KeystoneAuthProvider(AuthProvider):
@@ -225,11 +233,13 @@
         # no change to method or body
         return str(_url), _headers, body
 
+    @abc.abstractmethod
     def _auth_client(self):
-        raise NotImplementedError
+        return
 
+    @abc.abstractmethod
     def _auth_params(self):
-        raise NotImplementedError
+        return
 
     def _get_auth(self):
         # Bypasses the cache
@@ -321,7 +331,7 @@
             if noversion_path != "":
                 path += "/" + noversion_path
             _base_url = _base_url.replace(parts.path, path)
-        if filters.get('skip_path', None) is not None:
+        if filters.get('skip_path', None) is not None and parts.path != '':
             _base_url = _base_url.replace(parts.path, "/")
 
         return _base_url
diff --git a/tempest/clients.py b/tempest/clients.py
index 276b702..0edcdf4 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -52,6 +52,8 @@
     MigrationsClientJSON
 from tempest.services.compute.json.quotas_client import QuotaClassesClientJSON
 from tempest.services.compute.json.quotas_client import QuotasClientJSON
+from tempest.services.compute.json.security_group_default_rules_client import \
+    SecurityGroupDefaultRulesClientJSON
 from tempest.services.compute.json.security_groups_client import \
     SecurityGroupsClientJSON
 from tempest.services.compute.json.servers_client import ServersClientJSON
@@ -422,6 +424,8 @@
         self.data_processing_client = DataProcessingClient(
             self.auth_provider)
         self.migrations_client = MigrationsClientJSON(self.auth_provider)
+        self.security_group_default_rules_client = (
+            SecurityGroupDefaultRulesClientJSON(self.auth_provider))
 
 
 class AltManager(Manager):
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index c1a2e46..67b92b0 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -219,7 +219,7 @@
 
     def check_objects(self):
         """Check that the objects created are still there."""
-        if 'objects' not in self.res:
+        if not self.res.get('objects'):
             return
         LOG.info("checking objects")
         for obj in self.res['objects']:
@@ -231,7 +231,7 @@
 
     def check_servers(self):
         """Check that the servers are still up and running."""
-        if 'servers' not in self.res:
+        if not self.res.get('servers'):
             return
         LOG.info("checking servers")
         for server in self.res['servers']:
@@ -254,7 +254,7 @@
 
     def check_volumes(self):
         """Check that the volumes are still there and attached."""
-        if 'volumes' not in self.res:
+        if not self.res.get('volumes'):
             return
         LOG.info("checking volumes")
         for volume in self.res['volumes']:
diff --git a/tempest/common/custom_matchers.py b/tempest/common/custom_matchers.py
index 4a7921f..996c365 100644
--- a/tempest/common/custom_matchers.py
+++ b/tempest/common/custom_matchers.py
@@ -69,10 +69,24 @@
             elif self.target == 'Object':
                 if 'etag' not in actual:
                     return NonExistentHeader('etag')
-        elif self.method == 'PUT' or self.method == 'COPY':
+                if 'last-modified' not in actual:
+                    return NonExistentHeader('last-modified')
+        elif self.method == 'PUT':
             if self.target == 'Object':
                 if 'etag' not in actual:
                     return NonExistentHeader('etag')
+                if 'last-modified' not in actual:
+                    return NonExistentHeader('last-modified')
+        elif self.method == 'COPY':
+            if self.target == 'Object':
+                if 'etag' not in actual:
+                    return NonExistentHeader('etag')
+                if 'last-modified' not in actual:
+                    return NonExistentHeader('last-modified')
+                if 'x-copied-from' not in actual:
+                    return NonExistentHeader('x-copied-from')
+                if 'x-copied-from-last-modified' not in actual:
+                    return NonExistentHeader('x-copied-from-last-modified')
 
         return None
 
@@ -122,11 +136,17 @@
                 return InvalidFormat(key, value)
             elif key == 'content-type' and not value:
                 return InvalidFormat(key, value)
+            elif key == 'x-copied-from' and not re.match("\S+/\S+", value):
+                return InvalidFormat(key, value)
+            elif key == 'x-copied-from-last-modified' and not value:
+                return InvalidFormat(key, value)
             elif key == 'x-trans-id' and \
                 not re.match("^tx[0-9a-f]{21}-[0-9a-f]{10}.*", value):
                 return InvalidFormat(key, value)
             elif key == 'date' and not value:
                 return InvalidFormat(key, value)
+            elif key == 'last-modified' 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():
diff --git a/tempest/common/utils/data_utils.py b/tempest/common/utils/data_utils.py
index 174e557..5a29ea0 100644
--- a/tempest/common/utils/data_utils.py
+++ b/tempest/common/utils/data_utils.py
@@ -71,3 +71,11 @@
     if not base_text:
         base_text = 'test'
     return ''.join(itertools.islice(itertools.cycle(base_text), size))
+
+
+def random_bytes(size=1024):
+    """
+    Return size randomly selected bytes as a string.
+    """
+    return ''.join([chr(random.randint(0, 255))
+                    for i in range(size)])
diff --git a/tempest/services/compute/json/security_group_default_rules_client.py b/tempest/services/compute/json/security_group_default_rules_client.py
new file mode 100644
index 0000000..6d29837
--- /dev/null
+++ b/tempest/services/compute/json/security_group_default_rules_client.py
@@ -0,0 +1,74 @@
+# Copyright 2014 NEC Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import json
+
+from tempest.common import rest_client
+from tempest import config
+
+CONF = config.CONF
+
+
+class SecurityGroupDefaultRulesClientJSON(rest_client.RestClient):
+
+    def __init__(self, auth_provider):
+        super(SecurityGroupDefaultRulesClientJSON,
+              self).__init__(auth_provider)
+        self.service = CONF.compute.catalog_type
+
+    def create_security_default_group_rule(self, ip_protocol, from_port,
+                                           to_port, **kwargs):
+        """
+        Creating security group default rules.
+        ip_protocol : ip_protocol (icmp, tcp, udp).
+        from_port: Port at start of range.
+        to_port  : Port at end of range.
+        cidr     : CIDR for address range.
+        """
+        post_body = {
+            'ip_protocol': ip_protocol,
+            'from_port': from_port,
+            'to_port': to_port,
+            'cidr': kwargs.get('cidr'),
+        }
+        post_body = json.dumps({'security_group_default_rule': post_body})
+        url = 'os-security-group-default-rules'
+        resp, body = self.post(url, post_body)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return resp, body['security_group_default_rule']
+
+    def delete_security_group_default_rule(self,
+                                           security_group_default_rule_id):
+        """Deletes the provided Security Group default rule."""
+        resp, body = self.delete('os-security-group-default-rules/%s' % str(
+            security_group_default_rule_id))
+        self.expected_success(204, resp.status)
+        return resp, body
+
+    def list_security_group_default_rules(self):
+        """List all Security Group default rules."""
+        resp, body = self.get('os-security-group-default-rules')
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return resp, body['security_group_default_rules']
+
+    def get_security_group_default_rule(self, security_group_default_rule_id):
+        """Return the details of provided Security Group default rule."""
+        resp, body = self.get('os-security-group-default-rules/%s' % str(
+            security_group_default_rule_id))
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return resp, body['security_group_default_rule']
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index 05f74cd..a4e3641 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -93,7 +93,11 @@
         # with return reservation id set True
         if 'reservation_id' in body:
             return resp, body
-        self.validate_response(schema.create_server, resp, body)
+        if CONF.compute_feature_enabled.enable_instance_password:
+            create_schema = schema.create_server_with_admin_pass
+        else:
+            create_schema = schema.create_server
+        self.validate_response(create_schema, resp, body)
         return resp, body['server']
 
     def update_server(self, server_id, name=None, meta=None, accessIPv4=None,
@@ -455,7 +459,8 @@
 
     def rescue_server(self, server_id, **kwargs):
         """Rescue the provided server."""
-        return self.action(server_id, 'rescue', 'adminPass', None, **kwargs)
+        return self.action(server_id, 'rescue', 'adminPass',
+                           schema.rescue_server, **kwargs)
 
     def unrescue_server(self, server_id):
         """Unrescue the provided server."""
diff --git a/tempest/services/compute/v3/json/servers_client.py b/tempest/services/compute/v3/json/servers_client.py
index 27e95e8..c3fd355 100644
--- a/tempest/services/compute/v3/json/servers_client.py
+++ b/tempest/services/compute/v3/json/servers_client.py
@@ -96,7 +96,11 @@
         # with return reservation id set True
         if 'servers_reservation' in body:
             return resp, body['servers_reservation']
-        self.validate_response(schema.create_server, resp, body)
+        if CONF.compute_feature_enabled.enable_instance_password:
+            create_schema = schema.create_server_with_admin_pass
+        else:
+            create_schema = schema.create_server
+        self.validate_response(create_schema, resp, body)
         return resp, body['server']
 
     def update_server(self, server_id, name=None, meta=None, access_ip_v4=None,
@@ -450,8 +454,16 @@
 
     def rescue_server(self, server_id, **kwargs):
         """Rescue the provided server."""
-        return self.action(server_id, 'rescue', 'admin_password',
-                           None, **kwargs)
+        post_body = json.dumps({'rescue': kwargs})
+        resp, body = self.post('servers/%s/action' % str(server_id),
+                               post_body)
+        if CONF.compute_feature_enabled.enable_instance_password:
+            rescue_schema = schema.rescue_server_with_admin_pass
+        else:
+            rescue_schema = schema.rescue_server
+        body = json.loads(body)
+        self.validate_response(rescue_schema, resp, body)
+        return resp, body
 
     def unrescue_server(self, server_id):
         """Unrescue the provided server."""
diff --git a/tempest/services/identity/v3/json/identity_client.py b/tempest/services/identity/v3/json/identity_client.py
index 0188c2a..d57b931 100644
--- a/tempest/services/identity/v3/json/identity_client.py
+++ b/tempest/services/identity/v3/json/identity_client.py
@@ -135,8 +135,11 @@
         body = json.loads(body)
         return resp, body['project']
 
-    def list_projects(self):
-        resp, body = self.get("projects")
+    def list_projects(self, params=None):
+        url = "projects"
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+        resp, body = self.get(url)
         self.expected_success(200, resp.status)
         body = json.loads(body)
         return resp, body['projects']
diff --git a/tempest/services/identity/v3/xml/identity_client.py b/tempest/services/identity/v3/xml/identity_client.py
index f3e084e..c2bd77e 100644
--- a/tempest/services/identity/v3/xml/identity_client.py
+++ b/tempest/services/identity/v3/xml/identity_client.py
@@ -197,9 +197,12 @@
         body = self._parse_body(etree.fromstring(body))
         return resp, body
 
-    def list_projects(self):
+    def list_projects(self, params=None):
         """Get the list of projects."""
-        resp, body = self.get("projects")
+        url = 'projects'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+        resp, body = self.get(url)
         self.expected_success(200, resp.status)
         body = self._parse_projects(etree.fromstring(body))
         return resp, body
diff --git a/tempest/tests/test_auth.py b/tempest/tests/test_auth.py
index 1dcddad..6a2e335 100644
--- a/tempest/tests/test_auth.py
+++ b/tempest/tests/test_auth.py
@@ -59,12 +59,24 @@
     obviously don't test not implemented method or the ones which strongly
     depends on them.
     """
-    _auth_provider_class = auth.AuthProvider
 
-    def test_check_credentials_class(self):
-        self.assertRaises(NotImplementedError,
-                          self.auth_provider.check_credentials,
-                          auth.Credentials())
+    class FakeAuthProviderImpl(auth.AuthProvider):
+        def _decorate_request():
+            pass
+
+        def _fill_credentials():
+            pass
+
+        def _get_auth():
+            pass
+
+        def base_url():
+            pass
+
+        def is_expired():
+            pass
+
+    _auth_provider_class = FakeAuthProviderImpl
 
     def test_check_credentials_bad_type(self):
         self.assertFalse(self.auth_provider.check_credentials([]))
@@ -74,16 +86,6 @@
         auth_provider = self._auth(credentials={})
         self.assertIsInstance(auth_provider.credentials, auth.Credentials)
 
-    def test_instantiate_with_bad_credentials_type(self):
-        """
-        Assure that credentials with bad type fail with TypeError
-        """
-        self.assertRaises(TypeError, self._auth, [])
-
-    def test_auth_data_property(self):
-        self.assertRaises(NotImplementedError, getattr, self.auth_provider,
-                          'auth_data')
-
     def test_auth_data_property_when_cache_exists(self):
         self.auth_provider.cache = 'foo'
         self.useFixture(mockpatch.PatchObject(self.auth_provider,
@@ -110,9 +112,10 @@
         self.assertIsNone(self.auth_provider.alt_part)
         self.assertIsNone(self.auth_provider.alt_auth_data)
 
-    def test_fill_credentials(self):
-        self.assertRaises(NotImplementedError,
-                          self.auth_provider.fill_credentials)
+    def test_auth_class(self):
+        self.assertRaises(TypeError,
+                          auth.AuthProvider,
+                          fake_credentials.FakeCredentials)
 
 
 class TestKeystoneV2AuthProvider(BaseAuthTestsSetUp):