summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.openstack.org>2018-01-03 14:22:36 +0000
committerGerrit Code Review <review@openstack.org>2018-01-03 14:22:36 +0000
commit77beab6cc4e57330bd0990d3b481887e290ee953 (patch)
tree57602109e2be430e2b24a9191f640894571aa471
parenta368c4cdf67b61b593bbd35cbd3897bdcd7adcd9 (diff)
parent2e9c34b4cc6d41b3d84c00b80658c14a62d27670 (diff)
Merge "Added support for injecting non-maskable interrupts"
-rwxr-xr-xironic_ui/api/ironic.py12
-rwxr-xr-xironic_ui/api/ironic_rest_api.py17
-rw-r--r--ironic_ui/static/dashboard/admin/ironic/ironic.backend-mock.service.js18
-rwxr-xr-xironic_ui/static/dashboard/admin/ironic/ironic.service.js21
-rw-r--r--ironic_ui/static/dashboard/admin/ironic/ironic.service.spec.js21
-rwxr-xr-xironic_ui/static/dashboard/admin/ironic/node-details/node-details.controller.js11
-rwxr-xr-xironic_ui/static/dashboard/admin/ironic/node-details/node-details.controller.spec.js13
-rw-r--r--ironic_ui/static/dashboard/admin/ironic/node-details/node-details.html8
-rw-r--r--releasenotes/notes/inject-nmi-0320453eaf1bda9b.yaml6
9 files changed, 127 insertions, 0 deletions
diff --git a/ironic_ui/api/ironic.py b/ironic_ui/api/ironic.py
index c93a0e7..66af176 100755
--- a/ironic_ui/api/ironic.py
+++ b/ironic_ui/api/ironic.py
@@ -259,6 +259,18 @@ def node_get_supported_boot_devices(request, node_id):
259 return result.get('supported_boot_devices', []) 259 return result.get('supported_boot_devices', [])
260 260
261 261
262def node_inject_nmi(request, node_id):
263 """Inject Non-Masking Interrupts into a specified node.
264
265 :param request: HTTP request.
266 :param node_id: The UUID or name of the node.
267 :return: Empty response.
268
269 http://docs.openstack.org/developer/python-ironicclient/api/ironicclient.v1.node.html#ironicclient.v1.node.NodeManager.inject_nmi
270 """
271 return ironicclient(request).node.inject_nmi(node_id)
272
273
262def driver_list(request): 274def driver_list(request):
263 """Retrieve a list of drivers. 275 """Retrieve a list of drivers.
264 276
diff --git a/ironic_ui/api/ironic_rest_api.py b/ironic_ui/api/ironic_rest_api.py
index a75325e..e7e6d44 100755
--- a/ironic_ui/api/ironic_rest_api.py
+++ b/ironic_ui/api/ironic_rest_api.py
@@ -467,3 +467,20 @@ class DriverDetails(generic.View):
467 :return: Dictionary of details 467 :return: Dictionary of details
468 """ 468 """
469 return ironic.driver_details(request, driver_name) 469 return ironic.driver_details(request, driver_name)
470
471
472@urls.register
473class InjectNmi(generic.View):
474
475 url_regex = r'ironic/nodes/(?P<node_id>{})/management/inject_nmi$'. \
476 format(LOGICAL_NAME_PATTERN)
477
478 @rest_utils.ajax(data_required=True)
479 def put(self, request, node_id):
480 """Inject Non-Masking Interrupts into a specified node.
481
482 :param request: HTTP request.
483 :param node_id: Node name or uuid.
484 :return: Empty response.
485 """
486 return ironic.node_inject_nmi(request, node_id)
diff --git a/ironic_ui/static/dashboard/admin/ironic/ironic.backend-mock.service.js b/ironic_ui/static/dashboard/admin/ironic/ironic.backend-mock.service.js
index 9e1b16c..7aa2db2 100644
--- a/ironic_ui/static/dashboard/admin/ironic/ironic.backend-mock.service.js
+++ b/ironic_ui/static/dashboard/admin/ironic/ironic.backend-mock.service.js
@@ -662,6 +662,24 @@
662 return [status, null]; 662 return [status, null];
663 }); 663 });
664 664
665 // Inject NMI
666 $httpBackend.whenPUT(/\/api\/ironic\/nodes\/(.+)\/management\/inject_nmi/,
667 undefined,
668 undefined,
669 ['nodeId'])
670 .respond(function(method, url, data, headers, params) {
671 var status, response;
672 if (angular.isDefined(nodes[params.nodeId])) {
673 status = responseCode.EMPTY_RESPONSE;
674 response = '';
675 } else {
676 status = responseCode.INTERNAL_SERVER_ERROR;
677 response = 'Node ' + params.nodeId +
678 ' could not be found. (HTTP 404)';
679 }
680 return [status, response];
681 });
682
665 // Validate the interfaces associated with a specified node 683 // Validate the interfaces associated with a specified node
666 $httpBackend.whenGET(/\/api\/ironic\/nodes\/([^\/]+)\/validate$/, 684 $httpBackend.whenGET(/\/api\/ironic\/nodes\/([^\/]+)\/validate$/,
667 undefined, 685 undefined,
diff --git a/ironic_ui/static/dashboard/admin/ironic/ironic.service.js b/ironic_ui/static/dashboard/admin/ironic/ironic.service.js
index 87bdbc1..6e79ad7 100755
--- a/ironic_ui/static/dashboard/admin/ironic/ironic.service.js
+++ b/ironic_ui/static/dashboard/admin/ironic/ironic.service.js
@@ -53,6 +53,7 @@
53 getPortsWithNode: getPortsWithNode, 53 getPortsWithNode: getPortsWithNode,
54 getBootDevice: getBootDevice, 54 getBootDevice: getBootDevice,
55 getSupportedBootDevices: getSupportedBootDevices, 55 getSupportedBootDevices: getSupportedBootDevices,
56 injectNmi: injectNmi,
56 nodeGetConsole: nodeGetConsole, 57 nodeGetConsole: nodeGetConsole,
57 nodeSetConsoleMode: nodeSetConsoleMode, 58 nodeSetConsoleMode: nodeSetConsoleMode,
58 nodeSetMaintenance: nodeSetMaintenance, 59 nodeSetMaintenance: nodeSetMaintenance,
@@ -355,6 +356,26 @@
355 } 356 }
356 357
357 /** 358 /**
359 * @description Inject Non-Masking Interrupts into a specified node
360 *
361 * http://developer.openstack.org/api-ref/baremetal/#inject-nmi
362 *
363 * @param {string} nodeId – UUID or logical name of a node.
364 * @return {promise} Promise. No content on success.
365 */
366 function injectNmi(nodeId) {
367 return apiService.put('/api/ironic/nodes/' + nodeId +
368 '/management/inject_nmi')
369 .catch(function(response) {
370 var msg = interpolate(gettext('Unable to inject NMI: %s'),
371 [response.data],
372 false);
373 toastService.add('error', msg);
374 return $q.reject(msg);
375 });
376 }
377
378 /**
358 * @description Create an Ironic node 379 * @description Create an Ironic node
359 * 380 *
360 * http://developer.openstack.org/api-ref/baremetal/#create-node 381 * http://developer.openstack.org/api-ref/baremetal/#create-node
diff --git a/ironic_ui/static/dashboard/admin/ironic/ironic.service.spec.js b/ironic_ui/static/dashboard/admin/ironic/ironic.service.spec.js
index ce833f1..7ed820a 100644
--- a/ironic_ui/static/dashboard/admin/ironic/ironic.service.spec.js
+++ b/ironic_ui/static/dashboard/admin/ironic/ironic.service.spec.js
@@ -34,6 +34,7 @@
34 'getPortsWithNode', 34 'getPortsWithNode',
35 'getBootDevice', 35 'getBootDevice',
36 'getSupportedBootDevices', 36 'getSupportedBootDevices',
37 'injectNmi',
37 'nodeGetConsole', 38 'nodeGetConsole',
38 'nodeSetBootDevice', 39 'nodeSetBootDevice',
39 'nodeSetConsoleMode', 40 'nodeSetConsoleMode',
@@ -662,6 +663,26 @@
662 ironicBackendMockService.flush(); 663 ironicBackendMockService.flush();
663 }); 664 });
664 665
666 it('injectNmi', function() {
667 createNode({driver: defaultDriver})
668 .then(function(node) {
669 return ironicAPI.injectNmi(node.uuid);
670 })
671 .then(function(response) {
672 expect(response.status).toBe(204);
673 expect(response.data).toBe('');
674 })
675 .catch(failTest);
676
677 ironicBackendMockService.flush();
678 });
679
680 it('injectNmi - nonexistent node', function() {
681 ironicAPI.injectNmi(0)
682 .then(failTest);
683
684 ironicBackendMockService.flush();
685 });
665 }); 686 });
666 }); 687 });
667})(); 688})();
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 25e59b3..25b9ac3 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
@@ -104,6 +104,7 @@
104 ctrl.refresh = refresh; 104 ctrl.refresh = refresh;
105 ctrl.toggleConsoleMode = toggleConsoleMode; 105 ctrl.toggleConsoleMode = toggleConsoleMode;
106 ctrl.deletePortgroups = deletePortgroups; 106 ctrl.deletePortgroups = deletePortgroups;
107 ctrl.injectNmi = injectNmi;
107 108
108 $scope.emptyObject = function(obj) { 109 $scope.emptyObject = function(obj) {
109 return angular.isUndefined(obj) || Object.keys(obj).length === 0; 110 return angular.isUndefined(obj) || Object.keys(obj).length === 0;
@@ -353,5 +354,15 @@
353 ctrl.refresh(); 354 ctrl.refresh();
354 }); 355 });
355 } 356 }
357
358 /**
359 * @name horizon.dashboard.admin.ironic.NodeDetailsController.injectNmi
360 * @description Inject non-masking interrupts into the current node
361 *
362 * @return {void}
363 */
364 function injectNmi() {
365 ironic.injectNmi(ctrl.node.uuid);
366 }
356 } 367 }
357})(); 368})();
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 abe2aed..0592c06 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
@@ -255,5 +255,18 @@
255 expect(ctrl.node['' + interfaceName + '_interface']).toBeDefined(); 255 expect(ctrl.node['' + interfaceName + '_interface']).toBeDefined();
256 expect(ctrl.nodeValidation[0].hw_interface).toEqual(hwInterface); 256 expect(ctrl.nodeValidation[0].hw_interface).toEqual(hwInterface);
257 }); 257 });
258
259 it('should have injectNmi', function () {
260 var ctrl;
261 createNode()
262 .then(function(node) {
263 ctrl = createController(node);
264 })
265 .catch(function() {
266 fail();
267 });
268 ironicBackendMockService.flush();
269 expect(ctrl.injectNmi).toBeDefined();
270 });
258 }); 271 });
259})(); 272})();
diff --git a/ironic_ui/static/dashboard/admin/ironic/node-details/node-details.html b/ironic_ui/static/dashboard/admin/ironic/node-details/node-details.html
index e8e3eb9..55890df 100644
--- a/ironic_ui/static/dashboard/admin/ironic/node-details/node-details.html
+++ b/ironic_ui/static/dashboard/admin/ironic/node-details/node-details.html
@@ -70,6 +70,14 @@
70 callback="ctrl.toggleConsoleMode"> 70 callback="ctrl.toggleConsoleMode">
71 {$ ctrl.node.console_enabled ? 'Disable console' : 'Enable console' | translate $} 71 {$ ctrl.node.console_enabled ? 'Disable console' : 'Enable console' | translate $}
72 </action> 72 </action>
73 <li role="presentation">
74 <a role="menuitem"
75 ng-click="ctrl.injectNmi();
76 $event.stopPropagation();
77 $event.preventDefault()">
78 <span>{$ "Inject NMI" | translate $}</span>
79 </a>
80 </li>
73 </menu> 81 </menu>
74 </action-list> 82 </action-list>
75 </div> 83 </div>
diff --git a/releasenotes/notes/inject-nmi-0320453eaf1bda9b.yaml b/releasenotes/notes/inject-nmi-0320453eaf1bda9b.yaml
new file mode 100644
index 0000000..d1c1d49
--- /dev/null
+++ b/releasenotes/notes/inject-nmi-0320453eaf1bda9b.yaml
@@ -0,0 +1,6 @@
1---
2features:
3 - |
4 Adds support for injecting non-maskable interrupts into a node. A new
5 action ``Inject NMI`` has been added to the node actions dropdown menu
6 in the ``Node Details`` page.