Consolidate node last_error processing

Consolidate last_error processing for the node-list and node-detail
views using a newly added node-error service. The service provides
a function checkNodeError that will compare the error condition
of a specified node with its last known value which is stored
in browser session persistent storage (as part of each check).
If a change in the node error condition has occurred the user
is notified using the toast service. The use of persistent storage
eliminates duplicate notifications that would otherwise be
generated from page transitions and service re-initializations.

The checkNodeError function is called whenever node information
is retrieved using the ironic service getNode/getNodes functions.

Change-Id: Iba7bdaaa78d51384b6b9d79d2d723b8e7607eb9a
This commit is contained in:
Peter Piela 2016-12-02 10:45:38 -05:00
parent 39eff39501
commit 7971aea3d9
4 changed files with 94 additions and 24 deletions

View File

@ -59,7 +59,8 @@
ironicAPI.$inject = [
'horizon.framework.util.http.service',
'horizon.framework.widgets.toast.service'
'horizon.framework.widgets.toast.service',
'horizon.dashboard.admin.ironic.node-error.service'
];
/**
@ -67,9 +68,10 @@
*
* @param {object} apiService - HTTP service
* @param {object} toastService - User message service
* @param {object} nodeErrorService - Node error service
* @return {object} Ironic API service
*/
function ironicAPI(apiService, toastService) {
function ironicAPI(apiService, toastService, nodeErrorService) {
var service = {
createNode: createNode,
createPort: createPort,
@ -101,7 +103,12 @@
*/
function getNodes() {
return apiService.get('/api/ironic/nodes/')
.error(function() {
.then(function(response) {
angular.forEach(response.data.items, function(node) {
nodeErrorService.checkNodeError(node);
});
return response;
}, function() {
toastService.add('error',
gettext('Unable to retrieve Ironic nodes.'));
});
@ -118,7 +125,10 @@
*/
function getNode(uuid) {
return apiService.get('/api/ironic/nodes/' + uuid)
.error(function(reason) {
.then(function(response) {
nodeErrorService.checkNodeError(response.data);
return response;
}, function(reason) {
var msg = gettext('Unable to retrieve the Ironic node: %s');
toastService.add('error', interpolate(msg, [reason], false));
});

View File

@ -137,21 +137,9 @@
* @return {promise} promise
*/
function retrieveNode(uuid) {
var lastError = ctrl.node ? ctrl.node.last_error : null;
return ironic.getNode(uuid).then(function (response) {
ctrl.node = response.data;
ctrl.node.id = uuid;
if (lastError &&
ctrl.node.last_error !== "" &&
ctrl.node.last_error !== null &&
ctrl.node.last_error !== lastError) {
toastService.add('error',
"Error detected on node " +
ctrl.node.name + ". " +
ctrl.node.last_error);
}
});
}

View File

@ -0,0 +1,80 @@
/*
* © Copyright 2016 Cray Inc.
*
* 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.admin.ironic')
.service('horizon.dashboard.admin.ironic.node-error.service',
nodeErrorService);
nodeErrorService.$inject = [
'horizon.framework.widgets.toast.service'
];
function nodeErrorService(toastService) {
// Node last_error cache indexed by node uuid
var lastError = sessionStorage.nodeErrorService
? angular.fromJson(sessionStorage.nodeErrorService) : {};
/**
* @description Get the error condition for a specified node
*
* @param {string} nodeUuid node uuid
* @return {string} Error condition
*/
this.getLastError = function(nodeUuid) {
return angular.isDefined(lastError[nodeUuid])
? lastError[nodeUuid] : null;
};
/**
* @description Store the error condition for a specified node
*
* @param {node} node node
* @return {void}
*/
function setLastError(node) {
lastError[node.uuid] = node.last_error;
// Store node error condition in browser session storage
// which provides persistence across page transitions.
sessionStorage.nodeErrorService = angular.toJson(lastError);
}
/**
* @description Notify the user of a change in error condition for
* specified node.
*
* @param {node} node node being checked
* @return {void}
*/
this.checkNodeError = function(node) {
if (node.last_error !== null &&
node.last_error !== "" &&
(!angular.isDefined(lastError[node.uuid]) ||
node.last_error !== lastError[node.uuid])) {
toastService.add(
'error',
"Detected change in error condition on node " +
node.name + ". " +
node.last_error);
}
// Update stored node error condition
setLastError(node);
};
}
})();

View File

@ -147,14 +147,6 @@
angular.forEach(response.data.items, function (node) {
node.id = node.uuid;
promises.push(retrievePorts(node));
// Report any changes in last-error
if (node.last_error !== "" &&
angular.isDefined(ctrl.nodesSrc[node.uuid]) &&
node.last_error !== ctrl.nodesSrc[node.uuid].last_error) {
toastService.add('error',
"Node " + node.name + ". " + node.last_error);
}
});
$q.all(promises).then(function() {
ctrl.nodesSrc = response.data.items;