From 811401f40e8c7cca1d34e8daef06e8eeecbad772 Mon Sep 17 00:00:00 2001 From: kunw Date: Tue, 25 Oct 2016 12:44:27 +0800 Subject: [PATCH] Added volume info of UI. --- make/docker-compose.yml | 1 + src/ui/api/systeminfo.go | 62 +++++++++++++++++++ src/ui/router.go | 2 + .../optional-menu/optional-menu.directive.js | 36 ++++++++--- src/ui/static/resources/js/harbor.module.js | 1 + .../js/services/i18n/locale_messages_en-US.js | 1 + .../js/services/i18n/locale_messages_zh-CN.js | 1 + .../services.system-info.module.js | 20 ++++++ .../system-info/services.volume-info.js | 33 ++++++++++ src/ui/views/sections/script-include.htm | 3 + 10 files changed, 152 insertions(+), 8 deletions(-) create mode 100644 src/ui/api/systeminfo.go create mode 100644 src/ui/static/resources/js/services/system-info/services.system-info.module.js create mode 100644 src/ui/static/resources/js/services/system-info/services.volume-info.js diff --git a/make/docker-compose.yml b/make/docker-compose.yml index 1e7e81f71..fd7945edb 100644 --- a/make/docker-compose.yml +++ b/make/docker-compose.yml @@ -50,6 +50,7 @@ services: volumes: - ./common/config/ui/app.conf:/etc/ui/app.conf - ./common/config/ui/private_key.pem:/etc/ui/private_key.pem + - /data:/harbor_storage depends_on: - log logging: diff --git a/src/ui/api/systeminfo.go b/src/ui/api/systeminfo.go new file mode 100644 index 000000000..86f4e9673 --- /dev/null +++ b/src/ui/api/systeminfo.go @@ -0,0 +1,62 @@ +package api + +import ( + "net/http" + "path/filepath" + "syscall" + + "github.com/vmware/harbor/src/common/api" + "github.com/vmware/harbor/src/common/dao" + "github.com/vmware/harbor/src/common/utils/log" +) + +type SystemInfoApi struct { + api.BaseAPI + currentUserID int + isAdmin bool +} + +const harbor_storage_path = "/harbor_storage" + +type SystemInfo struct { + HarborStorage Storage `json:"harbor_storage"` +} + +type Storage struct { + Total uint64 `json:"total"` + Free uint64 `json:"free"` +} + +var systemInfo SystemInfo = SystemInfo{} + +func (sia *SystemInfoApi) Prepare() { + sia.currentUserID = sia.ValidateUser() + + var err error + sia.isAdmin, err = dao.IsAdminRole(sia.currentUserID) + if err != nil { + log.Errorf("Error occurred in IsAdminRole:%v", err) + sia.CustomAbort(http.StatusInternalServerError, "Internal error.") + } +} + +func (sia *SystemInfoApi) GetVolumeInfo() { + if !sia.isAdmin { + sia.RenderError(http.StatusForbidden, "User does not have admin role.") + return + } + var stat syscall.Statfs_t + err := syscall.Statfs(filepath.Join("/", harbor_storage_path), &stat) + if err != nil { + log.Errorf("Error occurred in syscall.Statfs: %v", err) + sia.CustomAbort(http.StatusInternalServerError, "Internal error.") + return + } + storage := Storage{ + Total: stat.Blocks * uint64(stat.Bsize), + Free: stat.Bfree * uint64(stat.Bsize), + } + systemInfo.HarborStorage = storage + sia.Data["json"] = systemInfo + sia.ServeJSON() +} diff --git a/src/ui/router.go b/src/ui/router.go index 5dbab9bae..097ff39d8 100644 --- a/src/ui/router.go +++ b/src/ui/router.go @@ -84,6 +84,8 @@ func initRouters() { beego.Router("/api/users/:id/sysadmin", &api.UserAPI{}, "put:ToggleUserAdminRole") beego.Router("/api/repositories/top", &api.RepositoryAPI{}, "get:GetTopRepos") beego.Router("/api/logs", &api.LogAPI{}) + + beego.Router("/api/systeminfo/volumes", &api.SystemInfoApi{}, "get:GetVolumeInfo") //external service that hosted on harbor process: beego.Router("/service/notifications", &service.NotificationHandler{}) beego.Router("/service/token", &token.Handler{}) diff --git a/src/ui/static/resources/js/components/optional-menu/optional-menu.directive.js b/src/ui/static/resources/js/components/optional-menu/optional-menu.directive.js index 64b7121ef..c7bfda6cf 100644 --- a/src/ui/static/resources/js/components/optional-menu/optional-menu.directive.js +++ b/src/ui/static/resources/js/components/optional-menu/optional-menu.directive.js @@ -20,9 +20,9 @@ .module('harbor.optional.menu') .directive('optionalMenu', optionalMenu); - OptionalMenuController.$inject = ['$scope', '$window', 'I18nService', 'LogOutService', 'currentUser', '$timeout', 'trFilter', '$filter']; + OptionalMenuController.$inject = ['$scope', '$window', 'I18nService', 'LogOutService', 'currentUser', '$timeout', 'trFilter', '$filter', 'GetVolumeInfoService']; - function OptionalMenuController($scope, $window, I18nService, LogOutService, currentUser, $timeoutm, trFilter, $filter) { + function OptionalMenuController($scope, $window, I18nService, LogOutService, currentUser, $timeoutm, trFilter, $filter, GetVolumeInfoService) { var vm = this; vm.currentLanguage = I18nService().getCurrentLanguage(); @@ -55,16 +55,36 @@ function logOutFailed(data, status) { console.log('Failed to log out:' + data); } + + var raiseInfo = { + 'confirmOnly': true, + 'contentType': 'text/html', + 'action': function() {} + }; + function about() { $scope.$emit('modalTitle', $filter('tr')('about_harbor')); - $scope.$emit('modalMessage', $filter('tr')('current_version', [vm.version || 'Unknown'])); - var raiseInfo = { - 'confirmOnly': true, - 'contentType': 'text/html', - 'action': function() {} - }; + vm.modalMessage = $filter('tr')('current_version', [vm.version || 'Unknown']); + GetVolumeInfoService("data") + .then(getVolumeInfoSuccess, getVolumeInfoFailed); + + } + function getVolumeInfoSuccess(response) { + var storage = response.data; + vm.modalMessage += '
' + $filter('tr')('current_storage', + [toGigaBytes(storage['harbor_storage']['free']), toGigaBytes(storage['harbor_storage']['total'])]); + $scope.$emit('modalMessage', vm.modalMessage); + $scope.$emit('raiseInfo', raiseInfo); + + } + function getVolumeInfoFailed(response) { + $scope.$emit('modalMessage', vm.modalMessage); $scope.$emit('raiseInfo', raiseInfo); } + function toGigaBytes(val) { + return Math.round(val / (1024 * 1024 * 1024)); + } + } function optionalMenu() { diff --git a/src/ui/static/resources/js/harbor.module.js b/src/ui/static/resources/js/harbor.module.js index 64dec5ea4..345dfd0e5 100644 --- a/src/ui/static/resources/js/harbor.module.js +++ b/src/ui/static/resources/js/harbor.module.js @@ -42,6 +42,7 @@ 'harbor.services.replication.policy', 'harbor.services.replication.job', 'harbor.services.destination', + 'harbor.services.system.info', 'harbor.summary', 'harbor.user.log', 'harbor.top.repository', diff --git a/src/ui/static/resources/js/services/i18n/locale_messages_en-US.js b/src/ui/static/resources/js/services/i18n/locale_messages_en-US.js index 0ac5025c5..ca2654210 100644 --- a/src/ui/static/resources/js/services/i18n/locale_messages_en-US.js +++ b/src/ui/static/resources/js/services/i18n/locale_messages_en-US.js @@ -230,6 +230,7 @@ var locale_messages = { 'about': 'About', 'about_harbor': 'About Harbor', 'current_version': '  $0', + 'current_storage': '  $0 GB available of $1 GB.', 'failed_to_get_project_member': 'Failed to get current project member.', 'failed_to_delete_repo': 'Failed to delete repository. ', 'failed_to_delete_repo_insuffient_permissions': 'Failed to delete repository, insuffient permissions.', diff --git a/src/ui/static/resources/js/services/i18n/locale_messages_zh-CN.js b/src/ui/static/resources/js/services/i18n/locale_messages_zh-CN.js index a896ba848..c91801d5f 100644 --- a/src/ui/static/resources/js/services/i18n/locale_messages_zh-CN.js +++ b/src/ui/static/resources/js/services/i18n/locale_messages_zh-CN.js @@ -230,6 +230,7 @@ var locale_messages = { 'about': '关于', 'about_harbor': '关于 Harbor', 'current_version': '  $0', + 'current_storage': '  可用: $0 GB,总共: $1 GB。', 'failed_to_get_project_member': '无法获取当前项目成员。', 'failed_to_delete_repo': '无法删除镜像仓库。', 'failed_to_delete_repo_insuffient_permissions': '无法删除镜像仓库,权限不足。', diff --git a/src/ui/static/resources/js/services/system-info/services.system-info.module.js b/src/ui/static/resources/js/services/system-info/services.system-info.module.js new file mode 100644 index 000000000..cc38c1b2d --- /dev/null +++ b/src/ui/static/resources/js/services/system-info/services.system-info.module.js @@ -0,0 +1,20 @@ +/* + Copyright (c) 2016 VMware, 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. +*/ +(function() { + 'use strict'; + + angular.module('harbor.services.system.info', []); + +})(); \ No newline at end of file diff --git a/src/ui/static/resources/js/services/system-info/services.volume-info.js b/src/ui/static/resources/js/services/system-info/services.volume-info.js new file mode 100644 index 000000000..545db5561 --- /dev/null +++ b/src/ui/static/resources/js/services/system-info/services.volume-info.js @@ -0,0 +1,33 @@ +/* + Copyright (c) 2016 VMware, 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. +*/ +(function() { + 'use strict'; + + angular + .module('harbor.services.system.info') + .factory('GetVolumeInfoService', GetVolumeInfoService); + + GetVolumeInfoService.$inject = ['$http']; + + function GetVolumeInfoService($http) { + return getVolumeInfo; + + function getVolumeInfo(path) { + return $http + .get('/api/systeminfo/volumes'); + } + } + +})(); \ No newline at end of file diff --git a/src/ui/views/sections/script-include.htm b/src/ui/views/sections/script-include.htm index f07b60649..74805fc4b 100644 --- a/src/ui/views/sections/script-include.htm +++ b/src/ui/views/sections/script-include.htm @@ -110,6 +110,9 @@ + + +