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; diff --git a/perl-xCAT/xCAT/DSHCLI.pm b/perl-xCAT/xCAT/DSHCLI.pm index ecdb2b4c3..9b09140c5 100644 --- a/perl-xCAT/xCAT/DSHCLI.pm +++ b/perl-xCAT/xCAT/DSHCLI.pm @@ -3237,7 +3237,17 @@ 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 $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) { @@ -3246,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, @@ -4079,11 +4087,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/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/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; 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/PPCdb.pm b/perl-xCAT/xCAT/PPCdb.pm index 145652510..f034906a3 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) { @@ -897,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}))) { @@ -967,7 +1066,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]; 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/perl-xCAT/xCAT/Utils.pm b/perl-xCAT/xCAT/Utils.pm index 26f3f867b..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 @@ -3253,6 +3257,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 +3271,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 +3325,7 @@ sub filter_nodes{ } else { push @{$mpnodes}, @ngpfsp; } + push @{$mpnodes}, @ngpbmc; } elsif ($cmd eq "rvitals") { if (@args && (grep /^lcds$/,@args)) { push @{$fspnodes},@ngpfsp; diff --git a/xCAT-OpenStack/lib/perl/xCAT/Cloud.pm b/xCAT-OpenStack/lib/perl/xCAT/Cloud.pm new file mode 100644 index 000000000..cb9ae9f50 --- /dev/null +++ b/xCAT-OpenStack/lib/perl/xCAT/Cloud.pm @@ -0,0 +1,167 @@ +# 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', '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"; + $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 $node = shift; + my $clients = shift; + my $cloudres; + my $cloudlist; + 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}) ) { + my $cloud=$cloudinfo_hash->{$node}->{cloud}; + my $pubinterface=$cloudinfo_hash->{$cloud}->{pubinterface}; + $cloudres="PUBINTERFACE='$pubinterface'\nexport PUBINTERFACE\n"; + } + 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/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 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-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/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 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-buildkit/bin/buildkit b/xCAT-buildkit/bin/buildkit index c2705ecc5..e717029f6 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,21 @@ sub kit_buildtar $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; @@ -1905,6 +1920,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; } @@ -1928,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; @@ -1943,6 +1961,8 @@ sub build_kitcomp return 1; } } + + $::VALID_PRER_COMPONENT = 1; } @@ -1998,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; @@ -2042,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; @@ -2059,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; } @@ -2100,6 +2122,7 @@ sub update_kitcomp_kitpkgdeps $new_kitpkgdeps =~ s/(\,)*$//; $comp->{kitpkgdeps} = $new_kitpkgdeps; } + return 0; } @@ -2260,7 +2283,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/; @@ -3120,12 +3148,15 @@ sub kit_addpkgs 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); @@ -3155,10 +3186,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 +3500,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"; @@ -3503,15 +3543,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)) ) { @@ -3649,11 +3690,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 +3707,7 @@ sub check_framework my $kitbasename; my $kitcompat; + my $kitframework; my $section = ''; foreach my $l (@kitconflines) { # skip blank and comment lines @@ -3691,6 +3733,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 +3757,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; } 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; +} diff --git a/xCAT-client/pods/man1/chkkitcomp.1.pod b/xCAT-client/pods/man1/chkkitcomp.1.pod index e4c220523..6c964ab01 100644 --- a/xCAT-client/pods/man1/chkkitcomp.1.pod +++ b/xCAT-client/pods/man1/chkkitcomp.1.pod @@ -10,7 +10,9 @@ 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. Note: The xCAT support for Kits is only available for Linux operating systems. 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 + 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-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 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 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 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/perl/xCAT/Postage.pm b/xCAT-server/lib/perl/xCAT/Postage.pm index a3456a1b6..7cd83050e 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, $node, \@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,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 $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 $node = 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, $node, $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/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, ""); } diff --git a/xCAT-server/lib/xcat/plugins/blade.pm b/xCAT-server/lib/xcat/plugins/blade.pm index 88e49dcb2..4d4d8dc65 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";} @@ -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]); diff --git a/xCAT-server/lib/xcat/plugins/configfpc.pm b/xCAT-server/lib/xcat/plugins/configfpc.pm new file mode 100644 index 000000000..de1ed3692 --- /dev/null +++ b/xCAT-server/lib/xcat/plugins/configfpc.pm @@ -0,0 +1,477 @@ +# 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; +use Net::Ping; + +########################################################################## +## 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; + + 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, + ); + + # 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(); + + 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; +} + +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 \n "; + push @{ $rsp->{data} }, + " configfpc [-V|--verbose] -i interface \n "; + push @{ $rsp->{data} }, " configfpc [-h|--help|-?] \n"; + xCAT::MsgUtils->message( "I", $rsp, $::CALLBACK ); + 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; + + # 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 + # + 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; + + 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; + } + + + 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 + # + 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); + + # message changed network settings + my %rsp = {}; + push@{ $rsp{data} }, "Configured FPC with MAC $fpcmac as $node ($newfpcip)"; + xCAT::MsgUtils->message( "I", \%rsp, $callback ); + + # Validate that new IP is working - Use ping to check if the new IP has been set + 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 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( "E", \%rsp, $callback ); + $foundfpc = 0; + } + + # + # 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`; + + 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; + } + } + } + + # + # Cleanup on the way out - Delete route and remove the deffpc node definition + # + # 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 => [ $defnode ] + }, + $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 + 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"], + 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 + 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"], + 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 + 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"], + 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); + # 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; 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"; 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; } } } 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/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 } } diff --git a/xCAT-server/lib/xcat/plugins/esx.pm b/xCAT-server/lib/xcat/plugins/esx.pm index 235264205..168fa6515 100644 --- a/xCAT-server/lib/xcat/plugins/esx.pm +++ b/xCAT-server/lib/xcat/plugins/esx.pm @@ -125,6 +125,8 @@ sub handled_commands{ rpower => 'nodehm:power,mgt', 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', @@ -210,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") { + 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]; @@ -319,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; @@ -636,6 +639,10 @@ 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 'rescansan') { + generic_hyp_operation(\&rescansan,@exargs); } elsif ($command eq 'rmhypervisor') { generic_hyp_operation(\&rmhypervisor,@exargs); } elsif ($command eq 'rshutdown') { @@ -2173,6 +2180,48 @@ 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}; + $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}; @@ -4514,12 +4563,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; @@ -4925,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); } @@ -4937,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; @@ -4965,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/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/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/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}=[]; 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); 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... diff --git a/xCAT-server/lib/xcat/plugins/lsslp.pm b/xCAT-server/lib/xcat/plugins/lsslp.pm index f2b4a6dd2..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"; } @@ -1450,10 +1449,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}; } } @@ -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; + + 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/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/svc.pm b/xCAT-server/lib/xcat/plugins/svc.pm index 10b2b437b..c807b87ba 100644 --- a/xCAT-server/lib/xcat/plugins/svc.pm +++ b/xCAT-server/lib/xcat/plugins/svc.pm @@ -20,29 +20,132 @@ my %controllersessions; 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 @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); + 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}}; + 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; 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, 'size=f' => \$size, + 'name=s' => \$name, 'pool=s' => \$pool, )) { foreach (@nodes) { @@ -74,14 +177,31 @@ 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); + sendmsg($lun->{name}.": id: ".$lun->{wwn},$callback); my $wwns = get_wwns(@nodes); - makehosts($wwns, controller=>$controller, cfg=>$storents); - bindhosts(\@nodes, $lun, controller=>$controller); + 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} ] + ); + $dorequest->(\%request, $callback); + %request = ( + node => \@nodes, + command => [ 'rescansan' ], + ); + $dorequest->(\%request, $callback); + } } 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}); } } @@ -115,15 +235,51 @@ 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}); } } +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 %nodenamemap; foreach my $node (keys %$wwnmap) { my $wwnstr = ""; foreach my $wwn (@{$wwnmap->{$node}}) { @@ -134,7 +290,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 + $nodenamemap{$node} = fixup_host($session, $wwnmap->{$node}); + } else { + die $result." while trying to create host"; + } + } else { + $nodenamemap{$node} = $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 +315,7 @@ sub makehosts { my $ctrstring = join ",", @currentcontrollers; $stortab->setNodeAttribs($node,{controller=>$ctrstring}); } + return %nodenamemap; } my %wwnmap; @@ -216,7 +384,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; @@ -246,7 +418,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); @@ -258,6 +430,7 @@ sub assure_identical_table_values { $callback, $node); return undef; } + if (not defined $lastval) { $lastval = $currval; } } return $lastval; } @@ -287,14 +460,20 @@ 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 $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); + sendmsg($lun->{name}.": id: ".$lun->{wwn},$callback,$node); my $wwns = get_wwns($node); - makehosts($wwns, controller=>$controller, cfg=>{$node=>$cfg}); - bindhosts([$node], $lun, controller=>$controller); + my %namemap = makehosts($wwns, controller=>$controller, cfg=>{$node=>$cfg}); + my @names = values %namemap; + bindhosts(\@names, $lun, controller=>$controller); } sub process_request { @@ -303,6 +482,12 @@ 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 'rmstorage') { + rmstorage($request); + } elsif ($request->{command}->[0] eq 'detachstorage') { + detachstorage($request); } elsif ($request->{command}->[0] eq 'lspool') { lsmdiskgrp($request); } diff --git a/xCAT-server/lib/xcat/plugins/updatenode.pm b/xCAT-server/lib/xcat/plugins/updatenode.pm index 119c59a3d..425074fac 100644 --- a/xCAT-server/lib/xcat/plugins/updatenode.pm +++ b/xCAT-server/lib/xcat/plugins/updatenode.pm @@ -294,17 +294,20 @@ 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; + } + # For -s flag just run this one script + if ($::SETSERVER) { + $::RERUNPS = "setuppostbootscripts"; } - # -f or -F not both if (($::FILESYNC) && ($::SNFILESYNC)) { @@ -393,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; } @@ -1099,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); @@ -1306,7 +1310,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 +1727,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"; 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..2e71b594d 100644 --- a/xCAT-server/lib/xcat/plugins/yaboot.pm +++ b/xCAT-server/lib/xcat/plugins/yaboot.pm @@ -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=(); @@ -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..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 @@ -2124,23 +2124,20 @@ sub setupMNinDB my $defined = 0; 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 + my @output = xCAT::Utils->runcmd("$cmds", -1); + + if ($::RUNCMD_RC == 0) # found nodes in __mgmtnode { my $chtabcmds; - my @mn = split(",", $output); - $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; + # 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; } - } else { # it is defined and good - xCAT::MsgUtils->message('I', "$mnname already defined in the nodelist table."); - $defined=1; } } # now add with the new name , if not already there @@ -2195,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; } #----------------------------------------------------------------------------- diff --git a/xCAT-server/sbin/xcatd b/xCAT-server/sbin/xcatd index fc5657c35..d95060fdc 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 @@ -1064,9 +1065,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 +1112,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; @@ -2260,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(); 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; 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 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/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 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++; } } 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-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; 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/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" diff --git a/xCAT/postscripts/confignics b/xCAT/postscripts/confignics index 4fc91aae6..37fe95bd8 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 @@ -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='' @@ -59,6 +64,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 +153,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 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/remoteshell b/xCAT/postscripts/remoteshell index 85ef54d71..ea7492a16 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 @@ -24,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 @@ -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/runxcatpost b/xCAT/postscripts/runxcatpost index d7c86c66b..83284ca55 100644 --- a/xCAT/postscripts/runxcatpost +++ b/xCAT/postscripts/runxcatpost @@ -1,13 +1,73 @@ #!/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 + +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` +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 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/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." diff --git a/xCAT/postscripts/xcatdsklspost b/xCAT/postscripts/xcatdsklspost index ea1be0b24..a26b5660d 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; @@ -555,6 +561,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. @@ -732,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 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 diff --git a/xCAT/postscripts/xcatserver b/xCAT/postscripts/xcatserver index 8dca02e45..b4886e412 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 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