Merge "Extend support for the Ironic state machine"
This commit is contained in:
commit
b7a3844479
@ -18,41 +18,6 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var provisionStateTransitionMatrix = {
|
||||
enroll: {
|
||||
manageable: 'manage'
|
||||
},
|
||||
manageable: {
|
||||
active: 'adopt',
|
||||
available: 'provide'
|
||||
},
|
||||
active: {
|
||||
available: 'deleted'
|
||||
},
|
||||
available: {
|
||||
active: 'active',
|
||||
manageable: 'manage'
|
||||
},
|
||||
'adopt failed': {
|
||||
manageable: 'manage',
|
||||
active: 'adopt'
|
||||
},
|
||||
'inspect failed': {
|
||||
manageable: 'manage'
|
||||
},
|
||||
'clean failed': {
|
||||
manageable: 'manage'
|
||||
},
|
||||
'deploy failed': {
|
||||
active: 'active',
|
||||
manageable: 'deleted'
|
||||
},
|
||||
error: {
|
||||
active: 'rebuild',
|
||||
manageable: 'deleted'
|
||||
}
|
||||
};
|
||||
|
||||
angular
|
||||
.module('horizon.app.core.openstack-service-api')
|
||||
.factory('horizon.app.core.openstack-service-api.ironic', ironicAPI);
|
||||
@ -82,7 +47,6 @@
|
||||
getNode: getNode,
|
||||
getNodes: getNodes,
|
||||
getPortsWithNode: getPortsWithNode,
|
||||
getProvisionStateTransitionVerb: getProvisionStateTransitionVerb,
|
||||
powerOffNode: powerOffNode,
|
||||
powerOnNode: powerOnNode,
|
||||
putNodeInMaintenanceMode: putNodeInMaintenanceMode,
|
||||
@ -447,25 +411,6 @@
|
||||
toastService.add('error', interpolate(msg, [reason], false));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Get the verb used to transition a node from a source
|
||||
* provision-state to a target provision-state
|
||||
*
|
||||
* @param {string} sourceState – source state
|
||||
* @param {string} targetState – target state
|
||||
* @return {string} Verb used to transition from source to target state.
|
||||
* null if the requested transition is not allowed.
|
||||
*/
|
||||
function getProvisionStateTransitionVerb(sourceState, targetState) {
|
||||
var verb = null;
|
||||
if (angular.isDefined(provisionStateTransitionMatrix[sourceState]) &&
|
||||
angular.isDefined(
|
||||
provisionStateTransitionMatrix[sourceState][targetState])) {
|
||||
verb = provisionStateTransitionMatrix[sourceState][targetState];
|
||||
}
|
||||
return verb;
|
||||
}
|
||||
}
|
||||
|
||||
}());
|
||||
|
@ -75,7 +75,6 @@
|
||||
deleteNodes: deleteNodes,
|
||||
deletePort: deletePort,
|
||||
deletePorts: deletePorts,
|
||||
getProvisionStateTransitionVerb: getProvisionStateTransitionVerb,
|
||||
powerOn: powerOn,
|
||||
powerOff: powerOff,
|
||||
powerOnAll: powerOnNodes,
|
||||
@ -207,10 +206,6 @@
|
||||
ironic.setNodeProvisionState(args.node.uuid, args.verb);
|
||||
}
|
||||
|
||||
function getProvisionStateTransitionVerb(sourceState, targetState) {
|
||||
return ironic.getProvisionStateTransitionVerb(sourceState, targetState);
|
||||
}
|
||||
|
||||
function createPort(node) {
|
||||
return createPortService.modal(node);
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
'horizon.dashboard.admin.ironic.basePath',
|
||||
'horizon.dashboard.admin.ironic.edit-node.service',
|
||||
'horizon.dashboard.admin.ironic.maintenance.service',
|
||||
'horizon.dashboard.admin.ironic.node-state-transition.service',
|
||||
'horizon.dashboard.admin.ironic.validUuidPattern'
|
||||
];
|
||||
|
||||
@ -46,6 +47,7 @@
|
||||
basePath,
|
||||
editNodeService,
|
||||
maintenanceService,
|
||||
nodeStateTransitionService,
|
||||
validUuidPattern) {
|
||||
var ctrl = this;
|
||||
var path = basePath + '/node-details/sections/';
|
||||
@ -67,6 +69,7 @@
|
||||
|
||||
ctrl.node = null;
|
||||
ctrl.nodeValidation = {};
|
||||
ctrl.nodeStateTransitions = [];
|
||||
ctrl.ports = [];
|
||||
ctrl.portsSrc = [];
|
||||
ctrl.basePath = basePath;
|
||||
@ -121,6 +124,8 @@
|
||||
var uuid = $location.absUrl().match(pattern)[2];
|
||||
|
||||
retrieveNode(uuid).then(function () {
|
||||
ctrl.nodeStateTransitions =
|
||||
nodeStateTransitionService.getTransitions(ctrl.node.provision_state);
|
||||
retrievePorts(uuid);
|
||||
ironic.validateNode(uuid).then(function(response) {
|
||||
ctrl.nodeValidation = response.data;
|
||||
|
@ -32,18 +32,17 @@
|
||||
disabled="!ctrl.node.maintenance">
|
||||
{$ 'Maintenance off' | translate $}
|
||||
</action>
|
||||
<action ng-repeat="targetState in ['manageable', 'available', 'active']"
|
||||
button-type="menu-item"
|
||||
callback="ctrl.actions.setProvisionState"
|
||||
item="{node: ctrl.node,
|
||||
verb: ctrl.actions.getProvisionStateTransitionVerb(
|
||||
ctrl.node.provision_state,
|
||||
targetState)}"
|
||||
disabled="ctrl.actions.getProvisionStateTransitionVerb(
|
||||
ctrl.node.provision_state,
|
||||
targetState) === null">
|
||||
{$ ('Move to ' | translate) + targetState $}
|
||||
</action>
|
||||
<li role="presentation"
|
||||
ng-repeat="transition in ctrl.nodeStateTransitions">
|
||||
<a role="menuitem"
|
||||
ng-click="ctrl.actions.setProvisionState({
|
||||
node: ctrl.node,
|
||||
verb: transition.verb});
|
||||
$event.stopPropagation();
|
||||
$event.preventDefault()">
|
||||
<span>{$ transition.label $}</span>
|
||||
</a>
|
||||
</li>
|
||||
<action button-type="menu-item"
|
||||
callback="ctrl.editNode">
|
||||
{$ 'Edit' | translate $}
|
||||
|
@ -31,7 +31,8 @@
|
||||
'horizon.dashboard.admin.ironic.actions',
|
||||
'horizon.dashboard.admin.ironic.maintenance.service',
|
||||
'horizon.dashboard.admin.ironic.enroll-node.service',
|
||||
'horizon.dashboard.admin.ironic.edit-node.service'
|
||||
'horizon.dashboard.admin.ironic.edit-node.service',
|
||||
'horizon.dashboard.admin.ironic.node-state-transition.service'
|
||||
];
|
||||
|
||||
function IronicNodeListController($scope,
|
||||
@ -43,7 +44,8 @@
|
||||
actions,
|
||||
maintenanceService,
|
||||
enrollNodeService,
|
||||
editNodeService) {
|
||||
editNodeService,
|
||||
nodeStateTransitionService) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.nodes = [];
|
||||
@ -57,6 +59,7 @@
|
||||
ctrl.enrollNode = enrollNode;
|
||||
ctrl.editNode = editNode;
|
||||
ctrl.refresh = refresh;
|
||||
ctrl.getNodeStateTransitions = getNodeStateTransitions;
|
||||
|
||||
/**
|
||||
* Filtering - client-side MagicSearch
|
||||
@ -188,6 +191,10 @@
|
||||
function refresh() {
|
||||
init();
|
||||
}
|
||||
|
||||
function getNodeStateTransitions(node) {
|
||||
return nodeStateTransitionService.getTransitions(node.provision_state);
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
||||
|
@ -172,19 +172,17 @@
|
||||
item="node">
|
||||
{$ 'Create port' | translate $}
|
||||
</action>
|
||||
<action ng-repeat="targetState in
|
||||
['manageable', 'available', 'active']"
|
||||
button-type="menu-item"
|
||||
callback="table.actions.setProvisionState"
|
||||
item="{node: node,
|
||||
verb: table.actions.getProvisionStateTransitionVerb(
|
||||
node.provision_state,
|
||||
targetState)}"
|
||||
disabled="table.actions.getProvisionStateTransitionVerb(
|
||||
node.provision_state,
|
||||
targetState) === null">
|
||||
{$ ('Move to ' | translate) + targetState $}
|
||||
</action>
|
||||
<li role="presentation"
|
||||
ng-repeat="transition in table.getNodeStateTransitions(node)">
|
||||
<a role="menuitem"
|
||||
ng-click="table.actions.setProvisionState({
|
||||
node: node,
|
||||
verb: transition.verb});
|
||||
$event.stopPropagation();
|
||||
$event.preventDefault()">
|
||||
<span>{$ transition.label $}</span>
|
||||
</a>
|
||||
</li>
|
||||
<action button-type="menu-item"
|
||||
callback="table.editNode"
|
||||
item="node">
|
||||
|
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* © 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-state-transition.service',
|
||||
nodeStateTransitionService);
|
||||
|
||||
nodeStateTransitionService.$inject = [];
|
||||
|
||||
/**
|
||||
* @description Utility service for working with the node state machine
|
||||
* @return {void}
|
||||
*/
|
||||
function nodeStateTransitionService() {
|
||||
// Dictionary of NodeState objects indexed by state name
|
||||
var states = {};
|
||||
|
||||
// Create node state objects
|
||||
angular.forEach(['enroll',
|
||||
'manageable',
|
||||
'active',
|
||||
'available',
|
||||
'adopt failed',
|
||||
'clean failed',
|
||||
'inspect failed',
|
||||
'clean wait',
|
||||
'deploy failed',
|
||||
'error'],
|
||||
function(state) {
|
||||
states[state] = new NodeState(state);
|
||||
});
|
||||
|
||||
// Add state transitions
|
||||
|
||||
states.enroll.addTransition('manageable', 'manage');
|
||||
|
||||
states.manageable.addTransition('active', 'adopt');
|
||||
states.manageable.addTransition('available', 'provide');
|
||||
|
||||
states.active.addTransition('available', 'deleted');
|
||||
|
||||
states.available.addTransition('active', 'active');
|
||||
states.available.addTransition('manageable', 'manage');
|
||||
|
||||
states['adopt failed'].addTransition('manageable', 'manage');
|
||||
states['adopt failed'].addTransition('active', 'adopt');
|
||||
|
||||
states['inspect failed'].addTransition('manageable', 'manage');
|
||||
|
||||
states['clean failed'].addTransition('manageable', 'manage');
|
||||
|
||||
states['deploy failed'].addTransition('active', 'active');
|
||||
states['deploy failed'].addTransition('manageable', 'deleted');
|
||||
|
||||
states.error.addTransition('active', 'rebuild');
|
||||
states.error.addTransition('manageable', 'deleted');
|
||||
|
||||
/**
|
||||
* @description Class constructor for NodeState object.
|
||||
* A NodeState maintains a set of transitions to other states.
|
||||
*
|
||||
* @param {name} name – Name of state
|
||||
* @return {void}
|
||||
*/
|
||||
function NodeState(name) {
|
||||
this.name = name;
|
||||
this.transitions = {};
|
||||
|
||||
/**
|
||||
* @description Add a transition to a specified target state.
|
||||
*
|
||||
* @param {string} target – Name of target state
|
||||
* @param {string} verb – Verb used to accomplish transition
|
||||
* @param {string} label – Description of the transition. Optional.
|
||||
* @return {void}
|
||||
*/
|
||||
this.addTransition = function(target, verb, label) {
|
||||
this.transitions[target] =
|
||||
{source: this.name,
|
||||
target: target,
|
||||
verb: verb,
|
||||
label: angular.isDefined(label)
|
||||
? label : gettext("Move to") + " " + target};
|
||||
};
|
||||
|
||||
/**
|
||||
* @description Get the transition object associated with a
|
||||
* specified target state.
|
||||
*
|
||||
* @param {string} targetState – Name of target state
|
||||
* @return {object} Transition object. A value of null
|
||||
* is returned if a transition does not exist.
|
||||
*/
|
||||
this.getTransition = function(targetState) {
|
||||
return this.transitions.hasOwnProperty(targetState)
|
||||
? this.transitions[targetState] : null;
|
||||
};
|
||||
}
|
||||
|
||||
this.getTransitions = function(sourceState) {
|
||||
var transitions = [];
|
||||
if (states.hasOwnProperty(sourceState)) {
|
||||
angular.forEach(states[sourceState].transitions,
|
||||
function(transition) {
|
||||
transitions.push(transition);
|
||||
});
|
||||
}
|
||||
return transitions;
|
||||
};
|
||||
}
|
||||
}());
|
Loading…
x
Reference in New Issue
Block a user