Metadata definition namespaces api added

Test case added

This is to check the functionality of namespaces api:
creation of namespace, get the detail about created namespace,
verify that namespace in non-protective mode can only be deleted,
parameter updated for created namespace.

Change-Id: I9e0e434240ce2eeed3b3a3a511a5a1e8944371f5
diff --git a/tempest/api/image/v2/test_images_metadefs_namespaces.py b/tempest/api/image/v2/test_images_metadefs_namespaces.py
new file mode 100644
index 0000000..21247b1
--- /dev/null
+++ b/tempest/api/image/v2/test_images_metadefs_namespaces.py
@@ -0,0 +1,71 @@
+# Copyright 2015 Red Hat, Inc.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.image import base
+from tempest.common.utils import data_utils
+from tempest import test
+from tempest_lib import exceptions as lib_exc
+
+
+class MetadataNamespacesTest(base.BaseV2ImageTest):
+    """
+    Here we will test the Metadata definition Namespaces basic functionality.
+    """
+    @test.idempotent_id('319b765e-7f3d-4b3d-8b37-3ca3876ee768')
+    def test_basic_metadata_definition_namespaces(self):
+        # get the available resource types and use one resource_type
+        body = self.client.list_resource_types()
+        resource_name = body['resource_types'][0]['name']
+        name = [{'name': resource_name}]
+        namespace_name = data_utils.rand_name('namespace')
+        # create the metadef namespaces
+        body = self.client.create_namespaces(namespace=namespace_name,
+                                             visibility='public',
+                                             description='Tempest',
+                                             display_name=namespace_name,
+                                             resource_type_associations=name,
+                                             protected=True)
+        self.addCleanup(self._cleanup_namespace, namespace_name)
+        # get namespaces details
+        body = self.client.show_namespaces(namespace_name)
+        self.assertEqual(namespace_name, body['namespace'])
+        self.assertEqual('public', body['visibility'])
+        # unable to delete protected namespace
+        self.assertRaises(lib_exc.Forbidden, self.client.delete_namespaces,
+                          namespace_name)
+        # update the visibility to private and protected to False
+        body = self.client.update_namespaces(namespace=namespace_name,
+                                             description='Tempest',
+                                             visibility='private',
+                                             display_name=namespace_name,
+                                             protected=False)
+        self.assertEqual('private', body['visibility'])
+        self.assertEqual(False, body['protected'])
+        # now able to delete the non-protected namespace
+        self.client.delete_namespaces(namespace_name)
+
+    def _cleanup_namespace(self, namespace_name):
+        # this is used to cleanup the resources
+        try:
+            body = self.client.show_namespaces(namespace_name)
+            self.assertEqual(namespace_name, body['namespace'])
+            body = self.client.update_namespaces(namespace=namespace_name,
+                                                 description='Tempest',
+                                                 visibility='private',
+                                                 display_name=namespace_name,
+                                                 protected=False)
+            self.client.delete_namespaces(namespace_name)
+        except lib_exc.NotFound:
+            pass
diff --git a/tempest/services/image/v2/json/image_client.py b/tempest/services/image/v2/json/image_client.py
index 6cad746..eea179d 100644
--- a/tempest/services/image/v2/json/image_client.py
+++ b/tempest/services/image/v2/json/image_client.py
@@ -212,3 +212,63 @@
         self.expected_success(200, resp.status)
         body = json.loads(body)
         return service_client.ResponseBody(resp, body)
+
+    def list_resource_types(self):
+        url = '/v2/metadefs/resource_types'
+        resp, body = self.get(url)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def create_namespaces(self, namespace, **kwargs):
+        params = {
+            "namespace": namespace,
+        }
+
+        for option in kwargs:
+            value = kwargs.get(option)
+            if isinstance(value, dict) or isinstance(value, tuple):
+                params.update(value)
+            else:
+                params[option] = value
+
+        data = json.dumps(params)
+        self._validate_schema(data)
+
+        resp, body = self.post('/v2/metadefs/namespaces', data)
+        self.expected_success(201, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def show_namespaces(self, namespace):
+        url = '/v2/metadefs/namespaces/%s' % namespace
+        resp, body = self.get(url)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def update_namespaces(self, namespace, visibility, **kwargs):
+        params = {
+            "namespace": namespace,
+            "visibility": visibility
+        }
+        for option in kwargs:
+            value = kwargs.get(option)
+            if isinstance(value, dict) or isinstance(value, tuple):
+                params.update(value)
+            else:
+                params[option] = value
+
+        data = json.dumps(params)
+        self._validate_schema(data)
+        url = '/v2/metadefs/namespaces/%s' % namespace
+        resp, body = self.put(url, body=data)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def delete_namespaces(self, namespace):
+        url = '/v2/metadefs/namespaces/%s' % namespace
+        resp, _ = self.delete(url)
+        self.expected_success(204, resp.status)
+        return service_client.ResponseBody(resp)