diff --git a/openstack_dashboard/api/glance.py b/openstack_dashboard/api/glance.py index a5ed6fdd73..ac45a0d17b 100644 --- a/openstack_dashboard/api/glance.py +++ b/openstack_dashboard/api/glance.py @@ -346,7 +346,12 @@ def metadefs_namespace_delete(request, namespace_name): def metadefs_resource_types_list(request): - return glanceclient(request, '2').metadefs_resource_type.list() + # Listing Resource Types requires the v2 API. If not supported we return + # an empty array so callers don't need to worry about version checking. + if get_version() < 2: + return [] + else: + return glanceclient(request, '2').metadefs_resource_type.list() def metadefs_namespace_resource_types(request, namespace_name): diff --git a/openstack_dashboard/api/rest/glance.py b/openstack_dashboard/api/rest/glance.py index f9fb02aa4b..06a1bf13de 100644 --- a/openstack_dashboard/api/rest/glance.py +++ b/openstack_dashboard/api/rest/glance.py @@ -253,6 +253,33 @@ class MetadefsNamespaces(generic.View): request, filters=filters, **kwargs ))) + +@urls.register +class MetadefsResourceTypesList(generic.View): + """API for getting Metadata Definitions Resource Types List. + + http://docs.openstack.org/developer/glance/metadefs-concepts.html + """ + url_regex = r'glance/metadefs/resourcetypes/$' + + @rest_utils.ajax() + def get(self, request): + """Get Metadata definitions resource types list. + + The listing result is an object with property "items". Each item is + a resource type. + + Example GET: + http://localhost/api/glance/resourcetypes/ + + Any request parameters will be passed through the API as filters. + """ + return { + 'items': [resource_type for resource_type in + api.glance.metadefs_resource_types_list(request)] + } + + def create_image_metadata(data): try: """Use the given dict of image form data to generate the metadata used for @@ -309,4 +336,3 @@ def handle_visibility(visibility, meta): meta['is_public'] = mapping_to_v1[visibility] except KeyError as e: raise rest_utils.AjaxError(400, "invalid visibility option: %s" % e.args[0]) - diff --git a/openstack_dashboard/static/app/core/openstack-service-api/glance.service.js b/openstack_dashboard/static/app/core/openstack-service-api/glance.service.js index 0e447b93db..5c8816e6ec 100644 --- a/openstack_dashboard/static/app/core/openstack-service-api/glance.service.js +++ b/openstack_dashboard/static/app/core/openstack-service-api/glance.service.js @@ -40,7 +40,8 @@ getImageProps: getImageProps, editImageProps: editImageProps, getImages: getImages, - getNamespaces: getNamespaces + getNamespaces: getNamespaces, + getResourceTypes: getResourceTypes }; return service; @@ -343,5 +344,30 @@ }); } + /** + * @name horizon.app.core.openstack-service-api.glance.getResourceTypes + * @description + * Get a list of metadata definition resource types. + * + * http://docs.openstack.org/developer/glance/metadefs-concepts.html + * + * The listing result is an object with property "items". + * Each item is a resource type. Resource types are Strings that + * correlate to Heat and Searchlight resource types. + * For example: OS::Glance::Image and OS::Nova::Instance. + * + */ + function getResourceTypes() { + var config = { + cache: true + }; + + return apiService + .get('/api/glance/metadefs/resourcetypes/', config) + .error(function() { + toastService.add('error', gettext('Unable to retrieve the resource types.')); + }); + } + } }()); diff --git a/openstack_dashboard/static/app/core/openstack-service-api/glance.service.spec.js b/openstack_dashboard/static/app/core/openstack-service-api/glance.service.spec.js index 0428684578..3dfb0e471e 100644 --- a/openstack_dashboard/static/app/core/openstack-service-api/glance.service.spec.js +++ b/openstack_dashboard/static/app/core/openstack-service-api/glance.service.spec.js @@ -154,6 +154,15 @@ "cache": true }, "error": "Unable to retrieve the namespaces." + }, + { + "func": "getResourceTypes", + "method": "get", + "path": "/api/glance/metadefs/resourcetypes/", + "data": { + "cache": true + }, + "error": "Unable to retrieve the resource types." } ]; diff --git a/openstack_dashboard/test/api_tests/glance_rest_tests.py b/openstack_dashboard/test/api_tests/glance_rest_tests.py index 49de1c67e8..e6962a4fad 100644 --- a/openstack_dashboard/test/api_tests/glance_rest_tests.py +++ b/openstack_dashboard/test/api_tests/glance_rest_tests.py @@ -341,3 +341,28 @@ class ImagesRestTestCase(test.TestCase): gc.metadefs_namespace_full_list.assert_called_once_with( request, filters=filters, **kwargs ) + + @mock.patch.object(glance.api, 'glance') + def test_resource_types_get_list(self, gc): + request = self.mock_rest_request(**{'GET': {}}) + gc.metadefs_resource_types_list.return_value = ([ + {"created_at": "2015-08-21T16:49:43Z", + "name": "OS::Glance::Image", + "updated_at": "2015-08-21T16:49:43Z"}, + {"created_at": "2015-08-21T16:49:43Z", + "name": "OS::Cinder::Volume", + "updated_at": "2015-08-21T16:49:43Z"} + ]) + + response = glance.MetadefsResourceTypesList().get(request) + self.assertStatusCode(response, 200) + self.assertEqual(response.json, {"items": [ + {"created_at": "2015-08-21T16:49:43Z", + "name": "OS::Glance::Image", + "updated_at": "2015-08-21T16:49:43Z"}, + {"created_at": "2015-08-21T16:49:43Z", + "name": "OS::Cinder::Volume", + "updated_at": "2015-08-21T16:49:43Z"} + ]}) + + gc.metadefs_resource_types_list.assert_called_once_with(request) diff --git a/openstack_dashboard/test/api_tests/glance_tests.py b/openstack_dashboard/test/api_tests/glance_tests.py index e9b3fa6cf9..b345eaf922 100644 --- a/openstack_dashboard/test/api_tests/glance_tests.py +++ b/openstack_dashboard/test/api_tests/glance_tests.py @@ -280,3 +280,12 @@ class GlanceApiTests(test.APITestCase): self.assertItemsEqual(defs, []) self.assertFalse(more) self.assertFalse(prev) + + def test_metadefs_resource_types_list_v1(self): + api.glance.get_version = self.mox.CreateMockAnything() + api.glance.get_version().AndReturn(1) + + self.mox.ReplayAll() + + res_types = api.glance.metadefs_resource_types_list(self.request) + self.assertItemsEqual(res_types, [])