From 04973a788d912a443f194d48ef260aa380007d74 Mon Sep 17 00:00:00 2001 From: Peter Piela Date: Tue, 19 Jul 2016 16:39:24 -0400 Subject: [PATCH] Added support for creating/deleting network ports Network ports can be created in both the node list and node detail pages. Network ports can be deleted from the the node detail page. Change-Id: I3047a0adef9df58aaabd0f2d99a09351233fa06b --- ironic_ui/api/ironic.py | 21 ++++ ironic_ui/api/ironic_rest_api.py | 19 ++++ .../admin/ironic/auto-focus.directive.js | 35 ++++++ .../create-port/create-port.controller.js | 95 +++++++++++++++++ .../admin/ironic/create-port/create-port.html | 90 ++++++++++++++++ .../ironic/create-port/create-port.service.js | 49 +++++++++ .../enroll-node/enroll-node.controller.js | 4 +- .../dashboard/admin/ironic/ironic.module.js | 12 ++- .../dashboard/admin/ironic/ironic.service.js | 67 +++++++++--- .../admin/ironic/node-actions.service.js | 67 +++++++++++- .../node-details/node-details.controller.js | 97 +++++++++++++++-- .../node-details/sections/configuration.html | 100 +++++++++++++++--- .../ironic/node-list/node-list.controller.js | 14 ++- .../admin/ironic/node-list/node-list.html | 7 +- 14 files changed, 632 insertions(+), 45 deletions(-) create mode 100644 ironic_ui/static/dashboard/admin/ironic/auto-focus.directive.js create mode 100644 ironic_ui/static/dashboard/admin/ironic/create-port/create-port.controller.js create mode 100644 ironic_ui/static/dashboard/admin/ironic/create-port/create-port.html create mode 100644 ironic_ui/static/dashboard/admin/ironic/create-port/create-port.service.js diff --git a/ironic_ui/api/ironic.py b/ironic_ui/api/ironic.py index 4c87b525..5aaaedcc 100755 --- a/ironic_ui/api/ironic.py +++ b/ironic_ui/api/ironic.py @@ -166,3 +166,24 @@ def driver_properties(request, driver_name): :return: Property list """ return ironicclient(request).driver.properties(driver_name) + + +def port_create(request, params): + """Create network port + + :param request: HTTP request + :param params: Port creation parameters + :return: Port + """ + port_manager = ironicclient(request).port + return port_manager.create(**params) + + +def port_delete(request, port_uuid): + """Delete a network port + + :param request: HTTP request + :param port_uuid: Port uuid + :return: Port + """ + return ironicclient(request).port.delete(port_uuid) diff --git a/ironic_ui/api/ironic_rest_api.py b/ironic_ui/api/ironic_rest_api.py index eedf0886..d27b9fae 100755 --- a/ironic_ui/api/ironic_rest_api.py +++ b/ironic_ui/api/ironic_rest_api.py @@ -93,6 +93,25 @@ class Ports(generic.View): 'items': [i.to_dict() for i in items], } + @rest_utils.ajax(data_required=True) + def post(self, request): + """Create a network port + + :param request: HTTP request + :return: Port + """ + port = request.DATA.get('port') + return ironic.port_create(request, port).to_dict() + + @rest_utils.ajax(data_required=True) + def delete(self, request): + """Delete a network port + + :param request: HTTP request + """ + params = request.DATA.get('port_uuid') + return ironic.port_delete(request, params) + @urls.register class StatesPower(generic.View): diff --git a/ironic_ui/static/dashboard/admin/ironic/auto-focus.directive.js b/ironic_ui/static/dashboard/admin/ironic/auto-focus.directive.js new file mode 100644 index 00000000..6ff13c38 --- /dev/null +++ b/ironic_ui/static/dashboard/admin/ironic/auto-focus.directive.js @@ -0,0 +1,35 @@ +/* + * Copyright 2016 Cray Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +(function () { + 'use strict'; + + angular + .module('horizon.dashboard.admin.ironic') + .directive('autoFocus', AutoFocus); + + AutoFocus.$inject = ['$timeout']; + + function AutoFocus($timeout) { + return { + restrict: 'AC', + link: function(scope, elem) { + $timeout(function() { + elem[0].focus(); + }, 1000); + } + }; + } +})(); diff --git a/ironic_ui/static/dashboard/admin/ironic/create-port/create-port.controller.js b/ironic_ui/static/dashboard/admin/ironic/create-port/create-port.controller.js new file mode 100644 index 00000000..03c2dbfb --- /dev/null +++ b/ironic_ui/static/dashboard/admin/ironic/create-port/create-port.controller.js @@ -0,0 +1,95 @@ +/* + * Copyright 2016 Cray Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +(function() { + 'use strict'; + + /** + * Controller used to create a network port on a specified node + */ + angular + .module('horizon.dashboard.admin.ironic') + .controller('CreatePortController', CreatePortController); + + CreatePortController.$inject = [ + '$rootScope', + '$modalInstance', + 'horizon.app.core.openstack-service-api.ironic', + 'horizon.dashboard.admin.ironic.events', + '$log', + 'node' + ]; + + function CreatePortController($rootScope, + $modalInstance, + ironic, + ironicEvents, + $log, + node) { + var ctrl = this; + + // Paramater object that defines the port to be created + ctrl.port = { + node_uuid: node.id, + address: null, + extra: {} + }; + + /** + * Cancel the port creation process + * + * @return {void} + */ + ctrl.cancel = function() { + $modalInstance.dismiss('cancel'); + }; + + /** + * Create the defined port + * + * @return {void} + */ + ctrl.createPort = function() { + ironic.createPort(ctrl.port).then( + function() { + $modalInstance.close(); + $rootScope.$emit(ironicEvents.CREATE_PORT_SUCCESS); + }, + function() { + }); + }; + + /** + * Delete a port metadata property + * + * @param {string} propertyName - Name of the property + * @return {void} + */ + ctrl.deleteExtra = function(propertyName) { + delete ctrl.port.extra[propertyName]; + }; + + /** + * Check whether the specified port metadata property already exists + * + * @param {string} propertyName - Name of the metadata property + * @return {boolean} True if the property already exists, + * otherwise false + */ + ctrl.checkExtraUnique = function(propertyName) { + return !(propertyName in ctrl.port.extra); + }; + } +})(); diff --git a/ironic_ui/static/dashboard/admin/ironic/create-port/create-port.html b/ironic_ui/static/dashboard/admin/ironic/create-port/create-port.html new file mode 100644 index 00000000..1da80a2c --- /dev/null +++ b/ironic_ui/static/dashboard/admin/ironic/create-port/create-port.html @@ -0,0 +1,90 @@ + + + + diff --git a/ironic_ui/static/dashboard/admin/ironic/create-port/create-port.service.js b/ironic_ui/static/dashboard/admin/ironic/create-port/create-port.service.js new file mode 100644 index 00000000..618f4bb7 --- /dev/null +++ b/ironic_ui/static/dashboard/admin/ironic/create-port/create-port.service.js @@ -0,0 +1,49 @@ +/* + * Copyright 2016 Cray Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +(function() { + 'use strict'; + + angular + .module('horizon.dashboard.admin.ironic') + .factory('horizon.dashboard.admin.ironic.create-port.service', + createPortService); + + createPortService.$inject = [ + '$modal', + 'horizon.dashboard.admin.basePath' + ]; + + function createPortService($modal, basePath) { + var service = { + modal: modal + }; + return service; + + function modal(node) { + var options = { + controller: 'CreatePortController as ctrl', + backdrop: 'static', + resolve: { + node: function() { + return node; + } + }, + templateUrl: basePath + '/ironic/create-port/create-port.html' + }; + return $modal.open(options); + } + } +})(); diff --git a/ironic_ui/static/dashboard/admin/ironic/enroll-node/enroll-node.controller.js b/ironic_ui/static/dashboard/admin/ironic/enroll-node/enroll-node.controller.js index 55fdb335..5102f691 100644 --- a/ironic_ui/static/dashboard/admin/ironic/enroll-node/enroll-node.controller.js +++ b/ironic_ui/static/dashboard/admin/ironic/enroll-node/enroll-node.controller.js @@ -27,6 +27,7 @@ '$rootScope', '$modalInstance', 'horizon.app.core.openstack-service-api.ironic', + 'horizon.dashboard.admin.ironic.events', 'horizon.app.core.openstack-service-api.glance', 'horizon.dashboard.admin.ironic.enroll-node.service', 'horizon.dashboard.admin.ironic.validHostNamePattern', @@ -36,6 +37,7 @@ function EnrollNodeController($rootScope, $modalInstance, ironic, + ironicEvents, glance, enrollNodeService, validHostNamePattern, @@ -276,7 +278,7 @@ ironic.createNode(ctrl.node).then( function() { $modalInstance.close(); - $rootScope.$emit('ironic-ui:new-node'); + $rootScope.$emit(ironicEvents.ENROLL_NODE_SUCCESS); }, function() { // No additional error processing for now diff --git a/ironic_ui/static/dashboard/admin/ironic/ironic.module.js b/ironic_ui/static/dashboard/admin/ironic/ironic.module.js index 2fc0946b..a85bf6c7 100755 --- a/ironic_ui/static/dashboard/admin/ironic/ironic.module.js +++ b/ironic_ui/static/dashboard/admin/ironic/ironic.module.js @@ -31,6 +31,16 @@ '^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$') // eslint-disable-line max-len .constant('horizon.dashboard.admin.ironic.validUuidPattern', - '^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$'); // eslint-disable-line max-len + '^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$') // eslint-disable-line max-len + .constant('horizon.dashboard.admin.ironic.events', events()); + + function events() { + return { + ENROLL_NODE_SUCCESS:'horizon.dashboard.admin.ironic.ENROLL_NODE_SUCCESS', + DELETE_NODE_SUCCESS:'horizon.dashboard.admin.ironic.DELETE_NODE_SUCCESS', + CREATE_PORT_SUCCESS:'horizon.dashboard.admin.ironic.CREATE_PORT_SUCCESS', + DELETE_PORT_SUCCESS:'horizon.dashboard.admin.ironic.DELETE_PORT_SUCCESS' + }; + } })(); diff --git a/ironic_ui/static/dashboard/admin/ironic/ironic.service.js b/ironic_ui/static/dashboard/admin/ironic/ironic.service.js index ab13eef0..ee98ba09 100755 --- a/ironic_ui/static/dashboard/admin/ironic/ironic.service.js +++ b/ironic_ui/static/dashboard/admin/ironic/ironic.service.js @@ -28,7 +28,7 @@ ]; /** - * Service that provides access to the Ironic client API + * @description Service that provides access to the Ironic client API * * @param {object} apiService - HTTP service * @param {object} toastService - User message service @@ -37,7 +37,9 @@ function ironicAPI(apiService, toastService) { var service = { createNode: createNode, + createPort: createPort, deleteNode: deleteNode, + deletePort: deletePort, getDrivers: getDrivers, getDriverProperties: getDriverProperties, getNode: getNode, @@ -52,7 +54,7 @@ return service; /** - * Retrieve a list of nodes + * @description Retrieve a list of nodes * http://docs.openstack.org/developer/ironic/webapi/v1.html#get--v1-nodes * * @return {promise} Node collection in JSON @@ -67,7 +69,7 @@ } /** - * Retrieve information about the given node. + * @description Retrieve information about the given node. * * http://docs.openstack.org/developer/ironic/webapi/v1.html#get--v1- * nodes-(node_ident) @@ -84,7 +86,7 @@ } /** - * Retrieve a list of ports associated with a node. + * @description Retrieve a list of ports associated with a node. * * http://docs.openstack.org/developer/ironic/webapi/v1.html#get--v1-ports * @@ -106,7 +108,7 @@ } /** - * Put the node in maintenance mode. + * @description Put the node in maintenance mode. * * http://docs.openstack.org/developer/ironic/webapi/v1.html# * put--v1-nodes-(node_ident)-maintenance @@ -130,7 +132,7 @@ } /** - * Remove the node from maintenance mode. + * @description Remove the node from maintenance mode. * * http://docs.openstack.org/developer/ironic/webapi/v1.html# * delete--v1-nodes-(node_ident)-maintenance @@ -148,7 +150,7 @@ } /** - * Set the power state of the node. + * @description Set the power state of the node. * * http://docs.openstack.org/developer/ironic/webapi/v1.html# * put--v1-nodes-(node_ident)-states-power @@ -173,7 +175,7 @@ } /** - * Set the power state of the node. + * @description Set the power state of the node. * * http://docs.openstack.org/developer/ironic/webapi/v1.html# * put--v1-nodes-(node_ident)-states-power @@ -198,7 +200,7 @@ } /** - * Create an Ironic node + * @description Create an Ironic node * * http://docs.openstack.org/developer/ironic/webapi/v1.html#post--v1-nodes * @@ -220,7 +222,7 @@ } /** - * Delete the specified node from inventory + * @description Delete the specified node from inventory * * http://docs.openstack.org/developer/ironic/webapi/v1.html# * delete--v1-nodes @@ -244,7 +246,7 @@ } /** - * Retrieve the list of Ironic drivers + * @description Retrieve the list of Ironic drivers * * http://docs.openstack.org/developer/ironic/webapi/v1.html#get--v1-drivers * @@ -259,7 +261,7 @@ } /** - * Retrieve properities of a specified driver + * @description Retrieve properities of a specified driver * * http://docs.openstack.org/developer/ironic/webapi/v1.html# * get--v1-drivers-properties @@ -276,6 +278,47 @@ toastService.add('error', interpolate(msg, [reason], false)); }); } + + /** + * @description Create a network port + * + * @param {object} port – Object containing parameters that define + * the port to be created + * @return {promise} Promise + */ + function createPort(port) { + var data = { + port: port + }; + return apiService.post('/api/ironic/ports/', data) + .success(function() { + toastService.add('success', + gettext('Port successfully created')); + }) + .error(function(reason) { + var msg = gettext('Unable to create port: %s'); + toastService.add('error', interpolate(msg, [reason], false)); + }); + } + + /** + * @description Delete a network port + * + * @param {string} portUuid – UUID of the port to be deleted + * @return {promise} Promise + */ + function deletePort(portUuid) { + var data = { + port_uuid: portUuid + }; + return apiService.delete('/api/ironic/ports/', data) + .success(function() { + }) + .error(function(reason) { + var msg = gettext('Unable to delete port: %s'); + toastService.add('error', interpolate(msg, [reason], false)); + }); + } } }()); diff --git a/ironic_ui/static/dashboard/admin/ironic/node-actions.service.js b/ironic_ui/static/dashboard/admin/ironic/node-actions.service.js index dcddd803..b3d62db5 100755 --- a/ironic_ui/static/dashboard/admin/ironic/node-actions.service.js +++ b/ironic_ui/static/dashboard/admin/ironic/node-actions.service.js @@ -34,6 +34,20 @@ var DELETE_NODES_SUCCESS = gettext('Successfully deleted nodes "%s"'); var DELETE_NODES_ERROR = gettext('Error deleting nodes "%s"'); + var DELETE_PORT_TITLE = gettext("Delete Port"); + var DELETE_PORT_MSG = + gettext('Are you sure you want to delete port "%s"? ' + + 'This action cannot be undone.'); + var DELETE_PORT_SUCCESS = gettext('Successfully deleted port "%s"'); + var DELETE_PORT_ERROR = gettext('Unable to delete port "%s"'); + + var DELETE_PORTS_TITLE = gettext("Delete Ports"); + var DELETE_PORTS_MSG = + gettext('Are you sure you want to delete ports "%s"? ' + + 'This action cannot be undone.'); + var DELETE_PORTS_SUCCESS = gettext('Successfully deleted ports "%s"'); + var DELETE_PORTS_ERROR = gettext('Error deleting ports "%s"'); + angular .module('horizon.dashboard.admin.ironic') .factory('horizon.dashboard.admin.ironic.actions', actions); @@ -41,15 +55,26 @@ actions.$inject = [ 'horizon.app.core.openstack-service-api.ironic', 'horizon.framework.widgets.toast.service', + 'horizon.dashboard.admin.ironic.events', 'horizon.framework.widgets.modal.deleteModalService', + 'horizon.dashboard.admin.ironic.create-port.service', '$q', '$rootScope' ]; - function actions(ironic, toastService, deleteModalService, $q, $rootScope) { + function actions(ironic, + toastService, + ironicEvents, + deleteModalService, + createPortService, + $q, + $rootScope) { var service = { + createPort: createPort, deleteNode: deleteNode, deleteNodes: deleteNodes, + deletePort: deletePort, + deletePorts: deletePorts, powerOn: powerOn, powerOff: powerOff, powerOnAll: powerOnNodes, @@ -73,7 +98,7 @@ var context = { labels: labels, deleteEntity: ironic.deleteNode, - successEvent: "ironic-ui:delete-node-success" + successEvent: ironicEvents.DELETE_NODE_SUCCESS }; return deleteModalService.open($rootScope, [node], context); } @@ -89,7 +114,7 @@ var context = { labels: labels, deleteEntity: ironic.deleteNode, - successEvent: "ironic-ui:delete-node-success" + successEvent: ironicEvents.DELETE_NODE_SUCCESS }; return deleteModalService.open($rootScope, nodes, context); } @@ -166,6 +191,42 @@ return applyFuncToNodes(removeFromMaintenanceMode, nodes); } + function createPort(node) { + return createPortService.modal(node); + } + + function deletePort(port) { + var labels = { + title: DELETE_PORT_TITLE, + message: DELETE_PORT_MSG, + submit: DELETE_PORT_TITLE, + success: DELETE_PORT_SUCCESS, + error: DELETE_PORT_ERROR + }; + var context = { + labels: labels, + deleteEntity: ironic.deletePort, + successEvent: ironicEvents.DELETE_PORT_SUCCESS + }; + return deleteModalService.open($rootScope, [port], context); + } + + function deletePorts(ports) { + var labels = { + title: DELETE_PORTS_TITLE, + message: DELETE_PORTS_MSG, + submit: DELETE_PORTS_TITLE, + success: DELETE_PORTS_SUCCESS, + error: DELETE_PORTS_ERROR + }; + var context = { + labels: labels, + deleteEntity: ironic.deletePort, + successEvent: ironicEvents.DELETE_PORT_SUCCESS + }; + return deleteModalService.open($rootScope, ports, context); + } + /* * @name horizon.dashboard.admin.ironic.actions.applyFuncToNodes * @description Apply a specified function to each member of a 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 bc51d404..4c3f705f 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 @@ -23,21 +23,31 @@ IronicNodeDetailsController); IronicNodeDetailsController.$inject = [ + '$scope', + '$rootScope', '$location', 'horizon.app.core.openstack-service-api.ironic', + 'horizon.dashboard.admin.ironic.events', 'horizon.dashboard.admin.ironic.actions', 'horizon.dashboard.admin.basePath', - 'horizon.dashboard.admin.ironic.maintenance.service' + 'horizon.dashboard.admin.ironic.maintenance.service', + 'horizon.dashboard.admin.ironic.validUuidPattern' ]; - function IronicNodeDetailsController($location, + function IronicNodeDetailsController($scope, + $rootScope, + $location, ironic, + ironicEvents, actions, basePath, - maintenanceService) { + maintenanceService, + validUuidPattern) { var ctrl = this; var path = basePath + 'ironic/node-details/sections/'; + ctrl.noPortsText = gettext('No network ports have been defined'); + ctrl.actions = actions; ctrl.sections = [ @@ -51,18 +61,42 @@ } ]; + ctrl.ports = []; + ctrl.portsSrc = []; ctrl.basePath = basePath; - ctrl.re_uuid = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/; + ctrl.re_uuid = new RegExp(validUuidPattern); ctrl.isUuid = isUuid; ctrl.getVifPortId = getVifPortId; ctrl.putNodeInMaintenanceMode = putNodeInMaintenanceMode; ctrl.removeNodeFromMaintenanceMode = removeNodeFromMaintenanceMode; + ctrl.createPort = createPort; + ctrl.deletePort = deletePort; + ctrl.deletePorts = deletePorts; + + var createPortHandler = + $rootScope.$on(ironicEvents.CREATE_PORT_SUCCESS, + function() { + init(); + }); + + var deletePortHandler = + $rootScope.$on(ironicEvents.DELETE_PORT_SUCCESS, + function() { + init(); + $scope.$broadcast('hzTable:clearSelected'); + }); + + $scope.$on('$destroy', function() { + createPortHandler(); + deletePortHandler(); + }); init(); /** * @name horizon.dashboard.admin.ironic.NodeDetailsController.init - * @description Initialize the controller instance based on the current page url. + * @description Initialize the controller instance based on the + * current page url. * * @return {void} */ @@ -87,20 +121,24 @@ function retrieveNode(uuid) { return ironic.getNode(uuid).then(function (response) { ctrl.node = response.data; + ctrl.node.id = uuid; }); } /** * @name horizon.dashboard.admin.ironic.NodeDetailsController.retrievePorts - * @description Retrieve the ports associated with a specified node, and store - * them in the controller instance. + * @description Retrieve the ports associated with a specified node, + * and store them in the controller instance. * * @param {string} nodeId – Node name or UUID * @return {void} */ function retrievePorts(nodeId) { ironic.getPortsWithNode(nodeId).then(function (response) { - ctrl.ports = response.data.items; + ctrl.portsSrc = response.data.items; + ctrl.portsSrc.forEach(function(port) { + port.id = port.uuid; + }); }); } @@ -109,7 +147,8 @@ * @description Test whether a string is an OpenStack UUID * * @param {string} str – string - * @return {boolean} True if the string is an OpenStack UUID, otherwise false + * @return {boolean} True if the string is an OpenStack UUID, + * otherwise false */ function isUuid(str) { return !!str.match(ctrl.re_uuid); @@ -120,7 +159,8 @@ * @description Get the vif_port_id property of a specified port * * @param {object} port – instance of port - * @return {string} Value of vif_port_id property or "" if the property does not exist + * @return {string} Value of vif_port_id property or + * "" if the property does not exist */ function getVifPortId(port) { return angular.isDefined(port.extra) && @@ -135,5 +175,42 @@ function removeNodeFromMaintenanceMode() { maintenanceService.removeNodeFromMaintenanceMode(ctrl.node); } + + /** + * @name horizon.dashboard.admin.ironic.NodeDetailsController.createPort + * @description Initiate creation of a newtwork port for the current + * node + * + * @return {void} + */ + function createPort() { + ctrl.actions.createPort(ctrl.node); + } + + /** + * @name horizon.dashboard.admin.ironic.NodeDetailsController.deletePort + * @description Delete a specified port + * + * @param {port []} port – port to be deleted + * @return {void} + */ + function deletePort(port) { + ctrl.actions.deletePort({id: port.uuid, name: port.address}); + } + + /** + * @name horizon.dashboard.admin.ironic.NodeDetailsController.deletePorts + * @description Delete a specified list of ports + * + * @param {port []} ports – list of ports to be deleted + * @return {void} + */ + function deletePorts(ports) { + var selectedPorts = []; + angular.forEach(ports, function(port) { + selectedPorts.push({id: port.uuid, name: port.address}); + }); + ctrl.actions.deletePorts(selectedPorts); + } } })(); 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 d217094d..9bc51c3b 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 @@ -8,9 +8,9 @@
Node ID
{$ ctrl.node.uuid $}
Chassis ID
-
{$ ctrl.node.chassis_uuid $}
+
{$ ctrl.node.chassis_uuid | noValue $}
Created At
-
{$ ctrl.node.created_at $}
+
{$ ctrl.node.created_at | date:'medium' $}
Extra
{$ ctrl.node.extra $}
@@ -20,19 +20,89 @@

Ports


-
-
- {$ 'MAC ' + (1 + $index) $}
-
- - {$ port.address $} - -
-
- {$ port.address $} -
-

-
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + {$ 'Create port' | translate $} + + + + + {$ 'Delete ports' | translate $} + + + +
+ + + MAC Address + + Extra + + Actions +
+ + + + {$ port.address $} + + + {$ port.address $} + +
+
+ {$ id $} +
+
+ {$ value $} +
+

+
+
+ + + + + +
diff --git a/ironic_ui/static/dashboard/admin/ironic/node-list/node-list.controller.js b/ironic_ui/static/dashboard/admin/ironic/node-list/node-list.controller.js index 2a1fad8b..295d96c1 100755 --- a/ironic_ui/static/dashboard/admin/ironic/node-list/node-list.controller.js +++ b/ironic_ui/static/dashboard/admin/ironic/node-list/node-list.controller.js @@ -24,6 +24,7 @@ IronicNodeListController.$inject = [ '$rootScope', 'horizon.app.core.openstack-service-api.ironic', + 'horizon.dashboard.admin.ironic.events', 'horizon.dashboard.admin.ironic.actions', 'horizon.dashboard.admin.basePath', 'horizon.dashboard.admin.ironic.maintenance.service', @@ -32,6 +33,7 @@ function IronicNodeListController($rootScope, ironic, + ironicEvents, actions, basePath, maintenanceService, @@ -87,11 +89,19 @@ ]; // Listen for the creation of new nodes, and update the node list - $rootScope.$on('ironic-ui:new-node', function() { + $rootScope.$on(ironicEvents.ENROLL_NODE_SUCCESS, function() { init(); }); - $rootScope.$on('ironic-ui:delete-node-success', function() { + $rootScope.$on(ironicEvents.DELETE_NODE_SUCCESS, function() { + init(); + }); + + $rootScope.$on(ironicEvents.CREATE_PORT_SUCCESS, function() { + init(); + }); + + $rootScope.$on(ironicEvents.DELETE_PORT_SUCCESS, function() { init(); }); diff --git a/ironic_ui/static/dashboard/admin/ironic/node-list/node-list.html b/ironic_ui/static/dashboard/admin/ironic/node-list/node-list.html index 8dbcfc88..ffef2839 100644 --- a/ironic_ui/static/dashboard/admin/ironic/node-list/node-list.html +++ b/ironic_ui/static/dashboard/admin/ironic/node-list/node-list.html @@ -122,7 +122,7 @@ {$ node.provision_state $} - {$ node.maintenance $} + {$ node.maintenance | yesno $} {$ node.ports.length $} {$ node.driver $} @@ -160,6 +160,11 @@ {$ 'Delete node' | translate $} + + {$ 'Create port' | translate $} +