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:
parent
7ebff515a7
commit
ddb31065ab
@ -1,4 +1,5 @@
|
|||||||
@import "containers/containers";
|
@import "containers/containers";
|
||||||
|
@import "hosts/hosts";
|
||||||
|
|
||||||
.batch-action {
|
.batch-action {
|
||||||
float: right;
|
float: right;
|
||||||
|
@ -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'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})();
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
@ -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>
|
@ -25,7 +25,8 @@
|
|||||||
*/
|
*/
|
||||||
angular
|
angular
|
||||||
.module('horizon.dashboard.container.hosts', [
|
.module('horizon.dashboard.container.hosts', [
|
||||||
'ngRoute'
|
'ngRoute',
|
||||||
|
'horizon.dashboard.container.hosts.details'
|
||||||
])
|
])
|
||||||
.constant('horizon.dashboard.container.hosts.resourceType', 'OS::Zun::Host')
|
.constant('horizon.dashboard.container.hosts.resourceType', 'OS::Zun::Host')
|
||||||
.run(run)
|
.run(run)
|
||||||
@ -45,6 +46,7 @@
|
|||||||
// for detail summary view on table row.
|
// for detail summary view on table row.
|
||||||
.setSummaryTemplateUrl(basePath + 'drawer.html')
|
.setSummaryTemplateUrl(basePath + 'drawer.html')
|
||||||
// for table row items and detail summary view.
|
// for table row items and detail summary view.
|
||||||
|
.setDefaultIndexUrl('/admin/container/hosts/')
|
||||||
.setProperties(hostProperties())
|
.setProperties(hostProperties())
|
||||||
.setListFunction(hostService.getHostsPromise)
|
.setListFunction(hostService.getHostsPromise)
|
||||||
.tableColumns
|
.tableColumns
|
||||||
@ -55,7 +57,8 @@
|
|||||||
.append({
|
.append({
|
||||||
id: 'hostname',
|
id: 'hostname',
|
||||||
priority: 1,
|
priority: 1,
|
||||||
sortDefault: true
|
sortDefault: true,
|
||||||
|
urlFunction: hostService.getDetailsPath
|
||||||
})
|
})
|
||||||
.append({
|
.append({
|
||||||
id: 'mem_total',
|
id: 'mem_total',
|
||||||
@ -95,13 +98,14 @@
|
|||||||
'disk_used': { label: gettext('Disk Used'), filters: ['noValue', 'gb'] },
|
'disk_used': { label: gettext('Disk Used'), filters: ['noValue', 'gb'] },
|
||||||
'disk_quota_supported': { label: gettext('Disk Quota Supported'),
|
'disk_quota_supported': { label: gettext('Disk Quota Supported'),
|
||||||
filters: ['noValue', 'yesno'] },
|
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': { label: gettext('OS'), filters: ['noValue'] },
|
||||||
'os_type': { label: gettext('OS Type'), filters: ['noValue'] },
|
'os_type': { label: gettext('OS Type'), filters: ['noValue'] },
|
||||||
'architecture': { label: gettext('Architecture'), filters: ['noValue'] },
|
'architecture': { label: gettext('Architecture'), filters: ['noValue'] },
|
||||||
'kernel_version': { label: gettext('Kernel Version'), filters: ['noValue'] },
|
'kernel_version': { label: gettext('Kernel Version'), filters: ['noValue'] },
|
||||||
'runtimes': { label: gettext('Runtimes'), filters: ['noValue'] },
|
'runtimes': { label: gettext('Runtimes'), filters: ['noValue', 'json'] },
|
||||||
'labels': { label: gettext('Labels'), filters: ['noValue'] }
|
'labels': { label: gettext('Labels'), filters: ['noValue', 'json'] },
|
||||||
|
'links': { label: gettext('Links'), filters: ['noValue', 'json'] }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
45
zun_ui/static/dashboard/container/hosts/hosts.scss
Normal file
45
zun_ui/static/dashboard/container/hosts/hosts.scss
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -33,9 +33,36 @@
|
|||||||
*/
|
*/
|
||||||
function hostsService(detailRoute, zun) {
|
function hostsService(detailRoute, zun) {
|
||||||
return {
|
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
|
* @ngdoc function
|
||||||
* @name getHostsPromise
|
* @name getHostsPromise
|
||||||
@ -49,12 +76,12 @@
|
|||||||
|
|
||||||
function modifyResponse(response) {
|
function modifyResponse(response) {
|
||||||
return {data: {items: response.data.items.map(modifyItem)}};
|
return {data: {items: response.data.items.map(modifyItem)}};
|
||||||
|
}
|
||||||
|
|
||||||
function modifyItem(item) {
|
function modifyItem(item) {
|
||||||
var timestamp = new Date();
|
var timestamp = new Date();
|
||||||
item.trackBy = item.id.concat(timestamp.getTime());
|
item.trackBy = item.id.concat(timestamp.getTime());
|
||||||
return item;
|
return item;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user