Add support for starting/stopping/accessing the serial console
- The action menu in the node-details panel has a new item Enable|Disable console. - The node-details/overview panel has a new "Console info." item in the "General" section. The value of this field is dependent on the console type. For "shellinabox" the value is an anchor with the URL of the console and title "shellinabox". For others, the value is a string representation of the console_info object returned by the get_console api call. Closes-Bug: #1655690 Change-Id: Ibfa687f50d2251987276367d743ffb2a88e52796
This commit is contained in:
parent
327aa2022f
commit
6193569103
@ -27,7 +27,6 @@ from openstack_dashboard.api import base
|
||||
DEFAULT_IRONIC_API_VERSION = '1.20'
|
||||
DEFAULT_INSECURE = False
|
||||
DEFAULT_CACERT = None
|
||||
|
||||
IRONIC_CLIENT_CLASS_NAME = 'baremetal'
|
||||
|
||||
|
||||
@ -117,6 +116,31 @@ def node_set_provision_state(request, node_id, state, cleansteps=None):
|
||||
cleansteps=cleansteps)
|
||||
|
||||
|
||||
def node_set_console_mode(request, node_id, enabled):
|
||||
"""Start or stop the serial console for a given node.
|
||||
|
||||
:param request: HTTP request.
|
||||
:param node_id: The UUID or name of the node.
|
||||
:param enabled: True to start the console, False to stop it
|
||||
:return: node.
|
||||
|
||||
http://docs.openstack.org/developer/python-ironicclient/api/ironicclient.v1.node.html#ironicclient.v1.node.NodeManager.set_console_mode
|
||||
"""
|
||||
return ironicclient(request).node.set_console_mode(node_id, enabled)
|
||||
|
||||
|
||||
def node_get_console(request, node_id):
|
||||
"""Get connection information for a node's console.
|
||||
|
||||
:param request: HTTP request.
|
||||
:param node_id: The UUID or name of the node.
|
||||
:return: Console connection information
|
||||
|
||||
http://docs.openstack.org/developer/python-ironicclient/api/ironicclient.v1.node.html#ironicclient.v1.node.NodeManager.get_console
|
||||
"""
|
||||
return ironicclient(request).node.get_console(node_id)
|
||||
|
||||
|
||||
def node_set_maintenance(request, node_id, state, maint_reason=None):
|
||||
"""Set the maintenance mode on a given node.
|
||||
|
||||
@ -194,7 +218,7 @@ def node_get_boot_device(request, node_id):
|
||||
"""Get the boot device for a specified node.
|
||||
|
||||
:param request: HTTP request.
|
||||
:param node_id: The id of the node.
|
||||
:param node_id: The UUID or name of the node.
|
||||
:return: Dictionary with keys "boot_device" and "persistent"
|
||||
|
||||
http://docs.openstack.org/developer/python-ironicclient/api/ironicclient.v1.node.html#ironicclient.v1.node.NodeManager.get_boot_device
|
||||
@ -250,16 +274,16 @@ def port_delete(request, port_uuid):
|
||||
return ironicclient(request).port.delete(port_uuid)
|
||||
|
||||
|
||||
def port_update(request, port_id, patch):
|
||||
def port_update(request, port_uuid, patch):
|
||||
"""Update a specified port.
|
||||
|
||||
:param request: HTTP request.
|
||||
:param node_id: The uuid of the port.
|
||||
:param port_id: The UUID of the port.
|
||||
:param patch: Sequence of update operations
|
||||
:return: port.
|
||||
:return: Port.
|
||||
|
||||
http://docs.openstack.org/developer/python-ironicclient/api/ironicclient.v1.port.html#ironicclient.v1.port.PortManager.update
|
||||
"""
|
||||
port = ironicclient(request).port.update(port_id, patch)
|
||||
port = ironicclient(request).port.update(port_uuid, patch)
|
||||
return dict([(f, getattr(port, f, ''))
|
||||
for f in res_fields.PORT_DETAILED_RESOURCE.fields])
|
||||
|
@ -177,6 +177,34 @@ class StatesProvision(generic.View):
|
||||
clean_steps)
|
||||
|
||||
|
||||
@urls.register
|
||||
class StatesConsole(generic.View):
|
||||
|
||||
url_regex = r'ironic/nodes/(?P<node_uuid>[0-9a-f-]+)/states/console$'
|
||||
|
||||
@rest_utils.ajax()
|
||||
def get(self, request, node_uuid):
|
||||
"""Get connection information for the node's console
|
||||
|
||||
:param request: HTTP request.
|
||||
:param node_id: Node uuid
|
||||
:return: Connection information
|
||||
"""
|
||||
return ironic.node_get_console(request, node_uuid)
|
||||
|
||||
@rest_utils.ajax(data_required=True)
|
||||
def put(self, request, node_uuid):
|
||||
"""Start or stop the serial console.
|
||||
|
||||
:param request: HTTP request.
|
||||
:param node_id: Node uuid
|
||||
:return: Return code
|
||||
"""
|
||||
return ironic.node_set_console_mode(request,
|
||||
node_uuid,
|
||||
request.DATA.get('enabled'))
|
||||
|
||||
|
||||
@urls.register
|
||||
class Maintenance(generic.View):
|
||||
|
||||
|
@ -50,6 +50,8 @@
|
||||
getNodes: getNodes,
|
||||
getPortsWithNode: getPortsWithNode,
|
||||
getBootDevice: getBootDevice,
|
||||
nodeGetConsole: nodeGetConsole,
|
||||
nodeSetConsoleMode: nodeSetConsoleMode,
|
||||
powerOffNode: powerOffNode,
|
||||
powerOnNode: powerOnNode,
|
||||
putNodeInMaintenanceMode: putNodeInMaintenanceMode,
|
||||
@ -514,6 +516,44 @@
|
||||
return $q.reject(msg);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Set the console mode of the node.
|
||||
*
|
||||
* http://developer.openstack.org/api-ref/baremetal/?
|
||||
* expanded=start-stop-console-detail#start-stop-console
|
||||
*
|
||||
* @param {string} uuid – UUID of a node.
|
||||
* @param {boolean} enabled – true to start the console, false to stop it
|
||||
* @return {promise} Promise
|
||||
*/
|
||||
function nodeSetConsoleMode(uuid, enabled) {
|
||||
return apiService.put('/api/ironic/nodes/' + uuid + '/states/console',
|
||||
{enabled: enabled})
|
||||
.then(function(response) {
|
||||
var msg = gettext('Refresh page to see updated console details');
|
||||
toastService.add('success', interpolate(msg, [uuid], false));
|
||||
return response.data;
|
||||
})
|
||||
.catch(function(response) {
|
||||
var msg = gettext('Unable to set console mode: %s');
|
||||
toastService.add('error', interpolate(msg, [response.data], false));
|
||||
return $q.reject(msg);
|
||||
});
|
||||
}
|
||||
|
||||
function nodeGetConsole(uuid) {
|
||||
return apiService.get('/api/ironic/nodes/' + uuid + '/states/console')
|
||||
.then(function(response) {
|
||||
return response.data; // Object containing console information
|
||||
})
|
||||
.catch(function(response) {
|
||||
var msg = gettext('Unable to get console for node %s: %s');
|
||||
toastService.add('error',
|
||||
interpolate(msg, [uuid, response.data], false));
|
||||
return $q.reject(msg);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}());
|
||||
|
@ -72,6 +72,7 @@
|
||||
|
||||
ctrl.node = null;
|
||||
ctrl.nodeValidation = [];
|
||||
ctrl.nodeValidationMap = {}; // Indexed by interface
|
||||
ctrl.nodeStateTransitions = [];
|
||||
ctrl.ports = [];
|
||||
ctrl.portsSrc = [];
|
||||
@ -84,11 +85,14 @@
|
||||
ctrl.deletePort = deletePort;
|
||||
ctrl.editPort = editPort;
|
||||
ctrl.refresh = refresh;
|
||||
ctrl.toggleConsoleMode = toggleConsoleMode;
|
||||
|
||||
$scope.emptyObject = function(obj) {
|
||||
return angular.isUndefined(obj) || Object.keys(obj).length === 0;
|
||||
};
|
||||
|
||||
$scope.isDefined = angular.isDefined;
|
||||
|
||||
var editNodeHandler =
|
||||
$rootScope.$on(ironicEvents.EDIT_NODE_SUCCESS,
|
||||
function() {
|
||||
@ -149,6 +153,10 @@
|
||||
return ironic.getNode(uuid).then(function (node) {
|
||||
ctrl.node = node;
|
||||
ctrl.node.id = ctrl.node.uuid;
|
||||
ironic.nodeGetConsole(uuid).then(function(consoleData) {
|
||||
ctrl.node.console_enabled = consoleData.console_enabled;
|
||||
ctrl.node.console_info = consoleData.console_info;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -188,9 +196,11 @@
|
||||
function validateNode() {
|
||||
ironic.validateNode(ctrl.node.uuid).then(function(response) {
|
||||
var nodeValidation = [];
|
||||
ctrl.nodeValidationMap = {};
|
||||
angular.forEach(response.data, function(status) {
|
||||
status.id = status.interface;
|
||||
nodeValidation.push(status);
|
||||
ctrl.nodeValidationMap[status.interface] = status;
|
||||
});
|
||||
ctrl.nodeValidation = nodeValidation;
|
||||
});
|
||||
@ -274,5 +284,15 @@
|
||||
function refresh() {
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* @name horizon.dashboard.admin.ironic.NodeDetailsController.toggleConsoleMode
|
||||
* @description Toggle the state of the console for the current node
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function toggleConsoleMode() {
|
||||
ironic.nodeSetConsoleMode(ctrl.node.uuid, !ctrl.node.console_enabled);
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
@ -49,6 +49,12 @@
|
||||
callback="ctrl.editNode">
|
||||
{$ ::'Edit' | translate $}
|
||||
</action>
|
||||
<action button-type="menu-item"
|
||||
disabled="isDefined(ctrl.nodeValidationMap.console)
|
||||
&& ctrl.nodeValidationMap.console.result===false"
|
||||
callback="ctrl.toggleConsoleMode">
|
||||
{$ ctrl.node.console_enabled ? 'Disable console' : 'Enable console' | translate $}
|
||||
</action>
|
||||
</menu>
|
||||
</action-list>
|
||||
</div>
|
||||
|
@ -21,6 +21,16 @@
|
||||
<dd>{$ ctrl.node.reservation | noValue $}</dd>
|
||||
<dt translate>Console Enabled</dt>
|
||||
<dd>{$ ctrl.node.console_enabled | yesno $}</dd>
|
||||
<dt translate>Console Info</dt>
|
||||
<dd ng-if="ctrl.node.console_info.type==='shellinabox'">
|
||||
<a href="{$ ctrl.node.console_info.url $}"
|
||||
title="{$ 'Click link to view console' | translate $}">
|
||||
shellinabox
|
||||
</a>
|
||||
</dd>
|
||||
<dd ng-if="ctrl.node.console_info.type!=='shellinabox'">
|
||||
{$ ctrl.node.console_info | noValue $}
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
|
15
releasenotes/notes/add-console-support-ccffcedc845ca214.yaml
Normal file
15
releasenotes/notes/add-console-support-ccffcedc845ca214.yaml
Normal file
@ -0,0 +1,15 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Support has been added for starting, stopping, and accessing the
|
||||
console associated with a node.
|
||||
- |
|
||||
The action dropdown menu in the node-details panel has a new item
|
||||
``Enable|Disable console``.
|
||||
- |
|
||||
The node-details/overview panel has a new ``Console info`` item in the
|
||||
``General`` section. The value of this field is dependent on the console
|
||||
type. For ``shellinabox`` the value is an anchor with the URL required
|
||||
to access the web console and title ``shellinabox``. For others, the
|
||||
value is a string representation of the console_info object returned
|
||||
by the get_console api call.
|
Loading…
Reference in New Issue
Block a user