/** * Global variables */ var diskDatatable; // zVM datatable containing disks var networkDatatable; // zVM datatable containing networks /** * Get the disk datatable * * @param Nothing * @return Data table object */ function getDiskDataTable() { return diskDatatable; } /** * Set the disk datatable * * @param table * Data table object * @return Nothing */ function setDiskDataTable(table) { diskDatatable = table; } /** * Get the network datatable * * @param Nothing * @return Data table object */ function getNetworkDataTable() { return networkDatatable; } /** * Set the network datatable * * @param table * Data table object * @return Nothing */ function setNetworkDataTable(table) { networkDatatable = table; } /** * Load HCP specific info * * @param data * Data from HTTP request * @return Nothing */ function loadHcpInfo(data) { var args = data.msg.split(';'); // Get group var group = args[0].replace('group=', ''); // Get hardware control point var hcp = args[1].replace('hcp=', ''); // Get user directory entry var userEntry = data.rsp; if (userEntry[0].indexOf('Failed') < 0) { if (hcp) { // If there is no cookie for the disk pool names if (!$.cookie(hcp + 'diskpools')) { // Get disk pools $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'lsvm', tgt : hcp, args : '--diskpoolnames', msg : hcp }, success : setDiskPoolCookies }); } // If there is no cookie for the network names if (!$.cookie(hcp + 'networks')) { // Get network names $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'lsvm', tgt : hcp, args : '--getnetworknames', msg : hcp }, success : setNetworkCookies }); } } // End of if (hcp) } else { // Create warning dialog var warning = createWarnBar('z/VM SMAPI is not responding to ' + hcp + '. It needs to be reset.'); var warnDialog = $('<div></div>').append(warning); // Open dialog warnDialog.dialog({ title:'Warning', modal: true, width: 400, buttons: { "Reset": function(){ $(this).dialog("close"); // Reset SMAPI $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'chvm', tgt : hcp, args : '--resetsmapi', msg : 'group=' + group + ';hcp=' + hcp }, /** * Refresh group tab * * @param data * Data from HTTP request * @return Nothing */ success : function(data) { var args = data.msg.split(';'); // Get group var group = args[0].replace('group=', ''); // Get hardware control point var hcp = args[1].replace('hcp=', ''); // Clear nodes division $('#nodes').children().remove(); // Create loader var loader = $('<center></center>').append(createLoader()); // Create a tab for this group var tab = new Tab(); setNodesTab(tab); tab.init(); $('#nodes').append(tab.object()); tab.add('nodesTab', 'Nodes', loader, false); // Get nodes within selected group $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'lsdef', tgt : '', args : group, msg : group }, success : loadNodes }); } // End of function }); }, "Ignore": function() { $(this).dialog("close"); } } }); } } /** * Load user entry of a given node * * @param data * Data from HTTP request * @return Nothing */ function loadUserEntry(data) { var args = data.msg.split(';'); // Get tab ID var ueDivId = args[0].replace('out=', ''); // Get node var node = args[1].replace('node=', ''); // Get user directory entry var userEntry = data.rsp[0].split(node + ':'); // Remove loader $('#' + node + 'TabLoader').remove(); var toggleLinkId = node + 'ToggleLink'; $('#' + toggleLinkId).click(function() { // Get text within this link var lnkText = $(this).text(); // Toggle user entry division $('#' + node + 'UserEntry').toggle(); // Toggle inventory division $('#' + node + 'Inventory').toggle(); // Change text if (lnkText == 'Show directory entry') { $(this).text('Show inventory'); } else { $(this).text('Show directory entry'); } }); // Put user entry into a list var fieldSet = $('<fieldset></fieldset>'); var legend = $('<legend>Directory Entry</legend>'); fieldSet.append(legend); var txtArea = $('<textarea></textarea>'); for ( var i = 1; i < userEntry.length; i++) { userEntry[i] = jQuery.trim(userEntry[i]); txtArea.append(userEntry[i]); if (i < userEntry.length) { txtArea.append('\n'); } } txtArea.attr('readonly', 'readonly'); fieldSet.append(txtArea); /** * Edit user entry */ txtArea.bind('dblclick', function(event) { txtArea.attr('readonly', ''); txtArea.css( { 'border-width' : '1px' }); saveBtn.show(); cancelBtn.show(); saveBtn.css('display', 'inline-table'); cancelBtn.css('display', 'inline-table'); }); /** * Save */ var saveBtn = createButton('Save').hide(); saveBtn.bind('click', function(event) { // Show loader $('#' + node + 'StatusBarLoader').show(); $('#' + node + 'StatusBar').show(); // Replace user entry var newUserEntry = jQuery.trim(txtArea.val()) + '\n'; // Replace user entry $.ajax( { url : 'lib/zCmd.php', dataType : 'json', data : { cmd : 'chvm', tgt : node, args : '--replacevs', att : newUserEntry, msg : node }, success : updateZNodeStatus }); // Increment node process and save it in a cookie incrementNodeProcess(node); txtArea.attr('readonly', 'readonly'); txtArea.css( { 'border-width' : '0px' }); // Disable save button $(this).hide(); cancelBtn.hide(); }); /** * Cancel */ var cancelBtn = createButton('Cancel').hide(); cancelBtn.bind('click', function(event) { txtArea.attr('readonly', 'readonly'); txtArea.css( { 'border-width' : '0px' }); cancelBtn.hide(); saveBtn.hide(); }); // Create info bar var infoBar = createInfoBar('Double click on the directory entry to edit it.'); // Append user entry into division $('#' + ueDivId).append(infoBar); $('#' + ueDivId).append(fieldSet); $('#' + ueDivId).append(saveBtn); $('#' + ueDivId).append(cancelBtn); } /** * Increment number of processes running against a node * * @param node * Node to increment running processes * @return Nothing */ function incrementNodeProcess(node) { // Get current processes var procs = $.cookie(node + 'processes'); if (procs) { // One more process procs = parseInt(procs) + 1; $.cookie(node + 'processes', procs); } else { $.cookie(node + 'processes', 1); } } /** * Update provision new node status * * @param data * Data returned from HTTP request * @return Nothing */ function updateZProvisionNewStatus(data) { // Get ajax response var rsp = data.rsp; var args = data.msg.split(';'); // Get command invoked var cmd = args[0].replace('cmd=', ''); // Get output ID var out2Id = args[1].replace('out=', ''); // Get status bar ID var statBarId = 'zProvisionStatBar' + out2Id; // Get provision tab ID var tabId = 'zvmProvisionTab' + out2Id; // Get loader ID var loaderId = 'zProvisionLoader' + out2Id; // Get node name var node = $('#' + tabId + ' input[name=nodeName]').val(); /** * (2) Update /etc/hosts */ if (cmd == 'nodeadd') { // If there was an error, do not continue if (rsp.length) { $('#' + loaderId).hide(); $('#' + statBarId).find('div').append('<pre>(Error) Failed to create node definition</pre>'); } else { $('#' + statBarId).find('div').append('<pre>Node definition created for ' + node + '</pre>'); $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'makehosts', tgt : '', args : '', msg : 'cmd=makehosts;out=' + out2Id }, success : updateZProvisionNewStatus }); } } /** * (3) Update DNS */ else if (cmd == 'makehosts') { // If there was an error, do not continue if (rsp.length) { $('#' + loaderId).hide(); $('#' + statBarId).find('div').append('<pre>(Error) Failed to update /etc/hosts</pre>'); } else { $('#' + statBarId).find('div').append('<pre>/etc/hosts updated</pre>'); $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'makedns', tgt : '', args : '', msg : 'cmd=makedns;out=' + out2Id }, success : updateZProvisionNewStatus }); } } /** * (4) Create user entry */ else if (cmd == 'makedns') { // Reset number of tries $.cookie('tries4' + tabId, 0); // Write ajax response to status bar var prg = writeRsp(rsp, ''); $('#' + statBarId).find('div').append(prg); // Get user entry var userEntry = $('#' + tabId + ' textarea').val(); // Create user entry $.ajax( { url : 'lib/zCmd.php', dataType : 'json', data : { cmd : 'mkvm', tgt : node, args : '', att : userEntry, msg : 'cmd=mkvm;out=' + out2Id }, success : updateZProvisionNewStatus }); } /** * (5) Add disk */ else if (cmd == 'mkvm') { // Write ajax response to status bar var prg = writeRsp(rsp, ''); $('#' + statBarId).find('div').append(prg); // If there was an error, do not continue if (prg.html().indexOf('Error') > -1) { // Try again var tries = parseInt($.cookie('tries4' + tabId)); if (tries < 2) { $('#' + statBarId).find('div').append('<pre>Trying again...</pre>'); tries = tries + 1; // One more try $.cookie('tries4' + tabId, tries); // Get user entry var userEntry = $('#' + tabId + ' textarea').val(); // Create user entry $.ajax( { url : 'lib/zCmd.php', dataType : 'json', data : { cmd : 'mkvm', tgt : node, args : '', att : userEntry, msg : 'cmd=mkvm;out=' + out2Id }, success : updateZProvisionNewStatus }); } else { $('#' + loaderId).hide(); } } else { // Reset number of tries $.cookie('tries4' + tabId, 0); // Set cookie for number of disks var diskRows = $('#' + tabId + ' table:visible tbody tr'); $.cookie('disks2add' + out2Id, diskRows.length); if (diskRows.length > 0) { for ( var i = 0; i < diskRows.length; i++) { // Get disk type, address, size, mode, pool, and password var diskArgs = diskRows.eq(i).find('td'); var type = diskArgs.eq(1).find('select').val(); var address = diskArgs.eq(2).find('input').val(); var size = diskArgs.eq(3).find('input').val(); var mode = diskArgs.eq(4).find('select').val(); var pool = diskArgs.eq(5).find('input').val(); var password = diskArgs.eq(6).find('input').val(); // Create ajax arguments var args = ''; if (type == '3390') { args = '--add' + type + ';' + pool + ';' + address + ';' + size + ';' + mode + ';' + password + ';' + password + ';' + password; } else if (type == '9336') { var blkSize = '512'; args = '--add' + type + ';' + pool + ';' + address + ';' + blkSize + ';' + size + ';' + mode + ';' + password + ';' + password + ';' + password; } // Add disk $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'chvm', tgt : node, args : args, msg : 'cmd=chvm;out=' + out2Id }, success : updateZProvisionNewStatus }); } } else { $('#' + loaderId).hide(); } } } /** * (6) Set operating system for given node */ else if (cmd == 'chvm') { // Write ajax response to status bar var prg = writeRsp(rsp, ''); $('#' + statBarId).find('div').append(prg); // If there was an error, do not continue if (prg.html().indexOf('Error') > -1) { $('#' + loaderId).hide(); // Try again var tries = parseInt($.cookie('tries4' + tabId)); if (tries < 2) { $('#' + statBarId).find('div').append('<pre>Trying again...</pre>'); tries = tries + 1; // One more try $.cookie('tries4' + tabId, tries); // Set cookie for number of disks var diskRows = $('#' + tabId + ' table:visible tbody tr'); $.cookie('disks2add' + out2Id, diskRows.length); if (diskRows.length > 0) { for ( var i = 0; i < diskRows.length; i++) { // Get disk type, address, size, pool, and password var diskArgs = diskRows.eq(i).find('td'); var type = diskArgs.eq(1).find('select').val(); var address = diskArgs.eq(2).find('input').val(); var size = diskArgs.eq(3).find('input').val(); var mode = diskArgs.eq(4).find('select').val(); var pool = diskArgs.eq(5).find('input').val(); var password = diskArgs.eq(6).find('input').val(); // Create ajax arguments var args = ''; if (type == '3390') { args = '--add' + type + ';' + pool + ';' + address + ';' + size + ';' + mode + ';' + password + ';' + password + ';' + password; } else if (type == '9336') { var blkSize = '512'; args = '--add' + type + ';' + pool + ';' + address + ';' + blkSize + ';' + size + ';' + mode + ';' + password + ';' + password + ';' + password; } // Add disk $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'chvm', tgt : node, args : args, msg : 'cmd=chvm;out=' + out2Id }, success : updateZProvisionNewStatus }); } } else { $('#' + loaderId).hide(); } } else { $('#' + loaderId).hide(); } } else { // Reset number of tries $.cookie('tries4' + tabId, 0); // Get operating system image var osImage = $('#' + tabId + ' input[name=os]:visible').val(); // Get cookie for number of disks var disks2add = $.cookie('disks2add' + out2Id); // One less disk to add disks2add = disks2add - 1; // Set cookie for number of disks $.cookie('disks2add' + out2Id, disks2add); // If an operating system image is given if (osImage) { var tmp = osImage.split('-'); // Get operating system, architecture, provision method, and profile var os = tmp[0]; var arch = tmp[1]; var profile = tmp[3]; // If the last disk is added if (disks2add < 1) { $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'nodeadd', tgt : '', args : node + ';noderes.netboot=zvm;nodetype.os=' + os + ';nodetype.arch=' + arch + ';nodetype.profile=' + profile, msg : 'cmd=noderes;out=' + out2Id }, success : updateZProvisionNewStatus }); } } else { $('#' + loaderId).hide(); } } } /** * (7) Update DHCP */ else if (cmd == 'noderes') { // If there was an error, do not continue if (rsp.length) { $('#' + loaderId).hide(); $('#' + statBarId).find('div').append('<pre>(Error) Failed to set operating system</pre>'); } else { $('#' + statBarId).find('div').append('<pre>Operating system for ' + node + ' set</pre>'); $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'makedhcp', tgt : '', args : '-a', msg : 'cmd=makedhcp;out=' + out2Id }, success : updateZProvisionNewStatus }); } } /** * (8) Prepare node for boot */ else if (cmd == 'makedhcp') { // Prepare node for boot $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'nodeset', tgt : node, args : 'install', msg : 'cmd=nodeset;out=' + out2Id }, success : updateZProvisionNewStatus }); } /** * (9) Boot node to network */ else if (cmd == 'nodeset') { // Write ajax response to status bar var prg = writeRsp(rsp, ''); $('#' + statBarId).find('div').append(prg); // If there was an error // Do not continue if (prg.html().indexOf('Error') > -1) { $('#' + loaderId).hide(); } else { $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'rnetboot', tgt : node, args : 'ipl=000C', msg : 'cmd=rnetboot;out=' + out2Id }, success : updateZProvisionNewStatus }); } } /** * (10) Done */ else if (cmd == 'rnetboot') { // Write ajax response to status bar var prg = writeRsp(rsp, ''); $('#' + statBarId).find('div').append(prg); if (prg.html().indexOf('Error') < 0) { $('#' + statBarId).find('div').append('<pre>Open a VNC viewer to see the installation progress. It might take a couple of minutes before you can connect.</pre>'); } // Hide loader $('#' + loaderId).hide(); } } /** * Update the provision existing node status * * @param data * Data returned from HTTP request * @return Nothing */ function updateZProvisionExistingStatus(data) { // Get ajax response var rsp = data.rsp; var args = data.msg.split(';'); // Get command invoked var cmd = args[0].replace('cmd=', ''); // Get provision tab instance var inst = args[1].replace('out=', ''); // Get provision tab and status bar ID var statBarId = 'zProvisionStatBar' + inst; var tabId = 'zvmProvisionTab' + inst; /** * (2) Prepare node for boot */ if (cmd == 'nodeadd') { // Get operating system var bootMethod = $('#' + tabId + ' select[name=bootMethod]').val(); // Get nodes that were checked var dTableId = 'zNodesDatatable' + inst; var tgts = getNodesChecked(dTableId); // Prepare node for boot $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'nodeset', tgt : tgts, args : bootMethod, msg : 'cmd=nodeset;out=' + inst }, success : updateZProvisionExistingStatus }); } /** * (3) Boot node from network */ else if (cmd == 'nodeset') { // Write ajax response to status bar var prg = writeRsp(rsp, ''); $('#' + statBarId).find('div').append(prg); // If there was an error, do not continue if (prg.html().indexOf('Error') > -1) { var loaderId = 'zProvisionLoader' + inst; $('#' + loaderId).remove(); return; } // Get nodes that were checked var dTableId = 'zNodesDatatable' + inst; var tgts = getNodesChecked(dTableId); // Boot node from network $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'rnetboot', tgt : tgts, args : 'ipl=000C', msg : 'cmd=rnetboot;out=' + inst }, success : updateZProvisionExistingStatus }); } /** * (4) Done */ else if (cmd == 'rnetboot') { // Write ajax response to status bar var prg = writeRsp(rsp, ''); $('#' + statBarId).find('div').append(prg); var loaderId = 'zProvisionLoader' + inst; $('#' + loaderId).remove(); } } /** * Update zVM node status * * @param data * Data returned from HTTP request * @return Nothing */ function updateZNodeStatus(data) { var node = data.msg; var rsp = data.rsp; // Get cookie for number processes performed against this node var actions = $.cookie(node + 'processes'); // One less process actions = actions - 1; $.cookie(node + 'processes', actions); if (actions < 1) { // Hide loader when there are no more processes var statusBarLoaderId = node + 'StatusBarLoader'; $('#' + statusBarLoaderId).hide(); } var statBarId = node + 'StatusBar'; // Write ajax response to status bar var prg = writeRsp(rsp, '[A-Za-z0-9._-]+:'); $('#' + statBarId).find('div').append(prg); } /** * Update clone status * * @param data * Data returned from HTTP request * @return Nothing */ function updateZCloneStatus(data) { // Get ajax response var rsp = data.rsp; var args = data.msg.split(';'); var cmd = args[0].replace('cmd=', ''); // Get provision instance var inst = args[1].replace('inst=', ''); // Get output division ID var out2Id = args[2].replace('out=', ''); /** * (2) Update /etc/hosts */ if (cmd == 'nodeadd') { var node = args[3].replace('node=', ''); // If there was an error, do not continue if (rsp.length) { $('#' + out2Id).find('img').hide(); $('#' + out2Id).find('div').append('<pre>(Error) Failed to create node definition</pre>'); } else { $('#' + out2Id).find('div').append('<pre>Node definition created for ' + node + '</pre>'); // If last node definition was created var tmp = inst.split('/'); if (tmp[0] == tmp[1]) { $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'makehosts', tgt : '', args : '', msg : 'cmd=makehosts;inst=' + inst + ';out=' + out2Id }, success : updateZCloneStatus }); } } } /** * (3) Update DNS */ else if (cmd == 'makehosts') { // If there was an error, do not continue if (rsp.length) { $('#' + out2Id).find('img').hide(); $('#' + out2Id).find('div').append('<pre>(Error) Failed to update /etc/hosts</pre>'); } else { $('#' + out2Id).find('div').append('<pre>/etc/hosts updated</pre>'); $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'makedns', tgt : '', args : '', msg : 'cmd=makedns;inst=' + inst + ';out=' + out2Id }, success : updateZCloneStatus }); } } /** * (4) Clone */ else if (cmd == 'makedns') { // Write ajax response to status bar var prg = writeRsp(rsp, ''); $('#' + out2Id).find('div').append(prg); // Get clone tab var tabId = out2Id.replace('CloneStatusBar', 'CloneTab'); // If a node range is given var tgtNodeRange = $('#' + tabId + ' input[name=tgtNode]').val(); var tgtNodes = ''; if (tgtNodeRange.indexOf('-') > -1) { var tmp = tgtNodeRange.split('-'); // Get node base name var nodeBase = tmp[0].match(/[a-zA-Z]+/); // Get the starting index var nodeStart = parseInt(tmp[0].match(/\d+/)); // Get the ending index var nodeEnd = parseInt(tmp[1].match(/\d+/)); for ( var i = nodeStart; i <= nodeEnd; i++) { // Do not append comma for last node if (i == nodeEnd) { tgtNodes += nodeBase + i.toString(); } else { tgtNodes += nodeBase + i.toString() + ','; } } } else { tgtNodes = tgtNodeRange; } // Get other inputs var srcNode = $('#' + tabId + ' input[name=srcNode]').val(); hcp = $('#' + tabId + ' input[name=newHcp]').val(); var group = $('#' + tabId + ' input[name=newGroup]').val(); var diskPool = $('#' + tabId + ' input[name=diskPool]').val(); var diskPw = $('#' + tabId + ' input[name=diskPw]').val(); if (!diskPw) { diskPw = ''; } // Clone $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'mkvm', tgt : tgtNodes, args : srcNode + ';pool=' + diskPool + ';pw=' + diskPw, msg : 'cmd=mkvm;inst=' + inst + ';out=' + out2Id }, success : updateZCloneStatus }); } /** * (5) Done */ else if (cmd == 'mkvm') { // Write ajax response to status bar var prg = writeRsp(rsp, ''); $('#' + out2Id).find('div').append(prg); // Hide loader $('#' + out2Id).find('img').hide(); } } /** * Get zVM resources * * @param data * Data from HTTP request * @return Nothing */ function getZResources(data) { // Do not continue if there is no output if (data.rsp) { // Loop through each line var node, hcp; var hcpHash = new Object(); for ( var i in data.rsp) { node = data.rsp[i][0]; hcp = data.rsp[i][1]; hcpHash[hcp] = 1; } // Create an array for hardware control points var hcps = new Array(); for ( var key in hcpHash) { hcps.push(key); // Get the short host name hcp = key.split('.')[0]; // Get disk pools $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'lsvm', tgt : hcp, args : '--diskpoolnames', msg : hcp }, success : getDiskPool }); // Get network names $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'lsvm', tgt : hcp, args : '--getnetworknames', msg : hcp }, success : getNetwork }); } // Set cookie $.cookie('hcp', hcps); } } /** * Get node attributes from HTTP request data * * @param propNames * Hash table of property names * @param keys * Property keys * @param data * Data from HTTP request * @return Hash table of property values */ function getAttrs(keys, propNames, data) { // Create hash table for property values var attrs = new Object(); // Go through inventory and separate each property out var curKey; // Current property key var addLine; // Add a line to the current property? for ( var i = 1; i < data.length; i++) { addLine = true; // Loop through property keys // Does this line contains one of the properties? for ( var j = 0; j < keys.length; j++) { // Find property name if (data[i].indexOf(propNames[keys[j]]) > -1) { attrs[keys[j]] = new Array(); // Get rid of property name in the line data[i] = data[i].replace(propNames[keys[j]], ''); // Trim the line data[i] = jQuery.trim(data[i]); // Do not insert empty line if (data[i].length > 0) { attrs[keys[j]].push(data[i]); } curKey = keys[j]; addLine = false; // This line belongs to a property } } // Line does not contain a property // Must belong to previous property if (addLine && data[i].length > 1) { data[i] = jQuery.trim(data[i]); attrs[curKey].push(data[i]); } } return attrs; } /** * Create add processor dialog * * @param node * Node to add processor to * @return Nothing */ function openAddProcDialog(node) { // Create form to add processor var addProcForm = $('<div class="form"></div>'); // Create info bar var info = createInfoBar('Add a temporary processor to this virtual server.'); addProcForm.append(info); addProcForm.append('<div><label for="procNode">Node:</label><input type="text" readonly="readonly" id="procNode" name="procNode" value="' + node + '"/></div>'); addProcForm.append('<div><label for="procAddress">Processor address:</label><input type="text" id="procAddress" name="procAddress"/></div>'); // Create drop down for processor type var procType = $('<div></div>'); procType.append('<label for="procType">Processor type:</label>'); var typeSelect = $('<select id="procType" name="procType"></select>'); typeSelect.append('<option>CP</option>' + '<option>IFL</option>' + '<option>ZAAP</option>' + '<option>ZIIP</option>' ); procType.append(typeSelect); addProcForm.append(procType); // Open dialog to add processor addProcForm.dialog({ title:'Add processor', modal: true, width: 400, buttons: { "Ok": function(){ // Remove any warning messages $(this).find('.ui-state-error').remove(); // Get inputs var node = $(this).find('input[name=procNode]').val(); var address = $(this).find('input[name=procAddress]').val(); var type = $(this).find('select[name=procType]').val(); // If inputs are not complete, show warning message if (!node || !address || !type) { var warn = createWarnBar('Please provide a value for each missing field.'); warn.prependTo($(this)); } else { // Add processor $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'chvm', tgt : node, args : '--addprocessoractive;' + address + ';' + type, msg : node }, success : updateZNodeStatus }); // Increment node process incrementNodeProcess(node); // Show loader var statusId = node + 'StatusBar'; var statusBarLoaderId = node + 'StatusBarLoader'; $('#' + statusBarLoaderId).show(); $('#' + statusId).show(); // Close dialog $(this).dialog( "close" ); } }, "Cancel": function() { $(this).dialog( "close" ); } } }); } /** * Create add disk dialog * * @param node * Node to add disk to * @param hcp * Hardware control point of node * @return Nothing */ function openAddDiskDialog(node, hcp) { // Get list of disk pools var cookie = $.cookie(hcp + 'diskpools'); var pools = cookie.split(','); // Create form to add disk var addDiskForm = $('<div class="form"></div>'); // Create info bar var info = createInfoBar('Add a ECKD|3390 or FBA|9336 disk to this virtual server.'); addDiskForm.append(info); addDiskForm.append('<div><label for="diskNode">Node:</label><input type="text" readonly="readonly" id="diskNode" name="diskNode" value="' + node + '"/></div>'); addDiskForm.append('<div><label for="diskType">Disk type:</label><select id="diskType" name="diskType"><option value="3390">3390</option><option value="9336">9336</option></select></div>'); addDiskForm.append('<div><label for="diskAddress">Disk address:</label><input type="text" id="diskAddress" name="diskAddress"/></div>'); addDiskForm.append('<div><label for="diskSize">Disk size:</label><input type="text" id="diskSize" name="diskSize"/></div>'); // Create drop down for disk pool var diskPool = $('<div></div>'); diskPool.append('<label for="diskPool">Disk pool:</label>'); var poolSelect = $('<select id="diskPool" name="diskPool"></select>'); for ( var i = 0; i < pools.length; i++) { poolSelect.append('<option>' + pools[i] + '</option>'); } diskPool.append(poolSelect); addDiskForm.append(diskPool); // Create drop down for disk mode var diskMode = $('<div></div>'); diskMode.append('<label for="diskMode">Disk mode:</label>'); var modeSelect = $('<select id="diskMode" name="diskMode"></select>'); modeSelect.append('<option>R</option>' + '<option>RR</option>' + '<option>W</option>' + '<option>WR</option>' + '<option>M</option>' + '<option>MR</option>' + '<option>MW</option>' ); diskMode.append(modeSelect); addDiskForm.append(diskMode); addDiskForm.append('<div><label for="diskPassword">Disk password:</label><input type="password" id="diskPassword" name="diskPassword"/></div>'); // Open dialog to add disk addDiskForm.dialog({ title:'Add disk', modal: true, width: 400, buttons: { "Ok": function(){ // Remove any warning messages $(this).find('.ui-state-error').remove(); // Get inputs var node = $(this).find('input[name=diskNode]').val(); var type = $(this).find('select[name=diskType]').val(); var address = $(this).find('input[name=diskAddress]').val(); var size = $(this).find('input[name=diskSize]').val(); var pool = $(this).find('select[name=diskPool]').val(); var mode = $(this).find('select[name=diskMode]').val(); var password = $(this).find('input[name=diskPassword]').val(); // If inputs are not complete, show warning message if (!node || !type || !address || !size || !pool || !mode) { var warn = createWarnBar('Please provide a value for each missing field.'); warn.prependTo($(this)); } else { // Add disk if (type == '3390') { $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'chvm', tgt : node, args : '--add3390;' + pool + ';' + address + ';' + size + ';' + mode + ';' + password + ';' + password + ';' + password, msg : node }, success : updateZNodeStatus }); // Increment node process incrementNodeProcess(node); // Show loader var statusId = node + 'StatusBar'; var statusBarLoaderId = node + 'StatusBarLoader'; $('#' + statusBarLoaderId).show(); $('#' + statusId).show(); } else if (type == '9336') { // Default block size for FBA volumes = 512 var blkSize = '512'; $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'chvm', tgt : node, args : '--add9336;' + pool + ';' + address + ';' + blkSize + ';' + size + ';' + mode + ';' + password + ';' + password + ';' + password, msg : node }, success : updateZNodeStatus }); // Increment node process incrementNodeProcess(node); // Show loader var statusId = node + 'StatusBar'; var statusBarLoaderId = node + 'StatusBarLoader'; $('#' + statusBarLoaderId).show(); $('#' + statusId).show(); } // Close dialog $(this).dialog( "close" ); } // End of else }, "Cancel": function() { $(this).dialog( "close" ); } } }); } /** * Create add NIC dialog * * @param node * Node to add NIC to * @param hcp * Hardware control point of node * @return Nothing */ function openAddNicDialog(node, hcp) { // Get network names var networks = $.cookie(hcp + 'networks').split(','); // Create form to add NIC var addNicForm = $('<div class="form"></div>'); // Create info bar var info = createInfoBar('Add a NIC to this virtual server.'); addNicForm.append(info); addNicForm.append('<div><label for="nicNode">Node:</label><input type="text" readonly="readonly" id="nicNode" name="nicNode" value="' + node + '"/></div>'); addNicForm.append('<div><label for="nicAddress">NIC address:</label><input type="text" id="nicAddress" name="nicAddress"/></div>'); // Create drop down for NIC types var nicType = $('<div></div>'); nicType.append('<label for="nicType">NIC type:</label>'); var nicTypeSelect = $('<select id="nicType" name="nicType"></select>'); nicTypeSelect.append('<option></option>' + '<option>QDIO</option>' + '<option>HiperSockets</option>' ); nicType.append(nicTypeSelect); addNicForm.append(nicType); // Create drop down for network types var networkType = $('<div></div>'); networkType.append('<label for="nicNetworkType">Network type:</label>'); var networkTypeSelect = $('<select id="nicNetworkType" name="nicNetworkType"></select>'); networkTypeSelect.append('<option></option>' + '<option>Guest LAN</option>' + '<option>Virtual Switch</option>' ); networkType.append(networkTypeSelect); addNicForm.append(networkType); // Create drop down for network names var gLansQdioSelect = $('<select id="nicLanQdioName" name="nicLanQdioName"></select>'); var gLansHipersSelect = $('<select id="nicLanHipersName" name="nicLanHipersName"></select>'); var vswitchSelect = $('<select id="nicVSwitchName" name="nicVSwitchName"></select>'); for ( var i = 0; i < networks.length; i++) { var network = networks[i].split(' '); var networkOption = $('<option>' + network[1] + ' ' + network[2] + '</option>'); if (network[0] == 'VSWITCH') { vswitchSelect.append(networkOption); } else if (network[0] == 'LAN:QDIO') { gLansQdioSelect.append(networkOption); } else if (network[0] == 'LAN:HIPERS') { gLansHipersSelect.append(networkOption); } } // Hide network name drop downs until the NIC type and network type is selected // QDIO Guest LAN drop down var guestLanQdio = $('<div></div>').hide(); guestLanQdio.append('<label for="nicLanQdioName">Guest LAN name:</label>'); guestLanQdio.append(gLansQdioSelect); addNicForm.append(guestLanQdio); // HIPERS Guest LAN drop down var guestLanHipers = $('<div></div>').hide(); guestLanHipers.append('<label for="nicLanHipersName">Guest LAN name:</label>'); guestLanHipers.append(gLansHipersSelect); addNicForm.append(guestLanHipers); // VSWITCH drop down var vswitch = $('<div></div>').hide(); vswitch.append('<label for="nicVSwitchName">VSWITCH name:</label>'); vswitch.append(vswitchSelect); addNicForm.append(vswitch); // Show network names on change networkTypeSelect.change(function(){ // Remove any warning messages $(this).parent().parent().find('.ui-state-error').remove(); // Get NIC type and network type var nicType = $(this).parent().parent().find('select[name=nicType]').val(); var networkType = $(this).val(); // Hide network name drop downs var guestLanQdio = $(this).parent().parent().find('select[name=nicLanQdioName]').parent(); var guestLanHipers = $(this).parent().parent().find('select[name=nicLanHipersName]').parent(); var vswitch = $(this).parent().parent().find('select[name=nicVSwitchName]').parent(); guestLanQdio.hide(); guestLanHipers.hide(); vswitch.hide(); // Show correct network name if (networkType == 'Guest LAN' && nicType == 'QDIO') { guestLanQdio.show(); } else if (networkType == 'Guest LAN' && nicType == 'HiperSockets') { guestLanHipers.show(); } else if (networkType == 'Virtual Switch') { if (nicType == 'QDIO') { vswitch.show(); } else { // No such thing as HIPERS VSWITCH var warn = createWarnBar('The selected choices are not valid.'); warn.prependTo($(this).parent().parent()); } } }); // Show network names on change nicTypeSelect.change(function(){ // Remove any warning messages $(this).parent().parent().find('.ui-state-error').remove(); // Get NIC type and network type var nicType = $(this).val(); var networkType = $(this).parent().parent().find('select[name=nicNetworkType]').val(); // Hide network name drop downs var guestLanQdio = $(this).parent().parent().find('select[name=nicLanQdioName]').parent(); var guestLanHipers = $(this).parent().parent().find('select[name=nicLanHipersName]').parent(); var vswitch = $(this).parent().parent().find('select[name=nicVSwitchName]').parent(); guestLanQdio.hide(); guestLanHipers.hide(); vswitch.hide(); // Show correct network name if (networkType == 'Guest LAN' && nicType == 'QDIO') { guestLanQdio.show(); } else if (networkType == 'Guest LAN' && nicType == 'HiperSockets') { guestLanHipers.show(); } else if (networkType == 'Virtual Switch') { if (nicType == 'QDIO') { vswitch.show(); } else { // No such thing as HIPERS VSWITCH var warn = createWarnBar('The selected choices are not valid.'); warn.prependTo($(this).parent().parent()); } } }); // Open dialog to add NIC addNicForm.dialog({ title:'Add NIC', modal: true, width: 400, buttons: { "Ok": function(){ // Remove any warning messages $(this).find('.ui-state-error').remove(); var ready = true; var errMsg = ''; // Get inputs var node = $(this).find('input[name=nicNode]').val(); var nicType = $(this).find('select[name=nicType]').val(); var networkType = $(this).find('select[name=nicNetworkType]').val(); var address = $(this).find('input[name=nicAddress]').val(); // If inputs are not complete, show warning message if (!node || !nicType || !networkType || !address) { errMsg = 'Please provide a value for each missing field.<br>'; ready = false; } // If a HIPERS VSWITCH is selected, show warning message if (nicType == 'HiperSockets' && networkType == 'Virtual Switch') { errMsg += 'The selected choices are not valid.'; ready = false; } // If there are errors if (!ready) { // Show warning message var warn = createWarnBar(errMsg); warn.prependTo($(this)); } else { // Add guest LAN if (networkType == 'Guest LAN') { var temp; if (nicType == 'QDIO') { temp = $(this).find('select[name=nicLanQdioName]').val().split(' '); } else { temp = $(this).find('select[name=nicLanHipersName]').val().split(' '); } var lanOwner = temp[0]; var lanName = temp[1]; $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'chvm', tgt : node, args : '--addnic;' + address + ';' + nicType + ';3', msg : 'node=' + node + ';addr=' + address + ';lan=' + lanName + ';owner=' + lanOwner }, success : connect2GuestLan }); } // Add virtual switch else if (networkType == 'Virtual Switch' && nicType == 'QDIO') { var temp = $(this).find('select[name=nicVSwitchName]').val().split(' '); var vswitchName = temp[1]; $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'chvm', tgt : node, args : '--addnic;' + address + ';' + nicType + ';3', msg : 'node=' + node + ';addr=' + address + ';vsw=' + vswitchName }, success : connect2VSwitch }); } // Increment node process incrementNodeProcess(node); // Show loader $('#' + node + 'StatusBarLoader').show(); $('#' + node + 'StatusBar').show(); // Close dialog $(this).dialog( "close" ); } // End of else }, "Cancel": function(){ $(this).dialog( "close" ); } } }); } /** * Remove processor * * @param node * Node where processor is attached * @param address * Virtual address of processor * @return Nothing */ function removeProcessor(node, address) { $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'chvm', tgt : node, args : '--removeprocessor;' + address, msg : node }, success : updateZNodeStatus }); // Increment node process incrementNodeProcess(node); // Show loader $('#' + node + 'StatusBarLoader').show(); $('#' + node + 'StatusBar').show(); } /** * Remove disk * * @param node * Node where disk is attached * @param address * Virtual address of disk * @return Nothing */ function removeDisk(node, address) { $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'chvm', tgt : node, args : '--removedisk;' + address, msg : node }, success : updateZNodeStatus }); // Increment node process incrementNodeProcess(node); // Show loader $('#' + node + 'StatusBarLoader').show(); $('#' + node + 'StatusBar').show(); } /** * Remove NIC * * @param node * Node where NIC is attached * @param address * Virtual address of NIC * @return Nothing */ function removeNic(node, nic) { var args = nic.split('.'); var address = args[0]; $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'chvm', tgt : node, args : '--removenic;' + address, msg : node }, success : updateZNodeStatus }); // Increment node process incrementNodeProcess(node); // Show loader $('#' + node + 'StatusBarLoader').show(); $('#' + node + 'StatusBar').show(); } /** * Set a cookie for the network names of a given node * * @param data * Data from HTTP request * @return Nothing */ function setNetworkCookies(data) { if (data.rsp) { var node = data.msg; var networks = data.rsp[0].split(node + ': '); // Set cookie to expire in 60 minutes var exDate = new Date(); exDate.setTime(exDate.getTime() + (60 * 60 * 1000)); $.cookie(node + 'networks', networks, { expires: exDate }); } } /** * Get contents of each disk pool * * @param data * HTTP request data * @return Nothing */ function getDiskPool(data) { if (data.rsp) { var hcp = data.msg; var pools = data.rsp[0].split(hcp + ': '); // Get contents of each disk pool for ( var i in pools) { if (pools[i]) { pools[i] = jQuery.trim(pools[i]); // Get used space $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'lsvm', tgt : hcp, args : '--diskpool;' + pools[i] + ';used', msg : 'hcp=' + hcp + ';pool=' + pools[i] + ';stat=used' }, success : loadDiskPoolTable }); // Get free space $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'lsvm', tgt : hcp, args : '--diskpool;' + pools[i] + ';free', msg : 'hcp=' + hcp + ';pool=' + pools[i] + ';stat=free' }, success : loadDiskPoolTable }); } // End of if } // End of for } } /** * Get details of each network * * @param data * HTTP request data * @return Nothing */ function getNetwork(data) { if (data.rsp) { var hcp = data.msg; var networks = data.rsp[0].split(hcp + ': '); // Loop through each network for ( var i = 1; i < networks.length; i++) { var args = networks[i].split(' '); var type = args[0]; var name = args[2]; // Get network details $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'lsvm', tgt : hcp, args : '--getnetwork;' + name, msg : 'hcp=' + hcp + ';type=' + type + ';network=' + name }, success : loadNetworkTable }); } // End of for } // End of if } /** * Load disk pool contents into a table * * @param data * HTTP request data * @return Nothing */ function loadDiskPoolTable(data) { var args = data.msg.split(';'); var hcp = args[0].replace('hcp=', ''); var pool = args[1].replace('pool=', ''); var stat = args[2].replace('stat=', ''); var tmp = data.rsp[0].split(hcp + ': '); // Remove loader var loaderId = 'zvmResourceLoader'; if ($('#' + loaderId).length) { $('#' + loaderId).remove(); } // Resource tab ID var tabID = 'zvmResourceTab'; var info = $('#' + tabID).find('.ui-state-highlight'); // If there is no info bar if (!info.length) { // Create info bar info = createInfoBar('Below are disks and networks found by the hardware control point. It shows disk pools defined in the EXTENT CONTROL file and LANs|VSWITCHes available to use.'); $('#' + tabID).append(info); } // Get datatable var dTable = getDiskDataTable(); if (!dTable) { // Create disks section var fieldSet = $('<fieldset></fieldset>'); var legend = $('<legend>Disks</legend>'); fieldSet.append(legend); // Create a datatable var tableID = 'zDiskDataTable'; var table = new DataTable(tableID); // Resource headers: volume ID, device type, start address, and size table.init( [ 'HCP', 'Pool', 'Status', 'Volume ID', 'Device type', 'Start address', 'Size' ]); // Append datatable to tab fieldSet.append(table.object()); $('#' + tabID).append(fieldSet); // Turn into datatable dTable = $('#' + tableID).dataTable(); setDiskDataTable(dTable); } // Skip index 0 and 1 because it contains nothing for ( var i = 2; i < tmp.length; i++) { tmp[i] = jQuery.trim(tmp[i]); var diskAttrs = tmp[i].split(' '); dTable.fnAddData( [ hcp, pool, stat, diskAttrs[0], diskAttrs[1], diskAttrs[2], diskAttrs[3] ]); } } /** * Load network details into a table * * @param data * HTTP request data * @return Nothing */ function loadNetworkTable(data) { var args = data.msg.split(';'); var hcp = args[0].replace('hcp=', ''); var type = args[1].replace('type=', ''); var name = args[2].replace('network=', ''); var tmp = data.rsp[0].split(hcp + ': '); // Remove loader var loaderId = 'zvmResourceLoader'; if ($('#' + loaderId).length) { $('#' + loaderId).remove(); } // Resource tab ID var tabId = 'zvmResourceTab'; var info = $('#' + tabId).find('.ui-state-highlight'); // If there is no info bar if (!info.length) { // Create info bar info = createInfoBar('Below are disks and networks found by the hardware control point. It shows disk pools defined in the EXTENT CONTROL file and LANs|VSWITCHes available to use.'); $('#' + tabId).append(info); } // Get datatable var dTable = getNetworkDataTable(); if (!dTable) { // Create networks section var fieldSet = $('<fieldset></fieldset>'); var legend = $('<legend>Networks</legend>'); fieldSet.append(legend); // Create table var tableId = 'zNetworkDataTable'; var table = new DataTable(tableId); table.init( [ 'HCP', 'Type', 'Name', 'Details' ]); // Append datatable to tab fieldSet.append(table.object()); $('#' + tabId).append(fieldSet); // Turn into datatable dTable = $('#' + tableId).dataTable(); setNetworkDataTable(dTable); // Set the column width var cols = table.object().find('thead tr th'); cols.eq(0).css('width', '20px'); // HCP column cols.eq(1).css('width', '20px'); // Type column cols.eq(2).css('width', '20px'); // Name column cols.eq(3).css({'width': '600px'}); // Details column } // Skip index 0 because it contains nothing var details = '<pre style="text-align: left;">'; for ( var i = 1; i < tmp.length; i++) { details += tmp[i]; } details += '</pre>'; dTable.fnAddData( [ hcp, type, name, details ]); } /** * Connect a NIC to a Guest LAN * * @param data * Data from HTTP request * @return Nothing */ function connect2GuestLan(data) { var rsp = data.rsp; var args = data.msg.split(';'); var node = args[0].replace('node=', ''); var address = args[1].replace('addr=', ''); var lanName = args[2].replace('lan=', ''); var lanOwner = args[3].replace('owner=', ''); // Write ajax response to status bar var prg = writeRsp(rsp, node + ': '); $('#' + node + 'StatusBar').find('div').append(prg); // Connect NIC to Guest LAN $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'chvm', tgt : node, args : '--connectnic2guestlan;' + address + ';' + lanName + ';' + lanOwner, msg : node }, success : updateZNodeStatus }); } /** * Connect a NIC to a VSwitch * * @param data * Data from HTTP request * @return Nothing */ function connect2VSwitch(data) { var rsp = data.rsp; var args = data.msg.split(';'); var node = args[0].replace('node=', ''); var address = args[1].replace('addr=', ''); var vswitchName = args[2].replace('vsw=', ''); // Write ajax response to status bar var prg = writeRsp(rsp, node + ': '); $('#' + node + 'StatusBar').find('div').append(prg); // Connect NIC to VSwitch $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'chvm', tgt : node, args : '--connectnic2vswitch;' + address + ';' + vswitchName, msg : node }, success : updateZNodeStatus }); } /** * Create provision existing node division * * @param inst * Provision tab instance * @return Provision existing node division */ function createZProvisionExisting(inst) { // Create provision existing and hide it var provExisting = $('<div></div>').hide(); var vmFS = $('<fieldset></fieldset>'); var vmLegend = $('<legend>Virtual Machine</legend>'); vmFS.append(vmLegend); provExisting.append(vmFS); var vmAttr = $('<div style="display: inline-table; vertical-align: middle; width: 85%; margin-left: 10px;"></div>'); vmFS.append($('<div style="display: inline-table; vertical-align: middle;"><img src="images/provision/computer.png"></img></div>')); vmFS.append(vmAttr); var osFS = $('<fieldset></fieldset>'); var osLegend = $('<legend>Operating System</legend>'); osFS.append(osLegend); provExisting.append(osFS); var osAttr = $('<div style="display: inline-table; vertical-align: middle;"></div>'); osFS.append($('<div style="display: inline-table; vertical-align: middle;"><img src="images/provision/operating_system.png"></img></div>')); osFS.append(osAttr); // Create group input var group = $('<div></div>'); var groupLabel = $('<label for="provType">Group:</label>'); group.append(groupLabel); // Turn on auto complete for group var groupNames = $.cookie('groups'); if (groupNames) { // Split group names into an array var tmp = groupNames.split(','); // Create drop down for groups var groupSelect = $('<select></select>'); groupSelect.append('<option></option>'); for (var i in tmp) { // Add group into drop down var opt = $('<option value="' + tmp[i] + '">' + tmp[i] + '</option>'); groupSelect.append(opt); } group.append(groupSelect); // Create node datatable groupSelect.change(function(){ // Get group selected var thisGroup = $(this).val(); // If a valid group is selected if (thisGroup) { createNodesDatatable(thisGroup, 'zNodesDatatableDIV' + inst); } }); } else { // If no groups are cookied var groupInput = $('<input type="text" name="group"/>'); group.append(groupInput); } vmAttr.append(group); // Create node input var node = $('<div></div>'); var nodeLabel = $('<label for="nodeName">Nodes:</label>'); var nodeDatatable = $('<div class="indent" id="zNodesDatatableDIV' + inst + '" style="display: inline-block; max-width: 800px;"><p>Select a group to view its nodes</p></div>'); node.append(nodeLabel); node.append(nodeDatatable); vmAttr.append(node); // Create operating system image input var os = $('<div></div>'); var osLabel = $('<label for="os">Operating system image:</label>'); var osInput = $('<input type="text" name="os" title="You must give the operating system to install on this node or node range, e.g. rhel5.5-s390x-install-compute"/>'); // Get image names on focus osInput.one('focus', function(){ var imageNames = $.cookie('imagenames'); if (imageNames) { // Turn on auto complete $(this).autocomplete({ source: imageNames.split(',') }); } }); os.append(osLabel); os.append(osInput); osAttr.append(os); // Create boot method drop down var bootMethod = $('<div></div>'); var methoddLabel = $('<label>Boot method:</label>'); var methodSelect = $('<select name="bootMethod"></select>'); methodSelect.append('<option value="boot">boot</option>' + '<option value="install">install</option>' + '<option value="iscsiboot">iscsiboot</option>' + '<option value="netboot">netboot</option>' + '<option value="statelite">statelite</option>' ); bootMethod.append(methoddLabel); bootMethod.append(methodSelect); osAttr.append(bootMethod); // Generate tooltips provExisting.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" } }); /** * Provision existing */ var provisionBtn = createButton('Provision'); provisionBtn.bind('click', function(event) { // Remove any warning messages $(this).parent().parent().find('.ui-state-error').remove(); var ready = true; var errMsg = ''; // Get provision tab ID var thisTabId = $(this).parent().parent().parent().attr('id'); // Get provision tab instance var inst = thisTabId.replace('zvmProvisionTab', ''); // Get nodes that were checked var dTableId = 'zNodesDatatable' + inst; var tgts = getNodesChecked(dTableId); if (!tgts) { errMsg += 'You need to select a node.<br>'; ready = false; } // Check operating system image var os = $('#' + thisTabId + ' input[name=os]:visible'); if (!os.val()) { errMsg += 'You need to select a operating system image.'; os.css('border', 'solid #FF0000 1px'); ready = false; } else { os.css('border', 'solid #BDBDBD 1px'); } // If all inputs are valid, ready to provision if (ready) { // Disable provision button $(this).attr('disabled', 'true'); // Show loader $('#zProvisionStatBar' + inst).show(); $('#zProvisionLoader' + inst).show(); // Disable all inputs var inputs = $('#' + thisTabId + ' input:visible'); inputs.attr('disabled', 'disabled'); // Disable all selects var selects = $('#' + thisTabId + ' select'); selects.attr('disabled', 'disabled'); // Get operating system image var osImage = $('#' + thisTabId + ' input[name=os]:visible').val(); var tmp = osImage.split('-'); var os = tmp[0]; var arch = tmp[1]; var profile = tmp[3]; /** * (1) Set operating system */ $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'nodeadd', tgt : '', args : tgts + ';noderes.netboot=zvm;nodetype.os=' + os + ';nodetype.arch=' + arch + ';nodetype.profile=' + profile, msg : 'cmd=nodeadd;out=' + inst }, success : updateZProvisionExistingStatus }); } else { // Show warning message var warn = createWarnBar(errMsg); warn.prependTo($(this).parent().parent()); } }); provExisting.append(provisionBtn); return provExisting; } /** * Create provision new node division * * @param inst * Provision tab instance * @return Provision new node division */ function createZProvisionNew(inst) { // Create provision new node division var provNew = $('<div></div>'); // Create VM fieldset var vmFS = $('<fieldset></fieldset>'); var vmLegend = $('<legend>Virtual Machine</legend>'); vmFS.append(vmLegend); provNew.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 OS fieldset var osFS = $('<fieldset></fieldset>'); var osLegend = $('<legend>Operating System</legend>'); osFS.append(osLegend); provNew.append(osFS); // Create hardware fieldset var hwFS = $('<fieldset></fieldset>'); var hwLegend = $('<legend>Hardware</legend>'); hwFS.append(hwLegend); provNew.append(hwFS); var hwAttr = $('<div style="display: inline-table; vertical-align: middle;"></div>'); hwFS.append($('<div style="display: inline-table; vertical-align: middle;"><img src="images/provision/hardware.png"></img></div>')); hwFS.append(hwAttr); var osAttr = $('<div style="display: inline-table; vertical-align: middle;"></div>'); osFS.append($('<div style="display: inline-table; vertical-align: middle;"><img src="images/provision/operating_system.png"></img></div>')); osFS.append(osAttr); // Create group input var group = $('<div></div>'); var groupLabel = $('<label>Group:</label>'); var groupInput = $('<input type="text" name="group" title="You must give the group name that the node(s) will be placed under"/>'); // Get groups on-focus 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 node input var nodeName = $('<div></div>'); var nodeLabel = $('<label>Node:</label>'); var nodeInput = $('<input type="text" name="nodeName" title="You must give a node or a node range. A node range must be given as: node1-node9 or node[1-9]."/>'); nodeName.append(nodeLabel); nodeName.append(nodeInput); vmAttr.append(nodeName); // Create user ID input var userId = $('<div><label>User ID:</label><input type="text" name="userId" 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(userId); // Create hardware control point input var hcpDiv = $('<div></div>'); var hcpLabel = $('<label for="hcp">Hardware control point:</label>'); var hcpInput = $('<input type="text" name="hcp" title="You must give the System z hardware control point (zHCP) responsible for managing the node(s)"/>'); hcpInput.blur(function() { if ($(this).val()) { var args = $(this).val().split('.'); if (!$.cookie(args[0] + 'diskpools')) { // Get disk pools $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'lsvm', tgt : args[0], args : '--diskpoolnames', msg : args[0] }, success : setDiskPoolCookies }); } } }); hcpDiv.append(hcpLabel); hcpDiv.append(hcpInput); vmAttr.append(hcpDiv); // 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:</label><input type="text" name="ip" ' + 'title="Optional. Specify the IP address that will be assigned to this node. An IP address must be given in the following format: 192.168.0.1."/></div>'); advanced.append(ip); var hostname = $('<div><label>Hostname:</label><input type="text" name="hostname" ' + 'title="Optional. Specify the hostname that will be assigned to this node. A hostname must be given in the following format: ihost1.sourceforge.net."/></div>'); advanced.append(hostname); // Show IP address and hostname inputs on-click advancedLnk.click(function() { advanced.toggle(); }); // Create operating system image input var os = $('<div></div>'); var osLabel = $('<label for="os">Operating system image:</label>'); var osInput = $('<input type="text" name="os" title="You must give the operating system to install on this node or node range, e.g. rhel5.5-s390x-install-compute"/>'); // Get image names on focus osInput.one('focus', function(){ var imageNames = $.cookie('imagenames'); if (imageNames) { // Turn on auto complete $(this).autocomplete({ source: imageNames.split(',') }); } }); os.append(osLabel); os.append(osInput); osAttr.append(os); // Create user entry input var defaultChkbox = $('<input type="checkbox" name="userEntry" value="default"/>').click(function() { // Remove any warning messages $(this).parents('.form').find('.ui-state-error').remove(); // Get tab ID var thisTabId = $(this).parents('.ui-tabs-panel').attr('id'); // Get objects for HCP, user ID, and OS var hcp = $('#' + thisTabId + ' input[name=hcp]'); var userId = $('#' + thisTabId + ' input[name=userId]'); var os = $('#' + thisTabId + ' input[name=os]'); // Get default user entry when clicked if ($(this).attr('checked')) { if (!hcp.val() || !os.val() || !userId.val()) { // Show warning message var warn = createWarnBar('Please specify the hardware control point, operating system, and user ID before checking this box'); warn.prependTo($(this).parents('.form')); // Highlight empty fields jQuery.each([hcp, os, userId], function() { if (!$(this).val()) { $(this).css('border', 'solid #FF0000 1px'); } }); } else { // Un-highlight empty fields jQuery.each([hcp, os, userId], function() { $(this).css('border', 'solid #BDBDBD 1px'); }); // Get profile name var tmp = os.val().split('-'); var profile = tmp[3]; $.ajax({ url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'webrun', tgt : '', args : 'getdefaultuserentry;' + hcp.val() + ';' + profile, msg : thisTabId }, success:function(data) { // Populate user entry var tabId = data.msg; var entry = new String(data.rsp); var userId = $('#' + tabId + ' input[name=userId]').val(); entry = entry.replace(new RegExp('LXUSR', 'g'), userId); $('#' + tabId + ' textarea:visible').val(entry); } }); } } else { $('#' + thisTabId + ' textarea:visible').val(''); // Un-highlight empty fields jQuery.each([hcp, os, userId], function() { $(this).css('border', 'solid #BDBDBD 1px'); }); } }); var userEntry = $('<div><label style="vertical-align: top;">Directory entry:</label><textarea/></textarea></div>'); userEntry.append($('<span></span>').append(defaultChkbox, 'Use default')); hwAttr.append(userEntry); // Create disk table var diskDiv = $('<div class="provision"></div>'); var diskLabel = $('<label>Disks:</label>'); var diskTable = $('<table></table>'); var diskHeader = $('<thead class="ui-widget-header"> <th></th> <th>Type</th> <th>Address</th> <th>Size</th> <th>Mode</th> <th>Pool</th> <th>Password</th> </thead>'); // Adjust header width diskHeader.find('th').css( { 'width' : '80px' }); diskHeader.find('th').eq(0).css( { 'width' : '20px' }); var diskBody = $('<tbody></tbody>'); var diskFooter = $('<tfoot></tfoot>'); /** * Add disks */ var addDiskLink = $('<a>Add disk</a>'); addDiskLink.bind('click', function(event) { // Create a row var diskRow = $('<tr></tr>'); // Add remove button var removeBtn = $('<span class="ui-icon ui-icon-close"></span>'); var col = $('<td></td>').append(removeBtn); removeBtn.bind('click', function(event) { diskRow.remove(); }); diskRow.append(col); // Create disk type drop down var diskType = $('<td></td>'); var diskTypeSelect = $('<select></select>'); diskTypeSelect.append('<option value="3390">3390</option>' + '<option value="9336">9336</option>' ); diskType.append(diskTypeSelect); diskRow.append(diskType); // Create disk address input var diskAddr = $('<td><input type="text" title="You must give the virtual device address of the disk to be added"/></td>'); diskRow.append(diskAddr); // Create disk size input var diskSize = $('<td><input type="text" title="You must give the size of the disk to be created. The size value is one of the following: cylinders or block size. "/></td>'); diskRow.append(diskSize); // Create disk mode input var diskMode = $('<td></td>'); var diskModeSelect = $('<select></select>'); diskModeSelect.append('<option value="R">R</option>' + '<option value="RR">RR</option>' + '<option value="W">W</option>' + '<option value="WR">WR</option>' + '<option value="M">M</option>' + '<option value="MR">MR</option>' + '<option value="MW">MW</option>' ); diskMode.append(diskModeSelect); diskRow.append(diskMode); // Get list of disk pools var thisTabId = $(this).parents('.tab').attr('id'); var thisHcp = $('#' + thisTabId + ' input[name=hcp]').val(); var definedPools; if (thisHcp) { // Get node without domain name var temp = thisHcp.split('.'); definedPools = $.cookie(temp[0] + 'diskpools'); } // Create disk pool input // Turn on auto complete for disk pool var diskPoolInput = $('<input type="text" title="You must give the group or region where the new image disk is to be created"/>').autocomplete({ source: definedPools.split(',') }); var diskPool = $('<td></td>').append(diskPoolInput); diskRow.append(diskPool); // Create disk password input var diskPw = $('<td><input type="password" title="You must give the password that will be used for accessing the disk"/></td>'); diskRow.append(diskPw); diskBody.append(diskRow); // Generate tooltips diskBody.find('td input[title]').tooltip({ position: "top right", offset: [-4, 4], effect: "fade", opacity: 0.7, predelay: 800, events: { def: "mouseover,mouseout", input: "mouseover,mouseout", widget: "focus mouseover,blur mouseout", tooltip: "mouseover,mouseout" } }); }); // Create disk table diskFooter.append(addDiskLink); diskTable.append(diskHeader); diskTable.append(diskBody); diskTable.append(diskFooter); diskDiv.append(diskLabel); diskDiv.append(diskTable); hwAttr.append(diskDiv); // Generate tooltips provNew.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" } }); /** * Provision new */ var provisionBtn = createButton('Provision'); provisionBtn.bind('click', function(event) { // Remove any warning messages $(this).parent().parent().find('.ui-state-error').remove(); var ready = true; var errMsg = ''; // Get tab ID var thisTabId = $(this).parents('.ui-tabs-panel').attr('id'); // Get provision tab instance var inst = thisTabId.replace('zvmProvisionTab', ''); // Check node name, userId, hardware control point, and group var inputs = $('#' + thisTabId + ' input:visible'); for ( var i = 0; i < inputs.length; i++) { // Do not check OS or disk password if (!inputs.eq(i).val() && inputs.eq(i).attr('name') != 'os' && inputs.eq(i).attr('type') != 'password') { inputs.eq(i).css('border', 'solid #FF0000 1px'); ready = false; } else { inputs.eq(i).css('border', 'solid #BDBDBD 1px'); } } // Check user entry var thisUserEntry = $('#' + thisTabId + ' textarea:visible'); thisUserEntry.val(thisUserEntry.val().toUpperCase()); if (!thisUserEntry.val()) { thisUserEntry.css('border', 'solid #FF0000 1px'); ready = false; } else { thisUserEntry.css('border', 'solid #BDBDBD 1px'); } // Show error message for missing inputs if (!ready) { errMsg = errMsg + 'Please provide a value for each missing field.<br>'; } // Check if user entry contains user ID var thisUserId = $('#' + thisTabId + ' input[name=userId]:visible'); var pos = thisUserEntry.val().indexOf('USER ' + thisUserId.val().toUpperCase()); if (pos < 0) { errMsg = errMsg + 'The directory entry does not contain the correct user ID.<br>'; ready = false; } // If no operating system is specified, create only user entry os = $('#' + thisTabId + ' input[name=os]:visible'); // Check number of disks var diskRows = $('#' + thisTabId + ' table tr'); // If an OS is given, disks are needed if (os.val() && (diskRows.length < 1)) { errMsg = errMsg + 'You need to add at some disks.<br>'; ready = false; } // Check address, size, mode, pool, and password var diskArgs = $('#' + thisTabId + ' table input:visible'); for ( var i = 0; i < diskArgs.length; i++) { if (!diskArgs.eq(i).val() && diskArgs.eq(i).attr('type') != 'password') { diskArgs.eq(i).css('border', 'solid #FF0000 1px'); ready = false; } else { diskArgs.eq(i).css('border', 'solid #BDBDBD 1px'); } } // If inputs are valid, ready to provision if (ready) { if (!os.val()) { // If no OS is given, create a virtual server var msg = ''; if (diskRows.length > 0) { msg = 'Do you want to create a virtual server without an operating system?'; } else { // If no disks are given, create a virtual server (no disk) msg = 'Do you want to create a virtual server without an operating system or disks?'; } // Open dialog to confirm var confirmDialog = $('<div><p>' + msg + '</p></div>'); confirmDialog.dialog({ title:'Confirm', modal: true, width: 400, buttons: { "Ok": function(){ // Disable provision button provisionBtn.attr('disabled', 'true'); // Show loader $('#zProvisionStatBar' + inst).show(); $('#zProvisionLoader' + inst).show(); // Disable add disk button addDiskLink.attr('disabled', 'true'); // Disable close button on disk table $('#' + thisTabId + ' table span').unbind('click'); // Disable all inputs var inputs = $('#' + thisTabId + ' input'); inputs.attr('disabled', 'disabled'); // Disable all selects var selects = $('#' + thisTabId + ' select'); selects.attr('disabled', 'disabled'); // Add a new line at the end of the user entry var textarea = $('#' + thisTabId + ' textarea'); var tmp = jQuery.trim(textarea.val()); textarea.val(tmp + '\n'); textarea.attr('readonly', 'readonly'); textarea.css( { 'background-color' : '#F2F2F2' }); // Get node name var node = $('#' + thisTabId + ' input[name=nodeName]').val(); // Get userId var userId = $('#' + thisTabId + ' input[name=userId]').val(); // Get hardware control point var hcp = $('#' + thisTabId + ' input[name=hcp]').val(); // Get group var group = $('#' + thisTabId + ' input[name=group]').val(); // Get IP address and hostname var ip = $('#' + thisTabId + ' input[name=ip]').val(); var hostname = $('#' + thisTabId + ' input[name=hostname]').val(); // Generate arguments to sent var args = node + ';zvm.hcp=' + hcp + ';zvm.userid=' + userId + ';nodehm.mgt=zvm' + ';groups=' + group; if (ip) args += ';hosts.ip=' + ip; if (hostname) args += ';hosts.hostnames=' + hostname; /** * (1) Define node */ $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'nodeadd', tgt : '', args : args, msg : 'cmd=nodeadd;out=' + inst }, success : updateZProvisionNewStatus }); $(this).dialog("close"); }, "Cancel": function() { $(this).dialog("close"); } } }); } else { /** * Create a virtual server and install OS */ // Disable provision button $(this).attr('disabled', 'true'); // Show loader $('#zProvisionStatBar' + inst).show(); $('#zProvisionLoader' + inst).show(); // Disable add disk button addDiskLink.attr('disabled', 'true'); // Disable close button on disk table $('#' + thisTabId + ' table span').unbind('click'); // Disable all inputs var inputs = $('#' + thisTabId + ' input'); inputs.attr('disabled', 'disabled'); inputs.css( { 'background-color' : '#F2F2F2' }); // Disable all selects var selects = $('#' + thisTabId + ' select'); selects.attr('disabled', 'disabled'); selects.css( { 'background-color' : '#F2F2F2' }); // Add a new line at the end of the user entry var textarea = $('#' + thisTabId + ' textarea'); var tmp = jQuery.trim(textarea.val()); textarea.val(tmp + '\n'); textarea.attr('readonly', 'readonly'); textarea.css( { 'background-color' : '#F2F2F2' }); // Get node name var node = $('#' + thisTabId + ' input[name=nodeName]').val(); // Get userId var userId = $('#' + thisTabId + ' input[name=userId]').val(); // Get hardware control point var hcp = $('#' + thisTabId + ' input[name=hcp]').val(); // Get group var group = $('#' + thisTabId + ' input[name=group]').val(); // Get IP address and hostname var ip = $('#' + thisTabId + ' input[name=ip]').val(); var hostname = $('#' + thisTabId + ' input[name=hostname]').val(); // Generate arguments to sent var args = node + ';zvm.hcp=' + hcp + ';zvm.userid=' + userId + ';nodehm.mgt=zvm' + ';groups=' + group; if (ip) args += ';hosts.ip=' + ip; if (hostname) args += ';hosts.hostnames=' + hostname; /** * (1) Define node */ $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'nodeadd', tgt : '', args : args, msg : 'cmd=nodeadd;out=' + inst }, success : updateZProvisionNewStatus }); } } else { // Show warning message var warn = createWarnBar(errMsg); warn.prependTo($(this).parent().parent()); } }); provNew.append(provisionBtn); return provNew; } /** * Load zVMs into column (service page) * * @param col * Table column where OS images will be placed * @return Nothing */ function loadzVMs(col) { // Get group names and description and append to group column var groupNames = $.cookie('srv_zvms').split(','); var radio, zvmBlock, args, zvm, hcp; for (var i in groupNames) { args = groupNames[i].split(':'); zvm = args[0]; hcp = args[1]; // Create block for each group zvmBlock = $('<div class="ui-state-default"></div>').css({ 'border': '1px solid', 'max-width': '200px', 'margin': '5px auto', 'padding': '5px', 'display': 'block', 'vertical-align': 'middle', 'cursor': 'pointer', 'white-space': 'normal' }).click(function(){ $(this).children('input:radio').attr('checked', 'checked'); $(this).parents('td').find('div').attr('class', 'ui-state-default'); $(this).attr('class', 'ui-state-active'); }); radio = $('<input type="radio" name="hcp" value="' + hcp + '"/>').css('display', 'none'); zvmBlock.append(radio, $('<span style="font-weight: normal;"><b>' + zvm + '</b> managed by ' + hcp + '</span>')); zvmBlock.children('span').css({ 'display': 'block', 'margin': '5px', 'text-align': 'left' }); col.append(zvmBlock); } } /** * Load groups into column * * @param col * Table column where OS images will be placed * @return Nothing */ function loadSrvGroups(col) { // Get group names and description and append to group column var groupNames = $.cookie('srv_groups').split(','); var groupBlock, radio, args, name, ip, hostname, desc; for (var i in groupNames) { args = groupNames[i].split(':'); name = args[0]; ip = args[1]; hostname = args[2]; desc = args[3]; // Create block for each group groupBlock = $('<div class="ui-state-default"></div>').css({ 'border': '1px solid', 'max-width': '200px', 'margin': '5px auto', 'padding': '5px', 'display': 'block', 'vertical-align': 'middle', 'cursor': 'pointer', 'white-space': 'normal' }).click(function(){ $(this).children('input:radio').attr('checked', 'checked'); $(this).parents('td').find('div').attr('class', 'ui-state-default'); $(this).attr('class', 'ui-state-active'); }); radio = $('<input type="radio" name="group" value="' + name + '"/>').css('display', 'none'); groupBlock.append(radio, $('<span style="font-weight: normal;"><b>' + name + '</b>: ' + desc + '</span>')); groupBlock.children('span').css({ 'display': 'block', 'margin': '5px', 'text-align': 'left' }); col.append(groupBlock); } } /** * Load OS images into column * * @param col * Table column where OS images will be placed * @return Nothing */ function loadOSImages(col) { // Get group names and description and append to group column var imgNames = $.cookie('srv_imagenames').split(','); var imgBlock, radio, args, name, desc; for (var i in imgNames) { args = imgNames[i].split(':'); name = args[0]; desc = args[1]; // Create block for each image imgBlock = $('<div class="ui-state-default"></div>').css({ 'border': '1px solid', 'max-width': '200px', 'margin': '5px auto', 'padding': '5px', 'display': 'block', 'vertical-align': 'middle', 'cursor': 'pointer', 'white-space': 'normal' }).click(function(){ $(this).children('input:radio').attr('checked', 'checked'); $(this).parents('td').find('div').attr('class', 'ui-state-default'); $(this).attr('class', 'ui-state-active'); }); radio = $('<input type="radio" name="image" value="' + name + '"/>').css('display', 'none'); imgBlock.append(radio, $('<span style="font-weight: normal;"><b>' + name + '</b>: ' + desc + '</span>')); imgBlock.children('span').css({ 'display': 'block', 'margin': '5px', 'text-align': 'left' }); col.append(imgBlock); } } /** * Set a cookie for zVM host names (service page) * * @param data * Data from HTTP request * @return Nothing */ function setzVMCookies(data) { if (data.rsp) { var zvms = new Array(); for ( var i = 0; i < data.rsp.length; i++) { zvms.push(data.rsp[i]); } // Set cookie to expire in 60 minutes var exDate = new Date(); exDate.setTime(exDate.getTime() + (240 * 60 * 1000)); $.cookie('srv_zvms', zvms, { expires: exDate }); } } /** * Set a cookie for disk pool names of a given node (service page) * * @param data * Data from HTTP request * @return Nothing */ function setDiskPoolCookies(data) { if (data.rsp) { var node = data.msg; var pools = data.rsp[0].split(node + ': '); for (var i in pools) { pools[i] = jQuery.trim(pools[i]); } // Set cookie to expire in 60 minutes var exDate = new Date(); exDate.setTime(exDate.getTime() + (240 * 60 * 1000)); $.cookie(node + 'diskpools', pools, { expires: exDate }); } } /** * Create virtual machine (service page) * * @param tabId * Tab ID * @param group * Group * @param hcp * Hardware control point * @param img * OS image * @return Nothing */ function createzVM(tabId, group, hcp, img, owner) { // Submit request to create VM // webportal provzlinux [group] [hcp] [image] [owner] var iframe = createIFrame('lib/srv_cmd.php?cmd=webportal&tgt=&args=provzlinux;' + group + ';' + hcp + ';' + img + ';' + owner + '&msg=&opts=flush'); iframe.prependTo($('#' + tabId)); }