Added Swift tests:
      * account: delete account metadata
      * container: retrieve/delete container metadata
      * object: retrieve/copy(2 ways) object
Syntax bug fix in container_client.py:
      return resp. body => return resp, body
Fixed passing headers parameter in head method in rest_client.py:
      return self.request('HEAD', url, headers)
Removed unused imports.

Change-Id: Ica67d6ecae80f851e9e05ebeb4c7d461eba143ee
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index 6683b78..52ed6bc 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -172,7 +172,10 @@
         return self.request('PUT', url, headers, body)
 
     def head(self, url, headers=None):
-        return self.request('HEAD', url, headers=None)
+        return self.request('HEAD', url, headers)
+
+    def copy(self, url, headers=None):
+        return self.request('COPY', url, headers)
 
     def _log(self, req_url, body, resp, resp_body):
         self.log.error('Request URL: ' + req_url)
diff --git a/tempest/services/object_storage/account_client.py b/tempest/services/object_storage/account_client.py
index 2a686f6..4eaeb34 100644
--- a/tempest/services/object_storage/account_client.py
+++ b/tempest/services/object_storage/account_client.py
@@ -47,6 +47,18 @@
         resp, body = self.post('', headers=headers, body=None)
         return resp, body
 
+    def delete_account_metadata(self, metadata,
+                                metadata_prefix='X-Remove-Account-Meta-'):
+        """
+        Deletes an account metadata entry.
+        """
+
+        headers = {"X-Storage-Token": self.token}
+        for item in metadata:
+            headers[metadata_prefix + item] = 'x'
+        resp, body = self.post('', headers=headers, body=None)
+        return resp, body
+
     def list_account_containers(self, params=None):
         """
         GET on the (base) storage URL
diff --git a/tempest/services/object_storage/container_client.py b/tempest/services/object_storage/container_client.py
index 56dffde..bb08de2 100644
--- a/tempest/services/object_storage/container_client.py
+++ b/tempest/services/object_storage/container_client.py
@@ -63,8 +63,29 @@
                 headers[metadata_prefix + key] = metadata[key]
 
         resp, body = self.post(url, body=None, headers=headers)
+        return resp, body
 
-        return resp. body
+    def delete_container_metadata(self, container_name, metadata,
+                                  metadata_prefix='X-Remove-Container-Meta-'):
+        """Deletes arbitrary metadata on container"""
+        url = container_name
+        headers = {}
+
+        if metadata is not None:
+            for item in metadata:
+                headers[metadata_prefix + item] = 'x'
+
+        resp, body = self.post(url, body=None, headers=headers)
+        return resp, body
+
+    def list_container_metadata(self, container_name):
+        """
+        Retrieves container metadata headers
+        """
+        url = container_name
+        headers = {"X-Storage-Token": self.token}
+        resp, body = self.head(url, headers=headers)
+        return resp, body
 
     def list_all_container_objects(self, container, params=None):
         """
diff --git a/tempest/services/object_storage/object_client.py b/tempest/services/object_storage/object_client.py
index 0fc7ad4..440d043 100644
--- a/tempest/services/object_storage/object_client.py
+++ b/tempest/services/object_storage/object_client.py
@@ -61,3 +61,41 @@
         url = "%s/%s" % (str(container), str(object_name))
         resp, body = self.head(url)
         return resp, body
+
+    def get_object(self, container, object_name):
+        """Retrieve object's data."""
+
+        url = "{0}/{1}".format(container, object_name)
+        resp, body = self.get(url)
+        return resp, body
+
+    def copy_object(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)
+        headers = {}
+        headers['X-Copy-From'] = "%s/%s" % (str(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"""
+
+        url = "{0}/{1}".format(container, src_object_name)
+        headers = {}
+        headers['Destination'] = "%s/%s" % (str(container),
+                                            str(dest_object_name))
+        if metadata:
+            for key in metadata:
+                headers[str(key)] = metadata[key]
+
+        resp, body = self.copy(url, headers=headers)
+        return resp, body
diff --git a/tempest/tests/object_storage/test_account_services.py b/tempest/tests/object_storage/test_account_services.py
index 6d34bb8..db3aa69 100644
--- a/tempest/tests/object_storage/test_account_services.py
+++ b/tempest/tests/object_storage/test_account_services.py
@@ -15,13 +15,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import unittest2 as unittest
-import tempest.config
-import re
-
 from nose.plugins.attrib import attr
-from tempest import exceptions
-from tempest import openstack
 from tempest.common.utils.data_utils import rand_name
 from tempest.tests.object_storage import base
 
@@ -74,3 +68,15 @@
         resp, metadata = self.account_client.list_account_metadata()
         self.assertIn('x-account-meta-test-account-meta', resp)
         self.assertEqual(resp['x-account-meta-test-account-meta'], 'Meta!')
+
+    @attr(type='smoke')
+    def test_delete_account_metadata(self):
+        """Delete metadata from account"""
+
+        metadata = ['test-account-meta']
+        resp, _ = \
+            self.account_client.delete_account_metadata(metadata=metadata)
+        self.assertEqual(resp['status'], '204')
+
+        resp, metadata = self.account_client.list_account_metadata()
+        self.assertNotIn('x-account-meta-test-account-meta', resp)
diff --git a/tempest/tests/object_storage/test_container_services.py b/tempest/tests/object_storage/test_container_services.py
index 639698b..e57256b 100644
--- a/tempest/tests/object_storage/test_container_services.py
+++ b/tempest/tests/object_storage/test_container_services.py
@@ -15,13 +15,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import re
-import unittest2 as unittest
-import tempest.config
-
 from nose.plugins.attrib import attr
-from tempest import exceptions
-from tempest import openstack
 from tempest.common.utils.data_utils import rand_name, arbitrary_string
 from tempest.tests.object_storage import base
 
@@ -108,3 +102,47 @@
 
         object_names = [obj['name'] for obj in object_list]
         self.assertIn(object_name, object_names)
+
+    @attr(type='smoke')
+    def test_container_metadata(self):
+        """Update/Retrieve/Delete Container Metadata"""
+
+        # Create a container
+        container_name = rand_name(name='TestContainer')
+        resp, _ = self.container_client.create_container(container_name)
+        self.containers.append(container_name)
+
+        # Update container metadata
+        metadata = {'name': 'Pictures',
+                    'description': 'Travel'
+                    }
+        resp, _ = \
+            self.container_client.update_container_metadata(container_name,
+                                                            metadata=metadata)
+        self.assertEqual(resp['status'], '204')
+
+        # List container metadata
+        resp, _ = self.container_client.list_container_metadata(
+                                                            container_name)
+        self.assertEqual(resp['status'], '204')
+        self.assertIn('x-container-meta-name', resp)
+        self.assertIn('x-container-meta-description', resp)
+        self.assertEqual(resp['x-container-meta-name'], 'Pictures')
+        self.assertEqual(resp['x-container-meta-description'], 'Travel')
+
+        # Delete container metadata
+        resp, _ = \
+            self.container_client.delete_container_metadata(
+                                                    container_name,
+                                                    metadata=metadata.keys())
+        self.assertEqual(resp['status'], '204')
+
+        resp, _ = self.container_client.list_container_metadata(container_name)
+        self.assertEqual(resp['status'], '204')
+        self.assertNotIn('x-container-meta-name', resp)
+        self.assertNotIn('x-container-meta-description', resp)
+
+        # Delete Container
+        resp, _ = self.container_client.delete_container(container_name)
+        self.assertEqual(resp['status'], '204')
+        self.containers.remove(container_name)
diff --git a/tempest/tests/object_storage/test_object_services.py b/tempest/tests/object_storage/test_object_services.py
index ab92d26..cb72e9d 100644
--- a/tempest/tests/object_storage/test_object_services.py
+++ b/tempest/tests/object_storage/test_object_services.py
@@ -15,13 +15,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import re
-import unittest2 as unittest
-import tempest.config
-
 from nose.plugins.attrib import attr
-from tempest import exceptions
-from tempest import openstack
 from tempest.common.utils.data_utils import rand_name, arbitrary_string
 from tempest.tests.object_storage import base
 
@@ -110,3 +104,104 @@
         actual_meta_key = 'x-object-meta-' + meta_key
         self.assertTrue(actual_meta_key in resp)
         self.assertEqual(resp[actual_meta_key], meta_value)
+
+    @attr(type='smoke')
+    def test_get_object(self):
+        """Retrieve object's data(in response body)"""
+
+        #Create Object
+        object_name = rand_name(name='TestObject')
+        data = arbitrary_string()
+        resp, _ = self.object_client.create_object(self.container_name,
+                                                   object_name, data)
+
+        resp, body = self.object_client.get_object(self.container_name,
+                                                   object_name)
+        self.assertEqual(resp['status'], '200')
+        # Check data
+        self.assertEqual(body, data)
+
+    @attr(type='smoke')
+    def test_copy_object(self):
+        """Copy storage object"""
+
+        # Create source Object
+        src_object_name = rand_name(name='SrcObject')
+        src_data = arbitrary_string(size=len(src_object_name) * 2,
+                                    base_text=src_object_name)
+        resp, _ = self.object_client.create_object(self.container_name,
+                                                   src_object_name, src_data)
+
+        # Create destinametion Object
+        dst_object_name = rand_name(name='DstObject')
+        dst_data = arbitrary_string(size=len(dst_object_name) * 3,
+                                    base_text=dst_object_name)
+        resp, _ = self.object_client.create_object(self.container_name,
+                                                   dst_object_name, dst_data)
+
+        # Copy source object to destination
+        resp, _ = self.object_client.copy_object(self.container_name,
+                                                 src_object_name,
+                                                 dst_object_name)
+        self.assertEqual(resp['status'], '201')
+
+        # Check data
+        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_to_itself(self):
+        """Change the content type of an existing object"""
+
+        # Create Object
+        object_name = rand_name(name='TestObject')
+        data = arbitrary_string()
+        resp, _ = self.object_client.create_object(self.container_name,
+                                                   object_name, data)
+        # Get the old content type
+        resp_tmp, _ = self.object_client.list_object_metadata(
+                                                        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)
+        self.assertEqual(resp['status'], '201')
+
+        # Check the content type
+        resp, _ = self.object_client.list_object_metadata(self.container_name,
+                                                          object_name)
+        self.assertEqual(resp['content-type'], metadata['content-type'])
+
+    @attr(type='smoke')
+    def test_copy_object_2d_way(self):
+        """Copy storage object"""
+
+        # Create source Object
+        src_object_name = rand_name(name='SrcObject')
+        src_data = arbitrary_string(size=len(src_object_name) * 2,
+                                    base_text=src_object_name)
+        resp, _ = self.object_client.create_object(self.container_name,
+                                                   src_object_name, src_data)
+
+        # Create destinametion Object
+        dst_object_name = rand_name(name='DstObject')
+        dst_data = arbitrary_string(size=len(dst_object_name) * 3,
+                                    base_text=dst_object_name)
+        resp, _ = self.object_client.create_object(self.container_name,
+                                                   dst_object_name, dst_data)
+
+        # Copy source object to destination
+        resp, _ = self.object_client.copy_object_2d_way(self.container_name,
+                                                        src_object_name,
+                                                        dst_object_name)
+        self.assertEqual(resp['status'], '201')
+
+        # Check data
+        resp, body = self.object_client.get_object(self.container_name,
+                                                   dst_object_name)
+        self.assertEqual(body, src_data)