diff --git a/openstack_dashboard/api/rest/cinder.py b/openstack_dashboard/api/rest/cinder.py index fd1e6a759f..ef97ae4566 100644 --- a/openstack_dashboard/api/rest/cinder.py +++ b/openstack_dashboard/api/rest/cinder.py @@ -425,3 +425,25 @@ class QuotaSets(generic.View): api.cinder.tenant_quota_update(request, project_id, **cinder_data) else: raise rest_utils.AjaxError(501, _('Service Cinder is disabled.')) + + +@urls.register +class AvailabilityZones(generic.View): + """API for cinder availability zones.""" + url_regex = r'cinder/availzones/$' + + @rest_utils.ajax() + def get(self, request): + """Get a list of availability zones. + + The following get parameters may be passed in the GET + request: + + :param detailed: If this equals "true" then the result will + include more detail. + + The listing result is an object with property "items". + """ + detailed = request.GET.get('detailed') == 'true' + result = api.cinder.availability_zone_list(request, detailed) + return {'items': [u.to_dict() for u in result]} diff --git a/openstack_dashboard/static/app/core/images/steps/create-volume/create-volume.controller.js b/openstack_dashboard/static/app/core/images/steps/create-volume/create-volume.controller.js index dc7dc4ec55..698d8f20b0 100644 --- a/openstack_dashboard/static/app/core/images/steps/create-volume/create-volume.controller.js +++ b/openstack_dashboard/static/app/core/images/steps/create-volume/create-volume.controller.js @@ -137,7 +137,7 @@ function init() { cinder.getVolumeTypes().success(onGetVolumeTypes); cinder.getAbsoluteLimits().success(onGetAbsoluteLimits); - nova.getAvailabilityZones().success(onGetAvailabilityZones); + cinder.getAvailabilityZones().success(onGetAvailabilityZones); } function onGetVolumeTypes(response) { diff --git a/openstack_dashboard/static/app/core/images/steps/create-volume/create-volume.controller.spec.js b/openstack_dashboard/static/app/core/images/steps/create-volume/create-volume.controller.spec.js index a142b6ddb0..caee3bd310 100644 --- a/openstack_dashboard/static/app/core/images/steps/create-volume/create-volume.controller.spec.js +++ b/openstack_dashboard/static/app/core/images/steps/create-volume/create-volume.controller.spec.js @@ -34,6 +34,13 @@ } }; }, + getAvailabilityZones: function() { + return { + success: function(callback) { + return callback({ items: [{zoneName: 'zone1'}] }); + } + }; + }, getAbsoluteLimits: angular.noop }; @@ -43,15 +50,6 @@ beforeEach(inject(function ($injector, _$rootScope_, _$filter_) { - nova = { - getAvailabilityZones: function() { - return { - success: function(callback) { - return callback({ items: [{zoneName: 'zone1'}] }); - } - }; - } - }; $scope = _$rootScope_.$new(); $scope.image = { name: 'ImageName', @@ -358,7 +356,7 @@ it('not default the availability_zone if none present', function() { - nova.getAvailabilityZones = function() { + cinder.getAvailabilityZones = function() { return { success: function(callback) { return callback({ items: [] }); diff --git a/openstack_dashboard/static/app/core/openstack-service-api/cinder.service.js b/openstack_dashboard/static/app/core/openstack-service-api/cinder.service.js index dd0ce2d702..45e889d305 100644 --- a/openstack_dashboard/static/app/core/openstack-service-api/cinder.service.js +++ b/openstack_dashboard/static/app/core/openstack-service-api/cinder.service.js @@ -46,6 +46,7 @@ getVolumeSnapshots: getVolumeSnapshots, getExtensions: getExtensions, getQoSSpecs: getQoSSpecs, + getAvailabilityZones:getAvailabilityZones, createVolume: createVolume, getAbsoluteLimits: getAbsoluteLimits, getServices: getServices, @@ -403,6 +404,25 @@ toastService.add('error', gettext('Unable to update project quota data.')); }); } + + // Availability Zones + + /** + * @name getAvailabilityZones + * @description + * Get a list of Availability Zones. + * + * The listing result is an object with property "items". Each item is + * an availability zone. + * @returns {Object} The result of the API call + */ + function getAvailabilityZones() { + return apiService.get('/api/cinder/availzones/') + .error(function () { + toastService.add('error', + gettext('Unable to retrieve the volume availability zones.')); + }); + } } }()); diff --git a/openstack_dashboard/static/app/core/openstack-service-api/cinder.service.spec.js b/openstack_dashboard/static/app/core/openstack-service-api/cinder.service.spec.js index 4b2ba4d704..d08bf741ed 100644 --- a/openstack_dashboard/static/app/core/openstack-service-api/cinder.service.spec.js +++ b/openstack_dashboard/static/app/core/openstack-service-api/cinder.service.spec.js @@ -222,6 +222,13 @@ testInput: [ 42, {a: '1', b: '2'}, ['c', 'd'] ] + }, + { + func: 'getAvailabilityZones', + method: 'get', + path: '/api/cinder/availzones/', + error: 'Unable to retrieve the volume availability zones.', + testInput: [] } ]; diff --git a/openstack_dashboard/test/api_tests/cinder_rest_tests.py b/openstack_dashboard/test/api_tests/cinder_rest_tests.py index 925dffa6ba..2f2436a037 100644 --- a/openstack_dashboard/test/api_tests/cinder_rest_tests.py +++ b/openstack_dashboard/test/api_tests/cinder_rest_tests.py @@ -482,3 +482,21 @@ class CinderRestTestCase(test.TestCase): self.assertEqual(response.content.decode('utf-8'), '"Service Cinder is disabled."') cc.tenant_quota_update.assert_not_called() + + @test.create_stubs({api.base: ('is_service_enabled',)}) + @mock.patch.object(cinder.api, 'cinder') + def test_availability_zones_get(self, cc): + request = self.mock_rest_request(GET={}) + mock_az = mock.Mock() + mock_az.to_dict.return_value = { + 'name': 'cinder', + 'status': 'available' + } + cc.availability_zone_list.return_value = [mock_az] + self.mox.ReplayAll() + + response = cinder.AvailabilityZones().get(request) + self.assertStatusCode(response, 200) + response_as_json = json.loads(response.content.decode('utf-8')) + self.assertEqual(response_as_json['items'][0]['name'], 'cinder') + cc.availability_zone_list.assert_called_once_with(request, False)