From ed105693c3ce53c58c0b99715f445dcf4e7a161e Mon Sep 17 00:00:00 2001 From: Shu Muto Date: Fri, 15 Dec 2017 14:49:03 +0900 Subject: [PATCH] Add APIs for Quotas This patch adds APIs for Quotas. Added APIs are for CLI, REST API for Ajax and REST service for Angular. Change-Id: Ibf5dbd73eafefaff688f225b7e3dbdce0d3de47f Depends-On: I1d61bcb3a4fd4b93a5f42eb2c440d2a22c673a0b --- magnum_ui/api/magnum.py | 35 +++++++++-- magnum_ui/api/rest/magnum.py | 61 +++++++++++++++++++ .../container-infra/magnum.service.js | 47 ++++++++++++++ .../container-infra/magnum.service.spec.js | 61 ++++++++++++++++++- 4 files changed, 199 insertions(+), 5 deletions(-) diff --git a/magnum_ui/api/magnum.py b/magnum_ui/api/magnum.py index 4cafcd34..e6958e00 100644 --- a/magnum_ui/api/magnum.py +++ b/magnum_ui/api/magnum.py @@ -26,12 +26,14 @@ from magnumclient.v1 import certificates from magnumclient.v1 import client as magnum_client from magnumclient.v1 import cluster_templates from magnumclient.v1 import clusters +from magnumclient.v1 import quotas LOG = logging.getLogger(__name__) CLUSTER_TEMPLATE_CREATE_ATTRS = cluster_templates.CREATION_ATTRIBUTES CLUSTER_CREATE_ATTRS = clusters.CREATION_ATTRIBUTES CERTIFICATE_CREATE_ATTRS = certificates.CREATION_ATTRIBUTES +QUOTA_CREATION_ATTRIBUTES = quotas.CREATION_ATTRIBUTES def _cleanup_params(attrs, create, **params): @@ -197,7 +199,32 @@ def certificate_rotate(request, id): return magnumclient(request).certificates.rotate_ca(**args) -def stats_list(request, limit=None, marker=None, sort_key=None, - sort_dir=None, detail=True): - return magnumclient(request).stats.list( - limit, marker, sort_key, sort_dir, detail) +def stats_list(request, project_id=None): + return magnumclient(request).stats.list(project_id=project_id) + + +def quotas_list(request, limit=None, marker=None, sort_key=None, + sort_dir=None, all_tenants=True): + return magnumclient(request).quotas.list( + limit, marker, sort_key, sort_dir, all_tenants) + + +def quotas_show(request, project_id, resource): + return magnumclient(request).quotas.get(project_id, resource) + + +def quotas_create(request, **kwargs): + args = _cleanup_params(QUOTA_CREATION_ATTRIBUTES, True, **kwargs) + return magnumclient(request).quotas.create(**args) + + +def quotas_update(request, project_id, resource, **kwargs): + new = _cleanup_params(QUOTA_CREATION_ATTRIBUTES, True, **kwargs) + old = magnumclient(request).quotas.get(project_id, resource).to_dict() + old = _cleanup_params(QUOTA_CREATION_ATTRIBUTES, False, **old) + patch = _create_patches(old, new) + return magnumclient(request).quotas.update(project_id, resource, patch) + + +def quotas_delete(request, project_id, resource): + return magnumclient(request).quotas.delete(project_id, resource) diff --git a/magnum_ui/api/rest/magnum.py b/magnum_ui/api/rest/magnum.py index 799aa1c1..e2450861 100644 --- a/magnum_ui/api/rest/magnum.py +++ b/magnum_ui/api/rest/magnum.py @@ -205,8 +205,69 @@ class Stats(generic.View): item under this is a Stat. """ result = magnum.stats_list(request) + return {'stats': {'clusters': result.clusters, 'nodes': result.nodes}} + + +@urls.register +class Quota(generic.View): + """API for retrieving a single Quota""" + url_regex =\ + r'container_infra/quotas/(?P[^/]+)/(?P[^/]+)$' + + @rest_utils.ajax() + def get(self, request, project_id, resource): + """Get a specific quota""" + return magnum.quotas_show(request, project_id, resource).to_dict() + + @rest_utils.ajax(data_required=True) + def patch(self, request, project_id, resource): + """Update a Quota. + + Returns the Quota object on success. + """ + params = request.DATA + updated = magnum.quotas_update( + request, project_id, resource, **params) + return rest_utils.CreatedResponse( + ('/api/container_infra/quotas/%s/%s' % project_id, resource), + updated.to_dict()) + + @rest_utils.ajax(data_required=True) + def delete(self, request, project_id, resource): + """Delete one Quota by id and resource. + + Returns HTTP 204 (no content) on successful deletion. + """ + magnum.quotas_delete(request, project_id, resource) + + +@urls.register +class Quotas(generic.View): + """API for Magnum Quotas""" + url_regex = r'container_infra/quotas/$' + + @rest_utils.ajax() + def get(self, request): + """Get a list of the Quotas for a project. + + The returned result is an object with property 'items' and each + item under this is a Quota. + """ + result = magnum.quotas_list(request) return {'items': [change_to_id(n.to_dict()) for n in result]} + @rest_utils.ajax(data_required=True) + def post(self, request): + """Create a new Quota. + + Returns the new Quota object on success. + """ + created = magnum.quotas_create(request, **request.DATA) + return rest_utils.CreatedResponse( + ('/api/container_infra/quotas/%s/%s' % created.uuid, + created.resource), + created.to_dict()) + @urls.register class Networks(generic.View): diff --git a/magnum_ui/static/dashboard/container-infra/magnum.service.js b/magnum_ui/static/dashboard/container-infra/magnum.service.js index 7641e2c0..85a01e2a 100644 --- a/magnum_ui/static/dashboard/container-infra/magnum.service.js +++ b/magnum_ui/static/dashboard/container-infra/magnum.service.js @@ -45,6 +45,11 @@ signCertificate: signCertificate, rotateCertificate: rotateCertificate, getStats: getStats, + getQuotas: getQuotas, + getQuota: getQuota, + createQuota: createQuota, + updateQuota: updateQuota, + deleteQuota: deleteQuota, getNetworks: getNetworks, downloadTextAsFile: downloadTextAsFile }; @@ -183,6 +188,48 @@ }); } + ////////////// + // Quotas // + ////////////// + + function getQuotas() { + return apiService.get('/api/container_infra/quotas/') + .error(function() { + toastService.add('error', gettext('Unable to retrieve the quotas.')); + }); + } + + function getQuota(projectId, resource, suppressError) { + var promise = apiService.get('/api/container_infra/quotas/' + projectId + '/' + resource); + return suppressError ? promise : promise.error(function() { + toastService.add('error', gettext('Unable to retrieve the quota.')); + }); + } + + function createQuota(projectId, resource, params) { + return apiService.post('/api/container_infra/quotas/' + projectId + '/' + resource, params) + .error(function() { + toastService.add('error', gettext('Unable to create quota.')); + }); + } + + function updateQuota(projectId, resource, params) { + return apiService.patch('/api/container_infra/quotas/' + projectId + '/' + resource, params) + .error(function() { + toastService.add('error', gettext('Unable to update quota.')); + }); + } + + function deleteQuota(projectId, resource, suppressError) { + var promise = apiService.delete('/api/container_infra/quotas/' + projectId + '/' + resource); + return suppressError ? promise : promise.error(function() { + var msg = gettext('Unable to delete the quota with project id: %(projectId)s and ' + + 'resource: %(resource)s.'); + toastService.add('error', + interpolate(msg, { projectId: projectId, resource: resource }, true)); + }); + } + ////////////////// // Networks // ////////////////// diff --git a/magnum_ui/static/dashboard/container-infra/magnum.service.spec.js b/magnum_ui/static/dashboard/container-infra/magnum.service.spec.js index 511cc1cd..be8bb19b 100644 --- a/magnum_ui/static/dashboard/container-infra/magnum.service.spec.js +++ b/magnum_ui/static/dashboard/container-infra/magnum.service.spec.js @@ -61,7 +61,6 @@ "path": "/api/container_infra/clusters/123", "error": "Unable to retrieve the cluster.", "testInput": ["123"] - }, { "func": "getClusters", @@ -161,6 +160,66 @@ "error": "Unable to rotate the certificate.", "testInput": [123, [123]] }, + { + "func": "getQuotas", + "method": "get", + "path": "/api/container_infra/quotas/", + "error": "Unable to retrieve the quotas." + }, + { + "func": "getQuota", + "method": "get", + "path": "/api/container_infra/quotas/123/Cluster", + "error": "Unable to retrieve the quota.", + "testInput": ["123", "Cluster"] + }, + { + "func": "createQuota", + "method": "post", + "path": "/api/container_infra/quotas/123/Cluster", + "data": { + "project_id": "123", + "resource": "Cluster", + "hard_limit": "1" + }, + "error": "Unable to create quota.", + "testInput": [ + "123", + "Cluster", + { + "project_id": "123", + "resource": "Cluster", + "hard_limit": "1" + } + ] + }, + { + "func": "updateQuota", + "method": "patch", + "path": "/api/container_infra/quotas/123/Cluster", + "data": { + "project_id": "123", + "resource": "Cluster", + "hard_limit": "1" + }, + "error": "Unable to update quota.", + "testInput": [ + "123", + "Cluster", + { + "project_id": "123", + "resource": "Cluster", + "hard_limit": "1" + } + ] + }, + { + "func": "deleteQuota", + "method": "delete", + "path": "/api/container_infra/quotas/123/Cluster", + "error": "Unable to delete the quota with project id: 123 and resource: Cluster.", + "testInput": ["123", "Cluster"] + }, { "func": "getStats", "method": "get",