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/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: $!" ); } } 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-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-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-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 55e492145..ce73bb671 100644 --- a/xCAT-OpenStack/xCAT-OpenStack.spec +++ b/xCAT-OpenStack/xCAT-OpenStack.spec @@ -28,17 +28,41 @@ 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/* + +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/lib/perl/xCAT/Postage.pm b/xCAT-server/lib/perl/xCAT/Postage.pm index a3456a1b6..250c28eb8 100644 --- a/xCAT-server/lib/perl/xCAT/Postage.pm +++ b/xCAT-server/lib/perl/xCAT/Postage.pm @@ -211,8 +211,10 @@ sub makescript { return; } - $mn = xCAT::Utils->noderangecontainsMn(@$nodes); + @::mn = xCAT::Utils->noderangecontainsMn(@$nodes); + my $cfgflag=0; + my $cloudflag=0; my $inc; my $t_inc; my %table; @@ -221,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; } @@ -239,6 +246,11 @@ sub makescript { } } + + if( $line =~ /#CFGMGTINFO_EXPORT#/ ) { + $cfgflag = 1; + } + } close($inh); @@ -334,6 +346,27 @@ sub makescript { # get all the nodes' setstate my $nodes_setstate_hash = getNodesSetState($nodes); + + my $cfginfo_hash; + my $cloudinfo_hash; + $cfginfo_hash = getcfginfo(); + # + #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; @@ -447,6 +480,13 @@ sub makescript { my $enablesshbetweennodes = enableSSHbetweennodes($node, \%::GLOBAL_SN_HASH, $groups_hash); + my @clients; + my $cfgres; + my $cloudres; + $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; @@ -462,6 +502,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; @@ -609,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; } @@ -1699,6 +1742,126 @@ 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 $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}(); + } + } + return $result; +} + + +sub getcloudres +{ + my $module_name = shift; + my $cloud_exists = shift; + my $cloudinfo_hash = shift; + 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); +} 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; 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/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/lib/xcat/plugins/yaboot.pm b/xCAT-server/lib/xcat/plugins/yaboot.pm index fda2ccb33..2e71b594d 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,14 +568,15 @@ 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 + # 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; } @@ -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; @@ -612,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')) { @@ -629,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; @@ -649,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); } } } 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 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 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 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. diff --git a/xCAT-server/share/xcat/netboot/sles/genimage b/xCAT-server/share/xcat/netboot/sles/genimage index aa3eda6d6..22fcc24d4 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>; @@ -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"; 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 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; 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/mountinstall b/xCAT/postscripts/mountinstall new file mode 100755 index 000000000..62097e469 --- /dev/null +++ b/xCAT/postscripts/mountinstall @@ -0,0 +1,50 @@ +#!/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 +# 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,loadclouddata" +# + + +if [ -z "$INSTALLDIR" ]; then + INSTALLDIR="/install" +fi + + +mount | grep "$MASTER:$INSTALLDIR on /install" +if [ $? -eq 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 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