03af6076fd
Rework HTML and Javascript to provide better strings for the translators to work on. The existing code generated strings that contained unnecessary HTML markup. Change-Id: Ib528c64234d88c39b266e03a702f1ce50a96684f
302 lines
9.5 KiB
JavaScript
302 lines
9.5 KiB
JavaScript
/*
|
|
* 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 support operations on an Ironic node
|
|
*/
|
|
angular
|
|
.module('horizon.dashboard.admin.ironic')
|
|
.controller('BaseNodeController', BaseNodeController);
|
|
|
|
BaseNodeController.$inject = [
|
|
'$uibModalInstance',
|
|
'horizon.app.core.openstack-service-api.ironic',
|
|
'horizon.app.core.openstack-service-api.glance',
|
|
'horizon.dashboard.admin.ironic.base-node.service',
|
|
'horizon.dashboard.admin.ironic.validHostNamePattern',
|
|
'$log',
|
|
'ctrl'
|
|
];
|
|
|
|
function BaseNodeController($uibModalInstance,
|
|
ironic,
|
|
glance,
|
|
baseNodeService,
|
|
validHostNamePattern,
|
|
$log,
|
|
ctrl) {
|
|
ctrl.validHostNameRegex = new RegExp(validHostNamePattern);
|
|
ctrl.drivers = null;
|
|
ctrl.images = null;
|
|
ctrl.loadingDriverProperties = false;
|
|
// Object containing the set of properties associated with the currently
|
|
// selected driver
|
|
ctrl.driverProperties = null;
|
|
ctrl.driverPropertyGroups = null;
|
|
|
|
ctrl.modalTitle = gettext("Node");
|
|
ctrl.submitButtonTitle = gettext("Submit");
|
|
|
|
/* A property-collection is a set of properties that will be displayed
|
|
in the node view as a minimal browser ui that supports:
|
|
- adding new properties
|
|
- displaying the list of properties in the set
|
|
- changing the value of properties
|
|
*/
|
|
ctrl.propertyCollections = [
|
|
{id: "properties",
|
|
title: gettext("Properties"),
|
|
addPrompt: gettext("Add Property"),
|
|
placeholder: gettext("Property Name")
|
|
},
|
|
{id: "extra",
|
|
title: gettext("Extras"),
|
|
addPrompt: gettext("Add Extra"),
|
|
placeholder: gettext("Extra Property Name")
|
|
}];
|
|
|
|
// Node object suitable for Ironic api
|
|
ctrl.node = {
|
|
name: null,
|
|
driver: null,
|
|
driver_info: {},
|
|
properties: {},
|
|
extra: {},
|
|
network_interface: null
|
|
};
|
|
|
|
/**
|
|
* @description Get the list of currently active Ironic drivers
|
|
*
|
|
* @return {void}
|
|
*/
|
|
ctrl._loadDrivers = function() {
|
|
return ironic.getDrivers().then(function(drivers) {
|
|
ctrl.drivers = drivers;
|
|
});
|
|
};
|
|
|
|
/**
|
|
* @description Get the list of images from Glance
|
|
*
|
|
* @return {void}
|
|
*/
|
|
ctrl._getImages = function() {
|
|
glance.getImages().then(function(response) {
|
|
ctrl.images = response.data.items;
|
|
});
|
|
};
|
|
|
|
/**
|
|
* @description Check whether a group contains required properties
|
|
*
|
|
* @param {DriverProperty[]} group - Property group
|
|
* @return {boolean} Return true if the group contains required
|
|
* properties, false otherwise
|
|
*/
|
|
function driverPropertyGroupHasRequired(group) {
|
|
var hasRequired = false;
|
|
for (var i = 0; i < group.length; i++) {
|
|
if (group[i].required) {
|
|
hasRequired = true;
|
|
break;
|
|
}
|
|
}
|
|
return hasRequired;
|
|
}
|
|
|
|
/**
|
|
* @description Convert array of driver property groups to a string
|
|
*
|
|
* @param {array[]} groups - Array for driver property groups
|
|
* @return {string} Output string
|
|
*/
|
|
function driverPropertyGroupsToString(groups) {
|
|
var output = [];
|
|
angular.forEach(groups, function(group) {
|
|
var groupStr = [];
|
|
angular.forEach(group, function(property) {
|
|
groupStr.push(property.name);
|
|
});
|
|
groupStr = groupStr.join(", ");
|
|
output.push(['[', groupStr, ']'].join(""));
|
|
});
|
|
output = output.join(", ");
|
|
return ['[', output, ']'].join("");
|
|
}
|
|
|
|
/**
|
|
* @description Comaprison function used to sort driver property groups
|
|
*
|
|
* @param {DriverProperty[]} group1 - First group
|
|
* @param {DriverProperty[]} group2 - Second group
|
|
* @return {integer} Return:
|
|
* < 0 if group1 should precede group2 in an ascending ordering
|
|
* > 0 if group2 should precede group1
|
|
* 0 if group1 and group2 are considered equal from ordering perpsective
|
|
*/
|
|
function compareDriverPropertyGroups(group1, group2) {
|
|
var group1HasRequired = driverPropertyGroupHasRequired(group1);
|
|
var group2HasRequired = driverPropertyGroupHasRequired(group2);
|
|
|
|
if (group1HasRequired === group2HasRequired) {
|
|
if (group1.length === group2.length) {
|
|
return group1[0].name.localeCompare(group2[0].name);
|
|
} else {
|
|
return group1.length - group2.length;
|
|
}
|
|
} else {
|
|
return group1HasRequired ? -1 : 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @description Order driver properties in the form using the following
|
|
* rules:
|
|
*
|
|
* (1) Properties that are related to one another should occupy adjacent
|
|
* locations in the form
|
|
*
|
|
* (2) Required properties with no dependents should be located at the
|
|
* top of the form
|
|
*
|
|
* @return {void}
|
|
*/
|
|
ctrl._sortDriverProperties = function() {
|
|
// Build dependency graph between driver properties
|
|
var graph = new baseNodeService.Graph();
|
|
|
|
// Create vertices
|
|
angular.forEach(ctrl.driverProperties, function(property, name) {
|
|
graph.addVertex(name, property);
|
|
});
|
|
|
|
/* eslint-disable no-unused-vars */
|
|
|
|
// Create edges
|
|
angular.forEach(ctrl.driverProperties,
|
|
function(property, name) {
|
|
var activators = property.getActivators();
|
|
if (activators) {
|
|
angular.forEach(activators,
|
|
function(unused, activatorName) {
|
|
graph.addEdge(name, activatorName);
|
|
});
|
|
}
|
|
});
|
|
|
|
/* eslint-enable no-unused-vars */
|
|
|
|
// Perform depth-first-search to find groups of related properties
|
|
var groups = [];
|
|
graph.dfs(
|
|
function(vertexList, components) {
|
|
// Sort properties so that those with the largest number of
|
|
// immediate dependents are the top of the list
|
|
vertexList.sort(function(vertex1, vertex2) {
|
|
return vertex2.adjacents.length - vertex1.adjacents.length;
|
|
});
|
|
|
|
// Build component and add to list
|
|
var component = new Array(vertexList.length);
|
|
angular.forEach(vertexList, function(vertex, index) {
|
|
component[index] = vertex.data;
|
|
});
|
|
components.push(component);
|
|
},
|
|
groups);
|
|
groups.sort(compareDriverPropertyGroups);
|
|
|
|
$log.debug("Found the following property groups: " +
|
|
driverPropertyGroupsToString(groups));
|
|
return groups;
|
|
};
|
|
|
|
/**
|
|
* @description Get the properties associated with a specified driver
|
|
*
|
|
* @param {string} driverName - Name of driver
|
|
* @return {void}
|
|
*/
|
|
ctrl.loadDriverProperties = function(driverName) {
|
|
ctrl.node.driver = driverName;
|
|
ctrl.node.driver_info = {};
|
|
|
|
ctrl.loadingDriverProperties = true;
|
|
ctrl.driverProperties = null;
|
|
ctrl.driverPropertyGroups = null;
|
|
|
|
return ironic.getDriverProperties(driverName).then(function(properties) {
|
|
ctrl.driverProperties = {};
|
|
angular.forEach(properties, function(desc, property) {
|
|
ctrl.driverProperties[property] =
|
|
new baseNodeService.DriverProperty(property,
|
|
desc,
|
|
ctrl.driverProperties);
|
|
});
|
|
ctrl.driverPropertyGroups = ctrl._sortDriverProperties();
|
|
ctrl.loadingDriverProperties = false;
|
|
});
|
|
};
|
|
|
|
/**
|
|
* @description Cancel the current node operation
|
|
*
|
|
* @return {void}
|
|
*/
|
|
ctrl.cancel = function() {
|
|
$uibModalInstance.dismiss('cancel');
|
|
};
|
|
|
|
/**
|
|
* @description Check whether the specified property already exists
|
|
*
|
|
* @param {string} collectionId - Collection ID
|
|
* @param {string} propertyName - Name of the property
|
|
* @return {boolean} True if the property already exists,
|
|
* otherwise false
|
|
*/
|
|
ctrl.collectionCheckPropertyUnique = function(collectionId, propertyName) {
|
|
return !(propertyName in ctrl.node[collectionId]);
|
|
};
|
|
|
|
/**
|
|
* @description Delete a node metadata property
|
|
*
|
|
* @param {string} collectionId - Collection ID
|
|
* @param {string} propertyName - Name of the property
|
|
* @return {void}
|
|
*/
|
|
ctrl.collectionDeleteProperty = function(collectionId, propertyName) {
|
|
delete ctrl.node[collectionId][propertyName];
|
|
};
|
|
|
|
/**
|
|
* @description Check whether a specified driver property is
|
|
* currently active
|
|
*
|
|
* @param {string} property - Driver property
|
|
* @return {boolean} True if the property is active, false otherwise
|
|
*/
|
|
ctrl.isDriverPropertyActive = function(property) {
|
|
return property.isActive();
|
|
};
|
|
}
|
|
})();
|