diff --git a/magnum_ui/static/dashboard/container-infra/clusters/cluster-stats.controller.js b/magnum_ui/static/dashboard/container-infra/clusters/cluster-stats.controller.js new file mode 100644 index 00000000..72111de1 --- /dev/null +++ b/magnum_ui/static/dashboard/container-infra/clusters/cluster-stats.controller.js @@ -0,0 +1,94 @@ +/** + * 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. + */ + +(function() { + 'use strict'; + + /** + * @ngdoc controller + * @name clusterStatsController + * @ngController + * + * @description + * Controller to show stats and quota charts for cluster in cluster table view + */ + angular + .module('horizon.dashboard.container-infra.clusters') + .controller( + 'horizon.dashboard.container-infra.clusters.clusterStatsController', + clusterStatsController); + + clusterStatsController.$inject = [ + '$q', + '$scope', + 'horizon.app.core.openstack-service-api.magnum', + 'horizon.app.core.openstack-service-api.userSession' + ]; + + function clusterStatsController($q, $scope, magnum, userSession) { + var ctrl = this; + ctrl.chartSettings = { + innerRadius: 24, + outerRadius: 48, + titleClass: "pie-chart-title-medium", + showTitle: false, + showLabel: true, + showLegend: false, + tooltipIcon: 'fa-square' + }; + // Chart data is watched by pie-chart directive. + // So to refresh chart after retrieving data, update whole of 'data' array. + ctrl.chartDataClusters = { + maxLimit: 20, + data: [] + }; + // container for temporal chart data + var dataClusters = []; + userSession.get().then(onGetUserSession); + + function onGetUserSession(session) { + ctrl.projectId = session.project_id; + magnum.getStats().then(onGetStats); + } + + function onGetStats(response) { + ctrl.stats = response.data.stats; + dataClusters = [ + {label: gettext("Exists"), value: response.data.stats.clusters, colorClass: "exists"}, + {label: gettext("Margin"), value: 20 - response.data.stats.clusters, colorClass: "margin"} + ]; + magnum.getQuota(ctrl.projectId, "Cluster", true).then(onGetQuotaCluster, onGetQuotaCluster); + } + + function onGetQuotaCluster(response) { + // set data for clusters chart + var sum = dataClusters[0].value; + var max = dataClusters[1].value; + if (response.data.hard_limit) { + max = response.data.hard_limit; + dataClusters[1].value = max - sum; + } + var percent = Math.round(sum / max * 100); + var overMax = percent > 100; + ctrl.chartDataClusters = { + title: gettext("Clusters"), + label: percent + '%', + maxLimit: max, + overMax: overMax, + data: dataClusters + }; + ctrl.quota = {clusters: max}; + } + } +})(); diff --git a/magnum_ui/static/dashboard/container-infra/clusters/cluster-stats.controller.spec.js b/magnum_ui/static/dashboard/container-infra/clusters/cluster-stats.controller.spec.js new file mode 100644 index 00000000..9effe050 --- /dev/null +++ b/magnum_ui/static/dashboard/container-infra/clusters/cluster-stats.controller.spec.js @@ -0,0 +1,74 @@ +/** + * 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. + */ + +(function() { + 'use strict'; + describe('horizon.dashboard.container-infra.clusters', function() { + var magnum, userSession, controller, $scope, $q, deferredSession, deferred, deferredQuota; + + beforeEach(module('horizon.framework')); + beforeEach(module('horizon.app.core.openstack-service-api')); + beforeEach(module('horizon.dashboard.container-infra.clusters')); + + beforeEach(inject(function ($injector, _$rootScope_, _$q_) { + $q = _$q_; + $scope = _$rootScope_.$new(); + magnum = $injector.get('horizon.app.core.openstack-service-api.magnum'); + userSession = $injector.get('horizon.app.core.openstack-service-api.userSession'); + controller = $injector.get('$controller'); + deferredSession = $q.defer(); + deferredSession.resolve({project_id: "1"}); + spyOn(userSession, 'get').and.returnValue(deferredSession.promise); + deferred = $q.defer(); + deferred.resolve({data: {stats: {clusters: 1}}}); + spyOn(magnum, 'getStats').and.returnValue(deferred.promise); + createController($scope); + })); + + function createController($scoped) { + return controller( + 'horizon.dashboard.container-infra.clusters.clusterStatsController', + { + $q: $q, + $scope: $scoped, + magnum: magnum, + userSession: userSession + }); + } + + it('should load user session', function() { + expect(userSession.get).toHaveBeenCalled(); + }); + + it('should load stats and quotas', function() { + deferredQuota = $q.defer(); + deferredQuota.resolve({data: {hard_limit: 20}}); + spyOn(magnum, 'getQuota').and.returnValue(deferredQuota.promise); + + $scope.$apply(); + expect(magnum.getStats).toHaveBeenCalled(); + expect(magnum.getQuota).toHaveBeenCalled(); + }); + + it('should load stats and default quotas', function() { + deferredQuota = $q.defer(); + deferredQuota.resolve({data: {hard_limit: null}}); + spyOn(magnum, 'getQuota').and.returnValue(deferredQuota.promise); + + $scope.$apply(); + expect(magnum.getStats).toHaveBeenCalled(); + expect(magnum.getQuota).toHaveBeenCalled(); + }); + }); +})(); diff --git a/magnum_ui/static/dashboard/container-infra/clusters/clusters.scss b/magnum_ui/static/dashboard/container-infra/clusters/clusters.scss index e69de29b..009af360 100644 --- a/magnum_ui/static/dashboard/container-infra/clusters/clusters.scss +++ b/magnum_ui/static/dashboard/container-infra/clusters/clusters.scss @@ -0,0 +1,45 @@ +.pie-chart { + display: block; + .svg-pie-chart { + .slice { + &.exists { + fill: lighten(blue, 20%); + } + &.margin { + fill: $gray-lighter; + } + } + } + .pie-chart-legend { + display: inline-block; + margin-left: 20px; + .slice-legend { + .slice-key { + &.exists { + background-color: lighten(blue, 20%); + } + &.margin { + background-color: $gray-lighter; + } + } + .chartless { + &.exists { + color: lighten(blue, 20%); + } + &.margin { + color: $gray-lighter; + } + } + } + } +} +.chart-tooltip { + span.fa { + &.exists { + color: lighten(blue, 20%); + } + &.margin { + color: $gray-lighter; + } + } +} \ No newline at end of file diff --git a/magnum_ui/static/dashboard/container-infra/clusters/panel.html b/magnum_ui/static/dashboard/container-infra/clusters/panel.html index 8c69df14..dbbe425b 100644 --- a/magnum_ui/static/dashboard/container-infra/clusters/panel.html +++ b/magnum_ui/static/dashboard/container-infra/clusters/panel.html @@ -1,4 +1,27 @@ +
+
+
+
+
+ +
+
+

Stats

+
+
+
Clusters
+
Used {$ ctrl.stats.clusters $} of {$ ctrl.quota.clusters $}
+
Nodes
+
{$ ctrl.stats.nodes $}
+
+
+
+
+
+
+