health check reports UI

Change-Id: I36f2dacce5e4d9b7b1ea4a4bb571d0a36c6fe49c
This commit is contained in:
sharonlucong 2015-01-06 09:32:06 -08:00
parent 2d9bd1e6a9
commit 3cd7dc02aa
6 changed files with 348 additions and 1 deletions

View File

@ -24,6 +24,228 @@ compassAppDev.run(function($httpBackend, settings, $http) {
return [200, message, {}];
});
$httpBackend.whenPOST(/\.*\/clusters\/([0-9]|[1-9][0-9])\/action$/).respond(function(method, url, data){
console.log(method, url, data);
var healthrequest = {
"status": "start to check cluster health.",
"cluster_id": 1
};
return [200, healthrequest, {}];
});
$httpBackend.whenGET(/\.*\/clusters\/([0-9]|[1-9][0-9])*\/healthreports$/).respond(function(method, url, data){
console.log(method, url, data);
var healthStates = ["verifying","finished","error"];
var reports = [
{
"name": "name1",
"state": healthStates[Math.floor((Math.random()*3))],
"error_message": "",
"cluster_id": 1,
"report": {
"report": {
"actions": {
"nova.boot_server": {
"duration": {
"data": [
83.646584987640381,
48.459306001663208
],
"summary": {
"errors": 0,
"success": "100.0%",
"min (sec)": 48.459000000000003,
"avg (sec)": 66.052999999999997,
"max (sec)": 83.647000000000006,
"total": 2
}
}
},
"nova.delete_server": {
"duration": {
"data": [
2.3977420330047607,
2.6214451789855957
],
"summary": {
"errors": 0,
"success": "100.0%",
"min (sec)": 2.3980000000000001,
"avg (sec)": 2.5099999999999998,
"max (sec)": 2.621,
"total": 2
}
}
}
},
"errors_info": []
},
"raw_output": "output1"
}
},
{
"name": "name2",
"state": "finished",
"error_message": "",
"cluster_id": 2,
"report": {
"report": {
"actions": {
"neutron.create_network": {
"duration": {
"data": [
0.87460207939147949,
0.97025418281555176
],
"summary": {
"errors": 0,
"success": "100.0%",
"min (sec)": 0.875,
"avg (sec)": 0.92200000000000004,
"max (sec)": 0.96999999999999997,
"total": 2
}
}
},
"neutron.delete_network": {
"duration": {
"data": [
0.58310413360595703,
0.6661829948425293
],
"summary": {
"errors": 0,
"success": "100.0%",
"min (sec)": 0.58299999999999996,
"avg (sec)": 0.625,
"max (sec)": 0.66600000000000004,
"total": 2
}
}
}
},
"errors_info": []
},
"raw_output": "output2"
}
}];
return [200, reports, {}];
});
$httpBackend.whenGET(/\.*\/clusters\/([0-9]|[1-9][0-9])\/healthreports\/([0-9]|[1-9][0-9])*/).respond(function(method, url, data){
console.log(method, url, data);
var healthStates = ["verifying","finished","error"];
var indireports =
{
"name": "name1",
"state": healthStates[Math.floor((Math.random()*3))],
"error_message": "",
"cluster_id": 1,
"report": {
"report": {
"actions": {
"nova.boot_server": {
"duration": {
"data": [
83.646584987640381,
48.459306001663208
],
"summary": {
"errors": 0,
"success": "100.0%",
"min (sec)": 48.459000000000003,
"avg (sec)": 66.052999999999997,
"max (sec)": 83.647000000000006,
"total": 2
}
}
},
"nova.delete_server": {
"duration": {
"data": [
2.3977420330047607,
2.6214451789855957
],
"summary": {
"errors": 0,
"success": "100.0%",
"min (sec)": 2.3980000000000001,
"avg (sec)": 2.5099999999999998,
"max (sec)": 2.621,
"total": 2
}
}
}
},
"errors_info": []
},
"raw_output": {
"result": [
{
"duration": 86.044774055480957,
"scenario_output": {
"errors": "",
"data": {}
},
"idle_duration": 0.0,
"atomic_actions": {
"nova.boot_server": 83.646584987640381,
"nova.delete_server": 2.3977420330047607
},
"error": []
},
{
"duration": 51.081114053726196,
"scenario_output": {
"errors": "",
"data": {}
},
"idle_duration": 0.0,
"atomic_actions": {
"nova.boot_server": 48.459306001663208,
"nova.delete_server": 2.6214451789855957
},
"error": []
}
],
"key": {
"kw": {
"runner": {
"type": "constant",
"concurrency": 2,
"times": 2
},
"args": {
"flavor": {
"name": "m1.tiny"
},
"image": {
"name": "cirros"
}
},
"context": {
"users": {
"project_domain": "default",
"users_per_tenant": 2,
"tenants": 3,
"resource_management_workers": 30,
"user_domain": "default"
}
}
},
"name": "NovaServers.boot_and_delete_server",
"pos": 0
},
"sla": []
}
}
};
return [200, indireports, {}];
});
$httpBackend.whenGET(settings.apiUrlBase + '/adapters').respond(function(method, url, data) {
console.log(method, url);
var adapters = [{

View File

@ -84,6 +84,13 @@
</a>
</li>
<li ng-class="{active:state.includes('cluster.report')}">
<a ui-sref="cluster.report">
<i class="menu-icon glyphicon glyphicon-list-alt glyphicon-list-alt"></i>
<span class="menu-text">Report</span>
</a>
</li>
</ul>
<div class="sidebar-toggle sidebar-collapse" ng-click="sidebarCollapse = !sidebarCollapse">

View File

@ -82,6 +82,10 @@
</div>
<div class="pull-right">
<div class="btn-group" dropdown>
<button type="button" class="btn btn-info" ng-click="startChecking()" ng-disabled="clusterProgress.state == 'INSTALLING'">
Report
</button>
<button type="button" class="btn btn-info dropdown-toggle" ng-disabled="clusterProgress.state == 'INSTALLING'">
Actions
<span class="ace-icon fa fa-caret-down icon-on-right"></span>

View File

@ -0,0 +1,42 @@
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
<div class="panel panel-default" ng-repeat = "report in reports">
<div class="panel-heading" role="tab" id="headingOne">
<h4 class="panel-title">
<span>{{report.name}}</span>
<span ng-if="reportStates[report.name] =='finished'">
<i class='class="ace-icon fa fa fa-check bigger-160 green'></i>
</span>
<span ng-if="reportStates[report.name] =='verifying'">
<i class='class="ace-icon fa fa-spinner fa-spin bigger-160 orange'></i>
</span>
<span ng-if="reportStates[report.name] =='error'">
<i class='class="ace-icon fa fa-times bigger-160 red'></i>
</span>
<button class="pull-right btn btn-default btn-xs" data-toggle="collapse" data-parent="#accordion" href="#{{report.name}}" aria-expanded="true" aria-controls="{{report.name}}" ng-disabled = "reportStates[report.name] == 'verifying'" ng-style="{color: notFinished ? 'white' : 'grey'}">
<i class="glyphicon glyphicon-chevron-down"></i>
</button>
</h4>
</div>
<div id="{{report.name}}" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingOne">
<div class="panel-body">
<table class="table table-striped">
<thead>
<tr>
<th>Actions</th>
<th>Avg(sec)</th>
<th>Errors</th>
<th>Max(sec)</th>
<th>Min(sec)</th>
<th>Success</th>
<th>Total(sec)</th>
</tr>
</thead>
<tr ng-repeat="detail in details">
<td >{{detail.name}}</td>
<td ng-repeat="(key,detail) in detail.summary.duration.summary">{{detail}}</td>
</tr>
</table>
</div>
</div>
</div>
</div>

View File

@ -62,8 +62,57 @@ define(['angular'], function() {
controller: "clusterLogCtrl",
templateUrl: 'src/app/cluster/cluster-log.tpl.html',
authenticate: true
})
.state('cluster.report',{
url:'/report',
controller: "clusterReportCtrl",
templateUrl:'src/app/cluster/cluster-report.tpl.html',
authenticate:true,
resolve: {
reportData: function($stateParams, $q, dataService) {
var clusterId = $stateParams.id;
var name = $stateParams.name;
var deferred = $q.defer();
dataService.getHealthReports(clusterId).success(function(data) {
deferred.resolve(data);
});
return deferred.promise;
}
}
});
});
clusterModule.controller('clusterReportCtrl', function($scope, $state, dataService, $stateParams, $timeout, reportData){
$scope.reports = reportData;
$scope.details = [];
var progressTimer;
var fireTimer = true;
$scope.notFinished = true;
$scope.reportStates = {};
var getClusterReport= function(){
angular.forEach($scope.reports, function(rd){
if($scope.reportStates[rd.name]!="finished" && $scope.reportStates[rd.name]!="error"){
dataService.getIndividualReports(rd.cluster_id, rd.name).success(function(dt){
$scope.details = [];
$scope.reportStates[rd.name] = dt.state;
angular.forEach(dt.report.report.actions, function(value,key){
$scope.details.push({"name":key,"summary":value});
});
});
}
});
if(fireTimer){
progressTimer = $timeout(getClusterReport, 3000);
};
getClusterReport();
$scope.$on('$destroy', function() {
fireTimer = false;
$timeout.cancel(progressTimer);
});
});
clusterModule.controller('clusterCtrl', function($scope, $state, dataService, $stateParams) {
$scope.clusterId = $stateParams.id;
@ -98,12 +147,18 @@ define(['angular'], function() {
});
clusterModule.controller('clusterProgressCtrl', function($scope, dataService, $stateParams, $filter, ngTableParams, $timeout, $modal, clusterhostsData) {
clusterModule.controller('clusterProgressCtrl', function($scope, dataService, $state, $stateParams, $filter, ngTableParams, $timeout, $modal, clusterhostsData) {
var clusterId = $stateParams.id;
var progressTimer;
var fireTimer = true;
$scope.hosts = clusterhostsData;
$scope.startChecking = function(){
dataService.startHealthCheck($scope.clusterId).success(function(data){
$state.go('cluster.report',data);
});
};
var getClusterProgress = function() {
dataService.getClusterProgress(clusterId).success(function(data) {
$scope.clusterProgress = data;

View File

@ -126,6 +126,23 @@ define(['angular','uiBootstrap'], function(ng, uiBootstrap) {
this.getUserLog = function() {
return $http.get(settings.apiUrlBase + '/users/logs');
}
this.getHealthReports = function(id){
return $http.get(settings.apiUrlBase + '/clusters/' + id + '/healthreports');
};
this.getIndividualReports = function(id, name){
return $http.get(settings.apiUrlBase + '/clusters/' + id + '/healthreports/' + name);
};
this.postHealthCheck = function(id, checkHealth){
return $http.post(settings.apiUrlBase + '/clusters/' + id + '/action', angular.toJason(checkHealth));
};
this.startHealthCheck = function(id){
return $http.post(settings.apiUrlBase + '/clusters/' + id + '/action',angular.toJson(id));
};
this.getClusters = function() {
return $http.get(settings.apiUrlBase + '/clusters');
};