Backport z/VM code in trunk to 2.8 branch.
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/branches/2.8@15441 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
parent
91fbf65bbf
commit
43de2697b3
@ -731,7 +731,7 @@ function configGroupPanel(data) {
|
||||
// Create table
|
||||
var tableId = panelId + 'Datatable';
|
||||
var table = new DataTable(tableId);
|
||||
table.init(['<input type="checkbox" onclick="selectAllCheckbox(event, $(this))">', 'Name', 'Selectable', 'IP', 'Hostname', 'Network', 'Description']);
|
||||
table.init(['<input type="checkbox" onclick="selectAllCheckbox(event, $(this))">', 'Name', 'Selectable', 'IP', 'Hostname', 'Description']);
|
||||
|
||||
// Insert groups into table
|
||||
var nodePos = 0;
|
||||
@ -787,12 +787,6 @@ function configGroupPanel(data) {
|
||||
desc = jQuery.trim(desc);
|
||||
}
|
||||
|
||||
// Save network
|
||||
if (tmp[j].indexOf('network:') > -1) {
|
||||
network = tmp[j].replace('network:', '');
|
||||
network = jQuery.trim(network);
|
||||
}
|
||||
|
||||
// Is the group selectable?
|
||||
if (tmp[j].indexOf('selectable:') > -1) {
|
||||
selectable = tmp[j].replace('selectable:', '');
|
||||
@ -802,7 +796,7 @@ function configGroupPanel(data) {
|
||||
}
|
||||
|
||||
// Columns are: name, selectable, network, and description
|
||||
var cols = new Array(name, selectable, ip, hostname, network, desc);
|
||||
var cols = new Array(name, selectable, ip, hostname, desc);
|
||||
|
||||
// Add remove button where id = user name
|
||||
cols.unshift('<input type="checkbox" name="' + name + '"/>');
|
||||
@ -851,10 +845,9 @@ function configGroupPanel(data) {
|
||||
var selectable = cols.eq(2).text();
|
||||
var ip = cols.eq(3).text();
|
||||
var hostnames = cols.eq(4).text();
|
||||
var network = cols.eq(5).text();
|
||||
var description = cols.eq(6).text();
|
||||
var description = cols.eq(5).text();
|
||||
|
||||
editGroupDialog(group, selectable, ip, hostnames, network, description);
|
||||
editGroupDialog(group, selectable, ip, hostnames, description);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -913,9 +906,10 @@ function groupDialog() {
|
||||
var selectable = $('<div><label>Selectable:</label><input type="checkbox" name="selectable" title="Select if you want this group to appear on the self service portal"/></div>');
|
||||
var ip = $('<div><label>IP:</label><input type="text" name="ip" title="The IP address of the nodes, usually given as a regular expression, e.g. |ihost(\d+)|10.1.1.($1+0)|"/></div>');
|
||||
var hostnames = $('<div><label>Hostnames:</label><input type="text" name="hostnames" title="The hostname of the nodes, usually given as a regular expression, e.g. |(.*)|($1).sourceforge.net|"/></div>');
|
||||
var network = $('<div><label>Network:</label><input type="text" name="network" title="The groups network and its subnet mask, e.g. 10.1.1.0/24"/></div>');
|
||||
var comments = $('<div><label>Description:</label><input type="text" name="comments" title="A description of the group"/></div>');
|
||||
groupForm.append(group, selectable, ip, hostnames, network, comments);
|
||||
var ipPool = $('<div><label style="vertical-align: top;">IP pool:</label><textarea name="ip_pool" title="A pool of node names, IP addresses, and hostnames that can be chosen from for a newly provisioned virtual machine. An entry in the pool could be: ihost12,10.1.2.12,ihost12.endicott.ibm.com. A newline separates each entry."/></div>');
|
||||
|
||||
groupForm.append(group, selectable, ip, hostnames, comments, ipPool);
|
||||
|
||||
// Generate tooltips
|
||||
groupForm.find('div input[title],textarea[title],select[title]').tooltip({
|
||||
@ -945,7 +939,7 @@ function groupDialog() {
|
||||
close: function(){
|
||||
$(this).remove();
|
||||
},
|
||||
width: 400,
|
||||
width: 600,
|
||||
buttons: {
|
||||
"Ok": function() {
|
||||
// Remove any warning messages
|
||||
@ -956,12 +950,12 @@ function groupDialog() {
|
||||
var selectable = $(this).find('input[name="selectable"]');
|
||||
var ip = $(this).find('input[name="ip"]');
|
||||
var hostnames = $(this).find('input[name="hostnames"]');
|
||||
var network = $(this).find('input[name="network"]');
|
||||
var comments = $(this).find('input[name="comments"]');
|
||||
var ipPool = $(this).find('textarea[name=ip_pool]').val();
|
||||
|
||||
// Check that group attributes are provided before continuing
|
||||
var ready = 1;
|
||||
var inputs = new Array(group, ip, hostnames, network);
|
||||
var inputs = new Array(group, ip, hostnames);
|
||||
for (var i in inputs) {
|
||||
if (!inputs[i].val()) {
|
||||
inputs[i].css('border-color', 'red');
|
||||
@ -980,6 +974,10 @@ function groupDialog() {
|
||||
'Close': function() {$(this).dialog("close");}
|
||||
});
|
||||
|
||||
// A newline at the end of IP pool is needed
|
||||
ipPool = ipPool.replace(/^\s+|\s+$/g, '');
|
||||
ipPool += '\n';
|
||||
|
||||
// Set default description
|
||||
if (!comments.val())
|
||||
comments.val('No description');
|
||||
@ -988,12 +986,12 @@ function groupDialog() {
|
||||
var args = "updategroup;" + group.val() + ";'" + ip.val() + "';'" + hostnames.val() + "';";
|
||||
|
||||
if (selectable.attr("checked"))
|
||||
args += "'description:" + comments.val() + "|network:" + network.val() + "|selectable:yes";
|
||||
args += "'description:" + comments.val() + "|selectable:yes";
|
||||
else
|
||||
args += "'description:" + comments.val() + "|network:" + network.val() + "|selectable:no";
|
||||
args += "'description:" + comments.val() + "|selectable:no";
|
||||
|
||||
// Add image to xCAT
|
||||
$.ajax( {
|
||||
$.ajax({
|
||||
url : 'lib/cmd.php',
|
||||
dataType : 'json',
|
||||
data : {
|
||||
@ -1005,6 +1003,37 @@ function groupDialog() {
|
||||
|
||||
success : updatePanel
|
||||
});
|
||||
|
||||
// Write IP pool file to /var/tmp
|
||||
$.ajax({
|
||||
url : 'lib/cmd.php',
|
||||
dataType : 'json',
|
||||
data : {
|
||||
cmd : 'write',
|
||||
tgt : '/var/tmp/' + group.val() + '.pool',
|
||||
args : '',
|
||||
cont : ipPool,
|
||||
msg : dialogId + ';' + group.val()
|
||||
},
|
||||
|
||||
success : function(data) {
|
||||
var args = data.msg.split(';');
|
||||
|
||||
// Create profile in xCAT
|
||||
$.ajax({
|
||||
url : 'lib/cmd.php',
|
||||
dataType : 'json',
|
||||
data : {
|
||||
cmd : 'webrun',
|
||||
tgt : '',
|
||||
args : 'mkippool;' + args[1],
|
||||
msg : args[0]
|
||||
},
|
||||
|
||||
success: updatePanel
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
"Cancel": function() {
|
||||
@ -1021,10 +1050,9 @@ function groupDialog() {
|
||||
* @param iSelectable Is group selectable from the service page
|
||||
* @param iIp Group IP regex
|
||||
* @param iHostnames Group hostnames regex
|
||||
* @param iNetwork Group network, e.g. 10.1.2.0/24
|
||||
* @param iComments Group description
|
||||
*/
|
||||
function editGroupDialog(iGroup, iSelectable, iIp, iHostnames, iNetwork, iComments) {
|
||||
function editGroupDialog(iGroup, iSelectable, iIp, iHostnames, iComments) {
|
||||
// Create form to add profile
|
||||
var dialogId = 'createGroup-' + iGroup;
|
||||
var groupForm = $('<div id="' + dialogId + '" class="form"></div>');
|
||||
@ -1037,15 +1065,32 @@ function editGroupDialog(iGroup, iSelectable, iIp, iHostnames, iNetwork, iCommen
|
||||
var selectable = $('<div><label>Selectable:</label><input type="checkbox" name="selectable" title="Select if you want this group to appear on the self service portal"/></div>');
|
||||
var ip = $('<div><label>IP:</label><input type="text" name="ip" title="The IP address for the group, usually given as a regular expression, e.g. |ihost(\d+)|10.1.1.($1+0)|"/></div>');
|
||||
var hostnames = $('<div><label>Hostnames:</label><input type="text" name="hostnames" title="The hostname for the group, usually given as a regular expression, e.g. |(.*)|($1).sourceforge.net|"/></div>');
|
||||
var network = $('<div><label>Network:</label><input type="text" name="network" title="The groups network and its subnet mask, e.g. 10.1.1.0/24"/></div>');
|
||||
var comments = $('<div><label>Description:</label><input type="text" name="comments" title="A description of the group"/></div>');
|
||||
groupForm.append(group, selectable, ip, hostnames, network, comments);
|
||||
var ipPool = $('<div><label style="vertical-align: top;">IP pool:</label><textarea name="ip_pool" title="A pool of node names, IP addresses, and hostnames that can be chosen from for a newly provisioned virtual machine."/></div>');
|
||||
|
||||
groupForm.append(group, selectable, ip, hostnames, comments, ipPool);
|
||||
|
||||
// Query IP pool based on group name
|
||||
$.ajax({
|
||||
url : 'lib/cmd.php',
|
||||
dataType : 'json',
|
||||
data : {
|
||||
cmd : 'webrun',
|
||||
tgt : '',
|
||||
args : 'lsippool;' + iGroup,
|
||||
msg : dialogId
|
||||
},
|
||||
|
||||
success : function(data) {
|
||||
// Populate textarea with IP pool entries
|
||||
$('#' + data.msg).find('textarea[name="ip_pool"]').val(data.rsp[0]);
|
||||
}
|
||||
});
|
||||
|
||||
// Fill in group attributes
|
||||
groupForm.find('input[name="group"]').val(iGroup);
|
||||
groupForm.find('input[name="ip"]').val(iIp);
|
||||
groupForm.find('input[name="hostnames"]').val(iHostnames);
|
||||
groupForm.find('input[name="network"]').val(iNetwork);
|
||||
groupForm.find('input[name="comments"]').val(iComments);
|
||||
if (iSelectable == "yes")
|
||||
groupForm.find('input[name="selectable"]').attr('checked', 'checked');
|
||||
@ -1078,7 +1123,7 @@ function editGroupDialog(iGroup, iSelectable, iIp, iHostnames, iNetwork, iCommen
|
||||
close: function(){
|
||||
$(this).remove();
|
||||
},
|
||||
width: 400,
|
||||
width: 600,
|
||||
buttons: {
|
||||
"Ok": function() {
|
||||
// Remove any warning messages
|
||||
@ -1089,12 +1134,12 @@ function editGroupDialog(iGroup, iSelectable, iIp, iHostnames, iNetwork, iCommen
|
||||
var selectable = $(this).find('input[name="selectable"]');
|
||||
var ip = $(this).find('input[name="ip"]');
|
||||
var hostnames = $(this).find('input[name="hostnames"]');
|
||||
var network = $(this).find('input[name="network"]');
|
||||
var comments = $(this).find('input[name="comments"]');
|
||||
var ipPool = $(this).find('textarea[name=ip_pool]').val();
|
||||
|
||||
// Check that group attributes are provided before continuing
|
||||
var ready = 1;
|
||||
var inputs = new Array(group, ip, hostnames, network);
|
||||
var inputs = new Array(group, ip, hostnames);
|
||||
for (var i in inputs) {
|
||||
if (!inputs[i].val()) {
|
||||
inputs[i].css('border-color', 'red');
|
||||
@ -1113,6 +1158,10 @@ function editGroupDialog(iGroup, iSelectable, iIp, iHostnames, iNetwork, iCommen
|
||||
'Close': function() {$(this).dialog("close");}
|
||||
});
|
||||
|
||||
// A newline at the end of IP pool is needed
|
||||
ipPool = ipPool.replace(/^\s+|\s+$/g, '');
|
||||
ipPool += '\n';
|
||||
|
||||
// Set default description
|
||||
if (!comments.val())
|
||||
comments.val('No description');
|
||||
@ -1121,9 +1170,9 @@ function editGroupDialog(iGroup, iSelectable, iIp, iHostnames, iNetwork, iCommen
|
||||
var args = "updategroup;" + group.val() + ";'" + ip.val() + "';'" + hostnames.val() + "';";
|
||||
|
||||
if (selectable.attr("checked"))
|
||||
args += "'description:" + comments.val() + "|network:" + network.val() + "|selectable:yes";
|
||||
args += "'description:" + comments.val() + "|selectable:yes";
|
||||
else
|
||||
args += "'description:" + comments.val() + "|network:" + network.val() + "|selectable:no";
|
||||
args += "'description:" + comments.val() + "|selectable:no";
|
||||
|
||||
// Add image to xCAT
|
||||
$.ajax( {
|
||||
@ -1138,6 +1187,37 @@ function editGroupDialog(iGroup, iSelectable, iIp, iHostnames, iNetwork, iCommen
|
||||
|
||||
success : updatePanel
|
||||
});
|
||||
|
||||
// Write IP pool file to /var/tmp
|
||||
$.ajax({
|
||||
url : 'lib/cmd.php',
|
||||
dataType : 'json',
|
||||
data : {
|
||||
cmd : 'write',
|
||||
tgt : '/var/tmp/' + group.val() + '.pool',
|
||||
args : '',
|
||||
cont : ipPool,
|
||||
msg : dialogId + ';' + group.val()
|
||||
},
|
||||
|
||||
success : function(data) {
|
||||
var args = data.msg.split(';');
|
||||
|
||||
// Create profile in xCAT
|
||||
$.ajax({
|
||||
url : 'lib/cmd.php',
|
||||
dataType : 'json',
|
||||
data : {
|
||||
cmd : 'webrun',
|
||||
tgt : '',
|
||||
args : 'mkippool;' + args[1],
|
||||
msg : args[0]
|
||||
},
|
||||
|
||||
success: updatePanel
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
"Cancel": function() {
|
||||
|
@ -33,7 +33,7 @@ zvmPlugin.prototype.loadConfigPage = function(tabId) {
|
||||
|
||||
// Create accordion panel for images
|
||||
var imgSection = $('<div id="zvmConfigImages"></div>');
|
||||
var imgLnk = $('<h3><a href="#">Images</a></h3>').click(function () {
|
||||
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;
|
||||
@ -67,7 +67,7 @@ zvmPlugin.prototype.loadConfigPage = function(tabId) {
|
||||
*
|
||||
* @param node Node to clone
|
||||
*/
|
||||
zvmPlugin.prototype.serviceClone = function(node) {
|
||||
zvmPlugin.prototype.serviceClone = function(node) {
|
||||
var owner = $.cookie('xcat_username');
|
||||
var group = getUserNodeAttr(node, 'groups');
|
||||
|
||||
@ -95,7 +95,7 @@ zvmPlugin.prototype.loadServiceProvisionPage = function(tabId) {
|
||||
|
||||
// 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>Image</th></thead>');
|
||||
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);
|
||||
@ -108,16 +108,18 @@ zvmPlugin.prototype.loadServiceProvisionPage = function(tabId) {
|
||||
// Create row to contain selections
|
||||
var provRow = $('<tr></tr>');
|
||||
provBody.append(provRow);
|
||||
// Create columns for zVM, group, and image
|
||||
// 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 imageCol = $('<td style="vertical-align: top;"></td>');
|
||||
provRow.append(imageCol);
|
||||
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': '250px'
|
||||
'min-width': '200px'
|
||||
});
|
||||
|
||||
/**
|
||||
@ -130,23 +132,38 @@ zvmPlugin.prototype.loadServiceProvisionPage = function(tabId) {
|
||||
|
||||
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 img = $('#select-table tbody tr:eq(0) td:eq(2) input[name="image"]: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 (!hcp || !group || !img) {
|
||||
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 an option for each column');
|
||||
var warn = createWarnBar('You need to select a zHCP, group, and image');
|
||||
warn.prependTo($(this).parent());
|
||||
} else {
|
||||
// Begin by creating VM
|
||||
createzVM(tabId, group, hcp, img, owner);
|
||||
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, and images into their respective columns
|
||||
// Load zVMs, groups, template, and image into their respective columns
|
||||
loadSrvGroups(groupCol);
|
||||
loadOSImages(imageCol);
|
||||
loadOSImages(tmplCol);
|
||||
loadGoldenImages(imgCol);
|
||||
|
||||
// Get zVM host names
|
||||
if (!$.cookie('zvms')){
|
||||
|
@ -5569,6 +5569,9 @@ function loadOSImages(col) {
|
||||
$(this).children('input:radio').attr('checked', 'checked');
|
||||
$(this).parents('td').find('div').attr('class', 'ui-state-default');
|
||||
$(this).attr('class', 'ui-state-active');
|
||||
|
||||
$('#select-table tbody tr:eq(0) td:eq(3) input[name="master"]').attr('checked', '');
|
||||
$('#select-table tbody tr:eq(0) td:eq(3) input[name="master"]').parents('td').find('div').attr('class', 'ui-state-default');
|
||||
});
|
||||
radio = $('<input type="radio" name="image" value="' + name + '"/>').css('display', 'none');
|
||||
imgBlock.append(radio, $('<span style="font-weight: normal;"><b>' + name + '</b>: ' + desc + '</span>'));
|
||||
@ -5581,6 +5584,60 @@ function loadOSImages(col) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load golden images into column
|
||||
*
|
||||
* @param col Table column where master copies will be placed
|
||||
*/
|
||||
function loadGoldenImages(col) {
|
||||
// Get group names and description and append to group column
|
||||
if (!$.cookie('srv_goldenimages')) {
|
||||
var infoBar = createInfoBar('No selectable master copies available');
|
||||
col.append(infoBar);
|
||||
return;
|
||||
}
|
||||
|
||||
var imgNames = $.cookie('srv_goldenimages').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');
|
||||
|
||||
// Un-select zVM and image
|
||||
$('#select-table tbody tr:eq(0) td:eq(2) input[name="image"]').attr('checked', '');
|
||||
$('#select-table tbody tr:eq(0) td:eq(2) input[name="image"]').parents('td').find('div').attr('class', 'ui-state-default');
|
||||
|
||||
$('#select-table tbody tr:eq(0) td:eq(0) input[name="hcp"]').attr('checked', '');
|
||||
$('#select-table tbody tr:eq(0) td:eq(0) input[name="hcp"]').parents('td').find('div').attr('class', 'ui-state-default');
|
||||
});
|
||||
radio = $('<input type="radio" name="master" 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)
|
||||
*
|
||||
@ -5603,6 +5660,28 @@ function setzVMCookies(data) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a cookie for master copies (service page)
|
||||
*
|
||||
* @param data Data from HTTP request
|
||||
*/
|
||||
function setGoldenImagesCookies(data) {
|
||||
if (data.rsp[0].length) {
|
||||
var copies = new Array();
|
||||
var tmp = data.rsp[0].split(",");
|
||||
for ( var i = 0; i < tmp.length; i++) {
|
||||
if (tmp[i] != null && tmp[i] != "") {
|
||||
copies.push(tmp[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Set cookie to expire in 60 minutes
|
||||
var exDate = new Date();
|
||||
exDate.setTime(exDate.getTime() + (240 * 60 * 1000));
|
||||
$.cookie('srv_goldenimages', copies, { expires: exDate });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a cookie for disk pool names of a given node
|
||||
*
|
||||
|
@ -239,22 +239,38 @@ function loadServiceProvisionPage(tabId) {
|
||||
title = 'z/VM';
|
||||
|
||||
// Get zVM host names
|
||||
if (!$.cookie('zvms')){
|
||||
$.ajax( {
|
||||
url : 'lib/srv_cmd.php',
|
||||
dataType : 'json',
|
||||
data : {
|
||||
cmd : 'webportal',
|
||||
tgt : '',
|
||||
args : 'lszvm',
|
||||
msg : ''
|
||||
},
|
||||
$.ajax({
|
||||
url : 'lib/srv_cmd.php',
|
||||
dataType : 'json',
|
||||
async : false,
|
||||
data : {
|
||||
cmd : 'webportal',
|
||||
tgt : '',
|
||||
args : 'lszvm',
|
||||
msg : ''
|
||||
},
|
||||
|
||||
success : function(data) {
|
||||
setzVMCookies(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
success : function(data) {
|
||||
setzVMCookies(data);
|
||||
}
|
||||
});
|
||||
|
||||
// Get master copies for clone
|
||||
$.ajax({
|
||||
url : 'lib/srv_cmd.php',
|
||||
dataType : 'json',
|
||||
async : false,
|
||||
data : {
|
||||
cmd : 'webportal',
|
||||
tgt : '',
|
||||
args : 'lsgoldenimages',
|
||||
msg : ''
|
||||
},
|
||||
|
||||
success : function(data) {
|
||||
setGoldenImagesCookies(data);
|
||||
}
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
@ -1077,11 +1093,27 @@ function setUserNodes(data) {
|
||||
// where column names are: node, os, arch, profile, provmethod, supportedarchs, nodetype, comments, disable
|
||||
var cols = data.rsp[i].split(',');
|
||||
var node = cols[0].replace(new RegExp('"', 'g'), '');
|
||||
var owner = cols[7].replace(new RegExp('"', 'g'), '');
|
||||
owner = owner.replace('owner:', '');
|
||||
|
||||
if (owner == userName) {
|
||||
usrNodes.push(node);
|
||||
// Comments can contain the owner and description
|
||||
var comments = new Array();
|
||||
if (cols[7].indexOf(';') > -1) {
|
||||
comments = cols[7].replace(new RegExp('"', 'g'), '').split(';');
|
||||
} else {
|
||||
comments.push(cols[7].replace(new RegExp('"', 'g'), ''));
|
||||
}
|
||||
|
||||
// Extract the owner
|
||||
var owner;
|
||||
for (var j in comments) {
|
||||
if (comments[j].indexOf('owner:') > -1) {
|
||||
owner = comments[j].replace('owner:', '');
|
||||
|
||||
if (owner == userName) {
|
||||
usrNodes.push(node);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // End of for
|
||||
|
||||
|
@ -93,7 +93,7 @@ function submit_request($req, $skipVerify, $opts_array){
|
||||
syslog(LOG_INFO, "Sending request: $cmd $nr");
|
||||
stream_set_blocking($fp, 0); // Set as non-blocking
|
||||
fwrite($fp,$req->asXML()); // Send XML to xcatd
|
||||
set_time_limit(900); // Set 15 minutes timeout (for long running requests)
|
||||
set_time_limit(3600); // Set 15 minutes timeout (for long running requests)
|
||||
// The default is 30 seconds which is too short for some requests
|
||||
|
||||
// Turn on output buffering
|
||||
|
@ -91,7 +91,7 @@ function submit_request($req, $skipVerify, $opts_array){
|
||||
syslog(LOG_INFO, "Sending request: $cmd $nr");
|
||||
stream_set_blocking($fp, 0); // Set as non-blocking
|
||||
fwrite($fp,$req->asXML()); // Send XML to xcatd
|
||||
set_time_limit(900); // Set 15 minutes timeout (for long running requests)
|
||||
set_time_limit(3600); // Set 15 minutes timeout (for long running requests)
|
||||
// The default is 30 seconds which is too short for some requests
|
||||
|
||||
// Turn on output buffering
|
||||
|
@ -70,6 +70,9 @@ sub process_request {
|
||||
'deleteuser' => \&web_deleteuser,
|
||||
'mkzprofile' => \&web_mkzprofile,
|
||||
'rmzprofile' => \&web_rmzprofile,
|
||||
'mkippool' => \&web_mkippool,
|
||||
'rmippool' => \&web_rmippool,
|
||||
'lsippool' => \&web_lsippool,
|
||||
'updateosimage' => \&web_updateosimage,
|
||||
'rmosimage' => \&web_rmosimage,
|
||||
'updategroup' => \&web_updategroup,
|
||||
@ -2369,6 +2372,7 @@ sub web_mkzprofile() {
|
||||
`echo "$var=$size" >> /var/opt/xcat/profiles/$profile.conf`;
|
||||
|
||||
# Move directory entry into /var/opt/xcat/profiles from /var/tmp
|
||||
`mkdir -p /var/opt/xcat/profiles`;
|
||||
`mv /var/tmp/$profile.direct /var/opt/xcat/profiles`;
|
||||
|
||||
my $info = "Profile successfully created/updated";
|
||||
@ -2394,6 +2398,60 @@ sub web_rmzprofile() {
|
||||
$callback->( { info => $info } );
|
||||
}
|
||||
|
||||
sub web_mkippool() {
|
||||
|
||||
# Create group IP pool
|
||||
my ( $request, $callback, $sub_req ) = @_;
|
||||
|
||||
# Get profile
|
||||
my $group = $request->{arg}->[1];
|
||||
|
||||
# Move directory entry into /var/opt/xcat/ippool from /var/tmp
|
||||
`mkdir -p /var/opt/xcat/ippool`;
|
||||
`mv /var/tmp/$group.pool /var/opt/xcat/ippool`;
|
||||
|
||||
my $info = "IP pool successfully created/updated";
|
||||
$callback->( { info => $info } );
|
||||
}
|
||||
|
||||
sub web_rmippool() {
|
||||
|
||||
# Delete group IP pool
|
||||
my ( $request, $callback, $sub_req ) = @_;
|
||||
|
||||
# Get profile
|
||||
my $group = $request->{arg}->[1];
|
||||
my @groups = split( ',', $group );
|
||||
|
||||
# Delete IP pool under /var/opt/xcat/ippool
|
||||
foreach (@groups) {
|
||||
`rm -rf /var/opt/xcat/ippool/$_.pool`;
|
||||
}
|
||||
|
||||
my $info = "IP pool successfully deleted";
|
||||
$callback->( { info => $info } );
|
||||
}
|
||||
|
||||
sub web_lsippool() {
|
||||
|
||||
# List IP pool
|
||||
my ( $request, $callback, $sub_req ) = @_;
|
||||
|
||||
# Get profile
|
||||
my $group = $request->{arg}->[1];
|
||||
|
||||
# IP pool contained in /var/opt/xcat/ippool where a file exists per group
|
||||
my $entries;
|
||||
if ( !(`test -e /var/opt/xcat/ippool/$group.pool && echo Exists`) ) {
|
||||
$entries = "No IP pool found!";
|
||||
} else {
|
||||
# List IP pool under /var/opt/xcat/ippool
|
||||
$entries = `cat /var/opt/xcat/ippool/$group.pool`;
|
||||
}
|
||||
|
||||
$callback->( { info => $entries } );
|
||||
}
|
||||
|
||||
sub web_updateosimage() {
|
||||
|
||||
# Add OS image to xCAT table
|
||||
@ -2464,6 +2522,7 @@ sub web_rmgroup() {
|
||||
# Delete user from xCAT passwd and policy tables
|
||||
foreach (@names) {
|
||||
`chtab -d node=$_ hosts`;
|
||||
`rm -rf /var/opt/xcat/ippool/$_.pool`;
|
||||
}
|
||||
|
||||
my $info = "Group successfully deleted";
|
||||
|
@ -40,7 +40,8 @@ sub process_request {
|
||||
'clonezlinux' => \&clonezlinux,
|
||||
'genhostip' => \&genhostip,
|
||||
'getmaxvm' => \&getmaxvm,
|
||||
'getuserprivilege' => \&getuserprivilege
|
||||
'getuserprivilege' => \&getuserprivilege,
|
||||
'lsgoldenimages' => \&lsgoldenimages
|
||||
);
|
||||
|
||||
# Check if the request is authorized
|
||||
@ -214,12 +215,13 @@ sub provzlinux {
|
||||
|
||||
# Create VM
|
||||
# e.g. webportal provzlinux [group] [hcp] [image]
|
||||
my ($node, $ip, $base_digit) = gennodename( $callback, $group );
|
||||
if (!$base_digit) {
|
||||
println( $callback, "(Error) Failed to generate node name" );
|
||||
# my ($node, $ip, $base_digit) = gennodename( $callback, $group );
|
||||
my ($node, $ip, $hostname) = findfreenode( $callback, $group );
|
||||
if (!$node) {
|
||||
println( $callback, "Unable to find a free node, IP, and hostname for $group from the IP pool" );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
my $userid = $node;
|
||||
|
||||
# Set node definitions
|
||||
@ -231,9 +233,9 @@ sub provzlinux {
|
||||
$out = `mkdef -t node -o $node userid=$userid hcp=$hcp mgt=zvm groups=$group,all`;
|
||||
}
|
||||
println( $callback, "$out" );
|
||||
|
||||
|
||||
# Set nodetype definitions
|
||||
$out = `chtab node=$node noderes.netboot=zvm nodetype.nodetype=osi nodetype.provmethod=install nodetype.os=$os nodetype.arch=$arch nodetype.profile=$profile nodetype.comments="owner:$owner"`;
|
||||
$out = `chtab node=$node hosts.ip=$ip hosts.hostnames=$hostname noderes.netboot=zvm nodetype.nodetype=osi nodetype.provmethod=install nodetype.os=$os nodetype.arch=$arch nodetype.profile=$profile nodetype.comments="owner:$owner"`;
|
||||
|
||||
# Create user directory entry replacing LXUSR with user ID
|
||||
# Use /opt/zhcp/conf/default.direct on zHCP as the template
|
||||
@ -673,7 +675,13 @@ sub clonezlinux {
|
||||
|
||||
# Create VM
|
||||
# e.g. webportal provzlinux [group] [hcp] [image]
|
||||
my ($node, $ip, $base_digit) = gennodename( $callback, $group );
|
||||
# my ($node, $ip, $base_digit) = gennodename( $callback, $group );
|
||||
my ($node, $ip, $hostname) = findfreenode( $callback, $group );
|
||||
if (!$node) {
|
||||
println( $callback, "Unable to find a free node, IP, and hostname for $group from the IP pool" );
|
||||
return;
|
||||
}
|
||||
|
||||
my $userid = $node;
|
||||
|
||||
# Set node definitions
|
||||
@ -681,7 +689,7 @@ sub clonezlinux {
|
||||
println( $callback, "$out" );
|
||||
|
||||
# Set nodetype definitions
|
||||
$out = `chtab node=$node noderes.netboot=zvm nodetype.nodetype=osi nodetype.provmethod=install nodetype.os=$os nodetype.arch=$arch nodetype.profile=$profile nodetype.comments="owner:$owner"`;
|
||||
$out = `chtab node=$node hosts.ip=$ip hosts.hostnames=$hostname noderes.netboot=zvm nodetype.nodetype=osi nodetype.provmethod=install nodetype.os=$os nodetype.arch=$arch nodetype.profile=$profile nodetype.comments="owner:$owner"`;
|
||||
|
||||
# Update hosts table and DNS
|
||||
sleep(5); # Time needed to update /etc/hosts
|
||||
@ -715,8 +723,9 @@ sub genhostip {
|
||||
my ( $request, $callback, $sub_req ) = @_;
|
||||
my $group = $request->{arg}->[1];
|
||||
|
||||
my ($node, $ip, $base_digit) = gennodename( $callback, $group );
|
||||
println( $callback, "$node: $ip" );
|
||||
# my ($node, $ip, $base_digit) = gennodename( $callback, $group );
|
||||
my ($node, $ip, $hostname) = findfreenode( $callback, $group );
|
||||
println( $callback, "$node: $ip, $hostname" );
|
||||
}
|
||||
|
||||
sub getmaxvm {
|
||||
@ -781,4 +790,86 @@ sub getuserprivilege {
|
||||
|
||||
$callback->( { data => "Privilege: $privilege" } );
|
||||
}
|
||||
|
||||
sub lsgoldenimages {
|
||||
my ( $request, $callback, $sub_req ) = @_;
|
||||
|
||||
# Find the golden image that can be cloned by searching nodetype table for nodetype.provmethod=clone
|
||||
my $clones = "";
|
||||
my $comments = "";
|
||||
my $description = "";
|
||||
my @args;
|
||||
|
||||
# Look in 'policy' table
|
||||
my $tab = xCAT::Table->new( 'nodetype', -create => 1, -autocommit => 0 );
|
||||
my @results = $tab->getAllAttribsWhere( "provmethod='clone'", 'node', 'comments' );
|
||||
foreach (@results) {
|
||||
if ($_->{'node'}) {
|
||||
$clones .= $_->{'node'} . ": ";
|
||||
|
||||
$comments = $_->{'comments'};
|
||||
@args = split(';', $comments);
|
||||
foreach (@args) {
|
||||
if ($_ =~ m/description:/i) {
|
||||
$description = $_;
|
||||
$description =~ s/description://g;
|
||||
$description =~ s/\s*$//; # Trim right
|
||||
$description =~ s/^\s*//; # Trim left
|
||||
} else {
|
||||
$description = "No comments";
|
||||
}
|
||||
}
|
||||
|
||||
$clones .= $description . ",";
|
||||
}
|
||||
}
|
||||
|
||||
# Delete last comma
|
||||
$clones = substr($clones, 0, -1);
|
||||
|
||||
$callback->( { data => $clones } );
|
||||
}
|
||||
|
||||
sub findfreenode {
|
||||
# Generate node name based on given group
|
||||
my ( $callback, $group ) = @_;
|
||||
|
||||
# IP pool contained in /var/opt/xcat/ippool where a file exists per group
|
||||
if ( !(`test -e /var/opt/xcat/ippool/$group.pool && echo Exists`) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
# IP pool group format: node, IP, hostname
|
||||
# It would look similar to:
|
||||
# ihost10,10.1.136.10,ihost10.endicott.ibm.com
|
||||
# ihost11,10.1.136.11,ihost11.endicott.ibm.com
|
||||
# ihost12,10.1.136.12,ihost12.endicott.ibm.com
|
||||
my $node;
|
||||
my $ipaddr;
|
||||
my $hostname;
|
||||
|
||||
my $out = `cat /var/opt/xcat/ippool/$group.pool | grep -v "#"`;
|
||||
my @entries = split( /\n/, $out );
|
||||
if (@entries < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
my $found = 0;
|
||||
foreach(@entries) {
|
||||
# Grab the 1st free entry found
|
||||
($node, $ipaddr, $hostname) = split(/,/, $_);
|
||||
if ($node && $ipaddr && $hostname) {
|
||||
|
||||
# Check against xCAT tables, /etc/hosts, and ping to see if hostname is already used
|
||||
if (`nodels $node` || `cat /etc/hosts | grep "$ipaddr "` || !(`ping -c 4 $ipaddr` =~ m/100% packet loss/)) {
|
||||
next;
|
||||
} else {
|
||||
$found = 1;
|
||||
return ($node, $ipaddr, $hostname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
1;
|
@ -3202,6 +3202,35 @@ sub cloneVM {
|
||||
my $sourceId = $propVals->{'userid'};
|
||||
# Capitalize user ID
|
||||
$sourceId =~ tr/a-z/A-Z/;
|
||||
|
||||
# Get operating system, e.g. sles11sp2 or rhel6.2
|
||||
@propNames = ( 'os' );
|
||||
$propVals = xCAT::zvmUtils->getNodeProps( 'nodetype', $sourceNode, @propNames );
|
||||
my $srcOs = $propVals->{'os'};
|
||||
|
||||
# Set IP address
|
||||
my $sourceIp = xCAT::zvmUtils->getIp($sourceNode);
|
||||
|
||||
# Get networks in 'networks' table
|
||||
my $netEntries = xCAT::zvmUtils->getAllTabEntries('networks');
|
||||
my $srcNetwork = "";
|
||||
my $srcMask;
|
||||
foreach (@$netEntries) {
|
||||
# Get source network and mask
|
||||
$srcNetwork = $_->{'net'};
|
||||
$srcMask = $_->{'mask'};
|
||||
|
||||
# If the host IP address is in this subnet, return
|
||||
if (xCAT::NetworkUtils->ishostinsubnet($sourceIp, $srcMask, $srcNetwork)) {
|
||||
|
||||
# Exit loop
|
||||
last;
|
||||
} else {
|
||||
$srcNetwork = "";
|
||||
}
|
||||
}
|
||||
|
||||
xCAT::zvmUtils->printSyslog("cloneVM() srcHcp:$srcHcp sourceId:$sourceId srcOs:$srcOs srcNetwork:$srcNetwork srcMask:$srcMask");
|
||||
|
||||
foreach (@nodes) {
|
||||
xCAT::zvmUtils->printLn( $callback, "$_: Cloning $sourceNode" );
|
||||
@ -3223,6 +3252,18 @@ sub cloneVM {
|
||||
xCAT::zvmUtils->printLn( $callback, "$_: (Error) Missing source user ID" );
|
||||
return;
|
||||
}
|
||||
|
||||
# Exit if missing source operating system
|
||||
if ( !$srcOs ) {
|
||||
xCAT::zvmUtils->printLn( $callback, "$_: (Error) Missing source operating system" );
|
||||
return;
|
||||
}
|
||||
|
||||
# Exit if missing source operating system
|
||||
if ( !$sourceIp || !$srcNetwork || !$srcMask ) {
|
||||
xCAT::zvmUtils->printLn( $callback, "$_: (Error) Missing source IP, network, or mask" );
|
||||
return;
|
||||
}
|
||||
|
||||
# Get target node
|
||||
@propNames = ( 'hcp', 'userid' );
|
||||
@ -3279,6 +3320,8 @@ sub cloneVM {
|
||||
# Generate new MACID
|
||||
$out = xCAT::zvmUtils->generateMacId($::SUDOER, $tgtHcp);
|
||||
}
|
||||
|
||||
xCAT::zvmUtils->printSyslog("cloneVM() tgtHcp:$tgtHcp tgtId:$tgtId targetMac:$targetMac macId:$macId");
|
||||
}
|
||||
|
||||
#*** Link source disks ***
|
||||
@ -3286,11 +3329,8 @@ sub cloneVM {
|
||||
my @words;
|
||||
my $addr;
|
||||
my $type;
|
||||
my $srcMultiPw;
|
||||
my $linkAddr;
|
||||
|
||||
# Load vmcp module
|
||||
xCAT::zvmCPUtils->loadVmcp($::SUDOER, $sourceNode);
|
||||
my $i;
|
||||
|
||||
# Hash table of source disk addresses
|
||||
# $srcLinkAddr[$addr] = $linkAddr
|
||||
@ -3300,15 +3340,21 @@ sub cloneVM {
|
||||
# Hash table of source disk type
|
||||
# $srcLinkAddr[$addr] = $type
|
||||
my %srcDiskType;
|
||||
|
||||
my @srcDisks = xCAT::zvmUtils->getMdisks( $callback, $::SUDOER, $sourceNode );
|
||||
|
||||
# Get details about source disks
|
||||
# Output is similar to:
|
||||
# MDISK=VDEV=0100 DEVTYPE=3390 START=0001 COUNT=10016 VOLID=EMC2C4 MODE=MR
|
||||
$out = `ssh $::SUDOER\@$srcHcp "$::SUDO $::DIR/smcli Image_Definition_Query_DM -T $sourceId -k MDISK"`;
|
||||
xCAT::zvmUtils->printSyslog("cloneVM() smcli Image_Definition_Query_DM -T $sourceId -k MDISK");
|
||||
xCAT::zvmUtils->printSyslog("cloneVM() $out");
|
||||
my $srcDiskDet = xCAT::zvmUtils->trimStr($out);
|
||||
foreach (@srcDisks) {
|
||||
|
||||
# Get disk address
|
||||
@words = split( ' ', $_ );
|
||||
$addr = $words[1];
|
||||
$type = $words[2];
|
||||
$srcMultiPw = $words[9];
|
||||
|
||||
# Add 0 in front if address length is less than 4
|
||||
while (length($addr) < 4) {
|
||||
@ -3320,10 +3366,20 @@ sub cloneVM {
|
||||
|
||||
# Get disk size (cylinders or blocks)
|
||||
# ECKD or FBA disk
|
||||
if ( $type eq '3390' || $type eq '9336' ) {
|
||||
$out = `ssh -o ConnectTimeout=5 $::SUDOER\@$sourceNode "/sbin/vmcp q v dasd" | grep "DASD $addr"`;
|
||||
@words = split( ' ', $out );
|
||||
$srcDiskSize{$addr} = xCAT::zvmUtils->trimStr( $words[5] );
|
||||
if ( $type eq '3390' || $type eq '9336' ) {
|
||||
my @lines = split( '\n', $srcDiskDet );
|
||||
|
||||
# Loop through each line
|
||||
for ( $i = 0 ; $i < @lines ; $i++ ) {
|
||||
$lines[$i] =~ s/MDISK=//g;
|
||||
|
||||
# Extract NIC address
|
||||
@words = ($lines[$i] =~ m/=(\S+)/g);
|
||||
my $srcDiskAddr = $words[0];
|
||||
|
||||
$srcDiskSize{$srcDiskAddr} = $words[3];
|
||||
xCAT::zvmUtils->printSyslog("cloneVM() addr:$addr type:$type srcDiskAddr:$srcDiskAddr srcDiskSize:$words[3]");
|
||||
}
|
||||
}
|
||||
|
||||
# If source disk is not linked
|
||||
@ -3352,7 +3408,7 @@ sub cloneVM {
|
||||
foreach (@nodes) {
|
||||
xCAT::zvmUtils->printLn( $callback, "$_: Linking source disk ($addr) as ($linkAddr)" );
|
||||
}
|
||||
$out = `ssh -o ConnectTimeout=5 $::SUDOER\@$srcHcp "$::SUDO /sbin/vmcp link $sourceId $addr $linkAddr RR $srcMultiPw"`;
|
||||
$out = `ssh -o ConnectTimeout=5 $::SUDOER\@$srcHcp "$::SUDO /sbin/vmcp link $sourceId $addr $linkAddr RR"`;
|
||||
|
||||
if ( $out =~ m/not linked/i ) {
|
||||
# Do nothing
|
||||
@ -3385,13 +3441,19 @@ sub cloneVM {
|
||||
|
||||
# Get the NICDEF address of the network on the source node
|
||||
my @tmp;
|
||||
my $i;
|
||||
my $hcpNicAddr = '';
|
||||
my $srcNicAddr = '';
|
||||
my $hcpNetName = '';
|
||||
|
||||
# Find the NIC address
|
||||
xCAT::zvmCPUtils->loadVmcp($::SUDOER, $sourceNode);
|
||||
$out = `ssh $::SUDOER\@$sourceNode "/sbin/vmcp q v nic"`;
|
||||
$out = `ssh $::SUDOER\@$srcHcp "$::SUDO $::DIR/smcli Image_Definition_Query_DM -T $sourceId -k NICDEF"`;
|
||||
xCAT::zvmUtils->printSyslog("cloneVM() smcli Image_Definition_Query_DM -T $sourceId -k NICDEF");
|
||||
xCAT::zvmUtils->printSyslog("cloneVM() $out");
|
||||
# Output is similar to:
|
||||
# NICDEF_PROFILE=VDEV=0800 TYPE=QDIO LAN=SYSTEM SWITCHNAME=VSW2
|
||||
# NICDEF=VDEV=0900 TYPE=QDIO DEVICES=3 LAN=SYSTEM SWITCHNAME=GLAN1
|
||||
# NICDEF=VDEV=0A00 TYPE=QDIO DEVICES=3 LAN=SYSTEM SWITCHNAME=VSW2
|
||||
|
||||
my @lines = split( '\n', $out );
|
||||
|
||||
# Loop through each line
|
||||
@ -3400,48 +3462,48 @@ sub cloneVM {
|
||||
# Loop through each network name
|
||||
foreach (@hcpNets) {
|
||||
# If the network is found
|
||||
if ( $lines[$i] =~ m/ $_/i ) {
|
||||
if ( $lines[$i] =~ m/SWITCHNAME=$_/i ) {
|
||||
# Save network name
|
||||
$hcpNetName = $_;
|
||||
|
||||
# Get NIC address
|
||||
$line = xCAT::zvmUtils->trimStr( $lines[ $i - 1 ] );
|
||||
@words = split( ' ', $line );
|
||||
@tmp = split( /\./, $words[1] );
|
||||
$hcpNicAddr = $tmp[0];
|
||||
$lines[$i] =~ s/NICDEF_PROFILE=//g;
|
||||
$lines[$i] =~ s/NICDEF=//g;
|
||||
|
||||
# Extract NIC address
|
||||
@words = ($lines[$i] =~ m/=(\S+)/g);
|
||||
$srcNicAddr = $words[0];
|
||||
xCAT::zvmUtils->printSyslog("cloneVM() hcpNetName:$hcpNetName srcNicAddr:$srcNicAddr");
|
||||
|
||||
# Grab only the 1st match
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# If no network name is found, exit
|
||||
if (!$hcpNetName || !$hcpNicAddr) {
|
||||
if (!$hcpNetName || !$srcNicAddr) {
|
||||
#*** Detatch source disks ***
|
||||
for $addr ( keys %srcLinkAddr ) {
|
||||
$linkAddr = $srcLinkAddr{$addr};
|
||||
|
||||
# Disable and detatch source disk
|
||||
$out = xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $srcHcp, "-d", $linkAddr );
|
||||
$out = `ssh -o ConnectTimeout=5 $::SUDOER\@$srcHcp "$::SUDO /sbin/vmcp det $linkAddr"`;
|
||||
$out = `ssh -o ConnectTimeout=5 $::SUDOER\@$srcHcp "$::SUDO /sbin/vmcp det $linkAddr"`;
|
||||
foreach (@nodes) {
|
||||
xCAT::zvmUtils->printLn( $callback, "$_: Detatching source disk ($addr) at ($linkAddr)" );
|
||||
}
|
||||
}
|
||||
|
||||
foreach (@nodes) {
|
||||
xCAT::zvmUtils->printLn( $callback, "$_: (Error) No suitable network device found in user directory entry" );
|
||||
xCAT::zvmUtils->printLn( $callback, "$_: (Solution) Verify that the node has one of the following network devices: @hcpNets" );
|
||||
xCAT::zvmUtils->printLn( $callback, "$_: Detatching source disk ($addr) at ($linkAddr)" );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
# Get VSwitch of source node (if any)
|
||||
my @srcVswitch = xCAT::zvmCPUtils->getVswitchId($::SUDOER, $sourceNode);
|
||||
|
||||
# Get device address that is the root partition (/)
|
||||
my $srcRootPartAddr = xCAT::zvmUtils->getRootDeviceAddr($::SUDOER, $sourceNode);
|
||||
|
||||
# Get source node OS
|
||||
my $srcOs = xCAT::zvmUtils->getOs($::SUDOER, $sourceNode);
|
||||
# Get vSwitch of source node (if any)
|
||||
my @srcVswitch = xCAT::zvmCPUtils->getVswitchId($::SUDOER, $srcHcp);
|
||||
|
||||
# Get source MAC address in 'mac' table
|
||||
my $srcMac;
|
||||
@ -3452,35 +3514,7 @@ sub cloneVM {
|
||||
# Get MAC address
|
||||
$srcMac = $propVals->{'mac'};
|
||||
}
|
||||
|
||||
# Get network configuration file
|
||||
# Location of this file depends on the OS
|
||||
my $srcIfcfg = xCAT::zvmUtils->getIfcfgByNic( $::SUDOER, $sourceNode, "0.0." . $hcpNicAddr );
|
||||
if (!$srcIfcfg) {
|
||||
|
||||
#*** Detatch source disks ***
|
||||
for $addr ( keys %srcLinkAddr ) {
|
||||
$linkAddr = $srcLinkAddr{$addr};
|
||||
|
||||
# Disable and detatch source disk
|
||||
$out = xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $srcHcp, "-d", $linkAddr );
|
||||
$out = `ssh -o ConnectTimeout=5 $::SUDOER\@$srcHcp "$::SUDO /sbin/vmcp det $linkAddr"`;
|
||||
}
|
||||
|
||||
foreach (@nodes) {
|
||||
xCAT::zvmUtils->printLn( $callback, "$_: (Error) No suitable network configuration file found in Linux directory" );
|
||||
xCAT::zvmUtils->printLn( $callback, "$_: Detatching source disk ($addr) at ($linkAddr)" );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
# Get source hardware configuration (SUSE only)
|
||||
my $srcHwcfg = '';
|
||||
if ( $srcOs =~ m/SUSE/i ) {
|
||||
$srcHwcfg = xCAT::zvmUtils->getHwcfg($::SUDOER, $sourceNode);
|
||||
}
|
||||
|
||||
# Get user entry of source node
|
||||
my $srcUserEntry = "/tmp/$sourceNode.txt";
|
||||
$out = `rm $srcUserEntry`;
|
||||
@ -3493,13 +3527,18 @@ sub cloneVM {
|
||||
if ( $out =~ m/USER $sourceId/i ) {
|
||||
|
||||
# Turn off source node
|
||||
$out = `ssh -o ConnectTimeout=10 $sourceNode "shutdown -h now"`;
|
||||
sleep(90); # Wait 1.5 minutes before logging user off
|
||||
if (`pping $sourceNode` =~ m/ ping/i) {
|
||||
$out = `ssh -o ConnectTimeout=10 $sourceNode "shutdown -h now"`;
|
||||
sleep(90); # Wait 1.5 minutes before logging user off
|
||||
|
||||
foreach (@nodes) {
|
||||
xCAT::zvmUtils->printLn( $callback, "$_: Shutting down $sourceNode" );
|
||||
}
|
||||
}
|
||||
|
||||
$out = `ssh $::SUDOER\@$srcHcp "$::SUDO $::DIR/smcli Image_Deactivate -T $sourceId -f IMMED"`;
|
||||
foreach (@nodes) {
|
||||
xCAT::zvmUtils->printLn( $callback, "$_: $out" );
|
||||
}
|
||||
xCAT::zvmUtils->printSyslog("cloneVM() smcli Image_Deactivate -T $sourceId -f IMMED");
|
||||
xCAT::zvmUtils->printSyslog("cloneVM() $out");
|
||||
|
||||
#*** Clone source node ***
|
||||
# Remove flashcopy lock (if any)
|
||||
@ -3516,8 +3555,7 @@ sub cloneVM {
|
||||
elsif ( $pid == 0 ) {
|
||||
clone(
|
||||
$callback, $_, $args, \@srcDisks, \%srcLinkAddr, \%srcDiskSize, \%srcDiskType,
|
||||
$hcpNicAddr, $hcpNetName, \@srcVswitch, $srcOs, $srcMac, $srcRootPartAddr, $srcIfcfg,
|
||||
$srcHwcfg
|
||||
$srcNicAddr, $hcpNetName, \@srcVswitch, $srcOs, $srcMac, $netEntries, $sourceIp, $srcNetwork, $srcMask
|
||||
);
|
||||
|
||||
# Exit process
|
||||
@ -3568,12 +3606,6 @@ sub cloneVM {
|
||||
}
|
||||
}
|
||||
|
||||
# Turn back on source node
|
||||
$out = `ssh $::SUDOER\@$srcHcp "$::SUDO $::DIR/smcli Image_Activate -T $sourceId"`;
|
||||
foreach (@nodes) {
|
||||
xCAT::zvmUtils->printLn( $callback, "$_: $out" );
|
||||
}
|
||||
|
||||
#*** Done ***
|
||||
foreach (@nodes) {
|
||||
xCAT::zvmUtils->printLn( $callback, "$_: Done" );
|
||||
@ -3603,8 +3635,8 @@ sub cloneVM {
|
||||
Path to hardware configuration file (SUSE only)
|
||||
Returns : Nothing
|
||||
Example : clone($callback, $_, $args, \@srcDisks, \%srcLinkAddr, \%srcDiskSize,
|
||||
$hcpNicAddr, $hcpNetName, \@srcVswitch, $srcOs, $srcMac,
|
||||
$srcRootPartAddr, $srcIfcfg, $srcHwcfg);
|
||||
$srcNicAddr, $hcpNetName, \@srcVswitch, $srcOs, $srcMac, $netEntries,
|
||||
$sourceIp, $srcNetwork, $srcMask);
|
||||
|
||||
=cut
|
||||
|
||||
@ -3614,7 +3646,7 @@ sub clone {
|
||||
# Get inputs
|
||||
my (
|
||||
$callback, $tgtNode, $args, $srcDisksRef, $srcLinkAddrRef, $srcDiskSizeRef, $srcDiskTypeRef,
|
||||
$hcpNicAddr, $hcpNetName, $srcVswitchRef, $srcOs, $srcMac, $srcRootPartAddr, $srcIfcfg, $srcHwcfg
|
||||
$srcNicAddr, $hcpNetName, $srcVswitchRef, $srcOs, $srcMac, $netEntries, $sourceIp, $srcNetwork, $srcMask
|
||||
)
|
||||
= @_;
|
||||
|
||||
@ -3667,7 +3699,7 @@ sub clone {
|
||||
xCAT::zvmUtils->printLn( $callback, "$tgtNode: (Solution) Set the source and target HCP appropriately in the zvm table" );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
# Get target IP from /etc/hosts
|
||||
`makehosts`;
|
||||
sleep(5);
|
||||
@ -3677,6 +3709,7 @@ sub clone {
|
||||
xCAT::zvmUtils->printLn( $callback, "$tgtNode: (Solution) Verify that the node's IP address is specified in the hosts table and then run makehosts" );
|
||||
return;
|
||||
}
|
||||
xCAT::zvmUtils->printSyslog("clone() hcp:$hcp tgtUserId:$tgtUserId targetIp:$targetIp");
|
||||
|
||||
my $out;
|
||||
my @lines;
|
||||
@ -3702,6 +3735,7 @@ sub clone {
|
||||
xCAT::zvmUtils->printLn( $callback, "$tgtNode: (Error) Missing disk pool. Please specify one." );
|
||||
return;
|
||||
}
|
||||
xCAT::zvmUtils->printSyslog("clone() pool:$pool");
|
||||
|
||||
# Get multi password
|
||||
# It is Ok not have a password
|
||||
@ -3710,9 +3744,6 @@ sub clone {
|
||||
$tgtPw = $inputs{"pw"};
|
||||
}
|
||||
|
||||
# Set IP address
|
||||
my $sourceIp = xCAT::zvmUtils->getIp($sourceNode);
|
||||
|
||||
# Save user directory entry as /tmp/hostname.txt, e.g. /tmp/gpok3.txt
|
||||
# The source user entry is retrieved in cloneVM()
|
||||
my $userEntry = "/tmp/$tgtNode.txt";
|
||||
@ -3795,6 +3826,8 @@ sub clone {
|
||||
xCAT::zvmUtils->printLn( $callback, "$tgtNode: Trying again ($try) to create user directory entry" );
|
||||
}
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Create_DM -T $tgtUserId -f $userEntry"`;
|
||||
xCAT::zvmUtils->printSyslog("clone() smcli Image_Create_DM -T $tgtUserId -f $userEntry");
|
||||
xCAT::zvmUtils->printSyslog("clone() $out");
|
||||
|
||||
# Check if user entry is created
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Query_DM -T $tgtUserId" | sed '\$d'`;
|
||||
@ -3847,7 +3880,6 @@ sub clone {
|
||||
my $type;
|
||||
my $mode;
|
||||
my $cyl;
|
||||
my $srcMultiPw;
|
||||
foreach (@srcDisks) {
|
||||
|
||||
# Get disk address
|
||||
@ -3856,7 +3888,6 @@ sub clone {
|
||||
push( @tgtDisks, $addr );
|
||||
$type = $words[2];
|
||||
$mode = $words[6];
|
||||
$srcMultiPw = $words[9];
|
||||
|
||||
# Add 0 in front if address length is less than 4
|
||||
while (length($addr) < 4) {
|
||||
@ -3879,7 +3910,9 @@ sub clone {
|
||||
xCAT::zvmUtils->printLn( $callback, "$tgtNode: Trying again ($try) to add minidisk ($addr)" );
|
||||
}
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Disk_Create_DM -T $tgtUserId -v $addr -t 3390 -a AUTOG -r $pool -u 1 -z $cyl -m $mode -f 1 -R $tgtPw -W $tgtPw -M $tgtPw"`;
|
||||
|
||||
xCAT::zvmUtils->printSyslog("clone() smcli Image_Disk_Create_DM -T $tgtUserId -v $addr -t 3390 -a AUTOG -r $pool -u 1 -z $cyl -m $mode -f 1 -R $tgtPw -W $tgtPw -M $tgtPw");
|
||||
xCAT::zvmUtils->printSyslog("clone() $out");
|
||||
|
||||
# Check output
|
||||
$rc = xCAT::zvmUtils->checkOutput( $callback, $out );
|
||||
if ( $rc == -1 ) {
|
||||
@ -3920,7 +3953,9 @@ sub clone {
|
||||
xCAT::zvmUtils->printLn( $callback, "$tgtNode: Trying again ($try) to add minidisk ($addr)" );
|
||||
}
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Disk_Create_DM -T $tgtUserId -v $addr -t 9336 -a AUTOG -r $pool -u 1 -z $blks -m $mode -f 1 -R $tgtPw -W $tgtPw -M $tgtPw"`;
|
||||
|
||||
xCAT::zvmUtils->printSyslog("clone() smcli Image_Disk_Create_DM -T $tgtUserId -v $addr -t 9336 -a AUTOG -r $pool -u 1 -z $blks -m $mode -f 1 -R $tgtPw -W $tgtPw -M $tgtPw");
|
||||
xCAT::zvmUtils->printSyslog("clone() $out");
|
||||
|
||||
# Check output
|
||||
$rc = xCAT::zvmUtils->checkOutput( $callback, $out );
|
||||
if ( $rc == -1 ) {
|
||||
@ -3953,6 +3988,8 @@ sub clone {
|
||||
|
||||
# Get disks within user entry
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Query_DM -T $tgtUserId" | sed '\$d' | grep "MDISK"`;
|
||||
xCAT::zvmUtils->printSyslog("clone() smcli Image_Query_DM -T $tgtUserId | grep MDISK");
|
||||
xCAT::zvmUtils->printSyslog("clone() $out");
|
||||
@disks = split( '\n', $out );
|
||||
xCAT::zvmUtils->printLn( $callback, "$tgtNode: Disks added (" . @tgtDisks . "). Disks in user entry (" . @disks . ")" );
|
||||
|
||||
@ -4046,6 +4083,7 @@ sub clone {
|
||||
xCAT::zvmUtils->printLn( $callback, "$tgtNode: Copying source disk ($srcAddr) to target disk ($tgtAddr) using FLASHCOPY" );
|
||||
if (xCAT::zvmUtils->smapi4xcat($::SUDOER, $hcp)) {
|
||||
$out = xCAT::zvmCPUtils->smapiFlashCopy($::SUDOER, $hcp, $sourceId, $srcAddr, $tgtUserId, $tgtAddr);
|
||||
xCAT::zvmUtils->printSyslog("clone() smapiFlashCopy:$out");
|
||||
|
||||
# Exit if flashcopy completed successfully
|
||||
# Otherwsie, try CP FLASHCOPY
|
||||
@ -4081,6 +4119,7 @@ sub clone {
|
||||
|
||||
# Flashcopy source disk
|
||||
$out = xCAT::zvmCPUtils->flashCopy( $::SUDOER, $hcp, $srcAddr, $tgtAddr );
|
||||
xCAT::zvmUtils->printSyslog("clone() flashCopy:$out");
|
||||
$rc = xCAT::zvmUtils->checkOutput( $callback, $out );
|
||||
if ( $rc == -1 ) {
|
||||
xCAT::zvmUtils->printLn( $callback, "$tgtNode: $out" );
|
||||
@ -4120,6 +4159,7 @@ sub clone {
|
||||
if ($tgtDiskType eq '3390') {
|
||||
xCAT::zvmUtils->printLn( $callback, "$tgtNode: Formating target disk ($tgtAddr)" );
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/dasdfmt -b 4096 -y -f /dev/$tgtDevNode"`;
|
||||
xCAT::zvmUtils->printSyslog("clone() dasdfmt -b 4096 -y -f /dev/$tgtDevNode");
|
||||
|
||||
# Check for errors
|
||||
$rc = xCAT::zvmUtils->checkOutput( $callback, $out );
|
||||
@ -4134,19 +4174,19 @@ sub clone {
|
||||
|
||||
# Sleep 2 seconds to let the system settle
|
||||
sleep(2);
|
||||
|
||||
# Automatically create a partition using the entire disk
|
||||
xCAT::zvmUtils->printLn( $callback, "$tgtNode: Creating a partition using the entire disk ($tgtDevNode)" );
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/fdasd -a /dev/$tgtDevNode"`;
|
||||
|
||||
|
||||
# Copy source disk to target disk
|
||||
xCAT::zvmUtils->printLn( $callback, "$tgtNode: Copying source disk ($srcAddr) to target disk ($tgtAddr)" );
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO /bin/dd if=/dev/$srcDevNode of=/dev/$tgtDevNode bs=4096 oflag=sync"`;
|
||||
xCAT::zvmUtils->printSyslog("clone() dd if=/dev/$srcDevNode of=/dev/$tgtDevNode bs=4096 oflag=sync");
|
||||
xCAT::zvmUtils->printSyslog("clone() $out");
|
||||
} else {
|
||||
# Copy source disk to target disk
|
||||
# Block size = 512
|
||||
xCAT::zvmUtils->printLn( $callback, "$tgtNode: Copying source disk ($srcAddr) to target disk ($tgtAddr)" );
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO /bin/dd if=/dev/$srcDevNode of=/dev/$tgtDevNode bs=512 oflag=sync"`;
|
||||
xCAT::zvmUtils->printSyslog("clone() dd if=/dev/$srcDevNode of=/dev/$tgtDevNode bs=512 oflag=sync");
|
||||
xCAT::zvmUtils->printSyslog("clone() $out");
|
||||
|
||||
# Force Linux to re-read partition table
|
||||
xCAT::zvmUtils->printLn( $callback, "$tgtNode: Forcing Linux to re-read partition table" );
|
||||
@ -4174,6 +4214,14 @@ EOM"`;
|
||||
# Sleep 2 seconds to let the system settle
|
||||
sleep(2);
|
||||
}
|
||||
|
||||
# Re-scan partition table
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO /usr/sbin/partprobe /dev/$tgtDevNode"`; # SLES
|
||||
xCAT::zvmUtils->printSyslog("clone() /usr/sbin/partprobe /dev/$tgtDevNode");
|
||||
xCAT::zvmUtils->printSyslog("clone() $out");
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/partprobe /dev/$tgtDevNode"`; # RHEL
|
||||
xCAT::zvmUtils->printSyslog("clone() /sbin/partprobe /dev/$tgtDevNode");
|
||||
xCAT::zvmUtils->printSyslog("clone() $out");
|
||||
|
||||
# Disable and enable target disk
|
||||
$out = xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $hcp, "-d", $tgtAddr );
|
||||
@ -4182,87 +4230,142 @@ EOM"`;
|
||||
# Determine target device node (it might have changed)
|
||||
$tgtDevNode = xCAT::zvmUtils->getDeviceNode($::SUDOER, $hcp, $tgtAddr);
|
||||
|
||||
# Get disk address that is the root partition (/)
|
||||
if ( $_ eq $srcRootPartAddr ) {
|
||||
|
||||
# Mount target disk
|
||||
my $cloneMntPt = "/mnt/$tgtUserId";
|
||||
# Mount device and check if it is the root partition
|
||||
# If it is, then modify the network configuration
|
||||
|
||||
# Mount target disk
|
||||
my $cloneMntPt = "/mnt/$tgtUserId";
|
||||
|
||||
# Disk can contain more than 1 partition. Find the right one (not swap)
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO /usr/bin/file -s /dev/$tgtDevNode*" | grep -v swap | grep -o "$tgtDevNode\[0-9\]"`;
|
||||
my @tgtDevNodes = split( "\n", $out );
|
||||
my $iTgtDevNode = 0;
|
||||
$tgtDevNode = xCAT::zvmUtils->trimStr($tgtDevNodes[$iTgtDevNode]);
|
||||
# Disk can contain more than 1 partition. Find the right one (not swap)
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO /usr/bin/file -s /dev/$tgtDevNode*"`;
|
||||
xCAT::zvmUtils->printSyslog("clone() file -s /dev/$tgtDevNode*");
|
||||
xCAT::zvmUtils->printSyslog("clone() $out");
|
||||
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO /usr/bin/file -s /dev/$tgtDevNode*" | grep -v swap | grep -o "$tgtDevNode\[0-9\]"`;
|
||||
xCAT::zvmUtils->printSyslog("clone() file -s /dev/$tgtDevNode* | grep -v swap | grep -o $tgtDevNode\[0-9\]");
|
||||
xCAT::zvmUtils->printSyslog("clone() $out");
|
||||
|
||||
my @tgtDevNodes = split( "\n", $out );
|
||||
my $iTgtDevNode = 0;
|
||||
$tgtDevNode = xCAT::zvmUtils->trimStr($tgtDevNodes[$iTgtDevNode]);
|
||||
|
||||
xCAT::zvmUtils->printLn( $callback, "$tgtNode: Mounting /dev/$tgtDevNode to $cloneMntPt" );
|
||||
xCAT::zvmUtils->printLn( $callback, "$tgtNode: Mounting /dev/$tgtDevNode to $cloneMntPt" );
|
||||
|
||||
# Check the disk is mounted
|
||||
$try = 5;
|
||||
while ( !(`ssh $::SUDOER\@$hcp "$::SUDO ls $cloneMntPt/etc/"`) && $try > 0 ) {
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO mkdir -p $cloneMntPt"`;
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO mount /dev/$tgtDevNode $cloneMntPt"`;
|
||||
# Check the disk is mounted
|
||||
$try = 5;
|
||||
while ( !(`ssh $::SUDOER\@$hcp "$::SUDO ls $cloneMntPt"`) && $try > 0 ) {
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO mkdir -p $cloneMntPt"`;
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO mount /dev/$tgtDevNode $cloneMntPt"`;
|
||||
xCAT::zvmUtils->printSyslog("clone() mount /dev/$tgtDevNode $cloneMntPt");
|
||||
|
||||
# If more than 1 partition, try other partitions
|
||||
if (@tgtDevNodes > 1 && $iTgtDevNode < @tgtDevNodes) {
|
||||
$iTgtDevNode++;
|
||||
$tgtDevNode = xCAT::zvmUtils->trimStr($tgtDevNodes[$iTgtDevNode]);
|
||||
}
|
||||
# If more than 1 partition, try other partitions
|
||||
if (@tgtDevNodes > 1 && $iTgtDevNode < @tgtDevNodes) {
|
||||
$iTgtDevNode++;
|
||||
$tgtDevNode = xCAT::zvmUtils->trimStr($tgtDevNodes[$iTgtDevNode]);
|
||||
}
|
||||
|
||||
# Wait before trying again
|
||||
sleep(10);
|
||||
$try = $try - 1;
|
||||
}
|
||||
|
||||
# If the disk is not mounted
|
||||
if ( !(`ssh $::SUDOER\@$hcp "$::SUDO ls $cloneMntPt/etc/"`) ) {
|
||||
xCAT::zvmUtils->printLn( $callback, "$tgtNode: (Error) Could not mount /dev/$tgtDevNode" );
|
||||
|
||||
# Flush disk
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO sync"`;
|
||||
|
||||
# Unmount disk
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO umount $cloneMntPt"`;
|
||||
|
||||
# Remove mount point
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO rm -rf $cloneMntPt"`;
|
||||
|
||||
# Disable disks
|
||||
$out = xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $hcp, "-d", $tgtAddr );
|
||||
|
||||
# Detatch disks from HCP
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/vmcp det $tgtAddr"`;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
# Wait before trying again
|
||||
sleep(10);
|
||||
$try = $try - 1;
|
||||
}
|
||||
|
||||
if (!(`ssh $::SUDOER\@$hcp "$::SUDO ls $cloneMntPt"`)) {
|
||||
xCAT::zvmUtils->printLn( $callback, "$tgtNode: Failed to mount /dev/$tgtDevNode. Skipping device." );
|
||||
}
|
||||
|
||||
# Is this the partition containing /etc?
|
||||
if (`ssh $::SUDOER\@$hcp "$::SUDO test -d $cloneMntPt/etc && echo Exists"`) {
|
||||
#*** Set network configuration ***
|
||||
# Set hostname
|
||||
xCAT::zvmUtils->printLn( $callback, "$tgtNode: Setting network configuration" );
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO sed --in-place -e "s/$sourceNode/$tgtNode/i" $cloneMntPt/etc/HOSTNAME"`;
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO sed --in-place -e \"s/$sourceNode/$tgtNode/i\" $cloneMntPt/etc/HOSTNAME"`;
|
||||
xCAT::zvmUtils->printSyslog("clone() sed --in-place -e s/$sourceNode/$tgtNode/i $cloneMntPt/etc/HOSTNAME");
|
||||
|
||||
# If Red Hat - Set hostname in /etc/sysconfig/network
|
||||
if ( $srcOs =~ m/Red Hat/i ) {
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO sed --in-place -e "s/$sourceNode/$tgtNode/i" $cloneMntPt/etc/sysconfig/network"`;
|
||||
if ( $srcOs =~ m/rhel/i ) {
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO sed --in-place -e \"s/$sourceNode/$tgtNode/i\" $cloneMntPt/etc/sysconfig/network"`;
|
||||
xCAT::zvmUtils->printSyslog("clone() sed --in-place -e s/$sourceNode/$tgtNode/i $cloneMntPt/etc/sysconfig/network");
|
||||
}
|
||||
|
||||
# Get network configuration file
|
||||
# Location of this file depends on the OS
|
||||
my $ifcfgPath = $cloneMntPt;
|
||||
$ifcfgPath .= $srcIfcfg;
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO sed --in-place -e "s/$sourceNode/$tgtNode/i" \ -e "s/$sourceIp/$targetIp/i" $cloneMntPt/etc/hosts"`;
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO sed --in-place -e "s/$sourceIp/$targetIp/i" \ -e "s/$sourceNode/$tgtNode/i" $ifcfgPath"`;
|
||||
|
||||
# Get network layer
|
||||
my $layer = xCAT::zvmCPUtils->getNetworkLayer( $::SUDOER, $hcp, $hcpNetName );
|
||||
xCAT::zvmUtils->printSyslog("clone() hcp:$hcp hcpNetName:$hcpNetName layer:$layer");
|
||||
|
||||
# Get network configuration file
|
||||
# Location of this file depends on the OS
|
||||
my $srcIfcfg = '';
|
||||
|
||||
# If it is Red Hat - ifcfg-qeth file is in /etc/sysconfig/network-scripts
|
||||
my @files;
|
||||
if ( $srcOs =~ m/rhel/i ) {
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO grep -H -r $srcNicAddr $cloneMntPt/etc/sysconfig/network-scripts"`;
|
||||
xCAT::zvmUtils->printSyslog("clone() grep -H -r $srcNicAddr $cloneMntPt/etc/sysconfig/network-scripts");
|
||||
xCAT::zvmUtils->printSyslog("clone() $out");
|
||||
@files = split('\n', $out);
|
||||
@words = split( ':', $files[0] );
|
||||
$srcIfcfg = $words[0];
|
||||
}
|
||||
|
||||
# If it is SLES 10 - ifcfg-qeth file is in /etc/sysconfig/network
|
||||
elsif ( $srcOs =~ m/sles10/i ) {
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO grep -H -r $srcNicAddr $cloneMntPt/etc/sysconfig/network/ifcfg-qeth*"`;
|
||||
xCAT::zvmUtils->printSyslog("clone() grep -H -r $srcNicAddr $cloneMntPt/etc/sysconfig/network/ifcfg-qeth*");
|
||||
xCAT::zvmUtils->printSyslog("clone() $out");
|
||||
@files = split('\n', $out);
|
||||
@words = split( ':', $files[0] );
|
||||
$srcIfcfg = $words[0];
|
||||
}
|
||||
|
||||
# If it is SLES 11 - ifcfg-qeth file is in /etc/sysconfig/network
|
||||
elsif ( $srcOs =~ m/sles11/i ) {
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO grep -H -r $srcNicAddr $cloneMntPt/etc/sysconfig/network/ifcfg-eth*"`;
|
||||
xCAT::zvmUtils->printSyslog("clone() grep -H -r $srcNicAddr $cloneMntPt/etc/sysconfig/network/ifcfg-eth*");
|
||||
xCAT::zvmUtils->printSyslog("clone() $out");
|
||||
@files = split('\n', $out);
|
||||
@words = split( ':', $files[0] );
|
||||
$srcIfcfg = $words[0];
|
||||
}
|
||||
|
||||
my $ifcfgPath = $srcIfcfg;
|
||||
|
||||
# Change IP, network, and mask
|
||||
# Go through each network
|
||||
my $tgtNetwork = "";
|
||||
my $tgtMask;
|
||||
foreach (@$netEntries) {
|
||||
|
||||
# Get network and mask
|
||||
$tgtNetwork = $_->{'net'};
|
||||
$tgtMask = $_->{'mask'};
|
||||
|
||||
# If the host IP address is in this subnet, return
|
||||
if (xCAT::NetworkUtils->ishostinsubnet($targetIp, $tgtMask, $tgtNetwork)) {
|
||||
|
||||
# Exit loop
|
||||
last;
|
||||
} else {
|
||||
$tgtNetwork = "";
|
||||
}
|
||||
}
|
||||
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO sed --in-place -e \"s/$sourceNode/$tgtNode/i\" \ -e \"s/$sourceIp/$targetIp/i\" $cloneMntPt/etc/hosts"`;
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO sed --in-place -e \"s/$sourceIp/$targetIp/i\" \ -e \"s/$sourceNode/$tgtNode/i\" $ifcfgPath"`;
|
||||
xCAT::zvmUtils->printSyslog("clone() sed --in-place -e s/$sourceNode/$tgtNode/i \ -e s/$sourceIp/$targetIp/i $cloneMntPt/etc/hosts");
|
||||
xCAT::zvmUtils->printSyslog("clone() sed --in-place -e s/$sourceIp/$targetIp/i \ -e s/$sourceNode/$tgtNode/i $ifcfgPath");
|
||||
|
||||
if ($tgtNetwork && $tgtMask) {
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO sed --in-place -e \"s/$srcNetwork/$tgtNetwork/i\" \ -e \"s/$srcMask/$tgtMask/i\" $ifcfgPath"`;
|
||||
xCAT::zvmUtils->printSyslog("clone() sed --in-place -e s/$srcNetwork/$tgtNetwork/i \ -e s/$srcMask/$tgtMask/i $ifcfgPath");
|
||||
}
|
||||
|
||||
# Set MAC address
|
||||
my $networkFile = $tgtNode . "NetworkConfig";
|
||||
my $config;
|
||||
if ( $srcOs =~ m/Red Hat/i ) {
|
||||
if ( $srcOs =~ m/rhel/i ) {
|
||||
|
||||
# Red Hat only
|
||||
$config = `ssh $::SUDOER\@$hcp "$::SUDO cat $ifcfgPath" | grep -v "MACADDR"`;
|
||||
$config .= "MACADDR='$targetMac'\n";
|
||||
$config .= "MACADDR='" . $targetMac . "'\n";
|
||||
} else {
|
||||
|
||||
# SUSE only
|
||||
@ -4270,15 +4373,16 @@ EOM"`;
|
||||
|
||||
# Set to MAC address (only for layer 2)
|
||||
if ( $layer == 2 ) {
|
||||
$config .= "LLADDR='$targetMac'\n";
|
||||
$config .= "LLADDR='" . $targetMac . "'\n";
|
||||
$config .= "UNIQUE=''\n";
|
||||
}
|
||||
}
|
||||
xCAT::zvmUtils->printSyslog("clone() $config");
|
||||
|
||||
# Write network configuration
|
||||
# You cannot SCP file over to mount point as sudo, so you have to copy file to zHCP
|
||||
# and move it to mount point
|
||||
$out = `echo -e \"$config\" > /tmp/$networkFile`;
|
||||
$out = `echo -e "$config" > /tmp/$networkFile`;
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO rm -rf $ifcfgPath"`;
|
||||
$out = `cat /tmp/$networkFile | ssh $::SUDOER\@$hcp "$::SUDO cat > /tmp/$networkFile"`;
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO mv /tmp/$networkFile $ifcfgPath"`;
|
||||
@ -4286,46 +4390,19 @@ EOM"`;
|
||||
|
||||
# Set to hardware configuration (only for layer 2)
|
||||
if ( $layer == 2 ) {
|
||||
|
||||
#*** Red Hat ***
|
||||
if ( $srcOs =~ m/Red Hat/i ) {
|
||||
my $srcMac;
|
||||
|
||||
# Get source MAC address in 'mac' table
|
||||
@propNames = ('mac');
|
||||
$propVals = xCAT::zvmUtils->getNodeProps( 'mac', $sourceNode, @propNames );
|
||||
if ($propVals) {
|
||||
|
||||
# Get MAC address
|
||||
$srcMac = $propVals->{'mac'};
|
||||
}
|
||||
else {
|
||||
xCAT::zvmUtils->printLn( $callback, "$tgtNode: (Error) Could not find MAC address of $sourceNode" );
|
||||
|
||||
# Unmount disk
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO umount $cloneMntPt"`;
|
||||
|
||||
# Disable disks
|
||||
$out = xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $hcp, "-d", $tgtAddr );
|
||||
|
||||
# Detatch disks from HCP
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/vmcp det $tgtAddr"`;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $srcOs =~ m/rhel/i && $srcMac ) {
|
||||
#*** Red Hat Linux ***
|
||||
|
||||
# Set MAC address
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO sed --in-place -e "s/$srcMac/$targetMac/i" $ifcfgPath"`;
|
||||
}
|
||||
|
||||
#*** SUSE ***
|
||||
else {
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO sed --in-place -e \"s/$srcMac/$targetMac/i\" $ifcfgPath"`;
|
||||
xCAT::zvmUtils->printSyslog("clone() sed --in-place -e s/$srcMac/$targetMac/i $ifcfgPath");
|
||||
} else {
|
||||
#*** SuSE Linux ***
|
||||
|
||||
# Get hardware configuration
|
||||
my $hwcfgPath = $cloneMntPt;
|
||||
|
||||
# Set layer 2 support
|
||||
$hwcfgPath .= $srcHwcfg;
|
||||
# hwcfg-qeth file is in /etc/sysconfig/hardware
|
||||
my $hwcfgPath = $cloneMntPt . "/etc/sysconfig/hardware/hwcfg-qeth-bus-ccw-0.0.$srcNicAddr";
|
||||
xCAT::zvmUtils->printSyslog("clone() hwcfgPath=$hwcfgPath");
|
||||
my $hardwareFile = $tgtNode . "HardwareConfig";
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO cat $hwcfgPath" | grep -v "QETH_LAYER2_SUPPORT" > /tmp/$hardwareFile`;
|
||||
$out = `echo "QETH_LAYER2_SUPPORT='1'" >> /tmp/$hardwareFile`;
|
||||
@ -4338,16 +4415,16 @@ EOM"`;
|
||||
|
||||
# Remove old SSH keys
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO rm -f $cloneMntPt/etc/ssh/ssh_host_*"`;
|
||||
|
||||
# Flush disk
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO /bin/sync"`;
|
||||
|
||||
# Unmount disk
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO /bin/umount $cloneMntPt"`;
|
||||
|
||||
# Remove mount point
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO rm -rf $cloneMntPt"`;
|
||||
}
|
||||
|
||||
# Flush disk
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO /bin/sync"`;
|
||||
|
||||
# Unmount disk
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO /bin/umount $cloneMntPt"`;
|
||||
|
||||
# Remove mount point
|
||||
$out = `ssh $::SUDOER\@$hcp "$::SUDO rm -rf $cloneMntPt"`;
|
||||
|
||||
# Disable disks
|
||||
$out = xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $hcp, "-d", $tgtAddr );
|
||||
@ -4358,8 +4435,11 @@ EOM"`;
|
||||
sleep(5);
|
||||
} # End of foreach (@tgtDisks)
|
||||
|
||||
# Update DHCP
|
||||
$out = `makedhcp -a`;
|
||||
# Update DHCP (only if it is running)
|
||||
$out = `service dhcpd status`;
|
||||
if (!($out =~ m/unused/i || $out =~ m/stopped/i)) {
|
||||
$out = `makedhcp -a`;
|
||||
}
|
||||
|
||||
# Power on target virtual server
|
||||
xCAT::zvmUtils->printLn( $callback, "$tgtNode: Powering on" );
|
||||
@ -4766,20 +4846,16 @@ sub nodeSet {
|
||||
|
||||
@propNames = ( 'nfsserver', 'xcatmaster' );
|
||||
$propVals = xCAT::zvmUtils->getNodeProps( 'noderes', $node, @propNames );
|
||||
my $nfs = $propVals->{'nfsserver'};
|
||||
my $repo = $propVals->{'nfsserver'}; # Repository containing Linux ISO
|
||||
my $xcatmaster = $propVals->{'xcatmaster'};
|
||||
|
||||
# Use noderes.xcatmaster instead of site.master if it is given
|
||||
if ( $xcatmaster ) {
|
||||
$master = $xcatmaster;
|
||||
}
|
||||
|
||||
if ( !$nfs ) {
|
||||
$nfs = $master;
|
||||
}
|
||||
|
||||
|
||||
# Combine NFS server and installation directory, e.g. 10.0.0.1/install
|
||||
$nfs .= $installDir;
|
||||
my $nfs = $master . $installDir;
|
||||
|
||||
# Get broadcast address of NIC
|
||||
my $ifcfg = xCAT::zvmUtils->getIfcfgByNic( $::SUDOER, $hcp, $readChannel );
|
||||
@ -5008,6 +5084,10 @@ END
|
||||
# Install=ftp://10.0.0.1/sles10.2/s390x/1/
|
||||
# UseVNC=1 VNCPassword=12345678
|
||||
# InstNetDev=osa OsaInterface=qdio OsaMedium=eth Manual=0
|
||||
if (!$repo) {
|
||||
$repo = "http://$nfs/$os/s390x/1/";
|
||||
}
|
||||
|
||||
my $ay = "http://$nfs/custom/install/sles/" . $node . "." . $profile . ".tmpl";
|
||||
|
||||
$parms = $parmHeader . "\n";
|
||||
@ -5024,7 +5104,7 @@ END
|
||||
|
||||
$parms = $parms . "ReadChannel=$readChannel WriteChannel=$writeChannel DataChannel=$dataChannel\n";
|
||||
$parms = $parms . "Nameserver=$nameserver Portname=$portName Portno=0\n";
|
||||
$parms = $parms . "Install=http://$nfs/$os/s390x/1/\n";
|
||||
$parms = $parms . "Install=$repo\n";
|
||||
$parms = $parms . "UseVNC=1 VNCPassword=12345678\n";
|
||||
$parms = $parms . "InstNetDev=$instNetDev OsaInterface=$osaInterface OsaMedium=$osaMedium Manual=0\n";
|
||||
|
||||
@ -5127,9 +5207,12 @@ END
|
||||
$out = `sed --in-place -e "s,replace_xcatinstallpost,,g" $customTmpl`;
|
||||
|
||||
# Edit template
|
||||
my $url = "http://$nfs/$os/s390x/";
|
||||
if (!$repo) {
|
||||
$repo = "http://$nfs/$os/s390x/";
|
||||
}
|
||||
|
||||
$out =
|
||||
`sed --in-place -e "s,replace_url,$url,g" \ -e "s,replace_ip,$hostIP,g" \ -e "s,replace_netmask,$mask,g" \ -e "s,replace_gateway,$gateway,g" \ -e "s,replace_nameserver,$nameserver,g" \ -e "s,replace_hostname,$hostname,g" \ -e "s,replace_rootpw,$passwd,g" \ -e "s,replace_master,$master,g" \ -e "s,replace_install_dir,$installDir,g" $customTmpl`;
|
||||
`sed --in-place -e "s,replace_url,$repo,g" \ -e "s,replace_ip,$hostIP,g" \ -e "s,replace_netmask,$mask,g" \ -e "s,replace_gateway,$gateway,g" \ -e "s,replace_nameserver,$nameserver,g" \ -e "s,replace_hostname,$hostname,g" \ -e "s,replace_rootpw,$passwd,g" \ -e "s,replace_master,$master,g" \ -e "s,replace_install_dir,$installDir,g" $customTmpl`;
|
||||
|
||||
# Attach SCSI FCP devices (if any)
|
||||
# Go through each pool
|
||||
|
Loading…
Reference in New Issue
Block a user