Merge "Add support for starting/stopping/accessing the serial console"
This commit is contained in:
commit
31d3897a20
@ -27,7 +27,6 @@ from openstack_dashboard.api import base
|
|||||||
DEFAULT_IRONIC_API_VERSION = '1.20'
|
DEFAULT_IRONIC_API_VERSION = '1.20'
|
||||||
DEFAULT_INSECURE = False
|
DEFAULT_INSECURE = False
|
||||||
DEFAULT_CACERT = None
|
DEFAULT_CACERT = None
|
||||||
|
|
||||||
IRONIC_CLIENT_CLASS_NAME = 'baremetal'
|
IRONIC_CLIENT_CLASS_NAME = 'baremetal'
|
||||||
|
|
||||||
|
|
||||||
@ -117,6 +116,31 @@ def node_set_provision_state(request, node_id, state, cleansteps=None):
|
|||||||
cleansteps=cleansteps)
|
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):
|
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.
|
||||||
|
|
||||||
@ -194,7 +218,7 @@ def node_get_boot_device(request, node_id):
|
|||||||
"""Get the boot device for a specified node.
|
"""Get the boot device for a specified node.
|
||||||
|
|
||||||
:param request: HTTP request.
|
: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"
|
: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
|
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)
|
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.
|
"""Update a specified port.
|
||||||
|
|
||||||
:param request: HTTP request.
|
: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
|
: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
|
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, ''))
|
return dict([(f, getattr(port, f, ''))
|
||||||
for f in res_fields.PORT_DETAILED_RESOURCE.fields])
|
for f in res_fields.PORT_DETAILED_RESOURCE.fields])
|
||||||
|
@ -177,6 +177,34 @@ class StatesProvision(generic.View):
|
|||||||
clean_steps)
|
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
|
@urls.register
|
||||||
class Maintenance(generic.View):
|
class Maintenance(generic.View):
|
||||||
|
|
||||||
|
@ -50,6 +50,8 @@
|
|||||||
getNodes: getNodes,
|
getNodes: getNodes,
|
||||||
getPortsWithNode: getPortsWithNode,
|
getPortsWithNode: getPortsWithNode,
|
||||||
getBootDevice: getBootDevice,
|
getBootDevice: getBootDevice,
|
||||||
|
nodeGetConsole: nodeGetConsole,
|
||||||
|
nodeSetConsoleMode: nodeSetConsoleMode,
|
||||||
powerOffNode: powerOffNode,
|
powerOffNode: powerOffNode,
|
||||||
powerOnNode: powerOnNode,
|
powerOnNode: powerOnNode,
|
||||||
putNodeInMaintenanceMode: putNodeInMaintenanceMode,
|
putNodeInMaintenanceMode: putNodeInMaintenanceMode,
|
||||||
@ -514,6 +516,44 @@
|
|||||||
return $q.reject(msg);
|
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.node = null;
|
||||||
ctrl.nodeValidation = [];
|
ctrl.nodeValidation = [];
|
||||||
|
ctrl.nodeValidationMap = {}; // Indexed by interface
|
||||||
ctrl.nodeStateTransitions = [];
|
ctrl.nodeStateTransitions = [];
|
||||||
ctrl.ports = [];
|
ctrl.ports = [];
|
||||||
ctrl.portsSrc = [];
|
ctrl.portsSrc = [];
|
||||||
@ -84,11 +85,14 @@
|
|||||||
ctrl.deletePort = deletePort;
|
ctrl.deletePort = deletePort;
|
||||||
ctrl.editPort = editPort;
|
ctrl.editPort = editPort;
|
||||||
ctrl.refresh = refresh;
|
ctrl.refresh = refresh;
|
||||||
|
ctrl.toggleConsoleMode = toggleConsoleMode;
|
||||||
|
|
||||||
$scope.emptyObject = function(obj) {
|
$scope.emptyObject = function(obj) {
|
||||||
return angular.isUndefined(obj) || Object.keys(obj).length === 0;
|
return angular.isUndefined(obj) || Object.keys(obj).length === 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.isDefined = angular.isDefined;
|
||||||
|
|
||||||
var editNodeHandler =
|
var editNodeHandler =
|
||||||
$rootScope.$on(ironicEvents.EDIT_NODE_SUCCESS,
|
$rootScope.$on(ironicEvents.EDIT_NODE_SUCCESS,
|
||||||
function() {
|
function() {
|
||||||
@ -149,6 +153,10 @@
|
|||||||
return ironic.getNode(uuid).then(function (node) {
|
return ironic.getNode(uuid).then(function (node) {
|
||||||
ctrl.node = node;
|
ctrl.node = node;
|
||||||
ctrl.node.id = ctrl.node.uuid;
|
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() {
|
function validateNode() {
|
||||||
ironic.validateNode(ctrl.node.uuid).then(function(response) {
|
ironic.validateNode(ctrl.node.uuid).then(function(response) {
|
||||||
var nodeValidation = [];
|
var nodeValidation = [];
|
||||||
|
ctrl.nodeValidationMap = {};
|
||||||
angular.forEach(response.data, function(status) {
|
angular.forEach(response.data, function(status) {
|
||||||
status.id = status.interface;
|
status.id = status.interface;
|
||||||
nodeValidation.push(status);
|
nodeValidation.push(status);
|
||||||
|
ctrl.nodeValidationMap[status.interface] = status;
|
||||||
});
|
});
|
||||||
ctrl.nodeValidation = nodeValidation;
|
ctrl.nodeValidation = nodeValidation;
|
||||||
});
|
});
|
||||||
@ -274,5 +284,15 @@
|
|||||||
function refresh() {
|
function refresh() {
|
||||||
init();
|
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">
|
callback="ctrl.editNode">
|
||||||
{$ ::'Edit' | translate $}
|
{$ ::'Edit' | translate $}
|
||||||
</action>
|
</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>
|
</menu>
|
||||||
</action-list>
|
</action-list>
|
||||||
</div>
|
</div>
|
||||||
|
@ -21,6 +21,16 @@
|
|||||||
<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>
|
||||||
|
<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>
|
</dl>
|
||||||
</div>
|
</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