Add support for specifying a maintenance reason

Co-Authored-By: Beth Elwell <e.r.elwell@gmail.com>

Change-Id: Ie2eaf309ffbb9055afaf837c751d7898b0d9d9ee
This commit is contained in:
Peter Piela 2016-03-23 10:20:44 -04:00 committed by Elizabeth Elwell
parent a4c47b80f7
commit 409fdec238
8 changed files with 260 additions and 24 deletions

View File

@ -0,0 +1,48 @@
/*
* Copyright 2016 Cray Inc.
* Copyright (c) 2016 Hewlett Packard Enterprise Development Company LP
*
* 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 controller
* @name horizon.dashboard.admin.ironic:MaintenanceController
* @ngController
*
* @description
* Controller used to prompt the user for information associated with
* putting one or more nodes into maintenance mode
*/
angular
.module('horizon.dashboard.admin.ironic')
.controller('MaintenanceController', MaintenanceController);
MaintenanceController.$inject = [
'$modalInstance'
];
function MaintenanceController($modalInstance) {
var ctrl = this;
ctrl.cancel = function() {
$modalInstance.dismiss('cancel');
};
ctrl.putInMaintenanceMode = function(maintReason) {
$modalInstance.close(maintReason);
};
}
})();

View File

@ -0,0 +1,30 @@
<div class="modal-header">
<h3 class="modal-title" translate>Put Node(s) Into Maintenance Mode</h3>
</div>
<div class="modal-body clearfix">
<div class="content">
<div translate class="subtitle">Provide a reason for why you are putting the selected node(s) into maintenance mode (optional)</div>
<div class="form-group">
<div class="form-field">
<input type="text"
class="form-control input-sm"
ng-model="maintReason"
placeholder="">
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-default secondary"
type="button"
ng-click="ctrl.cancel()"
translate>
Cancel
</button>
<button class="btn btn-primary"
type="button"
ng-click="ctrl.putInMaintenanceMode(maintReason)"
translate>
Put Node(s) Into Maintenance Mode
</button>
</div>

View File

@ -0,0 +1,106 @@
/*
* Copyright 2016 Cray Inc.
* Copyright (c) 2016 Hewlett Packard Enterprise Development Company LP
*
* 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 service
* @name horizon.dashboard.admin.ironic.maintenance.service
* @description Service for putting nodes in, and removing them from
* maintenance mode
*/
angular
.module('horizon.dashboard.admin.ironic')
.factory('horizon.dashboard.admin.ironic.maintenance.service',
maintenanceService);
maintenanceService.$inject = [
'$modal',
'horizon.dashboard.admin.basePath',
'horizon.dashboard.admin.ironic.actions'
];
function maintenanceService($modal, basePath, actions) {
var service = {
putNodeInMaintenanceMode: putNodeInMaintenanceMode,
putNodesInMaintenanceMode: putNodesInMaintenanceMode,
removeNodeFromMaintenanceMode: removeNodeFromMaintenanceMode,
removeNodesFromMaintenanceMode: removeNodesFromMaintenanceMode
};
return service;
/*
* @name horizon.dashboard.admin.ironic.maintenance.service.
* putNodeInMaintenanceMode
* @description Put a specified node in maintenance mode
* @param {object} - Node
*
* @return {void}
*/
function putNodeInMaintenanceMode(node) {
var options = {
controller: "MaintenanceController as ctrl",
templateUrl: basePath + '/ironic/maintenance/maintenance.html'
};
$modal.open(options).result.then(function(maintReason) {
actions.putNodeInMaintenanceMode(node, maintReason);
});
}
/*
* @name horizon.dashboard.admin.ironic.maintenance.service.
* putNodesInMaintenanceMode
* @description Put the specified nodes in maintenance mode
* @param {Array<object>} - Nodes
*
* @return {void}
*/
function putNodesInMaintenanceMode(nodes) {
var options = {
controller: "MaintenanceController as ctrl",
templateUrl: basePath + '/ironic/maintenance/maintenance.html'
};
$modal.open(options).result.then(function(maintReason) {
actions.putAllInMaintenanceMode(nodes, maintReason);
});
}
/*
* @name horizon.dashboard.admin.ironic.maintenance.service.
* removeNodeInMaintenanceMode
* @description Remove a specified node from maintenance mode
* @param {object} - Node
*
* @return {void}
*/
function removeNodeFromMaintenanceMode(node) {
actions.removeNodeFromMaintenanceMode(node);
}
/*
* @name horizon.dashboard.admin.ironic.maintenance.service.
* removeNodesFromMaintenanceMode
* @description Remove the specified nodes from maintenance mode
* @param {Array<object>} - Nodes
*
* @return {void}
*/
function removeNodesFromMaintenanceMode(nodes) {
actions.removeAllFromMaintenanceMode(nodes);
}
}
})();

View File

@ -56,7 +56,7 @@
node.power_state = null;
},
function(reason) {
toastService.add('error', gettext(reason));
toastService.add('error', reason);
});
}
@ -70,7 +70,7 @@
node.power_state = null;
},
function(reason) {
toastService.add('error', gettext(reason));
toastService.add('error', reason);
}
);
}
@ -85,16 +85,17 @@
// maintenance
function putInMaintenanceMode(node) {
function putInMaintenanceMode(node, maintReason) {
if (node.maintenance !== false) {
return $q.reject(gettext("Node is already in maintenance mode."));
}
return ironic.putNodeInMaintenanceMode(node.uuid, "").then(
return ironic.putNodeInMaintenanceMode(node.uuid, maintReason).then(
function () {
node.maintenance = true;
node.maintenance_reason = maintReason;
},
function(reason) {
toastService.add('error', gettext(reason));
toastService.add('error', reason);
}
);
}
@ -106,26 +107,41 @@
return ironic.removeNodeFromMaintenanceMode(node.uuid).then(
function () {
node.maintenance = false;
node.maintenance_reason = "";
},
function (reason) {
toastService.add('error', gettext(reason));
toastService.add('error', reason);
}
);
}
function putNodesInMaintenanceMode(nodes) {
return applyFuncToNodes(putInMaintenanceMode, nodes);
function putNodesInMaintenanceMode(nodes, maintReason) {
return applyFuncToNodes(putInMaintenanceMode, nodes, maintReason);
}
function removeNodesFromMaintenanceMode(nodes) {
return applyFuncToNodes(removeFromMaintenanceMode, nodes);
}
function applyFuncToNodes(fn, nodes) {
/*
* @name horizon.dashboard.admin.ironic.actions.applyFuncToNodes
* @description Apply a specified function to each member of a
* collection of nodes
*
* @param {function} fn Function to be applied.
* The function should accept a node as the first argument. An optional
* second argument can be used to provide additional information.
* @param {Array<node>} nodes - Collection of nodes
* @param {object} extra - Additional argument passed to the function
* @return {promise} - Single promise that represents the combined
* return status from all function invocations. The promise is rejected
* if any individual call fails.
*/
function applyFuncToNodes(fn, nodes, extra) {
var promises = [];
angular.forEach(nodes,
function(node) {
promises.push(fn(node));
promises.push(fn(node, extra));
});
return $q.all(promises);
}

View File

@ -26,10 +26,15 @@
'$location',
'horizon.app.core.openstack-service-api.ironic',
'horizon.dashboard.admin.ironic.actions',
'horizon.dashboard.admin.basePath'
'horizon.dashboard.admin.basePath',
'horizon.dashboard.admin.ironic.maintenance.service'
];
function IronicNodeDetailsController($location, ironic, actions, basePath) {
function IronicNodeDetailsController($location,
ironic,
actions,
basePath,
maintenanceService) {
var ctrl = this;
var path = basePath + 'ironic/node-details/sections/';
@ -50,6 +55,8 @@
ctrl.re_uuid = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;
ctrl.isUuid = isUuid;
ctrl.getVifPortId = getVifPortId;
ctrl.putNodeInMaintenanceMode = putNodeInMaintenanceMode;
ctrl.removeNodeFromMaintenanceMode = removeNodeFromMaintenanceMode;
init();
@ -120,6 +127,13 @@
angular.isDefined(port.extra.vif_port_id)
? port.extra.vif_port_id : "";
}
}
function putNodeInMaintenanceMode() {
maintenanceService.putNodeInMaintenanceMode(ctrl.node);
}
function removeNodeFromMaintenanceMode() {
maintenanceService.removeNodeFromMaintenanceMode(ctrl.node);
}
}
})();

View File

@ -18,14 +18,12 @@
{$ 'Power off' | translate $}
</action>
<action button-type="menu-item"
callback="ctrl.actions.promptForPutNodeInMaintenanceMode"
item="ctrl.node"
callback="ctrl.putNodeInMaintenanceMode"
disabled="ctrl.node['maintenance']">
{$ 'Maintenance on' | translate $}
</action>
<action button-type="menu-item"
callback="ctrl.actions.removeNodeFromMaintenanceMode"
item="ctrl.node"
callback="ctrl.removeNodeFromMaintenanceMode"
disabled="!ctrl.node['maintenance']">
{$ 'Maintenance off' | translate $}
</action>

View File

@ -22,13 +22,16 @@
.controller('IronicNodeListController', IronicNodeListController);
IronicNodeListController.$inject = [
'$scope',
'horizon.app.core.openstack-service-api.ironic',
'horizon.dashboard.admin.ironic.actions',
'horizon.dashboard.admin.basePath'
'horizon.dashboard.admin.basePath',
'horizon.dashboard.admin.ironic.maintenance.service'
];
function IronicNodeListController($scope, ironic, actions, basePath) {
function IronicNodeListController(ironic,
actions,
basePath,
maintenanceService) {
var ctrl = this;
ctrl.nodes = [];
@ -36,6 +39,11 @@
ctrl.basePath = basePath;
ctrl.actions = actions;
ctrl.putNodeInMaintenanceMode = putNodeInMaintenanceMode;
ctrl.putNodesInMaintenanceMode = putNodesInMaintenanceMode;
ctrl.removeNodeFromMaintenanceMode = removeNodeFromMaintenanceMode;
ctrl.removeNodesFromMaintenanceMode = removeNodesFromMaintenanceMode;
/**
* Filtering - client-side MagicSearch
* all facets for node table
@ -100,6 +108,22 @@
}
);
}
function putNodeInMaintenanceMode(node) {
maintenanceService.putNodeInMaintenanceMode(node);
}
function putNodesInMaintenanceMode(nodes) {
maintenanceService.putNodesInMaintenanceMode(nodes);
}
function removeNodeFromMaintenanceMode(node) {
maintenanceService.removeNodeFromMaintenanceMode(node);
}
function removeNodesFromMaintenanceMode(nodes) {
maintenanceService.removeNodesFromMaintenanceMode(nodes);
}
}
})();

View File

@ -32,13 +32,13 @@
{$ 'Power off' | translate $}
</action>
<action button-type="menu-item"
callback="table.actions.putAllInMaintenanceMode"
callback="table.putNodesInMaintenanceMode"
item="tCtrl.selected"
disabled="tCtrl.selected.length === 0">
{$ 'Maintenance on' | translate $}
</action>
<action button-type="menu-item"
callback="table.actions.removeAllFromMaintenanceMode"
callback="table.removeNodesFromMaintenanceMode"
item="tCtrl.selected"
disabled="tCtrl.selected.length === 0">
{$ 'Maintenance off' | translate $}
@ -129,13 +129,13 @@
{$ 'Power off' | translate $}
</action>
<action button-type="menu-item"
callback="table.actions.putNodeInMaintenanceMode"
callback="table.putNodeInMaintenanceMode"
disabled="node['maintenance']"
item="node">
{$ 'Maintenance on' | translate $}
</action>
<action button-type="menu-item"
callback="table.actions.removeNodeFromMaintenanceMode"
callback="table.removeNodeFromMaintenanceMode"
disabled="!node['maintenance']"
item="node">
{$ 'Maintenance off' | translate $}