b3b29d3c76
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@16970 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
2706 lines
106 KiB
JavaScript
2706 lines
106 KiB
JavaScript
/**
|
|
* Execute when the DOM is fully loaded
|
|
*/
|
|
$(document).ready(function() {
|
|
// Load utility scripts
|
|
includeJs("js/custom/zvmUtils.js");
|
|
});
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
var zvmPlugin = function() {
|
|
|
|
};
|
|
|
|
/**
|
|
* Configure self-service configure page
|
|
*/
|
|
zvmPlugin.prototype.loadConfigPage = function(tabId) {
|
|
var configAccordion = $('<div id="zvmConfigAccordion"></div>');
|
|
|
|
// Create accordion panel for profiles
|
|
var profileSection = $('<div id="zvmConfigProfile"></div>');
|
|
var profileLnk = $('<h3><a href="#">Profiles</a></h3>').click(function () {
|
|
// Do not load panel again if it is already loaded
|
|
if ($('#zvmConfigProfile').find('.dataTables_wrapper').length)
|
|
return;
|
|
else
|
|
$('#zvmConfigProfile').append(createLoader(''));
|
|
|
|
queryProfiles('zvmConfigProfile');
|
|
});
|
|
|
|
// Create accordion panel for images
|
|
var imgSection = $('<div id="zvmConfigImages"></div>');
|
|
var imgLnk = $('<h3><a href="#">Templates</a></h3>').click(function () {
|
|
// Do not load panel again if it is already loaded
|
|
if ($('#zvmConfigImages').find('.dataTables_wrapper').length)
|
|
return;
|
|
else
|
|
$('#zvmConfigImages').append(createLoader(''));
|
|
|
|
queryImages('zvmConfigImages');
|
|
});
|
|
|
|
// Create accordion panel for groups
|
|
var groupsSection = $('<div id="zvmConfigGroups"></div>');
|
|
var groupsLnk = $('<h3><a href="#">Groups</a></h3>').click(function () {
|
|
// Do not load panel again if it is already loaded
|
|
if ($('#zvmConfigGroups').find('.dataTables_wrapper').length)
|
|
return;
|
|
else
|
|
$('#zvmConfigGroups').append(createLoader(''));
|
|
|
|
queryGroups('zvmConfigGroups');
|
|
});
|
|
|
|
configAccordion.append(profileLnk, profileSection, imgLnk, imgSection, groupsLnk, groupsSection);
|
|
$('#' + tabId).append(configAccordion);
|
|
configAccordion.accordion();
|
|
|
|
profileLnk.trigger('click');
|
|
};
|
|
|
|
/**
|
|
* Clone node (service page)
|
|
*
|
|
* @param node Node to clone
|
|
*/
|
|
zvmPlugin.prototype.serviceClone = function(node) {
|
|
var owner = $.cookie('xcat_username');
|
|
var group = getUserNodeAttr(node, 'groups');
|
|
|
|
// Submit request to clone VM
|
|
// webportal clonezlinux [src node] [group] [owner]
|
|
var iframe = createIFrame('lib/srv_cmd.php?cmd=webportal&tgt=&args=clonezlinux;' + node + ';' + group + ';' + owner + '&msg=&opts=flush');
|
|
iframe.prependTo($('#manageTab'));
|
|
};
|
|
|
|
/**
|
|
* Load provision page (service page)
|
|
*
|
|
* @param tabId Tab ID where page will reside
|
|
*/
|
|
zvmPlugin.prototype.loadServiceProvisionPage = function(tabId) {
|
|
// Create provision form
|
|
var provForm = $('<div></div>');
|
|
|
|
// Create info bar
|
|
var infoBar = createInfoBar('Provision a Linux virtual machine on System z by selecting the appropriate choices below. Once you are ready, click on Provision to provision the virtual machine.');
|
|
provForm.append(infoBar);
|
|
|
|
// Append to provision tab
|
|
$('#' + tabId).append(provForm);
|
|
|
|
// Create provision table
|
|
var provTable = $('<table id="select-table" style="margin: 10px;"></table');
|
|
var provHeader = $('<thead class="ui-widget-header"> <th>zVM</th> <th>Group</th> <th>Template</th> <th>Image</th></thead>');
|
|
var provBody = $('<tbody></tbody>');
|
|
var provFooter = $('<tfoot></tfoot>');
|
|
provTable.append(provHeader, provBody, provFooter);
|
|
provForm.append(provTable);
|
|
|
|
provHeader.children('th').css({
|
|
'font': 'bold 12px verdana, arial, helvetica, sans-serif'
|
|
});
|
|
|
|
// Create row to contain selections
|
|
var provRow = $('<tr></tr>');
|
|
provBody.append(provRow);
|
|
// Create columns for zVM, group, template, and image
|
|
var zvmCol = $('<td style="vertical-align: top;"></td>');
|
|
provRow.append(zvmCol);
|
|
var groupCol = $('<td style="vertical-align: top;"></td>');
|
|
provRow.append(groupCol);
|
|
var tmplCol = $('<td style="vertical-align: top;"></td>');
|
|
provRow.append(tmplCol);
|
|
var imgCol = $('<td style="vertical-align: top;"></td>');
|
|
provRow.append(imgCol);
|
|
|
|
provRow.children('td').css({
|
|
'min-width': '200px'
|
|
});
|
|
|
|
/**
|
|
* Provision VM
|
|
*/
|
|
var provisionBtn = createButton('Provision');
|
|
provisionBtn.bind('click', function(event) {
|
|
// Remove any warning messages
|
|
$(this).parent().find('.ui-state-error').remove();
|
|
|
|
var hcp = $('#select-table tbody tr:eq(0) td:eq(0) input[name="hcp"]:checked').val();
|
|
var group = $('#select-table tbody tr:eq(0) td:eq(1) input[name="group"]:checked').val();
|
|
var tmpl = $('#select-table tbody tr:eq(0) td:eq(2) input[name="image"]:checked').val();
|
|
var img = $('#select-table tbody tr:eq(0) td:eq(3) input[name="master"]:checked').val();
|
|
var owner = $.cookie('xcat_username');
|
|
|
|
if (img && !group) {
|
|
// Show warning message
|
|
var warn = createWarnBar('You need to select a group');
|
|
warn.prependTo($(this).parent());
|
|
} else if (!img && (!hcp || !group || !tmpl)) {
|
|
// Show warning message
|
|
var warn = createWarnBar('You need to select a zHCP, group, and image');
|
|
warn.prependTo($(this).parent());
|
|
} else {
|
|
if (img) {
|
|
// Begin by clonning VM
|
|
|
|
// Submit request to clone VM
|
|
// webportal clonezlinux [src node] [group] [owner]
|
|
var iframe = createIFrame('lib/srv_cmd.php?cmd=webportal&tgt=&args=clonezlinux;' + img + ';' + group + ';' + owner + '&msg=&opts=flush');
|
|
iframe.prependTo($('#zvmProvisionTab'));
|
|
} else {
|
|
// Begin by creating VM
|
|
createzVM(tabId, group, hcp, tmpl, owner);
|
|
}
|
|
}
|
|
});
|
|
provForm.append(provisionBtn);
|
|
|
|
// Load zVMs, groups, template, and image into their respective columns
|
|
loadSrvGroups(groupCol);
|
|
loadOSImages(tmplCol);
|
|
loadGoldenImages(imgCol);
|
|
|
|
// Get zVM host names
|
|
if (!$.cookie('zvms')){
|
|
$.ajax( {
|
|
url : 'lib/srv_cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'webportal',
|
|
tgt : '',
|
|
args : 'lszvm',
|
|
msg : ''
|
|
},
|
|
|
|
success : function(data) {
|
|
setzVMCookies(data);
|
|
loadzVMs(zvmCol);
|
|
}
|
|
});
|
|
} else {
|
|
loadzVMs(zvmCol);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Show node inventory (service page)
|
|
*
|
|
* @param data Data from HTTP request
|
|
*/
|
|
zvmPlugin.prototype.loadServiceInventory = function(data) {
|
|
var args = data.msg.split(',');
|
|
|
|
// Get tab ID
|
|
var tabId = args[0].replace('out=', '');
|
|
// Get node
|
|
var node = args[1].replace('node=', '');
|
|
|
|
// Remove loader
|
|
$('#' + tabId).find('img').remove();
|
|
|
|
// Do not continue if error is found
|
|
if (data.rsp[0].indexOf('Error') > -1) {
|
|
var warn = createWarnBar(data.rsp[0]);
|
|
$('#' + tabId).append(warn);
|
|
return;
|
|
}
|
|
|
|
// Get node inventory
|
|
var inv = data.rsp[0].split(node + ':');
|
|
|
|
// Create array of property keys (VM)
|
|
var keys = new Array('userId', 'host', 'os', 'arch', 'uptime', 'cpuusedtime', 'hcp', 'priv', 'memory', 'maxmemory', 'proc', 'disk', 'zfcp', 'nic');
|
|
|
|
// Create hash table for property names (VM)
|
|
var attrNames = new Object();
|
|
attrNames['userId'] = 'z/VM UserID:';
|
|
attrNames['host'] = 'z/VM Host:';
|
|
attrNames['os'] = 'Operating System:';
|
|
attrNames['arch'] = 'Architecture:';
|
|
attrNames['uptime'] = 'Uptime:';
|
|
attrNames['cpuusedtime'] = 'CPU Used Time:';
|
|
attrNames['hcp'] = 'HCP:';
|
|
attrNames['priv'] = 'Privileges:';
|
|
attrNames['memory'] = 'Total Memory:';
|
|
attrNames['maxmemory'] = 'Max Memory:';
|
|
attrNames['proc'] = 'Processors:';
|
|
attrNames['disk'] = 'Disks:';
|
|
attrNames['zfcp'] = 'zFCP:';
|
|
attrNames['nic'] = 'NICs:';
|
|
|
|
// Create hash table for node attributes
|
|
var attrs = getAttrs(keys, attrNames, inv);
|
|
|
|
// Create division to hold inventory
|
|
var invDivId = node + 'Inventory';
|
|
var invDiv = $('<div class="inventory" id="' + invDivId + '"></div>');
|
|
|
|
var infoBar = createInfoBar('Below is the inventory for the virtual machine you selected.');
|
|
invDiv.append(infoBar);
|
|
|
|
/**
|
|
* General info section
|
|
*/
|
|
var fieldSet = $('<fieldset></fieldset>');
|
|
var legend = $('<legend>General</legend>');
|
|
fieldSet.append(legend);
|
|
var oList = $('<ol></ol>');
|
|
var item, label, args;
|
|
|
|
// Loop through each property
|
|
for ( var k = 0; k < 5; k++) {
|
|
// Create a list item for each property
|
|
item = $('<li></li>');
|
|
|
|
// Create a label - Property name
|
|
label = $('<label>' + attrNames[keys[k]] + '</label>');
|
|
item.append(label);
|
|
|
|
for ( var l = 0; l < attrs[keys[k]].length; l++) {
|
|
// Create a input - Property value(s)
|
|
// Handle each property uniquely
|
|
item.append(attrs[keys[k]][l]);
|
|
}
|
|
|
|
oList.append(item);
|
|
}
|
|
// Append to inventory form
|
|
fieldSet.append(oList);
|
|
invDiv.append(fieldSet);
|
|
|
|
/**
|
|
* Monitoring section
|
|
*/
|
|
fieldSet = $('<fieldset id="' + node + '_monitor"></fieldset>');
|
|
legend = $('<legend>Monitoring [<a style="font-weight: normal; color: blue; text-decoration: none;">Refresh</a>]</legend>');
|
|
fieldSet.append(legend);
|
|
// var info = createInfoBar('No data available');
|
|
// fieldSet.append(info.css('width', '300px'));
|
|
|
|
getMonitorMetrics(node);
|
|
|
|
// Refresh monitoring charts on-click
|
|
legend.find('a').click(function() {
|
|
getMonitorMetrics(node);
|
|
});
|
|
|
|
// Append to inventory form
|
|
invDiv.append(fieldSet);
|
|
|
|
/**
|
|
* Hardware info section
|
|
*/
|
|
var hwList, hwItem;
|
|
fieldSet = $('<fieldset></fieldset>');
|
|
legend = $('<legend>Hardware</legent>');
|
|
fieldSet.append(legend);
|
|
oList = $('<ol></ol>');
|
|
|
|
// Loop through each property
|
|
var label;
|
|
for (k = 5; k < keys.length; k++) {
|
|
// Create a list item
|
|
item = $('<li></li>');
|
|
|
|
// Create a list to hold the property value(s)
|
|
hwList = $('<ul></ul>');
|
|
hwItem = $('<li></li>');
|
|
|
|
/**
|
|
* Privilege section
|
|
*/
|
|
if (keys[k] == 'priv') {
|
|
// Create a label - Property name
|
|
label = $('<label><b>' + attrNames[keys[k]].replace(':', '') + '</b></label>');
|
|
item.append(label);
|
|
|
|
// Loop through each line
|
|
for (l = 0; l < attrs[keys[k]].length; l++) {
|
|
// Create a new list item for each line
|
|
hwItem = $('<li></li>');
|
|
|
|
// Determine privilege
|
|
args = attrs[keys[k]][l].split(' ');
|
|
if (args[0] == 'Directory:') {
|
|
label = $('<label>' + args[0] + '</label>');
|
|
hwItem.append(label);
|
|
hwItem.append(args[1]);
|
|
} else if (args[0] == 'Currently:') {
|
|
label = $('<label>' + args[0] + '</label>');
|
|
hwItem.append(label);
|
|
hwItem.append(args[1]);
|
|
}
|
|
|
|
hwList.append(hwItem);
|
|
}
|
|
|
|
item.append(hwList);
|
|
}
|
|
|
|
/**
|
|
* Memory section
|
|
*/
|
|
else if (keys[k] == 'memory') {
|
|
// Create a label - Property name
|
|
label = $('<label><b>' + attrNames[keys[k]].replace(':', '') + '</b></label>');
|
|
item.append(label);
|
|
|
|
// Loop through each value line
|
|
for (l = 0; l < attrs[keys[k]].length; l++) {
|
|
// Create a new list item for each line
|
|
hwItem = $('<li></li>');
|
|
hwItem.append(attrs[keys[k]][l]);
|
|
hwList.append(hwItem);
|
|
}
|
|
|
|
item.append(hwList);
|
|
}
|
|
|
|
/**
|
|
* Processor section
|
|
*/
|
|
else if (keys[k] == 'proc') {
|
|
// Create a label - Property name
|
|
label = $('<label><b>' + attrNames[keys[k]].replace(':', '') + '</b></label>');
|
|
item.append(label);
|
|
|
|
// Create a table to hold processor data
|
|
var procTable = $('<table></table>');
|
|
var procBody = $('<tbody></tbody>');
|
|
|
|
// Table columns - Type, Address, ID, Base, Dedicated, and Affinity
|
|
var procTabRow = $('<thead class="ui-widget-header"> <th>Type</th> <th>Address</th> <th>ID</th> <th>Base</th> <th>Dedicated</th> <th>Affinity</th> </thead>');
|
|
procTable.append(procTabRow);
|
|
var procType, procAddr, procId, procAff;
|
|
|
|
// Loop through each processor
|
|
var n, temp;
|
|
for (l = 0; l < attrs[keys[k]].length; l++) {
|
|
if (attrs[keys[k]][l]) {
|
|
args = attrs[keys[k]][l].split(' ');
|
|
|
|
// Get processor type, address, ID, and affinity
|
|
n = 3;
|
|
temp = args[args.length - n];
|
|
while (!jQuery.trim(temp)) {
|
|
n = n + 1;
|
|
temp = args[args.length - n];
|
|
}
|
|
procType = $('<td>' + temp + '</td>');
|
|
procAddr = $('<td>' + args[1] + '</td>');
|
|
procId = $('<td>' + args[5] + '</td>');
|
|
procAff = $('<td>' + args[args.length - 1] + '</td>');
|
|
|
|
// Base processor
|
|
if (args[6] == '(BASE)') {
|
|
baseProc = $('<td>' + true + '</td>');
|
|
} else {
|
|
baseProc = $('<td>' + false + '</td>');
|
|
}
|
|
|
|
// Dedicated processor
|
|
if (args[args.length - 3] == 'DEDICATED') {
|
|
dedicatedProc = $('<td>' + true + '</td>');
|
|
} else {
|
|
dedicatedProc = $('<td>' + false + '</td>');
|
|
}
|
|
|
|
// Create a new row for each processor
|
|
procTabRow = $('<tr></tr>');
|
|
procTabRow.append(procType);
|
|
procTabRow.append(procAddr);
|
|
procTabRow.append(procId);
|
|
procTabRow.append(baseProc);
|
|
procTabRow.append(dedicatedProc);
|
|
procTabRow.append(procAff);
|
|
procBody.append(procTabRow);
|
|
}
|
|
}
|
|
|
|
procTable.append(procBody);
|
|
item.append(procTable);
|
|
}
|
|
|
|
/**
|
|
* Disk section
|
|
*/
|
|
else if (keys[k] == 'disk') {
|
|
// Create a label - Property name
|
|
label = $('<label><b>' + attrNames[keys[k]].replace(':', '') + '</b></label>');
|
|
item.append(label);
|
|
|
|
// Create a table to hold disk (DASD) data
|
|
var dasdTable = $('<table></table>');
|
|
var dasdBody = $('<tbody></tbody>');
|
|
|
|
// Table columns - Virtual Device, Type, VolID, Type of Access, and Size
|
|
var dasdTabRow = $('<thead class="ui-widget-header"> <th>Virtual Device #</th> <th>Type</th> <th>VolID</th> <th>Type of Access</th> <th>Size</th> </thead>');
|
|
dasdTable.append(dasdTabRow);
|
|
var dasdVDev, dasdType, dasdVolId, dasdAccess, dasdSize;
|
|
|
|
// Loop through each DASD
|
|
for (l = 0; l < attrs[keys[k]].length; l++) {
|
|
if (attrs[keys[k]][l]) {
|
|
args = attrs[keys[k]][l].split(' ');
|
|
|
|
// Get DASD virtual device, type, volume ID, access, and size
|
|
dasdVDev = $('<td>' + args[1] + '</td>');
|
|
dasdType = $('<td>' + args[2] + '</td>');
|
|
dasdVolId = $('<td>' + args[3] + '</td>');
|
|
dasdAccess = $('<td>' + args[4] + '</td>');
|
|
dasdSize = $('<td>' + args[args.length - 9] + ' ' + args[args.length - 8] + '</td>');
|
|
|
|
// Create a new row for each DASD
|
|
dasdTabRow = $('<tr></tr>');
|
|
dasdTabRow.append(dasdVDev);
|
|
dasdTabRow.append(dasdType);
|
|
dasdTabRow.append(dasdVolId);
|
|
dasdTabRow.append(dasdAccess);
|
|
dasdTabRow.append(dasdSize);
|
|
dasdBody.append(dasdTabRow);
|
|
}
|
|
}
|
|
|
|
dasdTable.append(dasdBody);
|
|
item.append(dasdTable);
|
|
}
|
|
|
|
/**
|
|
* zFCP section
|
|
*/
|
|
else if (keys[k] == 'zfcp') {
|
|
// Create a label - Property name
|
|
label = $('<label><b>' + attrNames[keys[k]].replace(':', '') + '</b></label>');
|
|
item.append(label);
|
|
|
|
// Create a table to hold NIC data
|
|
var zfcpTable = $('<table></table>');
|
|
var zfcpBody = $('<tbody></tbody>');
|
|
|
|
// Table columns - Virtual device, Adapter Type, Port Name, # of Devices, MAC Address, and LAN Name
|
|
var zfcpTabRow = $('<thead class="ui-widget-header"> <th>Virtual Device #</th> <th>Port Name</th> <th>Unit Number</th> <th>Size</th></thead>');
|
|
zfcpTable.append(zfcpTabRow);
|
|
var zfcpVDev, zfcpPortName, zfcpLun, zfcpSize;
|
|
|
|
// Loop through each zFCP device
|
|
if (attrs[keys[k]]) {
|
|
for (l = 0; l < attrs[keys[k]].length; l++) {
|
|
if (attrs[keys[k]][l]) {
|
|
args = attrs[keys[k]][l].split(' ');
|
|
|
|
// Get zFCP virtual device, port name (WWPN), unit number (LUN), and size
|
|
zfcpVDev = $('<td>' + args[1].replace('0.0.', '') + '</td>');
|
|
zfcpPortName = $('<td>' + args[4] + '</td>');
|
|
zfcpLun = $('<td>' + args[7] + '</td>');
|
|
zfcpSize = $('<td>' + args[args.length - 2] + ' ' + args[args.length - 1] + '</td>');
|
|
|
|
// Create a new row for each zFCP device
|
|
zfcpTabRow = $('<tr></tr>');
|
|
zfcpTabRow.append(zfcpVDev);
|
|
zfcpTabRow.append(zfcpPortName);
|
|
zfcpTabRow.append(zfcpLun);
|
|
zfcpTabRow.append(zfcpSize);
|
|
|
|
zfcpBody.append(zfcpTabRow);
|
|
}
|
|
}
|
|
}
|
|
|
|
zfcpTable.append(zfcpBody);
|
|
item.append(zfcpTable);
|
|
}
|
|
|
|
/**
|
|
* NIC section
|
|
*/
|
|
else if (keys[k] == 'nic') {
|
|
// Create a label - Property name
|
|
label = $('<label><b>' + attrNames[keys[k]].replace(':', '') + '</b></label>');
|
|
item.append(label);
|
|
|
|
// Create a table to hold NIC data
|
|
var nicTable = $('<table></table>');
|
|
var nicBody = $('<tbody></tbody>');
|
|
|
|
// Table columns - Virtual device, Adapter Type, Port Name, # of Devices, MAC Address, and LAN Name
|
|
var nicTabRow = $('<thead class="ui-widget-header"><th>Virtual Device #</th> <th>Adapter Type</th> <th>Port Name</th> <th># of Devices</th> <th>LAN Name</th></thead>');
|
|
nicTable.append(nicTabRow);
|
|
var nicVDev, nicType, nicPortName, nicNumOfDevs, nicLanName;
|
|
|
|
// Loop through each NIC (Data contained in 2 lines)
|
|
for (l = 0; l < attrs[keys[k]].length; l++) {
|
|
if (attrs[keys[k]][l].indexOf('Adapter') != -1) {
|
|
args = attrs[keys[k]][l].split(' ');
|
|
|
|
// Get NIC virtual device, type, port name, and number of devices
|
|
nicVDev = $('<td>' + args[1] + '</td>');
|
|
nicType = $('<td>' + args[3] + '</td>');
|
|
nicPortName = $('<td>' + args[10] + '</td>');
|
|
nicNumOfDevs = $('<td>' + args[args.length - 1] + '</td>');
|
|
|
|
args = attrs[keys[k]][l + 1].split(' ');
|
|
nicLanName = $('<td>' + args[args.length - 2] + ' ' + args[args.length - 1] + '</td>');
|
|
|
|
// Create a new row for each DASD
|
|
nicTabRow = $('<tr></tr>');
|
|
nicTabRow.append(nicVDev);
|
|
nicTabRow.append(nicType);
|
|
nicTabRow.append(nicPortName);
|
|
nicTabRow.append(nicNumOfDevs);
|
|
nicTabRow.append(nicLanName);
|
|
|
|
nicBody.append(nicTabRow);
|
|
}
|
|
}
|
|
|
|
nicTable.append(nicBody);
|
|
item.append(nicTable);
|
|
}
|
|
|
|
// Ignore any fields not in key
|
|
else {
|
|
continue;
|
|
}
|
|
|
|
oList.append(item);
|
|
}
|
|
|
|
// Append inventory to division
|
|
fieldSet.append(oList);
|
|
invDiv.append(fieldSet);
|
|
invDiv.find('th').css({
|
|
'padding': '5px 10px',
|
|
'font-weight': 'bold'
|
|
});
|
|
|
|
// Append to tab
|
|
$('#' + tabId).append(invDiv);
|
|
};
|
|
|
|
/**
|
|
* Load clone page
|
|
*
|
|
* @param node Source node to clone
|
|
*/
|
|
zvmPlugin.prototype.loadClonePage = function(node) {
|
|
// Get nodes tab
|
|
var tab = getNodesTab();
|
|
var newTabId = node + 'CloneTab';
|
|
|
|
// If there is no existing clone tab
|
|
if (!$('#' + newTabId).length) {
|
|
// Get table headers
|
|
var tableId = $('#' + node).parents('table').attr('id');
|
|
var headers = $('#' + tableId).parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th');
|
|
var cols = new Array();
|
|
for ( var i = 0; i < headers.length; i++) {
|
|
var col = headers.eq(i).text();
|
|
cols.push(col);
|
|
}
|
|
|
|
// Get hardware control point column
|
|
var hcpCol = $.inArray('hcp', cols);
|
|
|
|
// Get hardware control point
|
|
var nodeRow = $('#' + node).parent().parent();
|
|
var datatable = $('#' + getNodesTableId()).dataTable();
|
|
var rowPos = datatable.fnGetPosition(nodeRow.get(0));
|
|
var aData = datatable.fnGetData(rowPos);
|
|
var hcp = aData[hcpCol];
|
|
|
|
// Create status bar and hide it
|
|
var statBarId = node + 'CloneStatusBar';
|
|
var statBar = createStatusBar(statBarId).hide();
|
|
|
|
// Create info bar
|
|
var infoBar = createInfoBar('Clone a zVM node.');
|
|
|
|
// Create clone form
|
|
var cloneForm = $('<div class="form"></div>');
|
|
cloneForm.append(statBar);
|
|
cloneForm.append(infoBar);
|
|
|
|
// Create VM fieldset
|
|
var vmFS = $('<fieldset></fieldset>');
|
|
var vmLegend = $('<legend>Virtual Machine</legend>');
|
|
vmFS.append(vmLegend);
|
|
cloneForm.append(vmFS);
|
|
|
|
var vmAttr = $('<div style="display: inline-table; vertical-align: middle;"></div>');
|
|
vmFS.append($('<div style="display: inline-table; vertical-align: middle;"><img src="images/provision/computer.png"></img></div>'));
|
|
vmFS.append(vmAttr);
|
|
|
|
// Create hardware fieldset
|
|
var storageFS = $('<fieldset></fieldset>');
|
|
var storageLegend = $('<legend>Storage</legend>');
|
|
storageFS.append(storageLegend);
|
|
cloneForm.append(storageFS);
|
|
|
|
var storageAttr = $('<div style="display: inline-table; vertical-align: middle;"></div>');
|
|
storageFS.append($('<div style="display: inline-table; vertical-align: middle;"><img src="images/provision/hdd.png"></img></div>'));
|
|
storageFS.append(storageAttr);
|
|
|
|
vmAttr.append('<div><label>Target node range:</label><input type="text" id="tgtNode" name="tgtNode" title="You must give a node or a node range. A node range must be given as: node1-node9 or node[1-9]."/></div>');
|
|
vmAttr.append('<div><label>Target user ID range:</label><input type="text" id="tgtUserId" name="tgtUserId" title="You must give a user ID or a user ID range. A user ID range must be given as: user1-user9 or user[1-9]."/></div>');
|
|
vmAttr.append('<div><label>Clone source:</label><input type="text" id="srcNode" name="srcNode" readonly="readonly" value="' + node + '" title="The source node to be cloned"/></div>');
|
|
vmAttr.append('<div><label>Hardware control point:</label><input type="text" id="newHcp" name="newHcp" readonly="readonly" value="' + hcp + '" title="The System z hardware control point (zHCP) responsible for managing the node(s). It must be the same as the source node."/></div>');
|
|
|
|
// Create group input
|
|
var group = $('<div></div>');
|
|
var groupLabel = $('<label>Group:</label>');
|
|
var groupInput = $('<input type="text" id="newGroup" name="newGroup" title="You must give the group where the new node(s) will be placed under."/>');
|
|
groupInput.one('focus', function(){
|
|
var groupNames = $.cookie('groups');
|
|
if (groupNames) {
|
|
// Turn on auto complete
|
|
$(this).autocomplete({
|
|
source: groupNames.split(',')
|
|
});
|
|
}
|
|
});
|
|
group.append(groupLabel);
|
|
group.append(groupInput);
|
|
vmAttr.append(group);
|
|
|
|
// Create an advanced link to set IP address and hostname
|
|
var advancedLnk = $('<div><label><a style="color: blue; cursor: pointer;">Advanced</a></label></div>');
|
|
vmAttr.append(advancedLnk);
|
|
var advanced = $('<div style="margin-left: 20px;"></div>').hide();
|
|
vmAttr.append(advanced);
|
|
|
|
var ip = $('<div><label>IP address range:</label><input type="text" name="ip" ' +
|
|
'title="Optional. Specify the IP address range that will be assigned to these nodes. An IP address range must be given in the following format: 192.168.0.1-192.168.9."/></div>');
|
|
advanced.append(ip);
|
|
var hostname = $('<div><label>Hostname range:</label><input type="text" name="hostname" ' +
|
|
'title="Optional. Specify the hostname range that will be assigned to these node. A hostname range must be given in the following format: ihost1.sourceforge.net-ihost9.sourceforge.net."/></div>');
|
|
advanced.append(hostname);
|
|
|
|
// Show IP address and hostname inputs on-click
|
|
advancedLnk.click(function() {
|
|
advanced.toggle();
|
|
});
|
|
|
|
// Get list of disk pools
|
|
var temp = hcp.split('.');
|
|
var diskPools = $.cookie(temp[0] + 'diskpools');
|
|
|
|
// Create disk pool input
|
|
var poolDiv = $('<div></div>');
|
|
var poolLabel = $('<label>Disk pool:</label>');
|
|
var poolInput = $('<input type="text" id="diskPool" name="diskPool" title="You must give a disk pool. xCAT relies on DirMaint to allocate minidisks out of a pool of DASD volumes. These DASD volume pools are defined in the EXTENT CONTROL file."/>').autocomplete({
|
|
source: diskPools.split(',')
|
|
});
|
|
poolDiv.append(poolLabel);
|
|
poolDiv.append(poolInput);
|
|
storageAttr.append(poolDiv);
|
|
|
|
storageAttr.append('<div><label>Disk password:</label><input type="password" id="diskPw" name="diskPw" title="The password that will be used for accessing the disk. This input is optional."/></div>');
|
|
|
|
// Generate tooltips
|
|
cloneForm.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"
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Clone node
|
|
*/
|
|
var cloneBtn = createButton('Clone');
|
|
cloneBtn.bind('click', function(event) {
|
|
// Remove any warning messages
|
|
$(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
|
|
|
|
var ready = true;
|
|
var errMsg = '';
|
|
|
|
// Check node name, userId, hardware control point, group, and password
|
|
var inputs = $('#' + newTabId + ' input');
|
|
for ( var i = 0; i < inputs.length; i++) {
|
|
if (!inputs.eq(i).val()
|
|
&& inputs.eq(i).attr('name') != 'diskPw'
|
|
&& inputs.eq(i).attr('name') != 'diskPool'
|
|
&& inputs.eq(i).attr('name') != 'ip'
|
|
&& inputs.eq(i).attr('name') != 'hostname') {
|
|
inputs.eq(i).css('border', 'solid #FF0000 1px');
|
|
ready = false;
|
|
} else {
|
|
inputs.eq(i).css('border', 'solid #BDBDBD 1px');
|
|
}
|
|
}
|
|
|
|
// Write error message
|
|
if (!ready) {
|
|
errMsg = errMsg + 'Please provide a value for each missing field.<br>';
|
|
}
|
|
|
|
// Get target node
|
|
var nodeRange = $('#' + newTabId + ' input[name=tgtNode]').val();
|
|
// Get target user ID
|
|
var userIdRange = $('#' + newTabId + ' input[name=tgtUserId]').val();
|
|
// Get IP address range
|
|
var ipRange = $('#' + newTabId + ' input[name=ip]').val();
|
|
// Get hostname range
|
|
var hostnameRange = $('#' + newTabId + ' input[name=hostname]').val();
|
|
|
|
// Check node range and user ID range
|
|
if (nodeRange.indexOf('-') > -1 || userIdRange.indexOf('-') > -1 || ipRange.indexOf('-') > -1 || hostnameRange.indexOf('-') > -1) {
|
|
if (nodeRange.indexOf('-') < 0 || userIdRange.indexOf('-') < 0) {
|
|
errMsg = errMsg + 'A user ID range and node range needs to be given.<br>';
|
|
ready = false;
|
|
} else {
|
|
var tmp = nodeRange.split('-');
|
|
|
|
// Get node base name
|
|
var nodeBase = tmp[0].match(/[a-zA-Z]+/);
|
|
// Get starting index
|
|
var nodeStart = parseInt(tmp[0].match(/\d+/));
|
|
// Get ending index
|
|
var nodeEnd = parseInt(tmp[1].match(/\d+/));
|
|
|
|
tmp = userIdRange.split('-');
|
|
|
|
// Get user ID base name
|
|
var userIdBase = tmp[0].match(/[a-zA-Z]+/);
|
|
// Get starting index
|
|
var userIdStart = parseInt(tmp[0].match(/\d+/));
|
|
// Get ending index
|
|
var userIdEnd = parseInt(tmp[1].match(/\d+/));
|
|
|
|
var ipStart = "", ipEnd = "";
|
|
if (ipRange) {
|
|
tmp = ipRange.split('-');
|
|
|
|
// Get starting IP address
|
|
ipStart = tmp[0].substring(tmp[0].lastIndexOf(".") + 1);
|
|
// Get ending IP address
|
|
ipEnd = tmp[1].substring(tmp[1].lastIndexOf(".") + 1);
|
|
}
|
|
|
|
var hostnameStart = "", hostnameEnd = "";
|
|
if (hostnameRange) {
|
|
tmp = hostnameRange.split('-');
|
|
|
|
// Get starting hostname
|
|
hostnameStart = parseInt(tmp[0].substring(0, tmp[0].indexOf(".")).match(/\d+/));
|
|
// Get ending hostname
|
|
hostnameEnd = parseInt(tmp[1].substring(0, tmp[1].indexOf(".")).match(/\d+/));
|
|
}
|
|
|
|
// If starting and ending index do not match
|
|
if (!(nodeStart == userIdStart) || !(nodeEnd == userIdEnd)) {
|
|
// Not ready to provision
|
|
errMsg = errMsg + 'The node range and user ID range does not match.<br>';
|
|
ready = false;
|
|
}
|
|
|
|
// If an IP address range is given and the starting and ending index do not match
|
|
if (ipRange && (!(nodeStart == ipStart) || !(nodeEnd == ipEnd))) {
|
|
errMsg = errMsg + 'The node range and IP address range does not match. ';
|
|
ready = false;
|
|
}
|
|
|
|
// If a hostname range is given and the starting and ending index do not match
|
|
if (hostnameRange && (!(nodeStart == hostnameStart) || !(nodeEnd == hostnameEnd))) {
|
|
errMsg = errMsg + 'The node range and hostname range does not match. ';
|
|
ready = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get source node, hardware control point, group, disk pool, and disk password
|
|
var srcNode = $('#' + newTabId + ' input[name=srcNode]').val();
|
|
var hcp = $('#' + newTabId + ' input[name=newHcp]').val();
|
|
var group = $('#' + newTabId + ' input[name=newGroup]').val();
|
|
var diskPool = $('#' + newTabId + ' input[name=diskPool]').val();
|
|
var diskPw = $('#' + newTabId + ' input[name=diskPw]').val();
|
|
|
|
// If a value is given for every input
|
|
if (ready) {
|
|
// Disable all inputs
|
|
var inputs = $('#' + newTabId + ' input');
|
|
inputs.attr('disabled', 'disabled');
|
|
|
|
// If a node range is given
|
|
if (nodeRange.indexOf('-') > -1) {
|
|
var tmp = nodeRange.split('-');
|
|
|
|
// Get node base name
|
|
var nodeBase = tmp[0].match(/[a-zA-Z]+/);
|
|
// Get starting index
|
|
var nodeStart = parseInt(tmp[0].match(/\d+/));
|
|
// Get ending index
|
|
var nodeEnd = parseInt(tmp[1].match(/\d+/));
|
|
|
|
tmp = userIdRange.split('-');
|
|
|
|
// Get user ID base name
|
|
var userIdBase = tmp[0].match(/[a-zA-Z]+/);
|
|
|
|
var ipBase = "";
|
|
if (ipRange) {
|
|
tmp = ipRange.split('-');
|
|
|
|
// Get network base
|
|
ipBase = tmp[0].substring(0, tmp[0].lastIndexOf(".") + 1);
|
|
}
|
|
|
|
var domain = "";
|
|
if (hostnameRange) {
|
|
tmp = hostnameRange.split('-');
|
|
|
|
// Get domain name
|
|
domain = tmp[0].substring(tmp[0].indexOf("."));
|
|
}
|
|
|
|
// Loop through each node in the node range
|
|
for ( var i = nodeStart; i <= nodeEnd; i++) {
|
|
var node = nodeBase + i.toString();
|
|
var userId = userIdBase + i.toString();
|
|
var inst = i + '/' + nodeEnd;
|
|
|
|
var args = node
|
|
+ ';zvm.hcp=' + hcp
|
|
+ ';zvm.userid=' + userId
|
|
+ ';nodehm.mgt=zvm'
|
|
+ ';groups=' + group;
|
|
|
|
if (ipRange) {
|
|
var ip = ipBase + i.toString();
|
|
args += ';hosts.ip=' + ip;
|
|
}
|
|
|
|
if (hostnameRange) {
|
|
var hostname = node + domain;
|
|
args += ';hosts.hostnames=' + hostname;
|
|
}
|
|
|
|
/**
|
|
* (1) Define node
|
|
*/
|
|
$.ajax( {
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'nodeadd',
|
|
tgt : '',
|
|
args : args,
|
|
msg : 'cmd=nodeadd;inst=' + inst
|
|
+ ';out=' + statBarId
|
|
+ ';node=' + node
|
|
},
|
|
|
|
success : updateZCloneStatus
|
|
});
|
|
}
|
|
} else {
|
|
var args = nodeRange
|
|
+ ';zvm.hcp=' + hcp
|
|
+ ';zvm.userid=' + userIdRange
|
|
+ ';nodehm.mgt=zvm'
|
|
+ ';groups=' + group;
|
|
|
|
if (ipRange)
|
|
args += ';hosts.ip=' + ipRange;
|
|
|
|
if (hostnameRange)
|
|
args += ';hosts.hostnames=' + hostnameRange;
|
|
|
|
/**
|
|
* (1) Define node
|
|
*/
|
|
$.ajax( {
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'nodeadd',
|
|
tgt : '',
|
|
args : args,
|
|
msg : 'cmd=nodeadd;inst=1/1;out=' + statBarId
|
|
+ ';node=' + nodeRange
|
|
},
|
|
|
|
success : updateZCloneStatus
|
|
});
|
|
}
|
|
|
|
// Create loader
|
|
$('#' + statBarId).find('div').append(createLoader());
|
|
$('#' + statBarId).show();
|
|
|
|
// Disable clone button
|
|
$(this).attr('disabled', 'true');
|
|
} else {
|
|
// Show warning message
|
|
var warn = createWarnBar(errMsg);
|
|
warn.prependTo($(this).parent().parent());
|
|
}
|
|
});
|
|
cloneForm.append(cloneBtn);
|
|
|
|
// Add clone tab
|
|
tab.add(newTabId, 'Clone', cloneForm, true);
|
|
}
|
|
|
|
tab.select(newTabId);
|
|
};
|
|
|
|
/**
|
|
* Load node inventory
|
|
*
|
|
* @param data Data from HTTP request
|
|
*/
|
|
zvmPlugin.prototype.loadInventory = function(data) {
|
|
var args = data.msg.split(',');
|
|
|
|
// Get tab ID
|
|
var tabId = args[0].replace('out=', '');
|
|
// Get node
|
|
var node = args[1].replace('node=', '');
|
|
// Clear any existing cookie
|
|
$.cookie(node + 'processes', null);
|
|
|
|
// Remove loader
|
|
$('#' + tabId).find('img').remove();
|
|
|
|
// Check for error
|
|
var error = false;
|
|
if (data.rsp.length && data.rsp[0].indexOf('Error') > -1) {
|
|
error = true;
|
|
|
|
var warn = createWarnBar(data.rsp[0]);
|
|
$('#' + tabId).append(warn);
|
|
}
|
|
|
|
// Determine the node type
|
|
if (data.rsp.length && data.rsp[0].indexOf('Hypervisor OS:') > -1) {
|
|
loadHypervisorInventory(data);
|
|
return;
|
|
}
|
|
|
|
// Create status bar
|
|
var statBarId = node + 'StatusBar';
|
|
var statBar = createStatusBar(statBarId);
|
|
|
|
// Add loader to status bar and hide it
|
|
var loader = createLoader(node + 'StatusBarLoader').hide();
|
|
statBar.find('div').append(loader);
|
|
statBar.hide();
|
|
|
|
// Create division to hold user entry
|
|
var ueDivId = node + 'UserEntry';
|
|
var ueDiv = $('<div class="userEntry" id="' + ueDivId + '"></div>');
|
|
|
|
// Create division to hold inventory
|
|
var invDivId = node + 'Inventory';
|
|
var invDiv = $('<div class="inventory" id="' + invDivId + '"></div>');
|
|
|
|
/**
|
|
* Show user entry
|
|
*/
|
|
var toggleLinkId = node + 'ToggleLink';
|
|
var toggleLink = $('<a style="color: blue;" id="' + toggleLinkId + '">Show directory entry</a>');
|
|
toggleLink.one('click', function(event) {
|
|
// Toggle inventory division
|
|
$('#' + invDivId).toggle();
|
|
|
|
// Create loader
|
|
var loader = createLoader(node + 'TabLoader');
|
|
loader = $('<center></center>').append(loader);
|
|
ueDiv.append(loader);
|
|
|
|
// Get user entry
|
|
var msg = 'out=' + ueDivId + ';node=' + node;
|
|
$.ajax( {
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'lsvm',
|
|
tgt : node,
|
|
args : '',
|
|
msg : msg
|
|
},
|
|
|
|
success : loadUserEntry
|
|
});
|
|
|
|
// Change text
|
|
$(this).text('Show inventory');
|
|
|
|
// Disable toggle link
|
|
$(this).unbind(event);
|
|
});
|
|
|
|
// Align toggle link to the right
|
|
var toggleLnkDiv = $('<div class="toggle"></div>').css({
|
|
'text-align' : 'right'
|
|
});
|
|
toggleLnkDiv.append(toggleLink);
|
|
|
|
// Append to tab
|
|
$('#' + tabId).append(statBar);
|
|
$('#' + tabId).append(toggleLnkDiv);
|
|
$('#' + tabId).append(ueDiv);
|
|
$('#' + tabId).append(invDiv);
|
|
|
|
// Do not load inventory if no inventory is returned
|
|
if (data.rsp.length && data.rsp[0].indexOf('z/VM UserID:') > -1) {
|
|
// Do nothing
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
// Create array of property keys (VM)
|
|
var keys = new Array('userId', 'host', 'os', 'arch', 'uptime', 'cpuusedtime', 'hcp', 'priv', 'memory', 'maxmemory', 'proc', 'disk', 'zfcp', 'nic');
|
|
|
|
// Create hash table for property names (VM)
|
|
var attrNames = new Object();
|
|
attrNames['userId'] = 'z/VM UserID:';
|
|
attrNames['host'] = 'z/VM Host:';
|
|
attrNames['os'] = 'Operating System:';
|
|
attrNames['arch'] = 'Architecture:';
|
|
attrNames['uptime'] = 'Uptime:';
|
|
attrNames['cpuusedtime'] = 'CPU Used Time:';
|
|
attrNames['hcp'] = 'HCP:';
|
|
attrNames['priv'] = 'Privileges:';
|
|
attrNames['memory'] = 'Total Memory:';
|
|
attrNames['maxmemory'] = 'Max Memory:';
|
|
attrNames['proc'] = 'Processors:';
|
|
attrNames['disk'] = 'Disks:';
|
|
attrNames['zfcp'] = 'zFCP:';
|
|
attrNames['nic'] = 'NICs:';
|
|
|
|
// Create hash table for node attributes
|
|
var inv = data.rsp[0].split(node + ':');
|
|
var attrs;
|
|
if (!error) {
|
|
attrs = getAttrs(keys, attrNames, inv);
|
|
}
|
|
|
|
// Do not continue if error
|
|
if (error) {
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* General info section
|
|
*/
|
|
var fieldSet = $('<fieldset></fieldset>');
|
|
var legend = $('<legend>General</legend>');
|
|
fieldSet.append(legend);
|
|
var oList = $('<ol></ol>');
|
|
var item, label, args;
|
|
|
|
// Loop through each property
|
|
for (var k = 0; k < 6; k++) {
|
|
// Create a list item for each property
|
|
item = $('<li></li>');
|
|
|
|
// Create a label - Property name
|
|
label = $('<label>' + attrNames[keys[k]] + '</label>');
|
|
item.append(label);
|
|
|
|
for (var l = 0; l < attrs[keys[k]].length; l++) {
|
|
// Create a input - Property value(s)
|
|
// Handle each property uniquely
|
|
item.append(attrs[keys[k]][l]);
|
|
}
|
|
|
|
oList.append(item);
|
|
}
|
|
// Append to inventory form
|
|
fieldSet.append(oList);
|
|
invDiv.append(fieldSet);
|
|
|
|
/**
|
|
* Hardware info section
|
|
*/
|
|
var hwList, hwItem;
|
|
fieldSet = $('<fieldset></fieldset>');
|
|
legend = $('<legend>Hardware</legent>');
|
|
fieldSet.append(legend);
|
|
oList = $('<ol></ol>');
|
|
|
|
// Loop through each property
|
|
var label;
|
|
for (k = 6; k < keys.length; k++) {
|
|
// Create a list item
|
|
item = $('<li></li>');
|
|
|
|
// Create a list to hold the property value(s)
|
|
hwList = $('<ul></ul>');
|
|
hwItem = $('<li></li>');
|
|
|
|
/**
|
|
* Privilege section
|
|
*/
|
|
if (keys[k] == 'priv') {
|
|
// Create a label - Property name
|
|
label = $('<label><b>' + attrNames[keys[k]].replace(':', '') + '</b></label>');
|
|
item.append(label);
|
|
|
|
// Loop through each line
|
|
for (l = 0; l < attrs[keys[k]].length; l++) {
|
|
// Create a new list item for each line
|
|
hwItem = $('<li></li>');
|
|
|
|
// Determine privilege
|
|
args = attrs[keys[k]][l].split(' ');
|
|
if (args[0] == 'Directory:') {
|
|
label = $('<label>' + args[0] + '</label>');
|
|
hwItem.append(label);
|
|
hwItem.append(args[1]);
|
|
} else if (args[0] == 'Currently:') {
|
|
label = $('<label>' + args[0] + '</label>');
|
|
hwItem.append(label);
|
|
hwItem.append(args[1]);
|
|
}
|
|
|
|
hwList.append(hwItem);
|
|
}
|
|
|
|
item.append(hwList);
|
|
}
|
|
|
|
/**
|
|
* Memory section
|
|
*/
|
|
else if (keys[k] == 'memory') {
|
|
// Create a label - Property name
|
|
label = $('<label><b>' + attrNames[keys[k]].replace(':', '') + '</b></label>');
|
|
item.append(label);
|
|
|
|
// Loop through each value line
|
|
for (l = 0; l < attrs[keys[k]].length; l++) {
|
|
// Create a new list item for each line
|
|
hwItem = $('<li></li>');
|
|
hwItem.append(attrs[keys[k]][l]);
|
|
hwList.append(hwItem);
|
|
}
|
|
|
|
item.append(hwList);
|
|
}
|
|
|
|
/**
|
|
* Processor section
|
|
*/
|
|
else if (keys[k] == 'proc') {
|
|
// Create a label - Property name
|
|
label = $('<label><b>' + attrNames[keys[k]].replace(':', '') + '</b></label>');
|
|
item.append(label);
|
|
|
|
// Create a table to hold processor data
|
|
var procTable = $('<table></table>');
|
|
var procBody = $('<tbody></tbody>');
|
|
var procFooter = $('<tfoot></tfoot>');
|
|
|
|
// Table columns - Type, Address, ID, Base, Dedicated, and Affinity
|
|
var procTabRow = $('<thead class="ui-widget-header"> <th>Type</th> <th>Address</th> <th>ID</th> <th>Base</th> <th>Dedicated</th> <th>Affinity</th> </thead>');
|
|
procTable.append(procTabRow);
|
|
var procId, procAff;
|
|
|
|
/**
|
|
* Remove processor
|
|
*/
|
|
var contextMenu = [{
|
|
'Remove' : function(menuItem, menu) {
|
|
var addr = $(this).text();
|
|
|
|
// Open dialog to confirm
|
|
var confirmDialog = $('<div><p>Are you sure you want to remove this processor?</p></div>');
|
|
confirmDialog.dialog({
|
|
title: "Confirm",
|
|
modal: true,
|
|
width: 300,
|
|
buttons: {
|
|
"Ok": function(){
|
|
removeProcessor(node, addr);
|
|
$(this).dialog("close");
|
|
},
|
|
"Cancel": function() {
|
|
$(this).dialog("close");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}];
|
|
|
|
// Loop through each processor
|
|
var n, temp;
|
|
var procType, procAddr, procLink;
|
|
for (l = 0; l < attrs[keys[k]].length; l++) {
|
|
if (attrs[keys[k]][l]) {
|
|
args = attrs[keys[k]][l].split(' ');
|
|
|
|
// Get processor type, address, ID, and affinity
|
|
n = 3;
|
|
temp = args[args.length - n];
|
|
while (!jQuery.trim(temp)) {
|
|
n = n + 1;
|
|
temp = args[args.length - n];
|
|
}
|
|
procType = $('<td>' + temp + '</td>');
|
|
procAddr = $('<td></td>');
|
|
procLink = $('<a>' + args[1] + '</a>');
|
|
|
|
// Append context menu to link
|
|
procLink.contextMenu(contextMenu, {
|
|
theme : 'vista'
|
|
});
|
|
|
|
procAddr.append(procLink);
|
|
procId = $('<td>' + args[5] + '</td>');
|
|
procAff = $('<td>' + args[args.length - 1] + '</td>');
|
|
|
|
// Base processor
|
|
if (args[6] == '(BASE)') {
|
|
baseProc = $('<td>' + true + '</td>');
|
|
} else {
|
|
baseProc = $('<td>' + false + '</td>');
|
|
}
|
|
|
|
// Dedicated processor
|
|
if (args[args.length - 3] == 'DEDICATED') {
|
|
dedicatedProc = $('<td>' + true + '</td>');
|
|
} else {
|
|
dedicatedProc = $('<td>' + false + '</td>');
|
|
}
|
|
|
|
// Create a new row for each processor
|
|
procTabRow = $('<tr></tr>');
|
|
procTabRow.append(procType);
|
|
procTabRow.append(procAddr);
|
|
procTabRow.append(procId);
|
|
procTabRow.append(baseProc);
|
|
procTabRow.append(dedicatedProc);
|
|
procTabRow.append(procAff);
|
|
procBody.append(procTabRow);
|
|
}
|
|
}
|
|
|
|
procTable.append(procBody);
|
|
|
|
/**
|
|
* Add processor
|
|
*/
|
|
var addProcLink = $('<a>+ Add temporary processor</a>');
|
|
addProcLink.bind('click', function(event) {
|
|
openAddProcDialog(node);
|
|
});
|
|
|
|
procFooter.append(addProcLink);
|
|
procTable.append(procFooter);
|
|
item.append(procTable);
|
|
}
|
|
|
|
/**
|
|
* Disk section
|
|
*/
|
|
else if (keys[k] == 'disk') {
|
|
// Create a label - Property name
|
|
label = $('<label><b>' + attrNames[keys[k]].replace(':', '') + '</b></label>');
|
|
item.append(label);
|
|
|
|
// Create a table to hold disk (DASD) data
|
|
var dasdTable = $('<table></table>');
|
|
var dasdBody = $('<tbody></tbody>');
|
|
var dasdFooter = $('<tfoot></tfoot>');
|
|
|
|
/**
|
|
* Remove disk
|
|
*/
|
|
contextMenu = [{
|
|
'Remove' : function(menuItem, menu) {
|
|
var addr = $(this).text();
|
|
|
|
// Open dialog to confirm
|
|
var confirmDialog = $('<div><p>Are you sure you want to remove this disk?</p></div>');
|
|
confirmDialog.dialog({
|
|
title: "Confirm",
|
|
modal: true,
|
|
width: 300,
|
|
buttons: {
|
|
"Ok": function(){
|
|
removeDisk(node, addr);
|
|
$(this).dialog("close");
|
|
},
|
|
"Cancel": function() {
|
|
$(this).dialog("close");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}];
|
|
|
|
// Table columns - Virtual Device, Type, VolID, Type of Access, and Size
|
|
var dasdTabRow = $('<thead class="ui-widget-header"> <th>Virtual Device #</th> <th>Type</th> <th>VolID</th> <th>Type of Access</th> <th>Size</th> </thead>');
|
|
dasdTable.append(dasdTabRow);
|
|
var dasdVDev, dasdType, dasdVolId, dasdAccess, dasdSize;
|
|
|
|
// Loop through each DASD
|
|
for (l = 0; l < attrs[keys[k]].length; l++) {
|
|
if (attrs[keys[k]][l]) {
|
|
args = attrs[keys[k]][l].split(' ');
|
|
|
|
// Get DASD virtual device, type, volume ID, access, and size
|
|
dasdVDev = $('<td></td>');
|
|
dasdLink = $('<a>' + args[1] + '</a>');
|
|
|
|
// Append context menu to link
|
|
dasdLink.contextMenu(contextMenu, {
|
|
theme : 'vista'
|
|
});
|
|
dasdVDev.append(dasdLink);
|
|
|
|
dasdType = $('<td>' + args[2] + '</td>');
|
|
dasdVolId = $('<td>' + args[3] + '</td>');
|
|
dasdAccess = $('<td>' + args[4] + '</td>');
|
|
dasdSize = $('<td>' + args[args.length - 9] + ' ' + args[args.length - 8] + '</td>');
|
|
|
|
// Create a new row for each DASD
|
|
dasdTabRow = $('<tr></tr>');
|
|
dasdTabRow.append(dasdVDev);
|
|
dasdTabRow.append(dasdType);
|
|
dasdTabRow.append(dasdVolId);
|
|
dasdTabRow.append(dasdAccess);
|
|
dasdTabRow.append(dasdSize);
|
|
dasdBody.append(dasdTabRow);
|
|
}
|
|
}
|
|
|
|
dasdTable.append(dasdBody);
|
|
|
|
/**
|
|
* Add disk
|
|
*/
|
|
var addDasdLink = $('<a>+ Add disk</a>');
|
|
addDasdLink.bind('click', function(event) {
|
|
var hcp = attrs['hcp'][0].split('.');
|
|
openAddDiskDialog(node, hcp[0]);
|
|
});
|
|
dasdFooter.append(addDasdLink);
|
|
dasdTable.append(dasdFooter);
|
|
|
|
item.append(dasdTable);
|
|
}
|
|
|
|
/**
|
|
* zFCP section
|
|
*/
|
|
else if (keys[k] == 'zfcp') {
|
|
// Create a label - Property name
|
|
label = $('<label><b>' + attrNames[keys[k]].replace(':', '') + '</b></label>');
|
|
item.append(label);
|
|
|
|
// Create a table to hold NIC data
|
|
var zfcpTable = $('<table></table>');
|
|
var zfcpBody = $('<tbody></tbody>');
|
|
var zfcpFooter = $('<tfoot></tfoot>');
|
|
|
|
/**
|
|
* Remove zFCP
|
|
*/
|
|
contextMenu = [ {
|
|
'Remove' : function(menuItem, menu) {
|
|
var addr = $(this).text();
|
|
var portName = $(this).parents('tr').find('td:eq(1)').text();
|
|
var unitNo = $(this).parents('tr').find('td:eq(2)').text();
|
|
|
|
// Open dialog to confirm
|
|
var confirmDialog = $('<div><p>Are you sure you want to remove this zFCP device?</p></div>');
|
|
confirmDialog.dialog({
|
|
title: "Confirm",
|
|
modal: true,
|
|
width: 300,
|
|
buttons: {
|
|
"Ok": function(){
|
|
removeZfcp(node, addr, portName, unitNo);
|
|
$(this).dialog("close");
|
|
},
|
|
"Cancel": function() {
|
|
$(this).dialog("close");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
} ];
|
|
|
|
// Table columns - Virtual device, Adapter Type, Port Name, # of Devices, MAC Address, and LAN Name
|
|
var zfcpTabRow = $('<thead class="ui-widget-header"> <th>Virtual Device #</th> <th>Port Name</th> <th>Unit Number</th> <th>Size</th></thead>');
|
|
zfcpTable.append(zfcpTabRow);
|
|
var zfcpVDev, zfcpPortName, zfcpLun, zfcpSize;
|
|
|
|
// Loop through each zFCP device
|
|
if (attrs[keys[k]]) {
|
|
for (l = 0; l < attrs[keys[k]].length; l++) {
|
|
if (attrs[keys[k]][l]) {
|
|
args = attrs[keys[k]][l].split(' ');
|
|
|
|
// Get zFCP virtual device, port name (WWPN), unit number (LUN), and size
|
|
zfcpVDev = $('<td></td>');
|
|
zfcpLink = $('<a>' + args[1].replace('0.0.', '') + '</a>');
|
|
|
|
// Append context menu to link
|
|
zfcpLink.contextMenu(contextMenu, {
|
|
theme : 'vista'
|
|
});
|
|
zfcpVDev.append(zfcpLink);
|
|
|
|
zfcpPortName = $('<td>' + args[4] + '</td>');
|
|
zfcpLun = $('<td>' + args[7] + '</td>');
|
|
zfcpSize = $('<td>' + args[args.length - 2] + ' ' + args[args.length - 1] + '</td>');
|
|
|
|
// Create a new row for each zFCP device
|
|
zfcpTabRow = $('<tr></tr>');
|
|
zfcpTabRow.append(zfcpVDev);
|
|
zfcpTabRow.append(zfcpPortName);
|
|
zfcpTabRow.append(zfcpLun);
|
|
zfcpTabRow.append(zfcpSize);
|
|
|
|
zfcpBody.append(zfcpTabRow);
|
|
}
|
|
}
|
|
}
|
|
|
|
zfcpTable.append(zfcpBody);
|
|
|
|
/**
|
|
* Add dedicated device
|
|
*/
|
|
var dedicateDeviceLink = $('<a>+ Add dedicated device</a>').css('display', 'block');
|
|
dedicateDeviceLink.bind('click', function(event) {
|
|
var hcp = attrs['hcp'][0].split('.');
|
|
openDedicateDeviceDialog(node, hcp[0]);
|
|
});
|
|
|
|
/**
|
|
* Add zFCP device
|
|
*/
|
|
var addZfcpLink = $('<a>+ Add zFCP</a>').css('display', 'block');
|
|
addZfcpLink.bind('click', function(event) {
|
|
var hcp = attrs['hcp'][0].split('.');
|
|
var zvm = attrs['host'][0].toLowerCase();
|
|
openAddZfcpDialog(node, hcp[0], zvm);
|
|
});
|
|
|
|
zfcpFooter.append(dedicateDeviceLink, addZfcpLink);
|
|
zfcpTable.append(zfcpFooter);
|
|
|
|
item.append(zfcpTable);
|
|
}
|
|
|
|
/**
|
|
* NIC section
|
|
*/
|
|
else if (keys[k] == 'nic') {
|
|
// Create a label - Property name
|
|
label = $('<label><b>' + attrNames[keys[k]].replace(':', '') + '</b></label>');
|
|
item.append(label);
|
|
|
|
// Create a table to hold NIC data
|
|
var nicTable = $('<table></table>');
|
|
var nicBody = $('<tbody></tbody>');
|
|
var nicFooter = $('<tfoot></tfoot>');
|
|
|
|
/**
|
|
* Remove NIC
|
|
*/
|
|
contextMenu = [ {
|
|
'Remove' : function(menuItem, menu) {
|
|
var addr = $(this).text();
|
|
|
|
// Open dialog to confirm
|
|
var confirmDialog = $('<div><p>Are you sure you want to remove this NIC?</p></div>');
|
|
confirmDialog.dialog({
|
|
title: "Confirm",
|
|
modal: true,
|
|
width: 300,
|
|
buttons: {
|
|
"Ok": function(){
|
|
removeNic(node, addr);
|
|
$(this).dialog("close");
|
|
},
|
|
"Cancel": function() {
|
|
$(this).dialog("close");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
} ];
|
|
|
|
// Table columns - Virtual device, Adapter Type, Port Name, # of Devices, MAC Address, and LAN Name
|
|
var nicTabRow = $('<thead class="ui-widget-header"> <th>Virtual Device #</th> <th>Adapter Type</th> <th>Port Name</th> <th># of Devices</th> <th>LAN Name</th></thead>');
|
|
nicTable.append(nicTabRow);
|
|
var nicVDev, nicType, nicPortName, nicNumOfDevs, nicLanName;
|
|
|
|
// Loop through each NIC (Data contained in 2 lines)
|
|
for (l = 0; l < attrs[keys[k]].length; l++) {
|
|
if (attrs[keys[k]][l].indexOf('Adapter') != -1) {
|
|
args = attrs[keys[k]][l].split(' ');
|
|
|
|
// Get NIC virtual device, type, port name, and number of devices
|
|
nicVDev = $('<td></td>');
|
|
nicLink = $('<a>' + args[1] + '</a>');
|
|
|
|
// Append context menu to link
|
|
nicLink.contextMenu(contextMenu, {
|
|
theme : 'vista'
|
|
});
|
|
nicVDev.append(nicLink);
|
|
|
|
nicType = $('<td>' + args[3] + '</td>');
|
|
nicPortName = $('<td>' + args[10] + '</td>');
|
|
nicNumOfDevs = $('<td>' + args[args.length - 1] + '</td>');
|
|
|
|
args = attrs[keys[k]][l + 1].split(' ');
|
|
nicLanName = $('<td>' + args[args.length - 2] + ' ' + args[args.length - 1] + '</td>');
|
|
|
|
// Create a new row for each NIC
|
|
nicTabRow = $('<tr></tr>');
|
|
nicTabRow.append(nicVDev);
|
|
nicTabRow.append(nicType);
|
|
nicTabRow.append(nicPortName);
|
|
nicTabRow.append(nicNumOfDevs);
|
|
nicTabRow.append(nicLanName);
|
|
|
|
nicBody.append(nicTabRow);
|
|
}
|
|
}
|
|
|
|
nicTable.append(nicBody);
|
|
|
|
/**
|
|
* Add NIC
|
|
*/
|
|
var addNicLink = $('<a>+ Add NIC</a>');
|
|
addNicLink.bind('click', function(event) {
|
|
var hcp = attrs['hcp'][0].split('.');
|
|
openAddNicDialog(node, hcp[0]);
|
|
});
|
|
nicFooter.append(addNicLink);
|
|
nicTable.append(nicFooter);
|
|
|
|
item.append(nicTable);
|
|
}
|
|
|
|
// Ignore any fields not in key
|
|
else {
|
|
continue;
|
|
}
|
|
|
|
oList.append(item);
|
|
}
|
|
|
|
// Append inventory to division
|
|
fieldSet.append(oList);
|
|
invDiv.append(fieldSet);
|
|
};
|
|
|
|
/**
|
|
* Load hypervisor inventory
|
|
*
|
|
* @param data Data from HTTP request
|
|
*/
|
|
function loadHypervisorInventory(data) {
|
|
var args = data.msg.split(',');
|
|
|
|
// Get tab ID
|
|
var tabId = args[0].replace('out=', '');
|
|
// Get node
|
|
var node = args[1].replace('node=', '');
|
|
|
|
// Remove loader
|
|
$('#' + tabId).find('img').remove();
|
|
|
|
// Check for error
|
|
var error = false;
|
|
if (data.rsp.length && data.rsp[0].indexOf('Error') > -1) {
|
|
error = true;
|
|
|
|
var warn = createWarnBar(data.rsp[0]);
|
|
$('#' + tabId).append(warn);
|
|
}
|
|
|
|
// Get node inventory
|
|
var inv = data.rsp[0].split(node + ':');
|
|
|
|
// Create status bar
|
|
var statBarId = node + 'StatusBar';
|
|
var statBar = createStatusBar(statBarId);
|
|
|
|
// Add loader to status bar and hide it
|
|
var loader = createLoader(node + 'StatusBarLoader').hide();
|
|
statBar.find('div').append(loader);
|
|
statBar.hide();
|
|
|
|
// Create array of property keys (z/VM hypervisor)
|
|
var keys = new Array('host', 'hcp', 'arch', 'cecvendor', 'cecmodel', 'hypos', 'hypname', 'lparcputotal', 'lparcpuused', 'lparmemorytotal', 'lparmemoryused', 'lparmemoryoffline');
|
|
|
|
// Create hash table for property names (z/VM hypervisor)
|
|
var attrNames = new Object();
|
|
attrNames['host'] = 'z/VM Host:';
|
|
attrNames['hcp'] = 'zHCP:';
|
|
attrNames['arch'] = 'Architecture:';
|
|
attrNames['cecvendor'] = 'CEC Vendor:';
|
|
attrNames['cecmodel'] = 'CEC Model:';
|
|
attrNames['hypos'] = 'Hypervisor OS:';
|
|
attrNames['hypname'] = 'Hypervisor Name:';
|
|
attrNames['lparcputotal'] = 'LPAR CPU Total:';
|
|
attrNames['lparcpuused'] = 'LPAR CPU Used:';
|
|
attrNames['lparmemorytotal'] = 'LPAR Memory Total:';
|
|
attrNames['lparmemoryused'] = 'LPAR Memory Used:';
|
|
attrNames['lparmemoryoffline'] = 'LPAR Memory Offline:';
|
|
|
|
// Remove loader
|
|
$('#' + tabId).find('img').remove();
|
|
|
|
// Create hash table for node attributes
|
|
var attrs;
|
|
if (!error) {
|
|
attrs = getAttrs(keys, attrNames, inv);
|
|
}
|
|
|
|
// Create division to hold inventory
|
|
var invDivId = node + 'Inventory';
|
|
var invDiv = $('<div class="inventory" id="' + invDivId + '"></div>');
|
|
|
|
// Append to tab
|
|
$('#' + tabId).append(statBar);
|
|
$('#' + tabId).append(invDiv);
|
|
|
|
// Do not continue if error
|
|
if (error) {
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* General info section
|
|
*/
|
|
var fieldSet = $('<fieldset></fieldset>');
|
|
var legend = $('<legend>General</legend>');
|
|
fieldSet.append(legend);
|
|
var oList = $('<ol></ol>');
|
|
var item, label, args;
|
|
|
|
// Loop through each property
|
|
for (var k = 0; k < 7; k++) {
|
|
// Create a list item for each property
|
|
item = $('<li></li>');
|
|
|
|
// Create a label - Property name
|
|
label = $('<label>' + attrNames[keys[k]] + '</label>');
|
|
item.append(label);
|
|
|
|
for (var l = 0; l < attrs[keys[k]].length; l++) {
|
|
// Create a input - Property value(s)
|
|
// Handle each property uniquely
|
|
item.append(attrs[keys[k]][l]);
|
|
}
|
|
|
|
oList.append(item);
|
|
}
|
|
// Append to inventory form
|
|
fieldSet.append(oList);
|
|
invDiv.append(fieldSet);
|
|
|
|
/**
|
|
* Hardware info section
|
|
*/
|
|
var hwList, hwItem;
|
|
fieldSet = $('<fieldset></fieldset>');
|
|
legend = $('<legend>Hardware</legent>');
|
|
fieldSet.append(legend);
|
|
oList = $('<ol></ol>');
|
|
|
|
// Loop through each property
|
|
var label;
|
|
for (k = 7; k < keys.length; k++) {
|
|
// Create a list item for each property
|
|
item = $('<li></li>');
|
|
|
|
// Create a label - Property name
|
|
label = $('<label>' + attrNames[keys[k]] + '</label>');
|
|
item.append(label);
|
|
|
|
for (var l = 0; l < attrs[keys[k]].length; l++) {
|
|
// Create a input - Property value(s)
|
|
// Handle each property uniquely
|
|
item.append(attrs[keys[k]][l]);
|
|
}
|
|
|
|
oList.append(item);
|
|
}
|
|
// Append to inventory form
|
|
fieldSet.append(oList);
|
|
invDiv.append(fieldSet);
|
|
|
|
// Append to inventory form
|
|
$('#' + tabId).append(invDiv);
|
|
};
|
|
|
|
/**
|
|
* Load provision page
|
|
*
|
|
* @param tabId The provision tab ID
|
|
*/
|
|
zvmPlugin.prototype.loadProvisionPage = function(tabId) {
|
|
// Get OS image names
|
|
$.ajax( {
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'tabdump',
|
|
tgt : '',
|
|
args : 'osimage',
|
|
msg : ''
|
|
},
|
|
|
|
success : setOSImageCookies
|
|
});
|
|
|
|
// Get groups
|
|
$.ajax( {
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'extnoderange',
|
|
tgt : '/.*',
|
|
args : 'subgroups',
|
|
msg : ''
|
|
},
|
|
|
|
success : setGroupsCookies
|
|
});
|
|
|
|
// Get provision tab instance
|
|
var inst = tabId.replace('zvmProvisionTab', '');
|
|
|
|
// Create provision form
|
|
var provForm = $('<div class="form"></div>');
|
|
|
|
// Create status bar
|
|
var statBarId = 'zProvisionStatBar' + inst;
|
|
var statBar = createStatusBar(statBarId).hide();
|
|
provForm.append(statBar);
|
|
|
|
// Create loader
|
|
var loader = createLoader('zProvisionLoader' + inst).hide();
|
|
statBar.find('div').append(loader);
|
|
|
|
// Create info bar
|
|
var infoBar = createInfoBar('Provision a node on System z.');
|
|
provForm.append(infoBar);
|
|
|
|
// Append to provision tab
|
|
$('#' + tabId).append(provForm);
|
|
|
|
var typeFS = $('<fieldset></fieldset>');
|
|
var typeLegend = $('<legend>Type</legend>');
|
|
typeFS.append(typeLegend);
|
|
provForm.append(typeFS);
|
|
|
|
// Create provision type drop down
|
|
var provType = $('<div></div>');
|
|
var typeLabel = $('<label>Type:</label>');
|
|
var typeSelect = $('<select></select>');
|
|
var provNewNode = $('<option value="new">New node</option>');
|
|
var provExistNode = $('<option value="existing">Existing node</option>');
|
|
typeSelect.append(provNewNode);
|
|
typeSelect.append(provExistNode);
|
|
provType.append(typeLabel);
|
|
provType.append(typeSelect);
|
|
typeFS.append(provType);
|
|
|
|
/**
|
|
* Create provision new node division
|
|
*/
|
|
var provNew = createZProvisionNew(inst);
|
|
provForm.append(provNew);
|
|
|
|
/**
|
|
* Create provision existing node division
|
|
*/
|
|
var provExisting = createZProvisionExisting(inst);
|
|
provForm.append(provExisting);
|
|
|
|
// Toggle provision new/existing on select
|
|
typeSelect.change(function(){
|
|
var selected = $(this).val();
|
|
if (selected == 'new') {
|
|
provNew.toggle();
|
|
provExisting.toggle();
|
|
} else {
|
|
provNew.toggle();
|
|
provExisting.toggle();
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Load the resources
|
|
*/
|
|
zvmPlugin.prototype.loadResources = function() {
|
|
// Reset resource table
|
|
setNetworkDataTable('');
|
|
|
|
// Get hardware control points
|
|
$.ajax( {
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'nodels',
|
|
tgt : 'mgt==zvm',
|
|
args : 'zvm.hcp',
|
|
msg : ''
|
|
},
|
|
success : getZResources
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Add node range
|
|
*/
|
|
zvmPlugin.prototype.addNode = function() {
|
|
// Create form to add node range
|
|
var addNodeForm = $('<div id="addZvm" class="form"></div>');
|
|
var info = createInfoBar('Add a z/VM node range');
|
|
addNodeForm.append(info);
|
|
|
|
// Create provision type drop down
|
|
var type = $('<div></div>');
|
|
var typeLabel = $('<label>Type:</label>');
|
|
var typeSelect = $('<select type="text" name="type" title="The type of node"></select>');
|
|
typeSelect.append('<option value="vm" selected="selected">VM</option>');
|
|
typeSelect.append('<option value="host">Host</option>');
|
|
type.append(typeLabel);
|
|
type.append(typeSelect);
|
|
addNodeForm.append(type);
|
|
|
|
addNodeForm.append('<div><label>Node range *:</label><input type="text" name="node" title="The node or node range to add into xCAT. A node range must be given as: node1-node9 or node[1-9]."/></div>');
|
|
addNodeForm.append('<div><label>User ID range *:</label><input type="text" name="userId" title="The user ID or a user ID range. A user ID range must be given as: user1-user9 or user[1-9]."/></div>');
|
|
addNodeForm.append('<div><label>zHCP *:</label><input type="text" name="hcp" title="The System z hardware control point (zHCP) responsible for managing the node(s)"/></div>');
|
|
addNodeForm.append('<div><label>Groups *:</label><input type="text" name="groups" title="The group where the new node(s) will be placed under"/></div>');
|
|
addNodeForm.append('<div><label>Operating system *:</label><input type="text" name="os" title="The z/VM operating system version, e.g. zvm6.1."/></div>');
|
|
addNodeForm.append('<div><label>IP address range:</label><input name="ip" type="text" title="The IP address range for the node(s). An IP address range must be given in the following format: 192.168.0.1-192.168.9."></div>');
|
|
addNodeForm.append('<div><label>Hostname range:</label><input name="hostname" type="text" title="The hostname range for the node(s). A hostname range must be given in the following format: ihost1.sourceforge.net-ihost9.sourceforge.net."></div>');
|
|
addNodeForm.append('<div><label>* required</label></div>');
|
|
|
|
// OS field only required for hosts
|
|
addNodeForm.find('input[name=os]').parent().hide();
|
|
|
|
// Toggle user Id on select
|
|
typeSelect.change(function(){
|
|
var selected = $(this).val();
|
|
if (selected == 'host') {
|
|
addNodeForm.find('input[name=userId]').parent().toggle();
|
|
addNodeForm.find('input[name=os]').parent().toggle();
|
|
} else {
|
|
addNodeForm.find('input[name=userId]').parent().toggle();
|
|
addNodeForm.find('input[name=os]').parent().toggle();
|
|
}
|
|
});
|
|
|
|
// Generate tooltips
|
|
addNodeForm.find('div input[title],select[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"
|
|
},
|
|
|
|
// Change z index to show tooltip in front
|
|
onBeforeShow: function() {
|
|
this.getTip().css('z-index', $.topZIndex());
|
|
}
|
|
});
|
|
|
|
// Open form as a dialog
|
|
addNodeForm.dialog({
|
|
title: 'Add node',
|
|
modal: true,
|
|
width: 400,
|
|
buttons: {
|
|
"Ok": function(){
|
|
// Remove any warning messages
|
|
$(this).find('.ui-state-error').remove();
|
|
|
|
// Get inputs
|
|
var type = $(this).find('select[name=type]').val();
|
|
var nodeRange = $(this).find('input[name=node]').val();
|
|
var ipRange = $(this).find('input[name=ip]').val();
|
|
var hostnameRange = $(this).find('input[name=hostname]').val();
|
|
var userIdRange = $(this).find('input[name=userId]').val();
|
|
var os = $(this).find('input[name=os]').val();
|
|
var group = $(this).find('input[name=groups]').val();
|
|
var hcp = $(this).find('input[name=hcp]').val();
|
|
|
|
// Check required fields
|
|
if (type == 'host') {
|
|
if (!nodeRange || !os || !group || !hcp) {
|
|
var warn = createWarnBar('Please provide a value for each missing field!');
|
|
warn.prependTo($(this));
|
|
return;
|
|
}
|
|
} else {
|
|
if (!nodeRange || !userIdRange || !group || !hcp) {
|
|
var warn = createWarnBar('Please provide a value for each missing field!');
|
|
warn.prependTo($(this));
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Check node range and user ID range
|
|
// Range can be given as gpok10-gpok20, gpok[10-20], or gpok10+10
|
|
var errMsg = '';
|
|
var ready = true;
|
|
if (nodeRange.indexOf('-') > -1 || userIdRange.indexOf('-') > -1) {
|
|
if (nodeRange.indexOf('-') < 0 || userIdRange.indexOf('-') < 0) {
|
|
errMsg = errMsg + 'A user ID range and node range needs to be given. ';
|
|
ready = false;
|
|
} else {
|
|
var tmp = nodeRange.split('-');
|
|
|
|
// Get starting index
|
|
var nodeStart = parseInt(tmp[0].match(/\d+/));
|
|
// Get ending index
|
|
var nodeEnd = parseInt(tmp[1].match(/\d+/));
|
|
|
|
tmp = userIdRange.split('-');
|
|
|
|
// Get starting index
|
|
var userIdStart = parseInt(tmp[0].match(/\d+/));
|
|
// Get ending index
|
|
var userIdEnd = parseInt(tmp[1].match(/\d+/));
|
|
|
|
var ipStart = "", ipEnd = "";
|
|
if (ipRange != "" && ipRange != null) {
|
|
tmp = ipRange.split('-');
|
|
|
|
// Get starting IP address
|
|
ipStart = tmp[0].substring(tmp[0].lastIndexOf(".") + 1);
|
|
// Get ending IP address
|
|
ipEnd = tmp[1].substring(tmp[1].lastIndexOf(".") + 1);
|
|
}
|
|
|
|
var hostnameStart = "", hostnameEnd = "";
|
|
if (hostnameRange != "" && hostnameRange != null) {
|
|
tmp = hostnameRange.split('-');
|
|
|
|
// Get starting hostname
|
|
hostnameStart = parseInt(tmp[0].substring(0, tmp[0].indexOf(".")).match(/\d+/));
|
|
// Get ending hostname
|
|
hostnameEnd = parseInt(tmp[1].substring(0, tmp[1].indexOf(".")).match(/\d+/));
|
|
}
|
|
|
|
// If starting and ending index do not match
|
|
if (!(nodeStart == userIdStart) || !(nodeEnd == userIdEnd)) {
|
|
errMsg = errMsg + 'The node range and user ID range does not match. ';
|
|
ready = false;
|
|
}
|
|
|
|
// If an IP address range is given and the starting and ending index do not match
|
|
if (ipRange != "" && ipRange != null && (!(nodeStart == ipStart) || !(nodeEnd == ipEnd))) {
|
|
errMsg = errMsg + 'The node range and IP address range does not match. ';
|
|
ready = false;
|
|
}
|
|
|
|
// If a hostname range is given and the starting and ending index do not match
|
|
if (hostnameRange != "" && hostnameRange != null && (!(nodeStart == hostnameStart) || !(nodeEnd == hostnameEnd))) {
|
|
errMsg = errMsg + 'The node range and hostname range does not match. ';
|
|
ready = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If there are no errors
|
|
if (ready) {
|
|
$('#addZvm').append(createLoader());
|
|
|
|
// Change dialog buttons
|
|
$('#addZvm').dialog('option', 'buttons', {
|
|
'Close':function() {
|
|
$('#addZvm').dialog('destroy').remove();
|
|
}
|
|
});
|
|
|
|
// If a node range is given
|
|
if (nodeRange.indexOf('-') > -1 && userIdRange.indexOf('-') > -1) {
|
|
var tmp = nodeRange.split('-');
|
|
|
|
// Get node base name
|
|
var nodeBase = tmp[0].match(/[a-zA-Z]+/);
|
|
// Get starting index
|
|
var nodeStart = parseInt(tmp[0].match(/\d+/));
|
|
// Get ending index
|
|
var nodeEnd = parseInt(tmp[1].match(/\d+/));
|
|
|
|
tmp = userIdRange.split('-');
|
|
|
|
// Get user ID base name
|
|
var userIdBase = tmp[0].match(/[a-zA-Z]+/);
|
|
|
|
var ipBase = "";
|
|
if (ipRange != "" && ipRange != null) {
|
|
tmp = ipRange.split('-');
|
|
|
|
// Get network base
|
|
ipBase = tmp[0].substring(0, tmp[0].lastIndexOf(".") + 1);
|
|
}
|
|
|
|
var domain = "";
|
|
if (hostnameRange != "" && hostnameRange != null) {
|
|
tmp = hostnameRange.split('-');
|
|
|
|
// Get domain name
|
|
domain = tmp[0].substring(tmp[0].indexOf("."));
|
|
}
|
|
|
|
// Loop through each node in the node range
|
|
for ( var i = nodeStart; i <= nodeEnd; i++) {
|
|
var node = nodeBase + i.toString();
|
|
var userId = userIdBase + i.toString();
|
|
var inst = i + '/' + nodeEnd;
|
|
|
|
var args = "";
|
|
if (type == 'host') {
|
|
args = node + ';zvm.hcp=' + hcp
|
|
+ ';nodehm.mgt=zvm;nodetype.arch=s390x;hypervisor.type=zvm;groups=' + group
|
|
+ ';nodetype.os=' + os;
|
|
} else {
|
|
args = node + ';zvm.hcp=' + hcp
|
|
+ ';zvm.userid=' + userId
|
|
+ ';nodehm.mgt=zvm' + ';nodetype.arch=s390x' + ';groups=' + group;
|
|
}
|
|
|
|
if (ipRange != "" && ipRange != null) {
|
|
var ip = ipBase + i.toString();
|
|
args += ';hosts.ip=' + ip;
|
|
}
|
|
|
|
if (hostnameRange != "" && hostnameRange != null) {
|
|
var hostname = node + domain;
|
|
args += ';hosts.hostnames=' + hostname;
|
|
}
|
|
|
|
/**
|
|
* (1) Define node
|
|
*/
|
|
$.ajax( {
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'nodeadd',
|
|
tgt : '',
|
|
args : args,
|
|
msg : 'cmd=addnewnode;inst=' + inst + ';noderange=' + nodeRange
|
|
},
|
|
|
|
/**
|
|
* Return function on successful AJAX call
|
|
*
|
|
* @param data
|
|
* Data returned from HTTP request
|
|
* @return Nothing
|
|
*/
|
|
success : function (data) {
|
|
// Get ajax response
|
|
var rsp = data.rsp;
|
|
var args = data.msg.split(';');
|
|
|
|
// Get instance returned and node range
|
|
var inst = args[1].replace('inst=', '');
|
|
var nodeRange = args[2].replace('noderange=', '');
|
|
|
|
// If the last node was added
|
|
var tmp = inst.split('/');
|
|
if (tmp[0] == tmp[1]) {
|
|
// Update /etc/hosts
|
|
$.ajax({
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'makehosts',
|
|
tgt : '',
|
|
args : '',
|
|
msg : ''
|
|
}
|
|
});
|
|
|
|
// Remove loader
|
|
$('#addZvm img').remove();
|
|
|
|
// If there was an error, do not continue
|
|
if (rsp.length) {
|
|
$('#addZvm').prepend(createWarnBar('Failed to create node definitions'));
|
|
} else {
|
|
$('#addZvm').prepend(createInfoBar('Node definitions created for ' + nodeRange));
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
} else {
|
|
var args = "";
|
|
if (type == 'host') {
|
|
args = nodeRange + ';zvm.hcp=' + hcp
|
|
+ ';nodehm.mgt=zvm;nodetype.arch=s390x;hypervisor.type=zvm;groups=' + group
|
|
+ ';nodetype.os=' + os;
|
|
} else {
|
|
args = nodeRange + ';zvm.hcp=' + hcp
|
|
+ ';zvm.userid=' + userIdRange
|
|
+ ';nodehm.mgt=zvm' + ';nodetype.arch=s390x' + ';groups=' + group;
|
|
}
|
|
|
|
if (ipRange)
|
|
args += ';hosts.ip=' + ipRange;
|
|
|
|
if (hostnameRange)
|
|
args += ';hosts.hostnames=' + hostnameRange;
|
|
|
|
// Only one node to add
|
|
$.ajax( {
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'nodeadd',
|
|
tgt : '',
|
|
args : args,
|
|
msg : 'cmd=addnewnode;node=' + nodeRange
|
|
},
|
|
|
|
/**
|
|
* Return function on successful AJAX call
|
|
*
|
|
* @param data
|
|
* Data returned from HTTP request
|
|
* @return Nothing
|
|
*/
|
|
success : function (data) {
|
|
// Get ajax response
|
|
var rsp = data.rsp;
|
|
var args = data.msg.split(';');
|
|
var node = args[1].replace('node=', '');
|
|
|
|
// Update /etc/hosts
|
|
$.ajax({
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'makehosts',
|
|
tgt : '',
|
|
args : '',
|
|
msg : ''
|
|
}
|
|
});
|
|
|
|
// Remove loader
|
|
$('#addZvm img').remove();
|
|
|
|
// If there was an error, do not continue
|
|
if (rsp.length) {
|
|
$('#addZvm').prepend(createWarnBar('Failed to create node definitions'));
|
|
} else {
|
|
$('#addZvm').prepend(createInfoBar('Node definitions created for ' + node));
|
|
}
|
|
}
|
|
});
|
|
}
|
|
} else {
|
|
// Show warning message
|
|
var warn = createWarnBar(errMsg);
|
|
warn.prependTo($(this));
|
|
}
|
|
},
|
|
"Cancel": function(){
|
|
$(this).dialog('destroy').remove();
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Migrate page
|
|
*
|
|
* @param tgtNode Targets to migrate
|
|
*/
|
|
zvmPlugin.prototype.loadMigratePage = function(tgtNode) {
|
|
var hosts = $.cookie('zvms').split(',');
|
|
var radio, zvmBlock, args;
|
|
var zvms = new Array();
|
|
var hcp = new Object();
|
|
|
|
// Create a drop-down for z/VM destinations
|
|
var destSelect = $('<select name="dest" title="The z/VM SSI cluster name of the destination system to which the specified virtual machine will be relocated."></select>')
|
|
destSelect.append($('<option></option>'));
|
|
for (var i in hosts) {
|
|
args = hosts[i].split(':');
|
|
hcp[args[0]] = args[1];
|
|
zvms.push(args[0]);
|
|
|
|
destSelect.append($('<option>' + args[0] + '</option>'));
|
|
}
|
|
|
|
// Get nodes tab
|
|
var tab = getNodesTab();
|
|
|
|
// Generate new tab ID
|
|
var inst = 0;
|
|
var newTabId = 'migrateTab' + inst;
|
|
while ($('#' + newTabId).length) {
|
|
// If one already exists, generate another one
|
|
inst = inst + 1;
|
|
newTabId = 'migrateTab' + inst;
|
|
}
|
|
|
|
// Open new tab
|
|
// Create remote script form
|
|
var migrateForm = $('<div class="form"></div>');
|
|
|
|
// Create status bar
|
|
var barId = 'migrateStatusBar' + inst;
|
|
var statBar = createStatusBar(barId);
|
|
statBar.hide();
|
|
migrateForm.append(statBar);
|
|
|
|
// Create loader
|
|
var loader = createLoader('migrateLoader' + inst);
|
|
statBar.find('div').append(loader);
|
|
|
|
// Create info bar
|
|
var infoBar = createInfoBar('Migrate, test relocation eligibility, or cancel the relocation of the specified virtual machine, while it continues to run, to the specified system within the z/VM SSI cluster.');
|
|
migrateForm.append(infoBar);
|
|
|
|
// Virtual machine label
|
|
var vmFS = $('<fieldset><legend>Virtual Machine</legend></fieldset>');
|
|
migrateForm.append(vmFS);
|
|
|
|
var vmAttr = $('<div style="display: inline-table; vertical-align: middle;"></div>');
|
|
vmFS.append($('<div style="display: inline-table; vertical-align: middle;"><img src="images/provision/computer.png"></img></div>'));
|
|
vmFS.append(vmAttr);
|
|
|
|
// Target node or group
|
|
var tgt = $('<div><label>Target node range:</label><input type="text" name="target" value="' + tgtNode + '" title="The node or node range to migrate, test, or cancel relocation"/></div>');
|
|
vmAttr.append(tgt);
|
|
|
|
// Destination
|
|
var dest = $('<div><label>Destination:</label></div>');
|
|
var destInput = $('<input type="text" name="dest" title="The z/VM SSI cluster name of the destination system to which the specified virtual machine will be relocated"/>');
|
|
destInput.autocomplete({
|
|
source: zvms
|
|
});
|
|
|
|
// Create a drop-down if there are known z/VMs
|
|
if (zvms.length) {
|
|
dest.append(destSelect);
|
|
} else {
|
|
dest.append(destInput);
|
|
}
|
|
vmAttr.append(dest);
|
|
|
|
// Action Parameter
|
|
var actionparam = $('<div><label>Action:</label><select name="action" title="Initiate a VMRELOCATE of the virtual machine. Test the specified virtual machine and determine if it is eligible to be relocated. Stop the relocation of the specified virtual machine.">' +
|
|
'<option value=""></option>' +
|
|
'<option value="MOVE">Move</option>' +
|
|
'<option value="TEST">Test</option>' +
|
|
'<option value="CANCEL">Cancel</option>' +
|
|
'</select></div>');
|
|
vmAttr.append(actionparam);
|
|
|
|
// Parameters label
|
|
var optionalFS = $('<fieldset><legend>Optional</legend></fieldset>').css('margin-top', '20px');
|
|
migrateForm.append(optionalFS);
|
|
|
|
var optAttr = $('<div style="display: inline-table; vertical-align: middle;"></div>');
|
|
optionalFS.append($('<div style="display: inline-table; vertical-align: middle; width: 70px;"><img src="images/provision/setting.png" style="width: 90%;"></img></div>'));
|
|
optionalFS.append(optAttr);
|
|
|
|
// Immediate Parameter
|
|
var immediateparam = $('<div><label>Immediate:</label><select name="immediate" title="Select No to specify immediate processing (default). Select Yes to specify the VMRELOCATE command will do one early pass through virtual machine storage and then go directly to the quiesce stage. The defaults for both max_total and max_quiesce are NOLIMIT when immediate=YES is specified.">' +
|
|
'<option value="NO">No (default)</option>' +
|
|
'<option value="YES">Yes</option>' +
|
|
'</select></div>');
|
|
optAttr.append(immediateparam);
|
|
immediateparam.change(function() {
|
|
if ($('#' + newTabId + ' select[name=immediate]').val() == 'yes') {
|
|
$('#' + newTabId + ' input[name=maxQuiesce]').val('0');
|
|
} else {
|
|
$('#' + newTabId + ' input[name=maxQuiesce]').val('10');
|
|
}
|
|
});
|
|
|
|
// Max total
|
|
var maxTotalParam = $('<div><label>Max total time:</label><input type="text" name="maxTotal" value="0" title="The maximum total time in seconds that the command issuer is willing to wait for the entire relocation (0 indicates no limit)"/></div>');
|
|
optAttr.append(maxTotalParam);
|
|
|
|
// Max quiesce
|
|
var maxQuiesceParam = $('<div><label>Max quiesce time:</label><input type="text" name="maxQuiesce" value="10" title="The maximum quiesce time (in seconds) a virtual machine may be stopped during a relocation attempt (0 indicates no limit)"/></div>');
|
|
optAttr.append(maxQuiesceParam);
|
|
|
|
// Force parameter
|
|
var forceParam = $('<div style="width: 500px;"><label>Force:</label><input type="checkbox" name="force" value="ARCHITECTURE" style="margin-left:10px">Architecture</input><input type="checkbox" name="force" value="DOMAIN" style="margin-left:10px">Domain</input><input type="checkbox" name="force" value="STORAGE" style="margin-left:10px">Storage</input></div>');
|
|
optAttr.append(forceParam);
|
|
|
|
// Generate tooltips
|
|
migrateForm.find('div input[title],select[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"
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Run
|
|
*/
|
|
var runBtn = createButton('Run');
|
|
runBtn.click(function() {
|
|
// Remove any warning messages
|
|
$(this).parent().parent().find('.ui-state-error').remove();
|
|
|
|
var tgt = $('#' + newTabId + ' input[name=target]');
|
|
|
|
// Drop-down box exists if z/VM systems are known
|
|
// Otherwise, only input box exists
|
|
var dest = $('#' + newTabId + ' select[name=dest]');
|
|
if (!dest.length) {
|
|
dest = $('#' + newTabId + ' input[name=dest]');
|
|
}
|
|
|
|
var action = $('#' + newTabId + ' select[name=action]');
|
|
var immediate = $('#' + newTabId + ' select[name=immediate]');
|
|
var maxTotal = $('#' + newTabId + ' input[name=maxTotal]');
|
|
var maxQuiesce = $('#' + newTabId + ' input[name=maxQuiesce]');
|
|
var tgts = $('#' + newTabId + ' input[name=target]');
|
|
|
|
// Change borders color back to normal
|
|
var inputs = $('#' + newTabId + ' input').css('border', 'solid #BDBDBD 1px');
|
|
var inputs = $('#' + newTabId + ' select').css('border', 'solid #BDBDBD 1px');
|
|
|
|
// Check if required arguments are given
|
|
var message = "";
|
|
if (!isInteger(maxTotal.val())) {
|
|
message += "Max total time must be an integer. ";
|
|
maxTotal.css('border', 'solid #FF0000 1px');
|
|
} if (!isInteger(maxQuiesce.val())) {
|
|
message += "Max quiesce time must be an integer. ";
|
|
maxQuiesce.css('border', 'solid #FF0000 1px');
|
|
} if (!tgt.val()) {
|
|
message += "Target must be specified. ";
|
|
tgt.css('border', 'solid #FF0000 1px');
|
|
} if (!dest.val()) {
|
|
message += "Destination must be specified. ";
|
|
dest.css('border', 'solid #FF0000 1px');
|
|
} if (!action.val()) {
|
|
message += "Action must be specified. ";
|
|
action.css('border', 'solid #FF0000 1px');
|
|
}
|
|
|
|
// Show warning message
|
|
if (message) {
|
|
var warn = createWarnBar(message);
|
|
warn.prependTo($(this).parent().parent());
|
|
return;
|
|
}
|
|
|
|
var args = "destination=" + dest.val() + ";action=" + action.val() + ";immediate=" + immediate.val() + ";";
|
|
|
|
// Append max total argument. Specified <= 0 to accomodate negative values.
|
|
if (maxTotal.val() <= 0) {
|
|
args = args + "max_total=NOLIMIT;";
|
|
} else {
|
|
args = args + "max_total=" + maxTotal.val() + ";";
|
|
}
|
|
|
|
// Append max quiesce argument. Specified <= 0 to accomodate negative values.
|
|
if (maxQuiesce.val() <= 0) {
|
|
args = args + "max_quiesce=NOLIMIT;";
|
|
} else {
|
|
args = args + "max_quiesce=" + maxQuiesce.val() + ";";
|
|
}
|
|
|
|
// Append force argument
|
|
if ($("input[name=force]:checked").length > 0) {
|
|
args = args + "'force="
|
|
$("input[name=force]:checked").each(function() {
|
|
args += $(this).val() + ' ';
|
|
});
|
|
args += "';";
|
|
}
|
|
|
|
var statBarId = 'migrateStatusBar' + inst;
|
|
$('#' + statBarId).show();
|
|
|
|
// Disable all fields
|
|
$('#' + newTabId + ' input').attr('disabled', 'true');
|
|
$('#' + newTabId + ' select').attr('disabled', 'true');
|
|
|
|
// Disable buttons
|
|
$('#' + newTabId + ' button').attr('disabled', 'true');
|
|
|
|
// Run migrate
|
|
$.ajax( {
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'rmigrate',
|
|
tgt : tgts.val(),
|
|
args : args,
|
|
msg : 'out=migrateStatusBar' + inst + ';cmd=rmigrate;tgt=' + tgts.val()
|
|
},
|
|
|
|
success : updateStatusBar
|
|
});
|
|
});
|
|
migrateForm.append(runBtn);
|
|
|
|
// Append to discover tab
|
|
tab.add(newTabId, 'Migrate', migrateForm, true);
|
|
|
|
// Select new tab
|
|
tab.select(newTabId);
|
|
};
|
|
|
|
/**
|
|
* Load event log configuration page
|
|
*
|
|
* @param node Source node to clone
|
|
*/
|
|
zvmPlugin.prototype.loadLogPage = function(node) {
|
|
// Get nodes tab
|
|
var tab = getNodesTab();
|
|
var newTabId = node + 'LogsTab';
|
|
|
|
// If there is no existing clone tab
|
|
if (!$('#' + newTabId).length) {
|
|
// Get table headers
|
|
var tableId = $('#' + node).parents('table').attr('id');
|
|
var headers = $('#' + tableId).parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th');
|
|
var cols = new Array();
|
|
for ( var i = 0; i < headers.length; i++) {
|
|
var col = headers.eq(i).text();
|
|
cols.push(col);
|
|
}
|
|
|
|
// Get hardware control point column
|
|
var hcpCol = $.inArray('hcp', cols);
|
|
|
|
// Get hardware control point
|
|
var nodeRow = $('#' + node).parent().parent();
|
|
var datatable = $('#' + getNodesTableId()).dataTable();
|
|
var rowPos = datatable.fnGetPosition(nodeRow.get(0));
|
|
var aData = datatable.fnGetData(rowPos);
|
|
var hcp = aData[hcpCol];
|
|
|
|
// Create status bar and hide it
|
|
var statBarId = node + 'CloneStatusBar';
|
|
var statBar = createStatusBar(statBarId).hide();
|
|
|
|
// Create info bar
|
|
var infoBar = createInfoBar('Retrieve, clear, or set options for event logs.');
|
|
|
|
// Create clone form
|
|
var logForm = $('<div class="form"></div>');
|
|
logForm.append(statBar);
|
|
logForm.append(infoBar);
|
|
|
|
// Create VM fieldset
|
|
var vmFS = $('<fieldset></fieldset>');
|
|
var vmLegend = $('<legend>Virtual Machine</legend>');
|
|
vmFS.append(vmLegend);
|
|
logForm.append(vmFS);
|
|
|
|
var vmAttr = $('<div style="display: inline-table; vertical-align: middle;"></div>');
|
|
vmFS.append($('<div style="display: inline-table; vertical-align: middle;"><img src="images/provision/computer.png"></img></div>'));
|
|
vmFS.append(vmAttr);
|
|
|
|
// Create logs fieldset
|
|
var logFS = $('<fieldset></fieldset>');
|
|
var logLegend = $('<legend>Logs</legend>');
|
|
logFS.append(logLegend);
|
|
logForm.append(logFS);
|
|
|
|
var logAttr = $('<div style="display: inline-table; vertical-align: middle;"></div>');
|
|
logFS.append($('<div style="display: inline-table; vertical-align: middle;"><img src="images/nodes/log.png"></img></div>'));
|
|
logFS.append(logAttr);
|
|
|
|
vmAttr.append('<div><label>Target node range:</label><input type="text" id="tgtNode" name="tgtNode" value="' + node + '" title="You must give a node or a node range. A node range must be given as: node1-node9 or node[1-9]."/></div>');
|
|
logAttr.append('<div><label>Source log:</label><input type="text" name="srcLog" title="The log file to retrieve, clear, or set."/></div>');
|
|
|
|
var optsLabel = $('<label>Options:</label>');
|
|
var optsList = $('<ul></ul>');
|
|
logAttr.append(optsLabel);
|
|
logAttr.append(optsList);
|
|
|
|
// Create retrieve log checkbox
|
|
var retrieveChkBox = $('<li><input type="checkbox" name="t"/></li>');
|
|
optsList.append(retrieveChkBox);
|
|
retrieveChkBox.append('Retrieve log');
|
|
|
|
// Create log destination input
|
|
var tgtLog = $('<li><label>Log destination:</label><input type="text" name="tgtLog"/></li>');
|
|
tgtLog.hide();
|
|
optsList.append(tgtLog);
|
|
|
|
// Create set log checkbox
|
|
var setChkBox = $('<li><input type="checkbox" name="o"/></li>');
|
|
optsList.append(setChkBox);
|
|
setChkBox.append('Set options');
|
|
|
|
// Create log options input
|
|
var logOpt = $('<li><label style="width: 80px; vertical-align: top;">Log options:</label><textarea name="logOpt"></textarea></li>');
|
|
logOpt.hide();
|
|
optsList.append(logOpt);
|
|
|
|
// Create clear log checkbox
|
|
var clearChkBox = $('<li><input type="checkbox" name="c"/></li>');
|
|
optsList.append(clearChkBox);
|
|
clearChkBox.append('Clear log');
|
|
|
|
retrieveChkBox.bind('click', function(event) {
|
|
tgtLog.toggle();
|
|
});
|
|
|
|
setChkBox.find('input').bind('click', function(event) {
|
|
logOpt.toggle();
|
|
});
|
|
|
|
// Generate tooltips
|
|
logForm.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"
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Run node
|
|
*/
|
|
var runBtn = createButton('Run');
|
|
runBtn.bind('click', function(event) {
|
|
// Remove any warning messages
|
|
$(this).parent().parent().find('.ui-state-error').remove();
|
|
|
|
var ready = true;
|
|
var errMsg = '';
|
|
|
|
// Verify required inputs are provided
|
|
var inputs = $('#' + newTabId + ' input');
|
|
for ( var i = 0; i < inputs.length; i++) {
|
|
if (!inputs.eq(i).val()
|
|
&& inputs.eq(i).attr('name') != 'tgtLog'
|
|
&& inputs.eq(i).attr('name') != 'logOpt') {
|
|
inputs.eq(i).css('border', 'solid #FF0000 1px');
|
|
ready = false;
|
|
} else {
|
|
inputs.eq(i).css('border', 'solid #BDBDBD 1px');
|
|
}
|
|
}
|
|
|
|
// Write error message
|
|
if (!ready) {
|
|
errMsg = errMsg + 'Please provide a value for each missing field.<br>';
|
|
}
|
|
|
|
var tgts = $('#' + newTabId + ' input[name=tgtNode]').val();
|
|
var srcLog = $('#' + newTabId + ' input[name=srcLog]').val();
|
|
|
|
var chkBoxes = $("#" + newTabId + " input[type='checkbox']:checked");
|
|
var optStr = '-s;' + srcLog + ';';
|
|
var opt;
|
|
for ( var i = 0; i < chkBoxes.length; i++) {
|
|
opt = chkBoxes.eq(i).attr('name');
|
|
optStr += '-' + opt;
|
|
|
|
// If it is the retrieve log
|
|
if (opt == 't') {
|
|
// Append log destination
|
|
optStr += ';' + $('#' + newTabId + ' input[name=tgtLog]').val();
|
|
}
|
|
|
|
// If it is set options
|
|
if (opt == 'o') {
|
|
// Append options
|
|
optStr += ';' + $('#' + newTabId + ' textarea[name=logOpt]').val();
|
|
}
|
|
|
|
// Append ; to end of string
|
|
if (i < (chkBoxes.length - 1)) {
|
|
optStr += ';';
|
|
}
|
|
}
|
|
|
|
// If a value is given for every input
|
|
if (ready) {
|
|
// Disable all inputs
|
|
var inputs = $('#' + newTabId + ' input');
|
|
inputs.attr('disabled', 'disabled');
|
|
|
|
/**
|
|
* (1) Retrieve, clear, or set options for event logs
|
|
*/
|
|
$.ajax( {
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'reventlog',
|
|
tgt : tgts,
|
|
args : optStr,
|
|
msg : 'out=' + statBarId + ';cmd=reventlog;tgt=' + tgts
|
|
},
|
|
|
|
success : updateStatusBar
|
|
});
|
|
|
|
// Create loader
|
|
$('#' + statBarId).find('div').append(createLoader());
|
|
$('#' + statBarId).show();
|
|
|
|
// Disable run button
|
|
$(this).attr('disabled', 'true');
|
|
} else {
|
|
// Show warning message
|
|
var warn = createWarnBar(errMsg);
|
|
warn.prependTo($(this).parent().parent());
|
|
}
|
|
});
|
|
logForm.append(runBtn);
|
|
|
|
// Add clone tab
|
|
tab.add(newTabId, 'Logs', logForm, true);
|
|
}
|
|
|
|
tab.select(newTabId);
|
|
}; |