From 9d01a63782b9e5b941c0e44b8f0b70751cffc24d Mon Sep 17 00:00:00 2001 From: phamt Date: Tue, 26 Feb 2013 00:19:46 +0000 Subject: [PATCH] Fixed nodeset to accept noderes.nfsserver. Added golden images to self-service portal. git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@15254 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd --- perl-xCAT/xCAT/zvmUtils.pm | 12 +-- xCAT-UI/js/custom/zvm.js | 45 +++++++---- xCAT-UI/js/custom/zvmUtils.js | 79 +++++++++++++++++++ xCAT-UI/js/service/service.js | 70 ++++++++++++----- xCAT-UI/lib/functions.php | 2 +- xCAT-UI/lib/srv_functions.php | 2 +- xCAT-UI/xcat/plugins/webportal.pm | 113 +++++++++++++++++++++++++--- xCAT-server/lib/xcat/plugins/zvm.pm | 23 +++--- 8 files changed, 284 insertions(+), 62 deletions(-) diff --git a/perl-xCAT/xCAT/zvmUtils.pm b/perl-xCAT/xCAT/zvmUtils.pm index a7ee21798..cb337f473 100644 --- a/perl-xCAT/xCAT/zvmUtils.pm +++ b/perl-xCAT/xCAT/zvmUtils.pm @@ -2029,15 +2029,15 @@ sub smapi4xcat { # Check SMAPI level # Levels 621 and greater support SMAPI EXEC - my $out = `ssh $user\@$hcp "$sudo $dir/smcli Query_API_Functional_Level -T $hcpUserId"`; - $out = xCAT::zvmUtils->trimStr($out); - if ( !($out =~ m/V6.2/i || $out =~ m/V6.1/i || $out =~ m/V5.4/i) ) { - return 1; - } +# my $out = `ssh $user\@$hcp "$sudo $dir/smcli Query_API_Functional_Level -T $hcpUserId"`; +# $out = xCAT::zvmUtils->trimStr($out); +# if ( !($out =~ m/V6.2/i || $out =~ m/V6.1/i || $out =~ m/V5.4/i) ) { +# return 1; +# } # Check if SMAPI EXEC exists # EXEC found if RC = 8 and RS = 3002 - $out = `ssh $user\@$hcp "$sudo $dir/smcli xCAT_Commands_IUO -T $hcpUserId -c ''"`; + my $out = `ssh $user\@$hcp "$sudo $dir/smcli xCAT_Commands_IUO -T $hcpUserId -c ''"`; $out = xCAT::zvmUtils->trimStr($out); if ( $out =~ m/Return Code: 8/i && $out =~ m/Reason Code: 3002/i ) { return 1; diff --git a/xCAT-UI/js/custom/zvm.js b/xCAT-UI/js/custom/zvm.js index fee3b239f..8ceae3a1d 100644 --- a/xCAT-UI/js/custom/zvm.js +++ b/xCAT-UI/js/custom/zvm.js @@ -33,7 +33,7 @@ zvmPlugin.prototype.loadConfigPage = function(tabId) { // Create accordion panel for images var imgSection = $('
'); - var imgLnk = $('

Images

').click(function () { + var imgLnk = $('

Templates

').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 = $(''); + var provHeader = $(''); var provBody = $(''); var provFooter = $(''); provTable.append(provHeader, provBody, provFooter); @@ -108,16 +108,18 @@ zvmPlugin.prototype.loadServiceProvisionPage = function(tabId) { // Create row to contain selections var provRow = $(''); provBody.append(provRow); - // Create columns for zVM, group, and image + // Create columns for zVM, group, template, and image var zvmCol = $(''); provRow.append(zvmCol); var groupCol = $(''); provRow.append(groupCol); - var imageCol = $(''); - provRow.append(imageCol); + var tmplCol = $(''); + provRow.append(tmplCol); + var imgCol = $(''); + 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')){ diff --git a/xCAT-UI/js/custom/zvmUtils.js b/xCAT-UI/js/custom/zvmUtils.js index 27a50451c..2ec031c01 100644 --- a/xCAT-UI/js/custom/zvmUtils.js +++ b/xCAT-UI/js/custom/zvmUtils.js @@ -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 = $('').css('display', 'none'); imgBlock.append(radio, $('' + name + ': ' + desc + '')); @@ -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 = $('
').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 = $('').css('display', 'none'); + imgBlock.append(radio, $('' + name + ': ' + desc + '')); + 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 * diff --git a/xCAT-UI/js/service/service.js b/xCAT-UI/js/service/service.js index 4d60e2e5e..c25b24def 100644 --- a/xCAT-UI/js/service/service.js +++ b/xCAT-UI/js/service/service.js @@ -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 diff --git a/xCAT-UI/lib/functions.php b/xCAT-UI/lib/functions.php index 1fd1f97cc..a29856934 100644 --- a/xCAT-UI/lib/functions.php +++ b/xCAT-UI/lib/functions.php @@ -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 diff --git a/xCAT-UI/lib/srv_functions.php b/xCAT-UI/lib/srv_functions.php index c18a336fb..6dafe540e 100644 --- a/xCAT-UI/lib/srv_functions.php +++ b/xCAT-UI/lib/srv_functions.php @@ -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 diff --git a/xCAT-UI/xcat/plugins/webportal.pm b/xCAT-UI/xcat/plugins/webportal.pm index 3cf3d5437..22b79f3c8 100644 --- a/xCAT-UI/xcat/plugins/webportal.pm +++ b/xCAT-UI/xcat/plugins/webportal.pm @@ -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 | sed 1d`; + 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; \ No newline at end of file diff --git a/xCAT-server/lib/xcat/plugins/zvm.pm b/xCAT-server/lib/xcat/plugins/zvm.pm index f1afe596c..84103deea 100644 --- a/xCAT-server/lib/xcat/plugins/zvm.pm +++ b/xCAT-server/lib/xcat/plugins/zvm.pm @@ -4793,20 +4793,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 ); @@ -5025,6 +5021,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"; @@ -5041,7 +5041,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"; @@ -5136,9 +5136,12 @@ END $out = `sed --in-place -e "/%post/r $postScript" $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
zVM Group Image
zVM Group Template Image