Merge "Start making setup.py similar to other OpenStack Projects"
diff --git a/tempest/services/object_storage/object_client.py b/tempest/services/object_storage/object_client.py
index 440d043..c8f63ef 100644
--- a/tempest/services/object_storage/object_client.py
+++ b/tempest/services/object_storage/object_client.py
@@ -69,8 +69,8 @@
         resp, body = self.get(url)
         return resp, body
 
-    def copy_object(self, container, src_object_name, dest_object_name,
-                    metadata=None):
+    def copy_object_in_same_container(self, container, src_object_name,
+                                      dest_object_name, metadata=None):
         """Copy storage object's data to the new object using PUT"""
 
         url = "{0}/{1}".format(container, dest_object_name)
@@ -85,6 +85,23 @@
         resp, body = self.put(url, None, headers=headers)
         return resp, body
 
+    def copy_object_across_containers(self, src_container, src_object_name,
+                                      dst_container, dst_object_name,
+                                      metadata=None):
+        """Copy storage object's data to the new object using PUT"""
+
+        url = "{0}/{1}".format(dst_container, dst_object_name)
+        headers = {}
+        headers['X-Copy-From'] = "%s/%s" % (str(src_container),
+                                            str(src_object_name))
+        headers['content-length'] = '0'
+        if metadata:
+            for key in metadata:
+                headers[str(key)] = metadata[key]
+
+        resp, body = self.put(url, None, headers=headers)
+        return resp, body
+
     def copy_object_2d_way(self, container, src_object_name, dest_object_name,
                            metadata=None):
         """Copy storage object's data to the new object using COPY"""
diff --git a/tempest/tests/compute/keypairs/test_keypairs.py b/tempest/tests/compute/keypairs/test_keypairs.py
index 95520b5..9d297f6 100644
--- a/tempest/tests/compute/keypairs/test_keypairs.py
+++ b/tempest/tests/compute/keypairs/test_keypairs.py
@@ -137,6 +137,7 @@
             self.fail('Expected BadRequest for invalid public key')
 
     @attr(type='negative')
+    @unittest.skip("Skipped until the Bug #1086980 is resolved")
     def test_keypair_delete_nonexistant_key(self):
         """Non-existant key deletion should throw a proper error"""
         k_name = rand_name("keypair-non-existant-")
diff --git a/tempest/tests/compute/servers/test_create_server.py b/tempest/tests/compute/servers/test_create_server.py
index 5d6c2ba..0d9efc6 100644
--- a/tempest/tests/compute/servers/test_create_server.py
+++ b/tempest/tests/compute/servers/test_create_server.py
@@ -35,6 +35,9 @@
         cls.meta = {'hello': 'world'}
         cls.accessIPv4 = '1.1.1.1'
         cls.accessIPv6 = '::babe:220.12.22.2'
+        # See: http://tools.ietf.org/html/rfc5952 (section 4)
+        # This is the canonicalized form of the above.
+        cls.accessIPv6canon = '::babe:dc0c:1602'
         cls.name = rand_name('server')
         file_contents = 'This is a test file.'
         personality = [{'path': '/etc/test.txt',
@@ -66,9 +69,9 @@
     @attr(type='smoke')
     def test_verify_server_details(self):
         """Verify the specified server attributes are set correctly"""
-
         self.assertEqual(self.accessIPv4, self.server['accessIPv4'])
-        self.assertEqual(self.accessIPv6, self.server['accessIPv6'])
+        self.assertIn(self.server['accessIPv6'],
+                      [self.accessIPv6, self.accessIPv6canon])
         self.assertEqual(self.name, self.server['name'])
         self.assertEqual(self.image_ref, self.server['image']['id'])
         self.assertEqual(str(self.flavor_ref), self.server['flavor']['id'])
diff --git a/tempest/tests/compute/test_authorization.py b/tempest/tests/compute/test_authorization.py
index 12fa94b..0d08c18 100644
--- a/tempest/tests/compute/test_authorization.py
+++ b/tempest/tests/compute/test_authorization.py
@@ -232,6 +232,7 @@
 
     @raises(exceptions.NotFound)
     @attr(type='negative')
+    @unittest.skip("Skipped until the Bug #1086980 is resolved")
     def test_delete_keypair_of_alt_account_fails(self):
         """A DELETE request for another user's keypair should fail"""
         self.alt_keypairs_client.delete_keypair(self.keypairname)
diff --git a/tempest/tests/object_storage/test_object_services.py b/tempest/tests/object_storage/test_object_services.py
index d0862eb..97b7e0d 100644
--- a/tempest/tests/object_storage/test_object_services.py
+++ b/tempest/tests/object_storage/test_object_services.py
@@ -122,7 +122,7 @@
         self.assertEqual(body, data)
 
     @attr(type='smoke')
-    def test_copy_object(self):
+    def test_copy_object_in_same_container(self):
         """Copy storage object"""
 
         # Create source Object
@@ -140,9 +140,8 @@
                                                    dst_object_name, dst_data)
 
         # Copy source object to destination
-        resp, _ = self.object_client.copy_object(self.container_name,
-                                                 src_object_name,
-                                                 dst_object_name)
+        resp, _ = self.object_client.copy_object_in_same_container(
+            self.container_name, src_object_name, dst_object_name)
         self.assertEqual(resp['status'], '201')
 
         # Check data
@@ -161,15 +160,13 @@
                                                    object_name, data)
         # Get the old content type
         resp_tmp, _ = self.object_client.list_object_metadata(
-                                                        self.container_name,
-                                                        object_name)
+            self.container_name,
+            object_name)
         # Change the content type of the object
         metadata = {'content-type': 'text/plain; charset=UTF-8'}
         self.assertNotEqual(resp_tmp['content-type'], metadata['content-type'])
-        resp, _ = self.object_client.copy_object(self.container_name,
-                                                 object_name,
-                                                 object_name,
-                                                 metadata)
+        resp, _ = self.object_client.copy_object_in_same_container(
+            self.container_name, object_name, object_name, metadata)
         self.assertEqual(resp['status'], '201')
 
         # Check the content type
@@ -205,3 +202,62 @@
         resp, body = self.object_client.get_object(self.container_name,
                                                    dst_object_name)
         self.assertEqual(body, src_data)
+
+    @attr(type='smoke')
+    def test_copy_object_across_containers(self):
+        """Copy storage object across containers"""
+
+        #Create a container so as to use as source container
+        src_container_name = rand_name(name='TestSourceContainer')
+        self.container_client.create_container(src_container_name)
+
+        #Create a container so as to use as destination container
+        dst_container_name = rand_name(name='TestDestinationContainer')
+        self.container_client.create_container(dst_container_name)
+
+        # Create Object in source container
+        object_name = rand_name(name='Object')
+        data = arbitrary_string(size=len(object_name) * 2,
+                                base_text=object_name)
+        resp, _ = self.object_client.create_object(src_container_name,
+                                                   object_name, data)
+        #Set Object Metadata
+        meta_key = rand_name(name='test-')
+        meta_value = rand_name(name='MetaValue-')
+        orig_metadata = {meta_key: meta_value}
+
+        resp, _ = \
+            self.object_client.update_object_metadata(src_container_name,
+                                                      object_name,
+                                                      orig_metadata)
+        self.assertEqual(resp['status'], '202')
+
+        try:
+            # Copy object from source container to destination container
+            resp, _ = self.object_client.copy_object_across_containers(
+                src_container_name, object_name, dst_container_name,
+                object_name)
+            self.assertEqual(resp['status'], '201')
+
+            # Check if object is present in destination container
+            resp, body = self.object_client.get_object(dst_container_name,
+                                                       object_name)
+            self.assertEqual(body, data)
+            actual_meta_key = 'x-object-meta-' + meta_key
+            self.assertTrue(actual_meta_key in resp)
+            self.assertEqual(resp[actual_meta_key], meta_value)
+
+        except Exception as e:
+            self.fail("Got exception :%s ; while copying"
+                      " object across containers" % e)
+        finally:
+            #Delete objects from respective containers
+            resp, _ = self.object_client.delete_object(dst_container_name,
+                                                       object_name)
+            resp, _ = self.object_client.delete_object(src_container_name,
+                                                       object_name)
+            #Delete containers created in this method
+            resp, _ = self.container_client.delete_container(
+                src_container_name)
+            resp, _ = self.container_client.delete_container(
+                dst_container_name)