diff --git a/ironic_ui/api/ironic.py b/ironic_ui/api/ironic.py index 63221e07..d67a9345 100755 --- a/ironic_ui/api/ironic.py +++ b/ironic_ui/api/ironic.py @@ -190,6 +190,18 @@ def node_validate(request, node_id): return result +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. + :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 + """ + return ironicclient(request).node.get_boot_device(node_id) + + def driver_list(request): """Retrieve a list of drivers. diff --git a/ironic_ui/api/ironic_rest_api.py b/ironic_ui/api/ironic_rest_api.py index 5088388b..b1e6209c 100755 --- a/ironic_ui/api/ironic_rest_api.py +++ b/ironic_ui/api/ironic_rest_api.py @@ -224,6 +224,22 @@ class Validate(generic.View): return ironic.node_validate(request, node_id) +@urls.register +class BootDevice(generic.View): + + url_regex = r'ironic/nodes/(?P[0-9a-f-]+)/boot_device$' + + @rest_utils.ajax() + def get(self, request, node_id): + """Get the boot device for a specified node + + :param request: HTTP request. + :param node_id: Node name or uuid + :return: Dictionary with keys "boot_device" and "persistent" + """ + return ironic.node_get_boot_device(request, node_id) + + @urls.register class Drivers(generic.View): diff --git a/ironic_ui/static/dashboard/admin/ironic/ironic.service.js b/ironic_ui/static/dashboard/admin/ironic/ironic.service.js index 997dc271..454cc37a 100755 --- a/ironic_ui/static/dashboard/admin/ironic/ironic.service.js +++ b/ironic_ui/static/dashboard/admin/ironic/ironic.service.js @@ -49,6 +49,7 @@ getNode: getNode, getNodes: getNodes, getPortsWithNode: getPortsWithNode, + getBootDevice: getBootDevice, powerOffNode: powerOffNode, powerOnNode: powerOnNode, putNodeInMaintenanceMode: putNodeInMaintenanceMode, @@ -111,6 +112,28 @@ }); } + /** + * @description Retrieve the boot device for a node + * https://developer.openstack.org/api-ref/baremetal/#get-boot-device + * + * @param {string} uuid – UUID or logical name of a node. + * @return {promise} Dictionary describing the current boot device + */ + function getBootDevice(uuid) { + return apiService.get('/api/ironic/nodes/' + uuid + '/boot_device') + .then(function(response) { + return response.data; + }) + .catch(function(response) { + var msg = interpolate( + gettext('Unable to retrieve boot device for Ironic node. %s'), + [response.data], + false); + toastService.add('error', msg); + return $q.reject(msg); + }); + } + /** * @description Retrieve a list of ports associated with a node. * diff --git a/ironic_ui/static/dashboard/admin/ironic/node-details/node-details.controller.js b/ironic_ui/static/dashboard/admin/ironic/node-details/node-details.controller.js index 5c760a6a..b9f018ec 100755 --- a/ironic_ui/static/dashboard/admin/ironic/node-details/node-details.controller.js +++ b/ironic_ui/static/dashboard/admin/ironic/node-details/node-details.controller.js @@ -132,6 +132,7 @@ ctrl.nodeStateTransitions = nodeStateTransitionService.getTransitions(ctrl.node.provision_state); retrievePorts(); + retrieveBootDevice(); validateNode(); }); } @@ -164,6 +165,19 @@ }); } + /** + * @name horizon.dashboard.admin.ironic.NodeDetailsController.retrieveBootDevice + * @description Retrieve the boot device associated with the current node, + * and store it in the controller instance. + * + * @return {void} + */ + function retrieveBootDevice() { + ironic.getBootDevice(ctrl.node.uuid).then(function (bootDevice) { + ctrl.node.bootDevice = bootDevice; + }); + } + /** * @name horizon.dashboard.admin.ironic.NodeDetailsController.validateNode * @description Retrieve the ports associated with the current node, diff --git a/ironic_ui/static/dashboard/admin/ironic/node-details/node-details.controller.spec.js b/ironic_ui/static/dashboard/admin/ironic/node-details/node-details.controller.spec.js index 8fe5095f..8a252214 100755 --- a/ironic_ui/static/dashboard/admin/ironic/node-details/node-details.controller.spec.js +++ b/ironic_ui/static/dashboard/admin/ironic/node-details/node-details.controller.spec.js @@ -22,6 +22,7 @@ var nodeUuid = "0123abcd-0123-4567-abcd-0123456789ab"; var nodeName = "herp"; var numPorts = 2; + var bootDevice = {boot_device: 'pxe', persistent: true}; function portUuid(nodeUuid, index) { return '' + index + index + nodeUuid.substring(2); @@ -66,6 +67,10 @@ return $q.when(ports); }, + getBootDevice: function () { + return $q.when(bootDevice); + }, + validateNode: function() { return $q.when({}); } @@ -125,6 +130,7 @@ expect(ctrl.node).toBeDefined(); var node = createNode(nodeName, nodeUuid); node.id = node.uuid; + node.bootDevice = bootDevice; expect(ctrl.node).toEqual(node); }); @@ -170,5 +176,10 @@ expect(ctrl.nodeValidation).toBeDefined(); expect(ctrl.nodeValidation).toEqual([]); }); + + it('should have a boot device', function () { + expect(ctrl.node.bootDevice).toBeDefined(); + expect(ctrl.node.bootDevice).toEqual(bootDevice); + }); }); })(); diff --git a/ironic_ui/static/dashboard/admin/ironic/node-details/sections/configuration.html b/ironic_ui/static/dashboard/admin/ironic/node-details/sections/configuration.html index f34be246..dc67af90 100644 --- a/ironic_ui/static/dashboard/admin/ironic/node-details/sections/configuration.html +++ b/ironic_ui/static/dashboard/admin/ironic/node-details/sections/configuration.html @@ -267,6 +267,18 @@ + + +
+

Boot Device

+
+
+
Device
+
{$ ctrl.node.bootDevice.boot_device | noValue $}
+
Persistent
+
{$ ctrl.node.bootDevice.persistent | noValue $}
+
+
diff --git a/releasenotes/notes/bug-1671567-a95d7cb0d21470e4.yaml b/releasenotes/notes/bug-1671567-a95d7cb0d21470e4.yaml new file mode 100644 index 00000000..e735ae0b --- /dev/null +++ b/releasenotes/notes/bug-1671567-a95d7cb0d21470e4.yaml @@ -0,0 +1,4 @@ +--- +features: + - | + The Node Details/Configuration tab now shows the node's boot device.