From 3aca3b2a70bf08478a3a54a0fe509b0c8d083f5b Mon Sep 17 00:00:00 2001 From: wanghuaz Date: Tue, 15 Oct 2013 17:49:01 +0800 Subject: [PATCH 01/91] fixing bug 3510 remove useless repos after genimage --- xCAT-client/pods/man1/addkitcomp.1.pod | 4 +-- xCAT-server/share/xcat/netboot/rh/genimage | 10 +++++--- xCAT-server/share/xcat/netboot/sles/genimage | 26 +++++++++++++++----- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/xCAT-client/pods/man1/addkitcomp.1.pod b/xCAT-client/pods/man1/addkitcomp.1.pod index cff400964..821d403fd 100644 --- a/xCAT-client/pods/man1/addkitcomp.1.pod +++ b/xCAT-client/pods/man1/addkitcomp.1.pod @@ -15,9 +15,9 @@ The B command will assign kit components to an xCAT osimage. The kit Note: The xCAT support for Kits is only available for Linux operating systems. =head1 OPTIONS - -=over 10 +=over 10 + =item B<-a|--adddeps> Assign kitcomponent dependencies to the osimage. diff --git a/xCAT-server/share/xcat/netboot/rh/genimage b/xCAT-server/share/xcat/netboot/rh/genimage index d99271dd1..6b75afe34 100755 --- a/xCAT-server/share/xcat/netboot/rh/genimage +++ b/xCAT-server/share/xcat/netboot/rh/genimage @@ -408,13 +408,15 @@ unless ($onlyinitrd) { } } $yumcmd = $yumcmd_base; + + # run yum update to update any installed rpms + # needed when running genimage again after updating software in repositories + my $yumcmd_update = $yumcmd_base . " update "; + $rc = system("$yumcmd_update"); + } } - # run yum update to update any installed rpms - # needed when running genimage again after updating software in repositories - my $yumcmd_update = $yumcmd_base . " update "; - $rc = system("$yumcmd_update"); # ignore any return code postscripts(); #run 'postscripts' diff --git a/xCAT-server/share/xcat/netboot/sles/genimage b/xCAT-server/share/xcat/netboot/sles/genimage index d22bf48eb..aa3eda6d6 100755 --- a/xCAT-server/share/xcat/netboot/sles/genimage +++ b/xCAT-server/share/xcat/netboot/sles/genimage @@ -544,17 +544,31 @@ unless ($onlyinitrd) { $rc = system("$envlist $yumcmd_remove $rm_packges"); } } + + # run zypper update to update any installed rpms + # needed when running genimage again after updating software in repositories + my $yumcmd_update; + if ($osver_host == 11) { + $yumcmd_update = "zypper -R $rootimg_dir $non_interactive update "; + } else { + $yumcmd_update = "zypper -R $rootimg_dir $non_interactive update "; + } + $rc = system("$yumcmd_update"); } - # run zypper update to update any installed rpms - # needed when running genimage again after updating software in repositories - my $yumcmd_update; + #remove the old repository for extra packages if ($osver_host == 11) { - $yumcmd_update = "zypper -R $rootimg_dir $non_interactive update "; + my $result=`zypper -R $rootimg_dir $non_interactive lr |grep otherpkg|cut -f2 -d '|'|tr "\n" " "`; + if ($result =~ /\S/) { + system("zypper -R $rootimg_dir $non_interactive rr $result"); + } } else { - $yumcmd_update = "zypper -R $rootimg_dir $non_interactive update "; + my $result=`zypper -R $rootimg_dir $non_interactive sl |grep otherpkg|cut -f2 -d '|'|tr "\n" " "`; + if ($result =~ /\S/) { + system("zypper -R $rootimg_dir $non_interactive sd $result"); + } } - $rc = system("$yumcmd_update"); + # ignore any return code postscripts(); #run 'postscripts' From 248415daea194432e5d8dc9cdde632d032042df2 Mon Sep 17 00:00:00 2001 From: lissav Date: Tue, 15 Oct 2013 08:15:12 -0400 Subject: [PATCH 02/91] defect 3819 enhance -s behavior --- xCAT-server/lib/xcat/plugins/updatenode.pm | 24 +++++++--------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/updatenode.pm b/xCAT-server/lib/xcat/plugins/updatenode.pm index 119c59a3d..f67c67bdb 100644 --- a/xCAT-server/lib/xcat/plugins/updatenode.pm +++ b/xCAT-server/lib/xcat/plugins/updatenode.pm @@ -294,17 +294,18 @@ sub preprocess_updatenode return; } - # -s must work with -P or -S or --security - if ($::SETSERVER && !($::SWMAINTENANCE || $::RERUNPS || $::SECURITY)) + # -s must not be with any other flag, this updates xcatinfo and run setuppostbootscripts + if ($::SETSERVER && ($::SWMAINTENANCE || $::RERUNPS || $::SECURITY)) { my $rsp = {}; $rsp->{data}->[0] = - "If you specify the -s flag you must specify either the -S or -k or -P + "If you specify the -s flag you must not specify either the -S or -k or -P flags"; $callback->($rsp); return; + } else { + $::RERUNPS = "setuppostbootscripts"; } - # -f or -F not both if (($::FILESYNC) && ($::SNFILESYNC)) { @@ -1306,7 +1307,7 @@ sub updatenoderunps # should be kept the same. my $runpscmd; - if ($::SETSERVER){ + if ($::SETSERVER){ # update the xcatinfo file on the node and run setuppostbootscripts $runpscmd = "$installdir/postscripts/xcatdsklspost $mode -M $snkey '$postscripts' --tftp $tftpdir --installdir $installdir --nfsv4 $nfsv4 -c"; } else { @@ -1723,19 +1724,8 @@ sub updatenodesoftware my $nodestring = join(',', @{$servernodes{$snkey}}); my $cmd; my $args1; - if ($::SETSERVER) - { - $cmd = - "$installdir/postscripts/xcatdsklspost 2 -M $snkey 'ospkgs,otherpkgs' --tftp $tftpdir --installdir $installdir --nfsv4 $nfsv4 -c" ; - - - - } - else - { - $cmd = + $cmd = "$installdir/postscripts/xcatdsklspost 2 -m $snkey 'ospkgs,otherpkgs' --tftp $tftpdir --installdir $installdir --nfsv4 $nfsv4 -c"; - } # add flowcontrol flag if ($flowcontrol == 1){ $cmd .= " -F"; From 9c7f3e41c0aafbdc990be3420ba91a0c34bef523 Mon Sep 17 00:00:00 2001 From: lissav Date: Tue, 15 Oct 2013 09:05:44 -0400 Subject: [PATCH 03/91] defect 3819 enhance -s behavior --- xCAT-server/lib/xcat/plugins/updatenode.pm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xCAT-server/lib/xcat/plugins/updatenode.pm b/xCAT-server/lib/xcat/plugins/updatenode.pm index f67c67bdb..3162d71fa 100644 --- a/xCAT-server/lib/xcat/plugins/updatenode.pm +++ b/xCAT-server/lib/xcat/plugins/updatenode.pm @@ -303,7 +303,9 @@ sub preprocess_updatenode flags"; $callback->($rsp); return; - } else { + } + # For -s flag just run this one script + if ($::SETSERVER) { $::RERUNPS = "setuppostbootscripts"; } # -f or -F not both From 53974fcaa8067d4128640d90ba57ed6390f5affd Mon Sep 17 00:00:00 2001 From: lissav Date: Tue, 15 Oct 2013 10:21:53 -0400 Subject: [PATCH 04/91] defect 3819, changes for xcatdsklspost and setuppostbootscripts --- xCAT/postscripts/setuppostbootscripts | 26 +++++++++++++++++++++++--- xCAT/postscripts/xcatdsklspost | 27 +++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/xCAT/postscripts/setuppostbootscripts b/xCAT/postscripts/setuppostbootscripts index 21cb3df25..48a601be0 100755 --- a/xCAT/postscripts/setuppostbootscripts +++ b/xCAT/postscripts/setuppostbootscripts @@ -16,7 +16,7 @@ if [ "$NODESETSTATE" = "netboot" -o \ "$NODESETSTATE" = "statelite" -o \ "$NODESETSTATE" = "diskless" -o \ "$NODESETSTATE" = "dataless" ]; then - echo "Nothng to do for stateless and statelite node." + logger -t xCAT -p local4.info "setuppostbootscripts: Nothing to do for stateless and statelite nodes." exit 0 fi @@ -24,7 +24,20 @@ fi if [ ! -d "/opt/xcat" ]; then mkdir -p /opt/xcat fi - +infofile="/opt/xcat/xcatinfo" +if [ "$RUNBOOTSCRIPTS" = "yes" ] || [ "$RUNBOOTSCRIPTS" = "YES" ]; then + RUNBOOTSCRIPTS=YES +else + RUNBOOTSCRIPTS=NO +fi +# check to see if current setting is already in the file, if so nothing to do +if [ -f $infofile ]; then + value=`grep "RUNBOOTSCRIPTS=$RUNBOOTSCRIPTS" $infofile` + if [[ -n $value ]]; then # match + logger -t xCAT -p local4.info "setuppostbootscripts: xcatinfo uptodate, nothing to do." + exit 0 + fi +fi #copy the necessary files rsync /xcatpost/xcatdsklspost /opt/xcat/xcatdsklspost rsync /xcatpost/xcatinstallpost /opt/xcat/xcatinstallpost @@ -42,10 +55,11 @@ if [ ! -f "/etc/rc.d/rc5.d/S84xcatpostinit1" ]; then fi #put correct info in /opt/xcat/xcatinfo -infofile="/opt/xcat/xcatinfo" + if [ ! -f $infofile ]; then echo "XCATSERVER=$MASTER" > $infofile echo "REBOOT=TRUE" >> $infofile + echo "RUNBOOTSCRIPTS=$RUNBOOTSCRIPTS" >> $infofile else value=`grep XCATSERVER $infofile` if [[ -n $value ]]; then @@ -59,6 +73,12 @@ else else echo REBOOT=TRUE >> $infofile fi + value=`grep RUNBOOTSCRIPTS $infofile` + if [[ -n $value ]]; then + sed -i "s/^RUNBOOTSCRIPTS=.*$/RUNBOOTSCRIPTS=$RUNBOOTSCRIPTS/" $infofile + else + echo "RUNBOOTSCRIPTS=$RUNBOOTSCRIPTS" >> $infofile + fi fi #enable/disable the running of postscripts according to site.runbootscripts if [[ "$RUNBOOTSCRIPTS" = "yes" ]]; then diff --git a/xCAT/postscripts/xcatdsklspost b/xCAT/postscripts/xcatdsklspost index ea1be0b24..19e031cd7 100755 --- a/xCAT/postscripts/xcatdsklspost +++ b/xCAT/postscripts/xcatdsklspost @@ -555,6 +555,33 @@ if [ -n "$new_ms" ]; then fi fi +#save the USEFLOWCONTROL into the xcatinfo file +#for updatenode case, passwd in with the -f flag +if [ $NODE_DEPLOYMENT -eq 1 ] || [ "$MODE" = "4" ]; then + useflowcontrol=`grep '^USEFLOWCONTROL' /$xcatpost/mypostscript |cut -d= -f2` +fi +if [ ! -f /opt/xcat/xcatinfo ]; then + mkdir -p /opt/xcat + touch /opt/xcat/xcatinfo +fi +if [ -n "$useflowcontrol" ]; then + # lets just put YES or NO in xcatinfo + if [ "$useflowcontrol" = "1" ] || [ "$useflowcontrol" = "yes" ] || [ "$useflowcontrol" = "YES" ]; then + new_fc="YES" + else + new_fc="NO" + fi + grep 'USEFLOWCONTROL' /opt/xcat/xcatinfo 2>&1 > /dev/null + if [ $? -eq 0 ]; then + sed -i "s/USEFLOWCONTROL=.*/USEFLOWCONTROL=$new_fc/" /opt/xcat/xcatinfo + else + echo "USEFLOWCONTROL=$new_fc" >> /opt/xcat/xcatinfo + fi +# no setting means do not use flowcontrol +else + echo "USEFLOWCONTROL=NO" >> /opt/xcat/xcatinfo +fi + # when called by the updatenode command MODE=1,2 # the nodename is passed in by xdsh in the NODE environment variable by xdsh. From a52dc5b5f946028ee53cc9e043570d61b9f07b6c Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Tue, 15 Oct 2013 13:39:20 -0400 Subject: [PATCH 05/91] Correct problem introduced by partial backout of storable. Client.pm was still expecting some output to a request no longer sent. Correct that. --- perl-xCAT/xCAT/Client.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/perl-xCAT/xCAT/Client.pm b/perl-xCAT/xCAT/Client.pm index 0599b5c3c..e0934796d 100644 --- a/perl-xCAT/xCAT/Client.pm +++ b/perl-xCAT/xCAT/Client.pm @@ -269,7 +269,7 @@ if (ref($request) eq 'HASH') { # the request is an array, not pure XML #if ($ENV{XCATXMLTRACE} or $ENV{XCATXMLWARNING}) { $encode="xml"; } if (ref($request) eq 'HASH') { # the request is an array, not pure XML #print $client "xcatencoding: $encode\n"; - my $encok=<$client>; + #my $encok=<$client>; send_request($request,$client,$encode); } else { #XML $straightprint=1; From b9144fc0287188fb84ed2b84211cbea9a5a096d6 Mon Sep 17 00:00:00 2001 From: lissav Date: Tue, 15 Oct 2013 14:24:43 -0400 Subject: [PATCH 06/91] comment out for now disable buffering on the socket --- xCAT-server/sbin/xcatd | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/xCAT-server/sbin/xcatd b/xCAT-server/sbin/xcatd index fc5657c35..85d05da73 100755 --- a/xCAT-server/sbin/xcatd +++ b/xCAT-server/sbin/xcatd @@ -1064,9 +1064,9 @@ until ($quit) { } #we have a pending connection and we are under the threshold, grab one from the list and process it... my $cnnection=shift @pendingconnections; - my $previous = select ($cnnection); #assure that perl buffering is not in play at the low level - $|=1; - select ($previous); + #my $previous = select ($cnnection); #assure that perl buffering is not in play at the low level + #$|=1; + #select ($previous); my $connection; my $child = xCAT::Utils->xfork(); #Yes we fork, IO::Socket::SSL is not threadsafe.. if ($child) { @@ -1111,9 +1111,9 @@ until ($quit) { unless ($connection) { xexit 0; } - $previous=select($connection); #also assure buffering not in play at SSL socket, which seems to be possibly independent of lower socket - $|=1; - select($previous); + # $previous=select($connection); #also assure buffering not in play at SSL socket, which seems to be possibly independent of lower socket + # $|=1; + # select($previous); $clientselect->add($connection); my $peerhost=undef; my $peerfqdn=undef; From 7040aebf37cb623e1b3a97a3064234bd8665d766 Mon Sep 17 00:00:00 2001 From: Bruce Potter Date: Tue, 15 Oct 2013 20:44:05 -0400 Subject: [PATCH 07/91] require perl-IO-Stty on x86_64 too, in case managing ppc64 nodes --- xCAT/xCAT.spec | 3 +-- xCATsn/xCATsn.spec | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/xCAT/xCAT.spec b/xCAT/xCAT.spec index a181b3e00..ec8b3458e 100644 --- a/xCAT/xCAT.spec +++ b/xCAT/xCAT.spec @@ -37,8 +37,7 @@ Requires: /etc/xinetd.d/tftp Requires: xCAT-buildkit # yaboot-xcat is pulled in so any MN can manage ppc nodes #Requires: yaboot-xcat -%endif -%ifarch ppc64 +# Stty is only needed for rcons on ppc64 nodes, but for mixed clusters require it on both x and p Requires: perl-IO-Stty %endif %endif diff --git a/xCATsn/xCATsn.spec b/xCATsn/xCATsn.spec index d8ebae509..2e514c536 100644 --- a/xCATsn/xCATsn.spec +++ b/xCATsn/xCATsn.spec @@ -34,8 +34,7 @@ Requires: /usr/bin/ssh Requires: /etc/xinetd.d/tftp # yaboot-xcat is pulled in so any MN can manage ppc nodes #Requires: yaboot-xcat -%endif -%ifarch ppc64 +# Stty is only needed for rcons on ppc64 nodes, but for mixed clusters require it on both x and p Requires: perl-IO-Stty %endif %endif From 3bd7a65b374492148fd42175df0593e306ae24fd Mon Sep 17 00:00:00 2001 From: Bruce Potter Date: Tue, 15 Oct 2013 21:10:22 -0400 Subject: [PATCH 08/91] remove xcat.1.pod, it is generated by xpod2man --- xCAT-client/pods/man1/xcat.1.pod | 657 ------------------------------- 1 file changed, 657 deletions(-) delete mode 100644 xCAT-client/pods/man1/xcat.1.pod diff --git a/xCAT-client/pods/man1/xcat.1.pod b/xCAT-client/pods/man1/xcat.1.pod deleted file mode 100644 index 4c0cf2e46..000000000 --- a/xCAT-client/pods/man1/xcat.1.pod +++ /dev/null @@ -1,657 +0,0 @@ -=head1 NAME - -B - extreme Cluster Administration Tool. - -=head1 DESCRIPTION - -Extreme Cluster Administration Toolkit (xCAT). xCAT is a scalable distributed computing management -and provisioning tool that provides a unified interface for hardware control, discovery, and -OS diskful/diskfree deployment. - - -=head1 XCAT DATABASE - -All of the cluster configuration information is in the xCAT database. See L for -descriptions of every table in the database. - -=head1 XCAT COMMANDS - -What follows is a short description of each xCAT command. To get more information about a particular -command, see its man page. Note that the commands are listed in alphabetical order B, -i.e. all the commands in section 1, then the commands in section 3, etc. - -=over 12 - -=item L - -Install a kit on the xCAT management node - -=item L - -Assign kit components to osimage. - -=item L - -Configure the elements for a virtual environment. - -=item L - -Migrates the CFM setup in CSM to the xdcp rsync setup in xCAT. - -=item L - -Change xCAT data object definitions. - -=item L - -Configure the virtualization hosts. - -=item L - -Check if kit component fits to osimage. - -=item L - -Use this xCAT command to check an xCAT osimage. - -=item L - -Changes HMC-, IVM-, and zVM-managed partition profiles or virtual machines. For Power 775, chvm could be used to change the octant configuration values for generating LPARs; change the I/O slots assignment to LPARs within the same CEC. - -=item L - -Create masters from virtual machines and virtual machines from masters. - -=item L - -Allows the migration of a CSM database to an xCAT database. - -=item L - -Sets up the IBM DB2 for xCAT to use. - -=item L - -dumps the xCAT db tables . - -=item L - -Generates a stateless image to be used for a diskless install. - -=item L - -Collects node MAC address. - -=item L - -select table rows, based on attribute criteria, and display specific attributes. - -=item L - -downloads the xCAT documentation and converts to HTML and PDF - -=item L - -Builds a directory of files for each defined nodegroup in xCAT. - -=item L - -Captures an image from a Linux diskful node and create a diskless image on the management node. - -=item L - -Exports an xCAT image. - -=item L - -Imports an xCAT image or configuration file into the xCAT tables so that you can immediately begin deploying with it. - -=item L - -Modify statelite image by creating a series of links. - -=item L - -Use this command to list xCAT data object definitions. - -=item L - -Display the information of flexible node - -=item L - -Use this command to display the connection status for CEC and Frame nodes. - -=item L - -list kernel driver modules in rpms or driver disk image files - -=item L - -Display a summary of the statelite information. - -=item L - -Discovers selected networked services information within the same subnet. - -=item L - -Display the tree of service node hierarchy, hardware hierarchy, or VM hierarchy. - -=item L - -Lists detail attributes for a virtual environment. - -=item L - -Lists partition profile information for HMC-, IVM-, KVM-, Vmware- and zVM-managed nodes. For Power 775, it lists the LPARs' I/O slots information and CEC configuration. - -=item L - -lists xCAT daemon information. - -=item L - -Use this command to create xCAT data object definitions. - -=item L - -Use this xCAT command to define and initialize AIX/NIM diskless machines. - -=item L - -Create a flexible node. - -=item L - -Sets up connections for CEC and Frame nodes to HMC nodes or hardware server. - -=item L - -Use this xCAT command to create xCAT osimage definitions and related AIX/NIM resources. The command can also be used to update an existing AIX diskless image(SPOT). - -=item L - -Creates HMC-, IVM-, and zVM-managed partitions or other virtual machines. - -=item L - -Registers a monitoring plug-in to the xCAT cluster. - -=item L - -Configures a 3rd party monitoring software to monitor the xCAT cluster. - -=item L - -Deconfigures a 3rd party monitoring software from monitoring the xCAT cluster. - -=item L - -Lists monitoring plug-in modules that can be used to monitor the xCAT cluster. - -=item L - -Unregisters a monitoring plug-in module from the xCAT cluster. - -=item L - -Shows event data for monitoring. - -=item L - -Starts a plug-in module to monitor the xCAT cluster. - -=item L - -Stops a monitoring plug-in module to monitor the xCAT cluster. - -=item L - -Sets up the MySQL database for xCAT to use. - -=item L - -Use this xCAT command to customize AIX/NIM standalone machines. - -=item L - -Use this xCAT command to initialize AIX/NIM standalone machines. - -=item L - -Create a unmanaged node. - -=item L - -Changes nodes' attributes in the xCAT cluster database. - -=item L - -Updates the MAC address for a node. - -=item L - -updates a profile used by a node - -=item L - -List all discovered nodes - -=item L - -starts the node discovery process - -=item L - -gets the node discovery process status - -=item L - -stops the node discovery process. - -=item L - -Changes attributes at the group level in the xCAT cluster database. - -=item L - -Create profiled nodes by importing hostinfo file. - -=item L - -lists the nodes, and their attributes, from the xCAT database. - -=item L - -Removes nodes. - -=item L - -Update nodes configurations by running associated kit plugins. - -=item L - -Removes the nodes in the noderange from all database table. - -=item L - -display the running status of each node in a noderange - -=item L - -Packs the stateless image from the chroot file system. - -=item L - -run the ASU to many nodes in parallel - -=item L - -Runs a command on the noderange using the out-of-band console. - -=item L - -Sets up the PostgreSQL database for xCAT to use. - -=item L - -parallel ping the nodes. - -=item L - -parallel ping from nodes to other nodes in the cluster. - -=item L - -parallel rsync - -=item L - -parallel remote copy - -=item L - -parallel remote shell - -=item L - -Turns beacon on/off/blink or gives status of a node or noderange. - -=item L - -Persistently sets the order of boot devices for BladeCenter blades or PPC LPARs using Direct FSP Management (DFM). - -=item L - -remotely accesses the serial console of a node - -=item L - -Registers a Perl module or a command that will get called when changes occur in the desired xCAT database tables. - -=item L - -remote energy management tool - -=item L - -replay the console output for a node - -=item L - -Restart the xCAT daemon (xcatd) on AIX. - -=item L - -restores the xCAT db tables . - -=item L - -retrieve or clear remote hardware event logs - -=item L - -Performs Licensed Internal Code (LIC) update support for HMC-attached POWER5 and POWER6 Systems, and POWER7 systems using Direct FSP management. - -=item L - -Remote hardware inventory - -=item L - -Use this command to remove xCAT data object definitions. - -=item L - -Use this xCAT command to remove AIX/NIM diskless machine definitions. - -=item L - -Delete a flexible node. - -=item L - -Use this command to remove connections from CEC and Frame nodes to HMC nodes. - -=item L - -Remove the virtualization hosts. - -=item L - -Execute migration of a guest VM between hosts/hypervisors - -=item L - -Removes the Linux stateless or statelite image from the file system. - -=item L - -Remove Kits from xCAT - -=item L - -Remove kit components from osimage. - -=item L - -Use this xCAT command to remove NIM resources specified in an xCAT osimage definition. - -=item L - -Removes HMC-, IVM-, KVM-, Vmware- and zVM-managed partitions or virtual machines. - -=item L - -Cause the range of nodes to boot to network. - -=item L - -performs cluster rolling update - -=item L - -remote power control of nodes - -=item L - -Collects node information from one or more hardware control points. - -=item L - -Sets the boot device to be used for BMC-based servers for the next boot only. - -=item L - -Configures nodes' service processors - -=item L - -resets the service processors associated with the specified nodes - -=item L - -remote hardware vitals - -=item L - -Checks the software configuration of the nodes in the cluster. - -=item L - -Move xCAT compute nodes to a different xCAT service node. - -=item L - -swap the location info in the db (all the attributes in the ppc table and the nodepos table) between 2 nodes. If swapping within a cec, it will assign the IO adapters that were assigned to the defective node to the available node. - -=item L - -reassign the BladeCenter media tray and/or KVM to the specified blade - -=item L - -list table names in which an entry for the given node appears. - -=item L - -unregister a Perl module or a command that was watching for the changes of the desired xCAT database tables. - -=item L - -Adds the needed Service Node configuration files to the install image. - -=item L - -Update nodes in an xCAT cluster environment. - -=item L - -windowed remote console - -=item L - -kill windowed remote consoles - -=item L - -windowed remote video console for nodes - -=item L - -Sample client program for xCAT. - -=item L - -extreme Cluster Administration Tool. - -=item L - -Use this command to create and manage AIX NIM definitions based on xCAT node, group and network object definitions. - -=item L - -Use this xCAT command to modify an xCAT AIX diskless operating system image. - -=item L - -Formats and consolidates the output of the B, B commands. - -=item L - -Concurrently copies files to or from multiple nodes. In addition, provides an option to use rsync to update the files on the nodes, or to an installation image on the local node. - -=item L - -Concurrently runs remote commands on multiple nodes (Management Node, Service Nodes, compute nodes), or an install image. - -=item L - -Formats the output of the B command. - -=item L - -Formats and consolidates the output of the B commands. - -=item L - -PBS pbsnodes front-end for a noderange. - -=item L - -syntax for compactly expressing a list of node names - -=item L - -Format of a stanza file that can be used with xCAT data object definition commands. - -=item L - -Add, delete or update rows in the database tables. - -=item L - -Client side wrapper for copycds supporting physical drives. - -=item L - -Copies Linux distributions and service levels from DVDs/ISOs to the xCAT /install directory. - -=item L - -creates the conserver configuration file from info in the xCAT database - -=item L - -Creates and updates DHCP configuration files. - -=item L - -sets up domain name services (DNS). - -=item L - -sets up /etc/hosts from the xCAT hosts table. - -=item L - -Make a known_hosts file under $ROOTHOME/.ssh for input noderange. - -=item L - -Gather cluster network information and add it to the xCAT database. - -=item L - -add or delete routes to/from the os route table on nodes. - -=item L - -creates a network boot root image for node discovery and flashing - -=item L - -Adds or deletes BladeCenter management module and switch node definitions in the xCAT cluster database. - -=item L - -Adds or deletes nodes in the xCAT cluster database. - -=item L - -Adds nodes to the xCAT cluster database. - -=item L - -set the boot state for a noderange - -=item L - -Begin installation on a noderange - -=item L - -remove OS Distro - -=item L - -Runs sql command files against the current xCAT database. - -=item L - -creates a LUN for a node to boot up with, using iSCSI - -=item L - -Add, delete or update rows in the database tables. - -=item L - -display an xCAT database table in CSV format. - -=item L - -view an xCAT database table in an editor and make changes. - -=item L - -Deletes records from the eventlog,auditlog,isnm_perf,isnm_perf_sum tables. - -=item L - -replaces the contents of an xCAT database table with the contents in a csv file. - -=item L - -Begin installation on a noderange and display in wcons - -=item L - -Sets up the Management Node during the xCAT install. - -=item L - -The xCAT daemon - -=item L - -Enable or disable the trace facilities for xCAT. (Only supports Linux Operating System) - -=item L - -Prime the xCAT database using naming conventions specified in a config file. - -=item L - -Gathers information for service about the current running xCAT environment. - -=item L - -Run automated xCAT test cases. - -=item L - -Build product software kits to be installed in an xCAT cluster. - -=back From ace7a82ef943026145fde439fd6c012d132f66f1 Mon Sep 17 00:00:00 2001 From: zhaoertao Date: Tue, 15 Oct 2013 19:38:18 -0700 Subject: [PATCH 09/91] modifying 'rscan -u|-w' for working through DFM --- perl-xCAT/xCAT/FSPscan.pm | 6 ++- perl-xCAT/xCAT/PPCdb.pm | 96 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 95 insertions(+), 7 deletions(-) diff --git a/perl-xCAT/xCAT/FSPscan.pm b/perl-xCAT/xCAT/FSPscan.pm index 6ed064c17..1dacbeeb9 100644 --- a/perl-xCAT/xCAT/FSPscan.pm +++ b/perl-xCAT/xCAT/FSPscan.pm @@ -260,7 +260,8 @@ sub format_output { # Strip errors for results ####################################### my @val = grep( !/^#.*: ERROR /, @$values ); - xCAT::PPCdb::add_ppc( $hwtype, \@val ); + #xCAT::PPCdb::add_ppc( $hwtype, \@val ); + $values = xCAT::PPCdb::update_lpar( $hwtype, \@val, "write"); } ########################################### @@ -271,7 +272,8 @@ sub format_output { # Strip errors for results ####################################### my @val = grep( !/^#.*: ERROR /, @$values ); - $values = xCAT::PPCdb::update_ppc( $hwtype, \@val ); + #$values = xCAT::PPCdb::update_ppc( $hwtype, \@val ); + $values = xCAT::PPCdb::update_lpar( $hwtype, \@val ); if ( exists( $opt->{x} ) or exists( $opt->{z} )) { unshift @$values, "hmc"; diff --git a/perl-xCAT/xCAT/PPCdb.pm b/perl-xCAT/xCAT/PPCdb.pm index 145652510..5a69acf7f 100644 --- a/perl-xCAT/xCAT/PPCdb.pm +++ b/perl-xCAT/xCAT/PPCdb.pm @@ -101,7 +101,6 @@ sub add_ppc { $parent, $ips, $mac ) = split /,/; - ############################### # Update nodetype table ############################### @@ -241,6 +240,97 @@ sub add_ppc { } return undef; } +########################################################################## +# Update lpar information in the xCAT databases +########################################################################## +sub update_lpar { + my $hwtype = shift; + my $values = shift; + my $write = shift; + my @tabs = qw(ppc vpd nodehm nodelist nodetype ppcdirect hosts mac); + my %db = (); + my @update_list = (); + my @write_list = (); + ################################### + # Open database needed + ################################### + foreach ( @tabs ) { + $db{$_} = xCAT::Table->new( $_, -create=>1, -autocommit=>0 ); + if ( !$db{$_} ) { + return( "Error opening '$_'" ); + } + } + my @vpdlist = $db{vpd}->getAllNodeAttribs(['node','serial','mtm','side']); + my @ppclist = $db{ppc}->getAllNodeAttribs(['node','hcp','id', + 'pprofile','parent','nodetype', + 'comments', 'disable']); + # 'cec,cec1,,8246-L1D,100A9DA,,cec1,,cec1', + # 'lpar,10-0A9DA,1,8246-L1D,100A9DA,,cec1,,cec1' + my %ppchash = (); + my %vpdhash = (); + foreach my $ppcent (@ppclist) { + if ($ppcent->{id} and $ppcent->{nodetype} and $ppcent->{nodetype} eq "lpar") { + my $key = $ppcent->{node}; + $ppchash{$key}{id} = $ppcent->{id}; + $ppchash{$key}{parent} = $ppcent->{parent}; + } + } + foreach my $vpdent (@vpdlist) + { + my $key = $vpdent->{node}; + $vpdhash{$key}{mtm} = $vpdent->{mtm}; + $vpdhash{$key}{serial} = $vpdent->{serial}; + } + my @ppc_lpars = keys %ppchash; + foreach my $value ( @$values ) { + my ($ttype, + $tname, + $tid, + $tmtm, + $tsn, + $tside, + $server, + $pprofile, + $parent) = split /,/, $value; + if ($ttype ne "lpar") { + push @update_list, $value; + next; + } + my $find_node = undef; + foreach my $tmp_node (@ppc_lpars) { + if ($ppchash{$tmp_node}{id} eq $tid) { + if (exists($ppchash{$tmp_node}{parent}) and $ppchash{$tmp_node}{parent} eq $parent) { + $find_node = $tmp_node; + last; + } elsif ($vpdhash{$tmp_node}{mtm} eq $tmtm and $vpdhash{$tmp_node}{serial} eq $tsn) { + $find_node = $tmp_node; + last; + } + } + } + if (defined($find_node)) { + if ( update_node_attribs($hwtype, $ttype, $find_node, $tid, $tmtm, $tsn, $tside, + $server, $pprofile, $parent, "", \%db, $tname, \@ppclist)) + { + $value =~ s/^$ttype,$tname,/$ttype,$find_node,/; + push @update_list, $value; + } + } elsif (defined($write)) { + push @write_list, $value; + } + } + if (defined($write)) { + &add_ppc($hwtype, \@write_list); + return ([@update_list,@write_list]); + } else { + foreach ( @tabs ) { + if ( exists( $db{$_}{commit} )) { + $db{$_}->commit; + } + } + return \@update_list; + } +} ########################################################################## # Update nodes in the xCAT databases @@ -283,7 +373,6 @@ sub update_ppc { $pprofile, $parent, $ips ) = split /,/, $value; - if ( $ttype eq 'cec' ) { my $hostname = get_host($tname, "FSP", $tmtm, $tsn, "", "", $tid, "",""); @@ -334,9 +423,7 @@ sub update_ppc { $pprofile, $parent, $ips ) = split /,/, $value; - next if ( $type ne 'cec' ); - my $predefined_node = undef; foreach my $vpdent (@vpdlist) { @@ -967,7 +1054,6 @@ sub get_host { # get the information of existed nodes to do the migration read_from_table() unless (%::OLD_DATA_CACHE); - foreach my $oldnode ( keys %::OLD_DATA_CACHE ) { my $tmpmtm = @{$::OLD_DATA_CACHE{$oldnode}}[0]; From 8081d7bf4fddc03f06b8b5fa7a02a72a1d504683 Mon Sep 17 00:00:00 2001 From: zhaoertao Date: Wed, 16 Oct 2013 02:20:54 -0700 Subject: [PATCH 10/91] modify the operating for CMM doesn't rely on 'id' attribute --- xCAT-server/lib/xcat/plugins/blade.pm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/blade.pm b/xCAT-server/lib/xcat/plugins/blade.pm index 88e49dcb2..b40d05fe5 100644 --- a/xCAT-server/lib/xcat/plugins/blade.pm +++ b/xCAT-server/lib/xcat/plugins/blade.pm @@ -3875,7 +3875,7 @@ sub build_depend { if (!defined($ent->{mpa})) { return("no mpa defined for node $name"); } - my $id = (defined($ent->{id})) ? $ent->{id} : ""; + my $id = (defined($ent->{id}) && $name ne $ent->{mpa}) ? $ent->{id} : ""; push @{$mpa_hash{$name}},$ent->{mpa}; push @{$mpa_hash{$name}},$id; @@ -3887,7 +3887,7 @@ sub build_depend { if (!defined($ent->{mpa})) { return("no mpa defined for node $_"); } - my $id = (defined($ent->{id})) ? $ent->{id} : ""; + my $id = (defined($ent->{id}) && $ent->{mpa} ne $_) ? $ent->{id} : ""; push @{$mpa_hash{$_}},$ent->{mpa}; push @{$mpa_hash{$_}},$id; } @@ -4158,7 +4158,7 @@ sub preprocess_request { $request = {}; return; } - if (defined($ent->{id})) { push @{$mpa_hash{$ent->{mpa}}{ids}}, $ent->{id};} + if (defined($ent->{id}) && $node ne $ent->{mpa}) { push @{$mpa_hash{$ent->{mpa}}{ids}}, $ent->{id};} else { push @{$mpa_hash{$ent->{mpa}}{ids}}, "";} if (defined($mpatype{$ent->{mpa}})) { push @{$mpa_hash{$ent->{mpa}}{nodetype}}, $mpatype{$ent->{mpa}};} else { push @{$mpa_hash{$ent->{mpa}}{nodetype}}, "mm";} @@ -4220,7 +4220,7 @@ sub build_more_info{ $callback->({data=>["no mpa defined for node $node"]}); return @moreinfo;; } - if (defined($ent->{id})) { push @{$mpa_hash{$ent->{mpa}}{ids}}, $ent->{id};} + if (defined($ent->{id}) && $node ne $ent->{mpa}) { push @{$mpa_hash{$ent->{mpa}}{ids}}, $ent->{id};} else { push @{$mpa_hash{$ent->{mpa}}{ids}}, "";} if (defined($mpatype{$ent->{mpa}})) { push @{$mpa_hash{$ent->{mpa}}{nodetype}}, $mpatype{$ent->{mpa}};} else { push @{$mpa_hash{$ent->{mpa}}{nodetype}}, "mm";} From c8899e694a8c26b2e6d0ea72f377897ef629d23e Mon Sep 17 00:00:00 2001 From: zhaoertao Date: Wed, 16 Oct 2013 02:31:38 -0700 Subject: [PATCH 11/91] fix bug 3834: 'lsslp -s CMM -w' write different id for cmm01 with 'rscan cmm01 -u' --- xCAT-server/lib/xcat/plugins/lsslp.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/lsslp.pm b/xCAT-server/lib/xcat/plugins/lsslp.pm index f2b4a6dd2..a6b3db461 100644 --- a/xCAT-server/lib/xcat/plugins/lsslp.pm +++ b/xCAT-server/lib/xcat/plugins/lsslp.pm @@ -1450,10 +1450,10 @@ sub xCATdB { $machash{$hostname} = {mac=>$mac}; }elsif ($type =~ /^cmm$/){ $nodelisthash{$hostname} = {groups=>$groups, hidden=>$hidden}; - $vpdhash{$hostname} = {mtm=>$model, serial=>$serial}; + $vpdhash{$hostname} = {mtm=>$model, serial=>$serial, side=>$side}; $nodetypehash{$hostname} = {nodetype=>$globalnodetype{$type}}; $nodehmhash{$hostname} = {mgt=>"blade"}; - $mphash{$hostname} = {nodetype=>$globalhwtype{$type}, mpa=>$hostname, id=>$side}; + $mphash{$hostname} = {nodetype=>$globalhwtype{$type}, mpa=>$hostname}; $hostshash{$hostname} = {otherinterfaces=>$otherif}; } } From 5e5cf68068b83c740d919855a463821c2c54e450 Mon Sep 17 00:00:00 2001 From: lissav Date: Wed, 16 Oct 2013 06:08:30 -0400 Subject: [PATCH 12/91] put manpage back --- xCAT-client/pods/man1/xdshbak.1.pod | 127 ++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 xCAT-client/pods/man1/xdshbak.1.pod diff --git a/xCAT-client/pods/man1/xdshbak.1.pod b/xCAT-client/pods/man1/xdshbak.1.pod new file mode 100644 index 000000000..661f1f302 --- /dev/null +++ b/xCAT-client/pods/man1/xdshbak.1.pod @@ -0,0 +1,127 @@ +=head1 NAME + +B - Formats the output of the B command. + +=head1 B + +B [B<-c> | B<-x> | B<-h> | B<-q>] + +=head1 DESCRIPTION + +The B command formats output from the B command. The B +command takes, as input, lines in the following format: + + host_name: line of output from remote command + +The B command formats the lines as follows and writes them to +standard output. Assume that the output from node3 and node4 +is identical, and the B<-c> (collapse) flag was specified: + + HOSTS -------------------------------------------------------- + node1 + -------------------------------------------------------------- + . + . + lines from xdsh for node1 with hostnames stripped off + . + . + HOSTS -------------------------------------------------------- + node2 + -------------------------------------------------------------- + . + . + lines from xdsh for node2 with hostnames stripped off + . + . + HOSTS -------------------------------------------------------- + node3, node4 + -------------------------------------------------------------- + . + . + lines from xdsh for node 3 with hostnames stripped off + . + . + +When output is displayed from more than one node in collapsed form, the +host names are displayed alphabetically. When output is not collapsed, +output is displayed sorted alphabetically by host name. + +If the B<-q> quiet flag is not set then B +command writes "." for each 1000 lines of output processed (to show progress), +since it won't display the output until it has processed all of it. + +If the B<-x> flag is specified, the extra header lines that xdshbak normally +displays for each node will be omitted, and the hostname at the beginning +of each line is not stripped off, but B still sorts +the output by hostname for easier viewing: + + node1: lines from xdsh for node1 + . + . + node2: lines from xdsh for node2 + . + . + +=head2 Standard Error + +When the B filter is used and standard error messages are generated, +all error messages on standard error appear before all standard +output messages. This is true with and without the B<-c> flag. + +=head1 OPTIONS + +=over 6 + +=item B<-c> + +If the output from multiple nodes is identical it will be collapsed +and displayed only once. + +=item B<-x> + +Omit the extra header lines that xdshbak normally displays for +each node. This provides +more compact output, but xdshbak still sorts the output by +node name for easier viewing. +This option should not be used with B<-c>. + +=item B<-h> + +Displays usage information. + +=item B<-q> + +Quiet mode, do not display "." for each 1000 lines of output. + +=back + +=head1 B + +=over 3 + +=item * + +To display the results of a command issued on several nodes, in +the format used in the Description, enter: + + xdsh node1,node2,node3 cat /etc/passwd | xdshbak + +=item * + +To display the results of a command issued on several nodes with +identical output displayed only once, enter: + + xdsh host1,host2,host3 pwd | xdshbak -c + +=item * + +To display the results of a command issued on several nodes with +compact output and be sorted alphabetically by host name, enter: + + xdsh host1,host2,host3 date | xdshbak -x + +=back + +=head1 B + +L, L From 6043695181a63c182ca6450ac211a5b2c3351099 Mon Sep 17 00:00:00 2001 From: xq2005 Date: Wed, 16 Oct 2013 08:43:20 -0700 Subject: [PATCH 13/91] bug 3801: the booted status after syslone reboot --- xCAT/postscripts/updatenetwork | 46 +++++++++++++--------------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/xCAT/postscripts/updatenetwork b/xCAT/postscripts/updatenetwork index bc318dce6..40d76a51d 100644 --- a/xCAT/postscripts/updatenetwork +++ b/xCAT/postscripts/updatenetwork @@ -9,45 +9,35 @@ fi hostname $HOSTNAME -device_name='' -str_mac='' -for str_temp in `cat /proc/cmdline`;do - echo $str_temp | grep -i 'BOOTIF' - if [ $? -eq 0 ];then - str_mac=`echo $str_temp | awk -F= '{print $2}' | sed -r 's/^01-//' | tr '-' ':' | tr 'a-z' 'A-Z'` - device_name=`ifconfig -a | grep -i $str_mac | awk '{print $1}' | head -n 1` - fi - -done - -if [ -z "$device_name" ];then - device_name=$DEVICE - str_mac=`ifconfig $device_name|grep -i HWaddr|awk '{print $5}'` -fi +#write the config files, the device name may change after reboot +#so use the dhcp for all interface +device_names=`ifconfig -a | grep -i hwaddr | grep -i 'Ethernet' | grep -v usb| awk '{print $1}'` str_cfg_file='' if [ -d "/etc/sysconfig/network-scripts/" ];then #redhat - rm -f /etc/sysconfig/network-scripts/ifcfg-* - str_cfg_file="/etc/sysconfig/network-scripts/ifcfg-$device_name" - grep HOSTNAME /etc/sysconfig/network + grep -i HOSTNAME /etc/sysconfig/network if [ $? -eq 0 ];then sed -i "s/HOSTNAME=.*/HOSTNAME=$HOSTNAME/g" /etc/sysconfig/network else echo "HOSTNAME=$HOSTNAME" >> /etc/sysconfig/network fi - echo "DEVICE=$device_name" > $str_cfg_file - echo "BOOTPROTO=dhcp" >> $str_cfg_file - echo "NM_CONTROLLED=yes" >> $str_cfg_file - echo "ONBOOT=yes" >> $str_cfg_file + for i in $device_names;do + str_cfg_file="/etc/sysconfig/network-scripts/ifcfg-$i" + echo "DEVICE=$i" > $str_cfg_file + echo "BOOTPROTO=dhcp" >> $str_cfg_file + echo "NM_CONTROLLED=yes" >> $str_cfg_file + echo "ONBOOT=yes" >> $str_cfg_file + done elif [ -d "/etc/sysconfig/network/" ];then #suse - rm -f /etc/sysconfig/network/ifcfg-* - str_cfg_file="/etc/sysconfig/network/ifcfg-$device_name" echo "$HOSTNAME" > /etc/HOSTNAME - echo "DEVICE=$device_name" > $str_cfg_file - echo "BOOTPROTO=dhcp" >> $str_cfg_file - echo "STARTMODE=onboot" >> $str_cfg_file - echo "DHCLIENT_PRIMARY_DEVICE=yes" >> $str_cfg_file + for i in $device_names;do + str_cfg_file="/etc/sysconfig/network/ifcfg-$i" + echo "DEVICE=$i" > $str_cfg_file + echo "BOOTPROTO=dhcp" >> $str_cfg_file + echo "STARTMODE=onboot" >> $str_cfg_file + echo "DHCLIENT_PRIMARY_DEVICE=yes" >> $str_cfg_file + done else #ubuntu echo "Does not support ubuntu." From b3a222e8111d54400f8a300d720bdba1753036f2 Mon Sep 17 00:00:00 2001 From: nott Date: Wed, 16 Oct 2013 15:03:55 -0400 Subject: [PATCH 14/91] add build_input subdir to complete kit --- xCAT-buildkit/bin/buildkit | 43 +++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/xCAT-buildkit/bin/buildkit b/xCAT-buildkit/bin/buildkit index c2705ecc5..95a828bbe 100755 --- a/xCAT-buildkit/bin/buildkit +++ b/xCAT-buildkit/bin/buildkit @@ -497,7 +497,7 @@ sub usage To add packages to an existing Kit. buildkit [-V│--verbose] addpkgs [-p│--pkgdir ] [-k│--kitversion ] [-r│--kitrelease ] [-k│--kitversion ] [-r│--kitrelease ] This tool is used to build and manage a Kit package. @@ -505,7 +505,7 @@ sub usage -h - Provide usage info. -k - Kit version. -l - Location of kit files. (Including kit name.) - -p - RPM package directory. + -p - RPM package directory locations. -r - Kit release. -v - Provide the version info. command - Several commands are supported. See the list below. @@ -912,6 +912,7 @@ sub kit_buildtar return 1; } } + if (&create_kitconf) { print "Error creating kit configuration file \n"; return 1; @@ -945,7 +946,16 @@ sub kit_buildtar $kitfilename =~ s/tar\.bz2\s*$//; } $kitfilename = $kitfilename.$extpkgs.".tar.bz2"; + my $tarfile = $::deploy_dir."/".$kitfilename; + + if ( system("cd $::deploy_dir; cd ..; cp -r build_input $kitname" ) ) { + print "Error: Could not copy building tarfile $tarfile \n"; + return 1; + } + + print "Creating tar file $tarfile.\n"; + if ( system("cd $::deploy_dir; cd ..; tar -cjhf $tarfile $kitname/*") ) { print "Error building tarfile $tarfile \n"; return 1; @@ -2100,6 +2110,7 @@ sub update_kitcomp_kitpkgdeps $new_kitpkgdeps =~ s/(\,)*$//; $comp->{kitpkgdeps} = $new_kitpkgdeps; } + return 0; } @@ -3120,12 +3131,15 @@ sub kit_addpkgs return 1; } + print "Extracting tar file $kittarfile.\n"; + if ( system("cd $tmpdir_base; tar -jxf $kittarfile ") ) { print "Error extracting tarfile $kittarfile \n"; # Cleanup system ("rm -Rf $tmpdir_base"); return 1; } + my $tmp_kit_conf = `find $tmpdir_base -name kit.conf`; chomp($tmp_kit_conf); my $tmpdir = dirname($tmp_kit_conf); @@ -3155,10 +3169,18 @@ sub kit_addpkgs # # check contents of kit.conf to make sure the framework # is compatible with this codes framework - if (&check_framework(\@lines)) { + $::kitframework = &check_framework(\@lines); + if (!defined($::kitframework)) { return 1; } + # if this in not a partial kit then the framework must be 2 or greater + my $kit_name = basename($kittarfile); + if ( (!($kit_name =~ /NEED_PRODUCT_PKGS/)) && ($::kitframework < 2) ) { + print "This kit cannot be updated. To update a complete kit the kit framework\n value must be greater than or equal to 2. You can use the\n\t\'lskit -F \' \ncommand to check the framework value of the kit.\n"; + return 1; + } + ### Check if this is a new partial kit built with xCAT 2.8.1 or newer if (-d "$tmpdir/build_input") { system ("mv $tmpdir/build_input $tmpdir_base"); @@ -3461,6 +3483,7 @@ sub NEW_kit_addpkgs $::deploy_dir = $tmpdir_base; #kitname appended by validate_bldkitconf routine my $tmp_buildkit_conf = `find $tmpdir_base -name $::buildkit_conf`; + chomp($tmp_buildkit_conf); if ($tmp_buildkit_conf ne $::full_buildkit_conf) { print "$tmp_buildkit_conf should match $::full_buildkit_conf .... error??? \n"; @@ -3649,11 +3672,11 @@ sub NEW_kit_addpkgs and kit frameworks that I can be added to. Returns: - 0 - OK - 1 - error + 0 - kit framework value + undef - error Example: - my $rc = &check_framework(\@lines); + my $kitframework = &check_framework(\@lines); =cut @@ -3666,6 +3689,7 @@ sub check_framework my $kitbasename; my $kitcompat; + my $kitframework; my $section = ''; foreach my $l (@kitconflines) { # skip blank and comment lines @@ -3691,6 +3715,9 @@ sub check_framework if ( $attr eq 'compatible_kitframeworks' ) { $kitcompat = $val; } + if ( $attr eq 'kitframework' ) { + $kitframework = $val; + } } if ($section eq 'kit') { if ( $attr eq 'basename' ) { $kitbasename = $val; } @@ -3712,10 +3739,10 @@ sub check_framework chomp $kitfw; if ($myfw eq $kitfw) { - return 0; + return $kitframework; } } } print "Error: The kit named \'$kitbasename\' is not compatible with this version of the buildkit command. \'$kitbasename\' is compatible with \'$kitcompat\' and the buildkit command is compatible with \'$::COMPATIBLE_KITFRAMEWORKS\'\n"; - return 1; + return undef; } From f8a56d371256ecfe2f50c7e65f256aa6c557d3b9 Mon Sep 17 00:00:00 2001 From: xq2005 Date: Wed, 16 Oct 2013 20:12:52 -0700 Subject: [PATCH 15/91] bug 3801: the booted status after syslone reboot --- xCAT/postscripts/runxcatpost | 60 +++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/xCAT/postscripts/runxcatpost b/xCAT/postscripts/runxcatpost index d7c86c66b..973425802 100644 --- a/xCAT/postscripts/runxcatpost +++ b/xCAT/postscripts/runxcatpost @@ -1,13 +1,63 @@ #!/bin/bash + +if [ ! -f "/opt/xcat/xcatdsklspost" ];then + echo "sysclone require /opt/xcat/xcatdsklspost, but it can not be found. return error!" + exit 1 +fi if [ -f "/opt/xcat/xcatinfo" ];then rm -f "/opt/xcat/xcatinfo" fi -/opt/xcat/xcatdsklspost -. /tmp/post-install/variables.txt -if [ -x "/xcatpost/updateflag.awk" ];then - /xcatpost/updateflag.awk $IMAGESERVER 3002 - /xcatpost/updateflag.awk $IMAGESERVER 3002 "installstatus booted" +#some modification to the xcatdsklspost, only download scripts +line_num=`sed -n -e '/postbootscripts-start-here.*postbootscripts-end-here.*run_ps/=' /opt/xcat/xcatdsklspost | tail -n 1` +line_num=`sed -n -e "$line_num,$ {/echo.*TMP.*>.*mypostscript/=}" /opt/xcat/xcatdsklspost | head -n 1` + +sed -n -e "1,${line_num}p" /opt/xcat/xcatdsklspost > /tmp/xcatsysclonepost +echo "cd /" >> /tmp/xcatsysclonepost +chmod +x /tmp/xcatsysclonepost +/tmp/xcatsysclonepost + +cd /xcatpost/ +#save the postboot scripts to /xcatpost/mypostscript.post +TMP=`sed "/postscripts-start-here/,/postscripts-end-here/ d" /xcatpost/mypostscript` +echo "$TMP" > /xcatpost/mypostscript.post +chmod 755 /xcatpost/mypostscript.post + +#create the post init +cp -f /xcatpost/xcatpostinit1 /etc/init.d/xcatpostinit1 +chmod 755 /etc/init.d/xcatpostinit1 +ln -s /etc/init.d/xcatpostinit1 /etc/rc.d/rc3.d/S84xcatpostinit1 +ln -s /etc/init.d/xcatpostinit1 /etc/rc.d/rc4.d/S84xcatpostinit1 +ln -s /etc/init.d/xcatpostinit1 /etc/rc.d/rc5.d/S84xcatpostinit1 + +cp -f /xcatpost/xcatinstallpost /opt/xcat/xcatinstallpost +cat >> /opt/xcat/xcatinstallpost << EOF +if [ -f /xcatpost/mypostscript.post ]; then + RUNBOOTSCRIPTS=`grep 'RUNBOOTSCRIPTS=' /xcatpost/mypostscript.post |cut -d= -f2` +fi +if [ "$RUNBOOTSCRIPTS" != "'yes'" ]; then + chkconfig xcatpostinit1 off +fi +EOF +chmod 755 /opt/xcat/xcatinstallpost + +ls /etc | grep -i suse +if [ $? -eq 0 ];then + /sbin/insserv -p /etc/init.d xcatpostinit1 fi +TMP=`sed "/postbootscripts-start-here/,/postbootscripts-end-here/ d" /xcatpost/mypostscript` +echo "$TMP" > /xcatpost/mypostscript + +chmod +x /xcatpost/mypostscript +/xcatpost/mypostscript + +TMP=`sed "/postscripts-start-here/,/postscripts-end-here/ d" /xcatpost/mypostscript` +echo "$TMP" > /tmp/xcatenv +. /tmp/xcatenv +/xcatpost/addsiteyum + +if [ -z "$NODESTATUS" ] || [ "$NODESTATUS" != "0" -a "$NODESTATUS" != "N" -a "$NODESTATUS" != "n" ]; then + /xcatpost/updateflag.awk $MASTER 3002 +fi From 52344f9997fe1768c2875afdfb1796b70796dd1d Mon Sep 17 00:00:00 2001 From: zhaoertao Date: Wed, 16 Oct 2013 23:49:51 -0700 Subject: [PATCH 16/91] fix bug 3835: 'rspconfig blade network=*' result need to be enhanced --- xCAT-server/lib/xcat/plugins/blade.pm | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/blade.pm b/xCAT-server/lib/xcat/plugins/blade.pm index b40d05fe5..4d4d8dc65 100644 --- a/xCAT-server/lib/xcat/plugins/blade.pm +++ b/xCAT-server/lib/xcat/plugins/blade.pm @@ -5308,6 +5308,11 @@ sub network { } else { return([1,"No changes specified"]); } + if (!$ip && !$host && !$gateway && !$mask) { + return([1, "No changes specified"]); + } elsif (!$ip) { + return([1, "No ip address specified"]); + } if ($ip) { $cmd.=" -i $ip"; } if ($host) { $cmd.=" -n $host"; } @@ -5330,10 +5335,10 @@ sub network { @result = (); } - if ($ip) { push @result,"IP: $ip"; } - if ($host) { push @result,"Hostname: $host"; } - if ($gateway){ push @result,"Gateway: $gateway"; } - if ($mask) { push @result,"Subnet Mask: $mask"; } + if ($mask) { unshift @result,"Subnet Mask: $mask"; } + if ($gateway){ unshift @result,"Gateway: $gateway"; } + if ($host) { unshift @result,"Hostname: $host"; } + if ($ip) { unshift @result,"IP: $ip"; } return([0,@result]); From 87db317493f16b9baeb8ee8eda838a080cffc923 Mon Sep 17 00:00:00 2001 From: xq2005 Date: Thu, 17 Oct 2013 02:21:02 -0700 Subject: [PATCH 17/91] add env parameters in runxcatpost --- xCAT/postscripts/runxcatpost | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/xCAT/postscripts/runxcatpost b/xCAT/postscripts/runxcatpost index 973425802..83284ca55 100644 --- a/xCAT/postscripts/runxcatpost +++ b/xCAT/postscripts/runxcatpost @@ -18,6 +18,15 @@ echo "cd /" >> /tmp/xcatsysclonepost chmod +x /tmp/xcatsysclonepost /tmp/xcatsysclonepost +if [ -x /usr/bin/openssl ]; then + USEOPENSSLFORXCAT=1 #Though this is the only method going forward, flag to allow backward compatibility with 2.2 generated netboot images + export USEOPENSSLFORXCAT +fi + +. /opt/xcat/xcatinfo +XCATSERVER="$XCATSERVER:3001" +export XCATSERVER + cd /xcatpost/ #save the postboot scripts to /xcatpost/mypostscript.post TMP=`sed "/postscripts-start-here/,/postscripts-end-here/ d" /xcatpost/mypostscript` @@ -50,6 +59,7 @@ fi TMP=`sed "/postbootscripts-start-here/,/postbootscripts-end-here/ d" /xcatpost/mypostscript` echo "$TMP" > /xcatpost/mypostscript + chmod +x /xcatpost/mypostscript /xcatpost/mypostscript From 6d00593449d43d037115e67276e251f80ca6a551 Mon Sep 17 00:00:00 2001 From: lissav Date: Thu, 17 Oct 2013 11:04:01 -0400 Subject: [PATCH 18/91] enhance error reporting --- xCAT-server/lib/xcat/plugins/credentials.pm | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/credentials.pm b/xCAT-server/lib/xcat/plugins/credentials.pm index 6b667b494..bc4f3c397 100644 --- a/xCAT-server/lib/xcat/plugins/credentials.pm +++ b/xCAT-server/lib/xcat/plugins/credentials.pm @@ -118,20 +118,23 @@ sub process_request if (/ssh_root_key/) { unless (-r "$root/.ssh/id_rsa") { push @{$rsp->{'error'}},"Unable to read root's private ssh key"; + `logger -t xCAT -p local4.info "credentials: Unable to read root's private ssh key"` ; next; } $tfilename = "$root/.ssh/id_rsa"; } elsif (/xcat_server_cred/) { unless (-r "/etc/xcat/cert/server-cred.pem") { - push @{$rsp->{'error'}},"Unable to read root's private xCAT key"; + push @{$rsp->{'error'}},"Unable to read xcat_server_cred"; + `logger -t xCAT -p local4.info "credentials: Unable to read xcat_server_cred"` ; next; } $tfilename = "/etc/xcat/cert/server-cred.pem"; } elsif (/xcat_client_cred/ or /xcat_root_cred/) { unless (-r "$root/.xcat/client-cred.pem") { - push @{$rsp->{'error'}},"Unable to read root's private xCAT key"; + push @{$rsp->{'error'}},"Unable to read xcat_client_cred or xcat_root_cred"; + `logger -t xCAT -p local4.info "credentials: Unable to read xcat_client_cred or xcat_root_cred"` ; next; } $tfilename = "$root/.xcat/client-cred.pem"; @@ -143,6 +146,7 @@ sub process_request $tfilename="/etc/xcat/hostkeys/ssh_host_dsa_key"; } else { push @{$rsp->{'error'}},"Unable to read private DSA key from /etc/xcat/hostkeys"; + `logger -t xCAT -p local4.info "credentials: Unable to read private DSA key"` ; next; } } elsif (/ssh_rsa_hostkey/) { @@ -152,11 +156,13 @@ sub process_request $tfilename="/etc/xcat/hostkeys/ssh_host_rsa_key"; } else { push @{$rsp->{'error'}},"Unable to read private RSA key from /etc/xcat/hostkeys"; + `logger -t xCAT -p local4.info "credentials: Unable to read private RSA key"` ; next; } } elsif (/xcat_cfgloc/) { unless (-r "/etc/xcat/cfgloc") { - push @{$rsp->{'error'}},"Unable to read xCAT database location"; + push @{$rsp->{'error'}},"Unable to read /etc/xcat/cfgloc "; + `logger -t xCAT -p local4.info "credentials: Unable to read /etc/xcat/cfgloc"` ; next; } $tfilename = "/etc/xcat/cfgloc"; From c05b7c9a662d4c5f05d1644030fc5a219a29527d Mon Sep 17 00:00:00 2001 From: lissav Date: Thu, 17 Oct 2013 11:46:12 -0400 Subject: [PATCH 19/91] additional flowcontrol error handling defect 3819 --- xCAT/postscripts/remoteshell | 109 ++++++++++++--------- xCAT/postscripts/xcatdsklspost | 18 ++-- xCAT/postscripts/xcatserver | 171 +++++++++++++++++++++++++++++---- 3 files changed, 226 insertions(+), 72 deletions(-) diff --git a/xCAT/postscripts/remoteshell b/xCAT/postscripts/remoteshell index 85ef54d71..c5813b827 100755 --- a/xCAT/postscripts/remoteshell +++ b/xCAT/postscripts/remoteshell @@ -1,6 +1,14 @@ #!/bin/sh # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html #(C)IBM Corp +# This script adds xCAT specific setup to the /etc/ssh/sshd_config and ssh_config file +# It calls getcredentials.awk to get from the xcatmaster ssh host keys from the +# /etc/xcat/hostkeys directory and puts in /etc/ssh on the node the following keys +# ssh_host_dsa_key,ssh_host_rsa_key +# It calls getcredentials.awk to get from the xcatmaster root ssh keys from the +# ~/.ssh directory on the xcatmaster and put in ~/.ssh on the node the following keys: +# If site.enablesshbetweennodes is yes +# id.rsa # # if on the Management Node, exit if [ -e /etc/xCATMN ]; then @@ -47,7 +55,7 @@ then fi fi -if [ -r /etc/ssh/sshd_config ] +if [ -r /etc/ssh/ssh_config ] then sed -i '/StrictHostKeyChecking /'d /etc/ssh/ssh_config echo "StrictHostKeyChecking no" >> /etc/ssh/ssh_config @@ -65,11 +73,6 @@ then chmod 600 /root/.ssh/* fi -#if [ -d /xcatpost/hostkeys ] -#then -# logger -t xcat "Install: using server provided host key for convenience." -# cp /xcatpost/hostkeys/*_key /etc/ssh/ -#fi if [ ! -x /usr/bin/openssl ]; then logger -t xcat -p local4.err "Install: /usr/bin/openssl is not executable." exit 0 @@ -78,27 +81,31 @@ allowcred.awk & CREDPID=$! sleep 1 - if [ $useflowcontrol = "1" ]; then #first contact daemon xcatflowrequest 3001 - logger -t xCAT -p local4.info "remoteshell: sending /$xcatpost/xcatflowrequest $master 3001" - /$xcatpost/xcatflowrequest $master 3001 + logger -t xCAT -p local4.info "remoteshell: sending xcatflowrequest $master 3001" + /$xcatpost/xcatflowrequest $master 3001 + rc=$? + logger -t xCAT -p local4.info "remoteshell:xcatflowrequest received response return=$rc" + if [ $rc -ne 0 ]; then + logger -t xCAT -p local4.info "remoteshell: error from xcatflowrequest, will not use flow control" + useflowcontrol=0 + fi + + fi getcredentials.awk ssh_dsa_hostkey | grep -E -v '|' | sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /tmp/ssh_dsa_hostkey -if [ $useflowcontrol = "1" ]; then - logger -t xCAT -p local4.info "remoteshell: received response /$xcatpost/xcatflowrequest $master 3001" -fi #check the message is an error or not grep -E '' /tmp/ssh_dsa_hostkey if [ $? -ne 0 ]; then #the message received is the data cat /tmp/ssh_dsa_hostkey | grep -E -v '||' >/etc/ssh/ssh_host_dsa_key - logger -t xCAT -p local4.info ssh_dsa_hostkey + logger -t xCAT -p local4.info "remoteshell: getting ssh_host_dsa_key" MAX_RETRIES=10 RETRY=0 - MYCONT=`cat /etc/ssh/ssh_host_dsa_key` - while [ -z "$MYCONT" ]; do + MYCONT=`cat /etc/ssh/ssh_host_dsa_key` + while [ -z "$MYCONT" ]; do # not using flow control , need to sleep if [ $useflowcontrol = "0" ]; then let SLI=$RANDOM%10 @@ -113,23 +120,26 @@ if [ $? -ne 0 ]; then fi if [ $useflowcontrol = "1" ]; then #first contact daemon xcatflowrequest 3001 - logger -t xCAT -p local4.info "remoteshell: sending /$xcatpost/xcatflowrequest $master 3001" + logger -t xCAT -p local4.info "remoteshell: sending xcatflowrequest $master 3001" /$xcatpost/xcatflowrequest $master 3001 + rc=$? + logger -t xCAT -p local4.info "remoteshell:xcatflowrequest return=$rc" + if [ $rc -ne 0 ]; then + logger -t xCAT -p local4.info "remoteshell: error from xcatflowrequest, will not use flow control" + useflowcontrol=0 + fi fi getcredentials.awk ssh_dsa_hostkey | grep -v '<'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /etc/ssh/ssh_host_dsa_key - if [ $useflowcontrol = "1" ]; then - logger -t xCAT -p local4.info "remoteshell: received response /$xcatpost/xcatflowrequest $master 3001" - fi MYCONT=`cat /etc/ssh/ssh_host_dsa_key` - done - chmod 600 /etc/ssh/ssh_host_dsa_key - if ! grep "PRIVATE KEY" /etc/ssh/ssh_host_dsa_key > /dev/null 2>&1 ; then - rm /etc/ssh/ssh_host_dsa_key + done + chmod 600 /etc/ssh/ssh_host_dsa_key + if ! grep "PRIVATE KEY" /etc/ssh/ssh_host_dsa_key > /dev/null 2>&1 ; then + rm /etc/ssh/ssh_host_dsa_key else ssh-keygen -y -f /etc/ssh/ssh_host_dsa_key > /etc/ssh/ssh_host_dsa_key.pub chmod 644 /etc/ssh/ssh_host_dsa_key.pub chown root /etc/ssh/ssh_host_dsa_key.pub - fi + fi else #the message received is an error, so parse it ERR_MSG=`sed -n 's%.*\(.*\).*%\1%p' /tmp/ssh_dsa_hostkey` @@ -137,17 +147,19 @@ else fi rm /tmp/ssh_dsa_hostkey -# first contact daemon xcatflowrequest 3001 if [ $useflowcontrol = "1" ]; then #first contact daemon xcatflowrequest 3001 - logger -t xCAT -p local4.info "remoteshell: sending /$xcatpost/xcatflowrequest $master 3001" + logger -t xCAT -p local4.info "remoteshell: sending xcatflowrequest $master 3001" /$xcatpost/xcatflowrequest $master 3001 + rc=$? + logger -t xCAT -p local4.info "remoteshell:xcatflowrequest return=$rc" + if [ $rc -ne 0 ]; then + logger -t xCAT -p local4.info "remoteshell: error from xcatflowrequest, will not use flow control" + useflowcontrol=0 + fi fi getcredentials.awk ssh_rsa_hostkey | grep -E -v '|' | sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /tmp/ssh_rsa_hostkey -if [ $useflowcontrol = "1" ]; then - logger -t xCAT -p local4.info "remoteshell: received response /$xcatpost/xcatflowrequest $master 3001" -fi #check whether the message is an error or not grep -E '' /tmp/ssh_rsa_hostkey if [ $? -ne 0 ]; then @@ -169,17 +181,19 @@ if [ $? -ne 0 ]; then then break fi - # first contact daemon xcatflowrequest 3001 if [ $useflowcontrol = "1" ]; then #first contact daemon xcatflowrequest 3001 - logger -t xCAT -p local4.info "remoteshell: sending /$xcatpost/xcatflowrequest $master 3001" + logger -t xCAT -p local4.info "remoteshell: sending xcatflowrequest $master 3001" /$xcatpost/xcatflowrequest $master 3001 + rc=$? + logger -t xCAT -p local4.info "remoteshell:xcatflowrequest return=$rc" + if [ $rc -ne 0 ]; then + logger -t xCAT -p local4.info "remoteshell: error from xcatflowrequest, will not use flow control" + useflowcontrol=0 + fi fi getcredentials.awk ssh_rsa_hostkey | grep -v '<'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /etc/ssh/ssh_host_rsa_key - if [ $useflowcontrol = "1" ]; then - logger -t xCAT -p local4.info "remoteshell: received response /$xcatpost/xcatflowrequest $master 3001" - fi MYCONT=`cat /etc/ssh/ssh_host_rsa_key` done chmod 600 /etc/ssh/ssh_host_rsa_key @@ -206,20 +220,21 @@ fi umask 0077 mkdir -p /root/.ssh/ -sleep 1 -if [ $ENABLESSHBETWEENNODES = "YES" ]; +if [ $ENABLESSHBETWEENNODES = "YES" ]; # want nodes to be able to ssh to each other without password then - #first contact daemon xcatflowrequest 3001 if [ $useflowcontrol = "1" ]; then #first contact daemon xcatflowrequest 3001 - logger -t xCAT -p local4.info "remoteshell: sending /$xcatpost/xcatflowrequest $master 3001" + logger -t xCAT -p local4.info "remoteshell: sending xcatflowrequest $master 3001" /$xcatpost/xcatflowrequest $master 3001 + rc=$? + logger -t xCAT -p local4.info "remoteshell:xcatflowrequest return=$rc" + if [ $rc -ne 0 ]; then + logger -t xCAT -p local4.info "remoteshell: error from xcatflowrequest, will not use flow control" + useflowcontrol=0 + fi fi getcredentials.awk ssh_root_key | grep -E -v '|'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /tmp/ssh_root_key - if [ $useflowcontrol = "1" ]; then - logger -t xCAT -p local4.info "remoteshell: received response /$xcatpost/xcatflowrequest $master 3001" - fi #check whether the message is an error or not grep -E '' /tmp/ssh_root_key if [ $? -ne 0 ]; then @@ -240,16 +255,18 @@ then then break fi - # first contact daemon xcatflowrequest 3001 if [ $useflowcontrol = "1" ]; then #first contact daemon xcatflowrequest 3001 - logger -t xCAT -p local4.info "remoteshell: sending /$xcatpost/xcatflowrequest $master 3001" + logger -t xCAT -p local4.info "remoteshell: sending xcatflowrequest $master 3001" /$xcatpost/xcatflowrequest $master 3001 + rc=$? + logger -t xCAT -p local4.info "remoteshell:xcatflowrequest return=$rc" + if [ $rc -ne 0 ]; then + logger -t xCAT -p local4.info "remoteshell: error from xcatflowrequest, will not use flow control" + useflowcontrol=0 + fi fi getcredentials.awk ssh_root_key | grep -v '<'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /root/.ssh/id_rsa - if [ $useflowcontrol = "1" ]; then - logger -t xCAT -p local4.info "remoteshell: received response /$xcatpost/xcatflowrequest $master 3001" - fi MYCONT=`cat /root/.ssh/id_rsa` done else diff --git a/xCAT/postscripts/xcatdsklspost b/xCAT/postscripts/xcatdsklspost index 19e031cd7..75dd32a9b 100755 --- a/xCAT/postscripts/xcatdsklspost +++ b/xCAT/postscripts/xcatdsklspost @@ -497,12 +497,15 @@ if [ ! -x /$xcatpost/mypostscript ]; then # first contact daemon xcatflowrequest 3001 logger -t xCAT -p local4.info "xcatdsklspost:sending xcatflowrequest $SIP 3001" /$xcatpost/xcatflowrequest $SIP 3001 + rc=$? + logger -t xCAT -p local4.info "xcatdsklspost:xcatflowrequest return=$rc" + if [ $rc -ne 0 ]; then + logger -t xCAT -p local4.info "xcatdsklspost: error from xcatflowrequest, will not use flow control" + useflowcontrol=0 + fi fi /$xcatpost/getpostscript.awk | egrep '' | sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' > /$xcatpost/mypostscript; - if [ $useflowcontrol = "1" ]; then - logger -t xCAT -p local4.info "xcatdsklspost: received response /$xcatpost/xcatflowrequest $master 3001" - fi MYCONT=`grep MASTER /$xcatpost/mypostscript` MAX_RETRIES=10 @@ -525,11 +528,14 @@ if [ ! -x /$xcatpost/mypostscript ]; then # contact daemon xcatflowrequest 3001 logger -t xCAT -p local4.info "xcatdsklspost: sending xcatflowrequest $SIP 3001" /$xcatpost/xcatflowrequest $SIP 3001 + rc=$? + logger -t xCAT -p local4.info "xcatdsklspost:xcatflowrequest return=$rc" + if [ $rc -ne 0 ]; then + logger -t xCAT -p local4.info "xcatdsklspost: error from xcatflowrequest, will not use flow control" + useflowcontrol=0 + fi fi /$xcatpost/getpostscript.awk | sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' > /$xcatpost/mypostscript; - if [ $useflowcontrol = "1" ]; then - logger -t xCAT -p local4.info "xcatdsklspost: received response /$xcatpost/xcatflowrequest $master 3001" - fi MYCONT=`grep MASTER /$xcatpost/mypostscript` if [ ! -z "$MYCONT" ]; then break; diff --git a/xCAT/postscripts/xcatserver b/xCAT/postscripts/xcatserver index 8dca02e45..8b698ae8a 100755 --- a/xCAT/postscripts/xcatserver +++ b/xCAT/postscripts/xcatserver @@ -29,26 +29,157 @@ if [ ! -x /usr/bin/openssl ]; then fi USEOPENSSLFORXCAT=1 export USEOPENSSLFORXCAT - allowcred.awk & - CREDPID=$! - sleep 1 - mkdir -p /etc/xcat/cert - getcredentials.awk xcat_server_cred | grep -v '<'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /etc/xcat/cert/server-cred.pem +# are we using xcat flow control +useflowcontrol=0 +if [ $USEFLOWCONTROL = "YES" ] || [ $USEFLOWCONTROL = "yes" ] || [ $USEFLOWCONTROL = "1" ]; then + useflowcontrol=1 +fi + +xcatpost="xcatpost" +master=$MASTER + +allowcred.awk & +CREDPID=$! +sleep 1 + +# setup and get the xCAT SSL credentials down to the service node +# create SSL certificate directory and then get them +mkdir -p /etc/xcat/cert +if [ $useflowcontrol = "1" ]; then + #first contact daemon xcatflowrequest 3001 + logger -t xCAT -p local4.info "xcatserver: sending xcatflowrequest $master 3001" + /$xcatpost/xcatflowrequest $master 3001 + rc=$? + logger -t xCAT -p local4.info "xcatserver:xcatflowrequest received response return=$rc" + if [ $rc -ne 0 ]; then + logger -t xCAT -p local4.info "xcatserver: error from xcatflowrequest, will not use flow control" + useflowcontrol=0 + fi + + +fi +getcredentials.awk xcat_server_cred | grep -v '<'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /etc/xcat/cert/server-cred.pem + +#check the message is an error or not +grep -E '' /etc/xcat/cert/server-cred.pem +if [ $? -ne 0 ]; then + #the message received is the data + logger -t xCAT -p local4.info "xcatserver: getting server-cred.pem" + MAX_RETRIES=10 + RETRY=0 + MYCONT=`cat /etc/xcat/cert/server-cred.pem` + + while [ -z "$MYCONT" ]; do + # not using flow control , need to sleep + if [ $useflowcontrol = "0" ]; then + let SLI=$RANDOM%10 + let SLI=SLI+10 + sleep $SLI + fi + + RETRY=$(($RETRY+1)) + if [ $RETRY -eq $MAX_RETRIES ] + then + break + fi + if [ $useflowcontrol = "1" ]; then + #first contact daemon xcatflowrequest 3001 + logger -t xCAT -p local4.info "xcatserver: sending xcatflowrequest $master 3001" + /$xcatpost/xcatflowrequest $master 3001 + rc=$? + logger -t xCAT -p local4.info "xcatserver:xcatflowrequest return=$rc" + if [ $rc -ne 0 ]; then + logger -t xCAT -p local4.info "xcatserver: error from xcatflowrequest, will not use flow control" + useflowcontrol=0 + fi + fi + getcredentials.awk xcat_server_cred | grep -v '<'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /etc/xcat/cert/server-cred.pem + MYCONT=`cat /etc/xcat/cert/server-cred.pem` + done + chmod 600 /etc/xcat/cert/* - getcredentials.awk xcat_cfgloc | grep -v '<'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /etc/xcat/cfgloc - # if not DB2 - grep "DB2" /etc/xcat/cfgloc 2>&1 1> /dev/null - if [ $? -ne 0 ]; then - sed s/host=[^\|]*/host=$MASTER/ /etc/xcat/cfgloc > /etc/xcat/cfgloc.new - mv /etc/xcat/cfgloc.new /etc/xcat/cfgloc - else - if [ -n "$UPDATENODE" ] && [ $UPDATENODE -eq 1 ]; then - cp /etc/xcat/cfgloc /etc/xcat/cfgloc.db2 - else - mv /etc/xcat/cfgloc /etc/xcat/cfgloc.db2 - fi - fi - chmod 600 /etc/xcat/cfgloc* # do not assume working directory, use the full path cp /xcatpost/_xcat/ca.pem /etc/xcat/cert/ca.pem - kill -9 $CREDPID +else # error from first getcredential call + #the message received is an error from credentials.pm, so parse it + ERR_MSG=`sed -n 's%.*\(.*\).*%\1%p' /etc/xcat/cert/server-cred.pem` + logger -t xCAT -p local4.err xcatserver: $ERR_MSG + rm /etc/xcat/cert/server-cred.pem +fi + +# get the xcat cfgloc file + +if [ $useflowcontrol = "1" ]; then + #first contact daemon xcatflowrequest 3001 + logger -t xCAT -p local4.info "xcatserver: sending xcatflowrequest $master 3001" + /$xcatpost/xcatflowrequest $master 3001 + rc=$? + logger -t xCAT -p local4.info "xcatserver:xcatflowrequest received response return=$rc" + if [ $rc -ne 0 ]; then + logger -t xCAT -p local4.info "xcatserver: error from xcatflowrequest, will not use flow control" + useflowcontrol=0 + fi + +fi +getcredentials.awk xcat_cfgloc | grep -v '<'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /etc/xcat/cfgloc + +#check the message is an error or not +grep -E '' /etc/xcat/cfgloc +if [ $? -ne 0 ]; then + #the message received is the data + logger -t xCAT -p local4.info "xcatserver: getting cfgloc" + MAX_RETRIES=10 + RETRY=0 + MYCONT=`cat /etc/xcat/cfgloc` + + while [ -z "$MYCONT" ]; do + # not using flow control , need to sleep + if [ $useflowcontrol = "0" ]; then + let SLI=$RANDOM%10 + let SLI=SLI+10 + sleep $SLI + fi + + RETRY=$(($RETRY+1)) + if [ $RETRY -eq $MAX_RETRIES ] + then + break + fi + if [ $useflowcontrol = "1" ]; then + #first contact daemon xcatflowrequest 3001 + logger -t xCAT -p local4.info "xcatserver: sending xcatflowrequest $master 3001" + /$xcatpost/xcatflowrequest $master 3001 + rc=$? + logger -t xCAT -p local4.info "xcatserver:xcatflowrequest return=$rc" + if [ $rc -ne 0 ]; then + logger -t xCAT -p local4.info "xcatserver: error from xcatflowrequest, will not use flow control" + useflowcontrol=0 + fi + fi + getcredentials.awk xcat_cfgloc | grep -v '<'|sed -e 's/<//' -e 's/&/&/' -e 's/"/"/' -e "s/'/'/" > /etc/xcat/cfgloc + MYCONT=`cat /etc/xcat/cfgloc` + done + # if we successfully got cfgloc + if [ -f /etc/xcat/cfgloc ]; then + # if not DB2 + grep "DB2" /etc/xcat/cfgloc 2>&1 1> /dev/null + if [ $? -ne 0 ]; then + sed s/host=[^\|]*/host=$MASTER/ /etc/xcat/cfgloc > /etc/xcat/cfgloc.new + mv /etc/xcat/cfgloc.new /etc/xcat/cfgloc + else # DB2 cfgloc has different format + if [ -n "$UPDATENODE" ] && [ $UPDATENODE -eq 1 ]; then + cp /etc/xcat/cfgloc /etc/xcat/cfgloc.db2 + else + mv /etc/xcat/cfgloc /etc/xcat/cfgloc.db2 + fi + fi + chmod 600 /etc/xcat/cfgloc* + fi +else # error from first getcredentials call + #the message received is an error from credentials.pm, so parse it + ERR_MSG=`sed -n 's%.*\(.*\).*%\1%p' /etc/xcat/cfgloc` + logger -t xCAT -p local4.err xcatserver: $ERR_MSG + rm /etc/xcat/cfgloc +fi + +kill -9 $CREDPID From 899be1a70d8d5583c68684f768ff106b1d76471d Mon Sep 17 00:00:00 2001 From: nott Date: Thu, 17 Oct 2013 15:02:18 -0400 Subject: [PATCH 20/91] add -F option to lskit --- xCAT-server/lib/xcat/plugins/kit.pm | 108 ++++++++++++++++++++++++++-- 1 file changed, 103 insertions(+), 5 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/kit.pm b/xCAT-server/lib/xcat/plugins/kit.pm index 4c0245dd7..40d6e92d9 100644 --- a/xCAT-server/lib/xcat/plugins/kit.pm +++ b/xCAT-server/lib/xcat/plugins/kit.pm @@ -20,6 +20,7 @@ use Getopt::Long; #use Data::Dumper; use File::Basename; use File::Path; +use Cwd; my $kitconf = "kit.conf"; @@ -3402,10 +3403,10 @@ sub lskit_usage { push @{ $rsp->{data} }, "\nUsage: lskit - List infomation for one or more kits.\n"; push @{ $rsp->{data} }, - " lskit [-V|--verbose] [-x|--xml|--XML] [-K|--kitattr kitattr_names] [-R|--repoattr repoattr_names] [-C|--compattr compattr_names] [kit_names]\n "; - push @{ $rsp->{data} }, " lskit [-h|--help|-?] \n"; - push @{ $rsp->{data} }, - " lskit [-v|--version] \n "; + "\tlskit [-V|--verbose] [-x|--xml|--XML] [-K|--kitattr kitattr_names]\n\t[-R|--repoattr repoattr_names] [-C|--compattr compattr_names]\n\t[kit_names]\n "; + push @{ $rsp->{data} }, "\tlskit [-h|--help|-?]\n"; + push @{ $rsp->{data} }, "\tlskit [-v|--version]\n "; + push @{ $rsp->{data} }, "\tlskit [-F|--framework] kit_path_name\n "; xCAT::MsgUtils->message( "I", $rsp, $::CALLBACK ); return 0; } @@ -3514,6 +3515,7 @@ sub lskit_processargs { 'kitattr|K=s' => \$::opt_K, 'repoattr|R=s' => \$::opt_R, 'compattr|C=s' => \$::opt_C, + 'framework|F=s' => \$::opt_F, 'verbose|V' => \$::opt_V, 'version|v' => \$::opt_v, 'xml|XML|x' => \$::opt_x, @@ -3912,9 +3914,12 @@ sub check_attr_values_exist { =cut #----------------------------------------------------------------------------- - sub lskit { + my $request = shift; + my $callback = shift; + my $request_command = shift; + my $rc = 0; # process the command line @@ -3935,6 +3940,99 @@ sub lskit { return 1; } + if ( defined($::opt_F) ) { + if ( defined($::opt_x) || defined($::opt_K) || defined($::opt_R) || defined($::opt_C) ) { + my $rsp = {}; + push @{ $rsp->{data}}, "\nThe \'-F\' option cannot be used with the x, R, K, or C options.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + lskit_usage(1); + return 1; + } + my $tarpathname = $::opt_F; + + # check if full path + my $dir = $request->{cwd}; #getcwd; + my $cwd = $dir->[0]; + + if ($tarpathname !~ /^\//) + { + my $fullpath = xCAT::Utils->full_path($tarpathname, $cwd); + if ($fullpath) + { + $tarpathname = $fullpath; + } + } + + unless (-e $tarpathname) { + my $rsp = {}; + push @{ $rsp->{data} }, "Could not find $tarpathname.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return 1; + } + # create a unique /tmp dir name name + my $thisdate = `/bin/date +%s`; + my $tmp_dir_name = qq~/tmp/tmp_kit_$thisdate~; + $tmp_dir_name =~ s/\s*//g; #remove blanks + + # extract the kit.conf file + my $rsp = {}; + push @{ $rsp->{data} }, "\nExtracting the kit.conf file from $tarpathname. Please wait.\n"; + xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); + + my $tcmd = qq~/bin/mkdir -p $tmp_dir_name;/bin/tar -C $tmp_dir_name -jxvf $tarpathname --wildcards */kit.conf~; + my $kitconffile = xCAT::Utils->runcmd("$tcmd", -1); + if ($::RUNCMD_RC != 0) { + my $rsp = {}; + push @{ $rsp->{data} }, "No kit.conf file was found.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return 1; + } + + # get the framework from the file + my $fcmd = "/bin/cat $tmp_dir_name/$kitconffile | grep 'kitframework '"; + my $fline = xCAT::Utils->runcmd("$fcmd", -1); + if ($::RUNCMD_RC != 0) { + my $rsp = {}; + push @{ $rsp->{data} }, "No kitframework value was found.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return 1; + } + my ($junk, $kitframework) = split(/=/, $fline); + $kitframework =~ s/\s*//g; #remove blanks + + my $cfcmd = "/bin/cat $tmp_dir_name/$kitconffile | grep 'compatible_kitframeworks'"; + my $cfline = xCAT::Utils->runcmd("$cfcmd", -1); + if ($::RUNCMD_RC != 0) { + my $rsp = {}; + push @{ $rsp->{data} }, "No compatible_kitframeworks value was found.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return 1; + } + my ($junk, $compatframework) = split(/=/, $cfline); + $compatframework =~ s/\s*//g; #remove blanks + + my $rcmd = qq~/bin/rm -Rf $tmp_dir_name 2>/dev/null~; + my $out = xCAT::Utils->runcmd("$rcmd", -1); + if ($::RUNCMD_RC != 0) { + my $rsp = {}; + push @{ $rsp->{data} }, "Could not remove $tmp_dir_name.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + } + + if ($kitframework && $compatframework) { + my $rsp = {}; + push @{ $rsp->{data} }, "\tkitframework=$kitframework\n\tcompatible_kitframeworks=$compatframework\n"; + xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); + return 0; + } else { + my $rsp = {}; + push @{ $rsp->{data} }, "Could not determine framework values for Kit $tarpathname.\n"; + xCAT::MsgUtils->message("E", $rsp, $::CALLBACK); + return 1; + } + return 0; + } + # Prepare the hash tables to pass to the output routines my $kit_hash = get_kit_hash($::kitnames, $::kitattrs); my $kitrepo_hash = get_kitrepo_hash($::kitnames, $::kitrepoattrs); From 6bdf5bfc3f400467b5203182635eaca38d0affbd Mon Sep 17 00:00:00 2001 From: nott Date: Thu, 17 Oct 2013 15:18:07 -0400 Subject: [PATCH 21/91] add -F option to lskit man --- xCAT-client/pods/man1/lskit.1.pod | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/xCAT-client/pods/man1/lskit.1.pod b/xCAT-client/pods/man1/lskit.1.pod index 63249786f..521252cdc 100644 --- a/xCAT-client/pods/man1/lskit.1.pod +++ b/xCAT-client/pods/man1/lskit.1.pod @@ -6,6 +6,7 @@ B - Lists information for one or more Kits. =head1 SYNOPSIS B [B<-V> | B<--verbose>] + [B<-F> | B<--framework> I] [B<-x> | B<--xml> | B<--XML>] [B<-K> | B<--kitattr> I] [B<-R> | B<--repoattr> I] @@ -14,6 +15,8 @@ B [B<-V> | B<--verbose>] B [B<-?> | B<-h> | B<--help> | B<-v> | B<--version>] +B [B<-F> | B<--framework> I] + =head1 DESCRIPTION @@ -29,6 +32,10 @@ Input to the command can specify any number or combination of the input options. =over 10 +=item B<-F|--framework> I + +Use this option to display the framework values of the specified Kit tarfile. This information is retreived directly from the tarfile and can be done before the Kit has been defined in the xCAT database. This option cannot be combined with other options. + =item B<-K|--kitattr> I Where I is a comma-delimited list of kit attribute names. The names correspond to attribute names in the B table. The B command will only display the specified kit attributes. @@ -138,6 +145,17 @@ To list the kit "kit-test1-1.0-Linux" for selected attributes, enter: lskit -K basename,description -R kitreponame -C kitcompname kit-test1-1.0-Linux +=item 4. + +To list the framework value of a Kit tarfile. + + lskit -F /myhome/mykits/pperte-1.3.0.2-0-x86_64.tar.bz2 + + Extracting the kit.conf file from /myhome/mykits/pperte-1.3.0.2-0-x86_64.tar.bz2. Please wait. + + kitframework=2 + compatible_kitframeworks=0,1,2 + =back From e5d8576cfd596b1fcfff11a1ba86261a8165d143 Mon Sep 17 00:00:00 2001 From: ligc Date: Fri, 18 Oct 2013 15:53:10 +0800 Subject: [PATCH 22/91] Update Clouds table for xCAT-OpenStack --- xCAT-OpenStack/lib/perl/xCAT_schema/Clouds.pm | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) mode change 100644 => 100755 xCAT-OpenStack/lib/perl/xCAT_schema/Clouds.pm diff --git a/xCAT-OpenStack/lib/perl/xCAT_schema/Clouds.pm b/xCAT-OpenStack/lib/perl/xCAT_schema/Clouds.pm old mode 100644 new mode 100755 index 9ab878a44..b14cc0212 --- a/xCAT-OpenStack/lib/perl/xCAT_schema/Clouds.pm +++ b/xCAT-OpenStack/lib/perl/xCAT_schema/Clouds.pm @@ -8,19 +8,19 @@ package xCAT_schema::Clouds; ################################################################################ %tabspec = ( clouds => { - cols => [qw(name controller publicnet novanet mgtnet vmnet adminpw dbpwcomments disable)], #do not change 'disable' and 'comments', it is required by xCAT + cols => [qw(name controller hostip pubinterface mgtinterface datainterface template repository virttype comments disable)], #do not change 'disable' and 'comments', it is required by xCAT keys => [qw(name)], required => [qw(name)], table_desc => 'OpenStack clouds managed by this xCAT cluster', descriptions => { - name => 'The name of this cloud', controller => 'The xCAT node name of the controller node', - publicnet => 'The name of the network in the xCAT networks table to be used for the OpenStack public network', - novanet => 'The name of the network in the xCAT networks table to be used for the OpenStack Nova network', - mgtnet => 'The name of the network in the xCAT networks table to be used for the OpenStack management network', - vmnet => 'The name of the network in the xCAT networks table to be used for the OpenStack virtual machine network', - adminpw => 'The administrative password', - dbpw => 'The database password', + hostip => 'The host IP is in openstack management network on the controller node. It is always the rabbitmq host IP and nova_metadata_ip.', + pubinterface => 'Interface to use for external bridge. The default value is eth1.', + mgtinterface => 'Interface to use for openstack management. It is supposed that the mgtinterface for all the nodes are the same, and in the same network.', + datainterface => 'Interface to use for OpenStack nova vm communication. It is supposed that the datainterface for all the nodes are the same, and in the same network.', + template => 'Every cloud should be related to one environment template file. The absolute path is required.', + repository => 'Every could should be related to the openstack-chef-cookbooks. The absolute path is required. In the repository, there are cookbooks, environments, roles and on on.', + virttype => 'What hypervisor software layer to use with libvirt (e.g., kvm, qemu).', comments => 'Any user-written notes.', disable => "Set to 'yes' or '1' to comment out this row.", }, @@ -60,37 +60,41 @@ package xCAT_schema::Clouds; @{$defspec{cloud}->{'attrs'}} = ( { attr_name => 'name', - tabentry => 'clouds.name', - access_tabentry => 'clouds.name=attr:name', + tabentry => 'clouds.name', + access_tabentry => 'clouds.name=attr:name', }, { attr_name => 'controller', tabentry => 'clouds.controller', access_tabentry => 'clouds.name=attr:name', }, - { attr_name => 'publicnet', - tabentry => 'clouds.publicnet', + { attr_name => 'hostip', + tabentry => 'clouds.hostip', access_tabentry => 'clouds.name=attr:name', }, - { attr_name => 'novanet', - tabentry => 'clouds.novanet', + { attr_name => 'pubinterface', + tabentry => 'clouds.pubinterface', access_tabentry => 'clouds.name=attr:name', }, - { attr_name => 'mgtnet', - tabentry => 'clouds.mgtnet', + { attr_name => 'mgtinterface', + tabentry => 'clouds.mgtinterface', access_tabentry => 'clouds.name=attr:name', }, - { attr_name => 'vmnet', - tabentry => 'clouds.vmnet', + { attr_name => 'datainterface', + tabentry => 'clouds.datainterface', access_tabentry => 'clouds.name=attr:name', }, - { attr_name => 'adminpw', - tabentry => 'clouds.adminpw', + { attr_name => 'template', + tabentry => 'clouds.template', access_tabentry => 'clouds.name=attr:name', }, - { attr_name => 'dbpw', - tabentry => 'clouds.dbpw', + { attr_name => 'repository', + tabentry => 'clouds.repository', access_tabentry => 'clouds.name=attr:name', }, + { attr_name => 'virttype', + tabentry => 'clouds.virttype', + access_tabentry => 'clouds.name=attr:name', + } ); # node attributes for clouds From c30f46cc805b4a827e4451e19e63a51b84129255 Mon Sep 17 00:00:00 2001 From: ligc Date: Fri, 18 Oct 2013 15:58:18 +0800 Subject: [PATCH 23/91] fix for bug 3841: syntax error in remoteshell postscript --- xCAT/postscripts/remoteshell | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT/postscripts/remoteshell b/xCAT/postscripts/remoteshell index c5813b827..ea7492a16 100755 --- a/xCAT/postscripts/remoteshell +++ b/xCAT/postscripts/remoteshell @@ -32,7 +32,7 @@ fi master=$MASTER # are we using xcat flow control useflowcontrol=0 -if [ $USEFLOWCONTROL = "YES" ] || [ $USEFLOWCONTROL = "yes" ] || [ $USEFLOWCONTROL = "1" ]; then +if [ "$USEFLOWCONTROL" = "YES" ] || [ "$USEFLOWCONTROL" = "yes" ] || [ "$USEFLOWCONTROL" = "1" ]; then useflowcontrol=1 fi From 4fcf3a96e62247ce5268978736c0fb08788c64bb Mon Sep 17 00:00:00 2001 From: immarvin Date: Fri, 18 Oct 2013 01:58:05 -0700 Subject: [PATCH 24/91] fix defect #3370 Create osimage definition for the Management Node --- xCAT-server/lib/perl/xCAT/SvrUtils.pm | 42 +++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/xCAT-server/lib/perl/xCAT/SvrUtils.pm b/xCAT-server/lib/perl/xCAT/SvrUtils.pm index d25cc5dbc..648d765a0 100644 --- a/xCAT-server/lib/perl/xCAT/SvrUtils.pm +++ b/xCAT-server/lib/perl/xCAT/SvrUtils.pm @@ -8,6 +8,7 @@ BEGIN } use lib "$::XCATROOT/lib/perl"; require xCAT::Table; +require xCAT::NodeRange; require xCAT::Utils; require xCAT::TableUtils; require xCAT::NetworkUtils; @@ -764,6 +765,14 @@ sub update_tables_with_mgt_image return (1, "Unable to find $::XCATROOT/share/xcat/install directory for $osver"); } } + + #if the arch of osimage does not match the arch of MN,return + my $myarch=qx(uname -i); + chop $myarch; + if($arch ne $myarch){ + return 0; + } + #for rhels5.1 genos=rhel5 my $genos = $osver; @@ -772,10 +781,10 @@ sub update_tables_with_mgt_image $genos = "rhel$1"; } - + #if the osver does not match the osver of MN, return my $myosver = xCAT::Utils->osver("all"); $myosver =~ s/,//; - if ( $osver != $myosver ) { + if ( $osver ne $myosver ) { return 0; } @@ -812,6 +821,7 @@ sub update_tables_with_mgt_image #update the osimage and linuximage table my $osimagetab; my $linuximagetab; + my $imagename=$osver . "-" . $arch . "-stateful" . "-mgmtnode"; foreach my $profile (keys %profiles) { #print "profile=$profile\n"; #get template file @@ -835,6 +845,7 @@ sub update_tables_with_mgt_image $osimagetab=xCAT::Table->new('osimage',-create=>1); } + if ($osimagetab) { #check if the image is already in the table if ($osimagetab) { @@ -850,7 +861,7 @@ sub update_tables_with_mgt_image } # if ($found) { next; } - my $imagename=$osver . "-" . $arch . "-mgmtimage"; + #TODO: check if there happen to be a row that has the same imagename but with different contents #now we can wirte the info into db my %key_col = (imagename=>$imagename); @@ -886,6 +897,31 @@ sub update_tables_with_mgt_image } if ($osimagetab) { $osimagetab->close(); } if ($linuximagetab) { $linuximagetab->close(); } + + #set nodetype.provmethod to the new created osimage if it is not set + my @mgtnodes=xCAT::NodeRange::noderange('__mgmtnode'); + if(scalar @mgtnodes){ + my $nttab=xCAT::Table->new('nodetype', -create=>1); + unless($nttab){ + return(1, "Cannot open the nodetype table."); + } + + my $ntents=$nttab->getNodesAttribs(\@mgtnodes, ['provmethod']); + my %ent; + foreach my $node (@mgtnodes){ + print "$node\n"; + unless($ntents->{$node} and $ntents->{$node}->['provmethod']){ + $ent{$node}{'provmethod'}=$imagename; + } + } + + $nttab->setNodesAttribs(\%ent); + + + if($nttab){ $nttab->close(); } + } + + return (0, ""); } From 059a4fd6f6e2a1ce1ef4064d5ba8b39b4a5f1dd9 Mon Sep 17 00:00:00 2001 From: lissav Date: Fri, 18 Oct 2013 07:24:00 -0400 Subject: [PATCH 25/91] defect 3841 --- xCAT/postscripts/xcatserver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT/postscripts/xcatserver b/xCAT/postscripts/xcatserver index 8b698ae8a..b4886e412 100755 --- a/xCAT/postscripts/xcatserver +++ b/xCAT/postscripts/xcatserver @@ -31,7 +31,7 @@ USEOPENSSLFORXCAT=1 export USEOPENSSLFORXCAT # are we using xcat flow control useflowcontrol=0 -if [ $USEFLOWCONTROL = "YES" ] || [ $USEFLOWCONTROL = "yes" ] || [ $USEFLOWCONTROL = "1" ]; then +if [ "$USEFLOWCONTROL" = "YES" ] || [ "$USEFLOWCONTROL" = "yes" ] || [ "$USEFLOWCONTROL" = "1" ]; then useflowcontrol=1 fi From e1c55be4fff5ac5943c0e4779b6715798991c49a Mon Sep 17 00:00:00 2001 From: lissav Date: Fri, 18 Oct 2013 07:50:22 -0400 Subject: [PATCH 26/91] defect 3844 --- xCAT-server/lib/xcat/plugins/destiny.pm | 4 ++-- xCAT-server/lib/xcat/plugins/nodediscover.pm | 4 ++-- xCAT-server/lib/xcat/plugins/pxe.pm | 16 ++++++++-------- xCAT-server/lib/xcat/plugins/vsmppxe.pm | 6 +++--- xCAT-server/lib/xcat/plugins/yaboot.pm | 10 +++++----- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/destiny.pm b/xCAT-server/lib/xcat/plugins/destiny.pm index 538cda78b..a29818908 100644 --- a/xCAT-server/lib/xcat/plugins/destiny.pm +++ b/xCAT-server/lib/xcat/plugins/destiny.pm @@ -553,12 +553,12 @@ sub nextdestiny { my $chainents = $chaintab->getNodesAttribs(\@nodes,[qw(currstate currchain chain)]); foreach $node (@nodes) { unless($chaintab) { - syslog("local1|err","ERROR: $node requested destiny update, no chain table"); + syslog("local4|err","ERROR: $node requested destiny update, no chain table"); return; #nothing to do... } my $ref = $chainents->{$node}->[0]; #$chaintab->getNodeAttribs($node,[qw(currstate currchain chain)]); unless ($ref->{chain} or $ref->{currchain}) { - syslog ("local1|err","ERROR: node requested destiny update, no path in chain.currchain"); + syslog ("local4|err","ERROR: node requested destiny update, no path in chain.currchain"); return; #Can't possibly do anything intelligent.. } unless ($ref->{currchain}) { #If no current chain, copy the default diff --git a/xCAT-server/lib/xcat/plugins/nodediscover.pm b/xCAT-server/lib/xcat/plugins/nodediscover.pm index bd828f8c8..34724164b 100644 --- a/xCAT-server/lib/xcat/plugins/nodediscover.pm +++ b/xCAT-server/lib/xcat/plugins/nodediscover.pm @@ -342,7 +342,7 @@ sub process_request { Timeout => '1', Proto => 'tcp' ); - unless ($sock) { syslog("err","Failed to notify $clientip that it's actually $node."); return; } #Give up if the node won't hear of it. + unless ($sock) { syslog("local4|err","Failed to notify $clientip that it's actually $node."); return; } #Give up if the node won't hear of it. print $sock $restartstring; close($sock); @@ -352,7 +352,7 @@ sub process_request { #Update the discoverydata table to indicate the successful discovery xCAT::DiscoveryUtils->update_discovery_data($request); - syslog("info","$node has been discovered"); + syslog("local4|info","$node has been discovered"); } 1; diff --git a/xCAT-server/lib/xcat/plugins/pxe.pm b/xCAT-server/lib/xcat/plugins/pxe.pm index 1247b76ec..23aa71ec4 100644 --- a/xCAT-server/lib/xcat/plugins/pxe.pm +++ b/xCAT-server/lib/xcat/plugins/pxe.pm @@ -205,7 +205,7 @@ sub setstate { close($pcfg); my $inetn = inet_aton($node); unless ($inetn) { - syslog("local1|err","xCAT unable to resolve IP for $node in pxe plugin"); + syslog("local4|err","xCAT unable to resolve IP for $node in pxe plugin"); return; } } else { #TODO: actually, should possibly default to xCAT image? @@ -215,12 +215,12 @@ sub setstate { my $mactab = xCAT::Table->new('mac'); #to get all the hostnames my %ipaddrs; unless (inet_aton($node)) { - syslog("local1|err","xCAT unable to resolve IP in pxe plugin"); + syslog("local4|err","xCAT unable to resolve IP in pxe plugin"); return; } my $ip = inet_ntoa(inet_aton($node));; unless ($ip) { - syslog("local1|err","xCAT unable to resolve IP in pxe plugin"); + syslog("local4|err","xCAT unable to resolve IP in pxe plugin"); return; } $ipaddrs{$ip} = 1; @@ -288,7 +288,6 @@ sub preprocess_request { @args=($req->{arg}); } @ARGV = @args; - Getopt::Long::Configure("bundling"); Getopt::Long::Configure("pass_through"); if (!GetOptions('h|?|help' => \$HELP, 'v|version' => \$VERSION) ) { @@ -326,6 +325,7 @@ sub preprocess_request { return; } + #my $sent = $stab->getAttribs({key=>'sharedtftp'},'value'); my @entries = xCAT::TableUtils->get_site_attribute("sharedtftp"); my $t_entry = $entries[0]; if ( defined($t_entry) and ($t_entry == 0 or $t_entry =~ /no/i)) { @@ -346,8 +346,8 @@ sub preprocess_request { if ($req->{inittime}->[0]) { return [$req]; } - if (@CN >0 ) { # there are computenodes then run on all servicenodes - return xCAT::Scope->get_broadcast_scope($req,@_); + if (@CN >0 ) { # if compute nodes broadcast to all servicenodes + return xCAT::Scope->get_broadcast_scope($req,@_); } } return [$req]; @@ -524,12 +524,12 @@ sub process_request { foreach my $node (@nodes) { my %ipaddrs; unless (inet_aton($node)) { - syslog("local1|err","xCAT unable to resolve IP in pxe plugin"); + syslog("local4|err","xCAT unable to resolve IP in pxe plugin"); return; } my $ip = inet_ntoa(inet_aton($node));; unless ($ip) { - syslog("local1|err","xCAT unable to resolve IP in pxe plugin"); + syslog("local4|err","xCAT unable to resolve IP in pxe plugin"); return; } $ipaddrs{$ip} = 1; diff --git a/xCAT-server/lib/xcat/plugins/vsmppxe.pm b/xCAT-server/lib/xcat/plugins/vsmppxe.pm index 8bf893bf8..4d157ccd5 100644 --- a/xCAT-server/lib/xcat/plugins/vsmppxe.pm +++ b/xCAT-server/lib/xcat/plugins/vsmppxe.pm @@ -131,7 +131,7 @@ sub setstate { close($pcfg); my $inetn = inet_aton($primarynode); unless ($inetn) { - syslog("local1|err","xCAT unable to resolve IP for $node in pxe plugin"); + syslog("local4|err","xCAT unable to resolve IP for $node in pxe plugin"); return; } } else { #TODO: actually, should possibly default to xCAT image? @@ -141,12 +141,12 @@ sub setstate { my $mactab = xCAT::Table->new('mac'); #to get all the hostnames my %ipaddrs; unless (inet_aton($primarynode)) { - syslog("local1|err","xCAT unable to resolve IP in pxe plugin"); + syslog("local4|err","xCAT unable to resolve IP in pxe plugin"); return; } my $ip = inet_ntoa(inet_aton($primarynode));; unless ($ip) { - syslog("local1|err","xCAT unable to resolve IP in pxe plugin"); + syslog("local4|err","xCAT unable to resolve IP in pxe plugin"); return; } $ipaddrs{$ip} = 1; diff --git a/xCAT-server/lib/xcat/plugins/yaboot.pm b/xCAT-server/lib/xcat/plugins/yaboot.pm index b68699dd3..fda2ccb33 100644 --- a/xCAT-server/lib/xcat/plugins/yaboot.pm +++ b/xCAT-server/lib/xcat/plugins/yaboot.pm @@ -194,7 +194,7 @@ sub setstate { close($pcfg); my $inetn = xCAT::NetworkUtils->getipaddr($node); unless ($inetn) { - syslog("local1|err","xCAT unable to resolve IP for $node in yaboot plugin"); + syslog("local4|err","xCAT unable to resolve IP for $node in yaboot plugin"); return; } } else { #TODO: actually, should possibly default to xCAT image? @@ -252,7 +252,7 @@ sub setstate { close($pcfg); my $inetn = xCAT::NetworkUtils->getipaddr($node); unless ($inetn) { - syslog("local1|err","xCAT unable to resolve IP for $node in yaboot plugin"); + syslog("local4|err","xCAT unable to resolve IP for $node in yaboot plugin"); return; } } else { #TODO: actually, should possibly default to xCAT image? @@ -261,7 +261,7 @@ sub setstate { } my $ip = xCAT::NetworkUtils->getipaddr($node); unless ($ip) { - syslog("local1|err","xCAT unable to resolve IP in yaboot plugin"); + syslog("local4|err","xCAT unable to resolve IP in yaboot plugin"); return; } my $mactab = xCAT::Table->new('mac'); @@ -397,7 +397,7 @@ sub preprocess_request { if ($req->{inittime}->[0]) { return [$req]; } - if (@CN >0 ) { # if compute nodes broadcast to all servicenodes + if (@CN >0 ) { # if compute nodes broadcast to all servicenodes return xCAT::Scope->get_broadcast_scope($req,@_); } } @@ -408,8 +408,8 @@ sub preprocess_request { sub process_request { $request = shift; $callback = shift; - $sub_req = shift; $::callback=$callback; + $sub_req = shift; my $command = $request->{command}->[0]; %breaknetbootnodes=(); %normalnodes=(); From 9f53a3c4e6322d944fec2da5efd0d70f875aa578 Mon Sep 17 00:00:00 2001 From: nott Date: Fri, 18 Oct 2013 07:57:49 -0400 Subject: [PATCH 27/91] check return from find_latest_pkg --- xCAT-buildkit/bin/buildkit | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/xCAT-buildkit/bin/buildkit b/xCAT-buildkit/bin/buildkit index 95a828bbe..0ba413645 100755 --- a/xCAT-buildkit/bin/buildkit +++ b/xCAT-buildkit/bin/buildkit @@ -3131,7 +3131,7 @@ sub kit_addpkgs return 1; } - print "Extracting tar file $kittarfile.\n"; + print "Extracting tar file $kittarfile. Please wait.\n"; if ( system("cd $tmpdir_base; tar -jxf $kittarfile ") ) { print "Error extracting tarfile $kittarfile \n"; @@ -3526,15 +3526,16 @@ sub NEW_kit_addpkgs my $ext_reponames = $kp->{kitreponame}; my $files = xCAT::BuildKitUtils->find_latest_pkg(\@pkgdirlist, $ext_filename); - my @fromfiles=@$files; - if (scalar(@fromfiles) ==0 ) { + if (!defined($files) ) { print "Error: The product package file $ext_filename was not found in the package directory(s) @pkgdirlist.\n"; # Cleanup system ("rm -Rf $tmpdir_base"); return 1; } + my @fromfiles=@$files; + foreach my $repo (split(/,/, $ext_reponames)) { my $repodir = $::base_repodir."/".$repo; if ( ! -d ($repodir) && (! mkpath($repodir)) ) { From c88d7751de9cc02a3402639397a1c7a655a86ebf Mon Sep 17 00:00:00 2001 From: nott Date: Fri, 18 Oct 2013 07:59:14 -0400 Subject: [PATCH 28/91] check return from find_latest_pkg --- xCAT-buildkit/bin/buildkit | 1 - 1 file changed, 1 deletion(-) diff --git a/xCAT-buildkit/bin/buildkit b/xCAT-buildkit/bin/buildkit index 0ba413645..2c4d2e374 100755 --- a/xCAT-buildkit/bin/buildkit +++ b/xCAT-buildkit/bin/buildkit @@ -3533,7 +3533,6 @@ sub NEW_kit_addpkgs system ("rm -Rf $tmpdir_base"); return 1; } - my @fromfiles=@$files; foreach my $repo (split(/,/, $ext_reponames)) { From 49f714850ba774a538835e6254a469de24fffe08 Mon Sep 17 00:00:00 2001 From: John Simpson Date: Fri, 18 Oct 2013 16:13:52 -0400 Subject: [PATCH 29/91] Adding a new plugin confgifpc to support discovery and configuring of NeXtScale FPCs --- xCAT-client/xCAT-client.spec | 1 + xCAT-server/lib/xcat/plugins/configfpc.pm | 350 ++++++++++++++++++++++ 2 files changed, 351 insertions(+) create mode 100644 xCAT-server/lib/xcat/plugins/configfpc.pm diff --git a/xCAT-client/xCAT-client.spec b/xCAT-client/xCAT-client.spec index fe86a0131..a76dd8ef2 100644 --- a/xCAT-client/xCAT-client.spec +++ b/xCAT-client/xCAT-client.spec @@ -229,6 +229,7 @@ ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/nodediscoverstatus ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/nodediscoverdef ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/nodeaddunmged ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/geninitrd +ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/configfpc ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/bin/nodepurge ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/bin/nodechprofile ln -sf ../bin/xcatclient $RPM_BUILD_ROOT/%{prefix}/bin/noderegenips diff --git a/xCAT-server/lib/xcat/plugins/configfpc.pm b/xCAT-server/lib/xcat/plugins/configfpc.pm new file mode 100644 index 000000000..7ba94c4ff --- /dev/null +++ b/xCAT-server/lib/xcat/plugins/configfpc.pm @@ -0,0 +1,350 @@ +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html +package xCAT_plugin::configfpc; + +BEGIN +{ + $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; +} +use strict; +use lib "$::XCATROOT/lib/perl"; +use xCAT::Utils; +use xCAT::MsgUtils; +use xCAT::SvrUtils; +use Sys::Hostname; +use xCAT::Table; +use xCAT::TableUtils; +use xCAT::NetworkUtils; +use Data::Dumper; +use xCAT::MacMap; +use Socket; + +########################################################################## +## Command handler method from tables +########################################################################### +sub handled_commands { + return { + configfpc => "configfpc", + }; +} + +sub process_request { + my $request = shift; + my $callback = shift; + my $subreq = shift; + + $::CALLBACK = $callback; + + my $command = $request->{command}->[0]; + my $localhostname = hostname(); + + if ($command eq "configfpc") + { + my $rc; + $rc = configfpc($request, $callback, $subreq); + } + else + { + my %rsp; + push@{ $rsp{data} }, "$localhostname: Unsupported command: $command"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + return 1; + } + +return 0; +} + +# +# Main process subroutine +# +########################################################################### +# This routine will look for NeXtWcale Fan Power Controllers (FPC) that have +# a default IP address of 192.169.0.100 +# +# For each FPC found the code will +# 1 - ping the default IP address to get the default IP and MAC in the arp table +# 2 - use arp to get the MAC address +# 3 - lookup the MAC address +# ------ check for the MAC on the switch adn save the port number +# ------ lookup the node with that switch port number +# 4 - get the IP address for the node name found +# 5 - determine the assocaited netmask and gateway for this node IP +# 6 - use rspconfig (IPMI) to set the netmask, gateway, and IP address +# 7 - check to make sure that the new FPC IP address is responding +# 8 - remove the default FPC IP from the arp table +# 9 - use ping to determine if there is another default FPC IP and if so start this process again +########################################################################### +sub configfpc { + my $request = shift; + my $callback = shift; + my $subreq = shift; + + + # Use default userid and passwd + my $ipmiuser = 'USERID'; + my $ipmipass = 'PASSW0RD'; + my $fpcip = '192.168.0.100'; + my $defnode = "deffpc"; + + # This is the default FPC IP that we are looking for + my $foundfpc = 0; + + # + # check for an FPC - this ping will also add the FPC IP and MAC to the ARP table + # + my $res = `LANG=C ping -c 1 -w 5 $fpcip`; + #my $res = system("LANG=C ping -c 1 -w 5 $fpcip 2>&1"); + if ( $res =~ /100% packet loss/g) { +# xCAT::MsgUtils->message ("I", "There are no default $fpcip FPC IP addresses to process"); + $foundfpc = 0; + exit; # EXIT if we find no more default IP addresses on the network + } + else { +# xCAT::MsgUtils->message ("I", "Found $fpcip FPC IP addresses to process"); + $foundfpc = 1; + } + + # + # make the FPC node definition - this is removed at the end of processing the FPCs + # this default FPC node definition is used by rspconfig to change the netmask, default route, and IP address of the default FPC + # + # Object name: deffpc + # bmc=deffpc + # bmcpassword=PASSW0RD + # bmcusername=USERID + # cons=ipmi + # groups=deffpc + # mgt=ipmi + # mpa=deffpc + # + my $out = xCAT::Utils->runxcmd( + { + command => ["mkdef"], + arg => [ "-t","node","-o",$defnode,"bmc=deffpc","bmcpassword=Passw0rd","bmcusername=USERID","cons=ipmi","groups=deffpc","mgt=ipmi","mpa=deffpc" ] + }, + $subreq, 0,1); + + # + # Main loop - check to see if we found an FPC and continue to set the FPC infomration and look for the next one + # + while ($foundfpc){ + + # Process the default FPC IP to find the node associated with this FPC MAC + my ($node,$fpcmac) = &get_node($callback); + + # Found the Node and MAC associated with this MAC - continue to setup this FPC + if ($node) { + + # get the network settings for this node + my ($netmask,$gateway,$newfpcip) = &get_network_parms($node,$callback); + + # Change the FPC network netmask, gateway, and ip + &set_FPC_network_parms($defnode,$netmask,$gateway,$newfpcip,$callback,$subreq); + + # sleep for 4 seconds to allow rspconfig to change the IP value before validating with ping + sleep 5; + + # + # Validate that new IP is working - Use ping to check if the new IP has been set + # + $res = `LANG=C ping -c 1 -w 5 $newfpcip`; + #$res = system("LANG=C ping -c 1 -w 5 $fpcip 2>&1"); + if ( $res =~ /100% packet loss/g) { + my %rsp; + push@{ $rsp{data} }, "The new ip $newfpcip was not accessible"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + #xCAT::MsgUtils->message("I","The new ip $newfpcip was not accessible"); + } else { + my %rsp; + push@{ $rsp{data} }, "Changed the IP address for the FPC with $fpcmac MAC to $newfpcip IP for node $node"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + #xCAT::MsgUtils->message("I","Changed the IP address for the FPC with $fpcmac MAC to $newfpcip IP for node $node"); + } + # The Node associated with this MAC was not found - print an infomrational message and continue + } else { + my %rsp; + push@{ $rsp{data} }, "No FPC node found that is associated with MAC address $fpcmac\nCheck to see if the switch and switch table conta ins the information needed to locate this FPC MAC"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + # xCAT::MsgUtils->message("I","No FPC node found that is associated with MAC address $fpcmac\nCheck to see if the switch and switch table contains the information needed to locate this FPC MAC"); + } + + # + # Delete this FPC default IP Arp entry to get ready to look for another defautl FPC + # + my $arpout = `arp -d $fpcip`; + + # check for another FPC + $res = `LANG=C ping -c 1 -w 5 $fpcip 2>&1`; + if ( $res =~ /100% packet loss/g) { + my %rsp; + push@{ $rsp{data} }, "There are no more default $fpcip FPC IP addresses to process"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + #xCAT::MsgUtils->message("I","There are no more default $fpcip FPC IP addresses to process"); + $foundfpc = 0; + } + else { + $foundfpc = 1; + } + } + + # + # Cleanup on the way out - Remove the deffpc node definition + # + $out=xCAT::Utils->runxcmd( + { + command => ['rmdef'], + arg => [ "deffpc"] + }, + $subreq, 0,1); + + return 1; +} + +# +# The get_network_parms subroutine +# takes the node name and gets the IP address for this node +# and collects the netmask and gateway and returns netmask, gateway, and IP address +# +sub get_network_parms { + + my $node = shift; + my $callback = shift; + # Get the new ip address for this FPC + my $newfpc = `getent hosts $node`; + my ($newfpcip, $junk) = split(/\s/,$newfpc); + + # collect gateway and netmask + my $ip = $newfpcip; + my $gateway; + my $netmask; + if (inet_aton($ip)) { + $ip = inet_ntoa(inet_aton($ip)); + } else { + my %rsp; + push@{ $rsp{data} }, "Unable to resolve $ip"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + #xCAT::MsgUtils->message("S","Unable to resolve $ip"); + return undef; + } + my $nettab = xCAT::Table->new('networks'); + unless ($nettab) { return undef }; + my @nets = $nettab->getAllAttribs('net','mask','gateway'); + foreach (@nets) { + my $net = $_->{'net'}; + my $mask =$_->{'mask'}; + my $gw = $_->{'gateway'}; + $ip =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/; + my $ipnum = ($1<<24)+($2<<16)+($3<<8)+$4; + $mask =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/; + my $masknum = ($1<<24)+($2<<16)+($3<<8)+$4; + $net =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/ or next; #next if ipv6, TODO: IPv6 support + my $netnum = ($1<<24)+($2<<16)+($3<<8)+$4; + if ($gw eq '') { + $gw=xCAT::NetworkUtils->my_ip_facing($ip); + } + if (($ipnum & $masknum)==$netnum) { + $netmask = $mask; + $gateway = $gw; + } + } + return ($netmask,$gateway,$newfpcip); +} + +# +# The set_FPC_network_parms subroutine +# uses rspconfig to set the netmask, gateway, and new ip address for this FPC +# +sub set_FPC_network_parms { + + my $defnode = shift; + my $netmask = shift; + my $gateway = shift; + my $newfpcip = shift; + my $callback = shift; + my $request = shift; + my $error; + + # Proceed with changing the FPC network parameters. + # Set FPC Netmask + + + my $netmaskout = xCAT::Utils->runxcmd( + { + command => ["rspconfig"], + node => [$defnode], + arg => [ "netmask=$netmask" ] + }, + $request, 0,1); + + if ($::RUNCMD_RC != 0) { + my %rsp; + push@{ $rsp{data} }, "Could not change nemask $netmask on default FPC"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + $error++; + } + + # Set FPC gateway + my $gatewayout = xCAT::Utils->runxcmd( + { + command => ["rspconfig"], + node => [$defnode], + arg => [ "gateway=$gateway" ] + }, + $request, 0,1); + + if ($::RUNCMD_RC != 0) { + my %rsp; + push@{ $rsp{data} }, "Could not change gateway $gateway on default FPC"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + $error++; + } + + + # Set FPC Ip address + my $ipout = xCAT::Utils->runxcmd( + { + command => ["rspconfig"], + node => [$defnode], + arg => [ "ip=$newfpcip" ] + }, + $request, 0,1); + + if ($::RUNCMD_RC != 0) { + my %rsp; + push@{ $rsp{data} }, "Could not change ip address $newfpcip on default FPC"; + xCAT::MsgUtils->message( "S", \%rsp, $callback ); + $error++; + } + return 1; +} + +# +# This subroutine +# 1) gets the MAC from the arp table +# 2) uses Macmap to find the node associated with this MAC +# 3) returns the node and MAC +sub get_node { + my $callback = shift; + + my $fpcip = '192.168.0.100'; + + # get the FPC from the arp table + my $arpout = `arp -a | grep $fpcip`; + + # format of arp command is: feihu-fpc (10.1.147.170) at 6c:ae:8b:08:20:35 [ether] on eth0 + # extract the MAC address + my ($junk1, $junk2, $junk3, $fpcmac, $junk4, $junk5, $junk6) = split(" ", $arpout); + + # Print a message that this MAC has been found + my %rsp; + push@{ $rsp{data} }, "Found FPC with default IP $fpcip and MAC $fpcmac"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + + # Usee find_mac to 1) look for which switch port contains this MAC address + # and 2) look in the xcat DB to find the node associated with the switch port this MAC was found in + my $macmap = xCAT::MacMap->new(); + my $node = ''; + $node = $macmap->find_mac($fpcmac,0); + + return ($node,$fpcmac); +} +1; From 617de03d136c9ea7f3ff17e78e9367274d6febeb Mon Sep 17 00:00:00 2001 From: xq2005 Date: Mon, 21 Oct 2013 01:08:59 -0700 Subject: [PATCH 30/91] delete 127.0.1.1 from /etc/hosts on ubuntu compute node --- xCAT-server/share/xcat/install/scripts/post.ubuntu | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xCAT-server/share/xcat/install/scripts/post.ubuntu b/xCAT-server/share/xcat/install/scripts/post.ubuntu index 70583feb4..eb64b7e4b 100644 --- a/xCAT-server/share/xcat/install/scripts/post.ubuntu +++ b/xCAT-server/share/xcat/install/scripts/post.ubuntu @@ -188,6 +188,10 @@ elif [[ -r /boot/grub/grub.cfg ]] ; then update-grub fi sed -i 's/\(deb.*security.*\)/#\1/' /etc/apt/sources.list +#iso does not contains source deb packages +sed -i 's/^\(\s*deb-src.*install.*\)$/#\1/g' /etc/apt/sources.list +#delete the 127.0.1.1 line from /etc/hosts +sed -i '/127.0.1.1/d' /etc/hosts updateflag.awk $MASTER 3002 cd / #rm -Rf /xcatpost From 80ba0a46012991d6d475b99647a48060a3096f8f Mon Sep 17 00:00:00 2001 From: zhaoertao Date: Mon, 21 Oct 2013 02:51:36 -0700 Subject: [PATCH 31/91] fix bug 3774 :getmacs -D -V failed --- perl-xCAT/xCAT/PPCcli.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/perl-xCAT/xCAT/PPCcli.pm b/perl-xCAT/xCAT/PPCcli.pm index 3de42e5b8..b76a34c4d 100644 --- a/perl-xCAT/xCAT/PPCcli.pm +++ b/perl-xCAT/xCAT/PPCcli.pm @@ -139,7 +139,7 @@ sub connect { my $timeout = $req->{ppctimeout}; my $verbose = $req->{verbose}; my $ssh; - my $expect_log; + my $expect_log = "/dev/null"; my $errmsg; if ($req->{command} eq 'rflash') { @@ -170,7 +170,7 @@ sub connect { ################################################## if ( $verbose ) { close STDERR; - if ( !open( STDERR, '>', \$expect_log )) { + if ( !open( STDERR, '>', $expect_log )) { return( "Unable to redirect STDERR: $!" ); } } @@ -179,7 +179,7 @@ sub connect { ################################################## if ( $verbose ) { close STDOUT; - if ( !open( STDOUT, '>', \$expect_log )) { + if ( !open( STDOUT, '>', $expect_log )) { return( "Unable to redirect STDOUT: $!" ); } } From 81679ffdb9ea1339b5b2402f2e4bccb6b6a5efe7 Mon Sep 17 00:00:00 2001 From: lissav Date: Mon, 21 Oct 2013 11:28:50 -0400 Subject: [PATCH 32/91] defect 3819 --- xCAT/postscripts/xcatflowrequest | 57 +++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/xCAT/postscripts/xcatflowrequest b/xCAT/postscripts/xcatflowrequest index fc09d59d9..b8dd84ea1 100644 --- a/xCAT/postscripts/xcatflowrequest +++ b/xCAT/postscripts/xcatflowrequest @@ -4,9 +4,41 @@ # ready to process the request # It is called by xcatdsklspost before calling getpostscripts.awk # it is called by remoteshell before calling getcredentials.awk +# For example xcatflowrequest 3001 +# Returns +# 0 = good +# 1 = ping/nmap to ip address of master failed (TBD) +# 2 = xcatd never gave goahead +# + +# Here we will test to see if nmap is available +# if available we will use it to see if the daemon is available +# If not available we will use ping to the ip address +# If nmap or ping fail then +# we will return with exit 1 +# + + # check bash version, if < 4 then cannot use autodetect of next FD bashversion=$BASH_VERSION bashversionnum=`echo $bashversion | cut -d. -f1` + +# cleanup before exiting +cleanup() +{ +sleeper=$(cat /tmp/sleeperpid.$parpid) +sleeper=$(ps -ef|awk "\$3==$sleeper"|awk '{print $2}') +rm /tmp/goahead.$parpid +rm /tmp/sleeperpid.$parpid +rm /tmp/killme.$parpid +if [[ $bashversionnum > 3 ]]; then + exec {REMOTEFD}>&- +else + exec 50>&- +fi +kill -TERM $sleeper +} + if [[ $bashversionnum > 3 ]]; then exec {REMOTEFD}<>/dev/udp/$1/$2 else @@ -19,6 +51,8 @@ parpid=$$ touch /tmp/goahead.$parpid touch /tmp/killme.$parpid exec 2> /dev/null +RETRY=0 +MAX_RETRIES=50 while ! grep 'resourcerequest: ok' /tmp/goahead.$parpid > /dev/null; do ( echo "resourcerequest: xcatd" >&$REMOTEFD @@ -34,16 +68,15 @@ while ! grep 'resourcerequest: ok' /tmp/goahead.$parpid > /dev/null; do echo $! > /tmp/sleeperpid.$parpid exec awk '{print $0 > "/tmp/goahead.'$parpid'";exit}' <&$REMOTEFD exec {LOCALFD}>&- - ) + ) + # limit retries, if we reach the max error out + RETRY=$(($RETRY+1)) + if [ $RETRY -eq $MAX_RETRIES ] + then + cleanup + exit 2 + fi + done -sleeper=$(cat /tmp/sleeperpid.$parpid) -sleeper=$(ps -ef|awk "\$3==$sleeper"|awk '{print $2}') -rm /tmp/goahead.$parpid -rm /tmp/sleeperpid.$parpid -rm /tmp/killme.$parpid -if [[ $bashversionnum > 3 ]]; then - exec {REMOTEFD}>&- -else - exec 50>&- -fi -kill -TERM $sleeper +cleanup +exit 0 From ef75e82fe3ad54bf4919dde53ad95aa8506af0f1 Mon Sep 17 00:00:00 2001 From: Chuck Brazie Date: Mon, 21 Oct 2013 14:01:20 -0400 Subject: [PATCH 33/91] Merge zVM updates into xCAT 2.8.3 --- perl-xCAT/xCAT/Client.pm | 1254 -------------------- xCAT-server/lib/xcat/plugins/imgcapture.pm | 2 +- xCAT-server/lib/xcat/plugins/imgport.pm | 474 +++++--- xCAT-server/lib/xcat/plugins/rmimage.pm | 39 +- xCAT-server/share/xcat/scripts/xcatconf4z | 73 +- 5 files changed, 356 insertions(+), 1486 deletions(-) delete mode 100644 perl-xCAT/xCAT/Client.pm diff --git a/perl-xCAT/xCAT/Client.pm b/perl-xCAT/xCAT/Client.pm deleted file mode 100644 index e0934796d..000000000 --- a/perl-xCAT/xCAT/Client.pm +++ /dev/null @@ -1,1254 +0,0 @@ -#!/usr/bin/env perl -# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html -package xCAT::Client; -BEGIN -{ - $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr'; -} - -# if AIX - make sure we include perl 5.8.2 in INC path. -# Needed to find perl dependencies shipped in deps tarball. -use Storable qw/nstore_fd fd_retrieve/; -if ($^O =~ /^aix/i) { - unshift(@INC, qw(/usr/opt/perl5/lib/5.8.2/aix-thread-multi /usr/opt/perl5/lib/5.8.2 /usr/opt/perl5/lib/site_perl/5.8.2/aix-thread-multi /usr/opt/perl5/lib/site_perl/5.8.2)); -} -use IO::Handle; - -my $inet6support; -if ($^O =~ /^aix/i) { # disable AIX IPV6 TODO fix - $inet6support = 0; -} else { - $inet6support=eval { require Socket6; 1; }; -} -if ($inet6support) { - $inet6support = eval { require IO::Socket::INET6; 1; }; -} -if ($inet6support) { - $inet6support = eval { require IO::Socket::SSL; IO::Socket::SSL->import('inet6'); 1;}; -} - -if ($^O =~ /^linux/i) { - # Is IPv6 enabled on the MN or xcat client node at all? - my $ipv6enabled = `ip addr | grep inet6`; - if (!$ipv6enabled) { - $inet6support = 0; - } -} - -unless ($inet6support) { - eval { require Socket }; - eval { require IO::Socket::INET }; - eval { require IO::Socket::SSL; IO::Socket::SSL->import('inet4') }; -} - - -use XML::Simple; #smaller than libxml.... -use Fcntl; -use POSIX qw/:errno_h/; -use IO::Select; -$XML::Simple::PREFERRED_PARSER='XML::Parser'; -#require Data::Dumper; -my $xcathost='localhost:3001'; -my $plugins_dir; -my %resps; -my $EXITCODE; # save the bitmask of all exit codes returned by calls to handle_response() -1; - - -sub rspclean { - my $response = shift; - my $callback = shift; - my $rsps = XMLin($response,SuppressEmpty=>undef,ForceArray=>1); - foreach my $rsp (@{$rsps->{xcatresponse}}) { - #add ESC back - foreach my $key (keys %$rsp) { - if (ref($rsp->{$key}) eq 'ARRAY') { - foreach my $text (@{$rsp->{$key}}) { - next unless defined $text; - $text =~ s/xxxxESCxxxx/\e/g; - } - } - else { - $rsp->{$key} =~ s/xxxxESCxxxx/\e/g; - } - } - $callback->($rsp); - if ($rsp->{serverdone}) { - return 1; - } - } - return 0; -} -sub send_request { - my $request = shift; - my $sock = shift; - my $encode = shift; - if ($encode eq "xml") { - my $msg=XMLout($request,RootName=>'xcatrequest',NoAttr=>1,KeyAttr=>[]); - if ($ENV{XCATXMLTRACE}) { print $msg; } - if($ENV{XCATXMLWARNING}) { - validateXML($msg); - } - print $sock $msg; - $sock->flush(); - } else { - nstore_fd($request,$sock); - $sock->flush(); - } -} -################################# -# submit_request will take an xCAT command and pass it to the xCAT -# server for execution. -# Note must not put a require or use for Utils.pm in the non-bypass path -# -# If the XCATBYPASS env var is set, the connection to the server/daemon -# will be bypassed and the plugin will be called directly. If it is -# set to one or more directories (separated by ":"), all perl modules -# in those directories will be loaded in as plugins (for duplicate -# commands, last one in wins). If it is set to any other value -# (e.g. "yes", "default", whatever string you want) the default plugin -# directory /opt/xcat/lib/perl/xCAT_plugin will be used. -# -# Input: -# Request hash - A hash ref containing the input command and args to be -# passed to the plugin. The the xcatd daemon (or this routine when -# XCATBYPASS) reads the {noderange} entry and builds a flattened array -# of nodes that gets added as request->{node} -# The format for the request hash is: -# { command => [ 'xcatcmd' ], -# noderange => [ 'noderange_string' ], -# arg => [ 'arg1', 'arg2', '...', 'argn' ] -# } -# Callback - A subroutine ref that will be called to process the output -# from the plugin. -# -# NOTE: The request hash will get converted to XML when passed to the -# xcatd daemon, and will get converted back to a hash before being -# passed to the plugin. The XMLin ForceArray option is used to -# force all XML constructs to be arrays so that the plugin code -# and callback routines can access the data consistently. -# The input request and the response hash created by the plugin should -# always create hashes with array values. -################################# -sub submit_request { - my $request = shift; - my $callback = shift; - my $keyfile = shift; - my $certfile = shift; - my $cafile = shift; - # get home directory - my @user = getpwuid($>); - my $homedir=$user[7]; - unless ($keyfile) { $keyfile = $homedir."/.xcat/client-cred.pem"; } - unless ($certfile) { $certfile = $homedir."/.xcat/client-cred.pem"; } - unless ($cafile) { $cafile = $homedir."/.xcat/ca.pem"; } - $xCAT::Client::EXITCODE = 0; # clear out exit code before invoking the plugin -if (ref($request) eq 'HASH') { # the request is an array, not pure XML - $request->{clienttype}->[0] = "cli"; # setup clienttype for auditlog -} -# If XCATBYPASS is set, invoke the plugin process_request method directly -# without going through the socket connection to the xcatd daemon - if ($ENV{XCATBYPASS}) { - #add current userid to the request - if (ref($request) eq 'HASH') { # the request is an array, not pure XML - if (!(defined($request->{username}))) { - $request->{username}->[0] = getpwuid($>); - } - - # only allow root to run - unless ($request->{username}->[0] =~ /root/) { - print ("WARNING: Only allow root to run XCATBYPASS mode, your current user ID is $request->{username}->[0].\n"); - return 0; - } - } - # Load plugins from either specified or default dir - require xCAT::Table; - my %cmd_handlers; - my @plugins_dirs = split('\:',$ENV{XCATBYPASS}); - if (-d $plugins_dirs[0]) { - foreach (@plugins_dirs) { - $plugins_dir = $_; - scan_plugins(); - } - } else { - # figure out default plugins dir - #my $sitetab=xCAT::Table->new('site'); - #unless ($sitetab) { - # print ("ERROR: Unable to open basic site table for configuration\n"); - #} - $plugins_dir=$::XCATROOT.'/lib/perl/xCAT_plugin'; - scan_plugins(); - } - - populate_site_hash(); - - # don't do XML transformation -- assume request is well-formed - # my $xmlreq=XMLout($request,RootName=>xcatrequest,NoAttr=>1,KeyAttr=>[]); - # $request = XMLin($xmlreq,SuppressEmpty=>undef,ForceArray=>1) ; - - - # Call the plugin directly - # ${"xCAT_plugin::".$modname."::"}{process_request}->($request,$callback); - plugin_command($request,undef,$callback); - return 0; - } - -# No XCATBYPASS, so establish a socket connection with the xcatd daemon -# and submit the request - if ($ENV{XCATHOST}) { - $xcathost=$ENV{XCATHOST}; - } - my %connargs=(); - if ($xcathost =~ s/%([^\]|:]*)//) { - $connargs{PeerScope} = $1; - } - $connargs{PeerAddr} = $xcathost; - $connargs{Timeout} = 15; - if ($connargs{PeerScope} and $connargs{PeerScope} =~ /[a-zA-Z]/) { #non-numeric, need to translate... - my @ipdata = `ip link`; - @ipdata = grep(/[^@]$connargs{PeerScope}(:|@)/,@ipdata); - if (scalar(@ipdata) != 1) { - print STDERR "Unable to identify scope ".$connargs{PeerScope}."\n"; - exit(1); - } - $connargs{PeerScope} = $ipdata[0]; - $connargs{PeerScope} =~ s/:.*//; - } - - - my $pclient; - if ($inet6support) { - $pclient = IO::Socket::INET6->new( - %connargs, - ); - } else { - $pclient = IO::Socket::INET->new( - PeerAddr => $xcathost, - Timeout => 15, - ); - } - unless ($pclient) { - print "Unable to open socket connection to xcatd daemon on $xcathost.\n"; - print "Verify that the xcatd daemon is running and that your SSL setup is correct.\n"; - if ($@ =~ /SSL Timeout/) { - die "Connection failure: SSL Timeout or incorrect certificates in ~/.xcat"; - } else { - die "Connection failure: $@" - } - } - my $client; - if (-r $keyfile and -r $certfile and -r $cafile) { - $client = IO::Socket::SSL->start_SSL($pclient, - SSL_key_file => $keyfile, - SSL_cert_file => $certfile, - SSL_ca_file => $cafile, - SSL_use_cert => 1, - Timeout => 0, - ); - } else { - $client = IO::Socket::SSL->start_SSL($pclient, - Timeout => 0, - ); - } - unless ($client) { - print "Unable to open socket connection to xcatd daemon on $xcathost.\n"; - print "Verify that the xcatd daemon is running and that your SSL setup is correct.\n"; - if ($@ =~ /SSL Timeout/) { - die "Connection failure: SSL Timeout or incorrect certificates in ~/.xcat"; - } else { - die "Connection failure: $@" - } - } - - my $msg; - my $encode = "xml"; - #storable encoding is unsafe, carry on with the unsafe xml scheme - #perhaps one day will support faster schemes - #my $encode = "storable"; - #my $straightprint=0; - #if ($ENV{XCATXMLTRACE} or $ENV{XCATXMLWARNING}) { $encode="xml"; } - if (ref($request) eq 'HASH') { # the request is an array, not pure XML - #print $client "xcatencoding: $encode\n"; - #my $encok=<$client>; - send_request($request,$client,$encode); - } else { #XML - $straightprint=1; - $msg=$request; - print $client $msg; - } - $SIG{TERM} = $SIG{INT} = sub { send_request({abortcommand=>[1]},$client,$encode); exit 0; }; - my $response; - my $rsp; - my $cleanexit=0; - if ($encode eq 'xml') { - my $massresponse=""; - my $nextcoalescetime=time()+1; - my $coalescenow=0; - my $flags=fcntl($client,F_GETFL,0); - $flags |= O_NONBLOCK; #select can be a bit.. fickle, make sysread work more easily... - fcntl($client,F_SETFL,$flags); - my $clientsel = new IO::Select; - $clientsel->add($client); - my $line; - my $newdata=0; - while (1) { - my $shouldexit; - if ($newdata and ($coalescenow or time() > $nextcoalescetime)) { - $coalescenow=0; - $newdata=0; - $nextcoalescetime=time()+1; - $massresponse .= ""; - $shouldexit = rspclean($massresponse,$callback); - $massresponse=""; - } - - if ($shouldexit) { - $cleanexit=1; - last; - } - $line = ""; - $clientsel->can_read(0.5); - my $readbytes; - do { $readbytes=sysread($client,$line,65535,length($line)); } while ($readbytes); - unless (length($line)) { - if (not defined $readbytes and $! == EAGAIN) { next; } - last; - } - $newdata=1; - $response .= $line; - if ($line =~ m/<\/xcatresponse>\s*\z/) { - if ($line =~ /serverdone/) { $coalescenow=1; } #if serverdone was detected, hint at coalesce code to flush things out now - #this means that coalesce can be triggered by stray words in the output prematurely, but that's harmless - #replace ESC with xxxxESCxxx because XMLin cannot handle it - $response =~ s/\e/xxxxESCxxxx/g; - - if ($ENV{XCATXMLTRACE}) { print $response; } - $massresponse.=$response; - $response=''; - if($ENV{XCATXMLWARNING}) { - validateXML($response); - } - } - } - if (not $cleanexit and $massresponse ne "") { - $massresponse .= ""; - $cleanexit = rspclean($massresponse,$callback); - } - } else { #storable encode - my $rsp; - eval { $rsp = fd_retrieve($client); }; - SERVERINPUT: while ($rsp) { - my @rsps; - if (ref $rsp eq 'ARRAY') { - @rsps = @$rsp; - } else { - @rsps = ($rsp); - } - foreach (@rsps) { - $callback->($_); - if ($_->{serverdone}) { - $cleanexit=1; - last SERVERINPUT; - } - } - $rsp = undef; - eval { $rsp = fd_retrieve($client); }; - } - } - $massresponse=""; - unless ($cleanexit) { - print STDERR "ERROR/WARNING: communication with the xCAT server seems to have been ended prematurely\n"; - $xCAT::Client::EXITCODE = 1; - } - -sub validateXML { - my $xml = shift; - my @lines = split /\n/, $xml; - my $invalidNewline = 0; - my $contentsColon = 0; - my $contentsLine; - - foreach (@lines) { - if(!$invalidNewline) { - if( ($_ =~ // && $_ !~ /<\/contents>/) || - ($_ =~ // && $_ !~ /<\/desc>/)) { - $invalidNewline = 1; - print "Possible invalid XML using newlines found: \n$xml\n"; - } - } - if($_ =~ /.+:.+<\/contents>/) { - $contentsColon = 1; - $contentsLine = $_; - } - if($_ =~ /.+<\/desc>/) { - $contentsColon = 0; - } - if($contentsColon && $_ =~ /<\/desc>/) { - print "Possible invalid XML found(data contents using colon and blank description): \n$contentsLine\n$_\n"; - $contentsColon = 0; - } - } -} - -################################### -# scan_plugins -# will load all plugin perl modules and build a list of supported -# commands -# -# NOTE: This is copied from xcatd (last merge 11/23/09). -# TODO: Will eventually move to using common source.... -################################### -sub scan_plugins { - my @plugins=glob($plugins_dir."/*.pm"); - foreach (@plugins) { - /.*\/([^\/]*).pm$/; - my $modname = $1; - unless ( eval { require "$_" }) { -# xCAT::MsgUtils->message("S","Error loading module ".$_." ...skipping"); - print "Error loading module $_ ...skipping\n"; - next; - } - no strict 'refs'; - my $cmd_adds=${"xCAT_plugin::".$modname."::"}{handled_commands}->(); - foreach (keys %$cmd_adds) { - my $value = $_; - if (defined($cmd_handlers{$_})) { - push @{$cmd_handlers{$_}},[$modname,$cmd_adds->{$_}]; - } else { - $cmd_handlers{$_} = [ [$modname,$cmd_adds->{$_}] ]; - } - } - } - foreach (@plugins) { - no strict 'refs'; - /.*\/([^\/]*).pm$/; - my $modname = $1; - unless (defined(${"xCAT_plugin::".$modname."::"}{init_plugin})) { - next; - } - ${"xCAT_plugin::".$modname."::"}{init_plugin}->(\&do_request); - } -} - - - - -################################### -# plugin_command -# will invoke the correct plugin -# -# NOTE: This is copied from xcatd (last merge 11/23/09). -# TODO: Will eventually move to using common source.... -################################### -sub plugin_command { - my $req = shift; - my $sock = shift; - my $callback = shift; - my %handler_hash; - my $usesiteglobal = 0; - # We require these only in bypass mode to reduce start up time for the normal case - #use lib "$::XCATROOT/lib/perl"; - #use xCAT::NodeRange; - require lib; - lib->import("$::XCATROOT/lib/perl"); - require xCAT::NodeRange; - require xCAT::Table; - - $Main::resps={}; - my $xmlreq; - if (ref($req) ne 'HASH') { # the request XML, get an array - $xmlreq=$req; # save the original XML - $req = XMLin($xmlreq,SuppressEmpty=>undef,ForceArray=>1) ; - - } - my @nodes; - if ($req->{node}) { - @nodes = @{$req->{node}}; - } elsif ($req->{noderange} and $req->{noderange}->[0]) { - @nodes = xCAT::NodeRange::noderange($req->{noderange}->[0]); - if (xCAT::NodeRange::nodesmissed()) { -# my $rsp = {errorcode=>1,error=>"Invalid nodes in noderange:".join(',',xCAT::NodeRange::nodesmissed)}; -# my $rsp->{serverdone} = {}; - print "Invalid nodes in noderange:".join(',',xCAT::NodeRange::nodesmissed())."\n"; -# if ($sock) { -# print $sock XMLout($rsp,RootName=>'xcatresponse' ,NoAttr=>1); -# } -# return ($rsp); - return 1; - } - unless (@nodes) { - $req->{emptynoderange} = [1]; - } - } - if (@nodes) { $req->{node} = \@nodes; } - my %unhandled_nodes; - foreach (@nodes) { - $unhandled_nodes{$_}=1; - } - my $useunhandled=0; - if (defined($cmd_handlers{$req->{command}->[0]})) { - my $hdlspec; - my @globalhandlers=(); - my $useglobals=1; #If it stays 1, then use globals normally, if 0, use only for 'unhandled_nodes, if -1, don't do at all - foreach (@{$cmd_handlers{$req->{command}->[0]}}) { - $hdlspec =$_->[1]; - my $ownmod = $_->[0]; - if ($hdlspec =~ /^site:/) { #A site entry specifies a plugin - my $sitekey = $hdlspec; - $sitekey =~ s/^site://; - #$sitetab = xCAT::Table->new('site'); - #my $sent = $sitetab->getAttribs({key=>$sitekey},['value']); - #if ($sent and $sent->{value}) { #A site style plugin specification is just like - if ($::XCATSITEVALS{$sitekey}) { #A site style plugin specification is just like - #a static global, it grabs all nodes rather than some - $useglobals = -1; #If they tried to specify anything, don't use the default global handlers at all - unless (@nodes) { - $handler_hash{$::XCATSITEVALS{$sitekey}} = 1; - $usesiteglobal = 1; - } - foreach (@nodes) { #Specified a specific plugin, not a table lookup - $handler_hash{$::XCATSITEVALS{$sitekey}}->{$_} = 1; - } - } - } elsif ($hdlspec =~ /:/) { #Specificed a table lookup path for plugin name - if (@nodes) { # only use table lookup plugin if nodelist exists - # Usage will be handled in common AAAhelp plugin - - $useglobals = 0; #Only contemplate nodes that aren't caught through searching below in the global handler - $useunhandled=1; - my $table; - my $cols; - ($table,$cols) = split(/:/,$hdlspec); - my @colmns=split(/,/,$cols); - my @columns; - my $hdlrtable=xCAT::Table->new($table); - unless ($hdlrtable) { - #TODO: proper error handling - } - my $node; - my $colvals = {}; - foreach my $colu (@colmns) { - if ($colu =~ /=/) { #a value redirect to a pattern/specific name - my $coln; my $colv; - ($coln,$colv) = split(/=/,$colu,2); - $colvals->{$coln} = $colv; - push (@columns,$coln); - } else { - push (@columns,$colu); - } - } - - - unless (@nodes) { #register the plugin in the event of usage - $handler_hash{$ownmod} = 1; - $useglobals = 1; - } - my $hdlrcache; - if ($hdlrtable) { - $hdlrcache = $hdlrtable->getNodesAttribs(\@nodes,\@columns); - } - foreach $node (@nodes) { - unless ($hdlrcache) { next; } - my $attribs = $hdlrcache->{$node}->[0]; #$hdlrtable->getNodeAttribs($node,\@columns); - unless (defined($attribs)) { next; } - foreach (@columns) { - my $col=$_; - if (defined($attribs->{$col})) { - if ($colvals->{$col}) { #A pattern match style request. - if ($attribs->{$col} =~ /$colvals->{$col}/) { - $handler_hash{$ownmod}->{$node} = 1; - delete $unhandled_nodes{$node}; - last; - } - } else { - # call the plugin that matches the table value for that node - if ($attribs->{$col} =~ /$ownmod/) { - $handler_hash{$attribs->{$col}}->{$node} = 1; - delete $unhandled_nodes{$node}; - last; - } - } - } - } - } - $hdlrtable->close; - } # end if (@nodes) - - } else { - push @globalhandlers,$hdlspec; - } - } - if ($useglobals == 1) { #Behavior when globals have not been overriden - my $hdlspec; - foreach $hdlspec (@globalhandlers) { - unless (@nodes) { - $handler_hash{$hdlspec} = 1; - } - foreach (@nodes) { #Specified a specific plugin, not a table lookup - $handler_hash{$hdlspec}->{$_} = 1; - } - } - } elsif ($useglobals == 0) { - unless (@nodes or $usesiteglobal) { #if something like 'makedhcp -n', - foreach (keys %handler_hash) { - if ($handler_hash{$_} == 1) { - delete ($handler_hash{$_}) - } - } - } - foreach $hdlspec (@globalhandlers) { - unless (@nodes or $usesiteglobal) { - $handler_hash{$hdlspec} = 1; - } - foreach (keys %unhandled_nodes) { #Specified a specific plugin, not a table lookup - $handler_hash{$hdlspec}->{$_} = 1; - } - } - } #Otherwise, global handler is implicitly disabled - } else { - print "Error request: $req->{command}->[0] has no known plugin for it.\n"; - return 1; - } - if ($useunhandled) { - my $queuelist; - foreach (@{$cmd_handlers{$req->{command}->[0]}}) { - my $queueitem = $_->[1]; - if (($queueitem =~ /:/) and !($queuelist =~ /($queueitem)/)) { - $queuelist .= "$_->[1];"; - } - } - $queuelist =~ s/;$//; - $queuelist =~ s/:/./g; - foreach (keys %unhandled_nodes) { -# if ($sock) { -# print $sock XMLout({node=>[{name=>[$_],data=>["Unable to identify plugin for this command, check relevant tables: $queuelist"],errorcode=>[1]}]},NoAttr=>1,RootName=>'xcatresponse'); -# } else { - my $tabdesc = $queuelist; - $tabdesc =~ s/=.*$//; - $callback->({node=>[{name=>[$_],error=>['Unable to identify plugin for this command, check relevant tables: '.$tabdesc],errorcode=>[1]}]}); -# } - } - } - -## FOR NOW, DON'T FORK CHILD PROCESS TO MAKE BYPASS SIMPLER AND EASIER TO DEBUG -# $plugin_numchildren=0; -# %plugin_children=(); -# $SIG{CHLD} = \&plugin_reaper; #sub {my $plugpid; while (($plugpid = waitpid(-1, WNOHANG)) > 0) { if ($plugin_children{$plugpid}) { delete $plugin_children{$plugpid}; $plugin_numchildren--; } } }; -# my $check_fds; -# if ($sock) { -# $check_fds = new IO::Select; -# } - foreach (keys %handler_hash) { - my $modname = $_; -# my $shouldbealivepid=$$; - if (-r $plugins_dir."/".$modname.".pm") { - require $plugins_dir."/".$modname.".pm"; -# $plugin_numchildren++; -# my $pfd; #will be referenced for inter-process messaging. -# my $parfd; #not causing a problem that I discern yet, but theoretically -# my $child; -# if ($sock) { #If $sock not passed in, don't fork.. -# socketpair($pfd, $parfd,AF_UNIX,SOCK_STREAM,PF_UNSPEC) or die "socketpair: $!"; -# #pipe($pfd,$cfd); -# $parfd->autoflush(1); -# $pfd->autoflush(1); -# $child = xCAT::Utils->xfork; -# } else { -# $child = 0; -# } -# unless (defined $child) { die "Fork failed"; } -# if ($child == 0) { -# if ($parfd) { #If xCAT is doing multiple requests in same communication PID, things would get unfortunate otherwise -# $parent_fd = $parfd; -# } - my $oldprogname=$$progname; - $$progname=$oldprogname.": $modname instance"; -# if ($sock) { close $pfd; } - unless ($handler_hash{$_} == 1) { - my @nodes = sort {($a =~ /(\d+)/)[0] <=> ($b =~ /(\d+)/)[0] || $a cmp $b } (keys %{$handler_hash{$_}}); - $req->{node}=\@nodes; - } - no strict "refs"; -# eval { #REMOVEEVALFORDEBUG -# if ($dispatch_requests) { - # backup the original req and recover it after the a run - my $org_req = {%$req}; - dispatch_request($req,$callback,$modname); - $req = {%$org_req}; -# } else { -# $SIG{CHLD}='DEFAULT'; -# ${"xCAT_plugin::".$modname."::"}{process_request}->($req,$callback,\&do_request); -# } - $$progname=$oldprogname; -# if ($sock) { -# close($parent_fd); -# xexit(0); -# } -# }; #REMOVEEVALFORDEBUG -# if ($sock or $shouldbealivepid != $$) { #We shouldn't still be alive, try to send as much detail to parent as possible as to why -# my $error= "$modname plugin bug, pid $$, process description: '$$progname'"; -# if ($@) { -# $error .= " with error '$@'"; -# } else { #Sys::Virt and perhaps Net::SNMP sometimes crashes in a way $@ won't catch.. -# $error .= " with missing eval error, probably due to special manipulation of $@ or strange circumstances in an XS library, remove evals in xcatd marked 'REMOVEEVALFORDEBUG and run xcatd -f for more info"; -# } -# if (scalar (@nodes)) { #Don't know which of the nodes, so one error message warning about the possibliity.. -# $error .= " while trying to fulfill request for the following nodes: ".join(",",@nodes); -# } -# xCAT::MsgUtils->message("S","xcatd: $error"); -# $callback->({error=>[$error],errorcode=>[1]}); -# xexit(0); #Die like we should have done -# } elsif ($@) { #We are still alive, should be alive, but yet we have an error. This means we are in the case of 'do_request' or something similar. Forward up the death since our communication channel is intact.. -# die $@; -# } -# } else { -# $plugin_children{$child}=1; -# close $parfd; -# $check_fds->add($pfd); -# } - } else { - my $pm_name = $plugins_dir."/".$modname.".pm"; - foreach my $node (keys %{$handler_hash{$_}}) { - if ($sock) { - print $sock XMLout({node=>[{name=>[$node],data=>["Cannot find the perl module to complete the operation: $pm_name"],errorcode=>[1]}]},NoAttr=>1,RootName=>'xcatresponse'); - } else { - $callback->({node=>[{name=>[$node],data=>["Cannot find the perl module to complete the operation: $pm_name"],errorcode=>[1]}]}); - } - } - } - } - unless ($sock) { return $Main::resps }; -# while (($plugin_numchildren > 0) and ($check_fds->count > 0)) { #this tracks end of useful data from children much more closely -# relay_fds($check_fds,$sock); -# } -# #while (relay_fds($check_fds,$sock)) {} -# my %done; -# $done{serverdone} = {}; -# if ($req->{transid}) { -# $done{transid}=$req->{transid}->[0]; -# } -# if ($sock) { -# my $clientpresence = new IO::Select; #The client may have gone away without confirmation, don't PIPE over this trivial thing -# $clientpresence->add($sock); -# if ($clientpresence->can_write(5)) { -# print $sock XMLout(\%done,RootName => 'xcatresponse',NoAttr=>1); -# } -# } -} - - - - -################################### -# dispatch_request -# dispatch the requested command -# -# NOTE: This is copied from xcatd (last merge 11/23/09). -# All we really need from this subroutine is to call preprocess_request -# and to only run the command for nodes handled by the local server -# Will eventually move to using common source.... -################################### -sub dispatch_request { -# %dispatched_children=(); - require xCAT::Utils; - my $req = shift; - $dispatch_cb = shift; - - my $modname = shift; - my $reqs = []; -# my $child_fdset = new IO::Select; - no strict "refs"; - - #Hierarchy support. Originally, the default scope for noderange commands was - #going to be the servicenode associated unless overriden. - #However, assume for example that you have blades and a blade is the service node - #rpower being executed by the servicenode for one of its subnodes would have to - #reach it's own management module. This has the potential to be non-trivial for some quite possible network configurations. - #Since plugins may commonly experience this, a preprocess_request implementation - #will for now be required for a command to be scaled through service nodes - #If the plugin offers a preprocess method, use it to set the request array - if (defined(${"xCAT_plugin::".$modname."::"}{preprocess_request})) { - $SIG{CHLD}='DEFAULT'; - $reqs = ${"xCAT_plugin::".$modname."::"}{preprocess_request}->($req,$dispatch_cb,\&do_request); - } else { #otherwise, pass it in without hierarchy support - $reqs = [$req]; - } - -# $dispatch_children=0; -# $SIG{CHLD} = \&dispatch_reaper; #sub {my $cpid; while (($cpid =waitpid(-1, WNOHANG)) > 0) { if ($dispatched_children{$cpid}) { delete $dispatched_children{$cpid}; $dispatch_children--; } } }; - my $onlyone=0; - if (defined $reqs and (scalar(@{$reqs}) == 1)) { - $onlyone=1; - } - - foreach (@{$reqs}) { -# my $pfd; -# my $parfd; #use a private variable so it won't trounce itself recursively -# my $child; - delete $_->{noderange}; -#----- added to Client.pm -----# - if ($_->{node}) { - $_->{noderange}->[0]=join(',',@{$_->{node}}); - } -#----- end added to Client.pm -----# - - if (ref $_->{'_xcatdest'} and (ref $_->{'_xcatdest'}) eq 'ARRAY') { - _->{'_xcatdest'} = $_->{'_xcatdest'}->[0]; - } - if ($onlyone and not ($_->{'_xcatdest'} and xCAT::NetworkUtils->thishostisnot($_->{'_xcatdest'}))) { - $SIG{CHLD}='DEFAULT'; - ${"xCAT_plugin::".$modname."::"}{process_request}->($_,$dispatch_cb,\&do_request); - return; - } - -# socketpair($pfd, $parfd,AF_UNIX,SOCK_STREAM,PF_UNSPEC) or die "socketpair: $!"; -# $parfd->autoflush(1); -# $pfd->autoflush(1); -# $child = xCAT::Utils->xfork; -# if ($child) { -# $dispatch_children++; -# $dispatched_children{$child}=1; -# $child_fdset->add($pfd); -# next; -# } -# unless (defined $child) { -# $dispatch_cb->({error=>['Fork failure dispatching request'],errorcode=>[1]}); -# } -# undef $SIG{CHLD}; -# $dispatch_parentfd = $parfd; - my @prexcatdests=(); - my @xcatdests=(); - if (ref($_->{'_xcatdest'}) eq 'ARRAY') { #If array, consider it an 'anycast' operation, broadcast done through dupe - #requests, or an alternative join '&' maybe? - @prexcatdests=@{$_->{'_xcatdest'}}; - } else { - @prexcatdests=($_->{'_xcatdest'}); - } - foreach (@prexcatdests) { - if ($_ and /,/) { - push @xcatdests,split /,/,$_; - } else { - push @xcatdests,$_; - } - } - my $xcatdest; - my $numdests=scalar(@xcatdests); - my $request_satisfied=0; - foreach $xcatdest (@xcatdests) { - my $dlock; - if ($xcatdest and xCAT::NetworkUtils->thishostisnot($xcatdest)) { -#----- added to Client.pm -----# - $dispatch_cb->({warning=>['XCATBYPASS is set, skipping hierarchy call to '.$_->{'_xcatdest'}.'']}); -#----- end added to Client.pm -----# - -# #mkpath("/var/lock/xcat/"); #For now, limit intra-xCAT requests to one at a time, to mitigate DB handle usage -# #open($dlock,">","/var/lock/xcat/dispatchto_$xcatdest"); -# #flock($dlock,LOCK_EX); -# $ENV{XCATHOST} = ($xcatdest =~ /:/ ? $xcatdest : $xcatdest.":3001" ); -# $$progname.=": connection to ".$ENV{XCATHOST}; -# my $errstr; -# eval { -# undef $_->{'_xcatdest'}; -# xCAT::Client::submit_request($_,\&dispatch_callback,$xcatdir."/cert/server-cred.pem",$xcatdir."/cert/server-cred.pem",$xcatdir."/cert/ca.pem"); -# }; -# if ($@) { -# $errstr=$@; -# } -# #unlink("/var/lock/xcat/dispatchto_$xcatdest"); -# #flock($dlock,LOCK_UN); -# if ($errstr) { -# if ($numdests == 1) { -# dispatch_callback({error=>["Unable to dispatch command to ".$ENV{XCATHOST}.", command will not make changes to that server ($errstr)"],errorcode=>[1]}); -# xCAT::MsgUtils->message("S","Error dispatching request to ".$ENV{XCATHOST}.": ".$errstr); -# } else { -# xCAT::MsgUtils->message("S","Error dispatching request to ".$ENV{XCATHOST}.", trying other service nodes: ".$errstr); -# } -# next; -# } else { -# $request_satisfied=1; -# last; -# } - } else { - $$progname.=": locally executing"; - $SIG{CHLD}='DEFAULT'; -# ${"xCAT_plugin::".$modname."::"}{process_request}->($_,\&dispatch_callback,\&do_request); -#----- changed in Client.pm -----# - ${"xCAT_plugin::".$modname."::"}{process_request}->($_,$dispatch_cb,\&do_request); -#----- end changed in Client.pm -----# - last; - } - } -# if ($numdests > 1 and not $request_satisfied) { -# xCAT::MsgUtils->message("S","Error dispatching a request to all possible service nodes for request"); -# dispatch_callback({error=>["Failed to dispatch command to any of the following service nodes: ".join(",",@xcatdests)],errorcode=>[1]}); -# } - -# xexit; - } -#while (($dispatch_children > 0) and ($child_fdset->count > 0)) { relay_dispatch($child_fdset) } -#while (relay_dispatch($child_fdset)) { } #Potentially useless drain. -} - - - -################################### -# do_request -# called from a plugin to execute another xCAT plugin command internally -# -# NOTE: This is copied from xcatd (last merge 11/23/09). -# Will eventually move to using common source.... -################################### -sub do_request { - my $req = shift; - my $second = shift; - my $rsphandler = \&build_response; - my $sock = undef; - if ($second) { - if (ref($second) eq "CODE") { - $rsphandler = $second; - } elsif (ref($second) eq "GLOB") { - $sock = $second; - } - } - - #my $sock = shift; #If no sock, will return a response hash - if ($cmd_handlers{$req->{command}->[0]}) { - return plugin_command($req,$sock,$rsphandler); - } elsif ($req->{command}->[0] eq "noderange" and $req->{noderange}) { - my @nodes = xCAT::NodeRange::noderange($req->{noderange}->[0]); - my %resp; - if (xCAT::NodeRange::nodesmissed()) { - $resp{warning}="Invalid nodes in noderange:".join ',',xCAT::NodeRange::nodesmissed() ."\n"; - } - $resp{serverdone} = {}; - @{$resp{node}}=@nodes; - if ($req->{transid}) { - $resp{transid}=$req->{transid}->[0]; - } - if ($sock) { - print $sock XMLout(\%resp,RootName => 'xcatresponse',NoAttr=>1); - } else { - return (\%resp); - } - } else { - my %resp=(error=>"Unsupported request"); - $resp{serverdone} = {}; - if ($req->{transid}) { - $resp{transid}=$req->{transid}->[0]; - } - if ($sock) { - print $sock XMLout(\%resp,RootName => 'xcatresponse',NoAttr=>1); - } else { - return (\%resp); - } - } -} - - -################################### -# build_response -# This callback handles responses from nested level plugin calls. -# It builds a merged hash of all responses that gets passed back -# to the calling plugin. -# Note: Need to create a "deep clone" of this response to add to the -# return, otherwise next time through the referenced data is overwritten -# -################################### -sub build_response { - my $rsp = shift; - require Storable; - foreach (keys %$rsp) { - my $subresp = Storable::dclone($rsp->{$_}); - push (@{$Main::resps->{$_}}, @{$subresp}); - } -} - - - -} # end of submit_request() - -#################################### -# populates all the site attributes into %::XCATSITEVALS -# This is used with XCATBYPASS=1 -################################### -sub populate_site_hash { - %::XCATSITEVALS=(); - my $sitetab = xCAT::Table->new('site',-create=>0); - unless ($sitetab) { - print ("ERROR: Unable to open basic site table for configuration\n"); - return; - } - my @records = $sitetab->getAllAttribs(qw/key value/); - foreach (@records) { - $::XCATSITEVALS{$_->{key}}=$_->{value}; - } -} - - - -########################################## -# handle_response is a default callback that can be passed into submit_request() -# It is invoked repeatedly by submit_request() to print out the data returned by -# the plugin. -# -# The normal flow is: -# -> client cmd (e.g. nodels, which is just a link to xcatclient) -# -> xcatclient -# -> submit_request() -# -> send xml request to xcatd -# -> xcatd -# -> process_request() of the plugin -# <- plugin callback -# <- xcatd -# <- xcatd sends xml response to client -# <- submit_request() read response -# <- handle_response() prints responses and saves exit codes -# <- xcatclient gets exit code and exits -# -# But in XCATBYPASS mode, the flow is: -# -> client cmd (e.g. nodels, which is just a link to xcatclient) -# -> xcatclient -# -> submit_request() -# -> process_request() of the plugin -# <- handle_response() prints responses and saves exit codes -# <- xcatclient gets exit code and exits -# -# Format of the response hash: -# {data => [ 'data str1', 'data str2', '...' ] } -# -# Results are printed as: -# data str1 -# data str2 -# -# or: -# {data => [ {desc => [ 'desc1' ], -# contents => [ 'contents1' ] }, -# {desc => [ 'desc2 ], -# contents => [ 'contents2' ] } -# : -# ] } -# NOTE: In this format, only the data array can have more than one -# element. All other arrays are assumed to be a single element. -# Results are printed as: -# desc1: contents1 -# desc2: contents2 -# -# or: -# {node => [ {name => ['node1'], -# data => [ {desc => [ 'node1 desc' ], -# contents => [ 'node1 contents' ] } ] }, -# {name => ['node2'], -# data => [ {desc => [ 'node2 desc' ], -# contents => [ 'node2 contents' ] } ] }, -# : -# ] } -# NOTE: Only the node array can have more than one element. -# All other arrays are assumed to be a single element. -# -# This was generated from the corresponding XML: -# -# -# node1 -# -# node1 desc -# node1 contents -# -# -# -# node2 -# -# node2 desc -# node2 contents -# -# -# -# -# Results are printed as: -# node_name: desc: contents -########################################## -sub handle_response { - my $rsp = shift; - if ($ENV{'XCATSHOWXML'}) { - my $xmlrec=XMLout($rsp,RootName=>'xcatresponse',NoAttr=>1,KeyAttr=>[]); - print "$xmlrec\n"; - return; - } -#print "in handle_response\n"; - # Handle errors - if (defined($rsp->{errorcode})) { - if (ref($rsp->{errorcode}) eq 'ARRAY') { - foreach my $ecode (@{$rsp->{errorcode}}) { - $xCAT::Client::EXITCODE |= $ecode; - } - } - else { - $xCAT::Client::EXITCODE |= $rsp->{errorcode}; - } # assume it is a non-reference scalar - } - if ($rsp->{error}) { -#print "printing error\n"; - if (ref($rsp->{error}) eq 'ARRAY') { - foreach my $text (@{$rsp->{error}}) { - if ($rsp->{NoErrorPrefix}) { - print STDERR "$text\n"; - } else { - print STDERR "Error: $text\n"; - } - } - } - else { - if ($rsp->{NoErrorPrefix}) { - print STDERR ($rsp->{error}."\n"); - } else { - print STDERR ("Error: ".$rsp->{error}."\n"); - } - } - } - if ($rsp->{warning}) { -#print "printing warning\n"; - if (ref($rsp->{warning}) eq 'ARRAY') { - foreach my $text (@{$rsp->{warning}}) { - if ($rsp->{NoWarnPrefix}) { - print STDERR "$text\n"; - } else { - print STDERR "Warning: $text\n"; - } - } - } - else { - if ($rsp->{NoWarnPrefix}) { - print STDERR ($rsp->{warning}."\n"); - } else { - print STDERR ("Warning: ".$rsp->{warning}."\n"); - } - } - } - if ($rsp->{info}) { -#print "printing info\n"; - if (ref($rsp->{info}) eq 'ARRAY') { - foreach my $text (@{$rsp->{info}}) { - print "$text\n"; - } - } - else { - print ($rsp->{info}."\n"); - } - } - - if ($rsp->{sinfo}) { - if (ref($rsp->{sinfo}) eq 'ARRAY') { - foreach my $text (@{$rsp->{sinfo}}) { - print "$text\r"; $|++; - } - } - else { - print ($rsp->{sinfo}."\r"); $|++; - } - } - - - - # Handle {node} structure - my $errflg=0; - my $nodes=($rsp->{node}); - unless (ref $nodes eq 'ARRAY') { - $nodes = [$nodes]; - } - if (scalar @{$nodes}) { -#print "printing node\n"; - my $node; - foreach $node (@$nodes) { - my $desc; - if (ref($node->{name}) eq 'ARRAY') { - $desc=$node->{name}->[0]; - } else { - $desc=$node->{name}; - } - if ($node->{errorcode}) { - if (ref($node->{errorcode}) eq 'ARRAY') { - foreach my $ecode (@{$node->{errorcode}}) { - $xCAT::Client::EXITCODE |= $ecode; - } - } - else { - $xCAT::Client::EXITCODE |= $node->{errorcode}; - } # assume it is a non-reference scalar - } - if ($node->{error}) { - $desc.=": Error: ".$node->{error}->[0]; - $errflg=1; - } - if ($node->{warning}) { - $desc.=": Warning: ".$node->{warning}->[0]; - $errflg=1; - } - if ($node->{data}) { - if (ref(\($node->{data})) eq 'SCALAR') { - $desc=$desc.": ".$node->{data}; - } elsif (ref($node->{data}) eq 'HASH') { - if ($node->{data}->{desc}) { - if (ref($node->{data}->{desc}) eq 'ARRAY') { - $desc=$desc.": ".$node->{data}->{desc}->[0]; - } else { - $desc=$desc.": ".$node->{data}->{desc}; - } - } - if ($node->{data}->{contents}) { - if (ref($node->{data}->{contents}) eq 'ARRAY') { - $desc="$desc: ".$node->{data}->{contents}->[0]; - } else { - $desc="$desc: ".$node->{data}->{contents}; - } - } - } elsif (ref(\($node->{data}->[0])) eq 'SCALAR') { - $desc=$desc.": ".$node->{data}->[0]; - } else { - if ($node->{data}->[0]->{desc}) { - $desc=$desc.": ".$node->{data}->[0]->{desc}->[0]; - } - if ($node->{data}->[0]->{contents}) { - $desc="$desc: ".$node->{data}->[0]->{contents}->[0]; - } - } - } - if ($desc) { - if ($errflg == 1) { - print STDERR ("$desc\n"); - } else { - print "$desc\n"; - } - } - } - } - - # Handle {data} structure with no nodes - if ($rsp->{data}) { -#print "printing data\n"; - my $data=($rsp->{data}); - my $data_entry; - foreach $data_entry (@$data) { - my $desc; - if (ref(\($data_entry)) eq 'SCALAR') { - $desc=$data_entry; - } else { - if ($data_entry->{desc}) { - $desc=$data_entry->{desc}->[0]; - } - if ($data_entry->{contents}) { - if ($desc) { - $desc="$desc: ".$data_entry->{contents}->[0]; - } else { - $desc=$data_entry->{contents}->[0]; - } - } - } - if ($desc) { print "$desc\n"; } - } - } -} # end of handle_response - - - - - - diff --git a/xCAT-server/lib/xcat/plugins/imgcapture.pm b/xCAT-server/lib/xcat/plugins/imgcapture.pm index bd4f881de..f0aa71fc9 100644 --- a/xCAT-server/lib/xcat/plugins/imgcapture.pm +++ b/xCAT-server/lib/xcat/plugins/imgcapture.pm @@ -123,7 +123,7 @@ sub process_request { # Handle image capture separately for s390x if ($arch eq 's390x') { eval { require xCAT_plugin::zvm; }; # Load z/VM plugin dynamically - xCAT_plugin::zvm->imageCapture($callback, $node, $os, $arch, $profile, $osimg, $device); + xCAT_plugin::zvm->imageCapture($callback, $node, $os, $arch, $type, $profile, $osimg, $device); return; } diff --git a/xCAT-server/lib/xcat/plugins/imgport.pm b/xCAT-server/lib/xcat/plugins/imgport.pm index 9e3e2af9a..e09706659 100644 --- a/xCAT-server/lib/xcat/plugins/imgport.pm +++ b/xCAT-server/lib/xcat/plugins/imgport.pm @@ -174,8 +174,15 @@ sub xexport { my $dest = shift @ARGV; my $cwd = $request->{cwd}; #getcwd; $cwd = $cwd->[0]; + + if (!defined $remoteHost) { + $callback->( {data => ["Exporting $img_name to $cwd..."]}); + } + else { + $callback->( {data => ["Exporting $img_name to $remoteHost..."]}); + } - $callback->( {data => ["Exporting $img_name to $cwd..."]}); + # check if all files are in place my $attrs = get_image_info($img_name, $callback, $node, @extra); #print Dumper($attrs); @@ -237,11 +244,16 @@ sub get_image_info { $errors++; } - unless($attrs0->{provmethod} =~ /install|netboot|statelite|raw/){ + unless($attrs0->{provmethod} =~ /install|netboot|statelite|raw|sysclone/){ $callback->({error=>["Exporting images with 'provemethod' " . $attrs0->{provmethod} . " is not supported. Hint: install, netboot, statelite, or raw"], errorcode=>[1]}); $errors++; } - + + if (($attrs0->{provmethod} =~ /sysclone/) && ($attrs0->{osarch} !~ /s390x/)) { + $callback->({error=>["Exporting images with 'provemethod' " . $attrs0->{provmethod} . " is not supported for osarch '" . $attrs0->{osarch} ."'"], errorcode=>[1]}); + $errors++; + } + #$attrs->{imagename} = $imagename; if($errors){ @@ -438,7 +450,7 @@ sub get_files{ my @files; my $dir = "$installroot/netboot/$osvers/s390x/$profile"; opendir(DIR, $dir) or $callback->({error=>["Could not open image files in directory $dir"], errorcode=>[1]}); - + while (my $file = readdir(DIR)) { # We only want files in the directory that end with .img next unless (-f "$dir/$file"); @@ -449,7 +461,7 @@ sub get_files{ if (@files) { $attrs->{rawimagefiles}->{files} = [@files]; } - + closedir(DIR); } else { @@ -465,7 +477,7 @@ sub get_files{ $attrs->{linuximage}->{pkglist} = $temp; } } - + @arr = ("$installroot/netboot"); my $rootimgdir=$attrs->{linuximage}->{rootimgdir}; my $ramdisk; @@ -489,27 +501,27 @@ sub get_files{ $rootimg = look_for_file('rootimg.gz', $callback, $attrs, @arr); } unless($ramdisk){ - $callback->({error=>["Couldn't find ramdisk (initrd-stateless.gz) for $imagename"],errorcode=>[1]}); - $errors++; - }else{ - $attrs->{ramdisk} = $ramdisk; - } + $callback->({error=>["Couldn't find ramdisk (initrd-stateless.gz) for $imagename"],errorcode=>[1]}); + $errors++; + }else{ + $attrs->{ramdisk} = $ramdisk; + } unless($kernel){ - $callback->({error=>["Couldn't find kernel (kernel) for $imagename"],errorcode=>[1]}); - $errors++; - }else{ - $attrs->{kernel} = $kernel; - } + $callback->({error=>["Couldn't find kernel (kernel) for $imagename"],errorcode=>[1]}); + $errors++; + }else{ + $attrs->{kernel} = $kernel; + } unless($rootimg){ - $callback->({error=>["Couldn't find rootimg (rootimg.gz) for $imagename"],errorcode=>[1]}); - $errors++; - }else{ - $attrs->{rootimg} = $rootimg; - } - } - } elsif ($provmethod =~ /statelite/) { + $callback->({error=>["Couldn't find rootimg (rootimg.gz) for $imagename"],errorcode=>[1]}); + $errors++; + }else{ + $attrs->{rootimg} = $rootimg; + } + } + } elsif ($provmethod =~ /statelite/) { @arr = ("$installroot/custom/netboot", "$xcatroot/share/xcat/netboot"); #get .pkglist file if (! $attrs->{linuximage}->{pkglist}) { @@ -541,24 +553,24 @@ sub get_files{ } unless($kernel){ - $callback->({error=>["Couldn't find kernel (kernel) for $imagename"],errorcode=>[1]}); - $errors++; - }else{ - $attrs->{kernel} = $kernel; - } + $callback->({error=>["Couldn't find kernel (kernel) for $imagename"],errorcode=>[1]}); + $errors++; + }else{ + $attrs->{kernel} = $kernel; + } unless($ramdisk){ - $callback->({error=>["Couldn't find ramdisk (initrd-statelite.gz) for $imagename"],errorcode=>[1]}); - $errors++; - }else{ - $attrs->{ramdisk} = $ramdisk; - } - } + $callback->({error=>["Couldn't find ramdisk (initrd-statelite.gz) for $imagename"],errorcode=>[1]}); + $errors++; + }else{ + $attrs->{ramdisk} = $ramdisk; + } + } } - if (( $provmethod =~ /raw/ ) and ( $arch =~ /s390x/ )) { + if (( $provmethod =~ /raw|sysclone/ ) and ( $arch =~ /s390x/ )) { my @files; - my $dir = "$installroot/raw/$osvers/s390x/$profile"; + my $dir = "$installroot/$provmethod/$osvers/s390x/$profile"; opendir(DIR, $dir) or $callback->({error=>["Could not open image files in directory $dir"], errorcode=>[1]}); while (my $file = readdir(DIR)) { @@ -634,32 +646,52 @@ sub look_for_file { } -# here's where we make the tarball +#------------------------------------------------------- + +=head3 make_bundle + + Description : Makes the image bundle tar ball. + Arguments : Image name from the command line + Destination command line parameter, i.e. name of the tar ball. For a + remote host this can include the target directory. + Remote host parameter from the command line, if specified + Image attributes from the osimage table + callback + Current working directory + Returns : None + Example : make_bundle( $img_name, $dest, $remoteHost, $attrs, $callback, $cwd ); + +=cut + +#------------------------------------------------------- sub make_bundle { my $imagename = shift; my $dest = shift; my $remoteHost = shift; my $attribs = shift; my $callback = shift; - - # tar ball is made in local working directory. Sometimes doing this in /tmp - # is bad. In the case of my development machine, the / filesystem was nearly full. - # so doing it in cwd is easy and predictable. my $dir = shift; - #my $dir = getcwd; + my $rc; + + # Determine the local working directory. It could be specified in the site table + # or we will default to the current working directory which was passed to this routine. + my @siteEntries = xCAT::TableUtils->get_site_attribute("tmpdir"); + my $workDir = $siteEntries[0]; + if (!$workDir) { + $workDir = $dir; + } # get rid of spaces and put in underlines. $imagename =~ s/\s+/_/g; - # we may find that cwd doesn't work, so we use the request cwd. - my $ttpath = mkdtemp("$dir/imgexport.$$.XXXXXX"); + # Create the directory in which we collect the files prior to tarring them. + my $ttpath = mkdtemp("$workDir/imgexport.$$.XXXXXX"); $callback->({data=>["Creating $ttpath..."]}) if $::VERBOSE; my $tpath = "$ttpath/$imagename"; mkdir("$tpath"); chmod 0755,$tpath; - #for statelite if ($attribs->{osimage}->{provmethod} eq 'statelite') { #copy the rootimgdir over @@ -670,6 +702,10 @@ sub make_bundle { $attribs->{'rootimgtree'} = "$rootimgdir/rootimgtree.gz"; } else { $callback->({error=>["Couldn't locate the root image directory. "],errorcode=>[1]}); + $rc = system("rm -rf $ttpath"); + if ($rc) { + $callback->({error=>["Failed to clean up temp space $ttpath"],errorcode=>[1]}); + } return 0; } @@ -677,6 +713,10 @@ sub make_bundle { my $lftab= xCAT::Table->new("litefile" ,-create=>1); if (!$lftab) { $callback->({error=>["Could not open the litefile table."],errorcode=>[1]}); + $rc = system("rm -rf $ttpath"); + if ($rc) { + $callback->({error=>["Failed to clean up temp space $ttpath"],errorcode=>[1]}); + } return 0; } @@ -777,7 +817,7 @@ sub make_bundle { # Copy any raw image files. Multiple files can exist (used by s390x) if ($attribs->{rawimagefiles}->{files}) { foreach my $fromf (@{$attribs->{rawimagefiles}->{files}}) { - my $rc = system("cp $fromf $tpath"); + $rc = system("cp $fromf $tpath"); if ($rc != 0) { $callback->({error=>["Unable to copy the raw image file $fromf."], errorcode=>[1]}); $rc = system("rm -rf $ttpath"); @@ -806,30 +846,39 @@ sub make_bundle { } } - # If this is an export to a remote host then split the destination into the - # remote directory portion and the name of the export bundle. - my $remoteDest; - if (defined $remoteHost) { - $remoteDest = $dest; - if (defined $dest) { - $dest = (split( '/', $dest))[-1]; - } - } - # now get right below all this stuff and tar it up. chdir($ttpath); $callback->( {data => ["Inside $ttpath."]}); - unless($dest){ - $dest = "$dir/$imagename.tgz"; - } - # if no absolute path specified put it in the cwd - unless($dest =~ /^\//){ - $dest = "$dir/$dest"; + # Determine the name of the bundle that we will create. + my ($bundleName, $destDir); + if (defined $dest) { + ($bundleName, $destDir) = fileparse($dest); + if ($bundleName eq '') { + $bundleName="$imagename.tgz"; + } + } else { + $bundleName="$imagename.tgz"; + } + + + # Determine the full file specification of the image bundle. + my $remoteDest; + my $tempBundle; + if (defined $remoteHost) { + # For a remote host, we need both a local build bundle + # and the final remote bundle file specification. + $tempBundle = mktemp("$workDir/imgexport.$$.XXXXXX"); + chomp($tempBundle); + $dest = $tempBundle; + $remoteDest = "$destDir$bundleName"; + } + else { + # Local imgexports go to the current working directory + $dest = "$dir/$bundleName"; } $callback->( {data => ["Compressing $imagename bundle. Please be patient."]}); - my $rc; if($::VERBOSE){ $callback->({data => ["tar czvf $dest . "]}); $rc = system("tar czvf $dest . "); @@ -854,28 +903,48 @@ sub make_bundle { if (defined $remoteHost) { my $remoteFile = $remoteHost . ':' . $remoteDest; - $callback->({data=>["Moving the image bundle to the remote system"]}); + $callback->({data=>["Moving the image bundle to the remote system location $remoteDest"]}); $rc = system("/usr/bin/scp -B $dest $remoteFile"); if ($rc) { - $callback->({error=>["Unable to copy the image bundle to the remote host"], errorcode=>[1]}); - } - - # Remove the image bundle that was sent to the remote system. - $rc = system("rm $dest"); - if ($rc) { - $callback->({error=>["Failed to clean up image bundle $dest"], errorcode=>[1]}); + $callback->({error=>["Unable to copy the image bundle $bundleName to the remote host"], errorcode=>[1]}); } } } - chdir($dir); + # Remove the temporary image bundle if it is still around (for remote exports). + if (-e $tempBundle) { + $rc = system("rm -f $tempBundle"); + if ($rc) { + $callback->({error=>["Failed to clean up the temporary image bundle $tempBundle"], errorcode=>[1]}); + } + } + + # Remove the directory that we used to collect the files prior to creating the tar ball. + chdir($dir); $rc = system("rm -rf $ttpath"); if ($rc) { $callback->({error=>["Failed to clean up temp space $ttpath"],errorcode=>[1]}); - return; - } + } + + return; } +#------------------------------------------------------- + +=head3 extract_bundle + + Description : Extract the files from the image tar ball. + Arguments : Request + callback + nodes + New profile name to use for the image, if specified. + Remote host parameter from the command line + Returns : None + Example : extract_bundle( $request, $callback, $nodes, $new_profile, $remoteHost ); + +=cut + +#------------------------------------------------------- sub extract_bundle { my $request = shift; #print Dumper($request); @@ -889,31 +958,43 @@ sub extract_bundle { my $data; my $datas; my $error = 0; + my $bundleCopy; my $bundle = shift @ARGV; - # extract the image in temp path in cwd + # Determine the current working directory. my $dir = $request->{cwd}; #getcwd; $dir = $dir->[0]; #print Dumper($dir); - # If we have a remote file then move it to the xCAT MN + # A working directory will hold the temporary image directory. + # It will also hold the local copy of a remote image bundle. + # The directory can be defined in the site table and if not + # defined there then we will default to using the current working + # directory. + my @siteEntries = xCAT::TableUtils->get_site_attribute("tmpdir"); + my $workDir = $siteEntries[0]; + if (!$workDir) { + $workDir = $dir; + } + + # If we have a remote file then transfer it to the xCAT MN first. if (defined $remoteHost) { - # Create unique directory for the bundle and copy the bundle to it + # Create unique copy the remote bundle in the working directory my $remoteFile = "$remoteHost:$bundle"; - $dir = `/bin/mktemp -d /var/tmp/XXXXXX`; - chomp($dir); - $bundle = $dir . '/' . (split( '/', $bundle))[-1]; + $bundleCopy = `/bin/mktemp $workDir/imgimport.$$.XXXXXX`; + chomp($bundleCopy); $callback->({data=>["Obtaining the image bundle from the remote system"]}); - my $rc = system("/usr/bin/scp -v -B $remoteFile $dir"); + my $rc = system("/usr/bin/scp -v -B $remoteFile $bundleCopy"); if ($rc != 0) { - $callback->({error=>["Unable to copy the image bundle from the remote host"], errorcode=>[1]}); - $rc = rmtree $dir; - if (! $rc) { - $callback->({error=>["Failed to clean up directory containing the remote image bundle $bundle"], errorcode=>[1]}); + $callback->({error=>["Unable to copy the image bundle $bundle from the remote host"], errorcode=>[1]}); + $rc = system("rm -rf $bundleCopy"); + if ($rc) { + $callback->({error=>["Failed to remove the local copy of the remote image bundle $bundleCopy"], errorcode=>[1]}); } return; } + $bundle = $bundleCopy; } else { # When we are not doing a remote copy, we need to verify the bundle exists and find its exact location unless(-r $bundle){ @@ -936,7 +1017,7 @@ sub extract_bundle { } } - my $tpath = mkdtemp("$dir/imgimport.$$.XXXXXX"); + my $tpath = mkdtemp("$workDir/imgimport.$$.XXXXXX"); $callback->({data=>["Unbundling image..."]}); my $rc; @@ -949,6 +1030,9 @@ sub extract_bundle { if ($rc) { $callback->({error => ["Failed to extract bundle $bundle"],errorcode=>[1]}); + # Remove the files in the untar directory so that we don't attempt to process + # a partially untarred image bundle. + system("rm -rf $tpath"); } # get all the files in the tpath. These should be all the image names. @@ -956,97 +1040,85 @@ sub extract_bundle { # go through each image directory. Find the XML and put it into the array. If there are any # errors then the whole thing is over and we error and leave. foreach my $imgdir (@files){ - unless(-r "$imgdir/manifest.xml"){ - $callback->({error=>["Failed to find manifest.xml file in image bundle"],errorcode=>[1]}); - if (defined $remoteHost) { - $rc = rmtree $dir; - if ( ! $rc ) { - $callback->({error=>["Failed to clean up directory containing the remote image bundle $bundle"], errorcode=>[1]}); - } - } - return; - } - $xml = new XML::Simple; - # get the data! - # put it in an eval string so that it - $data = eval { $xml->XMLin("$imgdir/manifest.xml") }; - if($@){ - $callback->({error=>["invalid manifest.xml file inside the bundle. Please verify the XML"],errorcode=>[1]}); - #my $foo = $@; - #$foo =~ s/\n//; - #$callback->({error=>[$foo],errorcode=>[1]}); - #foreach($@){ - # last; - #} - # If this was an import from a remote host then remove the directory created for the remote files. - # We do not want to leave files hanging around that were brought from another system. - if (defined $remoteHost) { - $rc = rmtree $dir; - if ( ! $rc ) { - $callback->({error=>["Failed to clean up directory containing the remote image bundle $bundle"], errorcode=>[1]}); - } - } - return; - } - #print Dumper($data); - #push @{$datas}, $data; - - # now we need to import the files... - unless(verify_manifest($data, $callback)){ - $error++; - next; + unless(-r "$imgdir/manifest.xml"){ + $callback->({error=>["Failed to find manifest.xml file in image bundle"],errorcode=>[1]}); + last; + } + + $xml = new XML::Simple; + # get the data! + # put it in an eval string so that it + $data = eval { $xml->XMLin("$imgdir/manifest.xml") }; + if($@){ + $callback->({error=>["invalid manifest.xml file inside the bundle. Please verify the XML"],errorcode=>[1]}); + #my $foo = $@; + #$foo =~ s/\n//; + #$callback->({error=>[$foo],errorcode=>[1]}); + #foreach($@){ + # last; + #} + last; + } + #print Dumper($data); + #push @{$datas}, $data; + + # now we need to import the files... + unless(verify_manifest($data, $callback)){ + $error++; + next; + } + + # check media first + unless(check_media($data, $callback)){ + $error++; + next; + } + + #change profile name if needed + if ($new_profile) { + $data=change_profile($data, $callback, $new_profile, $imgdir); + } + + #import manifest.xml into xCAT database + unless(set_config($data, $callback)){ + $error++; + next; + } + + # now place files in appropriate directories. + unless(make_files($data, $imgdir, $callback)){ + $error++; + next; + } + + # put postscripts in the postsctipts table + if ($nodes) { + unless(set_postscripts($data, $callback, $nodes)){ + $error++; + next; + } + } + + my $osimage = $data->{osimage}->{imagename}; + $callback->({data=>["Successfully imported the image $osimage."]}); } - # check media first - unless(check_media($data, $callback)){ - $error++; - next; - } - - #change profile name if needed - if ($new_profile) { - $data=change_profile($data, $callback, $new_profile, $imgdir); - } - - #import manifest.xml into xCAT database - unless(set_config($data, $callback)){ - $error++; - next; - } - - # now place files in appropriate directories. - unless(make_files($data, $imgdir, $callback)){ - $error++; - next; - } - - # put postscripts in the postsctipts table - if ($nodes) { - unless(set_postscripts($data, $callback, $nodes)){ - $error++; - next; - } - } - - my $osimage = $data->{osimage}->{imagename}; - $callback->({data=>["Successfully imported the image $osimage."]}); - } - - # remove temp file only if there were no problems. - unless($error){ + # Clean up for this routine. + # Remove the temp directory used for the exploded bundle + if ( -e $tpath ) { $rc = system("rm -rf $tpath"); if ($rc) { $callback->({error=>["Failed to clean up temp space $tpath"],errorcode=>[1]}); - return; - } + # Don't return just yet. We want the rest of the cleanup to occur. + } } - + # If this was an import from a remote host then remove the directory created for the remote files. # We do not want to leave files hanging around that were brought from another system. - if ( defined $remoteHost ) { - $rc = rmtree $dir; - if ( ! $rc ) { - $callback->({error=>["Failed to clean up directory containing the remote image bundle $bundle"],errorcode=>[1]}); + if ( -e $bundleCopy ) { + $rc = system("rm -rf $bundleCopy"); + if ($rc) { + $callback->({error=>["Failed to remove the local copy of the remote image bundle $bundleCopy"], errorcode=>[1]}); } } } @@ -1068,7 +1140,11 @@ sub change_profile { $installdir = '/install'; } if ($data->{linuximage}->{rootimgdir}) { - $data->{linuximage}->{rootimgdir}="$installdir/netboot/" . $data->{osimage}->{osvers} . "/" . $data->{osimage}->{osarch} . "/$new_profile"; + if (($data->{osimage}->{osarch} eq "s390x") && ($data->{osimage}->{provmethod} =~ /raw|sysclone/)) { + $data->{linuximage}->{rootimgdir}="$installdir/$data->{osimage}->{provmethod}/" . $data->{osimage}->{osvers} . "/" . $data->{osimage}->{osarch} . "/$new_profile"; + } else { + $data->{linuximage}->{rootimgdir}="$installdir/netboot/" . $data->{osimage}->{osvers} . "/" . $data->{osimage}->{osarch} . "/$new_profile"; + } for my $a ("kernel", "ramdisk", "rootimg", "rootimgtree", "litefile") { if ($data->{$a}) { @@ -1325,8 +1401,12 @@ sub verify_manifest { } $data->{osimage}->{osarch} =~ s/^\s*(\S*)\s*$/$1/; - unless($data->{osimage}->{provmethod} =~ /install|netboot|statelite|raw/){ - $callback->({error=>["Importing images with 'provemethod' " . $data->{osimage}->{provmethod} . " is not supported. Hint: install, netboot, statelite, or raw"],errorcode=>[1]}); + unless($data->{osimage}->{provmethod} =~ /install|netboot|statelite|sysclone|raw/){ + $callback->({error=>["Importing images with 'provmethod' " . $data->{osimage}->{provmethod} . " is not supported. Hint: install, netboot, statelite, sysclone or raw"],errorcode=>[1]}); + $errors++; + } + if (($data->{osimage}->{provmethod} =~ /sysclone/) && ($data->{osimage}->{osarch} !~ /s390x/)) { + $callback->({error=>["Importing images with 'provemethod' " . $data->{osimage}->{provmethod} . " is not supported for osarch '" . $data->{osimage}->{osarch} ."'"], errorcode=>[1]}); $errors++; } $data->{osimage}->{provmethod} =~ s/^\s*(\S*)\s*$/$1/; @@ -1344,18 +1424,28 @@ sub verify_manifest { $callback->({info => ['this is an esx image']}); # do nothing for ESX 1; - } elsif (($data->{osimage}->{provmethod} =~ /netboot/) and ($data->{osimage}->{osarch} !~ /s390x/)) { - unless($data->{ramdisk}){ - $callback->({error=>["The 'ramdisk' field is not defined in manifest.xml."],errorcode=>[1]}); - $errors++; - } - unless($data->{kernel}){ - $callback->({error=>["The 'kernel' field is not defined in manifest.xml."],errorcode=>[1]}); - $errors++; - } - unless($data->{rootimg}){ - $callback->({error=>["The 'rootimg' field is not defined in manifest.xml."],errorcode=>[1]}); - $errors++; + } elsif ($data->{osimage}->{provmethod} =~ /netboot/) { + if ($data->{osimage}->{osarch} =~ /s390x/) { + if (!$data->{rawimagefiles}) { + $callback->({error=>["The 'rawimagefiles' section is not defined in manifest.xml."],errorcode=>[1]}); + $errors++; + } elsif (!$data->{rawimagefiles}->{files}) { + $callback->({error=>["'files' were not specified in the 'rawimagefiles' section of manifest.xml."],errorcode=>[1]}); + $errors++; + } + } else { + unless($data->{ramdisk}){ + $callback->({error=>["The 'ramdisk' field is not defined in manifest.xml."],errorcode=>[1]}); + $errors++; + } + unless($data->{kernel}){ + $callback->({error=>["The 'kernel' field is not defined in manifest.xml."],errorcode=>[1]}); + $errors++; + } + unless($data->{rootimg}){ + $callback->({error=>["The 'rootimg' field is not defined in manifest.xml."],errorcode=>[1]}); + $errors++; + } } }elsif($data->{osimage}->{provmethod} =~ /statelite/){ @@ -1372,6 +1462,16 @@ sub verify_manifest { $errors++; } + } elsif ($data->{osimage}->{provmethod} =~ /sysclone/) { + if ($data->{osimage}->{osarch} =~ /s390x/) { + if (!$data->{rawimagefiles}) { + $callback->({error=>["The 'rawimagefiles' section is not defined in manifest.xml."],errorcode=>[1]}); + $errors++; + } elsif (!$data->{rawimagefiles}->{files}) { + $callback->({error=>["'files' were not specified in the 'rawimagefiles' section of manifest.xml."],errorcode=>[1]}); + $errors++; + } + } } if($errors){ @@ -1565,7 +1665,7 @@ sub make_files { $callback->( {data => ["Updating the litefile table."]}); my $fn=$data->{litefile}; if (!$fn) { - $callback->({error=>["Could not find liefile.csv."],errorcode=>[1]}); + $callback->({error=>["Could not find litefile.csv."],errorcode=>[1]}); return 1; } elsif (! -r $fn) { $callback->({error=>["Could not find $fn."],errorcode=>[1]}); @@ -1592,11 +1692,11 @@ sub make_files { close(FILE); $lftab->commit; - $callback->( {data => ["The litetree and statelite talbes are untouched. You can update them if needed."]}); + $callback->( {data => ["The litetree and statelite tables are untouched. You can update them if needed."]}); } # For s390x copy all image files from the root bundle directory to the repository location - if (($data->{osimage}->{osarch} =~ /s390x/) && (($data->{osimage}->{provmethod} =~ /raw/) || ($data->{osimage}->{provmethod} =~ /netboot/))) { + if (($data->{osimage}->{osarch} =~ /s390x/) && ($data->{osimage}->{provmethod} =~ /raw|netboot|sysclone/)) { my $reposImgDir = "$installroot/$data->{osimage}->{provmethod}/$data->{osimage}->{osvers}/$data->{osimage}->{osarch}/$data->{osimage}->{profile}"; mkpath($reposImgDir); diff --git a/xCAT-server/lib/xcat/plugins/rmimage.pm b/xCAT-server/lib/xcat/plugins/rmimage.pm index a22c50e06..3125cbc4c 100644 --- a/xCAT-server/lib/xcat/plugins/rmimage.pm +++ b/xCAT-server/lib/xcat/plugins/rmimage.pm @@ -105,8 +105,8 @@ sub process_request { if($verbose) { $callback->({info=>["For osimage $imagename: osver = $osver, arch = $arch, profile = $profile, method = $method in osimage table"]}); } - if (($method) && ($method ne "netboot") && ($method ne "statelite") && ($method ne "raw")) { - $callback->({error=>["Invalid method \"$method\", the rmimage command can only be used to remove the netboot, statelite, or raw image files"], errorcode=>[1]}); + if (($method) && ($method ne "netboot") && ($method ne "statelite") && ($method ne "raw") && ($method ne "sysclone")) { + $callback->({error=>["Invalid method \"$method\", the rmimage command can only be used to remove the netboot, statelite, sysclone or raw image files"], errorcode=>[1]}); return; } @@ -136,23 +136,31 @@ sub process_request { $callback->({error=>["Invalid image name $imagename"],errorcode=>[1]}); return; } - if (($method ne "netboot") && ($method ne "statelite") && ($method ne "raw")) { - $callback->({error=>["Invalid method \"$method\", the rmimage command can only be used to remove the netboot, statelite, or raw image files"], errorcode=>[1]}); + if (($method ne "netboot") && ($method ne "statelite") && ($method ne "raw") && ($method ne "sysclone")) { + $callback->({error=>["Invalid method \"$method\", the rmimage command can only be used to remove the netboot, statelite, sysclone or raw image files"], errorcode=>[1]}); return; } } - - if ($method eq "raw") { - $imagedir = "$installroot/$method/$osver/$arch/$profile"; + + if ($arch eq "s390x") { + if (($method eq "raw") || ($method eq "sysclone")) { + $imagedir = "$installroot/$method/$osver/$arch/$profile"; + } else { + $imagedir = "$installroot/netboot/$osver/$arch/$profile"; + } } else { $imagedir = "$installroot/netboot/$osver/$arch/$profile"; } } } else { # imagename is not specified - if ($method eq "raw") { - $imagedir = "$installroot/$method/$osver/$arch/$profile"; + if ($arch eq "s390x") { + if (($method eq "raw") || ($method eq "sysclone")) { + $imagedir = "$installroot/$method/$osver/$arch/$profile"; + } else { + $imagedir = "$installroot/netboot/$osver/$arch/$profile"; + } } else { - $imagedir = "$installroot/netboot/$osver/$arch/$profile"; + $imagedir = "$installroot/netboot/$osver/$arch/$profile"; } } @@ -164,7 +172,14 @@ sub process_request { $callback->({error=>["Image directory $imagedir does not exist"],errorcode=>[1]}); return; } - + + # Doing this extra check now because we now have a method and arch from either the node or the image name. + if (($method eq "sysclone") && ($arch ne "s390x")) { + # Only supporting removing sysclone images for s390x at this time. + $callback->({error=>["rmimage cannot be used to remove sysclone images for \"$arch\" architecture"], errorcode=>[1]}); + return; + } + my @filestoremove = ("$imagedir/rootimg.gz", "$imagedir/kernel", "$imagedir/initrd-stateless.gz", "$imagedir/initrd-statelite.gz"); #some rpms like atftp mount the rootimg/proc to /proc, we need to make sure rootimg/proc is free of junk @@ -196,7 +211,7 @@ sub process_request { } # For s390x, remove the image directory. - if (($arch eq "s390x") && (-d "$imagedir") && (($method eq "raw") || ($method eq "netboot"))) { + if (($arch eq "s390x") && (-d "$imagedir") && (($method eq "raw") || ($method eq "netboot") || ($method eq "sysclone"))) { $callback->({info=>["Removing directory $imagedir"]}); rmtree "$imagedir"; } diff --git a/xCAT-server/share/xcat/scripts/xcatconf4z b/xCAT-server/share/xcat/scripts/xcatconf4z index 605433dfa..83eb026de 100644 --- a/xCAT-server/share/xcat/scripts/xcatconf4z +++ b/xCAT-server/share/xcat/scripts/xcatconf4z @@ -1,5 +1,4 @@ #!/bin/sh -# IBM(c) 2013 EPL license http://www.eclipse.org/legal/epl-v10.html ### BEGIN INIT INFO # Provides: xcatconf4z @@ -181,16 +180,20 @@ function setupIso { # @Output: # None # @Code: - # Create ISO based on transport directory iso="/var/opt/xcat/transport.iso" - /usr/bin/mkisofs -l -o $iso $transportdir - # Create loop back device pointing to ISO9660 image - nextLoopDev=`/sbin/losetup -f` - if [[ -n $nextLoopDev ]]; then - /sbin/losetup $nextLoopDev $iso - else - return + # If there are files in the transport directory then create an ISO system. + if [ "$(ls -A .)" ]; then + /usr/bin/mkisofs -l -o $iso $transportdir + fi + + # If the ISO filesystem exists then create loop back device pointing + # to the ISO9660 image + if [[ -e $iso ]]; then + nextLoopDev=`/sbin/losetup -f` + if [[ -n $nextLoopDev ]]; then + /sbin/losetup $nextLoopDev $iso + fi fi # Execute init script (if one exists) @@ -263,18 +266,20 @@ function setupDisk { return fi - out=`stat -L --printf=%t:%T $xcat_srcFile` + out=`/usr/bin/stat --printf=%n ${xcat_srcFile}` if (( $? != 0 )); then echo "xcatconf4z $funcName (Error) Unable to stat the source file: $xcat_srcFile" return fi - major=${out%:*} - major=$(echo ${major} | sed -e 's/^ *//g') - minor=${out#*:} - minor=$(echo ${minor} | sed -e 's/^ *//g') + configFile='/etc/udev/rules.d/56-zfcp.rules' + tgtNode=$(echo ${xcat_tgtFile} | sed -e 's/^\/dev\///') + wwpn_lun=$(echo ${xcat_srcFile} | sed -e 's/^\/dev.*-zfcp-//') + wwpn=$(echo ${wwpn_lun} | sed -e 's/:0x.*//') + lun=$(echo ${wwpn_lun} | sed -e 's/^0x.*://') - mknod $xcat_tgtFile b 0x$major 0x$minor + echo "KERNEL==\"sd*\", SYSFS{wwpn}==\"${wwpn}\", SYSFS{fcp_lun}==\"${lun}\", SYMLINK+=\"${tgtNode}%n\"" >> ${configFile} + udevadm trigger --sysname-match=sd* ########################################################################## # Handle removing a file system node @@ -289,8 +294,11 @@ function setupDisk { return fi - umount "$xcat_tgtFile" - rm -f "$xcat_tgtFile" + configFile='/etc/udev/rules.d/56-zfcp.rules' + tgtNode=$(echo ${xcat_tgtFile} | sed -e 's/^\/dev\///') + + sed -i -e /SYMLINK+=\"${tgtNode}%n\"/d ${configFile} + udevadm trigger --sysname-match=sd* ########################################################################## # Handle adding a SCSI volume @@ -463,22 +471,23 @@ function setupDisk { # Main Code Section ############################################################################ case "$1" in - start) - if [[ -z "$authorizedSenders" ]]; then - echo "xcatconf4z is disabled. There are no authorized senders of configuration files." - else - echo "xcatconf4z is starting" - transportdir="/var/opt/xcat/transport" - rm -Rf $transportdir - /bin/mkdir -p $transportdir - cd $transportdir - - # Get Linux version - getOsVersion - + start) + echo "xcatconf4z is starting" + transportdir="/var/opt/xcat/transport" + rm -Rf $transportdir + /bin/mkdir -p $transportdir + cd $transportdir + + # Get Linux version + getOsVersion + + if [[ -n "$authorizedSenders" ]]; then pullReader - setupIso - fi + else + echo "xcatconf4z is disabled from accepting configuration reader files." + fi + + setupIso ;; stop|status|restart|reload|force-reload) # Do nothing From 66d62f7e65726529bc98562abe56a5805a7bfe83 Mon Sep 17 00:00:00 2001 From: Chuck Brazie Date: Mon, 21 Oct 2013 14:09:31 -0400 Subject: [PATCH 34/91] Adding file back in, not sure why it delted --- perl-xCAT/xCAT/Client.pm | 1254 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 1254 insertions(+) create mode 100644 perl-xCAT/xCAT/Client.pm diff --git a/perl-xCAT/xCAT/Client.pm b/perl-xCAT/xCAT/Client.pm new file mode 100644 index 000000000..e0934796d --- /dev/null +++ b/perl-xCAT/xCAT/Client.pm @@ -0,0 +1,1254 @@ +#!/usr/bin/env perl +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html +package xCAT::Client; +BEGIN +{ + $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr'; +} + +# if AIX - make sure we include perl 5.8.2 in INC path. +# Needed to find perl dependencies shipped in deps tarball. +use Storable qw/nstore_fd fd_retrieve/; +if ($^O =~ /^aix/i) { + unshift(@INC, qw(/usr/opt/perl5/lib/5.8.2/aix-thread-multi /usr/opt/perl5/lib/5.8.2 /usr/opt/perl5/lib/site_perl/5.8.2/aix-thread-multi /usr/opt/perl5/lib/site_perl/5.8.2)); +} +use IO::Handle; + +my $inet6support; +if ($^O =~ /^aix/i) { # disable AIX IPV6 TODO fix + $inet6support = 0; +} else { + $inet6support=eval { require Socket6; 1; }; +} +if ($inet6support) { + $inet6support = eval { require IO::Socket::INET6; 1; }; +} +if ($inet6support) { + $inet6support = eval { require IO::Socket::SSL; IO::Socket::SSL->import('inet6'); 1;}; +} + +if ($^O =~ /^linux/i) { + # Is IPv6 enabled on the MN or xcat client node at all? + my $ipv6enabled = `ip addr | grep inet6`; + if (!$ipv6enabled) { + $inet6support = 0; + } +} + +unless ($inet6support) { + eval { require Socket }; + eval { require IO::Socket::INET }; + eval { require IO::Socket::SSL; IO::Socket::SSL->import('inet4') }; +} + + +use XML::Simple; #smaller than libxml.... +use Fcntl; +use POSIX qw/:errno_h/; +use IO::Select; +$XML::Simple::PREFERRED_PARSER='XML::Parser'; +#require Data::Dumper; +my $xcathost='localhost:3001'; +my $plugins_dir; +my %resps; +my $EXITCODE; # save the bitmask of all exit codes returned by calls to handle_response() +1; + + +sub rspclean { + my $response = shift; + my $callback = shift; + my $rsps = XMLin($response,SuppressEmpty=>undef,ForceArray=>1); + foreach my $rsp (@{$rsps->{xcatresponse}}) { + #add ESC back + foreach my $key (keys %$rsp) { + if (ref($rsp->{$key}) eq 'ARRAY') { + foreach my $text (@{$rsp->{$key}}) { + next unless defined $text; + $text =~ s/xxxxESCxxxx/\e/g; + } + } + else { + $rsp->{$key} =~ s/xxxxESCxxxx/\e/g; + } + } + $callback->($rsp); + if ($rsp->{serverdone}) { + return 1; + } + } + return 0; +} +sub send_request { + my $request = shift; + my $sock = shift; + my $encode = shift; + if ($encode eq "xml") { + my $msg=XMLout($request,RootName=>'xcatrequest',NoAttr=>1,KeyAttr=>[]); + if ($ENV{XCATXMLTRACE}) { print $msg; } + if($ENV{XCATXMLWARNING}) { + validateXML($msg); + } + print $sock $msg; + $sock->flush(); + } else { + nstore_fd($request,$sock); + $sock->flush(); + } +} +################################# +# submit_request will take an xCAT command and pass it to the xCAT +# server for execution. +# Note must not put a require or use for Utils.pm in the non-bypass path +# +# If the XCATBYPASS env var is set, the connection to the server/daemon +# will be bypassed and the plugin will be called directly. If it is +# set to one or more directories (separated by ":"), all perl modules +# in those directories will be loaded in as plugins (for duplicate +# commands, last one in wins). If it is set to any other value +# (e.g. "yes", "default", whatever string you want) the default plugin +# directory /opt/xcat/lib/perl/xCAT_plugin will be used. +# +# Input: +# Request hash - A hash ref containing the input command and args to be +# passed to the plugin. The the xcatd daemon (or this routine when +# XCATBYPASS) reads the {noderange} entry and builds a flattened array +# of nodes that gets added as request->{node} +# The format for the request hash is: +# { command => [ 'xcatcmd' ], +# noderange => [ 'noderange_string' ], +# arg => [ 'arg1', 'arg2', '...', 'argn' ] +# } +# Callback - A subroutine ref that will be called to process the output +# from the plugin. +# +# NOTE: The request hash will get converted to XML when passed to the +# xcatd daemon, and will get converted back to a hash before being +# passed to the plugin. The XMLin ForceArray option is used to +# force all XML constructs to be arrays so that the plugin code +# and callback routines can access the data consistently. +# The input request and the response hash created by the plugin should +# always create hashes with array values. +################################# +sub submit_request { + my $request = shift; + my $callback = shift; + my $keyfile = shift; + my $certfile = shift; + my $cafile = shift; + # get home directory + my @user = getpwuid($>); + my $homedir=$user[7]; + unless ($keyfile) { $keyfile = $homedir."/.xcat/client-cred.pem"; } + unless ($certfile) { $certfile = $homedir."/.xcat/client-cred.pem"; } + unless ($cafile) { $cafile = $homedir."/.xcat/ca.pem"; } + $xCAT::Client::EXITCODE = 0; # clear out exit code before invoking the plugin +if (ref($request) eq 'HASH') { # the request is an array, not pure XML + $request->{clienttype}->[0] = "cli"; # setup clienttype for auditlog +} +# If XCATBYPASS is set, invoke the plugin process_request method directly +# without going through the socket connection to the xcatd daemon + if ($ENV{XCATBYPASS}) { + #add current userid to the request + if (ref($request) eq 'HASH') { # the request is an array, not pure XML + if (!(defined($request->{username}))) { + $request->{username}->[0] = getpwuid($>); + } + + # only allow root to run + unless ($request->{username}->[0] =~ /root/) { + print ("WARNING: Only allow root to run XCATBYPASS mode, your current user ID is $request->{username}->[0].\n"); + return 0; + } + } + # Load plugins from either specified or default dir + require xCAT::Table; + my %cmd_handlers; + my @plugins_dirs = split('\:',$ENV{XCATBYPASS}); + if (-d $plugins_dirs[0]) { + foreach (@plugins_dirs) { + $plugins_dir = $_; + scan_plugins(); + } + } else { + # figure out default plugins dir + #my $sitetab=xCAT::Table->new('site'); + #unless ($sitetab) { + # print ("ERROR: Unable to open basic site table for configuration\n"); + #} + $plugins_dir=$::XCATROOT.'/lib/perl/xCAT_plugin'; + scan_plugins(); + } + + populate_site_hash(); + + # don't do XML transformation -- assume request is well-formed + # my $xmlreq=XMLout($request,RootName=>xcatrequest,NoAttr=>1,KeyAttr=>[]); + # $request = XMLin($xmlreq,SuppressEmpty=>undef,ForceArray=>1) ; + + + # Call the plugin directly + # ${"xCAT_plugin::".$modname."::"}{process_request}->($request,$callback); + plugin_command($request,undef,$callback); + return 0; + } + +# No XCATBYPASS, so establish a socket connection with the xcatd daemon +# and submit the request + if ($ENV{XCATHOST}) { + $xcathost=$ENV{XCATHOST}; + } + my %connargs=(); + if ($xcathost =~ s/%([^\]|:]*)//) { + $connargs{PeerScope} = $1; + } + $connargs{PeerAddr} = $xcathost; + $connargs{Timeout} = 15; + if ($connargs{PeerScope} and $connargs{PeerScope} =~ /[a-zA-Z]/) { #non-numeric, need to translate... + my @ipdata = `ip link`; + @ipdata = grep(/[^@]$connargs{PeerScope}(:|@)/,@ipdata); + if (scalar(@ipdata) != 1) { + print STDERR "Unable to identify scope ".$connargs{PeerScope}."\n"; + exit(1); + } + $connargs{PeerScope} = $ipdata[0]; + $connargs{PeerScope} =~ s/:.*//; + } + + + my $pclient; + if ($inet6support) { + $pclient = IO::Socket::INET6->new( + %connargs, + ); + } else { + $pclient = IO::Socket::INET->new( + PeerAddr => $xcathost, + Timeout => 15, + ); + } + unless ($pclient) { + print "Unable to open socket connection to xcatd daemon on $xcathost.\n"; + print "Verify that the xcatd daemon is running and that your SSL setup is correct.\n"; + if ($@ =~ /SSL Timeout/) { + die "Connection failure: SSL Timeout or incorrect certificates in ~/.xcat"; + } else { + die "Connection failure: $@" + } + } + my $client; + if (-r $keyfile and -r $certfile and -r $cafile) { + $client = IO::Socket::SSL->start_SSL($pclient, + SSL_key_file => $keyfile, + SSL_cert_file => $certfile, + SSL_ca_file => $cafile, + SSL_use_cert => 1, + Timeout => 0, + ); + } else { + $client = IO::Socket::SSL->start_SSL($pclient, + Timeout => 0, + ); + } + unless ($client) { + print "Unable to open socket connection to xcatd daemon on $xcathost.\n"; + print "Verify that the xcatd daemon is running and that your SSL setup is correct.\n"; + if ($@ =~ /SSL Timeout/) { + die "Connection failure: SSL Timeout or incorrect certificates in ~/.xcat"; + } else { + die "Connection failure: $@" + } + } + + my $msg; + my $encode = "xml"; + #storable encoding is unsafe, carry on with the unsafe xml scheme + #perhaps one day will support faster schemes + #my $encode = "storable"; + #my $straightprint=0; + #if ($ENV{XCATXMLTRACE} or $ENV{XCATXMLWARNING}) { $encode="xml"; } + if (ref($request) eq 'HASH') { # the request is an array, not pure XML + #print $client "xcatencoding: $encode\n"; + #my $encok=<$client>; + send_request($request,$client,$encode); + } else { #XML + $straightprint=1; + $msg=$request; + print $client $msg; + } + $SIG{TERM} = $SIG{INT} = sub { send_request({abortcommand=>[1]},$client,$encode); exit 0; }; + my $response; + my $rsp; + my $cleanexit=0; + if ($encode eq 'xml') { + my $massresponse=""; + my $nextcoalescetime=time()+1; + my $coalescenow=0; + my $flags=fcntl($client,F_GETFL,0); + $flags |= O_NONBLOCK; #select can be a bit.. fickle, make sysread work more easily... + fcntl($client,F_SETFL,$flags); + my $clientsel = new IO::Select; + $clientsel->add($client); + my $line; + my $newdata=0; + while (1) { + my $shouldexit; + if ($newdata and ($coalescenow or time() > $nextcoalescetime)) { + $coalescenow=0; + $newdata=0; + $nextcoalescetime=time()+1; + $massresponse .= ""; + $shouldexit = rspclean($massresponse,$callback); + $massresponse=""; + } + + if ($shouldexit) { + $cleanexit=1; + last; + } + $line = ""; + $clientsel->can_read(0.5); + my $readbytes; + do { $readbytes=sysread($client,$line,65535,length($line)); } while ($readbytes); + unless (length($line)) { + if (not defined $readbytes and $! == EAGAIN) { next; } + last; + } + $newdata=1; + $response .= $line; + if ($line =~ m/<\/xcatresponse>\s*\z/) { + if ($line =~ /serverdone/) { $coalescenow=1; } #if serverdone was detected, hint at coalesce code to flush things out now + #this means that coalesce can be triggered by stray words in the output prematurely, but that's harmless + #replace ESC with xxxxESCxxx because XMLin cannot handle it + $response =~ s/\e/xxxxESCxxxx/g; + + if ($ENV{XCATXMLTRACE}) { print $response; } + $massresponse.=$response; + $response=''; + if($ENV{XCATXMLWARNING}) { + validateXML($response); + } + } + } + if (not $cleanexit and $massresponse ne "") { + $massresponse .= ""; + $cleanexit = rspclean($massresponse,$callback); + } + } else { #storable encode + my $rsp; + eval { $rsp = fd_retrieve($client); }; + SERVERINPUT: while ($rsp) { + my @rsps; + if (ref $rsp eq 'ARRAY') { + @rsps = @$rsp; + } else { + @rsps = ($rsp); + } + foreach (@rsps) { + $callback->($_); + if ($_->{serverdone}) { + $cleanexit=1; + last SERVERINPUT; + } + } + $rsp = undef; + eval { $rsp = fd_retrieve($client); }; + } + } + $massresponse=""; + unless ($cleanexit) { + print STDERR "ERROR/WARNING: communication with the xCAT server seems to have been ended prematurely\n"; + $xCAT::Client::EXITCODE = 1; + } + +sub validateXML { + my $xml = shift; + my @lines = split /\n/, $xml; + my $invalidNewline = 0; + my $contentsColon = 0; + my $contentsLine; + + foreach (@lines) { + if(!$invalidNewline) { + if( ($_ =~ // && $_ !~ /<\/contents>/) || + ($_ =~ // && $_ !~ /<\/desc>/)) { + $invalidNewline = 1; + print "Possible invalid XML using newlines found: \n$xml\n"; + } + } + if($_ =~ /.+:.+<\/contents>/) { + $contentsColon = 1; + $contentsLine = $_; + } + if($_ =~ /.+<\/desc>/) { + $contentsColon = 0; + } + if($contentsColon && $_ =~ /<\/desc>/) { + print "Possible invalid XML found(data contents using colon and blank description): \n$contentsLine\n$_\n"; + $contentsColon = 0; + } + } +} + +################################### +# scan_plugins +# will load all plugin perl modules and build a list of supported +# commands +# +# NOTE: This is copied from xcatd (last merge 11/23/09). +# TODO: Will eventually move to using common source.... +################################### +sub scan_plugins { + my @plugins=glob($plugins_dir."/*.pm"); + foreach (@plugins) { + /.*\/([^\/]*).pm$/; + my $modname = $1; + unless ( eval { require "$_" }) { +# xCAT::MsgUtils->message("S","Error loading module ".$_." ...skipping"); + print "Error loading module $_ ...skipping\n"; + next; + } + no strict 'refs'; + my $cmd_adds=${"xCAT_plugin::".$modname."::"}{handled_commands}->(); + foreach (keys %$cmd_adds) { + my $value = $_; + if (defined($cmd_handlers{$_})) { + push @{$cmd_handlers{$_}},[$modname,$cmd_adds->{$_}]; + } else { + $cmd_handlers{$_} = [ [$modname,$cmd_adds->{$_}] ]; + } + } + } + foreach (@plugins) { + no strict 'refs'; + /.*\/([^\/]*).pm$/; + my $modname = $1; + unless (defined(${"xCAT_plugin::".$modname."::"}{init_plugin})) { + next; + } + ${"xCAT_plugin::".$modname."::"}{init_plugin}->(\&do_request); + } +} + + + + +################################### +# plugin_command +# will invoke the correct plugin +# +# NOTE: This is copied from xcatd (last merge 11/23/09). +# TODO: Will eventually move to using common source.... +################################### +sub plugin_command { + my $req = shift; + my $sock = shift; + my $callback = shift; + my %handler_hash; + my $usesiteglobal = 0; + # We require these only in bypass mode to reduce start up time for the normal case + #use lib "$::XCATROOT/lib/perl"; + #use xCAT::NodeRange; + require lib; + lib->import("$::XCATROOT/lib/perl"); + require xCAT::NodeRange; + require xCAT::Table; + + $Main::resps={}; + my $xmlreq; + if (ref($req) ne 'HASH') { # the request XML, get an array + $xmlreq=$req; # save the original XML + $req = XMLin($xmlreq,SuppressEmpty=>undef,ForceArray=>1) ; + + } + my @nodes; + if ($req->{node}) { + @nodes = @{$req->{node}}; + } elsif ($req->{noderange} and $req->{noderange}->[0]) { + @nodes = xCAT::NodeRange::noderange($req->{noderange}->[0]); + if (xCAT::NodeRange::nodesmissed()) { +# my $rsp = {errorcode=>1,error=>"Invalid nodes in noderange:".join(',',xCAT::NodeRange::nodesmissed)}; +# my $rsp->{serverdone} = {}; + print "Invalid nodes in noderange:".join(',',xCAT::NodeRange::nodesmissed())."\n"; +# if ($sock) { +# print $sock XMLout($rsp,RootName=>'xcatresponse' ,NoAttr=>1); +# } +# return ($rsp); + return 1; + } + unless (@nodes) { + $req->{emptynoderange} = [1]; + } + } + if (@nodes) { $req->{node} = \@nodes; } + my %unhandled_nodes; + foreach (@nodes) { + $unhandled_nodes{$_}=1; + } + my $useunhandled=0; + if (defined($cmd_handlers{$req->{command}->[0]})) { + my $hdlspec; + my @globalhandlers=(); + my $useglobals=1; #If it stays 1, then use globals normally, if 0, use only for 'unhandled_nodes, if -1, don't do at all + foreach (@{$cmd_handlers{$req->{command}->[0]}}) { + $hdlspec =$_->[1]; + my $ownmod = $_->[0]; + if ($hdlspec =~ /^site:/) { #A site entry specifies a plugin + my $sitekey = $hdlspec; + $sitekey =~ s/^site://; + #$sitetab = xCAT::Table->new('site'); + #my $sent = $sitetab->getAttribs({key=>$sitekey},['value']); + #if ($sent and $sent->{value}) { #A site style plugin specification is just like + if ($::XCATSITEVALS{$sitekey}) { #A site style plugin specification is just like + #a static global, it grabs all nodes rather than some + $useglobals = -1; #If they tried to specify anything, don't use the default global handlers at all + unless (@nodes) { + $handler_hash{$::XCATSITEVALS{$sitekey}} = 1; + $usesiteglobal = 1; + } + foreach (@nodes) { #Specified a specific plugin, not a table lookup + $handler_hash{$::XCATSITEVALS{$sitekey}}->{$_} = 1; + } + } + } elsif ($hdlspec =~ /:/) { #Specificed a table lookup path for plugin name + if (@nodes) { # only use table lookup plugin if nodelist exists + # Usage will be handled in common AAAhelp plugin + + $useglobals = 0; #Only contemplate nodes that aren't caught through searching below in the global handler + $useunhandled=1; + my $table; + my $cols; + ($table,$cols) = split(/:/,$hdlspec); + my @colmns=split(/,/,$cols); + my @columns; + my $hdlrtable=xCAT::Table->new($table); + unless ($hdlrtable) { + #TODO: proper error handling + } + my $node; + my $colvals = {}; + foreach my $colu (@colmns) { + if ($colu =~ /=/) { #a value redirect to a pattern/specific name + my $coln; my $colv; + ($coln,$colv) = split(/=/,$colu,2); + $colvals->{$coln} = $colv; + push (@columns,$coln); + } else { + push (@columns,$colu); + } + } + + + unless (@nodes) { #register the plugin in the event of usage + $handler_hash{$ownmod} = 1; + $useglobals = 1; + } + my $hdlrcache; + if ($hdlrtable) { + $hdlrcache = $hdlrtable->getNodesAttribs(\@nodes,\@columns); + } + foreach $node (@nodes) { + unless ($hdlrcache) { next; } + my $attribs = $hdlrcache->{$node}->[0]; #$hdlrtable->getNodeAttribs($node,\@columns); + unless (defined($attribs)) { next; } + foreach (@columns) { + my $col=$_; + if (defined($attribs->{$col})) { + if ($colvals->{$col}) { #A pattern match style request. + if ($attribs->{$col} =~ /$colvals->{$col}/) { + $handler_hash{$ownmod}->{$node} = 1; + delete $unhandled_nodes{$node}; + last; + } + } else { + # call the plugin that matches the table value for that node + if ($attribs->{$col} =~ /$ownmod/) { + $handler_hash{$attribs->{$col}}->{$node} = 1; + delete $unhandled_nodes{$node}; + last; + } + } + } + } + } + $hdlrtable->close; + } # end if (@nodes) + + } else { + push @globalhandlers,$hdlspec; + } + } + if ($useglobals == 1) { #Behavior when globals have not been overriden + my $hdlspec; + foreach $hdlspec (@globalhandlers) { + unless (@nodes) { + $handler_hash{$hdlspec} = 1; + } + foreach (@nodes) { #Specified a specific plugin, not a table lookup + $handler_hash{$hdlspec}->{$_} = 1; + } + } + } elsif ($useglobals == 0) { + unless (@nodes or $usesiteglobal) { #if something like 'makedhcp -n', + foreach (keys %handler_hash) { + if ($handler_hash{$_} == 1) { + delete ($handler_hash{$_}) + } + } + } + foreach $hdlspec (@globalhandlers) { + unless (@nodes or $usesiteglobal) { + $handler_hash{$hdlspec} = 1; + } + foreach (keys %unhandled_nodes) { #Specified a specific plugin, not a table lookup + $handler_hash{$hdlspec}->{$_} = 1; + } + } + } #Otherwise, global handler is implicitly disabled + } else { + print "Error request: $req->{command}->[0] has no known plugin for it.\n"; + return 1; + } + if ($useunhandled) { + my $queuelist; + foreach (@{$cmd_handlers{$req->{command}->[0]}}) { + my $queueitem = $_->[1]; + if (($queueitem =~ /:/) and !($queuelist =~ /($queueitem)/)) { + $queuelist .= "$_->[1];"; + } + } + $queuelist =~ s/;$//; + $queuelist =~ s/:/./g; + foreach (keys %unhandled_nodes) { +# if ($sock) { +# print $sock XMLout({node=>[{name=>[$_],data=>["Unable to identify plugin for this command, check relevant tables: $queuelist"],errorcode=>[1]}]},NoAttr=>1,RootName=>'xcatresponse'); +# } else { + my $tabdesc = $queuelist; + $tabdesc =~ s/=.*$//; + $callback->({node=>[{name=>[$_],error=>['Unable to identify plugin for this command, check relevant tables: '.$tabdesc],errorcode=>[1]}]}); +# } + } + } + +## FOR NOW, DON'T FORK CHILD PROCESS TO MAKE BYPASS SIMPLER AND EASIER TO DEBUG +# $plugin_numchildren=0; +# %plugin_children=(); +# $SIG{CHLD} = \&plugin_reaper; #sub {my $plugpid; while (($plugpid = waitpid(-1, WNOHANG)) > 0) { if ($plugin_children{$plugpid}) { delete $plugin_children{$plugpid}; $plugin_numchildren--; } } }; +# my $check_fds; +# if ($sock) { +# $check_fds = new IO::Select; +# } + foreach (keys %handler_hash) { + my $modname = $_; +# my $shouldbealivepid=$$; + if (-r $plugins_dir."/".$modname.".pm") { + require $plugins_dir."/".$modname.".pm"; +# $plugin_numchildren++; +# my $pfd; #will be referenced for inter-process messaging. +# my $parfd; #not causing a problem that I discern yet, but theoretically +# my $child; +# if ($sock) { #If $sock not passed in, don't fork.. +# socketpair($pfd, $parfd,AF_UNIX,SOCK_STREAM,PF_UNSPEC) or die "socketpair: $!"; +# #pipe($pfd,$cfd); +# $parfd->autoflush(1); +# $pfd->autoflush(1); +# $child = xCAT::Utils->xfork; +# } else { +# $child = 0; +# } +# unless (defined $child) { die "Fork failed"; } +# if ($child == 0) { +# if ($parfd) { #If xCAT is doing multiple requests in same communication PID, things would get unfortunate otherwise +# $parent_fd = $parfd; +# } + my $oldprogname=$$progname; + $$progname=$oldprogname.": $modname instance"; +# if ($sock) { close $pfd; } + unless ($handler_hash{$_} == 1) { + my @nodes = sort {($a =~ /(\d+)/)[0] <=> ($b =~ /(\d+)/)[0] || $a cmp $b } (keys %{$handler_hash{$_}}); + $req->{node}=\@nodes; + } + no strict "refs"; +# eval { #REMOVEEVALFORDEBUG +# if ($dispatch_requests) { + # backup the original req and recover it after the a run + my $org_req = {%$req}; + dispatch_request($req,$callback,$modname); + $req = {%$org_req}; +# } else { +# $SIG{CHLD}='DEFAULT'; +# ${"xCAT_plugin::".$modname."::"}{process_request}->($req,$callback,\&do_request); +# } + $$progname=$oldprogname; +# if ($sock) { +# close($parent_fd); +# xexit(0); +# } +# }; #REMOVEEVALFORDEBUG +# if ($sock or $shouldbealivepid != $$) { #We shouldn't still be alive, try to send as much detail to parent as possible as to why +# my $error= "$modname plugin bug, pid $$, process description: '$$progname'"; +# if ($@) { +# $error .= " with error '$@'"; +# } else { #Sys::Virt and perhaps Net::SNMP sometimes crashes in a way $@ won't catch.. +# $error .= " with missing eval error, probably due to special manipulation of $@ or strange circumstances in an XS library, remove evals in xcatd marked 'REMOVEEVALFORDEBUG and run xcatd -f for more info"; +# } +# if (scalar (@nodes)) { #Don't know which of the nodes, so one error message warning about the possibliity.. +# $error .= " while trying to fulfill request for the following nodes: ".join(",",@nodes); +# } +# xCAT::MsgUtils->message("S","xcatd: $error"); +# $callback->({error=>[$error],errorcode=>[1]}); +# xexit(0); #Die like we should have done +# } elsif ($@) { #We are still alive, should be alive, but yet we have an error. This means we are in the case of 'do_request' or something similar. Forward up the death since our communication channel is intact.. +# die $@; +# } +# } else { +# $plugin_children{$child}=1; +# close $parfd; +# $check_fds->add($pfd); +# } + } else { + my $pm_name = $plugins_dir."/".$modname.".pm"; + foreach my $node (keys %{$handler_hash{$_}}) { + if ($sock) { + print $sock XMLout({node=>[{name=>[$node],data=>["Cannot find the perl module to complete the operation: $pm_name"],errorcode=>[1]}]},NoAttr=>1,RootName=>'xcatresponse'); + } else { + $callback->({node=>[{name=>[$node],data=>["Cannot find the perl module to complete the operation: $pm_name"],errorcode=>[1]}]}); + } + } + } + } + unless ($sock) { return $Main::resps }; +# while (($plugin_numchildren > 0) and ($check_fds->count > 0)) { #this tracks end of useful data from children much more closely +# relay_fds($check_fds,$sock); +# } +# #while (relay_fds($check_fds,$sock)) {} +# my %done; +# $done{serverdone} = {}; +# if ($req->{transid}) { +# $done{transid}=$req->{transid}->[0]; +# } +# if ($sock) { +# my $clientpresence = new IO::Select; #The client may have gone away without confirmation, don't PIPE over this trivial thing +# $clientpresence->add($sock); +# if ($clientpresence->can_write(5)) { +# print $sock XMLout(\%done,RootName => 'xcatresponse',NoAttr=>1); +# } +# } +} + + + + +################################### +# dispatch_request +# dispatch the requested command +# +# NOTE: This is copied from xcatd (last merge 11/23/09). +# All we really need from this subroutine is to call preprocess_request +# and to only run the command for nodes handled by the local server +# Will eventually move to using common source.... +################################### +sub dispatch_request { +# %dispatched_children=(); + require xCAT::Utils; + my $req = shift; + $dispatch_cb = shift; + + my $modname = shift; + my $reqs = []; +# my $child_fdset = new IO::Select; + no strict "refs"; + + #Hierarchy support. Originally, the default scope for noderange commands was + #going to be the servicenode associated unless overriden. + #However, assume for example that you have blades and a blade is the service node + #rpower being executed by the servicenode for one of its subnodes would have to + #reach it's own management module. This has the potential to be non-trivial for some quite possible network configurations. + #Since plugins may commonly experience this, a preprocess_request implementation + #will for now be required for a command to be scaled through service nodes + #If the plugin offers a preprocess method, use it to set the request array + if (defined(${"xCAT_plugin::".$modname."::"}{preprocess_request})) { + $SIG{CHLD}='DEFAULT'; + $reqs = ${"xCAT_plugin::".$modname."::"}{preprocess_request}->($req,$dispatch_cb,\&do_request); + } else { #otherwise, pass it in without hierarchy support + $reqs = [$req]; + } + +# $dispatch_children=0; +# $SIG{CHLD} = \&dispatch_reaper; #sub {my $cpid; while (($cpid =waitpid(-1, WNOHANG)) > 0) { if ($dispatched_children{$cpid}) { delete $dispatched_children{$cpid}; $dispatch_children--; } } }; + my $onlyone=0; + if (defined $reqs and (scalar(@{$reqs}) == 1)) { + $onlyone=1; + } + + foreach (@{$reqs}) { +# my $pfd; +# my $parfd; #use a private variable so it won't trounce itself recursively +# my $child; + delete $_->{noderange}; +#----- added to Client.pm -----# + if ($_->{node}) { + $_->{noderange}->[0]=join(',',@{$_->{node}}); + } +#----- end added to Client.pm -----# + + if (ref $_->{'_xcatdest'} and (ref $_->{'_xcatdest'}) eq 'ARRAY') { + _->{'_xcatdest'} = $_->{'_xcatdest'}->[0]; + } + if ($onlyone and not ($_->{'_xcatdest'} and xCAT::NetworkUtils->thishostisnot($_->{'_xcatdest'}))) { + $SIG{CHLD}='DEFAULT'; + ${"xCAT_plugin::".$modname."::"}{process_request}->($_,$dispatch_cb,\&do_request); + return; + } + +# socketpair($pfd, $parfd,AF_UNIX,SOCK_STREAM,PF_UNSPEC) or die "socketpair: $!"; +# $parfd->autoflush(1); +# $pfd->autoflush(1); +# $child = xCAT::Utils->xfork; +# if ($child) { +# $dispatch_children++; +# $dispatched_children{$child}=1; +# $child_fdset->add($pfd); +# next; +# } +# unless (defined $child) { +# $dispatch_cb->({error=>['Fork failure dispatching request'],errorcode=>[1]}); +# } +# undef $SIG{CHLD}; +# $dispatch_parentfd = $parfd; + my @prexcatdests=(); + my @xcatdests=(); + if (ref($_->{'_xcatdest'}) eq 'ARRAY') { #If array, consider it an 'anycast' operation, broadcast done through dupe + #requests, or an alternative join '&' maybe? + @prexcatdests=@{$_->{'_xcatdest'}}; + } else { + @prexcatdests=($_->{'_xcatdest'}); + } + foreach (@prexcatdests) { + if ($_ and /,/) { + push @xcatdests,split /,/,$_; + } else { + push @xcatdests,$_; + } + } + my $xcatdest; + my $numdests=scalar(@xcatdests); + my $request_satisfied=0; + foreach $xcatdest (@xcatdests) { + my $dlock; + if ($xcatdest and xCAT::NetworkUtils->thishostisnot($xcatdest)) { +#----- added to Client.pm -----# + $dispatch_cb->({warning=>['XCATBYPASS is set, skipping hierarchy call to '.$_->{'_xcatdest'}.'']}); +#----- end added to Client.pm -----# + +# #mkpath("/var/lock/xcat/"); #For now, limit intra-xCAT requests to one at a time, to mitigate DB handle usage +# #open($dlock,">","/var/lock/xcat/dispatchto_$xcatdest"); +# #flock($dlock,LOCK_EX); +# $ENV{XCATHOST} = ($xcatdest =~ /:/ ? $xcatdest : $xcatdest.":3001" ); +# $$progname.=": connection to ".$ENV{XCATHOST}; +# my $errstr; +# eval { +# undef $_->{'_xcatdest'}; +# xCAT::Client::submit_request($_,\&dispatch_callback,$xcatdir."/cert/server-cred.pem",$xcatdir."/cert/server-cred.pem",$xcatdir."/cert/ca.pem"); +# }; +# if ($@) { +# $errstr=$@; +# } +# #unlink("/var/lock/xcat/dispatchto_$xcatdest"); +# #flock($dlock,LOCK_UN); +# if ($errstr) { +# if ($numdests == 1) { +# dispatch_callback({error=>["Unable to dispatch command to ".$ENV{XCATHOST}.", command will not make changes to that server ($errstr)"],errorcode=>[1]}); +# xCAT::MsgUtils->message("S","Error dispatching request to ".$ENV{XCATHOST}.": ".$errstr); +# } else { +# xCAT::MsgUtils->message("S","Error dispatching request to ".$ENV{XCATHOST}.", trying other service nodes: ".$errstr); +# } +# next; +# } else { +# $request_satisfied=1; +# last; +# } + } else { + $$progname.=": locally executing"; + $SIG{CHLD}='DEFAULT'; +# ${"xCAT_plugin::".$modname."::"}{process_request}->($_,\&dispatch_callback,\&do_request); +#----- changed in Client.pm -----# + ${"xCAT_plugin::".$modname."::"}{process_request}->($_,$dispatch_cb,\&do_request); +#----- end changed in Client.pm -----# + last; + } + } +# if ($numdests > 1 and not $request_satisfied) { +# xCAT::MsgUtils->message("S","Error dispatching a request to all possible service nodes for request"); +# dispatch_callback({error=>["Failed to dispatch command to any of the following service nodes: ".join(",",@xcatdests)],errorcode=>[1]}); +# } + +# xexit; + } +#while (($dispatch_children > 0) and ($child_fdset->count > 0)) { relay_dispatch($child_fdset) } +#while (relay_dispatch($child_fdset)) { } #Potentially useless drain. +} + + + +################################### +# do_request +# called from a plugin to execute another xCAT plugin command internally +# +# NOTE: This is copied from xcatd (last merge 11/23/09). +# Will eventually move to using common source.... +################################### +sub do_request { + my $req = shift; + my $second = shift; + my $rsphandler = \&build_response; + my $sock = undef; + if ($second) { + if (ref($second) eq "CODE") { + $rsphandler = $second; + } elsif (ref($second) eq "GLOB") { + $sock = $second; + } + } + + #my $sock = shift; #If no sock, will return a response hash + if ($cmd_handlers{$req->{command}->[0]}) { + return plugin_command($req,$sock,$rsphandler); + } elsif ($req->{command}->[0] eq "noderange" and $req->{noderange}) { + my @nodes = xCAT::NodeRange::noderange($req->{noderange}->[0]); + my %resp; + if (xCAT::NodeRange::nodesmissed()) { + $resp{warning}="Invalid nodes in noderange:".join ',',xCAT::NodeRange::nodesmissed() ."\n"; + } + $resp{serverdone} = {}; + @{$resp{node}}=@nodes; + if ($req->{transid}) { + $resp{transid}=$req->{transid}->[0]; + } + if ($sock) { + print $sock XMLout(\%resp,RootName => 'xcatresponse',NoAttr=>1); + } else { + return (\%resp); + } + } else { + my %resp=(error=>"Unsupported request"); + $resp{serverdone} = {}; + if ($req->{transid}) { + $resp{transid}=$req->{transid}->[0]; + } + if ($sock) { + print $sock XMLout(\%resp,RootName => 'xcatresponse',NoAttr=>1); + } else { + return (\%resp); + } + } +} + + +################################### +# build_response +# This callback handles responses from nested level plugin calls. +# It builds a merged hash of all responses that gets passed back +# to the calling plugin. +# Note: Need to create a "deep clone" of this response to add to the +# return, otherwise next time through the referenced data is overwritten +# +################################### +sub build_response { + my $rsp = shift; + require Storable; + foreach (keys %$rsp) { + my $subresp = Storable::dclone($rsp->{$_}); + push (@{$Main::resps->{$_}}, @{$subresp}); + } +} + + + +} # end of submit_request() + +#################################### +# populates all the site attributes into %::XCATSITEVALS +# This is used with XCATBYPASS=1 +################################### +sub populate_site_hash { + %::XCATSITEVALS=(); + my $sitetab = xCAT::Table->new('site',-create=>0); + unless ($sitetab) { + print ("ERROR: Unable to open basic site table for configuration\n"); + return; + } + my @records = $sitetab->getAllAttribs(qw/key value/); + foreach (@records) { + $::XCATSITEVALS{$_->{key}}=$_->{value}; + } +} + + + +########################################## +# handle_response is a default callback that can be passed into submit_request() +# It is invoked repeatedly by submit_request() to print out the data returned by +# the plugin. +# +# The normal flow is: +# -> client cmd (e.g. nodels, which is just a link to xcatclient) +# -> xcatclient +# -> submit_request() +# -> send xml request to xcatd +# -> xcatd +# -> process_request() of the plugin +# <- plugin callback +# <- xcatd +# <- xcatd sends xml response to client +# <- submit_request() read response +# <- handle_response() prints responses and saves exit codes +# <- xcatclient gets exit code and exits +# +# But in XCATBYPASS mode, the flow is: +# -> client cmd (e.g. nodels, which is just a link to xcatclient) +# -> xcatclient +# -> submit_request() +# -> process_request() of the plugin +# <- handle_response() prints responses and saves exit codes +# <- xcatclient gets exit code and exits +# +# Format of the response hash: +# {data => [ 'data str1', 'data str2', '...' ] } +# +# Results are printed as: +# data str1 +# data str2 +# +# or: +# {data => [ {desc => [ 'desc1' ], +# contents => [ 'contents1' ] }, +# {desc => [ 'desc2 ], +# contents => [ 'contents2' ] } +# : +# ] } +# NOTE: In this format, only the data array can have more than one +# element. All other arrays are assumed to be a single element. +# Results are printed as: +# desc1: contents1 +# desc2: contents2 +# +# or: +# {node => [ {name => ['node1'], +# data => [ {desc => [ 'node1 desc' ], +# contents => [ 'node1 contents' ] } ] }, +# {name => ['node2'], +# data => [ {desc => [ 'node2 desc' ], +# contents => [ 'node2 contents' ] } ] }, +# : +# ] } +# NOTE: Only the node array can have more than one element. +# All other arrays are assumed to be a single element. +# +# This was generated from the corresponding XML: +# +# +# node1 +# +# node1 desc +# node1 contents +# +# +# +# node2 +# +# node2 desc +# node2 contents +# +# +# +# +# Results are printed as: +# node_name: desc: contents +########################################## +sub handle_response { + my $rsp = shift; + if ($ENV{'XCATSHOWXML'}) { + my $xmlrec=XMLout($rsp,RootName=>'xcatresponse',NoAttr=>1,KeyAttr=>[]); + print "$xmlrec\n"; + return; + } +#print "in handle_response\n"; + # Handle errors + if (defined($rsp->{errorcode})) { + if (ref($rsp->{errorcode}) eq 'ARRAY') { + foreach my $ecode (@{$rsp->{errorcode}}) { + $xCAT::Client::EXITCODE |= $ecode; + } + } + else { + $xCAT::Client::EXITCODE |= $rsp->{errorcode}; + } # assume it is a non-reference scalar + } + if ($rsp->{error}) { +#print "printing error\n"; + if (ref($rsp->{error}) eq 'ARRAY') { + foreach my $text (@{$rsp->{error}}) { + if ($rsp->{NoErrorPrefix}) { + print STDERR "$text\n"; + } else { + print STDERR "Error: $text\n"; + } + } + } + else { + if ($rsp->{NoErrorPrefix}) { + print STDERR ($rsp->{error}."\n"); + } else { + print STDERR ("Error: ".$rsp->{error}."\n"); + } + } + } + if ($rsp->{warning}) { +#print "printing warning\n"; + if (ref($rsp->{warning}) eq 'ARRAY') { + foreach my $text (@{$rsp->{warning}}) { + if ($rsp->{NoWarnPrefix}) { + print STDERR "$text\n"; + } else { + print STDERR "Warning: $text\n"; + } + } + } + else { + if ($rsp->{NoWarnPrefix}) { + print STDERR ($rsp->{warning}."\n"); + } else { + print STDERR ("Warning: ".$rsp->{warning}."\n"); + } + } + } + if ($rsp->{info}) { +#print "printing info\n"; + if (ref($rsp->{info}) eq 'ARRAY') { + foreach my $text (@{$rsp->{info}}) { + print "$text\n"; + } + } + else { + print ($rsp->{info}."\n"); + } + } + + if ($rsp->{sinfo}) { + if (ref($rsp->{sinfo}) eq 'ARRAY') { + foreach my $text (@{$rsp->{sinfo}}) { + print "$text\r"; $|++; + } + } + else { + print ($rsp->{sinfo}."\r"); $|++; + } + } + + + + # Handle {node} structure + my $errflg=0; + my $nodes=($rsp->{node}); + unless (ref $nodes eq 'ARRAY') { + $nodes = [$nodes]; + } + if (scalar @{$nodes}) { +#print "printing node\n"; + my $node; + foreach $node (@$nodes) { + my $desc; + if (ref($node->{name}) eq 'ARRAY') { + $desc=$node->{name}->[0]; + } else { + $desc=$node->{name}; + } + if ($node->{errorcode}) { + if (ref($node->{errorcode}) eq 'ARRAY') { + foreach my $ecode (@{$node->{errorcode}}) { + $xCAT::Client::EXITCODE |= $ecode; + } + } + else { + $xCAT::Client::EXITCODE |= $node->{errorcode}; + } # assume it is a non-reference scalar + } + if ($node->{error}) { + $desc.=": Error: ".$node->{error}->[0]; + $errflg=1; + } + if ($node->{warning}) { + $desc.=": Warning: ".$node->{warning}->[0]; + $errflg=1; + } + if ($node->{data}) { + if (ref(\($node->{data})) eq 'SCALAR') { + $desc=$desc.": ".$node->{data}; + } elsif (ref($node->{data}) eq 'HASH') { + if ($node->{data}->{desc}) { + if (ref($node->{data}->{desc}) eq 'ARRAY') { + $desc=$desc.": ".$node->{data}->{desc}->[0]; + } else { + $desc=$desc.": ".$node->{data}->{desc}; + } + } + if ($node->{data}->{contents}) { + if (ref($node->{data}->{contents}) eq 'ARRAY') { + $desc="$desc: ".$node->{data}->{contents}->[0]; + } else { + $desc="$desc: ".$node->{data}->{contents}; + } + } + } elsif (ref(\($node->{data}->[0])) eq 'SCALAR') { + $desc=$desc.": ".$node->{data}->[0]; + } else { + if ($node->{data}->[0]->{desc}) { + $desc=$desc.": ".$node->{data}->[0]->{desc}->[0]; + } + if ($node->{data}->[0]->{contents}) { + $desc="$desc: ".$node->{data}->[0]->{contents}->[0]; + } + } + } + if ($desc) { + if ($errflg == 1) { + print STDERR ("$desc\n"); + } else { + print "$desc\n"; + } + } + } + } + + # Handle {data} structure with no nodes + if ($rsp->{data}) { +#print "printing data\n"; + my $data=($rsp->{data}); + my $data_entry; + foreach $data_entry (@$data) { + my $desc; + if (ref(\($data_entry)) eq 'SCALAR') { + $desc=$data_entry; + } else { + if ($data_entry->{desc}) { + $desc=$data_entry->{desc}->[0]; + } + if ($data_entry->{contents}) { + if ($desc) { + $desc="$desc: ".$data_entry->{contents}->[0]; + } else { + $desc=$data_entry->{contents}->[0]; + } + } + } + if ($desc) { print "$desc\n"; } + } + } +} # end of handle_response + + + + + + From 42bc6cef0713d2e5a6683bb856e5680b0ce97a28 Mon Sep 17 00:00:00 2001 From: jjhua Date: Tue, 22 Oct 2013 10:07:08 -0400 Subject: [PATCH 35/91] code for OpenStack-Chef-Cookbook/xCAT integration --- xCAT-OpenStack/lib/perl/xCAT_plugin/cloud.pm | 194 +++++++++++++++++++ xCAT-server/lib/perl/xCAT/Postage.pm | 161 ++++++++++++++- 2 files changed, 353 insertions(+), 2 deletions(-) create mode 100644 xCAT-OpenStack/lib/perl/xCAT_plugin/cloud.pm diff --git a/xCAT-OpenStack/lib/perl/xCAT_plugin/cloud.pm b/xCAT-OpenStack/lib/perl/xCAT_plugin/cloud.pm new file mode 100644 index 000000000..826894886 --- /dev/null +++ b/xCAT-OpenStack/lib/perl/xCAT_plugin/cloud.pm @@ -0,0 +1,194 @@ +# IBM(c) 2010 EPL license http://www.eclipse.org/legal/epl-v10.html +package xCAT_plugin::cloud; +BEGIN +{ + $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; +} +use lib "$::XCATROOT/lib/perl"; + +use strict; +use xCAT::Table; +use Getopt::Long; +Getopt::Long::Configure("bundling"); +Getopt::Long::Configure("pass_through"); +#use xCAT::Utils; +#use xCAT::TableUtils; +use xCAT::Template; + + + +sub handled_commands +{ + return {makeclouddata => "cloud",}; +} + +############################################################ +# check_options will process the options for makeclouddata and +# give a usage error for any invalid options +############################################################ +sub check_options +{ + my $req = shift; + my $callback = shift; + my $rc = 0; + + Getopt::Long::Configure("bundling"); + $Getopt::Long::ignorecase = 0; + Getopt::Long::Configure("no_pass_through"); + + # Exit if the packet has been preprocessed + if ($req->{_xcatpreprocessed}->[0] == 1) { return [$req]; } + + # Save the arguements in ARGV for GetOptions + if ($req && $req->{arg}) { @ARGV = @{$req->{arg}}; } + else { @ARGV = (); } + + + # Parse the options for makedhcp + if (!GetOptions( + 'h|help' => \$::opt_h, + )) + { + # If the arguements do not pass GetOptions then issue error message and return + return -1; + } + + # display the usage if -h + if ($::opt_h) + { + return 1; + + } + + my $cloudlist =shift( @ARGV ); + + if( defined($cloudlist) ) { + my @clouds = split(",", $cloudlist); + $req->{clouds} = \@clouds; + } + + return 0; +} + +sub cloudvars { + + my $inf = shift; + my $outf = shift; + my $cloud = shift; + my $callback = shift; + my $outh; + my $inh; + open($inh,"<",$inf); + unless ($inh) { + my $rsp; + $rsp->{errorcode}->[0]=1; + $rsp->{error}->[0]="Unable to open $inf, aborting\n"; + $callback->($rsp); + return; + } + my $inc; + #First load input into memory.. + while (<$inh>) { + $inc.=$_; + } + close($inh); + $inc =~ s/\$CLOUD/$cloud/eg; + $inc =~ s/#TABLE:([^:]+):([^:]+):([^#]+)#/xCAT::Template::tabdb($1,$2,$3)/eg; + + open($outh,">",$outf); + unless($outh) { + my $rsp; + $rsp->{errorcode}->[0]=1; + $rsp->{error}->[0]="Unable to open $inf, aborting\n"; + $callback->($rsp); + return; + } + print $outh $inc; + close($outh); + return 0; +} + + +sub process_request +{ + my $req = shift; + my $callback = shift; + my $rc = 0; + + # define usage statement + my $usage="Usage: \n\tmkcloudata\n\tmakeclouddata \n\tmakeclouddata [-h|--help]"; + + $rc = check_options($req,$callback); + if ($rc == -1) { + my $rsp = {}; + $rsp->{data}->[0] = $usage; + xCAT::MsgUtils->message("E", $rsp, $callback, 1); + return; + } elsif ($rc == 1) { + my $rsp = {}; + $rsp->{data}->[0] = $usage; + xCAT::MsgUtils->message("I", $rsp, $callback, 0); + return; + } + + my $tab = "clouds"; + my $ptab = xCAT::Table->new("$tab"); + + unless ($ptab) { + my $rsp; + $rsp->{errorcode}->[0]=1; + $rsp->{error}->[0]="Unable to open $tab table"; + $callback->($rsp); + return; + } + + + my $t = $req->{clouds}; + my %h; + if( defined(@$t) ) { + %h = map { $_ => 1} @$t; + } + + my @cloudentries = $ptab->getAllAttribs('name', 'template', 'repository'); + + foreach my $cloudentry (@cloudentries) { + + my $cloud = $cloudentry->{name}; + if( %h ) { + # if makeclouddata , and + if( $h{$cloud} != 1) { + next; + } + } + + my $tmplfile = $cloudentry->{template}; + my $repos = $cloudentry->{repository}; + + unless ( -r "$tmplfile") { + my $rsp; + $rsp->{errorcode}->[0]=1; + $rsp->{error}->[0]="The $cloud environment template $tmplfile doesn't exist."; + $callback->($rsp); + next; + } + + unless ( -r "$repos") { + my $rsp; + $rsp->{errorcode}->[0]=1; + $rsp->{error}->[0]="The $cloud repository $repos doesn't exist."; + $callback->($rsp); + next; + } + + my $tmperr = cloudvars( + $tmplfile, + "$repos/environments/$cloud.rb", + $cloud, + $callback + ); + + } + return; +} + +1; diff --git a/xCAT-server/lib/perl/xCAT/Postage.pm b/xCAT-server/lib/perl/xCAT/Postage.pm index a3456a1b6..2d96b9498 100644 --- a/xCAT-server/lib/perl/xCAT/Postage.pm +++ b/xCAT-server/lib/perl/xCAT/Postage.pm @@ -213,6 +213,8 @@ sub makescript { $mn = xCAT::Utils->noderangecontainsMn(@$nodes); + my $cfgflag=0; + my $cloudflag=0; my $inc; my $t_inc; my %table; @@ -239,6 +241,14 @@ sub makescript { } } + if( $line =~ /#CFGMGTINFO_EXPORT#/ ) { + $cfgflag = 1; + } + if ($cfgflag == 1) { + if( $line =~ /#CLOUDINFO_EXPORT#/ ) { + $cloudflag = 1; + } + } } close($inh); @@ -334,7 +344,23 @@ sub makescript { # get all the nodes' setstate my $nodes_setstate_hash = getNodesSetState($nodes); - + + my $cfginfo_hash; + my $cloudinfo_hash; + # + # if #CFGCLIENTLIST_EXPORT# exists, ... + if( $cfgflag == 1 ) { + $cfginfo_hash = getcfginfo(); + # + # if #CLOUDINFO_EXPORT# exists, ... + if( $cloudflag == 1) { + $cloudinfo_hash = getcloudinfo(); + + } + } + + + foreach my $n (@$nodes ) { $node = $n; $inc = $t_inc; @@ -447,7 +473,15 @@ sub makescript { my $enablesshbetweennodes = enableSSHbetweennodes($node, \%::GLOBAL_SN_HASH, $groups_hash); - + my @clients; + my $cfgres; + my $cloudres; + if ( $cfgflag == 1 ) { + $cfgres = getcfgres($cfginfo_hash, $node, \@clients); + if ( $cloudflag == 1 ) { + $cloudres = getcloudres($cloudinfo_hash, \@clients); + } + } #ok, now do everything else.. #$inc =~ s/#XCATVAR:([^#]+)#/envvar($1)/eg; #$inc =~ s/#ENV:([^#]+)#/envvar($1)/eg; @@ -462,6 +496,9 @@ sub makescript { $inc =~ s/#NETWORK_FOR_DISKLESS_EXPORT#/$diskless_net_vars/eg; $inc =~ s/#INCLUDE_POSTSCRIPTS_LIST#/$postscripts/eg; $inc =~ s/#INCLUDE_POSTBOOTSCRIPTS_LIST#/$postbootscripts/eg; + + $inc =~ s/#CFGMGTINFO_EXPORT#/$cfgres/eg; + $inc =~ s/#CLOUDINFO_EXPORT#/$cloudres/eg; $inc =~ s/\$ENABLESSHBETWEENNODES/$enablesshbetweennodes/eg; $inc =~ s/\$NSETSTATE/$nodesetstate/eg; @@ -1699,7 +1736,127 @@ sub getPostbootScripts return $result; } +sub getcfginfo +{ + my %info = (); + my $tab = "cfgmgt"; + my $ptab = xCAT::Table->new($tab); + unless ($ptab) { + xCAT::MsgUtils->message("E", "Unable to open $tab table"); + return undef + } + my @rs = $ptab->getAllAttribs('node','cfgserver','roles'); + + foreach my $r ( @rs ) { + my $node = $r->{'node'}; + my $server = $r->{'cfgserver'}; + my $roles = $r->{'roles'}; + $info{ $server }{clientlist} .= "$node,"; + $info{ $node }{roles} = $roles; + + } + + return \%info; + + +} + +sub getcfgres +{ + my $cfginfo_hash = shift; + my $server = shift; + my $clients = shift; + my $cfgclient_list; + my $cfgres; + if( ! ( exists($cfginfo_hash->{$server}) && exists( $cfginfo_hash->{$server}->{clientlist} ) ) ) { + return $cfgres; + } + + $cfgclient_list = $cfginfo_hash->{$server}->{clientlist}; + chop $cfgclient_list; + $cfgres = "CFGCLIENTLIST='$cfgclient_list'\n"; + $cfgres .= "export CFGCLIENTLIST\n"; + @$clients = split(',', $cfgclient_list); + foreach my $client (@$clients) { + my $roles = $cfginfo_hash->{$client}->{roles}; + #$cfgres .= "hput $client roles $roles\n"; + $cfgres .= "HASH".$client."roles='$roles'\nexport HASH".$client."roles\n"; + } + + return $cfgres; +} + +sub getcloudinfo +{ + my %info = (); + + my $tab = "clouds"; + my $ptab = xCAT::Table->new($tab); + unless ($ptab) { + xCAT::MsgUtils->message("E", "Unable to open $tab table"); + return undef; + } + my @rs = $ptab->getAllAttribs('name','repository'); + + foreach my $r ( @rs ) { + my $cloud = $r->{'name'}; + my $repos = $r->{'repository'}; + $info{ $cloud }{repository} = $repos; + } + + $tab = "cloud"; + $ptab = xCAT::Table->new($tab); + unless ($ptab) { + xCAT::MsgUtils->message("E", "Unable to open $tab table"); + return undef; + } + @rs = $ptab->getAllAttribs('node','cloudname'); + + my $pre; + my $curr; + foreach my $r ( @rs ) { + my $node = $r->{'node'}; + my $cloud = $r->{'cloudname'}; + $info{ $node }{cloud} = $cloud; + } + + return \%info; +} + +sub getcloudres +{ + my $cloudinfo_hash = shift; + my $clients = shift; + my $cloudres; + my $cloudlist; + my $repos; + if( @$clients == 0 ) { + return $cloudres; + } + foreach my $client (@$clients) { + my $cloud; + if( defined($cloudinfo_hash) && defined($cloudinfo_hash->{$client}) ) { + $cloud = $cloudinfo_hash->{$client}->{cloud}; + } + #$cloudres .= "hput $client cloud $cloud\n"; + $cloudres .= "HASH".$client."cloud='$cloud'\nexport HASH".$client."cloud\n"; + $cloudlist .="$cloud,"; + + my $t = $cloudinfo_hash->{$cloud}->{repository}; + if( !defined($repos) ) { + $repos = $t; + } + if( defined($repos) && ( $repos != $t && "$repos/" != $t && $repos != "$t/" ) ) { + xCAT::MsgUtils->message("E", "Two cloud repositories: $repos and $t.\n There should be only one cloud repository one ont chef-server."); + return undef; + } + } + chop $cloudlist; + $cloudres = "REPOSITORY='$repos'\nexport REPOSITORY\nCLOUDLIST='$cloudlist'\nexport CLOUDLIST\n$cloudres"; + return $cloudres; +} + 1; From a77996e9339518bfcbba21b59fd1b548f79e434f Mon Sep 17 00:00:00 2001 From: jjhua Date: Tue, 22 Oct 2013 10:22:39 -0400 Subject: [PATCH 36/91] Postscripts for OpenStack-Chef-Cookbook/xCAT integration --- xCAT/postscripts/config_chef_client | 19 +- xCAT/postscripts/config_chef_server | 28 +++ xCAT/postscripts/config_chef_workstation | 21 ++- xCAT/postscripts/hashlib.sh | 16 ++ xCAT/postscripts/loadchefdata | 212 +++++++++++++++++++++++ xCAT/postscripts/mountinstall | 50 ++++++ 6 files changed, 340 insertions(+), 6 deletions(-) create mode 100755 xCAT/postscripts/hashlib.sh create mode 100755 xCAT/postscripts/loadchefdata create mode 100755 xCAT/postscripts/mountinstall diff --git a/xCAT/postscripts/config_chef_client b/xCAT/postscripts/config_chef_client index ac95062d5..4d06eca7f 100755 --- a/xCAT/postscripts/config_chef_client +++ b/xCAT/postscripts/config_chef_client @@ -30,16 +30,29 @@ if [ -z "$chef_server" ]; then chef_server=$CHEFSERVER fi if [ -z "$chef_server" ]; then - chef_server=$SITEMASTER + chef_server=$MASTER fi fi mkdir -p /etc/chef +mkdir -p /etc/chef-server_tmp + +mount $chef_server:/etc/chef-server /etc/chef-server_tmp +if [ $? -ne 0 ] +then + errmsg="Failed to run 'mount $chef_server:/etc/chef-server /etc/chef-server_tmp' on $node" + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 +fi + # copy the validator.pem to chef client -scp root@$chef_server:/etc/chef-server/chef-validator.pem /etc/chef/validation.pem - +#scp root@$chef_server:/etc/chef-server/chef-validator.pem /etc/chef/validation.pem +cp /etc/chef-server_tmp/chef-validator.pem /etc/chef/validation.pem +umount /etc/chef-server_tmp +rmdir /etc/chef-server_tmp # Add the info to /etc/chef/client.rb echo -e "log_level :auto diff --git a/xCAT/postscripts/config_chef_server b/xCAT/postscripts/config_chef_server index b59938de2..b1ac1ce15 100755 --- a/xCAT/postscripts/config_chef_server +++ b/xCAT/postscripts/config_chef_server @@ -25,4 +25,32 @@ then exit 1 fi +# for ubuntu +if [ -e "/etc/lsb-release" ] +then + apt-get install nfs-kernel-server portmap nfs-common -y + + grep "/etc/chef-server" /etc/exports + if [ $? -ne 0 ] + then + echo -e "\n/etc/chef-server *(rw,no_root_squash,sync,no_subtree_check)\n" >> /etc/exports + fi + sudo /etc/init.d/nfs-kernel-server restart + if [ $? -ne 0 ] + then + errmsg="Failed to run sudo /etc/init.d/nfs-kernel-server restart on $node" + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi + service portmap restart + if [ $? -ne 0 ] + then + errmsg="Failed to run service portmap restart on $node" + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi +fi + exit 0; diff --git a/xCAT/postscripts/config_chef_workstation b/xCAT/postscripts/config_chef_workstation index c17e41cf7..23c104acc 100755 --- a/xCAT/postscripts/config_chef_workstation +++ b/xCAT/postscripts/config_chef_workstation @@ -35,7 +35,7 @@ then fi if [ -z "$chefserver" ] then - chefserver=$SITEMASTER + chefserver=$MASTER fi fi @@ -78,8 +78,23 @@ then validation_key='/etc/chef-server/chef-validator.pem' else # Remote chef-server - scp $chefserver:/etc/chef-server/admin.pem $homedir/.chef 2>&1 1>/dev/null - scp $chefserver:/etc/chef-server/chef-validator.pem $homedir/.chef 2>&1 1>/dev/null + #scp $chefserver:/etc/chef-server/admin.pem $homedir/.chef 2>&1 1>/dev/null + #scp $chefserver:/etc/chef-server/chef-validator.pem $homedir/.chef 2>&1 1>/dev/null + mkdir -p /etc/chef + mkdir -p /etc/chef-server_tmp + + mount $chef_server:/etc/chef-server /etc/chef-server_tmp + if [ $? -ne 0 ] + then + errmsg="Failed to run 'mount $chef_server:/etc/chef-server /etc/chef-server_tmp' on $node" + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi + cp /etc/chef-server_tmp/admin.pem $homedir/.chef 2>&1 1>/dev/null + cp /etc/chef-server_tmp/chef-validator.pem $homedir/.chef 2>&1 1>/dev/null + umount /etc/chef-server_tmp + rmdir /etc/chef-server_tmp if [ ! -e "$homedir/.chef/admin.pem" ] || [ ! -e "$homedir/.chef/chef-validator.pem" ] then errmsg="Could not get the chef keys from chef server $chefserver" diff --git a/xCAT/postscripts/hashlib.sh b/xCAT/postscripts/hashlib.sh new file mode 100755 index 000000000..78fb47c9e --- /dev/null +++ b/xCAT/postscripts/hashlib.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +## defined HASH functions here +hput() { + eval "HASH""$1""$2"='$3' +} + +hget() { + eval echo '${'"HASH$1$2"'}' +} + +hkeys() { + set | grep -o "^HASH${1}[[:alnum:]]*=" | sed -re "s/^HASH${1}(.*)=/\\1/g" +} + + diff --git a/xCAT/postscripts/loadchefdata b/xCAT/postscripts/loadchefdata new file mode 100755 index 000000000..41e525314 --- /dev/null +++ b/xCAT/postscripts/loadchefdata @@ -0,0 +1,212 @@ +#!/bin/sh +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html + +# This script, ("loadchefdata"), is a sample xCAT post script for +# upload the openstack-cookbooks, roles, enviornment to the +# xCAT chef-server node, and then create the chef-client +# nodes, and then assign the role and environment name to the +# chef-client nodes +# +# Make sure your script is executable and that is is in the +# /install/postscripts directory on the xCAT management node. +# +# You must add the script name to the list of scripts that +# must be run at install time, or use it with updatenode. +# +# To use this script you should make sure it gets run after the +# "mountinstall" script or any other scipts that may need to use +# scripts in the /install directory. +# +# For example, to get it to run after the "mountinstall" script you +# could set the "postbootscripts" attribute of the chef-server node +# definitions as follows: +# +# chdef -t node -o chef-server postbootscripts="mountinstall,loadchefdata" +# + + +# load shell hash lib +source ./hashlib.sh + +#flags +no_args=0 +only_load_cookbook=0 +only_load_role=0 +only_load_clouddata=0 + +if [ $# -eq 0 ] +then + no_args=1 +else + for arg in "$@" + do + if [ "$arg" = "--cookbook" ] + then + only_load_cookbook=1 + elif [ "$arg" = "--role" ] + then + only_load_role=1 + elif [ "$arg" = "--clouddata" ] + then + only_load_clouddata=1 + else + errmsg="no argument $arg in the loadchefdata script" + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi + done +fi + + + +# enter the repository director +# for example: cd /install/chef-cookbooks/grizzy-xcat/ +if [ ! -d "$REPOSITORY" ] +then + errmsg="$REPOSITORY is not a OpenStack Chef cookbooks directory." + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 +fi +cd $REPOSITORY + +if [ $no_args -eq 1 -o $only_load_cookbook -eq 1 ] +then + # upload coobooks + knife cookbook bulk delete '.*' -y > /dev/null 2>&1 + knife cookbook upload -o cookbooks --all + if [ $? != 0 ] + then + errmsg="Failed to run knife cookbook upload -o cookbooks --all on the chefserver $NODE." + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi +fi + +if [ $no_args -eq 1 -o $only_load_role -eq 1 ] +then + # upload roles + knife role bulk delete '.*' -y > /dev/null 2>&1 + knife role from file roles/*.rb + if [ $? != 0 ] + then + errmsg="Failed to run knife role from file roles/*.rb on the chefserver $NODE." + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi + +fi + + +if [ $no_args -eq 1 -o $only_load_clouddata -eq 1 ] +then + + if [ -z $CFGCLIENTLIST ] + then + msg="No cfgclient on the cfgserver $NODE?" + logger -t xcat -p local3.info $msg + echo $errmsg + exit 0 + fi + + #CLOUDLIST='cloud1,cloud1,cloud3' + OIFS=$IFS + IFS=',' + for cloud in $CLOUDLIST + do + echo "loading the enviornment file $cloud.rb for $cloud" + # knife environment delete xcat_per-tenant_routers_with_private_networks -y + # knife environment delete xcat_per-tenant_routers_with_private_networks -y + # load the environment file + # knife environment from file environments/xcat_per-tenant_routers_with_private_networks.rb + if [ ! -e "$REPOSITORY/environments/$cloud.rb" ] + then + errmsg="$REPOSITORY/environments/$cloud.rb doesn't exsit. run mkclouddata at first." + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi + knife environment from file environments/$cloud.rb + if [ $? != 0 ] + then + errmsg="Failed to run knife environment from file environments/$cloud.rb on the chef-server $NODE." + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi + done + #IFS=$OIFS + + #CFGCLIENTLIST='node1,node1,node3' + #OIFS=$IFS + #IFS=',' + for client in $CFGCLIENTLIST + do + echo "Configuring the chef-client node $client on the chef-server $NODE." + c_fullname="$client.$DOMAIN" + knife client delete -y $c_fullname > /dev/null 2>&1 + knife node delete -y $c_fullname > /dev/null 2>&1 + + #create nodes on this chef-server + # knife node create test3 -d + knife node create $c_fullname -d + if [ $? != 0 ] + then + errmsg="Failed to run knife node create $client -d on the chef-server $NODE." + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi + + roles=`hget $client roles` + if [ -z $roles ] + then + errmsg="No roles for $client. Please check the cfgmgt table." + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi + + # assign the role for the chef node + knife node run_list add $c_fullname "role[$roles]" + if [ $? != 0 ] + then + errmsg="Failed to run knife node run_list add $client 'role[$roles]' on the chef-server $NODE." + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi + + # assign the new environment to the chef client node + newenv=`hget $client cloud` + if [ -z $newenv ] + then + errmsg="No cloud for $client. Please check the cloud table." + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi + origenv=`knife node show $c_fullname -E | sed -e 's/[ ]*//g'| awk -F: '{print $2}'` + EDITOR="sed -e s/$origenv/$newenv/ -i" knife node edit $c_fullname + if [ $? != 0 ] + then + errmsg="Failed to run knife node edit $client on the chef-server $NODE." + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi + + + done +fi + +IFS=$OIFS + + +exit 0 + + + diff --git a/xCAT/postscripts/mountinstall b/xCAT/postscripts/mountinstall new file mode 100755 index 000000000..1ac5f7412 --- /dev/null +++ b/xCAT/postscripts/mountinstall @@ -0,0 +1,50 @@ +#!/bin/sh +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html + +# This script, ("mountinstall"), is a sample xCAT post script for +# mounting /install from managment node to xCAT chef-server +# nodes. +# +# Make sure your script is executable and that is is in the +# /install/postscripts directory on the xCAT management node. +# +# You must add the script name to the list of scripts that +# must be run at install time, or use it with updatenode. +# +# To use this script you should make sure it gets run before the +# "loadchefdata" script or any other scipts that may need to use +# scripts in the /install directory. +# +# For example, to get it to run before the "loadchefdata" script you +# could set the "postbootscripts" attribute of the chef-server node +# definitions as follows: +# +# chdef -t node -o chef-server postbootscripts="mountinstall,loadchefdata" +# + + +if [ -z "$INSTALLDIR" ]; then + INSTALLDIR="/install" +fi + + +mount | grep "$MASTER:$INSTALLDIR" +if [ $? -ne 0 ] +then + exit 0 +fi + + +# mount the files systems +mkdir /install + +mount $MASTER:$INSTALLDIR /install +if [ $? -ne 0 ] +then + errmsg="Failed to run mount $MASTER:$INSTALLDIR /install" + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 +fi + +exit 0 From e852d0b26411cb149f5ec14f2026b7a8a23eec8a Mon Sep 17 00:00:00 2001 From: jjhua Date: Tue, 22 Oct 2013 10:45:41 -0400 Subject: [PATCH 37/91] changes for the command makeclouddata --- xCAT-OpenStack/xCAT-OpenStack.spec | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xCAT-OpenStack/xCAT-OpenStack.spec b/xCAT-OpenStack/xCAT-OpenStack.spec index 55e492145..363a5935a 100644 --- a/xCAT-OpenStack/xCAT-OpenStack.spec +++ b/xCAT-OpenStack/xCAT-OpenStack.spec @@ -28,11 +28,15 @@ management. %install mkdir -p $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_schema +mkdir -p $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin cp -a lib/perl/xCAT_schema/* $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_schema find $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_schema -type d -exec chmod 755 {} \; find $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_schema -type f -exec chmod 644 {} \; +cp -a lib/perl/xCAT_plugin/* $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin + +ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/sbin/makeclouddata %clean rm -rf $RPM_BUILD_ROOT From f8daa39253f79633c0c5fdad1ffb4ed456707c11 Mon Sep 17 00:00:00 2001 From: jjhua Date: Tue, 22 Oct 2013 13:25:45 -0400 Subject: [PATCH 38/91] fixed a minor problem --- xCAT/postscripts/mountinstall | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xCAT/postscripts/mountinstall b/xCAT/postscripts/mountinstall index 1ac5f7412..bf8a0fe86 100755 --- a/xCAT/postscripts/mountinstall +++ b/xCAT/postscripts/mountinstall @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/sh -vx # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html # This script, ("mountinstall"), is a sample xCAT post script for @@ -28,8 +28,8 @@ if [ -z "$INSTALLDIR" ]; then fi -mount | grep "$MASTER:$INSTALLDIR" -if [ $? -ne 0 ] +mount | grep "$MASTER:$INSTALLDIR on /install" +if [ $? -eq 0 ] then exit 0 fi From d464001ca138d51ab8dfa23e906e1946a3dd8a37 Mon Sep 17 00:00:00 2001 From: jjhua Date: Tue, 22 Oct 2013 14:29:56 -0400 Subject: [PATCH 39/91] Add the chef-client to invoke the config_chef_client script --- xCAT/postscripts/chef-client | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100755 xCAT/postscripts/chef-client diff --git a/xCAT/postscripts/chef-client b/xCAT/postscripts/chef-client new file mode 100755 index 000000000..834b78f3f --- /dev/null +++ b/xCAT/postscripts/chef-client @@ -0,0 +1,20 @@ +#!/bin/sh + +#This script will invoke the config_chef_client directly. +#If the chef-server and chef-client are installed successfully at first, +#and then on the chef-server node configure the software for the chef-client nodes. +#We can run +# updatenode chef-client +#To configure the softare on the chef-client node. + +./config_chef_client + +if [ $? -ne 0 ] +then + errmsg="Failed to run the postscript ./config_chef_client on $node" + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 +fi + +exit 0; From bcd72b4040c111b1bcbb6b76bf02e15579306310 Mon Sep 17 00:00:00 2001 From: immarvin Date: Tue, 22 Oct 2013 00:57:14 -0700 Subject: [PATCH 40/91] fix defect #3626 yaboot.pm needs to use pkgdir --- xCAT-server/lib/xcat/plugins/yaboot.pm | 43 +++++++++++++++++--------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/yaboot.pm b/xCAT-server/lib/xcat/plugins/yaboot.pm index fda2ccb33..cc8863de3 100644 --- a/xCAT-server/lib/xcat/plugins/yaboot.pm +++ b/xCAT-server/lib/xcat/plugins/yaboot.pm @@ -194,7 +194,7 @@ sub setstate { close($pcfg); my $inetn = xCAT::NetworkUtils->getipaddr($node); unless ($inetn) { - syslog("local4|err","xCAT unable to resolve IP for $node in yaboot plugin"); + syslog("local1|err","xCAT unable to resolve IP for $node in yaboot plugin"); return; } } else { #TODO: actually, should possibly default to xCAT image? @@ -252,7 +252,7 @@ sub setstate { close($pcfg); my $inetn = xCAT::NetworkUtils->getipaddr($node); unless ($inetn) { - syslog("local4|err","xCAT unable to resolve IP for $node in yaboot plugin"); + syslog("local1|err","xCAT unable to resolve IP for $node in yaboot plugin"); return; } } else { #TODO: actually, should possibly default to xCAT image? @@ -261,7 +261,7 @@ sub setstate { } my $ip = xCAT::NetworkUtils->getipaddr($node); unless ($ip) { - syslog("local4|err","xCAT unable to resolve IP in yaboot plugin"); + syslog("local1|err","xCAT unable to resolve IP in yaboot plugin"); return; } my $mactab = xCAT::Table->new('mac'); @@ -500,8 +500,9 @@ sub process_request { my $nrtab=xCAT::Table->new('noderes',-create=>1); my $nrhash=$nrtab->getNodesAttribs(\@nodes,['servicenode']); my $typetab=xCAT::Table->new('nodetype',-create=>1); - my $typehash=$typetab->getNodesAttribs(\@nodes,['os','provmethod']); + my $typehash=$typetab->getNodesAttribs(\@nodes,['os','provmethod','arch','profile']); my $linuximgtab=xCAT::Table->new('linuximage',-create=>1); + my $osimagetab=xCAT::Table->new('osimage',-create=>1); my $rc; my $errstr; @@ -538,15 +539,22 @@ sub process_request { my @normalnodeset = keys %normalnodes; my @breaknetboot=keys %breaknetbootnodes; #print "yaboot:inittime=$inittime; normalnodeset=@normalnodeset; breaknetboot=@breaknetboot\n"; - my %oshash; + my %osimagenodehash; for my $nn (@normalnodeset){ #record the os version for node - my $ent = $typehash->{$nn}->[0]; - my $os = $ent->{'os'}; - push @{$oshash{$os}}, $nn; + my $ent = $typehash->{$nn}->[0]; + my $osimage=$ent->{'provmethod'}; + if($osimage =~ /^(install|netboot|statelite)$/){ + $osimage=($ent->{'os'}).'-'.($ent->{'arch'}).'-'.($ent->{'provmethod'}).'-'.($ent->{'profile'}); + } + push @{$osimagenodehash{$osimage}}, $nn; } - foreach my $os (keys %oshash) { + + foreach my $osimage (keys %osimagenodehash) { + my $osimgent = $osimagetab->getAttribs({imagename => $osimage },'osvers'); + my $os = $osimgent->{'osvers'}; + my $osv; my $osn; my $osm; @@ -560,6 +568,7 @@ sub process_request { $osn = $2; $osm = 0; } + if (($osv =~ /rh/ and int($osn) < 6) or ($osv =~ /sles/ and int($osn) < 11)) { # check if xcat-yaboot installed @@ -582,16 +591,20 @@ sub process_request { xCAT::MsgUtils->message("E", $rsp, $callback); return; } - my $yabootpath = $tftpdir."/yb/".$os; - mkpath $yabootpath; + my $yabootpath = $tftpdir."/yb/".$os; + mkpath $yabootpath; + + my $linuximgent = $linuximgtab->getAttribs({imagename => $osimage},'pkgdir'); + my @pkgdirlist = split /,/, $linuximgent->{'pkgdir'}; + my $pkgdir = $pkgdirlist[0]; + $pkgdir =~ s/\/+$//; + my $yabootfile; if ($os =~ /sles/) { - my $installdir = $::XCATSITEVALS{'installdir'} ? $::XCATSITEVALS{'installdir'} : "/install"; - $yabootfile = $installdir."/".$os."/ppc64/1/suseboot/yaboot"; + $yabootfile = $pkgdir."/1/suseboot/yaboot"; } elsif ($os =~ /rh/){ - my $installdir = $::XCATSITEVALS{'installdir'} ? $::XCATSITEVALS{'installdir'} : "/install"; - $yabootfile = $installdir."/".$os."/ppc64/ppc/chrp/yaboot"; + $yabootfile = $pkgdir."/ppc/chrp/yaboot"; } unless (-e "$yabootfile") { my $rsp; From 105b54d4cdb9161f12226dfc72d6578f7604d154 Mon Sep 17 00:00:00 2001 From: immarvin Date: Tue, 22 Oct 2013 04:53:02 -0700 Subject: [PATCH 41/91] fix defect #3626 yaboot.pm needs to use pkgdir --- xCAT-server/lib/xcat/plugins/yaboot.pm | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/yaboot.pm b/xCAT-server/lib/xcat/plugins/yaboot.pm index cc8863de3..f3de6d60b 100644 --- a/xCAT-server/lib/xcat/plugins/yaboot.pm +++ b/xCAT-server/lib/xcat/plugins/yaboot.pm @@ -625,7 +625,7 @@ sub process_request { return; } } - } #end of foreach oshash + } #end of foreach osimagenodehash #Don't bother to try dhcp binding changes if sub_req not passed, i.e. service node build time unless (($args[0] eq 'stat') || ($inittime) || ($args[0] eq 'offline')) { @@ -642,8 +642,11 @@ sub process_request { #} if ($do_dhcpsetup) { - if (%oshash) { - foreach my $osentry (keys %oshash) { + if (%osimagenodehash) { + foreach my $osimage (keys %osimagenodehash) { + my $osimgent = $osimagetab->getAttribs({imagename => $osimage },'osvers'); + my $osentry = $osimgent->{'osvers'}; + my $osv; my $osn; my $osm; @@ -662,20 +665,20 @@ sub process_request { my $fpath = "/yb/". $osentry."/yaboot"; if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command $sub_req->({command=>['makedhcp'], - node=>\@{$oshash{$osentry}}, + node=>\@{$osimagenodehash{$osimage}}, arg=>['-l','-s','filename = \"'.$fpath.'\";']},$callback); } else { $sub_req->({command=>['makedhcp'], - node=>\@{$oshash{$osentry}}, + node=>\@{$osimagenodehash{$osimage}}, arg=>['-s','filename = \"'.$fpath.'\";']},$callback); } } else { if ($request->{'_disparatetftp'}->[0]) { #reading hint from preprocess_command, only change local settings if already farmed $sub_req->({command=>['makedhcp'],arg=>['-l'], - node=>\@{$oshash{$osentry}}},$callback); + node=>\@{$osimagenodehash{$osimage}}},$callback); } else { $sub_req->({command=>['makedhcp'], - node=>\@{$oshash{$osentry}}},$callback); + node=>\@{$osimagenodehash{$osimage}}},$callback); } } } From 06e244202b8d06842fdf014dac2a85713481b63c Mon Sep 17 00:00:00 2001 From: immarvin Date: Tue, 22 Oct 2013 05:11:27 -0700 Subject: [PATCH 42/91] correct xcat-yaboot in error message to yaboot-xcat --- xCAT-server/lib/xcat/plugins/yaboot.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/yaboot.pm b/xCAT-server/lib/xcat/plugins/yaboot.pm index f3de6d60b..2e71b594d 100644 --- a/xCAT-server/lib/xcat/plugins/yaboot.pm +++ b/xCAT-server/lib/xcat/plugins/yaboot.pm @@ -571,12 +571,12 @@ sub process_request { if (($osv =~ /rh/ and int($osn) < 6) or ($osv =~ /sles/ and int($osn) < 11)) { - # check if xcat-yaboot installed + # check if yaboot-xcat installed my $yf = $tftpdir . "/yaboot"; unless (-e $yf) { my $rsp; push @{$rsp->{data}}, - "stop configuration because xcat-yaboot need to be installed for $os.\n"; + "stop configuration because yaboot-xcat need to be installed for $os.\n"; xCAT::MsgUtils->message("E", $rsp, $callback); return; } From 3243037a918374ae92919410c38122f1adc06e23 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Mon, 21 Oct 2013 10:44:15 -0400 Subject: [PATCH 43/91] For newer versions of esxi for which we have selected a less vague name, ensure we remake it every time. --- xCAT-server/lib/xcat/plugins/esx.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/esx.pm b/xCAT-server/lib/xcat/plugins/esx.pm index 235264205..1f4af072e 100644 --- a/xCAT-server/lib/xcat/plugins/esx.pm +++ b/xCAT-server/lib/xcat/plugins/esx.pm @@ -4514,12 +4514,12 @@ sub makecustomizedmod { my $modname; if ($osver =~ /esxi4/) { #want more descriptive name,but don't break esxi4 setups. $modname="mod.tgz"; + # if it already exists, do not overwrite it because it may be someone + # else's custom image + if(-f "$dest/$modname"){ return 1; } } else { $modname="xcatmod.tgz"; } - # if it already exists, do not overwrite it because it may be someone - # else's custom image - if(-f "$dest/$modname"){ return 1; } my $passtab = xCAT::Table->new('passwd'); my $tmp; my $password; From 50a853c96eccca20e28422b43a18999dbf338f37 Mon Sep 17 00:00:00 2001 From: daniceexi Date: Wed, 23 Oct 2013 14:00:09 -0400 Subject: [PATCH 44/91] add more kernel modules of scsi for localdisk support --- xCAT-server/share/xcat/netboot/sles/genimage | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-server/share/xcat/netboot/sles/genimage b/xCAT-server/share/xcat/netboot/sles/genimage index aa3eda6d6..3a11a8d3f 100755 --- a/xCAT-server/share/xcat/netboot/sles/genimage +++ b/xCAT-server/share/xcat/netboot/sles/genimage @@ -804,7 +804,7 @@ if (@new_order) { } # add drivers for local disk support -push @ndrivers, ("ext3.ko", "ext4.ko", "virtio_pci.ko", "virtio_blk.ko", "ata_piix.ko", "libata.ko", "scsi_mod.ko", "ibmvscsi.ko", "ibmvscsic.ko", "megaraid_sas.ko", "pcieport.ko", "sd_mod.ko"); +push @ndrivers, ("ext3.ko", "ext4.ko", "virtio_pci.ko", "virtio_blk.ko", "ata_piix.ko", "libata.ko", "scsi_mod.ko", "scsi_dh.ko", "ahci.ko", "ibmvscsi.ko", "ibmvscsic.ko", "megaraid_sas.ko", "pcieport.ko", "sd_mod.ko"); open($moddeps,"<","$rootimg_dir/lib/modules/$kernelver/modules.dep"); my @moddeps = <$moddeps>; From 4e59b13e0f5c9b28427d2db536d99d4c2ef026c2 Mon Sep 17 00:00:00 2001 From: jjhua Date: Wed, 23 Oct 2013 22:41:15 -0400 Subject: [PATCH 45/91] move out the code to read cloud/clouds table from Postage.pm to Cloud.pm in xCAT-OpenStack. Move out the loadchefdata script. --- xCAT-OpenStack/lib/perl/xCAT/Cloud.pm | 158 +++++++++++++++++++ xCAT-server/lib/perl/xCAT/Postage.pm | 174 +++++++++++---------- xCAT/postscripts/hashlib.sh | 16 -- xCAT/postscripts/loadchefdata | 212 -------------------------- xCAT/postscripts/mountinstall | 2 +- 5 files changed, 249 insertions(+), 313 deletions(-) create mode 100644 xCAT-OpenStack/lib/perl/xCAT/Cloud.pm delete mode 100755 xCAT/postscripts/hashlib.sh delete mode 100755 xCAT/postscripts/loadchefdata diff --git a/xCAT-OpenStack/lib/perl/xCAT/Cloud.pm b/xCAT-OpenStack/lib/perl/xCAT/Cloud.pm new file mode 100644 index 000000000..171b7ad4b --- /dev/null +++ b/xCAT-OpenStack/lib/perl/xCAT/Cloud.pm @@ -0,0 +1,158 @@ +# IBM(c) 2013 EPL license http://www.eclipse.org/legal/epl-v10.html +package xCAT::Cloud; + +BEGIN +{ + $::XCATROOT = + $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} + : -d '/opt/xcat' ? '/opt/xcat' + : '/usr'; +} +use lib "$::XCATROOT/lib/perl"; +use xCAT::Table; +use xCAT::MsgUtils; +use xCAT::NodeRange; +use xCAT::Utils; +use xCAT::TableUtils; +#use Data::Dumper; +use strict; + + + +#----------------------------------------------------------------------------- + +=head3 getcloudinfo + + This function will be invoked by Postage.pm. + get the chef cookbook repository for each cloud from the clouds table, and + then get all the node --> cloud from the cloud table. The two type information + will be stored in the %info + + If success, return the \%info. + + + Arguments: + none + Returns: + \%info + + Error: + none + Example: + + Comments: + none + +=cut + +#----------------------------------------------------------------------------- + + +sub getcloudinfo +{ + my %info = (); + + my $tab = "clouds"; + my $ptab = xCAT::Table->new($tab); + unless ($ptab) { + xCAT::MsgUtils->message("E", "Unable to open $tab table"); + return undef; + } + my @rs = $ptab->getAllAttribs('name','repository'); + + foreach my $r ( @rs ) { + my $cloud = $r->{'name'}; + my $repos = $r->{'repository'}; + $info{ $cloud }{repository} = $repos; + } + + $tab = "cloud"; + $ptab = xCAT::Table->new($tab); + unless ($ptab) { + xCAT::MsgUtils->message("E", "Unable to open $tab table"); + return undef; + } + @rs = $ptab->getAllAttribs('node','cloudname'); + + my $pre; + my $curr; + foreach my $r ( @rs ) { + my $node = $r->{'node'}; + my $cloud = $r->{'cloudname'}; + $info{ $node }{cloud} = $cloud; + } + + return \%info; + + + +} + + +#----------------------------------------------------------------------------- + +=head3 getcloudres + + This function will be invoked by Postage.pm. And it's only for one chef-server. + 1. get the chef cookbook repository for the clouds on one chef-server. + All the clouds's repositoryies on one chef-server should be the same one. + 2. get the cloud list for one chef-server + 3. get the cloud name for each node on the same chef-server + + + Arguments: + $cloudinfo_hash -- This is from the getcloudinfo function. + $clients -- an array which stores different cloud nodes(chef-client) + Returns: + $cloudres -- a string including cloud information + + Error: + none + Example: + + Comments: + none + +=cut + +#----------------------------------------------------------------------------- + + + +sub getcloudres +{ + my $cloudinfo_hash = shift; + my $clients = shift; + my $cloudres; + my $cloudlist; + my $repos; + if( @$clients == 0 ) { + return $cloudres; + } + foreach my $client (@$clients) { + my $cloud; + if( defined($cloudinfo_hash) && defined($cloudinfo_hash->{$client}) ) { + $cloud = $cloudinfo_hash->{$client}->{cloud}; + } + #$cloudres .= "hput $client cloud $cloud\n"; + $cloudres .= "HASH".$client."cloud='$cloud'\nexport HASH".$client."cloud\n"; + if ( $cloudlist !~ $cloud ) { + $cloudlist .="$cloud,"; + } + + my $t = $cloudinfo_hash->{$cloud}->{repository}; + if( !defined($repos) ) { + $repos = $t; + } + if( defined($repos) && ( $repos != $t && "$repos/" != $t && $repos != "$t/" ) ) { + xCAT::MsgUtils->message("E", "Two cloud repositories: $repos and $t.\n There should be only one cloud repository one ont chef-server."); + return undef; + } + } + chop $cloudlist; + $cloudres = "REPOSITORY='$repos'\nexport REPOSITORY\nCLOUDLIST='$cloudlist'\nexport CLOUDLIST\n$cloudres"; + return $cloudres; +} + + +1; diff --git a/xCAT-server/lib/perl/xCAT/Postage.pm b/xCAT-server/lib/perl/xCAT/Postage.pm index 2d96b9498..0ff0066df 100644 --- a/xCAT-server/lib/perl/xCAT/Postage.pm +++ b/xCAT-server/lib/perl/xCAT/Postage.pm @@ -223,6 +223,11 @@ sub makescript { #First load input into memory.. while (<$inh>) { my $line = $_; + + if( $line =~ /#INCLUDE:[^#^\n]+#/ ) { + $line =~ s/#INCLUDE:([^#^\n]+)#/includetmpl($1)/eg; + } + if ($line !~/^##/ ) { $t_inc.=$line; } @@ -241,14 +246,11 @@ sub makescript { } } + if( $line =~ /#CFGMGTINFO_EXPORT#/ ) { $cfgflag = 1; } - if ($cfgflag == 1) { - if( $line =~ /#CLOUDINFO_EXPORT#/ ) { - $cloudflag = 1; - } - } + } close($inh); @@ -347,20 +349,25 @@ sub makescript { my $cfginfo_hash; my $cloudinfo_hash; + $cfginfo_hash = getcfginfo(); # - # if #CFGCLIENTLIST_EXPORT# exists, ... - if( $cfgflag == 1 ) { - $cfginfo_hash = getcfginfo(); - # - # if #CLOUDINFO_EXPORT# exists, ... - if( $cloudflag == 1) { - $cloudinfo_hash = getcloudinfo(); - - } + #check it the cloud module exists or not + #the default doesn't exist. + my $cloud_exists = 0; + my $cloud_module_name="xCAT::Cloud"; + eval("use $cloud_module_name;"); + if (!$@) { + $cloud_exists = 1; + if( $cfgflag == 0) { + my $rsp; + $rsp->{errorcode}->[0]=1; + $rsp->{error}->[0]="xCAT-OpenStack needs the tag #CFGMGTINFO_EXPORT# in $tmpl.\n"; + $callback->($rsp); + return; + } + $cloudinfo_hash = getcloudinfo($cloud_module_name, $cloud_exists); } - - - + foreach my $n (@$nodes ) { $node = $n; $inc = $t_inc; @@ -476,12 +483,11 @@ sub makescript { my @clients; my $cfgres; my $cloudres; - if ( $cfgflag == 1 ) { - $cfgres = getcfgres($cfginfo_hash, $node, \@clients); - if ( $cloudflag == 1 ) { - $cloudres = getcloudres($cloudinfo_hash, \@clients); - } + $cfgres = getcfgres($cfginfo_hash, $node, \@clients); + if ( $cloud_exists == 1 ) { + $cloudres = getcloudres($cloud_module_name, $cloud_exists, $cloudinfo_hash, \@clients); } + #ok, now do everything else.. #$inc =~ s/#XCATVAR:([^#]+)#/envvar($1)/eg; #$inc =~ s/#ENV:([^#]+)#/envvar($1)/eg; @@ -1788,75 +1794,75 @@ sub getcfgres sub getcloudinfo { - my %info = (); - my $tab = "clouds"; - my $ptab = xCAT::Table->new($tab); - unless ($ptab) { - xCAT::MsgUtils->message("E", "Unable to open $tab table"); - return undef; + my $module_name = shift; + my $cloud_exists = shift; + my $result; + + #get cloud info + if ( $cloud_exists ) { + no strict "refs"; + if (defined(${$module_name."::"}{getcloudinfo})) { + $result=${$module_name."::"}{getcloudinfo}(); + } } - my @rs = $ptab->getAllAttribs('name','repository'); + return $result; +} - foreach my $r ( @rs ) { - my $cloud = $r->{'name'}; - my $repos = $r->{'repository'}; - $info{ $cloud }{repository} = $repos; - } - - $tab = "cloud"; - $ptab = xCAT::Table->new($tab); - unless ($ptab) { - xCAT::MsgUtils->message("E", "Unable to open $tab table"); - return undef; - } - @rs = $ptab->getAllAttribs('node','cloudname'); - - my $pre; - my $curr; - foreach my $r ( @rs ) { - my $node = $r->{'node'}; - my $cloud = $r->{'cloudname'}; - $info{ $node }{cloud} = $cloud; - } - - return \%info; - - - -} sub getcloudres { + my $module_name = shift; + my $cloud_exists = shift; my $cloudinfo_hash = shift; - my $clients = shift; - my $cloudres; - my $cloudlist; - my $repos; - if( @$clients == 0 ) { - return $cloudres; - } - foreach my $client (@$clients) { - my $cloud; - if( defined($cloudinfo_hash) && defined($cloudinfo_hash->{$client}) ) { - $cloud = $cloudinfo_hash->{$client}->{cloud}; - } - #$cloudres .= "hput $client cloud $cloud\n"; - $cloudres .= "HASH".$client."cloud='$cloud'\nexport HASH".$client."cloud\n"; - $cloudlist .="$cloud,"; - - my $t = $cloudinfo_hash->{$cloud}->{repository}; - if( !defined($repos) ) { - $repos = $t; - } - if( defined($repos) && ( $repos != $t && "$repos/" != $t && $repos != "$t/" ) ) { - xCAT::MsgUtils->message("E", "Two cloud repositories: $repos and $t.\n There should be only one cloud repository one ont chef-server."); - return undef; - } - } - chop $cloudlist; - $cloudres = "REPOSITORY='$repos'\nexport REPOSITORY\nCLOUDLIST='$cloudlist'\nexport CLOUDLIST\n$cloudres"; - return $cloudres; + my $clients = shift; + my $result; + + #get cloud res + if ( $cloud_exists ) { + no strict "refs"; + if (defined(${$module_name."::"}{getcloudres})) { + $result=${$module_name."::"}{getcloudres}($cloudinfo_hash, $clients); + } + } + return $result; } +## +# +#This function only can be used for #INCLUDE:filepath# in mypostscript.tmpl . +#It doesn't support the #INCLUDE:filepath# in the new $file. So it doesn't +#support the repeated include. +#It will put all the content of the file into @text excetp the empty line +sub includetmpl +{ + my $file = shift; + my @text = (); + + if ( ! -r $file ) { + return ""; + } + + open(INCLUDE, $file) || \return ""; + + while () + { + chomp($_); #remove newline + s/\s+$//; #remove trailing spaces + next if /^\s*$/; #-- skip empty lines + if (/^@(.*)/) + { #for groups that has space in name + my $save = $1; + if ($1 =~ / /) { $_ = "\@" . $save; } + } + push(@text, $_); + } + + close(INCLUDE); + + return join(',', @text); +} + + + 1; diff --git a/xCAT/postscripts/hashlib.sh b/xCAT/postscripts/hashlib.sh deleted file mode 100755 index 78fb47c9e..000000000 --- a/xCAT/postscripts/hashlib.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -## defined HASH functions here -hput() { - eval "HASH""$1""$2"='$3' -} - -hget() { - eval echo '${'"HASH$1$2"'}' -} - -hkeys() { - set | grep -o "^HASH${1}[[:alnum:]]*=" | sed -re "s/^HASH${1}(.*)=/\\1/g" -} - - diff --git a/xCAT/postscripts/loadchefdata b/xCAT/postscripts/loadchefdata deleted file mode 100755 index 41e525314..000000000 --- a/xCAT/postscripts/loadchefdata +++ /dev/null @@ -1,212 +0,0 @@ -#!/bin/sh -# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html - -# This script, ("loadchefdata"), is a sample xCAT post script for -# upload the openstack-cookbooks, roles, enviornment to the -# xCAT chef-server node, and then create the chef-client -# nodes, and then assign the role and environment name to the -# chef-client nodes -# -# Make sure your script is executable and that is is in the -# /install/postscripts directory on the xCAT management node. -# -# You must add the script name to the list of scripts that -# must be run at install time, or use it with updatenode. -# -# To use this script you should make sure it gets run after the -# "mountinstall" script or any other scipts that may need to use -# scripts in the /install directory. -# -# For example, to get it to run after the "mountinstall" script you -# could set the "postbootscripts" attribute of the chef-server node -# definitions as follows: -# -# chdef -t node -o chef-server postbootscripts="mountinstall,loadchefdata" -# - - -# load shell hash lib -source ./hashlib.sh - -#flags -no_args=0 -only_load_cookbook=0 -only_load_role=0 -only_load_clouddata=0 - -if [ $# -eq 0 ] -then - no_args=1 -else - for arg in "$@" - do - if [ "$arg" = "--cookbook" ] - then - only_load_cookbook=1 - elif [ "$arg" = "--role" ] - then - only_load_role=1 - elif [ "$arg" = "--clouddata" ] - then - only_load_clouddata=1 - else - errmsg="no argument $arg in the loadchefdata script" - logger -t xcat -p local4.err $errmsg - echo $errmsg - exit 1 - fi - done -fi - - - -# enter the repository director -# for example: cd /install/chef-cookbooks/grizzy-xcat/ -if [ ! -d "$REPOSITORY" ] -then - errmsg="$REPOSITORY is not a OpenStack Chef cookbooks directory." - logger -t xcat -p local4.err $errmsg - echo $errmsg - exit 1 -fi -cd $REPOSITORY - -if [ $no_args -eq 1 -o $only_load_cookbook -eq 1 ] -then - # upload coobooks - knife cookbook bulk delete '.*' -y > /dev/null 2>&1 - knife cookbook upload -o cookbooks --all - if [ $? != 0 ] - then - errmsg="Failed to run knife cookbook upload -o cookbooks --all on the chefserver $NODE." - logger -t xcat -p local4.err $errmsg - echo $errmsg - exit 1 - fi -fi - -if [ $no_args -eq 1 -o $only_load_role -eq 1 ] -then - # upload roles - knife role bulk delete '.*' -y > /dev/null 2>&1 - knife role from file roles/*.rb - if [ $? != 0 ] - then - errmsg="Failed to run knife role from file roles/*.rb on the chefserver $NODE." - logger -t xcat -p local4.err $errmsg - echo $errmsg - exit 1 - fi - -fi - - -if [ $no_args -eq 1 -o $only_load_clouddata -eq 1 ] -then - - if [ -z $CFGCLIENTLIST ] - then - msg="No cfgclient on the cfgserver $NODE?" - logger -t xcat -p local3.info $msg - echo $errmsg - exit 0 - fi - - #CLOUDLIST='cloud1,cloud1,cloud3' - OIFS=$IFS - IFS=',' - for cloud in $CLOUDLIST - do - echo "loading the enviornment file $cloud.rb for $cloud" - # knife environment delete xcat_per-tenant_routers_with_private_networks -y - # knife environment delete xcat_per-tenant_routers_with_private_networks -y - # load the environment file - # knife environment from file environments/xcat_per-tenant_routers_with_private_networks.rb - if [ ! -e "$REPOSITORY/environments/$cloud.rb" ] - then - errmsg="$REPOSITORY/environments/$cloud.rb doesn't exsit. run mkclouddata at first." - logger -t xcat -p local4.err $errmsg - echo $errmsg - exit 1 - fi - knife environment from file environments/$cloud.rb - if [ $? != 0 ] - then - errmsg="Failed to run knife environment from file environments/$cloud.rb on the chef-server $NODE." - logger -t xcat -p local4.err $errmsg - echo $errmsg - exit 1 - fi - done - #IFS=$OIFS - - #CFGCLIENTLIST='node1,node1,node3' - #OIFS=$IFS - #IFS=',' - for client in $CFGCLIENTLIST - do - echo "Configuring the chef-client node $client on the chef-server $NODE." - c_fullname="$client.$DOMAIN" - knife client delete -y $c_fullname > /dev/null 2>&1 - knife node delete -y $c_fullname > /dev/null 2>&1 - - #create nodes on this chef-server - # knife node create test3 -d - knife node create $c_fullname -d - if [ $? != 0 ] - then - errmsg="Failed to run knife node create $client -d on the chef-server $NODE." - logger -t xcat -p local4.err $errmsg - echo $errmsg - exit 1 - fi - - roles=`hget $client roles` - if [ -z $roles ] - then - errmsg="No roles for $client. Please check the cfgmgt table." - logger -t xcat -p local4.err $errmsg - echo $errmsg - exit 1 - fi - - # assign the role for the chef node - knife node run_list add $c_fullname "role[$roles]" - if [ $? != 0 ] - then - errmsg="Failed to run knife node run_list add $client 'role[$roles]' on the chef-server $NODE." - logger -t xcat -p local4.err $errmsg - echo $errmsg - exit 1 - fi - - # assign the new environment to the chef client node - newenv=`hget $client cloud` - if [ -z $newenv ] - then - errmsg="No cloud for $client. Please check the cloud table." - logger -t xcat -p local4.err $errmsg - echo $errmsg - exit 1 - fi - origenv=`knife node show $c_fullname -E | sed -e 's/[ ]*//g'| awk -F: '{print $2}'` - EDITOR="sed -e s/$origenv/$newenv/ -i" knife node edit $c_fullname - if [ $? != 0 ] - then - errmsg="Failed to run knife node edit $client on the chef-server $NODE." - logger -t xcat -p local4.err $errmsg - echo $errmsg - exit 1 - fi - - - done -fi - -IFS=$OIFS - - -exit 0 - - - diff --git a/xCAT/postscripts/mountinstall b/xCAT/postscripts/mountinstall index bf8a0fe86..62097e469 100755 --- a/xCAT/postscripts/mountinstall +++ b/xCAT/postscripts/mountinstall @@ -19,7 +19,7 @@ # could set the "postbootscripts" attribute of the chef-server node # definitions as follows: # -# chdef -t node -o chef-server postbootscripts="mountinstall,loadchefdata" +# chdef -t node -o chef-server postbootscripts="mountinstall,loadclouddata" # From 7cff2524011e0c8203a8481b74b574bb3d97c4ab Mon Sep 17 00:00:00 2001 From: jjhua Date: Wed, 23 Oct 2013 22:56:17 -0400 Subject: [PATCH 46/91] add the loadclouddata, share/xcat/mypostscript/mypostscript_cloud.tmpl into xCAT-OpenStack --- xCAT-OpenStack/postscripts/loadclouddata | 224 ++++++++++++++++++ xCAT-OpenStack/sbin/makeclouddata | 56 +++++ .../xcat/mypostscript/mypostscript_cloud.tmpl | 1 + xCAT-OpenStack/xCAT-OpenStack.spec | 22 +- .../share/xcat/mypostscript/mypostscript.tmpl | 4 + 5 files changed, 306 insertions(+), 1 deletion(-) create mode 100755 xCAT-OpenStack/postscripts/loadclouddata create mode 100755 xCAT-OpenStack/sbin/makeclouddata create mode 100644 xCAT-OpenStack/share/xcat/mypostscript/mypostscript_cloud.tmpl diff --git a/xCAT-OpenStack/postscripts/loadclouddata b/xCAT-OpenStack/postscripts/loadclouddata new file mode 100755 index 000000000..5e27bd25d --- /dev/null +++ b/xCAT-OpenStack/postscripts/loadclouddata @@ -0,0 +1,224 @@ +#!/bin/sh +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html + +# This script, ("loadclouddata"), is a sample xCAT post script for +# upload the openstack-cookbooks, roles, enviornment to the +# xCAT chef-server node, and then create the chef-client +# nodes, and then assign the role and environment name to the +# chef-client nodes +# +# Make sure your script is executable and that is is in the +# /install/postscripts directory on the xCAT management node. +# +# You must add the script name to the list of scripts that +# must be run at install time, or use it with updatenode. +# +# To use this script you should make sure it gets run after the +# "mountinstall" script or any other scipts that may need to use +# scripts in the /install directory. +# +# For example, to get it to run after the "mountinstall" script you +# could set the "postbootscripts" attribute of the chef-server node +# definitions as follows: +# +# chdef -t node -o chef-server postbootscripts="mountinstall,loadclouddata" +# + + +## defined HASH functions here +hput() { + eval "HASH""$1""$2"='$3' +} + +hget() { + eval echo '${'"HASH$1$2"'}' +} + +hkeys() { + set | grep -o "^HASH${1}[[:alnum:]]*=" | sed -re "s/^HASH${1}(.*)=/\\1/g" +} + + + +#flags +no_args=0 +only_load_cookbook=0 +only_load_role=0 +only_load_clouddata=0 + +if [ $# -eq 0 ] +then + no_args=1 +else + for arg in "$@" + do + if [ "$arg" = "--cookbook" ] + then + only_load_cookbook=1 + elif [ "$arg" = "--role" ] + then + only_load_role=1 + elif [ "$arg" = "--clouddata" ] + then + only_load_clouddata=1 + else + errmsg="no argument $arg in the loadchefdata script" + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi + done +fi + + + +# enter the repository director +# for example: cd /install/chef-cookbooks/grizzy-xcat/ +if [ ! -d "$REPOSITORY" ] +then + errmsg="$REPOSITORY is not a OpenStack Chef cookbooks directory." + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 +fi +cd $REPOSITORY + +if [ $no_args -eq 1 -o $only_load_cookbook -eq 1 ] +then + # upload coobooks + knife cookbook bulk delete '.*' -y > /dev/null 2>&1 + knife cookbook upload -o cookbooks --all + if [ $? != 0 ] + then + errmsg="Failed to run knife cookbook upload -o cookbooks --all on the chefserver $NODE." + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi +fi + +if [ $no_args -eq 1 -o $only_load_role -eq 1 ] +then + # upload roles + knife role bulk delete '.*' -y > /dev/null 2>&1 + knife role from file roles/*.rb + if [ $? != 0 ] + then + errmsg="Failed to run knife role from file roles/*.rb on the chefserver $NODE." + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi + +fi + + +if [ $no_args -eq 1 -o $only_load_clouddata -eq 1 ] +then + + if [ -z $CFGCLIENTLIST ] + then + msg="No cfgclient on the cfgserver $NODE?" + logger -t xcat -p local3.info $msg + echo $errmsg + exit 0 + fi + + #CLOUDLIST='cloud1,cloud1,cloud3' + OIFS=$IFS + IFS=',' + for cloud in $CLOUDLIST + do + echo "loading the enviornment file $cloud.rb for $cloud" + # knife environment delete xcat_per-tenant_routers_with_private_networks -y + # knife environment delete xcat_per-tenant_routers_with_private_networks -y + # load the environment file + # knife environment from file environments/xcat_per-tenant_routers_with_private_networks.rb + if [ ! -e "$REPOSITORY/environments/$cloud.rb" ] + then + errmsg="$REPOSITORY/environments/$cloud.rb doesn't exsit. run mkclouddata at first." + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi + knife environment from file environments/$cloud.rb + if [ $? != 0 ] + then + errmsg="Failed to run knife environment from file environments/$cloud.rb on the chef-server $NODE." + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi + done + #IFS=$OIFS + + #CFGCLIENTLIST='node1,node1,node3' + #OIFS=$IFS + #IFS=',' + for client in $CFGCLIENTLIST + do + echo "Configuring the chef-client node $client on the chef-server $NODE." + c_fullname="$client.$DOMAIN" + knife client delete -y $c_fullname > /dev/null 2>&1 + knife node delete -y $c_fullname > /dev/null 2>&1 + + #create nodes on this chef-server + # knife node create test3 -d + knife node create $c_fullname -d + if [ $? != 0 ] + then + errmsg="Failed to run knife node create $client -d on the chef-server $NODE." + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi + + roles=`hget $client roles` + if [ -z $roles ] + then + errmsg="No roles for $client. Please check the cfgmgt table." + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi + + # assign the role for the chef node + knife node run_list add $c_fullname "role[$roles]" + if [ $? != 0 ] + then + errmsg="Failed to run knife node run_list add $client 'role[$roles]' on the chef-server $NODE." + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi + + # assign the new environment to the chef client node + newenv=`hget $client cloud` + if [ -z $newenv ] + then + errmsg="No cloud for $client. Please check the cloud table." + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi + origenv=`knife node show $c_fullname -E | sed -e 's/[ ]*//g'| awk -F: '{print $2}'` + EDITOR="sed -e s/$origenv/$newenv/ -i" knife node edit $c_fullname + if [ $? != 0 ] + then + errmsg="Failed to run knife node edit $client on the chef-server $NODE." + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit 1 + fi + + + done +fi + +IFS=$OIFS + + +exit 0 + + + diff --git a/xCAT-OpenStack/sbin/makeclouddata b/xCAT-OpenStack/sbin/makeclouddata new file mode 100755 index 000000000..583d7c549 --- /dev/null +++ b/xCAT-OpenStack/sbin/makeclouddata @@ -0,0 +1,56 @@ +#!/usr/bin/env perl +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html + +# Used as a standard client cmd that can be used for xcat cmds that do not have +# noderange as an argument. See xcatclient for additional documentation. + +# To put the cloud command only in xCAT-OpenStack, just copy the ../bin/xcatclientnnr +# as makeclouddata command here. we couldn't sym link the command makecloudata +# to this script ../bin/xcatclientnnr in xCAT-OpenStack.spec. + +BEGIN { $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr'; } +use lib "$::XCATROOT/lib/perl"; +use Cwd; +use File::Basename; +use xCAT::Client; +use strict; + +my $bname = basename($0); +my $cmdref; +if ($bname =~ /xcatclientnnr/) { $cmdref->{command}->[0]=shift @ARGV; } # xcatclientnnr was invoked directly and the 1st arg is cmd name that is used to locate the plugin +else { $cmdref->{command}->[0] = $bname; } # the cmd was sym linked to xcatclientnnr +$cmdref->{cwd}->[0] = cwd(); +my $data; +# allows our plugins to get the stdin of the cmd that invoked the plugin +if ( (($^O =~ /^linux/i) && ($ENV{'SHELL'} =~ /\/ksh$/)) || !defined($ENV{'TERM'}) ) +{ + my $rout; + my $rin=""; + vec($rin,fileno(STDIN),1)=1; + my $nfound=select($rout=$rin,"","",1); + if ($nfound) + { + while ( ) { $data.=$_; } + $cmdref->{stdin}->[0]=$data; + } +} +else +{ + if (-p STDIN) { + while ( ) { $data.=$_; } + $cmdref->{stdin}->[0]=$data; + } +} + + +push (@{$cmdref->{arg}}, @ARGV); +foreach (keys %ENV) { + if (/^XCAT_/) { + $cmdref->{environment}->{$_} = $ENV{$_}; + } +} + +xCAT::Client::submit_request($cmdref,\&xCAT::Client::handle_response); +exit $xCAT::Client::EXITCODE; + + diff --git a/xCAT-OpenStack/share/xcat/mypostscript/mypostscript_cloud.tmpl b/xCAT-OpenStack/share/xcat/mypostscript/mypostscript_cloud.tmpl new file mode 100644 index 000000000..1a1554069 --- /dev/null +++ b/xCAT-OpenStack/share/xcat/mypostscript/mypostscript_cloud.tmpl @@ -0,0 +1 @@ +#CLOUDINFO_EXPORT# diff --git a/xCAT-OpenStack/xCAT-OpenStack.spec b/xCAT-OpenStack/xCAT-OpenStack.spec index 363a5935a..ce73bb671 100644 --- a/xCAT-OpenStack/xCAT-OpenStack.spec +++ b/xCAT-OpenStack/xCAT-OpenStack.spec @@ -29,20 +29,40 @@ management. %install mkdir -p $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_schema mkdir -p $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin +mkdir -p $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT +mkdir -p $RPM_BUILD_ROOT/install/postscripts +mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/xcat/mypostscript +mkdir -p $RPM_BUILD_ROOT/%{prefix}/sbin cp -a lib/perl/xCAT_schema/* $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_schema find $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_schema -type d -exec chmod 755 {} \; find $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_schema -type f -exec chmod 644 {} \; cp -a lib/perl/xCAT_plugin/* $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin +chmod 644 $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin/* -ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/sbin/makeclouddata +cp -a lib/perl/xCAT/* $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT +chmod 644 $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT/* + +cp sbin/* $RPM_BUILD_ROOT/%{prefix}/sbin +chmod 755 $RPM_BUILD_ROOT/%{prefix}/sbin/* + + +#ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/sbin/makeclouddata + +#cd - +cp -a postscripts/* $RPM_BUILD_ROOT/install/postscripts +chmod 755 $RPM_BUILD_ROOT/install/postscripts/* + +cp -a share/xcat/mypostscript/* $RPM_BUILD_ROOT/%{prefix}/share/xcat/mypostscript +chmod 644 $RPM_BUILD_ROOT/%{prefix}/share/xcat/mypostscript/* %clean rm -rf $RPM_BUILD_ROOT %files %{prefix} +/install/postscripts %defattr(-,root,root) diff --git a/xCAT-server/share/xcat/mypostscript/mypostscript.tmpl b/xCAT-server/share/xcat/mypostscript/mypostscript.tmpl index 05e07433c..1dd311b95 100755 --- a/xCAT-server/share/xcat/mypostscript/mypostscript.tmpl +++ b/xCAT-server/share/xcat/mypostscript/mypostscript.tmpl @@ -121,6 +121,10 @@ export CFGMGR CFGSERVER=#TABLE:cfgmgt:$NODE:cfgserver# export CFGSERVER +#CFGMGTINFO_EXPORT# + +#INCLUDE:/opt/xcat/share/xcat/mypostscript/mypostscript_cloud.tmpl# + ## ##The line postscripts-start-here must not be deleted. From 67f5b9c8084e71b3473f6a9300d01c3d86b4eeae Mon Sep 17 00:00:00 2001 From: daniceexi Date: Wed, 23 Oct 2013 15:01:40 -0400 Subject: [PATCH 47/91] change the position to run localdisk script that put it before killing udev. For stateless only. --- xCAT-server/share/xcat/netboot/sles/genimage | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-server/share/xcat/netboot/sles/genimage b/xCAT-server/share/xcat/netboot/sles/genimage index 3a11a8d3f..22fcc24d4 100755 --- a/xCAT-server/share/xcat/netboot/sles/genimage +++ b/xCAT-server/share/xcat/netboot/sles/genimage @@ -1374,6 +1374,7 @@ EOMS print $inifile " exit\n"; print $inifile "fi\n"; + print $inifile "\$NEWROOT/etc/init.d/localdisk\n"; # to run the localdisk # udevd needed by s390x for networking # but for other type of machine, udevd will affect the start of devices which detected # after the chroot, so kill it before the switching root @@ -1382,7 +1383,6 @@ EOMS } print $inifile "cd /\n"; - print $inifile "\$NEWROOT/etc/init.d/localdisk\n"; # to run the localdisk print $inifile "mkdir \$NEWROOT/var/lib/dhcpcd/\n"; #neccessary for SLES11, not sure for SLES10 print $inifile "cp /var/lib/dhcpcd/* \$NEWROOT/var/lib/dhcpcd/\n"; print $inifile "cp /etc/resolv.conf \$NEWROOT/etc/\n"; From 857af4d4983a9942d5fb397443ba74ca5a0eeab0 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Wed, 23 Oct 2013 11:15:04 -0400 Subject: [PATCH 48/91] Send a positive acknowledgement of flow request --- xCAT-server/sbin/xcatd | 1 + 1 file changed, 1 insertion(+) diff --git a/xCAT-server/sbin/xcatd b/xCAT-server/sbin/xcatd index 85d05da73..ec8f2b3f2 100755 --- a/xCAT-server/sbin/xcatd +++ b/xCAT-server/sbin/xcatd @@ -694,6 +694,7 @@ sleep 0.05; store_fd({data=>$data,sockaddr=>$saddr},$discoctl); } else { # for *now*, we'll do a tiny YAML subset if ($data =~ /^resourcerequest: xcatd$/) { + $socket->send("ackresourcerequest\n",0,$packets{$pkey}->[0]); $tcclients->{$pkey}={ sockaddr=>$packets{$pkey}->[0], timestamp=>time() } } } # JSON maybe one day if important From 3bf30fcc3851ea60e2242a39428e9405b45f8ce3 Mon Sep 17 00:00:00 2001 From: lissav Date: Wed, 23 Oct 2013 13:50:05 -0400 Subject: [PATCH 49/91] defect 3851- handle multiple MN in DB --- perl-xCAT/xCAT/DSHCLI.pm | 16 +++++++++---- perl-xCAT/xCAT/ServiceNodeUtils.pm | 13 ++++++----- xCAT-server/lib/perl/xCAT/Postage.pm | 4 ++-- xCAT-server/lib/xcat/plugins/updatenode.pm | 7 +++--- xCAT-server/sbin/xcatconfig | 26 +++++++++++++--------- 5 files changed, 40 insertions(+), 26 deletions(-) diff --git a/perl-xCAT/xCAT/DSHCLI.pm b/perl-xCAT/xCAT/DSHCLI.pm index ecdb2b4c3..73d1a9232 100644 --- a/perl-xCAT/xCAT/DSHCLI.pm +++ b/perl-xCAT/xCAT/DSHCLI.pm @@ -3237,7 +3237,14 @@ sub bld_resolve_nodes_hash # find out if we have an MN in the list, local cp and sh will be used # not remote shell - my $mname = xCAT::Utils->noderangecontainsMn(@target_list); + # find out the names for the Management Node + my @MNnodeinfo = xCAT::NetworkUtils->determinehostname; + my $mname = pop @MNnodeinfo; # hostname + #my $rsp = {}; + #$rsp->{info}->[0] = + # "Management node name is $mname."; + # xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); + foreach my $target (@target_list) { @@ -4079,11 +4086,12 @@ sub parse_and_run_dsh # check if any node in the noderange is the Management Node and exit # with error, if the Management Node is in the Database and in the # noderange - my $mname = xCAT::Utils->noderangecontainsMn(@nodelist); - if ($mname) { # MN in the nodelist + my @mname = xCAT::Utils->noderangecontainsMn(@nodelist); + if (@mname) { # MN in the nodelist + my $nodes=join(',', @mname); my $rsp = {}; $rsp->{error}->[0] = - "You must not run -K option against the Management Node:$mname."; + "You must not run -K option against the Management Node:$nodes."; xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1); return; } diff --git a/perl-xCAT/xCAT/ServiceNodeUtils.pm b/perl-xCAT/xCAT/ServiceNodeUtils.pm index 5bcf6508b..28bf81a98 100644 --- a/perl-xCAT/xCAT/ServiceNodeUtils.pm +++ b/perl-xCAT/xCAT/ServiceNodeUtils.pm @@ -242,12 +242,13 @@ sub getAllSN # if did not input "ALL" and there is a MN, remove it my @newservicenodes; if ((!defined($options)) || ($options ne "ALL")) { - my $mname = xCAT::Utils->noderangecontainsMn(@servicenodes); - if ($mname) { # if there is a MN - foreach my $nodes (@servicenodes) { - if ($mname ne ($nodes)){ - push @newservicenodes, $nodes; - } + my @mname = xCAT::Utils->noderangecontainsMn(@servicenodes); + if (@mname) { # if there is a MN + foreach my $node (@servicenodes) { + # check to see if node in MN list + if (!(grep(/^$node$/, @mname))) { # if node not in the MN array + push @newservicenodes, $node; + } } $servicenodetab->close; return @newservicenodes; # return without the MN in the array diff --git a/xCAT-server/lib/perl/xCAT/Postage.pm b/xCAT-server/lib/perl/xCAT/Postage.pm index 0ff0066df..250c28eb8 100644 --- a/xCAT-server/lib/perl/xCAT/Postage.pm +++ b/xCAT-server/lib/perl/xCAT/Postage.pm @@ -211,7 +211,7 @@ sub makescript { return; } - $mn = xCAT::Utils->noderangecontainsMn(@$nodes); + @::mn = xCAT::Utils->noderangecontainsMn(@$nodes); my $cfgflag=0; my $cloudflag=0; @@ -652,7 +652,7 @@ sub getNodeType my $node = shift; my $result; - if ( $node =~ /^$mn$/) { + if (grep(/^$node$/, @::mn)) { # is it in the Management Node array $result="MN"; return $result; } diff --git a/xCAT-server/lib/xcat/plugins/updatenode.pm b/xCAT-server/lib/xcat/plugins/updatenode.pm index 3162d71fa..6adc76019 100644 --- a/xCAT-server/lib/xcat/plugins/updatenode.pm +++ b/xCAT-server/lib/xcat/plugins/updatenode.pm @@ -396,12 +396,13 @@ sub preprocess_updatenode # check to see if the Management Node is in the noderange and # if it is abort - my $mname = xCAT::Utils->noderangecontainsMn(@$nodes); - if ($mname) + my @mname = xCAT::Utils->noderangecontainsMn(@$nodes); + if (@mname) { # MN in the nodelist + my $nodes=join(',', @mname); my $rsp = {}; $rsp->{error}->[0] = - "You must not run -k option against the Management Node:$mname."; + "You must not run -k option against a management node: $nodes."; xCAT::MsgUtils->message("E", $rsp, $callback, 1); return; } diff --git a/xCAT-server/sbin/xcatconfig b/xCAT-server/sbin/xcatconfig index 5d0aa1191..f9d0b428a 100755 --- a/xCAT-server/sbin/xcatconfig +++ b/xCAT-server/sbin/xcatconfig @@ -2124,23 +2124,27 @@ sub setupMNinDB my $defined = 0; my $cmds="XCATBYPASS=Y $::XCATROOT/sbin/tabdump nodelist | grep __mgmtnode"; - my $output = xCAT::Utils->runcmd("$cmds", -1); + my @output = xCAT::Utils->runcmd("$cmds", -1); + if ($::RUNCMD_RC == 0) # found a management node defined { my $chtabcmds; - my @mn = split(",", $output); + my @mn = split(",", $output[0]); $mn[0] =~ s/"//g; # remove the quotes if ($mn[0] ne $mnname) { # does not match current host name,delete it - $chtabcmds = "$::XCATROOT/sbin/chtab -d node=$mn[0] nodelist;"; - my $outref = xCAT::Utils->runcmd("$chtabcmds", 0); - if ($::RUNCMD_RC != 0) - { - xCAT::MsgUtils->message('E', "Could not run $chtabcmds."); - return; - } + my $size=@output; # if more than one management node defined, do not remove any + if ($size == 1) { + $chtabcmds = "$::XCATROOT/sbin/chtab -d node=$mn[0] nodelist;"; + my $outref = xCAT::Utils->runcmd("$chtabcmds", 0); + if ($::RUNCMD_RC != 0) + { + xCAT::MsgUtils->message('E', "Could not run $chtabcmds."); + return; + } + } } else { # it is defined and good - xCAT::MsgUtils->message('I', "$mnname already defined in the nodelist table."); - $defined=1; + xCAT::MsgUtils->message('I', "$mnname already defined in the nodelist table."); + $defined=1; } } # now add with the new name , if not already there From eac9954e26e8f06721582b33f8ba74b10f881c67 Mon Sep 17 00:00:00 2001 From: zhaoertao Date: Wed, 23 Oct 2013 23:44:04 -0700 Subject: [PATCH 50/91] fix bug 3651: rspconfig with cmm does not execute or provide error when entry found in ipmi table --- perl-xCAT/xCAT/Utils.pm | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/perl-xCAT/xCAT/Utils.pm b/perl-xCAT/xCAT/Utils.pm index 26f3f867b..fd6052a90 100644 --- a/perl-xCAT/xCAT/Utils.pm +++ b/perl-xCAT/xCAT/Utils.pm @@ -3253,6 +3253,11 @@ sub filter_nodes{ if ($ipmitab) { $ipmitabhash = $ipmitab->getNodesAttribs(\@nodes,['bmc']); } + my $nodehmhash; + my $nodehmtab = xCAT::Table->new("nodehm"); + if ($nodehmtab) { + $nodehmhash = $nodehmtab->getNodesAttribs(\@nodes,['mgt']); + } my (@mp, @ngpfsp, @ngpbmc, @commonfsp, @commonbmc, @unknow); @@ -3262,6 +3267,15 @@ sub filter_nodes{ # if only in 'ipmi', a common x86 node foreach (@nodes) { if (defined ($mptabhash->{$_}->[0]) && defined ($mptabhash->{$_}->[0]->{'mpa'})) { + if ($mptabhash->{$_}->[0]->{'mpa'} eq $_) { + if (defined($nodehmhash->{$_}->[0]) && defined($nodehmhash->{$_}->[0]->{'mgt'}) && + $nodehmhash->{$_}->[0]->{'mgt'} eq "blade") { + push @mp, $_; + } else { + push @unknow, $_; + } + next; + } if (defined ($ppctabhash->{$_}->[0]) && defined ($ppctabhash->{$_}->[0]->{'hcp'})) { # flex power node push @ngpfsp, $_; @@ -3307,6 +3321,7 @@ sub filter_nodes{ } else { push @{$mpnodes}, @ngpfsp; } + push @{$mpnodes}, @ngpbmc; } elsif ($cmd eq "rvitals") { if (@args && (grep /^lcds$/,@args)) { push @{$fspnodes},@ngpfsp; From 5565f20b8b1bfe5a8609d76ed433af29dfd443ff Mon Sep 17 00:00:00 2001 From: wanghuaz Date: Thu, 24 Oct 2013 15:07:04 +0800 Subject: [PATCH 51/91] fixing bug 3848: add prerequisite component as dependency of kit component meta rpm --- xCAT-buildkit/bin/buildkit | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/xCAT-buildkit/bin/buildkit b/xCAT-buildkit/bin/buildkit index 2c4d2e374..02ca942cb 100755 --- a/xCAT-buildkit/bin/buildkit +++ b/xCAT-buildkit/bin/buildkit @@ -1915,6 +1915,8 @@ sub build_kitcomp # specifically reference it's version-release if ( &update_kitcomp_kitpkgdeps($comp,$repodir) ) { return 1; } + $::VALID_PRER_COMPONENT = 0; + if ( !$::PREREQUISITE ) { if ( $comp->{ospkgdeps} || $comp->{preinstall} || $comp->{preupgrade} || $comp->{preuninstall} ) { if ( &gen_kitcomp_spec($comp,\%repo, 'PREREQUISITE') ) { return 1; } @@ -1954,6 +1956,8 @@ sub build_kitcomp } } + $::VALID_PRER_COMPONENT = 1; + } if ( &gen_kitcomp_spec($comp,\%repo, 'METARPM') ) { return 1; } @@ -2271,7 +2275,12 @@ sub gen_kitcomp_spec s/<<>>/$::bldkit_config->{kit}{entries}[0]->{url}/; s/<<>>//; s/<<>>/$comp->{kitpkgdeps}/; - s/<<>>/$comp->{kitcompdeps}/; + #Update kitcompdeps for prep_ + if ( $::VALID_PRER_COMPONENT ) { + s/<<>>/$comp->{kitcompdeps},prep_$comp->{basename}/; + } else { + s/<<>>/$comp->{kitcompdeps}/; + } s/<<>>/$comp->{description}/; s/<<>>/$nonnativepkgs/; s/<<>>/$sourcetar/; From fb60b65258d42a04dec6c822ce4c99d52a37b33e Mon Sep 17 00:00:00 2001 From: sjing Date: Thu, 24 Oct 2013 04:19:47 -0400 Subject: [PATCH 52/91] Handle the case where networks.nameservers is a comma delimited list --- xCAT-server/lib/xcat/plugins/ddns.pm | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/ddns.pm b/xCAT-server/lib/xcat/plugins/ddns.pm index 397284f39..9c543d9eb 100644 --- a/xCAT-server/lib/xcat/plugins/ddns.pm +++ b/xCAT-server/lib/xcat/plugins/ddns.pm @@ -296,14 +296,23 @@ sub process_request { my @networks = $networkstab->getAllAttribs('net','mask','ddnsdomain','domain','nameservers'); # exclude the net if it is using an external dns server. - foreach (@networks) + foreach my $net (@networks) { - if ($_ and $_->{nameservers}) + if ($net and $net->{nameservers}) { - my $myip = xCAT::NetworkUtils->my_ip_facing($_->{net}); - unless (($_->{nameservers} eq $myip) || ($_->{nameservers} eq '') || ($_->{nameservers} eq $sitens)) + my $valid = 0; + my $myip = xCAT::NetworkUtils->my_ip_facing($net->{net}); + foreach (split /,/, $net->{nameservers}) { - $_ = undef; + chomp $_; + if (($_ eq $myip) || ($_ eq '') || ($_ eq $sitens)) + { + $valid += 1; + } + } + unless ($valid > 0) + { + $net = undef; } } } From b18d580dd5bb1975f376dbab025bfb088833c6e6 Mon Sep 17 00:00:00 2001 From: daniceexi Date: Thu, 24 Oct 2013 08:05:29 -0400 Subject: [PATCH 53/91] defect 3369: to add the flag -g for genimage command like for sles that make rh could handle the case that the kernel version is different with the name of kernel rpm when using -k to specify a new kernel version. --- xCAT-client/pods/man1/genimage.1.pod | 2 +- xCAT-server/lib/xcat/plugins/genimage.pm | 8 -------- xCAT-server/share/xcat/netboot/rh/genimage | 13 +++++++++---- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/xCAT-client/pods/man1/genimage.1.pod b/xCAT-client/pods/man1/genimage.1.pod index 9a65efa24..d297e6edd 100644 --- a/xCAT-client/pods/man1/genimage.1.pod +++ b/xCAT-client/pods/man1/genimage.1.pod @@ -132,7 +132,7 @@ in the install image. =item B<-g> I -This flag is for SLES only. Use this flag to specify the rpm version for kernel packages in the image. It must be present if -k flag is specified in the command for SLES. +Use this flag to specify the rpm version for kernel packages in the image. It must be present if -k flag is specified in the command for SLES. Generally, the value of -g is the part after B and before B<.rpm> in a kernel rpm name. =item B<-m> statelite diff --git a/xCAT-server/lib/xcat/plugins/genimage.pm b/xCAT-server/lib/xcat/plugins/genimage.pm index 9108dec90..e2e3bb08a 100644 --- a/xCAT-server/lib/xcat/plugins/genimage.pm +++ b/xCAT-server/lib/xcat/plugins/genimage.pm @@ -270,14 +270,6 @@ sub process_request { return 1; } - if ($krpmver) { - if ($osfamily ne "sles") { - $krpmver=""; - $callback->({error=>["-g flag is valid for Sles only."],errorcode=>[1]}); - return 1; - } - } - my $cmd="cd $profDir; ./genimage"; if ($arch) { $cmd .= " -a $arch";} if ($osver) { $cmd .= " -o $osver";} diff --git a/xCAT-server/share/xcat/netboot/rh/genimage b/xCAT-server/share/xcat/netboot/rh/genimage index 6b75afe34..a4c232542 100755 --- a/xCAT-server/share/xcat/netboot/rh/genimage +++ b/xCAT-server/share/xcat/netboot/rh/genimage @@ -48,6 +48,7 @@ my $tmplimit; my $installroot = "/install"; my $kerneldir; my $kernelver = ""; #`uname -r`; +my $krpmver; my $basekernelver; # = $kernelver; my $customdir=$fullpath; $customdir =~ s/.*share\/xcat/$installroot\/custom/; @@ -80,6 +81,7 @@ GetOptions( 'l=s' => \$rootlimit, 't=s' => \$tmplimit, 'k=s' => \$kernelver, + 'g=s' => \$krpmver, 'permission=s' => \$permission, 'kerneldir=s' => \$kerneldir, 'tempfile=s' =>\$tempfile, #internal flag @@ -266,16 +268,19 @@ unless ($onlyinitrd) { # replace the kernel package with the name has the specific version foreach my $p (@$pa) { if ($p =~ /^kernel$/ && $kernelver) { - my $kernelname = "kernel-".$kernelver; + my $kernelname; + if ($krpmver) { + $kernelname = "kernel-".$krpmver; + } else { + $kernelname = "kernel-".$kernelver; + } my $searchkern = $yumcmd . " list $kernelname -q"; my @kernpkgs = `$searchkern`; my $found = 0; foreach my $k (@kernpkgs) { if ($k =~ /\s*kernel[^\s]*\s+([\w\.-]+)/) { my $version = $1; - my $relversion = $kernelver; - $relversion =~ s/\.[^\.]+$//; - if ($version == $relversion) { + if ($kernelver =~ /$version/) { $found++; } } From 245c3eab838f21bd4a45bf9833eed7c2b5c2c3f5 Mon Sep 17 00:00:00 2001 From: daniceexi Date: Thu, 24 Oct 2013 08:58:21 -0400 Subject: [PATCH 54/91] defect 3588: For rpower reset on kvm, in the case persistkvmguests is enabled, check the domain is inactive before resetting the domain --- xCAT-server/lib/xcat/plugins/kvm.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-server/lib/xcat/plugins/kvm.pm b/xCAT-server/lib/xcat/plugins/kvm.pm index 5679815d6..8c68dd488 100644 --- a/xCAT-server/lib/xcat/plugins/kvm.pm +++ b/xCAT-server/lib/xcat/plugins/kvm.pm @@ -2348,7 +2348,7 @@ sub power { $dom->shutdown(); } else { $retstring .= "$status_noop"; } } elsif ($subcommand eq 'reset') { - if ($dom) { + if ($dom && $dom->is_active()) { my $oldxml=$dom->get_xml_description(); my $newxml=reconfigvm($node,$oldxml); #This *was* to be clever, but libvirt doesn't even frontend the capability, great... From d53c777ca15cb96fbaddcb2a8259c2f2de567b60 Mon Sep 17 00:00:00 2001 From: zhaoertao Date: Thu, 24 Oct 2013 02:09:20 -0700 Subject: [PATCH 55/91] fix bug 3820: rinv for feihu FPC is producing errors --- xCAT-server/lib/xcat/plugins/ipmi.pm | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/ipmi.pm b/xCAT-server/lib/xcat/plugins/ipmi.pm index 1de465611..cd62f9800 100644 --- a/xCAT-server/lib/xcat/plugins/ipmi.pm +++ b/xCAT-server/lib/xcat/plugins/ipmi.pm @@ -2974,8 +2974,10 @@ sub parsefru { return "unknown-COULDGUESS",undef; #be lazy for now, TODO revisit this and add guessing if it ever matters } $currsize=($bytes->[$curridx+1])*8; - @currarea=@{$bytes}[$curridx..($curridx+$currsize-1)]; #splice @$bytes,$curridx,$currsize; - $fruhash->{chassis} = parsechassis(@currarea); + if ($currsize > 0) { + @currarea=@{$bytes}[$curridx..($curridx+$currsize-1)]; #splice @$bytes,$curridx,$currsize; + $fruhash->{chassis} = parsechassis(@currarea); + } } if ($bytes->[3]) { #Board info area, to be preserved $curridx=$bytes->[3]*8; @@ -2983,8 +2985,10 @@ sub parsefru { return "unknown-COULDGUESS",undef; } $currsize=($bytes->[$curridx+1])*8; - @currarea=@{$bytes}[$curridx..($curridx+$currsize-1)]; - $fruhash->{board} = parseboard(@currarea); + if ($currsize > 0) { + @currarea=@{$bytes}[$curridx..($curridx+$currsize-1)]; + $fruhash->{board} = parseboard(@currarea); + } } if (ref $global_sessdata->{currmacs}) { $fruhash->{board}->{macaddrs}=[]; @@ -3001,8 +3005,10 @@ sub parsefru { return "unknown-COULDGUESS",undef; } $currsize=($bytes->[$curridx+1])*8; - @currarea=@{$bytes}[$curridx..($curridx+$currsize-1)]; - $fruhash->{product} = parseprod(@currarea); + if ($currsize > 0) { + @currarea=@{$bytes}[$curridx..($curridx+$currsize-1)]; + $fruhash->{product} = parseprod(@currarea); + } } if ($bytes->[5]) { #Generic multirecord present.. $fruhash->{extra}=[]; From 399e71a4c03eda8bbf9700951dfc8e1dc7d3348c Mon Sep 17 00:00:00 2001 From: daniceexi Date: Thu, 24 Oct 2013 10:41:48 -0400 Subject: [PATCH 56/91] defect 3789: fixed the issue that xcatdebug command kill the xcatd ssl listening process. The fix is that just remove the handling debug message from plugin modules since xcatd loads plugin modules for each command run, don't need xcatdebug for plugin any more. --- xCAT-server/sbin/xcatd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-server/sbin/xcatd b/xCAT-server/sbin/xcatd index ec8f2b3f2..d95060fdc 100755 --- a/xCAT-server/sbin/xcatd +++ b/xCAT-server/sbin/xcatd @@ -2261,7 +2261,7 @@ sub enable_callingtrace{ my @xcatdfuncs = (); # function list that will be enabled for xcatd # call the subroutine scan_plugins to fill the symbol table - scan_plugins(); + #scan_plugins(); # Backup the trace log my ($sec,$min,$hour,$mday,$mon,$year) = localtime(); From 3cae77406c362f572ea737c93733fe6e6db36af0 Mon Sep 17 00:00:00 2001 From: lissav Date: Thu, 24 Oct 2013 06:55:54 -0400 Subject: [PATCH 57/91] defect 3851, further enhancements --- perl-xCAT/xCAT/DSHCLI.pm | 19 ++++++++++--------- xCAT-server/sbin/xcatconfig | 32 +++++++++++++------------------- 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/perl-xCAT/xCAT/DSHCLI.pm b/perl-xCAT/xCAT/DSHCLI.pm index 73d1a9232..9b09140c5 100644 --- a/perl-xCAT/xCAT/DSHCLI.pm +++ b/perl-xCAT/xCAT/DSHCLI.pm @@ -3240,11 +3240,14 @@ sub bld_resolve_nodes_hash # find out the names for the Management Node my @MNnodeinfo = xCAT::NetworkUtils->determinehostname; my $mname = pop @MNnodeinfo; # hostname - #my $rsp = {}; - #$rsp->{info}->[0] = - # "Management node name is $mname."; - # xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); - + my $cmd="hostname"; + my $localhostname = xCAT::Utils->runcmd($cmd,0); + if ($::RUNCMD_RC != 0) + { + my $rsp = {}; + $rsp->{info}->[0] = "Command: $cmd failed. Continuing..."; + xCAT::MsgUtils->message("I", $rsp, $::CALLBACK); + } foreach my $target (@target_list) { @@ -3253,11 +3256,9 @@ sub bld_resolve_nodes_hash my $localhost; my $user; my $context = "XCAT"; - # check to see if this node is the Management Node - if ($mname) { - if ($mname eq $target) { + # check to see if this node is the Management Node we are on, can run local commands (sh,cp) + if (($mname eq $target) || ($localhostname eq $target)){ $localhost=$target; - } } my %properties = ( 'hostname' => $hostname, diff --git a/xCAT-server/sbin/xcatconfig b/xCAT-server/sbin/xcatconfig index f9d0b428a..3106f2b90 100755 --- a/xCAT-server/sbin/xcatconfig +++ b/xCAT-server/sbin/xcatconfig @@ -2107,8 +2107,8 @@ sub cleanupPSTable =head3 setupMNinDB - Will add/replace the management node to the noderes table with group=__mgmtnode - Will add/replace the management node to the servicenode tble with group=__mgmtnode + Will add the management node to the noderes table with group=__mgmtnode + Will add the management node to the servicenode tble with group=__mgmtnode =cut @@ -2126,25 +2126,18 @@ sub setupMNinDB my $cmds="XCATBYPASS=Y $::XCATROOT/sbin/tabdump nodelist | grep __mgmtnode"; my @output = xCAT::Utils->runcmd("$cmds", -1); - if ($::RUNCMD_RC == 0) # found a management node defined + if ($::RUNCMD_RC == 0) # found nodes in __mgmtnode { my $chtabcmds; - my @mn = split(",", $output[0]); - $mn[0] =~ s/"//g; # remove the quotes - if ($mn[0] ne $mnname) { # does not match current host name,delete it - my $size=@output; # if more than one management node defined, do not remove any - if ($size == 1) { - $chtabcmds = "$::XCATROOT/sbin/chtab -d node=$mn[0] nodelist;"; - my $outref = xCAT::Utils->runcmd("$chtabcmds", 0); - if ($::RUNCMD_RC != 0) - { - xCAT::MsgUtils->message('E', "Could not run $chtabcmds."); - return; - } - } - } else { # it is defined and good - xCAT::MsgUtils->message('I', "$mnname already defined in the nodelist table."); + # Look through the MN list and see if this MN is defined + foreach my $line (@output) { + my @mn = split(",", $line); + $mn[0]=~ s/"//g; # remove the quotes + if ($mn[0] eq $mnname) { # already in the database + verbose("$mnname already defined in the the nodelist table."); $defined=1; + last; + } } } # now add with the new name , if not already there @@ -2199,9 +2192,10 @@ sub setupMNinDB } } else { # it was already defined in the servicenode table - xCAT::MsgUtils->message('I', "$mnname was already defined in the servicenode table."); + verbose("$mnname already defined in the the servicenode table."); } + xCAT::MsgUtils->message('I', "Management Node defined in the database."); return; } #----------------------------------------------------------------------------- From 4bac6666750eff57f097871e0d7470e60f7508b3 Mon Sep 17 00:00:00 2001 From: lissav Date: Thu, 24 Oct 2013 07:23:59 -0400 Subject: [PATCH 58/91] defect 3851, further enhancements --- perl-xCAT/xCAT/Utils.pm | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/perl-xCAT/xCAT/Utils.pm b/perl-xCAT/xCAT/Utils.pm index fd6052a90..558df696f 100644 --- a/perl-xCAT/xCAT/Utils.pm +++ b/perl-xCAT/xCAT/Utils.pm @@ -3174,7 +3174,7 @@ sub isSELINUX Input: array of nodes in the noderange Example: - my $mn=xCAT::Utils->noderangecontainsMN($noderange); + my @mn=xCAT::Utils->noderangecontainsMN($noderange); Comments: =cut @@ -3183,26 +3183,30 @@ sub noderangecontainsMn { my ($class, @noderange)=@_; # check if any node in the noderange is the Management Node return the - # name - my $mname; + # name + my @mnames; # management node names in the database, members of __mgmtnode my $tab = xCAT::Table->new('nodelist'); my @nodelist=$tab->getAllNodeAttribs(['node','groups']); foreach my $n (@nodelist) { if (defined($n->{'groups'})) { my @groups=split(",",$n->{'groups'}); if ((grep (/__mgmtnode/,@groups))) { # this is the MN - $mname=$n->{'node'}; - last; + push @mnames,$n->{'node'}; } } } - if ($mname) { # if Management Node defined in the database - if (grep(/^$mname$/, @noderange)) { # if MN in the noderange - return $mname; - } else { - return ; + my @MNs; # management node names found the noderange + if (@mnames) { # if any Management Node defined in the database + foreach my $mn (@mnames) { + if (grep(/^$mn$/, @noderange)) { # if MN in the noderange + push @MNs, $mn; + } + } + if (@MNs) { # management nodes in the noderange + return @MNs; } } + return; # if no MN in the noderange, return nothing } =head3 filter_nodes From 9a09552de561a0fff1da6ee13720ee9dfa66e211 Mon Sep 17 00:00:00 2001 From: lissav Date: Thu, 24 Oct 2013 08:05:59 -0400 Subject: [PATCH 59/91] defect 3851, further enhancements --- xCAT-server/lib/xcat/plugins/updatenode.pm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/updatenode.pm b/xCAT-server/lib/xcat/plugins/updatenode.pm index 6adc76019..425074fac 100644 --- a/xCAT-server/lib/xcat/plugins/updatenode.pm +++ b/xCAT-server/lib/xcat/plugins/updatenode.pm @@ -1103,16 +1103,16 @@ sub updatenode # check to see if the Management Node is in the noderange and # if it is abort - my $mname = xCAT::Utils->noderangecontainsMn(@$nodes); - if ($mname) + my @mname = xCAT::Utils->noderangecontainsMn(@$nodes); + if (@mname) { # MN in the nodelist + my $nodes=join(',', @mname); my $rsp = {}; $rsp->{error}->[0] = - "You must not run -k option against the Management Node:$mname."; - xCAT::MsgUtils->message("E", $rsp, $::CALLBACK, 1); + "You must not run -k option against a management node: $nodes."; + xCAT::MsgUtils->message("E", $rsp, $callback, 1); return; } - # setup the root ssh keys ( runs xdsh -k) &security_update_sshkeys($request, $callback, $subreq, \@$nodes); From 5de59481e1a4357e5b5e028d7e41e69f4a8a8a32 Mon Sep 17 00:00:00 2001 From: zhaoertao Date: Thu, 24 Oct 2013 22:57:58 -0700 Subject: [PATCH 60/91] fix bug 3850: "chtab key=fsp,username=HMC ..." doesn't work for Powerlinux --- perl-xCAT/xCAT/PPCdb.pm | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/perl-xCAT/xCAT/PPCdb.pm b/perl-xCAT/xCAT/PPCdb.pm index 5a69acf7f..f034906a3 100644 --- a/perl-xCAT/xCAT/PPCdb.pm +++ b/perl-xCAT/xCAT/PPCdb.pm @@ -984,6 +984,18 @@ sub get_usr_passwd { } else { ($ent) = $passwdtab->getNodeAttribs($key, qw(username password)); } + if (!$ent) { + if ($key eq "cec") { + $key = "fsp"; + } elsif ($key eq "frame") { + $key = "bpa"; + } + if ($user) { + ($ent) = $passwdtab->getAttribs({key => $key, username => $user}, qw(password cryptmethod)); + } else { + ($ent) = $passwdtab->getNodeAttribs($key, qw(username password)); + } + } if (!$ent or !$ent->{password}) { my $hash = $default_passwd_accounts{$key}; if (!$hash or ($user and !defined($hash->{$user}))) { From a5424b703b2c8c3d5ecf686b1eb367aa57bf1604 Mon Sep 17 00:00:00 2001 From: jjhua Date: Fri, 25 Oct 2013 14:33:18 -0400 Subject: [PATCH 61/91] add a new script configbr-ex to configure the IP of the external bridge for network node --- xCAT-OpenStack/lib/perl/xCAT/Cloud.pm | 13 ++++++-- xCAT-OpenStack/postscripts/configbr-ex | 41 ++++++++++++++++++++++++++ xCAT-server/lib/perl/xCAT/Postage.pm | 5 ++-- 3 files changed, 55 insertions(+), 4 deletions(-) create mode 100755 xCAT-OpenStack/postscripts/configbr-ex diff --git a/xCAT-OpenStack/lib/perl/xCAT/Cloud.pm b/xCAT-OpenStack/lib/perl/xCAT/Cloud.pm index 171b7ad4b..72b71d844 100644 --- a/xCAT-OpenStack/lib/perl/xCAT/Cloud.pm +++ b/xCAT-OpenStack/lib/perl/xCAT/Cloud.pm @@ -58,12 +58,14 @@ sub getcloudinfo xCAT::MsgUtils->message("E", "Unable to open $tab table"); return undef; } - my @rs = $ptab->getAllAttribs('name','repository'); + my @rs = $ptab->getAllAttribs('name','repository', 'pubinterface'); foreach my $r ( @rs ) { my $cloud = $r->{'name'}; my $repos = $r->{'repository'}; + my $pubinterface = $r->{'pubinterface'}; $info{ $cloud }{repository} = $repos; + $info{ $cloud }{pubinterface} = $pubinterface; } $tab = "cloud"; @@ -122,11 +124,18 @@ sub getcloudinfo sub getcloudres { my $cloudinfo_hash = shift; + my $node = shift; my $clients = shift; my $cloudres; my $cloudlist; - my $repos; + my $repos;use Data::Dumper; print Dumper($cloudinfo_hash); if( @$clients == 0 ) { + #This should not be a chef-server, and it's a chef-client + if( defined($cloudinfo_hash) && defined($cloudinfo_hash->{$node}) ) { + my $cloud=$cloudinfo_hash->{$node}->{cloud}; + my $pubinterface=$cloudinfo_hash->{$cloud}->{pubinterface}; + $cloudres="PUBINTERFACE='$pubinterface'\nexport PUBINTERFACE\n"; + } return $cloudres; } foreach my $client (@$clients) { diff --git a/xCAT-OpenStack/postscripts/configbr-ex b/xCAT-OpenStack/postscripts/configbr-ex new file mode 100755 index 000000000..2ea97dce6 --- /dev/null +++ b/xCAT-OpenStack/postscripts/configbr-ex @@ -0,0 +1,41 @@ +#!/bin/sh -vx + + +bridge_name="br-ex" + +pubinterface=$PUBINTERFACE +#pubinterface="eth0" +if [ -z "pubinterface" ] +then + errmsg="no pubinterface setting for the $NODE's cloudname in clouds table" + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit -1 +fi +ifconfig $pubinterface 0 + +pubinterface=`echo $pubinterface | sed 's/^ \+//' | sed 's/ \+$//'` +str_value=$(hashget hash_defined_nics $pubinterface) +old_ifs=$IFS +IFS=$',' +array_temp=($str_value) +FS=$old_ifs + +if [ -n "${array_temp[1]}" ];then + str_nic_type=`echo ${array_temp[1]} | tr "[A-Z]" "[a-z]"` +else + if [ `echo $pubinterface | grep -E '(eth|en)[0-9]+'` ];then + str_nic_type="ethernet" + else + errmsg="currently, it only supports eth|en, instead of $pubinterface." + logger -t xcat -p local4.err $errmsg + echo $errmsg + exit -1; + fi +fi + + +configeth $bridge_name ${array_temp[0]} ${array_temp[2]} + + + diff --git a/xCAT-server/lib/perl/xCAT/Postage.pm b/xCAT-server/lib/perl/xCAT/Postage.pm index 250c28eb8..7cd83050e 100644 --- a/xCAT-server/lib/perl/xCAT/Postage.pm +++ b/xCAT-server/lib/perl/xCAT/Postage.pm @@ -485,7 +485,7 @@ sub makescript { my $cloudres; $cfgres = getcfgres($cfginfo_hash, $node, \@clients); if ( $cloud_exists == 1 ) { - $cloudres = getcloudres($cloud_module_name, $cloud_exists, $cloudinfo_hash, \@clients); + $cloudres = getcloudres($cloud_module_name, $cloud_exists, $cloudinfo_hash, $node, \@clients); } #ok, now do everything else.. @@ -1815,6 +1815,7 @@ sub getcloudres my $module_name = shift; my $cloud_exists = shift; my $cloudinfo_hash = shift; + my $node = shift; my $clients = shift; my $result; @@ -1822,7 +1823,7 @@ sub getcloudres if ( $cloud_exists ) { no strict "refs"; if (defined(${$module_name."::"}{getcloudres})) { - $result=${$module_name."::"}{getcloudres}($cloudinfo_hash, $clients); + $result=${$module_name."::"}{getcloudres}($cloudinfo_hash, $node, $clients); } } return $result; From b8f9d5719418ec50d09d38daac921fda7bdb2eab Mon Sep 17 00:00:00 2001 From: zhaoertao Date: Thu, 24 Oct 2013 23:30:54 -0700 Subject: [PATCH 62/91] fix bug 3856: rmvm could remove cec --- perl-xCAT/xCAT/FSPvm.pm | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/perl-xCAT/xCAT/FSPvm.pm b/perl-xCAT/xCAT/FSPvm.pm index 09b885a7f..f81030134 100644 --- a/perl-xCAT/xCAT/FSPvm.pm +++ b/perl-xCAT/xCAT/FSPvm.pm @@ -1720,6 +1720,10 @@ sub remove { my @result = (); while (my ($mtms, $h) = each (%$hash)) { while (my ($name, $d) = each (%$h)) { + if (@$d[4] ne "lpar") { + push @result, [$name, "Node must be LPAR", 1]; + last; + } &clear_service_authority_lpar($request, $name, $d); my $values = &set_lpar_undefined($request, $name, $d); push @result, $values; @@ -1878,6 +1882,10 @@ sub mkspeclpar { my @nodes = keys(%$h); my $ent = $vmtab->getNodesAttribs(\@nodes, ['cpus', 'memory','physlots', 'othersettings']); while (my ($name, $d) = each (%$h)) { + if (@$d[4] ne 'lpar') { + push @result, [$name, "Node must be LPAR", 1]; + last; + } if (!exists($memhash->{run})) { my @td = @$d; @td[0] = 0; @@ -1954,6 +1962,10 @@ sub mkfulllpar { while (my ($mtms, $h) = each (%$hash)) { my $rethash; while (my ($name, $d) = each (%$h)) { + if (@$d[4] ne 'lpar') { + push @result, [$name, "Node must be LPAR", 1]; + last; + } if (!exists($rethash->{run})) { my @td = @$d; @td[0] = 0; From aaed135c1e60878d24924ce1732bb603b8c3b207 Mon Sep 17 00:00:00 2001 From: jjhua Date: Fri, 25 Oct 2013 14:52:08 -0400 Subject: [PATCH 63/91] add a new optional --script for confignics --- xCAT/postscripts/confignics | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/xCAT/postscripts/confignics b/xCAT/postscripts/confignics index 4fc91aae6..f523d9b1c 100755 --- a/xCAT/postscripts/confignics +++ b/xCAT/postscripts/confignics @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash str_dir_name=`dirname $0` . $str_dir_name/xcatlib.sh @@ -59,6 +59,22 @@ do fi done +boot_myscript=0 +if [ $# -eq 2 ] +then + if [ "$1" = "--script" ] + then + if [ $bool_cfg_inst_nic -eq 1 -o $bool_remove -eq 1 -o ! -z "$num_iba_ports" ] + then + logger -t xcat -p local4.info "confignics --script could Not be used with other options" + echo "confignics --script could Not be used with other options" + exit -1 + fi + boot_myscript=1 + myscript=$2; + fi +fi + logger -t xcat -p local4.info "confignics is called: config install nic:$bool_cfg_inst_nic, remove: $bool_remove, iba ports: $num_iba_ports" echo "confignics on $NODE: config install nic:$bool_cfg_inst_nic, remove: $bool_remove, iba ports: $num_iba_ports" @@ -132,6 +148,14 @@ splitconfig $NICTYPES splitconfig $NICNETWORKS splitconfig $NICCUSTOMSCRIPTS +if [ $boot_myscript -eq 1 ];then + . $str_dir_name/$myscript + if [ $? -ne 0 ];then + exit -1 + fi + exit 0 +fi + #get state of nic in "UP" status #If bonded redhat then "SLAVE" or "MASTER" will be in the first line of stanza #do not configure the loopback nic From 3d9582728bc7001356e9a97485afced7488eb4f9 Mon Sep 17 00:00:00 2001 From: immarvin Date: Fri, 25 Oct 2013 00:27:46 -0700 Subject: [PATCH 64/91] fix defect #3694 [PCM] Showing booting status always for NGP X node status after power reset: update site.status during normal diskful reboot --- xCAT/postscripts/xcatdsklspost | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT/postscripts/xcatdsklspost b/xCAT/postscripts/xcatdsklspost index 75dd32a9b..a26b5660d 100755 --- a/xCAT/postscripts/xcatdsklspost +++ b/xCAT/postscripts/xcatdsklspost @@ -765,7 +765,7 @@ echo "$TMP" >> /$xcatpost/mypostscript TMP=`sed "/# postbootscripts-start-here/,/# postbootscripts-end-here/ s/\(.*\)/run_ps \1/;s/run_ps\s*#/#/;s/run_ps\s*$//" /$xcatpost/mypostscript` echo "$TMP" > /$xcatpost/mypostscript -if [ $NODE_DEPLOYMENT -eq 1 ] || [ "$MODE" = "4" ]; then +if [ $NODE_DEPLOYMENT -eq 1 ] || [ "$MODE" = "4" ] || [ "$MODE" = "6" ]; then #notify the server that we are done with netbooting CNS=`grep NODESTATUS= /$xcatpost/mypostscript |awk -F = '{print $2}'` if [ -z "$CNS" ] || [ "$CNS" != "'0'" -a "$CNS" != "'N'" -a "$CNS" != "'n'" ]; then From dc9c746cbc21059a23a0f412d02a96e9ae418cd4 Mon Sep 17 00:00:00 2001 From: lissav Date: Fri, 25 Oct 2013 08:28:24 -0400 Subject: [PATCH 65/91] defect 3859 --- xCAT-server/share/xcat/tools/reorgtbls | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/xCAT-server/share/xcat/tools/reorgtbls b/xCAT-server/share/xcat/tools/reorgtbls index 129fdeec0..b0867ced9 100755 --- a/xCAT-server/share/xcat/tools/reorgtbls +++ b/xCAT-server/share/xcat/tools/reorgtbls @@ -56,7 +56,7 @@ my $DBname = xCAT::Utils->get_DBName; if ($DBname ne "DB2") { print " Reorg of table only supported for DB2 database\n"; - `logger -p local4.err -txcat " reorgtbls:Only supports DB2 database"` ; + `logger -p local4.err -t xcat " reorgtbls:Only supports DB2 database"` ; exit 1; } @@ -67,7 +67,7 @@ if ($tablelist) { # input list of tables @tablist = xCAT::Utils->runcmd($cmd, 0); if ($::RUNCMD_RC != 0) { - `logger -p local4.err -txcat " reorgtbls:error in select tabname from syscat.tables"` ; + `logger -p local4.err -t xcat " reorgtbls:error in select tabname from syscat.tables"` ; exit 1; } } @@ -99,22 +99,23 @@ foreach my $table (@tablist) { $table =~ tr/a-z/A-Z/; # convert to upper if ($::VERBOSE) { print " Reorg of table $table\n"; + `logger -p local4.info -t xcat " Reorg of table $table."`; } $cmd="$::XCATROOT/sbin/runsqlcmd \"reorg indexes all for table $table allow write access;\""; xCAT::Utils->runcmd($cmd, 0); if ($::RUNCMD_RC != 0) { - `logger -p local4.warning -txcat " reorgtbls:error $cmd"`; + `logger -p local4.warning -t xcat " reorgtbls:error $cmd"`; } else { - `logger -p local4.info -txcat " reorgtbls:reorg indexes for $table"`; + `logger -p local4.info -t xcat " reorgtbls:reorg indexes for $table"`; } $cmd="$::XCATROOT/sbin/runsqlcmd \"reorg table $table inplace allow write access;\""; xCAT::Utils->runcmd($cmd, 0); if ($::RUNCMD_RC != 0) { - `logger -p local4.warning -txcat " reorgtbls:error $cmd"`; + `logger -p local4.warning -t xcat " reorgtbls:error $cmd"`; } else { - `logger -p local4.info-txcat " reorgtbls:reorg $table inplace"`; + `logger -p local4.info -t xcat " reorgtbls:reorg $table inplace"`; } } exit 0; From f7ae606485c80b9876fa71e02ca280fff5b3d6b0 Mon Sep 17 00:00:00 2001 From: wanghuaz Date: Sat, 26 Oct 2013 00:17:42 +0800 Subject: [PATCH 66/91] fixing bug 3821 give better description for chkkitcomp --- xCAT-client/pods/man1/chkkitcomp.1.pod | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xCAT-client/pods/man1/chkkitcomp.1.pod b/xCAT-client/pods/man1/chkkitcomp.1.pod index e4c220523..b25c80e3b 100644 --- a/xCAT-client/pods/man1/chkkitcomp.1.pod +++ b/xCAT-client/pods/man1/chkkitcomp.1.pod @@ -12,6 +12,8 @@ B [B<-V>|B<--verbose>] B<-i> I I The B command will check if the kit components are compatible with the xCAT osimage. This command will if the kitcompname_list provided on the command line is compatible with the osimage. +This command will ignore the current osimage.kitcomponents setting, and just to check if the kitcompname list in the cmdline are compatible with the osimage by osversion/ostype/osarch/ and kit component dependencies. + Note: The xCAT support for Kits is only available for Linux operating systems. =head1 OPTIONS From 0ffc189feecced42b52c850d0b5cfe4165419962 Mon Sep 17 00:00:00 2001 From: wanghuaz Date: Sat, 26 Oct 2013 00:19:27 +0800 Subject: [PATCH 67/91] fixing bug 3821 give better description for chkkitcomp --- xCAT-client/pods/man1/chkkitcomp.1.pod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-client/pods/man1/chkkitcomp.1.pod b/xCAT-client/pods/man1/chkkitcomp.1.pod index b25c80e3b..6c964ab01 100644 --- a/xCAT-client/pods/man1/chkkitcomp.1.pod +++ b/xCAT-client/pods/man1/chkkitcomp.1.pod @@ -10,7 +10,7 @@ B [B<-V>|B<--verbose>] B<-i> I I =head1 DESCRIPTION -The B command will check if the kit components are compatible with the xCAT osimage. This command will if the kitcompname_list provided on the command line is compatible with the osimage. +The B command will check if the kit components are compatible with the xCAT osimage. This command will ignore the current osimage.kitcomponents setting, and just to check if the kitcompname list in the cmdline are compatible with the osimage by osversion/ostype/osarch/ and kit component dependencies. From 84f4f2c7c96bf8c29b8a5f526695c48c2dc6fad6 Mon Sep 17 00:00:00 2001 From: John Simpson Date: Fri, 25 Oct 2013 12:17:17 -0400 Subject: [PATCH 68/91] update to add the configfpc man page --- xCAT-client/pods/man1/configfpc.1.pod | 55 +++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 xCAT-client/pods/man1/configfpc.1.pod diff --git a/xCAT-client/pods/man1/configfpc.1.pod b/xCAT-client/pods/man1/configfpc.1.pod new file mode 100644 index 000000000..a426275c5 --- /dev/null +++ b/xCAT-client/pods/man1/configfpc.1.pod @@ -0,0 +1,55 @@ +=head1 NAME + +B - discover the Fan Power Controllers (FPCs) and configure the FPC interface + +=head1 SYNOPSIS + +B B<-i> I + +B [B<-V>|B<--verbose>] + +B [B<-h>|B<--help>|B<-?>] + +=head1 DESCRIPTION + +B will discover and configure all FPCs that are set to the default IP address. + +The B<-i> B is required to direct B to the xCAT MN interface which is on the same VLAN as the FPCs. + +There are several bits of information that must be included in the xCAT database before running this command. + +You must create the FPC node definitions for all FPCs being discovered including the IP address and switch port information. + +The B command discovers the FPCs and collects the MAC address. The MAC address is used to relate the FPC to a FPC node using the switch information for this MAC. Once the relationship is discovered the FPC is configured with the FPC node IP settings. + +This process is repeated until no more FPCs are discovered. + +For more information on xCAT support of NeXtScale and configfpc see: +https://sourceforge.net/apps/mediawiki/xcat/index.php?title=XCAT_NeXtScale_Clusters + +=head1 OPTIONS + +=over 6 + +=item B<-i> I + +Use this flag to specify which xCAT MN interface (example: eth4) that is connected to the NeXtScale FPCs. This option is required. + +=item B<-V>|B<--verbose> + +Verbose mode + +=back + +=head1 Example + +=over 6 + +=item 1 + +To discover and configure all NeXtScale Fan Power Controllers (FPCs) connected on eth0 interface. + +B B<-i> I + +=back + From ca3e7da99bf9fb8bfff93d110c96d2e3dd2f0a87 Mon Sep 17 00:00:00 2001 From: John Simpson Date: Wed, 23 Oct 2013 17:01:35 -0400 Subject: [PATCH 69/91] update to configfpc to add support for verbose and -i option and a ping verification --- xCAT-server/lib/xcat/plugins/configfpc.pm | 230 +++++++++++++++++----- 1 file changed, 177 insertions(+), 53 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/configfpc.pm b/xCAT-server/lib/xcat/plugins/configfpc.pm index 7ba94c4ff..e74f78d7d 100644 --- a/xCAT-server/lib/xcat/plugins/configfpc.pm +++ b/xCAT-server/lib/xcat/plugins/configfpc.pm @@ -17,6 +17,7 @@ use xCAT::NetworkUtils; use Data::Dumper; use xCAT::MacMap; use Socket; +use Net::Ping; ########################################################################## ## Command handler method from tables @@ -34,6 +35,41 @@ sub process_request { $::CALLBACK = $callback; + if ( defined( @{$::args} ) ) { + @ARGV = @{$::args}; + } + Getopt::Long::Configure( "bundling", "no_ignore_case", "no_pass_through" ); + my $getopt_success = Getopt::Long::GetOptions( + 'help|h|?' => \$::opt_h, + 'i|I=s' => \$::opt_I, + 'verbose|V' => \$::opt_V, + 'version|v' => \$::opt_v, + ); + + # Option -h for Help + if ( defined($::opt_h) || (!$getopt_success) ) { + &configfpc_usage; + return 0; + } + + if ( (!$::opt_I) ) { # missing required option - msg and return + my $rsp; + push @{ $rsp->{data} }, "Missing required option -i \n"; + xCAT::MsgUtils->message( "I", $rsp, $::CALLBACK ); + &configfpc_usage; + return 0; + } + + # Option -V for verbose output + if ( defined($::opt_V) ) { + $::VERBOSE=$::opt_V; + } + + # Option -i for kit component attributes + if ( defined($::opt_I) ) { + $::interface = $::opt_I; + } + my $command = $request->{command}->[0]; my $localhostname = hostname(); @@ -53,6 +89,19 @@ sub process_request { return 0; } +sub configfpc_usage { + my $rsp; + push @{ $rsp->{data} }, + "\nUsage: configfpc - Configure the NeXtScale FPCs.i This command requires the -i option to give specify which network adapter to use to look for the FPCs.\n"; + push @{ $rsp->{data} }, + " configfpc -i interface_adapter \n "; + push @{ $rsp->{data} }, + " configfpc [-V|--verbose] -i adapter_interface \n "; + push @{ $rsp->{data} }, " configfpc [-h|--help|-?] \n"; + xCAT::MsgUtils->message( "I", $rsp, $::CALLBACK ); + return 0; +} + # # Main process subroutine # @@ -87,6 +136,14 @@ sub configfpc { # This is the default FPC IP that we are looking for my $foundfpc = 0; + + # Setup routing to 182.168.0.100 network + if($::VERBOSE){ + my %rsp = {}; + push@{ $rsp{data} }, "Adding route definition for $::interface and 192.168.0.101 network"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + } + my $setroute = `ip addr add dev $::interface 192.168.0.101/16`; # # check for an FPC - this ping will also add the FPC IP and MAC to the ARP table @@ -96,33 +153,25 @@ sub configfpc { if ( $res =~ /100% packet loss/g) { # xCAT::MsgUtils->message ("I", "There are no default $fpcip FPC IP addresses to process"); $foundfpc = 0; + + my %rsp = {}; + push@{ $rsp{data} }, "No nodes Found FPC with $fpcip address"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); exit; # EXIT if we find no more default IP addresses on the network } else { # xCAT::MsgUtils->message ("I", "Found $fpcip FPC IP addresses to process"); + if($::VERBOSE){ + my %rsp = {}; + push@{ $rsp{data} }, "Found FPC with $fpcip address"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + } $foundfpc = 1; } - # - # make the FPC node definition - this is removed at the end of processing the FPCs - # this default FPC node definition is used by rspconfig to change the netmask, default route, and IP address of the default FPC - # - # Object name: deffpc - # bmc=deffpc - # bmcpassword=PASSW0RD - # bmcusername=USERID - # cons=ipmi - # groups=deffpc - # mgt=ipmi - # mpa=deffpc - # - my $out = xCAT::Utils->runxcmd( - { - command => ["mkdef"], - arg => [ "-t","node","-o",$defnode,"bmc=deffpc","bmcpassword=Passw0rd","bmcusername=USERID","cons=ipmi","groups=deffpc","mgt=ipmi","mpa=deffpc" ] - }, - $subreq, 0,1); - + + my $addnode = &add_node($defnode,$callback); + # # Main loop - check to see if we found an FPC and continue to set the FPC infomration and look for the next one # @@ -139,46 +188,55 @@ sub configfpc { # Change the FPC network netmask, gateway, and ip &set_FPC_network_parms($defnode,$netmask,$gateway,$newfpcip,$callback,$subreq); + + # message changed network settings + my %rsp = {}; + push@{ $rsp{data} }, "Configured FPC with MAC $fpcmac as $node ($newfpcip)"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); - # sleep for 4 seconds to allow rspconfig to change the IP value before validating with ping - sleep 5; - - # # Validate that new IP is working - Use ping to check if the new IP has been set - # - $res = `LANG=C ping -c 1 -w 5 $newfpcip`; - #$res = system("LANG=C ping -c 1 -w 5 $fpcip 2>&1"); - if ( $res =~ /100% packet loss/g) { - my %rsp; - push@{ $rsp{data} }, "The new ip $newfpcip was not accessible"; - xCAT::MsgUtils->message( "I", \%rsp, $callback ); - #xCAT::MsgUtils->message("I","The new ip $newfpcip was not accessible"); - } else { - my %rsp; - push@{ $rsp{data} }, "Changed the IP address for the FPC with $fpcmac MAC to $newfpcip IP for node $node"; - xCAT::MsgUtils->message( "I", \%rsp, $callback ); - #xCAT::MsgUtils->message("I","Changed the IP address for the FPC with $fpcmac MAC to $newfpcip IP for node $node"); + my $p = Net::Ping->new(); + my $ping_success=1; + while ($ping_success) { + if ($p->ping($newfpcip)) { + my %rsp = {}; + push@{ $rsp{data} }, "Verified the FPC with MAC $fpcmac is responding to the new IP $newfpcip as node $node"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + $ping_success=0; + } + else { + if($::VERBOSE){ + my %rsp = {}; + push@{ $rsp{data} }, "ping to $newfpcip is unsuccessful. Retrying "; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + } + } } + $p->close(); + # The Node associated with this MAC was not found - print an infomrational message and continue } else { my %rsp; - push@{ $rsp{data} }, "No FPC node found that is associated with MAC address $fpcmac\nCheck to see if the switch and switch table conta ins the information needed to locate this FPC MAC"; + push@{ $rsp{data} }, "No FPC found that is associated with MAC address $fpcmac.\nCheck to see if the switch and switch table contain the information needed to locate this FPC MAC"; xCAT::MsgUtils->message( "I", \%rsp, $callback ); - # xCAT::MsgUtils->message("I","No FPC node found that is associated with MAC address $fpcmac\nCheck to see if the switch and switch table contains the information needed to locate this FPC MAC"); } # # Delete this FPC default IP Arp entry to get ready to look for another defautl FPC # + if($::VERBOSE){ + my %rsp = {}; + push@{ $rsp{data} }, "Removing default IP $fpcip from the arp table"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + } my $arpout = `arp -d $fpcip`; # check for another FPC $res = `LANG=C ping -c 1 -w 5 $fpcip 2>&1`; if ( $res =~ /100% packet loss/g) { my %rsp; - push@{ $rsp{data} }, "There are no more default $fpcip FPC IP addresses to process"; + push@{ $rsp{data} }, "There are no more FPCs with the default IP address to process"; xCAT::MsgUtils->message( "I", \%rsp, $callback ); - #xCAT::MsgUtils->message("I","There are no more default $fpcip FPC IP addresses to process"); $foundfpc = 0; } else { @@ -187,12 +245,30 @@ sub configfpc { } # - # Cleanup on the way out - Remove the deffpc node definition + # Cleanup on the way out - Delete route and remove the deffpc node definition # - $out=xCAT::Utils->runxcmd( + # Delete routing to 182.168.0.100 network + if($::VERBOSE){ + my %rsp = {}; + push@{ $rsp{data} }, "Deleting route definition for $::interface and 192.168.0.101 network"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + } + my $setroute = `ip addr del dev $::interface 192.168.0.101/16`; + + # Delete routing to 182.168.0.100 network + if($::VERBOSE){ + my %rsp = {}; + push@{ $rsp{data} }, "Removing default FPC node definition $defnode"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + } + + if($::VERBOSE){ $::VERBOSE = {}; } + #if($::VERBOSE){ undef $::VERBOSE; } + + my $out=xCAT::Utils->runxcmd( { command => ['rmdef'], - arg => [ "deffpc"] + arg => [ $defnode ] }, $subreq, 0,1); @@ -265,16 +341,18 @@ sub set_FPC_network_parms { # Proceed with changing the FPC network parameters. # Set FPC Netmask - - + if($::VERBOSE){ + my %rsp = {}; + push@{ $rsp{data} }, "Use rspconfig to set the FPC netmask $netmask for node $defnode"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + } my $netmaskout = xCAT::Utils->runxcmd( { command => ["rspconfig"], - node => [$defnode], + node => ["$defnode"], arg => [ "netmask=$netmask" ] }, $request, 0,1); - if ($::RUNCMD_RC != 0) { my %rsp; push@{ $rsp{data} }, "Could not change nemask $netmask on default FPC"; @@ -283,14 +361,18 @@ sub set_FPC_network_parms { } # Set FPC gateway + if($::VERBOSE){ + my %rsp = {}; + push@{ $rsp{data} }, "Use rspconfig to set the FPC gateway $gateway"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + } my $gatewayout = xCAT::Utils->runxcmd( { command => ["rspconfig"], - node => [$defnode], + node => ["$defnode"], arg => [ "gateway=$gateway" ] }, $request, 0,1); - if ($::RUNCMD_RC != 0) { my %rsp; push@{ $rsp{data} }, "Could not change gateway $gateway on default FPC"; @@ -298,16 +380,19 @@ sub set_FPC_network_parms { $error++; } - # Set FPC Ip address + if($::VERBOSE){ + my %rsp = {}; + push@{ $rsp{data} }, "Use rspconfig to set the FPC IP address $newfpcip"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + } my $ipout = xCAT::Utils->runxcmd( { command => ["rspconfig"], - node => [$defnode], + node => ["$defnode"], arg => [ "ip=$newfpcip" ] }, $request, 0,1); - if ($::RUNCMD_RC != 0) { my %rsp; push@{ $rsp{data} }, "Could not change ip address $newfpcip on default FPC"; @@ -344,7 +429,46 @@ sub get_node { my $macmap = xCAT::MacMap->new(); my $node = ''; $node = $macmap->find_mac($fpcmac,0); + # verbose + if($::VERBOSE){ + my %rsp = {}; + push@{ $rsp{data} }, "Found FPC with MAC $fpcmac associated with node $node"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + } return ($node,$fpcmac); } + +# +# This subroutine adds the deffpc node entry for use by rspconfig +# +sub add_node { + my $defnode = shift; + my $callback = shift; +# add this node entry +# Object name: feihu-fpc +# bmc=feihu-fpc (Table:ipmi - Key:node - Column:bmc) +# bmcpassword=PASSW0RD (Table:ipmi - Key:node - Column:password) +# bmcusername=USERID (Table:ipmi - Key:node - Column:username) +# cons=ipmi (Table:nodehm - Key:node - Column:cons) +# groups=fpc (Table:nodelist - Key:node - Column:groups) +# mgt=ipmi (Table:nodehm - Key:node - Column:mgt) +# + + if($::VERBOSE){ + my %rsp = {}; + push@{ $rsp{data} }, "Creating default FPC node deffpc with IP 192.168.0.100 for later use with rspconfig"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + } + + my $nodelisttab = xCAT::Table->new('nodelist',-create=>1); + $nodelisttab->setNodeAttribs($defnode, {groups =>'defaultfpc'}); + my $nodehmtab = xCAT::Table->new('nodehm',-create=>1); + $nodehmtab->setNodeAttribs($defnode, {mgt => 'ipmi'}); + my $ipmitab = xCAT::Table->new('ipmi',-create=>1); + $ipmitab->setNodeAttribs($defnode, {bmc => $defnode, username => 'USERID', password => 'PASSW0RD'}); + +return 0; +} + 1; From fbc44597cad6f6a3f5d6da8ef59e43015ad22ad5 Mon Sep 17 00:00:00 2001 From: jjhua Date: Sun, 27 Oct 2013 16:16:57 -0400 Subject: [PATCH 70/91] remove the print Dumper() --- xCAT-OpenStack/lib/perl/xCAT/Cloud.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-OpenStack/lib/perl/xCAT/Cloud.pm b/xCAT-OpenStack/lib/perl/xCAT/Cloud.pm index 72b71d844..cb9ae9f50 100644 --- a/xCAT-OpenStack/lib/perl/xCAT/Cloud.pm +++ b/xCAT-OpenStack/lib/perl/xCAT/Cloud.pm @@ -128,7 +128,7 @@ sub getcloudres my $clients = shift; my $cloudres; my $cloudlist; - my $repos;use Data::Dumper; print Dumper($cloudinfo_hash); + my $repos; if( @$clients == 0 ) { #This should not be a chef-server, and it's a chef-client if( defined($cloudinfo_hash) && defined($cloudinfo_hash->{$node}) ) { From b44b1bbd6e2c75e3d62b3dbe24f1d0e477737357 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Sun, 27 Oct 2013 11:08:20 -0400 Subject: [PATCH 71/91] Tolerate and amend host definitions in SVC removing hard requirement for host names to match svc and xCAT --- xCAT-server/lib/xcat/plugins/svc.pm | 58 ++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/svc.pm b/xCAT-server/lib/xcat/plugins/svc.pm index 10b2b437b..3d0185338 100644 --- a/xCAT-server/lib/xcat/plugins/svc.pm +++ b/xCAT-server/lib/xcat/plugins/svc.pm @@ -76,8 +76,8 @@ sub mkstorage { } my $lun = create_lun(controller=>$controller, size=>$size, pool=>$pool); my $wwns = get_wwns(@nodes); - makehosts($wwns, controller=>$controller, cfg=>$storents); - bindhosts(\@nodes, $lun, controller=>$controller); + my @names = makehosts($wwns, controller=>$controller, cfg=>$storents); + bindhosts(\@names, $lun, controller=>$controller); } else { foreach my $node (@nodes) { mkstorage_single(node=>$node, size=>$size, pool=>$pool, @@ -119,11 +119,47 @@ sub bindhosts { } } +sub fixup_host { + my $session = shift; + my $wwnlist = shift; + my @hosts = hashifyoutput($session->cmd("lshost -delim :")); + my %wwnmap; + my %hostmap; + foreach my $host (@hosts) { + my @hostd = $session->cmd("lshost -delim : ".$host->{name}); + foreach my $hdatum (@hostd) { + if ($hdatum =~ m/^WWPN:(.*)$/) { + $wwnmap{$1} = $host->{name}; + $hostmap{$host->{name}}->{$1} = 1; + } + } + } + my $name; + foreach my $wwn (@$wwnlist) { + $wwn =~ s/://g; + $wwn = uc($wwn); + if (defined $wwnmap{$wwn}) { # found the matching host + #we want to give the host all the ports that may be relevant + $name = $wwnmap{$wwn}; + foreach my $mwwn (@$wwnlist) { + $mwwn =~ s/://g; + $mwwn = uc($mwwn); + if (not defined $hostmap{$name}->{$mwwn}) { + $session->cmd("addhostport -hbawwpn $mwwn -force $name"); + } + } + return $name; + } + } + die "unable to find host to fixup"; +} + sub makehosts { my $wwnmap = shift; my %args = @_; my $session = establish_session(%args); my $stortab = xCAT::Table->new('storage'); + my @hosts; foreach my $node (keys %$wwnmap) { my $wwnstr = ""; foreach my $wwn (@{$wwnmap->{$node}}) { @@ -134,7 +170,18 @@ sub makehosts { #TODO: what if the given wwn exists, but *not* as the nodename we want #the correct action is to look at hosts, see if one exists, and reuse, #create, or warn depending - $session->cmd("mkhost -name $node -fcwwpn $wwnstr -force"); + my @hostres = $session->cmd("mkhost -name $node -hbawwpn $wwnstr -force"); + my $result = $hostres[0]; + if ($result =~ m/^CMM/) { # we have some exceptional case.... + if ($result =~ m/^CMMVC6035E/) { #duplicate name and/or wwn.. + #need to finde the host and massage it to being viable + push @hosts, fixup_host($session, $wwnmap->{$node}); + } else { + die $result." while trying to create host"; + } + } else { + push @hosts, $node; + } my @currentcontrollers = split /,/, $args{cfg}->{$node}->[0]->{controller}; if ($args{cfg}->{$node}->[0] and $args{cfg}->{$node}->[0]->{controller}) { @currentcontrollers = split /,/, $args{cfg}->{$node}->[0]->{controller}; @@ -148,6 +195,7 @@ sub makehosts { my $ctrstring = join ",", @currentcontrollers; $stortab->setNodeAttribs($node,{controller=>$ctrstring}); } + return @hosts; } my %wwnmap; @@ -293,8 +341,8 @@ sub mkstorage_single { } my $lun = create_lun(controller=>$controller, size=>$size, pool=>$pool); my $wwns = get_wwns($node); - makehosts($wwns, controller=>$controller, cfg=>{$node=>$cfg}); - bindhosts([$node], $lun, controller=>$controller); + my @names = makehosts($wwns, controller=>$controller, cfg=>{$node=>$cfg}); + bindhosts(\@names, $lun, controller=>$controller); } sub process_request { From 2aaeb87959fde184de10bdc3511cd84c97072cb1 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Sun, 27 Oct 2013 11:17:50 -0400 Subject: [PATCH 72/91] Fix shared mkstorage to actually function correctly in svc --- xCAT-server/lib/xcat/plugins/svc.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-server/lib/xcat/plugins/svc.pm b/xCAT-server/lib/xcat/plugins/svc.pm index 3d0185338..196efe594 100644 --- a/xCAT-server/lib/xcat/plugins/svc.pm +++ b/xCAT-server/lib/xcat/plugins/svc.pm @@ -115,7 +115,7 @@ sub bindhosts { #TODO: get what failure looks like... somehow... #I guess I could make something with mismatched name and see how it #goes - $session->cmd("mkvdiskhostmap -host $node ".$lun->{id}); + $session->cmd("mkvdiskhostmap -force -host $node ".$lun->{id}); } } From 1e8ebff8ac395f76852845dfc88379751c40cbd6 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Sun, 27 Oct 2013 14:51:20 -0400 Subject: [PATCH 73/91] Add lsstorage command to the svc plugin --- xCAT-server/lib/xcat/plugins/svc.pm | 46 ++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/svc.pm b/xCAT-server/lib/xcat/plugins/svc.pm index 196efe594..d428c5f3c 100644 --- a/xCAT-server/lib/xcat/plugins/svc.pm +++ b/xCAT-server/lib/xcat/plugins/svc.pm @@ -20,14 +20,42 @@ my %controllersessions; sub handled_commands { return { mkstorage => "storage:type", + lsstorage => "storage:type", rmstorage => "storage:type", lspool => "storage:type", } } +sub lsstorage { + my $request = shift; + my @nodes = @{$request->{node}}; + my $storagetab = xCAT::Table->new("storage",-create=>0); + unless ($storagetab) { return; } + my $storents = $storagetab->getNodesAttribs(\@nodes,[qw/controller/]); + my $wwns = get_wwns(@nodes); + foreach my $node (@nodes) { + if ($storents and $storents->{$node} and $storents->{$node}->[0]->{controller}) { + my $ctls = $storents->{$node}->[0]->{controller}; + foreach my $ctl (split /,/, $ctls) { # TODO: scan all controllers at once + my $session = establish_session(controller=>$ctl); + my %namemap = makehosts($wwns, controller=>$ctl, cfg=>$storents); + my @vdisks = hashifyoutput($session->cmd("lsvdisk -delim :")); + foreach my $vdisk (@vdisks) { + my @maps = hashifyoutput($session->cmd("lsvdiskhostmap -delim : ".$vdisk->{'id'})); + foreach my $map (@maps) { + if ($map->{host_name} eq $namemap{$node}) { + sendmsg($vdisk->{name}.': size: '.$vdisk->{capacity}.' id: '.$vdisk->{vdisk_UID},$callback,$node); + last; + } + } + } + } + } + } +} + sub mkstorage { my $request = shift; - my $ctx = shift; my @nodes = @{$request->{node}}; my $shared = 0; my $controller; @@ -76,7 +104,8 @@ sub mkstorage { } my $lun = create_lun(controller=>$controller, size=>$size, pool=>$pool); my $wwns = get_wwns(@nodes); - my @names = makehosts($wwns, controller=>$controller, cfg=>$storents); + my %namemap = makehosts($wwns, controller=>$controller, cfg=>$storents); + my @names = values %namemap; bindhosts(\@names, $lun, controller=>$controller); } else { foreach my $node (@nodes) { @@ -159,7 +188,7 @@ sub makehosts { my %args = @_; my $session = establish_session(%args); my $stortab = xCAT::Table->new('storage'); - my @hosts; + my %nodenamemap; foreach my $node (keys %$wwnmap) { my $wwnstr = ""; foreach my $wwn (@{$wwnmap->{$node}}) { @@ -175,12 +204,12 @@ sub makehosts { if ($result =~ m/^CMM/) { # we have some exceptional case.... if ($result =~ m/^CMMVC6035E/) { #duplicate name and/or wwn.. #need to finde the host and massage it to being viable - push @hosts, fixup_host($session, $wwnmap->{$node}); + $nodenamemap{$node} = fixup_host($session, $wwnmap->{$node}); } else { die $result." while trying to create host"; } } else { - push @hosts, $node; + $nodenamemap{$node} = $node; } my @currentcontrollers = split /,/, $args{cfg}->{$node}->[0]->{controller}; if ($args{cfg}->{$node}->[0] and $args{cfg}->{$node}->[0]->{controller}) { @@ -195,7 +224,7 @@ sub makehosts { my $ctrstring = join ",", @currentcontrollers; $stortab->setNodeAttribs($node,{controller=>$ctrstring}); } - return @hosts; + return %nodenamemap; } my %wwnmap; @@ -341,7 +370,8 @@ sub mkstorage_single { } my $lun = create_lun(controller=>$controller, size=>$size, pool=>$pool); my $wwns = get_wwns($node); - my @names = makehosts($wwns, controller=>$controller, cfg=>{$node=>$cfg}); + my %namemap = makehosts($wwns, controller=>$controller, cfg=>{$node=>$cfg}); + my @names = values %namemap; bindhosts(\@names, $lun, controller=>$controller); } @@ -351,6 +381,8 @@ sub process_request { $dorequest = shift; if ($request->{command}->[0] eq 'mkstorage') { mkstorage($request); + } elsif ($request->{command}->[0] eq 'lsstorage') { + lsstorage($request); } elsif ($request->{command}->[0] eq 'lspool') { lsmdiskgrp($request); } From dc9dd79a5b1521c808dc81b3811ec12b06420e41 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Sun, 27 Oct 2013 15:16:14 -0400 Subject: [PATCH 74/91] Add ability to request a specific name when doing mkstorage --- xCAT-server/lib/xcat/plugins/svc.pm | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/svc.pm b/xCAT-server/lib/xcat/plugins/svc.pm index d428c5f3c..c12b386f2 100644 --- a/xCAT-server/lib/xcat/plugins/svc.pm +++ b/xCAT-server/lib/xcat/plugins/svc.pm @@ -65,12 +65,14 @@ sub mkstorage { unless (ref $request->{arg}) { die "TODO: usage"; } + my $name; @ARGV = @{$request->{arg}}; unless (GetOptions( 'shared' => \$shared, 'controller=s' => \$controller, 'boot' => \$boot, 'size=f' => \$size, + 'name=s' => \$name, 'pool=s' => \$pool, )) { foreach (@nodes) { @@ -102,7 +104,9 @@ sub mkstorage { unless (defined $pool and defined $controller) { return; } - my $lun = create_lun(controller=>$controller, size=>$size, pool=>$pool); + my %lunargs = (controller=>$controller, size=>$size, pool=>$pool); + if ($name) { $lunargs{name} = $name; } + my $lun = create_lun(%lunargs); my $wwns = get_wwns(@nodes); my %namemap = makehosts($wwns, controller=>$controller, cfg=>$storents); my @names = values %namemap; @@ -110,7 +114,7 @@ sub mkstorage { } else { foreach my $node (@nodes) { mkstorage_single(node=>$node, size=>$size, pool=>$pool, - boot=>$boot, controller=>$controller, + boot=>$boot, name=>$name, controller=>$controller, cfg=>$storents->{$node}); } } @@ -293,7 +297,11 @@ sub create_lun { my $session = establish_session(%args); my $pool = $args{pool}; my $size = $args{size}; - my @result = $session->cmd("mkvdisk -iogrp io_grp0 -mdiskgrp $pool -size $size -unit gb"); + my $cmd="mkvdisk -iogrp io_grp0 -mdiskgrp $pool -size $size -unit gb"; + if ($args{name}) { + $cmd .= " -name ".$args{name}; + } + my @result = $session->cmd($cmd); if ($result[0] =~ m/Virtual Disk, id \[(\d*)\], successfully created/) { my $diskid = $1; my $name; @@ -368,7 +376,11 @@ sub mkstorage_single { $controller = $cfg->{controller}; $controller =~ s/.*,//; } - my $lun = create_lun(controller=>$controller, size=>$size, pool=>$pool); + my %lunargs = (controller=>$controller, size=>$size, pool=>$pool); + if ($args{name}) { + $lunargs{name} = $args{name}."-".$node; + } + my $lun = create_lun(%lunargs); my $wwns = get_wwns($node); my %namemap = makehosts($wwns, controller=>$controller, cfg=>{$node=>$cfg}); my @names = values %namemap; From 7cab5a1f4172b6e5ce5a74c5aa35002a64de9f0e Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Sun, 27 Oct 2013 15:22:50 -0400 Subject: [PATCH 75/91] Have mkstorage report the volumes created. --- xCAT-server/lib/xcat/plugins/svc.pm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xCAT-server/lib/xcat/plugins/svc.pm b/xCAT-server/lib/xcat/plugins/svc.pm index c12b386f2..304db92fb 100644 --- a/xCAT-server/lib/xcat/plugins/svc.pm +++ b/xCAT-server/lib/xcat/plugins/svc.pm @@ -107,6 +107,7 @@ sub mkstorage { my %lunargs = (controller=>$controller, size=>$size, pool=>$pool); if ($name) { $lunargs{name} = $name; } my $lun = create_lun(%lunargs); + sendmsg($lun->{name}.": id: ".$lun->{wwn},$callback); my $wwns = get_wwns(@nodes); my %namemap = makehosts($wwns, controller=>$controller, cfg=>$storents); my @names = values %namemap; @@ -381,6 +382,7 @@ sub mkstorage_single { $lunargs{name} = $args{name}."-".$node; } my $lun = create_lun(%lunargs); + sendmsg($lun->{name}.": id: ".$lun->{wwn},$callback,$node); my $wwns = get_wwns($node); my %namemap = makehosts($wwns, controller=>$controller, cfg=>{$node=>$cfg}); my @names = values %namemap; From bd899691b0da6b1ffea5c16d21328590aa62fb04 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Sun, 27 Oct 2013 16:23:52 -0400 Subject: [PATCH 76/91] Add detachstorage call to svc plugin --- xCAT-server/lib/xcat/plugins/svc.pm | 38 ++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/xCAT-server/lib/xcat/plugins/svc.pm b/xCAT-server/lib/xcat/plugins/svc.pm index 304db92fb..6bd4f6900 100644 --- a/xCAT-server/lib/xcat/plugins/svc.pm +++ b/xCAT-server/lib/xcat/plugins/svc.pm @@ -21,11 +21,44 @@ sub handled_commands { return { mkstorage => "storage:type", lsstorage => "storage:type", + detachstorage => "storage:type", rmstorage => "storage:type", lspool => "storage:type", } } +sub detachstorage { + my $request = shift; + my @nodes = @{$request->{node}}; + my $controller; + @ARGV = @{$request->{arg}}; + unless (GetOptions( + 'controller=s' => \$controller, + )) { + foreach (@nodes) { + sendmsg([1,"Error parsing arguments"],$callback,$_); + } + } + my $storagetab = xCAT::Table->new('storage'); + my $storents = $storagetab->getNodesAttribs(\@nodes, [qw/controller/]); + unless ($controller) { + $controller = assure_identical_table_values(\@nodes, $storents, 'controller'); + } + my $volname = shift @ARGV; + my $wwns = get_wwns(@nodes); + use Data::Dumper; + my %namemap = makehosts($wwns, controller=>$controller, cfg=>$storents); + foreach my $node (keys %namemap) { + my $host = $namemap{$node}; + my $session = establish_session(controller=>$controller); + my @rets = $session->cmd("rmvdiskhostmap -host $host $volname"); + my $ret = $rets[0]; + if ($ret =~ m/^CMMVC5842E/) { + sendmsg([1,"Node not attached"],$callback,$node); + } + } +} + sub lsstorage { my $request = shift; my @nodes = @{$request->{node}}; @@ -332,7 +365,7 @@ sub assure_identical_table_values { $callback, $node); return undef; } - my $currval = $storents->{$node}->{$attribute}; + my $currval = $sent->{$attribute}; unless ($currval) { sendmsg([1, "No $attribute in arguments or table"], $callback, $node); @@ -344,6 +377,7 @@ sub assure_identical_table_values { $callback, $node); return undef; } + if (not defined $lastval) { $lastval = $currval; } } return $lastval; } @@ -397,6 +431,8 @@ sub process_request { mkstorage($request); } elsif ($request->{command}->[0] eq 'lsstorage') { lsstorage($request); + } elsif ($request->{command}->[0] eq 'detachstorage') { + detachstorage($request); } elsif ($request->{command}->[0] eq 'lspool') { lsmdiskgrp($request); } From bb351003dc13131e8a24cb67c32c608bfb955884 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Sun, 27 Oct 2013 16:39:23 -0400 Subject: [PATCH 77/91] Implement rmstorage for sc --- xCAT-server/lib/xcat/plugins/svc.pm | 50 ++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/svc.pm b/xCAT-server/lib/xcat/plugins/svc.pm index 6bd4f6900..7345cf3f1 100644 --- a/xCAT-server/lib/xcat/plugins/svc.pm +++ b/xCAT-server/lib/xcat/plugins/svc.pm @@ -44,21 +44,59 @@ sub detachstorage { unless ($controller) { $controller = assure_identical_table_values(\@nodes, $storents, 'controller'); } - my $volname = shift @ARGV; + my @volnames = @ARGV; my $wwns = get_wwns(@nodes); use Data::Dumper; my %namemap = makehosts($wwns, controller=>$controller, cfg=>$storents); foreach my $node (keys %namemap) { my $host = $namemap{$node}; my $session = establish_session(controller=>$controller); - my @rets = $session->cmd("rmvdiskhostmap -host $host $volname"); - my $ret = $rets[0]; - if ($ret =~ m/^CMMVC5842E/) { - sendmsg([1,"Node not attached"],$callback,$node); + foreach my $volname (@volnames) { + my @rets = $session->cmd("rmvdiskhostmap -host $host $volname"); + my $ret = $rets[0]; + if ($ret =~ m/^CMMVC5842E/) { + sendmsg([1,"Node not attached to $volname"],$callback,$node); + } } } } +sub rmstorage { + my $request = shift; + my @nodes = @{$request->{node}}; + my $controller; + @ARGV = @{$request->{arg}}; + unless (GetOptions( + 'controller=s' => \$controller, + )) { + foreach (@nodes) { + sendmsg([1,"Error parsing arguments"],$callback,$_); + } + } + my @volnames = @ARGV; + my $storagetab = xCAT::Table->new('storage'); + my $storents = $storagetab->getNodesAttribs(\@nodes, [qw/controller/]); + unless ($controller) { + $controller = assure_identical_table_values(\@nodes, $storents, 'controller'); + } + detachstorage($request); + my $session = establish_session(controller=>$controller); + foreach my $volname (@volnames) { + my @info = $session->cmd("rmvdisk $volname"); + my $ret = $info[0]; + if ($ret =~ m/^CMMVC5753E/) { + foreach my $node (@nodes) { + sendmsg([1,"Disk $volname does not exist"], $callback, @nodes); + } + } elsif ($ret =~ m/^CMMVC5840E/) { + foreach my $node (@nodes) { + sendmsg([1,"Disk $volname is mapped to other nodes and/or busy"], $callback, @nodes); + } + } + } +} + + sub lsstorage { my $request = shift; my @nodes = @{$request->{node}}; @@ -431,6 +469,8 @@ sub process_request { mkstorage($request); } elsif ($request->{command}->[0] eq 'lsstorage') { lsstorage($request); + } elsif ($request->{command}->[0] eq 'rmstorage') { + rmstorage($request); } elsif ($request->{command}->[0] eq 'detachstorage') { detachstorage($request); } elsif ($request->{command}->[0] eq 'lspool') { From 06fe33434a94f18b3267e9037c33b562b5f16a46 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Sun, 27 Oct 2013 16:49:25 -0400 Subject: [PATCH 78/91] Fix table sourced controller pointing in *storage calls in svc --- xCAT-server/lib/xcat/plugins/svc.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/svc.pm b/xCAT-server/lib/xcat/plugins/svc.pm index 7345cf3f1..98352215b 100644 --- a/xCAT-server/lib/xcat/plugins/svc.pm +++ b/xCAT-server/lib/xcat/plugins/svc.pm @@ -445,8 +445,8 @@ sub mkstorage_single { } if (defined $args{controller}) { $controller = $args{controller}; - } elsif ($cfg->{controller}) { - $controller = $cfg->{controller}; + } elsif ($cfg->[0]->{controller}) { + $controller = $cfg->[0]->{controller}; $controller =~ s/.*,//; } my %lunargs = (controller=>$controller, size=>$size, pool=>$pool); From 428058af5a2885f8dd8ba01460743cf3440114d0 Mon Sep 17 00:00:00 2001 From: jjhua Date: Mon, 28 Oct 2013 11:02:30 -0400 Subject: [PATCH 79/91] move setup_openstack_repo from xCAT/postscripts/ to xCAT-OpenStack/postscripts, and it will be packed into xCAT-OpenStack package --- {xCAT => xCAT-OpenStack}/postscripts/setup_openstack_repo | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {xCAT => xCAT-OpenStack}/postscripts/setup_openstack_repo (100%) diff --git a/xCAT/postscripts/setup_openstack_repo b/xCAT-OpenStack/postscripts/setup_openstack_repo similarity index 100% rename from xCAT/postscripts/setup_openstack_repo rename to xCAT-OpenStack/postscripts/setup_openstack_repo From 0c7e33c045569bc5a08abc5f34fa4ff110a7fac0 Mon Sep 17 00:00:00 2001 From: yinle Date: Mon, 28 Oct 2013 06:28:45 -0700 Subject: [PATCH 80/91] Add check in configeth to give message to AIX user. --- xCAT/postscripts/configeth | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xCAT/postscripts/configeth b/xCAT/postscripts/configeth index 356dbb872..d66ec3d15 100755 --- a/xCAT/postscripts/configeth +++ b/xCAT/postscripts/configeth @@ -314,6 +314,10 @@ if [ "$str_os_type" = "linux" ];then str_os_type="redhat" str_cfg_dir="/etc/sysconfig/network-scripts/" fi +else + echo "configeth dose not support AIX in this build" + exit 0 + fi logger -t xcat -p local4.err "configeth: os type: $str_os_type" From 8ecf88438cbb338a3ac2129c9eab1bd2be7101d6 Mon Sep 17 00:00:00 2001 From: yinle Date: Mon, 28 Oct 2013 06:33:44 -0700 Subject: [PATCH 81/91] Add check in confignics to give message to AIX user. --- xCAT/postscripts/confignics | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xCAT/postscripts/confignics b/xCAT/postscripts/confignics index f523d9b1c..37fe95bd8 100755 --- a/xCAT/postscripts/confignics +++ b/xCAT/postscripts/confignics @@ -45,6 +45,11 @@ bool_cfg_inst_nic=0 str_inst_nic='' str_ib_nics='' str_os_type=`uname | tr 'A-Z' 'a-z'` +if [ "$str_os_type" = "aix" ];then + logger -t xcat -p local4.err "confignics: aix does not support in this build" + echo "confignics: aix does not support in this build" + exit 0 +fi bool_remove=0 num_iba_ports= str_all_nics='' From 3be3d26ac392e24cf0420658dd2c5c58a613d7d4 Mon Sep 17 00:00:00 2001 From: yinle Date: Mon, 28 Oct 2013 07:27:29 -0700 Subject: [PATCH 82/91] Add lsslp support for IMM2. --- xCAT-server/lib/xcat/plugins/lsslp.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/lsslp.pm b/xCAT-server/lib/xcat/plugins/lsslp.pm index a6b3db461..74e66424e 100644 --- a/xCAT-server/lib/xcat/plugins/lsslp.pm +++ b/xCAT-server/lib/xcat/plugins/lsslp.pm @@ -525,7 +525,7 @@ sub invoke_dodiscover { if ($globalopt{service}) { $services = $globalopt{service}; } else { - $services = [WILDCARD_SERVICE,HARDWARE_SERVICE,SOFTWARE_SERVICE]; + $services = [WILDCARD_SERVICE,HARDWARE_SERVICE,SOFTWARE_SERVICE,SERVICE_IMM2]; } #efix for hmc bug if ($services =~ /hardware-management-console/) { @@ -1421,7 +1421,6 @@ sub xCATdB { my $hidden = ($type =~ /bpa|fsp/)? 1:0; my $groups = lc($type).",all"; my $tmp_pre = xCAT::data::ibmhwtypes::parse_group($model); - if (defined($tmp_pre)) { $groups .= ",$tmp_pre"; } @@ -1504,7 +1503,6 @@ sub format_stanza { if (defined($tmp_pre)) { $groups .= ",$tmp_pre"; } - ################################# # Node attributes @@ -2099,3 +2097,5 @@ sub bt_handle_new_slp_entity { $btresult{$mac} = $data; } 1; + + From ec85d061177f460c1f100c35f1e735ef325d4e0a Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Mon, 28 Oct 2013 10:43:08 -0400 Subject: [PATCH 83/91] Suppress warnings about ssh/tech support shell --- xCAT-server/share/xcat/install/esxi/hypervisor.tmpl | 1 + 1 file changed, 1 insertion(+) diff --git a/xCAT-server/share/xcat/install/esxi/hypervisor.tmpl b/xCAT-server/share/xcat/install/esxi/hypervisor.tmpl index 0f3d2a6b2..6a200daa6 100644 --- a/xCAT-server/share/xcat/install/esxi/hypervisor.tmpl +++ b/xCAT-server/share/xcat/install/esxi/hypervisor.tmpl @@ -52,6 +52,7 @@ echo -e "\nnextdestiny\n" | /bin/o chkconfig SSH on chkconfig ESXShell on esxcli system settings advanced set --int-value 0 --option /VMFS3/EnableBlockDelete +esxcli system settings advanced set --int-value 1 --option /UserVars/SuppressShellWarning esxcli network ip set -e y esxcli network firewall ruleset set -r DHCPv6 -e y esxcli network firewall ruleset set -r sshServer -e y From b0ddf05865bfce26d54084f462f30b4d6acc4068 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Mon, 28 Oct 2013 10:44:40 -0400 Subject: [PATCH 84/91] Fix stateless esxi warning about ssh --- xCAT-server/share/xcat/netboot/esxi/48.esxifixup | 1 + 1 file changed, 1 insertion(+) diff --git a/xCAT-server/share/xcat/netboot/esxi/48.esxifixup b/xCAT-server/share/xcat/netboot/esxi/48.esxifixup index df4500688..dc99ab1e6 100644 --- a/xCAT-server/share/xcat/netboot/esxi/48.esxifixup +++ b/xCAT-server/share/xcat/netboot/esxi/48.esxifixup @@ -1,6 +1,7 @@ #!/bin/sh #first off, let's ditch UNMAP, per vwmare's recall... localcli system settings advanced set --int-value 0 --option /VMFS3/EnableBlockDelete +localcli system settings advanced set --int-value 1 --option /UserVars/SuppressShellWarning #ok, now let's turn on some SSH and ESXShell fun localcli network firewall ruleset set -r sshServer -e y chkconfig ESXShell on From fbce5a6a000b009ccb8ed40cde3cdbad5e8eecdf Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Mon, 28 Oct 2013 16:07:06 -0400 Subject: [PATCH 85/91] Add formatdisk to esx plugin, to be called by mkstorage --- xCAT-server/lib/xcat/plugins/esx.pm | 36 ++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/xCAT-server/lib/xcat/plugins/esx.pm b/xCAT-server/lib/xcat/plugins/esx.pm index 1f4af072e..44bf57902 100644 --- a/xCAT-server/lib/xcat/plugins/esx.pm +++ b/xCAT-server/lib/xcat/plugins/esx.pm @@ -125,6 +125,7 @@ sub handled_commands{ rpower => 'nodehm:power,mgt', rsetboot => 'nodehm:power,mgt', rmigrate => 'nodehm:power,mgt', + formatdisk => "nodetype:os=(esxi.*)", mkvm => 'nodehm:mgt', rmvm => 'nodehm:mgt', clonevm => 'nodehm:mgt', @@ -210,7 +211,7 @@ sub preprocess_request { my $vmtabhash = $vmtab->getNodesAttribs($noderange,['host','migrationdest']); foreach my $node (@$noderange){ - if ($command eq "rmhypervisor" or $command eq 'lsvm' or $command eq 'rshutdown' or $command eq "chhypervisor") { + if ($command eq "rmhypervisor" or $command eq 'lsvm' or $command eq 'rshutdown' or $command eq "chhypervisor" or $command eq "formatdisk") { $hyp_hash{$node}{nodes} = [$node]; } else { my $ent = $vmtabhash->{$node}->[0]; @@ -636,6 +637,8 @@ sub do_cmd { generic_vm_operation(['config.name','runtime.host'],\&setboot,@exargs); } elsif ($command eq 'rinv') { generic_vm_operation(['config.name','config','runtime.host','layoutEx'],\&inv,@exargs); + } elsif ($command eq 'formatdisk') { + generic_hyp_operation(\&formatdisk,@exargs); } elsif ($command eq 'rmhypervisor') { generic_hyp_operation(\&rmhypervisor,@exargs); } elsif ($command eq 'rshutdown') { @@ -2173,6 +2176,37 @@ sub rshutdown_inmaintenance { return; } +sub formatdisk { + my %args = @_; + my $hyp = $args{hyp}; + $hyphash{$hyp}->{hostview} = get_hostview(hypname=>$hyp,conn=>$hyphash{$hyp}->{conn},properties=>['config','configManager']); + @ARGV = @{$args{exargs}}; + my $nid; + my $name; + GetOptions( + 'id=s' => \$nid, + 'name=s' => \$name, + ); + my $hostview = $hyphash{$hyp}->{hostview}; + if (defined $hyphash{$hyp}->{hostview}) { + my $hdss = $hostview->{vim}->get_view(mo_ref=>$hostview->configManager->storageSystem); + $hdss->RescanAllHba(); + my $dss = $hostview->{vim}->get_view(mo_ref=>$hostview->configManager->datastoreSystem); + my $diskList = $dss->QueryAvailableDisksForVmfs(); + foreach my $disk (@$diskList) { + foreach my $id (@{$disk->{descriptor}}) { + if (lc($id->{id}) eq lc('naa.'.$nid)) { + my $options = $dss->QueryVmfsDatastoreCreateOptions(devicePath => $disk->devicePath); + @$options[0]->spec->vmfs->volumeName($name); + my $newDatastore = $dss->CreateVmfsDatastore(spec => @$options[0]->spec ); + } + } + } + + } + return; +} + sub rmhypervisor { my %args = @_; my $hyp = $args{hyp}; From 952ff38ce42385b3797a15bebc128812c597836c Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Mon, 28 Oct 2013 16:15:25 -0400 Subject: [PATCH 86/91] Add --format to mkstorage --- xCAT-server/lib/xcat/plugins/svc.pm | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/xCAT-server/lib/xcat/plugins/svc.pm b/xCAT-server/lib/xcat/plugins/svc.pm index 98352215b..e3830a975 100644 --- a/xCAT-server/lib/xcat/plugins/svc.pm +++ b/xCAT-server/lib/xcat/plugins/svc.pm @@ -133,12 +133,14 @@ sub mkstorage { my $pool; my $size; my $boot = 0; + my $format = 0; unless (ref $request->{arg}) { die "TODO: usage"; } my $name; @ARGV = @{$request->{arg}}; unless (GetOptions( + 'format' => \$format, 'shared' => \$shared, 'controller=s' => \$controller, 'boot' => \$boot, @@ -183,6 +185,16 @@ sub mkstorage { my %namemap = makehosts($wwns, controller=>$controller, cfg=>$storents); my @names = values %namemap; bindhosts(\@names, $lun, controller=>$controller); + if ($format) { + my %request = ( + node => [$nodes[0]], + command => [ 'formatdisk' ], + arg => [ '--id', $lun->{wwn}, '--name', $lun->{name} ] + ); + use Data::Dumper; + print Dumper($request{arg}); + $dorequest->(\%request, $callback); + } } else { foreach my $node (@nodes) { mkstorage_single(node=>$node, size=>$size, pool=>$pool, From 08accdf517c51f39ed7224b462c1a774e1c01667 Mon Sep 17 00:00:00 2001 From: John Simpson Date: Mon, 28 Oct 2013 16:14:27 -0400 Subject: [PATCH 87/91] update to configfpc to add support for verbose and -i option and a ping verification --- xCAT-server/lib/xcat/plugins/configfpc.pm | 31 +++++++++++++---------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/configfpc.pm b/xCAT-server/lib/xcat/plugins/configfpc.pm index e74f78d7d..de1ed3692 100644 --- a/xCAT-server/lib/xcat/plugins/configfpc.pm +++ b/xCAT-server/lib/xcat/plugins/configfpc.pm @@ -43,7 +43,6 @@ sub process_request { 'help|h|?' => \$::opt_h, 'i|I=s' => \$::opt_I, 'verbose|V' => \$::opt_V, - 'version|v' => \$::opt_v, ); # Option -h for Help @@ -94,9 +93,9 @@ sub configfpc_usage { push @{ $rsp->{data} }, "\nUsage: configfpc - Configure the NeXtScale FPCs.i This command requires the -i option to give specify which network adapter to use to look for the FPCs.\n"; push @{ $rsp->{data} }, - " configfpc -i interface_adapter \n "; + " configfpc -i interface \n "; push @{ $rsp->{data} }, - " configfpc [-V|--verbose] -i adapter_interface \n "; + " configfpc [-V|--verbose] -i interface \n "; push @{ $rsp->{data} }, " configfpc [-h|--help|-?] \n"; xCAT::MsgUtils->message( "I", $rsp, $::CALLBACK ); return 0; @@ -218,7 +217,8 @@ sub configfpc { } else { my %rsp; push@{ $rsp{data} }, "No FPC found that is associated with MAC address $fpcmac.\nCheck to see if the switch and switch table contain the information needed to locate this FPC MAC"; - xCAT::MsgUtils->message( "I", \%rsp, $callback ); + xCAT::MsgUtils->message( "E", \%rsp, $callback ); + $foundfpc = 0; } # @@ -231,16 +231,19 @@ sub configfpc { } my $arpout = `arp -d $fpcip`; - # check for another FPC - $res = `LANG=C ping -c 1 -w 5 $fpcip 2>&1`; - if ( $res =~ /100% packet loss/g) { - my %rsp; - push@{ $rsp{data} }, "There are no more FPCs with the default IP address to process"; - xCAT::MsgUtils->message( "I", \%rsp, $callback ); - $foundfpc = 0; - } - else { - $foundfpc = 1; + if ( ($foundfpc==1) ) { # if the last FPC was found and processed + + # check for another FPC + $res = `LANG=C ping -c 1 -w 5 $fpcip 2>&1`; + if ( ($res =~ /100% packet loss/g) && ($foundfpc==1) ) { + my %rsp; + push@{ $rsp{data} }, "There are no more FPCs with the default IP address to process"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + $foundfpc = 0; + } + else { + $foundfpc = 1; + } } } From 3664f1d5c3290b988581864303fefe9bfd7e4ac6 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Mon, 28 Oct 2013 20:26:40 -0400 Subject: [PATCH 88/91] Implement rescansan in esx.pm and wire up svc.pm to issue rescansan --- xCAT-server/lib/xcat/plugins/esx.pm | 21 ++++++++++++++++----- xCAT-server/lib/xcat/plugins/svc.pm | 9 ++++++--- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/esx.pm b/xCAT-server/lib/xcat/plugins/esx.pm index 44bf57902..168fa6515 100644 --- a/xCAT-server/lib/xcat/plugins/esx.pm +++ b/xCAT-server/lib/xcat/plugins/esx.pm @@ -126,6 +126,7 @@ sub handled_commands{ rsetboot => 'nodehm:power,mgt', rmigrate => 'nodehm:power,mgt', formatdisk => "nodetype:os=(esxi.*)", + rescansan => "nodetype:os=(esxi.*)", mkvm => 'nodehm:mgt', rmvm => 'nodehm:mgt', clonevm => 'nodehm:mgt', @@ -211,7 +212,7 @@ sub preprocess_request { my $vmtabhash = $vmtab->getNodesAttribs($noderange,['host','migrationdest']); foreach my $node (@$noderange){ - if ($command eq "rmhypervisor" or $command eq 'lsvm' or $command eq 'rshutdown' or $command eq "chhypervisor" or $command eq "formatdisk") { + if ($command eq "rmhypervisor" or $command eq 'lsvm' or $command eq 'rshutdown' or $command eq "chhypervisor" or $command eq "formatdisk" or $command eq 'rescansan') { $hyp_hash{$node}{nodes} = [$node]; } else { my $ent = $vmtabhash->{$node}->[0]; @@ -320,6 +321,7 @@ sub process_request { if ($request->{_xcat_authname}->[0]) { $requester=$request->{_xcat_authname}->[0]; } + %vcenterhash = ();#A data structure to reflect the state of vcenter connectivity to hypervisors my $level = shift; my $distname = undef; my $arch = undef; @@ -639,6 +641,8 @@ sub do_cmd { generic_vm_operation(['config.name','config','runtime.host','layoutEx'],\&inv,@exargs); } elsif ($command eq 'formatdisk') { generic_hyp_operation(\&formatdisk,@exargs); + } elsif ($command eq 'rescansan') { + generic_hyp_operation(\&rescansan,@exargs); } elsif ($command eq 'rmhypervisor') { generic_hyp_operation(\&rmhypervisor,@exargs); } elsif ($command eq 'rshutdown') { @@ -2176,6 +2180,17 @@ sub rshutdown_inmaintenance { return; } +sub rescansan { + my %args = @_; + my $hyp = $args{hyp}; + my $hostview = get_hostview(hypname=>$hyp,conn=>$hyphash{$hyp}->{conn},properties=>['config','configManager']); + if (defined $hostview) { + my $hdss = $hostview->{vim}->get_view(mo_ref=>$hostview->configManager->storageSystem); + $hdss->RescanAllHba(); + $hdss->RescanVmfs(); + } +} + sub formatdisk { my %args = @_; my $hyp = $args{hyp}; @@ -4959,7 +4974,6 @@ sub cpNetbootImages { chdir($tmpDir); xCAT::SvrUtils::sendmsg("extracting netboot files from OS image. This may take about a minute or two...hopefully you have ~1GB free in your /tmp dir\n", $output_handler); my $cmd = "tar zxf $srcDir/image.tgz"; - print "\n$cmd\n"; if(system($cmd)){ xCAT::SvrUtils::sendmsg([1,"Unable to extract $srcDir/image.tgz\n"], $output_handler); } @@ -4971,13 +4985,11 @@ sub cpNetbootImages { # now we need to get partition 5 which has the installation goods in it. my $scmd = "fdisk -lu $tmpDir/usr/lib/vmware/installer/*dd 2>&1 | grep dd5 | awk '{print \$2}'"; - print "running: $scmd\n"; my $sector = `$scmd`; chomp($sector); my $offset = $sector * 512; mkdir "/mnt/xcat"; my $mntcmd = "mount $tmpDir/usr/lib/vmware/installer/*dd /mnt/xcat -o loop,offset=$offset"; - print "$mntcmd\n"; if(system($mntcmd)){ xCAT::SvrUtils::sendmsg([1,"unable to mount partition 5 of the ESX netboot image to /mnt/xcat"], $output_handler); return; @@ -4999,7 +5011,6 @@ sub cpNetbootImages { } chdir("/tmp"); system("umount /mnt/xcat"); - print "tempDir: $tmpDir\n"; system("rm -rf $tmpDir"); } elsif (-r "$srcDir/cim.vgz" and -r "$srcDir/vmkernel.gz" and -r "$srcDir/vmkboot.gz" and -r "$srcDir/sys.vgz") { use File::Basename; diff --git a/xCAT-server/lib/xcat/plugins/svc.pm b/xCAT-server/lib/xcat/plugins/svc.pm index e3830a975..c807b87ba 100644 --- a/xCAT-server/lib/xcat/plugins/svc.pm +++ b/xCAT-server/lib/xcat/plugins/svc.pm @@ -185,14 +185,17 @@ sub mkstorage { my %namemap = makehosts($wwns, controller=>$controller, cfg=>$storents); my @names = values %namemap; bindhosts(\@names, $lun, controller=>$controller); - if ($format) { + if ($format) { my %request = ( node => [$nodes[0]], command => [ 'formatdisk' ], arg => [ '--id', $lun->{wwn}, '--name', $lun->{name} ] ); - use Data::Dumper; - print Dumper($request{arg}); + $dorequest->(\%request, $callback); + %request = ( + node => \@nodes, + command => [ 'rescansan' ], + ); $dorequest->(\%request, $callback); } } else { From cac2677c1cfe4c3936a037c1a36994043153ae56 Mon Sep 17 00:00:00 2001 From: ligc Date: Tue, 29 Oct 2013 10:48:31 +0800 Subject: [PATCH 89/91] temp fix for bug 3792: multiple nics in the same subnet, use the first nic that in the subnet for dhcp --- xCAT-server/lib/xcat/plugins/dhcp.pm | 12 ++++++++++++ 1 file changed, 12 insertions(+) mode change 100644 => 100755 xCAT-server/lib/xcat/plugins/dhcp.pm diff --git a/xCAT-server/lib/xcat/plugins/dhcp.pm b/xCAT-server/lib/xcat/plugins/dhcp.pm old mode 100644 new mode 100755 index 46963a50e..90f3b55db --- a/xCAT-server/lib/xcat/plugins/dhcp.pm +++ b/xCAT-server/lib/xcat/plugins/dhcp.pm @@ -1998,6 +1998,11 @@ sub addnet if ($ent[0] eq $net and $ent[2] eq $mask) { $nic = $ent[1]; + # The first nic that matches the network, + # what will happen if there are more than one nics in the same subnet, + # and we want to use the second nic as the dhcp interfaces? + # this is a TODO + last; } } #print " add $net $mask under $nic\n"; @@ -2014,6 +2019,13 @@ sub addnet } unless ($dhcpconf[$idx] =~ /\} # $nic nic_end\n/) { + $callback->( + { + error => + ["Could not add the subnet $net/$mask for nic $nic into $dhcpconffile."], + errorcode => [1] + } + ); return 1; #TODO: this is an error condition } } From 0eb918b7bdfb0e4f6d510c612466baf05db3cc76 Mon Sep 17 00:00:00 2001 From: lissav Date: Tue, 29 Oct 2013 11:08:40 -0400 Subject: [PATCH 90/91] 3865,3864 --- xCAT-server/sbin/xcatsnap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xCAT-server/sbin/xcatsnap b/xCAT-server/sbin/xcatsnap index 500f62b06..64f8b07de 100755 --- a/xCAT-server/sbin/xcatsnap +++ b/xCAT-server/sbin/xcatsnap @@ -102,7 +102,7 @@ sub run_cmd { print "\n\tExecuting: $Command \n"; eval { local $SIG{ALRM} = sub { die "Timeout\n" }; - alarm 60; + alarm 600; @output = `$Command`; alarm 0; }; @@ -238,7 +238,7 @@ sub snap_it { "ls $installdir","/usr/bin/crontab -l", "find /tftpboot -size -32k","ls -lR $xcatroot", "arp -a","ps -edlf","ps -aux","ulimit -a","df -k", - "cat /etc/issue","lsxcatd -a"); + "cat /etc/issue","lsxcatd -a","cat /proc/meminfo", "cat /proc/cpuinfo"); } foreach my $item (@Commands_array) { $Command = $item; From 13e7903b436b68e3c625271eee3f99886e663a76 Mon Sep 17 00:00:00 2001 From: nott Date: Tue, 29 Oct 2013 14:45:14 -0400 Subject: [PATCH 91/91] buildkit fixes 3845, 3855, 3857 --- xCAT-buildkit/bin/buildkit | 29 +- xCAT-buildkit/bin/buildkit.fix | 3766 ++++++++++++++++++++++++++++++++ 2 files changed, 3785 insertions(+), 10 deletions(-) create mode 100755 xCAT-buildkit/bin/buildkit.fix diff --git a/xCAT-buildkit/bin/buildkit b/xCAT-buildkit/bin/buildkit index 02ca942cb..e717029f6 100755 --- a/xCAT-buildkit/bin/buildkit +++ b/xCAT-buildkit/bin/buildkit @@ -949,9 +949,14 @@ sub kit_buildtar my $tarfile = $::deploy_dir."/".$kitfilename; - if ( system("cd $::deploy_dir; cd ..; cp -r build_input $kitname" ) ) { - print "Error: Could not copy building tarfile $tarfile \n"; - return 1; + my $dir = dirname($::deploy_dir); + my $bidir = "$dir/build_input"; + + if ( -d "$bidir") { + if ( system("cd $::deploy_dir; cd ..; cp -r build_input $kitname" ) ) { + print "Error: Could not copy building tarfile $tarfile \n"; + return 1; + } } print "Creating tar file $tarfile.\n"; @@ -1940,9 +1945,10 @@ sub build_kitcomp my $specfile = $::workdir."/tmp/$comp->{kitcompname}-prep.spec"; my $rpmbuild_cmd = "rpmbuild --define \"_topdir $rpmbuild_dir\" -ba $specfile"; - if (!$::VERBOSE) { + # don't want debug info - 3845 +# if (!$::VERBOSE) { $rpmbuild_cmd .= ' --quiet '; - } +# } if ( system($rpmbuild_cmd) ) { print "Error running rpmbuild command for kit component $comp->{kitcompname} meta package\n"; return 1; @@ -1955,7 +1961,7 @@ sub build_kitcomp return 1; } } - + $::VALID_PRER_COMPONENT = 1; } @@ -2012,9 +2018,12 @@ sub build_kitcomp return 1; } } - if (!$::VERBOSE) { + + # - don't want debug info - 3845 +# if (!$::VERBOSE) { $rpmbuild_cmd .= ' --quiet '; - } +# } + if ( system($rpmbuild_cmd) ) { print "Error running rpmbuild command for kit component $comp->{kitcompname} meta package\n"; return 1; @@ -2056,7 +2065,7 @@ sub update_kitcomp_kitpkgdeps my $repodir = shift; if (defined($comp->{kitpkgdeps})) { - # we have some rpms listed -n buildkit.conf file + # we have some rpms listed in buildkit.conf file my $new_kitpkgdeps = ''; foreach my $d (split(/,/, $comp->{kitpkgdeps})) { $d =~ s/\s+//g; @@ -2073,7 +2082,6 @@ sub update_kitcomp_kitpkgdeps my @rpmlist = `$lscmd`; if ( scalar(@rpmlist) == 0) { - print "Error: Could not find rpm named $d in $repodir. \n"; next; } @@ -3542,6 +3550,7 @@ sub NEW_kit_addpkgs system ("rm -Rf $tmpdir_base"); return 1; } + my @fromfiles=@$files; foreach my $repo (split(/,/, $ext_reponames)) { diff --git a/xCAT-buildkit/bin/buildkit.fix b/xCAT-buildkit/bin/buildkit.fix new file mode 100755 index 000000000..e717029f6 --- /dev/null +++ b/xCAT-buildkit/bin/buildkit.fix @@ -0,0 +1,3766 @@ +#!/usr/bin/env perl +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html +# + +#----------------------------------------------------------------------------- + +=head1 buildkit + + xCAT/PCM Kit Build utilities + +This script is designed to run on a non-xCAT system so that Kits can be +built on any product build machine. + +=cut + +BEGIN +{ + $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; + $::XCATDIR = $ENV{'XCATDIR'} ? $ENV{'XCATDIR'} : '/etc/xcat'; + $::XCATSHARE = $::XCATROOT.'/share/xcat'; +} + +if ($^O =~ /^aix/i) { + print "ERROR - the buildkit command is not supported on AIX \n"; + exit 1; +} + +use lib "$::XCATROOT/lib/perl"; +require xCAT::BuildKitUtils; +use Getopt::Long; +use strict; +use Cwd; +use Cwd 'abs_path'; +use File::Path; +use File::Basename; + +#----------------------------------------------------------------------------- +# Main + +$::progname = "buildkit"; +$::buildkit_conf = "buildkit.conf"; +$::kit_conf = "kit.conf"; +$::current_dir = cwd(); + +# this code will build a kit using framework 1. +$::KITFRAMEWORK ="2"; + +# this code is compatible with other kits that are at framework 0 or 1. +$::COMPATIBLE_KITFRAMEWORKS = "0,1,2"; + +%::buildkit_def = ( + kit => { basename => { + description=>'The kit base name (e.g., kit-lsf)', + value_desc=>'Must be: Generic Name String', + mandatory=>1, + cp_to_kitconfig=>1}, + description => { + description=>'The kit description', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>1}, + version => { + description=>'The kit version (e.g., 9.0)', + value_desc=>'Must be: Generic Name String', + mandatory=>1, + cp_to_kitconfig=>1}, + release => { + description=>'The kit release (e.g., 1)', + value_desc=>'Must be: Generic Name String', + mandatory=>0, + cp_to_kitconfig=>1}, + ostype => { + description=>'The kit OS type (e.g., Linux)', + value_desc=>'Must be: OS Type String', + mandatory=>1, + cp_to_kitconfig=>1}, + osbasename => { + description=>'The kit OS basename', + value_desc=>'Must be: Generic Name String', + mandatory=>0, + cp_to_kitconfig=>0}, + osmajorversion => { + description=>'The kit OS majorversion', + value_desc=>'Must be: Generic Name String', + mandatory=>0, + cp_to_kitconfig=>0}, + osminorversion => { + description=>'The kit OS minorversion', + value_desc=>'Must be: Generic Name String', + mandatory=>0, + cp_to_kitconfig=>0}, + osarch => { + description=>'The kit OS architecture', + value_desc=>'Must be: Generic Name String', + mandatory=>0, + cp_to_kitconfig=>0}, + isinternal=> { + description=>'Flag to say if this Kit is used for internal use only. It is only used for information purposes.', + value_desc=>'Must be: empty string or boolean string', + mandatory=>0, + cp_to_kitconfig=>1}, + kitdeployparams=> { + description=>'The path to the Kit Deployment Parameters file.', + value_desc=>'Must be: empty string or relative path string', + mandatory=>0, + base_dir=>'other_files', + cp_to_kitconfig=>2}, # 2 = rename with KIT_KITNAME_ on cp + kitlicense=> { + description=>'The Kit license string to be built into all kitcomponent packages.', + value_desc=>'any string', + mandatory=>1, + cp_to_kitconfig=>0}, + kittarfilename=> { + description=>'The filename to use for the generated kit.', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>0}, + vendor=> { + description=>'The Vendor value to use when building the rpms.', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>0}, + packager=> { + description=>'The Packager value to use when building the rpms.', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>0}, + url=> { + description=>'The URL value to use when building the rpms.', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>0}}, + kitrepo => {kitrepoid => { + description=>'The Kit Package Repository ID. (e.g., rhels-6.2-x86_64)', + value_desc=>'Must be: Generic Name String, unique in kit', + mandatory=>1, + cp_to_kitconfig=>0}, + osbasename => { + description=>'The OS distro base name (e.g., rhels)', + value_desc=>'Must be OS Name String', + mandatory=>1, + cp_to_kitconfig=>1}, + osmajorversion => { + description=>'The OS distro major version (e.g., 6)', + value_desc=>'Must be Generic Number String', + mandatory=>1, + cp_to_kitconfig=>1}, + osminorversion => { + description=>'The OS distro minor version (e.g., 3)', + value_desc=>'Must be Generic Number String', + mandatory=>0, + cp_to_kitconfig=>1}, + osarch => { + description=>'The OS distro architecture (e.g., x86_64)', + value_desc=>'Must be OS Arch String', + mandatory=>1, + cp_to_kitconfig=>1}, + compat_osbasenames => { + description=>'Comma-separated list of compatible OS base names. ', + value_desc=>'Must be Empty String or list of OS Name Strings', + mandatory=>0, + cp_to_kitconfig=>1} }, + kitcomponent => {basename => { + description=>'The component name. It is used as the meta-package name.', + value_desc=>'any string', + mandatory=>1, + cp_to_kitconfig=>1}, + description => { + description=>'The component description. The description is added to the meta-package.', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>1}, + version => { + description=>'The component version (e.g., 9.0). It is used as the meta-package version.', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>1}, + release => { + description=>'The component release number (e.g., 1). It is used as the meta-package release number.', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>1}, + serverroles => { + description=>'tbd', + value_desc=>'any string', + mandatory=>1, + cp_to_kitconfig=>1}, + kitrepoid => { + description=>'tbd', + value_desc=>'any string', + mandatory=>1, + cp_to_kitconfig=>0}, + kitcompdeps => { + description=>'tbd', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>1}, + ospkgdeps => { + description=>'tbd', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>0}, + kitpkgdeps => { + description=>'tbd', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>1}, + non_native_pkgs => { + description=>'tbd', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>0}, + driverpacks => { + description=>'tbd', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>1}, + exlist => { + description=>'tbd', + value_desc=>'any string', + mandatory=>0, + base_dir=>'other_files', + cp_to_kitconfig=>2}, + preinstall => { + description=>'tbd', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>0}, + postinstall => { + description=>'tbd', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>0}, + preuninstall => { + description=>'tbd', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>0}, + postuninstall => { + description=>'tbd', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>0}, + preupgrade => { + description=>'tbd', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>0}, + postupgrade => { + description=>'tbd', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>0}, + postbootscripts => { + description=>'tbd', + value_desc=>'any string', + mandatory=>0, + base_dir=>'scripts', + cp_to_kitconfig=>2}, + genimage_postinstall => { + description=>'tbd', + value_desc=>'any string', + mandatory=>0, + base_dir=>'scripts', + cp_to_kitconfig=>2} }, + kitpackage => {filename => { + description=>'tbd', + value_desc=>'any string', + mandatory=>1, + cp_to_kitconfig=>0}, + kitrepoid => { + description=>'tbd', + value_desc=>'any string', + mandatory=>1, + cp_to_kitconfig=>0}, + rpm_spec => { + description=>'tbd', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>0}, + rpm_srcdir => { + description=>'tbd', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>0}, + rpm_srctarball => { + description=>'tbd', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>0}, + rpm_srpm => { + description=>'tbd', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>0}, + rpm_prebuiltdir => { + description=>'tbd', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>0}, + isexternalpkg => { + description=>'tbd', + value_desc=>'any string', + mandatory=>0, + cp_to_kitconfig=>0}} +); + + +my $args = join ' ', @ARGV; +$::command = "$0 $args"; +Getopt::Long::Configure("bundling"); +$Getopt::Long::ignorecase = 0; + +# parse the options +if ( + !GetOptions( + 'h|help' => \$::HELP, + 'v|version' => \$::VERSION, + 'V|verbose' => \$::VERBOSE, + 'n|noprerequisite' => \$::PREREQUISITE, + 'p|pkgdir=s' => \$::PKGDIR, + 'k|kitversion=s' => \$::KITVERSION, + 'r|kitrelease=s' => \$::KITRELEASE, + 'l|kitloc=s' => \$::KITLOC, + ) + ) +{ + &usage; + exit(1); +} + +# display the usage if -h or --help is specified +if ($::HELP) +{ + &usage; + exit(0); +} + +my $debianflag = 0; +my $tempstring = xCAT::BuildKitUtils->osver(); +if ( $tempstring =~ /debian/ || $tempstring =~ /ubuntu/ ){ + $debianflag = 1; +} + +# display the version statement if -v or --version is specified +if ($::VERSION) +{ + my $versioncmd = "rpm -q --qf \"%{NAME}: %{VERSION}-%{RELEASE} \n\" xCAT-buildkit"; + my $message = "Error quering xCAT-buildkit rpm. Version info is not available. \n"; + if ( $debianflag ){ + $versioncmd = "dpkg-query --show -f='\${PackageSpec}: \${Version}\n' xcat-buildkit"; + $message = "Error quering xcat-buildkit package. Version info is not available. \n"; + } + if ( system($versioncmd) ) { + # non-zero return from system call + print $message; + exit 1; + } + # add framework info to output + print "\tkitframework = $::KITFRAMEWORK\n"; + print "\tcompatible_frameworks = $::COMPATIBLE_KITFRAMEWORKS\n"; + + exit 0; +} + +my $arg=shift(@ARGV); +if ( ! $arg ) { + &usage; + exit (0); +} + +# set kit location +if ($::KITLOC) { + $::workdir = $::KITLOC; + $::current_dir = $::workdir; +} else { + $::workdir = $::current_dir; +} + +$::full_buildkit_conf = $::workdir."/".$::buildkit_conf; +$::build_dir = $::workdir."/build"; +$::deploy_dir = $::build_dir; #kitname appended by validate_bldkitconf routine +$::base_repodir = $::build_dir."/kit_repodir"; + +while ($arg) { + my $command = $arg; + $command =~ tr/A-Z/a-z/; # convert to lowercase + if ( $command eq 'create' ) { + $::KIT_CREATE=shift(@ARGV); + if ($::KITLOC) { + $::workdir = dirname($::KITLOC); + $::current_dir = $::workdir; + } + if ( ! $::KIT_CREATE ) { + print "The Kit basename was not specified for the buildkit create command.\n"; + &usage; + exit 1; + } + } elsif ( $command eq 'chkconfig' ) { + $::KIT_CHKCONFIG=1; + } elsif ( $command eq 'buildrepo' ) { + $::KIT_BUILDREPO=shift(@ARGV); + if ( ! $::KIT_BUILDREPO ) { + print "The Kit package repository name was not specified for buildkit buildrepo command.\n"; + &usage; + exit 1; + } + } elsif ( $command eq 'listrepo' ) { + $::KIT_LISTREPO=1; + } elsif ( $command eq 'cleanrepo' ) { + $::KIT_CLEANREPO=shift(@ARGV); + if ( ! $::KIT_CLEANREPO ) { + print "kit package repository name not specified for buildkit cleanrepo command \n"; + &usage; + exit 1; + } + } elsif ( $command eq 'buildtar' ) { + $::KIT_BUILDTAR=1; + } elsif ( $command eq 'cleantar' ) { + $::KIT_CLEANTAR=1; + } elsif ( $command eq 'cleanall' ) { + $::KIT_CLEANALL=1; + } elsif ( $command eq 'addpkgs' ) { + $::KIT_ADDPKGS=shift(@ARGV); + if (!($::KIT_ADDPKGS)){ + print "Missing parameter: the name must be specified when using the \'buildkit addpkgs\' command.\n"; + &usage; + exit (1); + } + if (!($::PKGDIR)){ + print "Missing option: the -p option must be specified with \'buildkit addpkgs\' command. \n"; + &usage; + exit (1); + } + } else { + print "The buildkit command $arg is not recognized.\n"; + &usage; + exit (1); + } + $arg=shift(@ARGV); +} + +my $rc = 0; +if ( $::KIT_CREATE ) { + $rc = &kit_create; +} +if ( $::KIT_CHKCONFIG ) { + unless ($rc = &kit_chkconfig) { + print "No errors were found in Kit Build File $::full_buildkit_conf. \n"; + } +} +if ( $::KIT_LISTREPO ) { + unless ($rc = &kit_chkconfig) { $rc = &kit_listrepo; } +} +if ( $::KIT_BUILDREPO ) { + unless ($rc = &kit_chkconfig) { $rc = &kit_buildrepo; } +} +if ( $::KIT_CLEANREPO ) { + unless ($rc = &kit_chkconfig) { $rc = &kit_cleanrepo; } +} +if ( $::KIT_BUILDTAR ) { + unless ($rc = &kit_chkconfig) { $rc = &kit_buildtar; } +} +if ( $::KIT_CLEANTAR ) { + unless ($rc = &kit_chkconfig) { $rc = &kit_cleantar; } +} +if ( $::KIT_CLEANALL ) { + unless ($rc = &kit_chkconfig) { $rc = &kit_cleanall; } +} +if ( $::KIT_ADDPKGS ) { $rc = &kit_addpkgs; } + +exit $rc; + +##################################### +# subroutines +##################################### + +#----------------------------------------------------------------------------- + +=head3 usage + + Displays message for -h option + +=cut + +#----------------------------------------------------------------------------- +sub usage +{ + print "Usage: + buildkit [-?│-h│--help] [-v│--version] + + To build a new Kit + + buildkit [-V│--verbose] [] [│all] + [-l│--kitloc ] + + To add packages to an existing Kit. + + buildkit [-V│--verbose] addpkgs [-p│--pkgdir ] [-k│--kitversion ] [-r│--kitrelease ] + + This tool is used to build and manage a Kit package. + The options are: + -h - Provide usage info. + -k - Kit version. + -l - Location of kit files. (Including kit name.) + -p - RPM package directory locations. + -r - Kit release. + -v - Provide the version info. + command - Several commands are supported. See the list below. + -V - Verbose mode. Outputs additional debug messages. + + Supported subcommands: + create - creates a new Kit with the specified basename + chkconfig - checks the Kit build file + listrepo - lists the Kit package repositories in the Kit + build file, and their build status + buildrepo - builds the specified Kit package repository + buildrepo all - builds all the Kit package repositories + cleanrepo - deletes the build files for the specified Kit + package repository + cleanrepo all - deletes the build files for all Kit package + repositories + buildtar - builds the Kit tarfile + cleantar - deletes the Kit deployment directory and Kit + tarfile + cleanall - equivalent to buildkit cleanrepo all and + buildkit cleantar + addpkgs -p + - add product package rpms to a shipped tarfile + named kitname.NEEDS_PRODUCT_PKGS.tar.bz2 + \n"; +} + +#----------------------------------------------------------------------------- + +=head3 kit_create + + buildkit create + +=cut + +#----------------------------------------------------------------------------- + +sub kit_create + +{ + # create Kit directory in pwd + my $kitname=$::KIT_CREATE; + my $kitdir; + if ($::KITLOC ) { + $kitdir=$::KITLOC; + } else { + $kitdir=$::workdir."/$kitname"; + } + + if ( -d $kitdir ) { + print "Another directory already exists with the name $kitdir. Not able to create new Kit. \n"; + exit 1; + } + if ( ! mkdir($kitdir) ) { + print "Error creating Kit directory $kitdir. Verify that the current user has privileges to create the directory. \n"; + exit 1; + } + + # Recursive copy the shipped template directory to the Kit directory + if ( system("cp -fRp $::XCATSHARE/kits/kit_template/* $kitdir") ) { + # non-zero return from system call + print "Error copying sample Kit template files from $::XCAT_SHARE/kits/kit_template to $kitdir \n"; + exit 1; + } + + if (&edit_bldkitconf($kitdir."/".$::buildkit_conf,$kitname)) { + exit 1; + } + + print "Kit template for $kitname created in $kitdir directory \n"; + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 kit_chkconfig + + buildkit chkconfig + +=cut + +#----------------------------------------------------------------------------- + +sub kit_chkconfig + +{ + if ( $::CHKCONFIG_DONE ) { return 0; } + my $bldkitconf = $::full_buildkit_conf; + + my $chkrc = &load_bldkitconf($bldkitconf); + if ( $chkrc != 0 ) { return 1; }; + + $chkrc = &validate_bldkitconf(); + if ( $chkrc != 0 ) { return 1; }; + + $::CHKCONFIG_DONE=1; + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 kit_buildrepo + + buildkit buildrepo + +=cut + +#----------------------------------------------------------------------------- + +sub kit_buildrepo +{ + my $rc = 0; + my $repoid = $::KIT_BUILDREPO; + + if ( !$debianflag ){ + # Check if createrepo exists or not. Fail at the beginning. + #- don't use specific path - may not be correct in build env + my $rcmd = "createrepo -h > /dev/null"; + if ( system( $rcmd ) ) { + print "Error: the createrepo command does not seem to be installed. Make sure createrepo is installed before running the buildkit command. \n"; + return 1; + } + } + + $repoid =~ s/\s+//g; + $repoid =~ tr/A-Z/a-z/; # convert to lowercase + if ( $repoid ne 'all' ) { + return &kit_buildrepo1($::KIT_BUILDREPO); + } else { + foreach my $kr (@{$::bldkit_config->{kitrepo}{entries}}) { + if ( &kit_buildrepo1($kr->{kitrepoid}) ) { return 1; } + } + } + return $rc; +} + +#----------------------------------------------------------------------------- + +=head3 kit_buildrepo1 + + + +=cut + +#----------------------------------------------------------------------------- +sub kit_buildrepo1 +{ + my $rc = 0; + my $repoid = shift; + $repoid =~ s/\s+//g; + my $repodir = $::base_repodir; + my $srcdir = $::workdir."/source_packages/"; + my $basedir = $repodir; + my $repo; + + # find the repo + my $found = 0; + foreach my $kr (@{$::bldkit_config->{kitrepo}{entries}}) { + if ( $kr->{kitrepoid} eq $repoid ) { + $found = 1; + $repo = $kr; + if ( &validate_os($kr)) { + print "The buildrepo operation will continue, but errors may occur. You may need to run this command on a host with the same OS.\n"; + } + $repodir .= "/$kr->{kitreponame}"; + last; + } + } + if (! $found) { + print "The specified Kit Package Repository \"$repoid\" does not exist in the Kit Build File. \n"; + return 1; + } + + # Create repo build directory + if ( (! -d $repodir) && (! mkpath($repodir)) ) { + print "Error creating build repository directory $repodir.\n"; + return 1; + } + + # Build kitpackages first + my $kitrepohash; + foreach my $kr (@{$::bldkit_config->{kitrepo}{entries}}) { + $kitrepohash->{$kr->{kitrepoid}} = $kr->{kitreponame}; + } + + foreach my $kp (@{$::bldkit_config->{kitpackage}{entries}}) { + # For this kitrepo? + my $found = 0; + foreach my $kprid (split(/,/, $kp->{kitrepoid})) { + $kprid =~ s/\s+//g; + if ($repoid eq $kprid) { + $found = 1; + last; + } + } + if (!$found) { next; } + + # is this package already built? + my $rpm = "$repodir/$kp->{filename}"; + if ( -r $rpm) { next; } + + my $kprid; + my $rpm_built; + foreach $kprid (split(/,/, $kp->{kitrepoid})) { + if ($repoid eq $kprid) { + next; + } + if ( (-d "$basedir/$kitrepohash->{$kprid}") and (-f "$basedir/$kitrepohash->{$kprid}/$kp->{filename}") ) { + $rpm_built = $kitrepohash->{$kprid}; + last; + } + } + + + # determine build method + if ($kp->{isexternalpkg} eq 'yes') { + if ($::VERBOSE) { print "skipping build of external kitpackage $kp->{filename} \n";} + next; + } else { + if ($::VERBOSE) { print "building kitpackage $kp->{filename} \n";} + } + if (defined($kp->{rpm_prebuiltdir})) { + # simply copy the file to the build directory + my $full_prebuiltrpm = $srcdir.$kp->{rpm_prebuiltdir}."/".$kp->{filename}; + + if ( $rpm_built ) { + if (system("cd $repodir;ln -sf ../$rpm_built/$kp->{filename} $kp->{filename}")) { + # non-zero return from system call + print "Error create symlink for prebuilt rpm $kp->{filename} to Kit Build directory. \n"; + return; + } + } else { + if (system("cp -fp $full_prebuiltrpm $repodir")) { + # non-zero return from system call + print "Error copying prebuilt rpm $kp->{filename} to Kit Build directory. \n"; + return 1; + } + } + } elsif (defined($kp->{rpm_srpm})) { + # run rpmbuild --rebuild on the source rpm + print "SKIPPING BUILD FOR KIT PACKAGE $kp->{filename} \n"; + print "TBD - only buildrepo for prebuilt rpms is available at this time \n\n"; + } elsif (defined($kp->{rpm_srctarball}) && + defined($kp->{rpm_spec}) ) { + # run rpmbuild + print "SKIPPING BUILD FOR KIT PACKAGE $kp->{filename} \n"; + print "TBD - only buildrepo for prebuilt rpms is available at this time \n\n"; + } elsif (defined($kp->{rpm_srcdir}) && + defined($kp->{rpm_spec}) ) { + # build tarfile and run rpmbuild + print "SKIPPING BUILD FOR KIT PACKAGE $kp->{filename} \n"; + print "TBD - only buildrepo for prebuilt rpms is available at this time \n\n"; + } else { + print "Cannot determine build method for Kit Package $kp->{filename}. Verify that your Kit Build File is correct. \n"; + return 1; + } + } + + # Build kitcomponent metapackages + if ( $debianflag ){ + foreach my $kc (@{$::bldkit_config->{kitcomponent}{entries}}) { + if ($repoid ne $kc->{kitrepoid}) { next; } + my $debname = "$repodir/".&comppkgname($kc); + if (-r $debname) { next; } + if ($::VERBOSE) { print "building kitcomponent metapackage for $kc->{basename} \n";} + if (&build_kitcomp_debian($kc)) { + print "Error building kitcomponent metapackage for $kc->{basename} \n"; + return 1; + } + } + if ( system("dpkg-scanpackages $repodir > $repodir/Packages") ) { + print "Error building the repository meta-data with the dpkg-scanpackages command \n"; + return 1; + } + } + else{ + foreach my $kc (@{$::bldkit_config->{kitcomponent}{entries}}) { + # Check if this kitcomponent is in the requested repo + if ($repoid ne $kc->{kitrepoid}) { next; } + + # Check if already built + my $rpm = "$repodir/".&comppkgname($kc); + if (-r $rpm) { next; } + + # Build it + if ($::VERBOSE) { print "building kitcomponent metapackage for $kc->{basename} \n";} + if (&build_kitcomp($kc)) { + print "Error building kitcomponent metapackage for $kc->{basename} \n"; + return 1; + } + } + + # run createrepo + my $cr_opts = ''; + if (( $repo->{osbasename} =~ m/rh|RH|centos|CentOS/ ) && + ( $repo->{osmajorversion} eq '5') ) { + $cr_opts = '-s md5'; + } + if ( system("createrepo $cr_opts $repodir") ) { + print "Error building the repository meta-data with the createrepo command \n"; + return 1; + } + } + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 kit_listrepo + + buildkit listrepo + +=cut + +#----------------------------------------------------------------------------- +sub kit_listrepo +{ + # print "Kit Repository: Status \n"; + foreach my $kr (@{$::bldkit_config->{kitrepo}{entries}}) { + my $rc = 0; + my $status = "NOT DONE"; + unless ($rc = &validate_repo($kr)) {$status = "DONE";} + print "$kr->{kitrepoid}: $status \n"; + } + + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 kit_cleanrepo + + buildkit cleanrepo + +=cut + +#----------------------------------------------------------------------------- +sub kit_cleanrepo +{ + my $repoid = $::KIT_CLEANREPO; + my $tmp_repoid = $repoid; + $tmp_repoid =~ tr/A-Z/a-z/; # convert to lowercase + + if (($tmp_repoid eq 'all') && + -d $::base_repodir ) { + if ( system("rm -Rf $::base_repodir ") ) { + print "Error removing contents of $::base_repodir \n"; + return 1; + } else { + print "Contents of $::base_repodir has been successfully removed. \n"; + } + } else { + my $got_one = 0; + foreach my $kr (@{$::bldkit_config->{kitrepo}{entries}}) { + if ($repoid eq $kr->{kitrepoid}) { + my $repodir = $::base_repodir.'/'.$kr->{kitreponame}; + if ( -d $repodir ){ + if ( system("rm -Rf $repodir ") ) { + print "Error removing directory $repodir \n"; + return 1; + } else { + print "Kit repository $kr->{kitrepoid} has been removed. \n"; + } + } else { + print "Kit repository $kr->{kitrepoid} directory $repodir does not exist. Nothing to remove for this repository. \n"; + } + $got_one = 1; + last; + } + } + if ( !$got_one ) { + print "Kit repository $repoid does not exist.\n"; + return 1; + } + } + if ( -d "$::workdir/rpmbuild" ) { + system("rm -Rf $::workdir/rpmbuild "); + } + if ( -d "$::workdir/tmp" ) { + system("rm -Rf $::workdir/tmp "); + } + if ( -d "$::workdir/debbuild" ){ + system("rm -Rf $::workdir/debbuild"); + } + + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 kit_buildtar + + buildkit buildtar + +=cut + +#----------------------------------------------------------------------------- +sub kit_buildtar +{ + foreach my $kr (@{$::bldkit_config->{kitrepo}{entries}}) { + if (&validate_repo($kr)) { + print "Kit Repository $kr->{kitrepoid} not built. Run: \n"; + print " buildkit buildrepo $kr->{kitrepoid} \n"; + return 1; + } + } + + if (&create_kitconf) { + print "Error creating kit configuration file \n"; + return 1; + } + + if ($::HAVE_EXTERNAL_PKG or $::HAVE_NON_NATIVE_PKGS) { + if (&create_PARTIAL_builddir) { + print "Error creating PARTIAL kit build directory contents \n"; + return 1; + } + } else { + if (&create_builddir) { + print "Error creating kit build directory contents \n"; + return 1; + } + } + + if (! -d "$::deploy_dir/repos") { + symlink "$::build_dir/kit_repodir","$::deploy_dir/repos"; + } + + # build the tarfile + my $extpkgs = ''; + if ($::HAVE_EXTERNAL_PKG or $::HAVE_NON_NATIVE_PKGS) { + $extpkgs = '.NEED_PRODUCT_PKGS'; + } + my $kitname = $::bldkit_config->{kit}{entries}[0]->{kitname}; + my $kitfilename = $kitname; + if ( defined($::bldkit_config->{kit}{entries}[0]->{kittarfilename}) ) { + $kitfilename = $::bldkit_config->{kit}{entries}[0]->{kittarfilename}; + $kitfilename =~ s/tar\.bz2\s*$//; + } + $kitfilename = $kitfilename.$extpkgs.".tar.bz2"; + + my $tarfile = $::deploy_dir."/".$kitfilename; + + my $dir = dirname($::deploy_dir); + my $bidir = "$dir/build_input"; + + if ( -d "$bidir") { + if ( system("cd $::deploy_dir; cd ..; cp -r build_input $kitname" ) ) { + print "Error: Could not copy building tarfile $tarfile \n"; + return 1; + } + } + + print "Creating tar file $tarfile.\n"; + + if ( system("cd $::deploy_dir; cd ..; tar -cjhf $tarfile $kitname/*") ) { + print "Error building tarfile $tarfile \n"; + return 1; + } + + system("mv $tarfile $::current_dir"); + print "Kit tar file $::current_dir/$kitfilename successfully built. \n"; + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 kit_cleantar + + buildkit cleantar + + Remove tar files from the kit location directory. + + This removes all tar files - not just the last one created! + + Also clean up several other files/dirs + +=cut + +#----------------------------------------------------------------------------- +sub kit_cleantar +{ + my $basename = $::bldkit_config->{kit}{entries}[0]->{basename}; + my $rmfiles = "$basename\*tar.bz2"; + + my $tarfile = "$::workdir/$rmfiles"; + + if ( $rmfiles ) { + if ( system("rm -f $tarfile ") ) { + print "Error removing kit tar files in $::workdir.\n"; + } else { + print "Kit tar files have been successfully removed from $::workdir.\n"; + } + } + + if ( -d $::deploy_dir ) { + if ( system("rm -Rf $::deploy_dir ") ) { + print "Error removing contents of $::deploy_dir \n"; + } else { + print "Removed $::deploy_dir.\n"; + } + } + if ( -d "$::workdir/rpmbuild" ) { + if ( system("rm -Rf $::workdir/rpmbuild ")) { + # print "Error removing $::workdir/rpmbuild\n"; + } else { + print "Removed $::workdir/rpmbuild\n"; + } + } + if ( -d "$::workdir/tmp" ) { + if ( system("rm -Rf $::workdir/tmp ") ) { + # print "Error removing $::workdir/tmp \n"; + } else { + print "Removed $::workdir/tmp \n"; + } + } + if ( -d "$::workdir/debbuild" ){ + if ( system("rm -Rf $::workdir/debbuild")) { + # print "Error removing $::workdir/debbuild.\n"; + } else { + print "Removed $::workdir/debbuild\n"; + } + } + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 kit_cleanall + + buildkit cleanall + +=cut + +#----------------------------------------------------------------------------- +sub kit_cleanall +{ + print "Running buildkit cleanall... \n"; + + &kit_cleantar; + + if ( -d $::build_dir ) { + if ( system("rm -Rf $::build_dir/* ") ) { + print "Error removing contents of $::build_dir \n"; + } else { + print "All $::build_dir contents have been successfully removed \n"; + } + } + if ( -d "$::workdir/rpmbuild" ) { + system("rm -Rf $::workdir/rpmbuild "); + } + if ( -d "$::workdir/tmp" ) { + system("rm -Rf $::workdir/tmp "); + } + if ( -d "$::workdir/debbuild" ){ + system("rm -Rf $::workdir/debbuild"); + } + + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 edit_bldkitconf + + edit the shipped template buildkit.conf file to insert initial values + for the new kit +=cut + +#----------------------------------------------------------------------------- +sub edit_bldkitconf +{ + my $bldkitconf = shift; + my $kitname = shift; + + # read in the buildkit.conf file + my $CF; + unless ( open( $CF, "<", $bldkitconf ) ) { + print "The Kit build file $bldkitconf does not exist. \n"; + return 1; + } + if ($::VERBOSE) { + print "Reading kit configuration file $bldkitconf \n"; + } + my @lines = <$CF>; + close $CF; + + my $osinfo = xCAT::BuildKitUtils->osver(); + my $kitrepoid = $osinfo; + $kitrepoid =~ s/\,//; + my ($osbasename,$osmore) = split(/\,/, $osinfo); + my ($osmajorversion,$osminorversion) = split(/\./, $osmore); + my $osarch=`uname -p`; + my $kitcomponent_basename = $kitname."_compute"; + + for (@lines) { + s/<<>>/$kitname/; + s/<<>>/$kitrepoid/; + s/<<>>/$osbasename/; + s/<<>>/$osmajorversion/; + s/<<>>/$osminorversion/; + s/<<>>/$osarch/; + s/<<>>/$kitcomponent_basename/; + if ($debianflag){ + s/(filename=.*?)\-(.*)\.noarch\.rpm/$1_$2_all.deb/; + } + } + + # Write the buildkit.conf back out + my $NCF; + unless ( open( $NCF, ">$bldkitconf" ) ) { + return 1; + } + if ($::VERBOSE) { + print "Inserted initial values into $bldkitconf \n"; + } + print $NCF @lines; + close($NCF); + + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 load_bldkitconf + + load the kitbuild.conf file into a global data structure and + verify that the general syntax is correct. + +=cut + +#----------------------------------------------------------------------------- +sub load_bldkitconf +{ + my $bldkitconf = shift; + + # read in the buildkit.conf file + my $CF; + unless ( open( $CF, "<", $bldkitconf ) ) { + print "The Kit build file $bldkitconf does not exist in the current directory. \n"; + return 1; + } + if ($::VERBOSE) { + print "Reading kit configuration file $bldkitconf \n"; + } + my @lines = <$CF>; + close $CF; + + my $current_section = 'no section'; + my %current_entry; + my $syntax_error = ''; + my $bad_line = ''; + my $line_number = 0; + foreach my $l (@lines) { + $line_number++; + # skip blank and comment lines + next if ( $l =~ /^\s*$/ || $l =~ /^\s*#/ ); + + # process a real line + # new section? + if ( $l =~ /^\s*(\w+)\s*:/ ) { + my $section = $1; + if ( defined( $::buildkit_def{$section} ) ) { + if (($section eq 'kit') && + ($::bldkit_config->{$section}{'exists'})) { + $syntax_error = "More than one \"$section:\" section exists "; + $bad_line = $l; + last; + } + $::bldkit_config->{$section}{'exists'} = 1; + push ( @{ $::bldkit_config->{$current_section}{'entries'} }, {%current_entry}); + $current_section = $section; + undef %current_entry; + next; + } + } + if ( $l =~ /^\s*(\w+)\s*=\s*(.*)\s*/ ) { + my $attr = $1; + my $val = $2; + my $orig_attr = $attr; + my $orig_val = $val; + $attr =~ s/^\s*//; # Remove any leading whitespace + $attr =~ s/\s*$//; # Remove any trailing whitespace + $attr =~ tr/A-Z/a-z/; # Convert to lowercase + $val =~ s/^\s*//; + $val =~ s/\s*$//; + + if ( defined( $::buildkit_def{$current_section}{$attr} ) ) { + if ( $val ne '') { $current_entry{$attr} = $val; } + } else { + if ( $current_section eq 'no section' ) { + $syntax_error = "No section specified for attribute $attr."; + } else { + my $valid_attrs = join (', ', (keys (%{$::buildkit_def{$current_section}}))); + $syntax_error = "Attribute \"$attr\" is not valid for section \"$current_section\". Valid attributes are: $valid_attrs.\n"; + } + $bad_line = $l; + last; + } + + } else { + $syntax_error = "Invalid line format"; + $bad_line = $l; + last; + + } + } + + # Need at least one kit and one kitrepo section + if (! $syntax_error) { + if ( !($::bldkit_config->{'kit'}{'exists'})) { + $syntax_error = "No \"kit:\" section found. At least one section required. "; + $bad_line = ''; + } elsif ( !($::bldkit_config->{'kitrepo'}{'exists'})) { + $syntax_error = "No \"kitrepo:\" section found. At least one section required. "; + $bad_line = ''; + } else { + push ( @{ $::bldkit_config->{$current_section}{'entries'} }, {%current_entry}); + } + } + + if ($syntax_error) { + print "Error processing file $bldkitconf \n"; + print "Syntax error found on line $line_number:\n"; + print "$bad_line \n"; + print "$syntax_error \n"; + print "\n"; + print "The Kit build file does not have the correct format. \n"; + print "The format should be: \n"; + print "
: \n"; + print " = \n"; + print " = \n"; + print " ... \n"; + print "
: \n"; + print " = \n"; + print " = \n"; + print " ... \n"; + print "The valid section names are: kit, kitrepo, kitcomponent, kitpackages. \n"; + print "There must be exactly one kit, and must be at least one kitrepo section. \n"; + return 1; + } + + # Check for mandatory attributes + foreach my $s (keys %{$::bldkit_config}) { + if (! defined($::buildkit_def{$s}) ) { next;} + foreach my $se (@{$::bldkit_config->{$s}{entries}}) { + foreach my $a (keys %{$::buildkit_def{$s}}) { + if (( $::buildkit_def{$s}{$a}->{mandatory} ) && + ( ! defined ($se->{$a}) ) ) { + print "The \"$a\" mandatory attribute must be defined in the \"$s\" section of the Kit build file \n"; + return 1; + } + } + } + } + +#use Data::Dumper; +#print Dumper($::bldkit_config); + + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 validate_bldkitconf + + validate the loaded buildkit configuration data + +=cut + +#----------------------------------------------------------------------------- +sub validate_bldkitconf +{ + my $kitname = $::bldkit_config->{kit}{entries}[0]->{basename}; + my $full_kitname = $kitname; + $full_kitname .= '-'.$::bldkit_config->{kit}{entries}[0]->{version}; + if (defined($::bldkit_config->{kit}{entries}[0]->{release})) { + $full_kitname .= '-'.$::bldkit_config->{kit}{entries}[0]->{release}; + } + my $short_kitname = $full_kitname; + if (defined($::bldkit_config->{kit}{entries}[0]->{osbasename})) { + $full_kitname .= '-'.$::bldkit_config->{kit}{entries}[0]->{osbasename}; + } + if (defined($::bldkit_config->{kit}{entries}[0]->{osmajorversion})) { + if ( ! defined($::bldkit_config->{kit}{entries}[0]->{osbasename})) { + print "Error: Kit osmajorversion attribute was specified but Kit osbasename was not set. \n"; + return 1; + } + $full_kitname .= '-'.$::bldkit_config->{kit}{entries}[0]->{osmajorversion}; + } + if (defined($::bldkit_config->{kit}{entries}[0]->{osminorversion})) { + if ( ( ! defined($::bldkit_config->{kit}{entries}[0]->{osbasename})) || + ( ! defined($::bldkit_config->{kit}{entries}[0]->{osmajorversion}))) { + print "Error: Kit osminorversion attribute was specified but either Kit osbasename or Kit osmajorversion were not set. \n"; + return 1; + } + $full_kitname .= '-'.$::bldkit_config->{kit}{entries}[0]->{osminorversion}; + } + if (defined($::bldkit_config->{kit}{entries}[0]->{osarch})) { + $full_kitname .= '-'.$::bldkit_config->{kit}{entries}[0]->{osarch}; + } + $::bldkit_config->{kit}{entries}[0]->{kitname} = $full_kitname; + $::deploy_dir .= "/".$full_kitname; + + # Make sure each kit kitdeployparams file exists + if (defined($::bldkit_config->{kit}{entries}[0]->{kitdeployparams})){ + my $kd_file = $::workdir."/other_files/".$::bldkit_config->{kit}{entries}[0]->{kitdeployparams}; + if (! -r $kd_file ) { + print "Kit Deployment Parameters file $kd_file does not exist or is not readable\n"; + return 1; + } + if (&edit_deployparams($kd_file,1)) { return 1;} + } + + # Make sure each kitrepo has unique distro info + my $kr_count = scalar @{$::bldkit_config->{kitrepo}{entries}}; + if ($kr_count > 1) { + foreach my $kri (0..$kr_count-2) { + foreach my $kri2 ($kri+1..$kr_count-1) { + my $kr = $::bldkit_config->{kitrepo}{entries}[$kri]; + my $kr2 = $::bldkit_config->{kitrepo}{entries}[$kri2]; + if ( $kr->{kitrepoid} eq $kr2->{kitrepoid} ) { + print "There are two or more kitrepo sections with the same kitrepoid \"$kr->{kitrepoid}\". \n"; + return 1; + } + if ( ($kr->{osbasename} eq $kr2->{osbasename}) && + ($kr->{osmajorversion} eq $kr2->{osmajorversion}) && + ($kr->{osarch} eq $kr2->{osarch}) ) { + if( ( defined ($kr->{osminorversion}) && + defined ($kr2->{osminorversion}) && + ($kr->{osminorversion} eq $kr2->{osminorversion}) ) || + ( ! defined ($kr->{osminorversion}) && + ! defined ($kr2->{osminorversion}) ) ) { + print "There are two or more kitrepo sections which are defined with the same OS name, major/minor version, and architecture. \n"; + return 1; + } + } + } + } + } + + # Kitcomponent version/release are now optional - + # default to kit version/release + foreach my $kc (@{$::bldkit_config->{kitcomponent}{entries}}) { + if (! defined($kc->{version})) { + $kc->{version} = $::bldkit_config->{kit}{entries}[0]->{version}; + } + if (! defined($kc->{release})) { + if (! defined($::bldkit_config->{kit}{entries}[0]->{release})) { + print "Kitcomponent $kc->{basename} does not have a release specified and there is no Kit release value set to use as a default. \n"; + return 1; + } else { + $kc->{release} = $::bldkit_config->{kit}{entries}[0]->{release}; + } + } + + } + + # Make sure each kitcomponent has unique basename/repoid + # If same basename, make sure version/release are same, too + my $kc_count = scalar @{$::bldkit_config->{kitcomponent}{entries}}; + if ($kc_count > 1) { + foreach my $kci (0..$kc_count-2) { + foreach my $kci2 ($kci+1..$kc_count-1) { + if ( $::bldkit_config->{kitcomponent}{entries}[$kci]->{basename} + eq $::bldkit_config->{kitcomponent}{entries}[$kci2]->{basename} ) { + if ( $::bldkit_config->{kitcomponent}{entries}[$kci]->{kitrepoid} + eq $::bldkit_config->{kitcomponent}{entries}[$kci2]->{kitrepoid} ) { + + print "Two or more kitcomponents are defined with the same basename \"$::bldkit_config->{kitcomponent}{entries}[$kci]->{basename}\" and the same repoid \"$::bldkit_config->{kitcomponent}{entries}[$kci]->{kitrepoid}\". \n"; + return 1; + } + if ( ($::bldkit_config->{kitcomponent}{entries}[$kci]->{version} + ne $::bldkit_config->{kitcomponent}{entries}[$kci2]->{version}) || + ($::bldkit_config->{kitcomponent}{entries}[$kci]->{release} + ne $::bldkit_config->{kitcomponent}{entries}[$kci2]->{release}) + ) { + print "Two or more kitcomponents are defined with the same basename \"$::bldkit_config->{kitcomponent}{entries}[$kci]->{basename}\" but with different version or release. \n"; + return 1; + } + } + } + } + } + + # Kitrepo checks + foreach my $kr (@{$::bldkit_config->{kitrepo}{entries}}) { + my $reponame = $short_kitname; + if ((defined($::bldkit_config->{kit}{entries}[0]->{osbasename})) && + ($::bldkit_config->{kit}{entries}[0]->{osbasename} ne + $kr->{osbasename} ) ) { + print "Warning: Kit osbasename is set to \"$::bldkit_config->{kit}{entries}[0]->{osbasename}\", but this does not match kitrepo $kr->{kitrepoid} osbasename \"$kr->{osbasename}\". Processing will continue, but verify that you do not have an error in your buildkit configuration file. \n"; + } + $reponame .= '-'.$kr->{osbasename}; + if ( (defined($::bldkit_config->{kit}{entries}[0]->{osmajorversion})) && + ($::bldkit_config->{kit}{entries}[0]->{osmajorversion} ne + $kr->{osmajorversion} ) ) { + print "Warning: Kit osmajorversion is set to \"$::bldkit_config->{kit}{entries}[0]->{osmajorversion}\", but this does not match kitrepo $kr->{kitrepoid} osmajorversion \"$kr->{osmajorversion}\". Processing will continue, but verify that you do not have an error in your buildkit configuration file. \n"; + } + $reponame .= '-'.$kr->{osmajorversion}; + if (defined($kr->{osminorversion})){ + if ( (defined($::bldkit_config->{kit}{entries}[0]->{osminorversion})) && + ($::bldkit_config->{kit}{entries}[0]->{osminorversion} ne + $kr->{osminorversion} ) ) { + print "Warning: Kit osminorversion is set to \"$::bldkit_config->{kit}{entries}[0]->{osminorversion}\", but this does not match kitrepo $kr->{kitrepoid} osminorversion \"$kr->{osminorversion}\". Processing will continue, but verify that you do not have an error in your buildkit configuration file. \n"; + } + $reponame .= '.'.$kr->{osminorversion}; + } + if ( (defined($::bldkit_config->{kit}{entries}[0]->{osarch})) && + ($::bldkit_config->{kit}{entries}[0]->{osarch} ne + $kr->{osarch} ) ) { + print "Warning: Kit osarch is set to \"$::bldkit_config->{kit}{entries}[0]->{osarch}\", but this does not match kitrepo $kr->{kitrepoid} osarch \"$kr->{osarch}\". Processing will continue, but verify that you do not have an error in your buildkit configuration file. \n"; + } + $reponame .= '-'.$kr->{osarch}; + $kr->{kitreponame} = $reponame; + } + + # Kitcomponent checks + foreach my $kc (@{$::bldkit_config->{kitcomponent}{entries}}) { + # Make sure all kitcomponent kitrepoids are defined + my $found = 0; + my %repo; + if ($debianflag){ + if ($kc->{basename} =~ /_/){ + print "Kit Component basename can not contain underscore.\n"; + return 1; + } + } + foreach my $kr (@{$::bldkit_config->{kitrepo}{entries}}) { + if ($kc->{kitrepoid} eq $kr->{kitrepoid}) { + $found = 1; + %repo = %{$kr}; + $kc->{kitreponame} = $kr->{kitreponame}; + push (@{$kr->{packages}}, &comppkgname($kc,$kr)); + last; + } + } + if ( ! $found ) { + print "Kit Repository \"$kc->{kitrepoid}\" required by the Kit Component \"$kc->{basename}\" not defined in the Kit Build file.\n"; + return 1; + } + # Create full kitcomponent name + my $compname = $kc->{basename}; + $compname .= '-'.$kc->{version}; + $compname .= '-'.$kc->{release}; + $compname .= '-'.$repo{osbasename}; + $compname .= '-'.$repo{osmajorversion}; + if ( defined($repo{osminorversion}) ) { + $compname .= '.'.$repo{osminorversion}; + } + $compname .= '-'.$repo{osarch}; + $kc->{kitcompname} = $compname; + # Make sure all kitcomponent kitpkgdeps are defined + if (defined($kc->{kitpkgdeps})) { + foreach my $d (split(/,/, $kc->{kitpkgdeps})) { + $d =~ s/\s+//g; + $d =~ s/^([\w\.\-]+)[<>=]*.*$/$1/; + my $found = 0; + foreach my $kp (@{$::bldkit_config->{kitpackage}{entries}}) { + if ( $kp->{filename} =~ /^$d[\.\-]?/ ) { + foreach my $kprid (split(/,/, $kp->{kitrepoid})) { + $kprid =~ s/\s+//g; + if ($kc->{kitrepoid} eq $kprid) { + $found = 1; + last; + } + } + } + if ($found) { last; } + } + if ( !$found ) { + print "Kit Package \"$d\" required by the Kit Component \"$kc->{basename}\" was not found in the Kit Component\'s repository \"$kc->{kitrepoid}\".\n"; + return 1; + } + } + } + # Make sure all kitcomponent driverpacks are defined + if (defined($kc->{driverpacks})) { + my @drvs = split(/,/, $kc->{driverpacks}); + foreach my $d (@drvs) { + $d =~ s/\s+//g; + my $found = 0; + foreach my $kp (@{$::bldkit_config->{kitpackage}{entries}}) { + if ( $kp->{filename} eq $d ) { + foreach my $kprid (split(/,/, $kp->{kitrepoid})) { + $kprid =~ s/\s+//g; + if ($kc->{kitrepoid} eq $kprid) { + $found = 1; + last; + } + } + } + if ($found) { last; } + } + if ( !$found ) { + print "Driver package \"$d\" required by the Kit Component \"$kc->{basename}\" was not found in the Kit Component\'s repository \"$kc->{kitrepoid}\".\n"; + return 1; + } + } + } + # Make sure files exist + if (defined($kc->{exlist})){ + my $ck_file = $::workdir."/other_files/".$kc->{exlist}; + if (! -r $ck_file ) { + print "Exclude List file $ck_file defined in Kit Componenet \"$kc->{basename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kc->{preinstall})){ + my $ck_file = $::workdir."/scripts/".$kc->{preinstall}; + if (! -r $ck_file ) { + print "Pre-Install script $ck_file defined in Kit Componenet \"$kc->{basename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kc->{postinstall})){ + my $ck_file = $::workdir."/scripts/".$kc->{postinstall}; + if (! -r $ck_file ) { + print "Post-Install script $ck_file defined in Kit Componenet \"$kc->{basename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kc->{preuninstall})){ + my $ck_file = $::workdir."/scripts/".$kc->{preuninstall}; + if (! -r $ck_file ) { + print "Pre-Uninstall script $ck_file defined in Kit Componenet \"$kc->{basename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kc->{postuninstall})){ + my $ck_file = $::workdir."/scripts/".$kc->{postuninstall}; + if (! -r $ck_file ) { + print "Post-Uninstall script $ck_file defined in Kit Componenet \"$kc->{basename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kc->{preupgrade})){ + my $ck_file = $::workdir."/scripts/".$kc->{preupgrade}; + if (! -r $ck_file ) { + print "Pre-Upgrade script $ck_file defined in Kit Componenet \"$kc->{basename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kc->{postupgrade})){ + my $ck_file = $::workdir."/scripts/".$kc->{postupgrade}; + if (! -r $ck_file ) { + print "Post-Upgrade script $ck_file defined in Kit Componenet \"$kc->{basename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kc->{genimage_postinstall})){ + foreach my $script (split(/\,/, $kc->{genimage_postinstall})){ + $script =~ s/\s+//g; + my $ck_file = $::workdir."/scripts/".$script; + if (! -r $ck_file ) { + print "genimage_postinstall script $ck_file defined in Kit Componenet \"$kc->{basename}\" does not exist or is not readable\n"; + return 1; + } + } + } + if (defined($kc->{postbootscripts})){ + foreach my $script (split(/\,/, $kc->{postbootscripts})){ + $script =~ s/\s+//g; + my $ck_file = $::workdir."/scripts/".$script; + if (! -r $ck_file ) { + print "Postboot script $ck_file defined in Kit Componenet \"$kc->{basename}\" does not exist or is not readable\n"; + return 1; + } + } + } + if (defined($kc->{non_native_pkgs})){ + if ($kc->{non_native_pkgs} =~ /EXTERNALPKGS/) { + $::NON_NATIVE_PKGS->{$kc->{kitcompname}} = 1; + $::HAVE_NON_NATIVE_PKGS = 1; + } + } + } + + # Kitpackage checks + foreach my $kp (@{$::bldkit_config->{kitpackage}{entries}}) { + # determine if valid build method + if ( (defined($kp->{isexternalpkg})) || + (defined($kp->{rpm_prebuiltdir})) ) { + if ((defined($kp->{rpm_srpm})) || + (defined($kp->{rpm_srctarball})) || + (defined($kp->{rpm_spec})) || + (defined($kp->{rpm_srcdir})) ) { + print "Cannot determine build method for Kit Package $kp->{filename}. Conflicting attributes were specified.\n"; + return 1; + } + if ( !(defined($kp->{isexternalpkg})) ) { $kp->{isexternalpkg} = 'no'; } + my $orig_isext = $kp->{isexternalpkg}; + $kp->{isexternalpkg} =~ s/\s+//g; + $kp->{isexternalpkg} =~ tr/A-Z/a-z/; # convert to lowercase + if ( $kp->{isexternalpkg} eq '0' ) { $kp->{isexternalpkg} = 'no'; } + if ( $kp->{isexternalpkg} eq '1' ) { $kp->{isexternalpkg} = 'yes'; } + if ( ( $kp->{isexternalpkg} ne 'yes' ) && + ( $kp->{isexternalpkg} ne 'no' ) ) { + print "Error in definition for Kit Package $kp->{filename}. Invalid attribute value \'isexternalpkg=$orig_isext\'. Valid values are \'no\'|\'0\' or \'yes\'|\'1\'.\n"; + return 1; + } + if ( ( $kp->{isexternalpkg} eq 'yes' ) ) { + $::HAVE_EXTERNAL_PKG=1; + } + if ( ( $kp->{isexternalpkg} eq 'yes' ) && + (defined($kp->{rpm_prebuiltdir})) ) { + print "Error in definition for Kit Package $kp->{filename}. Do not specify \'isexternalpkg=$orig_isext\' with 'rpm_prebuiltdir'.\n"; + return 1; + } + } elsif (defined($kp->{rpm_srpm})) { + if ((defined($kp->{rpm_prebuiltdir})) || + (defined($kp->{rpm_srctarball})) || + (defined($kp->{rpm_spec})) || + (defined($kp->{rpm_srcdir})) ) { + print "Cannot determine build method for Kit Package $kp->{filename}. Conflicting attributes were specified.\n"; + return 1; + } + } elsif (defined($kp->{rpm_srctarball}) && + defined($kp->{rpm_spec}) ) { + if ((defined($kp->{rpm_prebuiltdir})) || + (defined($kp->{rpm_srpm})) || + (defined($kp->{rpm_srcdir})) ) { + print "Cannot determine build method for Kit Package $kp->{filename}. Conflicting attributes were specified.\n"; + return 1; + } + } elsif (defined($kp->{rpm_srcdir}) && + defined($kp->{rpm_spec}) ) { + if ((defined($kp->{rpm_prebuiltdir})) || + (defined($kp->{rpm_srpm})) || + (defined($kp->{rpm_srctarball})) ) { + print "Cannot determine build method for Kit Package $kp->{filename}. Conflicting attributes were specified.\n"; + return 1; + } + } else { + print "Cannot determine build method for Kit Package $kp->{filename}. Verify that your Kit Build File is correct. \n"; + return 1; + } + # Make sure all kitpackage kitrepoids are defined + foreach my $kprid (split(/,/, $kp->{kitrepoid})) { + my $found = 0; + $kprid =~ s/\s+//g; + foreach my $kr (@{$::bldkit_config->{kitrepo}{entries}}) { + if ($kprid eq $kr->{kitrepoid}) { + $found = 1; + $kp->{kitreponame}.=",".$kr->{kitreponame}; + if ( !( $kp->{isexternalpkg} eq 'yes' ) ) { + push (@{$kr->{packages}}, $kp->{filename}); + } + last; + } + } + if ( ! $found ) { + print "Kit Repository \"$kprid\" required by the Kit Package \"$kp->{filename}\" is not defined in the Kit Build file.\n"; + return 1; + } + } + $kp->{kitreponame} =~ s/^,//; + if (!$::NEW_PARTIAL_KIT) { + # Make sure files exist + if (defined($kp->{rpm_spec})){ + my $ck_file = $::workdir."/source_packages/".$kp->{rpm_spec}; + if (! -r $ck_file ) { + print "RPM spec file $ck_file defined in Kit Package \"$kp->{filename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kp->{rpm_srcdir})){ + my $ck_dir = $::workdir."/source_packages/".$kp->{rpm_srcdir}; + if (! -d $ck_dir ) { + print "RPM source directory $ck_dir defined in Kit Package \"$kp->{filename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kp->{rpm_srctarball})){ + my $ck_file = $::workdir."/source_packages/".$kp->{rpm_srctarball}; + if (! -r $ck_file ) { + print "RPM source tarfile $ck_file defined in Kit Package \"$kp->{filename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kp->{rpm_srpm})){ + my $ck_file = $::workdir."/source_packages/".$kp->{rpm_srpm}; + if (! -r $ck_file ) { + print "Source RPM $ck_file defined in Kit Package \"$kp->{filename}\" does not exist or is not readable\n"; + return 1; + } + } + if (defined($kp->{rpm_prebuiltdir})){ + my $ck_dir = $::workdir."/source_packages/".$kp->{rpm_prebuiltdir}; + if (! -d $ck_dir ) { + print "Pre-built RPM directory $ck_dir defined in Kit Package \"$kp->{filename}\" does not exist or is not readable\n"; + return 1; + } + my $ck_file = $ck_dir."/".$kp->{filename}; + if ( system("ls $ck_file > /dev/null") ) { +# if (! -r $ck_file ) { + print "Pre-built rpm $ck_file defined in Kit Package \"$kp->{filename}\" does not exist or is not readable\n"; + return 1; + } + } + } + } +#use Data::Dumper; +#print Dumper($::bldkit_config->{kitrepo}); + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 comppkgname + + build a metapkg rpm filename for this kitcomponent + input: kitcomponent hash + kitrepo hash that this kitcomponent belongs to + +=cut + +#----------------------------------------------------------------------------- +sub comppkgname +{ + my $comp = shift; + + my $pkgname = $comp->{basename}; + if ($debianflag) { + $pkgname .= '_'.$comp->{version}; + $pkgname .= '-'.$comp->{release}; + $pkgname .= '_all.deb'; + } + else{ + $pkgname .= '-'.$comp->{version}; + $pkgname .= '-'.$comp->{release}; + $pkgname .= '.noarch.rpm'; + } + return $pkgname; +} + +#----------------------------------------------------------------------------- + +=head3 validate_repo + + validate whether a kit repo has been built + input: repo hash + returns rc: + 0 - repo status is DONE + 1 - repo status is NOT DONE + verbose mode displays message for first rpm not built + +=cut + +#----------------------------------------------------------------------------- +sub validate_repo +{ + my $repo = shift; + + my $repodir = $::base_repodir."/".$repo->{kitreponame}; + if ( ! -d $repodir ) { + if ($::VERBOSE) { + print "\n$repodir does not exist. No rpms have been built for this kitrepo. \n"; + } + return 1; + } + + # Make sure each repo pkg exists + foreach my $pkg (@{$repo->{packages}}){ + # skip check for kit component meta rpm if it includes + # external non-native pkgs + my $skip_check = 0; + foreach my $kc (@{$::bldkit_config->{kitcomponent}{entries}}) { + if ($repo->{kitrepoid} eq $kc->{kitrepoid}) { + my $kitpkgname = comppkgname($kc); + if (($kitpkgname eq $pkg) && + ($::NON_NATIVE_PKGS->{$kc->{kitcompname}}) ) { + $skip_check = 1; + last; + } + } + } + if ( ! $skip_check ) { + my $pkg_filename = $repodir.'/'.$pkg; + if ( system("ls $pkg_filename > /dev/null") ) { + if ($::VERBOSE) { + print "\nFile $pkg in directory $repodir does not exist or is not readable. \n"; + } + return 1; + } + } + } + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 validate_os + + validate whether a kit repo matches the current OS + input: repo hash + returns rc: + 0 - match + 1 - no match + verbose mode displays message for mismatch details + +=cut + +#----------------------------------------------------------------------------- +sub validate_os +{ + my $repo = shift; + + my $osinfo = xCAT::BuildKitUtils->osver(); + my ($osbasename,$osmore) = split(/\,/, $osinfo); + my ($osmajorversion,$osminorversion) = split(/\./, $osmore); + my $osarch=`uname -p`; + chomp($osarch); + $osinfo =~ s/\,//; + my $repo_osinfo = "$repo->{osbasename}$repo->{osmajorversion}"; + if (defined($repo->{osminorversion})){ + $repo_osinfo .= ".$repo->{osminorversion}"; + } + $repo_osinfo .= "-$repo->{osarch} "; + my $mismatch_msg = "The local host is running $osinfo-$osarch. This does not match the Kit Repository \"$repo->{kitrepoid}\" data: $repo_osinfo"; + if (defined($repo->{compat_osbasenames})){ + $mismatch_msg .= " or the compatible OS distros: $repo->{compat_osbasenames} "; + } + + + my $compat_match = 0; + if ($repo->{osbasename} ne $osbasename) { + if (defined($repo->{compat_osbasenames})){ + foreach my $cos (split(/,/, $repo->{compat_osbasenames})) { + if ($cos eq $osbasename) { + $compat_match = 1; + last; + } + } + } + if (!$compat_match) { + print "$mismatch_msg \n"; + if ($::VERBOSE) { + print "\n Local OS basename $osbasename does not match repository.\n"; + } + return 1; + } + } + if ( ($repo->{osmajorversion} ne $osmajorversion) && + (!$compat_match) ) { + print "$mismatch_msg \n"; + if ($::VERBOSE) { + print "\n Local OS major version $osmajorversion does not match repository.\n"; + } + return 1; + } + if (defined($repo->{osminorversion})) { + if ( ($repo->{osminorversion} ne $osminorversion) && + (!$compat_match) ) { + print "$mismatch_msg \n"; + if ($::VERBOSE) { + print "\n Local OS minor version $osminorversion does not match repository.\n"; + } + return 1; + } + } + if ($repo->{osarch} ne $osarch) { + print "$mismatch_msg \n"; + if ($::VERBOSE) { + print "\n Local OS arch $osarch does not match repository.\n"; + } + return 1; + } + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 build_kitcomp + + build a metapkg rpm for this kitcomponent + input: kitcomponent hash + +=cut + +#----------------------------------------------------------------------------- +sub build_kitcomp +{ + my $comp = shift; + my %repo; + my $rpmbuild_dir = $::workdir."/rpmbuild"; + my $tmpdir = $::workdir."/tmp/$comp->{kitcompname}"; + my $kcmetaname = comppkgname($comp); + + # If this kitcomponent has external non-native pkgs, + # skip the meta rpm build + if ( defined($::NON_NATIVE_PKGS) && + defined($::NON_NATIVE_PKGS->{$comp->{kitcompname}}) && + $::NON_NATIVE_PKGS->{$comp->{kitcompname}} ) { + if ($::VERBOSE) { + print "Kit component $comp->{kitcompname} has external non-native packages. Skipping rpm build for $kcmetaname. \n"; + } + return 0; + } + + # find the kitrepo hash for this component + foreach my $kr (@{$::bldkit_config->{kitrepo}{entries}}) { + if ($comp->{kitrepoid} eq $kr->{kitrepoid}) { + %repo = %{$kr}; + last; + } + } + my $repodir = $::base_repodir."/".$repo{kitreponame}; + + # Fix the kitpkgdeps value for this kitcomponent + # For any kitpkgdep that has an rpm file in the repo, + # specifically reference it's version-release + if ( &update_kitcomp_kitpkgdeps($comp,$repodir) ) { return 1; } + + $::VALID_PRER_COMPONENT = 0; + + if ( !$::PREREQUISITE ) { + if ( $comp->{ospkgdeps} || $comp->{preinstall} || $comp->{preupgrade} || $comp->{preuninstall} ) { + if ( &gen_kitcomp_spec($comp,\%repo, 'PREREQUISITE') ) { return 1; } + + # run the rpmbuild command + my $curdir = $::workdir; + my $cmd = "rm -Rf $curdir/rpmbuild"; + system($cmd); + my $avoiderr = $rpmbuild_dir."/BUILDROOT/prep_".$comp->{basename}; + $avoiderr .= "-$comp->{version}-$comp->{release}.$repo{osarch}"; + mkpath($avoiderr); + $avoiderr = $rpmbuild_dir."/BUILD/"; + mkpath($avoiderr); + $avoiderr = $rpmbuild_dir."/SRPMS/"; + mkpath($avoiderr); + $avoiderr = $rpmbuild_dir."/RPMS/noarch/"; + mkpath($avoiderr); + + # Read the kit component prerequisite rpm name + + my $specfile = $::workdir."/tmp/$comp->{kitcompname}-prep.spec"; + my $rpmbuild_cmd = "rpmbuild --define \"_topdir $rpmbuild_dir\" -ba $specfile"; + + # don't want debug info - 3845 +# if (!$::VERBOSE) { + $rpmbuild_cmd .= ' --quiet '; +# } + if ( system($rpmbuild_cmd) ) { + print "Error running rpmbuild command for kit component $comp->{kitcompname} meta package\n"; + return 1; + } + my @built_rpms = `find $rpmbuild_dir/RPMS -name "*.rpm"`; + foreach my $rpm (@built_rpms) { + chomp($rpm); + if ( system ("cp -fp $rpm $repodir") ) { + print "Error copying rpm $rpm to build repo directory $repodir \n"; + return 1; + } + } + + $::VALID_PRER_COMPONENT = 1; + + } + + if ( &gen_kitcomp_spec($comp,\%repo, 'METARPM') ) { return 1; } + } else { + # Create spec file for this kit component + if ( &gen_kitcomp_spec($comp,\%repo, 'ALL') ) { return 1; } + } + + # run the rpmbuild command + my $curdir = $::workdir; + my $cmd = "rm -Rf $curdir/rpmbuild"; + system($cmd); + my $avoiderr = $rpmbuild_dir."/BUILDROOT/".$comp->{basename}; + $avoiderr .= "-$comp->{version}-$comp->{release}.$repo{osarch}"; + mkpath($avoiderr); + $avoiderr = $rpmbuild_dir."/BUILD/"; + mkpath($avoiderr); + $avoiderr = $rpmbuild_dir."/SRPMS/"; + mkpath($avoiderr); + $avoiderr = $rpmbuild_dir."/RPMS/noarch/"; + mkpath($avoiderr); + + # Read the kit component meta rpm name + + my $specfile = $::workdir."/tmp/$comp->{kitcompname}.spec"; + my $rpmbuild_cmd = "rpmbuild --define \"_topdir $rpmbuild_dir\" -ba $specfile"; + + # Copy in any non-native packages + if (defined($comp->{non_native_pkgs}) ) { + mkpath($tmpdir); + mkpath("$rpmbuild_dir/SOURCES"); + my $sourcedir = $::workdir."/source_packages"; + + foreach my $pkgfile (split(/,/, $comp->{non_native_pkgs})) { + my $pkg_file; + my ($key,$value) = split /:/,$pkgfile; + if ("$key" =~ /EXTERNALPKGS/) { + $pkg_file = $value; + } else { + $pkg_file = $key; + } + + $cmd = "cp -p $sourcedir/$pkg_file $tmpdir"; + if ( system($cmd) ) { + print "Error copying non-native package file $sourcedir/$pkg_file to $tmpdir\n"; + return 1; + } + } + $cmd = "cd $tmpdir/..;mv $comp->{kitcompname} $comp->{basename}; tar -czf $rpmbuild_dir/SOURCES/$comp->{basename}.tar.gz $comp->{basename};mv $comp->{basename} $comp->{kitcompname}"; + if ( system($cmd) ) { + print "Error creating tarfile $rpmbuild_dir/SOURCES/$comp->{kitreponame}-$comp->{kitcompname}.tar from $sourcedir/*"; + return 1; + } + } + + # - don't want debug info - 3845 +# if (!$::VERBOSE) { + $rpmbuild_cmd .= ' --quiet '; +# } + + if ( system($rpmbuild_cmd) ) { + print "Error running rpmbuild command for kit component $comp->{kitcompname} meta package\n"; + return 1; + } + my @built_rpms = `find $rpmbuild_dir/RPMS -name "*.rpm"`; + foreach my $rpm (@built_rpms) { + chomp($rpm); + if ( system ("cp -fp $rpm $repodir") ) { + print "Error copying rpm $rpm to build repo directory $repodir \n"; + return 1; + } + } + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 update_kitcomp_kitpkgdeps + + Update the kitcomponent kitpkgdeps string + For any kitpkgdep that does not explicitly specify a version-release + comparison string and for which an rpm exists in the repo, + query the rpm for its version-release info and set an explicit + comparison string. + Reason we need to do all this: We need to force yum/zypper to update + the product rpms. A simple package name in the kitcomponent meta rpm + REQUIRES entry will not cause the product to get updated if an older + version is already installed. Need to explicitly require this version + and release of the product package. + input: kitcomponent hash + kitrepo directory + +=cut + +#----------------------------------------------------------------------------- +sub update_kitcomp_kitpkgdeps +{ + my $comp = shift; + my $repodir = shift; + + if (defined($comp->{kitpkgdeps})) { + # we have some rpms listed in buildkit.conf file + my $new_kitpkgdeps = ''; + foreach my $d (split(/,/, $comp->{kitpkgdeps})) { + $d =~ s/\s+//g; + my $d_short = $d; + # strip off everything after ">=" + $d_short =~ s/^([\w\.\-]+)[<>=]*.*$/$1/; + + # if they are the same then there was no v/r info provided + if ( $d_short eq $d ) { + # no version-release comparisons specified for this kitpkgdep + # do we have this rpm file? + # get a list of any matches + my $lscmd = "cd $repodir; /bin/ls $d-\[0-9\]\*.rpm 2>/dev/null"; + my @rpmlist = `$lscmd`; + + if ( scalar(@rpmlist) == 0) { + next; + } + + # get the newest version there is + my $newestrpm = xCAT::BuildKitUtils->get_latest_version($repodir, \@rpmlist); + + if (!$newestrpm) { + print "Error: Could not determine the latest version of rpm $d contained in $repodir. \n"; + next; + } + + # get the Version and release values for this rpm + my $cmd = "rpm -q --qf \"%{NAME} >= %{VERSION}-%{RELEASE}\" -p $repodir/$newestrpm 2>/dev/null"; + if ($::VERBOSE) { + print "running rpm query to get version-release info: \n $cmd \n"; + } + + my $new_d = `$cmd`; + if (!$new_d) { + print "Error: Could not determine the latest version of rpm $d. \n"; + next; + } + + chomp($new_d); + if ($::VERBOSE) { + print "output: \n \'$new_d\' \n"; + } + if ( $new_d ne '' ) { + $new_kitpkgdeps .= "$new_d,"; + } else { + $new_kitpkgdeps .= "$d,"; + } + } else { + $new_kitpkgdeps .= "$d,"; + } + } + + $new_kitpkgdeps =~ s/(\,)*$//; + $comp->{kitpkgdeps} = $new_kitpkgdeps; + } + + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 gen_kitcomp_spec + + generate the rpm spec file for the kitcomponent metapkg rpm + input: kitcomponent hash + kitrepo hash + +=cut + +#----------------------------------------------------------------------------- +sub gen_kitcomp_spec +{ + my $comp = shift; + my $repo = shift; + my $level = shift; + my $scriptdir = $::workdir."/scripts/"; + my $tmpdir = $::workdir."/tmp/"; + + # read in the template spec file + my $spec_template = $::XCATSHARE."/kits/kitcomponent.spec.template"; + my $SF; + unless ( open( $SF, "<", $spec_template ) ) { + print "Error attempting to open the xCAT Kit Component template file $spec_template. \n"; + return 1; + } + if ($::VERBOSE) { + print "Reading the xCAT Kit Component template file $spec_template. \n"; + } + my @lines = <$SF>; + close $SF; + + my $kitname = $::bldkit_config->{kit}{entries}[0]->{basename}; + my $kitcompname = $comp->{kitcompname}; + + my ($prescript,$postscript,$preupscript,$postupscript,$preunscript,$postunscript,$nonnativepkgs,$sourcetar,$setup,$files) = ' '; + if ( $level eq 'PREREQUISITE' || $level eq 'ALL' ) { + if (defined($comp->{preinstall})) { + $prescript = &load_script("$scriptdir$comp->{preinstall}"); + $prescript = "if [ \"\$1\" = \"1\" ] ; then\n" . $prescript . "\nfi";} + if (defined($comp->{preupgrade})) { + $preupscript = &load_script("$scriptdir$comp->{preupgrade}"); + $preupscript = "if [ \"\$1\" = \"2\" ] ; then\n" . $preupscript . "\nfi";} + if (defined($comp->{preuninstall})) { + $preunscript = &load_script("$scriptdir$comp->{preuninstall}"); } + } + if ( $level eq 'METARPM' || $level eq 'ALL' ) { + if (defined($comp->{postinstall})) { + $postscript = &load_script("$scriptdir$comp->{postinstall}"); + $postscript = "if [ \"\$1\" = \"1\" ] ; then\n" . $postscript . "\nfi"; } + if (defined($comp->{postupgrade})) { + $postupscript = &load_script("$scriptdir$comp->{postupgrade}"); + $postupscript = "if [ \"\$1\" = \"2\" ] ; then\n" . $postupscript . "\nfi";} + if (defined($comp->{postuninstall})) { + $postunscript = &load_script("$scriptdir$comp->{postuninstall}"); } + if (defined($comp->{non_native_pkgs})) { + $nonnativepkgs = "\n"; + $nonnativepkgs .= "mkdir -p \$RPM_BUILD_ROOT/opt/xcat/kits/$kitname/$kitcompname \n"; + $nonnativepkgs .= "cp -a * \$RPM_BUILD_ROOT/opt/xcat/kits/$kitname/$kitcompname \n"; + $sourcetar = "Source: $comp->{basename}.tar.gz"; + $setup = "\%setup -q -n $comp->{basename}"; + $files = "/opt/xcat/kits"; + } + } + + # remove lines that correspond to optional tags that have no values + # in this instance. Adding lines to the spec file that have + # no values will cause a build error. + my @newlines; + foreach my $l (@lines) { + chomp; + # don't add vendor,packager,url to spec file unless we have a value + if ($l =~ /INSERT_vendor_HERE/) { + if (!$::bldkit_config->{kit}{entries}[0]->{vendor} ) { + next; + } + } + if ($l =~ /INSERT_packager_HERE/) { + if (!$::bldkit_config->{kit}{entries}[0]->{packager} ) { + next; + } + } + if ($l =~ /INSERT_url_HERE/) { + if (!$::bldkit_config->{kit}{entries}[0]->{url}) { + next; + } + } + push @newlines, $l; + } + @lines=@newlines; + + if ( $level eq 'ALL' ) { + for (@lines) { + chomp; + s/<<>>/$kitname/; + s/<<>>/$comp->{basename}/; + s/<<>>/$comp->{version}/; + s/<<>>/$comp->{release}/; + s/<<>>/$::bldkit_config->{kit}{entries}[0]->{kitlicense}/; + s/<<>>/$::bldkit_config->{kit}{entries}[0]->{vendor}/; + s/<<>>/$::bldkit_config->{kit}{entries}[0]->{packager}/; + s/<<>>/$::bldkit_config->{kit}{entries}[0]->{url}/; + s/<<>>/$comp->{ospkgdeps}/; + s/<<>>/$comp->{kitpkgdeps}/; + s/<<>>/$comp->{kitcompdeps}/; + s/<<>>/$comp->{description}/; + s/<<>>/$nonnativepkgs/; + s/<<>>/$sourcetar/; + s/<<>>/$setup/; + s/<<>>/$files/; + s/<<>>/$prescript/; + s/<<>>/$postscript/; + s/<<>>/$preupscript/; + s/<<>>/$postupscript/; + s/<<>>/$preunscript/; + s/<<>>/$postunscript/; + } + } elsif ( $level eq 'PREREQUISITE' ) { + for (@lines) { + chomp; + s/<<>>/$kitname/; + s/<<>>/prep_$comp->{basename}/; + s/<<>>/$comp->{version}/; + s/<<>>/$comp->{release}/; + s/<<>>/$::bldkit_config->{kit}{entries}[0]->{kitlicense}/; + s/<<>>/$::bldkit_config->{kit}{entries}[0]->{vendor}/; + s/<<>>/$::bldkit_config->{kit}{entries}[0]->{packager}/; + s/<<>>/$::bldkit_config->{kit}{entries}[0]->{url}/; + s/<<>>/$comp->{ospkgdeps}/; + s/<<>>//; + s/<<>>//; + s/<<>>/$comp->{description}/; + s/<<>>//; + s/<<>>//; + s/<<>>//; + s/<<>>//; + s/<<>>/$prescript/; + s/<<>>//; + s/<<>>/$preupscript/; + s/<<>>//; + s/<<>>/$preunscript/; + s/<<>>//; + } + + } elsif ( $level eq 'METARPM' ) { + for (@lines) { + chomp; + s/<<>>/$kitname/; + s/<<>>/$comp->{basename}/; + s/<<>>/$comp->{version}/; + s/<<>>/$comp->{release}/; + s/<<>>/$::bldkit_config->{kit}{entries}[0]->{kitlicense}/; + s/<<>>/$::bldkit_config->{kit}{entries}[0]->{vendor}/; + s/<<>>/$::bldkit_config->{kit}{entries}[0]->{packager}/; + s/<<>>/$::bldkit_config->{kit}{entries}[0]->{url}/; + s/<<>>//; + s/<<>>/$comp->{kitpkgdeps}/; + #Update kitcompdeps for prep_ + if ( $::VALID_PRER_COMPONENT ) { + s/<<>>/$comp->{kitcompdeps},prep_$comp->{basename}/; + } else { + s/<<>>/$comp->{kitcompdeps}/; + } + s/<<>>/$comp->{description}/; + s/<<>>/$nonnativepkgs/; + s/<<>>/$sourcetar/; + s/<<>>/$setup/; + s/<<>>/$files/; + s/<<>>//; + s/<<>>/$postscript/; + s/<<>>//; + s/<<>>/$postupscript/; + s/<<>>//; + s/<<>>/$postunscript/; + } + } + + # Write the generated spec file + mkpath($tmpdir); + + my $fn; + my $NSF; + if ( $level eq 'PREREQUISITE' ) { + $fn = $comp->{kitcompname}."-prep.spec" + } else { + $fn = $comp->{kitcompname}.".spec" + } + unless ( open( $NSF, ">$tmpdir$fn" ) ) { + return 1; + } + if ($::VERBOSE) { + print "Created kitcomponent spec file \'$tmpdir$fn\'\n"; + + } + foreach my $line (@lines) { + print $NSF $line,"\n"; + } + + close($NSF); + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 build_kitcomp_debian + + + +=cut + +#----------------------------------------------------------------------------- +sub build_kitcomp_debian{ + my $comp = shift; + my %repo; + my $debbuilddir = $::workdir."/debbuild/".$comp->{kitcompname}; + my $kcmetaname = comppkgname($comp); + + #If this kitcomponent has external non-native pkgs, + #skip the meta package build + if ( defined($::NON_NATIVE_PKGS) && + defined($::NON_NATIVE_PKGS->{$comp->{kitcompname}}) && + $::NON_NATIVE_PKGS->{$comp->{kitcompname}} ) { + if ($::VERBOSE) { + print "Kit component $comp->{kitcompname} has external non-native packages. Skipping rpm build for $kcmetaname. \n"; + } + return 0; + } + # find the kitrepo hash for this component + foreach my $kr (@{$::bldkit_config->{kitrepo}{entries}}) { + if ($comp->{kitrepoid} eq $kr->{kitrepoid}) { + %repo = %{$kr}; + last; + } + } + + #run the dpkg-buildpackage command + my $curdir = $::workdir; + my $cmd = "rm -Rf $debbuilddir"; + system($cmd); + mkpath($debbuilddir); + + #Create debian directory for this kit component + if ( &gen_kitcomp_debdir($comp,\%repo) ) { return 1; } + + if (defined($comp->{non_native_pkgs}) ) { + my $sourcedir = $::workdir."/source_packages"; + + foreach my $pkgfile (split(/,/, $comp->{non_native_pkgs})) { + my $pkg_file; + my ($key,$value) = split /:/,$pkgfile; + if ("$key" =~ /EXTERNALPKGS/) { + $pkg_file = $value; + } else { + $pkg_file = $key; + } + + $cmd = "cp -p $sourcedir/$pkg_file $debbuilddir"; + if ( system($cmd) ) { + print "Error copying non-native package file $sourcedir/$pkg_file to debbuilddir\n"; + return 1; + } + } + } + my $compversion = $comp->{version} . "-" . $comp->{release}; + my $buildstring = "Kit component build package."; + my $debianbuildcmd = "cd $debbuilddir;dch -v $compversion -b -c debian/changelog $buildstring;dpkg-buildpackage -uc -us"; + if ( !$::NON_NATIVE_PKGS->{$comp->{kitcompname}} ) { + if ( system($debianbuildcmd) ) { + print "Error running \"dpkg-buildpackage -uc -us\" command for kit component $comp->{kitcompname} meta package\n"; + return 1; + } + my $repodir = $::base_repodir."/".$repo{kitreponame}; + my @builtdebs = `find $::workdir/debbuild -maxdepth 1 -name "*.deb"`; + foreach my $deb (@builtdebs) { + chomp($deb); + if ( system ("cp -fp $deb $repodir") ) { + print "Error copying package $deb to build repo directory $repodir \n"; + return 1; + } + } + } + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 gen_kitcomp_debdir + + + +=cut + +#----------------------------------------------------------------------------- +sub gen_kitcomp_debdir{ + my $comp = shift; + my $repo = shift; + my $scriptdir = $::workdir."/scripts/"; + my $combuilddir = $::workdir."/debbuild/".$comp->{kitcompname}; + + #copy the debian dir template to the build path + mkpath("$combuilddir/debian"); + my $cmd = "cp -Rf " . $::XCATSHARE . "/kits/debian_template/* $combuilddir/debian/"; + system($cmd); + + my $kitname = $::bldkit_config->{kit}{entries}[0]->{basename}; + my $kitcompname = $comp->{kitcompname}; + my $upgradeflag = $comp->{basename} . ".tmp"; + + my ($prescript,$postscript,$preupscript,$postupscript,$preunscript,$postunscript,$nonnativepkgs) = ''; + if (defined($comp->{preinstall})) { + $prescript = &load_script("$scriptdir$comp->{preinstall}"); + } + if (defined($comp->{postinstall})) { + $postscript = &load_script("$scriptdir$comp->{postinstall}"); + } + if (defined($comp->{preupgrade})) { + $preupscript = &load_script("$scriptdir$comp->{preupgrade}"); + } + if (defined($comp->{postupgrade})) { + $postupscript = &load_script("$scriptdir$comp->{postupgrade}"); + } + if (defined($comp->{preuninstall})) { + $preunscript = &load_script("$scriptdir$comp->{preuninstall}"); + } + if (defined($comp->{postuninstall})) { + $postunscript = &load_script("$scriptdir$comp->{postuninstall}"); + } + if (defined($comp->{non_native_pkgs})) { + $nonnativepkgs = "\n"; + $nonnativepkgs .= "mkdir -p \$RPM_BUILD_ROOT/opt/xcat/kits/$kitname/$kitcompname \n"; + $nonnativepkgs .= "cp -a * \$RPM_BUILD_ROOT/opt/xcat/kits/$kitname/$kitcompname \n"; + } + + #replace all special sub string in all files under debian + unless (opendir(DH, "${combuilddir}/debian/")){ + print "Can not open the xCAT Kit Component debian dir: ${combuilddir}/debian/"; + return 1; + } + + foreach (readdir(DH)){ + my $file = "${combuilddir}/debian/$_"; + if ( -d $file){ + next; + } + + unless ( open ( FH, "<", $file )){ + print "Error attempting to open the xCAT Kit Component ${kitcompname}'s debian template file $file.\n"; + close(DH); + return 1; + } + + if ($::VERBOSE){ + print "Reading the xCAT Kit Component ${kitcompname}'s debian template file $file. \n"; + } + my @lines = ; + close(FH); + for(@lines) { + chomp; + s/<<>>/$comp->{basename}/; + s/<<>>/$comp->{ospkgdeps}/; + s/<<>>/$comp->{kitpkgdeps}/; + s/<<>>/$comp->{kitcompdeps}/; + s/<<>>/$comp->{description}/; + s/<<>>/$upgradeflag/; + s/<<>>/$prescript/; + s/<<>>/$postscript/; + s/<<>>/$preupscript/; + s/<<>>/$postupscript/; + s/<<>>/$preunscript/; + s/<<>>/$postunscript/; + } + my $joined_lines = join("\n", @lines); + @lines = split(/\\n/,$joined_lines); + + open (FH, ">", $file); + if ($::VERBOSE){ + print "Created kitcomponent ${kitcompname}'s build file under debian dir $file"; + } + print FH @lines; + close(FH); + } + closedir(DH); + + if (defined($comp->{non_native_pkgs})) { + unless (open (FH, ">", "${combuilddir}/debian/dir")) { + print "Error attempting to open the xCAT Kit Component ${kitcompname}'s debian file dir.\n"; + return 1; + } + print FH "opt/xcat/kits/$kitname/$kitcompname/"; + close (FH); + + unless ( open (FH, ">", "${combuilddir}/debian/install") ){ + print "Error attempting to open the xCAT Kit Component ${kitcompname}'s debian file dir.\n"; + return 1; + } + foreach my $pkgfile (split(/,/, $comp->{non_native_pkgs})) { + my $pkgname = ''; + my ($key,$value) = split /:/,$pkgfile; + if ("$key" =~ /EXTERNALPKGS/) { + $pkgname = $value; + } else { + $pkgname = $key; + } + print FH "$pkgname opt/xcat/kits/$kitname/$kitcompname/ \n"; + } + close(FH); + } + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 load_script + + load a kitcomponent script into a single return string + with imbedded newline chars + input: fullpath of scriptname + +=cut + +#----------------------------------------------------------------------------- +sub load_script +{ + my $scriptname = shift; + my $SF; + unless ( open( $SF, "<", $scriptname ) ) { + print "Error attempting to open the file $scriptname. \n"; + return; + } + if ($::VERBOSE) { + print "Reading the file $scriptname. \n"; + } + my @lines = <$SF>; + close $SF; + + my $script_contents = join('', @lines); + return $script_contents; +} + +#----------------------------------------------------------------------------- + +=head3 create_kitconf + + Create the kit configuration file to put into the kit tar file. + +=cut + +#----------------------------------------------------------------------------- +sub create_kitconf +{ + # Build kit config file entries from buildkit config input + my $kitname = $::bldkit_config->{kit}{entries}[0]->{kitname}; + foreach my $s (keys %{$::bldkit_config}) { + if (! defined($::buildkit_def{$s}) ) { next;} + if ( $s eq 'kitpackage' ) { next; } + my $li = 0; + foreach my $se (@{$::bldkit_config->{$s}{entries}}) { + $::kit_config->{$s}{entries}[$li]->{kitname} = $kitname; + # copy all defined attrs over + foreach my $a (keys %{$::buildkit_def{$s}}) { + if (( $::buildkit_def{$s}{$a}->{cp_to_kitconfig} eq '1' ) && + ( defined ($se->{$a}) ) ) { + if ( $s eq 'kitcomponent' ) { + if ($a eq 'kitpkgdeps') { + my $value; + foreach my $d (split(/,/, $se->{$a})) { + $d =~ s/\s+//g; + $d =~ s/^([\w\.\-]+)[<>=]*.*$/$1/; + $value .= "$d,"; + } + $value =~ s/(\,)*$//; + $se->{$a} = $value; + } + } + $::kit_config->{$s}{entries}[$li]->{$a} = $se->{$a}; + } + # cp_to_kitconfig=2 means copy the file to the new kit + # but only do the copy if this is a final kit build + if (( $::buildkit_def{$s}{$a}->{cp_to_kitconfig} eq '2' ) && + ( defined ($se->{$a}) ) && + !$::HAVE_EXTERNAL_PKG && !$::HAVE_NON_NATIVE_PKGS ) { + my $prefix = "$kitname"; + if ( $s eq 'kitcomponent' ) { + $prefix = "$::bldkit_config->{$s}{entries}[$li]->{kitcompname}"; + if (($a eq 'postbootscripts') || + ($a eq 'genimage_postinstall')) { + $prefix = "KIT_".$prefix; + } + if ( !($::kit_config->{$s}{entries}[$li]->{$a} = + &cp_to_builddir($a,$se->{$a},$::workdir.'/'.$::buildkit_def{$s}{$a}->{base_dir},$prefix, $::bldkit_config->{$s}{entries}[$li])) ) { + return 1; + } + } else { + if ( !($::kit_config->{$s}{entries}[$li]->{$a} = + &cp_to_builddir($a,$se->{$a},$::workdir.'/'.$::buildkit_def{$s}{$a}->{base_dir},$prefix)) ) { + return 1; + } + } + } + } + # Handle special attrs, these 3 attributes did not defined in the buildkit.conf, special cases. + if ( $s eq 'kitrepo' ) { + $::kit_config->{$s}{entries}[$li]->{kitreponame} = + $se->{kitreponame}; + } elsif ( $s eq 'kitcomponent' ) { + $::kit_config->{$s}{entries}[$li]->{kitcompname} = + $se->{kitcompname}; + $::kit_config->{$s}{entries}[$li]->{kitreponame} = + $se->{kitreponame}; + if ( !$::PREREQUISITE and ($se->{ospkgdeps} || $se->{preinstall} || $se->{preupgrade} || $se->{preuninstall}) ) { + $::kit_config->{$s}{entries}[$li]->{prerequisite} = + "prep_" . $se->{basename}; + } + } + $li++; + } + } + + # Handle external packages + if ($::HAVE_EXTERNAL_PKG) { + foreach my $kp (@{$::bldkit_config->{kitpackage}{entries}}) { + if ($kp->{isexternalpkg} eq 'yes') { + my %current_entry; + $current_entry{filename} = $kp->{filename}; + $current_entry{kitreponame} = $kp->{kitreponame}; + push ( @{ $::kit_config->{EXTERNALPKG}{'entries'} }, {%current_entry}); + } + } + } + + + # Handle non_native_pkgs + foreach my $kc (@{$::bldkit_config->{kitcomponent}{entries}}) { + if ($::NON_NATIVE_PKGS->{$kc->{kitcompname}}) { + my @nativefiles; + foreach my $pkgfile (split(/,/, $kc->{non_native_pkgs})) { + my ($key,$value) = split /:/,$pkgfile; + if ("$key" =~ /EXTERNALPKGS/) { + push (@nativefiles, $value); + } + } + + my %current_entry; + $current_entry{filename} = join ',', @nativefiles; + $current_entry{kitcompname} = $kc->{kitcompname}; + $current_entry{basename} = $kc->{basename}; + $current_entry{kitreponame} = $kc->{kitreponame}; + push ( @{ $::kit_config->{NONNATIVEPKGS}{'entries'} }, {%current_entry}); + } + } + + + # Write Kit Config File + my @lines; + my $li=0; + $lines[$li++] = "# Kit Configuration File for $kitname generated by buildkit\n"; + $lines[$li++] = "kitbuildinfo: \n"; + my $xCAT_buildkit_version = ''; + if ( $debianflag ){ + $xCAT_buildkit_version = `dpkg-query --show -f='\${Version}' xcat-buildkit`; + } + else{ + $xCAT_buildkit_version = `rpm -q --qf \"%{VERSION}-%{RELEASE}\" xCAT-buildkit`; + } + $lines[$li++] = " xCAT_version = $xCAT_buildkit_version \n"; + $lines[$li++] = " build_date = ".localtime()."\n"; + $lines[$li++] = " kitframework = $::KITFRAMEWORK \n"; + $lines[$li++] = " compatible_kitframeworks = $::COMPATIBLE_KITFRAMEWORKS \n"; + + foreach my $s ('kit','kitrepo','kitcomponent','EXTERNALPKG', 'NONNATIVEPKGS') { + foreach my $se (@{$::kit_config->{$s}{entries}}) { + $lines[$li++] = "$s: \n"; + foreach my $a (keys %{$se}) { + $lines[$li++] = " $a = $se->{$a} \n"; + } + } + } + + if ( (! -d $::deploy_dir) && (! mkpath($::deploy_dir)) ) { + print "Error creating build directory $::deploy_dir.\n"; + return; + } + + my $full_kit_conf = $::deploy_dir."/".$::kit_conf; + my $NCF; + unless ( open( $NCF, ">$full_kit_conf" ) ) { + return 1; + } + if ($::VERBOSE) { + print "Wrote new kit configuration file $full_kit_conf \n"; + } + print $NCF @lines; + close($NCF); + + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 cp_to_builddir + + Copy specified files into the build directory renaming as indicated + and substituting strings if needed + +=cut + +#----------------------------------------------------------------------------- +sub cp_to_builddir +{ + my $type = shift; + my $files = shift; + my $from_dir = shift; + my $prefix = shift; + my $kitcomp = shift; + + my $copied_files; + my $other_files = $::deploy_dir."/other_files"; + if ( (! -d $other_files) && (! mkpath($other_files)) ) { + print "Error creating build directory $other_files.\n"; + return; + } + foreach my $file (split(/\,/, $files)) { + $file =~ s/\s+//g; + my $from_file = $from_dir."/".$file; + my $from_file_base = basename($file); + my $to_file_base = $prefix."_".$from_file_base; + my $to_file = $other_files."/".$to_file_base; + + # Read in the file + my $FF; + unless ( open( $FF, "<", $from_file ) ) { + print "The Kit file $from_file could not be read. \n"; + return 1; + } + my @lines = <$FF>; + for (@lines) { + s/<<>>/$::bldkit_config->{kit}{entries}[0]->{kitname}/g; + s/<<>>/$::bldkit_config->{kit}{entries}[0]->{basename}/g; + s/<<>>/$::bldkit_config->{kit}{entries}[0]->{version}/g; + s/<<>>/$::bldkit_config->{kit}{entries}[0]->{release}/g; + if ( defined ($kitcomp) ) { + s/<<>>/$kitcomp->{kitcompname}/g; + s/<<>>/$kitcomp->{basename}/g; + s/<<>>/$kitcomp->{version}/g; + s/<<>>/$kitcomp->{release}/g; + } + } + # Write the file back out + my $TF; + unless ( open( $TF, ">$to_file" ) ) { + print "Error copying file $from_file to build directory $other_files \n"; + return 1; + } + if ($::VERBOSE) { + print "Copied $from_file to $to_file replacing kit and kitcomponent strings as needed. \n"; + } + print $TF @lines; + close($TF); + + $copied_files .= ",$to_file_base"; + + if (($type eq 'postbootscripts') || + ($type eq 'genimage_postinstall')) { + system("chmod 755 $to_file"); + } + } + $copied_files =~ s/^\,//; + return $copied_files; +} + +#----------------------------------------------------------------------------- + +=head3 create_builddir + + Create the build directory and copy in all required files for building + the kit tar file. + +=cut + +#----------------------------------------------------------------------------- +sub create_builddir +{ + my $kitname = $::bldkit_config->{kit}{entries}[0]->{kitname}; + + # Note: + # - repos already created and validated + # - kit.conf file already created + # - exlists, postbootscripts, and deployparams already copied + + # copy plugins to build dir and edit to insert correct plugin and kit names + my $plugin_dir = $::deploy_dir."/plugins"; + if ( -d "$::workdir/plugins" ) { + if ( (! -d $plugin_dir) && (! mkpath($plugin_dir)) ) { + print "Error creating build directory $plugin_dir.\n"; + return 1; + } + + foreach my $plugin (<$::workdir/plugins/*.pm>){ + my $plugin_base = basename($plugin); + my $mod_kitname = $kitname; + $mod_kitname =~ s/\-/\_/g; + $mod_kitname =~ s/\./\_/g; + my $to_plugin = $plugin_dir."/".$mod_kitname."_".$plugin_base; + + if ( system("cp -fp $plugin $to_plugin") ) { + # non-zero return from system call + print "Error copying plugin file $plugin to build directory $plugin_dir \n"; + return 1; + } + if (&edit_plugin($to_plugin)) { return 1;} + } + } + + # copy docs to build dir + if ( -d "$::workdir/docs" ) { + if ( system("cp -fRp $::workdir/docs $::deploy_dir") ) { + # non-zero return from system call + print "Error copying doc files $::workdir/docs to build directory $::deploy_dir \n"; + return 1; + } + } + + # Edit deploy params file to make sure correct format for xCAT + if (defined($::kit_config->{kit}{entries}[0]->{kitdeployparams})){ + my $kd_file = $::deploy_dir."/other_files/".$::kit_config->{kit}{entries}[0]->{kitdeployparams}; + if (&edit_deployparams($kd_file)) { return 1;} + } + + if ($::HAVE_EXTERNAL_PKG or $::HAVE_NON_NATIVE_PKGS) { + # Copy the kitcomponent meta rpm spec if there is external non_native_pkgs. + if ( $debianflag ) { + foreach my $comp (keys %{$::NON_NATIVE_PKGS}) { + my $kitrepo; + foreach my $kc (@{$::bldkit_config->{kitcomponent}{entries}}) { + if ($comp eq $kc->{kitcompname}) { + $kitrepo = $kc->{kitreponame} + } + } + mkpath("$::deploy_dir/tmp/"); + my $cmd = "cp -fRP $::workdir/debbuild/$comp $::deploy_dir/tmp/$comp"; + if ( system("$cmd") ) { + print "Error copying kitcomponent meta debian build file $::workdir/debbuild/$comp to build directory $::deploy_dir \n"; + return 1; + } + } + } + + # Copy over the original buildkit.conf file and input files + # to help make addpkgs processing easier later + mkpath("$::deploy_dir/build_input/"); + if ( system("cp -fp $::full_buildkit_conf $::deploy_dir/build_input") ) { + # non-zero return from system call + print "Error copying buildkit config file $::full_buildkit_conf to build directory $::deploy_dir/build_input \n"; + return 1; + } + } + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 create_PARTIAL_builddir + + Create the build directory for a PARTIAL kit (needs external pkgs) + and copy in all required files for building the kit tar file. + This includes most build input without editting files since + they will need to be generated at addpkgs time. + +=cut + +#----------------------------------------------------------------------------- +sub create_PARTIAL_builddir +{ + my $kitname = $::bldkit_config->{kit}{entries}[0]->{kitname}; + + # Note: + # - repos already created and validated + # - kit.conf file already created + # - exlists, postbootscripts, and deployparams already copied + + # copy docs to build dir + if ( -d "$::workdir/docs" ) { + if ( system("cp -fRp $::workdir/docs $::deploy_dir") ) { + # non-zero return from system call + print "Error copying doc files $::workdir/docs to build directory $::deploy_dir \n"; + return 1; + } + } + + # Copy over the original buildkit.conf file and input files + # to help make addpkgs processing easier later + mkpath("$::deploy_dir/build_input/"); + if ( system("cp -fp $::full_buildkit_conf $::deploy_dir/build_input") ) { + # non-zero return from system call + print "Error copying buildkit config file $::full_buildkit_conf to build directory $::deploy_dir/build_input \n"; + return 1; + } + if ( -d "$::workdir/other_files" ) { + if ( system("cp -fpR $::workdir/other_files $::deploy_dir/build_input") ) { + # non-zero return from system call + print "Error copying $::workdir/otherfiles to build directory $::deploy_dir/build_input \n"; + return 1; + } + } + if ( -d "$::workdir/plugins" ) { + if ( system("cp -fpR $::workdir/plugins $::deploy_dir/build_input") ) { + # non-zero return from system call + print "Error copying $::workdir/plugins to build directory $::deploy_dir/build_input \n"; + return 1; + } + } + if ( -d "$::workdir/scripts" ) { + if ( system("cp -fpR $::workdir/scripts $::deploy_dir/build_input") ) { + # non-zero return from system call + print "Error copying $::workdir/scripts to build directory $::deploy_dir/build_input \n"; + return 1; + } + } + # Copy over any provided non-native packages + my $to_source_dir = "$::deploy_dir/build_input/source_packages"; + mkpath("$to_source_dir"); + foreach my $kc (@{$::bldkit_config->{kitcomponent}{entries}}) { + if (defined($kc->{non_native_pkgs}) ) { + my $sourcedir = $::workdir."/source_packages"; + foreach my $pkgfile (split(/,/, $kc->{non_native_pkgs})) { + my $pkg_file; + my ($key,$value) = split /:/,$pkgfile; + if ("$key" =~ /EXTERNALPKGS/) { + next; + } else { + $pkg_file = $key; + } + + my $cmd = "cp -p $sourcedir/$pkg_file $to_source_dir"; + if ( system($cmd) ) { + print "Error copying non-native package file $sourcedir/$pkg_file to $to_source_dir \n"; + return 1; + } + } + } + } + + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 edit_deployparams + + Edit the kit deployment parameters to make sure it has correct + syntax for xCAT otherpkglist support + + +=cut + +#----------------------------------------------------------------------------- +sub edit_deployparams +{ + my $file = shift; + my $validate_only = shift; + + # read in the file + my $DF; + unless ( open( $DF, "<", $file ) ) { + print "The Kit deployment parameters file $file could not be read. \n"; + return 1; + } + my @lines = <$DF>; + close $DF; + + # Edit the files + my $changed = 0; + my @new_lines; + my $ln = 0; + foreach my $l (@lines) { + $ln++; + # skip blank lines + if ( $l =~ /^\s*$/ ) { + push (@new_lines, $l); + next; + } + # #ENV lines + $l =~ s/^\s+//; # compress leading blanks + if ( $l =~ /^\#ENV\:/ ) { + if ( !($l =~ /\#\s*$/) ) { + chomp $l; + $l .= "#\n"; + $changed = 1; + } + push (@new_lines, $l); + next; + } + # skip all other comments + if ( $l =~ /^\s*#/ ) { + push (@new_lines, $l); + next; + } + # Add #ENV if not specified + if ( $l =~ /^\w*\s*\=/ ) { + chomp $l; + $l = "#ENV: $l #"; + $changed = 1; + push (@new_lines, $l); + next; + } + # Syntax error + print "Syntax error in kit deployment parameters file $file \n"; + print "line $ln: \n"; + print "$l \n"; + return 1; + } + + # Write the file back out + if ($changed && !$validate_only) { + my $NDF; + unless ( open( $NDF, ">$file" ) ) { + return 1; + } + if ($::VERBOSE) { + print "Editted kit deployment parameters file $file \n"; + } + print $NDF @lines; + close($NDF); + } + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 edit_plugin + + Edit the kit plugin file to insert the full kit name + + +=cut + +#----------------------------------------------------------------------------- +sub edit_plugin +{ + my $file = shift; + my $kitname = $::bldkit_config->{kit}{entries}[0]->{kitname}; + # convert dashes to underscore since the kitname is used as perl pkg names + # in the plugin and this causes perl syntax errors + my $mod_kitname = $kitname; + $mod_kitname =~ s/\-/\_/g; + $mod_kitname =~ s/\./\_/g; + + # read in the file + my $PF; + unless ( open( $PF, "<", $file ) ) { + print "The Kit plugin file $file could not be read. \n"; + return 1; + } + my @lines = <$PF>; + close $PF; + + for (@lines) { + s/<<>>/$kitname/g; + s/<<>>/$mod_kitname/g; + } + + # Write the plugin back out + my $NPF; + unless ( open( $NPF, ">$file" ) ) { + return 1; + } + if ($::VERBOSE) { + print "Inserted kitname values into $file \n"; + } + print $NPF @lines; + close($NPF); + + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 kit_addpkgs + + buildkit addpkgs + +=cut + +#----------------------------------------------------------------------------- +sub kit_addpkgs +{ + # add RPM pkgs to an existing kit tarfile + my $kittarfile=$::KIT_ADDPKGS; + my $kitbfname = basename($kittarfile); + $kitbfname =~ s/.tar.bz2$//; + $kitbfname =~ s/.NEED_PRODUCT_PKGS$//; + my $tmpdir_base = "/tmp/$kitbfname"; + + # - could be list of pkgdir s + my @pkgdirlist = split(",", $::PKGDIR); + + # Cleanup - should have been removed when last command ran + # - but just in case + system ("rm -Rf $tmpdir_base"); + + # the tar file may not be in the current dir + $kittarfile = "$::workdir/$kittarfile"; + + if ( !(-r $kittarfile) ) { + print "The Kit tar file $kittarfile could not be read. \n"; + return 1; + } + $kittarfile = abs_path($kittarfile); + + foreach my $rpmdir (@pkgdirlist) { + if ( !(-d $rpmdir) ) { + print "The package directory $rpmdir could not be read. \n"; + return 1; + } + } + + # Create work directory + if ( (! -d $tmpdir_base) && (! mkpath($tmpdir_base)) ) { + print "Error creating temporary work directory $tmpdir_base\n"; + return 1; + } + + print "Extracting tar file $kittarfile. Please wait.\n"; + + if ( system("cd $tmpdir_base; tar -jxf $kittarfile ") ) { + print "Error extracting tarfile $kittarfile \n"; + # Cleanup + system ("rm -Rf $tmpdir_base"); + return 1; + } + + my $tmp_kit_conf = `find $tmpdir_base -name kit.conf`; + chomp($tmp_kit_conf); + my $tmpdir = dirname($tmp_kit_conf); + + # read in the file + my $CKF; + unless ( open( $CKF, "<", $tmp_kit_conf ) ) { + print "The Kit configuration file $tmp_kit_conf could not be read or was not included in the kit tar file. \n"; + # Cleanup + system ("rm -Rf $tmpdir_base"); + return 1; + } + my @lines = <$CKF>; + close $CKF; + + $::PREREQUISITE = 1; + foreach my $l (@lines) { + # skip blank and comment lines + if ( $l =~ /^\s*$/ || $l =~ /^\s*#/ ) { + next; + } + if ($l =~ /prerequisite/ ) { + $::PREREQUISITE = 0; + } + } + + # + # check contents of kit.conf to make sure the framework + # is compatible with this codes framework + $::kitframework = &check_framework(\@lines); + if (!defined($::kitframework)) { + return 1; + } + + # if this in not a partial kit then the framework must be 2 or greater + my $kit_name = basename($kittarfile); + if ( (!($kit_name =~ /NEED_PRODUCT_PKGS/)) && ($::kitframework < 2) ) { + print "This kit cannot be updated. To update a complete kit the kit framework\n value must be greater than or equal to 2. You can use the\n\t\'lskit -F \' \ncommand to check the framework value of the kit.\n"; + return 1; + } + + ### Check if this is a new partial kit built with xCAT 2.8.1 or newer + if (-d "$tmpdir/build_input") { + system ("mv $tmpdir/build_input $tmpdir_base"); + return &NEW_kit_addpkgs($tmpdir_base,$tmpdir); + } + + ### OLD KITS BUILT PRIOR TO xCAT 2.8.1 + ### this code will eventually become obsolete and should be removed + ### do not update + if (defined($::KITVERSION) || defined($::KITRELEASE)) { + print "kitversion and kitrelease substitution is not supported for this incomplete kit. Run \"buildkit addpkgs\" without the \"-k|--kitversion\" and \"-r| --kitrelease\" options. \n"; + exit 1; + } + + my $rpmdir=$::PKGDIR; + + my $ext_filename = ''; + my $ext_reponames = ''; + my $non_native_filename = ''; + my $non_native_kitcompname = ''; + my $non_native_basename = ''; + my $non_native_kitreponame = ''; + my %create_repodata_list; + my @new_lines; + my $section = ''; + my $kitname = ''; + my $kitbasename = ''; + my $kitversion = ''; + my $kitostype = ''; + foreach my $l (@lines) { + # skip blank and comment lines + if ( $l =~ /^\s*$/ || $l =~ /^\s*#/ ) { + push(@new_lines, $l); + next; + } + # new section? + if ( $l =~ /^\s*(\w+)\s*:/ ) { + $section = $1; + if ($section eq 'EXTERNALPKG') { + $ext_filename = ''; + $ext_reponames = ''; + next; + } + if ($section eq 'NONNATIVEPKGS') { + $non_native_filename = ''; + $non_native_kitcompname = ''; + $non_native_basename = ''; + $non_native_kitreponame = ''; + next; + } + push(@new_lines, $l); + next; + } + if ( $l =~ /^\s*(\w+)\s*=\s*(.*)\s*/ ) { + my $attr = $1; + my $val = $2; + my $orig_attr = $attr; + my $orig_val = $val; + $attr =~ s/^\s*//; # Remove any leading whitespace + $attr =~ s/\s*$//; # Remove any trailing whitespace + $attr =~ tr/A-Z/a-z/; # Convert to lowercase + $val =~ s/^\s*//; + $val =~ s/\s*$//; + + + if ($section eq 'kit') { + if ( $attr eq 'basename' ) { $kitbasename = $val; } + if ( $attr eq 'version' ) { $kitversion = $val; } + if ( $attr eq 'ostype' ) { $kitostype = $val; } + if ( ($kitbasename ne '') && ($kitversion ne '') && + ($kitostype ne '') ) { + $kitname = "$kitbasename-$kitversion-$kitostype"; + } + } + + if ($section eq 'EXTERNALPKG') { + if ($attr eq 'filename') { + $ext_filename = $val; + } elsif ($attr eq 'kitreponame') { + $ext_reponames = $val; + } else { + next; + } + if ( ($ext_filename ne '') && ($ext_reponames ne '') ){ + my $fromfile = $rpmdir."/".$ext_filename; + if ( system("ls $fromfile > /dev/null") ){ + print "The product package file $ext_filename could not be read from the package directory $rpmdir. \n"; + # Cleanup + system ("rm -Rf $tmpdir_base"); + return 1; + } + foreach my $repo (split(/,/, $ext_reponames)) { + my $repodir = $tmpdir."/repos/".$repo; + if ( ! -d ($repodir) && (! mkpath($repodir)) ) { + print "Error creating repository directory $repodir\n"; + # Cleanup + system ("rm -Rf $tmpdir_base"); + return 1; + } + if (system("cp -fp $fromfile $repodir")) { + print "Error copying package file $fromfile to $repodir \n"; + # Cleanup + system ("rm -Rf $tmpdir_base"); + return 1; + } + $create_repodata_list{$repodir}=1; + } + } + next; + } + + if ($section eq 'NONNATIVEPKGS') { + if ( $attr eq 'filename' ) { + $non_native_filename = $val; + } elsif ($attr eq 'kitcompname') { + $non_native_kitcompname = $val; + } elsif ($attr eq 'basename') { + $non_native_basename = $val; + } elsif ($attr eq 'kitreponame') { + $non_native_kitreponame = $val; + } else { + next; + } + if ( ($non_native_filename ne '') + && ($non_native_kitcompname ne '') + && ($non_native_basename ne '') + && ($non_native_kitreponame ne '')) { + #find out the useful dir + my $tdir = $tmpdir."/tmp/"; + my $source_dir = "$tdir/$non_native_kitcompname"; + my $spec = "$tdir/$non_native_kitcompname.spec"; + if (!-d "$tdir" or !-d "$source_dir") { + print "Error open kitcomponent rpm build direcotry $tdir or $tdir/$non_native_kitcompname \n"; + # Cleanup + system ("rm -Rf $tmpdir_base"); + return 1; + } + + #copy the nan_native_pkgs to the source dir + foreach my $tepmfilename (split(/,/, $non_native_filename)){ + #the $non_native_filename may contain several pkgs, can check and copy at the same time + my $fromfile = $rpmdir."/".$tepmfilename; + if ( system("ls $fromfile > /dev/null") ){ + print "The product package file $non_native_filename could not be read from the package directory $rpmdir. \n"; + system ("rm -Rf $tmpdir_base"); + return 1; + } + if (system("cp -fp $fromfile $tdir/$non_native_kitcompname")) { + print "Error copying package file $fromfile to $tdir/$non_native_kitcompname \n"; + # Cleanup + system ("rm -Rf $tmpdir_base"); + return 1; + } + } + #for debian/ubuntu + my $repodir = $tmpdir . "/repos/".$non_native_kitreponame; + if ( $debianflag ){ + my $debbuildcmd = "cd $source_dir;dpkg-buildpackage -uc -us"; + if ( system($debbuildcmd) ){ + print "error running debian build cmd for kit component $non_native_basename meta package.\n"; + return 1; + } + my @debs = `find $tdir -maxdepth 1 -name "*.deb"`; + foreach my $debname (@debs){ + chomp($debname); + if ( system("mv -f $debname $repodir") ){ + print "Error copying package $debname to build repo directory $repodir. \n"; + return 1; + } + } + } + else{ + if (!-r "$spec") { + print "Error open kitcomponent rpm build spec $tdir/$non_native_kitcompname.spec \n"; + # Cleanup + system ("rm -Rf $tmpdir_base"); + return 1; + } + my $rpmbuild_dir = $tmpdir."/rpmbuild"; + my $cmd = "rm -Rf $rpmbuild_dir"; + system($cmd); + + my $avoiderr = $rpmbuild_dir."/BUILDROOT/"; + mkpath($avoiderr); + $avoiderr = $rpmbuild_dir."/BUILD/"; + mkpath($avoiderr); + $avoiderr = $rpmbuild_dir."/SRPMS/"; + mkpath($avoiderr); + $avoiderr = $rpmbuild_dir."/RPMS/noarch/"; + mkpath($avoiderr); + + unless ( open( SF, "<", $spec ) ) { + print "Error attempting to open spec $spec of kitcomponent $non_native_basename. \n"; + return 1; + } + + mkpath("$rpmbuild_dir/SOURCES"); + $cmd = "cd $source_dir/..;mv $non_native_kitcompname $non_native_basename; tar -czf $rpmbuild_dir/SOURCES/$non_native_basename.tar.gz $non_native_basename;mv $non_native_basename $non_native_kitcompname;"; + if ( system($cmd) ) { + print "Error creating tarfile $rpmbuild_dir/SOURCES/$non_native_basename.tar from $source_dir/*"; + return 1; + } + my $rpmbuild_cmd = "rpmbuild --define \"_topdir $rpmbuild_dir\" -ba $spec"; + if (!$::VERBOSE) { + $rpmbuild_cmd .= ' --quiet '; + } + if ( system($rpmbuild_cmd) ) { + print "Error running rpmbuild command for kit component $non_native_basename meta package\n"; + return 1; + } + + # Copy the built meta rpm to repo + my @built_rpms = `find $rpmbuild_dir/RPMS -name "*.rpm"`; + foreach my $rpm (@built_rpms) { + chomp($rpm); + if ( system ("cp -fp $rpm $repodir") ) { + print "Error copying rpm $rpm to build repo directory $repodir \n"; + return 1; + } + } + } + $create_repodata_list{$repodir}=1; + } + next; + } + + push(@new_lines, $l); + } + } + + # Re-write kit.conf with EXTERNALPKG and NONNATIVEPKGS sections removed + my $NCF; + unless ( open( $NCF, ">$tmp_kit_conf" ) ) { + return 1; + } + print $NCF @new_lines; + close($NCF); + + # Clean up RPMBUILD and tmp in kit directory + my $cmd = "rm -Rf $tmpdir/tmp"; + system("$cmd"); + unless ( $debianflag ){ + $cmd = "rm -Rf $tmpdir/rpmbuild"; + system("$cmd"); + } + + # Run createrepo for each updated directory + foreach my $repo (keys(%create_repodata_list)) { + my $createrepocmd = ''; + if ( $debianflag ){ + $createrepocmd = "cd $repo;dpkg-scanpackages . > Packages"; + } + else{ + $createrepocmd = "createrepo $repo"; + } + if (system( $createrepocmd )) { + print "Error running $createrepocmd. \n"; + # Cleanup + system ("rm -Rf $tmpdir_base"); + return 1; + } + } + + # Create new tar file in current directory + my $new_tarfile = $::workdir.'/'.$kitbfname.'.tar.bz2'; + if ( system("cd $tmpdir; cd ..; tar -cjhf $new_tarfile $kitname/*") ) { + print "Error building tarfile $new_tarfile \n"; + # Cleanup + system ("rm -Rf $tmpdir_base"); + return 1; + } + print "Kit tar file $new_tarfile successfully built \n"; + + # Cleanup + system ("rm -Rf $tmpdir_base"); + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 NEW_kit_addpkgs + + buildkit addpkgs + +=cut + +#----------------------------------------------------------------------------- +sub NEW_kit_addpkgs +{ + # add RPM pkgs to an existing kit tarfile + my $tmpdir_base = shift; + my $tmpdir = shift; + + # - could be list of pkgdir dirs + my @pkgdirlist = split(",", $::PKGDIR); + + $::NEW_PARTIAL_KIT = 1; + $::workdir = "$tmpdir_base/build_input"; + $::full_buildkit_conf = $::workdir."/".$::buildkit_conf; + $::deploy_dir = $tmpdir_base; #kitname appended by validate_bldkitconf routine + + my $tmp_buildkit_conf = `find $tmpdir_base -name $::buildkit_conf`; + + chomp($tmp_buildkit_conf); + if ($tmp_buildkit_conf ne $::full_buildkit_conf) { + print "$tmp_buildkit_conf should match $::full_buildkit_conf .... error??? \n"; + } + + my $loadrc = &load_bldkitconf($tmp_buildkit_conf); + if ( $loadrc != 0 ) { + print "Error reading buildkit config file $tmp_buildkit_conf \n"; + return 1; + } + + if ( defined($::KITVERSION) ) { + $::bldkit_config->{kit}{entries}[0]->{version} = $::KITVERSION; + } + if ( defined($::KITRELEASE) ) { + $::bldkit_config->{kit}{entries}[0]->{release} = $::KITRELEASE; + } + + my $chkrc = &validate_bldkitconf(); + if ( $chkrc != 0 ) { + print "Error validating buildkit config file $tmp_buildkit_conf \n"; + return 1; + } + + if ($tmpdir ne $::deploy_dir) { + if (system ("mv $tmpdir $::deploy_dir ") ) { + print "Error moving $tmpdir to $::deploy_dir \n"; + return 1; + } + } + $::build_dir = $::deploy_dir; + $::base_repodir = "$::deploy_dir/repos"; + my $kitname = $::bldkit_config->{kit}{entries}[0]->{kitname}; + + # Handle external packages + if ($::HAVE_EXTERNAL_PKG) { + foreach my $kp (@{$::bldkit_config->{kitpackage}{entries}}) { + if ($kp->{isexternalpkg} eq 'yes') { + my $ext_filename = $kp->{filename}; + my $ext_reponames = $kp->{kitreponame}; + + my $files = xCAT::BuildKitUtils->find_latest_pkg(\@pkgdirlist, $ext_filename); + + if (!defined($files) ) { + print "Error: The product package file $ext_filename was not found in the package directory(s) @pkgdirlist.\n"; + # Cleanup + system ("rm -Rf $tmpdir_base"); + return 1; + } + + my @fromfiles=@$files; + + foreach my $repo (split(/,/, $ext_reponames)) { + my $repodir = $::base_repodir."/".$repo; + if ( ! -d ($repodir) && (! mkpath($repodir)) ) { + print "Error creating repository directory $repodir\n"; + # Cleanup + system ("rm -Rf $tmpdir_base"); + return 1; + } + + foreach my $fromfile (@fromfiles) { + if (system("cp -fp $fromfile $repodir")) { + print "Error copying package file $fromfile to $repodir \n"; + # Cleanup + system ("rm -Rf $tmpdir_base"); + return 1; + } + } + if ($::VERBOSE) { + print "Copied @fromfiles\n to $repodir\n"; + } + } + } + } + } + + # Handle non_native_pkgs + # Comma-separated list of non-native package + # paths that will be included as files in this kit + # component. + # these are not RPMs! + my $to_source_dir = "$::workdir/source_packages"; + mkpath("$to_source_dir"); + foreach my $kc (@{$::bldkit_config->{kitcomponent}{entries}}) { + if ($::NON_NATIVE_PKGS->{$kc->{kitcompname}}) { + my @nativefiles; + foreach my $pkgfile (split(/,/, $kc->{non_native_pkgs})) { + my ($key,$value) = split /:/,$pkgfile; + if ("$key" =~ /EXTERNALPKGS/) { + #the $non_native_filename may contain several pkgs, can check and copy at the same time + foreach my $nnpkg (split(/,/, $value)){ + my $found=0; + foreach my $pdir (@pkgdirlist) { + my $fromfile = $pdir."/".$nnpkg; + if ( system("ls $fromfile > /dev/null") ){ + next; + } else { + $found++; + if (system("cp -fp $fromfile $to_source_dir")) { + print "Error copying package file $fromfile to $to_source_dir \n"; + # Cleanup + system ("rm -Rf $tmpdir_base"); + next; + } else { + if ($::VERBOSE) { + print "Copied $fromfile to $to_source_dir\n"; + } + } + } + } + if (!$found) { + print "Could not find $nnpkg.\n"; + } + } + } + } + } + } + + # Turn off external pkg flags and build the kit component meta pkgs + $::HAVE_EXTERNAL_PKG = ''; + $::HAVE_NON_NATIVE_PKGS = ''; + $::NON_NATIVE_PKGS = {}; + + foreach my $kc (@{$::bldkit_config->{kitcomponent}{entries}}) { + my $rc=0; + if ( $debianflag ){ + $rc = &build_kitcomp_debian($kc); + } + else{ + $rc = &build_kitcomp($kc); + } + if ( $rc ) { + print "Error building kitcomponent metapackage for $kc->{basename} \n"; + return 1; + } + } + + # run createrepo + foreach my $kr (@{$::bldkit_config->{kitrepo}{entries}}) { + my $repodir = "$::base_repodir/$kr->{kitreponame}"; + if ( -d $repodir ) { + my $cr_opts = ''; + if (( $kr->{osbasename} =~ m/rh|RH|centos|CentOS/ ) && + ( $kr->{osmajorversion} eq '5') ) { + $cr_opts = '-s md5'; + } + my $repocmd = ""; + if ( $debianflag ){ + $repocmd = "cd $repodir;dpkg-scanpackages . > Packages"; + } + else{ + $repocmd = "createrepo $cr_opts $repodir"; + } + if ( system( $repocmd ) ) { + print "Error building the repository meta-data with the createrepo command \n"; + return 1; + } + } + } + + # Build the full kit tar file + my $buildtar_rc = &kit_buildtar; + + # clean out the tmp dir + system ("rm -Rf $tmpdir_base"); + + if ($buildtar_rc) { + print "Error building full kit tarfile \n"; + return 1; + } + return 0; +} + +#----------------------------------------------------------------------------- + +=head3 check_framework + + Check the compatible frameworks of the kit to see if it is + compatible with the running code. + + If one of the compatible frameworks of the kit matches one of the + compatible frameworks of the running code then we're good. + + NOTE: compatible_kitframeworks are the kitframeworks that I can add + and kit frameworks that I can be added to. + + Returns: + 0 - kit framework value + undef - error + + Example: + my $kitframework = &check_framework(\@lines); + +=cut + +#----------------------------------------------------------------------------- +sub check_framework +{ + my $lines = shift; + + my @kitconflines = @$lines; + + my $kitbasename; + my $kitcompat; + my $kitframework; + my $section = ''; + foreach my $l (@kitconflines) { + # skip blank and comment lines + if ( $l =~ /^\s*$/ || $l =~ /^\s*#/ ) { + next; + } + + if ( $l =~ /^\s*(\w+)\s*:/ ) { + $section = $1; + next; + } + + if ( $l =~ /^\s*(\w+)\s*=\s*(.*)\s*/ ) { + my $attr = $1; + my $val = $2; + $attr =~ s/^\s*//; # Remove any leading whitespace + $attr =~ s/\s*$//; # Remove any trailing whitespace + $attr =~ tr/A-Z/a-z/; # Convert to lowercase + $val =~ s/^\s*//; + $val =~ s/\s*$//; + + if ($section eq 'kitbuildinfo') { + if ( $attr eq 'compatible_kitframeworks' ) { + $kitcompat = $val; + } + if ( $attr eq 'kitframework' ) { + $kitframework = $val; + } + } + if ($section eq 'kit') { + if ( $attr eq 'basename' ) { $kitbasename = $val; } + } + } + } + + if (!$kitcompat) { + print "Warning: Could not determine the kit compatible framework values for \'$kitbasename\' from the kit.conf file. Continuing for now.\n"; + return 0; + } + + my @kit_compat_list = split (',', $kitcompat); + my @my_compat_list = split (',', $::COMPATIBLE_KITFRAMEWORKS); + + foreach my $myfw (@my_compat_list) { + chomp $myfw; + foreach my $kitfw (@kit_compat_list) { + chomp $kitfw; + + if ($myfw eq $kitfw) { + return $kitframework; + } + } + } + print "Error: The kit named \'$kitbasename\' is not compatible with this version of the buildkit command. \'$kitbasename\' is compatible with \'$kitcompat\' and the buildkit command is compatible with \'$::COMPATIBLE_KITFRAMEWORKS\'\n"; + return undef; +}