Updated to ironic API v1.11 and added manageable state
Newly registered nodes begin in the enroll provision state by default instead of available. Actions added to the current dropdown on node view to enable move to manageable, available and active states. Actions are enabled and disabled in view as the current state permits. All necessary fields required to move a node to available state are still required on the enroll node modal. This will be changed to only the necessary fields to move a node to enroll state once the functionality for editing a node is ready. Change-Id: I349a293a1069ad01fd782d1828bad607f9b9d6b0 Co-Authored-By: Peter Piela <ppiela@cray.com>
This commit is contained in:
parent
7d226b75da
commit
e476fe9344
|
@ -27,7 +27,7 @@ from openstack_dashboard.api import base
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEFAULT_IRONIC_API_VERSION = '1.6'
|
DEFAULT_IRONIC_API_VERSION = '1.11'
|
||||||
DEFAULT_INSECURE = False
|
DEFAULT_INSECURE = False
|
||||||
DEFAULT_CACERT = None
|
DEFAULT_CACERT = None
|
||||||
|
|
||||||
|
@ -103,6 +103,19 @@ def node_set_power_state(request, node_id, state):
|
||||||
return ironicclient(request).node.set_power_state(node_id, state)
|
return ironicclient(request).node.set_power_state(node_id, state)
|
||||||
|
|
||||||
|
|
||||||
|
def node_set_provision_state(request, node_uuid, state):
|
||||||
|
"""Set the target provision state for a given node.
|
||||||
|
|
||||||
|
:param request: HTTP request.
|
||||||
|
:param node_uuid: The UUID of the node.
|
||||||
|
:param state: the target provision state to set.
|
||||||
|
:return: node.
|
||||||
|
|
||||||
|
http://docs.openstack.org/developer/python-ironicclient/api/ironicclient.v1.node.html#ironicclient.v1.node.NodeManager.set_provision_state
|
||||||
|
"""
|
||||||
|
return ironicclient(request).node.set_provision_state(node_uuid, state)
|
||||||
|
|
||||||
|
|
||||||
def node_set_maintenance(request, node_id, state, maint_reason=None):
|
def node_set_maintenance(request, node_id, state, maint_reason=None):
|
||||||
"""Set the maintenance mode on a given node.
|
"""Set the maintenance mode on a given node.
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,23 @@ class StatesPower(generic.View):
|
||||||
return ironic.node_set_power_state(request, node_id, state)
|
return ironic.node_set_power_state(request, node_id, state)
|
||||||
|
|
||||||
|
|
||||||
|
@urls.register
|
||||||
|
class StatesProvision(generic.View):
|
||||||
|
|
||||||
|
url_regex = r'ironic/nodes/(?P<node_uuid>[0-9a-f-]+)/states/provision$'
|
||||||
|
|
||||||
|
@rest_utils.ajax(data_required=True)
|
||||||
|
def put(self, request, node_uuid):
|
||||||
|
"""Set the provision state for a specified node.
|
||||||
|
|
||||||
|
:param request: HTTP request.
|
||||||
|
:param node_id: Node uuid
|
||||||
|
:return: Return code
|
||||||
|
"""
|
||||||
|
state = request.DATA.get('state')
|
||||||
|
return ironic.node_set_provision_state(request, node_uuid, state)
|
||||||
|
|
||||||
|
|
||||||
@urls.register
|
@urls.register
|
||||||
class Maintenance(generic.View):
|
class Maintenance(generic.View):
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ PANEL_GROUP = 'admin'
|
||||||
ADD_PANEL = 'ironic_ui.content.ironic.panel.Ironic'
|
ADD_PANEL = 'ironic_ui.content.ironic.panel.Ironic'
|
||||||
# A list of applications to be prepended to INSTALLED_APPS
|
# A list of applications to be prepended to INSTALLED_APPS
|
||||||
ADD_INSTALLED_APPS = ['ironic_ui', ]
|
ADD_INSTALLED_APPS = ['ironic_ui', ]
|
||||||
|
# A list of AngularJS modules to be loaded when Angular bootstraps.
|
||||||
ADD_ANGULAR_MODULES = ['horizon.dashboard.admin.ironic']
|
ADD_ANGULAR_MODULES = ['horizon.dashboard.admin.ironic']
|
||||||
# Automatically discover static resources in installed apps
|
# Automatically discover static resources in installed apps
|
||||||
AUTO_DISCOVER_STATIC_FILES = True
|
AUTO_DISCOVER_STATIC_FILES = True
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
// selected driver
|
// selected driver
|
||||||
ctrl.driverProperties = null;
|
ctrl.driverProperties = null;
|
||||||
ctrl.driverPropertyGroups = null;
|
ctrl.driverPropertyGroups = null;
|
||||||
|
ctrl.moveNodeToManageableState = false;
|
||||||
|
|
||||||
// Parameter object that defines the node to be enrolled
|
// Parameter object that defines the node to be enrolled
|
||||||
ctrl.node = {
|
ctrl.node = {
|
||||||
|
@ -276,9 +277,14 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
ironic.createNode(ctrl.node).then(
|
ironic.createNode(ctrl.node).then(
|
||||||
function() {
|
function(response) {
|
||||||
|
$log.info("create node response = " + JSON.stringify(response));
|
||||||
$modalInstance.close();
|
$modalInstance.close();
|
||||||
$rootScope.$emit(ironicEvents.ENROLL_NODE_SUCCESS);
|
$rootScope.$emit(ironicEvents.ENROLL_NODE_SUCCESS);
|
||||||
|
if (ctrl.moveNodeToManageableState) {
|
||||||
|
$log.info("Setting node provision state");
|
||||||
|
ironic.setNodeProvisionState(response.data.uuid, 'manage');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
function() {
|
function() {
|
||||||
// No additional error processing for now
|
// No additional error processing for now
|
||||||
|
|
|
@ -254,10 +254,8 @@
|
||||||
<!--end driver details tab-->
|
<!--end driver details tab-->
|
||||||
</div>
|
</div>
|
||||||
<!--end tabbed content-->
|
<!--end tabbed content-->
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
<!--end enroll node form-->
|
<!--end enroll node form-->
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--modal footer-->
|
<!--modal footer-->
|
||||||
|
@ -267,6 +265,7 @@
|
||||||
<span class="fa fa-close"></span>
|
<span class="fa fa-close"></span>
|
||||||
<span class="ng-scope" translate>Cancel</span>
|
<span class="ng-scope" translate>Cancel</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button type="submit"
|
<button type="submit"
|
||||||
ng-disabled="!ctrl.driverProperties ||
|
ng-disabled="!ctrl.driverProperties ||
|
||||||
enrollNodeForm.$invalid"
|
enrollNodeForm.$invalid"
|
||||||
|
|
|
@ -18,6 +18,41 @@
|
||||||
(function () {
|
(function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var provisionStateTransitionMatrix = {
|
||||||
|
enroll: {
|
||||||
|
manageable: 'manage'
|
||||||
|
},
|
||||||
|
manageable: {
|
||||||
|
active: 'adopt',
|
||||||
|
available: 'provide'
|
||||||
|
},
|
||||||
|
active: {
|
||||||
|
manageable: '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
|
angular
|
||||||
.module('horizon.app.core.openstack-service-api')
|
.module('horizon.app.core.openstack-service-api')
|
||||||
.factory('horizon.app.core.openstack-service-api.ironic', ironicAPI);
|
.factory('horizon.app.core.openstack-service-api.ironic', ironicAPI);
|
||||||
|
@ -45,10 +80,12 @@
|
||||||
getNode: getNode,
|
getNode: getNode,
|
||||||
getNodes: getNodes,
|
getNodes: getNodes,
|
||||||
getPortsWithNode: getPortsWithNode,
|
getPortsWithNode: getPortsWithNode,
|
||||||
|
getProvisionStateTransitionVerb: getProvisionStateTransitionVerb,
|
||||||
powerOffNode: powerOffNode,
|
powerOffNode: powerOffNode,
|
||||||
powerOnNode: powerOnNode,
|
powerOnNode: powerOnNode,
|
||||||
putNodeInMaintenanceMode: putNodeInMaintenanceMode,
|
putNodeInMaintenanceMode: putNodeInMaintenanceMode,
|
||||||
removeNodeFromMaintenanceMode: removeNodeFromMaintenanceMode
|
removeNodeFromMaintenanceMode: removeNodeFromMaintenanceMode,
|
||||||
|
setNodeProvisionState: setNodeProvisionState
|
||||||
};
|
};
|
||||||
|
|
||||||
return service;
|
return service;
|
||||||
|
@ -199,6 +236,33 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Set the target provision state of the node.
|
||||||
|
*
|
||||||
|
* http://docs.openstack.org/developer/ironic/webapi/v1.html#
|
||||||
|
* put--v1-nodes-(node_ident)-states-provision
|
||||||
|
*
|
||||||
|
* @param {string} uuid – UUID of a node.
|
||||||
|
* @param {string} state – Target provision state
|
||||||
|
* @return {promise} Promise
|
||||||
|
*/
|
||||||
|
function setNodeProvisionState(uuid, state) {
|
||||||
|
var data = {
|
||||||
|
state: state
|
||||||
|
};
|
||||||
|
return apiService.put('/api/ironic/nodes/' + uuid + '/states/provision',
|
||||||
|
data)
|
||||||
|
.success(function() {
|
||||||
|
toastService.add(
|
||||||
|
'success',
|
||||||
|
gettext('Successfully set target node provision state'));
|
||||||
|
})
|
||||||
|
.error(function(reason) {
|
||||||
|
var msg = gettext('Unable to set node provision state: %s');
|
||||||
|
toastService.add('error', interpolate(msg, [reason], false));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Create an Ironic node
|
* @description Create an Ironic node
|
||||||
*
|
*
|
||||||
|
@ -319,6 +383,25 @@
|
||||||
toastService.add('error', interpolate(msg, [reason], false));
|
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,6 +75,7 @@
|
||||||
deleteNodes: deleteNodes,
|
deleteNodes: deleteNodes,
|
||||||
deletePort: deletePort,
|
deletePort: deletePort,
|
||||||
deletePorts: deletePorts,
|
deletePorts: deletePorts,
|
||||||
|
getProvisionStateTransitionVerb: getProvisionStateTransitionVerb,
|
||||||
powerOn: powerOn,
|
powerOn: powerOn,
|
||||||
powerOff: powerOff,
|
powerOff: powerOff,
|
||||||
powerOnAll: powerOnNodes,
|
powerOnAll: powerOnNodes,
|
||||||
|
@ -82,7 +83,8 @@
|
||||||
putNodeInMaintenanceMode: putInMaintenanceMode,
|
putNodeInMaintenanceMode: putInMaintenanceMode,
|
||||||
removeNodeFromMaintenanceMode: removeFromMaintenanceMode,
|
removeNodeFromMaintenanceMode: removeFromMaintenanceMode,
|
||||||
putAllInMaintenanceMode: putNodesInMaintenanceMode,
|
putAllInMaintenanceMode: putNodesInMaintenanceMode,
|
||||||
removeAllFromMaintenanceMode: removeNodesFromMaintenanceMode
|
removeAllFromMaintenanceMode: removeNodesFromMaintenanceMode,
|
||||||
|
setProvisionState: setProvisionState
|
||||||
};
|
};
|
||||||
|
|
||||||
return service;
|
return service;
|
||||||
|
@ -191,6 +193,24 @@
|
||||||
return applyFuncToNodes(removeFromMaintenanceMode, nodes);
|
return applyFuncToNodes(removeFromMaintenanceMode, nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @name horizon.dashboard.admin.ironic.actions.setProvisionState
|
||||||
|
* @description Set the provisioning state of a specified node
|
||||||
|
*
|
||||||
|
* @param {object} args - Object with two properties named 'node'
|
||||||
|
* and 'verb'.
|
||||||
|
* node: node object.
|
||||||
|
* verb: string the value of which is the verb used to move
|
||||||
|
* the node to the desired target state for the node.
|
||||||
|
*/
|
||||||
|
function setProvisionState(args) {
|
||||||
|
ironic.setNodeProvisionState(args.node.uuid, args.verb);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getProvisionStateTransitionVerb(sourceState, targetState) {
|
||||||
|
return ironic.getProvisionStateTransitionVerb(sourceState, targetState);
|
||||||
|
}
|
||||||
|
|
||||||
function createPort(node) {
|
function createPort(node) {
|
||||||
return createPortService.modal(node);
|
return createPortService.modal(node);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
'$scope',
|
'$scope',
|
||||||
'$rootScope',
|
'$rootScope',
|
||||||
'$location',
|
'$location',
|
||||||
|
'horizon.framework.widgets.toast.service',
|
||||||
'horizon.app.core.openstack-service-api.ironic',
|
'horizon.app.core.openstack-service-api.ironic',
|
||||||
'horizon.dashboard.admin.ironic.events',
|
'horizon.dashboard.admin.ironic.events',
|
||||||
'horizon.dashboard.admin.ironic.actions',
|
'horizon.dashboard.admin.ironic.actions',
|
||||||
|
@ -37,6 +38,7 @@
|
||||||
function IronicNodeDetailsController($scope,
|
function IronicNodeDetailsController($scope,
|
||||||
$rootScope,
|
$rootScope,
|
||||||
$location,
|
$location,
|
||||||
|
toastService,
|
||||||
ironic,
|
ironic,
|
||||||
ironicEvents,
|
ironicEvents,
|
||||||
actions,
|
actions,
|
||||||
|
@ -61,6 +63,7 @@
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
ctrl.node = null;
|
||||||
ctrl.ports = [];
|
ctrl.ports = [];
|
||||||
ctrl.portsSrc = [];
|
ctrl.portsSrc = [];
|
||||||
ctrl.basePath = basePath;
|
ctrl.basePath = basePath;
|
||||||
|
@ -72,6 +75,7 @@
|
||||||
ctrl.createPort = createPort;
|
ctrl.createPort = createPort;
|
||||||
ctrl.deletePort = deletePort;
|
ctrl.deletePort = deletePort;
|
||||||
ctrl.deletePorts = deletePorts;
|
ctrl.deletePorts = deletePorts;
|
||||||
|
ctrl.refresh = refresh;
|
||||||
|
|
||||||
var createPortHandler =
|
var createPortHandler =
|
||||||
$rootScope.$on(ironicEvents.CREATE_PORT_SUCCESS,
|
$rootScope.$on(ironicEvents.CREATE_PORT_SUCCESS,
|
||||||
|
@ -119,9 +123,19 @@
|
||||||
* @return {promise} promise
|
* @return {promise} promise
|
||||||
*/
|
*/
|
||||||
function retrieveNode(uuid) {
|
function retrieveNode(uuid) {
|
||||||
|
var lastError = ctrl.node ? ctrl.node.last_error : null;
|
||||||
|
|
||||||
return ironic.getNode(uuid).then(function (response) {
|
return ironic.getNode(uuid).then(function (response) {
|
||||||
ctrl.node = response.data;
|
ctrl.node = response.data;
|
||||||
ctrl.node.id = uuid;
|
ctrl.node.id = uuid;
|
||||||
|
|
||||||
|
if (lastError &&
|
||||||
|
ctrl.node.last_error !== "" &&
|
||||||
|
ctrl.node.last_error !== lastError) {
|
||||||
|
toastService.add(
|
||||||
|
'error',
|
||||||
|
"Node " + ctrl.node.name + ". " + ctrl.node.last_error);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,5 +226,15 @@
|
||||||
});
|
});
|
||||||
ctrl.actions.deletePorts(selectedPorts);
|
ctrl.actions.deletePorts(selectedPorts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name horizon.dashboard.admin.ironic.NodeDetailsController.refresh
|
||||||
|
* @description Update node information
|
||||||
|
*
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
function refresh() {
|
||||||
|
init();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -2,31 +2,48 @@
|
||||||
ng-controller="horizon.dashboard.admin.ironic.NodeDetailsController as ctrl">
|
ng-controller="horizon.dashboard.admin.ironic.NodeDetailsController as ctrl">
|
||||||
|
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
|
<button class="btn btn-default btn-sm"
|
||||||
|
style="margin-right:10px;"
|
||||||
|
ng-click="ctrl.refresh()">
|
||||||
|
<span translate>Refresh</span>
|
||||||
|
</button>
|
||||||
<action-list dropdown>
|
<action-list dropdown>
|
||||||
<action button-type="split-button"
|
<action button-type="split-button"
|
||||||
action-classes="'btn btn-default btn-sm'"
|
action-classes="'btn btn-default btn-sm'"
|
||||||
callback="ctrl.actions.powerOn"
|
callback="ctrl.actions.powerOn"
|
||||||
item="ctrl.node"
|
item="ctrl.node"
|
||||||
disabled="ctrl.node['power_state']!=='power off'">
|
disabled="ctrl.node.power_state!=='power off'">
|
||||||
{$ 'Power on' | translate $}
|
{$ 'Power on' | translate $}
|
||||||
</action>
|
</action>
|
||||||
<menu>
|
<menu>
|
||||||
<action button-type="menu-item"
|
<action button-type="menu-item"
|
||||||
callback="ctrl.actions.powerOff"
|
callback="ctrl.actions.powerOff"
|
||||||
item="ctrl.node"
|
item="ctrl.node"
|
||||||
disabled="ctrl.node['power_state']!=='power on'">
|
disabled="ctrl.node.power_state!=='power on'">
|
||||||
{$ 'Power off' | translate $}
|
{$ 'Power off' | translate $}
|
||||||
</action>
|
</action>
|
||||||
<action button-type="menu-item"
|
<action button-type="menu-item"
|
||||||
callback="ctrl.putNodeInMaintenanceMode"
|
callback="ctrl.putNodeInMaintenanceMode"
|
||||||
disabled="ctrl.node['maintenance']">
|
disabled="ctrl.node.maintenance">
|
||||||
{$ 'Maintenance on' | translate $}
|
{$ 'Maintenance on' | translate $}
|
||||||
</action>
|
</action>
|
||||||
<action button-type="menu-item"
|
<action button-type="menu-item"
|
||||||
callback="ctrl.removeNodeFromMaintenanceMode"
|
callback="ctrl.removeNodeFromMaintenanceMode"
|
||||||
disabled="!ctrl.node['maintenance']">
|
disabled="!ctrl.node.maintenance">
|
||||||
{$ 'Maintenance off' | translate $}
|
{$ 'Maintenance off' | translate $}
|
||||||
</action>
|
</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>
|
||||||
</menu>
|
</menu>
|
||||||
</action-list>
|
</action-list>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,19 +6,19 @@
|
||||||
<hr class="header_rule">
|
<hr class="header_rule">
|
||||||
<dl class="dl-horizontal">
|
<dl class="dl-horizontal">
|
||||||
<dt translate>Name</dt>
|
<dt translate>Name</dt>
|
||||||
<dd>{$ ctrl.node['name'] $}</dd>
|
<dd>{$ ctrl.node.name $}</dd>
|
||||||
<dt translate>Maintenance</dt>
|
<dt translate>Maintenance</dt>
|
||||||
<dd>{$ ctrl.node['maintenance'] | yesno $}</dd>
|
<dd>{$ ctrl.node.maintenance | yesno $}</dd>
|
||||||
<dt translate>Maintenance Reason</dt>
|
<dt translate>Maintenance Reason</dt>
|
||||||
<dd>{$ ctrl.node['maintenance_reason'] | noValue $}</dd>
|
<dd>{$ ctrl.node.maintenance_reason | noValue $}</dd>
|
||||||
<dt translate>Inspection Started At</dt>
|
<dt translate>Inspection Started At</dt>
|
||||||
<dd>{$ ctrl.node['inspection_started_at'] | date: 'medium' | noValue $}</dd>
|
<dd>{$ ctrl.node.inspection_started_at | date: 'medium' | noValue $}</dd>
|
||||||
<dt translate>Inspection Finished At</dt>
|
<dt translate>Inspection Finished At</dt>
|
||||||
<dd>{$ ctrl.node['inspection_finished_at'] | date: 'medium' | noValue $}</dd>
|
<dd>{$ ctrl.node.inspection_finished_at | date: 'medium' | noValue $}</dd>
|
||||||
<dt translate>Reservation</dt>
|
<dt translate>Reservation</dt>
|
||||||
<dd>{$ ctrl.node['reservation'] | noValue $}</dd>
|
<dd>{$ ctrl.node.reservation | noValue $}</dd>
|
||||||
<dt translate>Console Enabled</dt>
|
<dt translate>Console Enabled</dt>
|
||||||
<dd>{$ ctrl.node['console_enabled'] | yesno $}</dd>
|
<dd>{$ ctrl.node.console_enabled | yesno $}</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -29,22 +29,22 @@
|
||||||
<dl class="dl-horizontal">
|
<dl class="dl-horizontal">
|
||||||
<dt translate>Instance ID</dt>
|
<dt translate>Instance ID</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<a href="/admin/instances/{$ ctrl.node['instance_uuid'] $}/detail">
|
<a href="/admin/instances/{$ ctrl.node.instance_uuid $}/detail">
|
||||||
{$ ctrl.node['instance_uuid'] | noValue $}
|
{$ ctrl.node.instance_uuid | noValue $}
|
||||||
</a>
|
</a>
|
||||||
</dd>
|
</dd>
|
||||||
<dt translate>Power State</dt>
|
<dt translate>Power State</dt>
|
||||||
<dd ng-class="{'running': ctrl.node['target_power_state']}">{$ ctrl.node['power_state'] $}</dd>
|
<dd ng-class="{'running': ctrl.node.target_power_state}">{$ ctrl.node.power_state $}</dd>
|
||||||
<dt translate>Target Power State</dt>
|
<dt translate>Target Power State</dt>
|
||||||
<dd>{$ ctrl.node['target_power_state'] | noValue $}</dd>
|
<dd>{$ ctrl.node.target_power_state | noValue $}</dd>
|
||||||
<dt translate>Provision State</dt>
|
<dt translate>Provision State</dt>
|
||||||
<dd>{$ ctrl.node['provision_state'] | noValue $}</dd>
|
<dd>{$ ctrl.node.provision_state | noValue $}</dd>
|
||||||
<dt translate>Target Provision State</dt>
|
<dt translate>Target Provision State</dt>
|
||||||
<dd>{$ ctrl.node['target_provision_state'] | noValue $}</dd>
|
<dd>{$ ctrl.node.target_provision_state | noValue $}</dd>
|
||||||
<dt translate>Last Error</dt>
|
<dt translate>Last Error</dt>
|
||||||
<dd>{$ ctrl.node['last_error'] | noValue $}</dd>
|
<dd>{$ ctrl.node.last_error | noValue $}</dd>
|
||||||
<dt translate>Updated At</dt>
|
<dt translate>Updated At</dt>
|
||||||
<dd>{$ ctrl.node['updated_at'] | date: 'medium' | noValue $}</dd>
|
<dd>{$ ctrl.node.updated_at | date: 'medium' | noValue $}</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
IronicNodeListController.$inject = [
|
IronicNodeListController.$inject = [
|
||||||
'$scope',
|
'$scope',
|
||||||
'$rootScope',
|
'$rootScope',
|
||||||
|
'horizon.framework.widgets.toast.service',
|
||||||
'horizon.app.core.openstack-service-api.ironic',
|
'horizon.app.core.openstack-service-api.ironic',
|
||||||
'horizon.dashboard.admin.ironic.events',
|
'horizon.dashboard.admin.ironic.events',
|
||||||
'horizon.dashboard.admin.ironic.actions',
|
'horizon.dashboard.admin.ironic.actions',
|
||||||
|
@ -34,6 +35,7 @@
|
||||||
|
|
||||||
function IronicNodeListController($scope,
|
function IronicNodeListController($scope,
|
||||||
$rootScope,
|
$rootScope,
|
||||||
|
toastService,
|
||||||
ironic,
|
ironic,
|
||||||
ironicEvents,
|
ironicEvents,
|
||||||
actions,
|
actions,
|
||||||
|
@ -43,7 +45,7 @@
|
||||||
var ctrl = this;
|
var ctrl = this;
|
||||||
|
|
||||||
ctrl.nodes = [];
|
ctrl.nodes = [];
|
||||||
ctrl.nodeSrc = [];
|
ctrl.nodesSrc = [];
|
||||||
ctrl.basePath = basePath;
|
ctrl.basePath = basePath;
|
||||||
ctrl.actions = actions;
|
ctrl.actions = actions;
|
||||||
|
|
||||||
|
@ -52,6 +54,7 @@
|
||||||
ctrl.removeNodeFromMaintenanceMode = removeNodeFromMaintenanceMode;
|
ctrl.removeNodeFromMaintenanceMode = removeNodeFromMaintenanceMode;
|
||||||
ctrl.removeNodesFromMaintenanceMode = removeNodesFromMaintenanceMode;
|
ctrl.removeNodesFromMaintenanceMode = removeNodesFromMaintenanceMode;
|
||||||
ctrl.enrollNode = enrollNode;
|
ctrl.enrollNode = enrollNode;
|
||||||
|
ctrl.refresh = refresh;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filtering - client-side MagicSearch
|
* Filtering - client-side MagicSearch
|
||||||
|
@ -132,11 +135,19 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function onGetNodes(response) {
|
function onGetNodes(response) {
|
||||||
ctrl.nodesSrc = response.data.items;
|
angular.forEach(response.data.items, function (node) {
|
||||||
ctrl.nodesSrc.forEach(function (node) {
|
|
||||||
node.id = node.uuid;
|
node.id = node.uuid;
|
||||||
retrievePorts(node);
|
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);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
ctrl.nodesSrc = response.data.items;
|
||||||
}
|
}
|
||||||
|
|
||||||
function retrievePorts(node) {
|
function retrievePorts(node) {
|
||||||
|
@ -166,6 +177,10 @@
|
||||||
function enrollNode() {
|
function enrollNode() {
|
||||||
enrollNodeService.modal();
|
enrollNodeService.modal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function refresh() {
|
||||||
|
init();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -15,11 +15,18 @@
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="8">
|
<th colspan="8">
|
||||||
<button class="btn btn-default btn-sm pull-right"
|
<div class="pull-right">
|
||||||
ng-click="table.enrollNode()">
|
<button class="btn btn-default btn-sm"
|
||||||
<span class="fa fa-plus"></span>
|
style="margin-right:10px;"
|
||||||
<span translate>Enroll Node</span>
|
ng-click="table.refresh()">
|
||||||
</button>
|
<span translate>Refresh</span>
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-default btn-sm"
|
||||||
|
ng-click="table.enrollNode()">
|
||||||
|
<span class="fa fa-plus"></span>
|
||||||
|
<span translate>Enroll Node</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th class="action-col">
|
<th class="action-col">
|
||||||
<action-list dropdown class="pull-right">
|
<action-list dropdown class="pull-right">
|
||||||
|
@ -117,7 +124,7 @@
|
||||||
<span ng-if="!node.instance_uuid">{$ 'No Instance' | translate $}</span>
|
<span ng-if="!node.instance_uuid">{$ 'No Instance' | translate $}</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="rsp-p2" >
|
<td class="rsp-p2" >
|
||||||
<div ng-class="{'running': node['target_power_state']}">
|
<div ng-class="{'running': node.target_power_state}">
|
||||||
{$ node.power_state $}
|
{$ node.power_state $}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
@ -130,32 +137,32 @@
|
||||||
<action button-type="split-button"
|
<action button-type="split-button"
|
||||||
action-classes="'btn btn-default btn-sm'"
|
action-classes="'btn btn-default btn-sm'"
|
||||||
callback="table.actions.powerOn"
|
callback="table.actions.powerOn"
|
||||||
disabled="node['power_state']!=='power off'"
|
disabled="node.power_state !== 'power off'"
|
||||||
item="node">
|
item="node">
|
||||||
{$ 'Power on' | translate $}
|
{$ 'Power on' | translate $}
|
||||||
</action>
|
</action>
|
||||||
<menu>
|
<menu>
|
||||||
<action button-type="menu-item"
|
<action button-type="menu-item"
|
||||||
callback="table.actions.powerOff"
|
callback="table.actions.powerOff"
|
||||||
disabled="node['power_state']!=='power on'"
|
disabled="node.power_state !== 'power on'"
|
||||||
item="node">
|
item="node">
|
||||||
{$ 'Power off' | translate $}
|
{$ 'Power off' | translate $}
|
||||||
</action>
|
</action>
|
||||||
<action button-type="menu-item"
|
<action button-type="menu-item"
|
||||||
callback="table.putNodeInMaintenanceMode"
|
callback="table.putNodeInMaintenanceMode"
|
||||||
disabled="node['maintenance']"
|
disabled="node.maintenance"
|
||||||
item="node">
|
item="node">
|
||||||
{$ 'Maintenance on' | translate $}
|
{$ 'Maintenance on' | translate $}
|
||||||
</action>
|
</action>
|
||||||
<action button-type="menu-item"
|
<action button-type="menu-item"
|
||||||
callback="table.removeNodeFromMaintenanceMode"
|
callback="table.removeNodeFromMaintenanceMode"
|
||||||
disabled="!node['maintenance']"
|
disabled="!node.maintenance"
|
||||||
item="node">
|
item="node">
|
||||||
{$ 'Maintenance off' | translate $}
|
{$ 'Maintenance off' | translate $}
|
||||||
</action>
|
</action>
|
||||||
<action button-type="menu-item"
|
<action button-type="menu-item"
|
||||||
callback="table.actions.deleteNode"
|
callback="table.actions.deleteNode"
|
||||||
disabled="!(node['provision_state']==='available' || node['provision_state']==='nostate' || node['provision_state']==='manageable' || node['provision_state']==='enroll')"
|
disabled="!(node.provision_state === 'available' || node.provision_state === 'nostate' || node.provision_state === 'manageable' || node.provision_state === 'enroll')"
|
||||||
item="node">
|
item="node">
|
||||||
<span class="fa fa-trash"></span>
|
<span class="fa fa-trash"></span>
|
||||||
{$ 'Delete node' | translate $}
|
{$ 'Delete node' | translate $}
|
||||||
|
@ -165,7 +172,19 @@
|
||||||
item="node">
|
item="node">
|
||||||
{$ 'Create port' | translate $}
|
{$ 'Create port' | translate $}
|
||||||
</action>
|
</action>
|
||||||
</menu>
|
<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>
|
||||||
</action-list>
|
</action-list>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
Loading…
Reference in New Issue