Hardware management: '
+ if (builtInXCAT == 0) {
+ addNodeForm.append('
Hardware management: '
+ ''
+ 'ESX '
+ 'KVM '
+ 'z\/VM '
- + 'iDataPlex '
+ + 'iDataPlex '
+ 'BladeCenter '
+ 'System p ' // Documentation refers to 'IBM System p' (where p is NOT capitalized)
- + ' '
+ + ''
+ + '
');
+ } else {
+ addNodeForm.append('
Hardware management: '
+ + ''
+ + 'z\/VM '
+ + ' '
+ '
');
-
+ }
+
// Create advanced link to set advanced node properties
var advanced = $('
');
var advancedLnk = $('
Advanced ').css({
@@ -388,7 +420,7 @@ function mkAddNodeLink() {
/**
* Set node attributes and open dialog
- *
+ *
* @param data Data returned from HTTP request
*/
success : function(data) {
@@ -398,13 +430,13 @@ function mkAddNodeLink() {
openSetAttrsDialog();
}
});
-
+
// Close dialog
addNodeForm.dialog('destroy').remove();
});
advanced.append(advancedLnk);
addNodeForm.append(advanced);
-
+
// Open dialog to add node
addNodeForm.dialog({
modal: true,
@@ -414,8 +446,8 @@ function mkAddNodeLink() {
buttons: {
'Ok': function() {
// Get hardware management
- var mgt = $(this).find('select[name=mgt]').val();
-
+ var mgt = $(this).find('select[name=mgt]').val();
+
var plugin;
switch(mgt) {
case "kvm":
@@ -437,7 +469,7 @@ function mkAddNodeLink() {
plugin = new zvmPlugin();
break;
}
-
+
$(this).dialog('destroy').remove();
plugin.addNode();
},
@@ -448,7 +480,7 @@ function mkAddNodeLink() {
});
});
-
+
// Generate tooltips
addNodeLink.tooltip({
position: 'center right',
@@ -457,20 +489,20 @@ function mkAddNodeLink() {
opacity: 0.7,
predelay: 800
});
-
+
return addNodeLink;
}
/**
* Load nodes belonging to a given group
- *
+ *
* @param data Data returned from HTTP request
*/
function loadNodes(data) {
// Clear the tab before inserting the table
$('#nodesTab').children().remove();
- // Data returned
+ // Data returned
var rsp = data.rsp;
// Group name
var group = data.msg;
@@ -478,13 +510,13 @@ function loadNodes(data) {
var attrs = new Object();
// Node attributes
var headers = new Object();
-
+
// Variable to send command and request node status
var getNodeStatus = true;
// Clear hash table containing node attributes
origAttrs = '';
-
+
var node, args;
for (var i in rsp) {
// Get node name
@@ -501,18 +533,18 @@ function loadNodes(data) {
args = rsp[i].split('=', 2);
var key = jQuery.trim(args[0]);
var val = jQuery.trim(rsp[i].substring(rsp[i].indexOf('=') + 1));
-
+
// Create a hash table
attrs[node][key] = val;
headers[key] = 1;
-
+
// If node status is available
if (key == 'status') {
// Do not request node status
getNodeStatus = false;
}
}
-
+
// Add nodes that are not in data returned
for (var i in nodesList) {
if (!attrs[nodesList[i]]) {
@@ -521,7 +553,7 @@ function loadNodes(data) {
attrs[nodesList[i]]['node'] = nodesList[i];
}
}
-
+
// Save attributes in hash table
origAttrs = attrs;
@@ -536,9 +568,9 @@ function loadNodes(data) {
sorted.sort();
// Add column for check box, node, ping, power, monitor, and comments
- sorted.unshift('
',
- 'node',
- '
status ',
+ sorted.unshift('
',
+ 'node',
+ '
status ',
'
power ',
'
monitor ',
'comments');
@@ -546,30 +578,30 @@ function loadNodes(data) {
// Create a datatable
var nodesTable = new DataTable(nodesTableId);
nodesTable.init(sorted);
-
+
// Go through each node
for (var node in attrs) {
// Create a row
var row = new Array();
-
+
// Create a check box, node link, and get node status
var checkBx = '
';
var nodeLink = $('
' + node + ' ').bind('click', loadNode);
-
+
// If there is no status attribute for the node, do not try to access hash table
// else the code will break
var status = '';
if (attrs[node]['status']) {
status = attrs[node]['status'].replace('sshd', 'ping');
}
-
+
// Push in checkbox, node, status, monitor, and power
row.push(checkBx, nodeLink, status, '', '');
-
+
// If the node attributes are known (i.e the group is known)
if (attrs[node]['groups']) {
// Put in comments
- var comments = attrs[node]['usercomment'];
+ var comments = attrs[node]['usercomment'];
// If no comments exists, show 'No comments' and set icon image source
var iconSrc;
if (!comments) {
@@ -578,25 +610,25 @@ function loadNodes(data) {
} else {
iconSrc = 'images/nodes/ui-icon-comment.png';
}
-
+
// Create comments icon
var tipID = node + 'Tip';
var icon = $('
').css({
'width': '18px',
'height': '18px'
});
-
+
// Create tooltip
var tip = createCommentsToolTip(comments);
var col = $('
').append(icon);
col.append(tip);
row.push(col);
-
+
// Generate tooltips
icon.tooltip({
position: "center right",
offset: [-2, 10],
- effect: "fade",
+ effect: "fade",
opacity: 0.8,
relative: true,
delay: 500
@@ -605,12 +637,12 @@ function loadNodes(data) {
// Do not put in comments if attributes are not known
row.push('');
}
-
+
// Go through each header
for (var i = 6; i < sorted.length; i++) {
// Add the node attributes to the row
var key = sorted[i];
-
+
// Do not put comments and status in twice
if (key != 'usercomment' && key != 'status' && key.indexOf('status') < 0) {
var val = attrs[node][key];
@@ -628,10 +660,12 @@ function loadNodes(data) {
// Clear the tab before inserting the table
$('#nodesTab').children().remove();
-
+
// Create info bar for nodes tab
var info = createInfoBar('Double-click on a cell to edit a node\'s properties. Click outside the table to save changes. Hit the Escape key to ignore changes.');
$('#nodesTab').append(info);
+ info.id = 'NodesInfoBar';
+ setNodesTabInfoBar(info);
// Create action bar
var actionBar = $('
').css("width", "400px");
@@ -648,26 +682,65 @@ function loadNodes(data) {
powerNode(tgtNodes, 'on');
}
});
-
+
// Power off
var powerOffLnk = $('
Power off ');
powerOffLnk.click(function() {
var tgtNodes = getNodesChecked(nodesTableId);
if (tgtNodes) {
+
+ var msg = 'Do you want to power off: ' + tgtNodes + '?';
+ // Open dialog to confirm
+ var confirmDialog = $('
');
+ confirmDialog.dialog({
+ title:'Confirm',
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ width: 400,
+ buttons: {
+ "Ok": function() {
powerNode(tgtNodes, 'off');
+ $(this).dialog("close");
+ },
+ "Cancel": function() {
+ $(this).dialog("close");
+ }
+ }
+ });
}
});
-
+
// Power softoff
var powerSoftoffLnk = $('
Shutdown ');
powerSoftoffLnk.click(function() {
var tgtNodes = getNodesChecked(nodesTableId);
if (tgtNodes) {
+ var msg = 'Do you want to shutdown: ' + tgtNodes + '?';
+ // Open dialog to confirm
+ var confirmDialog = $('
');
+ confirmDialog.dialog({
+ title:'Confirm',
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ width: 400,
+ buttons: {
+ "Ok": function() {
powerNode(tgtNodes, 'softoff');
+ $(this).dialog("close");
+ },
+ "Cancel": function() {
+ $(this).dialog("close");
+ }
+ }
+ });
}
});
-
- // Turn monitoring on
+ if (builtInXCAT == 0) {
+ // Turn monitoring on
var monitorOnLnk = $('
Monitor on ');
monitorOnLnk.click(function() {
var tgtNodes = getNodesChecked(nodesTableId);
@@ -684,6 +757,7 @@ function loadNodes(data) {
monitorNode(tgtNodes, 'off');
}
});
+ }
// Clone
var cloneLnk = $('
Clone ');
@@ -705,8 +779,14 @@ function loadNodes(data) {
plugin = new zvmPlugin();
break;
}
-
- plugin.loadClonePage(tgtNodes[i]);
+ if (mgt == "zvm") {
+ var nodeOS = getNodeAttr(tgtNodes[i], 'os');
+ var nodeArch = getNodeAttr(tgtNodes[i], 'arch');
+ plugin.loadClonePage(tgtNodes[i], nodeOS, nodeArch);
+ } else {
+ plugin.loadClonePage(tgtNodes[i]);
+ }
+
}
});
@@ -719,31 +799,89 @@ function loadNodes(data) {
}
});
- // Unlock
+ // Unlock Function
var unlockLnk = $('
Unlock ');
unlockLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesTableId);
- if (tgtNodes) {
- loadUnlockPage(tgtNodes);
+
+ // Get the "master" value from the site table.
+ var siteMaster;
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'site',
+ msg : 'cmd=tabdump site;'
+ },
+
+ success : function(data) {
+ var outId = $(data.msg);
+ var props = data.rsp;
+ if ( jQuery.isArray(data.rsp) ) {
+ for (var i in data.rsp) {
+ if ( data.rsp[i].indexOf('"master"') == 0 ) {
+ siteMaster = data.rsp[i].slice( 10, -3 );
+ }
+ }
+ } else {
+ if ( data.rsp.indexOf('"master"') == 0 ) {
+ siteMaster = data.rsp.slice( 10, -3 );
+ }
+ }
+
+ // Process the nodes that were checked.
+ var tgtNodes = getNodesChecked(nodesTableId).split(',');
+ var normalNodes = '';
+ var mnNode = '';
+ for (var i in tgtNodes) {
+ var nodeIP = getNodeAttr( tgtNodes[i], 'ip' );
+ if ( nodeIP == siteMaster ) {
+ if ( mnNode == '' ) {
+ // Only one xCAT node will have the same address as
+ // the site master IP address and this is the
+ // xCAT MN.
+ mnNode = tgtNodes[i];
+ }
+ } else {
+ if ( normalNodes == '' ) {
+ normalNodes = tgtNodes[i];
+ } else {
+ normalNodes = normalNodes + "," + tgtNodes[i];
+ }
+ }
+ }
+
+ if ( normalNodes != '' ) {
+ loadUnlockPage( normalNodes );
+ }
+ if ( mnNode != '' ) {
+ loadUnlockNonNodesPage( mnNode );
}
+ }
+ });
});
// Run script
var scriptLnk = $('
Run script ');
scriptLnk.click(function() {
var tgtNodes = getNodesChecked(nodesTableId);
- if (tgtNodes) {
+ if (tgtNodes) {
loadScriptPage(tgtNodes);
+ } else {
+ openDialog('warn', "No nodes checked!");
}
});
-
+
// Migrate VM
var migrateLnk = $('
Migrate ');
migrateLnk.click(function() {
var tgtNodes = getNodesChecked(nodesTableId).split(',');
var mgt = "", tmp = "";
+ var fromhcp = "";
for (var i in tgtNodes) {
tmp = getNodeAttr(tgtNodes[i], 'mgt');
+ fromhcp += getNodeAttr(tgtNodes[i], 'hcp') + ',';
if (!mgt) {
mgt = tmp
} else {
@@ -753,7 +891,7 @@ function loadNodes(data) {
}
}
}
-
+
// Create an instance of the plugin
var plugin;
switch(mgt) {
@@ -768,8 +906,11 @@ function loadNodes(data) {
plugin = new zvmPlugin();
break;
}
-
- plugin.loadMigratePage(tgtNodes);
+ if (mgt == "zvm") {
+ plugin.loadMigratePage(tgtNodes, fromhcp);
+ } else {
+ plugin.loadMigratePage(tgtNodes);
+ }
});
// Update
@@ -798,7 +939,7 @@ function loadNodes(data) {
loadNetbootPage(tgtNodes);
}
});
-
+
// Provision node
var provisionLnk = $('
Provision ');
provisionLnk.click(function() {
@@ -817,7 +958,34 @@ function loadNodes(data) {
loadRconsPage(tgtNodes);
}
});
-
+
+ // Discovery
+ var discoverLnk = $('
Discover systems ');
+ discoverLnk.bind( 'click', function(event) {
+ var tgtNodes = getNodesChecked(nodesTableId).split(',');
+ if ( tgtNodes ) {
+ var hosts;
+ for (var i in tgtNodes) {
+ var hostType = getNodeAttr( tgtNodes[i], 'hosttype' );
+ if ( hostType == 'zvm' ) {
+ if ( hosts ) {
+ hosts += "," + tgtNodes[i];
+ } else {
+ hosts = tgtNodes[i];
+ }
+
+ } else {
+ openDialog('warn', tgtNodes[i] + " does not have a hosttype of 'zvm': " + hostType );
+ }
+ }
+ if ( hosts ) {
+ discoverVMNodes( hosts );
+ }
+ } else {
+ openDialog('warn', "No nodes checked!");
+ }
+ });
+
// Edit properties
var editProps = $('
Edit properties ');
editProps.bind('click', function(event){
@@ -826,7 +994,7 @@ function loadNodes(data) {
editNodeProps(tgtNodes[i]);
}
});
-
+
// Install Ganglia
var installMonLnk = $('
Install monitoring ');
installMonLnk.click(function() {
@@ -835,7 +1003,7 @@ function loadNodes(data) {
installGanglia(tgtNodes);
}
});
-
+
// Scan
var rscanLnk = $('
Scan ');
rscanLnk.bind('click', function(event){
@@ -844,7 +1012,7 @@ function loadNodes(data) {
loadRscanPage(tgtNodes);
}
});
-
+
// Event log
var logLnk = $('
Event log ');
logLnk.click(function() {
@@ -874,29 +1042,106 @@ function loadNodes(data) {
plugin = new zvmPlugin();
break;
}
-
+
plugin.loadLogPage(tgtNodes[i]);
}
});
-
+
// Actions
var actionsLnk = '
Actions ';
- var actsMenu = createMenu([cloneLnk, deleteLnk, migrateLnk, monitorOnLnk, monitorOffLnk, powerOnLnk, powerOffLnk, scriptLnk, powerSoftoffLnk]);
+ if (builtInXCAT == 0) {
+ if (group == 'hosts') {
+ var actsMenu = createMenu([deleteLnk]);
+ } else {
+ var actsMenu = createMenu([cloneLnk, deleteLnk, migrateLnk, monitorOnLnk, monitorOffLnk, powerOnLnk, powerOffLnk, scriptLnk, powerSoftoffLnk]);
+ }
+ } else {
+ if (group == 'hosts') {
+ var actsMenu = createMenu([deleteLnk]);
+ } else {
+ var actsMenu = createMenu([cloneLnk, deleteLnk, migrateLnk, powerOnLnk, powerOffLnk, scriptLnk, powerSoftoffLnk]);
+ }
+ }
// Configurations
var configLnk = '
Configuration ';
- var configMenu = createMenu([editProps, logLnk, installMonLnk, rscanLnk, unlockLnk, updateLnk]);
+ if (builtInXCAT == 0) {
+ if (group == 'hosts') {
+ var configMenu = createMenu([editProps]);
+ } else {
+ var configMenu = createMenu([editProps, logLnk, installMonLnk, rscanLnk, unlockLnk, updateLnk]);
+ }
+ } else {
+ if (group == 'hosts') {
+ var configMenu = createMenu([ discoverLnk, editProps ]);
+ } else {
+ var configMenu = createMenu([editProps, logLnk, rscanLnk, unlockLnk, updateLnk]);
+ }
+ }
// Provision
var provLnk = '
Provision ';
- var provMenu = createMenu([boot2NetworkLnk, rcons, setBootStateLnk, provisionLnk]);
+ if (builtInXCAT == 0) {
+ var provMenu = createMenu([boot2NetworkLnk, rcons, setBootStateLnk, provisionLnk]);
+ } else {
+ var provMenu = createMenu([boot2NetworkLnk, setBootStateLnk]);
+ }
+
+ /**
+ * Refresh button
+ */
+ var refreshBtn = createButton('Refresh');
+ refreshBtn.click(function() {
+ // Remove any warning messages
+ $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
+
+ var zhcpsCheck = $.cookie('zhcps').split(',');
+ var zhcpHash = new Object();
+ for (var h in zhcpsCheck) {
+ if (!zhcpHash[zhcpsCheck[h]]) {
+
+ zhcpHash[zhcpsCheck[h]] = 1;
+ if (typeof console == "object"){
+ console.log("zhcp check for <"+zhcpsCheck[h]+">");
+ }
+
+ // Check if SMAPI is online
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'lsvm',
+ tgt : zhcpsCheck[h],
+ args : '',
+ msg : 'group=refreshgroups' + ';hcp=' + zhcpsCheck[h]
+ },
+
+ // Load hardware control point specific info
+ // Get disk pools and network names
+ success : loadHcpInfo
+ });
+ }
+ }
+
+ window.location.reload();
+ });
+ refreshBtn.css({'width': '80px'});
+ refreshBtn.css({'height': '27px'});
+ //refreshBtn.css('vertical-align', 'top');
+ refreshBtn.css({'align': 'top'});
// Create an action menu
- var actionsMenu = createMenu([ [ actionsLnk, actsMenu ], [ configLnk, configMenu ], [ provLnk, provMenu ] ]);
+ var actionsMenu;
+ if (group == 'hosts') {
+ actionsMenu = createMenu([ [ actionsLnk, actsMenu ], [ configLnk, configMenu ] ]);
+ } else {
+ actionsMenu = createMenu([ [ actionsLnk, actsMenu ], [ configLnk, configMenu ], [ provLnk, provMenu ] ]);
+ }
actionsMenu.superfish();
actionsMenu.css('display', 'inline-block');
actionBar.append(actionsMenu);
-
+ actionBar.append(refreshBtn);
+
// Set correct theme for action menu
actionsMenu.find('li').hover(function() {
setMenu2Theme($(this));
@@ -906,7 +1151,7 @@ function loadNodes(data) {
// Insert action bar and nodes datatable
$('#nodesTab').append(nodesTable.object());
-
+
// Turn table into a datatable
var nodesDatatable = $('#' + nodesTableId).dataTable({
'iDisplayLength': 50,
@@ -922,32 +1167,32 @@ function loadNodes(data) {
}
}
});
-
+
// Filter table when enter key is pressed
$('#' + nodesTableId + '_filter input').unbind();
$('#' + nodesTableId + '_filter input').bind('keyup', function(e){
if (e.keyCode == 13) {
var table = $('#' + nodesTableId).dataTable();
table.fnFilter($(this).val());
-
+
// If there are nodes found, get the node attributes
if (!$('#' + nodesTableId + ' .dataTables_empty').length) {
getNodeAttrs(group);
}
}
});
-
+
// Load node definitions when next or previous buttons are clicked
$('#' + nodesTableId + '_next, #' + nodesTableId + '_previous').click(function() {
getNodeAttrs(group);
});
-
+
/**
* Change how datatable behaves
*/
-
+
// Do not sort ping, power, and comment column
- var cols = $('#' + nodesTableId + ' thead tr th').click(function() {
+ var cols = $('#' + nodesTableId + ' thead tr th').click(function() {
getNodeAttrs(group);
});
var checkboxCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(0)');
@@ -960,16 +1205,16 @@ function loadNodes(data) {
powerCol.unbind('click');
monitorCol.unbind('click');
commentCol.unbind('click');
-
+
// Create enough space for loader to be displayed
// Center align power, ping, and comments
$('#' + nodesTableId + ' td:nth-child(3),td:nth-child(4),td:nth-child(5)').css({
'text-align': 'center'
});
-
+
// No minimum width for comments column
$('#' + nodesTableId + ' tbody tr td:nth-child(6)').css('text-align', 'center');
-
+
// Instead refresh the node, power, and monitor status
pingCol.find('span a').click(function() {
refreshNodeStatus(group, nodesTableId);
@@ -980,18 +1225,24 @@ function loadNodes(data) {
monitorCol.find('span a').click(function() {
refreshGangliaStatus(group, nodesTableId);
});
-
+
// Create a division to hold actions menu
- var menuDiv = $('');
- $('#' + nodesTableId + '_wrapper').prepend(menuDiv);
- menuDiv.append(actionBar);
- $('#' + nodesTableId + '_filter').appendTo(menuDiv);
-
+ var menuDiv = $(''); // # ');
update.append(createInfoBar('Updating table
'));
-
+
update.dialog({
title: 'Updating',
modal: true,
@@ -1214,7 +1465,7 @@ function getNodeAttrs(group) {
/**
* Add nodes to datatable
- *
+ *
* @param data Data returned from HTTP request
*/
function addNodes2Table(data) {
@@ -1226,10 +1477,10 @@ function addNodes2Table(data) {
var attrs = new Object();
// Node attributes
var headers = $('#' + nodesTableId).parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr th');
-
+
// Variable to send command and request node status
var getNodeStatus = true;
-
+
// Go through each attribute
var node, args;
for (var i in rsp) {
@@ -1247,19 +1498,19 @@ function addNodes2Table(data) {
args = rsp[i].split('=', 2);
var key = jQuery.trim(args[0]);
var val = jQuery.trim(rsp[i].substring(rsp[i].indexOf('=') + 1, rsp[i].length));
-
+
// Create a hash table
attrs[node][key] = val;
// Save attributes in original hash table
origAttrs[node][key] = val;
-
+
// If node status is available
if (key == 'status') {
// Do not request node status
getNodeStatus = false;
}
}
-
+
// Set the first five headers
var headersCol = new Object();
headersCol['node'] = 1;
@@ -1267,7 +1518,7 @@ function addNodes2Table(data) {
headersCol['power'] = 3;
headersCol['monitor'] = 4;
headersCol['comments'] = 5;
-
+
// Go through each header
for (var i = 6; i < headers.length; i++) {
// Get the column index
@@ -1287,15 +1538,15 @@ function addNodes2Table(data) {
break;
}
}
-
+
// Get node status
var status = '';
if (attrs[node]['status']){
status = attrs[node]['status'].replace('sshd', 'ping');
}
-
+
rows[nodeRowPos][headersCol['status']] = status;
-
+
// Go through each header
for (var key in headersCol) {
// Do not put comments and status in twice
@@ -1306,15 +1557,15 @@ function addNodes2Table(data) {
}
}
}
-
+
// Update row
- datatable.fnUpdate(rows[nodeRowPos], nodeRowPos, 0, false);
-
+ datatable.fnUpdate(rows[nodeRowPos], parseInt(nodeRowPos), undefined, false);
+
// Insert node comments
// This is done after datatable is updated because
// you cannot insert an object using fnUpdate()
var comments = attrs[node]['usercomment'];
-
+
// If no comments exists, show 'No comments' and
// set icon image source
var iconSrc;
@@ -1324,22 +1575,22 @@ function addNodes2Table(data) {
} else {
iconSrc = 'images/nodes/ui-icon-comment.png';
}
-
+
// Create icon for node comments
var tipID = node + 'Tip';
var commentsCol = $('#' + node).parent().parent().find('td').eq(5);
-
+
// Create tooltip
var icon = $('
').css({
'width': '18px',
'height': '18px'
});
-
+
var tip = createCommentsToolTip(comments);
var span = $('
').append(icon);
span.append(tip);
commentsCol.append(span);
-
+
// Generate tooltips
icon.tooltip({
position: "center right",
@@ -1350,19 +1601,19 @@ function addNodes2Table(data) {
delay: 500
});
}
-
+
// Enable node link
$('.node').bind('click', loadNode);
// Close dialog for updating table
$('.ui-dialog-content').dialog('destroy').remove();
-
+
/**
* Enable editable columns
*/
// Do not make 1st, 2nd, 3rd, 4th, 5th, or 6th column editable
$('#' + nodesTableId + ' td:not(td:nth-child(1),td:nth-child(2),td:nth-child(3),td:nth-child(4),td:nth-child(5),td:nth-child(6))').editable(
- function(value, settings) {
+ function(value, settings) {
// If users did not do changes, return the value directly
// jeditable save the old value in this.revert
if ($(this).attr('revert') == value){
@@ -1370,27 +1621,27 @@ function addNodes2Table(data) {
}
// Get column index
var colPos = this.cellIndex;
-
+
// Get row index
var dTable = $('#' + nodesTableId).dataTable();
var rowPos = dTable.fnGetPosition(this.parentNode);
-
+
// Update datatable
dTable.fnUpdate(value, rowPos, colPos, false);
-
+
// Get table headers
var headers = $('#' + nodesTableId + ' thead tr th');
-
+
// Get node name
var node = $(this).parent().find('td a.node').text();
// Get attribute name
var attrName = jQuery.trim(headers.eq(colPos).text());
// Get column value
var value = $(this).text();
-
+
// Build argument
var args = attrName + '=' + value;
-
+
// Send command to change node attributes
$.ajax( {
url : 'lib/cmd.php',
@@ -1413,7 +1664,7 @@ function addNodes2Table(data) {
event : 'dblclick',
height : '30px' // The height of the text area
});
-
+
// If request to get node status is made
if (getNodeStatus) {
// Get node status
@@ -1426,7 +1677,7 @@ function addNodes2Table(data) {
args : '-u',
msg : ''
},
-
+
success : loadNodeStatus
});
} else {
@@ -1434,7 +1685,7 @@ function addNodes2Table(data) {
var statCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
statCol.find('img').hide();
}
-
+
/**
* Additional ajax requests need to be made for zVM
*/
@@ -1444,7 +1695,7 @@ function addNodes2Table(data) {
/**
* Load the status of Ganglia for a given group
- *
+ *
* @param data Data returned from HTTP request
*/
function loadGangliaStatus(data) {
@@ -1461,7 +1712,7 @@ function loadGangliaStatus(data) {
if (node) {
// Get the row containing the node
rowNum = findRow(node, '#' + nodesTableId, 1);
-
+
// Update the power status column
datatable.fnUpdate(status, rowNum, 4);
}
@@ -1475,14 +1726,14 @@ function loadGangliaStatus(data) {
/**
* Refresh the status of Ganglia for each node
- *
+ *
* @param group Group name
*/
function refreshGangliaStatus(group) {
// Show ganglia loader
var gangliaCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
gangliaCol.find('img').show();
-
+
// Get power status for nodes shown
var nodes = getNodesShown(nodesTableId);
@@ -1503,7 +1754,7 @@ function refreshGangliaStatus(group) {
/**
* Load power status for each node
- *
+ *
* @param data Data returned from HTTP request
*/
function loadPowerStatus(data) {
@@ -1516,14 +1767,14 @@ function loadPowerStatus(data) {
args = power[i].split(':');
node = jQuery.trim(args[0]);
status = jQuery.trim(args[1]);
-
+
// Get the row containing the node
rowPos = findRow(node, '#' + nodesTableId, 1);
// Update the power status column
dTable.fnUpdate(status, rowPos, 3);
}
-
+
// Hide power loader
var powerCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
powerCol.find('img').hide();
@@ -1532,7 +1783,7 @@ function loadPowerStatus(data) {
/**
* Refresh power status for each node
- *
+ *
* @param group Group name
* @param tableId Table to update node status
*/
@@ -1540,10 +1791,10 @@ function refreshPowerStatus(group, tableId) {
// Show power loader
var powerCol = $('#' + tableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
powerCol.find('img').show();
-
+
// Get power status for nodes shown
var nodes = getNodesShown(tableId);
-
+
// Get power status
$.ajax( {
url : 'lib/cmd.php',
@@ -1561,7 +1812,7 @@ function refreshPowerStatus(group, tableId) {
/**
* Load node status for each node
- *
+ *
* @param data Data returned from HTTP request
*/
function loadNodeStatus(data) {
@@ -1572,18 +1823,18 @@ function loadNodeStatus(data) {
// Get all nodes within datatable
for (var i in rsp) {
args = rsp[i].split(':');
-
+
// args[0] = node and args[1] = status
node = jQuery.trim(args[0]);
status = jQuery.trim(args[1]).replace('sshd', 'ping');
-
+
// Get row containing node
rowPos = findRow(node, '#' + nodesTableId, 1);
// Update ping status column
dTable.fnUpdate(status, rowPos, 2, false);
}
-
+
// Hide status loader
var statCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
statCol.find('img').hide();
@@ -1592,7 +1843,7 @@ function loadNodeStatus(data) {
/**
* Refresh ping status for each node
- *
+ *
* @param group Group name
* @param tableId Table to update node status
*/
@@ -1600,10 +1851,10 @@ function refreshNodeStatus(group, tableId) {
// Show ping loader
var pingCol = $('#' + tableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
pingCol.find('img').show();
-
+
// Get power status for nodes shown
var nodes = getNodesShown(tableId);
-
+
// Get the node status
$.ajax( {
url : 'lib/cmd.php',
@@ -1621,18 +1872,18 @@ function refreshNodeStatus(group, tableId) {
/**
* Load inventory for given node
- *
+ *
* @param e Windows event
*/
function loadNode(e) {
if (!e) {
e = window.event;
}
-
+
// Get node that was clicked
var node = (e.target) ? e.target.id : e.srcElement.id;
var mgt = getNodeAttr(node, 'mgt');
-
+
// Create an instance of the plugin
var plugin;
switch(mgt) {
@@ -1694,7 +1945,7 @@ function loadNode(e) {
/**
* Unlock a node by setting the ssh keys
- *
+ *
* @param tgtNodes Nodes to unlock
*/
function loadUnlockPage(tgtNodes) {
@@ -1720,17 +1971,17 @@ function loadUnlockPage(tgtNodes) {
// Create info bar
var infoBar = createInfoBar('Give the root password for this node range to setup its SSH keys.');
-
+
// Create unlock form
var unlockForm = $('
');
unlockForm.append(statBar, infoBar);
-
+
// Create VM fieldset
var vmFS = $('
');
var vmLegend = $('
Virtual Machine ');
vmFS.append(vmLegend);
unlockForm.append(vmFS);
-
+
var vmAttr = $('
');
vmFS.append($('
'));
vmFS.append(vmAttr);
@@ -1752,7 +2003,7 @@ function loadUnlockPage(tgtNodes) {
tooltip : "mouseover,mouseout"
}
});
-
+
/**
* Ok
*/
@@ -1764,7 +2015,7 @@ function loadUnlockPage(tgtNodes) {
unlockBtn.click(function() {
// Remove any warning messages
$(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
-
+
// If a password is given
var password = $('#' + newTabId + ' input[name=password]').css('border', 'solid #BDBDBD 1px');
if (password.val()) {
@@ -1778,13 +2029,13 @@ function loadUnlockPage(tgtNodes) {
args : 'unlock;' + tgtNodes + ';' + password.val(),
msg : 'out=' + statBarId + ';cmd=unlock;tgt=' + tgtNodes
},
-
+
success : updateStatusBar
});
-
+
// Show status bar
statBar.show();
-
+
// Disable all inputs and Ok button
$('#' + newTabId + ' input').attr('disabled', 'disabled');
$(this).attr('disabled', 'true');
@@ -1801,9 +2052,297 @@ function loadUnlockPage(tgtNodes) {
tab.select(newTabId);
}
+function loadUnlockNonNodesPage( tgtNodes ) {
+
+ // Get nodes tab
+ var tab = getNodesTab();
+ var fs, legend;
+
+ // Generate new tab ID
+ var instance = 0;
+ var newTabId = 'unlockNonNodesTab' + instance;
+ while ($('#' + newTabId).length) {
+ // If one already exists, generate another one
+ instance = instance + 1;
+ newTabId = 'unlockNonNodesTab' + instance;
+ }
+
+ // Create info bar and status bar
+ var infoBar = createInfoBar( 'Unlock systems that have not been defined to xCAT. Either:
' +
+ '-Create a script to install the xCAT Management Node\'s public key on the target systems, or
' +
+ '-Unlock system(s) directly using their IP address(es) ' +
+ '(Specify multiple systems by separating the addresses with a comma),
' +
+ '-Show the xCAT Management Node\'s public key to use to unlock the system.' );
+
+ var statBarId = 'unlockNonNodesStatusBar' + instance;
+ var statBar = createStatusBar(statBarId).hide();
+ var loader = createLoader( '' );
+ statBar.find('div').append( loader );
+
+ // Create unlock form and put info and status bars on the form
+ var unlockNonNodesForm = $( '
' );
+ unlockNonNodesForm.append( infoBar, statBar );
+
+ // Create 'Create an Unlock Script' fieldset
+ fs = $( '
' );
+ legend = $( '
Create an Unlock Script ' );
+ fs.append( legend );
+ unlockNonNodesForm.append( fs );
+
+ // Create Script bar
+ var scriptBarId = 'unlockNonNodesScriptBar' + instance;
+ var scriptBar = createStatusBar(scriptBarId).hide();
+ unlockNonNodesForm.append( scriptBar );
+
+ var createBtn = createButton( 'Create Script' );
+ createBtn.css({
+ 'width': '200px',
+ 'display': 'block'
+ });
+
+ createBtn.click(function() {
+ // Remove any warning messages
+ $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
+
+ // Get the SSH keys for a non-node
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'unlockshow;' + tgtNodes + ';script;',
+ msg : 'out=' + statBarId + ';scriptBar=' + scriptBarId +';cmd=unlock;tgt=' + tgtNodes
+ },
+
+ success : updateScriptBar
+ });
+
+ // Show status bar
+ statBar.show();
+ });
+
+ unlockNonNodesForm.append( createBtn );
+
+ // Create 'Unlock a system using the root password' Script fieldset
+ fs = $( '
' );
+ legend = $( '
Unlock a system using the root password ' );
+ fs.append( legend );
+ unlockNonNodesForm.append( fs );
+
+ var vmAttr = $('
' );
+ fs.append($('
'));
+ fs.append( vmAttr );
+
+ vmAttr.append( '
IP Address:
' );
+ vmAttr.append( '
Password:
' );
+
+ /**
+ * Unlock button for non-nodes
+ */
+ var unlockBtn = createButton('Unlock');
+ unlockBtn.css({
+ 'width': '80px',
+ 'display': 'block'
+ });
+
+ unlockBtn.click(function() {
+ // Remove any warning messages
+ $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
+
+ // If an ip and password is given
+ var ip = $('#' + newTabId + ' input[name=ip]').css('border', 'solid #BDBDBD 1px');
+ var password = $( '#' + newTabId + ' input[name=password]').css('border', 'solid #BDBDBD 1px' );
+ if ( password.val() && ip.val() ) {
+ $('#' + statBarId).find('img').show();
+ // Setup SSH keys for a non-node
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'unlockbyip;' + tgtNodes + ';' + password.val() + ";" + ip.val(),
+ msg : 'out=' + statBarId + ';cmd=unlock;tgt=' + tgtNodes
+ },
+
+ success : updateStatusBar
+ });
+
+ // Show status bar
+ statBar.show();
+ } else {
+ // Show warning message
+ var warn = createWarnBar('Both ip address and password must be specified.');
+ warn.prependTo($(this).parents('.ui-tabs-panel'));
+ password.css('border', 'solid #FF0000 1px');
+ }
+ });
+
+ unlockNonNodesForm.append(unlockBtn);
+
+ // Create 'SSH Key' fieldset
+ var sshKey = '';
+ fs = $( '
' );
+ legend = $( '
xCAT Management Node Public Key ' );
+ fs.append( legend );
+ unlockNonNodesForm.append( fs );
+
+ // Create key bar, hide on load
+ var keyBarId = 'unlockNonNodesKeyBar' + instance;
+ var keyBar = createStatusBar(keyBarId).hide();
+ unlockNonNodesForm.append( keyBar );
+
+ // Generate tooltips
+ unlockNonNodesForm.find('div input[title]').tooltip({
+ position: "center right",
+ offset: [-2, 10],
+ effect: "fade",
+ opacity: 0.7,
+ predelay: 800,
+ events : {
+ def : "mouseover,mouseout",
+ input : "mouseover,mouseout",
+ widget : "focus mouseover,blur mouseout",
+ tooltip : "mouseover,mouseout"
+ }
+ });
+
+ /**
+ * "Get Key" button
+ */
+ var getBtn = createButton('Get Key');
+ getBtn.css({
+ 'width': '80px',
+ 'display': 'block'
+ });
+
+ getBtn.click(function() {
+ // Remove any warning messages
+ $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
+
+ // Get the SSH keys for a non-node
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'unlockshow;' + tgtNodes + ';key;',
+ msg : 'out=' + statBarId + ';keyBar=' + keyBarId +';cmd=unlock;tgt=' + tgtNodes
+ },
+
+ success : updateKeyBar
+ });
+
+ // Show status bar
+ statBar.show();
+ });
+
+ unlockNonNodesForm.append(getBtn);
+
+ tab.add(newTabId, 'Unlock System', unlockNonNodesForm, true);
+ tab.select(newTabId);
+}
+
+
+/**
+ * Update key and status bar of a given tab
+ *
+ * @param data Data returned from HTTP request
+ */
+function updateKeyBar(data) {
+ // Get ajax response
+ var rsp = data.rsp;
+ var args = data.msg.split(';');
+ var statBarId = args[0].replace('out=', '');
+ var keyBarId = args[1].replace('keyBar=', '');
+ var cmd = args[2].replace('cmd=', '');
+ var tgts = args[3].replace('tgt=', '').split(',');
+
+ $('#' + statBarId).find('img').hide();
+
+ // Extract the key portion and status portions from the response
+ var keyRespStart = rsp[0].indexOf("
");
+ var keyRespEnd = rsp[0].indexOf(" ");;
+ var keyOnly = rsp[0].substring( keyRespStart+9, keyRespEnd );
+ var statLines = rsp[0].substring( 0, keyRespStart-1 );
+
+ if ( keyOnly.length > 0 ) {
+ // Expected response was returned, show it in the key bar.
+ var keyLines = keyOnly.split(/\n/);
+ for ( var i in keyLines ) {
+ $('#' + keyBarId).find( 'div' ).append( keyLines[i] );
+ $('#' + keyBarId).find( 'div' ).append( '
' );
+ }
+ $('#' + keyBarId).show();
+
+ // Other lines from the response are shown in the Status bar.
+ if ( statLines.length > 0 ) {
+ prg = statLines.split(/\n/);
+ prg = writeRsp( prg, '' );
+ $('#' + statBarId).find( 'div' ).append( prg );
+ }
+ } else {
+ // Did not find the expected response, write the ajax response to status bar.
+ var prg = writeRsp(rsp, '');
+ $('#' + statBarId).find('div').append(prg);
+ }
+
+}
+
+
+/**
+ * Update the script and status bar of a given tab
+ *
+ * @param data Data returned from HTTP request
+ */
+function updateScriptBar(data) {
+ // Get ajax response
+ var rsp = data.rsp;
+ var args = data.msg.split(';');
+ var statBarId = args[0].replace('out=', '');
+ var scriptBarId = args[1].replace('scriptBar=', '');
+ var cmd = args[2].replace('cmd=', '');
+ var tgts = args[3].replace('tgt=', '').split(',');
+
+ $('#' + statBarId).find('img').hide();
+
+ // Extract the key portion and status portions from the response
+ var scriptRespStart = rsp[0].indexOf("
");
+ var scriptRespEnd = rsp[0].indexOf(" ");;
+ var scriptOnly = rsp[0].substring( scriptRespStart+12, scriptRespEnd );
+ var statLines = rsp[0].substring( 0, scriptRespStart-1 );
+
+ if ( scriptOnly.length > 0 ) {
+ // Expected response was returned, show it in the script bar along with the rest of the code.
+ var scriptLines = scriptOnly.split(/\n/);
+ for ( var i in scriptLines ) {
+ scriptLines[i] = scriptLines[i].replace(/^\s\s\s\s\s\s\s\s+/gm, ' ');
+ scriptLines[i] = scriptLines[i].replace(/^\s\s\s\s\s\s+/gm, ' ');
+ scriptLines[i] = scriptLines[i].replace(/^\s\s\s\s+/gm, ' ');
+ scriptLines[i] = scriptLines[i].replace(/^\s\s+/gm, ' ');
+ $('#' + scriptBarId).find( 'div' ).append( scriptLines[i] + '
' );
+ }
+ $('#' + scriptBarId).show();
+
+ // Other lines from the response are shown in the Status bar.
+ if ( statLines.length > 0 ) {
+ prg = statLines.split(/\n/);
+ prg = writeRsp( prg, '' );
+ $('#' + statBarId).find( 'div' ).append( prg );
+ }
+ } else {
+ // Did not find the expected response, write the ajax response to status bar.
+ var prg = writeRsp(rsp, '');
+ $('#' + statBarId).find('div').append(prg);
+ }
+
+}
+
/**
* Load script page
- *
+ *
* @param tgtNodes Targets to run script against
*/
function loadScriptPage(tgtNodes) {
@@ -1821,7 +2360,7 @@ function loadScriptPage(tgtNodes) {
// Create remote script form
var scriptForm = $('
');
-
+
// Create status bar
var barId = 'scriptStatusBar' + inst;
var statBar = createStatusBar(barId);
@@ -1831,28 +2370,28 @@ function loadScriptPage(tgtNodes) {
// Create info bar
var infoBar = createInfoBar('Load a script to run against this node range.');
- scriptForm.append(statBar, infoBar);
-
+ scriptForm.append(infoBar, statBar);
+
// Create VM fieldset
var vmFS = $('
');
var vmLegend = $('
Virtual Machine ');
vmFS.append(vmLegend);
scriptForm.append(vmFS);
-
+
var vmAttr = $('
');
vmFS.append($('
'));
vmFS.append(vmAttr);
-
+
// Create logs fieldset
var scriptFS = $('
');
var scriptLegend = $('
Script ');
scriptFS.append(scriptLegend);
scriptForm.append(scriptFS);
-
+
var scriptAttr = $('
');
scriptFS.append($('
'));
scriptFS.append(scriptAttr);
-
+
// Target node or group
var tgt = $('
Target node range:
');
vmAttr.append(tgt);
@@ -1864,11 +2403,11 @@ function loadScriptPage(tgtNodes) {
var subBtn = createButton('Load');
upload.append(label, file, subBtn);
scriptAttr.append(upload);
-
+
// Script
var script = $('
Script: ');
scriptAttr.append(script);
-
+
// Generate tooltips
scriptForm.find('div input[title],textarea').tooltip({
position: "center right",
@@ -1898,13 +2437,13 @@ function loadScriptPage(tgtNodes) {
runBtn.css({
'width': '80px'
});
- runBtn.click(function() {
+ runBtn.click(function() {
// Remove any warning messages
$(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
-
+
// Get script to run
var textarea = $('#' + newTabId + ' textarea').css('border', 'solid #BDBDBD 1px');
-
+
// If no inputs are empty
if (textarea.val()) {
// Run script
@@ -1927,7 +2466,7 @@ function loadScriptPage(tgtNodes) {
/**
* Sort a list
- *
+ *
* @return Sorted list
*/
jQuery.fn.sort = function() {
@@ -1940,7 +2479,7 @@ function sortAlpha(a, b) {
/**
* Power on a given node
- *
+ *
* @param node Node to power on or off
* @param power2 Power node to given state
*/
@@ -1948,7 +2487,7 @@ function powerNode(node, power2) {
// Show power loader
var powerCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
powerCol.find('img').show();
-
+
node = node.replace('Power', '');
$.ajax( {
url : 'lib/cmd.php',
@@ -1966,7 +2505,7 @@ function powerNode(node, power2) {
/**
* Load delete node page
- *
+ *
* @param tgtNodes Nodes to delete
*/
function loadDeletePage(tgtNodes) {
@@ -2009,7 +2548,7 @@ function loadDeletePage(tgtNodes) {
// Create delete form
var deleteForm = $('
');
-
+
// Create status bar, hide on load
var statBarId = 'deleteStatusBar' + inst;
var statBar = createStatusBar(statBarId).hide();
@@ -2017,22 +2556,22 @@ function loadDeletePage(tgtNodes) {
// Create loader
var loader = createLoader('');
statBar.find('div').append(loader);
- statBar.hide();
+ statBar.hide();
deleteForm.append(statBar);
-
+
// Create confirm fieldset
var confirmFS = $('
');
var confirmLegend = $('
Confirm ');
confirmFS.append(confirmLegend);
deleteForm.append(confirmFS);
-
+
var confirmAttr = $('
');
confirmFS.append($('
'));
confirmFS.append(confirmAttr);
-
+
// Confirm delete
var instr = $('
Are you sure you want to delete ' + tgtNodesStr + ' ?
').css('word-wrap', 'break-word');
- var dbOnly = $('
Only delete entries in database
');
+ var dbOnly = $('
Only delete entries in database
');
confirmAttr.append(instr);
confirmAttr.append(dbOnly);
@@ -2046,8 +2585,8 @@ function loadDeletePage(tgtNodes) {
if ($("#" + newTabId + " input[name='db-only']").attr('checked')) {
cmd = "noderm";
}
-
- // Delete the virtual server
+
+ // Delete the virtual server or remove the node.
$.ajax( {
url : 'lib/cmd.php',
dataType : 'json',
@@ -2067,7 +2606,7 @@ function loadDeletePage(tgtNodes) {
// Disable delete button
$(this).attr('disabled', 'true');
});
-
+
/**
* Cancel
*/
@@ -2084,7 +2623,7 @@ function loadDeletePage(tgtNodes) {
/**
* Update status bar of a given tab
- *
+ *
* @param data Data returned from HTTP request
*/
function updateStatusBar(data) {
@@ -2100,8 +2639,8 @@ function updateStatusBar(data) {
$('#' + statBarId).find('img').hide();
// Write ajax response to status bar
- var prg = writeRsp(rsp, '');
- $('#' + statBarId).find('div').append(prg);
+ var prg = writeRsp(rsp, '');
+ $('#' + statBarId).find('div').append(prg);
} else if (cmd == 'rmvm') {
// Get data table
var dTable = $('#' + nodesTableId).dataTable();
@@ -2112,8 +2651,8 @@ function updateStatusBar(data) {
// Write ajax response to status bar
var prg = writeRsp(rsp, '');
- $('#' + statBarId).find('div').append(prg);
-
+ $('#' + statBarId).find('div').append(prg);
+
// If there was an error, do not continue
if (prg.html().indexOf('Error') > -1) {
failed = true;
@@ -2121,7 +2660,8 @@ function updateStatusBar(data) {
} else if (cmd == 'xdsh') {
// Hide loader
$('#' + statBarId).find('img').hide();
-
+ $('#' + statBarId).find('#loadingpic2').remove();
+
// Write ajax response to status bar
var prg = $('
');
for (var i in rsp) {
@@ -2130,36 +2670,50 @@ function updateStatusBar(data) {
}
prg.append(rsp[i]);
- prg.append('
');
+ prg.append('
');
}
- $('#' + statBarId).find('div').append(prg);
-
+ $('#' + statBarId).find('div').append(prg);
+ $('#' + statBarId).find('div').append('
');
+
+ // The status area division contains useful scrollTop() and "scrollHeight dom 0" information.
+ // The inner div grows in height along with the status bar scroll height
+ // The status area client does not grow, that is the visible scroll area
+ var scrtop = $('#' + statBarId ).scrollTop();
+ var scrheight = $('#' + statBarId )[0].scrollHeight;
+ var dcheight = $('#' + statBarId)[0].clientHeight;
+ var dcheight2 = $('#' + statBarId).find('div')[0].clientHeight;
+
+ // Adjust the scroll bar to move to the bottom
+ if (scrtop < (scrheight-dcheight)) {
+ $('#' + statBarId ).scrollTop(scrheight-dcheight);
+ }
+
// Enable fields
$('#' + statBarId).parent().find('input').removeAttr('disabled');
$('#' + statBarId).parent().find('textarea').removeAttr('disabled');
-
+
// Enable buttons
$('#' + statBarId).parent().find('button').removeAttr('disabled');
} else if (cmd == 'noderm') {
// Hide loader
$('#' + statBarId).find('img').hide();
-
+
// Write ajax response to status bar
- var prg = $('
Entries deleted in database ');
- $('#' + statBarId).find('div').append(prg);
+ var prg = $('
Entries deleted in database ');
+ $('#' + statBarId).find('div').append(prg);
} else {
// Hide loader
$('#' + statBarId).find('img').hide();
-
+
// Write ajax response to status bar
- var prg = writeRsp(rsp, '');
- $('#' + statBarId).find('div').append(prg);
+ var prg = writeRsp(rsp, '');
+ $('#' + statBarId).find('div').append(prg);
}
}
/**
* Update power status of a node in the datatable
- *
+ *
* @param data Data from HTTP request
*/
function updatePowerStatus(data) {
@@ -2198,14 +2752,14 @@ function updatePowerStatus(data) {
alert(rsp[i]);
}
}
-
+
// Adjust datatable column size
adjustColumnSize(nodesTableId);
}
/**
* Run a script
- *
+ *
* @param inst Remote script tab instance
*/
function runScript(inst) {
@@ -2215,8 +2769,27 @@ function runScript(inst) {
var tgts = $('#' + tabId + ' input[name=target]').val();
// Get script
var script = $('#' + tabId + ' textarea').val();
-
+
var statBarId = 'scriptStatusBar' + inst;
+
+ // The status area division contains useful scrollTop() and "scrollHeight dom 0" information.
+ // The inner div grows in height along with the status bar scroll height
+ // The status area client does not grow, that is the visible scroll area
+ var scrtop = $('#' + statBarId ).scrollTop();
+ var scrheight = $('#' + statBarId )[0].scrollHeight;
+ var dcheight = $('#' + statBarId)[0].clientHeight;
+ var dcheight2 = $('#' + statBarId).find('div')[0].clientHeight;
+
+ //If this is not first time for run script and it has scrolled then add a progress gif at the end.
+ if (scrheight > dcheight) {
+ $('#'+statBarId).find('div').append("
");
+ scrtop = $('#' + statBarId ).scrollTop();
+ scrheight = $('#' + statBarId )[0].scrollHeight;
+ dcheight = $('#' + statBarId)[0].clientHeight;
+ // Scroll down so gif shows
+ $('#' + statBarId ).scrollTop(scrheight-dcheight);
+ }
+
$('#' + statBarId).show(); // Show status bar
$('#' + statBarId + ' img').show(); // Show loader
$('#' + statBarId + ' p').remove(); // Clear status bar
@@ -2224,7 +2797,7 @@ function runScript(inst) {
// Disable all fields
$('#' + tabId + ' input').attr('disabled', 'true');
$('#' + tabId + ' textarea').attr('disabled', 'true');
-
+
// Disable buttons
$('#' + tabId + ' button').attr('disabled', 'true');
@@ -2246,7 +2819,7 @@ function runScript(inst) {
/**
* Get an attribute of a given node
- *
+ *
* @param node The node
* @param attrName The attribute
* @return The attribute of the node
@@ -2257,7 +2830,7 @@ function getNodeAttr(node, attrName) {
// Search for the column containing the attribute
var attrCol;
-
+
var cols = row.parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th');
// Loop through each column
for (var i in cols) {
@@ -2267,7 +2840,7 @@ function getNodeAttr(node, attrName) {
break;
}
}
-
+
// If the column containing the attribute is found
if (attrCol) {
// Get the attribute column index
@@ -2283,7 +2856,7 @@ function getNodeAttr(node, attrName) {
/**
* Set a cookie for the OS images
- *
+ *
* @param data Data from HTTP request
*/
function setOSImageCookies(data) {
@@ -2298,7 +2871,7 @@ function setOSImageCookies(data) {
var profilePos = 0;
var osversPos = 0;
var osarchPos = 0;
-
+
// Get column value
var colNameArray = rsp[0].substr(1).split(',');
for (var i in colNameArray){
@@ -2319,7 +2892,7 @@ function setOSImageCookies(data) {
break;
}
}
-
+
// Go through each index
for (var i = 1; i < rsp.length; i++) {
// Get image name
@@ -2328,7 +2901,7 @@ function setOSImageCookies(data) {
var profile = cols[profilePos].replace(new RegExp('"', 'g'), '');
var osVer = cols[osversPos].replace(new RegExp('"', 'g'), '');
var osArch = cols[osarchPos].replace(new RegExp('"', 'g'), '');
-
+
imageNames.push(osImage);
profilesHash[profile] = 1;
osVersHash[osVer] = 1;
@@ -2362,7 +2935,7 @@ function setOSImageCookies(data) {
/**
* Set a cookie for the groups
- *
+ *
* @param data Data from HTTP request
*/
function setGroupsCookies(data) {
@@ -2372,17 +2945,17 @@ function setGroupsCookies(data) {
/**
* Find the row index containing a column with a given string
- *
+ *
* @param str String to search for
* @param table Table to check
* @param col Column to find string under
* @return The row index containing the search string
*/
-function findRow(str, table, col){
+function findRow(str, table, col){
// Get datatable
var dTable = $(table).dataTable();
var rows = dTable.fnGetData();
-
+
// Loop through each row
for (var i in rows) {
// If the column contains the search string
@@ -2390,13 +2963,13 @@ function findRow(str, table, col){
return parseInt(i);
}
}
-
+
return -1;
}
/**
* Select all checkboxes in the datatable
- *
+ *
* @param event Event on element
* @param obj Object triggering event
*/
@@ -2411,7 +2984,7 @@ function selectAllCheckbox(event, obj) {
/**
* Load rcons page
- *
+ *
* @param tgtNodes Targets to run rcons against
*/
function loadRconsPage(tgtNodes){
@@ -2419,25 +2992,25 @@ function loadRconsPage(tgtNodes){
var urlPath = window.location.pathname;
var redirectUrl = 'https://';
var pos = 0;
-
+
// We only support one node
if (-1 != tgtNodes.indexOf(',')){
alert("You can only open one console at a time!");
return;
}
-
+
redirectUrl += hostName;
pos = urlPath.lastIndexOf('/');
redirectUrl += urlPath.substring(0, pos + 1);
redirectUrl += 'rcons.php';
-
+
// Open the rcons page
window.open(redirectUrl + "?rconsnd=" + tgtNodes, '', "toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=no,width=590,height=436");
}
/**
* Create a tool tip for comments
- *
+ *
* @param comment Comments to be placed in a tool tip
* @return Tool tip
*/
@@ -2454,7 +3027,7 @@ function createCommentsToolTip(comment) {
'border': '0px',
'display': 'block'
});
-
+
// Create links to save and cancel changes
var lnkStyle = {
'color': '#58ACFA',
@@ -2463,17 +3036,17 @@ function createCommentsToolTip(comment) {
'padding': '5px',
'float': 'right'
};
-
+
var saveLnk = $('
Save ').css(lnkStyle).hide();
var cancelLnk = $('
Cancel ').css(lnkStyle).hide();
var infoSpan = $('
Click to edit ').css(lnkStyle);
-
+
// Save changes onclick
saveLnk.bind('click', function(){
// Get node and comment
var node = $(this).parent().parent().find('img').attr('id').replace('Tip', '');
var comments = $(this).parent().find('textarea').val();
-
+
// Save comment
$.ajax( {
url : 'lib/cmd.php',
@@ -2484,45 +3057,45 @@ function createCommentsToolTip(comment) {
args : '-t;node;-o;' + node + ';usercomment=' + comments,
msg : 'out=nodesTab;tgt=' + node
},
-
+
success: showChdefOutput
});
-
+
// Hide cancel and save links
$(this).hide();
cancelLnk.hide();
});
-
+
// Cancel changes onclick
cancelLnk.bind('click', function(){
// Get original comment and put it back
var orignComments = $(this).parent().find('textarea').text();
$(this).parent().find('textarea').val(orignComments);
-
+
// Hide cancel and save links
$(this).hide();
saveLnk.hide();
infoSpan.show();
});
-
+
// Show save link when comment is edited
txtArea.bind('click', function(){
saveLnk.show();
cancelLnk.show();
infoSpan.hide();
});
-
+
toolTip.append(txtArea);
toolTip.append(cancelLnk);
toolTip.append(saveLnk);
toolTip.append(infoSpan);
-
+
return toolTip;
}
/**
* Create a tool tip for node status
- *
+ *
* @return Tool tip
*/
function createStatusToolTip() {
@@ -2531,19 +3104,19 @@ function createStatusToolTip() {
'width': '150px',
'font-weight': 'normal'
});
-
+
// Create info text
var info = $('
').css({
'white-space': 'normal'
});
info.append('Click here to refresh the node status. To configure the xCAT monitor, ');
-
+
// Create link to turn on xCAT monitoring
var monitorLnk = $('
click here ').css({
'color': '#58ACFA',
'font-size': '10px'
});
-
+
// Open dialog to configure xCAT monitor
monitorLnk.bind('click', function(){
// Check if xCAT monitor is enabled
@@ -2560,16 +3133,16 @@ function createStatusToolTip() {
success : openConfXcatMon
});
});
-
+
info.append(monitorLnk);
toolTip.append(info);
-
+
return toolTip;
}
/**
* Create a tool tip for power status
- *
+ *
* @return Tool tip
*/
function createPowerToolTip() {
@@ -2584,7 +3157,7 @@ function createPowerToolTip() {
/**
* Create a tool tip for monitoring status
- *
+ *
* @return Tool tip
*/
function createMonitorToolTip() {
@@ -2593,13 +3166,13 @@ function createMonitorToolTip() {
'width': '150px',
'white-space': 'normal',
'font-weight': 'normal'
- });
+ });
return toolTip;
}
/**
* Open dialog to configure xCAT monitor
- *
+ *
* @param data Data returned from HTTP request
*/
function openConfXcatMon(data) {
@@ -2607,12 +3180,12 @@ function openConfXcatMon(data) {
var info = createInfoBar('Configure the xCAT monitor. Select to enable or disable the monitor below.');
var dialog = $('
');
dialog.append(info);
-
+
// Create status area
var statusArea = $('
').css('padding-top', '10px');
var label = $('
Status: ');
statusArea.append(label);
-
+
// Get xCAT monitor status
var status = data.rsp[0];
var buttons;
@@ -2620,7 +3193,7 @@ function openConfXcatMon(data) {
if (status.indexOf('not-monitored') > -1) {
status = $('
Disabled ').css('padding', '0px 5px');
statusArea.append(status);
-
+
// Create enable and cancel buttons
buttons = {
"Enable": function(){
@@ -2634,21 +3207,21 @@ function openConfXcatMon(data) {
args : 'xcatmon',
msg : ''
},
-
+
success : function(data){
openDialog('info', data.rsp[0]);
}
});
$(this).dialog("close");
},
- "Cancel": function(){
+ "Cancel": function(){
$(this).dialog("close");
}
};
} else {
status = $('
Enabled ').css('padding', '0px 5px');
statusArea.append(status);
-
+
// Create disable and cancel buttons
buttons = {
"Disable": function(){
@@ -2662,21 +3235,21 @@ function openConfXcatMon(data) {
args : 'xcatmon',
msg : ''
},
-
+
success : function(data){
openDialog('info', data.rsp[0]);
}
});
$(this).dialog("close");
},
- "Cancel": function(){
+ "Cancel": function(){
$(this).dialog("close");
}
};
}
-
+
dialog.append(statusArea);
-
+
// Open dialog
dialog.dialog({
modal: true,
@@ -2687,7 +3260,7 @@ function openConfXcatMon(data) {
/**
* Show chdef output
- *
+ *
* @param data Data returned from HTTP request
*/
function showChdefOutput(data) {
@@ -2696,7 +3269,7 @@ function showChdefOutput(data) {
var args = data.msg.split(';');
var tabID = args[0].replace('out=', '');
var tgt = args[1].replace('tgt=', '');
-
+
// Find info bar on nodes tab, if any
var info = $('#' + tabID).find('.ui-state-highlight');
if (!info.length) {
@@ -2704,25 +3277,25 @@ function showChdefOutput(data) {
info = createInfoBar('');
$('#' + tabID).append(info);
}
-
+
// Go through output and append to paragraph
var prg = $('
');
for (var i in out) {
prg.append(tgt + ': ' + out[i] + '
');
}
-
+
info.append(prg);
}
/**
* Set node attributes
- *
+ *
* @param data Data returned from HTTP request
*/
function setNodeAttrs(data) {
// Clear hash table containing definable node attributes
nodeAttrs = new Array();
-
+
// Get definable attributes
var attrs = data.rsp[2].split(/\n/);
@@ -2730,7 +3303,7 @@ function setNodeAttrs(data) {
var attr, key, descr;
for (var i in attrs) {
attr = attrs[i];
-
+
// If the line is not empty
if (attr) {
// If the line has the attribute name
@@ -2738,16 +3311,16 @@ function setNodeAttrs(data) {
// Get attribute name and description
key = jQuery.trim(attr.substring(0, attr.indexOf(':')));
descr = jQuery.trim(attr.substring(attr.indexOf(':') + 1));
-
+
// Remove arrow brackets
descr = descr.replace(new RegExp('<|>', 'g'), '');
-
+
// Set hash table where key = attribute name and value = description
nodeAttrs[key] = descr;
} else {
// Remove arrow brackets
attr = attr.replace(new RegExp('<|>', 'g'), '');
-
+
// Append description to hash table
nodeAttrs[key] = nodeAttrs[key] + '\n' + attr;
}
@@ -2755,9 +3328,368 @@ function setNodeAttrs(data) {
} // End of for
}
+
+/**
+ * Load the discover z/VM virtual systems page
+ *
+ * @param tgtNode Target node to set properties
+ */
+function discoverVMNodes(tgtNodes) {
+ var fs, legend, htmlLine;
+
+ // Get nodes tab
+ var tab = getNodesTab();
+
+ // Generate new tab ID
+ var inst = 0;
+ var newTabId = 'discoverVMNodesTab' + inst;
+ while ($('#' + newTabId).length) {
+ // If one already exists, generate another one
+ inst = inst + 1;
+ newTabId = 'discoverVMNodesTab' + inst;
+ }
+
+ // Open new tab
+ // Create set properties form
+ var discoverVMNodesForm = $('
');
+
+ // Create info bar
+ var infoBar = createInfoBar( 'Initiate, stop or query the status of z/VM node discovery. ' +
+ 'To initiate discovery, specify discovery parameters and click on the Discover button. ' +
+ 'To stop an on-going discovery related to a z/VM host, specify the host node name and '+
+ 'click on the Stop button. ' +
+ 'To obtain the status of discovery for a particular host, specify the host node name and '+
+ 'click on the Stop button.'
+ );
+ discoverVMNodesForm.append(infoBar);
+
+ // Create the status bar and hide it.
+ var statBarId = 'statusBar_' + newTabId;
+ //var statBar = $( '
' );
+ //discoverVMNodesForm.append( statBar );
+ statBar = createStatusBar( statBarId );
+ statBar.hide();
+ discoverVMNodesForm.append( statBar );
+
+ // Create Host fieldset
+ fs = $('
');
+ legend = $('
z/VM Host ');
+ fs.append(legend);
+ discoverVMNodesForm.append(fs);
+
+ // Target node or group
+ htmlLine = $('
z/VM host range:
');
+ discoverVMNodesForm.append( htmlLine );
+
+ // Create Discovery Parameters fieldset
+ fs = $('
');
+ legend = $('
Discovery Parameters ');
+ fs.append( legend );
+ discoverVMNodesForm.append( fs );
+
+ // Create an input for each definable attribute
+ var div, label, input, descr, value;
+
+ // Define DefineTo radio buttons
+ div = $('
').css( 'display', 'inline-block' ).css( 'vertical-align', 'top' );
+ div.append( '
Define systems to: ' );
+ div.append( '
xCAT and OpenStack' );
+ div.append( '
xCAT only' );
+ div.append( '
OpenStack only (only already discovered xCAT nodes)' );
+ discoverVMNodesForm.append( div );
+ discoverVMNodesForm.append( '
' );
+
+ // Userid filter
+ divUserid = newTabId + "_divUserid";
+ div = $('
').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' );
+ div.append( '
z/VM Userid Filter: ' );
+ div.append( '
' ).css( 'margin-top', '5px' );
+ discoverVMNodesForm.append( div );
+ discoverVMNodesForm.append( '
' );
+
+ // IP address filter
+ divIP = newTabId + "_divIP";
+ div = $('
').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' );
+ div.append( '
IP Address Filter: ' );
+ div.append( '
' ).css( 'margin-top', '5px' );
+ discoverVMNodesForm.append( div );
+ discoverVMNodesForm.append( '
' );
+
+ // Group name input
+ divGroup = newTabId + '_divGroup';
+ div = $('
').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' );
+ div.append( '
Assign to group(s): ' );
+ div.append( '
' ).css( 'margin-top', '5px' );
+ discoverVMNodesForm.append( div );
+ discoverVMNodesForm.append( '
' );
+
+ // Node Name Format input
+ divNodename = newTabId + '_divNodename';
+ div = $('
').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' );
+ div.append( '
xCAT node name format: ' );
+ div.append( '
' ).css( 'margin-top', '5px' );
+ discoverVMNodesForm.append( div );
+ discoverVMNodesForm.append( '
' );
+ discoverVMNodesForm.find('#' + divNodename).hide();
+
+ // OpenStack operand input
+ divOpenStackOps = newTabId + '_divOpenStackOps';
+ div = $('
').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' );
+ div.append( '
Assign to OpenStack Project: ' );
+ div.append( '
' ).css( 'margin-top', '5px' );
+ div.append( '
' );
+ div.append( '
Assign to OpenStack User: ' );
+ div.append( '
' ).css( 'margin-top', '5px' );
+ discoverVMNodesForm.append( div );
+ discoverVMNodesForm.append( '
' );
+
+ // Define Verbose radio buttons
+ div = $('
').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' ).css( 'text-align', 'top' );
+ div.append( '
Node discovery output: ' );
+ div.append( '
Normal response, showing only important information' );
+ div.append( '
Verbose response, normal response plus additional information (e.g. reason a system is ignored)' );
+ discoverVMNodesForm.append( div );
+ discoverVMNodesForm.append( '
' );
+
+ // Generate tooltips
+ discoverVMNodesForm.find('div input[title]').tooltip({
+ position: "center right",
+ offset: [-2, 10],
+ effect: "fade",
+ opacity: 0.8,
+ delay: 0,
+ predelay: 800,
+ events: {
+ def: "mouseover,mouseout",
+ input: "mouseover,mouseout",
+ widget: "focus mouseover,blur mouseout",
+ tooltip: "mouseover,mouseout"
+ }
+ });
+
+ // Show appropriate input fields for defineto choices.
+ discoverVMNodesForm.change(function(){
+ var defineTo = $(this).parent().find('input[name="defineTo"]:checked').val();
+ if ( defineTo == 'both' ) {
+ discoverVMNodesForm.find('#' + divUserid).show();
+ discoverVMNodesForm.find('#' + divIP).show();
+ discoverVMNodesForm.find('#' + divGroup).show();
+ discoverVMNodesForm.find('#' + divOpenStackOps).show();
+ discoverVMNodesForm.find('#' + divNodename).hide();
+ } else if ( defineTo == 'xcatonly' ) {
+ discoverVMNodesForm.find('#' + divUserid).show();
+ discoverVMNodesForm.find('#' + divIP).show();
+ discoverVMNodesForm.find('#' + divGroup).show();
+ discoverVMNodesForm.find('#' + divOpenStackOps).hide();
+ discoverVMNodesForm.find('#' + divNodename).show();
+ } else if ( defineTo == 'openstackonly' ) {
+ discoverVMNodesForm.find('#' + divUserid).hide();
+ discoverVMNodesForm.find('#' + divIP).hide();
+ discoverVMNodesForm.find('#' + divGroup).hide();
+ discoverVMNodesForm.find('#' + divOpenStackOps).show();
+ discoverVMNodesForm.find('#' + divNodename).hide();
+ }
+ });
+
+
+ // Discover nodes button action
+ var discoverBtn = createButton('Discover');
+ discoverBtn.click(function() {
+ var argList = '';
+ var filter = '';
+
+ var hosts = $(this).parent().find('input[name=hosts]').val();
+ if ( hosts != '' ) {
+ argList = 'zvmhost=' + hosts;
+ }
+
+ var defineTo = $(this).parent().find('input[name="defineTo"]:checked').val();
+ argList = argList + '||defineto=' + defineTo;
+
+ var verbose = $(this).parent().find('input[name="verbose"]:checked').val();
+ if ( verbose == 'yes' ) {
+ argList = argList + '||--verbose';
+ }
+
+ var useridFilter = $(this).parent().find('input[name=useridFilter]').val();
+ if (( defineTo == 'both' || defineTo == 'xcatonly' ) && ( useridFilter != '' )) {
+ argList = argList + '||useridfilter=' + useridFilter;
+ }
+
+ var ipFilter = $(this).parent().find('input[name=ipFilter]').val();
+ if (( defineTo == 'both' || defineTo == 'xcatonly' ) && ( ipFilter != '' )) {
+ argList = argList + '||ipfilter=' + ipFilter;
+ }
+
+ var group = $(this).parent().find('input[name=group]').val();
+ if (( defineTo == 'both' || defineTo == 'xcatonly' ) && ( group != '' )) {
+ argList = argList + '||groups=' + group;
+ }
+
+ var nodeNameFmt = $(this).parent().find('input[name=nodeNameFmt]').val();
+ if ( defineTo == 'xcatonly' && nodeNameFmt != '' ) {
+ argList = argList + '||nodenameformat=' + nodeNameFmt;
+ }
+
+ var openStackProj = $(this).parent().find('input[name=openStackProj]').val();
+ var openStackUser = $(this).parent().find('input[name=openStackUser]').val();
+ if ((( defineTo == 'both' ) || ( defineTo == 'openstackonly' )) &&
+ (( openStackProj != '' ) || ( openStackUser != '' ))) {
+ if ( openStackProj != '' ) {
+ osArgs = '--project ' + openStackProj;
+ } else {
+ osArgs = '';
+ }
+ if ( openStackUser != '' ) {
+ if ( osArgs != '' ) {
+ osArgs = osArgs + ' --user ' + openStackUser;
+ } else {
+ osArgs = '--user ' + openStackUser;
+ }
+ }
+ argList = argList + "||openstackoperands='" + osArgs + "'";
+ }
+
+ var out = $('
');
+ out.append( 'Starting node discovery...' );
+ out.append( '
' );
+ out.append( 'If node discovery is a short running task then its response will follow. If, however, the time it takes to complete discovery exceeds the http request timeout of a few minutes then the discovery response will not be returned to the browser. The status and list buttons can be used to obtained status on the discovery and see what systems have been discovered.' );
+ $( '#' + statBarId ).find( 'div' ).append( out );
+ statBar.show();
+
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'nodediscoverstart',
+ tgt : '',
+ args : argList,
+ att : '',
+ msg : statBarId
+ },
+ success: function(data) {
+ updateDiscoverStatusBar( data, 1 );
+ }
+ });
+
+ });
+ discoverVMNodesForm.append(discoverBtn);
+
+ // Status button
+ var statusBtn = createButton('Status');
+ statusBtn.click( function() {
+ var hosts = $(this).parent().find('input[name=hosts]').val();
+ var out = $('
');
+ out.append( 'Querying status for discovery on ' + hosts + '...' );
+ out.append( '
' );
+ $( '#' + statBarId ).find( 'div' ).append( out );
+
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'nodediscoverstatus',
+ tgt : '',
+ args : '--zvmhost||' + hosts,
+ att : '',
+ msg : statBarId
+ },
+ success: function(data) {
+ updateDiscoverStatusBar( data, 1 );
+ }
+ });
+
+ });
+ discoverVMNodesForm.append( statusBtn );
+
+ // List button
+ var listBtn = createButton('List');
+ listBtn.click( function() {
+ var hosts = $(this).parent().find('input[name=hosts]').val();
+ var out = $('
');
+ out.append( 'Listing systems discovered by the latest discovery on ' + hosts + '...' );
+ out.append( '
' );
+ $( '#' + statBarId ).find( 'div' ).append( out );
+
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'nodediscoverls',
+ tgt : '',
+ args : '-t||zvm||--zvmhost||' + hosts,
+ att : '',
+ msg : statBarId
+ },
+ success: function(data) {
+ updateDiscoverStatusBar( data, 1 );
+ }
+ });
+ });
+ discoverVMNodesForm.append( listBtn );
+
+ // Stop button
+ var stopBtn = createButton('Stop');
+ stopBtn.click(function() {
+ var hosts = $(this).parent().find('input[name=hosts]').val();
+ var out = $('
');
+ out.append( 'Stopping discovery on ' + hosts + '...' );
+ out.append( '
' );
+ $( '#' + statBarId ).find( 'div' ).append( out );
+
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'nodediscoverstop',
+ tgt : '',
+ args : '--zvmhost||' + hosts,
+ att : '',
+ msg : statBarId
+ },
+ success: function(data) {
+ updateDiscoverStatusBar( data, 1 );
+ }
+ });
+ });
+ discoverVMNodesForm.append( stopBtn );
+
+ // Append to discover tab
+ tab.add(newTabId, 'Discover', discoverVMNodesForm, true);
+
+ // Select new tab
+ tab.select(newTabId);
+}
+
+
+/**
+ * Update discovery status bar
+ *
+ * @param data Data returned from HTTP request
+ */
+function updateDiscoverStatusBar( data, preformatted ) {
+ var statBarId = data.msg;
+ var rsp = data.rsp;
+ var statBar = $( '#' + statBarId );
+
+ // Go through response to make it readable in the status bar.
+ var out = $('
');
+ for ( var i in rsp ) {
+ if ( preformatted == 1 ) {
+ out.append( '
' + rsp[i] + ' ' );
+ } else {
+ out.append( rsp[i] + '
' );
+ }
+ }
+
+ // Write response to status bar and show the bar.
+ $( '#' + statBarId ).find( 'div' ).append( out );
+ statBar.show();
+}
+
/**
* Load set node properties page
- *
+ *
* @param tgtNode Target node to set properties
*/
function editNodeProps(tgtNode) {
@@ -2793,17 +3725,17 @@ function editNodeProps(tgtNode) {
} else {
value = '';
}
-
+
// Create label and input for attribute
- div = $('
').css('display', 'inline-table');
+ div = $('
').css('display', 'inline-table');
label = $('
' + key + ': ').css('vertical-align', 'middle');
input = $('
').css('margin-top', '5px');
-
+
// Change border to blue onchange
input.bind('change', function(event) {
$(this).css('border-color', 'blue');
});
-
+
div.append(label);
div.append(input);
editPropsForm.append(div);
@@ -2814,7 +3746,7 @@ function editNodeProps(tgtNode) {
'display': 'block',
'margin': '0px 0px 10px 0px'
});
-
+
// Generate tooltips
editPropsForm.find('div input[title]').tooltip({
position: "center right",
@@ -2833,10 +3765,10 @@ function editNodeProps(tgtNode) {
// Save changes
var saveBtn = createButton('Save');
- saveBtn.click(function() {
+ saveBtn.click(function() {
// Get all inputs
var inputs = $('#' + newTabId + ' input');
-
+
// Go through each input
var args = '';
var attrName, attrVal;
@@ -2845,11 +3777,11 @@ function editNodeProps(tgtNode) {
if ($(this).css('border-left-color') == 'rgb(0, 0, 255)') {
// Change border color back to normal
$(this).css('border-color', '');
-
+
// Get attribute name and value
attrName = $(this).parent().find('label').text().replace(':', '');
attrVal = $(this).val();
-
+
// Build argument string
if (args) {
// Handle subsequent arguments
@@ -2860,7 +3792,7 @@ function editNodeProps(tgtNode) {
}
}
});
-
+
// Send command to change node attributes
$.ajax( {
url : 'lib/cmd.php',
@@ -2876,7 +3808,7 @@ function editNodeProps(tgtNode) {
});
});
editPropsForm.append(saveBtn);
-
+
// Cancel changes
var cancelBtn = createButton('Cancel');
cancelBtn.click(function() {
@@ -2903,33 +3835,33 @@ function openSetAttrsDialog() {
// Create info bar
var infoBar = createInfoBar('Choose the properties you wish to change on the node. When you are finished, click Save.');
setPropsForm.append(infoBar);
-
+
// Create an input for each definable attribute
var div, label, input, descr, value;
for (var key in nodeAttrs) {
value = '';
-
+
// Create label and input for attribute
div = $('
').css('display', 'inline');
label = $('
' + key + ': ').css('vertical-align', 'middle');
input = $('
').css('margin-top', '5px');
-
+
// Change border to blue onchange
input.bind('change', function(event) {
$(this).css('border-color', 'blue');
});
-
+
div.append(label);
div.append(input);
setPropsForm.append(div);
}
-
+
// Change style for last division
div.css({
'display': 'block',
'margin': '0px 0px 10px 0px'
});
-
+
// Generate tooltips
setPropsForm.find('div input[title]').tooltip({
position: "center right",
@@ -2950,10 +3882,10 @@ function openSetAttrsDialog() {
this.getTip().css('z-index', $.topZIndex());
}
});
-
+
// Enable vertical scroll
setPropsForm.css('overflow', 'auto');
-
+
// Open form as a dialog
setPropsForm.dialog({
title: 'Set attributes',
@@ -2967,10 +3899,10 @@ function openSetAttrsDialog() {
"Save": function() {
// Remove any warning messages
$(this).find('.ui-state-error').remove();
-
+
// Get all inputs
var inputs = $(this).find('input');
-
+
// Go through each input
var args = '';
var tgtNode, attrName, attrVal;
@@ -2979,11 +3911,11 @@ function openSetAttrsDialog() {
if ($(this).css('border-left-color') == 'rgb(0, 0, 255)') {
// Change border color back to normal
$(this).css('border-color', '');
-
+
// Get attribute name and value
attrName = $(this).parent().find('label').text().replace(':', '');
attrVal = $(this).val();
-
+
// Get node name
if (attrName == 'node') {
tgtNode = attrVal;
@@ -2999,7 +3931,7 @@ function openSetAttrsDialog() {
}
}
});
-
+
// Send command to change node attributes
$.ajax( {
url : 'lib/cmd.php',
@@ -3013,7 +3945,7 @@ function openSetAttrsDialog() {
/**
* Show results
- *
+ *
* @param data
* Data returned from HTTP request
* @return Nothing
@@ -3022,7 +3954,7 @@ function openSetAttrsDialog() {
// Get output
var out = data.rsp;
var node = data.msg.replace('node=', '');
-
+
// Go through output and append to paragraph
var msg = '';
for (var i in out) {
@@ -3032,11 +3964,11 @@ function openSetAttrsDialog() {
msg += '
' + node + ': ' + out[i];
}
}
-
+
openDialog('info', msg);
}
});
-
+
// Close dialog
$(this).dialog( "close" );
},
@@ -3049,7 +3981,7 @@ function openSetAttrsDialog() {
/**
* Turn on monitoring for a given node
- *
+ *
* @param node Node to monitor on or off
* @param monitor Monitor state, on or off
*/
@@ -3057,7 +3989,7 @@ function monitorNode(node, monitor) {
// Show ganglia loader
var gangliaCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
gangliaCol.find('img').show();
-
+
if (monitor == 'on') {
// Append loader to warning bar
var warningBar = $('#nodesTab').find('.ui-state-error p');
@@ -3079,7 +4011,7 @@ function monitorNode(node, monitor) {
/**
* Start ganglia on a given node range
- *
+ *
* @param data Data returned from HTTP request
*/
success : function(data) {
@@ -3093,7 +4025,7 @@ function monitorNode(node, monitor) {
// If an RPM is not installed
if (out[i].indexOf('not installed') > -1) {
warn = true;
-
+
if (warningMsg) {
warningMsg += '
' + out[i];
} else {
@@ -3101,7 +4033,7 @@ function monitorNode(node, monitor) {
}
}
}
-
+
// If there are warnings
if (warn) {
// Create warning bar
@@ -3122,7 +4054,7 @@ function monitorNode(node, monitor) {
success : function(data) {
// Remove any warnings
$('#nodesTab').find('.ui-state-error').remove();
-
+
// Update datatable
$.ajax( {
url : 'lib/cmd.php',
@@ -3187,20 +4119,20 @@ function monitorNode(node, monitor) {
/**
* Install Ganglia on a given node
- *
+ *
* @param node Node to install Ganglia on
*/
function installGanglia(node) {
var iframe = createIFrame('lib/cmd.php?cmd=webrun&tgt=&args=installganglia;' + node + '&msg=' + node + '&opts=flush');
iframe.prependTo($('#nodesTab'));
-
+
// Turn on Ganglia for node
monitorNode(node, 'on');
}
/**
- * After nodes are loaded, load more information based on different hardware architectures
- *
+ * After nodes are loaded, load more information based on different hardware architectures
+ *
* @param group Group name
*/
function advancedLoad(group){
@@ -3209,7 +4141,7 @@ function advancedLoad(group){
var colNameHash = new Object();
var colName = '';
var archCol = 0, hcpCol = 0;
-
+
// Find out the column name and their index
for (tempIndex = 0; tempIndex < tableHeaders.size(); tempIndex++){
var header = tableHeaders.eq(tempIndex);
@@ -3217,25 +4149,25 @@ function advancedLoad(group){
if (header.find('a').size() > 0){
continue;
}
-
+
colName = header.text();
-
+
if (colName) {
colNameHash[colName] = tempIndex;
}
}
-
+
// If there is no arch column, exit because you cannot distinguish hardware type
if (!colNameHash['arch']) {
return;
}
-
+
if (!colNameHash['hcp']) {
return;
}
archCol = colNameHash['arch'];
hcpCol = colNameHash['hcp'];
-
+
// Get hardware control point
var rows = $('#' + nodesTableId + ' tbody tr');
var hcps = new Object();
@@ -3249,13 +4181,26 @@ function advancedLoad(group){
hcps[val] = 1;
}
+ if (Object.keys(hcps).length == 0) {
+ openDialog('warn', "No node found with hcp column filled in and 390 arch!");
+ return;
+ }
+ // Get Nodes info bar
+ //var nodeInfoBar = getNodesTabInfoBar();
+ //nodeInfoBar.append("\nEntering Advanced Load...\n")
+
var args;
var shortzHcps = new Array();
+ var zhcpHash = new Object();
for (var h in hcps) {
// Get node without domain name
args = h.split('.');
- shortzHcps.push(args[0]);
-
+
+ if (!zhcpHash[args[0]]) {
+
+ shortzHcps.push(args[0]);
+ zhcpHash[args[0]] = 1;
+
// If there are no disk pools or network names cookie for this hcp
if (!$.cookie(args[0] + 'diskpools') || !$.cookie(args[0] + 'networks')) {
// Check if SMAPI is online
@@ -3273,12 +4218,13 @@ function advancedLoad(group){
// Get disk pools and network names
success : loadHcpInfo
});
+ }
}
} // End of for
-
+
// Save zHCPs as a cookie
setzHcpCookies(shortzHcps);
-
+
// Retrieve z/VM hypervisors and their zHCPs
if (!$.cookie('zvms')) {
$.ajax( {
@@ -3300,7 +4246,7 @@ function advancedLoad(group){
/**
* Jump to provision page on-click
- *
+ *
* @param tgtNodes Target nodes
*/
function jump2Provision(tgtNodes){
@@ -3313,21 +4259,21 @@ function jump2Provision(tgtNodes){
var tftpserver = '';
var nfsserver = '';
var diaDiv = $('
');
-
+
// Check the first node's arch type
for (index in nodeArray){
nodeName = nodeArray[index];
-
+
// Skip if node does not have arch
if (!origAttrs[nodeName]['arch']){
errorMsg = 'Nodes should have arch defined! ';
break;
}
-
+
if (index == 0) {
archType = origAttrs[nodeName]['arch'];
}
-
+
// Skip if nodes do not have same arch
if (archType != origAttrs[nodeName]['arch']){
errorMsg = 'Nodes should belong to the same arch!
';
@@ -3342,11 +4288,11 @@ function jump2Provision(tgtNodes){
break;
}
}
-
+
if (archType.indexOf('390') != -1) {
errorMsg += 'Please use the provision page';
}
-
+
// Open dialog to show error message
if (errorMsg){
diaDiv.append(createWarnBar(errorMsg));
@@ -3362,22 +4308,22 @@ function jump2Provision(tgtNodes){
}
}
});
-
+
return;
}
-
+
if (origAttrs[nodeName]['xcatmaster']) {
master = origAttrs[nodeName]['xcatmaster'];
}
-
+
if (origAttrs[nodeName]['tftpserver']) {
tftpserver = origAttrs[nodeName]['tftpserver'];
}
-
+
if (origAttrs[nodeName]['nfsserver']) {
nfsserver = origAttrs[nodeName]['nfsserver'];
}
-
+
window.location.href = 'provision.php?nodes=' + tgtNodes + '&arch=' + archType + '&master=' + master +
'&tftpserver=' + tftpserver + '&nfsserver=' + nfsserver;
}
\ No newline at end of file
diff --git a/xCAT-UI/js/nodes/nodeset.js b/xCAT-UI/js/nodes/nodeset.js
index a03820398..aea3ea310 100644
--- a/xCAT-UI/js/nodes/nodeset.js
+++ b/xCAT-UI/js/nodes/nodeset.js
@@ -1,6 +1,6 @@
/**
* Load nodeset page
- *
+ *
* @param tgtNodes Targets to run nodeset against
*/
function loadNodesetPage(tgtNodes) {
@@ -29,7 +29,7 @@ function loadNodesetPage(tgtNodes) {
inst = inst + 1;
tabId = 'nodesetTab' + inst;
}
-
+
// Create nodeset form
var nodesetForm = $('
');
@@ -44,23 +44,23 @@ function loadNodesetPage(tgtNodes) {
// Create info bar
var infoBar = createInfoBar('Set the boot state for a node range');
nodesetForm.append(statBar, infoBar);
-
+
// Create VM fieldset
var vmFS = $('
');
var vmLegend = $('
Virtual Machine ');
vmFS.append(vmLegend);
nodesetForm.append(vmFS);
-
+
var vmAttr = $('
');
vmFS.append($('
'));
vmFS.append(vmAttr);
-
+
// Create options fieldset
var imageFS = $('
');
var imageLegend = $('
Image ');
imageFS.append(imageLegend);
nodesetForm.append(imageFS);
-
+
var imageAttr = $('
');
imageFS.append($('
'));
imageFS.append(imageAttr);
@@ -68,7 +68,7 @@ function loadNodesetPage(tgtNodes) {
// Create target node or group
var tgt = $('
Target node range:
');
vmAttr.append(tgt);
-
+
// Create boot type drop down
var type = $('
');
var typeLabel = $('
Boot type: ');
@@ -80,13 +80,13 @@ function loadNodesetPage(tgtNodes) {
type.append(typeLabel);
type.append(typeSelect);
imageAttr.append(type);
-
+
// Create operating system image input
var os = $('
');
var osLabel = $('
Operating system image: ');
var osSelect = $('
');
osSelect.append($('
'));
-
+
var imageNames = $.cookie('imagenames').split(',');
if (imageNames) {
imageNames.sort();
@@ -112,7 +112,7 @@ function loadNodesetPage(tgtNodes) {
tooltip : "mouseover,mouseout"
}
});
-
+
/**
* Ok
*/
@@ -124,7 +124,7 @@ function loadNodesetPage(tgtNodes) {
okBtn.bind('click', function(event) {
// Remove any warning messages
$(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
-
+
// Check state, OS, arch, and profile
var ready = true;
var inputs = $('#' + tabId + ' input');
@@ -139,7 +139,7 @@ function loadNodesetPage(tgtNodes) {
if (ready) {
// Get nodes
- var tgts = $('#' + tabId + ' input[name=target]').val();
+ var tgts = $('#' + tabId + ' input[name=target]').val();
// Get boot type
var type = $('#' + tabId + ' select[id=bootType]').val();
// Get operating system image
@@ -185,7 +185,7 @@ function loadNodesetPage(tgtNodes) {
/**
* Update nodeset status
- *
+ *
* @param data Data returned from HTTP request
*/
function updateNodesetStatus(data) {
@@ -217,7 +217,7 @@ function updateNodesetStatus(data) {
// Create target nodes string
var tgtNodesStr = '';
var nodes = tgts.split(',');
-
+
// Loop through each node
for ( var i in nodes) {
// If it is the 1st and only node
@@ -239,7 +239,7 @@ function updateNodesetStatus(data) {
}
}
}
-
+
$('#' + statBarId).find('div').append('
Node definition created for ' + tgtNodesStr + ' ');
$.ajax( {
url : 'lib/cmd.php',
@@ -267,53 +267,7 @@ function updateNodesetStatus(data) {
$('#' + statBarId).find('div').append('
/etc/hosts updated ');
}
- // Update DNS
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'makedns',
- tgt : '',
- args : '',
- msg : 'cmd=makedns;inst=' + inst
- },
-
- success : updateNodesetStatus
- });
- }
-
- /**
- * (5) Update DHCP
- */
- else if (cmd == 'makedns') {
- // Write ajax response to status bar
- var prg = writeRsp(rsp, '');
- $('#' + statBarId).find('div').append(prg);
-
- // Update DHCP
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'makedhcp',
- tgt : '',
- args : '-a',
- msg : 'cmd=makedhcp;inst=' + inst
- },
-
- success : updateNodesetStatus
- });
- }
-
- /**
- * (6) Prepare node for boot
- */
- else if (cmd == 'makedhcp') {
- // Write ajax response to status bar
- var prg = writeRsp(rsp, '');
- $('#' + statBarId).find('div').append(prg);
-
- // Prepare node for boot
+ // Go straight to prepare node for boot
$.ajax( {
url : 'lib/cmd.php',
dataType : 'json',
@@ -329,12 +283,12 @@ function updateNodesetStatus(data) {
}
/**
- * (7) Boot node from network
+ * (5) Boot node from network
*/
else if (cmd == 'nodeset') {
// Write ajax response to status bar
- var prg = writeRsp(rsp, '');
- $('#' + statBarId).find('div').append(prg);
+ var prg = writeRsp(rsp, '');
+ $('#' + statBarId).find('div').append(prg);
// Hide loader
$('#' + statBarId).find('img').hide();
diff --git a/xCAT-UI/js/provision/images.js b/xCAT-UI/js/provision/images.js
index b7962c63d..59ad4c467 100644
--- a/xCAT-UI/js/provision/images.js
+++ b/xCAT-UI/js/provision/images.js
@@ -23,7 +23,7 @@ var softwareList = {
function loadImagesPage() {
// Set padding for images page
$('#imagesTab').css('padding', '20px 60px');
-
+
// Get images within the database
$.ajax( {
url : 'lib/cmd.php',
@@ -41,7 +41,7 @@ function loadImagesPage() {
/**
* Load images within the database
- *
+ *
* @param data Data returned from HTTP request
*/
function loadImages(data) {
@@ -50,12 +50,12 @@ function loadImages(data) {
if (rsp[0].indexOf('Could not find any object definitions') > -1) {
rsp = new Array();
}
-
+
// Image attributes hash
var attrs = new Object();
// Image attributes
var headers = new Object();
-
+
// Clear hash table containing image attributes
origAttrs = '';
@@ -82,7 +82,7 @@ function loadImages(data) {
attrs[image][key] = val;
headers[key] = 1;
}
-
+
// Save attributes in hash table
origAttrs = attrs;
@@ -108,7 +108,7 @@ function loadImages(data) {
var checkBx = '
';
// Push in checkbox and image name
row.push(checkBx, img);
-
+
// Go through each header
for (var i = 2; i < sorted.length; i++) {
// Add the node attributes to the row
@@ -127,7 +127,7 @@ function loadImages(data) {
// Clear the tab before inserting the table
$('#imagesTab').children().remove();
-
+
// Create info bar for images tab
var info = createInfoBar('Double click on a cell to edit. Click outside the table to save changes. Hit the Escape key to ignore changes.');
$('#imagesTab').append(info);
@@ -142,13 +142,13 @@ function loadImages(data) {
copyCDLnk.click(function() {
openCopyCdDialog();
});
-
+
// Generate stateless or statelite image
var generateLnk = $('
Generate image ');
generateLnk.click(function() {
loadCreateImage();
});
-
+
// Edit image attributes
var editLnk = $('
Edit ');
editLnk.click(function() {
@@ -159,22 +159,22 @@ function loadImages(data) {
}
}
});
-
+
// Add a row
var addLnk = $('
Add ');
addLnk.click(function() {
openAddImageDialog();
});
-
+
// Remove a row
var removeLnk = $('
Remove ');
removeLnk.click(function() {
var images = getNodesChecked(imgTableId);
if (images) {
confirmImageDeleteDialog(images);
- }
+ }
});
-
+
// Refresh image table
var refreshLnk = $('
Refresh ');
refreshLnk.click(function() {
@@ -192,7 +192,7 @@ function loadImages(data) {
success : loadImages
});
});
-
+
// Insert table
$('#imagesTab').append(dTable.object());
@@ -211,12 +211,12 @@ function loadImages(data) {
}
}
});
-
+
// Set datatable width
$('#' + imgTableId + '_wrapper').css({
'width': '880px'
});
-
+
// Actions
var actionBar = $('
').css("width", "450px");
var advancedLnk = '
Advanced ';
@@ -227,50 +227,50 @@ function loadImages(data) {
actionsMenu.superfish();
actionsMenu.css('display', 'inline-block');
actionBar.append(actionsMenu);
-
+
// Set correct theme for action menu
actionsMenu.find('li').hover(function() {
setMenu2Theme($(this));
}, function() {
setMenu2Normal($(this));
});
-
+
// Create a division to hold actions menu
var menuDiv = $('');
$('#' + imgTableId + '_wrapper').prepend(menuDiv);
- menuDiv.append(actionBar);
+ menuDiv.append(actionBar);
$('#' + imgTableId + '_filter').appendTo(menuDiv);
-
+
/**
* Enable editable columns
*/
-
+
// Do not make 1st or 2nd columns editable
$('#' + imgTableId + ' td:not(td:nth-child(1),td:nth-child(2))').editable(
- function(value, settings) {
+ function(value, settings) {
// Get column index
var colPos = this.cellIndex;
-
+
// Get row index
var dTable = $('#' + imgTableId).dataTable();
var rowPos = dTable.fnGetPosition(this.parentNode);
-
+
// Update datatable
dTable.fnUpdate(value, rowPos, colPos);
-
+
// Get image name
var image = $(this).parent().find('td:eq(1)').text();
-
+
// Get table headers
var headers = $('#' + imgTableId).parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th');
// Get attribute name
var attrName = jQuery.trim(headers.eq(colPos).text());
// Get column value
- var value = $(this).text();
+ var value = $(this).text();
// Build argument
var args = attrName + '=' + value;
-
+
// Send command to change image attributes
$.ajax( {
url : 'lib/cmd.php',
@@ -293,7 +293,7 @@ function loadImages(data) {
event : "dblclick", // Double click and edit
height : '30px' // The height of the text area
});
-
+
// Get definable node attributes
$.ajax( {
url : 'lib/cmd.php',
@@ -311,7 +311,7 @@ function loadImages(data) {
/**
* Open dialog to confirm deleting image
- *
+ *
* @param images Comma delimited image names
*/
function confirmImageDeleteDialog(images) {
@@ -321,7 +321,7 @@ function confirmImageDeleteDialog(images) {
var confirmDialog = $('
'
+ '
Are you sure you want to remove ' + tmp + '?
'
+ '
');
-
+
// Open dialog to confirm delete
confirmDialog.dialog({
modal: true,
@@ -331,12 +331,12 @@ function confirmImageDeleteDialog(images) {
title: 'Confirm',
width: 500,
buttons: {
- "Ok": function(){
+ "Ok": function(){
// Change dialog buttons
$(this).dialog('option', 'buttons', {
'Close': function() {$(this).dialog("close");}
});
-
+
// Add image to xCAT
$.ajax( {
url : 'lib/cmd.php',
@@ -351,7 +351,7 @@ function confirmImageDeleteDialog(images) {
success : updateImageDialog
});
},
- "Cancel": function(){
+ "Cancel": function(){
$(this).dialog("close");
}
}
@@ -365,32 +365,32 @@ function openAddImageDialog() {
// Create dialog to add image
var dialogId = 'addImage';
var addImageForm = $('
');
-
+
// Create info bar
var info = createInfoBar('Provide the following attributes for the image. The image name will be generated based on the attributes you will give.');
-
+
var imageFS = $('
');
var imageLegend = $('
Image ');
imageFS.append(imageLegend);
var imageAttr = $('
');
imageFS.append($('
'));
imageFS.append(imageAttr);
-
+
var optionFS = $('
');
var optionLegend = $('
Options ');
optionFS.append(optionLegend);
var optionAttr = $('
');
optionFS.append($('
'));
optionFS.append(optionAttr);
-
+
addImageForm.append(info, imageFS, optionFS);
-
+
// Create inputs for image attributes
var imageName = $('
Image name:
');
var imageType = $('
Image type:
');
- var architecture = $('
OS architecture:
');
+ var architecture = $('
OS architecture:
');
var osName = $('
OS name:
');
- var osVersion = $('
OS version:
');
+ var osVersion = $('
OS version:
');
var profile = $('
Profile:
');
var provisionMethod = $('
Provision method:
');
var provisionSelect = $('
'
@@ -400,7 +400,7 @@ function openAddImageDialog() {
+ 'statelite '
+ ' ');
provisionMethod.append(provisionSelect);
-
+
// Create inputs for optional attributes
var otherpkgDirectory = $('
Other package directory:
');
var otherpkgDirectoryInput = $('
');
@@ -498,10 +498,10 @@ function openAddImageDialog() {
height : '300',
basePath : '/install' // Limit user to only install directory
});
-
+
imageAttr.append(imageName, imageType, architecture, osName, osVersion, profile, provisionMethod);
optionAttr.append(otherpkgDirectory, packageDirectory, packageList, template);
-
+
// Generate tooltips
addImageForm.find('div input[title],select[title]').tooltip({
position: "center right",
@@ -522,7 +522,7 @@ function openAddImageDialog() {
this.getTip().css('z-index', $.topZIndex());
}
});
-
+
// Open dialog to add image
addImageForm.dialog({
title:'Add image',
@@ -536,7 +536,7 @@ function openAddImageDialog() {
"Ok": function(){
// Remove any warning messages
$(this).find('.ui-state-error').remove();
-
+
// Get image attributes
var imageType = $(this).find('input[name="imagetype"]');
var architecture = $(this).find('input[name="osarch"]');
@@ -544,13 +544,13 @@ function openAddImageDialog() {
var osVersion = $(this).find('input[name="osvers"]');
var profile = $(this).find('input[name="profile"]');
var provisionMethod = $(this).find('select[name="provmethod"]');
-
+
// Get optional image attributes
var otherpkgDirectory = $(this).find('input[name="otherpkgdir"]');
var pkgDirectory = $(this).find('input[name="pkgdir"]');
var pkgList = $(this).find('input[name="pkglist"]');
var template = $(this).find('input[name="template"]');
-
+
// Check that image attributes are provided before continuing
var ready = 1;
var inputs = new Array(imageType, architecture, osName, osVersion, profile, provisionMethod);
@@ -561,7 +561,7 @@ function openAddImageDialog() {
} else
inputs[i].css('border-color', '');
}
-
+
// If inputs are not complete, show warning message
if (!ready) {
var warn = createWarnBar('Please provide a value for each missing field.');
@@ -570,12 +570,12 @@ function openAddImageDialog() {
// Override image name
$(this).find('input[name="imagename"]').val(osVersion.val() + '-' + architecture.val() + '-' + provisionMethod.val() + '-' + profile.val());
var imageName = $(this).find('input[name="imagename"]');
-
+
// Change dialog buttons
$(this).dialog('option', 'buttons', {
'Close': function() {$(this).dialog("close");}
});
-
+
// Create arguments to send via AJAX
var args = '-t;osimage;-o;' + imageName.val() + ';' +
'imagetype=' + imageType.val() + ';' +
@@ -584,7 +584,7 @@ function openAddImageDialog() {
'osvers=' + osVersion.val() + ';' +
'profile=' + profile.val() + ';' +
'provmethod=' + provisionMethod.val();
-
+
// Get optional attributes
if (otherpkgDirectory.val())
args += ';otherpkgdir=' + otherpkgDirectory.val();
@@ -594,7 +594,7 @@ function openAddImageDialog() {
args += ';pkglist=' + pkgList.val();
if (template.val())
args += ';template=' + template.val();
-
+
// Add image to xCAT
$.ajax( {
url : 'lib/cmd.php',
@@ -605,7 +605,7 @@ function openAddImageDialog() {
args : args,
msg : dialogId
},
-
+
success : updateImageDialog
});
}
@@ -619,40 +619,40 @@ function openAddImageDialog() {
/**
* Update image dialog
- *
+ *
* @param data HTTP request data
*/
-function updateImageDialog(data) {
+function updateImageDialog(data) {
var dialogId = data.msg;
var infoMsg;
-
+
// Delete loader if one does exist
$('.ui-dialog #' + dialogId + ' img[src="images/loader.gif"]').remove();
// Create info message
if (jQuery.isArray(data.rsp)) {
infoMsg = '';
-
+
// If the data returned is more than 10 lines, get only the last line
var i, start;
if (data.rsp.length > 10)
start = data.rsp.length - 1;
else
start = 0;
-
+
for (i = start; i < data.rsp.length; i++)
infoMsg += data.rsp[i] + '';
} else {
infoMsg = data.rsp;
}
-
+
// Create info bar with close button
var infoBar = $('
').css('margin', '5px 0px');
var icon = $('
').css({
'display': 'inline-block',
'margin': '10px 5px'
});
-
+
// Create close button to close info bar
var close = $('
').css({
'display': 'inline-block',
@@ -660,25 +660,25 @@ function updateImageDialog(data) {
}).click(function() {
$(this).parent().remove();
});
-
+
var msg = $('
' + infoMsg + '
').css({
'display': 'inline-block',
'width': '90%'
});
-
- infoBar.append(icon, msg, close);
+
+ infoBar.append(icon, msg, close);
infoBar.prependTo($('.ui-dialog #' + dialogId));
}
/**
* Set definable image attributes
- *
+ *
* @param data Data returned from HTTP request
*/
function setImageDefAttrs(data) {
// Clear hash table containing definable image attributes
defAttrs = new Array();
-
+
// Get definable attributes
var attrs = data.rsp[2].split(/\n/);
@@ -686,19 +686,19 @@ function setImageDefAttrs(data) {
var attr, key, descr;
for (var i in attrs) {
attr = attrs[i];
-
+
// If the line is not empty
if (attr) {
- // If the line has the attribute name
+ // If the line has the attribute name
if (attr.indexOf(':') && attr.indexOf(' ')) {
// Get attribute name and description
key = jQuery.trim(attr.substring(0, attr.indexOf(':')));
descr = jQuery.trim(attr.substring(attr.indexOf(':') + 1));
descr = descr.replace(new RegExp('<', 'g'), '[').replace(new RegExp('>', 'g'), ']');
-
+
// Set hash table where key = attribute name and value = description
defAttrs[key] = descr;
- } else {
+ } else {
// Append description to hash table
defAttrs[key] = defAttrs[key] + '\n' + attr.replace(new RegExp('<', 'g'), '[').replace(new RegExp('>', 'g'), ']');
}
@@ -713,7 +713,7 @@ function loadCreateImage() {
// Get nodes tab
var tab = getProvisionTab();
var tabId = 'createImageTab';
-
+
// Generate new tab ID
if ($('#' + tabId).size()) {
tab.select(tabId);
@@ -723,7 +723,7 @@ function loadCreateImage() {
var imageOsVers = $.cookie("osvers").split(",");
var imageArch = $.cookie("osarchs").split(",");
var profiles = $.cookie("profiles").split(",");
-
+
var createImgForm = $('
');
var createImgFS = $('
').append('
Create Image ');
createImgForm.append(createImgFS);
@@ -746,20 +746,20 @@ function loadCreateImage() {
// Netboot interface input
createImgFS.append($('
Netboot interface:
'));
-
+
// Profile selector
var profileSelect = $('
');
for (var i in profiles)
profileSelect.append('' + profiles[i] + ' ');
createImgFS.append($('Profile:
').append(profileSelect));
-
+
// Boot method drop down
createImgFS.append($('Boot method: ' +
'' +
- 'stateless ' +
- 'statelite ' +
+ 'stateless ' +
+ 'statelite ' +
'
'));
-
+
// Create HPC software stack fieldset
createHpcFS(createImgForm);
@@ -770,25 +770,25 @@ function loadCreateImage() {
});
createImgForm.append(createImageBtn);
-
+
// Add tab
tab.add(tabId, 'Create', createImgForm, true);
tab.select(tabId);
// Check the selected OS version and OS arch for HPC stack
// If they are valid, show the HCP stack fieldset
- hpcShow();
+ hpcShow();
}
/**
* Create HPC fieldset
- *
+ *
* @param container The container to hold the HPC fieldset
*/
function createHpcFS(container) {
var hpcFieldset = $(' ');
hpcFieldset.append('HPC Software Stack ');
-
+
var str = 'Before selecting the software, you should have the following already completed on your xCAT cluster: '
+ '1. If you are using the xCAT hierarchy, your service nodes are installed and running. '
+ '2. Your compute nodes are defined in xCAT, and you have verified your hardware control capabilities, '
@@ -797,12 +797,12 @@ function createHpcFS(container) {
+ '4. You should install the software on the management node and copy all correponding packages into the location "/install/custom/otherpkgs/" based on '
+ 'these documents . ';
hpcFieldset.append(createInfoBar(str));
-
+
// Advanced software
str = '' +
'';
@@ -813,7 +813,7 @@ function createHpcFS(container) {
/**
* Check the dependance for ESSL and start the software check for ESSL
- *
+ *
* @param softwareObject The checkbox object of ESSL
*/
function esslCheck(softwareObject) {
@@ -821,11 +821,11 @@ function esslCheck(softwareObject) {
if (!$('#createImageTab input[name=pe]').attr('checked')) {
var warnBar = createWarnBar('You must first select the PE');
$(':checkbox[name=essl]').attr("checked", false);
-
+
// Clear existing warnings and append new warning
$('#hpcsoft .ui-state-error').remove();
$('#hpcsoft').prepend(warnBar);
-
+
return;
} else {
softwareCheck(softwareObject);
@@ -834,7 +834,7 @@ function esslCheck(softwareObject) {
/**
* Check the parameters for the HPC software
- *
+ *
* @param softwareObject Checkbox object of the HPC software
* @return True if the checkbox is checked, false otherwise
*/
@@ -869,14 +869,14 @@ function softwareCheck(softwareObject) {
/**
* Check if the RPMs are copied to the special location
- *
+ *
* @param data Data returned from HTTP request
*/
function rpmCopyCheck(data) {
// Remove the loading image
var errorStr = '';
var softwareName = data.msg;
-
+
// Check the return information
var reg = /.+:(.+): No such.*/;
var resultArray = data.rsp.split("\n");
@@ -891,7 +891,7 @@ function rpmCopyCheck(data) {
}
}
$('#createImageTab #' + softwareName + 'li').find('img').remove();
-
+
// No error, show the check image
if (!errorStr) {
var infoPart = '
';
@@ -901,7 +901,7 @@ function rpmCopyCheck(data) {
errorStr = 'To install the RSCT on your compute node. You should: ' + errorStr + ' ';
var warnBar = createWarnBar(errorStr);
$(':checkbox[name=' + softwareName + ']').attr("checked", false);
-
+
// Clear existing warnings and append new warning
$('#hpcsoft .ui-state-error').remove();
$('#hpcsoft').prepend(warnBar);
@@ -910,7 +910,7 @@ function rpmCopyCheck(data) {
/**
* Generate the RPM command for rpmcheck
- *
+ *
* @param softwareName The name of the software
* @return The RPM command
*/
@@ -924,13 +924,13 @@ function genRpmCmd(softwareName) {
for (var i in softwareList['base']) {
cmdString += softwareList['base'][i] + ' ';
}
-
+
return cmdString;
}
/**
* Check if the RPMs for the HPC software are copied to the special location
- *
+ *
* @param softwareName The name of the software
*/
function genLsCmd(softwareName) {
@@ -949,7 +949,7 @@ function genLsCmd(softwareName) {
/**
* Check if all RPMs are installed
- *
+ *
* @param checkInfo 'rpm -q' output
* @return True if all RPMs are installed, false otherwise
*/
@@ -969,7 +969,7 @@ function rpmCheck(checkInfo, name) {
errorStr = errorStr.substr(0, errorStr.length - 1);
$(':checkbox[name=' + name + ']').attr('checked', false);
-
+
// Add the error
var warnBar = createWarnBar(errorStr);
$('#createImageTab #' + name + 'li').find('img').remove();
@@ -977,7 +977,7 @@ function rpmCheck(checkInfo, name) {
// Clear existing warnings and append new warning
$('#hpcsoft .ui-state-error').remove();
$('#hpcsoft').prepend(warnBar);
-
+
return;
}
@@ -996,7 +996,7 @@ function hpcShow() {
/**
* Load set image properties page
- *
+ *
* @param tgtImage Target image to set properties
*/
function openEditImagePage(tgtImage) {
@@ -1033,7 +1033,7 @@ function openEditImagePage(tgtImage) {
} else {
value = '';
}
-
+
// Create label and input for attribute
div = $('
').css('display', 'inline');
label = $('
' + key + ': ').css('vertical-align', 'middle');
@@ -1042,17 +1042,17 @@ function openEditImagePage(tgtImage) {
'float': 'none',
'width': 'inherit'
});
-
+
// There is an element called groups that will override the defaults for the groups attribute.
// Hence, the input must have use CSS to override the float and width.
-
+
// Split attributes into 2 per row
if (attrIndex > 0 && !(attrIndex % 2)) {
div.css('display', 'inline-block');
}
-
+
attrIndex++;
-
+
// Create server browser
switch (key) {
case 'pkgdir':
@@ -1178,22 +1178,22 @@ function openEditImagePage(tgtImage) {
default:
// Do nothing
}
-
+
// Change border to blue onchange
input.bind('change', function(event) {
$(this).css('border-color', 'blue');
});
-
+
div.append(label, input);
setPropsForm.append(div);
}
-
+
// Change style for last division
div.css({
'display': 'block',
'margin': '0px 0px 10px 0px'
});
-
+
// Generate tooltips
setPropsForm.find('div input[title]').tooltip({
position: "center right",
@@ -1214,10 +1214,10 @@ function openEditImagePage(tgtImage) {
* Save
*/
var saveBtn = createButton('Save');
- saveBtn.bind('click', function(event) {
+ saveBtn.bind('click', function(event) {
// Get all inputs
var inputs = $('#' + newTabId + ' input');
-
+
// Go through each input
var args = '';
var attrName, attrVal;
@@ -1226,11 +1226,11 @@ function openEditImagePage(tgtImage) {
if ($(this).css('border-left-color') == 'rgb(0, 0, 255)') {
// Change border color back to normal
$(this).css('border-color', '');
-
+
// Get attribute name and value
attrName = $(this).parent().find('label').text().replace(':', '');
attrVal = $(this).val();
-
+
// Build argument string
if (args) {
// Handle subsequent arguments
@@ -1241,7 +1241,7 @@ function openEditImagePage(tgtImage) {
}
}
});
-
+
// Send command to change image attributes
$.ajax( {
url : 'lib/cmd.php',
@@ -1257,7 +1257,7 @@ function openEditImagePage(tgtImage) {
});
});
setPropsForm.append(saveBtn);
-
+
/**
* Cancel
*/
@@ -1278,15 +1278,15 @@ function openEditImagePage(tgtImage) {
/**
* Load copy CD page
*/
-function openCopyCdDialog() {
+function openCopyCdDialog() {
// Create copy Linux form
var dialogId = 'imageCopyCd';
var copyLinuxForm = $('
');
-
+
// Create info bar
var infoBar = createInfoBar('Copy Linux distributions and service levels from CDs or DVDs to the install directory.');
copyLinuxForm.append(infoBar);
-
+
// Create Linux ISO input
var iso = $('
');
var isoLabel = $('
Linux ISO/DVD: ').css('vertical-align', 'middle');
@@ -1294,12 +1294,12 @@ function openCopyCdDialog() {
iso.append(isoLabel);
iso.append(isoInput);
copyLinuxForm.append(iso);
-
+
// Create architecture input
- copyLinuxForm.append('
Architecture:
');
+ copyLinuxForm.append('
Architecture:
');
// Create distribution input
- copyLinuxForm.append('
Distribution:
');
-
+ copyLinuxForm.append('
Distribution:
');
+
/**
* Browse
*/
@@ -1328,7 +1328,7 @@ function openCopyCdDialog() {
height : '300',
basePath : '/install' // Limit user to only install directory
});
-
+
// Generate tooltips
copyLinuxForm.find('div input[title],select[title]').tooltip({
position: "center right",
@@ -1349,7 +1349,7 @@ function openCopyCdDialog() {
this.getTip().css('z-index', $.topZIndex());
}
});
-
+
// Open dialog to copy CD
copyLinuxForm.dialog({
title:'Copy CD',
@@ -1362,12 +1362,12 @@ function openCopyCdDialog() {
"Copy": function() {
// Show loader
$('.ui-dialog #imageCopyCd').append(createLoader(''));
-
+
// Change dialog buttons
$(this).dialog('option', 'buttons', {
'Close': function() {$(this).dialog("close");}
});
-
+
// Get image attributes
var iso = $(this).find('input[name="iso"]');
var arch = $(this).find('input[name="arch"]');
@@ -1383,7 +1383,7 @@ function openCopyCdDialog() {
args : '-n;' + distro.val() + ';-a;' + arch.val() + ';' + iso.val(),
msg : dialogId
},
-
+
success : updateImageDialog
});
},
@@ -1429,7 +1429,7 @@ function createImage() {
msg : ''
},
success : function(data) {
-
+
}
});
}
\ No newline at end of file
diff --git a/xCAT-UI/js/provision/provision.js b/xCAT-UI/js/provision/provision.js
index 4ec33dae2..a732f5653 100644
--- a/xCAT-UI/js/provision/provision.js
+++ b/xCAT-UI/js/provision/provision.js
@@ -5,7 +5,7 @@ var provisionTabs; // Provision tabs
/**
* Set the provision tab
- *
+ *
* @param obj Tab object
*/
function setProvisionTab(obj) {
@@ -14,7 +14,7 @@ function setProvisionTab(obj) {
/**
* Get the provision tab
- *
+ *
* @param Nothing
* @return Tab object
*/
@@ -63,10 +63,10 @@ function loadProvisionPage() {
success : setGroupsCookies
});
}
-
+
// Create info bar
var infoBar = createInfoBar('Select a platform to provision or re-provision a node on, then click Ok.');
-
+
// Create provision page
var provPg = $('
');
provPg.append(infoBar);
@@ -79,13 +79,13 @@ function loadProvisionPage() {
// Create radio buttons for platforms
var hwList = $('
Platforms available: ');
- var esx = $('
ESX');
- var kvm = $('
KVM');
- var zvm = $('
z\/VM');
- var ipmi = $('
iDataPlex');
- var blade = $('
BladeCenter');
- var hmc = $('
System p');
-
+ var esx = $('
ESX');
+ var kvm = $('
KVM');
+ var zvm = $('
z\/VM');
+ var ipmi = $('
iDataPlex');
+ var blade = $('
BladeCenter');
+ var hmc = $('
System p');
+
hwList.append(esx);
hwList.append(kvm);
hwList.append(zvm);
@@ -101,7 +101,7 @@ function loadProvisionPage() {
okBtn.bind('click', function(event) {
// Get hardware that was selected
var hw = $(this).parent().find('input[name="hw"]:checked').val();
-
+
var inst = 0;
var newTabId = hw + 'ProvisionTab' + inst;
while ($('#' + newTabId).length) {
@@ -109,7 +109,7 @@ function loadProvisionPage() {
inst = inst + 1;
newTabId = hw + 'ProvisionTab' + inst;
}
-
+
// Create an instance of the plugin
var title = '';
var plugin;
@@ -146,7 +146,7 @@ function loadProvisionPage() {
plugin.loadProvisionPage(newTabId);
});
provPg.append(okBtn);
-
+
// Create resources tab
var resrcPg = $('
');
@@ -156,20 +156,20 @@ function loadProvisionPage() {
// Create radio buttons for platforms
var rsrcHwList = $('
Platforms available: ');
- esx = $('
ESX');
- kvm = $('
KVM');
- zvm = $('
z\/VM');
- ipmi = $('
iDataPlex');
- blade = $('
BladeCenter');
- hmc = $('
System p');
-
+ esx = $('
ESX');
+ kvm = $('
KVM');
+ zvm = $('
z\/VM');
+ ipmi = $('
iDataPlex');
+ blade = $('
BladeCenter');
+ hmc = $('
System p');
+
rsrcHwList.append(esx);
rsrcHwList.append(kvm);
rsrcHwList.append(zvm);
rsrcHwList.append(blade);
rsrcHwList.append(ipmi);
rsrcHwList.append(hmc);
-
+
resrcPg.append(rsrcHwList);
var okBtn = createButton('Ok');
@@ -212,7 +212,7 @@ function loadProvisionPage() {
displayName = "z\/VM";
break;
}
-
+
// Add resource tab and load resources
tab.add(newTabId, displayName, loader, true);
plugin.loadResources();
@@ -221,8 +221,8 @@ function loadProvisionPage() {
// Select tab
tab.select(newTabId);
});
-
- resrcPg.append(okBtn);
+
+ resrcPg.append(okBtn);
// Add provision tab
tab.add('provisionTab', 'Provision', provPg, false);
@@ -230,21 +230,21 @@ function loadProvisionPage() {
tab.add('imagesTab', 'Images', '', false);
// Add resource tab
tab.add('resourceTab', 'Resources', resrcPg, false);
-
+
// Load tabs onselect
- $('#provisionPageTabs').bind('tabsselect', function(event, ui){
- // Load image page
+ $('#provisionPageTabs').bind('tabsselect', function(event, ui){
+ // Load image page
if (!$('#imagesTab').children().length && ui.index == 1) {
$('#imagesTab').append($('
').append(createLoader('')));
loadImagesPage();
}
});
-
+
// Open the quick provision tab
if (window.location.search) {
tab.add('quickProvisionTab', 'Quick Provision', '', true);
tab.select('quickProvisionTab');
-
+
var provForm = $('
');
$('#quickProvisionTab').append(provForm);
appendProvisionSection('quick', provForm);
diff --git a/xCAT-UI/js/service/service.js b/xCAT-UI/js/service/service.js
index 757d2cbdd..96be4c75a 100644
--- a/xCAT-UI/js/service/service.js
+++ b/xCAT-UI/js/service/service.js
@@ -1,2171 +1,2153 @@
-/**
- * Global variables
- */
-var serviceTabs;
-var nodeName;
-var nodePath;
-var nodeStatus;
-var gangliaTimer;
-
-/**
- * Initialize service page
- */
-function initServicePage() {
- // Load theme
- var theme = $.cookie('xcat_theme');
- if (theme) {
- switch (theme) {
- case 'cupertino':
- includeCss("css/themes/jquery-ui-cupertino.css");
- break;
- case 'dark_hive':
- includeCss("css/themes/jquery-ui-dark_hive.css");
- break;
- case 'redmond':
- includeCss("css/themes/jquery-ui-redmond.css");
- break;
- case 'start':
- includeCss("css/themes/jquery-ui-start.css");
- break;
- case 'sunny':
- includeCss("css/themes/jquery-ui-sunny.css");
- break;
- case 'ui_dark':
- includeCss("css/themes/jquery-ui-ui_darkness.css");
- break;
- default:
- includeCss("css/themes/jquery-ui-start.css");
- }
- } else {
- includeCss("css/themes/jquery-ui-start.css");
- }
-
- // Load jQuery stylesheets
- includeCss("css/jquery.dataTables.css");
- includeCss("css/superfish.css");
- includeCss("css/jstree.css");
- includeCss("css/jquery.jqplot.css");
-
- // Load custom stylesheet
- includeCss("css/style.css");
-
- // Reuqired JQuery plugins
- includeJs("js/jquery/jquery.dataTables.min.js");
- includeJs("js/jquery/jquery.cookie.min.js");
- includeJs("js/jquery/tooltip.min.js");
- includeJs("js/jquery/superfish.min.js");
- includeJs("js/jquery/jquery.jqplot.min.js");
- includeJs("js/jquery/jqplot.dateAxisRenderer.min.js");
-
- // Custom plugins
- includeJs("js/custom/esx.js");
- includeJs("js/custom/kvm.js");
- includeJs("js/custom/zvm.js");
-
- // Enable settings link
- $('#xcat_settings').click(function() {
- openSettings();
- });
-
- // Show service page
- $("#content").children().remove();
- includeJs("js/service/utils.js");
- loadServicePage();
-
- // Initialize tab index history
- $.cookie('tabindex_history', '0,0');
-}
-
-/**
- * Load service page
- */
-function loadServicePage() {
- // If the page is loaded
- if ($('#content').children().length) {
- // Do not load again
- return;
- }
-
- // Create manage and provision tabs
- serviceTabs = new Tab();
- serviceTabs.init();
- $('#content').append(serviceTabs.object());
-
- var manageTabId = 'manageTab';
- serviceTabs.add(manageTabId, 'Manage', '', false);
-
- // Get nodes owned by user
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'tabdump',
- tgt : '',
- args : 'nodetype',
- msg : ''
- },
-
- success : function(data) {
- setUserNodes(data);
- setMaxVM();
- getUserNodesDef();
- getNodesCurrentLoad();
- loadManagePage(manageTabId);
- }
- });
-
- // Get OS image names
- $.ajax({
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- async : true,
- data : {
- cmd : 'tabdump',
- tgt : '',
- args : 'osimage',
- msg : ''
- },
-
- success : function(data) {
- setOSImageCookies(data);
- }
- });
-
- // Get contents of hosts table
- $.ajax({
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- async : true,
- data : {
- cmd : 'tabdump',
- tgt : '',
- args : 'hosts',
- msg : ''
- },
-
- success : function(data) {
- setGroupCookies(data);
- }
- });
-
- var provTabId = 'provisionTab';
- serviceTabs.add(provTabId, 'Provision', '', false);
- loadServiceProvisionPage(provTabId);
-
- serviceTabs.select(manageTabId);
-}
-
-/**
- * Load the service portal's provision page
- *
- * @param tabId Tab ID where page will reside
- */
-function loadServiceProvisionPage(tabId) {
- // Create info bar
- var infoBar = createInfoBar('Select a platform to provision a node on, then click Ok.');
-
- // Create provision page
- var provPg = $('
');
- $('#' + tabId).append(infoBar, provPg);
-
- // Create radio buttons for platforms
- var hwList = $('
Platforms available: ');
- var esx = $('
ESX');
- var kvm = $('
KVM');
- var zvm = $('
z\/VM');
-
- hwList.append(esx);
- hwList.append(kvm);
- hwList.append(zvm);
- provPg.append(hwList);
-
- /**
- * Ok
- */
- var okBtn = createButton('Ok');
- okBtn.bind('click', function(event) {
- var userName = $.cookie('xcat_username');
- var tmp = $.cookie(userName + '_usrnodes');
-
- // Get maximun number for nodes from cookie
- var nodes = '';
- var maxVM = 0;
- if (tmp.length) {
- nodes = tmp.split(',');
- maxVM = parseInt($.cookie(userName + '_maxvm'));
-
- // Do not allow user to clone if the maximum number of VMs is reached
- if (nodes.length >= maxVM) {
- var warn = createWarnBar('You have reached the maximum number of virtual machines allowed (' + maxVM + '). Delete unused virtual machines or contact your system administrator request more virtual machines.');
- warn.prependTo($('#' + tabId));
- return;
- }
- }
-
- // Get hardware that was selected
- var hw = $(this).parent().find('input[name="hw"]:checked').val();
- var newTabId = hw + 'ProvisionTab';
-
- if ($('#' + newTabId).size() > 0){
- serviceTabs.select(newTabId);
- } else {
- var title = '';
-
- // Create an instance of the plugin
- var plugin = null;
- switch (hw) {
- case "kvm":
- plugin = new kvmPlugin();
- title = 'KVM';
- break;
- case "esx":
- plugin = new esxPlugin();
- title = 'ESX';
- break;
- case "blade":
- plugin = new bladePlugin();
- title = 'BladeCenter';
- break;
- case "hmc":
- plugin = new hmcPlugin();
- title = 'System p';
- break;
- case "ipmi":
- plugin = new ipmiPlugin();
- title = 'iDataPlex';
- break;
- case "zvm":
- plugin = new zvmPlugin();
- title = 'z/VM';
-
- // Get zVM host names
- $.ajax({
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- async : false,
- data : {
- cmd : 'webportal',
- tgt : '',
- args : 'lszvm',
- msg : ''
- },
-
- success : function(data) {
- setzVMCookies(data);
- }
- });
-
- // Get master copies for clone
- $.ajax({
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- async : false,
- data : {
- cmd : 'webportal',
- tgt : '',
- args : 'lsgoldenimages',
- msg : ''
- },
-
- success : function(data) {
- setGoldenImagesCookies(data);
- }
- });
-
- break;
- }
-
- // Select tab
- serviceTabs.add(newTabId, title, '', true);
- serviceTabs.select(newTabId);
- plugin.loadServiceProvisionPage(newTabId);
- }
- });
- provPg.append(okBtn);
-}
-
-/**
- * Load manage page
- *
- * @param tabId Tab ID where page will reside
- */
-function loadManagePage(tabId) {
- // Create manage form
- var manageForm = $('
');
-
- // Append to manage tab
- $('#' + tabId).append(manageForm);
-}
-
-/**
- * Get the user nodes definitions
- */
-function getUserNodesDef() {
- var userName = $.cookie('xcat_username');
- var userNodes = $.cookie(userName + '_usrnodes');
- if (userNodes) {
- // Get nodes definitions
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'lsdef',
- tgt : '',
- args : userNodes,
- msg : ''
- },
-
- success : loadNodesTable
- });
- } else {
- // Clear the tab before inserting the table
- $('#manageTab').append(createWarnBar('No nodes were found belonging to you!'));
- }
-}
-
-/**
- * Load user nodes definitions into a table
- *
- * @param data Data from HTTP request
- */
-function loadNodesTable(data) {
- // Clear the tab before inserting the table
- $('#manageTab').children().remove();
-
- // Nodes datatable ID
- var nodesDTId = 'userNodesDT';
-
- // Hash of node attributes
- var attrs = new Object();
- // Node attributes
- var headers = new Object();
- var node = null, args;
- // Create hash of node attributes
- for (var i in data.rsp) {
- // Get node name
- if (data.rsp[i].indexOf('Object name:') > -1) {
- var temp = data.rsp[i].split(': ');
- node = jQuery.trim(temp[1]);
-
- // Create a hash for the node attributes
- attrs[node] = new Object();
- i++;
- }
-
- // Get key and value
- args = data.rsp[i].split('=', 2);
- var key = jQuery.trim(args[0]);
- var val = jQuery.trim(data.rsp[i].substring(data.rsp[i].indexOf('=') + 1, data.rsp[i].length));
-
- // Create a hash table
- attrs[node][key] = val;
- headers[key] = 1;
- }
-
- // Sort headers
- var sorted = new Array();
- var attrs2show = new Array('arch', 'groups', 'hcp', 'hostnames', 'ip', 'os', 'userid', 'mgt');
- for (var key in headers) {
- // Show node attributes
- if (jQuery.inArray(key, attrs2show) > -1) {
- sorted.push(key);
- }
- }
- sorted.sort();
-
- // Add column for check box, node, ping, power, monitor, and comments
- sorted.unshift('
',
- 'node',
- '
status ',
- '
power ',
- '
monitor ',
- 'comments');
-
- // Create a datatable
- var nodesDT = new DataTable(nodesDTId);
- nodesDT.init(sorted);
-
- // Go through each node
- for (var node in attrs) {
- // Create a row
- var row = new Array();
-
- // Create a check box, node link, and get node status
- var checkBx = $('
');
- var nodeLink = $('
' + node + ' ').bind('click', loadNode);
-
- // If there is no status attribute for the node, do not try to access hash table
- // Else the code will break
- var status = '';
- if (attrs[node]['status']) {
- status = attrs[node]['status'].replace('sshd', 'ping');
- }
-
- // Push in checkbox, node, status, monitor, and power
- row.push(checkBx, nodeLink, status, '', '');
-
- // If the node attributes are known (i.e the group is known)
- if (attrs[node]['groups']) {
- // Put in comments
- var comments = attrs[node]['usercomment'];
- // If no comments exists, show 'No comments' and set icon image source
- var iconSrc;
- if (!comments) {
- comments = 'No comments';
- iconSrc = 'images/nodes/ui-icon-no-comment.png';
- } else {
- iconSrc = 'images/nodes/ui-icon-comment.png';
- }
-
- // Create comments icon
- var tipID = node + 'Tip';
- var icon = $('
').css({
- 'width': '18px',
- 'height': '18px'
- });
-
- // Create tooltip
- var tip = createCommentsToolTip(comments);
- var col = $('
').append(icon);
- col.append(tip);
- row.push(col);
-
- // Generate tooltips
- icon.tooltip({
- position: "center right",
- offset: [-2, 10],
- effect: "fade",
- opacity: 0.8,
- relative: true,
- delay: 500
- });
- } else {
- // Do not put in comments if attributes are not known
- row.push('');
- }
-
- // Go through each header
- for (var i = 6; i < sorted.length; i++) {
- // Add the node attributes to the row
- var key = sorted[i];
-
- // Do not put comments and status in twice
- if (key != 'usercomment' && key != 'status' && key.indexOf('statustime') < 0) {
- var val = attrs[node][key];
- if (val) {
- row.push($('
' + val + ' '));
- } else {
- row.push('');
- }
- }
- }
-
- // Add the row to the table
- nodesDT.add(row);
- }
-
- // Create info bar
- var infoBar = createInfoBar('Manage and monitor your virtual machines.');
- $('#manageTab').append(infoBar);
-
- // Insert action bar and nodes datatable
- $('#manageTab').append(nodesDT.object());
-
- // Turn table into a datatable
- $('#' + nodesDTId).dataTable({
- 'iDisplayLength': 50,
- 'bLengthChange': false,
- "bScrollCollapse": true,
- "sScrollY": "400px",
- "sScrollX": "110%",
- "bAutoWidth": true,
- "oLanguage": {
- "oPaginate": {
- "sNext": "",
- "sPrevious": ""
- }
- }
- });
-
- // Set datatable header class to add color
- // $('.datatable thead').attr('class', 'ui-widget-header');
-
- // Do not sort ping, power, and comment column
- $('#' + nodesDTId + ' thead tr th').click(function() {
- getNodeAttrs(group);
- });
- var checkboxCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(0)');
- var pingCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
- var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
- var monitorCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
- var commentCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(5)');
- checkboxCol.unbind('click');
- pingCol.unbind('click');
- powerCol.unbind('click');
- monitorCol.unbind('click');
- commentCol.unbind('click');
-
- // Refresh the node ping, power, and monitor status on-click
- var nodes = getNodesShown(nodesDTId);
- pingCol.find('span a').click(function() {
- refreshNodeStatus(nodes);
- });
- powerCol.find('span a').click(function() {
- refreshPowerStatus(nodes);
- });
- monitorCol.find('span a').click(function() {
- refreshGangliaStatus(nodes);
- });
-
- // Create actions menu
- // Power on
- var powerOnLnk = $('
Power on ');
- powerOnLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesDTId);
- if (tgtNodes) {
- powerNode(tgtNodes, 'on');
- }
- });
-
- // Power off
- var powerOffLnk = $('
Power off ');
- powerOffLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesDTId);
- if (tgtNodes) {
- powerNode(tgtNodes, 'off');
- }
- });
-
- // Power softoff
- var powerSoftoffLnk = $('
Shutdown ');
- powerSoftoffLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesDTId);
- if (tgtNodes) {
- powerNode(tgtNodes, 'softoff');
- }
- });
-
- // Turn monitoring on
- var monitorOnLnk = $('
Monitor on ');
- monitorOnLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesDTId);
- if (tgtNodes) {
- monitorNode(tgtNodes, 'on');
- }
- });
-
- // Turn monitoring off
- var monitorOffLnk = $('
Monitor off ');
- monitorOffLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesDTId);
- if (tgtNodes) {
- monitorNode(tgtNodes, 'off');
- }
- });
-
- // Clone
- var cloneLnk = $('
Clone ');
- cloneLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesDTId);
- if (tgtNodes) {
- cloneNode(tgtNodes);
- }
- });
-
- // Delete
- var deleteLnk = $('
Delete ');
- deleteLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesDTId);
- if (tgtNodes) {
- deleteNode(tgtNodes);
- }
- });
-
- // Unlock
- var unlockLnk = $('
Unlock ');
- unlockLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesDTId);
- if (tgtNodes) {
- unlockNode(tgtNodes);
- }
- });
-
- // Create action bar
- var actionBar = $('
').css('width', '370px');
-
- // Prepend menu to datatable
- var actionsLnk = $('
Actions ');
- var refreshLnk = $('
Refresh ');
- refreshLnk.click(function() {
- // Get nodes owned by user
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'tabdump',
- tgt : '',
- args : 'nodetype',
- msg : ''
- },
-
- success : function(data) {
- // Save nodes owned by user
- setUserNodes(data);
- getNodesCurrentLoad();
-
- // Refresh nodes table
- var userName = $.cookie('xcat_username');
- var userNodes = $.cookie(userName + '_usrnodes');
- if (userNodes) {
- // Get nodes definitions
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'lsdef',
- tgt : '',
- args : userNodes,
- msg : ''
- },
-
- success : loadNodesTable
- });
- } else {
- // Clear the tab before inserting the table
- $('#manageTab').children().remove();
- $('#manageTab').append(createWarnBar('You are not managing any node. Try to provision a node.'));
- }
- }
- });
- });
-
- var actionMenu = createMenu([cloneLnk, deleteLnk, monitorOnLnk, monitorOffLnk, powerOnLnk, powerOffLnk, powerSoftoffLnk, unlockLnk]);
- var menu = createMenu([[actionsLnk, actionMenu], refreshLnk]);
- menu.superfish();
- actionBar.append(menu);
-
- // Set correct theme for action menu
- actionMenu.find('li').hover(function() {
- setMenu2Theme($(this));
- }, function() {
- setMenu2Normal($(this));
- });
-
- // Create a division to hold actions menu
- var menuDiv = $('');
- $('#' + nodesDTId + '_wrapper').prepend(menuDiv);
- menuDiv.append(actionBar);
- $('#' + nodesDTId + '_filter').appendTo(menuDiv);
-
- // Get power and monitor status
- var nodes = getNodesShown(nodesDTId);
- refreshPowerStatus(nodes);
- refreshGangliaStatus(nodes);
-}
-
-/**
- * Refresh ping status for each node
- *
- * @param nodes Nodes to get ping status
- */
-function refreshNodeStatus(nodes) {
- // Show ping loader
- var nodesDTId = 'userNodesDT';
- var pingCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
- pingCol.find('img').show();
-
- // Get the node ping status
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'nodestat',
- tgt : nodes,
- args : '-u',
- msg : ''
- },
-
- success : loadNodePing
- });
-}
-
-/**
- * Load node ping status for each node
- *
- * @param data Data returned from HTTP request
- */
-function loadNodePing(data) {
- var nodesDTId = 'userNodesDT';
- var datatable = $('#' + nodesDTId).dataTable();
- var rsp = data.rsp;
- var args, rowPos, node, status;
-
- // Get all nodes within datatable
- for (var i in rsp) {
- args = rsp[i].split(':');
-
- // args[0] = node and args[1] = status
- node = jQuery.trim(args[0]);
- status = jQuery.trim(args[1]).replace('sshd', 'ping');
-
- // Get row containing node
- rowPos = findRow(node, '#' + nodesDTId, 1);
-
- // Update ping status column
- datatable.fnUpdate(status, rowPos, 2, false);
- }
-
- // Hide status loader
- var pingCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
- pingCol.find('img').hide();
- adjustColumnSize(nodesDTId);
-}
-
-/**
- * Refresh power status for each node
- *
- * @param nodes Nodes to get power status
- */
-function refreshPowerStatus(nodes) {
- // Show power loader
- var nodesDTId = 'userNodesDT';
- var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
- powerCol.find('img').show();
-
- // Get power status
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'rpower',
- tgt : nodes,
- args : 'stat',
- msg : ''
- },
-
- success : loadPowerStatus
- });
-}
-
-/**
- * Load power status for each node
- *
- * @param data Data returned from HTTP request
- */
-function loadPowerStatus(data) {
- var nodesDTId = 'userNodesDT';
- var datatable = $('#' + nodesDTId).dataTable();
- var power = data.rsp;
- var rowPos, node, status, args;
-
- for (var i in power) {
- // power[0] = nodeName and power[1] = state
- args = power[i].split(':');
- node = jQuery.trim(args[0]);
- status = jQuery.trim(args[1]);
-
- // Get the row containing the node
- rowPos = findRow(node, '#' + nodesDTId, 1);
-
- // Update the power status column
- datatable.fnUpdate(status, rowPos, 3, false);
- }
-
- // Hide power loader
- var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
- powerCol.find('img').hide();
- adjustColumnSize(nodesDTId);
-}
-
-/**
- * Refresh the status of Ganglia for each node
- *
- * @param nodes Nodes to get Ganglia status
- */
-function refreshGangliaStatus(nodes) {
- // Show ganglia loader
- var nodesDTId = 'userNodesDT';
- var gangliaCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
- gangliaCol.find('img').show();
-
- // Get the status of Ganglia
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'gangliastatus;' + nodes,
- msg : ''
- },
-
- success : loadGangliaStatus
- });
-}
-
-/**
- * Load the status of Ganglia for a given group
- *
- * @param data Data returned from HTTP request
- */
-function loadGangliaStatus(data) {
- // Get datatable
- var nodesDTId = 'userNodesDT';
- var datatable = $('#' + nodesDTId).dataTable();
- var ganglia = data.rsp;
- var rowNum, node, status;
-
- for ( var i in ganglia) {
- // ganglia[0] = nodeName and ganglia[1] = state
- node = jQuery.trim(ganglia[i][0]);
- status = jQuery.trim(ganglia[i][1]);
-
- if (node) {
- // Get the row containing the node
- rowNum = findRow(node, '#' + nodesDTId, 1);
-
- // Update the power status column
- datatable.fnUpdate(status, rowNum, 4);
- }
- }
-
- // Hide Ganglia loader
- var gangliaCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
- gangliaCol.find('img').hide();
- adjustColumnSize(nodesDTId);
-}
-
-/**
- * Load inventory for given node
- *
- * @param e Windows event
- */
-function loadNode(e) {
- if (!e) {
- e = window.event;
- }
-
- // Get node that was clicked
- var node = (e.target) ? e.target.id : e.srcElement.id;
-
- // Create a new tab to show inventory
- var tabId = node + '_inventory';
-
- if(!$('#' + tabId).length) {
- // Add new tab, only if one does not exist
- var loader = createLoader(node + 'Loader');
- loader = $('
').append(loader);
- serviceTabs.add(tabId, node, loader, true);
-
- // Get node inventory
- var msg = 'out=' + tabId + ',node=' + node;
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'rinv',
- tgt : node,
- args : 'all',
- msg : msg
- },
-
- success : function(data) {
- var args = data.msg.split(',');
-
- // Get node
- var node = args[1].replace('node=', '');
-
- // Get the management plugin
- var mgt = getNodeAttr(node, 'mgt');
-
- // Create an instance of the plugin
- var plugin;
- switch (mgt) {
- case "kvm":
- plugin = new kvmPlugin();
- break;
- case "esx":
- plugin = new esxPlugin();
- break;
- case "zvm":
- plugin = new zvmPlugin();
- break;
- }
-
- // Select tab
- plugin.loadServiceInventory(data);
- }
- });
- }
-
- // Select new tab
- serviceTabs.select(tabId);
-}
-
-/**
- * Set a cookie for group names
- *
- * @param data Data from HTTP request
- */
-function setGroupCookies(data) {
- if (data.rsp) {
- var groups = new Array();
-
- // Index 0 is the table header
- var cols, name, ip, hostname, desc, selectable, comments, tmp;
- for (var i = 1; i < data.rsp.length; i++) {
- // Set default description and selectable
- selectable = "no";
- desc = "No description";
-
- // Split into columns:
- // node, ip, hostnames, otherinterfaces, comments, disable
- cols = data.rsp[i].split(',');
- name = cols[0].replace(new RegExp('"', 'g'), '');
- ip = cols[1].replace(new RegExp('"', 'g'), '');
- hostname = cols[2].replace(new RegExp('"', 'g'), '');
-
- // It should return: "description: All machines; network: 10.1.100.0/24;"
- comments = cols[4].replace(new RegExp('"', 'g'), '');
- tmp = comments.split('|');
- for (var j = 0; j < tmp.length; j++) {
- // Save description
- if (tmp[j].indexOf('description:') > -1) {
- desc = tmp[j].replace('description:', '');
- desc = jQuery.trim(desc);
- }
-
- // Is the group selectable?
- if (tmp[j].indexOf('selectable:') > -1) {
- selectable = tmp[j].replace('selectable:', '');
- selectable = jQuery.trim(selectable);
- }
- }
-
- // Save groups that are selectable
- if (selectable == "yes")
- groups.push(name + ':' + ip + ':' + hostname + ':' + desc);
- }
-
- // Set cookie to expire in 60 minutes
- var exDate = new Date();
- exDate.setTime(exDate.getTime() + (240 * 60 * 1000));
- $.cookie('srv_groups', groups, { expires: exDate });
- }
-}
-
-/**
- * Set a cookie for the OS images
- *
- * @param data Data from HTTP request
- */
-function setOSImageCookies(data) {
- // Get response
- var rsp = data.rsp;
-
- var imageNames = new Array();
- var profilesHash = new Object();
- var osVersHash = new Object();
- var osArchsHash = new Object();
- var imagePos = 0;
- var profilePos = 0;
- var osversPos = 0;
- var osarchPos = 0;
- var provMethodPos = 0;
- var comments = 0;
- var desc, selectable, tmp;
- // Get column index for each attribute
- var colNameArray = rsp[0].substr(1).split(',');
- for (var i in colNameArray){
- switch (colNameArray[i]){
- case 'imagename': {
- imagePos = i;
- }
- break;
-
- case 'profile':{
- profilePos = i;
- }
- break;
-
- case 'osvers':{
- osversPos = i;
- }
- break;
-
- case 'osarch':{
- osarchPos = i;
- }
- break;
-
- case 'comments':{
- comments = i;
- }
- break;
-
- case 'provmethod':{
- provMethodPos = i;
- }
- break;
-
- default :
- break;
- }
- }
-
- // Go through each index
- for (var i = 1; i < rsp.length; i++) {
- // Get image name
- var cols = rsp[i].split(',');
- var osImage = cols[imagePos].replace(new RegExp('"', 'g'), '');
- var profile = cols[profilePos].replace(new RegExp('"', 'g'), '');
- var provMethod = cols[provMethodPos].replace(new RegExp('"', 'g'), '');
- var osVer = cols[osversPos].replace(new RegExp('"', 'g'), '');
- var osArch = cols[osarchPos].replace(new RegExp('"', 'g'), '');
- var osComments = cols[comments].replace(new RegExp('"', 'g'), '');
-
- // Only save install boot
- if (provMethod.indexOf('install') > -1) {
- if (osComments) {
- // Only enable images where description and selectable comments exist
- // Set default description and selectable
- selectable = "no";
- desc = "No description";
-
- tmp = osComments.split('|');
- for (var j = 0; j < tmp.length; j++) {
- // Save description
- if (tmp[j].indexOf('description:') > -1) {
- desc = tmp[j].replace('description:', '');
- desc = jQuery.trim(desc);
- }
-
- // Is the image selectable?
- if (tmp[j].indexOf('selectable:') > -1) {
- selectable = tmp[j].replace('selectable:', '');
- selectable = jQuery.trim(selectable);
- }
- }
-
- // Save images that are selectable
- if (selectable == "yes")
- imageNames.push(osImage + ':' + desc);
- }
-
- profilesHash[profile] = 1;
- osVersHash[osVer] = 1;
- osArchsHash[osArch] = 1;
- }
- }
-
- // Save image names in a cookie
- $.cookie('srv_imagenames', imageNames);
-
- // Save profiles in a cookie
- var tmp = new Array;
- for (var key in profilesHash) {
- tmp.push(key);
- }
- $.cookie('srv_profiles', tmp);
-
- // Save OS versions in a cookie
- tmp = new Array;
- for (var key in osVersHash) {
- tmp.push(key);
- }
- $.cookie('srv_osvers', tmp);
-
- // Save OS architectures in a cookie
- tmp = new Array;
- for (var key in osArchsHash) {
- tmp.push(key);
- }
- $.cookie('srv_osarchs', tmp);
-}
-
-
-
-/**
- * Set a cookie for user nodes
- *
- * @param data Data from HTTP request
- */
-function setUserNodes(data) {
- if (data.rsp) {
- // Get user name that is logged in
- var userName = $.cookie('xcat_username');
- var usrNodes = new Array();
-
- // Ignore first columns because it is the header
- for ( var i = 1; i < data.rsp.length; i++) {
- // Go through each column
- // where column names are: node, os, arch, profile, provmethod, supportedarchs, nodetype, comments, disable
- var cols = data.rsp[i].split(',');
- var node = cols[0].replace(new RegExp('"', 'g'), '');
-
- // Comments can contain the owner and description
- var comments = new Array();
- if (cols[7].indexOf(';') > -1) {
- comments = cols[7].replace(new RegExp('"', 'g'), '').split(';');
- } else {
- comments.push(cols[7].replace(new RegExp('"', 'g'), ''));
- }
-
- // Extract the owner
- var owner;
- for (var j in comments) {
- if (comments[j].indexOf('owner:') > -1) {
- owner = comments[j].replace('owner:', '');
-
- if (owner == userName) {
- usrNodes.push(node);
- }
-
- break;
- }
- }
- } // End of for
-
- // Set cookie to expire in 240 minutes
- var exDate = new Date();
- exDate.setTime(exDate.getTime() + (240 * 60 * 1000));
- $.cookie(userName + '_usrnodes', usrNodes, { expires: exDate });
- } // End of if
-}
-
-/**
- * Power on a given node
- *
- * @param tgtNodes Node to power on or off
- * @param power2 Power node to given state
- */
-function powerNode(tgtNodes, power2) {
- // Show power loader
- var nodesDTId = 'userNodesDT';
- var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
- powerCol.find('img').show();
-
- var nodes = tgtNodes.split(',');
- for (var n in nodes) {
- // Get hardware that was selected
- var hw = getUserNodeAttr(nodes[n], 'mgt');
-
- // Change to power softoff (to gracefully shutdown)
- switch (hw) {
- case "blade":
- break;
- case "hmc":
- break;
- case "ipmi":
- break;
- case "zvm":
- if (power2 == 'off') {
- power2 = 'softoff';
- }
-
- break;
- }
- }
-
- $.ajax({
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'rpower',
- tgt : tgtNodes,
- args : power2,
- msg : tgtNodes
- },
-
- success : updatePowerStatus
- });
-}
-
-/**
- * Update power status of a node in the datatable
- *
- * @param data Data from HTTP request
- */
-function updatePowerStatus(data) {
- // Get datatable
- var nodesDTId = 'userNodesDT';
- var dTable = $('#' + nodesDTId).dataTable();
-
- // Get xCAT response
- var rsp = data.rsp;
- // Loop through each line
- var node, status, rowPos, strPos;
- for (var i in rsp) {
- // Get node name
- node = rsp[i].split(":")[0];
-
- // If there is no error
- if (rsp[i].indexOf("Error") < 0 || rsp[i].indexOf("Failed") < 0) {
- // Get the row containing the node link
- rowPos = findRow(node, '#' + nodesDTId, 1);
-
- // If it was power on, then the data return would contain "Starting"
- strPos = rsp[i].indexOf("Starting");
- if (strPos > -1) {
- status = 'on';
- } else {
- status = 'off';
- }
-
- // Update the power status column
- dTable.fnUpdate(status, rowPos, 3, false);
- } else {
- // Power on/off failed
- alert(rsp[i]);
- }
- }
-
- var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
- powerCol.find('img').hide();
- adjustColumnSize(nodesDTId);
-}
-
-/**
- * Turn on monitoring for a given node
- *
- * @param node Node to monitor on or off
- * @param monitor Monitor state, on or off
- */
-function monitorNode(node, monitor) {
- // Show ganglia loader
- var nodesDTId = 'userNodesDT';
- var gangliaCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
- gangliaCol.find('img').show();
-
- if (monitor == 'on') {
- if (node) {
- // Check if ganglia RPMs are installed
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'gangliacheck;' + node,
- msg : node // Node range will be passed along in data.msg
- },
-
- /**
- * Start ganglia on a given node range
- *
- * @param data
- * Data returned from HTTP request
- * @return Nothing
- */
- success : function(data) {
- // Get response
- var out = data.rsp[0].split(/\n/);
-
- // Go through each line
- var warn = false;
- var warningMsg = '';
- for (var i in out) {
- // If an RPM is not installed
- if (out[i].indexOf('not installed') > -1) {
- warn = true;
-
- if (warningMsg) {
- warningMsg += '
' + out[i];
- } else {
- warningMsg = out[i];
- }
- }
- }
-
- // If there are warnings
- if (warn) {
- // Create warning bar
- var warningBar = createWarnBar(warningMsg);
- warningBar.css('margin-bottom', '10px');
- warningBar.prependTo($('#nodesTab'));
- } else {
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'gangliastart;' + data.msg,
- msg : data.msg
- },
-
- success : function(data) {
- // Remove any warnings
- $('#nodesTab').find('.ui-state-error').remove();
- refreshGangliaStatus(data.msg);
- }
- });
- } // End of if (warn)
- } // End of function(data)
- });
- }
- } else {
- var args;
- if (node) {
- args = 'gangliastop;' + node;
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : args,
- msg : node
- },
-
- success : function(data) {
- refreshGangliaStatus(data.msg);
- }
- });
- }
- }
-}
-
-/**
- * Open a dialog to clone node
- *
- * @param tgtNodes Nodes to clone
- */
-function cloneNode(tgtNodes) {
- var userName = $.cookie('xcat_username');
- var nodes = tgtNodes.split(',');
- var tmp = $.cookie(userName + '_usrnodes');
- var usrNodes = tmp.split(',');
-
- var maxVM = parseInt($.cookie(userName + '_maxvm'));
-
- // Do not allow user to clone if the maximum number of VMs is reached
- if (usrNodes.length >= maxVM) {
- var warn = createWarnBar('You have reached the maximum number of virtual machines allowed (' + maxVM + '). Delete un-used virtual machines or contact your system administrator request more virtual machines.');
- warn.prependTo($('#manageTab'));
- return;
- }
-
- for (var n in nodes) {
- // Get hardware that was selected
- var hw = getUserNodeAttr(nodes[n], 'mgt');
-
- // Create an instance of the plugin
- var plugin;
- switch (hw) {
- case "kvm":
- plugin = new kvmPlugin();
- break;
- case "esx":
- plugin = new esxPlugin();
- break;
- case "zvm":
- plugin = new zvmPlugin();
- break;
- }
-
- // Clone node
- plugin.serviceClone(nodes[n]);
- }
-}
-
-
-/**
- * Open a dialog to delete node
- *
- * @param tgtNodes Nodes to delete
- */
-function deleteNode(tgtNodes) {
- var nodes = tgtNodes.split(',');
-
- // Loop through each node and create target nodes string
- var tgtNodesStr = '';
- for (var i in nodes) {
- if (i == 0 && i == nodes.length - 1) {
- // If it is the 1st and only node
- tgtNodesStr += nodes[i];
- } else if (i == 0 && i != nodes.length - 1) {
- // If it is the 1st node of many nodes, append a comma to the string
- tgtNodesStr += nodes[i] + ', ';
- } else {
- if (i == nodes.length - 1) {
- // If it is the last node, append nothing to the string
- tgtNodesStr += nodes[i];
- } else {
- // Append a comma to the string
- tgtNodesStr += nodes[i] + ', ';
- }
- }
- }
-
- // Confirm delete of node
- var dialog = $('
');
- var warn = createWarnBar('Are you sure you want to delete ' + tgtNodesStr + '?');
- dialog.append(warn);
-
- // Open dialog
- dialog.dialog({
- title: "Confirm",
- modal: true,
- close: function(){
- $(this).remove();
- },
- width: 400,
- buttons: {
- "Yes": function(){
- // Create status bar and append to tab
- var instance = 0;
- var statBarId = 'deleteStat' + instance;
- while ($('#' + statBarId).length) {
- // If one already exists, generate another one
- instance = instance + 1;
- statBarId = 'deleteStat' + instance;
- }
-
- var statBar = createStatusBar(statBarId);
- var loader = createLoader('');
- statBar.find('div').append(loader);
- statBar.prependTo($('#manageTab'));
-
- // Delete the virtual server
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'rmvm',
- tgt : tgtNodes,
- args : '',
- msg : 'out=' + statBarId + ';cmd=rmvm;tgt=' + tgtNodes
- },
-
- success : function(data) {
- var args = data.msg.split(';');
- var statBarId = args[0].replace('out=', '');
- var tgts = args[2].replace('tgt=', '').split(',');
-
- // Get data table
- var nodesDTId = 'userNodesDT';
- var dTable = $('#' + nodesDTId).dataTable();
- var failed = false;
-
- // Create an info box to show output
- var output = writeRsp(data.rsp, '');
- output.css('margin', '0px');
- // Remove loader and append output
- $('#' + statBarId + ' img').remove();
- $('#' + statBarId + ' div').append(output);
-
- // If there was an error, do not continue
- if (output.html().indexOf('Error') > -1) {
- failed = true;
- }
-
- // Update data table
- var rowPos;
- for (var i in tgts) {
- if (!failed) {
- // Get row containing the node link and delete it
- rowPos = findRow(tgts[i], '#' + nodesDTId, 1);
- dTable.fnDeleteRow(rowPos);
- }
- }
-
- // Refresh nodes owned by user
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'tabdump',
- tgt : '',
- args : 'nodetype',
- msg : ''
- },
-
- success : function(data) {
- setUserNodes(data);
- }
- });
- }
- });
-
- $(this).dialog("close");
- },
- "No": function() {
- $(this).dialog("close");
- }
- }
- });
-}
-
-/**
- * Unlock a node by setting the ssh keys
- *
- * @param tgtNodes Nodes to unlock
- */
-function unlockNode(tgtNodes) {
- var nodes = tgtNodes.split(',');
-
- // Loop through each node and create target nodes string
- var tgtNodesStr = '';
- for (var i in nodes) {
- if (i == 0 && i == nodes.length - 1) {
- // If it is the 1st and only node
- tgtNodesStr += nodes[i];
- } else if (i == 0 && i != nodes.length - 1) {
- // If it is the 1st node of many nodes, append a comma to the string
- tgtNodesStr += nodes[i] + ', ';
- } else {
- if (i == nodes.length - 1) {
- // If it is the last node, append nothing to the string
- tgtNodesStr += nodes[i];
- } else {
- // Append a comma to the string
- tgtNodesStr += nodes[i] + ', ';
- }
- }
- }
-
- var dialog = $('
');
- var infoBar = createInfoBar('Give the root password for this node range to setup its SSH keys.');
- dialog.append(infoBar);
-
- var unlockForm = $('
').css('margin', '5px');
- unlockForm.append('
Target node range:
');
- unlockForm.append('
Password:
');
- dialog.append(unlockForm);
-
- dialog.find('div input').css('margin', '5px');
-
- // Generate tooltips
- unlockForm.find('div input[title]').tooltip({
- position: "center right",
- offset: [-2, 10],
- effect: "fade",
- opacity: 0.7,
- predelay: 800,
- events : {
- def : "mouseover,mouseout",
- input : "mouseover,mouseout",
- widget : "focus mouseover,blur mouseout",
- tooltip : "mouseover,mouseout"
- }
- });
-
- // Open dialog
- dialog.dialog({
- title: "Confirm",
- modal: true,
- close: function(){
- $(this).remove();
- },
- width: 450,
- buttons: {
- "Ok": function(){
- // Create status bar and append to tab
- var instance = 0;
- var statBarId = 'unlockStat' + instance;
- while ($('#' + statBarId).length) {
- // If one already exists, generate another one
- instance = instance + 1;
- statBarId = 'unlockStat' + instance;
- }
-
- var statBar = createStatusBar(statBarId);
- var loader = createLoader('');
- statBar.find('div').append(loader);
- statBar.prependTo($('#manageTab'));
-
- // If a password is given
- var password = unlockForm.find('input[name=password]:eq(0)');
- if (password.val()) {
- // Setup SSH keys
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'unlock;' + tgtNodes + ';' + password.val(),
- msg : 'out=' + statBarId + ';cmd=unlock;tgt=' + tgtNodes
- },
-
- success : function(data) {
- // Create an info box to show output
- var output = writeRsp(data.rsp, '');
- output.css('margin', '0px');
- // Remove loader and append output
- $('#' + statBarId + ' img').remove();
- $('#' + statBarId + ' div').append(output);
- }
- });
-
- $(this).dialog("close");
- }
- },
- "Cancel": function() {
- $(this).dialog("close");
- }
- }
- });
-}
-
-/**
- * Get nodes current load information
- */
-function getNodesCurrentLoad(){
- var userName = $.cookie('xcat_username');
- var nodes = $.cookie(userName + '_usrnodes');
-
- // Get nodes current status
- $.ajax({
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'gangliacurrent;node;' + nodes,
- msg : ''
- },
-
- success: saveNodeLoad
- });
-}
-
-/**
- * Save node load data
- *
- * @param status Data returned from HTTP request
- */
-function saveNodeLoad(status){
- // Save node path and status for future use
- nodePath = new Object();
- nodeStatus = new Object();
-
- // Get nodes status
- var nodes = status.rsp[0].split(';');
-
- var i = 0, pos = 0;
- var node = '', tmpStr = '';
- var tmpArry;
-
- for (i = 0; i < nodes.length; i++){
- tmpStr = nodes[i];
- pos = tmpStr.indexOf(':');
- node = tmpStr.substring(0, pos);
- tmpArry = tmpStr.substring(pos + 1).split(',');
-
- switch(tmpArry[0]){
- case 'UNKNOWN':{
- nodeStatus[node] = -2;
- }
- break;
- case 'ERROR':{
- nodeStatus[node] = -1;
- }
- break;
- case 'WARNING':{
- nodeStatus[node] = 0;
- nodePath[node] = tmpArry[1];
- }
- break;
- case 'NORMAL':{
- nodeStatus[node] = 1;
- nodePath[node] = tmpArry[1];
- }
- break;
- }
- }
-}
-
-/**
- * Get monitoring metrics and load into inventory fieldset
- *
- * @param node Node to collect metrics
- */
-function getMonitorMetrics(node) {
- // Inventory tab should have this fieldset already created
- // e.g.
- $('#' + node + '_monitor').children('div').remove();
-
- // Before trying to get the metrics, check if Ganglia is running
- $.ajax({
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'gangliastatus;' + node,
- msg : ''
- },
-
- success: function(data) {
- var ganglia = data.rsp;
- var node, status;
-
- // Get the ganglia status
- for (var i in ganglia) {
- // ganglia[0] = nodeName and ganglia[1] = state
- node = jQuery.trim(ganglia[i][0]);
- status = jQuery.trim(ganglia[i][1]);
-
- if (node && status == 'on') {
- // Get monitoring metrics
- $.ajax({
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'gangliashow;' + nodePath[node] + ';hour;_summary_',
- msg : node
- },
-
- success: drawMonitoringCharts
- });
- } else if (node && status == 'off') {
- var info = createInfoBar('Ganglia monitoring is disabled for this node');
- $('#' + node + '_monitor').append(info.css('width', '300px'));
- }
- } // End of for
- } // End of function
- });
-}
-
-/**
- * Draw monitoring charts based on node metrics
- *
- * @param data Data returned from HTTP request
- */
-function drawMonitoringCharts(data){
- var nodeMetrics = new Object();
- var metricData = data.rsp[0].split(';');
- var node = data.msg;
-
- var metricName = '';
- var metricVal = '';
- var pos = 0;
-
- // Go through the metrics returned
- for (var m = 0; m < metricData.length; m++){
- pos = metricData[m].indexOf(':');
-
- // Get metric name
- metricName = metricData[m].substr(0, pos);
- nodeMetrics[metricName] = new Array();
- // Get metric values
- metricVal = metricData[m].substr(pos + 1).split(',');
- // Save node metrics
- for (var i = 0; i < metricVal.length; i++){
- nodeMetrics[metricName].push(Number(metricVal[i]));
- }
- }
-
- drawLoadFlot(node, nodeMetrics['load_one'], nodeMetrics['cpu_num']);
- drawCpuFlot(node, nodeMetrics['cpu_idle']);
- drawMemFlot(node, nodeMetrics['mem_free'], nodeMetrics['mem_total']);
- drawDiskFlot(node, nodeMetrics['disk_free'], nodeMetrics['disk_total']);
- drawNetworkFlot(node, nodeMetrics['bytes_in'], nodeMetrics['bytes_out']);
-}
-
-/**
- * Draw load metrics flot
- *
- * @param node Node name
- * @param loadpair Load timestamp and value pair
- * @param cpupair CPU number and value pair
- */
-function drawLoadFlot(node, loadPair, cpuPair){
- var load = new Array();
- var cpu = new Array();
-
- var i = 0;
- var yAxisMax = 0;
- var interval = 1;
-
- // Append flot to node monitoring fieldset
- var loadFlot = $('
').css({
- 'float': 'left',
- 'height': '150px',
- 'margin': '0 0 10px',
- 'width': '300px'
- });
- $('#' + node + '_monitor').append(loadFlot);
- $('#' + node + '_load').empty();
-
- // Parse load pair where:
- // timestamp must be mutiplied by 1000 and Javascript timestamp is in ms
- for (i = 0; i < loadPair.length; i += 2){
- load.push([loadPair[i] * 1000, loadPair[i + 1]]);
- if (loadPair[i + 1] > yAxisMax){
- yAxisMax = loadPair[i + 1];
- }
- }
-
- // Parse CPU pair
- for (i = 0; i < cpuPair.length; i += 2){
- cpu.push([cpuPair[i] * 1000, cpuPair[i + 1]]);
- if (cpuPair[i + 1] > yAxisMax){
- yAxisMax = cpuPair[i + 1];
- }
- }
-
- interval = parseInt(yAxisMax / 3);
- if (interval < 1){
- interval = 1;
- }
-
- $.jqplot(node + '_load', [load, cpu],{
- title: ' Loads/Procs Last Hour',
- axes:{
- xaxis:{
- renderer : $.jqplot.DateAxisRenderer,
- numberTicks: 4,
- tickOptions : {
- formatString : '%R',
- show : true
- }
- },
- yaxis: {
- min : 0,
- tickInterval : interval
- }
- },
- legend : {
- show: true,
- location: 'nw'
- },
- series:[{label:'Load'}, {label: 'CPU Number'}],
- seriesDefaults : {showMarker: false}
- });
-}
-
-/**
- * Draw CPU usage flot
- *
- * @param node Node name
- * @param cpuPair CPU timestamp and value pair
- */
-function drawCpuFlot(node, cpuPair){
- var cpu = new Array();
-
- // Append flot to node monitoring fieldset
- var cpuFlot = $('
').css({
- 'float': 'left',
- 'height': '150px',
- 'margin': '0 0 10px',
- 'width': '300px'
- });
- $('#' + node + '_monitor').append(cpuFlot);
- $('#' + node + '_cpu').empty();
-
- // Time stamp should by mutiplied by 1000
- // CPU idle comes from server, subtract 1 from idle
- for(var i = 0; i < cpuPair.length; i +=2){
- cpu.push([(cpuPair[i] * 1000), (100 - cpuPair[i + 1])]);
- }
-
- $.jqplot(node + '_cpu', [cpu],{
- title: 'CPU Use Last Hour',
- axes:{
- xaxis:{
- renderer : $.jqplot.DateAxisRenderer,
- numberTicks: 4,
- tickOptions : {
- formatString : '%R',
- show : true
- }
- },
- yaxis: {
- min : 0,
- max : 100,
- tickOptions:{formatString : '%d\%'}
- }
- },
- seriesDefaults : {showMarker: false}
- });
-}
-
-/**
- * Draw memory usage flot
- *
- * @param node Node name
- * @param freePair Free memory timestamp and value pair
- * @param totalPair Total memory timestamp and value pair
- */
-function drawMemFlot(node, freePair, totalPair){
- var used = new Array();
- var total = new Array();
- var size = 0;
-
- // Append flot to node monitoring fieldset
- var memoryFlot = $('
').css({
- 'float': 'left',
- 'height': '150px',
- 'margin': '0 0 10px',
- 'width': '300px'
- });
- $('#' + node + '_monitor').append(memoryFlot);
- $('#' + node + '_memory').empty();
-
- if(freePair.length < totalPair.length){
- size = freePair.length;
- } else {
- size = freePair.length;
- }
-
- var tmpTotal, tmpUsed;
- for(var i = 0; i < size; i+=2){
- tmpTotal = totalPair[i+1];
- tmpUsed = tmpTotal-freePair[i+1];
- tmpTotal = tmpTotal/1000000;
- tmpUsed = tmpUsed/1000000;
- total.push([totalPair[i]*1000, tmpTotal]);
- used.push([freePair[i]*1000, tmpUsed]);
- }
-
- $.jqplot(node + '_memory', [used, total],{
- title: 'Memory Use Last Hour',
- axes:{
- xaxis:{
- renderer : $.jqplot.DateAxisRenderer,
- numberTicks: 4,
- tickOptions : {
- formatString : '%R',
- show : true
- }
- },
- yaxis: {
- min : 0,
- tickOptions:{formatString : '%.2fG'}
- }
- },
- legend : {
- show: true,
- location: 'nw'
- },
- series:[{label:'Used'}, {label: 'Total'}],
- seriesDefaults : {showMarker: false}
- });
-}
-
-/**
- * Draw disk usage flot
- *
- * @param node Node name
- * @param freePair Free disk space (Ganglia only logs free data)
- * @param totalPair Total disk space
- */
-function drawDiskFlot(node, freePair, totalPair) {
- var used = new Array();
- var total = new Array();
- var size = 0;
-
- // Append flot to node monitoring fieldset
- var diskFlot = $('
').css({
- 'float' : 'left',
- 'height' : '150px',
- 'margin' : '0 0 10px',
- 'width' : '300px'
- });
- $('#' + node + '_monitor').append(diskFlot);
- $('#' + node + '_disk').empty();
-
- if (freePair.length < totalPair.length) {
- size = freePair.length;
- } else {
- size = freePair.length;
- }
-
- var tmpTotal, tmpUsed;
- for ( var i = 0; i < size; i += 2) {
- tmpTotal = totalPair[i + 1];
- tmpUsed = tmpTotal - freePair[i + 1];
- total.push([ totalPair[i] * 1000, tmpTotal ]);
- used.push([ freePair[i] * 1000, tmpUsed ]);
- }
-
- $.jqplot(node + '_disk', [ used, total ], {
- title : 'Disk Use Last Hour',
- axes : {
- xaxis : {
- renderer : $.jqplot.DateAxisRenderer,
- numberTicks : 4,
- tickOptions : {
- formatString : '%R',
- show : true
- }
- },
- yaxis : {
- min : 0,
- tickOptions : {
- formatString : '%.2fG'
- }
- }
- },
- legend : {
- show : true,
- location : 'nw'
- },
- series : [ {
- label : 'Used'
- }, {
- label : 'Total'
- } ],
- seriesDefaults : {
- showMarker : false
- }
- });
-}
-
-/**
- * Draw network usage flot
- *
- * @param node Node name
- * @param freePair Free memory timestamp and value pair
- * @param totalPair Total memory timestamp and value pair
- */
-function drawNetworkFlot(node, inPair, outPair) {
- var inArray = new Array();
- var outArray = new Array();
- var maxVal = 0;
- var unitName = 'B';
- var divisor = 1;
-
- // Append flot to node monitoring fieldset
- var diskFlot = $('
').css({
- 'float' : 'left',
- 'height' : '150px',
- 'margin' : '0 0 10px',
- 'width' : '300px'
- });
- $('#' + node + '_monitor').append(diskFlot);
- $('#' + node + '_network').empty();
-
- for (var i = 0; i < inPair.length; i += 2) {
- if (inPair[i + 1] > maxVal) {
- maxVal = inPair[i + 1];
- }
- }
-
- for (var i = 0; i < outPair.length; i += 2) {
- if (outPair[i + 1] > maxVal) {
- maxVal = outPair[i + 1];
- }
- }
-
- if (maxVal > 3000000) {
- divisor = 1000000;
- unitName = 'GB';
- } else if (maxVal >= 3000) {
- divisor = 1000;
- unitName = 'MB';
- } else {
- // Do nothing
- }
-
- for (i = 0; i < inPair.length; i += 2) {
- inArray.push([ (inPair[i] * 1000), (inPair[i + 1] / divisor) ]);
- }
-
- for (i = 0; i < outPair.length; i += 2) {
- outArray.push([ (outPair[i] * 1000), (outPair[i + 1] / divisor) ]);
- }
-
- $.jqplot(node + '_network', [ inArray, outArray ], {
- title : 'Network Last Hour',
- axes : {
- xaxis : {
- renderer : $.jqplot.DateAxisRenderer,
- numberTicks : 4,
- tickOptions : {
- formatString : '%R',
- show : true
- }
- },
- yaxis : {
- min : 0,
- tickOptions : {
- formatString : '%d' + unitName
- }
- }
- },
- legend : {
- show : true,
- location : 'nw'
- },
- series : [ {
- label : 'In'
- }, {
- label : 'Out'
- } ],
- seriesDefaults : {
- showMarker : false
- }
- });
-}
-
-/**
- * Get an attribute of a given node
- *
- * @param node The node
- * @param attrName The attribute
- * @return The attribute of the node
- */
-function getNodeAttr(node, attrName) {
- // Get the row
- var row = $('[id=' + node + ']').parents('tr');
-
- // Search for the column containing the attribute
- var attrCol = null;
-
- var cols = row.parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th');
- // Loop through each column
- for (var i in cols) {
- // Find column that matches the attribute
- if (cols.eq(i).html() == attrName) {
- attrCol = cols.eq(i);
- break;
- }
- }
-
- // If the column containing the attribute is found
- if (attrCol) {
- // Get the attribute column index
- var attrIndex = attrCol.index();
-
- // Get the attribute for the given node
- var attr = row.find('td:eq(' + attrIndex + ')');
- return attr.text();
- } else {
- return '';
- }
-}
-
-/**
- * Set the maximum number of VMs a user could have
- */
-function setMaxVM() {
- var userName = $.cookie('xcat_username');
-
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webportal',
- tgt : '',
- args : 'getmaxvm;' + userName,
- msg : ''
- },
-
- success : function(data) {
- // Get response
- var rsp = jQuery.trim(data.rsp);
- rsp = rsp.replace('Max allowed:', '');
-
- // Set cookie to expire in 60 minutes
- var exDate = new Date();
- exDate.setTime(exDate.getTime() + (240 * 60 * 1000));
- $.cookie(userName + '_maxvm', rsp, { expires: exDate });
- }
- });
+/**
+ * Global variables
+ */
+var serviceTabs;
+var nodeName;
+var nodePath;
+var nodeStatus;
+var gangliaTimer;
+
+/**
+ * Initialize service page
+ */
+function initServicePage() {
+ // Load theme
+ var theme = $.cookie('xcat_theme');
+ if (theme) {
+ switch (theme) {
+ case 'cupertino':
+ includeCss("css/themes/jquery-ui-cupertino.css");
+ break;
+ case 'dark_hive':
+ includeCss("css/themes/jquery-ui-dark_hive.css");
+ break;
+ case 'redmond':
+ includeCss("css/themes/jquery-ui-redmond.css");
+ break;
+ case 'start':
+ includeCss("css/themes/jquery-ui-start.css");
+ break;
+ case 'sunny':
+ includeCss("css/themes/jquery-ui-sunny.css");
+ break;
+ case 'ui_dark':
+ includeCss("css/themes/jquery-ui-ui_darkness.css");
+ break;
+ default:
+ includeCss("css/themes/jquery-ui-start.css");
+ }
+ } else {
+ includeCss("css/themes/jquery-ui-start.css");
+ }
+
+ // Load jQuery stylesheets
+ includeCss("css/jquery.dataTables.css");
+ includeCss("css/superfish.css");
+ includeCss("css/jstree.css");
+ includeCss("css/jquery.jqplot.css");
+
+ // Load custom stylesheet
+ includeCss("css/style.css");
+
+ // Reuqired JQuery plugins
+ includeJs("js/jquery/jquery.dataTables.min.js");
+ includeJs("js/jquery/jquery.cookie.min.js");
+ includeJs("js/jquery/tooltip.min.js");
+ includeJs("js/jquery/superfish.min.js");
+ includeJs("js/jquery/jquery.jqplot.min.js");
+ includeJs("js/jquery/jqplot.dateAxisRenderer.min.js");
+
+ // Custom plugins
+ includeJs("js/custom/esx.js");
+ includeJs("js/custom/kvm.js");
+ includeJs("js/custom/zvm.js");
+
+ // Enable settings link
+ $('#xcat_settings').click(function() {
+ openSettings();
+ });
+
+ // Show service page
+ $("#content").children().remove();
+ includeJs("js/service/utils.js");
+ loadServicePage();
+
+ // Initialize tab index history
+ $.cookie('tabindex_history', '0,0');
+}
+
+/**
+ * Load service page
+ */
+function loadServicePage() {
+ // If the page is loaded
+ if ($('#content').children().length) {
+ // Do not load again
+ return;
+ }
+
+ // Create manage and provision tabs
+ serviceTabs = new Tab();
+ serviceTabs.init();
+ $('#content').append(serviceTabs.object());
+
+ var manageTabId = 'manageTab';
+ serviceTabs.add(manageTabId, 'Manage', '', false);
+
+ // Get nodes owned by user
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'nodetype',
+ msg : ''
+ },
+
+ success : function(data) {
+ setUserNodes(data);
+ setMaxVM();
+ getUserNodesDef();
+ getNodesCurrentLoad();
+ loadManagePage(manageTabId);
+ }
+ });
+
+ // Get OS image names
+ $.ajax({
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ async : true,
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'osimage',
+ msg : ''
+ },
+
+ success : function(data) {
+ setOSImageCookies(data);
+ }
+ });
+
+ // Get contents of hosts table
+ $.ajax({
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ async : true,
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'hosts',
+ msg : ''
+ },
+
+ success : function(data) {
+ setGroupCookies(data);
+ }
+ });
+
+ var provTabId = 'provisionTab';
+ serviceTabs.add(provTabId, 'Provision', '', false);
+ loadServiceProvisionPage(provTabId);
+
+ serviceTabs.select(manageTabId);
+}
+
+/**
+ * Load the service portal's provision page
+ *
+ * @param tabId Tab ID where page will reside
+ */
+function loadServiceProvisionPage(tabId) {
+ // Create info bar
+ var infoBar = createInfoBar('Select a platform to provision a node on, then click Ok.');
+
+ // Create provision page
+ var provPg = $('
');
+ $('#' + tabId).append(infoBar, provPg);
+
+ // Create radio buttons for platforms
+ var hwList = $('
Platforms available: ');
+ var esx = $('
ESX');
+ var kvm = $('
KVM');
+ var zvm = $('
z\/VM');
+
+ hwList.append(esx);
+ hwList.append(kvm);
+ hwList.append(zvm);
+ provPg.append(hwList);
+
+ /**
+ * Ok
+ */
+ var okBtn = createButton('Ok');
+ okBtn.bind('click', function(event) {
+ var userName = $.cookie('xcat_username');
+ var tmp = $.cookie(userName + '_usrnodes');
+
+ // Get maximun number for nodes from cookie
+ var nodes = '';
+ var maxVM = 0;
+ if (tmp.length) {
+ nodes = tmp.split(',');
+ maxVM = parseInt($.cookie(userName + '_maxvm'));
+
+ // Do not allow user to clone if the maximum number of VMs is reached
+ if (nodes.length >= maxVM) {
+ var warn = createWarnBar('You have reached the maximum number of virtual machines allowed (' + maxVM + '). Delete unused virtual machines or contact your system administrator request more virtual machines.');
+ warn.prependTo($('#' + tabId));
+ return;
+ }
+ }
+
+ // Get hardware that was selected
+ var hw = $(this).parent().find('input[name="hw"]:checked').val();
+ var newTabId = hw + 'ProvisionTab';
+
+ if ($('#' + newTabId).size() > 0){
+ serviceTabs.select(newTabId);
+ } else {
+ var title = '';
+
+ // Create an instance of the plugin
+ var plugin = null;
+ switch (hw) {
+ case "kvm":
+ plugin = new kvmPlugin();
+ title = 'KVM';
+ break;
+ case "esx":
+ plugin = new esxPlugin();
+ title = 'ESX';
+ break;
+ case "blade":
+ plugin = new bladePlugin();
+ title = 'BladeCenter';
+ break;
+ case "hmc":
+ plugin = new hmcPlugin();
+ title = 'System p';
+ break;
+ case "ipmi":
+ plugin = new ipmiPlugin();
+ title = 'iDataPlex';
+ break;
+ case "zvm":
+ plugin = new zvmPlugin();
+ title = 'z/VM';
+
+ // Get zVM host names
+ $.ajax({
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ async : false,
+ data : {
+ cmd : 'webportal',
+ tgt : '',
+ args : 'lszvm',
+ msg : ''
+ },
+
+ success : function(data) {
+ setzVMCookies(data);
+ }
+ });
+
+ // Get master copies for clone
+ $.ajax({
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ async : false,
+ data : {
+ cmd : 'webportal',
+ tgt : '',
+ args : 'lsgoldenimages',
+ msg : ''
+ },
+
+ success : function(data) {
+ setGoldenImagesCookies(data);
+ }
+ });
+
+ break;
+ }
+
+ // Select tab
+ serviceTabs.add(newTabId, title, '', true);
+ serviceTabs.select(newTabId);
+ plugin.loadServiceProvisionPage(newTabId);
+ }
+ });
+ provPg.append(okBtn);
+}
+
+/**
+ * Load manage page
+ *
+ * @param tabId Tab ID where page will reside
+ */
+function loadManagePage(tabId) {
+ // Create manage form
+ var manageForm = $('
');
+
+ // Append to manage tab
+ $('#' + tabId).append(manageForm);
+}
+
+/**
+ * Get the user nodes definitions
+ */
+function getUserNodesDef() {
+ var userName = $.cookie('xcat_username');
+ var userNodes = $.cookie(userName + '_usrnodes');
+ if (userNodes) {
+ // Get nodes definitions
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'lsdef',
+ tgt : '',
+ args : userNodes,
+ msg : ''
+ },
+
+ success : loadNodesTable
+ });
+ } else {
+ // Clear the tab before inserting the table
+ $('#manageTab').append(createWarnBar('No nodes were found belonging to you!'));
+ }
+}
+
+/**
+ * Load user nodes definitions into a table
+ *
+ * @param data Data from HTTP request
+ */
+function loadNodesTable(data) {
+ // Clear the tab before inserting the table
+ $('#manageTab').children().remove();
+
+ // Nodes datatable ID
+ var nodesDTId = 'userNodesDT';
+
+ // Hash of node attributes
+ var attrs = new Object();
+ // Node attributes
+ var headers = new Object();
+ var node = null, args;
+ // Create hash of node attributes
+ for (var i in data.rsp) {
+ // Get node name
+ if (data.rsp[i].indexOf('Object name:') > -1) {
+ var temp = data.rsp[i].split(': ');
+ node = jQuery.trim(temp[1]);
+
+ // Create a hash for the node attributes
+ attrs[node] = new Object();
+ i++;
+ }
+
+ // Get key and value
+ args = data.rsp[i].split('=', 2);
+ var key = jQuery.trim(args[0]);
+ var val = jQuery.trim(data.rsp[i].substring(data.rsp[i].indexOf('=') + 1, data.rsp[i].length));
+
+ // Create a hash table
+ attrs[node][key] = val;
+ headers[key] = 1;
+ }
+
+ // Sort headers
+ var sorted = new Array();
+ var attrs2show = new Array('arch', 'groups', 'hcp', 'hostnames', 'ip', 'os', 'userid', 'mgt');
+ for (var key in headers) {
+ // Show node attributes
+ if (jQuery.inArray(key, attrs2show) > -1) {
+ sorted.push(key);
+ }
+ }
+ sorted.sort();
+
+ // Add column for check box, node, ping, power, monitor, and comments
+ sorted.unshift('
',
+ 'node',
+ '
status ',
+ '
power ',
+ '
monitor ',
+ 'comments');
+
+ // Create a datatable
+ var nodesDT = new DataTable(nodesDTId);
+ nodesDT.init(sorted);
+
+ // Go through each node
+ for (var node in attrs) {
+ // Create a row
+ var row = new Array();
+
+ // Create a check box, node link, and get node status
+ var checkBx = $('
');
+ var nodeLink = $('
' + node + ' ').bind('click', loadNode);
+
+ // If there is no status attribute for the node, do not try to access hash table
+ // Else the code will break
+ var status = '';
+ if (attrs[node]['status']) {
+ status = attrs[node]['status'].replace('sshd', 'ping');
+ }
+
+ // Push in checkbox, node, status, monitor, and power
+ row.push(checkBx, nodeLink, status, '', '');
+
+ // If the node attributes are known (i.e the group is known)
+ if (attrs[node]['groups']) {
+ // Put in comments
+ var comments = attrs[node]['usercomment'];
+ // If no comments exists, show 'No comments' and set icon image source
+ var iconSrc;
+ if (!comments) {
+ comments = 'No comments';
+ iconSrc = 'images/nodes/ui-icon-no-comment.png';
+ } else {
+ iconSrc = 'images/nodes/ui-icon-comment.png';
+ }
+
+ // Create comments icon
+ var tipID = node + 'Tip';
+ var icon = $('
').css({
+ 'width': '18px',
+ 'height': '18px'
+ });
+
+ // Create tooltip
+ var tip = createCommentsToolTip(comments);
+ var col = $('
').append(icon);
+ col.append(tip);
+ row.push(col);
+
+ // Generate tooltips
+ icon.tooltip({
+ position: "center right",
+ offset: [-2, 10],
+ effect: "fade",
+ opacity: 0.8,
+ relative: true,
+ delay: 500
+ });
+ } else {
+ // Do not put in comments if attributes are not known
+ row.push('');
+ }
+
+ // Go through each header
+ for (var i = 6; i < sorted.length; i++) {
+ // Add the node attributes to the row
+ var key = sorted[i];
+
+ // Do not put comments and status in twice
+ if (key != 'usercomment' && key != 'status' && key.indexOf('statustime') < 0) {
+ var val = attrs[node][key];
+ if (val) {
+ row.push($('
' + val + ' '));
+ } else {
+ row.push('');
+ }
+ }
+ }
+
+ // Add the row to the table
+ nodesDT.add(row);
+ }
+
+ // Create info bar
+ var infoBar = createInfoBar('Manage and monitor your virtual machines.');
+ $('#manageTab').append(infoBar);
+
+ // Insert action bar and nodes datatable
+ $('#manageTab').append(nodesDT.object());
+
+ // Turn table into a datatable
+ $('#' + nodesDTId).dataTable({
+ 'iDisplayLength': 50,
+ 'bLengthChange': false,
+ "bScrollCollapse": true,
+ "sScrollY": "400px",
+ "sScrollX": "110%",
+ "bAutoWidth": true,
+ "oLanguage": {
+ "oPaginate": {
+ "sNext": "",
+ "sPrevious": ""
+ }
+ }
+ });
+
+ // Set datatable header class to add color
+ // $('.datatable thead').attr('class', 'ui-widget-header');
+
+ // Do not sort ping, power, and comment column
+ $('#' + nodesDTId + ' thead tr th').click(function() {
+ getNodeAttrs(group);
+ });
+ var checkboxCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(0)');
+ var pingCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
+ var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
+ var monitorCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
+ var commentCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(5)');
+ checkboxCol.unbind('click');
+ pingCol.unbind('click');
+ powerCol.unbind('click');
+ monitorCol.unbind('click');
+ commentCol.unbind('click');
+
+ // Refresh the node ping, power, and monitor status on-click
+ var nodes = getNodesShown(nodesDTId);
+ pingCol.find('span a').click(function() {
+ refreshNodeStatus(nodes);
+ });
+ powerCol.find('span a').click(function() {
+ refreshPowerStatus(nodes);
+ });
+ monitorCol.find('span a').click(function() {
+ refreshGangliaStatus(nodes);
+ });
+
+ // Create actions menu
+ // Power on
+ var powerOnLnk = $('
Power on ');
+ powerOnLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesDTId);
+ if (tgtNodes) {
+ powerNode(tgtNodes, 'on');
+ }
+ });
+
+ // Power off
+ var powerOffLnk = $('
Power off ');
+ powerOffLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesDTId);
+ if (tgtNodes) {
+ powerNode(tgtNodes, 'off');
+ }
+ });
+
+ // Power softoff
+ var powerSoftoffLnk = $('
Shutdown ');
+ powerSoftoffLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesDTId);
+ if (tgtNodes) {
+ powerNode(tgtNodes, 'softoff');
+ }
+ });
+
+ // Clone
+ var cloneLnk = $('
Clone ');
+ cloneLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesDTId);
+ if (tgtNodes) {
+ cloneNode(tgtNodes);
+ }
+ });
+
+ // Delete
+ var deleteLnk = $('
Delete ');
+ deleteLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesDTId);
+ if (tgtNodes) {
+ deleteNode(tgtNodes);
+ }
+ });
+
+ // Unlock
+ var unlockLnk = $('
Unlock ');
+ unlockLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesDTId);
+ if (tgtNodes) {
+ unlockNode(tgtNodes);
+ }
+ });
+
+ // Create action bar
+ var actionBar = $('
').css('width', '370px');
+
+ // Prepend menu to datatable
+ var actionsLnk = $('
Actions ');
+ var refreshLnk = $('
Refresh ');
+ refreshLnk.click(function() {
+ // Get nodes owned by user
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'nodetype',
+ msg : ''
+ },
+
+ success : function(data) {
+ // Save nodes owned by user
+ setUserNodes(data);
+ getNodesCurrentLoad();
+
+ // Refresh nodes table
+ var userName = $.cookie('xcat_username');
+ var userNodes = $.cookie(userName + '_usrnodes');
+ if (userNodes) {
+ // Get nodes definitions
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'lsdef',
+ tgt : '',
+ args : userNodes,
+ msg : ''
+ },
+
+ success : loadNodesTable
+ });
+ } else {
+ // Clear the tab before inserting the table
+ $('#manageTab').children().remove();
+ $('#manageTab').append(createWarnBar('You are not managing any node. Try to provision a node.'));
+ }
+ }
+ });
+ });
+
+ var actionMenu = createMenu([cloneLnk, deleteLnk, powerOnLnk, powerOffLnk, powerSoftoffLnk, unlockLnk]);
+ var menu = createMenu([[actionsLnk, actionMenu], refreshLnk]);
+ menu.superfish();
+ actionBar.append(menu);
+
+ // Set correct theme for action menu
+ actionMenu.find('li').hover(function() {
+ setMenu2Theme($(this));
+ }, function() {
+ setMenu2Normal($(this));
+ });
+
+ // Create a division to hold actions menu
+ var menuDiv = $('');
+ $('#' + nodesDTId + '_wrapper').prepend(menuDiv);
+ menuDiv.append(actionBar);
+ $('#' + nodesDTId + '_filter').appendTo(menuDiv);
+
+ // Get power and monitor status
+ var nodes = getNodesShown(nodesDTId);
+ refreshPowerStatus(nodes);
+ refreshGangliaStatus(nodes);
+}
+
+/**
+ * Refresh ping status for each node
+ *
+ * @param nodes Nodes to get ping status
+ */
+function refreshNodeStatus(nodes) {
+ // Show ping loader
+ var nodesDTId = 'userNodesDT';
+ var pingCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
+ pingCol.find('img').show();
+
+ // Get the node ping status
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'nodestat',
+ tgt : nodes,
+ args : '-u',
+ msg : ''
+ },
+
+ success : loadNodePing
+ });
+}
+
+/**
+ * Load node ping status for each node
+ *
+ * @param data Data returned from HTTP request
+ */
+function loadNodePing(data) {
+ var nodesDTId = 'userNodesDT';
+ var datatable = $('#' + nodesDTId).dataTable();
+ var rsp = data.rsp;
+ var args, rowPos, node, status;
+
+ // Get all nodes within datatable
+ for (var i in rsp) {
+ args = rsp[i].split(':');
+
+ // args[0] = node and args[1] = status
+ node = jQuery.trim(args[0]);
+ status = jQuery.trim(args[1]).replace('sshd', 'ping');
+
+ // Get row containing node
+ rowPos = findRow(node, '#' + nodesDTId, 1);
+
+ // Update ping status column
+ datatable.fnUpdate(status, rowPos, 2, false);
+ }
+
+ // Hide status loader
+ var pingCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
+ pingCol.find('img').hide();
+ adjustColumnSize(nodesDTId);
+}
+
+/**
+ * Refresh power status for each node
+ *
+ * @param nodes Nodes to get power status
+ */
+function refreshPowerStatus(nodes) {
+ // Show power loader
+ var nodesDTId = 'userNodesDT';
+ var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
+ powerCol.find('img').show();
+
+ // Get power status
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rpower',
+ tgt : nodes,
+ args : 'stat',
+ msg : ''
+ },
+
+ success : loadPowerStatus
+ });
+}
+
+/**
+ * Load power status for each node
+ *
+ * @param data Data returned from HTTP request
+ */
+function loadPowerStatus(data) {
+ var nodesDTId = 'userNodesDT';
+ var datatable = $('#' + nodesDTId).dataTable();
+ var power = data.rsp;
+ var rowPos, node, status, args;
+
+ for (var i in power) {
+ // power[0] = nodeName and power[1] = state
+ args = power[i].split(':');
+ node = jQuery.trim(args[0]);
+ status = jQuery.trim(args[1]);
+
+ // Get the row containing the node
+ rowPos = findRow(node, '#' + nodesDTId, 1);
+
+ // Update the power status column
+ datatable.fnUpdate(status, rowPos, 3, false);
+ }
+
+ // Hide power loader
+ var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
+ powerCol.find('img').hide();
+ adjustColumnSize(nodesDTId);
+}
+
+/**
+ * Refresh the status of Ganglia for each node
+ *
+ * @param nodes Nodes to get Ganglia status
+ */
+function refreshGangliaStatus(nodes) {
+ // Show ganglia loader
+ var nodesDTId = 'userNodesDT';
+ var gangliaCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
+ gangliaCol.find('img').show();
+
+ // Get the status of Ganglia
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliastatus;' + nodes,
+ msg : ''
+ },
+
+ success : loadGangliaStatus
+ });
+}
+
+/**
+ * Load the status of Ganglia for a given group
+ *
+ * @param data Data returned from HTTP request
+ */
+function loadGangliaStatus(data) {
+ // Get datatable
+ var nodesDTId = 'userNodesDT';
+ var datatable = $('#' + nodesDTId).dataTable();
+ var ganglia = data.rsp;
+ var rowNum, node, status;
+
+ for ( var i in ganglia) {
+ // ganglia[0] = nodeName and ganglia[1] = state
+ node = jQuery.trim(ganglia[i][0]);
+ status = jQuery.trim(ganglia[i][1]);
+
+ if (node) {
+ // Get the row containing the node
+ rowNum = findRow(node, '#' + nodesDTId, 1);
+
+ // Update the power status column
+ datatable.fnUpdate(status, rowNum, 4);
+ }
+ }
+
+ // Hide Ganglia loader
+ var gangliaCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
+ gangliaCol.find('img').hide();
+ adjustColumnSize(nodesDTId);
+}
+
+/**
+ * Load inventory for given node
+ *
+ * @param e Windows event
+ */
+function loadNode(e) {
+ if (!e) {
+ e = window.event;
+ }
+
+ // Get node that was clicked
+ var node = (e.target) ? e.target.id : e.srcElement.id;
+
+ // Create a new tab to show inventory
+ var tabId = node + '_inventory';
+
+ if(!$('#' + tabId).length) {
+ // Add new tab, only if one does not exist
+ var loader = createLoader(node + 'Loader');
+ loader = $('
').append(loader);
+ serviceTabs.add(tabId, node, loader, true);
+
+ // Get node inventory
+ var msg = 'out=' + tabId + ',node=' + node;
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rinv',
+ tgt : node,
+ args : 'all',
+ msg : msg
+ },
+
+ success : function(data) {
+ var args = data.msg.split(',');
+
+ // Get node
+ var node = args[1].replace('node=', '');
+
+ // Get the management plugin
+ var mgt = getNodeAttr(node, 'mgt');
+
+ // Create an instance of the plugin
+ var plugin;
+ switch (mgt) {
+ case "kvm":
+ plugin = new kvmPlugin();
+ break;
+ case "esx":
+ plugin = new esxPlugin();
+ break;
+ case "zvm":
+ plugin = new zvmPlugin();
+ break;
+ }
+
+ // Select tab
+ plugin.loadServiceInventory(data);
+ }
+ });
+ }
+
+ // Select new tab
+ serviceTabs.select(tabId);
+}
+
+/**
+ * Set a cookie for group names
+ *
+ * @param data Data from HTTP request
+ */
+function setGroupCookies(data) {
+ if (data.rsp) {
+ var groups = new Array();
+
+ // Index 0 is the table header
+ var cols, name, ip, hostname, desc, selectable, comments, tmp;
+ for (var i = 1; i < data.rsp.length; i++) {
+ // Set default description and selectable
+ selectable = "no";
+ desc = "No description";
+
+ // Split into columns:
+ // node, ip, hostnames, otherinterfaces, comments, disable
+ cols = data.rsp[i].split(',');
+ name = cols[0].replace(new RegExp('"', 'g'), '');
+ ip = cols[1].replace(new RegExp('"', 'g'), '');
+ hostname = cols[2].replace(new RegExp('"', 'g'), '');
+
+ // It should return: "description: All machines; network: 10.1.100.0/24;"
+ comments = cols[4].replace(new RegExp('"', 'g'), '');
+ tmp = comments.split('|');
+ for (var j = 0; j < tmp.length; j++) {
+ // Save description
+ if (tmp[j].indexOf('description:') > -1) {
+ desc = tmp[j].replace('description:', '');
+ desc = jQuery.trim(desc);
+ }
+
+ // Is the group selectable?
+ if (tmp[j].indexOf('selectable:') > -1) {
+ selectable = tmp[j].replace('selectable:', '');
+ selectable = jQuery.trim(selectable);
+ }
+ }
+
+ // Save groups that are selectable
+ if (selectable == "yes")
+ groups.push(name + ':' + ip + ':' + hostname + ':' + desc);
+ }
+
+ // Set cookie to expire in 60 minutes
+ var exDate = new Date();
+ exDate.setTime(exDate.getTime() + (240 * 60 * 1000));
+ $.cookie('srv_groups', groups, { expires: exDate });
+ }
+}
+
+/**
+ * Set a cookie for the OS images
+ *
+ * @param data Data from HTTP request
+ */
+function setOSImageCookies(data) {
+ // Get response
+ var rsp = data.rsp;
+
+ var imageNames = new Array();
+ var profilesHash = new Object();
+ var osVersHash = new Object();
+ var osArchsHash = new Object();
+ var imagePos = 0;
+ var profilePos = 0;
+ var osversPos = 0;
+ var osarchPos = 0;
+ var provMethodPos = 0;
+ var comments = 0;
+ var desc, selectable, tmp;
+ // Get column index for each attribute
+ var colNameArray = rsp[0].substr(1).split(',');
+ for (var i in colNameArray){
+ switch (colNameArray[i]){
+ case 'imagename': {
+ imagePos = i;
+ }
+ break;
+
+ case 'profile':{
+ profilePos = i;
+ }
+ break;
+
+ case 'osvers':{
+ osversPos = i;
+ }
+ break;
+
+ case 'osarch':{
+ osarchPos = i;
+ }
+ break;
+
+ case 'comments':{
+ comments = i;
+ }
+ break;
+
+ case 'provmethod':{
+ provMethodPos = i;
+ }
+ break;
+
+ default :
+ break;
+ }
+ }
+
+ // Go through each index
+ for (var i = 1; i < rsp.length; i++) {
+ // Get image name
+ var cols = rsp[i].split(',');
+ var osImage = cols[imagePos].replace(new RegExp('"', 'g'), '');
+ var profile = cols[profilePos].replace(new RegExp('"', 'g'), '');
+ var provMethod = cols[provMethodPos].replace(new RegExp('"', 'g'), '');
+ var osVer = cols[osversPos].replace(new RegExp('"', 'g'), '');
+ var osArch = cols[osarchPos].replace(new RegExp('"', 'g'), '');
+ var osComments = cols[comments].replace(new RegExp('"', 'g'), '');
+
+ // Only save install boot
+ if (provMethod.indexOf('install') > -1) {
+ if (osComments) {
+ // Only enable images where description and selectable comments exist
+ // Set default description and selectable
+ selectable = "no";
+ desc = "No description";
+
+ tmp = osComments.split('|');
+ for (var j = 0; j < tmp.length; j++) {
+ // Save description
+ if (tmp[j].indexOf('description:') > -1) {
+ desc = tmp[j].replace('description:', '');
+ desc = jQuery.trim(desc);
+ }
+
+ // Is the image selectable?
+ if (tmp[j].indexOf('selectable:') > -1) {
+ selectable = tmp[j].replace('selectable:', '');
+ selectable = jQuery.trim(selectable);
+ }
+ }
+
+ // Save images that are selectable
+ if (selectable == "yes")
+ imageNames.push(osImage + ':' + desc);
+ }
+
+ profilesHash[profile] = 1;
+ osVersHash[osVer] = 1;
+ osArchsHash[osArch] = 1;
+ }
+ }
+
+ // Save image names in a cookie
+ $.cookie('srv_imagenames', imageNames);
+
+ // Save profiles in a cookie
+ var tmp = new Array;
+ for (var key in profilesHash) {
+ tmp.push(key);
+ }
+ $.cookie('srv_profiles', tmp);
+
+ // Save OS versions in a cookie
+ tmp = new Array;
+ for (var key in osVersHash) {
+ tmp.push(key);
+ }
+ $.cookie('srv_osvers', tmp);
+
+ // Save OS architectures in a cookie
+ tmp = new Array;
+ for (var key in osArchsHash) {
+ tmp.push(key);
+ }
+ $.cookie('srv_osarchs', tmp);
+}
+
+
+
+/**
+ * Set a cookie for user nodes
+ *
+ * @param data Data from HTTP request
+ */
+function setUserNodes(data) {
+ if (data.rsp) {
+ // Get user name that is logged in
+ var userName = $.cookie('xcat_username');
+ var usrNodes = new Array();
+
+ // Ignore first columns because it is the header
+ for ( var i = 1; i < data.rsp.length; i++) {
+ // Go through each column
+ // where column names are: node, os, arch, profile, provmethod, supportedarchs, nodetype, comments, disable
+ var cols = data.rsp[i].split(',');
+ var node = cols[0].replace(new RegExp('"', 'g'), '');
+
+ // Comments can contain the owner and description
+ var comments = new Array();
+ if (cols[7].indexOf(';') > -1) {
+ comments = cols[7].replace(new RegExp('"', 'g'), '').split(';');
+ } else {
+ comments.push(cols[7].replace(new RegExp('"', 'g'), ''));
+ }
+
+ // Extract the owner
+ var owner;
+ for (var j in comments) {
+ if (comments[j].indexOf('owner:') > -1) {
+ owner = comments[j].replace('owner:', '');
+
+ if (owner == userName) {
+ usrNodes.push(node);
+ }
+
+ break;
+ }
+ }
+ } // End of for
+
+ // Set cookie to expire in 240 minutes
+ var exDate = new Date();
+ exDate.setTime(exDate.getTime() + (240 * 60 * 1000));
+ $.cookie(userName + '_usrnodes', usrNodes, { expires: exDate });
+ } // End of if
+}
+
+/**
+ * Power on a given node
+ *
+ * @param tgtNodes Node to power on or off
+ * @param power2 Power node to given state
+ */
+function powerNode(tgtNodes, power2) {
+ // Show power loader
+ var nodesDTId = 'userNodesDT';
+ var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
+ powerCol.find('img').show();
+
+ var nodes = tgtNodes.split(',');
+ for (var n in nodes) {
+ // Get hardware that was selected
+ var hw = getUserNodeAttr(nodes[n], 'mgt');
+
+ // Change to power softoff (to gracefully shutdown)
+ switch (hw) {
+ case "blade":
+ break;
+ case "hmc":
+ break;
+ case "ipmi":
+ break;
+ case "zvm":
+ if (power2 == 'off') {
+ power2 = 'softoff';
+ }
+
+ break;
+ }
+ }
+
+ $.ajax({
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rpower',
+ tgt : tgtNodes,
+ args : power2,
+ msg : tgtNodes
+ },
+
+ success : updatePowerStatus
+ });
+}
+
+/**
+ * Update power status of a node in the datatable
+ *
+ * @param data Data from HTTP request
+ */
+function updatePowerStatus(data) {
+ // Get datatable
+ var nodesDTId = 'userNodesDT';
+ var dTable = $('#' + nodesDTId).dataTable();
+
+ // Get xCAT response
+ var rsp = data.rsp;
+ // Loop through each line
+ var node, status, rowPos, strPos;
+ for (var i in rsp) {
+ // Get node name
+ node = rsp[i].split(":")[0];
+
+ // If there is no error
+ if (rsp[i].indexOf("Error") < 0 || rsp[i].indexOf("Failed") < 0) {
+ // Get the row containing the node link
+ rowPos = findRow(node, '#' + nodesDTId, 1);
+
+ // If it was power on, then the data return would contain "Starting"
+ strPos = rsp[i].indexOf("Starting");
+ if (strPos > -1) {
+ status = 'on';
+ } else {
+ status = 'off';
+ }
+
+ // Update the power status column
+ dTable.fnUpdate(status, rowPos, 3, false);
+ } else {
+ // Power on/off failed
+ alert(rsp[i]);
+ }
+ }
+
+ var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
+ powerCol.find('img').hide();
+ adjustColumnSize(nodesDTId);
+}
+
+/**
+ * Turn on monitoring for a given node
+ *
+ * @param node Node to monitor on or off
+ * @param monitor Monitor state, on or off
+ */
+function monitorNode(node, monitor) {
+ // Show ganglia loader
+ var nodesDTId = 'userNodesDT';
+ var gangliaCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
+ gangliaCol.find('img').show();
+
+ if (monitor == 'on') {
+ if (node) {
+ // Check if ganglia RPMs are installed
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliacheck;' + node,
+ msg : node // Node range will be passed along in data.msg
+ },
+
+ /**
+ * Start ganglia on a given node range
+ *
+ * @param data
+ * Data returned from HTTP request
+ * @return Nothing
+ */
+ success : function(data) {
+ // Get response
+ var out = data.rsp[0].split(/\n/);
+
+ // Go through each line
+ var warn = false;
+ var warningMsg = '';
+ for (var i in out) {
+ // If an RPM is not installed
+ if (out[i].indexOf('not installed') > -1) {
+ warn = true;
+
+ if (warningMsg) {
+ warningMsg += '
' + out[i];
+ } else {
+ warningMsg = out[i];
+ }
+ }
+ }
+
+ // If there are warnings
+ if (warn) {
+ // Create warning bar
+ var warningBar = createWarnBar(warningMsg);
+ warningBar.css('margin-bottom', '10px');
+ warningBar.prependTo($('#nodesTab'));
+ } else {
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliastart;' + data.msg,
+ msg : data.msg
+ },
+
+ success : function(data) {
+ // Remove any warnings
+ $('#nodesTab').find('.ui-state-error').remove();
+ refreshGangliaStatus(data.msg);
+ }
+ });
+ } // End of if (warn)
+ } // End of function(data)
+ });
+ }
+ } else {
+ var args;
+ if (node) {
+ args = 'gangliastop;' + node;
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : args,
+ msg : node
+ },
+
+ success : function(data) {
+ refreshGangliaStatus(data.msg);
+ }
+ });
+ }
+ }
+}
+
+/**
+ * Open a dialog to clone node
+ *
+ * @param tgtNodes Nodes to clone
+ */
+function cloneNode(tgtNodes) {
+ var userName = $.cookie('xcat_username');
+ var nodes = tgtNodes.split(',');
+ var tmp = $.cookie(userName + '_usrnodes');
+ var usrNodes = tmp.split(',');
+
+ var maxVM = parseInt($.cookie(userName + '_maxvm'));
+
+ // Do not allow user to clone if the maximum number of VMs is reached
+ if (usrNodes.length >= maxVM) {
+ var warn = createWarnBar('You have reached the maximum number of virtual machines allowed (' + maxVM + '). Delete un-used virtual machines or contact your system administrator request more virtual machines.');
+ warn.prependTo($('#manageTab'));
+ return;
+ }
+
+ for (var n in nodes) {
+ // Get hardware that was selected
+ var hw = getUserNodeAttr(nodes[n], 'mgt');
+
+ // Create an instance of the plugin
+ var plugin;
+ switch (hw) {
+ case "kvm":
+ plugin = new kvmPlugin();
+ break;
+ case "esx":
+ plugin = new esxPlugin();
+ break;
+ case "zvm":
+ plugin = new zvmPlugin();
+ break;
+ }
+
+ // Clone node
+ plugin.serviceClone(nodes[n]);
+ }
+}
+
+
+/**
+ * Open a dialog to delete node
+ *
+ * @param tgtNodes Nodes to delete
+ */
+function deleteNode(tgtNodes) {
+ var nodes = tgtNodes.split(',');
+
+ // Loop through each node and create target nodes string
+ var tgtNodesStr = '';
+ for (var i in nodes) {
+ if (i == 0 && i == nodes.length - 1) {
+ // If it is the 1st and only node
+ tgtNodesStr += nodes[i];
+ } else if (i == 0 && i != nodes.length - 1) {
+ // If it is the 1st node of many nodes, append a comma to the string
+ tgtNodesStr += nodes[i] + ', ';
+ } else {
+ if (i == nodes.length - 1) {
+ // If it is the last node, append nothing to the string
+ tgtNodesStr += nodes[i];
+ } else {
+ // Append a comma to the string
+ tgtNodesStr += nodes[i] + ', ';
+ }
+ }
+ }
+
+ // Confirm delete of node
+ var dialog = $('
');
+ var warn = createWarnBar('Are you sure you want to delete ' + tgtNodesStr + '?');
+ dialog.append(warn);
+
+ // Open dialog
+ dialog.dialog({
+ title: "Confirm",
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ width: 400,
+ buttons: {
+ "Yes": function(){
+ // Create status bar and append to tab
+ var instance = 0;
+ var statBarId = 'deleteStat' + instance;
+ while ($('#' + statBarId).length) {
+ // If one already exists, generate another one
+ instance = instance + 1;
+ statBarId = 'deleteStat' + instance;
+ }
+
+ var statBar = createStatusBar(statBarId);
+ var loader = createLoader('');
+ statBar.find('div').append(loader);
+ statBar.prependTo($('#manageTab'));
+
+ // Delete the virtual server
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rmvm',
+ tgt : tgtNodes,
+ args : '',
+ msg : 'out=' + statBarId + ';cmd=rmvm;tgt=' + tgtNodes
+ },
+
+ success : function(data) {
+ var args = data.msg.split(';');
+ var statBarId = args[0].replace('out=', '');
+ var tgts = args[2].replace('tgt=', '').split(',');
+
+ // Get data table
+ var nodesDTId = 'userNodesDT';
+ var dTable = $('#' + nodesDTId).dataTable();
+ var failed = false;
+
+ // Create an info box to show output
+ var output = writeRsp(data.rsp, '');
+ output.css('margin', '0px');
+ // Remove loader and append output
+ $('#' + statBarId + ' img').remove();
+ $('#' + statBarId + ' div').append(output);
+
+ // If there was an error, do not continue
+ if (output.html().indexOf('Error') > -1) {
+ failed = true;
+ }
+
+ // Update data table
+ var rowPos;
+ for (var i in tgts) {
+ if (!failed) {
+ // Get row containing the node link and delete it
+ rowPos = findRow(tgts[i], '#' + nodesDTId, 1);
+ dTable.fnDeleteRow(rowPos);
+ }
+ }
+
+ // Refresh nodes owned by user
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'nodetype',
+ msg : ''
+ },
+
+ success : function(data) {
+ setUserNodes(data);
+ }
+ });
+ }
+ });
+
+ $(this).dialog("close");
+ },
+ "No": function() {
+ $(this).dialog("close");
+ }
+ }
+ });
+}
+
+/**
+ * Unlock a node by setting the ssh keys
+ *
+ * @param tgtNodes Nodes to unlock
+ */
+function unlockNode(tgtNodes) {
+ var nodes = tgtNodes.split(',');
+
+ // Loop through each node and create target nodes string
+ var tgtNodesStr = '';
+ for (var i in nodes) {
+ if (i == 0 && i == nodes.length - 1) {
+ // If it is the 1st and only node
+ tgtNodesStr += nodes[i];
+ } else if (i == 0 && i != nodes.length - 1) {
+ // If it is the 1st node of many nodes, append a comma to the string
+ tgtNodesStr += nodes[i] + ', ';
+ } else {
+ if (i == nodes.length - 1) {
+ // If it is the last node, append nothing to the string
+ tgtNodesStr += nodes[i];
+ } else {
+ // Append a comma to the string
+ tgtNodesStr += nodes[i] + ', ';
+ }
+ }
+ }
+
+ var dialog = $('
');
+ var infoBar = createInfoBar('Give the root password for this node range to setup its SSH keys.');
+ dialog.append(infoBar);
+
+ var unlockForm = $('
').css('margin', '5px');
+ unlockForm.append('
Target node range:
');
+ unlockForm.append('
Password:
');
+ dialog.append(unlockForm);
+
+ dialog.find('div input').css('margin', '5px');
+
+ // Generate tooltips
+ unlockForm.find('div input[title]').tooltip({
+ position: "center right",
+ offset: [-2, 10],
+ effect: "fade",
+ opacity: 0.7,
+ predelay: 800,
+ events : {
+ def : "mouseover,mouseout",
+ input : "mouseover,mouseout",
+ widget : "focus mouseover,blur mouseout",
+ tooltip : "mouseover,mouseout"
+ }
+ });
+
+ // Open dialog
+ dialog.dialog({
+ title: "Confirm",
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ width: 450,
+ buttons: {
+ "Ok": function(){
+ // Create status bar and append to tab
+ var instance = 0;
+ var statBarId = 'unlockStat' + instance;
+ while ($('#' + statBarId).length) {
+ // If one already exists, generate another one
+ instance = instance + 1;
+ statBarId = 'unlockStat' + instance;
+ }
+
+ var statBar = createStatusBar(statBarId);
+ var loader = createLoader('');
+ statBar.find('div').append(loader);
+ statBar.prependTo($('#manageTab'));
+
+ // If a password is given
+ var password = unlockForm.find('input[name=password]:eq(0)');
+ if (password.val()) {
+ // Setup SSH keys
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'unlock;' + tgtNodes + ';' + password.val(),
+ msg : 'out=' + statBarId + ';cmd=unlock;tgt=' + tgtNodes
+ },
+
+ success : function(data) {
+ // Create an info box to show output
+ var output = writeRsp(data.rsp, '');
+ output.css('margin', '0px');
+ // Remove loader and append output
+ $('#' + statBarId + ' img').remove();
+ $('#' + statBarId + ' div').append(output);
+ }
+ });
+
+ $(this).dialog("close");
+ }
+ },
+ "Cancel": function() {
+ $(this).dialog("close");
+ }
+ }
+ });
+}
+
+/**
+ * Get nodes current load information
+ */
+function getNodesCurrentLoad(){
+ var userName = $.cookie('xcat_username');
+ var nodes = $.cookie(userName + '_usrnodes');
+
+ // Get nodes current status
+ $.ajax({
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliacurrent;node;' + nodes,
+ msg : ''
+ },
+
+ success: saveNodeLoad
+ });
+}
+
+/**
+ * Save node load data
+ *
+ * @param status Data returned from HTTP request
+ */
+function saveNodeLoad(status){
+ // Save node path and status for future use
+ nodePath = new Object();
+ nodeStatus = new Object();
+
+ // Get nodes status
+ var nodes = status.rsp[0].split(';');
+
+ var i = 0, pos = 0;
+ var node = '', tmpStr = '';
+ var tmpArry;
+
+ for (i = 0; i < nodes.length; i++){
+ tmpStr = nodes[i];
+ pos = tmpStr.indexOf(':');
+ node = tmpStr.substring(0, pos);
+ tmpArry = tmpStr.substring(pos + 1).split(',');
+
+ switch(tmpArry[0]){
+ case 'UNKNOWN':{
+ nodeStatus[node] = -2;
+ }
+ break;
+ case 'ERROR':{
+ nodeStatus[node] = -1;
+ }
+ break;
+ case 'WARNING':{
+ nodeStatus[node] = 0;
+ nodePath[node] = tmpArry[1];
+ }
+ break;
+ case 'NORMAL':{
+ nodeStatus[node] = 1;
+ nodePath[node] = tmpArry[1];
+ }
+ break;
+ }
+ }
+}
+
+/**
+ * Get monitoring metrics and load into inventory fieldset
+ *
+ * @param node Node to collect metrics
+ */
+function getMonitorMetrics(node) {
+ // Inventory tab should have this fieldset already created
+ // e.g.
+ $('#' + node + '_monitor').children('div').remove();
+
+ // Before trying to get the metrics, check if Ganglia is running
+ $.ajax({
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliastatus;' + node,
+ msg : ''
+ },
+
+ success: function(data) {
+ var ganglia = data.rsp;
+ var node, status;
+
+ // Get the ganglia status
+ for (var i in ganglia) {
+ // ganglia[0] = nodeName and ganglia[1] = state
+ node = jQuery.trim(ganglia[i][0]);
+ status = jQuery.trim(ganglia[i][1]);
+
+ if (node && status == 'on') {
+ // Get monitoring metrics
+ $.ajax({
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliashow;' + nodePath[node] + ';hour;_summary_',
+ msg : node
+ },
+
+ success: drawMonitoringCharts
+ });
+ } else if (node && status == 'off') {
+ var info = createInfoBar('Ganglia monitoring is disabled for this node');
+ $('#' + node + '_monitor').append(info.css('width', '300px'));
+ }
+ } // End of for
+ } // End of function
+ });
+}
+
+/**
+ * Draw monitoring charts based on node metrics
+ *
+ * @param data Data returned from HTTP request
+ */
+function drawMonitoringCharts(data){
+ var nodeMetrics = new Object();
+ var metricData = data.rsp[0].split(';');
+ var node = data.msg;
+
+ var metricName = '';
+ var metricVal = '';
+ var pos = 0;
+
+ // Go through the metrics returned
+ for (var m = 0; m < metricData.length; m++){
+ pos = metricData[m].indexOf(':');
+
+ // Get metric name
+ metricName = metricData[m].substr(0, pos);
+ nodeMetrics[metricName] = new Array();
+ // Get metric values
+ metricVal = metricData[m].substr(pos + 1).split(',');
+ // Save node metrics
+ for (var i = 0; i < metricVal.length; i++){
+ nodeMetrics[metricName].push(Number(metricVal[i]));
+ }
+ }
+
+ drawLoadFlot(node, nodeMetrics['load_one'], nodeMetrics['cpu_num']);
+ drawCpuFlot(node, nodeMetrics['cpu_idle']);
+ drawMemFlot(node, nodeMetrics['mem_free'], nodeMetrics['mem_total']);
+ drawDiskFlot(node, nodeMetrics['disk_free'], nodeMetrics['disk_total']);
+ drawNetworkFlot(node, nodeMetrics['bytes_in'], nodeMetrics['bytes_out']);
+}
+
+/**
+ * Draw load metrics flot
+ *
+ * @param node Node name
+ * @param loadpair Load timestamp and value pair
+ * @param cpupair CPU number and value pair
+ */
+function drawLoadFlot(node, loadPair, cpuPair){
+ var load = new Array();
+ var cpu = new Array();
+
+ var i = 0;
+ var yAxisMax = 0;
+ var interval = 1;
+
+ // Append flot to node monitoring fieldset
+ var loadFlot = $('
').css({
+ 'float': 'left',
+ 'height': '150px',
+ 'margin': '0 0 10px',
+ 'width': '300px'
+ });
+ $('#' + node + '_monitor').append(loadFlot);
+ $('#' + node + '_load').empty();
+
+ // Parse load pair where:
+ // timestamp must be mutiplied by 1000 and Javascript timestamp is in ms
+ for (i = 0; i < loadPair.length; i += 2){
+ load.push([loadPair[i] * 1000, loadPair[i + 1]]);
+ if (loadPair[i + 1] > yAxisMax){
+ yAxisMax = loadPair[i + 1];
+ }
+ }
+
+ // Parse CPU pair
+ for (i = 0; i < cpuPair.length; i += 2){
+ cpu.push([cpuPair[i] * 1000, cpuPair[i + 1]]);
+ if (cpuPair[i + 1] > yAxisMax){
+ yAxisMax = cpuPair[i + 1];
+ }
+ }
+
+ interval = parseInt(yAxisMax / 3);
+ if (interval < 1){
+ interval = 1;
+ }
+
+ $.jqplot(node + '_load', [load, cpu],{
+ title: ' Loads/Procs Last Hour',
+ axes:{
+ xaxis:{
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks: 4,
+ tickOptions : {
+ formatString : '%R',
+ show : true
+ }
+ },
+ yaxis: {
+ min : 0,
+ tickInterval : interval
+ }
+ },
+ legend : {
+ show: true,
+ location: 'nw'
+ },
+ series:[{label:'Load'}, {label: 'CPU Number'}],
+ seriesDefaults : {showMarker: false}
+ });
+}
+
+/**
+ * Draw CPU usage flot
+ *
+ * @param node Node name
+ * @param cpuPair CPU timestamp and value pair
+ */
+function drawCpuFlot(node, cpuPair){
+ var cpu = new Array();
+
+ // Append flot to node monitoring fieldset
+ var cpuFlot = $('
').css({
+ 'float': 'left',
+ 'height': '150px',
+ 'margin': '0 0 10px',
+ 'width': '300px'
+ });
+ $('#' + node + '_monitor').append(cpuFlot);
+ $('#' + node + '_cpu').empty();
+
+ // Time stamp should by mutiplied by 1000
+ // CPU idle comes from server, subtract 1 from idle
+ for(var i = 0; i < cpuPair.length; i +=2){
+ cpu.push([(cpuPair[i] * 1000), (100 - cpuPair[i + 1])]);
+ }
+
+ $.jqplot(node + '_cpu', [cpu],{
+ title: 'CPU Use Last Hour',
+ axes:{
+ xaxis:{
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks: 4,
+ tickOptions : {
+ formatString : '%R',
+ show : true
+ }
+ },
+ yaxis: {
+ min : 0,
+ max : 100,
+ tickOptions:{formatString : '%d\%'}
+ }
+ },
+ seriesDefaults : {showMarker: false}
+ });
+}
+
+/**
+ * Draw memory usage flot
+ *
+ * @param node Node name
+ * @param freePair Free memory timestamp and value pair
+ * @param totalPair Total memory timestamp and value pair
+ */
+function drawMemFlot(node, freePair, totalPair){
+ var used = new Array();
+ var total = new Array();
+ var size = 0;
+
+ // Append flot to node monitoring fieldset
+ var memoryFlot = $('
').css({
+ 'float': 'left',
+ 'height': '150px',
+ 'margin': '0 0 10px',
+ 'width': '300px'
+ });
+ $('#' + node + '_monitor').append(memoryFlot);
+ $('#' + node + '_memory').empty();
+
+ if(freePair.length < totalPair.length){
+ size = freePair.length;
+ } else {
+ size = freePair.length;
+ }
+
+ var tmpTotal, tmpUsed;
+ for(var i = 0; i < size; i+=2){
+ tmpTotal = totalPair[i+1];
+ tmpUsed = tmpTotal-freePair[i+1];
+ tmpTotal = tmpTotal/1000000;
+ tmpUsed = tmpUsed/1000000;
+ total.push([totalPair[i]*1000, tmpTotal]);
+ used.push([freePair[i]*1000, tmpUsed]);
+ }
+
+ $.jqplot(node + '_memory', [used, total],{
+ title: 'Memory Use Last Hour',
+ axes:{
+ xaxis:{
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks: 4,
+ tickOptions : {
+ formatString : '%R',
+ show : true
+ }
+ },
+ yaxis: {
+ min : 0,
+ tickOptions:{formatString : '%.2fG'}
+ }
+ },
+ legend : {
+ show: true,
+ location: 'nw'
+ },
+ series:[{label:'Used'}, {label: 'Total'}],
+ seriesDefaults : {showMarker: false}
+ });
+}
+
+/**
+ * Draw disk usage flot
+ *
+ * @param node Node name
+ * @param freePair Free disk space (Ganglia only logs free data)
+ * @param totalPair Total disk space
+ */
+function drawDiskFlot(node, freePair, totalPair) {
+ var used = new Array();
+ var total = new Array();
+ var size = 0;
+
+ // Append flot to node monitoring fieldset
+ var diskFlot = $('
').css({
+ 'float' : 'left',
+ 'height' : '150px',
+ 'margin' : '0 0 10px',
+ 'width' : '300px'
+ });
+ $('#' + node + '_monitor').append(diskFlot);
+ $('#' + node + '_disk').empty();
+
+ if (freePair.length < totalPair.length) {
+ size = freePair.length;
+ } else {
+ size = freePair.length;
+ }
+
+ var tmpTotal, tmpUsed;
+ for ( var i = 0; i < size; i += 2) {
+ tmpTotal = totalPair[i + 1];
+ tmpUsed = tmpTotal - freePair[i + 1];
+ total.push([ totalPair[i] * 1000, tmpTotal ]);
+ used.push([ freePair[i] * 1000, tmpUsed ]);
+ }
+
+ $.jqplot(node + '_disk', [ used, total ], {
+ title : 'Disk Use Last Hour',
+ axes : {
+ xaxis : {
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks : 4,
+ tickOptions : {
+ formatString : '%R',
+ show : true
+ }
+ },
+ yaxis : {
+ min : 0,
+ tickOptions : {
+ formatString : '%.2fG'
+ }
+ }
+ },
+ legend : {
+ show : true,
+ location : 'nw'
+ },
+ series : [ {
+ label : 'Used'
+ }, {
+ label : 'Total'
+ } ],
+ seriesDefaults : {
+ showMarker : false
+ }
+ });
+}
+
+/**
+ * Draw network usage flot
+ *
+ * @param node Node name
+ * @param freePair Free memory timestamp and value pair
+ * @param totalPair Total memory timestamp and value pair
+ */
+function drawNetworkFlot(node, inPair, outPair) {
+ var inArray = new Array();
+ var outArray = new Array();
+ var maxVal = 0;
+ var unitName = 'B';
+ var divisor = 1;
+
+ // Append flot to node monitoring fieldset
+ var diskFlot = $('
').css({
+ 'float' : 'left',
+ 'height' : '150px',
+ 'margin' : '0 0 10px',
+ 'width' : '300px'
+ });
+ $('#' + node + '_monitor').append(diskFlot);
+ $('#' + node + '_network').empty();
+
+ for (var i = 0; i < inPair.length; i += 2) {
+ if (inPair[i + 1] > maxVal) {
+ maxVal = inPair[i + 1];
+ }
+ }
+
+ for (var i = 0; i < outPair.length; i += 2) {
+ if (outPair[i + 1] > maxVal) {
+ maxVal = outPair[i + 1];
+ }
+ }
+
+ if (maxVal > 3000000) {
+ divisor = 1000000;
+ unitName = 'GB';
+ } else if (maxVal >= 3000) {
+ divisor = 1000;
+ unitName = 'MB';
+ } else {
+ // Do nothing
+ }
+
+ for (i = 0; i < inPair.length; i += 2) {
+ inArray.push([ (inPair[i] * 1000), (inPair[i + 1] / divisor) ]);
+ }
+
+ for (i = 0; i < outPair.length; i += 2) {
+ outArray.push([ (outPair[i] * 1000), (outPair[i + 1] / divisor) ]);
+ }
+
+ $.jqplot(node + '_network', [ inArray, outArray ], {
+ title : 'Network Last Hour',
+ axes : {
+ xaxis : {
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks : 4,
+ tickOptions : {
+ formatString : '%R',
+ show : true
+ }
+ },
+ yaxis : {
+ min : 0,
+ tickOptions : {
+ formatString : '%d' + unitName
+ }
+ }
+ },
+ legend : {
+ show : true,
+ location : 'nw'
+ },
+ series : [ {
+ label : 'In'
+ }, {
+ label : 'Out'
+ } ],
+ seriesDefaults : {
+ showMarker : false
+ }
+ });
+}
+
+/**
+ * Get an attribute of a given node
+ *
+ * @param node The node
+ * @param attrName The attribute
+ * @return The attribute of the node
+ */
+function getNodeAttr(node, attrName) {
+ // Get the row
+ var row = $('[id=' + node + ']').parents('tr');
+
+ // Search for the column containing the attribute
+ var attrCol = null;
+
+ var cols = row.parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th');
+ // Loop through each column
+ for (var i in cols) {
+ // Find column that matches the attribute
+ if (cols.eq(i).html() == attrName) {
+ attrCol = cols.eq(i);
+ break;
+ }
+ }
+
+ // If the column containing the attribute is found
+ if (attrCol) {
+ // Get the attribute column index
+ var attrIndex = attrCol.index();
+
+ // Get the attribute for the given node
+ var attr = row.find('td:eq(' + attrIndex + ')');
+ return attr.text();
+ } else {
+ return '';
+ }
+}
+
+/**
+ * Set the maximum number of VMs a user could have
+ */
+function setMaxVM() {
+ var userName = $.cookie('xcat_username');
+
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webportal',
+ tgt : '',
+ args : 'getmaxvm;' + userName,
+ msg : ''
+ },
+
+ success : function(data) {
+ // Get response
+ var rsp = jQuery.trim(data.rsp);
+ rsp = rsp.replace('Max allowed:', '');
+
+ // Set cookie to expire in 60 minutes
+ var exDate = new Date();
+ exDate.setTime(exDate.getTime() + (240 * 60 * 1000));
+ $.cookie(userName + '_maxvm', rsp, { expires: exDate });
+ }
+ });
}
\ No newline at end of file
diff --git a/xCAT-UI/js/ui.js b/xCAT-UI/js/ui.js
index 0a825f456..c0600d7a5 100644
--- a/xCAT-UI/js/ui.js
+++ b/xCAT-UI/js/ui.js
@@ -1,6 +1,6 @@
/**
* Tab constructor
- *
+ *
* @param tabId Tab ID
* @param tabName Tab name
*/
@@ -12,7 +12,7 @@ var Tab = function(tabId) {
/**
* Initialize the tab
- *
+ *
* @param tabName Tab name to initialize
*/
Tab.prototype.init = function() {
@@ -32,14 +32,14 @@ Tab.prototype.init = function() {
if ($.cookie('tabindex_history')) {
order = $.cookie('tabindex_history').split(',');
order[1] = order[0]; // Set index 1 to last selected tab
- order[0] = ui.index; // Set index 0 to currently selected tab
+ order[0] = ui.index; // Set index 0 to currently selected tab
} else {
// Create an array to track the tab selected
order = new Array;
order[0] = ui.index;
order[1] = ui.index;
}
-
+
$.cookie('tabindex_history', order);
});
@@ -52,7 +52,7 @@ Tab.prototype.init = function() {
/**
* Return the tab object
- *
+ *
* @return Object representing the tab
*/
Tab.prototype.object = function() {
@@ -61,7 +61,7 @@ Tab.prototype.object = function() {
/**
* Add a new tab
- *
+ *
* @param tabId Tab ID
* @param tabName Tab name
* @param tabCont Tab content
@@ -77,21 +77,21 @@ Tab.prototype.add = function(tabId, tabName, tabCont, closeable) {
newTab.append(tabCont);
this.tab.append(newTab);
this.tab.tabs("add", "#" + tabId, tabName);
-
+
// Append close button
if (closeable) {
var header = this.tab.find('ul.ui-tabs-nav a[href="#' + tabId +'"]').parent();
header.append('
');
-
+
// Get this tab
var tabs = this.tab;
- var tabLink = 'a[href="\#' + tabId + '"]';
+ var tabLink = 'a[href="\#' + tabId + '"]';
var thisTab = $(tabLink, tabs).parent();
-
+
// Close tab when close button is clicked
thisTab.find('span.tab-close').bind('click', function(event) {
var tabIndex = ($('li', tabs).index(thisTab));
-
+
// Do not remove first tab
if (tabIndex != 0) {
// Go back to last tab if user is trying to close currently selected tab
@@ -102,9 +102,9 @@ Tab.prototype.add = function(tabId, tabName, tabCont, closeable) {
tabs.tabs('select', parseInt(order[1]));
} else {
tabs.tabs('select', 0);
- }
- }
-
+ }
+ }
+
tabs.tabs('remove', tabIndex);
}
});
@@ -113,7 +113,7 @@ Tab.prototype.add = function(tabId, tabName, tabCont, closeable) {
/**
* Select a tab
- *
+ *
* @param id Tab ID to select
*/
Tab.prototype.select = function(id) {
@@ -122,11 +122,11 @@ Tab.prototype.select = function(id) {
/**
* Remove a tab
- *
+ *
* @param id Tab ID to remove
*/
Tab.prototype.remove = function(id) {
- var selectorStr = 'a[href="\#' + id + '"]';
+ var selectorStr = 'a[href="\#' + id + '"]';
var selectTab = $(selectorStr, this.tab).parent();
var index = ($('li', this.tab).index(selectTab));
this.tab.tabs("remove", index);
@@ -134,7 +134,7 @@ Tab.prototype.remove = function(id) {
/**
* Table constructor
- *
+ *
* @param tabId Tab ID
* @param tabName Tab name
*/
@@ -150,7 +150,7 @@ var Table = function(tableId) {
/**
* Initialize the table
- *
+ *
* @param Headers Array of table headers
*/
Table.prototype.init = function(headers) {
@@ -174,7 +174,7 @@ Table.prototype.init = function(headers) {
/**
* Return the table object
- *
+ *
* @return Object representing the table
*/
Table.prototype.object = function() {
@@ -183,7 +183,7 @@ Table.prototype.object = function() {
/**
* Add a row to the table
- *
+ *
* @param rowCont Array of table row contents
*/
Table.prototype.add = function(rowCont) {
@@ -204,7 +204,7 @@ Table.prototype.add = function(rowCont) {
/**
* Add a footer to the table
- *
+ *
* @param rowCont Array of table row contents
*/
Table.prototype.addFooter = function(rowCont) {
@@ -225,7 +225,7 @@ Table.prototype.remove = function(id) {
/**
* Datatable class constructor
- *
+ *
* @param tabId Tab ID
* @param tabName Tab name
*/
@@ -236,7 +236,7 @@ var DataTable = function(tableId) {
/**
* Initialize the datatable
- *
+ *
* @param Headers Array of table headers
*/
DataTable.prototype.init = function(headers) {
@@ -260,7 +260,7 @@ DataTable.prototype.init = function(headers) {
/**
* Return the datatable object
- *
+ *
* @return Object representing the table
*/
DataTable.prototype.object = function() {
@@ -269,7 +269,7 @@ DataTable.prototype.object = function() {
/**
* Add a row to the datatable
- *
+ *
* @param rowCont Array of table row contents
*/
DataTable.prototype.add = function(rowCont) {
@@ -290,7 +290,7 @@ DataTable.prototype.add = function(rowCont) {
/**
* Create status bar
- *
+ *
* @param barId Status bar ID
*/
function createStatusBar(barId) {
@@ -302,21 +302,21 @@ function createStatusBar(barId) {
'max-height': '150px',
'overflow': 'auto'
});
-
+
// Create info icon
var icon = $('
').css({
'display': 'inline-block',
'margin': '10px 5px',
'vertical-align': 'top'
});
-
+
// Create message section
var msg = $('
').css({
'display': 'inline-block',
'margin': '10px 0px',
'width': '90%'
});
-
+
// Create hide button
var hide = $('
').css({
'display': 'inline-block',
@@ -326,7 +326,7 @@ function createStatusBar(barId) {
// Remove info box on-click
$(this).parent().hide();
});
-
+
statusBar.append(icon);
statusBar.append(msg);
statusBar.append(hide);
@@ -335,7 +335,7 @@ function createStatusBar(barId) {
/**
* Create info bar
- *
+ *
* @param msg Info message
* @return Info bar
*/
@@ -353,7 +353,7 @@ function createInfoBar(msg) {
'display': 'inline-block',
'width': '90%'
});
-
+
infoBar.append(icon);
infoBar.append(barMsg);
return infoBar;
@@ -361,7 +361,7 @@ function createInfoBar(msg) {
/**
* Create warning bar
- *
+ *
* @param msg Warning message
* @return Warning bar
*/
@@ -375,7 +375,7 @@ function createWarnBar(msg) {
'display': 'inline-block',
'width': '90%'
});
-
+
warnBar.append(icon);
warnBar.append(barMsg);
return warnBar;
@@ -383,7 +383,7 @@ function createWarnBar(msg) {
/**
* Create a loader
- *
+ *
* @param loaderId Loader ID
*/
function createLoader(loaderId) {
@@ -393,7 +393,7 @@ function createLoader(loaderId) {
/**
* Create a button
- *
+ *
* @param name Name of the button
*/
function createButton(name) {
@@ -403,7 +403,7 @@ function createButton(name) {
/**
* Create a menu
- *
+ *
* @param items An array of items to go into the menu
* @return A division containing the menu
*/
@@ -424,17 +424,17 @@ function createMenu(items) {
} else {
item.append(items[i]);
}
-
+
menu.append(item);
}
-
+
return menu;
}
/**
* Initialize the page
*/
-function initPage() {
+function initPage() {
// Load theme
var theme = $.cookie('xcat_theme');
if (theme) {
@@ -459,7 +459,7 @@ function initPage() {
break;
default:
includeCss("css/themes/jquery-ui-start.css");
- }
+ }
} else {
includeCss("css/themes/jquery-ui-start.css");
}
@@ -469,10 +469,10 @@ function initPage() {
includeCss("css/superfish.css");
// includeCss("css/jstree.css");
includeCss("css/jquery.jqplot.css");
-
+
// Load custom stylesheet
includeCss("css/style.css");
-
+
// JQuery plugins
includeJs("js/jquery/jquery.dataTables.min.js");
includeJs("js/jquery/jquery.form.min.js");
@@ -490,13 +490,13 @@ function initPage() {
includeJs("js/jquery/jqplot.categoryAxisRenderer.min.js");
includeJs("js/jquery/jqplot.dateAxisRenderer.min.js");
includeJs("js/jquery/jquery.topzindex.min.js");
-
+
// Page plugins
- includeJs("js/configure/configure.js");
+ includeJs("js/configure/configure.js");
includeJs("js/monitor/monitor.js");
includeJs("js/nodes/nodes.js");
includeJs("js/provision/provision.js");
-
+
// Custom plugins
includeJs("js/custom/esx.js");
includeJs("js/custom/kvm.js");
@@ -506,11 +506,11 @@ function initPage() {
includeJs("js/custom/hmc.js");
includeJs("js/custom/customUtils.js");
- // Enable settings link
+ // Enable settings link
$('#xcat_settings').click(function() {
openSettings();
});
-
+
// Set header to theme
var background = '', color = '';
var theme = $.cookie('xcat_theme');
@@ -539,17 +539,17 @@ function initPage() {
break;
default:
background = '#6EAC2C';
- }
+ }
} else {
background = '#6EAC2C';
}
-
+
$('#header').addClass('ui-state-default');
$('#header').css('border', '0px');
-
+
// Set theme to user span
$('#login_user').css('color', color);
-
+
// Style for selected page
var style = {
'background-color': background,
@@ -560,26 +560,20 @@ function initPage() {
var url = window.location.pathname;
var page = url.replace('/xcat/', '');
var headers = $('#header ul li a');
-
+
// Show the page
$("#content").children().remove();
if (page == 'configure.php') {
includeJs("js/configure/update.js");
- includeJs("js/configure/discover.js");
includeJs("js/configure/service.js");
includeJs("js/configure/users.js");
+ includeJs("js/configure/files.js");
headers.eq(1).css(style);
loadConfigPage();
} else if (page == 'provision.php') {
includeJs("js/provision/images.js");
headers.eq(2).css(style);
loadProvisionPage();
- } else if (page == 'monitor.php') {
- includeJs("js/monitor/xcatmon.js");
- includeJs("js/monitor/rmcmon.js");
- includeJs("js/monitor/gangliamon.js");
- headers.eq(3).css(style);
- loadMonitorPage();
} else if (page == 'help.php') {
includeJs("js/help/help.js");
headers.eq(4).css(style);
@@ -589,8 +583,6 @@ function initPage() {
includeJs("js/nodes/nodeset.js");
includeJs("js/nodes/rnetboot.js");
includeJs("js/nodes/updatenode.js");
- includeJs("js/nodes/physical.js");
- includeJs("js/nodes/mtm.js");
includeJs("js/nodes/rscan.js");
headers.eq(0).css(style);
loadNodesPage();
@@ -599,7 +591,7 @@ function initPage() {
/**
* Include javascript file in
- *
+ *
* @param file File to include
*/
function includeJs(file) {
@@ -620,7 +612,7 @@ function includeJs(file) {
/**
* Include CSS link in
- *
+ *
* @param file File to include
*/
function includeCss(file) {
@@ -642,7 +634,7 @@ function includeCss(file) {
/**
* Write ajax response to a paragraph
- *
+ *
* @param rsp Ajax response
* @param pattern Pattern to replace with a break
* @return Paragraph containing ajax response
@@ -650,7 +642,7 @@ function includeCss(file) {
function writeRsp(rsp, pattern) {
// Create paragraph to hold ajax response
var prg = $('
');
-
+
for ( var i in rsp) {
if (rsp[i]) {
// Create regular expression for given pattern
@@ -661,7 +653,7 @@ function writeRsp(rsp, pattern) {
} else {
prg.append(rsp[i]);
prg.append('
');
- }
+ }
}
}
@@ -670,7 +662,7 @@ function writeRsp(rsp, pattern) {
/**
* Open a dialog and show given message
- *
+ *
* @param type Type of dialog, i.e. warn or info
* @param msg Message to show
*/
@@ -678,7 +670,7 @@ function openDialog(type, msg) {
var msgDialog = $('
');
var title = "";
if (type == "warn") {
- // Create warning message
+ // Create warning message
msgDialog.append(createWarnBar(msg));
title = "Warning";
} else {
@@ -686,7 +678,7 @@ function openDialog(type, msg) {
msgDialog.append(createInfoBar(msg));
title = "Info";
}
-
+
// Open dialog
msgDialog.dialog({
title: title,
@@ -696,7 +688,7 @@ function openDialog(type, msg) {
},
width: 500,
buttons: {
- "Ok": function(){
+ "Ok": function(){
$(this).dialog("close");
}
}
@@ -705,7 +697,7 @@ function openDialog(type, msg) {
/**
* Create an iframe to hold the output of an xCAT command
- *
+ *
* @param src The URL of the document to show in the iframe
* @return Info box containing the iframe
*/
@@ -714,7 +706,7 @@ function createIFrame(src) {
var infoBar = $('
').css({
'margin-bottom': '5px'
});
-
+
// Create info and close icons
var icon = $('
').css({
'display': 'inline-block',
@@ -728,28 +720,28 @@ function createIFrame(src) {
// Remove info box on-click
$(this).parent().remove();
});
-
+
var iframe = $('
').attr('src', src).css({
'display': 'block',
'border': '0px',
'margin': '10px',
'width': '100%'
});
-
+
var loader = createLoader('iLoader').css({
'display': 'block',
'margin': '10px 0px'
});
-
+
infoBar.append(icon);
infoBar.append($('
').append(loader, iframe));
infoBar.append(close);
-
+
// Remove loader when done
iframe.load(function() {
loader.remove();
});
-
+
return infoBar;
}
@@ -762,19 +754,19 @@ function openSettings() {
var dialog = $('
');
var info = createInfoBar('Select from the following options');
dialog.append(info);
-
+
var style = {
'color': 'blue',
'cursor': 'pointer',
'padding': '5px'
};
-
+
var changeThemeOption = $('
').css(style);
dialog.append(changeThemeOption);
-
+
var changePasswordOption = $('
').css(style);
dialog.append(changePasswordOption);
-
+
// Open form as a dialog
dialog.dialog({
modal: true,
@@ -789,13 +781,13 @@ function openSettings() {
}
}
});
-
+
// Bind to click event
changeThemeOption.click(function() {
dialog.dialog("close");
changeTheme();
});
-
+
changePasswordOption.click(function() {
dialog.dialog("close");
changePassword();
@@ -810,7 +802,7 @@ function changeTheme() {
var dialog = $('
');
var info = createInfoBar('Select the xCAT theme you desire');
dialog.append(info);
-
+
// Create select drop down for themes
var oList = $('
');
oList.append($('
Cupertino'));
@@ -820,7 +812,7 @@ function changeTheme() {
oList.append($('
Sunny'));
oList.append($('
UI Darkness'));
dialog.append(oList);
-
+
if ($.cookie('xcat_theme')) {
// Select theme
oList.find('input[value="' + $.cookie('xcat_theme') + '"]').attr('checked', true);
@@ -841,12 +833,12 @@ function changeTheme() {
// Save selected theme
var theme = $(this).find('input[name="theme"]:checked').val();
$.cookie('xcat_theme', theme); // Do not expire cookie, keep it as long as possible
-
+
// Show instructions to apply theme
$(this).empty();
var info = createInfoBar('You will need to reload this page in order for changes to take effect');
$(this).append(info);
-
+
// Only show close button
$(this).dialog("option", "buttons", {
"Close" : function() {
@@ -869,10 +861,10 @@ function changePassword() {
var dialog = $('
');
var info = createInfoBar('Change your password');
dialog.append(info);
-
+
dialog.append('
New password:
');
dialog.append('
Confirm password:
');
-
+
// Open form as a dialog
dialog.dialog({
modal: true,
@@ -885,22 +877,22 @@ function changePassword() {
"Ok": function(){
// Remove any warning messages
$(this).find('.ui-state-error').remove();
-
+
var errorMessage = "";
-
+
// Check each input is provided
$('#changePassword input').each(function() {
if (!$(this).val()) {
errorMessage = "Please provide a value for each missing input!";
}
});
-
+
// Do not continue if error found
if (errorMessage) {
dialog.prepend(createWarnBar(errorMessage));
return;
}
-
+
// Check new and confirm passwords match
var user = $.cookie('xcat_username');
var newPassword = $('#changePassword input[name="newPassword"]').val();
@@ -909,14 +901,14 @@ function changePassword() {
dialog.prepend(createWarnBar("Please confirm new password!"));
return;
}
-
+
// Change dialog buttons
$('#changePassword').dialog('option', 'buttons', {
'Close':function(){
$('#changePassword').dialog('destroy').remove();
}
});
-
+
// Send request to change password
var url = window.location.pathname;
var page = url.replace('/xcat/', '');
@@ -933,13 +925,13 @@ function changePassword() {
args : 'passwd;' + user + ';' + newPassword,
msg : ''
},
-
+
success : function (data) {
// Show response message
var rspMessage = "";
for (var i in data.rsp)
rspMessage += data.rsp[i] + "
";
-
+
$('#changePassword').prepend(createInfoBar(rspMessage));
}
});
@@ -953,7 +945,7 @@ function changePassword() {
/**
* Adjust datatable column size
- *
+ *
* @param tableId Table ID
*/
function adjustColumnSize(tableId) {
@@ -963,7 +955,7 @@ function adjustColumnSize(tableId) {
/**
* Set menu theme
- *
+ *
* @param menu Menu object
*/
function setMenu2Theme(menu) {
@@ -995,18 +987,18 @@ function setMenu2Theme(menu) {
break;
default:
background = '#6EAC2C';
- }
+ }
} else {
background = '#6EAC2C';
}
-
+
menu.css('background', background);
menu.find('a:eq(0)').css('color', color);
}
/**
* Set menu back to normal before applying theme
- *
+ *
* @param menu Menu object
*/
function setMenu2Normal(menu) {
@@ -1017,7 +1009,7 @@ function setMenu2Normal(menu) {
/**
* Get nodes that are checked in a given datatable
- *
+ *
* @param datatableId The datatable ID
* @return Nodes that were checked
*/
@@ -1028,10 +1020,10 @@ function getNodesChecked(datatableId) {
var nodes = $('#' + datatableId + ' input[type=checkbox]:checked');
for (var i in nodes) {
var tgtNode = nodes.eq(i).attr('name');
-
+
if (tgtNode) {
tgts += tgtNode;
-
+
// Add a comma at the end
if (i < nodes.length - 1) {
tgts += ',';
@@ -1044,7 +1036,7 @@ function getNodesChecked(datatableId) {
/**
* Check if return message contains errors
- *
+ *
* @param msg Return message
* @return 0 If return message contains no errors
* -1 If return message contains errors
diff --git a/xCAT-UI/lib/functions.php b/xCAT-UI/lib/functions.php
index a59e44eef..51827fc4e 100644
--- a/xCAT-UI/lib/functions.php
+++ b/xCAT-UI/lib/functions.php
@@ -81,7 +81,7 @@ function submit_request($req, $skipVerify, $opts_array){
// Open syslog, include the process ID and also send the log to standard error,
// and use a user defined logging mechanism
- openlog("xcat", LOG_PID | LOG_PERROR, LOG_LOCAL0);
+ openlog("xCAT-UI", LOG_PID | LOG_PERROR, LOG_LOCAL0);
// Open a socket to xcatd
syslog(LOG_INFO, "Opening socket to xcatd...");
diff --git a/xCAT-UI/lib/srv_functions.php b/xCAT-UI/lib/srv_functions.php
index 161af8ecc..6dafe540e 100644
--- a/xCAT-UI/lib/srv_functions.php
+++ b/xCAT-UI/lib/srv_functions.php
@@ -79,7 +79,7 @@ function submit_request($req, $skipVerify, $opts_array){
// Open syslog, include the process ID and also send
// the log to standard error, and use a user defined
// logging mechanism
- openlog("xcat", LOG_PID | LOG_PERROR, LOG_LOCAL0);
+ openlog("xCAT-UI", LOG_PID | LOG_PERROR, LOG_LOCAL0);
// Open a socket to xcatd
syslog(LOG_INFO, "Opening socket to xcatd...");
diff --git a/xCAT-UI/lib/ui.php b/xCAT-UI/lib/ui.php
index c45b83a26..c2e8d515c 100644
--- a/xCAT-UI/lib/ui.php
+++ b/xCAT-UI/lib/ui.php
@@ -25,7 +25,6 @@ function loadPage() {
Nodes
Configure
Provision
-
Monitor
Help
';
diff --git a/xCAT-UI/xCAT-UI.spec b/xCAT-UI/xCAT-UI.spec
index 43d033b20..e0be817db 100644
--- a/xCAT-UI/xCAT-UI.spec
+++ b/xCAT-UI/xCAT-UI.spec
@@ -19,6 +19,12 @@ Requires: xCAT-UI-deps >= 2.6
Distribution: %{?_distribution:%{_distribution}}%{!?_distribution:%{_vendor}}
Prefix: /opt/xcat
+%define s390x %(if [ "$s390x" = "1" ];then echo 1; else echo 0; fi)
+%define nots390x %(if [ "$s390x" = "1" ];then echo 0; else echo 1; fi)
+
+# Define a different location for various httpd configs in s390x mode
+%define httpconfigdir %(if [ "$s390x" = "1" ];then echo "xcathttpdsave"; else echo "xcat"; fi)
+
%ifos linux
# httpd is provided as apache2 on SLES and httpd on RHEL
Requires: httpd
@@ -35,39 +41,24 @@ Provides a browser-based interface for xCAT (Extreme Cloud Administration Toolki
# Minify Javascript files using Google Compiler
echo "Minifying Javascripts... This will take a couple of minutes."
-COMPILER_JAR='/xcat2/build/tools/compiler.jar'
+#COMPILER_JAR='/xcat2/build/tools/compiler.jar'
+COMPILER_JAR='/root/scripts/compiler.jar'
UI_JS="js/"
%ifos linux
-JAVA='/opt/ibm/java-ppc64-60/jre/bin/java'
+JAVA='/usr/bin/java'
# Find all Javascript files
declare -a FILES
FILES=`find ${UI_JS} -name '*.js'`
for i in ${FILES[*]}; do
- # Ignore Javascripts that are already minified
- if [[ ! $i =~ '.*\.min\.js$' ]]; then
- echo " Minifying $i ..."
- `${JAVA} -jar ${COMPILER_JAR} --warning_level=QUIET --js=$i --js_output_file=$i.min`
-
- # Remove old Javascript and replace it with minified version
- rm -rf $i
- mv $i.min $i
- fi
-done
+ # Ignore Javascripts that are already minified
+ if [[ ! $i =~ '.*\.min\.js$' ]]; then
+ echo " Minifying $i ..."
+ `${JAVA} -jar ${COMPILER_JAR} --warning_level=QUIET --js=$i --js_output_file=$i.min`
-%else # AIX
-JAVA='/usr/java6_64/bin/java'
-# Find all Javascript files
-FILES=`find ${UI_JS} -name '*.js'`
-for i in ${FILES[*]}; do
- # Ignore Javascripts that are already minified
- if [[ ! $i = @(*.min.js) ]]; then
- echo " Minifying $i ..."
- `${JAVA} -jar ${COMPILER_JAR} --warning_level=QUIET --js=$i --js_output_file=$i.min`
-
- # Remove old Javascript and replace it with minified version
- rm -rf $i
- mv $i.min $i
+ # Remove old Javascript and replace it with minified version
+ rm -rf $i
+ mv $i.min $i
fi
done
%endif
@@ -81,6 +72,12 @@ rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT%{prefix}/ui
cp -r * $RPM_BUILD_ROOT%{prefix}/ui
chmod 755 $RPM_BUILD_ROOT%{prefix}/ui/*
+mkdir -p $RPM_BUILD_ROOT/etc/%httpconfigdir/conf.orig
+mkdir -p $RPM_BUILD_ROOT/etc/apache2/conf.d
+mkdir -p $RPM_BUILD_ROOT/etc/httpd/conf.d
+mkdir -p $RPM_BUILD_ROOT%{prefix}/etc/%httpconfigdir/conf.orig
+#mkdir -p $RPM_BUILD_ROOT%{prefix}/etc/apache2/conf.d
+#mkdir -p $RPM_BUILD_ROOT%{prefix}/etc/httpd/conf.d
# Copy over xCAT UI plugins
mkdir -p $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin
@@ -88,11 +85,24 @@ cp xcat/plugins/* $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin
chmod 644 $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin/web.pm
chmod 644 $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin/webportal.pm
+#Copy the different conf files for httpd
+cp etc/apache2/conf.d/xcat-ui.conf.apach22 $RPM_BUILD_ROOT/etc/%httpconfigdir/conf.orig/xcat-ui.conf.apach22
+cp etc/apache2/conf.d/xcat-ui.conf.apach24 $RPM_BUILD_ROOT/etc/%httpconfigdir/conf.orig/xcat-ui.conf.apach24
+
+#install lower version(<2.4) apache/httpd conf files by default
+cp $RPM_BUILD_ROOT/etc/%httpconfigdir/conf.orig/xcat-ui.conf.apach22 $RPM_BUILD_ROOT/etc/apache2/conf.d/xcat-ui.conf
+cp $RPM_BUILD_ROOT/etc/%httpconfigdir/conf.orig/xcat-ui.conf.apach22 $RPM_BUILD_ROOT/etc/httpd/conf.d/xcat-ui.conf
+
# Create symbolic link to webportal command
-mkdir -p $RPM_BUILD_ROOT/%{prefix}/bin
-ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/webportal
+mkdir -p $RPM_BUILD_ROOT%{prefix}/bin
+ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT%{prefix}/bin/webportal
%files
+/etc/apache2/conf.d/xcat-ui.conf
+/etc/httpd/conf.d/xcat-ui.conf
+/etc/%httpconfigdir/conf.orig/xcat-ui.conf.apach22
+/etc/%httpconfigdir/conf.orig/xcat-ui.conf.apach24
+
%defattr(-,root,root)
%{prefix}
@@ -100,19 +110,28 @@ ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/webportal
#********** Pre-install **********
# Inspect whether PHP related RPM packages are installed
%ifos linux
- if [ -e "/etc/redhat-release" ]; then
- if [ ! -e "/etc/httpd/conf.d/php.conf" ]; then
- echo ""
- echo "Error! php has not been installed. Please run 'yum install php' before installing xCAT-UI.";
- exit -1;
- fi
- else # SUSE
- if [ ! -e "/etc/apache2/conf.d/php5.conf" ]; then
- echo ""
- echo "Error! apache2-mod_php5 and php5 have not been installed. Please run 'zypper install apache2-mod_php5 php5' before installing xCAT-UI."
- exit -1;
- fi
- fi
+ if [ -e "/etc/redhat-release" ]; then
+ rpm -q php >/dev/null
+ if [ $? != 0 ]; then
+ echo ""
+ echo "Error! php has not been installed. Please run 'yum install php' before installing xCAT-UI.";
+ exit -1;
+ fi
+ elif [ -e "/opt/ibm/cmo/version" ]; then # IBM Cloud Manager Appliance
+ rpm -q php >/dev/null
+ if [ $? != 0 ]; then
+ echo ""
+ echo "Error! Can not find php. Please make sure php is installed before installing xCAT-UI.";
+ exit -1;
+ fi
+ else # SUSE
+ rpm -q apache2-mod_php5 php5 >/dev/null
+ if [ $? != 0 ]; then
+ echo ""
+ echo "Error! apache2-mod_php5 and php5 have not been installed. Please run 'zypper install apache2-mod_php5 php5' before installing xCAT-UI."
+ exit -1;
+ fi
+ fi
%else # AIX
if [ -e "/usr/IBM/HTTPServer/conf/httpd.conf" ]; then
echo "Installing xCAT-UI on AIX..."
@@ -127,92 +146,74 @@ ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/webportal
#********** Post-install **********
# Get apache name
%ifos linux
- if [ -e "/etc/redhat-release" ]; then
- apachedaemon='httpd'
- apacheuser='apache'
- else # SUSE
- apachedaemon='apache2'
- apacheuser='wwwrun'
- fi
+ if [ "$1" = 1 ] # Install
+ then
+ # Automatically put encrypted password into the xCAT passwd database
+ %{prefix}/sbin/chtab key=xcat,username=root passwd.password=`grep root /etc/shadow|cut -d : -f 2`
- if [ "$1" = 1 ] # Install
- then
- # Update apache conf
- /bin/rm -f /etc/$apachedaemon/conf.d/xcat-ui.conf
- /bin/ln -s %{prefix}/ui/etc/apache2/conf.d/xcat-ui.conf /etc/$apachedaemon/conf.d/xcat-ui.conf
-
- # Automatically put encrypted password into the xCAT passwd database
- %{prefix}/sbin/chtab key=xcat,username=root passwd.password=`grep root /etc/shadow|cut -d : -f 2`
-
- echo "To use xCAT-UI, point your browser to http://"`hostname -f`"/xcat"
- fi
-
- if [ "$1" = 1 ] || [ "$1" = 2 ] # Install or upgrade
- then
- # Restart xCAT
- /etc/init.d/xcatd restart
-
- # Copy php.ini file into /opt/xcat/ui and turn off output_buffering
- if [ -e "/etc/redhat-release" ]; then
- /bin/sed /etc/php.ini -e 's/output_buffering = 4096/output_buffering = Off/g' > %{prefix}/ui/php.ini
- else # SUSE
- /bin/sed /etc/php5/apache2/php.ini -e 's/output_buffering = 4096/output_buffering = Off/g' > %{prefix}/ui/php.ini
- fi
-
- # Restart Apache Server
- /etc/init.d/$apachedaemon restart
- true
- fi
-%else # AIX
- ihs_config_dir='/usr/IBM/HTTPServer/conf'
- if [ "$1" = 1 ] #initial install
- then
- # Check if IBM HTTP Server is installed in the default directory
- # Update the apache config
- echo "Updating IBM HTTP server configuration for xCAT..."
- bin/rm -f /usr/IBM/HTTPServer/conf/xcat-ui.conf
- cp /usr/IBM/HTTPServer/conf/httpd.conf /usr/IBM/HTTPServer/conf/httpd.conf.xcat.ui.bak
- cat ../ui/etc/apache2/conf.d/xcat-ui.conf >> /usr/IBM/HTTPServer/conf/httpd.conf
- /usr/IBM/HTTPServer/bin/apachectl restart
-
- # Put the encrypted password in /etc/security/passwd into the xcat passwd database
- CONT=`cat /etc/security/passwd`
- %{prefix}/sbin/chtab key=xcat,username=root passwd.password=`echo $CONT |cut -d ' ' -f 4`
- fi
+ echo "To use xCAT-UI, point your browser to http://"`hostname -f`"/xcat"
+ fi
- if [ "$1" = 1 ] || [ "$1" = 2 ] # Install or upgrade
- then
- # Uncomment this if we change xcat-ui.conf again
- # /etc/init.d/$apachedaemon restart
- true
- fi
-%endif
+ # If httpd is 2.4 or newer, use the file with the new configuration options
+ #Apply the correct httpd/apache configuration file according to the httpd/apache version
+ if [ -n "$(httpd -v 2>&1 |grep -e '^Server version\s*:.*\/2.4')" ]
+ then
+ /bin/rm -rf /etc/httpd/conf.d/xcat-ui.conf
+ /bin/rm -rf /opt/xcat/ui/etc/apache2/conf.d/xcat-ui.conf
+ /bin/cp -f /etc/%httpconfigdir/conf.orig/xcat-ui.conf.apach24 /etc/httpd/conf.d/xcat-ui.conf
+ /bin/cp -f /etc/%httpconfigdir/conf.orig/xcat-ui.conf.apach24 /etc/apache2/conf.d/xcat-ui.conf
+ fi
-%preun
-#********** Pre-uninstall **********
-%ifos linux
- if [ "$1" = 0 ] # RPM being removed
- then
- if [ -e "/etc/redhat-release" ]; then
- apachedaemon='httpd'
- apacheuser='apache'
- else # SUSE
- apachedaemon='apache2'
- apacheuser='wwwrun'
- fi
-
- # Remove links made during the post install script
- echo "Undoing $apachedaemon configuration for xCAT..."
- /bin/rm -f /etc/$apachedaemon/conf.d/xcat-ui.conf
- /bin/rm -f %{prefix}/ui/php.ini
- /etc/init.d/$apachedaemon reload
- fi
+ if [ -n "$(apachectl -v 2>&1 |grep -e '^Server version\s*:.*\/2.4')" ]
+ then
+ /bin/rm -rf /etc/httpd/conf.d/xcat-ui.conf
+ /bin/rm -rf /opt/xcat/ui/etc/apache2/conf.d/xcat-ui.conf
+ /bin/cp -f /etc/%httpconfigdir/conf.orig/xcat-ui.conf.apach24 /etc/httpd/conf.d/xcat-ui.conf
+ /bin/cp -f /etc/%httpconfigdir/conf.orig/xcat-ui.conf.apach24 /etc/apache2/conf.d/xcat-ui.conf
+ fi
+
+ if [ -n "$(apache2ctl -v 2>&1 |grep -e '^Server version\s*:.*\/2.4')" ]
+ then
+ /bin/rm -rf /etc/httpd/conf.d/xcat-ui.conf
+ /bin/rm -rf /opt/xcat/ui/etc/apache2/conf.d/xcat-ui.conf
+ /bin/cp -f /etc/%httpconfigdir/conf.orig/xcat-ui.conf.apach24 /etc/httpd/conf.d/xcat-ui.conf
+ /bin/cp -f /etc/%httpconfigdir/conf.orig/xcat-ui.conf.apach24 /etc/apache2/conf.d/xcat-ui.conf
+ fi
+
+
+ if [ "$1" = 1 ] || [ "$1" = 2 ] # Install or upgrade
+ then
+ # Restart xCAT
+ /etc/init.d/xcatd restart
+
+ # Copy php.ini file into /opt/xcat/ui and turn off output_buffering
+ if [ -e "/etc/redhat-release" ]; then
+ /bin/sed /etc/php.ini -e 's/output_buffering = 4096/output_buffering = Off/g' > %{prefix}/ui/php.ini
+ elif [ -e "/opt/ibm/cmo/version" ]; then # IBM Cloud Manager Appliance
+ /bin/sed /etc/php.ini -e 's/output_buffering = 4096/output_buffering = Off/g' > %{prefix}/ui/php.ini
+ else # SUSE
+ /bin/sed /etc/php5/apache2/php.ini -e 's/output_buffering = 4096/output_buffering = Off/g' > %{prefix}/ui/php.ini
+ fi
+
+ # Restart Apache Server
+ /etc/init.d/httpd restart
+ true
+ fi
%else # AIX
- # Remove links made during the post install script
- echo "Undoing IBM HTTP Server configuration for xCAT..."
- if [ -e "/usr/IBM/HTTPServer/conf/httpd.conf.xcat.ui.bak" ];then
- cp /usr/IBM/HTTPServer/conf/httpd.conf.xcat.ui.bak /usr/IBM/HTTPServer/conf/httpd.conf
- rm -rf /usr/IBM/HTTPServer/conf/httpd.conf.xcat.ui.bak
- fi
- /usr/IBM/HTTPServer/bin/apachectl restart
+ ihs_config_dir='/usr/IBM/HTTPServer/conf'
+ if [ "$1" = 1 ] #initial install
+ then
+ # Check if IBM HTTP Server is installed in the default directory
+ # Update the apache config
+ echo "Updating IBM HTTP server configuration for xCAT..."
+ bin/rm -f /usr/IBM/HTTPServer/conf/xcat-ui.conf
+ cp /usr/IBM/HTTPServer/conf/httpd.conf /usr/IBM/HTTPServer/conf/httpd.conf.xcat.ui.bak
+ cat ../ui/etc/apache2/conf.d/xcat-ui.conf >> /usr/IBM/HTTPServer/conf/httpd.conf
+ /usr/IBM/HTTPServer/bin/apachectl restart
+
+ # Put the encrypted password in /etc/security/passwd into the xcat passwd database
+ CONT=`cat /etc/security/passwd`
+ %{prefix}/sbin/chtab key=xcat,username=root passwd.password=`echo $CONT |cut -d ' ' -f 4`
+ fi
+
%endif
diff --git a/xCAT-UI/xcat/plugins/web.pm b/xCAT-UI/xcat/plugins/web.pm
index 6edf205e7..fd3c0650e 100644
--- a/xCAT-UI/xcat/plugins/web.pm
+++ b/xCAT-UI/xcat/plugins/web.pm
@@ -1,2596 +1,2686 @@
-# IBM(c) 2011 EPL license http://www.eclipse.org/legal/epl-v10.html
-#-------------------------------------------------------
-
-=head 1
-
- xCAT plugin to handle xCAT UI commands
-
-=cut
-
-#-------------------------------------------------------
-
-package xCAT_plugin::web;
-use strict;
-require xCAT::Utils;
-require xCAT::MsgUtils;
-require xCAT::DBobjUtils;
-require IO::Socket::INET;
-use Getopt::Long;
-use Data::Dumper;
-use LWP::Simple;
-use xCAT::Table;
-use xCAT::NodeRange;
-use xCAT::TableUtils;
-require XML::Parser;
-
-sub handled_commands {
- return { webrun => "web" };
-}
-
-sub process_request {
- my $request = shift;
- my $callback = shift;
- my $sub_req = shift;
- my %authorized_cmds = (
- 'update' => \&web_update,
- 'lscondition' => \&web_lscond,
- 'lsresponse' => \&web_lsresp,
- 'lscondresp' => \&web_lscondresp,
- 'mkcondresp' => \&web_mkcondresp,
- 'startcondresp' => \&web_startcondresp,
- 'stopcondresp' => \&web_stopcondresp,
- 'lsevent' => \&web_lsevent,
- 'unlock' => \&web_unlock,
- 'rmcstart' => \&web_rmcmonStart,
- 'rmcshow' => \&web_rmcmonShow,
- 'gangliaconf' => \&web_gangliaconf,
- 'gangliastart' => \&web_gangliastart,
- 'gangliastop' => \&web_gangliastop,
- 'gangliastatus' => \&web_gangliastatus,
- 'gangliacheck' => \&web_gangliacheck,
- 'installganglia' => \&web_installganglia,
- 'mkcondition' => \&web_mkcondition,
- 'monls' => \&web_monls,
- 'dynamiciprange' => \&web_dynamiciprange,
- 'discover' => \&web_discover,
- 'updatevpd' => \&web_updatevpd,
- 'writeconfigfile' => \&web_writeconfigfile,
- 'createimage' => \&web_createimage,
- 'provision' => \&web_provision,
- 'summary' => \&web_summary,
- 'gangliashow' => \&web_gangliaShow,
- 'gangliacurrent' => \&web_gangliaLatest,
- 'rinstall' => \&web_rinstall,
- 'addnode' => \&web_addnode,
- 'graph' => \&web_graphinfo,
- 'getdefaultuserentry' => \&web_getdefaultuserentry,
- 'getzdiskinfo' => \&web_getzdiskinfo,
- 'passwd' => \&web_passwd,
- 'policy' => \&web_policy,
- 'deleteuser' => \&web_deleteuser,
- 'mkzprofile' => \&web_mkzprofile,
- 'rmzprofile' => \&web_rmzprofile,
- 'mkippool' => \&web_mkippool,
- 'rmippool' => \&web_rmippool,
- 'lsippool' => \&web_lsippool,
- 'updateosimage' => \&web_updateosimage,
- 'rmosimage' => \&web_rmosimage,
- 'updategroup' => \&web_updategroup,
- 'rmgroup' => \&web_rmgroup,
- 'framesetup' => \&web_framesetup,
- 'cecsetup' => \&web_cecsetup
- );
-
- # Check whether the request is authorized or not
- split ' ', $request->{arg}->[0];
- my $cmd = $_[0];
- if ( grep { $_ eq $cmd } keys %authorized_cmds ) {
- my $func = $authorized_cmds{$cmd};
- $func->( $request, $callback, $sub_req );
- }
- else {
- $callback->(
- { error => "$cmd is not authorized!\n", errorcode => [1] } );
- }
-}
-
-sub web_lsevent {
- my ( $request, $callback, $sub_req ) = @_;
- my @ret = `$request->{arg}->[0]`;
-
- # Please refer the manpage for the output format of lsevent
- my $data = [];
- my $record = '';
- my $i = 0;
- my $j = 0;
-
- foreach my $item (@ret) {
- if ( $item ne "\n" ) {
- chomp $item;
- my ( $key, $value ) = split( "=", $item );
- if ( $j < 2 ) {
- $record .= $value . ';';
- }
- else {
- $record .= $value;
- }
-
- $j++;
- if ( $j == 3 ) {
- $i++;
- $j = 0;
- push( @$data, $record );
- $record = '';
- }
- }
-
- }
-
- $callback->( { data => $data } );
-}
-
-sub web_mkcondresp {
- my ( $request, $callback, $sub_req ) = @_;
- my $conditionName = $request->{arg}->[1];
- my $temp = $request->{arg}->[2];
- my $cmd = '';
- my @resp = split( ':', $temp );
-
- # Create new associations
- if ( 1 < length( @resp[0] ) ) {
- $cmd = substr( @resp[0], 1 );
- $cmd =~ s/,/ /;
- $cmd = 'mkcondresp ' . $conditionName . ' ' . $cmd;
- my $retInfo = xCAT::Utils->runcmd( $cmd, -1, 1 );
- }
-
- # Delete old associations
- if ( 1 < length( @resp[1] ) ) {
- $cmd = substr( @resp[1], 1 );
- $cmd =~ s/,/ /;
- $cmd = 'rmcondresp ' . $conditionName . ' ' . $cmd;
- my $retInfo = xCAT::Utils->runcmd( $cmd, -1, 1 );
- }
-
- # There is no output for mkcondresp
- $cmd = 'startcondresp ' . $conditionName;
- my $refInfo = xCAT::Utils->runcmd( $cmd, -1, 1 );
- $callback->( { data => "Success." } );
-}
-
-sub web_startcondresp {
- my ( $request, $callback, $sub_req ) = @_;
- my $conditionName = $request->{arg}->[1];
- my $cmd = 'startcondresp "' . $conditionName . '"';
- my $retInfo = xCAT::Utils->runcmd( $cmd, -1, 1 );
- $callback->(
- { data => 'start monitor "' . $conditionName . '" Successful.' } );
-}
-
-sub web_stopcondresp {
- my ( $request, $callback, $sub_req ) = @_;
- my $conditionName = $request->{arg}->[1];
- my $cmd = 'stopcondresp "' . $conditionName . '"';
- my $retInfo = xCAT::Utils->runcmd( $cmd, -1, 1 );
- $callback->(
- { data => 'stop monitor "' . $conditionName . '" Successful.' } );
-}
-
-sub web_lscond {
- my ( $request, $callback, $sub_req ) = @_;
- my $nodeRange = $request->{arg}->[1];
- my $names = '';
-
- # List all the conditions for all lpars in this group
- if ($nodeRange) {
- my @nodes = xCAT::NodeRange::noderange($nodeRange);
- my %tempHash;
- my $nodeCount = @nodes;
-
- # No node in this group
- if ( 1 > $nodeCount ) {
- return;
- }
-
- # No conditions return
- my $tempCmd = 'lscondition -d :' . join( ',', @nodes );
- my $retInfo = xCAT::Utils->runcmd( $tempCmd, -1, 1 );
- if ( 1 > @$retInfo ) {
- return;
- }
-
- shift @$retInfo;
- shift @$retInfo;
- foreach my $line (@$retInfo) {
- my @temp = split( ':', $line );
- $tempHash{ @temp[0] }++;
- }
-
- foreach my $name ( keys(%tempHash) ) {
- if ( $nodeCount == $tempHash{$name} ) {
- $names = $names . $name . ';';
- }
- }
- }
-
- # Only list the conditions on local
- else {
- my $retInfo = xCAT::Utils->runcmd( 'lscondition -d', -1, 1 );
- if ( 2 > @$retInfo ) {
- return;
- }
-
- shift @$retInfo;
- shift @$retInfo;
- foreach my $line (@$retInfo) {
- my @temp = split( ':', $line );
- $names = $names . @temp[0] . ':' . substr( @temp[2], 1, 3 ) . ';';
- }
- }
-
- if ( '' eq $names ) {
- return;
- }
-
- $names = substr( $names, 0, ( length($names) - 1 ) );
- $callback->( { data => $names } );
-}
-
-sub web_mkcondition {
- my ( $request, $callback, $sub_req ) = @_;
-
- if ( 'change' eq $request->{arg}->[1] ) {
- my @nodes;
- my $conditionName = $request->{arg}->[2];
- my $groupName = $request->{arg}->[3];
-
- my $retInfo =
- xCAT::Utils->runcmd( 'nodels ' . $groupName . " ppc.nodetype", -1,
- 1 );
- foreach my $line (@$retInfo) {
- my @temp = split( ':', $line );
- if ( @temp[1] !~ /lpar/ ) {
- $callback->(
- {
- data =>
- 'Error : only the compute nodes\' group could select.'
- }
- );
- return;
- }
-
- push( @nodes, @temp[0] );
- }
-
- xCAT::Utils->runcmd( 'chcondition -n ' + join( ',', @nodes ) + '-m m ' +
- $conditionName );
- $callback->( { data => 'Change scope success.' } );
- }
-
-}
-
-sub web_lsresp {
- my ( $request, $callback, $sub_req ) = @_;
- my $names = '';
- my @temp;
- my $retInfo = xCAT::Utils->runcmd( 'lsresponse -d', -1, 1 );
-
- shift @$retInfo;
- shift @$retInfo;
- foreach my $line (@$retInfo) {
- @temp = split( ':', $line );
- $names = $names . @temp[0] . ';';
- }
-
- $names = substr( $names, 0, ( length($names) - 1 ) );
- $callback->( { data => $names } );
-}
-
-sub web_lscondresp {
- my ( $request, $callback, $sub_req ) = @_;
- my $names = '';
- my @temp;
-
- # If there is a condition name, then we only show the condition linked associations
- if ( $request->{arg}->[1] ) {
- my $cmd = 'lscondresp -d ' . $request->{arg}->[1];
- my $retInfo = xCAT::Utils->runcmd( $cmd, -1, 1 );
- if ( 2 > @$retInfo ) {
- $callback->( { data => '' } );
- return;
- }
-
- shift @$retInfo;
- shift @$retInfo;
- for my $line (@$retInfo) {
- @temp = split( ':', $line );
- $names = $names . @temp[1] . ';';
- }
- }
-
- $names = substr( $names, 0, ( length($names) - 1 ) );
- $callback->( { data => $names } );
-}
-
-sub web_update {
- my ( $request, $callback, $sub_req ) = @_;
- my $os = "unknown";
- my $rpmNames = $request->{arg}->[1];
- my $repository = $request->{arg}->[2];
- my $fileHandle;
- my $cmd;
- my $returnInfo;
- my $webpageContent = undef;
- my $remoteRpmFilePath = undef;
- my $localRpmFilePath = undef;
-
- if ( xCAT::Utils->isLinux() ) {
- $os = xCAT::Utils->osver();
-
- # SUSE Linux
- if ( $os =~ /sles.*/ ) {
- $rpmNames =~ s/,/ /g;
-
- # Create zypper command
- $cmd = "zypper -n -p " . $repository . " update " . $rpmNames;
- }
-
- # Red Hat
- else {
-
- # Check the yum config file, and detect if it exists
- if ( -e "/tmp/xCAT_update.yum.conf" ) {
- unlink("/tmp/xCAT_update.yum.conf");
- }
-
- # Create file, return error if failed
- unless ( open( $fileHandle, '>>', "/tmp/xCAT_update.yum.conf" ) ) {
- $callback->(
- { error => "Created temp file error!\n", errorcode => [1] }
- );
- return;
- }
-
- # Write the RPM path into config file
- print $fileHandle "[xcat_temp_update]\n";
- print $fileHandle "name=temp prepository\n";
- $repository = "baseurl=" . $repository . "\n";
- print $fileHandle $repository;
- print $fileHandle "enabled=1\n";
- print $fileHandle "gpgcheck=0\n";
- close($fileHandle);
-
- # Use system to run the command: yum -y -c config-file update rpm-names
- $rpmNames =~ s/,/ /g;
- $cmd = "yum -y -c /tmp/xCAT_update.yum.conf update " . $rpmNames . " 2>&1";
- }
-
- # Run the command and return the result
- $returnInfo = readpipe($cmd);
- $callback->( { info => $returnInfo } );
- }
-
- # AIX
- else {
-
- # Open the RPM path and read the page's content
- $webpageContent = LWP::Simple::get($repository);
- unless ( defined($webpageContent) ) {
- $callback->({
- error => "open $repository error, please check!!",
- errorcode => [1]
- });
- return;
- }
-
- # Must support updating several RPM
- foreach ( split( /,/, $rpmNames ) ) {
-
- # Find out RPMs corresponding RPM HREF on the web page
- $webpageContent =~ m/href="($_-.*?[ppc64|noarch].rpm)/i;
- unless ( defined($1) ) {
- next;
- }
- $remoteRpmFilePath = $repository . $1;
- $localRpmFilePath = '/tmp/' . $1;
-
- # Download RPM package to temp
- unless ( -e $localRpmFilePath ) {
- $cmd = "wget -O " . $localRpmFilePath . " " . $remoteRpmFilePath;
- if ( 0 != system($cmd) ) {
- $returnInfo = $returnInfo . "update " . $_ . " failed: cannot download the RPM\n";
- $callback->( { error => $returnInfo, errorcode => [1] } );
- return;
- }
- }
-
- # Update RPM by RPM packages
- $cmd = "rpm -U " . $localRpmFilePath . " 2>&1";
- $returnInfo = $returnInfo . readpipe($cmd);
- }
-
- $callback->( { info => $returnInfo } );
- }
-}
-
-sub web_unlock {
- my ( $request, $callback, $sub_req ) = @_;
- my $node = $request->{arg}->[1];
- my $password = $request->{arg}->[2];
-
- # Unlock a node by setting up the SSH keys
- my $out = `DSH_REMOTE_PASSWORD=$password /opt/xcat/bin/xdsh $node -K`;
-
- $callback->( { data => $out } );
-}
-
-sub web_gangliastatus {
- my ( $request, $callback, $sub_req ) = @_;
-
- # Get node range
- my $nr = $request->{arg}->[1];
- my $out = `/opt/xcat/bin/xdsh $nr "service gmond status"`;
-
- # Parse output, and use $callback to send back to the web interface
- # Output looks like:
- # node_1: Checking for gmond: ..running
- # node_2: Checking for gmond: ..running
- my @lines = split( '\n', $out );
- my $line;
- my $status;
- foreach $line (@lines) {
- if ( $line =~ m/running/i ) {
- $status = 'on';
- }
- else {
- $status = 'off';
- }
-
- split( ': ', $line );
- $callback->({
- node => [{
- name => [ $_[0] ], # Node name
- data => [$status] # Output
- }]
- });
- }
-}
-
-sub web_gangliaconf() {
- my ( $request, $callback, $sub_req ) = @_;
-
- # Get node range
- my $nr = $request->{arg}->[1];
-
- my $info;
- my $output;
-
- # Add gangliamon to the monitoring table (if not already)
- $output = `/opt/xcat/bin/monadd gangliamon`;
-
- # Run the ganglia configuration script on node
- if ($nr) {
- $output = `/opt/xcat/bin/moncfg gangliamon $nr -r`;
- }
- else {
-
- # If no node range is given, then assume all nodes
-
- # Handle localhost (this needs to be 1st)
- $output = `/opt/xcat/bin/moncfg gangliamon`;
-
- # Handle remote nodes
- $output .= `/opt/xcat/bin/moncfg gangliamon -r`;
- }
-
- my @lines = split( '\n', $output );
- foreach (@lines) {
- if ($_) {
- $info .= ( $_ . "\n" );
- }
- }
-
- $callback->( { info => $info } );
- return;
-}
-
-sub web_gangliastart() {
- my ( $request, $callback, $sub_req ) = @_;
-
- # Get node range
- my $nr = $request->{arg}->[1];
-
- my $info;
- my $output;
-
- # Add gangliamon to the monitoring table (if not already)
- $output = `/opt/xcat/bin/monadd gangliamon`;
-
- # Start the gmond daemon on node
- if ($nr) {
- $output = `/opt/xcat/bin/moncfg gangliamon $nr -r`;
- $output .= `/opt/xcat/bin/monstart gangliamon $nr -r`;
- }
- else {
-
- # If no node range is given, then assume all nodes
-
- # Handle localhost (this needs to be 1st)
- $output = `/opt/xcat/bin/moncfg gangliamon`;
-
- # Handle remote nodes
- $output .= `/opt/xcat/bin/moncfg gangliamon -r`;
-
- # Handle localhost (this needs to be 1st)
- $output .= `/opt/xcat/bin/monstart gangliamon`;
-
- # Handle remote nodes
- $output .= `/opt/xcat/bin/monstart gangliamon -r`;
- }
-
- my @lines = split( '\n', $output );
- foreach (@lines) {
- if ($_) {
- $info .= ( $_ . "\n" );
- }
- }
-
- $callback->( { info => $info } );
- return;
-}
-
-sub web_gangliastop() {
- my ( $request, $callback, $sub_req ) = @_;
-
- # Get node range
- my $nr = $request->{arg}->[1];
-
- my $info;
- my $output;
-
- # Stop the gmond daemon on node
- if ($nr) {
- $output = `/opt/xcat/bin/monstop gangliamon $nr -r`;
- }
- else {
-
- # If no node range is given, then assume all nodes
-
- # Handle localhost (this needs to be 1st)
- $output = `/opt/xcat/bin/monstop gangliamon`;
-
- # Handle remote nodes
- $output .= `/opt/xcat/bin/monstop gangliamon -r`;
- }
-
- my @lines = split( '\n', $output );
- foreach (@lines) {
- if ($_) {
- $info .= ( $_ . "\n" );
- }
- }
-
- $callback->( { info => $info } );
- return;
-}
-
-sub web_gangliacheck() {
- my ( $request, $callback, $sub_req ) = @_;
-
- # Get node range
- my $nr = $request->{arg}->[1];
- if ( !$nr ) {
- $nr = '';
- }
-
- # Check if ganglia RPMs are installed
- my $info;
- my $info = `/opt/xcat/bin/xdsh $nr "rpm -q ganglia-gmond libganglia libconfuse"`;
- $callback->( { info => $info } );
- return;
-}
-
-sub web_installganglia() {
- my ( $request, $callback, $sub_req ) = @_;
-
- # Get node range
- my $nr = $request->{arg}->[1];
- my @nodes = split( ',', $nr );
-
- # Loop through each node
- my $info;
- my $tab;
- my $attrs;
- my $osType;
- my $dir;
- my $pkglist;
- my $defaultDir;
-
- foreach (@nodes) {
-
- # Get os, arch, profile, and provmethod
- $tab = xCAT::Table->new('nodetype');
- $attrs =
- $tab->getNodeAttribs( $_, [ 'os', 'arch', 'profile', 'provmethod' ] );
-
- # If any attributes are missing, skip
- if ( !$attrs->{'os'}
- || !$attrs->{'arch'}
- || !$attrs->{'profile'}
- || !$attrs->{'provmethod'} ){
- $callback->({ info => "$_: (Error) Missing attribute (os, arch, profile, or provmethod) in nodetype table" });
- next;
- }
-
- # Get the right OS type
- if ( $attrs->{'os'} =~ /fedora/ ) {
- $osType = 'fedora';
- } elsif ($attrs->{'os'} =~ /rh/
- || $attrs->{'os'} =~ /rhel/
- || $attrs->{'os'} =~ /rhels/ ) {
- $osType = 'rh';
- } elsif ( $attrs->{'os'} =~ /sles/ ) {
- $osType = 'sles';
- }
-
- # Assume /install/post/otherpkgs/
// directory is created
- # If Ganglia RPMs (ganglia-gmond-*, libconfuse-*, and libganglia-*) are not in directory
- $dir = "/install/post/otherpkgs/$attrs->{'os'}/$attrs->{'arch'}/";
- if (!( `test -e $dir/ganglia-gmond-* && echo 'File exists'`
- && `test -e $dir/libconfuse-* && echo 'File exists'`
- && `test -e $dir/libganglia-* && echo 'File exists'`
- )) {
-
- # Skip
- $callback->({ info => "$_: (Error) Missing Ganglia RPMs under $dir" });
- next;
- }
-
- # Find pkglist directory
- $dir = "/install/custom/$attrs->{'provmethod'}/$osType";
- if ( !(`test -d $dir && echo 'Directory exists'`) ) {
- # Create pkglist directory
- `mkdir -p $dir`;
- }
-
- # Find pkglist file
- # Ganglia RPM names should be added to /install/custom///...otherpkgs.pkglist
- $pkglist = "$attrs->{'profile'}.$attrs->{'os'}.$attrs->{'arch'}.otherpkgs.pkglist";
- if ( !(`test -e $dir/$pkglist && echo 'File exists'`) ) {
-
- # Copy default otherpkgs.pkglist
- $defaultDir = "/opt/xcat/share/xcat/$attrs->{'provmethod'}/$osType";
- if (`test -e $defaultDir/$pkglist && echo 'File exists'`) {
-
- # Copy default pkglist
- `cp $defaultDir/$pkglist $dir/$pkglist`;
- } else {
-
- # Create pkglist
- `touch $dir/$pkglist`;
- }
-
- # Add Ganglia RPMs to pkglist
- `echo ganglia-gmond >> $dir/$pkglist`;
- `echo libconfuse >> $dir/$pkglist`;
- `echo libganglia >> $dir/$pkglist`;
- }
-
- # Check if libapr1 is installed
- $info = `xdsh $_ "rpm -qa libapr1"`;
- if ( !( $info =~ /libapr1/ ) ) {
- $callback->(
- { info => "$_: (Error) libapr1 package not installed" } );
- next;
- }
-
- # Install Ganglia RPMs using updatenode
- $callback->( { info => "$_: Installing Ganglia..." } );
- $info = `/opt/xcat/bin/updatenode $_ -S`;
- $callback->( { info => "$info" } );
- }
-
- return;
-}
-
-sub web_gangliaShow {
- # Get ganglia data from RRD file
-
- my ( $request, $callback, $sub_req ) = @_;
- my $nodename = $request->{arg}->[1];
- my $timeRange = 'now-1h';
- my $resolution = 60;
- my $metric = $request->{arg}->[3];
- my @nodes = ();
- my $retStr = '';
- my $runInfo;
- my $cmd = '';
- my $dirname = '/var/lib/ganglia/rrds/__SummaryInfo__/';
-
- # Get the summary for this grid (the meaning of grid is referenced from Ganglia)
- if ( '_grid_' ne $nodename ) {
- $dirname = '/var/lib/ganglia/rrds/' . $nodename . '/';
- }
-
- if ( 'hour' eq $request->{arg}->[2] ) {
- $timeRange = 'now-1h';
- $resolution = 60;
- } elsif ( 'day' eq $request->{arg}->[2] ) {
- $timeRange = 'now-1d';
- $resolution = 1800;
- }
-
- if ( '_summary_' eq $metric ) {
- my @metricArray = (
- 'load_one', 'cpu_num', 'cpu_idle', 'mem_free',
- 'mem_total', 'disk_total', 'disk_free', 'bytes_in',
- 'bytes_out'
- );
-
- my $filename = '';
- my $step = 1;
- my $index = 0;
- my $size = 0;
- foreach my $tempmetric (@metricArray) {
- my $temp = '';
- my $line = '';
- $retStr .= $tempmetric . ':';
- $filename = $dirname . $tempmetric . '.rrd';
- $cmd = "rrdtool fetch $filename -s $timeRange -r $resolution AVERAGE";
- $runInfo = xCAT::Utils->runcmd( $cmd, -1, 1 );
- if ( scalar(@$runInfo) < 3 ) {
- $callback->( { data => 'error.' } );
- return;
- }
-
- # Delete the first 2 lines
- shift(@$runInfo);
- shift(@$runInfo);
-
- # We only support 60 lines for one metric, in order to reduce the data load for web GUI
- $size = scalar(@$runInfo);
- if ( $size > 60 ) {
- $step = int( $size / 60 ) + 1;
- }
-
- if ( ( $tempmetric eq 'cpu_idle' ) && ( '_grid_' eq $nodename ) ) {
- my $cpuidle = 0;
- my $cpunum = 0;
- for ( $index = 0 ; $index < $size ; $index += $step ) {
- if ( $runInfo->[$index] =~ /^(\S+): (\S+) (\S+)/ ) {
- my $timestamp = $1;
- my $value = $2;
- my $valuenum = $3;
- if (( lc($value) =~ /nanq/ ) || ( lc($value) =~ /nan/ )) {
- # The rrdtool fetch last line is always NaN, so no need to add into the return string
- if ( $index == ( $size - 1 ) ) {
- next;
- }
-
- $temp .= $timestamp . ',0,';
- } else {
- $cpuidle = sprintf "%.2f", $value;
- $cpunum = sprintf "%.2f", $valuenum;
- $temp .= $timestamp . ',' . ( sprintf "%.2f", $cpuidle / $cpunum ) . ',';
- }
- }
- }
- } else {
- for ( $index = 0 ; $index < $size ; $index += $step ) {
- if ( $runInfo->[$index] =~ /^(\S+): (\S+).*/ ) {
- my $timestamp = $1;
- my $value = $2;
- if (( lc($value) =~ /nanq/ ) || ( lc($value) =~ /nan/ )) {
- # The rrdtool fetch last line is always NaN, so no need to add into the return string
- if ( $index == ( $size - 1 ) ) {
- next;
- }
-
- $temp .= $timestamp . ',0,';
- } else {
- $temp .= $timestamp . ',' . ( sprintf "%.2f", $2 ) . ',';
- }
- }
- }
- }
-
- $retStr .= substr( $temp, 0, -1 ) . ';';
- }
-
- $retStr = substr( $retStr, 0, -1 );
- $callback->( { data => $retStr } );
- return;
- }
-}
-
-my $ganglia_return_flag = 0;
-my %gangliaHash;
-my $gangliaclustername;
-my $ganglianodename;
-
-sub web_gangliaLatest {
- # Use socket to connect ganglia port to get the latest value/status
-
- my ( $request, $callback, $sub_req ) = @_;
- my $type = $request->{arg}->[1];
- my $groupname = '';
- my $xmlparser;
- my $telnetcmd = '';
- my $connect;
- my $xmloutput = '';
- my $tmpFilename = '/tmp/gangliadata';
-
- $ganglia_return_flag = 0;
- $gangliaclustername = '';
- $ganglianodename = '';
- undef(%gangliaHash);
-
- if ( $request->{arg}->[2] ) {
- $groupname = $request->{arg}->[2];
- }
- if ( 'grid' eq $type ) {
- $xmlparser = XML::Parser->new(
- Handlers => {
- Start => \&web_gangliaGridXmlStart,
- End => \&web_gangliaXmlEnd
- });
- $telnetcmd = "/?filter=summary\n";
- $tmpFilename = '/tmp/gangliagriddata';
- } elsif ( 'node' eq $type ) {
- $xmlparser = XML::Parser->new(
- Handlers => {
- Start => \&web_gangliaNodeXmlStart,
- End => \&web_gangliaXmlEnd
- });
- $telnetcmd = "/\n";
- $tmpFilename = '/tmp/ganglianodedata';
- }
-
- # Use socket to telnet 127.0.0.1:8652 (Ganglia's interactive port)
- $connect = IO::Socket::INET->new('127.0.0.1:8652');
- unless ($connect) {
- $callback->( { 'data' => 'error: connect local port failed.' } );
- return;
- }
-
- print $connect $telnetcmd;
- open( TEMPFILE, '>' . $tmpFilename );
- while (<$connect>) {
- print TEMPFILE $_;
- }
-
- close($connect);
- close(TEMPFILE);
-
- $xmlparser->parsefile($tmpFilename);
-
- if ( 'grid' eq $type ) {
- web_gangliaGridLatest($callback);
- } elsif ( 'node' eq $type ) {
- web_gangliaNodeLatest( $callback, $groupname );
- }
- return;
-}
-
-sub web_gangliaGridLatest {
- # Create return data for grid current status
-
- my $callback = shift;
- my $retStr = '';
- my $timestamp = time();
- my $metricname = '';
- my @metricArray = (
- 'load_one', 'cpu_num', 'mem_total', 'mem_free',
- 'disk_total', 'disk_free', 'bytes_in', 'bytes_out'
- );
-
- if ( $gangliaHash{'cpu_idle'} ) {
- my $sum = $gangliaHash{'cpu_idle'}->{'SUM'};
- my $num = $gangliaHash{'cpu_idle'}->{'NUM'};
- $retStr .= 'cpu_idle:'
- . $timestamp . ','
- . ( sprintf( "%.2f", $sum / $num ) ) . ';';
- }
-
- foreach $metricname (@metricArray) {
- if ( $gangliaHash{$metricname} ) {
- $retStr .=
- $metricname . ':'
- . $timestamp . ','
- . $gangliaHash{$metricname}->{'SUM'} . ';';
- }
- }
-
- $retStr = substr( $retStr, 0, -1 );
- $callback->( { data => $retStr } );
-}
-
-sub web_gangliaNodeLatest {
- # Create return data for node current status
-
- my ( $callback, $groupname ) = @_;
- my $node = '';
- my $retStr = '';
- my $timestamp = time() - 180;
- my @nodes;
-
- # Get all nodes by group
- if ($groupname) {
- @nodes = xCAT::NodeRange::noderange( $groupname, 1 );
- } else {
- @nodes = xCAT::DBobjUtils->getObjectsOfType('node');
- }
-
- foreach $node (@nodes) {
- # If the node has Ganglia
- if ( $gangliaHash{$node} ) {
- my $lastupdate = $gangliaHash{$node}->{'timestamp'};
-
- # Cannot get monitor data for too long
- if ( $lastupdate < $timestamp ) {
- $retStr .= $node . ':ERROR,Can not get monitor data more than 3 minutes!;';
- next;
- }
-
- if ( $gangliaHash{$node}->{'load_one'} >
- $gangliaHash{$node}->{'cpu_num'} ) {
- $retStr .= $node . ':WARNING,';
- } else {
- $retStr .= $node . ':NORMAL,';
- }
-
- $retStr .= $gangliaHash{$node}->{'path'} . ';';
- } else {
- $retStr .= $node . ':UNKNOWN,;';
- }
- }
-
- $retStr = substr( $retStr, 0, -1 );
- $callback->( { data => $retStr } );
-}
-
-sub web_gangliaXmlEnd {
- # XML parser end function, do noting here
-}
-
-sub web_gangliaGridXmlStart {
- # XML parser start function
-
- my ( $parseinst, $elementname, %attrs ) = @_;
- my $metricname = '';
-
- # Only parse grid information
- if ($ganglia_return_flag) {
- return;
- }
-
- if ( 'METRICS' eq $elementname ) {
- $metricname = $attrs{'NAME'};
- $gangliaHash{$metricname}->{'SUM'} = $attrs{'SUM'};
- $gangliaHash{$metricname}->{'NUM'} = $attrs{'NUM'};
- } elsif ( 'CLUSTER' eq $elementname ) {
- $ganglia_return_flag = 1;
- return;
- } else {
- return;
- }
-}
-
-sub web_gangliaNodeXmlStart {
- # XML parser start function for node current status
-
- my ( $parseinst, $elementname, %attrs ) = @_;
- my $metricname = '';
-
- # Save cluster name
- if ( 'CLUSTER' eq $elementname ) {
- $gangliaclustername = $attrs{'NAME'};
- return;
- } elsif ( 'HOST' eq $elementname ) {
- if ( $attrs{'NAME'} =~ /(\S+?)\.(.*)/ ) {
- $ganglianodename = $1;
- } else {
- $ganglianodename = $attrs{'NAME'};
- }
-
- $gangliaHash{$ganglianodename}->{'path'} =
- $gangliaclustername . '/' . $attrs{'NAME'};
- $gangliaHash{$ganglianodename}->{'timestamp'} = $attrs{'REPORTED'};
- } elsif ( 'METRIC' eq $elementname ) {
- $metricname = $attrs{'NAME'};
- if ( ( 'load_one' eq $metricname ) || ( 'cpu_num' eq $metricname ) ) {
- $gangliaHash{$ganglianodename}->{$metricname} = $attrs{'VAL'};
- }
- }
-}
-
-sub web_rmcmonStart {
- my ( $request, $callback, $sub_req ) = @_;
- my $nodeRange = $request->{arg}->[1];
- my $table;
- my $retData = "";
- my $output;
-
- # Check running status
- $table = xCAT::Table->new('monitoring');
- my $rmcWorkingStatus = $table->getAttribs( { name => 'rmcmon' }, 'disable' );
- $table . close();
-
- # RMC monitoring is running so return
- if ($rmcWorkingStatus) {
- if ( $rmcWorkingStatus->{disable} =~ /0|No|no|NO|N|n/ ) {
- $callback->( { info => 'RMC Monitoring is running now.' } );
- return;
- }
- }
-
- $retData .= "RMC is not running, start it now.\n";
-
- # Check monsetting table to see if rmc's montype contains performance
- $table = xCAT::Table->new('monsetting');
- my $rmcmonType =
- $table->getAttribs( { name => 'rmcmon', key => 'montype' }, 'value' );
- $table . close();
-
- # RMC monitoring is not configured right, we should configure it again
- # There is no rmcmon in monsetting table
- if ( !$rmcmonType ) {
- $output = xCAT::Utils->runcmd( 'monadd rmcmon -s [montype=perf]', -1, 1 );
- foreach (@$output) {
- $retData .= ( $_ . "\n" );
- }
-
- $retData .= "Adding rmcmon to the monsetting table complete.\n";
- }
-
- # Configure before but there is no performance monitoring, so change the table
- else {
- if ( !( $rmcmonType->{value} =~ /perf/ ) ) {
- $output = xCAT::Utils->runcmd('chtab name=rmcmon,key=montype monsetting.value=perf', -1, 1 );
- foreach (@$output) {
- $retData .= ( $_ . "\n" );
- }
-
- $retData .= "Change the rmcmon configure in monsetting table finish.\n";
- }
- }
-
- # Run the rmccfg command to add all nodes into local RMC configuration
- $output = xCAT::Utils->runcmd("moncfg rmcmon $nodeRange", -1, 1);
- foreach (@$output) {
- $retData .= ( $_ . "\n" );
- }
-
- # Run the rmccfg command to add all nodes into remote RMC configuration
- $output = xCAT::Utils->runcmd( "moncfg rmcmon $nodeRange -r", -1, 1 );
- foreach (@$output) {
- $retData .= ( $_ . "\n" );
- }
-
- # Start the RMC monitor
- $output = xCAT::Utils->runcmd( "monstart rmcmon", -1, 1 );
- foreach (@$output) {
- $retData .= ( $_ . "\n" );
- }
-
- $callback->( { info => $retData } );
- return;
-}
-
-sub web_rmcmonShow() {
- my ( $request, $callback, $sub_req ) = @_;
- my $nodeRange = $request->{arg}->[1];
- my $attr = $request->{arg}->[2];
- my @nodes;
- my $retInfo;
- my $retHash = {};
- my $output;
- my $temp = "";
-
- # Only get the system RMC info
- if ( 'summary' eq $nodeRange ) {
- $output = xCAT::Utils->runcmd( "monshow rmcmon -s -t 60 -o p -a " . $attr, -1, 1 );
- foreach $temp (@$output) {
- # The attribute name
- if ( $temp =~ /Pct/ ) {
- $temp =~ s/ //g;
-
- # The first one
- if ( "" eq $retInfo ) {
- $retInfo .= ( $temp . ':' );
- } else {
- $retInfo =~ s/,$/;/;
- $retInfo .= ( $temp . ':' );
- }
-
- next;
- }
-
- # The content of the attribute
- $temp =~ m/\s+(\d+\.\d{4})/;
- if ( defined($1) ) {
- $retInfo .= ( $1 . ',' );
- }
- }
-
- # Return the RMC info
- $retInfo =~ s/,$//;
- $callback->( { info => $retInfo } );
- return;
- }
-
- if ('compute' eq $nodeRange) {
- my $node;
-
- @nodes = xCAT::NodeRange::noderange($nodeRange);
- for $node (@nodes) {
- if ( -e "/var/rrd/$node" ) {
- push( @{ $retHash->{node} }, { name => $node, data => 'OK' } );
- } else {
- push( @{ $retHash->{node} }, { name => $node, data => 'UNKNOWN' } );
- }
- }
-
- $callback->($retHash);
- return;
- }
-
- my $attrName = "";
- my @attrs = split( /,/, $attr );
- for $attrName (@attrs) {
- my @attrValue = ();
- $output = xCAT::Utils->runcmd( "rrdtool fetch /var/rrd/${nodeRange}/${attrName}.rrd -r 60 -s e-1h AVERAGE", -1, 1 );
- foreach (@$output) {
- $temp = $_;
- if ( $temp eq '' ) {
- next;
- }
-
- if ( lc($temp) =~ /[nanq|nan]/ ) {
- next;
- }
-
- if ( $temp =~ /^(\d+): (\S+) (\S+)/ ) {
- push( @attrValue, ( sprintf "%.2f", $2 ) );
- }
- }
-
- if ( scalar(@attrValue) > 1 ) {
- push( @{ $retHash->{node} }, { name => $attrName, data => join( ',', @attrValue ) } );
- } else {
- $retHash->{node} = { name => $attrName, data => '' };
- last;
- }
- }
-
- $callback->($retHash);
-}
-
-sub web_monls() {
- my ( $request, $callback, $sub_req ) = @_;
- my $retInfo = xCAT::Utils->runcmd( "monls", -1, 1 );
- my $ret = '';
- foreach my $line (@$retInfo) {
- my @temp = split( /\s+/, $line );
- $ret .= @temp[0];
- if ( 'not-monitored' eq @temp[1] ) {
- $ret .= ':Off;';
- } else {
- $ret .= ':On;';
- }
- }
-
- if ( '' eq $ret ) {
- return;
- }
-
- $ret = substr( $ret, 0, length($ret) - 1 );
- $callback->( { data => $ret } );
-}
-
-sub web_dynamiciprange {
- my ( $request, $callback, $sub_req ) = @_;
- my $iprange = $request->{arg}->[1];
-
- open( TEMPFILE, '>/tmp/iprange.conf' );
- print TEMPFILE "xcat-service-lan:\n";
- print TEMPFILE "dhcp-dynamic-range = " . $iprange . "\n";
- close(TEMPFILE);
-
- # Run xcatsetup command to change the dynamic IP range
- xCAT::Utils->runcmd( "xcatsetup /tmp/iprange.conf", -1, 1 );
- unlink('/tmp/iprange.conf');
- xCAT::Utils->runcmd( "makedhcp -n", -1, 1 );
-
- # Restart the DHCP server
- if ( xCAT::Utils->isLinux() ) {
- # xCAT::Utils->runcmd("service dhcpd restart", -1, 1);
- } else {
- # xCAT::Utils->runcmd("startsrc -s dhcpsd", -1, 1);
- }
-}
-
-sub web_discover {
- my ( $request, $callback, $sub_req ) = @_;
- my $type = uc( $request->{arg}->[1] );
-
- my $retStr = '';
- my $retInfo = xCAT::Utils->runcmd( "lsslp -m -s $type 2>/dev/null | grep -i $type | awk '{print \$1\":\" \$2\"-\"\$3}'", -1, 1 );
- if ( scalar(@$retInfo) < 1 ) {
- $retStr = 'Error: Can not discover frames in cluster!';
- } else {
- foreach my $line (@$retInfo) {
- $retStr .= $line . ';';
- }
-
- $retStr = substr( $retStr, 0, -1 );
- }
-
- $callback->( { data => $retStr } );
-}
-
-sub web_updatevpd {
- my ( $request, $callback, $sub_req ) = @_;
- my $harwareMtmsPair = $request->{arg}->[1];
- my @hardware = split( /:/, $harwareMtmsPair );
-
- my $vpdtab = xCAT::Table->new('vpd');
- unless ($vpdtab) {
- return;
- }
-
- foreach my $hard (@hardware) {
- # The sequence must be object name, mtm, serial
- my @temp = split( /,/, $hard );
- $vpdtab->setAttribs( { 'node' => @temp[0] }, { 'serial' => @temp[2], 'mtm' => @temp[1] } );
- }
-
- $vpdtab->close();
-}
-
-sub web_writeconfigfile {
- my ( $request, $callback, $sub_req ) = @_;
- my $filename = $request->{arg}->[1];
- my $content = $request->{arg}->[2];
-
- open( TEMPFILE, '>' . $filename );
- print TEMPFILE $content;
-
- close(TEMPFILE);
- return;
-}
-
-sub web_createimage {
- my ( $request, $callback, $sub_req ) = @_;
- my $ostype = $request->{arg}->[1];
- my $osarch = lc( $request->{arg}->[2] );
- my $profile = $request->{arg}->[3];
- my $bootif = $request->{arg}->[4];
- my $imagetype = lc( $request->{arg}->[5] );
- my @softArray;
- my $netdriver = '';
- my $installdir = xCAT::TableUtils->getInstallDir();
- my $tempos = $ostype;
- $tempos =~ s/[0-9\.]//g;
- my $CONFILE;
- my $archFlag = 0;
- my $ret = '';
- my $cmdPath = '';
-
- if ( $request->{arg}->[6] ) {
- @softArray = split( ',', $request->{arg}->[6] );
-
- # Check the custom package, if the directory does not exist, create the directory first
- if ( -e "$installdir/custom/netboot/$ostype/" ) {
- # The path exist, so archive all file under this path
- opendir( TEMPDIR, "$installdir/custom/netboot/$ostype/" );
- my @fileArray = readdir(TEMPDIR);
- closedir(TEMPDIR);
- if ( 2 < scalar(@fileArray) ) {
- $archFlag = 1;
- unless ( -e "/tmp/webImageArch/" ) {
- system("mkdir -p /tmp/webImageArch/");
- }
-
- system("mv $installdir/custom/netboot/$ostype/*.* /tmp/webImageArch/");
- } else {
- $archFlag = 0;
- }
- } else {
- # No need to archive
- $archFlag = 0;
- system("mkdir -p $installdir/custom/netboot/$ostype/");
- }
-
- # Write pkglist
- open( $CONFILE, ">$installdir/custom/netboot/$ostype/$profile.pkglist" );
- print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/IBMhpc.$ostype.ppc64.pkglist# \n";
- close($CONFILE);
-
- # Write otherpkglist
- open( $CONFILE, ">$installdir/custom/netboot/$ostype/$profile.otherpkgs.pkglist" );
- print $CONFILE "\n";
- close($CONFILE);
-
- # Write exlist for stateless
- open( $CONFILE, ">$installdir/custom/netboot/$ostype/$profile.exlist" );
- print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/IBMhpc.$ostype.$osarch.exlist#\n";
- close($CONFILE);
-
- # Write postinstall
- open( $CONFILE, ">$installdir/custom/netboot/$ostype/$profile.postinstall" );
- print $CONFILE "/opt/xcat/share/xcat/IBMhpc/IBMhpc.$tempos.postinstall \$1 \$2 \$3 \$4 \$5 \n";
- close($CONFILE);
-
- for my $soft (@softArray) {
- $soft = lc($soft);
- if ( 'gpfs' eq $soft ) {
- web_gpfsConfigure( $ostype, $profile, $osarch, $installdir );
- } elsif ( 'rsct' eq $soft ) {
- web_rsctConfigure( $ostype, $profile, $osarch, $installdir );
- } elsif ( 'pe' eq $soft ) {
- web_peConfigure( $ostype, $profile, $osarch, $installdir );
- } elsif ( 'essl' eq $soft ) {
- web_esslConfigure( $ostype, $profile, $osarch, $installdir );
- } elsif ( 'ganglia' eq $soft ) {
- web_gangliaConfig( $ostype, $profile, $osarch, 'netboot', $installdir );
- }
- }
-
- system("chmod 755 $installdir/custom/netboot/$ostype/*.*");
- }
-
- if ( $bootif =~ /hf/i ) {
- $netdriver = 'hf_if';
- } else {
- $netdriver = 'ibmveth';
- }
-
- if ( $tempos =~ /rh/i ) {
- $cmdPath = "/opt/xcat/share/xcat/netboot/rh";
- } else {
- $cmdPath = "/opt/xcat/share/xcat/netboot/sles";
- }
-
- # For stateless only run packimage
- if ( 'stateless' eq $imagetype ) {
- my $retInfo = xCAT::Utils->runcmd( "${cmdPath}/genimage -i $bootif -n $netdriver -o $ostype -p $profile", -1, 1 );
- $ret = join( "\n", @$retInfo );
-
- if ($::RUNCMD_RC) {
- web_restoreChange( $request->{arg}->[6], $archFlag, $imagetype, $ostype, $installdir );
- $callback->( { data => $ret } );
- return;
- }
-
- $ret .= "\n";
- my $retInfo = xCAT::Utils->runcmd( "packimage -o $ostype -p $profile -a $osarch", -1, 1 );
- $ret .= join( "\n", @$retInfo );
- } else {
- # For statelist we should check the litefile table
- # Step 1: Save the old litefile table content into litefilearchive.csv
- system('tabdump litefile > /tmp/litefilearchive.csv');
-
- # Step 2: Write the new litefile.csv for this lite image
- open( $CONFILE, ">/tmp/litefile.csv" );
- print $CONFILE "#image,file,options,comments,disable\n";
- print $CONFILE '"ALL","/etc/lvm/","tmpfs",,' . "\n";
- print $CONFILE '"ALL","/etc/ntp.conf","tmpfs",,' . "\n";
- print $CONFILE '"ALL","/etc/resolv.conf","tmpfs",,' . "\n";
- print $CONFILE '"ALL","/etc/sysconfig/","tmpfs",,' . "\n";
- print $CONFILE '"ALL","/etc/yp.conf","tmpfs",,' . "\n";
- print $CONFILE '"ALL","/etc/ssh/","tmpfs",,' . "\n";
- print $CONFILE '"ALL","/var/","tmpfs",,' . "\n";
- print $CONFILE '"ALL","/tmp/","tmpfs",,' . "\n";
- print $CONFILE '"ALL","/root/.ssh/","tmpfs",,' . "\n";
- print $CONFILE '"ALL","/opt/xcat/","tmpfs",,' . "\n";
- print $CONFILE '"ALL","/xcatpost/","tmpfs",,' . "\n";
-
- if ( 'rhels' eq $tempos ) {
- print $CONFILE '"ALL","/etc/adjtime","tmpfs",,' . "\n";
- print $CONFILE '"ALL","/etc/securetty","tmpfs",,' . "\n";
- print $CONFILE '"ALL","/etc/rsyslog.conf","tmpfs",,' . "\n";
- print $CONFILE '"ALL","/etc/rsyslog.conf.XCATORIG","tmpfs",,'
- . "\n";
- print $CONFILE '"ALL","/etc/udev/","tmpfs",,' . "\n";
- print $CONFILE '"ALL","/etc/ntp.conf.predhclient","tmpfs",,' . "\n";
- print $CONFILE '"ALL","/etc/resolv.conf.predhclient","tmpfs",,'
- . "\n";
- } else {
- print $CONFILE '"ALL","/etc/ntp.conf.org","tmpfs",,' . "\n";
- print $CONFILE '"ALL","/etc/syslog-ng/","tmpfs",,' . "\n";
- print $CONFILE '"ALL","/etc/fstab","tmpfs",,' . "\n";
- }
- close($CONFILE);
-
- # Write the HPC software litefile into temp litefile.csv
- for my $soft (@softArray) {
- $soft = lc($soft);
- if ( -e "/opt/xcat/share/xcat/IBMhpc/$soft/litefile.csv" ) {
- system("grep '^[^#]' /opt/xcat/share/xcat/IBMhpc/$soft/litefile.csv >> /tmp/litefile.csv");
- }
- }
-
- system("tabrestore /tmp/litefile.csv");
-
- # Create the image
- my $retInfo = xCAT::Utils->runcmd("${cmdPath}/genimage -i $bootif -n $netdriver -o $ostype -p $profile", -1, 1);
- $ret = join( "\n", @$retInfo );
- if ($::RUNCMD_RC) {
- web_restoreChange( $request->{arg}->[6], $archFlag, $imagetype, $ostype, $installdir );
- $callback->( { data => $ret } );
- return;
- }
-
- $ret .= "\n";
- my $retInfo = xCAT::Utils->runcmd( "liteimg -o $ostype -p $profile -a $osarch", -1, 1 );
- $ret .= join( "\n", @$retInfo );
- }
-
- web_restoreChange( $request->{arg}->[6], $archFlag, $imagetype, $ostype, $installdir );
- $callback->( { data => $ret } );
- return;
-}
-
-sub web_gpfsConfigure {
- my ( $ostype, $profile, $osarch, $installdir ) = @_;
- my $CONFILE;
-
- system("createrepo $installdir/post/otherpkgs/$ostype/$osarch/gpfs");
-
- open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.otherpkgs.pkglist" );
- print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/gpfs/gpfs.otherpkgs.pkglist#\n";
- close($CONFILE);
-
- open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.exlist" );
- print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/gpfs/gpfs.exlist#\n";
- close($CONFILE);
-
- system('cp /opt/xcat/share/xcat/IBMhpc/gpfs/gpfs_mmsdrfs $installdir/postscripts/gpfs_mmsdrfs');
- open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.postinstall" );
- print $CONFILE "NODESETSTATE=genimage installroot=\$1 /opt/xcat/share/xcat/IBMhpc/gpfs/gpfs_updates\n";
- print $CONFILE "installroot=\$1 $installdir/postscripts/gpfs_mmsdrfs\n";
- close($CONFILE);
-}
-
-sub web_rsctConfigure {
- my ( $ostype, $profile, $osarch, $installdir ) = @_;
- my $CONFILE;
-
- system("createrepo $installdir/post/otherpkgs/$ostype/$osarch/rsct");
-
- if ( $ostype =~ /sles/i ) {
- open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.pkglist" );
- print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/rsct/rsct.pkglist# \n";
- close($CONFILE);
- }
-
- open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.exlist" );
- print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/rsct/rsct.exlist#\n";
- close($CONFILE);
-
- open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.postinstall" );
- print $CONFILE "installroot=\$1 rsctdir=$installdir/post/otherpkgs/rhels6/ppc64/rsct NODESETSTATE=genimage /opt/xcat/share/xcat/IBMhpc/rsct/rsct_install\n";
- close($CONFILE);
-}
-
-sub web_peConfigure {
- my ( $ostype, $profile, $osarch, $installdir ) = @_;
- my $CONFILE;
-
- system("createrepo $installdir/post/otherpkgs/$ostype/$osarch/pe");
- system("createrepo $installdir/post/otherpkgs/$ostype/$osarch/compilers");
-
- open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.pkglist" );
- if ( $ostype =~ /rh/i ) {
- print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/pe/pe.$ostype.pkglist#\n";
- } else {
- print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/compilers/compilers.pkglist#\n";
- print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/pe/pe.pkglist#\n";
- }
-
- close($CONFILE);
-
- open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.otherpkgs.pkglist" );
- print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/pe/pe.otherpkgs.pkglist#\n";
- close($CONFILE);
-
- open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.exlist" );
- print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/compilers/compilers.exlist#\n";
- print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/pe/pe.exlist#\n";
- close($CONFILE);
-
- open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.postinstall" );
- print $CONFILE "installroot=\$1 NODESETSTATE=genimage /opt/xcat/share/xcat/IBMhpc/compilers/compilers_license";
- print $CONFILE "installroot=\$1 pedir=$installdir/post/otherpkgs/rhels6/ppc64/pe NODESETSTATE=genimage /opt/xcat/share/xcat/IBMhpc/pe/pe_install";
- close($CONFILE);
-}
-
-sub web_esslConfigure {
- my ( $ostype, $profile, $osarch, $installdir ) = @_;
- my $CONFILE;
-
- system("createrepo $installdir/post/otherpkgs/$ostype/$osarch/essl");
-
- open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.pkglist" );
- if ( $ostype =~ /rh/i ) {
- print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/compilers/compilers.rhels6.pkglist#\n";
- } else {
- print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/essl/essl.pkglist#\n";
- }
-
- open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.otherpkgs.pkglist" );
- print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/essl/essl.otherpkgs.pkglist#\n";
- close($CONFILE);
-
- open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.exlist" );
- print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/essl/essl.exlist#\n";
- close($CONFILE);
-
- open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.postinstall" );
- print $CONFILE, "installroot=\$1 essldir=$installdir/post/otherpkgs/rhels6/ppc64/essl NODESETSTATE=genimage /opt/xcat/share/xcat/IBMhpc/essl/essl_install";
- close($CONFILE);
-}
-
-sub web_gangliaConfig {
- my ( $ostype, $profile, $osarch, $provtype, $installdir ) = @_;
- my $CONFILE;
-
- system("createrepo $installdir/post/otherpkgs/$ostype/$osarch/ganglia");
-
- open( $CONFILE, ">>$installdir/custom/$provtype/$ostype/$profile.otherpkgs.pkglist" );
- print $CONFILE "#created by xCAT Web Gui.\n";
- print $CONFILE "ganglia/ganglia\n";
- print $CONFILE "ganglia/ganglia-gmond\n";
- print $CONFILE "ganglia/ganglia-gmetad\n";
- print $CONFILE "ganglia/rrdtool\n";
- close($CONFILE);
-}
-
-sub web_gangliaRpmCheck {
- my ( $ostype, $profile, $osarch, $installdir ) = @_;
- my @rpmnames = ( "rrdtool", "ganglia", "ganglia-gmond", "ganglia-gmetad" );
- my %temphash;
- my $rpmdir = "$installdir/post/otherpkgs/$ostype/$osarch/ganglia";
- my $errorstr = '';
- unless ( -e $rpmdir ) {
- return "Put rrdtool,ganglia,ganglia-gmond,ganglia-gmetad rpms into $rpmdir.";
- }
-
- opendir( DIRHANDLE, $rpmdir );
- foreach my $filename ( readdir(DIRHANDLE) ) {
- if ( $filename =~ /(\D+)-(\d+)\..*\.rpm$/ ) {
- $temphash{$1} = 1;
- }
- }
- closedir(DIRHANDLE);
-
- # Check if all RPMs are in the array
- foreach (@rpmnames) {
- unless ( $temphash{$_} ) {
- $errorstr .= $_ . ',';
- }
- }
-
- if ($errorstr) {
- $errorstr = substr( $errorstr, 0, -1 );
- return "Put $errorstr rpms into $rpmdir.";
- } else {
- return "";
- }
-}
-
-sub web_restoreChange {
- my ( $software, $archFlag, $imagetype, $ostype, $installdir ) = @_;
-
- # Recover all file in the $installdir/custom/netboot/$ostype/
- if ($software) {
- system("rm -f $installdir/custom/netboot/$ostype/*.*");
- }
-
- if ($archFlag) {
- system("mv /tmp/webImageArch/*.* $installdir/custom/netboot/$ostype/");
- }
-
- # Recover the litefile table for statelite image
- if ( 'statelite' == $imagetype ) {
- system("rm -r /tmp/litefile.csv ; mv /tmp/litefilearchive.csv /tmp/litefile.csv ; tabrestore /tmp/litefile.csv");
- }
-}
-
-sub web_provision_preinstall {
- my ( $ostype, $profile, $arch, $installdir, $softwarenames ) = @_;
- my $checkresult = '';
- my $errorstr = '';
- my @software = split( ',', $softwarenames );
- my $softwarenum = scalar(@software);
-
- if ( -e "$installdir/custom/install/$ostype/" ) {
- opendir( DIRHANDLE, "$installdir/custom/install/$ostype/" );
- foreach my $filename ( readdir(DIRHANDLE) ) {
- if ( '.' eq $filename || '..' eq $filename ) {
- next;
- }
-
- $filename = "$installdir/custom/install/$ostype/" . $filename;
- if ( $filename =~ /(.*)\.guibak$/ ) {
- if ( $softwarenum < 1 ) {
- system("mv $filename $1");
- }
- next;
- }
-
- `/bin/grep 'xCAT Web Gui' $filename`;
- if ($?) {
- # Backup the original config file
- if ( $softwarenum > 0 ) {
- system("mv $filename ${filename}.guibak");
- }
- } else {
- unlink($filename);
- }
- }
-
- closedir(DIRHANDLE);
- } else {
- `mkdir -p $installdir/custom/install/$ostype -m 0755`;
- }
-
- if ( $softwarenum < 1 ) {
- return '';
- }
-
- foreach (@software) {
- if ( 'ganglia' eq $_ ) {
- $checkresult = web_gangliaRpmCheck( $ostype, $profile, $arch, $installdir );
- }
-
- if ($checkresult) {
- $errorstr .= $checkresult . "\n";
- }
- }
-
- if ($errorstr) {
- return $errorstr;
- }
-
- foreach (@software) {
- if ( 'ganglia' eq $_ ) {
- web_gangliaConfig( $ostype, $profile, $arch, 'install', $installdir );
- }
- }
- return '';
-}
-
-sub web_provision {
- my ( $request, $callback, $sub_req ) = @_;
- my $nodes = $request->{arg}->[1];
- my $imageName = $request->{arg}->[2];
- my ( $arch, $inic, $pnic, $master, $tftp, $nfs ) = split( /,/, $request->{arg}->[3] );
- my $line = '';
- my %imageattr;
- my $retinfo = xCAT::Utils->runcmd( "lsdef -t osimage -l $imageName", -1, 1 );
- my $installdir = xCAT::TableUtils->getInstallDir();
-
- # Parse output, get the OS name and type
- foreach $line (@$retinfo) {
- if ( $line =~ /(\w+)=(\S*)/ ) {
- $imageattr{$1} = $2;
- }
- }
-
- # Check the output
- unless ( $imageattr{'osname'} ) {
- web_infomsg( "Image infomation error. Check the image first.\nprovision stop.", $callback );
- return;
- }
-
- if ( 'install' eq $imageattr{'provmethod'} ) {
- my $prepareinfo = web_provision_preinstall( $imageattr{'osvers'}, $imageattr{'profile'}, $arch, $installdir, $request->{arg}->[4] );
- if ($prepareinfo) {
- web_infomsg( "$prepareinfo \nprovision stop.", $callback );
- return;
- }
- }
-
- if ( $imageattr{'osname'} =~ /aix/i ) {
- web_provisionaix( $nodes, $imageName, $imageattr{'nimtype'}, $inic, $pnic, $master, $tftp, $nfs, $callback );
- } else {
- web_provisionlinux(
- $nodes, $arch,
- $imageattr{'osvers'}, $imageattr{'provmethod'},
- $imageattr{'profile'}, $inic,
- $pnic, $master,
- $tftp, $nfs,
- $callback
- );
- }
-}
-
-sub web_provisionlinux {
- my ($nodes, $arch, $os, $provmethod, $profile, $inic, $pnic, $master, $tftp, $nfs, $callback) = @_;
- my $outputMessage = '';
- my $retvalue = 0;
- my $netboot = '';
-
- if ( $arch =~ /ppc/i ) {
- $netboot = 'yaboot';
- } elsif ( $arch =~ /x.*86/i ) {
- $netboot = 'xnba';
- }
-
- $outputMessage =
- "Do provison : $nodes \n"
- . " Arch:$arch\n OS:$os\n Provision:$provmethod\n Profile:$profile\n Install NIC:$inic\n Primary NIC:$pnic\n"
- . " xCAT Master:$master\n TFTP Server:$tftp\n NFS Server:$nfs\n Netboot:$netboot\n";
-
- web_infomsg( $outputMessage, $callback );
-
- # Change the node attribute
- my $cmd = "chdef -t node -o $nodes arch=$arch os=$os provmethod=$provmethod profile=$profile installnic=$inic tftpserver=$tftp nfsserver=$nfs netboot=$netboot" . " xcatmaster=$master primarynic=$pnic";
- web_runcmd( $cmd, $callback );
- if ($::RUNCMD_RC) {
- web_infomsg( "Configure nodes' attributes error.\nProvision stop.", $callback );
- return;
- }
-
- $cmd = "makedhcp $nodes";
- web_runcmd( $cmd, $callback );
- if ($::RUNCMD_RC) {
- web_infomsg( "Make DHCP error.\nProvision stop.", $callback );
- return;
- }
-
- # Restart DHCP
- $cmd = "service dhcpd restart";
- web_runcmd( $cmd, $callback );
-
- # Conserver
- $cmd = "makeconservercf $nodes";
- web_runcmd( $cmd, $callback );
- if ($::RUNCMD_RC) {
- web_infomsg( "Configure conserver error.\nProvision stop.", $callback );
- return;
- }
-
- # For system x, should configure boot sequence first
- if ( $arch =~ /x.*86/i ) {
- $cmd = "rbootseq $nodes net,hd";
- web_runcmd( $cmd, $callback );
- if ($::RUNCMD_RC) {
- web_infomsg( "Set boot sequence error.\nProvision stop.",
- $callback );
- return;
- }
- }
-
- # Nodeset
- $cmd = "nodeset $nodes $provmethod";
- web_runcmd( $cmd, $callback );
- if ($::RUNCMD_RC) { web_infomsg( "Set nodes provision method error.\nprovision stop.", $callback );
- return;
- }
-
- # Reboot the node fro provision
- if ( $arch =~ /ppc/i ) {
- $cmd = "rnetboot $nodes";
- } else {
- $cmd = "rpower $nodes boot";
- }
-
- web_runcmd( $cmd, $callback );
- if ($::RUNCMD_RC) {
- web_infomsg( "Boot nodes error.\nProvision stop.", $callback );
- return;
- }
-
- # Provision complete
- web_infomsg("Provision on $nodes success.\nProvision stop.");
-}
-
-sub web_provisionaix {
- my (
- $nodes, $imagename, $nimtype, $inic, $pnic,
- $master, $tftp, $nfs, $callback
- ) = @_;
- my $outputMessage = '';
- my $retinfo;
- my %nimhash;
- my $line;
- my @updatenodes;
- my @addnodes;
- my $cmd = '';
-
- # Set attributes
- $cmd = "chdef -t node -o $nodes installnic=$inic tftpserver=$tftp nfsserver=$nfs xcatmaster=$master primarynic=$pnic";
- web_runcmd( $cmd, $callback );
- if ($::RUNCMD_RC) {
- web_infomsg( "Change nodes' attributes error.\nprovision stop.", $callback );
- return;
- }
-
- # Get all NIM resource to filter nodes
- $retinfo = xCAT::Utils->runcmd( "lsnim -c machines", -1, 1 );
- foreach $line (@$retinfo) {
- if ( $line =~ /(\S+)\s+\S+/ ) {
- $nimhash{$1} = 1;
- }
- }
-
- foreach my $node ( split( /,/, $nodes ) ) {
- if ( $nimhash{$node} ) {
- push( @updatenodes, $node );
- } else {
- push( @addnodes, $node );
- }
- }
-
- if ( 0 < scalar(@addnodes) ) {
- $cmd = "xcat2nim -t node -o " . join( ",", @addnodes );
- web_runcmd( $cmd, $callback );
- if ($::RUNCMD_RC) {
- web_infomsg( "xcat2nim command error.\nprovision stop.", $callback );
- return;
- }
- }
-
- if ( 0 < scalar(@updatenodes) ) {
- $cmd = "xcat2nim -u -t node -o " . join( ",", @updatenodes );
- web_runcmd( $cmd, $callback );
- if ($::RUNCMD_RC) {
- web_infomsg( "xcat2nim command error.\nprovision stop.", $callback );
- return;
- }
- }
-
- $cmd = "makeconservercf $nodes";
- web_runcmd( $cmd, $callback );
- if ($::RUNCMD_RC) {
- web_infomsg( "Configure conserver error.\nprovision stop.", $callback );
- return;
- }
-
- if ( $nimtype =~ /diskless/ ) {
- $cmd = "mkdsklsnode -i $imagename $nodes";
- } else {
- $cmd = "nimnodeset -i $imagename $nodes";
- }
-
- web_runcmd( $cmd, $callback );
- if ($::RUNCMD_RC) {
- web_infomsg( "Set node install method error.\nprovision stop.", $callback );
- return;
- }
-
- $cmd = "rnetboot $nodes";
- web_runcmd( $cmd, $callback );
- if ($::RUNCMD_RC) {
- web_infomsg( "Reboot nodes error.\nprovision stop.", $callback );
- return;
- }
-
- web_infomsg("Provision on $nodes success.\nprovision stop.");
-}
-
-sub web_runcmd {
- my $cmd = shift;
- my $callback = shift;
- my $showstr = "\n" . $cmd . "\n";
-
- web_infomsg( $showstr, $callback );
-
- my $retvalue = xCAT::Utils->runcmd( $cmd, -1, 1 );
- $showstr = join( "\n", @$retvalue );
- $showstr .= "\n";
-
- web_infomsg( $showstr, $callback );
-}
-
-sub web_infomsg {
- my $msg = shift;
- my $callback = shift;
- my %rsp;
-
- push @{ $rsp{info} }, $msg;
- xCAT::MsgUtils->message( 'I', \%rsp, $callback );
- return;
-}
-
-sub web_summary {
- my ( $request, $callback, $sub_req ) = @_;
- my $groupName = $request->{arg}->[1];
- my @nodes;
- my $nodetypeTab;
- my $nodelistTab;
- my $attrs;
- my %oshash;
- my %archhash;
- my %provhash;
- my %typehash;
- my %statushash;
- my $retHash = {};
- my $temp;
-
- if ( defined($groupName) ) {
- @nodes = xCAT::NodeRange::noderange($groupName);
- } else {
- @nodes = xCAT::DBobjUtils->getObjectsOfType('node');
- }
-
- $nodetypeTab = xCAT::Table->new('nodetype');
- unless ($nodetypeTab) {
- return;
- }
-
- $nodelistTab = xCAT::Table->new('nodelist');
- unless ($nodelistTab) {
- return;
- }
-
- $attrs = $nodetypeTab->getNodesAttribs( \@nodes, [ 'os', 'arch', 'provmethod', 'nodetype' ] );
- unless ($attrs) {
- return;
- }
-
- while ( my ( $key, $value ) = each( %{$attrs} ) ) {
- web_attrcount( $value->[0]->{'os'}, \%oshash );
- web_attrcount( $value->[0]->{'arch'}, \%archhash );
- web_attrcount( $value->[0]->{'provmethod'},, \%provhash );
- web_attrcount( $value->[0]->{'nodetype'},, \%typehash );
- }
-
- $attrs = $nodelistTab->getNodesAttribs( \@nodes, ['status'] );
- while ( my ( $key, $value ) = each( %{$attrs} ) ) {
- web_attrcount( $value->[0]->{'status'}, \%statushash );
- }
-
- # Status
- $temp = '';
- while ( my ( $key, $value ) = each(%statushash) ) {
- $temp .= ( $key . ':' . $value . ';' );
- }
- $temp = substr( $temp, 0, -1 );
- push( @{ $retHash->{'data'} }, 'Status=' . $temp );
-
- # OS
- $temp = '';
- while ( my ( $key, $value ) = each(%oshash) ) {
- $temp .= ( $key . ':' . $value . ';' );
- }
- $temp = substr( $temp, 0, -1 );
- push( @{ $retHash->{'data'} }, 'Operating System=' . $temp );
-
- # Architecture
- $temp = '';
- while ( my ( $key, $value ) = each(%archhash) ) {
- $temp .= ( $key . ':' . $value . ';' );
- }
- $temp = substr( $temp, 0, -1 );
- push( @{ $retHash->{'data'} }, 'Architecture=' . $temp );
-
- # Provision method
- $temp = '';
- while ( my ( $key, $value ) = each(%provhash) ) {
- $temp .= ( $key . ':' . $value . ';' );
- }
- $temp = substr( $temp, 0, -1 );
- push( @{ $retHash->{'data'} }, 'Provision Method=' . $temp );
-
- # Nodetype
- $temp = '';
- while ( my ( $key, $value ) = each(%typehash) ) {
- $temp .= ( $key . ':' . $value . ';' );
- }
- $temp = substr( $temp, 0, -1 );
- push( @{ $retHash->{'data'} }, 'Node Type=' . $temp );
-
- # Return data
- $callback->($retHash);
-}
-
-sub web_attrcount {
- my ( $key, $container ) = @_;
- unless ( defined($key) ) {
- $key = 'unknown';
- }
-
- if ( $container->{$key} ) {
- $container->{$key}++;
- } else {
- $container->{$key} = 1;
- }
-}
-
-sub web_rinstall {
- my ( $request, $callback, $sub_req ) = @_;
- my $os = $request->{arg}->[1];
- my $profile = $request->{arg}->[2];
- my $arch = $request->{arg}->[3];
- my $node = $request->{arg}->[4];
-
- # Begin installation
- my $out = `rinstall -o $os -p $profile -a $arch $node`;
-
- $callback->( { data => $out } );
-}
-
-sub web_addnode {
- my ( $request, $callback, $sub_req ) = @_;
- my $nodetype = $request->{arg}->[1];
- my @tempArray = split( ',', $request->{arg}->[2] );
-
- my $hcpname = shift(@tempArray);
- if ( 'node' ne $nodetype ) {
- my $username = $tempArray[0];
- my $passwd = $tempArray[1];
- my $ip = $tempArray[2];
- `/bin/grep '$hcpname' /etc/hosts`;
- if ($?) {
- open( OUTPUTFILE, '>>/etc/hosts' );
- print OUTPUTFILE "$ip $hcpname\n";
- close(OUTPUTFILE);
- }
-
- if ( 'hmc' eq $nodetype ) {
- `/opt/xcat/bin/chdef -t node -o $hcpname username=$username password=$passwd mgt=hmc nodetype=$nodetype ip=$ip groups=all`;
- } else {
- `/opt/xcat/bin/chdef -t node -o $hcpname username=$username password=$passwd mgt=blade mpa=$hcpname nodetype=$nodetype id=0 groups=mm,all`;
- }
- return;
- }
-
- my %temphash;
- my $writeflag = 0;
- my $line = '';
-
- # Save all nodes into a hash
- foreach (@tempArray) {
- $temphash{$_} = 1;
- }
-
- for ( my $i = 0 ; $i < scalar(@tempArray) ; $i = $i + 2 ) {
- $temphash{ $tempArray[$i] } = $tempArray[ $i + 1 ];
- }
-
- `/opt/xcat/bin/rscan $hcpname -z > /tmp/rscanall.tmp`;
-
- unless ( -e '/tmp/rscanall.tmp' ) {
- return;
- }
-
- open( INPUTFILE, '/tmp/rscanall.tmp' );
- open( OUTPUTFILE, '>/tmp/webrscan.tmp' );
- while ( $line = ) {
- if ( $line =~ /(\S+):$/ ) {
- if ( $temphash{$1} ) {
- $writeflag = 1;
- print OUTPUTFILE $temphash{$1} . ":\n";
- } else {
- $writeflag = 0;
- }
- } else {
- if ($writeflag) {
- print OUTPUTFILE $line;
- }
- }
- }
-
- close(INPUTFILE);
- close(OUTPUTFILE);
- unlink('/tmp/rscanall.tmp');
-
- `cat /tmp/webrscan.tmp | chdef -z`;
- unlink('/tmp/webrscan.tmp');
-}
-
-sub web_graphinfo {
- my ( $request, $callback, $sub_req ) = @_;
- my $nodetypeTab;
- my @nodes;
- my @parray;
- my @bladearray;
- my @xarray;
- my %phash;
- my %bladehash;
- my %xhash;
- my @unsupportarray;
- my @missinfoarray;
- my $result;
- my $pretstr = '';
- my $bladeretstr = '';
- my $xretstr = '';
- my $unsupretstr = '';
- my $missretstr = '';
-
- @nodes = xCAT::DBobjUtils->getObjectsOfType('node');
-
- $nodetypeTab = xCAT::Table->new('nodetype');
- unless ($nodetypeTab) {
- return;
- }
-
- # Get all nodetype and seperate nodes into different group
- $result = $nodetypeTab->getNodesAttribs( \@nodes, ['nodetype'] );
- while ( my ( $key, $value ) = each(%$result) ) {
- my $temptype = $value->[0]->{'nodetype'};
- if ( $temptype =~ /(ppc|lpar|cec|frame)/i ) {
- push( @parray, $key );
- } elsif ( $temptype =~ /blade/i ) {
- push( @bladearray, $key );
- } elsif ( $temptype =~ /osi/i ) {
- push( @xarray, $key );
- } else {
- push( @unsupportarray, $key );
- }
- }
- $nodetypeTab->close();
-
- # Get all information for System p node
- if ( scalar(@parray) > 0 ) {
- my $ppctab = xCAT::Table->new('ppc');
-
- $result = $ppctab->getNodesAttribs( \@parray, ['parent'] );
- my $typehash = xCAT::DBobjUtils->getnodetype( \@parray );
- foreach (@parray) {
- my $value = $result->{$_};
- if ( $value->[0] ) {
- $phash{$_} = $$typehash{$_} . ':' . $value->[0]->{'parent'} . ':';
- } else {
- $phash{$_} = $$typehash{$_} . '::';
- }
- }
- $ppctab->close();
-
- undef @parray;
- @parray = keys %phash;
- }
- if ( scalar(@parray) > 0 ) {
- # mtm
- my $vpdtab = xCAT::Table->new('vpd');
- $result = $vpdtab->getNodesAttribs( \@parray, ['mtm'] );
- foreach (@parray) {
- my $value = $result->{$_};
- $phash{$_} = $phash{$_} . $value->[0]->{'mtm'} . ':';
- }
- $vpdtab->close();
-
- # Status
- my $nodelisttab = xCAT::Table->new('nodelist');
- $result = $nodelisttab->getNodesAttribs( \@parray, ['status'] );
- foreach (@parray) {
- my $value = $result->{$_};
- $phash{$_} = $phash{$_} . $value->[0]->{'status'};
- }
- $nodelisttab->close();
-
- while ( my ( $key, $value ) = each(%phash) ) {
- $pretstr = $pretstr . $key . ':' . $value . ';';
- }
- }
-
- # Get all information for blade node
- if ( scalar(@bladearray) > 0 ) {
- my $mptab = xCAT::Table->new('mp');
- $result = $mptab->getNodesAttribs( \@bladearray, [ 'mpa', 'id' ] );
- foreach (@bladearray) {
- my $value = $result->{$_};
- if ( $value->[0]->{'mpa'} ) {
- $bladehash{$_} = 'blade:' . $value->[0]->{'mpa'} . ':' . $value->[0]->{'id'} . ':';
- } else {
- push( @missinfoarray, $_ );
- }
- }
-
- $mptab->close();
-
- undef @bladearray;
- @bladearray = keys %bladehash;
- }
-
- if ( scalar(@bladearray) > 0 ) {
- # Status
- my $nodelisttab = xCAT::Table->new('nodelist');
- $result = $nodelisttab->getNodesAttribs( \@bladearray, ['status'] );
- foreach (@bladearray) {
- my $value = $result->{$_};
- $bladehash{$_} = $bladehash{$_} . $value->[0]->{'status'};
- }
- $nodelisttab->close();
- while ( my ( $key, $value ) = each(%bladehash) ) {
- $bladeretstr = $bladeretstr . $key . ':' . $value . ';';
- }
- }
-
- # Get all information for System x node
- if ( scalar(@xarray) > 0 ) {
- # Rack and unit
- my $nodepostab = xCAT::Table->new('nodepos');
- $result = $nodepostab->getNodesAttribs( \@xarray, [ 'rack', 'u' ] );
- foreach (@xarray) {
- my $value = $result->{$_};
- if ( $value->[0]->{'rack'} ) {
- $xhash{$_} = 'systemx:' . $value->[0]->{'rack'} . ':' . $value->[0]->{'u'} . ':';
- } else {
- push( @missinfoarray, $_ );
- }
- }
-
- $nodepostab->close();
-
- undef @xarray;
- @xarray = keys %xhash;
- }
-
- if ( scalar(@xarray) > 0 ) {
- # mtm
- my $vpdtab = xCAT::Table->new('vpd');
- $result = $vpdtab->getNodesAttribs( \@xarray, ['mtm'] );
- foreach (@xarray) {
- my $value = $result->{$_};
- $xhash{$_} = $xhash{$_} . $value->[0]->{'mtm'} . ':';
- }
- $vpdtab->close();
-
- # Status
- my $nodelisttab = xCAT::Table->new('nodelist');
- $result = $nodelisttab->getNodesAttribs( \@xarray, ['status'] );
- foreach (@xarray) {
- my $value = $result->{$_};
- $xhash{$_} = $xhash{$_} . $value->[0]->{'status'};
- }
-
- while ( my ( $key, $value ) = each(%xhash) ) {
- $xretstr = $xretstr . $key . ':' . $value . ';';
- }
- }
-
- @missinfoarray = (@missinfoarray, @unsupportarray);
- foreach (@missinfoarray) {
- $missretstr = $missretstr . $_ . ':linux:other;';
- }
-
- # Combine all information into a string
- my $retstr = $pretstr . $bladeretstr . $xretstr . $missretstr;
- if ($retstr) {
- $retstr = substr( $retstr, 0, -1 );
- }
-
- $callback->( { data => $retstr } );
-}
-
-sub web_getdefaultuserentry {
-
- # Get default user entry
- my ( $request, $callback, $sub_req ) = @_;
-
- # Get profile
- my $profile = $request->{arg}->[1];
-
- if ( !$profile ) {
- $profile = 'default';
- }
-
- my $entry;
- if ( !(`test -e /var/opt/xcat/profiles/$profile.direct && echo 'File exists'`) ) {
- $entry = `cat /var/opt/xcat/profiles/default.direct`;
- } else {
- $entry = `cat /var/opt/xcat/profiles/$profile.direct`;
- }
-
- $callback->( { data => $entry } );
-}
-
-sub web_passwd() {
- my ( $request, $callback, $sub_req ) = @_;
-
- # Get current and new passwords
- my $user = $request->{arg}->[1];
- my $password = $request->{arg}->[2];
-
- # Generate encrypted password
- my $random = rand(10000000);
- my $encrypted = `perl -e "print crypt($password, $random)"`;
-
- # Save in xCAT passwd table
- `/opt/xcat/sbin/chtab username=$user passwd.key=xcat passwd.password=$encrypted`;
-
- my $info = "User password successfully updated";
- $callback->( { info => $info } );
- return;
-}
-
-sub web_policy() {
- my ( $request, $callback, $sub_req ) = @_;
-
- # Get user attributes
- my $priority = $request->{arg}->[1];
- my $args = $request->{arg}->[2];
-
- # Save in xCAT passwd and policy tables
- my $out = `/opt/xcat/sbin/chtab priority=$priority $args`;
-
- my $info = "User policy successfully updated";
- $callback->( { info => $info } );
- return;
-}
-
-sub web_deleteuser() {
- my ( $request, $callback, $sub_req ) = @_;
-
- # Get user attributes
- my $user = $request->{arg}->[1];
- my @users = split( ',', $user );
-
- # Delete user from xCAT passwd and policy tables
- foreach (@users) {
- `/opt/xcat/sbin/chtab -d username=$_ passwd`;
- `/opt/xcat/sbin/chtab -d name=$_ policy`;
- }
-
- my $info = "User successfully deleted";
- $callback->( { info => $info } );
- return;
-}
-
-sub web_getzdiskinfo() {
-
- # Get default disk info
- my ( $request, $callback, $sub_req ) = @_;
-
- # Get profile
- my $profile = $request->{arg}->[1];
-
- if ( !$profile ) {
- $profile = 'default';
- }
-
- my $info;
- if ( !(`test -e /var/opt/xcat/profiles/$profile.conf && echo 'File exists'`)) {
- $info = `cat /var/opt/xcat/profiles/default.conf`;
- } else {
- $info = `cat /var/opt/xcat/profiles/$profile.conf`;
- }
-
- $callback->( { info => $info } );
-}
-
-sub web_mkzprofile() {
-
- # Create default profile
- my ( $request, $callback, $sub_req ) = @_;
-
- # Get profile
- my $profile = $request->{arg}->[1];
- my $pool = $request->{arg}->[2];
- my $size = $request->{arg}->[3];
-
- # Create profile under /var/opt/xcat/profiles
- `mkdir -p /var/opt/xcat/profiles`;
- my $var = "";
-`echo "# Configuration for virtual machines" > /var/opt/xcat/profiles/$profile.conf`;
- $var = $profile . "_diskpool";
- `echo "$var=$pool" >> /var/opt/xcat/profiles/$profile.conf`;
- $var = $profile . "_eckd_size";
- `echo "$var=$size" >> /var/opt/xcat/profiles/$profile.conf`;
-
- # Move directory entry into /var/opt/xcat/profiles from /var/tmp
- `mv /var/tmp/$profile.direct /var/opt/xcat/profiles`;
-
- my $info = "Profile successfully created/updated";
- $callback->( { info => $info } );
-}
-
-sub web_rmzprofile() {
-
- # Delete default profile
- my ( $request, $callback, $sub_req ) = @_;
-
- # Get profile
- my $profile = $request->{arg}->[1];
- my @profiles = split( ',', $profile );
-
- # Delete profile under /var/opt/xcat/profiles
- foreach (@profiles) {
- `rm /var/opt/xcat/profiles/$_.conf`;
- `rm /var/opt/xcat/profiles/$_.direct`;
- }
-
- my $info = "Profile successfully deleted";
- $callback->( { info => $info } );
-}
-
-sub web_mkippool() {
-
- # Create group IP pool
- my ( $request, $callback, $sub_req ) = @_;
-
- # Get profile
- my $group = $request->{arg}->[1];
-
- # Move directory entry into /var/opt/xcat/ippool from /var/tmp
- `mkdir -p /var/opt/xcat/ippool`;
- `mv /var/tmp/$group.pool /var/opt/xcat/ippool`;
-
- my $info = "IP pool successfully created/updated";
- $callback->( { info => $info } );
-}
-
-sub web_rmippool() {
-
- # Delete group IP pool
- my ( $request, $callback, $sub_req ) = @_;
-
- # Get profile
- my $group = $request->{arg}->[1];
- my @groups = split( ',', $group );
-
- # Delete IP pool under /var/opt/xcat/ippool
- foreach (@groups) {
- `rm -rf /var/opt/xcat/ippool/$_.pool`;
- }
-
- my $info = "IP pool successfully deleted";
- $callback->( { info => $info } );
-}
-
-sub web_lsippool() {
-
- # List IP pool
- my ( $request, $callback, $sub_req ) = @_;
-
- # Get profile
- my $group = $request->{arg}->[1];
-
- # IP pool contained in /var/opt/xcat/ippool where a file exists per group
- my $entries;
- if ( !(`test -e /var/opt/xcat/ippool/$group.pool && echo Exists`) ) {
- $entries = "No IP pool found!";
- } else {
- # List IP pool under /var/opt/xcat/ippool
- $entries = `cat /var/opt/xcat/ippool/$group.pool`;
- }
-
- $callback->( { info => $entries } );
-}
-
-sub web_updateosimage() {
-
- # Add OS image to xCAT table
- my ( $request, $callback, $sub_req ) = @_;
-
- my $name = $request->{arg}->[1];
- my $type = $request->{arg}->[2];
- my $arch = $request->{arg}->[3];
- my $osName = $request->{arg}->[4];
- my $osVersion = $request->{arg}->[5];
- my $profile = $request->{arg}->[6];
- my $provMethod = $request->{arg}->[7];
- my $comments = $request->{arg}->[8];
-
- `/opt/xcat/sbin/chtab -d imagename=$name osimage`;
- `/opt/xcat/sbin/chtab osimage.imagename=$name osimage.imagetype=$type osimage.osarch=$arch osimage.osname=$osName osimage.osvers=$osVersion osimage.profile=$profile osimage.provmethod=$provMethod osimage.comments=$comments`;
- my $info = "Image successfully updated";
- $callback->( { info => $info } );
-}
-
-sub web_rmosimage() {
-
- # Delete OS image from xCAT table
- my ( $request, $callback, $sub_req ) = @_;
-
- my $name = $request->{arg}->[1];
- my @names = split( ',', $name );
-
- # Delete user from xCAT passwd and policy tables
- foreach (@names) {
- `/opt/xcat/sbin/chtab -d imagename=$_ osimage`;
- }
-
- my $info = "Image successfully deleted";
- $callback->( { info => $info } );
-}
-
-sub web_updategroup() {
-
- # Add group to xCAT table
- my ( $request, $callback, $sub_req ) = @_;
-
- my $name = $request->{arg}->[1];
- my $ip = $request->{arg}->[2];
- $ip =~ s/'//g;
-
- my $hostnames = $request->{arg}->[3];
- $hostnames =~ s/'//g;
-
- my $comments = $request->{arg}->[4];
- $comments =~ s/'//g;
-
- `/opt/xcat/sbin/chtab -d node=$name hosts`;
- `/opt/xcat/sbin/chtab node=$name hosts.ip="$ip" hosts.hostnames="$hostnames" hosts.comments="$comments"`;
-
- my $info = "Group successfully updated";
- $callback->( { info => $info } );
-}
-
-sub web_rmgroup() {
-
- # Delete group from xCAT table
- my ( $request, $callback, $sub_req ) = @_;
-
- my $name = $request->{arg}->[1];
- my @names = split( ',', $name );
-
- # Delete user from xCAT passwd and policy tables
- foreach (@names) {
- `/opt/xcat/sbin/chtab -d node=$_ hosts`;
- `rm -rf /var/opt/xcat/ippool/$_.pool`;
- }
-
- my $info = "Group successfully deleted";
- $callback->( { info => $info } );
-}
-
-sub web_framesetup() {
- my ( $request, $callback, $sub_req ) = @_;
- my $adminpasswd = $request->{arg}->[1];
- my $generalpasswd = $request->{arg}->[2];
- my $hmcpasswd = $request->{arg}->[3];
- my $configphase = $request->{arg}->[4];
- my @tempnode = 'bpa';
-
- if ($configphase == 1){
- #run makedhcp
- xCAT::Utils->runcmd('makedhcp bpa', -1, 1);
- sleep(10);
- #run makehosts
- xCAT::Utils->runcmd('makehosts bpa', -1, 1);
- $callback->( { info => 'FRAMEs DHCP, DNS configured.' } );
- } elsif ($configphase == 2){
- #run chtab command
- xCAT::Utils->runcmd('chtab key=bpa,username=HMC passwd.password=' . $hmcpasswd, -1, 1);
- xCAT::Utils->runcmd('chtab key=bpa,username=admin passwd.password=' . $adminpasswd, -1, 1);
- xCAT::Utils->runcmd('chtab key=bpa,username=general passwd.password=' . $generalpasswd, -1, 1);
-
- #mkhwconn
- xCAT::Utils->runcmd('mkhwconn frame -t', -1, 1);
- #rspconfig
- xCAT::Utils->runcmd('rspconfig frame general_passwd=general,' . $generalpasswd, -1, 1);
- xCAT::Utils->runcmd('rspconfig frame admin_passwd=admin,' . $adminpasswd, -1, 1);
- xCAT::Utils->runcmd('rspconfig frame HMC_passwd=,' . $hmcpasswd, -1, 1);
-
- $callback->( { info => 'Hardware connection and configure password created.' } );
- }
-}
-
-sub web_cecsetup() {
- my ( $request, $callback, $sub_req ) = @_;
- my $adminpasswd = $request->{arg}->[1];
- my $generalpasswd = $request->{arg}->[2];
- my $hmcpasswd = $request->{arg}->[3];
- my $configphase = $request->{arg}->[4];
- my @tempnode = 'bpa';
-
- if ($configphase == 1){
- # Run makedhcp
- xCAT::Utils->runcmd('makedhcp fsp', -1, 1);
- sleep(10);
- # Run makehosts
- xCAT::Utils->runcmd('makehosts fsp', -1, 1);
- $callback->( { info => 'CEC DHCP, DNS configured.' } );
- } elsif ($configphase == 2){
- # Run chtab command
- xCAT::Utils->runcmd('chtab key=fsp,username=HMC passwd.password=' . $hmcpasswd, -1, 1);
- xCAT::Utils->runcmd('chtab key=fsp,username=admin passwd.password=' . $adminpasswd, -1, 1);
- xCAT::Utils->runcmd('chtab key=fsp,username=general passwd.password=' . $generalpasswd, -1, 1);
- # Run mkhwconn
- xCAT::Utils->runcmd('mkhwconn cec -t', -1, 1);
- # Run rspconfig
- xCAT::Utils->runcmd('rspconfig cec general_passwd=general,' . $generalpasswd, -1, 1);
- xCAT::Utils->runcmd('rspconfig cec admin_passwd=admin,' . $adminpasswd, -1, 1);
- xCAT::Utils->runcmd('rspconfig cec HMC_passwd=,' . $hmcpasswd, -1, 1);
-
- $callback->( { info => 'Hardware connection and configure password created.' } );
- }
-}
-
-1;
+# IBM(c) 2011 EPL license http://www.eclipse.org/legal/epl-v10.html
+#-------------------------------------------------------
+
+=head 1
+
+ xCAT plugin to handle xCAT UI commands
+
+=cut
+
+#-------------------------------------------------------
+
+package xCAT_plugin::web;
+use strict;
+require xCAT::Utils;
+require xCAT::MsgUtils;
+require xCAT::DBobjUtils;
+require IO::Socket::INET;
+use Getopt::Long;
+use Data::Dumper;
+use LWP::Simple;
+use xCAT::Table;
+use xCAT::NodeRange;
+use xCAT::TableUtils;
+require XML::Parser;
+
+sub handled_commands {
+ return { webrun => "web" };
+}
+
+sub process_request {
+ my $request = shift;
+ my $callback = shift;
+ my $sub_req = shift;
+ my %authorized_cmds = (
+ 'update' => \&web_update,
+ 'lscondition' => \&web_lscond,
+ 'lsresponse' => \&web_lsresp,
+ 'lscondresp' => \&web_lscondresp,
+ 'mkcondresp' => \&web_mkcondresp,
+ 'startcondresp' => \&web_startcondresp,
+ 'stopcondresp' => \&web_stopcondresp,
+ 'lsevent' => \&web_lsevent,
+ 'unlock' => \&web_unlock,
+ 'unlockbyip' => \&web_unlockByIP,
+ 'unlockshow' => \&web_unlockShow,
+ 'rmcstart' => \&web_rmcmonStart,
+ 'rmcshow' => \&web_rmcmonShow,
+ 'gangliaconf' => \&web_gangliaconf,
+ 'gangliastart' => \&web_gangliastart,
+ 'gangliastop' => \&web_gangliastop,
+ 'gangliastatus' => \&web_gangliastatus,
+ 'gangliacheck' => \&web_gangliacheck,
+ 'installganglia' => \&web_installganglia,
+ 'mkcondition' => \&web_mkcondition,
+ 'monls' => \&web_monls,
+ 'dynamiciprange' => \&web_dynamiciprange,
+ 'discover' => \&web_discover,
+ 'updatevpd' => \&web_updatevpd,
+ 'writeconfigfile' => \&web_writeconfigfile,
+ 'createimage' => \&web_createimage,
+ 'provision' => \&web_provision,
+ 'summary' => \&web_summary,
+ 'gangliashow' => \&web_gangliaShow,
+ 'gangliacurrent' => \&web_gangliaLatest,
+ 'rinstall' => \&web_rinstall,
+ 'addnode' => \&web_addnode,
+ 'graph' => \&web_graphinfo,
+ 'getdefaultuserentry' => \&web_getdefaultuserentry,
+ 'getzdiskinfo' => \&web_getzdiskinfo,
+ 'passwd' => \&web_passwd,
+ 'policy' => \&web_policy,
+ 'deleteuser' => \&web_deleteuser,
+ 'mkzprofile' => \&web_mkzprofile,
+ 'rmzprofile' => \&web_rmzprofile,
+ 'mkippool' => \&web_mkippool,
+ 'rmippool' => \&web_rmippool,
+ 'lsippool' => \&web_lsippool,
+ 'updateosimage' => \&web_updateosimage,
+ 'rmosimage' => \&web_rmosimage,
+ 'updategroup' => \&web_updategroup,
+ 'rmgroup' => \&web_rmgroup,
+ 'framesetup' => \&web_framesetup,
+ 'cecsetup' => \&web_cecsetup,
+ 'deletefile' => \&web_deletefile,
+ 'createfolder' => \&web_createfolder,
+ 'getrepospace' => \&web_getrepospace
+ );
+
+ # Check whether the request is authorized or not
+ @_ = split ' ', $request->{arg}->[0];
+ my $cmd = $_[0];
+ if ( grep { $_ eq $cmd } keys %authorized_cmds ) {
+ my $func = $authorized_cmds{$cmd};
+ $func->( $request, $callback, $sub_req );
+ }
+ else {
+ $callback->(
+ { error => "$cmd is not authorized!\n", errorcode => [1] } );
+ }
+}
+
+sub web_lsevent {
+ my ( $request, $callback, $sub_req ) = @_;
+ my @ret = `$request->{arg}->[0]`;
+
+ # Please refer the manpage for the output format of lsevent
+ my $data = [];
+ my $record = '';
+ my $i = 0;
+ my $j = 0;
+
+ foreach my $item (@ret) {
+ if ( $item ne "\n" ) {
+ chomp $item;
+ my ( $key, $value ) = split( "=", $item );
+ if ( $j < 2 ) {
+ $record .= $value . ';';
+ }
+ else {
+ $record .= $value;
+ }
+
+ $j++;
+ if ( $j == 3 ) {
+ $i++;
+ $j = 0;
+ push( @$data, $record );
+ $record = '';
+ }
+ }
+
+ }
+
+ $callback->( { data => $data } );
+}
+
+sub web_mkcondresp {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $conditionName = $request->{arg}->[1];
+ my $temp = $request->{arg}->[2];
+ my $cmd = '';
+ my @resp = split( ':', $temp );
+
+ # Create new associations
+ if ( 1 < length( @resp[0] ) ) {
+ $cmd = substr( @resp[0], 1 );
+ $cmd =~ s/,/ /;
+ $cmd = 'mkcondresp ' . $conditionName . ' ' . $cmd;
+ my $retInfo = xCAT::Utils->runcmd( $cmd, -1, 1 );
+ }
+
+ # Delete old associations
+ if ( 1 < length( @resp[1] ) ) {
+ $cmd = substr( @resp[1], 1 );
+ $cmd =~ s/,/ /;
+ $cmd = 'rmcondresp ' . $conditionName . ' ' . $cmd;
+ my $retInfo = xCAT::Utils->runcmd( $cmd, -1, 1 );
+ }
+
+ # There is no output for mkcondresp
+ $cmd = 'startcondresp ' . $conditionName;
+ my $refInfo = xCAT::Utils->runcmd( $cmd, -1, 1 );
+ $callback->( { data => "Success." } );
+}
+
+sub web_startcondresp {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $conditionName = $request->{arg}->[1];
+ my $cmd = 'startcondresp "' . $conditionName . '"';
+ my $retInfo = xCAT::Utils->runcmd( $cmd, -1, 1 );
+ $callback->(
+ { data => 'start monitor "' . $conditionName . '" Successful.' } );
+}
+
+sub web_stopcondresp {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $conditionName = $request->{arg}->[1];
+ my $cmd = 'stopcondresp "' . $conditionName . '"';
+ my $retInfo = xCAT::Utils->runcmd( $cmd, -1, 1 );
+ $callback->(
+ { data => 'stop monitor "' . $conditionName . '" Successful.' } );
+}
+
+sub web_lscond {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $nodeRange = $request->{arg}->[1];
+ my $names = '';
+
+ # List all the conditions for all lpars in this group
+ if ($nodeRange) {
+ my @nodes = xCAT::NodeRange::noderange($nodeRange);
+ my %tempHash;
+ my $nodeCount = @nodes;
+
+ # No node in this group
+ if ( 1 > $nodeCount ) {
+ return;
+ }
+
+ # No conditions return
+ my $tempCmd = 'lscondition -d :' . join( ',', @nodes );
+ my $retInfo = xCAT::Utils->runcmd( $tempCmd, -1, 1 );
+ if ( 1 > @$retInfo ) {
+ return;
+ }
+
+ shift @$retInfo;
+ shift @$retInfo;
+ foreach my $line (@$retInfo) {
+ my @temp = split( ':', $line );
+ $tempHash{ @temp[0] }++;
+ }
+
+ foreach my $name ( keys(%tempHash) ) {
+ if ( $nodeCount == $tempHash{$name} ) {
+ $names = $names . $name . ';';
+ }
+ }
+ }
+
+ # Only list the conditions on local
+ else {
+ my $retInfo = xCAT::Utils->runcmd( 'lscondition -d', -1, 1 );
+ if ( 2 > @$retInfo ) {
+ return;
+ }
+
+ shift @$retInfo;
+ shift @$retInfo;
+ foreach my $line (@$retInfo) {
+ my @temp = split( ':', $line );
+ $names = $names . @temp[0] . ':' . substr( @temp[2], 1, 3 ) . ';';
+ }
+ }
+
+ if ( '' eq $names ) {
+ return;
+ }
+
+ $names = substr( $names, 0, ( length($names) - 1 ) );
+ $callback->( { data => $names } );
+}
+
+sub web_mkcondition {
+ my ( $request, $callback, $sub_req ) = @_;
+
+ if ( 'change' eq $request->{arg}->[1] ) {
+ my @nodes;
+ my $conditionName = $request->{arg}->[2];
+ my $groupName = $request->{arg}->[3];
+
+ my $retInfo =
+ xCAT::Utils->runcmd( 'nodels ' . $groupName . " ppc.nodetype", -1,
+ 1 );
+ foreach my $line (@$retInfo) {
+ my @temp = split( ':', $line );
+ if ( @temp[1] !~ /lpar/ ) {
+ $callback->(
+ {
+ data =>
+ 'Error : only the compute nodes\' group could select.'
+ }
+ );
+ return;
+ }
+
+ push( @nodes, @temp[0] );
+ }
+
+ xCAT::Utils->runcmd( 'chcondition -n ' + join( ',', @nodes ) + '-m m ' +
+ $conditionName );
+ $callback->( { data => 'Change scope success.' } );
+ }
+
+}
+
+sub web_lsresp {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $names = '';
+ my @temp;
+ my $retInfo = xCAT::Utils->runcmd( 'lsresponse -d', -1, 1 );
+
+ shift @$retInfo;
+ shift @$retInfo;
+ foreach my $line (@$retInfo) {
+ @temp = split( ':', $line );
+ $names = $names . @temp[0] . ';';
+ }
+
+ $names = substr( $names, 0, ( length($names) - 1 ) );
+ $callback->( { data => $names } );
+}
+
+sub web_lscondresp {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $names = '';
+ my @temp;
+
+ # If there is a condition name, then we only show the condition linked associations
+ if ( $request->{arg}->[1] ) {
+ my $cmd = 'lscondresp -d ' . $request->{arg}->[1];
+ my $retInfo = xCAT::Utils->runcmd( $cmd, -1, 1 );
+ if ( 2 > @$retInfo ) {
+ $callback->( { data => '' } );
+ return;
+ }
+
+ shift @$retInfo;
+ shift @$retInfo;
+ for my $line (@$retInfo) {
+ @temp = split( ':', $line );
+ $names = $names . @temp[1] . ';';
+ }
+ }
+
+ $names = substr( $names, 0, ( length($names) - 1 ) );
+ $callback->( { data => $names } );
+}
+
+sub web_update {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $os = "unknown";
+ my $rpmNames = $request->{arg}->[1];
+ my $repository = $request->{arg}->[2];
+ my $fileHandle;
+ my $cmd;
+ my $returnInfo;
+ my $webpageContent = undef;
+ my $remoteRpmFilePath = undef;
+ my $localRpmFilePath = undef;
+
+ if ( xCAT::Utils->isLinux() ) {
+ $os = xCAT::Utils->osver();
+
+ # SUSE Linux
+ if ( $os =~ /sles.*/ ) {
+ $rpmNames =~ s/,/ /g;
+
+ # Create zypper command
+ $cmd = "zypper -n -p " . $repository . " update " . $rpmNames;
+ }
+
+ # Red Hat
+ else {
+
+ # Check the yum config file, and detect if it exists
+ if ( -e "/tmp/xCAT_update.yum.conf" ) {
+ unlink("/tmp/xCAT_update.yum.conf");
+ }
+
+ # Create file, return error if failed
+ unless ( open( $fileHandle, '>>', "/tmp/xCAT_update.yum.conf" ) ) {
+ $callback->(
+ { error => "Created temp file error!\n", errorcode => [1] }
+ );
+ return;
+ }
+
+ # Write the RPM path into config file
+ print $fileHandle "[xcat_temp_update]\n";
+ print $fileHandle "name=temp prepository\n";
+ $repository = "baseurl=" . $repository . "\n";
+ print $fileHandle $repository;
+ print $fileHandle "enabled=1\n";
+ print $fileHandle "gpgcheck=0\n";
+ close($fileHandle);
+
+ # Use system to run the command: yum -y -c config-file update rpm-names
+ $rpmNames =~ s/,/ /g;
+ $cmd = "yum -y -c /tmp/xCAT_update.yum.conf update " . $rpmNames . " 2>&1";
+ }
+
+ # Run the command and return the result
+ $returnInfo = readpipe($cmd);
+ $callback->( { info => $returnInfo } );
+ }
+
+ # AIX
+ else {
+
+ # Open the RPM path and read the page's content
+ $webpageContent = LWP::Simple::get($repository);
+ unless ( defined($webpageContent) ) {
+ $callback->({
+ error => "open $repository error, please check!!",
+ errorcode => [1]
+ });
+ return;
+ }
+
+ # Must support updating several RPM
+ foreach ( split( /,/, $rpmNames ) ) {
+
+ # Find out RPMs corresponding RPM HREF on the web page
+ $webpageContent =~ m/href="($_-.*?[ppc64|noarch].rpm)/i;
+ unless ( defined($1) ) {
+ next;
+ }
+ $remoteRpmFilePath = $repository . $1;
+ $localRpmFilePath = '/tmp/' . $1;
+
+ # Download RPM package to temp
+ unless ( -e $localRpmFilePath ) {
+ $cmd = "wget -O " . $localRpmFilePath . " " . $remoteRpmFilePath;
+ if ( 0 != system($cmd) ) {
+ $returnInfo = $returnInfo . "update " . $_ . " failed: cannot download the RPM\n";
+ $callback->( { error => $returnInfo, errorcode => [1] } );
+ return;
+ }
+ }
+
+ # Update RPM by RPM packages
+ $cmd = "rpm -U " . $localRpmFilePath . " 2>&1";
+ $returnInfo = $returnInfo . readpipe($cmd);
+ }
+
+ $callback->( { info => $returnInfo } );
+ }
+}
+
+sub web_unlock {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $node = $request->{arg}->[1];
+ my $password = $request->{arg}->[2];
+
+ # Unlock a node by setting up the SSH keys
+ my $out = `DSH_REMOTE_PASSWORD=$password /opt/xcat/bin/xdsh $node -K 2>&1`;
+
+ $callback->( { data => $out } );
+}
+
+sub web_unlockByIP {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $node = $request->{arg}->[1];
+ my $password = $request->{arg}->[2];
+ my $ip = $request->{arg}->[3];
+
+ # Unlock a node by setting up the SSH keys
+ my $out = `DSH_REMOTE_PASSWORD=$password /opt/xcat/bin/xdsh $node -K --ip $ip 2>&1`;
+
+ $callback->( { data => $out } );
+}
+
+sub web_unlockShow {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $node = $request->{arg}->[1];
+ my $show = $request->{arg}->[2];
+
+ # Unlock a node by setting up the SSH keys
+ my $out = `/opt/xcat/bin/xdsh $node -K --show $show 2>&1`;
+
+ $callback->( { data => $out } );
+}
+
+sub web_gangliastatus {
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # Get node range
+ my $nr = $request->{arg}->[1];
+ my $out = `/opt/xcat/bin/xdsh $nr "service gmond status"`;
+
+ # Parse output, and use $callback to send back to the web interface
+ # Output looks like:
+ # node_1: Checking for gmond: ..running
+ # node_2: Checking for gmond: ..running
+ my @lines = split( '\n', $out );
+ my $line;
+ my $status;
+ foreach $line (@lines) {
+ if ( $line =~ m/running/i ) {
+ $status = 'on';
+ }
+ else {
+ $status = 'off';
+ }
+
+ @_ = split( ': ', $line );
+ $callback->({
+ node => [{
+ name => [ $_[0] ], # Node name
+ data => [$status] # Output
+ }]
+ });
+ }
+}
+
+sub web_gangliaconf() {
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # Get node range
+ my $nr = $request->{arg}->[1];
+
+ my $info;
+ my $output;
+
+ # Add gangliamon to the monitoring table (if not already)
+ $output = `/opt/xcat/bin/monadd gangliamon`;
+
+ # Run the ganglia configuration script on node
+ if ($nr) {
+ $output = `/opt/xcat/bin/moncfg gangliamon $nr -r`;
+ }
+ else {
+
+ # If no node range is given, then assume all nodes
+
+ # Handle localhost (this needs to be 1st)
+ $output = `/opt/xcat/bin/moncfg gangliamon`;
+
+ # Handle remote nodes
+ $output .= `/opt/xcat/bin/moncfg gangliamon -r`;
+ }
+
+ my @lines = split( '\n', $output );
+ foreach (@lines) {
+ if ($_) {
+ $info .= ( $_ . "\n" );
+ }
+ }
+
+ $callback->( { info => $info } );
+ return;
+}
+
+sub web_gangliastart() {
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # Get node range
+ my $nr = $request->{arg}->[1];
+
+ my $info;
+ my $output;
+
+ # Add gangliamon to the monitoring table (if not already)
+ $output = `/opt/xcat/bin/monadd gangliamon`;
+
+ # Start the gmond daemon on node
+ if ($nr) {
+ $output = `/opt/xcat/bin/moncfg gangliamon $nr -r`;
+ $output .= `/opt/xcat/bin/monstart gangliamon $nr -r`;
+ }
+ else {
+
+ # If no node range is given, then assume all nodes
+
+ # Handle localhost (this needs to be 1st)
+ $output = `/opt/xcat/bin/moncfg gangliamon`;
+
+ # Handle remote nodes
+ $output .= `/opt/xcat/bin/moncfg gangliamon -r`;
+
+ # Handle localhost (this needs to be 1st)
+ $output .= `/opt/xcat/bin/monstart gangliamon`;
+
+ # Handle remote nodes
+ $output .= `/opt/xcat/bin/monstart gangliamon -r`;
+ }
+
+ my @lines = split( '\n', $output );
+ foreach (@lines) {
+ if ($_) {
+ $info .= ( $_ . "\n" );
+ }
+ }
+
+ $callback->( { info => $info } );
+ return;
+}
+
+sub web_gangliastop() {
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # Get node range
+ my $nr = $request->{arg}->[1];
+
+ my $info;
+ my $output;
+
+ # Stop the gmond daemon on node
+ if ($nr) {
+ $output = `/opt/xcat/bin/monstop gangliamon $nr -r`;
+ }
+ else {
+
+ # If no node range is given, then assume all nodes
+
+ # Handle localhost (this needs to be 1st)
+ $output = `/opt/xcat/bin/monstop gangliamon`;
+
+ # Handle remote nodes
+ $output .= `/opt/xcat/bin/monstop gangliamon -r`;
+ }
+
+ my @lines = split( '\n', $output );
+ foreach (@lines) {
+ if ($_) {
+ $info .= ( $_ . "\n" );
+ }
+ }
+
+ $callback->( { info => $info } );
+ return;
+}
+
+sub web_gangliacheck() {
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # Get node range
+ my $nr = $request->{arg}->[1];
+ if ( !$nr ) {
+ $nr = '';
+ }
+
+ # Check if ganglia RPMs are installed
+ my $info;
+ my $info = `/opt/xcat/bin/xdsh $nr "rpm -q ganglia-gmond libganglia libconfuse"`;
+ $callback->( { info => $info } );
+ return;
+}
+
+sub web_installganglia() {
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # Get node range
+ my $nr = $request->{arg}->[1];
+ my @nodes = split( ',', $nr );
+
+ # Loop through each node
+ my $info;
+ my $tab;
+ my $attrs;
+ my $osType;
+ my $dir;
+ my $pkglist;
+ my $defaultDir;
+
+ foreach (@nodes) {
+
+ # Get os, arch, profile, and provmethod
+ $tab = xCAT::Table->new('nodetype');
+ $attrs =
+ $tab->getNodeAttribs( $_, [ 'os', 'arch', 'profile', 'provmethod' ] );
+
+ # If any attributes are missing, skip
+ if ( !$attrs->{'os'}
+ || !$attrs->{'arch'}
+ || !$attrs->{'profile'}
+ || !$attrs->{'provmethod'} ){
+ $callback->({ info => "$_: (Error) Missing attribute (os, arch, profile, or provmethod) in nodetype table" });
+ next;
+ }
+
+ # Get the right OS type
+ if ( $attrs->{'os'} =~ /fedora/ ) {
+ $osType = 'fedora';
+ } elsif ($attrs->{'os'} =~ /rh/
+ || $attrs->{'os'} =~ /rhel/
+ || $attrs->{'os'} =~ /rhels/ ) {
+ $osType = 'rh';
+ } elsif ( $attrs->{'os'} =~ /sles/ ) {
+ $osType = 'sles';
+ }
+
+ # Assume /install/post/otherpkgs/// directory is created
+ # If Ganglia RPMs (ganglia-gmond-*, libconfuse-*, and libganglia-*) are not in directory
+ $dir = "/install/post/otherpkgs/$attrs->{'os'}/$attrs->{'arch'}/";
+ if (!( `test -e $dir/ganglia-gmond-* && echo 'File exists'`
+ && `test -e $dir/libconfuse-* && echo 'File exists'`
+ && `test -e $dir/libganglia-* && echo 'File exists'`
+ )) {
+
+ # Skip
+ $callback->({ info => "$_: (Error) Missing Ganglia RPMs under $dir" });
+ next;
+ }
+
+ # Find pkglist directory
+ $dir = "/install/custom/$attrs->{'provmethod'}/$osType";
+ if ( !(`test -d $dir && echo 'Directory exists'`) ) {
+ # Create pkglist directory
+ `mkdir -p $dir`;
+ }
+
+ # Find pkglist file
+ # Ganglia RPM names should be added to /install/custom///...otherpkgs.pkglist
+ $pkglist = "$attrs->{'profile'}.$attrs->{'os'}.$attrs->{'arch'}.otherpkgs.pkglist";
+ if ( !(`test -e $dir/$pkglist && echo 'File exists'`) ) {
+
+ # Copy default otherpkgs.pkglist
+ $defaultDir = "/opt/xcat/share/xcat/$attrs->{'provmethod'}/$osType";
+ if (`test -e $defaultDir/$pkglist && echo 'File exists'`) {
+
+ # Copy default pkglist
+ `cp $defaultDir/$pkglist $dir/$pkglist`;
+ } else {
+
+ # Create pkglist
+ `touch $dir/$pkglist`;
+ }
+
+ # Add Ganglia RPMs to pkglist
+ `echo ganglia-gmond >> $dir/$pkglist`;
+ `echo libconfuse >> $dir/$pkglist`;
+ `echo libganglia >> $dir/$pkglist`;
+ }
+
+ # Check if libapr1 is installed
+ $info = `xdsh $_ "rpm -qa libapr1"`;
+ if ( !( $info =~ /libapr1/ ) ) {
+ $callback->(
+ { info => "$_: (Error) libapr1 package not installed" } );
+ next;
+ }
+
+ # Install Ganglia RPMs using updatenode
+ $callback->( { info => "$_: Installing Ganglia..." } );
+ $info = `/opt/xcat/bin/updatenode $_ -S`;
+ $callback->( { info => "$info" } );
+ }
+
+ return;
+}
+
+sub web_gangliaShow {
+ # Get ganglia data from RRD file
+
+ my ( $request, $callback, $sub_req ) = @_;
+ my $nodename = $request->{arg}->[1];
+ my $timeRange = 'now-1h';
+ my $resolution = 60;
+ my $metric = $request->{arg}->[3];
+ my @nodes = ();
+ my $retStr = '';
+ my $runInfo;
+ my $cmd = '';
+ my $dirname = '/var/lib/ganglia/rrds/__SummaryInfo__/';
+
+ # Get the summary for this grid (the meaning of grid is referenced from Ganglia)
+ if ( '_grid_' ne $nodename ) {
+ $dirname = '/var/lib/ganglia/rrds/' . $nodename . '/';
+ }
+
+ if ( 'hour' eq $request->{arg}->[2] ) {
+ $timeRange = 'now-1h';
+ $resolution = 60;
+ } elsif ( 'day' eq $request->{arg}->[2] ) {
+ $timeRange = 'now-1d';
+ $resolution = 1800;
+ }
+
+ if ( '_summary_' eq $metric ) {
+ my @metricArray = (
+ 'load_one', 'cpu_num', 'cpu_idle', 'mem_free',
+ 'mem_total', 'disk_total', 'disk_free', 'bytes_in',
+ 'bytes_out'
+ );
+
+ my $filename = '';
+ my $step = 1;
+ my $index = 0;
+ my $size = 0;
+ foreach my $tempmetric (@metricArray) {
+ my $temp = '';
+ my $line = '';
+ $retStr .= $tempmetric . ':';
+ $filename = $dirname . $tempmetric . '.rrd';
+ $cmd = "rrdtool fetch $filename -s $timeRange -r $resolution AVERAGE";
+ $runInfo = xCAT::Utils->runcmd( $cmd, -1, 1 );
+ if ( scalar(@$runInfo) < 3 ) {
+ $callback->( { data => 'error.' } );
+ return;
+ }
+
+ # Delete the first 2 lines
+ shift(@$runInfo);
+ shift(@$runInfo);
+
+ # We only support 60 lines for one metric, in order to reduce the data load for web GUI
+ $size = scalar(@$runInfo);
+ if ( $size > 60 ) {
+ $step = int( $size / 60 ) + 1;
+ }
+
+ if ( ( $tempmetric eq 'cpu_idle' ) && ( '_grid_' eq $nodename ) ) {
+ my $cpuidle = 0;
+ my $cpunum = 0;
+ for ( $index = 0 ; $index < $size ; $index += $step ) {
+ if ( $runInfo->[$index] =~ /^(\S+): (\S+) (\S+)/ ) {
+ my $timestamp = $1;
+ my $value = $2;
+ my $valuenum = $3;
+ if (( lc($value) =~ /nanq/ ) || ( lc($value) =~ /nan/ )) {
+ # The rrdtool fetch last line is always NaN, so no need to add into the return string
+ if ( $index == ( $size - 1 ) ) {
+ next;
+ }
+
+ $temp .= $timestamp . ',0,';
+ } else {
+ $cpuidle = sprintf "%.2f", $value;
+ $cpunum = sprintf "%.2f", $valuenum;
+ $temp .= $timestamp . ',' . ( sprintf "%.2f", $cpuidle / $cpunum ) . ',';
+ }
+ }
+ }
+ } else {
+ for ( $index = 0 ; $index < $size ; $index += $step ) {
+ if ( $runInfo->[$index] =~ /^(\S+): (\S+).*/ ) {
+ my $timestamp = $1;
+ my $value = $2;
+ if (( lc($value) =~ /nanq/ ) || ( lc($value) =~ /nan/ )) {
+ # The rrdtool fetch last line is always NaN, so no need to add into the return string
+ if ( $index == ( $size - 1 ) ) {
+ next;
+ }
+
+ $temp .= $timestamp . ',0,';
+ } else {
+ $temp .= $timestamp . ',' . ( sprintf "%.2f", $2 ) . ',';
+ }
+ }
+ }
+ }
+
+ $retStr .= substr( $temp, 0, -1 ) . ';';
+ }
+
+ $retStr = substr( $retStr, 0, -1 );
+ $callback->( { data => $retStr } );
+ return;
+ }
+}
+
+my $ganglia_return_flag = 0;
+my %gangliaHash;
+my $gangliaclustername;
+my $ganglianodename;
+
+sub web_gangliaLatest {
+ # Use socket to connect ganglia port to get the latest value/status
+
+ my ( $request, $callback, $sub_req ) = @_;
+ my $type = $request->{arg}->[1];
+ my $groupname = '';
+ my $xmlparser;
+ my $telnetcmd = '';
+ my $connect;
+ my $xmloutput = '';
+ my $tmpFilename = '/tmp/gangliadata';
+
+ $ganglia_return_flag = 0;
+ $gangliaclustername = '';
+ $ganglianodename = '';
+ undef(%gangliaHash);
+
+ if ( $request->{arg}->[2] ) {
+ $groupname = $request->{arg}->[2];
+ }
+ if ( 'grid' eq $type ) {
+ $xmlparser = XML::Parser->new(
+ Handlers => {
+ Start => \&web_gangliaGridXmlStart,
+ End => \&web_gangliaXmlEnd
+ });
+ $telnetcmd = "/?filter=summary\n";
+ $tmpFilename = '/tmp/gangliagriddata';
+ } elsif ( 'node' eq $type ) {
+ $xmlparser = XML::Parser->new(
+ Handlers => {
+ Start => \&web_gangliaNodeXmlStart,
+ End => \&web_gangliaXmlEnd
+ });
+ $telnetcmd = "/\n";
+ $tmpFilename = '/tmp/ganglianodedata';
+ }
+
+ # Use socket to telnet 127.0.0.1:8652 (Ganglia's interactive port)
+ $connect = IO::Socket::INET->new('127.0.0.1:8652');
+ unless ($connect) {
+ $callback->( { 'data' => 'error: connect local port failed.' } );
+ return;
+ }
+
+ print $connect $telnetcmd;
+ open( TEMPFILE, '>' . $tmpFilename );
+ while (<$connect>) {
+ print TEMPFILE $_;
+ }
+
+ close($connect);
+ close(TEMPFILE);
+
+ $xmlparser->parsefile($tmpFilename);
+
+ if ( 'grid' eq $type ) {
+ web_gangliaGridLatest($callback);
+ } elsif ( 'node' eq $type ) {
+ web_gangliaNodeLatest( $callback, $groupname );
+ }
+ return;
+}
+
+sub web_gangliaGridLatest {
+ # Create return data for grid current status
+
+ my $callback = shift;
+ my $retStr = '';
+ my $timestamp = time();
+ my $metricname = '';
+ my @metricArray = (
+ 'load_one', 'cpu_num', 'mem_total', 'mem_free',
+ 'disk_total', 'disk_free', 'bytes_in', 'bytes_out'
+ );
+
+ if ( $gangliaHash{'cpu_idle'} ) {
+ my $sum = $gangliaHash{'cpu_idle'}->{'SUM'};
+ my $num = $gangliaHash{'cpu_idle'}->{'NUM'};
+ $retStr .= 'cpu_idle:'
+ . $timestamp . ','
+ . ( sprintf( "%.2f", $sum / $num ) ) . ';';
+ }
+
+ foreach $metricname (@metricArray) {
+ if ( $gangliaHash{$metricname} ) {
+ $retStr .=
+ $metricname . ':'
+ . $timestamp . ','
+ . $gangliaHash{$metricname}->{'SUM'} . ';';
+ }
+ }
+
+ $retStr = substr( $retStr, 0, -1 );
+ $callback->( { data => $retStr } );
+}
+
+sub web_gangliaNodeLatest {
+ # Create return data for node current status
+
+ my ( $callback, $groupname ) = @_;
+ my $node = '';
+ my $retStr = '';
+ my $timestamp = time() - 180;
+ my @nodes;
+
+ # Get all nodes by group
+ if ($groupname) {
+ @nodes = xCAT::NodeRange::noderange( $groupname, 1 );
+ } else {
+ @nodes = xCAT::DBobjUtils->getObjectsOfType('node');
+ }
+
+ foreach $node (@nodes) {
+ # If the node has Ganglia
+ if ( $gangliaHash{$node} ) {
+ my $lastupdate = $gangliaHash{$node}->{'timestamp'};
+
+ # Cannot get monitor data for too long
+ if ( $lastupdate < $timestamp ) {
+ $retStr .= $node . ':ERROR,Can not get monitor data more than 3 minutes!;';
+ next;
+ }
+
+ if ( $gangliaHash{$node}->{'load_one'} >
+ $gangliaHash{$node}->{'cpu_num'} ) {
+ $retStr .= $node . ':WARNING,';
+ } else {
+ $retStr .= $node . ':NORMAL,';
+ }
+
+ $retStr .= $gangliaHash{$node}->{'path'} . ';';
+ } else {
+ $retStr .= $node . ':UNKNOWN,;';
+ }
+ }
+
+ $retStr = substr( $retStr, 0, -1 );
+ $callback->( { data => $retStr } );
+}
+
+sub web_gangliaXmlEnd {
+ # XML parser end function, do noting here
+}
+
+sub web_gangliaGridXmlStart {
+ # XML parser start function
+
+ my ( $parseinst, $elementname, %attrs ) = @_;
+ my $metricname = '';
+
+ # Only parse grid information
+ if ($ganglia_return_flag) {
+ return;
+ }
+
+ if ( 'METRICS' eq $elementname ) {
+ $metricname = $attrs{'NAME'};
+ $gangliaHash{$metricname}->{'SUM'} = $attrs{'SUM'};
+ $gangliaHash{$metricname}->{'NUM'} = $attrs{'NUM'};
+ } elsif ( 'CLUSTER' eq $elementname ) {
+ $ganglia_return_flag = 1;
+ return;
+ } else {
+ return;
+ }
+}
+
+sub web_gangliaNodeXmlStart {
+ # XML parser start function for node current status
+
+ my ( $parseinst, $elementname, %attrs ) = @_;
+ my $metricname = '';
+
+ # Save cluster name
+ if ( 'CLUSTER' eq $elementname ) {
+ $gangliaclustername = $attrs{'NAME'};
+ return;
+ } elsif ( 'HOST' eq $elementname ) {
+ if ( $attrs{'NAME'} =~ /(\S+?)\.(.*)/ ) {
+ $ganglianodename = $1;
+ } else {
+ $ganglianodename = $attrs{'NAME'};
+ }
+
+ $gangliaHash{$ganglianodename}->{'path'} =
+ $gangliaclustername . '/' . $attrs{'NAME'};
+ $gangliaHash{$ganglianodename}->{'timestamp'} = $attrs{'REPORTED'};
+ } elsif ( 'METRIC' eq $elementname ) {
+ $metricname = $attrs{'NAME'};
+ if ( ( 'load_one' eq $metricname ) || ( 'cpu_num' eq $metricname ) ) {
+ $gangliaHash{$ganglianodename}->{$metricname} = $attrs{'VAL'};
+ }
+ }
+}
+
+sub web_rmcmonStart {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $nodeRange = $request->{arg}->[1];
+ my $table;
+ my $retData = "";
+ my $output;
+
+ # Check running status
+ $table = xCAT::Table->new('monitoring');
+ my $rmcWorkingStatus = $table->getAttribs( { name => 'rmcmon' }, 'disable' );
+ $table . close();
+
+ # RMC monitoring is running so return
+ if ($rmcWorkingStatus) {
+ if ( $rmcWorkingStatus->{disable} =~ /0|No|no|NO|N|n/ ) {
+ $callback->( { info => 'RMC Monitoring is running now.' } );
+ return;
+ }
+ }
+
+ $retData .= "RMC is not running, start it now.\n";
+
+ # Check monsetting table to see if rmc's montype contains performance
+ $table = xCAT::Table->new('monsetting');
+ my $rmcmonType =
+ $table->getAttribs( { name => 'rmcmon', key => 'montype' }, 'value' );
+ $table . close();
+
+ # RMC monitoring is not configured right, we should configure it again
+ # There is no rmcmon in monsetting table
+ if ( !$rmcmonType ) {
+ $output = xCAT::Utils->runcmd( 'monadd rmcmon -s [montype=perf]', -1, 1 );
+ foreach (@$output) {
+ $retData .= ( $_ . "\n" );
+ }
+
+ $retData .= "Adding rmcmon to the monsetting table complete.\n";
+ }
+
+ # Configure before but there is no performance monitoring, so change the table
+ else {
+ if ( !( $rmcmonType->{value} =~ /perf/ ) ) {
+ $output = xCAT::Utils->runcmd('chtab name=rmcmon,key=montype monsetting.value=perf', -1, 1 );
+ foreach (@$output) {
+ $retData .= ( $_ . "\n" );
+ }
+
+ $retData .= "Change the rmcmon configure in monsetting table finish.\n";
+ }
+ }
+
+ # Run the rmccfg command to add all nodes into local RMC configuration
+ $output = xCAT::Utils->runcmd("moncfg rmcmon $nodeRange", -1, 1);
+ foreach (@$output) {
+ $retData .= ( $_ . "\n" );
+ }
+
+ # Run the rmccfg command to add all nodes into remote RMC configuration
+ $output = xCAT::Utils->runcmd( "moncfg rmcmon $nodeRange -r", -1, 1 );
+ foreach (@$output) {
+ $retData .= ( $_ . "\n" );
+ }
+
+ # Start the RMC monitor
+ $output = xCAT::Utils->runcmd( "monstart rmcmon", -1, 1 );
+ foreach (@$output) {
+ $retData .= ( $_ . "\n" );
+ }
+
+ $callback->( { info => $retData } );
+ return;
+}
+
+sub web_rmcmonShow() {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $nodeRange = $request->{arg}->[1];
+ my $attr = $request->{arg}->[2];
+ my @nodes;
+ my $retInfo;
+ my $retHash = {};
+ my $output;
+ my $temp = "";
+
+ # Only get the system RMC info
+ if ( 'summary' eq $nodeRange ) {
+ $output = xCAT::Utils->runcmd( "monshow rmcmon -s -t 60 -o p -a " . $attr, -1, 1 );
+ foreach $temp (@$output) {
+ # The attribute name
+ if ( $temp =~ /Pct/ ) {
+ $temp =~ s/ //g;
+
+ # The first one
+ if ( "" eq $retInfo ) {
+ $retInfo .= ( $temp . ':' );
+ } else {
+ $retInfo =~ s/,$/;/;
+ $retInfo .= ( $temp . ':' );
+ }
+
+ next;
+ }
+
+ # The content of the attribute
+ $temp =~ m/\s+(\d+\.\d{4})/;
+ if ( defined($1) ) {
+ $retInfo .= ( $1 . ',' );
+ }
+ }
+
+ # Return the RMC info
+ $retInfo =~ s/,$//;
+ $callback->( { info => $retInfo } );
+ return;
+ }
+
+ if ('compute' eq $nodeRange) {
+ my $node;
+
+ @nodes = xCAT::NodeRange::noderange($nodeRange);
+ for $node (@nodes) {
+ if ( -e "/var/rrd/$node" ) {
+ push( @{ $retHash->{node} }, { name => $node, data => 'OK' } );
+ } else {
+ push( @{ $retHash->{node} }, { name => $node, data => 'UNKNOWN' } );
+ }
+ }
+
+ $callback->($retHash);
+ return;
+ }
+
+ my $attrName = "";
+ my @attrs = split( /,/, $attr );
+ for $attrName (@attrs) {
+ my @attrValue = ();
+ $output = xCAT::Utils->runcmd( "rrdtool fetch /var/rrd/${nodeRange}/${attrName}.rrd -r 60 -s e-1h AVERAGE", -1, 1 );
+ foreach (@$output) {
+ $temp = $_;
+ if ( $temp eq '' ) {
+ next;
+ }
+
+ if ( lc($temp) =~ /[nanq|nan]/ ) {
+ next;
+ }
+
+ if ( $temp =~ /^(\d+): (\S+) (\S+)/ ) {
+ push( @attrValue, ( sprintf "%.2f", $2 ) );
+ }
+ }
+
+ if ( scalar(@attrValue) > 1 ) {
+ push( @{ $retHash->{node} }, { name => $attrName, data => join( ',', @attrValue ) } );
+ } else {
+ $retHash->{node} = { name => $attrName, data => '' };
+ last;
+ }
+ }
+
+ $callback->($retHash);
+}
+
+sub web_monls() {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $retInfo = xCAT::Utils->runcmd( "monls", -1, 1 );
+ my $ret = '';
+ foreach my $line (@$retInfo) {
+ my @temp = split( /\s+/, $line );
+ $ret .= @temp[0];
+ if ( 'not-monitored' eq @temp[1] ) {
+ $ret .= ':Off;';
+ } else {
+ $ret .= ':On;';
+ }
+ }
+
+ if ( '' eq $ret ) {
+ return;
+ }
+
+ $ret = substr( $ret, 0, length($ret) - 1 );
+ $callback->( { data => $ret } );
+}
+
+sub web_dynamiciprange {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $iprange = $request->{arg}->[1];
+
+ open( TEMPFILE, '>/tmp/iprange.conf' );
+ print TEMPFILE "xcat-service-lan:\n";
+ print TEMPFILE "dhcp-dynamic-range = " . $iprange . "\n";
+ close(TEMPFILE);
+
+ # Run xcatsetup command to change the dynamic IP range
+ xCAT::Utils->runcmd( "xcatsetup /tmp/iprange.conf", -1, 1 );
+ unlink('/tmp/iprange.conf');
+ xCAT::Utils->runcmd( "makedhcp -n", -1, 1 );
+
+ # Restart the DHCP server
+ if ( xCAT::Utils->isLinux() ) {
+ # xCAT::Utils->runcmd("service dhcpd restart", -1, 1);
+ } else {
+ # xCAT::Utils->runcmd("startsrc -s dhcpsd", -1, 1);
+ }
+}
+
+sub web_discover {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $type = uc( $request->{arg}->[1] );
+
+ my $retStr = '';
+ my $retInfo = xCAT::Utils->runcmd( "lsslp -m -s $type 2>/dev/null | grep -i $type | awk '{print \$1\":\" \$2\"-\"\$3}'", -1, 1 );
+ if ( scalar(@$retInfo) < 1 ) {
+ $retStr = 'Error: Can not discover frames in cluster!';
+ } else {
+ foreach my $line (@$retInfo) {
+ $retStr .= $line . ';';
+ }
+
+ $retStr = substr( $retStr, 0, -1 );
+ }
+
+ $callback->( { data => $retStr } );
+}
+
+sub web_updatevpd {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $harwareMtmsPair = $request->{arg}->[1];
+ my @hardware = split( /:/, $harwareMtmsPair );
+
+ my $vpdtab = xCAT::Table->new('vpd');
+ unless ($vpdtab) {
+ return;
+ }
+
+ foreach my $hard (@hardware) {
+ # The sequence must be object name, mtm, serial
+ my @temp = split( /,/, $hard );
+ $vpdtab->setAttribs( { 'node' => @temp[0] }, { 'serial' => @temp[2], 'mtm' => @temp[1] } );
+ }
+
+ $vpdtab->close();
+}
+
+sub web_writeconfigfile {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $filename = $request->{arg}->[1];
+ my $content = $request->{arg}->[2];
+
+ open( TEMPFILE, '>' . $filename );
+ print TEMPFILE $content;
+
+ close(TEMPFILE);
+ return;
+}
+
+sub web_createimage {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $ostype = $request->{arg}->[1];
+ my $osarch = lc( $request->{arg}->[2] );
+ my $profile = $request->{arg}->[3];
+ my $bootif = $request->{arg}->[4];
+ my $imagetype = lc( $request->{arg}->[5] );
+ my @softArray;
+ my $netdriver = '';
+ my $installdir = xCAT::TableUtils->getInstallDir();
+ my $tempos = $ostype;
+ $tempos =~ s/[0-9\.]//g;
+ my $CONFILE;
+ my $archFlag = 0;
+ my $ret = '';
+ my $cmdPath = '';
+
+ if ( $request->{arg}->[6] ) {
+ @softArray = split( ',', $request->{arg}->[6] );
+
+ # Check the custom package, if the directory does not exist, create the directory first
+ if ( -e "$installdir/custom/netboot/$ostype/" ) {
+ # The path exist, so archive all file under this path
+ opendir( TEMPDIR, "$installdir/custom/netboot/$ostype/" );
+ my @fileArray = readdir(TEMPDIR);
+ closedir(TEMPDIR);
+ if ( 2 < scalar(@fileArray) ) {
+ $archFlag = 1;
+ unless ( -e "/tmp/webImageArch/" ) {
+ system("mkdir -p /tmp/webImageArch/");
+ }
+
+ system("mv $installdir/custom/netboot/$ostype/*.* /tmp/webImageArch/");
+ } else {
+ $archFlag = 0;
+ }
+ } else {
+ # No need to archive
+ $archFlag = 0;
+ system("mkdir -p $installdir/custom/netboot/$ostype/");
+ }
+
+ # Write pkglist
+ open( $CONFILE, ">$installdir/custom/netboot/$ostype/$profile.pkglist" );
+ print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/IBMhpc.$ostype.ppc64.pkglist# \n";
+ close($CONFILE);
+
+ # Write otherpkglist
+ open( $CONFILE, ">$installdir/custom/netboot/$ostype/$profile.otherpkgs.pkglist" );
+ print $CONFILE "\n";
+ close($CONFILE);
+
+ # Write exlist for stateless
+ open( $CONFILE, ">$installdir/custom/netboot/$ostype/$profile.exlist" );
+ print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/IBMhpc.$ostype.$osarch.exlist#\n";
+ close($CONFILE);
+
+ # Write postinstall
+ open( $CONFILE, ">$installdir/custom/netboot/$ostype/$profile.postinstall" );
+ print $CONFILE "/opt/xcat/share/xcat/IBMhpc/IBMhpc.$tempos.postinstall \$1 \$2 \$3 \$4 \$5 \n";
+ close($CONFILE);
+
+ for my $soft (@softArray) {
+ $soft = lc($soft);
+ if ( 'gpfs' eq $soft ) {
+ web_gpfsConfigure( $ostype, $profile, $osarch, $installdir );
+ } elsif ( 'rsct' eq $soft ) {
+ web_rsctConfigure( $ostype, $profile, $osarch, $installdir );
+ } elsif ( 'pe' eq $soft ) {
+ web_peConfigure( $ostype, $profile, $osarch, $installdir );
+ } elsif ( 'essl' eq $soft ) {
+ web_esslConfigure( $ostype, $profile, $osarch, $installdir );
+ } elsif ( 'ganglia' eq $soft ) {
+ web_gangliaConfig( $ostype, $profile, $osarch, 'netboot', $installdir );
+ }
+ }
+
+ system("chmod 755 $installdir/custom/netboot/$ostype/*.*");
+ }
+
+ if ( $bootif =~ /hf/i ) {
+ $netdriver = 'hf_if';
+ } else {
+ $netdriver = 'ibmveth';
+ }
+
+ if ( $tempos =~ /rh/i ) {
+ $cmdPath = "/opt/xcat/share/xcat/netboot/rh";
+ } else {
+ $cmdPath = "/opt/xcat/share/xcat/netboot/sles";
+ }
+
+ # For stateless only run packimage
+ if ( 'stateless' eq $imagetype ) {
+ my $retInfo = xCAT::Utils->runcmd( "${cmdPath}/genimage -i $bootif -n $netdriver -o $ostype -p $profile", -1, 1 );
+ $ret = join( "\n", @$retInfo );
+
+ if ($::RUNCMD_RC) {
+ web_restoreChange( $request->{arg}->[6], $archFlag, $imagetype, $ostype, $installdir );
+ $callback->( { data => $ret } );
+ return;
+ }
+
+ $ret .= "\n";
+ my $retInfo = xCAT::Utils->runcmd( "packimage -o $ostype -p $profile -a $osarch", -1, 1 );
+ $ret .= join( "\n", @$retInfo );
+ } else {
+ # For statelist we should check the litefile table
+ # Step 1: Save the old litefile table content into litefilearchive.csv
+ system('tabdump litefile > /tmp/litefilearchive.csv');
+
+ # Step 2: Write the new litefile.csv for this lite image
+ open( $CONFILE, ">/tmp/litefile.csv" );
+ print $CONFILE "#image,file,options,comments,disable\n";
+ print $CONFILE '"ALL","/etc/lvm/","tmpfs",,' . "\n";
+ print $CONFILE '"ALL","/etc/ntp.conf","tmpfs",,' . "\n";
+ print $CONFILE '"ALL","/etc/resolv.conf","tmpfs",,' . "\n";
+ print $CONFILE '"ALL","/etc/sysconfig/","tmpfs",,' . "\n";
+ print $CONFILE '"ALL","/etc/yp.conf","tmpfs",,' . "\n";
+ print $CONFILE '"ALL","/etc/ssh/","tmpfs",,' . "\n";
+ print $CONFILE '"ALL","/var/","tmpfs",,' . "\n";
+ print $CONFILE '"ALL","/tmp/","tmpfs",,' . "\n";
+ print $CONFILE '"ALL","/root/.ssh/","tmpfs",,' . "\n";
+ print $CONFILE '"ALL","/opt/xcat/","tmpfs",,' . "\n";
+ print $CONFILE '"ALL","/xcatpost/","tmpfs",,' . "\n";
+
+ if ( 'rhels' eq $tempos ) {
+ print $CONFILE '"ALL","/etc/adjtime","tmpfs",,' . "\n";
+ print $CONFILE '"ALL","/etc/securetty","tmpfs",,' . "\n";
+ print $CONFILE '"ALL","/etc/rsyslog.conf","tmpfs",,' . "\n";
+ print $CONFILE '"ALL","/etc/rsyslog.conf.XCATORIG","tmpfs",,'
+ . "\n";
+ print $CONFILE '"ALL","/etc/udev/","tmpfs",,' . "\n";
+ print $CONFILE '"ALL","/etc/ntp.conf.predhclient","tmpfs",,' . "\n";
+ print $CONFILE '"ALL","/etc/resolv.conf.predhclient","tmpfs",,'
+ . "\n";
+ } else {
+ print $CONFILE '"ALL","/etc/ntp.conf.org","tmpfs",,' . "\n";
+ print $CONFILE '"ALL","/etc/syslog-ng/","tmpfs",,' . "\n";
+ print $CONFILE '"ALL","/etc/fstab","tmpfs",,' . "\n";
+ }
+ close($CONFILE);
+
+ # Write the HPC software litefile into temp litefile.csv
+ for my $soft (@softArray) {
+ $soft = lc($soft);
+ if ( -e "/opt/xcat/share/xcat/IBMhpc/$soft/litefile.csv" ) {
+ system("grep '^[^#]' /opt/xcat/share/xcat/IBMhpc/$soft/litefile.csv >> /tmp/litefile.csv");
+ }
+ }
+
+ system("tabrestore /tmp/litefile.csv");
+
+ # Create the image
+ my $retInfo = xCAT::Utils->runcmd("${cmdPath}/genimage -i $bootif -n $netdriver -o $ostype -p $profile", -1, 1);
+ $ret = join( "\n", @$retInfo );
+ if ($::RUNCMD_RC) {
+ web_restoreChange( $request->{arg}->[6], $archFlag, $imagetype, $ostype, $installdir );
+ $callback->( { data => $ret } );
+ return;
+ }
+
+ $ret .= "\n";
+ my $retInfo = xCAT::Utils->runcmd( "liteimg -o $ostype -p $profile -a $osarch", -1, 1 );
+ $ret .= join( "\n", @$retInfo );
+ }
+
+ web_restoreChange( $request->{arg}->[6], $archFlag, $imagetype, $ostype, $installdir );
+ $callback->( { data => $ret } );
+ return;
+}
+
+sub web_gpfsConfigure {
+ my ( $ostype, $profile, $osarch, $installdir ) = @_;
+ my $CONFILE;
+
+ system("createrepo $installdir/post/otherpkgs/$ostype/$osarch/gpfs");
+
+ open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.otherpkgs.pkglist" );
+ print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/gpfs/gpfs.otherpkgs.pkglist#\n";
+ close($CONFILE);
+
+ open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.exlist" );
+ print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/gpfs/gpfs.exlist#\n";
+ close($CONFILE);
+
+ system('cp /opt/xcat/share/xcat/IBMhpc/gpfs/gpfs_mmsdrfs $installdir/postscripts/gpfs_mmsdrfs');
+ open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.postinstall" );
+ print $CONFILE "NODESETSTATE=genimage installroot=\$1 /opt/xcat/share/xcat/IBMhpc/gpfs/gpfs_updates\n";
+ print $CONFILE "installroot=\$1 $installdir/postscripts/gpfs_mmsdrfs\n";
+ close($CONFILE);
+}
+
+sub web_rsctConfigure {
+ my ( $ostype, $profile, $osarch, $installdir ) = @_;
+ my $CONFILE;
+
+ system("createrepo $installdir/post/otherpkgs/$ostype/$osarch/rsct");
+
+ if ( $ostype =~ /sles/i ) {
+ open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.pkglist" );
+ print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/rsct/rsct.pkglist# \n";
+ close($CONFILE);
+ }
+
+ open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.exlist" );
+ print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/rsct/rsct.exlist#\n";
+ close($CONFILE);
+
+ open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.postinstall" );
+ print $CONFILE "installroot=\$1 rsctdir=$installdir/post/otherpkgs/rhels6/ppc64/rsct NODESETSTATE=genimage /opt/xcat/share/xcat/IBMhpc/rsct/rsct_install\n";
+ close($CONFILE);
+}
+
+sub web_peConfigure {
+ my ( $ostype, $profile, $osarch, $installdir ) = @_;
+ my $CONFILE;
+
+ system("createrepo $installdir/post/otherpkgs/$ostype/$osarch/pe");
+ system("createrepo $installdir/post/otherpkgs/$ostype/$osarch/compilers");
+
+ open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.pkglist" );
+ if ( $ostype =~ /rh/i ) {
+ print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/pe/pe.$ostype.pkglist#\n";
+ } else {
+ print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/compilers/compilers.pkglist#\n";
+ print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/pe/pe.pkglist#\n";
+ }
+
+ close($CONFILE);
+
+ open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.otherpkgs.pkglist" );
+ print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/pe/pe.otherpkgs.pkglist#\n";
+ close($CONFILE);
+
+ open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.exlist" );
+ print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/compilers/compilers.exlist#\n";
+ print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/pe/pe.exlist#\n";
+ close($CONFILE);
+
+ open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.postinstall" );
+ print $CONFILE "installroot=\$1 NODESETSTATE=genimage /opt/xcat/share/xcat/IBMhpc/compilers/compilers_license";
+ print $CONFILE "installroot=\$1 pedir=$installdir/post/otherpkgs/rhels6/ppc64/pe NODESETSTATE=genimage /opt/xcat/share/xcat/IBMhpc/pe/pe_install";
+ close($CONFILE);
+}
+
+sub web_esslConfigure {
+ my ( $ostype, $profile, $osarch, $installdir ) = @_;
+ my $CONFILE;
+
+ system("createrepo $installdir/post/otherpkgs/$ostype/$osarch/essl");
+
+ open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.pkglist" );
+ if ( $ostype =~ /rh/i ) {
+ print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/compilers/compilers.rhels6.pkglist#\n";
+ } else {
+ print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/essl/essl.pkglist#\n";
+ }
+
+ open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.otherpkgs.pkglist" );
+ print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/essl/essl.otherpkgs.pkglist#\n";
+ close($CONFILE);
+
+ open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.exlist" );
+ print $CONFILE "#INCLUDE:/opt/xcat/share/xcat/IBMhpc/essl/essl.exlist#\n";
+ close($CONFILE);
+
+ open( $CONFILE, ">>$installdir/custom/netboot/$ostype/$profile.postinstall" );
+ print $CONFILE, "installroot=\$1 essldir=$installdir/post/otherpkgs/rhels6/ppc64/essl NODESETSTATE=genimage /opt/xcat/share/xcat/IBMhpc/essl/essl_install";
+ close($CONFILE);
+}
+
+sub web_gangliaConfig {
+ my ( $ostype, $profile, $osarch, $provtype, $installdir ) = @_;
+ my $CONFILE;
+
+ system("createrepo $installdir/post/otherpkgs/$ostype/$osarch/ganglia");
+
+ open( $CONFILE, ">>$installdir/custom/$provtype/$ostype/$profile.otherpkgs.pkglist" );
+ print $CONFILE "#created by xCAT Web Gui.\n";
+ print $CONFILE "ganglia/ganglia\n";
+ print $CONFILE "ganglia/ganglia-gmond\n";
+ print $CONFILE "ganglia/ganglia-gmetad\n";
+ print $CONFILE "ganglia/rrdtool\n";
+ close($CONFILE);
+}
+
+sub web_gangliaRpmCheck {
+ my ( $ostype, $profile, $osarch, $installdir ) = @_;
+ my @rpmnames = ( "rrdtool", "ganglia", "ganglia-gmond", "ganglia-gmetad" );
+ my %temphash;
+ my $rpmdir = "$installdir/post/otherpkgs/$ostype/$osarch/ganglia";
+ my $errorstr = '';
+ unless ( -e $rpmdir ) {
+ return "Put rrdtool,ganglia,ganglia-gmond,ganglia-gmetad rpms into $rpmdir.";
+ }
+
+ opendir( DIRHANDLE, $rpmdir );
+ foreach my $filename ( readdir(DIRHANDLE) ) {
+ if ( $filename =~ /(\D+)-(\d+)\..*\.rpm$/ ) {
+ $temphash{$1} = 1;
+ }
+ }
+ closedir(DIRHANDLE);
+
+ # Check if all RPMs are in the array
+ foreach (@rpmnames) {
+ unless ( $temphash{$_} ) {
+ $errorstr .= $_ . ',';
+ }
+ }
+
+ if ($errorstr) {
+ $errorstr = substr( $errorstr, 0, -1 );
+ return "Put $errorstr rpms into $rpmdir.";
+ } else {
+ return "";
+ }
+}
+
+sub web_restoreChange {
+ my ( $software, $archFlag, $imagetype, $ostype, $installdir ) = @_;
+
+ # Recover all file in the $installdir/custom/netboot/$ostype/
+ if ($software) {
+ system("rm -f $installdir/custom/netboot/$ostype/*.*");
+ }
+
+ if ($archFlag) {
+ system("mv /tmp/webImageArch/*.* $installdir/custom/netboot/$ostype/");
+ }
+
+ # Recover the litefile table for statelite image
+ if ( 'statelite' == $imagetype ) {
+ system("rm -r /tmp/litefile.csv ; mv /tmp/litefilearchive.csv /tmp/litefile.csv ; tabrestore /tmp/litefile.csv");
+ }
+}
+
+sub web_provision_preinstall {
+ my ( $ostype, $profile, $arch, $installdir, $softwarenames ) = @_;
+ my $checkresult = '';
+ my $errorstr = '';
+ my @software = split( ',', $softwarenames );
+ my $softwarenum = scalar(@software);
+
+ if ( -e "$installdir/custom/install/$ostype/" ) {
+ opendir( DIRHANDLE, "$installdir/custom/install/$ostype/" );
+ foreach my $filename ( readdir(DIRHANDLE) ) {
+ if ( '.' eq $filename || '..' eq $filename ) {
+ next;
+ }
+
+ $filename = "$installdir/custom/install/$ostype/" . $filename;
+ if ( $filename =~ /(.*)\.guibak$/ ) {
+ if ( $softwarenum < 1 ) {
+ system("mv $filename $1");
+ }
+ next;
+ }
+
+ `/bin/grep 'xCAT Web Gui' $filename`;
+ if ($?) {
+ # Backup the original config file
+ if ( $softwarenum > 0 ) {
+ system("mv $filename ${filename}.guibak");
+ }
+ } else {
+ unlink($filename);
+ }
+ }
+
+ closedir(DIRHANDLE);
+ } else {
+ `mkdir -p $installdir/custom/install/$ostype -m 0755`;
+ }
+
+ if ( $softwarenum < 1 ) {
+ return '';
+ }
+
+ foreach (@software) {
+ if ( 'ganglia' eq $_ ) {
+ $checkresult = web_gangliaRpmCheck( $ostype, $profile, $arch, $installdir );
+ }
+
+ if ($checkresult) {
+ $errorstr .= $checkresult . "\n";
+ }
+ }
+
+ if ($errorstr) {
+ return $errorstr;
+ }
+
+ foreach (@software) {
+ if ( 'ganglia' eq $_ ) {
+ web_gangliaConfig( $ostype, $profile, $arch, 'install', $installdir );
+ }
+ }
+ return '';
+}
+
+sub web_provision {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $nodes = $request->{arg}->[1];
+ my $imageName = $request->{arg}->[2];
+ my ( $arch, $inic, $pnic, $master, $tftp, $nfs ) = split( /,/, $request->{arg}->[3] );
+ my $line = '';
+ my %imageattr;
+ my $retinfo = xCAT::Utils->runcmd( "lsdef -t osimage -l $imageName", -1, 1 );
+ my $installdir = xCAT::TableUtils->getInstallDir();
+
+ # Parse output, get the OS name and type
+ foreach $line (@$retinfo) {
+ if ( $line =~ /(\w+)=(\S*)/ ) {
+ $imageattr{$1} = $2;
+ }
+ }
+
+ # Check the output
+ unless ( $imageattr{'osname'} ) {
+ web_infomsg( "Image infomation error. Check the image first.\nprovision stop.", $callback );
+ return;
+ }
+
+ if ( 'install' eq $imageattr{'provmethod'} ) {
+ my $prepareinfo = web_provision_preinstall( $imageattr{'osvers'}, $imageattr{'profile'}, $arch, $installdir, $request->{arg}->[4] );
+ if ($prepareinfo) {
+ web_infomsg( "$prepareinfo \nprovision stop.", $callback );
+ return;
+ }
+ }
+
+ if ( $imageattr{'osname'} =~ /aix/i ) {
+ web_provisionaix( $nodes, $imageName, $imageattr{'nimtype'}, $inic, $pnic, $master, $tftp, $nfs, $callback );
+ } else {
+ web_provisionlinux(
+ $nodes, $arch,
+ $imageattr{'osvers'}, $imageattr{'provmethod'},
+ $imageattr{'profile'}, $inic,
+ $pnic, $master,
+ $tftp, $nfs,
+ $callback
+ );
+ }
+}
+
+sub web_provisionlinux {
+ my ($nodes, $arch, $os, $provmethod, $profile, $inic, $pnic, $master, $tftp, $nfs, $callback) = @_;
+ my $outputMessage = '';
+ my $retvalue = 0;
+ my $netboot = '';
+
+ if ( $arch =~ /ppc/i ) {
+ $netboot = 'yaboot';
+ } elsif ( $arch =~ /x.*86/i ) {
+ $netboot = 'xnba';
+ }
+
+ $outputMessage =
+ "Do provison : $nodes \n"
+ . " Arch:$arch\n OS:$os\n Provision:$provmethod\n Profile:$profile\n Install NIC:$inic\n Primary NIC:$pnic\n"
+ . " xCAT Master:$master\n TFTP Server:$tftp\n NFS Server:$nfs\n Netboot:$netboot\n";
+
+ web_infomsg( $outputMessage, $callback );
+
+ # Change the node attribute
+ my $cmd = "chdef -t node -o $nodes arch=$arch os=$os provmethod=$provmethod profile=$profile installnic=$inic tftpserver=$tftp nfsserver=$nfs netboot=$netboot" . " xcatmaster=$master primarynic=$pnic";
+ web_runcmd( $cmd, $callback );
+ if ($::RUNCMD_RC) {
+ web_infomsg( "Configure nodes' attributes error.\nProvision stop.", $callback );
+ return;
+ }
+
+ $cmd = "makedhcp $nodes";
+ web_runcmd( $cmd, $callback );
+ if ($::RUNCMD_RC) {
+ web_infomsg( "Make DHCP error.\nProvision stop.", $callback );
+ return;
+ }
+
+ # Restart DHCP
+ $cmd = "service dhcpd restart";
+ web_runcmd( $cmd, $callback );
+
+ # Conserver
+ $cmd = "makeconservercf $nodes";
+ web_runcmd( $cmd, $callback );
+ if ($::RUNCMD_RC) {
+ web_infomsg( "Configure conserver error.\nProvision stop.", $callback );
+ return;
+ }
+
+ # For system x, should configure boot sequence first
+ if ( $arch =~ /x.*86/i ) {
+ $cmd = "rbootseq $nodes net,hd";
+ web_runcmd( $cmd, $callback );
+ if ($::RUNCMD_RC) {
+ web_infomsg( "Set boot sequence error.\nProvision stop.",
+ $callback );
+ return;
+ }
+ }
+
+ # Nodeset
+ $cmd = "nodeset $nodes $provmethod";
+ web_runcmd( $cmd, $callback );
+ if ($::RUNCMD_RC) { web_infomsg( "Set nodes provision method error.\nprovision stop.", $callback );
+ return;
+ }
+
+ # Reboot the node fro provision
+ if ( $arch =~ /ppc/i ) {
+ $cmd = "rnetboot $nodes";
+ } else {
+ $cmd = "rpower $nodes boot";
+ }
+
+ web_runcmd( $cmd, $callback );
+ if ($::RUNCMD_RC) {
+ web_infomsg( "Boot nodes error.\nProvision stop.", $callback );
+ return;
+ }
+
+ # Provision complete
+ web_infomsg("Provision on $nodes success.\nProvision stop.");
+}
+
+sub web_provisionaix {
+ my (
+ $nodes, $imagename, $nimtype, $inic, $pnic,
+ $master, $tftp, $nfs, $callback
+ ) = @_;
+ my $outputMessage = '';
+ my $retinfo;
+ my %nimhash;
+ my $line;
+ my @updatenodes;
+ my @addnodes;
+ my $cmd = '';
+
+ # Set attributes
+ $cmd = "chdef -t node -o $nodes installnic=$inic tftpserver=$tftp nfsserver=$nfs xcatmaster=$master primarynic=$pnic";
+ web_runcmd( $cmd, $callback );
+ if ($::RUNCMD_RC) {
+ web_infomsg( "Change nodes' attributes error.\nprovision stop.", $callback );
+ return;
+ }
+
+ # Get all NIM resource to filter nodes
+ $retinfo = xCAT::Utils->runcmd( "lsnim -c machines", -1, 1 );
+ foreach $line (@$retinfo) {
+ if ( $line =~ /(\S+)\s+\S+/ ) {
+ $nimhash{$1} = 1;
+ }
+ }
+
+ foreach my $node ( split( /,/, $nodes ) ) {
+ if ( $nimhash{$node} ) {
+ push( @updatenodes, $node );
+ } else {
+ push( @addnodes, $node );
+ }
+ }
+
+ if ( 0 < scalar(@addnodes) ) {
+ $cmd = "xcat2nim -t node -o " . join( ",", @addnodes );
+ web_runcmd( $cmd, $callback );
+ if ($::RUNCMD_RC) {
+ web_infomsg( "xcat2nim command error.\nprovision stop.", $callback );
+ return;
+ }
+ }
+
+ if ( 0 < scalar(@updatenodes) ) {
+ $cmd = "xcat2nim -u -t node -o " . join( ",", @updatenodes );
+ web_runcmd( $cmd, $callback );
+ if ($::RUNCMD_RC) {
+ web_infomsg( "xcat2nim command error.\nprovision stop.", $callback );
+ return;
+ }
+ }
+
+ $cmd = "makeconservercf $nodes";
+ web_runcmd( $cmd, $callback );
+ if ($::RUNCMD_RC) {
+ web_infomsg( "Configure conserver error.\nprovision stop.", $callback );
+ return;
+ }
+
+ if ( $nimtype =~ /diskless/ ) {
+ $cmd = "mkdsklsnode -i $imagename $nodes";
+ } else {
+ $cmd = "nimnodeset -i $imagename $nodes";
+ }
+
+ web_runcmd( $cmd, $callback );
+ if ($::RUNCMD_RC) {
+ web_infomsg( "Set node install method error.\nprovision stop.", $callback );
+ return;
+ }
+
+ $cmd = "rnetboot $nodes";
+ web_runcmd( $cmd, $callback );
+ if ($::RUNCMD_RC) {
+ web_infomsg( "Reboot nodes error.\nprovision stop.", $callback );
+ return;
+ }
+
+ web_infomsg("Provision on $nodes success.\nprovision stop.");
+}
+
+sub web_runcmd {
+ my $cmd = shift;
+ my $callback = shift;
+ my $showstr = "\n" . $cmd . "\n";
+
+ web_infomsg( $showstr, $callback );
+
+ my $retvalue = xCAT::Utils->runcmd( $cmd, -1, 1 );
+ $showstr = join( "\n", @$retvalue );
+ $showstr .= "\n";
+
+ web_infomsg( $showstr, $callback );
+}
+
+sub web_infomsg {
+ my $msg = shift;
+ my $callback = shift;
+ my %rsp;
+
+ push @{ $rsp{info} }, $msg;
+ xCAT::MsgUtils->message( 'I', \%rsp, $callback );
+ return;
+}
+
+sub web_summary {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $groupName = $request->{arg}->[1];
+ my @nodes;
+ my $nodetypeTab;
+ my $nodelistTab;
+ my $attrs;
+ my %oshash;
+ my %archhash;
+ my %provhash;
+ my %typehash;
+ my %statushash;
+ my $retHash = {};
+ my $temp;
+
+ if ( defined($groupName) ) {
+ @nodes = xCAT::NodeRange::noderange($groupName);
+ } else {
+ @nodes = xCAT::DBobjUtils->getObjectsOfType('node');
+ }
+
+ $nodetypeTab = xCAT::Table->new('nodetype');
+ unless ($nodetypeTab) {
+ return;
+ }
+
+ $nodelistTab = xCAT::Table->new('nodelist');
+ unless ($nodelistTab) {
+ return;
+ }
+
+ $attrs = $nodetypeTab->getNodesAttribs( \@nodes, [ 'os', 'arch', 'provmethod', 'nodetype' ] );
+ unless ($attrs) {
+ return;
+ }
+
+ while ( my ( $key, $value ) = each( %{$attrs} ) ) {
+ web_attrcount( $value->[0]->{'os'}, \%oshash );
+ web_attrcount( $value->[0]->{'arch'}, \%archhash );
+ web_attrcount( $value->[0]->{'provmethod'},, \%provhash );
+ web_attrcount( $value->[0]->{'nodetype'},, \%typehash );
+ }
+
+ $attrs = $nodelistTab->getNodesAttribs( \@nodes, ['status'] );
+ while ( my ( $key, $value ) = each( %{$attrs} ) ) {
+ web_attrcount( $value->[0]->{'status'}, \%statushash );
+ }
+
+ # Status
+ $temp = '';
+ while ( my ( $key, $value ) = each(%statushash) ) {
+ $temp .= ( $key . ':' . $value . ';' );
+ }
+ $temp = substr( $temp, 0, -1 );
+ push( @{ $retHash->{'data'} }, 'Status=' . $temp );
+
+ # OS
+ $temp = '';
+ while ( my ( $key, $value ) = each(%oshash) ) {
+ $temp .= ( $key . ':' . $value . ';' );
+ }
+ $temp = substr( $temp, 0, -1 );
+ push( @{ $retHash->{'data'} }, 'Operating System=' . $temp );
+
+ # Architecture
+ $temp = '';
+ while ( my ( $key, $value ) = each(%archhash) ) {
+ $temp .= ( $key . ':' . $value . ';' );
+ }
+ $temp = substr( $temp, 0, -1 );
+ push( @{ $retHash->{'data'} }, 'Architecture=' . $temp );
+
+ # Provision method
+ $temp = '';
+ while ( my ( $key, $value ) = each(%provhash) ) {
+ $temp .= ( $key . ':' . $value . ';' );
+ }
+ $temp = substr( $temp, 0, -1 );
+ push( @{ $retHash->{'data'} }, 'Provision Method=' . $temp );
+
+ # Nodetype
+ $temp = '';
+ while ( my ( $key, $value ) = each(%typehash) ) {
+ $temp .= ( $key . ':' . $value . ';' );
+ }
+ $temp = substr( $temp, 0, -1 );
+ push( @{ $retHash->{'data'} }, 'Node Type=' . $temp );
+
+ # Return data
+ $callback->($retHash);
+}
+
+sub web_attrcount {
+ my ( $key, $container ) = @_;
+ unless ( defined($key) ) {
+ $key = 'unknown';
+ }
+
+ if ( $container->{$key} ) {
+ $container->{$key}++;
+ } else {
+ $container->{$key} = 1;
+ }
+}
+
+sub web_rinstall {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $os = $request->{arg}->[1];
+ my $profile = $request->{arg}->[2];
+ my $arch = $request->{arg}->[3];
+ my $node = $request->{arg}->[4];
+
+ # Begin installation
+ my $out = `rinstall -o $os -p $profile -a $arch $node`;
+
+ $callback->( { data => $out } );
+}
+
+sub web_addnode {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $nodetype = $request->{arg}->[1];
+ my @tempArray = split( ',', $request->{arg}->[2] );
+
+ my $hcpname = shift(@tempArray);
+ if ( 'node' ne $nodetype ) {
+ my $username = $tempArray[0];
+ my $passwd = $tempArray[1];
+ my $ip = $tempArray[2];
+ `/bin/grep '$hcpname' /etc/hosts`;
+ if ($?) {
+ open( OUTPUTFILE, '>>/etc/hosts' );
+ print OUTPUTFILE "$ip $hcpname\n";
+ close(OUTPUTFILE);
+ }
+
+ if ( 'hmc' eq $nodetype ) {
+ `/opt/xcat/bin/chdef -t node -o $hcpname username=$username password=$passwd mgt=hmc nodetype=$nodetype ip=$ip groups=all`;
+ } else {
+ `/opt/xcat/bin/chdef -t node -o $hcpname username=$username password=$passwd mgt=blade mpa=$hcpname nodetype=$nodetype id=0 groups=mm,all`;
+ }
+ return;
+ }
+
+ my %temphash;
+ my $writeflag = 0;
+ my $line = '';
+
+ # Save all nodes into a hash
+ foreach (@tempArray) {
+ $temphash{$_} = 1;
+ }
+
+ for ( my $i = 0 ; $i < scalar(@tempArray) ; $i = $i + 2 ) {
+ $temphash{ $tempArray[$i] } = $tempArray[ $i + 1 ];
+ }
+
+ `/opt/xcat/bin/rscan $hcpname -z > /tmp/rscanall.tmp`;
+
+ unless ( -e '/tmp/rscanall.tmp' ) {
+ return;
+ }
+
+ open( INPUTFILE, '/tmp/rscanall.tmp' );
+ open( OUTPUTFILE, '>/tmp/webrscan.tmp' );
+ while ( $line = ) {
+ if ( $line =~ /(\S+):$/ ) {
+ if ( $temphash{$1} ) {
+ $writeflag = 1;
+ print OUTPUTFILE $temphash{$1} . ":\n";
+ } else {
+ $writeflag = 0;
+ }
+ } else {
+ if ($writeflag) {
+ print OUTPUTFILE $line;
+ }
+ }
+ }
+
+ close(INPUTFILE);
+ close(OUTPUTFILE);
+ unlink('/tmp/rscanall.tmp');
+
+ `cat /tmp/webrscan.tmp | chdef -z`;
+ unlink('/tmp/webrscan.tmp');
+}
+
+sub web_graphinfo {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $nodetypeTab;
+ my @nodes;
+ my @parray;
+ my @bladearray;
+ my @xarray;
+ my %phash;
+ my %bladehash;
+ my %xhash;
+ my @unsupportarray;
+ my @missinfoarray;
+ my $result;
+ my $pretstr = '';
+ my $bladeretstr = '';
+ my $xretstr = '';
+ my $unsupretstr = '';
+ my $missretstr = '';
+
+ @nodes = xCAT::DBobjUtils->getObjectsOfType('node');
+
+ $nodetypeTab = xCAT::Table->new('nodetype');
+ unless ($nodetypeTab) {
+ return;
+ }
+
+ # Get all nodetype and seperate nodes into different group
+ $result = $nodetypeTab->getNodesAttribs( \@nodes, ['nodetype'] );
+ while ( my ( $key, $value ) = each(%$result) ) {
+ my $temptype = $value->[0]->{'nodetype'};
+ if ( $temptype =~ /(ppc|lpar|cec|frame)/i ) {
+ push( @parray, $key );
+ } elsif ( $temptype =~ /blade/i ) {
+ push( @bladearray, $key );
+ } elsif ( $temptype =~ /osi/i ) {
+ push( @xarray, $key );
+ } else {
+ push( @unsupportarray, $key );
+ }
+ }
+ $nodetypeTab->close();
+
+ # Get all information for System p node
+ if ( scalar(@parray) > 0 ) {
+ my $ppctab = xCAT::Table->new('ppc');
+
+ $result = $ppctab->getNodesAttribs( \@parray, ['parent'] );
+ my $typehash = xCAT::DBobjUtils->getnodetype( \@parray );
+ foreach (@parray) {
+ my $value = $result->{$_};
+ if ( $value->[0] ) {
+ $phash{$_} = $$typehash{$_} . ':' . $value->[0]->{'parent'} . ':';
+ } else {
+ $phash{$_} = $$typehash{$_} . '::';
+ }
+ }
+ $ppctab->close();
+
+ undef @parray;
+ @parray = keys %phash;
+ }
+ if ( scalar(@parray) > 0 ) {
+ # mtm
+ my $vpdtab = xCAT::Table->new('vpd');
+ $result = $vpdtab->getNodesAttribs( \@parray, ['mtm'] );
+ foreach (@parray) {
+ my $value = $result->{$_};
+ $phash{$_} = $phash{$_} . $value->[0]->{'mtm'} . ':';
+ }
+ $vpdtab->close();
+
+ # Status
+ my $nodelisttab = xCAT::Table->new('nodelist');
+ $result = $nodelisttab->getNodesAttribs( \@parray, ['status'] );
+ foreach (@parray) {
+ my $value = $result->{$_};
+ $phash{$_} = $phash{$_} . $value->[0]->{'status'};
+ }
+ $nodelisttab->close();
+
+ while ( my ( $key, $value ) = each(%phash) ) {
+ $pretstr = $pretstr . $key . ':' . $value . ';';
+ }
+ }
+
+ # Get all information for blade node
+ if ( scalar(@bladearray) > 0 ) {
+ my $mptab = xCAT::Table->new('mp');
+ $result = $mptab->getNodesAttribs( \@bladearray, [ 'mpa', 'id' ] );
+ foreach (@bladearray) {
+ my $value = $result->{$_};
+ if ( $value->[0]->{'mpa'} ) {
+ $bladehash{$_} = 'blade:' . $value->[0]->{'mpa'} . ':' . $value->[0]->{'id'} . ':';
+ } else {
+ push( @missinfoarray, $_ );
+ }
+ }
+
+ $mptab->close();
+
+ undef @bladearray;
+ @bladearray = keys %bladehash;
+ }
+
+ if ( scalar(@bladearray) > 0 ) {
+ # Status
+ my $nodelisttab = xCAT::Table->new('nodelist');
+ $result = $nodelisttab->getNodesAttribs( \@bladearray, ['status'] );
+ foreach (@bladearray) {
+ my $value = $result->{$_};
+ $bladehash{$_} = $bladehash{$_} . $value->[0]->{'status'};
+ }
+ $nodelisttab->close();
+ while ( my ( $key, $value ) = each(%bladehash) ) {
+ $bladeretstr = $bladeretstr . $key . ':' . $value . ';';
+ }
+ }
+
+ # Get all information for System x node
+ if ( scalar(@xarray) > 0 ) {
+ # Rack and unit
+ my $nodepostab = xCAT::Table->new('nodepos');
+ $result = $nodepostab->getNodesAttribs( \@xarray, [ 'rack', 'u' ] );
+ foreach (@xarray) {
+ my $value = $result->{$_};
+ if ( $value->[0]->{'rack'} ) {
+ $xhash{$_} = 'systemx:' . $value->[0]->{'rack'} . ':' . $value->[0]->{'u'} . ':';
+ } else {
+ push( @missinfoarray, $_ );
+ }
+ }
+
+ $nodepostab->close();
+
+ undef @xarray;
+ @xarray = keys %xhash;
+ }
+
+ if ( scalar(@xarray) > 0 ) {
+ # mtm
+ my $vpdtab = xCAT::Table->new('vpd');
+ $result = $vpdtab->getNodesAttribs( \@xarray, ['mtm'] );
+ foreach (@xarray) {
+ my $value = $result->{$_};
+ $xhash{$_} = $xhash{$_} . $value->[0]->{'mtm'} . ':';
+ }
+ $vpdtab->close();
+
+ # Status
+ my $nodelisttab = xCAT::Table->new('nodelist');
+ $result = $nodelisttab->getNodesAttribs( \@xarray, ['status'] );
+ foreach (@xarray) {
+ my $value = $result->{$_};
+ $xhash{$_} = $xhash{$_} . $value->[0]->{'status'};
+ }
+
+ while ( my ( $key, $value ) = each(%xhash) ) {
+ $xretstr = $xretstr . $key . ':' . $value . ';';
+ }
+ }
+
+ @missinfoarray = (@missinfoarray, @unsupportarray);
+ foreach (@missinfoarray) {
+ $missretstr = $missretstr . $_ . ':linux:other;';
+ }
+
+ # Combine all information into a string
+ my $retstr = $pretstr . $bladeretstr . $xretstr . $missretstr;
+ if ($retstr) {
+ $retstr = substr( $retstr, 0, -1 );
+ }
+
+ $callback->( { data => $retstr } );
+}
+
+sub web_getdefaultuserentry {
+
+ # Get default user entry
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # Get profile
+ my $profile = $request->{arg}->[1];
+
+ if ( !$profile ) {
+ $profile = 'default';
+ }
+
+ my $entry;
+ if ( !(`test -e /var/opt/xcat/profiles/$profile.direct && echo 'File exists'`) ) {
+ $entry = `cat /var/opt/xcat/profiles/default.direct`;
+ } else {
+ $entry = `cat /var/opt/xcat/profiles/$profile.direct`;
+ }
+
+ $callback->( { data => $entry } );
+}
+
+sub web_passwd() {
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # Get current and new passwords
+ my $user = $request->{arg}->[1];
+ my $password = $request->{arg}->[2];
+
+ # Generate encrypted password
+ my $random = rand(10000000);
+ my $encrypted = `perl -e "print crypt($password, $random)"`;
+
+ # Save in xCAT passwd table
+ `/opt/xcat/sbin/chtab username=$user passwd.key=xcat passwd.password=$encrypted`;
+
+ my $info = "User password successfully updated";
+ $callback->( { info => $info } );
+ return;
+}
+
+sub web_policy() {
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # Get user attributes
+ my $priority = $request->{arg}->[1];
+ my $args = $request->{arg}->[2];
+
+ # Save in xCAT passwd and policy tables
+ my $out = `/opt/xcat/sbin/chtab priority=$priority $args`;
+
+ my $info = "User policy successfully updated";
+ $callback->( { info => $info } );
+ return;
+}
+
+sub web_deleteuser() {
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # Get user attributes
+ my $user = $request->{arg}->[1];
+ my @users = split( ',', $user );
+
+ # Delete user from xCAT passwd and policy tables
+ foreach (@users) {
+ `/opt/xcat/sbin/chtab -d username=$_ passwd`;
+ `/opt/xcat/sbin/chtab -d name=$_ policy`;
+ }
+
+ my $info = "User successfully deleted";
+ $callback->( { info => $info } );
+ return;
+}
+
+sub web_getzdiskinfo() {
+
+ # Get default disk info
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # Get profile
+ my $profile = $request->{arg}->[1];
+
+ if ( !$profile ) {
+ $profile = 'default';
+ }
+
+ my $info;
+ if ( !(`test -e /var/opt/xcat/profiles/$profile.conf && echo 'File exists'`)) {
+ $info = `cat /var/opt/xcat/profiles/default.conf`;
+ } else {
+ $info = `cat /var/opt/xcat/profiles/$profile.conf`;
+ }
+
+ $callback->( { info => $info } );
+}
+
+sub web_mkzprofile() {
+
+ # Create default profile
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # Get profile
+ my $profile = $request->{arg}->[1];
+ my $pool = $request->{arg}->[2];
+ my $size = $request->{arg}->[3];
+
+ # Create profile under /var/opt/xcat/profiles
+ `mkdir -p /var/opt/xcat/profiles`;
+ my $var = "";
+`echo "# Configuration for virtual machines" > /var/opt/xcat/profiles/$profile.conf`;
+ $var = $profile . "_diskpool";
+ `echo "$var=$pool" >> /var/opt/xcat/profiles/$profile.conf`;
+ $var = $profile . "_eckd_size";
+ `echo "$var=$size" >> /var/opt/xcat/profiles/$profile.conf`;
+
+ # Move directory entry into /var/opt/xcat/profiles from /var/tmp
+ `mv /var/tmp/$profile.direct /var/opt/xcat/profiles`;
+
+ my $info = "Profile successfully created/updated";
+ $callback->( { info => $info } );
+}
+
+sub web_rmzprofile() {
+
+ # Delete default profile
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # Get profile
+ my $profile = $request->{arg}->[1];
+ my @profiles = split( ',', $profile );
+
+ # Delete profile under /var/opt/xcat/profiles
+ foreach (@profiles) {
+ `rm /var/opt/xcat/profiles/$_.conf`;
+ `rm /var/opt/xcat/profiles/$_.direct`;
+ }
+
+ my $info = "Profile successfully deleted";
+ $callback->( { info => $info } );
+}
+
+sub web_mkippool() {
+
+ # Create group IP pool
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # Get profile
+ my $group = $request->{arg}->[1];
+
+ # Move directory entry into /var/opt/xcat/ippool from /var/tmp
+ `mkdir -p /var/opt/xcat/ippool`;
+ `mv /var/tmp/$group.pool /var/opt/xcat/ippool`;
+
+ my $info = "IP pool successfully created/updated";
+ $callback->( { info => $info } );
+}
+
+sub web_rmippool() {
+
+ # Delete group IP pool
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # Get profile
+ my $group = $request->{arg}->[1];
+ my @groups = split( ',', $group );
+
+ # Delete IP pool under /var/opt/xcat/ippool
+ foreach (@groups) {
+ `rm -rf /var/opt/xcat/ippool/$_.pool`;
+ }
+
+ my $info = "IP pool successfully deleted";
+ $callback->( { info => $info } );
+}
+
+sub web_lsippool() {
+
+ # List IP pool
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # Get profile
+ my $group = $request->{arg}->[1];
+
+ # IP pool contained in /var/opt/xcat/ippool where a file exists per group
+ my $entries;
+ if ( !(`test -e /var/opt/xcat/ippool/$group.pool && echo Exists`) ) {
+ $entries = "No IP pool found!";
+ } else {
+ # List IP pool under /var/opt/xcat/ippool
+ $entries = `cat /var/opt/xcat/ippool/$group.pool`;
+ }
+
+ $callback->( { info => $entries } );
+}
+
+sub web_updateosimage() {
+
+ # Add OS image to xCAT table
+ my ( $request, $callback, $sub_req ) = @_;
+
+ my $name = $request->{arg}->[1];
+ my $type = $request->{arg}->[2];
+ my $arch = $request->{arg}->[3];
+ my $osName = $request->{arg}->[4];
+ my $osVersion = $request->{arg}->[5];
+ my $profile = $request->{arg}->[6];
+ my $provMethod = $request->{arg}->[7];
+ my $comments = $request->{arg}->[8];
+
+ `/opt/xcat/sbin/chtab -d imagename=$name osimage`;
+ `/opt/xcat/sbin/chtab osimage.imagename=$name osimage.imagetype=$type osimage.osarch=$arch osimage.osname=$osName osimage.osvers=$osVersion osimage.profile=$profile osimage.provmethod=$provMethod osimage.comments=$comments`;
+ my $info = "Image successfully updated";
+ $callback->( { info => $info } );
+}
+
+sub web_rmosimage() {
+
+ # Delete OS image from xCAT table
+ my ( $request, $callback, $sub_req ) = @_;
+
+ my $name = $request->{arg}->[1];
+ my @names = split( ',', $name );
+
+ # Delete user from xCAT passwd and policy tables
+ foreach (@names) {
+ `/opt/xcat/sbin/chtab -d imagename=$_ osimage`;
+ }
+
+ my $info = "Image successfully deleted";
+ $callback->( { info => $info } );
+}
+
+sub web_updategroup() {
+
+ # Add group to xCAT table
+ my ( $request, $callback, $sub_req ) = @_;
+
+ my $name = $request->{arg}->[1];
+ my $ip = $request->{arg}->[2];
+ $ip =~ s/'//g;
+
+ my $hostnames = $request->{arg}->[3];
+ $hostnames =~ s/'//g;
+
+ my $comments = $request->{arg}->[4];
+ $comments =~ s/'//g;
+
+ `/opt/xcat/sbin/chtab -d node=$name hosts`;
+ `/opt/xcat/sbin/chtab node=$name hosts.ip="$ip" hosts.hostnames="$hostnames" hosts.comments="$comments"`;
+
+ my $info = "Group successfully updated";
+ $callback->( { info => $info } );
+}
+
+sub web_rmgroup() {
+
+ # Delete group from xCAT table
+ my ( $request, $callback, $sub_req ) = @_;
+
+ my $name = $request->{arg}->[1];
+ my @names = split( ',', $name );
+
+ # Delete user from xCAT passwd and policy tables
+ foreach (@names) {
+ `/opt/xcat/sbin/chtab -d node=$_ hosts`;
+ `rm -rf /var/opt/xcat/ippool/$_.pool`;
+ }
+
+ my $info = "Group successfully deleted";
+ $callback->( { info => $info } );
+}
+
+sub web_framesetup() {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $adminpasswd = $request->{arg}->[1];
+ my $generalpasswd = $request->{arg}->[2];
+ my $hmcpasswd = $request->{arg}->[3];
+ my $configphase = $request->{arg}->[4];
+ my @tempnode = 'bpa';
+
+ if ($configphase == 1){
+ #run makedhcp
+ xCAT::Utils->runcmd('makedhcp bpa', -1, 1);
+ sleep(10);
+ #run makehosts
+ xCAT::Utils->runcmd('makehosts bpa', -1, 1);
+ $callback->( { info => 'FRAMEs DHCP, DNS configured.' } );
+ } elsif ($configphase == 2){
+ #run chtab command
+ xCAT::Utils->runcmd('chtab key=bpa,username=HMC passwd.password=' . $hmcpasswd, -1, 1);
+ xCAT::Utils->runcmd('chtab key=bpa,username=admin passwd.password=' . $adminpasswd, -1, 1);
+ xCAT::Utils->runcmd('chtab key=bpa,username=general passwd.password=' . $generalpasswd, -1, 1);
+
+ #mkhwconn
+ xCAT::Utils->runcmd('mkhwconn frame -t', -1, 1);
+ #rspconfig
+ xCAT::Utils->runcmd('rspconfig frame general_passwd=general,' . $generalpasswd, -1, 1);
+ xCAT::Utils->runcmd('rspconfig frame admin_passwd=admin,' . $adminpasswd, -1, 1);
+ xCAT::Utils->runcmd('rspconfig frame HMC_passwd=,' . $hmcpasswd, -1, 1);
+
+ $callback->( { info => 'Hardware connection and configure password created.' } );
+ }
+}
+
+sub web_cecsetup() {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $adminpasswd = $request->{arg}->[1];
+ my $generalpasswd = $request->{arg}->[2];
+ my $hmcpasswd = $request->{arg}->[3];
+ my $configphase = $request->{arg}->[4];
+ my @tempnode = 'bpa';
+
+ if ($configphase == 1){
+ # Run makedhcp
+ xCAT::Utils->runcmd('makedhcp fsp', -1, 1);
+ sleep(10);
+ # Run makehosts
+ xCAT::Utils->runcmd('makehosts fsp', -1, 1);
+ $callback->( { info => 'CEC DHCP, DNS configured.' } );
+ } elsif ($configphase == 2){
+ # Run chtab command
+ xCAT::Utils->runcmd('chtab key=fsp,username=HMC passwd.password=' . $hmcpasswd, -1, 1);
+ xCAT::Utils->runcmd('chtab key=fsp,username=admin passwd.password=' . $adminpasswd, -1, 1);
+ xCAT::Utils->runcmd('chtab key=fsp,username=general passwd.password=' . $generalpasswd, -1, 1);
+ # Run mkhwconn
+ xCAT::Utils->runcmd('mkhwconn cec -t', -1, 1);
+ # Run rspconfig
+ xCAT::Utils->runcmd('rspconfig cec general_passwd=general,' . $generalpasswd, -1, 1);
+ xCAT::Utils->runcmd('rspconfig cec admin_passwd=admin,' . $adminpasswd, -1, 1);
+ xCAT::Utils->runcmd('rspconfig cec HMC_passwd=,' . $hmcpasswd, -1, 1);
+
+ $callback->( { info => 'Hardware connection and configure password created.' } );
+ }
+}
+
+sub web_deletefile() {
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # Get file location
+ my $file = $request->{arg}->[1];
+
+ my $info;
+ if (substr($file, 0, 9) ne "/install/") {
+ $info = "(Error) Files are restricted to those in /install";
+ $callback->( { info => $info } );
+ return;
+ }
+
+ unless (-e $file) {
+ $info = "(Error) File does not exist";
+ $callback->( { info => $info } );
+ return;
+ }
+
+ # Escape spaces
+ $file =~ s/ /\\ /g;
+ my $out = `/bin/rm -rf $file`;
+
+ $info = "File successfully deleted";
+ $callback->( { info => $info } );
+}
+
+sub web_createfolder() {
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # Get folder location
+ my $folder = $request->{arg}->[1];
+
+ my $info;
+ if (substr($folder, 0, 9) ne "/install/") {
+ $info = "(Error) Folders are restricted to those in /install";
+ $callback->( { info => $info } );
+ return;
+ }
+
+ # Escape spaces
+ $folder =~ s/ /\\ /g;
+ my $out = `/bin/mkdir -p $folder`;
+ $out = `chown apache:apache $folder`;
+
+ $info = "Folder successfully created";
+ $callback->( { info => $info } );
+}
+
+sub web_getrepospace() {
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # Query repository space. Output is: size, used, available, used %, mount
+ # remove trailing / from /install so this query also works on CMO which uses cmo-data on /data
+ my $space = `/bin/df -h /install | egrep -i "/install"`;
+ $space =~ s/\s+/ /g;
+ $space =~ s/\s*$//;
+ $space =~ s/^\s*//;
+
+ $callback->( { info => $space } );
+}
+
+1;
diff --git a/xCAT-UI/xcat/plugins/webportal.pm b/xCAT-UI/xcat/plugins/webportal.pm
index 6ad82fbda..e6709710f 100644
--- a/xCAT-UI/xcat/plugins/webportal.pm
+++ b/xCAT-UI/xcat/plugins/webportal.pm
@@ -1,877 +1,882 @@
-# IBM(c) 2011 EPL license http://www.eclipse.org/legal/epl-v10.html
-#-------------------------------------------------------
-
-=head 1
-
- xCAT plugin to handle xCAT UI service portal commands
-
-=cut
-
-#-------------------------------------------------------
-
-package xCAT_plugin::webportal;
-use strict;
-require xCAT::Utils;
-require xCAT::MsgUtils;
-require xCAT::zvmUtils;
-require xCAT::DBobjUtils;
-require IO::Socket::INET;
-use Getopt::Long;
-use Data::Dumper;
-use xCAT::Table;
-use xCAT::NodeRange;
-use XML::Simple;
-require XML::Parser;
-
-sub handled_commands {
-
-# In order for this to work, you need to run: ln -s /opt/xcat/bin/xcatclientnnr /opt/xcat/bin/webportal
-# xcatclientnnr allows command to run without a node range
- return { webportal => "webportal" };
-}
-
-sub process_request {
- my $request = shift;
- my $callback = shift;
- my $sub_req = shift;
- my %authorized_cmds = (
- 'lszvm' => \&lszvm,
- 'provzlinux' => \&provzlinux,
- 'clonezlinux' => \&clonezlinux,
- 'genhostip' => \&genhostip,
- 'getmaxvm' => \&getmaxvm,
- 'getuserprivilege' => \&getuserprivilege,
- 'lsgoldenimages' => \&lsgoldenimages
- );
-
- # Check if the request is authorized
- split ' ', $request->{arg}->[0];
- my $cmd = $_[0];
- if ( grep { $_ eq $cmd } keys %authorized_cmds ) {
- my $func = $authorized_cmds{$cmd};
- $func->( $request, $callback, $sub_req );
- }
- else {
- $callback->(
- { error => "$cmd is not authorized!\n", errorcode => [1] } );
- }
-}
-
-sub println {
- my $callback = shift;
- my $msg = shift;
- my %rsp;
- push @{ $rsp{info} }, $msg;
- xCAT::MsgUtils->message( 'I', \%rsp, $callback );
- return;
-}
-
-sub lszvm {
- my ( $request, $callback, $sub_req ) = @_;
-
- # List the zVM and their respective HCP
- my $out = "";
- my %pair;
-
- # Look in 'zvm' table
- my $tab = xCAT::Table->new( 'zvm', -create => 1, -autocommit => 0 );
- my @results = $tab->getAllAttribsWhere( "nodetype='vm'", 'hcp', 'parent' );
- foreach (@results) {
- if ( $_->{'hcp'} && $_->{'parent'} && !$pair{ $_->{'hcp'} } ) {
-
- # Save zVM:HCP pairing
- $pair{ $_->{'hcp'} } = $_->{'parent'};
-
- # Print out zVM:HCP
- $out .= $_->{'parent'} . ":" . $_->{'hcp'} . "\n";
- }
- }
-
- $callback->( { data => $out } );
-}
-
-sub provzlinux {
- my ( $request, $callback, $sub_req ) = @_;
-
- my $group = $request->{arg}->[1];
- my $hcp = $request->{arg}->[2];
- my $img = $request->{arg}->[3];
- my $owner = $request->{arg}->[4];
-
- # Exit if missing inputs
- if ( !$group || !$hcp || !$img || !$owner ) {
- println( $callback, '(Error) Missing group, HCP, image, or owner' );
- return;
- }
-
- # Check the max # of virtual machines allowed
- my $out = `/opt/xcat/sbin/tabdump nodetype -w nodetype.comments=~"owner:$owner"`;
- my @tmp = split( /\n/, $out );
- my $usrVM = scalar(@tmp) - 1;
-
- $out = `/opt/xcat/bin/webportal getmaxvm $owner`;
- $out =~ s/Max allowed: //g;
- my $maxVM = int($out);
-
- # Do not continue if the max # is reached
- if ($usrVM >= $maxVM) {
- println( $callback, "You have reached the maximum number of virtual machines allowed ($maxVM). Delete unused virtual machines or contact your system administrator request more virtual machines.");
- return;
- }
-
- # Get node OS base
- my $profile;
- my $arch;
- my $os;
- ( $profile, $arch, $os ) = getosimagedef( $callback, $img );
- if ( $os =~ m/sp/i ) {
- @tmp = split( /sp/, $os );
- } else {
- @tmp = split( /\./, $os );
- }
- my $os_base = $tmp[0];
-
- # Read in default disk pool and disk size /opt/zhcp/conf/default.conf on zHCP
- # pool = POOL3
- # eckd_size = 10016
- my $disk_pool;
- my $eckd_size;
- my $fba_size;
- my $profile_conf = $profile;
- my $default_conf = "/var/opt/xcat/profiles/$profile.conf";
- my $default_direct = "/var/opt/xcat/profiles/$profile.direct";
-
- # Check if a group based directory entry exists, else use default one
- if ( !(`test -e /var/opt/xcat/profiles/$profile.direct && echo Exists`) ) {
- println( $callback, "$profile.direct does not exist. Using default.direct to generate directory entry." );
-
- # Exit if default.direct does not exist
- $default_direct = "/var/opt/xcat/profiles/default.direct";
- $default_conf = "/var/opt/xcat/profiles/default.conf";
- $profile_conf = "default";
- if ( !(`test -e $default_direct && echo Exists`) ) {
- println( $callback, "(Error) $default_direct does not exists" );
- return;
- }
- }
-
- # Exit if default.conf does not exist
- if ( !(`test -e $default_conf && echo Exists`) ) {
- println( $callback, "(Error) $default_conf does not exists" );
- return;
- }
-
- # Exit if default.direct does not exist
- if ( !(`test -e $default_direct && echo Exists`) ) {
- println( $callback, "(Error) $default_direct does not exists" );
- return;
- }
-
- $out = `cat $default_conf`;
- @tmp = split( /\n/, $out );
- # default.conf should contain:
-
- # Configuration for virtual machines
- # default_diskpool=POOL3
- # default_eckd_size=10016
- my $profile_diskpool_parm = $profile_conf . "_diskpool";
- my $profile_eckd_size_parm = $profile_conf . "_eckd_size";
- my $profile_fba_size_parm = $profile_conf . "_fba_size";
- my $default_disk_pool;
- my $default_eckd_size;
- my $default_fba_size;
- foreach (@tmp) {
- # Get profile disk pool (default)
- if ( $_ =~ m/$profile_diskpool_parm=/i ) {
- $disk_pool = $_;
- $disk_pool =~ s/$profile_diskpool_parm=//g;
- }
- # Get profile disk size (default)
- elsif ( $_ =~ m/$profile_eckd_size_parm=/i ) {
- $eckd_size = $_;
- $eckd_size =~ s/$profile_eckd_size_parm=//g;
- }
- elsif ( $_ =~ m/$profile_fba_size_parm=/i ) {
- $fba_size = $_;
- $fba_size =~ s/$profile_fba_size_parm=//g;
- }
- }
-
- # Use default configuration if profile configuration does not exist
- if (!$disk_pool && (!$eckd_size || !$fba_size)) {
- println( $callback, "(Error) $profile_conf configuration for disk pool and size does not exist" );
- return;
- }
-
- my $site_tab = xCAT::Table->new('site');
- my $hash = $site_tab->getAttribs( { key => "installdir" }, 'value' );
- my $install_dir = $hash->{'value'};
-
- # Get autoyast/kickstart template
- # Count the number of disks needed
- my $tmpl;
- if ( $os =~ m/sles/i ) {
- $tmpl = "$install_dir/custom/install/sles/$profile.$os_base.$arch.tmpl";
- } elsif ( $os =~ m/rhel/i ) {
- $tmpl = "$install_dir/custom/install/rh/$profile.$os_base.$arch.tmpl";
- }
-
- # Create VM
- # e.g. webportal provzlinux [group] [hcp] [image]
- # my ($node, $ip, $base_digit) = gennodename( $callback, $group );
- my ($node, $ip, $hostname) = findfreenode( $callback, $group );
- if (!$node) {
- println( $callback, "Unable to find a free node, IP, and hostname for $group from the IP pool" );
- return;
- }
-
- my $userid = $node;
-
- # Set node definitions
- # Also put node into all group
- if ($group eq 'all') {
- $out = `/opt/xcat/bin/mkdef -t node -o $node userid=$userid hcp=$hcp mgt=zvm groups=$group`;
- } else {
- # Put node in all group
- $out = `/opt/xcat/bin/mkdef -t node -o $node userid=$userid hcp=$hcp mgt=zvm groups=$group`;
- }
- println( $callback, "$out" );
-
- # Set nodetype definitions
- $out = `/opt/xcat/sbin/chtab node=$node hosts.ip=$ip hosts.hostnames=$hostname noderes.netboot=zvm nodetype.nodetype=osi nodetype.provmethod=install nodetype.os=$os nodetype.arch=$arch nodetype.profile=$profile nodetype.comments="owner:$owner"`;
-
- # Create user directory entry replacing LXUSR with user ID
- # Use /opt/zhcp/conf/default.direct on zHCP as the template
- # USER LXUSR PSWD 512M 1G G
- # INCLUDE LNXDFLT
- # COMMAND SET VSWITCH VSW2 GRANT LXUSR
- $out = `sed $default_direct -e s/LXUSR/$userid/g > /tmp/$node-direct.txt`;
- $out = `/opt/xcat/bin/mkvm $node /tmp/$node-direct.txt`;
- `rm -rf /tmp/$node-direct.txt`;
- println( $callback, "$out" );
- if ( $out =~ m/Error/i ) {
- return;
- }
-
- # Add MDISKs to user directory entry
- # Use /opt/zhcp/conf/default.conf on zHCP to determine disk pool and disk size
- # pool = POOL3
- # eckd_size = 10016
-
- my $type;
- my $virt_addr;
- if ( $os =~ m/sles/i ) {
- # Create XML object
- my $xml = new XML::Simple;
-
- # Read XML file
- my $data = $xml->XMLin($tmpl);
-
- my $devices_ref = $data->{'dasd'}->{'devices'}->{'listentry'};
- my @devices;
-
- if (ref($devices_ref) eq 'HASH') {
- # In the case of 1 device in the listentry, push hash into array
- push(@devices, $devices_ref);
- } else {
- # Listentry is an array reference
- @devices = @$devices_ref;
- }
-
- foreach (@devices) {
- # Get disk virtual address and disk type
- $type = $_->{'drivers'}->{'listentry'}->{'modules'}->{'module_entry'}->{'listentry'};
- $virt_addr = $_->{'sysfs_bus_id'};
- $virt_addr =~ s/0\.0\.//g;
- foreach (@$type) {
- # Add ECKD disk
- if ( $_ =~ m/dasd_eckd_mod/i ) {
- $out = `/opt/xcat/bin/chvm $node --add3390 $disk_pool $virt_addr $eckd_size MR`;
- println( $callback, "$out" );
- if ( $out =~ m/Error/i ) {
- return;
- }
- }
-
- # Add FBA disk
- elsif ( $_ =~ m/dasd_fba_mod/i ) {
- # To be continued
- # $out = `chvm $node --add9336 $disk_pool $virt_addr $fba_size MR`;
- }
- }
- } # End of foreach
- } elsif ( $os =~ m/rhel/i ) {
- my %devices;
- my $dev;
- $virt_addr = 100;
-
- # Read in kickstart file
- $out = `cat $tmpl | egrep "part /"`;
- @tmp = split( /\n/, $out );
- foreach (@tmp) {
- $out = substr( $out, index( $out, '--ondisk=' )+9 );
- $out =~ s/\s*$//; # Trim right
- $out =~ s/^\s*//; # Trim left
- $devices{$out} = 1;
- }
-
- # Add ECKD disk for each device found
- for $dev ( keys %devices ) {
- $out = `/opt/xcat/bin/chvm $node --add3390 $disk_pool $virt_addr $eckd_size MR`;
- println( $callback, "$out" );
- if ( $out =~ m/Error/i ) {
- return;
- }
-
- # Increment virtual address
- $virt_addr = $virt_addr + 1;
- }
- }
-
- # Update hosts table
- `/opt/xcat/sbin/makehosts`;
-
- # Update DHCP
- `makedhcp -a`;
-
- # Toggle node power so COMMAND SET will get executed
- `/opt/xcat/bin/rpower $node on`;
- `/opt/xcat/bin/rpower $node off`;
-
- # Punch kernel, initrd, and ramdisk to node reader
- $out = `/opt/xcat/sbin/nodeset $node install`;
- println( $callback, "$out" );
- if ( $out =~ m/Error/i ) {
- return;
- }
-
- # IPL reader and begin installation
- $out = `/opt/xcat/bin/rnetboot $node ipl=00C`;
- println( $callback, "$out" );
- if ( $out =~ m/Error/i ) {
- return;
- }
-
- # Configure Ganglia monitoring
- $out = `/opt/xcat/bin/moncfg gangliamon $node -r`;
-
- # Show node information, e.g. IP, hostname, and root password
- $out = `/opt/xcat/bin/lsdef $node -i ip,hostnames | egrep "ip=|hostnames="`;
- my $rootpw = getsysrootpw();
- println( $callback, "Your virtual machine is ready. It may take a few minutes before you can logon using VNC ($node:1). Below is your VM attributes." );
- println( $callback, "$out" );
- println( $callback, " rootpw = $rootpw" );
-}
-
-sub getsysrootpw {
- # Get the default root password for all xCAT provisioned VM
- my ( $callback ) = @_;
-
- my $tab = xCAT::Table->new('passwd');
- my $hash = $tab->getAttribs( { key => "system" }, 'password' );
- my $passwd = $hash->{'password'};
-
- return $passwd;
-}
-
-sub getosimagedef {
-
- # Get osimage definitions based on image name
- my ( $callback, $img_name ) = @_;
-
- my $profile;
- my $arch;
- my $os;
-
- # Get profile, osarch, and osver in 'osimage' table based on imagename
- my $tab = xCAT::Table->new( 'osimage', -create => 1, -autocommit => 0 );
- my @results = $tab->getAllAttribsWhere( "imagename='" . $img_name . "'",
- 'profile', 'osarch', 'osvers' );
- foreach (@results) {
-
- # It should return: |gpok(\d+)|10.1.100.($1+0)|
- $profile = $_->{'profile'};
- $arch = $_->{'osarch'};
- $os = $_->{'osvers'};
- }
-
- return ( $profile, $arch, $os );
-}
-
-sub gennodename {
-
- # Generate node name based on given group
- my ( $callback, $group ) = @_;
-
- # Only use the 1st group
- if ($group =~ m/,/) {
- my @groups = split(',', $group);
- $group = @groups[0];
- }
-
- # Hostname and IP address regular expressions
- my $hostname_regex;
- my $ipaddr_regex;
-
- my @comments;
- my $base_digit = 0;
- my $base_hostname;
- my $base_ipaddr;
-
- # Network, submask, submask prefix, and host ranges
- my $network = "";
- my $mask;
- my $prefix;
- my $hosts_count;
- my $range_low = 1;
- my $range_high = 254;
-
- # Hostname and IP address generated
- my $hostname;
- my $ipaddr;
- my $tmp;
-
- my @args;
-
- # Get regular expression for hostname in 'hosts' table
- my $tab = xCAT::Table->new( 'hosts', -create => 1, -autocommit => 0 );
- my @results = $tab->getAllAttribsWhere( "node='" . $group . "'", 'ip', 'comments' );
- foreach (@results) {
-
- # It should return: |gpok(\d+)|10.1.100.($1+0)|
- @args = split( /\|/, $_->{'ip'} );
- $hostname_regex = $args[1];
- $ipaddr_regex = $args[2];
-
- $base_hostname = $args[1];
- $base_hostname =~ s/\(\S*\)/#/g;
-
- # Get the 10.1.100.
- $base_ipaddr = $args[2];
- $base_ipaddr =~ s/\(\S*\)//g;
-
- # Get the ($1+0)
- $ipaddr_regex =~ s/$base_ipaddr//g;
-
- # Get the network within comments
- # It should return: "description: All machines; network: 10.1.100.0/24;"
- # This will help determine the 1st node in the group if none exists
- @comments = split( /|/, $_->{'comments'} );
- foreach (@comments) {
- if ($_ =~ m/network:/i) {
- $network = $_;
-
- # Remove network header
- $network =~ s/network://g;
-
- # Trim network section
- $network =~ s/\s*$//;
- $network =~ s/^\s*//;
-
- # Extract network
- $tmp = rindex($network, '/');
- if ($tmp > -1) {
- # Get submask prefix
- $prefix = substr($network, $tmp);
- $prefix =~ s|/||g;
-
- # Get the number of hosts possible using submask
- $hosts_count = 32 - int($prefix);
- # Minus network and broadcast addresses
- $hosts_count = 2 ** $hosts_count - 2;
-
- # Get network
- $network = substr($network, 0, $tmp);
- }
-
- # Extract base digit, which depends on the netmask used
- $base_digit = substr($network, rindex($network, '.') + 1);
- # 1st number in range is network
- $range_low = $base_digit + 1;
-
- # Get hosts range
- if ($tmp > -1) {
- $range_high = $base_digit + $hosts_count;
- }
- }
- } # End of foreach
- } # End of foreach
-
- # Generate hostname
- $hostname = $base_hostname;
- $hostname =~ s/#/$base_digit/g;
-
- # Generate IP address
- $ipaddr = $hostname;
- $ipaddr =~ s/$hostname_regex/$ipaddr_regex/gee;
- $ipaddr = $base_ipaddr . $ipaddr;
-
- # Get networks in 'networks' table
- $tab = xCAT::Table->new( 'networks', -create => 1, -autocommit => 0 );
- my $entries = $tab->getAllEntries();
-
- # Go through each network
- my $iprange;
- foreach (@$entries) {
-
- # Get network, mask, and range
- $network = $_->{'net'};
- $mask = $_->{'mask'};
- $iprange = $_->{'dynamicrange'};
-
- # If the host IP address is in this subnet, return
- if (xCAT::NetworkUtils->ishostinsubnet($ipaddr, $mask, $network)) {
-
- # Exit loop
- last;
- } else {
- $network = "";
- }
- }
-
- # Exit if no network exist for group
- if (!$network) {
- return;
- }
-
- # Find the network range for this group based on networks table
- my @ranges;
- if ($iprange) {
- @args = split( /;/, $iprange );
- foreach (@args) {
- # If a network range exists
- if ($_ =~ m/-/) {
- @ranges = split( /-/, $_ );
- $range_low = $ranges[0];
- $range_high = $ranges[1];
-
- # Get the low and high ends digit
- $range_low =~ s/$base_ipaddr//g;
- $range_high =~ s/$base_ipaddr//g;
- }
- }
- } # End of if ($iprange)
-
- # If no nodes exist in group
- # Set the base digit to the low end of the network range
- if ($range_low && $base_digit == 1) {
- $base_digit = $range_low;
-
- # Generate hostname
- $hostname = $base_hostname;
- $hostname =~ s/#/$base_digit/g;
-
- # Generate IP address
- $ipaddr = $hostname;
- $ipaddr =~ s/$hostname_regex/$ipaddr_regex/gee;
- $ipaddr = $base_ipaddr . $ipaddr;
- }
-
- # Check xCAT tables, /etc/hosts, and ping to see if hostname is already used
- while (`/opt/xcat/bin/nodels $hostname` || `cat /etc/hosts | grep "$ipaddr "` || !(`ping -c 4 $ipaddr` =~ m/100% packet loss/)) {
- # Base digit invalid if over 254
- if ($base_digit > $range_high) {
- last;
- }
-
- # +1 to base digit to obtain next hostname
- $base_digit = $base_digit + 1;
-
- $hostname = $base_hostname;
- $hostname =~ s/#/$base_digit/g;
-
- $ipaddr = $hostname;
- $ipaddr =~ s/$hostname_regex/$ipaddr_regex/gee;
- $ipaddr = $base_ipaddr . $ipaddr;
- }
-
- # Range must be within network range
- if ($base_digit > $range_high) {
- return;
- } else {
- return ($hostname, $ipaddr, $base_digit);
- }
-}
-
-sub clonezlinux {
- my ( $request, $callback, $sub_req ) = @_;
-
- # webportal clonezlinux [src node] [group] [owner]
- my $src_node = $request->{arg}->[1];
- my $group = $request->{arg}->[2];
- my $owner = $request->{arg}->[3];
-
- # Check the max # of virtual machines allowed
- my $out = `/opt/xcat/sbin/tabdump nodetype -w nodetype.comments=~"owner:$owner"`;
- my @tmp = split( /\n/, $out );
- my $usrVM = scalar(@tmp) - 1;
-
- $out = `/opt/xcat/bin/webportal getmaxvm $owner`;
- $out =~ s/Max allowed: //g;
- my $maxVM = int($out);
-
- # Do not continue if the max # is reached
- if ($usrVM >= $maxVM) {
- println( $callback, "You have reached the maximum number of virtual machines allowed ($maxVM). Delete unused virtual machines or contact your system administrator request more virtual machines.");
- return;
- }
-
- # Get source node's HCP
- my $props = xCAT::zvmUtils->getNodeProps( 'zvm', $src_node, ('hcp') );
- my $hcp = $props->{'hcp'};
-
- # Get source node's nodetype
- $props = xCAT::zvmUtils->getNodeProps( 'nodetype', $src_node, ('os', 'arch', 'profile') );
- my $os = $props->{'os'};
- my $arch = $props->{'arch'};
- my $profile = $props->{'profile'};
-
- # Read in default disk pool from /var/opt/xcat/profiles/default.conf on xCAT MN
- # pool = POOL3
- # eckd_size = 10016
- my $disk_pool;
- my $default_conf = '/var/opt/xcat/profiles/default.conf';
- my $default_direct = '/var/opt/xcat/profiles/default.direct';
-
- # Exit if default.conf does not exist
- if ( !(`test -e $default_conf && echo Exists`) ) {
- println( $callback, "(Error) $default_conf does not exists" );
- return;
- }
-
- # Exit if default.direct does not exist
- if ( !(`test -e $default_direct && echo Exists`) ) {
- println( $callback, "(Error) $default_direct does not exists" );
- return;
- }
-
- $out = `cat $default_conf`;
- @tmp = split( /\n/, $out );
- # default.conf should contain:
-
- # Default configuration for virtual machines handled by this zHCP
- # default_diskpool=POOL3
- # compute_diskpool=POOL3
- my $profile_diskpool_parm = '';
- if ($profile) {
- $profile_diskpool_parm = $profile . "_diskpool";
- }
-
- foreach (@tmp) {
- # Get disk pool (default)
- if ( $_ =~ m/default_diskpool=/i ) {
- $disk_pool = $_;
- $disk_pool =~ s/default_diskpool=//g;
- }
-
- # Get profile disk pool (default)
- elsif ( $_ =~ m/$profile_diskpool_parm=/i && $profile_diskpool_parm) {
- $disk_pool = $_;
- $disk_pool =~ s/$profile_diskpool_parm=//g;
- }
- }
-
- # Trim disk pool of white space
- $disk_pool =~ s/\s*$//; # Trim right
- $disk_pool =~ s/^\s*//; # Trim left
-
- # Create VM
- # e.g. webportal provzlinux [group] [hcp] [image]
- # my ($node, $ip, $base_digit) = gennodename( $callback, $group );
- my ($node, $ip, $hostname) = findfreenode( $callback, $group );
- if (!$node) {
- println( $callback, "Unable to find a free node, IP, and hostname for $group from the IP pool" );
- return;
- }
-
- my $userid = $node;
-
- # Set node definitions
- $out = `/opt/xcat/bin/mkdef -t node -o $node userid=$userid hcp=$hcp mgt=zvm groups=$group`;
- println( $callback, "$out" );
-
- # Set nodetype definitions
- $out = `/opt/xcat/sbin/chtab node=$node hosts.ip=$ip hosts.hostnames=$hostname noderes.netboot=zvm nodetype.nodetype=osi nodetype.provmethod=install nodetype.os=$os nodetype.arch=$arch nodetype.profile=$profile nodetype.comments="owner:$owner"`;
-
- # Update hosts table
- sleep(5); # Time needed to update /etc/hosts
- `/opt/xcat/sbin/makehosts`;
- `/opt/xcat/sbin/makedns`;
-
- # Update DHCP
- `/opt/xcat/sbin/makedhcp -a`;
- println( $callback, "hosts table, DHCP, and DNS updated" );
-
- # Clone virtual machine
- sleep(5); # Time needed to update /etc/hosts
- $out = `/opt/xcat/bin/mkvm $node $src_node pool=$disk_pool`;
- println( $callback, "$out" );
- if ( $out =~ m/Error/i || $out =~ m/Failed/i ) {
- return;
- }
-
- # Configure Ganglia monitoring
- $out = `/opt/xcat/bin/moncfg gangliamon $node -r`;
-
- # Show node information, e.g. IP, hostname, and root password
- $out = `/opt/xcat/bin/lsdef $node | egrep "ip=|hostnames="`;
- my $rootpw = getsysrootpw();
- println( $callback, "Your virtual machine is ready. It may take a few minutes before you can logon. Below is your VM attributes." );
- println( $callback, "$out" );
- println( $callback, " rootpw = Same as source node" );
-}
-
-sub genhostip {
- my ( $request, $callback, $sub_req ) = @_;
- my $group = $request->{arg}->[1];
-
- # my ($node, $ip, $base_digit) = gennodename( $callback, $group );
- my ($node, $ip, $hostname) = findfreenode( $callback, $group );
- println( $callback, "$node: $ip, $hostname" );
-}
-
-sub getmaxvm {
- my ( $request, $callback, $sub_req ) = @_;
- my $user = $request->{arg}->[1];
-
- my @args;
- my $max;
-
- # Look in 'policy' table
- my $tab = xCAT::Table->new( 'policy', -create => 1, -autocommit => 0 );
- my @results = $tab->getAllAttribsWhere( "name='" . $user . "'", 'comments' );
- foreach (@results) {
- if ( $_->{'comments'} ) {
- @args = split( ';', $_->{'comments'} );
-
- # Extract max VM
- foreach (@args) {
- if ($_ =~ m/max-vm:/i) {
- $_ =~ s/max-vm://g;
- $max = $_;
- last;
- }
- }
- }
- }
-
- $callback->( { data => "Max allowed: $max" } );
-}
-
-sub getuserprivilege {
- # Get the user privilege
- my ( $request, $callback, $sub_req ) = @_;
- my $user = $request->{arg}->[1];
- if (!$user) {
- $callback->( { data => "(Error) No user name is specified" } );
- return;
- }
-
- my @args;
- my $privilege = "user";
-
- # Look in 'policy' table
- my $tab = xCAT::Table->new( 'policy', -create => 1, -autocommit => 0 );
- my @results = $tab->getAllAttribsWhere( "name='" . $user . "'", 'comments' );
- foreach (@results) {
- if ( $_->{'comments'} ) {
- @args = split( ';', $_->{'comments'} );
-
- # Extract user privilege
- foreach (@args) {
- if ($_ =~ m/privilege:/i) {
- $_ =~ s/privilege://g;
- $privilege = $_;
- $privilege =~ s/\s*$//; # Trim right
- $privilege =~ s/^\s*//; # Trim left
- last;
- }
- }
- }
- }
-
- $callback->( { data => "Privilege: $privilege" } );
-}
-
-sub lsgoldenimages {
- my ( $request, $callback, $sub_req ) = @_;
-
- # Find the golden image that can be cloned by searching nodetype table for nodetype.provmethod=clone
- my $clones = "";
- my $comments = "";
- my $description = "";
- my @args;
-
- # Look in 'policy' table
- my $tab = xCAT::Table->new( 'nodetype', -create => 1, -autocommit => 0 );
- my @results = $tab->getAllAttribsWhere( "provmethod='clone'", 'node', 'comments' );
- foreach (@results) {
- if ($_->{'node'}) {
- $clones .= $_->{'node'} . ": ";
-
- $comments = $_->{'comments'};
- @args = split(';', $comments);
- foreach (@args) {
- if ($_ =~ m/description:/i) {
- $description = $_;
- $description =~ s/description://g;
- $description =~ s/\s*$//; # Trim right
- $description =~ s/^\s*//; # Trim left
- } else {
- $description = "No comments";
- }
- }
-
- $clones .= $description . ",";
- }
- }
-
- # Delete last comma
- $clones = substr($clones, 0, -1);
-
- $callback->( { data => $clones } );
-}
-
-sub findfreenode {
- # Generate node name based on given group
- my ( $callback, $group ) = @_;
-
- # IP pool contained in /var/opt/xcat/ippool where a file exists per group
- if ( !(`test -e /var/opt/xcat/ippool/$group.pool && echo Exists`) ) {
- return;
- }
-
- # IP pool group format: node, IP, hostname
- # It would look similar to:
- # ihost10,10.1.136.10,ihost10.endicott.ibm.com
- # ihost11,10.1.136.11,ihost11.endicott.ibm.com
- # ihost12,10.1.136.12,ihost12.endicott.ibm.com
- my $node;
- my $ipaddr;
- my $hostname;
-
- my $out = `cat /var/opt/xcat/ippool/$group.pool | grep -v "#"`;
- my @entries = split( /\n/, $out );
- if (@entries < 1) {
- return;
- }
-
- my $found = 0;
- foreach(@entries) {
- # Grab the 1st free entry found
- ($node, $ipaddr, $hostname) = split(/,/, $_);
- if ($node && $ipaddr && $hostname) {
-
- # Check against xCAT tables, /etc/hosts, and ping to see if hostname is already used
- if (`/opt/xcat/bin/nodels $node` || `cat /etc/hosts | grep "$ipaddr "` || !(`ping -c 4 $ipaddr` =~ m/100% packet loss/)) {
- next;
- } else {
- $found = 1;
- return ($node, $ipaddr, $hostname);
- }
- }
- }
-
- return;
-}
+# IBM(c) 2011 EPL license http://www.eclipse.org/legal/epl-v10.html
+#-------------------------------------------------------
+
+=head 1
+
+ xCAT plugin to handle xCAT UI service portal commands
+
+=cut
+
+#-------------------------------------------------------
+
+package xCAT_plugin::webportal;
+use strict;
+require xCAT::Utils;
+require xCAT::MsgUtils;
+require xCAT::zvmUtils;
+require xCAT::DBobjUtils;
+require IO::Socket::INET;
+use Getopt::Long;
+use Data::Dumper;
+use xCAT::Table;
+use xCAT::NodeRange;
+use XML::Simple;
+require XML::Parser;
+
+sub handled_commands {
+
+# In order for this to work, you need to run: ln -s /opt/xcat/bin/xcatclientnnr /opt/xcat/bin/webportal
+# xcatclientnnr allows command to run without a node range
+ return { webportal => "webportal" };
+}
+
+sub process_request {
+ my $request = shift;
+ my $callback = shift;
+ my $sub_req = shift;
+ my %authorized_cmds = (
+ 'lszvm' => \&lszvm,
+ 'provzlinux' => \&provzlinux,
+ 'clonezlinux' => \&clonezlinux,
+ 'genhostip' => \&genhostip,
+ 'getmaxvm' => \&getmaxvm,
+ 'getuserprivilege' => \&getuserprivilege,
+ 'lsgoldenimages' => \&lsgoldenimages
+ );
+
+ # Check if the request is authorized
+ @_ = split ' ', $request->{arg}->[0];
+ my $cmd = $_[0];
+ if ( grep { $_ eq $cmd } keys %authorized_cmds ) {
+ my $func = $authorized_cmds{$cmd};
+ $func->( $request, $callback, $sub_req );
+ }
+ else {
+ $callback->(
+ { error => "$cmd is not authorized!\n", errorcode => [1] } );
+ }
+}
+
+sub println {
+ my $callback = shift;
+ my $msg = shift;
+ my %rsp;
+ push @{ $rsp{info} }, $msg;
+ xCAT::MsgUtils->message( 'I', \%rsp, $callback );
+ return;
+}
+
+sub lszvm {
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # List the zVM and their respective HCP
+ my $out = "";
+ my %pair;
+
+ # Look in 'zvm2' table for zVM host systems
+ my $tab2 = xCAT::Table->new( 'zvm', -create => 1, -autocommit => 0 );
+ my @results2 = $tab2->getAllAttribsWhere( "nodetype='zvm'", 'hcp', 'node' );
+ foreach (@results2) {
+ if ( $_->{'hcp'} && !$pair{ $_->{'hcp'} } ) {
+
+ # Save zVM:HCP pairing
+ $pair{ $_->{'hcp'} } = $_->{'node'};
+
+ # Print out zVM:HCP
+ $out .= $_->{'node'} . ":" . $_->{'hcp'} . "\n";
+ }
+ }
+
+ # Look in 'zvm' table for zVM host systems that may not be setup with nodetype=zvm
+ # Look in 'zvm' table
+ my $tab = xCAT::Table->new( 'zvm', -create => 1, -autocommit => 0 );
+ my @results = $tab->getAllAttribsWhere( "nodetype='vm'", 'hcp', 'parent' );
+ foreach (@results) {
+ if ( $_->{'hcp'} && $_->{'parent'} && !$pair{ $_->{'hcp'} } ) {
+
+ # Save zVM:HCP pairing
+ $pair{ $_->{'hcp'} } = $_->{'parent'};
+
+ # Print out zVM:HCP
+ $out .= $_->{'parent'} . ":" . $_->{'hcp'} . "\n";
+ }
+ }
+
+ $callback->( { data => $out } );
+}
+
+sub provzlinux {
+ my ( $request, $callback, $sub_req ) = @_;
+
+ my $group = $request->{arg}->[1];
+ my $hcp = $request->{arg}->[2];
+ my $img = $request->{arg}->[3];
+ my $owner = $request->{arg}->[4];
+
+ # Exit if missing inputs
+ if ( !$group || !$hcp || !$img || !$owner ) {
+ println( $callback, '(Error) Missing group, HCP, image, or owner' );
+ return;
+ }
+
+ # Check the max # of virtual machines allowed
+ my $out = `/opt/xcat/sbin/tabdump nodetype -w nodetype.comments=~"owner:$owner"`;
+ my @tmp = split( /\n/, $out );
+ my $usrVM = scalar(@tmp) - 1;
+
+ $out = `/opt/xcat/bin/webportal getmaxvm $owner`;
+ $out =~ s/Max allowed: //g;
+ my $maxVM = int($out);
+
+ # Do not continue if the max # is reached
+ if ($usrVM >= $maxVM) {
+ println( $callback, "You have reached the maximum number of virtual machines allowed ($maxVM). Delete unused virtual machines or contact your system administrator request more virtual machines.");
+ return;
+ }
+
+ # Get node OS base
+ my $profile;
+ my $arch;
+ my $os;
+ ( $profile, $arch, $os ) = getosimagedef( $callback, $img );
+ if ( $os =~ m/sp/i ) {
+ @tmp = split( /sp/, $os );
+ } else {
+ @tmp = split( /\./, $os );
+ }
+ my $os_base = $tmp[0];
+
+ # Read in default disk pool and disk size /opt/zhcp/conf/default.conf on zHCP
+ # pool = POOL3
+ # eckd_size = 10016
+ my $disk_pool;
+ my $eckd_size;
+ my $fba_size;
+ my $profile_conf = $profile;
+ my $default_conf = "/var/opt/xcat/profiles/$profile.conf";
+ my $default_direct = "/var/opt/xcat/profiles/$profile.direct";
+
+ # Check if a group based directory entry exists, else use default one
+ if ( !(`test -e /var/opt/xcat/profiles/$profile.direct && echo Exists`) ) {
+ println( $callback, "$profile.direct does not exist. Using default.direct to generate directory entry." );
+
+ # Exit if default.direct does not exist
+ $default_direct = "/var/opt/xcat/profiles/default.direct";
+ $default_conf = "/var/opt/xcat/profiles/default.conf";
+ $profile_conf = "default";
+ if ( !(`test -e $default_direct && echo Exists`) ) {
+ println( $callback, "(Error) $default_direct does not exists" );
+ return;
+ }
+ }
+
+ # Exit if default.conf does not exist
+ if ( !(`test -e $default_conf && echo Exists`) ) {
+ println( $callback, "(Error) $default_conf does not exists" );
+ return;
+ }
+
+ # Exit if default.direct does not exist
+ if ( !(`test -e $default_direct && echo Exists`) ) {
+ println( $callback, "(Error) $default_direct does not exists" );
+ return;
+ }
+
+ $out = `cat $default_conf`;
+ @tmp = split( /\n/, $out );
+ # default.conf should contain:
+
+ # Configuration for virtual machines
+ # default_diskpool=POOL3
+ # default_eckd_size=10016
+ my $profile_diskpool_parm = $profile_conf . "_diskpool";
+ my $profile_eckd_size_parm = $profile_conf . "_eckd_size";
+ my $profile_fba_size_parm = $profile_conf . "_fba_size";
+ my $default_disk_pool;
+ my $default_eckd_size;
+ my $default_fba_size;
+ foreach (@tmp) {
+ # Get profile disk pool (default)
+ if ( $_ =~ m/$profile_diskpool_parm=/i ) {
+ $disk_pool = $_;
+ $disk_pool =~ s/$profile_diskpool_parm=//g;
+ }
+ # Get profile disk size (default)
+ elsif ( $_ =~ m/$profile_eckd_size_parm=/i ) {
+ $eckd_size = $_;
+ $eckd_size =~ s/$profile_eckd_size_parm=//g;
+ }
+ elsif ( $_ =~ m/$profile_fba_size_parm=/i ) {
+ $fba_size = $_;
+ $fba_size =~ s/$profile_fba_size_parm=//g;
+ }
+ }
+
+ # Use default configuration if profile configuration does not exist
+ if (!$disk_pool && (!$eckd_size || !$fba_size)) {
+ println( $callback, "(Error) $profile_conf configuration for disk pool and size does not exist" );
+ return;
+ }
+
+ my $site_tab = xCAT::Table->new('site');
+ my $hash = $site_tab->getAttribs( { key => "installdir" }, 'value' );
+ my $install_dir = $hash->{'value'};
+
+ # Get autoyast/kickstart template
+ # Count the number of disks needed
+ my $tmpl;
+ if ( $os =~ m/sles/i ) {
+ $tmpl = "$install_dir/custom/install/sles/$profile.$os_base.$arch.tmpl";
+ } elsif ( $os =~ m/rhel/i ) {
+ $tmpl = "$install_dir/custom/install/rh/$profile.$os_base.$arch.tmpl";
+ }
+
+ # Create VM
+ # e.g. webportal provzlinux [group] [hcp] [image]
+ # my ($node, $ip, $base_digit) = gennodename( $callback, $group );
+ my ($node, $ip, $hostname) = findfreenode( $callback, $group );
+ if (!$node) {
+ println( $callback, "Unable to find a free node, IP, and hostname for $group from the IP pool" );
+ return;
+ }
+
+ my $userid = $node;
+
+ # Set node definitions
+ # Also put node into all group
+ if ($group eq 'all') {
+ $out = `/opt/xcat/bin/mkdef -t node -o $node userid=$userid hcp=$hcp mgt=zvm groups=$group`;
+ } else {
+ # Put node in all group
+ $out = `/opt/xcat/bin/mkdef -t node -o $node userid=$userid hcp=$hcp mgt=zvm groups=$group`;
+ }
+ println( $callback, "$out" );
+
+ # Set nodetype definitions
+ $out = `/opt/xcat/sbin/chtab node=$node hosts.ip=$ip hosts.hostnames=$hostname noderes.netboot=zvm nodetype.nodetype=osi nodetype.provmethod=install nodetype.os=$os nodetype.arch=$arch nodetype.profile=$profile nodetype.comments="owner:$owner"`;
+
+ # Create user directory entry replacing LXUSR with user ID
+ # Use /opt/zhcp/conf/default.direct on zHCP as the template
+ # USER LXUSR PSWD 512M 1G G
+ # INCLUDE LNXDFLT
+ # COMMAND SET VSWITCH VSW2 GRANT LXUSR
+ $out = `sed $default_direct -e s/LXUSR/$userid/g > /tmp/$node-direct.txt`;
+ $out = `/opt/xcat/bin/mkvm $node /tmp/$node-direct.txt`;
+ `rm -rf /tmp/$node-direct.txt`;
+ println( $callback, "$out" );
+ if ( $out =~ m/Error/i ) {
+ return;
+ }
+
+ # Add MDISKs to user directory entry
+ # Use /opt/zhcp/conf/default.conf on zHCP to determine disk pool and disk size
+ # pool = POOL3
+ # eckd_size = 10016
+
+ my $type;
+ my $virt_addr;
+ if ( $os =~ m/sles/i ) {
+ # Create XML object
+ my $xml = new XML::Simple;
+
+ # Read XML file
+ my $data = $xml->XMLin($tmpl);
+
+ my $devices_ref = $data->{'dasd'}->{'devices'}->{'listentry'};
+ my @devices;
+
+ if (ref($devices_ref) eq 'HASH') {
+ # In the case of 1 device in the listentry, push hash into array
+ push(@devices, $devices_ref);
+ } else {
+ # Listentry is an array reference
+ @devices = @$devices_ref;
+ }
+
+ foreach (@devices) {
+ # Get disk virtual address and disk type
+ $type = $_->{'drivers'}->{'listentry'}->{'modules'}->{'module_entry'}->{'listentry'};
+ $virt_addr = $_->{'sysfs_bus_id'};
+ $virt_addr =~ s/0\.0\.//g;
+ foreach (@$type) {
+ # Add ECKD disk
+ if ( $_ =~ m/dasd_eckd_mod/i ) {
+ $out = `/opt/xcat/bin/chvm $node --add3390 $disk_pool $virt_addr $eckd_size MR`;
+ println( $callback, "$out" );
+ if ( $out =~ m/Error/i ) {
+ return;
+ }
+ }
+
+ # Add FBA disk
+ elsif ( $_ =~ m/dasd_fba_mod/i ) {
+ # To be continued
+ # $out = `chvm $node --add9336 $disk_pool $virt_addr $fba_size MR`;
+ }
+ }
+ } # End of foreach
+ } elsif ( $os =~ m/rhel/i ) {
+ my %devices;
+ my $dev;
+ $virt_addr = 100;
+
+ # Read in kickstart file
+ $out = `cat $tmpl | egrep "part /"`;
+ @tmp = split( /\n/, $out );
+ foreach (@tmp) {
+ $out = substr( $out, index( $out, '--ondisk=' )+9 );
+ $out =~ s/\s*$//; # Trim right
+ $out =~ s/^\s*//; # Trim left
+ $devices{$out} = 1;
+ }
+
+ # Add ECKD disk for each device found
+ for $dev ( keys %devices ) {
+ $out = `/opt/xcat/bin/chvm $node --add3390 $disk_pool $virt_addr $eckd_size MR`;
+ println( $callback, "$out" );
+ if ( $out =~ m/Error/i ) {
+ return;
+ }
+
+ # Increment virtual address
+ $virt_addr = $virt_addr + 1;
+ }
+ }
+
+ # Update hosts table
+ `/opt/xcat/sbin/makehosts`;
+
+ # Toggle node power so COMMAND SET will get executed
+ `/opt/xcat/bin/rpower $node on`;
+ `/opt/xcat/bin/rpower $node off`;
+
+ # Punch kernel, initrd, and ramdisk to node reader
+ $out = `/opt/xcat/sbin/nodeset $node install`;
+ println( $callback, "$out" );
+ if ( $out =~ m/Error/i ) {
+ return;
+ }
+
+ # IPL reader and begin installation
+ $out = `/opt/xcat/bin/rnetboot $node ipl=00C`;
+ println( $callback, "$out" );
+ if ( $out =~ m/Error/i ) {
+ return;
+ }
+
+ # Configure Ganglia monitoring
+ $out = `/opt/xcat/bin/moncfg gangliamon $node -r`;
+
+ # Show node information, e.g. IP, hostname, and root password
+ $out = `/opt/xcat/bin/lsdef $node -i ip,hostnames | egrep "ip=|hostnames="`;
+ my $rootpw = getsysrootpw();
+ println( $callback, "Your virtual machine is ready. It may take a few minutes before you can logon using VNC ($node:1). Below is your VM attributes." );
+ println( $callback, "$out" );
+ println( $callback, " rootpw = $rootpw" );
+}
+
+sub getsysrootpw {
+ # Get the default root password for all xCAT provisioned VM
+ my ( $callback ) = @_;
+
+ my $tab = xCAT::Table->new('passwd');
+ my $hash = $tab->getAttribs( { key => "system" }, 'password' );
+ my $passwd = $hash->{'password'};
+
+ return $passwd;
+}
+
+sub getosimagedef {
+
+ # Get osimage definitions based on image name
+ my ( $callback, $img_name ) = @_;
+
+ my $profile;
+ my $arch;
+ my $os;
+
+ # Get profile, osarch, and osver in 'osimage' table based on imagename
+ my $tab = xCAT::Table->new( 'osimage', -create => 1, -autocommit => 0 );
+ my @results = $tab->getAllAttribsWhere( "imagename='" . $img_name . "'",
+ 'profile', 'osarch', 'osvers' );
+ foreach (@results) {
+
+ # It should return: |gpok(\d+)|10.1.100.($1+0)|
+ $profile = $_->{'profile'};
+ $arch = $_->{'osarch'};
+ $os = $_->{'osvers'};
+ }
+
+ return ( $profile, $arch, $os );
+}
+
+sub gennodename {
+
+ # Generate node name based on given group
+ my ( $callback, $group ) = @_;
+
+ # Only use the 1st group
+ if ($group =~ m/,/) {
+ my @groups = split(',', $group);
+ $group = @groups[0];
+ }
+
+ # Hostname and IP address regular expressions
+ my $hostname_regex;
+ my $ipaddr_regex;
+
+ my @comments;
+ my $base_digit = 0;
+ my $base_hostname;
+ my $base_ipaddr;
+
+ # Network, submask, submask prefix, and host ranges
+ my $network = "";
+ my $mask;
+ my $prefix;
+ my $hosts_count;
+ my $range_low = 1;
+ my $range_high = 254;
+
+ # Hostname and IP address generated
+ my $hostname;
+ my $ipaddr;
+ my $tmp;
+
+ my @args;
+
+ # Get regular expression for hostname in 'hosts' table
+ my $tab = xCAT::Table->new( 'hosts', -create => 1, -autocommit => 0 );
+ my @results = $tab->getAllAttribsWhere( "node='" . $group . "'", 'ip', 'comments' );
+ foreach (@results) {
+
+ # It should return: |gpok(\d+)|10.1.100.($1+0)|
+ @args = split( /\|/, $_->{'ip'} );
+ $hostname_regex = $args[1];
+ $ipaddr_regex = $args[2];
+
+ $base_hostname = $args[1];
+ $base_hostname =~ s/\(\S*\)/#/g;
+
+ # Get the 10.1.100.
+ $base_ipaddr = $args[2];
+ $base_ipaddr =~ s/\(\S*\)//g;
+
+ # Get the ($1+0)
+ $ipaddr_regex =~ s/$base_ipaddr//g;
+
+ # Get the network within comments
+ # It should return: "description: All machines; network: 10.1.100.0/24;"
+ # This will help determine the 1st node in the group if none exists
+ @comments = split( /|/, $_->{'comments'} );
+ foreach (@comments) {
+ if ($_ =~ m/network:/i) {
+ $network = $_;
+
+ # Remove network header
+ $network =~ s/network://g;
+
+ # Trim network section
+ $network =~ s/\s*$//;
+ $network =~ s/^\s*//;
+
+ # Extract network
+ $tmp = rindex($network, '/');
+ if ($tmp > -1) {
+ # Get submask prefix
+ $prefix = substr($network, $tmp);
+ $prefix =~ s|/||g;
+
+ # Get the number of hosts possible using submask
+ $hosts_count = 32 - int($prefix);
+ # Minus network and broadcast addresses
+ $hosts_count = 2 ** $hosts_count - 2;
+
+ # Get network
+ $network = substr($network, 0, $tmp);
+ }
+
+ # Extract base digit, which depends on the netmask used
+ $base_digit = substr($network, rindex($network, '.') + 1);
+ # 1st number in range is network
+ $range_low = $base_digit + 1;
+
+ # Get hosts range
+ if ($tmp > -1) {
+ $range_high = $base_digit + $hosts_count;
+ }
+ }
+ } # End of foreach
+ } # End of foreach
+
+ # Generate hostname
+ $hostname = $base_hostname;
+ $hostname =~ s/#/$base_digit/g;
+
+ # Generate IP address
+ $ipaddr = $hostname;
+ $ipaddr =~ s/$hostname_regex/$ipaddr_regex/gee;
+ $ipaddr = $base_ipaddr . $ipaddr;
+
+ # Get networks in 'networks' table
+ $tab = xCAT::Table->new( 'networks', -create => 1, -autocommit => 0 );
+ my $entries = $tab->getAllEntries();
+
+ # Go through each network
+ my $iprange;
+ foreach (@$entries) {
+
+ # Get network, mask, and range
+ $network = $_->{'net'};
+ $mask = $_->{'mask'};
+ $iprange = $_->{'dynamicrange'};
+
+ # If the host IP address is in this subnet, return
+ if (xCAT::NetworkUtils->ishostinsubnet($ipaddr, $mask, $network)) {
+
+ # Exit loop
+ last;
+ } else {
+ $network = "";
+ }
+ }
+
+ # Exit if no network exist for group
+ if (!$network) {
+ return;
+ }
+
+ # Find the network range for this group based on networks table
+ my @ranges;
+ if ($iprange) {
+ @args = split( /;/, $iprange );
+ foreach (@args) {
+ # If a network range exists
+ if ($_ =~ m/-/) {
+ @ranges = split( /-/, $_ );
+ $range_low = $ranges[0];
+ $range_high = $ranges[1];
+
+ # Get the low and high ends digit
+ $range_low =~ s/$base_ipaddr//g;
+ $range_high =~ s/$base_ipaddr//g;
+ }
+ }
+ } # End of if ($iprange)
+
+ # If no nodes exist in group
+ # Set the base digit to the low end of the network range
+ if ($range_low && $base_digit == 1) {
+ $base_digit = $range_low;
+
+ # Generate hostname
+ $hostname = $base_hostname;
+ $hostname =~ s/#/$base_digit/g;
+
+ # Generate IP address
+ $ipaddr = $hostname;
+ $ipaddr =~ s/$hostname_regex/$ipaddr_regex/gee;
+ $ipaddr = $base_ipaddr . $ipaddr;
+ }
+
+ # Check xCAT tables, /etc/hosts, and ping to see if hostname is already used
+ while (`/opt/xcat/bin/nodels $hostname` || `cat /etc/hosts | grep "$ipaddr "` || !(`ping -c 4 $ipaddr` =~ m/100% packet loss/)) {
+ # Base digit invalid if over 254
+ if ($base_digit > $range_high) {
+ last;
+ }
+
+ # +1 to base digit to obtain next hostname
+ $base_digit = $base_digit + 1;
+
+ $hostname = $base_hostname;
+ $hostname =~ s/#/$base_digit/g;
+
+ $ipaddr = $hostname;
+ $ipaddr =~ s/$hostname_regex/$ipaddr_regex/gee;
+ $ipaddr = $base_ipaddr . $ipaddr;
+ }
+
+ # Range must be within network range
+ if ($base_digit > $range_high) {
+ return;
+ } else {
+ return ($hostname, $ipaddr, $base_digit);
+ }
+}
+
+sub clonezlinux {
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # webportal clonezlinux [src node] [group] [owner]
+ my $src_node = $request->{arg}->[1];
+ my $group = $request->{arg}->[2];
+ my $owner = $request->{arg}->[3];
+
+ # Check the max # of virtual machines allowed
+ my $out = `/opt/xcat/sbin/tabdump nodetype -w nodetype.comments=~"owner:$owner"`;
+ my @tmp = split( /\n/, $out );
+ my $usrVM = scalar(@tmp) - 1;
+
+ $out = `/opt/xcat/bin/webportal getmaxvm $owner`;
+ $out =~ s/Max allowed: //g;
+ my $maxVM = int($out);
+
+ # Do not continue if the max # is reached
+ if ($usrVM >= $maxVM) {
+ println( $callback, "You have reached the maximum number of virtual machines allowed ($maxVM). Delete unused virtual machines or contact your system administrator request more virtual machines.");
+ return;
+ }
+
+ # Get source node's HCP
+ my $props = xCAT::zvmUtils->getNodeProps( 'zvm', $src_node, ('hcp') );
+ my $hcp = $props->{'hcp'};
+
+ # Get source node's nodetype
+ $props = xCAT::zvmUtils->getNodeProps( 'nodetype', $src_node, ('os', 'arch', 'profile') );
+ my $os = $props->{'os'};
+ my $arch = $props->{'arch'};
+ my $profile = $props->{'profile'};
+
+ # Read in default disk pool from /var/opt/xcat/profiles/default.conf on xCAT MN
+ # pool = POOL3
+ # eckd_size = 10016
+ my $disk_pool;
+ my $default_conf = '/var/opt/xcat/profiles/default.conf';
+ my $default_direct = '/var/opt/xcat/profiles/default.direct';
+
+ # Exit if default.conf does not exist
+ if ( !(`test -e $default_conf && echo Exists`) ) {
+ println( $callback, "(Error) $default_conf does not exists" );
+ return;
+ }
+
+ # Exit if default.direct does not exist
+ if ( !(`test -e $default_direct && echo Exists`) ) {
+ println( $callback, "(Error) $default_direct does not exists" );
+ return;
+ }
+
+ $out = `cat $default_conf`;
+ @tmp = split( /\n/, $out );
+ # default.conf should contain:
+
+ # Default configuration for virtual machines handled by this zHCP
+ # default_diskpool=POOL3
+ # compute_diskpool=POOL3
+ my $profile_diskpool_parm = '';
+ if ($profile) {
+ $profile_diskpool_parm = $profile . "_diskpool";
+ }
+
+ foreach (@tmp) {
+ # Get disk pool (default)
+ if ( $_ =~ m/default_diskpool=/i ) {
+ $disk_pool = $_;
+ $disk_pool =~ s/default_diskpool=//g;
+ }
+
+ # Get profile disk pool (default)
+ elsif ( $_ =~ m/$profile_diskpool_parm=/i && $profile_diskpool_parm) {
+ $disk_pool = $_;
+ $disk_pool =~ s/$profile_diskpool_parm=//g;
+ }
+ }
+
+ # Trim disk pool of white space
+ $disk_pool =~ s/\s*$//; # Trim right
+ $disk_pool =~ s/^\s*//; # Trim left
+
+ # Create VM
+ # e.g. webportal provzlinux [group] [hcp] [image]
+ # my ($node, $ip, $base_digit) = gennodename( $callback, $group );
+ my ($node, $ip, $hostname) = findfreenode( $callback, $group );
+ if (!$node) {
+ println( $callback, "Unable to find a free node, IP, and hostname for $group from the IP pool" );
+ return;
+ }
+
+ my $userid = $node;
+
+ # Set node definitions
+ $out = `/opt/xcat/bin/mkdef -t node -o $node userid=$userid hcp=$hcp mgt=zvm groups=$group`;
+ println( $callback, "$out" );
+
+ # Set nodetype definitions
+ $out = `/opt/xcat/sbin/chtab node=$node hosts.ip=$ip hosts.hostnames=$hostname noderes.netboot=zvm nodetype.nodetype=osi nodetype.provmethod=install nodetype.os=$os nodetype.arch=$arch nodetype.profile=$profile nodetype.comments="owner:$owner"`;
+
+ # Update hosts table
+ sleep(5); # Time needed to update /etc/hosts
+ `/opt/xcat/sbin/makehosts`;
+ println( $callback, "hosts table updated" );
+
+ # Clone virtual machine
+ sleep(5); # Time needed to update /etc/hosts
+ $out = `/opt/xcat/bin/mkvm $node $src_node pool=$disk_pool`;
+ println( $callback, "$out" );
+ if ( $out =~ m/Error/i || $out =~ m/Failed/i ) {
+ return;
+ }
+
+ # Show node information, e.g. IP, hostname, and root password
+ $out = `/opt/xcat/bin/lsdef $node | egrep "ip=|hostnames="`;
+ my $rootpw = getsysrootpw();
+ println( $callback, "Your virtual machine is ready. It may take a few minutes before you can logon. Below is your VM attributes." );
+ println( $callback, "$out" );
+ println( $callback, " rootpw = Same as source node" );
+}
+
+sub genhostip {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $group = $request->{arg}->[1];
+
+ # my ($node, $ip, $base_digit) = gennodename( $callback, $group );
+ my ($node, $ip, $hostname) = findfreenode( $callback, $group );
+ println( $callback, "$node: $ip, $hostname" );
+}
+
+sub getmaxvm {
+ my ( $request, $callback, $sub_req ) = @_;
+ my $user = $request->{arg}->[1];
+
+ my @args;
+ my $max;
+
+ # Look in 'policy' table
+ my $tab = xCAT::Table->new( 'policy', -create => 1, -autocommit => 0 );
+ my @results = $tab->getAllAttribsWhere( "name='" . $user . "'", 'comments' );
+ foreach (@results) {
+ if ( $_->{'comments'} ) {
+ @args = split( ';', $_->{'comments'} );
+
+ # Extract max VM
+ foreach (@args) {
+ if ($_ =~ m/max-vm:/i) {
+ $_ =~ s/max-vm://g;
+ $max = $_;
+ last;
+ }
+ }
+ }
+ }
+
+ $callback->( { data => "Max allowed: $max" } );
+}
+
+sub getuserprivilege {
+ # Get the user privilege
+ my ( $request, $callback, $sub_req ) = @_;
+ my $user = $request->{arg}->[1];
+ if (!$user) {
+ $callback->( { data => "(Error) No user name is specified" } );
+ return;
+ }
+
+ my @args;
+ my $privilege = "user";
+
+ # Look in 'policy' table
+ my $tab = xCAT::Table->new( 'policy', -create => 1, -autocommit => 0 );
+ my @results = $tab->getAllAttribsWhere( "name='" . $user . "'", 'comments' );
+ foreach (@results) {
+ if ( $_->{'comments'} ) {
+ @args = split( ';', $_->{'comments'} );
+
+ # Extract user privilege
+ foreach (@args) {
+ if ($_ =~ m/privilege:/i) {
+ $_ =~ s/privilege://g;
+ $privilege = $_;
+ $privilege =~ s/\s*$//; # Trim right
+ $privilege =~ s/^\s*//; # Trim left
+ last;
+ }
+ }
+ }
+ }
+
+ $callback->( { data => "Privilege: $privilege" } );
+}
+
+sub lsgoldenimages {
+ my ( $request, $callback, $sub_req ) = @_;
+
+ # Find the golden image that can be cloned by searching nodetype table for nodetype.provmethod=clone
+ my $clones = "";
+ my $comments = "";
+ my $description = "";
+ my @args;
+
+ # Look in 'policy' table
+ my $tab = xCAT::Table->new( 'nodetype', -create => 1, -autocommit => 0 );
+ my @results = $tab->getAllAttribsWhere( "provmethod='clone'", 'node', 'comments' );
+ foreach (@results) {
+ if ($_->{'node'}) {
+ $clones .= $_->{'node'} . ": ";
+
+ $comments = $_->{'comments'};
+ @args = split(';', $comments);
+ foreach (@args) {
+ if ($_ =~ m/description:/i) {
+ $description = $_;
+ $description =~ s/description://g;
+ $description =~ s/\s*$//; # Trim right
+ $description =~ s/^\s*//; # Trim left
+ } else {
+ $description = "No comments";
+ }
+ }
+
+ $clones .= $description . ",";
+ }
+ }
+
+ # Delete last comma
+ $clones = substr($clones, 0, -1);
+
+ $callback->( { data => $clones } );
+}
+
+sub findfreenode {
+ # Generate node name based on given group
+ my ( $callback, $group ) = @_;
+
+ # IP pool contained in /var/opt/xcat/ippool where a file exists per group
+ if ( !(`test -e /var/opt/xcat/ippool/$group.pool && echo Exists`) ) {
+ return;
+ }
+
+ # IP pool group format: node, IP, hostname
+ # It would look similar to:
+ # ihost10,10.1.136.10,ihost10.endicott.ibm.com
+ # ihost11,10.1.136.11,ihost11.endicott.ibm.com
+ # ihost12,10.1.136.12,ihost12.endicott.ibm.com
+ my $node;
+ my $ipaddr;
+ my $hostname;
+
+ my $out = `cat /var/opt/xcat/ippool/$group.pool | grep -v "#"`;
+ my @entries = split( /\n/, $out );
+ if (@entries < 1) {
+ return;
+ }
+
+ my $found = 0;
+ foreach(@entries) {
+ # Grab the 1st free entry found
+ ($node, $ipaddr, $hostname) = split(/,/, $_);
+ if ($node && $ipaddr && $hostname) {
+
+ # Check against xCAT tables, /etc/hosts, and ping to see if hostname is already used
+ if (`/opt/xcat/bin/nodels $node` || `cat /etc/hosts | grep "$ipaddr "` || !(`ping -c 4 $ipaddr` =~ m/100% packet loss/)) {
+ next;
+ } else {
+ $found = 1;
+ return ($node, $ipaddr, $hostname);
+ }
+ }
+ }
+
+ return;
+}
1;
\ No newline at end of file