Add details view for hosts panel

This patch adds host details view for admin.

Change-Id: I99a7429f226bf62edea2f745e844c963099a48e8
Implements: blueprint add-host-panel
This commit is contained in:
Shu Muto 2018-10-16 18:52:22 +09:00
parent 7ebff515a7
commit ddb31065ab
7 changed files with 301 additions and 11 deletions

View File

@ -1,4 +1,5 @@
@import "containers/containers";
@import "hosts/hosts";
.batch-action {
float: right;

View File

@ -0,0 +1,51 @@
/**
* 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 overview
* @ngname horizon.dashboard.container.hosts.details
*
* @description
* Provides details for host.
*/
angular.module('horizon.dashboard.container.hosts.details',
['horizon.framework.conf', 'horizon.app.core'])
.run(registerDetails);
registerDetails.$inject = [
'horizon.dashboard.container.hosts.basePath',
'horizon.dashboard.container.hosts.resourceType',
'horizon.dashboard.container.hosts.service',
'horizon.framework.conf.resource-type-registry.service'
];
function registerDetails(
basePath,
resourceType,
hostService,
registry
) {
registry.getResourceType(resourceType)
.setLoadFunction(hostService.getHostPromise)
.detailsViews
.append({
id: 'hostDetailsOverview',
name: gettext('Overview'),
template: basePath + 'details/overview.html'
});
}
})();

View File

@ -0,0 +1,102 @@
/*
* 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('horizon.dashboard.container.hosts')
.controller('horizon.dashboard.container.hosts.OverviewController', controller);
controller.$inject = [
'$scope'
];
function controller(
$scope
) {
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.chartDataMem = {
maxLimit: 10,
data: []
};
ctrl.chartDataCpu = {
maxLimit: 10,
data: []
};
ctrl.chartDataDisk = {
maxLimit: 10,
data: []
};
// container for temporal chart data
var dataMem = [];
var dataCpu = [];
var dataDisk = [];
$scope.context.loadPromise.then(onGetHost);
function onGetHost(host) {
ctrl.host = host.data;
// set data for memory chart
dataMem = [
{label: gettext("Used"), value: host.data.mem_used, colorClass: "exists"},
{label: gettext("Margin"), value: host.data.mem_total - host.data.mem_used,
colorClass: "margin"}
];
ctrl.chartDataMem = generateChartData(dataMem, gettext("Memory"));
// set data for CPU chart
dataCpu = [
{label: gettext("Used"), value: host.data.cpu_used, colorClass: "exists"},
{label: gettext("Margin"), value: host.data.cpus - host.data.cpu_used,
colorClass: "margin"}
];
ctrl.chartDataCpu = generateChartData(dataCpu, gettext("CPU"));
// set data for disk chart
dataDisk = [
{label: gettext("Used"), value: host.data.disk_used, colorClass: "exists"},
{label: gettext("Margin"), value: host.data.disk_total - host.data.disk_used,
colorClass: "margin"}
];
ctrl.chartDataDisk = generateChartData(dataDisk, gettext("Disk"));
}
function generateChartData(data, title) {
var sum = data[0].value;
var max = data[0].value + data[1].value;
var percent = Math.round(sum / max * 100);
var overMax = percent > 100;
var result = {
title: title,
label: percent + '%',
maxLimit: max,
overMax: overMax,
data: data
};
return result;
}
}
})();

View File

@ -0,0 +1,60 @@
<div ng-controller="horizon.dashboard.container.hosts.OverviewController as ctrl">
<div class="row">
<div class="col-md-12 detail">
<h3 translate>Usage</h3>
<hr>
<div class="row">
<div class="col-md-4">
<h4 translate>Memory</h4>
<hr>
<pie-chart chart-data="ctrl.chartDataMem"
chart-settings="ctrl.chartSettings"></pie-chart>
<dl class="dl-horizontal">
<dd translate>Used {$ ctrl.host.mem_used | mb $} of {$ ctrl.host.mem_total | mb $}</dd>
</dl>
</div>
<div class="col-md-4">
<h4 translate>CPU</h4>
<hr>
<pie-chart chart-data="ctrl.chartDataCpu"
chart-settings="ctrl.chartSettings"></pie-chart>
<dl class="dl-horizontal">
<dd translate>Used {$ ctrl.host.cpu_used $} of {$ ctrl.host.cpus $}</dd>
</dl>
</div>
<div class="col-md-4">
<h4 translate>Disk</h4>
<hr>
<pie-chart chart-data="ctrl.chartDataDisk"
chart-settings="ctrl.chartSettings"></pie-chart>
<dl class="dl-horizontal">
<dd translate>Used {$ ctrl.host.disk_used | gb $} of {$ ctrl.host.disk_total | gb $}</dd>
</dl>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 detail">
<h3 translate>Info</h3>
<hr>
<hz-resource-property-list
resource-type-name="OS::Zun::Host"
cls="dl-horizontal"
item="ctrl.host"
property-groups="[['id', 'hostname', 'architecture', 'os', 'os_type',
'kernel_version', 'runtimes', 'total_containers', 'disk_quota_supported']]">
</hz-resource-property-list>
</div>
<div class="col-md-6 detail">
<h3 translate>Miscellaneous</h3>
<hr>
<hz-resource-property-list
resource-type-name="OS::Zun::Host"
cls="dl-horizontal"
item="ctrl.host"
property-groups="[['labels', 'links']]">
</hz-resource-property-list>
</div>
</div>
</div>

View File

@ -25,7 +25,8 @@
*/
angular
.module('horizon.dashboard.container.hosts', [
'ngRoute'
'ngRoute',
'horizon.dashboard.container.hosts.details'
])
.constant('horizon.dashboard.container.hosts.resourceType', 'OS::Zun::Host')
.run(run)
@ -45,6 +46,7 @@
// for detail summary view on table row.
.setSummaryTemplateUrl(basePath + 'drawer.html')
// for table row items and detail summary view.
.setDefaultIndexUrl('/admin/container/hosts/')
.setProperties(hostProperties())
.setListFunction(hostService.getHostsPromise)
.tableColumns
@ -55,7 +57,8 @@
.append({
id: 'hostname',
priority: 1,
sortDefault: true
sortDefault: true,
urlFunction: hostService.getDetailsPath
})
.append({
id: 'mem_total',
@ -95,13 +98,14 @@
'disk_used': { label: gettext('Disk Used'), filters: ['noValue', 'gb'] },
'disk_quota_supported': { label: gettext('Disk Quota Supported'),
filters: ['noValue', 'yesno'] },
'total_containers': { label: gettext('Disk Used'), filters: ['noValue'] },
'total_containers': { label: gettext('Total Containers'), filters: ['noValue'] },
'os': { label: gettext('OS'), filters: ['noValue'] },
'os_type': { label: gettext('OS Type'), filters: ['noValue'] },
'architecture': { label: gettext('Architecture'), filters: ['noValue'] },
'kernel_version': { label: gettext('Kernel Version'), filters: ['noValue'] },
'runtimes': { label: gettext('Runtimes'), filters: ['noValue'] },
'labels': { label: gettext('Labels'), filters: ['noValue'] }
'runtimes': { label: gettext('Runtimes'), filters: ['noValue', 'json'] },
'labels': { label: gettext('Labels'), filters: ['noValue', 'json'] },
'links': { label: gettext('Links'), filters: ['noValue', 'json'] }
};
}

View File

@ -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;
}
}
}

View File

@ -33,9 +33,36 @@
*/
function hostsService(detailRoute, zun) {
return {
getHostsPromise: getHostsPromise
getDetailsPath: getDetailsPath,
getHostsPromise: getHostsPromise,
getHostPromise: getHostPromise
};
/*
* @ngdoc function
* @name getDetailsPath
* @param item {Object} - The host object
* @description
* Returns the relative path to the details view.
*/
function getDetailsPath(item) {
return detailRoute + 'OS::Zun::Host/' + item.id;
}
/*
* @ngdoc function
* @name getHostPromise
* @description
* Given an id, returns a promise for the host data.
*/
function getHostPromise(identifier) {
return zun.getHost(identifier).then(modifyDetails);
}
function modifyDetails(response) {
return {data: modifyItem(response.data)};
}
/*
* @ngdoc function
* @name getHostsPromise
@ -49,12 +76,12 @@
function modifyResponse(response) {
return {data: {items: response.data.items.map(modifyItem)}};
}
function modifyItem(item) {
var timestamp = new Date();
item.trackBy = item.id.concat(timestamp.getTime());
return item;
}
function modifyItem(item) {
var timestamp = new Date();
item.trackBy = item.id.concat(timestamp.getTime());
return item;
}
}
})();