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 @@
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 $}
+
|