diff --git a/build-ubunturepo b/build-ubunturepo index c1391bc6a..b2b4e0e31 100755 --- a/build-ubunturepo +++ b/build-ubunturepo @@ -53,7 +53,7 @@ for i in $*; do done # Supported distributions -dists="maverick natty oneiric precise" +dists="maverick natty oneiric precise saucy" c_flag= # xcat-core (trunk-delvel) path d_flag= # xcat-dep (trunk) path diff --git a/perl-xCAT/xCAT/FSPvm.pm b/perl-xCAT/xCAT/FSPvm.pm index f81030134..5e61e3f53 100644 --- a/perl-xCAT/xCAT/FSPvm.pm +++ b/perl-xCAT/xCAT/FSPvm.pm @@ -15,6 +15,7 @@ use xCAT::PPCcli qw(SUCCESS EXPECT_ERROR RC_ERROR NR_ERROR); use xCAT::Usage; use xCAT::NodeRange; use xCAT::FSPUtils; +use xCAT::VMCommon; #use Data::Dumper; use xCAT::MsgUtils qw(verbose_message); ############################################## @@ -52,7 +53,7 @@ sub chvm_parse_extra_options { my $args = shift; my $opt = shift; # Partition used attributes # - my @support_ops = qw(vmcpus vmmemory vmphyslots vmothersetting); + my @support_ops = qw(vmcpus vmmemory vmphyslots vmothersetting vmstorage vmnics del_vadapter); if (ref($args) ne 'ARRAY') { return "$args"; } @@ -84,6 +85,24 @@ sub chvm_parse_extra_options { $opt->{bsr} = $1; } next; + } elsif ($cmd eq "vmstorage") { + if (exists($opt->{vios})) { + if ($value !~ /\d+/) { + return "'$value' is invalid, must be numbers"; + } else { + my @array = (); + for (1..$value) { + push @array, 0; + } + $value = \@array; + } + } else { + if ($value =~ /^([\w_-]*):(\d+)$/) { + $value = ["0,$1:$2"]; + } else { + return "'$value' is invalid, must be in form of 'Server_name:slotnum'"; + } + } } } else { @@ -124,7 +143,7 @@ sub chvm_parse_args { $Getopt::Long::ignorecase = 0; Getopt::Long::Configure( "bundling" ); - if ( !GetOptions( \%opt, qw(V|verbose p=s i=s m=s r=s p775) )) { + if ( !GetOptions( \%opt, qw(V|verbose p=s i=s m=s r=s p775 vios) )) { return( usage() ); } #################################### @@ -398,7 +417,7 @@ sub mkvm_parse_args { push @unsupport_ops, $tmpop; } } - my @support_ops = qw(vmcpus vmmemory vmphyslots vmothersetting); + my @support_ops = qw(vmcpus vmmemory vmphyslots vmothersetting vmnics vmstorage); if (defined(@ARGV[0]) and defined($opt{full})) { return(usage("Option 'full' shall be used alone.")); } elsif (defined(@ARGV[0])) { @@ -711,6 +730,45 @@ sub do_op_extra_cmds { $action = "part_set_lpar_pending_proc"; } elsif ($op eq "vmphyslots") { $action = "set_io_slot_owner_uber"; + } elsif ($op eq "del_vadapter") { + $action = "part_clear_vslot_config"; + } elsif ($op eq "vmnics") { + my @vlans = split /,/,$param; + foreach (@vlans) { + if (/vlan(\d+)/i) { + my $vlanid = $1; + my $mac = lc(xCAT::VMCommon::genMac($name)); + if ($mac =~ /(..):(..):(..):(..):(..):(..)/) { + my $tail = hex($6)+$vlanid; + $mac = sprintf("$1$2$3$4$5%02x",$tail); + } + my $value = xCAT::FSPUtils::fsp_api_action($request,$name, $d, "part_set_veth_slot_config",0,"0,$vlanid,$mac"); + if (@$value[1] && ((@$value[1] =~ /Error/i) && (@$value[2] ne '0'))) { + return ([[$name, @$value[1], '1']]) ; + } else { + push @values, [$name, "Success", '0']; + } + } + } + next; + } elsif ($op eq "vmstorage") { + foreach my $v_info (@$param) { + if ($v_info =~ /(\d+),([\w_-]*):(\d+)/) { + my $vios = &find_lpar_id($request, @$d[3], $2); + my $r_slotid = $3; + if (!defined($vios)) { + return ([[$name, "Cannot find lparid for Server lpar:$1", '1']]); + } + $v_info = "$1,$vios,$r_slotid"; + } + my $value = xCAT::FSPUtils::fsp_api_action($request,$name, $d, "part_set_vscsi_slot_config",0,$v_info); + if (@$value[1] && ((@$value[1] =~ /Error/i) && (@$value[2] ne '0'))) { + return ([[$name, @$value[1], '1']]) ; + } else { + push @values, [$name, "Success", '0']; + } + } + next; } elsif ($op eq "vmmemory") { my @td = @$d; @td[0] = 0; @@ -750,6 +808,9 @@ sub do_op_extra_cmds { $action = "part_set_lpar_pending_mem"; } elsif ($op eq "bsr") { $action = "set_lpar_bsr"; + } elsif ($op eq "vios") { + print __LINE__."=========>op=vios===\n"; + next; } else { last; } @@ -1638,6 +1699,34 @@ sub query_cec_info_actions { #$data .= "\n"; next; } + if ($action eq "part_get_all_vio_info") { + my @output = split /\n/, @$values[1]; + my ($drc_index,$drc_name); + foreach my $line (@output) { + chomp($line); + if ($line =~ /Index:.*drc_index:([^,]*),\s*drc_name:(.*)$/) { + $drc_index = $1; + $drc_name = $2; + next; + } elsif ($line =~ /\s*lpar_id=(\d+),type=(vSCSI|vSerial),slot=(\d+),attr=(\d+).*remote_lpar_id=(0x\w+),remote_slot_num=(0x\w+)/) { + if ($4 eq '0') { + push @array, [$name, "$1,$3,$drc_name,$drc_index,$2 Client(Server_lparid=$5,Server_slotid=$6)", 0]; + } else { + push @array, [$name, "$1,$3,$drc_name,$drc_index,$2 Server", 0]; + } + } elsif ($line =~ /\s*lpar_id=(\d+),type=(vEth),slot=(\d+).*port_vlan_id=(\d+),mac_addr=(\w+)/) { + push @array, [$name, "$1,$3,$drc_name,$drc_index,$2 (port_vlanid=$4,mac_addr=$5)", 0]; + #} elsif ($line =~ /\s*lpar_id=(\d+),type=(\w+),slot=(\d+)/) { + # push @array, [$name, "$1,$3,$drc_name,$drc_index,$2", 0]; + #} else { + #print "=====>line:$line\n"; + #push @array, [$name, $line, 0]; + } + $drc_index = ''; + $drc_name = ''; + } + next; + } } #$data .= "@$values[1]\n\n"; push @array, [$name, @$values[1], @$values[2]]; @@ -1660,14 +1749,16 @@ sub query_cec_info { my $args = $request->{opt}; my @td = (); my @result = (); + #print Dumper($request); + #print Dumper($hash); while (my ($mtms,$h) = each(%$hash) ) { while (my ($name, $d) = each (%$h)) { @td = @$d; - if (@$d[0] == 0 && @$d[4] ne "lpar") { + if (@$d[0] == 0 && @$d[4] !~ /lpar|vios/) { last; } #my $rethash = query_cec_info_actions($request, $name, $d, 0, ["part_get_lpar_processing","part_get_lpar_memory","part_get_all_vio_info","lpar_lhea_mac","part_get_all_io_bus_info","get_huge_page","get_cec_bsr"]); - my $rethash = query_cec_info_actions($request, $name, $d, 0, ["part_get_lpar_processing","part_get_lpar_memory","part_get_all_io_bus_info","get_huge_page","get_cec_bsr"]); + my $rethash = query_cec_info_actions($request, $name, $d, 0, ["part_get_lpar_processing","part_get_lpar_memory","part_get_all_io_bus_info","part_get_all_vio_info","get_huge_page","get_cec_bsr"]); #push @result, [$name, $rethash, 0]; push @result, @$rethash; } @@ -1766,7 +1857,7 @@ sub deal_with_avail_mem { } else { $cur_avail = $lparhash->{hyp_avail_mem} + $used_regions - $tmphash{lpar0_used_mem}; } - xCAT::MsgUtils->verbose_message($request, "====****====used:$used_regions,avail:$cur_avail,($min:$cur:$max)."); + #xCAT::MsgUtils->verbose_message($request, "====****====used:$used_regions,avail:$cur_avail,($min:$cur:$max)."); if ($cur_avail < $min) { return([$name, "Parse reserverd regions failed, no enough memory, available:$lparhash->{hyp_avail_mem}.", 1]); } @@ -1781,6 +1872,17 @@ sub deal_with_avail_mem { return 0; } +sub find_lpar_id { + my $request = shift; + my $parent = shift; + my $name = shift; + my %mapping = %{$request->{ppc}->{$parent}->{mapping}}; + if (exists($mapping{$name})) { + return $mapping{$name}; + } + return undef; +} + sub create_lpar { my $request = shift; my $name = shift; @@ -1804,12 +1906,42 @@ sub create_lpar { xCAT::FSPUtils::fsp_api_action($request, $name, $d, "part_set_lpar_group_id"); xCAT::FSPUtils::fsp_api_action($request, $name, $d, "part_set_lpar_avail_priority"); #print "======>physlots:$lparhash->{physlots}.\n"; - $values = xCAT::FSPUtils::fsp_api_action($request, $name, $d, "set_io_slot_owner_uber", 0, $lparhash->{physlots}); - #$values = xCAT::FSPUtils::fsp_api_action($request, $name, $d, "set_io_slot_owner", 0, join(",",@phy_io_array)); - if (@$values[2] ne 0) { - &set_lpar_undefined($request, $name, $d); - return ([$name, @$values[1], @$values[2]]); + if (exists($lparhash->{physlots})) { + $values = xCAT::FSPUtils::fsp_api_action($request, $name, $d, "set_io_slot_owner_uber", 0, $lparhash->{physlots}); + #$values = xCAT::FSPUtils::fsp_api_action($request, $name, $d, "set_io_slot_owner", 0, join(",",@phy_io_array)); + if (@$values[2] ne 0) { + &set_lpar_undefined($request, $name, $d); + return ([$name, @$values[1], @$values[2]]); + } } + if (exists($lparhash->{nics})) { + my @vlans = split /,/,$lparhash->{nics}; + foreach (@vlans) { + if (/vlan(\d+)/i) { + my $vlanid = $1; + my $mac = lc(xCAT::VMCommon::genMac($name)); + if ($mac =~ /(..):(..):(..):(..):(..):(..)/) { + my $tail = hex($6)+$vlanid; + $mac = sprintf("$1$2$3$4$5%02x",$tail); + } + $values = xCAT::FSPUtils::fsp_api_action($request,$name, $d, "part_set_veth_slot_config",0,"0,$vlanid,$mac"); + if (@$values[2] ne 0) { + &set_lpar_undefined($request, $name, $d); + return ([$name, @$values[1], @$values[2]]); + } + } + } + } + if (exists($lparhash->{storage})) { + foreach my $v_info (@{$lparhash->{storage}}) { + $values = xCAT::FSPUtils::fsp_api_action($request,$name, $d, "part_set_vscsi_slot_config",0,$v_info); + if (@$values[2] ne 0) { + &set_lpar_undefined($request, $name, $d); + return ([$name, @$values[1], @$values[2]]); + } + } + } + # ====== ====== # if (exists($lparhash->{phy_hea})) { my $phy_hash = $lparhash->{phy_hea}; foreach my $phy_drc (keys %$phy_hash) { @@ -1850,6 +1982,7 @@ sub create_lpar { &set_lpar_undefined($request, $name, $d); return ([$name, @$values[1], @$values[2]]); } + xCAT::FSPUtils::fsp_api_action($request, $name, $d, "part_set_lpar_comp_modes"); #print "======>memory:$lparhash->{huge_page}.\n"; xCAT::FSPUtils::fsp_api_action($request, $name, $d, "set_huge_page", 0, $lparhash->{huge_page}); @@ -1866,7 +1999,6 @@ sub create_lpar { } return ([$name, "Done", 0]); } - sub mkspeclpar { my $request = shift; my $hash = shift; @@ -1880,7 +2012,7 @@ sub mkspeclpar { while (my ($mtms, $h) = each (%$hash)) { my $memhash; my @nodes = keys(%$h); - my $ent = $vmtab->getNodesAttribs(\@nodes, ['cpus', 'memory','physlots', 'othersettings']); + my $ent = $vmtab->getNodesAttribs(\@nodes, ['cpus', 'memory','physlots', 'othersettings', 'storage', 'nics']); while (my ($name, $d) = each (%$h)) { if (@$d[4] ne 'lpar') { push @result, [$name, "Node must be LPAR", 1]; @@ -1889,7 +2021,7 @@ sub mkspeclpar { if (!exists($memhash->{run})) { my @td = @$d; @td[0] = 0; - $memhash = &query_cec_info_actions($request, $name, \@td, 1, ["part_get_hyp_process_and_mem","lpar_lhea_mac"]); + $memhash = &query_cec_info_actions($request, $name, \@td, 1, ["part_get_hyp_process_and_mem","lpar_lhea_mac","part_get_all_io_bus_info"]); $memhash->{run} = 1; } my $tmp_ent = $ent->{$name}->[0]; @@ -1902,13 +2034,50 @@ sub mkspeclpar { if (exists($opt->{vmphyslots})) { $tmp_ent->{physlots} = $opt->{vmphyslots}; } + if (exists($opt->{vmothersetting})) { $tmp_ent->{othersettings} = $opt->{vmothersetting}; } + if (exists($opt->{vmstorage})) { + $tmp_ent->{storage} = $opt->{vmstorage}; + } + if (exists($opt->{vmnics})) { + $tmp_ent->{nics} = $opt->{vmnics}; + } + if (exists($opt->{vios})) { + if (!exists($tmp_ent->{physlots})) { + my @phy_io_array = keys(%{$memhash->{bus}}); + $tmp_ent->{physlots} = join(",", @phy_io_array); + } + if (exists($tmp_ent->{storage}) and $tmp_ent->{storage} !~ /^\d+$/) { + return ([[$name, "Parameter for 'vmstorage' is invalid", 1]]); + } elsif (exists($tmp_ent->{storage})) { + my $num = $tmp_ent->{storage}; + my @array = (); + for (1..$num) { + push @array, '0'; + } + $tmp_ent->{storage} = \@array; + } + } else { + if (exists($tmp_ent->{storage}) and $tmp_ent->{storage} !~ /^[\w_-]*:\d+$/) { + return ([[$name, "Parameter for 'vmstorage' is invalid", 1]]); + } elsif (exists($tmp_ent->{storage})) { + if ($tmp_ent->{storage} =~ /([\w_-]*):(\d+)/) { + my $vios = &find_lpar_id($request, @$d[3], $1); + my $r_slotid = $2; + if (!defined($vios)) { + return ([[$name, "Cannot find lparid for Server lpar:$1"]]); + } + $tmp_ent->{storage} = ["0,$vios,$r_slotid"]; + } + } + } if (!defined($tmp_ent) ) { return ([[$name, "Not find params", 1]]); - } elsif (!exists($tmp_ent->{cpus}) || !exists($tmp_ent->{memory}) || !exists($tmp_ent->{physlots})) { - return ([[$name, "The attribute 'vmcpus', 'vmmemory' and 'vmphyslots' are all needed to be specified.", 1]]); + #} elsif (!exists($tmp_ent->{cpus}) || !exists($tmp_ent->{memory}) || !exists($tmp_ent->{physlots})) { + } elsif (!exists($tmp_ent->{cpus}) || !exists($tmp_ent->{memory})) { + return ([[$name, "The attribute 'vmcpus', 'vmmemory' are needed to be specified.", 1]]); } if ($tmp_ent->{memory} =~ /(\d+)([G|M]?)\/(\d+)([G|M]?)\/(\d+)([G|M]?)/i) { my $memsize = $memhash->{mem_region_size}; diff --git a/perl-xCAT/xCAT/InstUtils.pm b/perl-xCAT/xCAT/InstUtils.pm index ec1748b11..8fcef91fa 100644 --- a/perl-xCAT/xCAT/InstUtils.pm +++ b/perl-xCAT/xCAT/InstUtils.pm @@ -1353,6 +1353,16 @@ sub dolitesetup return 1; } + # also copy $instrootloc/.statelite contents + $ccmd = "/usr/bin/cp -p -r $instrootloc/.statelite $SRloc"; + $out = xCAT::Utils->runcmd("$ccmd", -1); + if ($::RUNCMD_RC != 0) + { + my $rsp; + push @{$rsp->{data}}, "Could not copy $instrootloc/.statelite to $SRloc."; + xCAT::MsgUtils->message("E", $rsp, $callback); + return 1; + } } } } diff --git a/perl-xCAT/xCAT/ProfiledNodeUtils.pm b/perl-xCAT/xCAT/ProfiledNodeUtils.pm index 8bff2eace..8c14fc39e 100644 --- a/perl-xCAT/xCAT/ProfiledNodeUtils.pm +++ b/perl-xCAT/xCAT/ProfiledNodeUtils.pm @@ -719,6 +719,28 @@ sub get_nodes_profiles return \%profile_dict; } +#------------------------------------------------------------------------------- + +=head3 get_imageprofile_prov_osvers + Description : Get A node's provisioning os version and profile from its imageprofile attribute. + Arguments : $imgprofilename - imageprofile name + Returns : node's osversion and profile +=cut + +#------------------------------------------------------------------------------- +sub get_imageprofile_prov_osvers +{ + + my $class = shift; + my $imgprofilename = shift; + my $osimgtab = xCAT::Table->new('osimage'); + my $osimgentry = ($osimgtab->getAllAttribsWhere("imagename = '$imgprofilename'", 'ALL' ))[0]; + my $osversion = $osimgentry->{'osvers'}; + my $profile = $osimgentry->{'profile'}; + return ($osversion, $profile); +} + + #------------------------------------------------------------------------------- =head3 get_imageprofile_prov_method @@ -1015,6 +1037,40 @@ sub parse_nodeinfo_file return 1, ""; } +#------------------------------------------------------- + +=head3 update the table prodkey, in order to support windows + per node license key + + Returns: $retcode. + $retcode = 1. update failed, the value is undef + $retcode = 0. save into db is OK.. +=cut +#------------------------------------------------------- + +sub update_windows_prodkey +{ + my $class = shift; + my $node = shift; + my $product = shift; + my $key = shift; + unless(defined($node) && defined($product) && defined($key)) + { + return 1; + } + # please notice this db usage + my %keyhash; + my %updates; + $keyhash{'node'} = $node; + $updates{'product'} = $product; + $updates{'key'} = $key; + my $tab = xCAT::Table->new('prodkey', -create=>1, -autocommit=>0); + $tab->setAttribs( \%keyhash,\%updates ); + $tab->commit; + $tab->close; + return 0; +} + #------------------------------------------------------------------------------- =head3 check_nicips Description: Check if the nicips defined in MAC file is correct diff --git a/perl-xCAT/xCAT/SLP.pm b/perl-xCAT/xCAT/SLP.pm index e1ebae53b..0dfa25f69 100755 --- a/perl-xCAT/xCAT/SLP.pm +++ b/perl-xCAT/xCAT/SLP.pm @@ -110,6 +110,12 @@ sub dodiscover { my @servernodes; my @iprange = split /,/, $ipranges; foreach my $range (@iprange) { + send_message($args{reqcallback}, 0, "Processing range $range..."); + if ($range =~/\/(\d+)/){ + if ($1 < 16) { + send_message($args{reqcallback}, 0, "The rarge is too large and may be time consuming. Broadcast is recommended."); + } + } `/usr/bin/nmap $range -sn -PE -n --send-ip -T5 `; my $nmapres = `/usr/bin/nmap $range -PE -p 427 -n --send-ip -T5 `; foreach my $line (split(/\n\n/,$nmapres)) { @@ -233,7 +239,7 @@ sub dodiscover { close PWRITE; if (@servernodes) { my $miss = join(",", @servernodes); - send_message($args{reqcallback}, 0, "Warning: can't got attributes from these nodes' replies: $miss. Please re-send unicast to these nodes.") if ($args{reqcallback}); + send_message($args{reqcallback}, 0, "Warning: can't get attributes from these nodes' replies: $miss. Please re-send unicast to these nodes.") if ($args{reqcallback}); } }# end of parent process } else { diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index aae45f201..ae79728ec 100755 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -1050,9 +1050,9 @@ site => { " nodesyncfiledir: The directory on the node, where xdcp will rsync the files\n". " SNsyncfiledir: The directory on the Service Node, where xdcp will rsync the files\n". " from the MN that will eventually be rsync'd to the compute nodes.\n\n". - " sshbetweennodes: Comma separated list of groups to enable passwordless root \n". + " sshbetweennodes: Comma separated list of groups of compute nodes to enable passwordless root \n". " ssh during install, or xdsh -K. Default is ALLGROUPS.\n". - " Set to NOGROUPS,if you do not wish to enabled any groups.\n". + " Set to NOGROUPS,if you do not wish to enabled any group of compute nodes.\n". " Service Nodes are not affected by this attribute\n". " they are always setup with\n". " passwordless root access to nodes and other SN.\n\n". diff --git a/perl-xCAT/xCAT/Usage.pm b/perl-xCAT/xCAT/Usage.pm index c36c0b9b4..cbf4ede50 100644 --- a/perl-xCAT/xCAT/Usage.pm +++ b/perl-xCAT/xCAT/Usage.pm @@ -207,6 +207,7 @@ my %usage = ( mkvm noderange [--full] mkvm noderange [vmcpus=min/req/max] [vmmemory=min/req/max] [vmphyslots=drc_index1,drc_index2...] [vmothersetting=hugepage:N,bsr:N] + [vmnics=vlan1,vlan2] [vmstorage=] [--vios] For KVM mkvm noderange -m|--master mastername -s|--size disksize -f|--force For zVM @@ -241,6 +242,8 @@ my %usage = ( chvm [lparname=<*|name>] chvm [vmcpus=min/req/max] [vmmemory=min/req/max] [vmphyslots=drc_index1,drc_index2...] [vmothersetting=hugepage:N,bsr:N] + [vmnics=vlan1,vlan2] [vmstorage=] [--vios] + chvm [del_vadapter=slotid] VMware specific: chvm [-a size][-d disk][-p disk][--resize disk=size][--cpus count][--mem memory] zVM specific: diff --git a/xCAT-buildkit/bin/buildkit b/xCAT-buildkit/bin/buildkit index 1a4f279a2..6b45d3ea9 100755 --- a/xCAT-buildkit/bin/buildkit +++ b/xCAT-buildkit/bin/buildkit @@ -952,11 +952,57 @@ sub kit_buildtar 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; + #It is for partial kit. + if ($::HAVE_EXTERNAL_PKG or $::HAVE_NON_NATIVE_PKGS) { + 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; + } } + } else { + #If it is complete kit and there is build_input directory in deploy_dir + #If there is tmp rpmbuild source_packages + #delete them from complete kit build_input + if ( -d "$bidir") { + if (system("cd $::deploy_dir; cd ..; rm -fr build_input/tmp" )){ + print "Error:Could not delete build_input/tmp \n"; + } + if (system("cd $::deploy_dir; cd ..; rm -fr build_input/rpmbuild" )){ + print "Error:Could not delete build_input/tmp \n"; + } + if (system("cd $::deploy_dir; cd ..; rm -fr build_input/source_packages" )){ + print "Error:Could not delete build_input/source_packages \n"; + } + if (system("cd $::deploy_dir; cd ..; cp -fr build_input $kitname")){ + print "Error: Could not copy building tarfile $tarfile \n"; + return 1; + } + } else{ + #If kit build dir is new created + #partial kit is never created before + #make sure there is build_input dir in complete kit dir + if (system("cd $::deploy_dir; mkdir -p build_input" )){ + print "Error creating kit build directory contents \n"; + return 1; + } + if (system("cd $::deploy_dir; cp -fp $::workdir/buildkit.conf build_input" )){ + print "Error creating kit build directory contents \n"; + return 1; + } + if (system("cd $::deploy_dir; cp -frp $::workdir/other_files build_input" )){ + print "Error creating kit build directory contents \n"; + return 1; + } + if (system("cd $::deploy_dir; cp -frp $::workdir/plugins build_input" )){ + print "Error creating kit build directory contents \n"; + return 1; + } + if (system("cd $::deploy_dir; cp -frp $::workdir/scripts build_input" )){ + print "Error creating kit build directory contents \n"; + return 1; + } + } } print "Creating tar file $tarfile.\n"; diff --git a/xCAT-client/bin/getxcatdocs b/xCAT-client/bin/getxcatdocs index e21737672..c9f0bcc8b 100755 --- a/xCAT-client/bin/getxcatdocs +++ b/xCAT-client/bin/getxcatdocs @@ -23,7 +23,7 @@ use Cwd; # Update this list if you group any xcat docs on a separate page such that they are no longer linked from the # main doc page. -my @indexdocs = ('XCAT_Documentation', 'Power_775_Cluster_Documentation', 'Highly_Available_Management_Node', 'Mixed_Cluster_Support'); +my @indexdocs = ('XCAT_Documentation', 'Power_775_Cluster_Documentation', 'Highly_Available_Management_Node', 'Mixed_Cluster_Support', 'IBM_HPC_Stack_in_an_xCAT_Cluster'); #my $VERSION; my $HELP; diff --git a/xCAT-client/bin/mysqlsetup b/xCAT-client/bin/mysqlsetup index 0a150224e..dd0711aac 100755 --- a/xCAT-client/bin/mysqlsetup +++ b/xCAT-client/bin/mysqlsetup @@ -205,10 +205,10 @@ if ($::osname eq 'AIX') &setulimits; } -# if not just odbc update and not already running mysql +# if not just odbc update and not already running mysql or mysqlsetup -u # Get root and admin passwords # -if (($odbconly == 0) && ( $::xcatrunningmysql == 0)) +if ((($odbconly == 0) && ( $::xcatrunningmysql == 0)) || $::UPDATE ) { # not just updating the odbc if ($ENV{'XCATMYSQLADMIN_PW'}) # input env sets the password { diff --git a/xCAT-client/pods/man1/imgexport.1.pod b/xCAT-client/pods/man1/imgexport.1.pod index d63597ca0..2996591a6 100644 --- a/xCAT-client/pods/man1/imgexport.1.pod +++ b/xCAT-client/pods/man1/imgexport.1.pod @@ -11,13 +11,14 @@ B table. All the columns in the I and I tables will be exported. In addition, the following files will also be exported. +The imgexport command will export an image that is being used by xCAT. To export images, you must have the images defined in the I table. All the columns in the I and I tables will be exported. If kits are used in statefull or stateless images, I, I and I tables will be exported. In addition, the following files will also be exported. For statefull: x.pkglist x.otherpkgs.pkglist x.tmpl x.synclist + kits related files For stateless: kernel @@ -28,6 +29,7 @@ For stateless: x.synclist x.postinstall x.exlist + kits related files For statelite: diff --git a/xCAT-client/pods/man1/imgimport.1.pod b/xCAT-client/pods/man1/imgimport.1.pod index 9897b6493..a6e9eedfb 100644 --- a/xCAT-client/pods/man1/imgimport.1.pod +++ b/xCAT-client/pods/man1/imgimport.1.pod @@ -17,6 +17,7 @@ For statefull, the following files will be copied to the appropriate directories x.otherpkgs.pkglist x.tmpl x.synclist + kits related files For stateless, the following files will be copied to the appropriate directories. kernel @@ -27,6 +28,7 @@ For stateless, the following files will be copied to the appropriate directories x.synclist x.postinstall x.exlist + kits related files For statelite, the following files will be copied to the appropriate directories. kernel diff --git a/xCAT-client/pods/man8/nodeset.8.pod b/xCAT-client/pods/man8/nodeset.8.pod index e9feaa184..2c8bd55cd 100644 --- a/xCAT-client/pods/man8/nodeset.8.pod +++ b/xCAT-client/pods/man8/nodeset.8.pod @@ -4,7 +4,7 @@ B - set the boot state for a noderange =head1 B -B [I] [I|I|I|I|I|I|I|I|I>]] +B [I] [I|I|I|I|I|I|I|I|I>]|I|I] B I I> [I<--noupdateinitrd>] [I<--ignorekernelchk>] @@ -93,9 +93,13 @@ for basic remote access. This causes the IP, netmask, gateway, username, and pa =item B -This instructs tho node to boot to the xCAT nbfs environment, and present a shell prompt on console. +This instructs tho node to boot to the xCAT genesis environment, and present a shell prompt on console. The node will also be able to be sshed into and have utilities such as wget, tftp, scp, nfs, and cifs. It will have storage drivers available for many common systems. +=item B + +To make the node to get into power off status. This status only can be used after B and B to power off the node after the performing of operations. + =item B<-h>|B<--help> Print help. diff --git a/xCAT-server/lib/perl/xCAT/PPC.pm b/xCAT-server/lib/perl/xCAT/PPC.pm old mode 100644 new mode 100755 index a833ac540..0f4f35334 --- a/xCAT-server/lib/perl/xCAT/PPC.pm +++ b/xCAT-server/lib/perl/xCAT/PPC.pm @@ -1007,13 +1007,18 @@ sub resolve_netwk { } my $gateway = $nethash{$_}{gateway}; my $gateway_ip; - if ( defined( $gateway )) { + if ( defined( $gateway ) && $gateway) { $ip = xCAT::NetworkUtils::toIP( $gateway ); if ( @$ip[0] != 0 ) { send_msg( $request, 1, "$_: Cannot resolve '$gateway'" ); next; } $gateway_ip = @$ip[1]; + } else { + # If the is the gateway, the ip forwarding must be enabled on the MN/SN, + # xCAT will setup the ipforarding automatically, but still see problems about the ip forwarding occassionally. + send_msg( $request, 1, "$_: No gateway defined for this node, check the networks table. If the gateway in the networks table is '', check the ip forwarding setup on the management node and service nodes."); + next; } my $netmask = $nethash{$_}{mask}; diff --git a/xCAT-server/lib/xcat/plugins/DBobjectdefs.pm b/xCAT-server/lib/xcat/plugins/DBobjectdefs.pm index cc5c4a928..e0b0a9b09 100755 --- a/xCAT-server/lib/xcat/plugins/DBobjectdefs.pm +++ b/xCAT-server/lib/xcat/plugins/DBobjectdefs.pm @@ -538,7 +538,7 @@ sub processArgs # --nics is the equivalent of -i nicips,nichostnamesuffixes... if ($::opt_nics) { - $::opt_i="nicips,nichostnamesuffixes,nihostnameprefixes,nictypes,niccustomscripts,nicnetworks,nicaliases"; + $::opt_i="nicips,nichostnamesuffixes,nichostnameprefixes,nictypes,niccustomscripts,nicnetworks,nicaliases"; } # -i and -s cannot be used together diff --git a/xCAT-server/lib/xcat/plugins/hosts.pm b/xCAT-server/lib/xcat/plugins/hosts.pm index d5426f8f8..77217fd52 100755 --- a/xCAT-server/lib/xcat/plugins/hosts.pm +++ b/xCAT-server/lib/xcat/plugins/hosts.pm @@ -91,7 +91,7 @@ sub addnode # at this point "othernames", if any is just a space # delimited list - so just add the node name to the list - #$othernames .= " $node"; + $othernames .= " $node"; $hosts[$idx] = build_line($callback, $ip, $hnode, $domain, $othernames); } else { # otherwise just try to completely update the existing @@ -120,6 +120,10 @@ sub build_line my $othernames = shift; my @o_names = (); my @n_names = (); + + # Trim spaces from the beginning and end from $othernames + $othernames =~ s/^\s+|\s+$//g; + if (defined $othernames) { # the "hostnames" attribute can be a list delimited by diff --git a/xCAT-server/lib/xcat/plugins/imgport.pm b/xCAT-server/lib/xcat/plugins/imgport.pm index 40878a222..c5a88e336 100644 --- a/xCAT-server/lib/xcat/plugins/imgport.pm +++ b/xCAT-server/lib/xcat/plugins/imgport.pm @@ -33,6 +33,7 @@ use xCAT::Schema; use Cwd; my $requestcommand; $::VERBOSE = 0; +my $hasplugin=0; 1; @@ -1214,7 +1215,8 @@ sub extract_bundle { my $osimage = $data->{osimage}->{imagename}; $callback->({data=>["Successfully imported the image $osimage."]}); - } + + } # Clean up for this routine. # Remove the temp directory used for the exploded bundle @@ -1435,6 +1437,64 @@ sub set_postscripts { return 1; } + +sub create_symlink { + my $data = shift; + my $callback = shift; + my $otherpkgdir = $data->{linuximage}->{otherpkgdir}; + my @kitcomps=split(',',$data->{osimage}->{kitcomponents}); + + my %tabs = (); + my @tables = qw(kit kitrepo kitcomponent); + foreach my $t ( @tables ) { + $tabs{$t} = xCAT::Table->new($t,-create => 1,-autocommit => 1); + + if ( !exists( $tabs{$t} )) { + my %rsp; + push@{ $rsp{data} }, "Could not open xCAT table $t"; + xCAT::MsgUtils->message( "E", \%rsp, $callback ); + return 1; + } + } + + + if ( defined($otherpkgdir) ) { + + # Create otherpkgdir if it doesn't exist + unless ( -d "$otherpkgdir" ) { + mkpath("$otherpkgdir"); + } + + if ( $data and $data->{osimage} and $data->{osimage}->{kitcomponents} ) { + foreach my $kitcomponent ( @kitcomps ){ + (my $kitcomptable) = $tabs{kitcomponent}->getAttribs({kitcompname => $kitcomponent}, 'kitreponame'); + if ( $kitcomptable and $kitcomptable->{'kitreponame'}){ + + # Create symlink if doesn't exist + unless ( -d "$otherpkgdir/$kitcomptable->{'kitreponame'}" ) { + (my $kitrepotable) = $tabs{kitrepo}->getAttribs({kitreponame => $kitcomptable->{'kitreponame'}}, 'kitrepodir'); + if ( $kitrepotable and $kitrepotable->{'kitrepodir'}){ + system("ln -sf $kitrepotable->{'kitrepodir'} $otherpkgdir/$kitcomptable->{'kitreponame'}"); + } else { + $callback->({error => ["Cannot open kitrepo table or kitrepodir do not exist"],errorcode=>[1]}); + next ; + } + } + } else { + $callback->({error => ["Cannot open kitcomponent table or kitreponame do not exist"],errorcode=>[1]}); + next; + } + } + } else { + $callback->({error => ["osimage table or kitcomponent do not exist"],errorcode=>[1]}); + return 1; + } + } + return 1; + + +} + sub set_config { my $data = shift; my $callback = shift; @@ -1830,11 +1890,20 @@ sub make_files { if (-r "$dirname/$kit") { $callback->( {data => [" Moving old $fn to $fn.ORIG."]}); move("$dirname/$kit", "$dirname/$kit.ORIG"); + } move("$imgdir/$kit","$dirname/$kit"); + #copy postscripts from kit dir to postscripts dir; + copyPostscripts($dirname,$kit,$installroot,$callback); + #copy plugin from kit to xCAT_plugin + movePlugin($dirname,$kit,$callback); } } - + if ( $hasplugin ) { + # Issue xcatd reload to load the new plugins + system("/etc/init.d/xcatd reload"); + $hasplugin=0; + } #unpack the rootimgtree.gz for statelite @@ -1960,6 +2029,47 @@ sub make_files { return 1; } +sub copyPostscripts{ + my $dirname=shift; + my $kit=shift; + my $installdir = shift; + my $callback = shift; + my $fenv='\.env$'; + my $fexlist='\.exlist$'; + + if ( -d "$dirname/$kit/other_files/") { + opendir(DIRP,"$dirname/$kit/other_files/"); + foreach my $f (readdir(DIRP)) { + if (($f=~m/^\./) || ($f =~ /$fexlist/i) || ($f =~ m/$fenv/i)) { + next; + } else { + print "$f\n"; + chmod(0755,"$dirname/$kit/other_files/$f"); + system("cp -rfv $dirname/$kit/other_files/$f $installdir/postscripts/"); + } + } + + closedir(DIRP); + } +} + +sub movePlugin { + + my $dirname=shift; + my $kit=shift; + my $callback=shift; + + if( -d "$dirname/$kit/plugins/") { + chmod(644, "$dirname/$kit/plugins/*"); + opendir(DIR,"$dirname/$kit/plugins/"); + if ( grep { ($_ ne '.') && ($_ ne '..') } readdir(DIR) ) { + system("cp -rfv $dirname/$kit/plugins/* $::XCATROOT/lib/perl/xCAT_plugin/"); + $hasplugin = 1; + } + closedir(DIR); + } + +} sub moveExtra { my $callback = shift; diff --git a/xCAT-server/lib/xcat/plugins/ipmi.pm b/xCAT-server/lib/xcat/plugins/ipmi.pm index 01a6945cc..2834af3e6 100644 --- a/xCAT-server/lib/xcat/plugins/ipmi.pm +++ b/xCAT-server/lib/xcat/plugins/ipmi.pm @@ -2681,7 +2681,9 @@ sub add_fruhash { $fru->rec_type("hw"); } $fru->value($sessdata->{currfrudata}); - $fru->desc($sessdata->{currfrusdr}->id_string); + if (exists($sessdata->{currfrusdr})) { + $fru->desc($sessdata->{currfrusdr}->id_string); + } $sessdata->{fru_hash}->{$sessdata->{frudex}} = $fru; $sessdata->{frudex} += 1; } elsif ($sessdata->{currfrutype} and $sessdata->{currfrutype} eq 'dimm') { @@ -2699,9 +2701,13 @@ sub add_fruhash { $fru->rec_type("hw"); } $fru->value($err); - $fru->desc($sessdata->{currfrusdr}->id_string); - $sessdata->{fru_hash}->{$sessdata->{frudex}} = $fru; - $sessdata->{frudex} += 1; + if (exists($sessdata->{currfrusdr})) { + $fru->desc($sessdata->{currfrusdr}->id_string); + } + if (exists($sessdata->{frudex})) { + $sessdata->{fru_hash}->{$sessdata->{frudex}} = $fru; + $sessdata->{frudex} += 1; + } undef $sessdata->{currfrudata}; #skip useless calls to add more frus when parsing failed miserably anyway #xCAT::SvrUtils::sendmsg([1,":Error reading fru area ".$sessdata->{currfruid}.": $err"],$callback); diff --git a/xCAT-server/lib/xcat/plugins/nimol.pm b/xCAT-server/lib/xcat/plugins/nimol.pm new file mode 100644 index 000000000..7491d6c09 --- /dev/null +++ b/xCAT-server/lib/xcat/plugins/nimol.pm @@ -0,0 +1,534 @@ +# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html + +# This module is only used for provisionging VIOS partition through rh MN. + +package xCAT_plugin::nimol; +BEGIN +{ + $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; +} +use lib "$::XCATROOT/lib/perl"; + +use strict; + +use POSIX qw(WNOHANG nice); +use POSIX qw(WNOHANG setsid :errno_h); +use File::Path; +use File::Copy; +use Fcntl qw/:flock/; + +#use Data::Dumper; +use Getopt::Long; +Getopt::Long::Configure("bundling"); +Getopt::Long::Configure("pass_through"); + +use xCAT::Table; +use xCAT::MsgUtils; +use xCAT::DBobjUtils; + +sub handled_commands { + return { + copycd => "nimol", + nodeset => "noderes:netboot", + }; +} + +my $global_callback; +sub copy_mksysb { + my $srcpath = shift; + my $dstpath = shift; + my @mksysb_files = (); + my %filehash = (); + my $dstfile = $dstpath."/mksysb/mksysb"; + unless (-e $srcpath."/nimol/ioserver_res/") { + return "No mksysb files found in this CD."; + } + unless (-e $dstpath."/mksysb") { + return "No mksysb directory available in $dstpath."; + } + #my $all_filesize = 0; + my $dir; + opendir($dir, $srcpath."/nimol/ioserver_res/"); + while (my $file = readdir($dir)) { + if ($file =~ /^mksysb/) { + $filehash{$file} = 1; + #my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = $stat($file); + #$all_filesize += $size / 1024 / 1024; + } + } + closedir($dir); + @mksysb_files = sort (keys %filehash); + foreach (@mksysb_files) { + my $rsp; + push @{$rsp->{data}}, "Copying file $_ to $dstfile"; + xCAT::MsgUtils->message("I", $rsp, $global_callback); + system("cat $srcpath/nimol/ioserver_res/$_ >> $dstfile"); + } + return undef; +} +sub copy_spot { + my $srcpath = shift; + my $dstpath = shift; + my $srcfile = $srcpath."/nimol/ioserver_res/ispot.tar.Z"; + my $dstfile = $dstpath."/spot/ispot.tar.Z"; + unless (-e $srcfile) { + return "No spot file found in this CD."; + } + if (-e $dstfile) { + return undef; + } + my $rsp; + push @{$rsp->{data}}, "Copying ispot.tar.z to $dstfile"; + xCAT::MsgUtils->message("I", $rsp, $global_callback); + + copy($srcfile, $dstfile); + xCAT::MsgUtils->message("I", {data=>["Extract file: $dstfile"]}, $global_callback); + system("/bin/tar zxvf $dstfile -C $dstpath/spot > /dev/null"); + return undef; +} +sub copy_bootimg { + my $srcpath = shift; + my $dstpath = shift; + my $srcfile = $srcpath."/nimol/ioserver_res/booti.chrp.mp.ent.Z"; + my $dstfile = $dstpath."/bootimg/booti.chrp.mp.ent.Z"; + unless (-e $srcfile) { + return "No bootimg file found in this CD."; + } + if (-e $dstfile) { + return undef; + } + my $rsp; + push @{$rsp->{data}}, "Copying file booti.chrp.mp.ent.Z to $dstfile"; + xCAT::MsgUtils->message("I", $rsp, $global_callback); + copy($srcfile, $dstfile); + xCAT::MsgUtils->message("I", {data=>["Extract file: $dstfile"]}, $global_callback); + system("/bin/gunzip $dstfile > /dev/null"); + + return undef; +} +sub copy_bosinstdata { + my $srcpath = shift; + my $dstpath = shift; + my $srcfile = $srcpath."/nimol/ioserver_res/bosinst.data"; + my $dstfile = $dstpath."/bosinst_data/bosinst.data"; + unless (-e $srcfile) { + return "No bosinst.data file found in this CD."; + } + if (-e $dstfile) { + return undef; + } + my $rsp; + push @{$rsp->{data}}, "Copying file bosinst.data to $dstfile"; + xCAT::MsgUtils->message("I", $rsp, $global_callback); + copy($srcfile, $dstfile); + return undef; +} +sub preprocess_request { + my $request = shift; + my $callback = shift; + my $command = $request->{command}->[0]; + + if ($command eq 'copycd') { + return [$request]; + } elsif ($command eq 'nodeset') { + my @args = (); + if (ref($request->{arg})) { + @args=@{$request->{arg}}; + } else { + @args=($request->{arg}); + } + if ($args[0] =~ /^osimage=(.*)$/) { + $request->{opt}->{osimage} = $1; + } else { + $callback->({error=>["Only option 'osimage' support"]}, errorcode=>[1]); + $request = {}; + return; + } + #print Dumper($request); + return [$request]; + } + + return undef; +} + +sub process_request { + my $request = shift; + my $callback = shift; + my $subreq = shift; + my $command = $request->{command}->[0]; + + if ($command eq 'copycd') { + return copycd($request, $callback, $subreq); + } elsif ($command eq 'nodeset') { + #print Dumper($request); + return nodeset($request, $callback, $subreq); + } +} + +sub copycd { + my $request = shift; + my $callback = shift; + my $subreq = shift; + @ARGV = @{$request->{arg}}; + $global_callback = $callback; +# copycd +# -m mntpath +# -p path +# -i inspection +# -a arch +# -f $file +# -w nonoverwrite + my $mntpath; + my $file; + my $distname; + my $path; + my $arch; + GetOptions( 'm=s' => \$mntpath, + 'a=s' => \$arch, + 'f=s' => \$file, + 'p=s' => \$path, + 'n=s' => \$distname, + ); + unless($distname && $file && $mntpath && $arch) { + $callback->({error=>"distname, file or mntpath not specified, $distname, $file, $mntpath"}); + return ; + } + if ($distname && $distname !~ /^vios/i) { + $callback->({error=>"distname incorrect"}); + return ; + } elsif ($arch !~ /^ppc64/i) { + $callback->({error=>"arch incorrect"}); + } elsif (!$file) { + $callback->({error=>"Only suport to use the iso file vios"}); + return; + } + #print __LINE__."=====>vios=====.\n"; + #print Dumper($request); + my $installroot = "/install"; + my @entries = xCAT::TableUtils->get_site_attribute("installdir"); + my $t_entry = $entries[0]; + if (defined($t_entry)) { + $installroot = $t_entry; + } + # OSLEVEL= 6.1.8.15 + #my $oslevel; + #if (-r "$mntpath/OSLEVEL" and -f "$mntpath/OSLEVEL") { + # my $oslevel_fd; + # open ($mkcd_fd, $mntpath."/OSLEVEL"); + # my $line = <$mkcd_fd>; + # if ($line =~ /^OSLEVEL=\s*(\d*\.\d*\.\d*\.\d*)/) { + # $oslevel_fd = $1; + # } + #} else { + # $callback->({error=>"There is no 'OSLEVEL' file found for this iso file"}); + # return; + #} + my $rsp; + push @{$rsp->{data}}, "Copying media to $installroot/nim/$distname/"; + xCAT::MsgUtils->message("I", $rsp, $callback); + unless($path) { + $path = "$installroot/nim/$distname"; + } + my $omask = umask 0022; + # check the disk number, the 1st or 2nd CD + unless (-e $path) { + mkpath("$path"); + } + unless (-e $path."/mksysb") { + mkpath($path."/mksysb"); + } + unless (-e $path."/spot") { + mkpath($path."/spot"); + } + unless (-e $path."/bootimg") { + mkpath($path."/bootimg"); + } + unless (-e $path."/bosinst_data") { + mkpath($path."/bosinst_data"); + } + umask $omask; + my $expect_cd; + my $oslevel; + unless (-e "$path/expect_cd") { + $expect_cd = 1; + } else { + my $expectcd_fd; + open ($expectcd_fd, "<", "$path/expect_cd"); + $expect_cd = <$expectcd_fd>; + chomp($expect_cd); + close($expectcd_fd); + } + if ($expect_cd eq "END") { + #goto CREATE_OBJ; + $callback->({error=>"All the cds for $distname are gotten."}); + return; + } + if (-r "$mntpath/mkcd.data" and -f "$mntpath/mkcd.data") { + my $mkcd_fd; + open ($mkcd_fd, "<", "$mntpath/mkcd.data"); + while (<$mkcd_fd>) { + if (/VOLUME=(\d+)/) { + if ($expect_cd ne $1) { + $callback->({error=>"The $expect_cd cd is expected."}); + return; + } else { + $expect_cd += 1; + } + } elsif (/LASTVOLUME/) { + $expect_cd = "END"; + } + } + close($mkcd_fd); + } else { + $callback->({error=>"There is no 'mkcd' file found for this iso file"}); + return; + } + { # write the expect cd num + my $expectcd_fd; + open ($expectcd_fd, ">", "$path/expect_cd"); + print $expectcd_fd $expect_cd; + close ($expectcd_fd); + } + { + my $oslevel_fd; + open($oslevel_fd, "<", "$mntpath/OSLEVEL"); + $oslevel = <$oslevel_fd>; + chomp $oslevel; + $oslevel =~ s/OSLEVEL=\s*(\d+\.\d+\.\d+\.\d+)/$1/; + close($oslevel_fd); + } + my $res; + $res = ©_mksysb($mntpath, $path); + if (defined($res)) { + $callback->({error=>$res}); + return; + } + $res = ©_spot($mntpath, $path); + if (defined($res)) { + $callback->({error=>$res}); + return; + } + $res = ©_bootimg($mntpath, $path); + if (defined($res)) { + $callback->({error=>$res}); + return; + } + $res = ©_bosinstdata($mntpath, $path); + if (defined($res)) { + $callback->({error=>$res}); + return; + } + #CREATE_OBJ: + if ($expect_cd eq "END") { + my $imagename = $distname.'_sysb'; + xCAT::MsgUtils->message("I", {data=>["create osimage object: $imagename"]}, $callback); + my $osimagetab = xCAT::Table->new('osimage', -create=>1); + if ($osimagetab) { + my %key_col = (imagename=>$imagename); + my %tb_cols = (imagetype=>"NIM", + provmethod=>"nimol", + osname=>"AIX", + osdistroname=>$distname, + osvers=>$oslevel, + osarch=>$arch); + #print Dumper(%tb_cols); + $osimagetab->setAttribs(\%key_col, \%tb_cols); + } else { + $callback->({error=>"Can not open 'osimage' table"}); + return; + } + $osimagetab->close(); + } +} + +sub update_export { + my $export_fd; + open ($export_fd, "<", "/etc/exports"); + flock($export_fd,LOCK_SH); + my @curr_export=<$export_fd>; + flock($export_fd,LOCK_UN); + close($export_fd); + my @new_export = (); + my $need_update = 0; + my $i = 0; + for ($i = 0; $i < scalar(@curr_export); $i++) { + my $line = $curr_export[$i]; + if ($line =~ /^\/install\s*\*\((.*)\)/) { + my @tmp_options = split /,/,$1; + unless (grep(/insecure/,@tmp_options)) { + push @tmp_options, "insecure"; + $need_update = 1; + } + push @new_export, join(',',@tmp_options); + } else { + push @new_export, $line; + } + } + unless ($need_update) { + return; + } + my $new_export_fd; + open($new_export_fd, ">>", "/etc/exports"); + flock($new_export_fd,LOCK_EX); + seek($new_export_fd,0,0); + truncate($new_export_fd,0); + for my $l (@new_export) { print $new_export_fd $l; } + flock($new_export_fd,LOCK_UN); + close($new_export_fd); + system("service nfs restart"); +} + +sub update_syslog { + my $syslog_fd; + open ($syslog_fd, "<", "/etc/rsyslog.conf"); + flock($syslog_fd,LOCK_SH); + my @curr_syslog=<$syslog_fd>; + flock($syslog_fd,LOCK_UN); + close($syslog_fd); + unless (grep /local2.*nimol\.log/, @curr_syslog) { + my $new_syslog_fd; + open($new_syslog_fd, ">>", "/etc/exports"); + print $new_syslog_fd "local2.* /var/log/nimol.log\n"; + close($new_syslog_fd); + system("service rsyslog restart"); + } else { + print "Don't need to update syslog configure file.\n"; + } +} + + + +sub create_imgconf_file { + my $nodes = shift; + my $subreq = shift; + my $nim_root = shift; + my $bootimg_root = shift; + my $relative_path = $bootimg_root; + $relative_path =~ s/^\/tftpboot//; + # Get nodes network information + my %nethash = (); + %nethash = xCAT::DBobjUtils->getNetwkInfo($nodes); + my $rootpw = undef; + my $passwdtab = xCAT::Table->new('passwd'); + if ($passwdtab) { + my $et = $passwdtab->getAttribs({key => 'system', username => 'root'}, 'password'); + if ($et and defined ($et->{'password'})) { + $rootpw = $et->{'password'}; + } + } + unless (defined($rootpw)) { + return "Unable to find requested password from passwd, with key=system,username=root"; + } + unless (-e $bootimg_root."/viobootimg") { + return "Unable to find VIOS bootimg file"; + } + chdir($bootimg_root); + foreach my $node (@$nodes) { + my $bootimg_conf_fd; + my $gateway = $nethash{$node}{gateway}; + my $mask = $nethash{$node}{mask}; + my $gateway_ip = xCAT::NetworkUtils->getipaddr($gateway); + my $master_node = xCAT::TableUtils->GetMasterNodeName($node); + my $master = xCAT::NetworkUtils->gethostname($master_node); + my $master_ip = xCAT::NetworkUtils->getipaddr($master); + my $node_ip = xCAT::NetworkUtils->getipaddr($node); + my $relative_bootfile = $relative_path."/viobootimg-$node"; + unless (-e "viobootimg-$node") { + symlink("viobootimg", "viobootimg-$node"); + } + if (-e $bootimg_root."/viobootimg-$node.info") { + unlink($bootimg_root."/viobootimg-$node.info"); + } + open ($bootimg_conf_fd, ">", $bootimg_root."/viobootimg-$node.info"); + print $bootimg_conf_fd "export NIM_SERVER_TYPE=linux\n"; + print $bootimg_conf_fd "export NIM_SYSLOG_PORT=514\n"; + print $bootimg_conf_fd "export NIM_SYSLOG_FACILITY=local2\n"; + print $bootimg_conf_fd "export NIM_NAME=viobootimg-$node\n"; + print $bootimg_conf_fd "export NIM_HOSTNAME=$node\n"; + print $bootimg_conf_fd "export NIM_CONFIGURATION=standalone\n"; + print $bootimg_conf_fd "export NIM_MASTER_HOSTNAME=$master\n"; + print $bootimg_conf_fd "export REMAIN_NIM_CLIENT=no\n"; + print $bootimg_conf_fd "export RC_CONFIG=rc.bos_inst\n"; + print $bootimg_conf_fd "export NIM_BOSINST_ENV=\"/../SPOT/usr/lpp/bos.sysmgt/nim/methods/c_bosinst_env\"\n"; + print $bootimg_conf_fd "export NIM_BOSINST_RECOVER=\"/../SPOT/usr/lpp/bos.sysmgt/nim/methods/c_bosinst_env -a hostname=$node\"\n"; + print $bootimg_conf_fd "export NIM_BOSINST_DATA=/NIM_BOSINST_DATA\n"; + print $bootimg_conf_fd "export SPOT=$master:$nim_root/spot/SPOT/usr\n"; + print $bootimg_conf_fd "export NIM_CUSTOM=\"/../SPOT/usr/lpp/bos.sysmgt/nim/methods/c_script -a location=$master:$nim_root/scripts/xcatvio.script\"\n"; + print $bootimg_conf_fd "export NIM_BOS_IMAGE=/NIM_BOS_IMAGE\n"; + print $bootimg_conf_fd "export NIM_BOS_FORMAT=mksysb\n"; + print $bootimg_conf_fd "export NIM_HOSTS=\" $node_ip:$node $master_ip:$master \"\n"; + print $bootimg_conf_fd "export NIM_MOUNTS=\" $master:$nim_root/bosinst_data/bosinst.data:/NIM_BOSINST_DATA:file $master:$nim_root/mksysb/mksysb:/NIM_BOS_IMAGE:file \"\n"; + print $bootimg_conf_fd "export ROUTES=\" default:0:$gateway_ip \"\n"; + print $bootimg_conf_fd "export NIM_IPADDR=$node_ip\n"; + print $bootimg_conf_fd "export NIM_NETMASK=$mask\n"; + print $bootimg_conf_fd "export PADMIN_PASSWD=$rootpw\n"; + print $bootimg_conf_fd "export SEA_ADAPTERS=bootnic\n"; + close($bootimg_conf_fd); + + $subreq->({command=>['makedhcp'], + node=>[$node], + arg=>['-s', 'supersede server.filename=\"'.$relative_bootfile.'\";']}, $global_callback); + } +} + +sub nodeset { + my $request = shift; + my $callback = shift; + my $subreq = shift; + + my $command = $request->{command}->[0]; + my $args = $request->{arg}; + my $nodes = $request->{node}; + + my $osimage = $request->{opt}->{osimage}; + my $nim_root; + my $bootimg_root; + unless ($osimage) { + $callback->({error=>["No param specified."], errorcode=>[1]}); + return; + } + { + my $installroot = "/install"; + my @entries = xCAT::TableUtils->get_site_attribute("installdir"); + my $t_entry = $entries[0]; + if (defined($t_entry)) { + $installroot = $t_entry; + } + + my $osimagetab = xCAT::Table->new('osimage'); + (my $ref) = $osimagetab->getAttribs({imagename=>$osimage}, 'osdistroname', 'provmethod'); + if ($ref) { + if ($ref->{provmethod} and $ref->{provmethod} eq 'nimol' and $ref->{osdistroname}) { + $nim_root = $installroot."/nim/".$ref->{osdistroname}; + $bootimg_root = "/tftpboot/".$ref->{osdistroname}."/nodes"; + } else { + $callback->({error=>["The 'provmethod' for OS image $osimage can only be 'nimol'."], errorcode=>[1]}); + return; + } + } else { + $callback->({error=>["No OS image $osimage found on the osimage table."], errorcode=>[1]}); + return; + } + } + + update_export(); + update_syslog(); + unless (-e $bootimg_root) { + mkpath($bootimg_root); + copy($nim_root."/bootimg/booti.chrp.mp.ent", $bootimg_root."/viobootimg"); + } + + unless (-e $nim_root."/scripts/xcatvio.script") { + mkpath($nim_root."/scripts/"); + copy($::XCATROOT."/share/xcat/scripts/xcatvio.script", $nim_root."/scripts/"); + } + + my $res = &create_imgconf_file($nodes, $subreq, $nim_root, $bootimg_root); + if ($res) { + $callback->({error=>["$res"], errorcode=>[1]}); + return; + } +} + + +1; diff --git a/xCAT-server/lib/xcat/plugins/profilednodes.pm b/xCAT-server/lib/xcat/plugins/profilednodes.pm index 863ebb8a2..de0e3980c 100644 --- a/xCAT-server/lib/xcat/plugins/profilednodes.pm +++ b/xCAT-server/lib/xcat/plugins/profilednodes.pm @@ -19,6 +19,7 @@ require xCAT::Utils; require xCAT::TableUtils; require xCAT::NetworkUtils; require xCAT::MsgUtils; +require xCAT::CFMUtils; require xCAT::ProfiledNodeUtils; # Globals. @@ -481,7 +482,7 @@ Usage: $warnstr = "Warning: failed to import some nodes."; setrsp_progress($warnstr); } - + setrsp_progress("Configuring nodes..."); my $retref = xCAT::Utils->runxcmd({command=>["kitnodeadd"], node=>\@nodelist, sequential=>[1], macflag=>[$mac_addr_mode]}, $request_command, 0, 2); my $retstrref = parse_runxcmd_ret($retref); @@ -1686,6 +1687,15 @@ sub gen_new_hostinfo_dict{ # Get node's provisioning method my $provmethod = xCAT::ProfiledNodeUtils->get_imageprofile_prov_method($args_dict{'imageprofile'}); + # start to check windows nodes, product will indicate it is a windows node: win2k8r2.enterprise + my ($osvers, $osprofile) = xCAT::ProfiledNodeUtils->get_imageprofile_prov_osvers($provmethod); + my $product = undef; + if ($osvers =~ /^win/) + { + $product = "$osvers.$osprofile"; + } + + # Check whether this is Power env. my $is_fsp = xCAT::ProfiledNodeUtils->is_fsp_node($args_dict{'networkprofile'}); @@ -1747,6 +1757,18 @@ sub gen_new_hostinfo_dict{ } $hostinfo_dict{$item}{"nicips"} = $nicips; + #save for windows node + if(defined($product) && exists($hostinfo_dict{$item}{"prodkey"})) + { + if(defined($hostinfo_dict{$item}{"prodkey"})) + { + my $rst = xCAT::ProfiledNodeUtils->update_windows_prodkey($item, $product, $hostinfo_dict{$item}{"prodkey"}); + if($rst == 1) + { + return 0, "Test Store windows per-node key failed for node: $item"; + } + } + } $hostinfo_dict{$item}{"objtype"} = "node"; $hostinfo_dict{$item}{"groups"} = "__Managed"; if (exists $args_dict{'networkprofile'}){$hostinfo_dict{$item}{"groups"} .= ",".$args_dict{'networkprofile'}} @@ -2056,7 +2078,7 @@ sub validate_node_entry{ $errmsg .= "Node name $node_name already exists. You must use a new node name.\n"; } # Must specify either MAC or switch + port. - if (exists $node_entry{"mac"} || + if (exists $node_entry{"mac"} || exists $node_entry{"switch"} && exists $node_entry{"switchport"}){ } else{ $errmsg .= "MAC address, switch and port is not specified. You must specify the MAC address or switch and port.\n"; @@ -2090,6 +2112,20 @@ sub validate_node_entry{ #push the IP into allips list. $allips{$node_entry{$_}} = 0; } + }elsif ($_ eq "prodkey"){ + # Get node's provisioning os version + my $osimagename = xCAT::ProfiledNodeUtils->get_imageprofile_prov_method($args_dict{'imageprofile'}); + my ($osvers, $profile) = xCAT::ProfiledNodeUtils->get_imageprofile_prov_osvers($osimagename); + if (!($osvers =~ /^win/)){ + $errmsg .= "Specified Windows per-node key to a non-windows node is not acceptable\n"; + } + + # it will handle windows pernode key + if (!($node_entry{$_} =~ /\w{5}-\w{5}-\w{5}-\w{5}-\w{5}/)){ + $errmsg .= "Specified Windows per-node key $node_entry{$_} is not valid\n"; + } + #Transfer to capital + $node_entry{$_} = uc $node_entry{$_}; }elsif ($_ eq "switch"){ #TODO: xCAT switch discovery enhance: verify whether switch exists. if (! exists $allswitches{$node_entry{$_}}){ diff --git a/xCAT-server/share/xcat/netboot/rh/genimage b/xCAT-server/share/xcat/netboot/rh/genimage index 2d4736e7a..52fd168ff 100755 --- a/xCAT-server/share/xcat/netboot/rh/genimage +++ b/xCAT-server/share/xcat/netboot/rh/genimage @@ -231,8 +231,16 @@ unless ($onlyinitrd) { exit 1; } + + mkpath "$rootimg_dir"; my $yumconfig; open($yumconfig,">","/tmp/genimage.$$.yum.conf"); + + #yum/rpm/zypper has defect on calculating diskspace usage when installing rpm on a NFS mounted installroot + if(isNFSdir("$rootimg_dir")){ + print $yumconfig "[main]\ndiskspacecheck=0\n\n"; + } + my $repnum=0; foreach $srcdir (@yumdirs) { print $yumconfig "[$osver-$arch-$repnum]\nname=$osver-$arch-$repnum\nbaseurl=file://$srcdir\ngpgpcheck=0\n\n"; @@ -252,10 +260,6 @@ unless ($onlyinitrd) { if (!$prompt) { $non_interactive="-y"; } my $yumcmd = "yum $non_interactive -c /tmp/genimage.$$.yum.conf --installroot=$rootimg_dir/ --disablerepo=* "; - #yum/rpm/zypper has defect on calculating diskspace usage when installing rpm on a NFS mounted installroot - if(isNFSdir("$rootimg_dir")){ - $yumcmd .= "--setopt=diskspacecheck=0 "; - } foreach (0..$repnum) { $yumcmd .= "--enablerepo=$osver-$arch-$_ "; diff --git a/xCAT-server/share/xcat/scripts/xcatvio.script b/xCAT-server/share/xcat/scripts/xcatvio.script new file mode 100755 index 000000000..61efa1390 --- /dev/null +++ b/xCAT-server/share/xcat/scripts/xcatvio.script @@ -0,0 +1,382 @@ +#!/usr/bin/env perl -w +# IBM(c) 2013 EPL license http://www.eclipse.org/legal/epl-v10.html +##################################################### +# +# xCAT script resource for VIOS installation +# +##################################################### + +use File::Path; +use Getopt::Long; + +# script file name +$::script = $0; +$::script =~ s/.*\///; + +##################################################### +# +# run the command +# +##################################################### + +sub runcmd +{ + my ($cmd) = @_; + my $rc=0; + $cmd .= ' 2>&1' ; + msg("Running command $cmd"); + $::outref = `$cmd`; + if ($?) + { + $rc = $? >> 8; + if ($rc > 0) + { + print "$::sdate $0: $::outref\n"; + print $::LOG_FILE "$::sdate $0: $::outref\n"; + } + } + return $rc; +} + +sub msg +{ + my $str = shift; + $sdate = `/bin/date`; + chomp $sdate; + print "$sdate $::script $str\n"; + print $::LOG_FILE "$sdate $::script $str\n"; +} + + +# since we don't have syslog set up yet we'll +# just save msgs in a local log file +$logdir = "/var/log/xcat"; + +if (!-d $logdir) { + mkpath($logdir); +} + +my $logfile = $logdir . "/xcat.log"; +# this log should not contain much so it might be ok to let it grow? +# at least we'll have the errors preserved +open(LOGFILE,">>",$logfile); +$::LOG_FILE = \*LOGFILE; +foreach my $env (keys %ENV) +{ + msg("ENV{$env} = $ENV{$env}"); +} + +my $cmd; +my $hostname; +my $ipaddr; +my $servnode; +# TODO: use the environment variable instead of reading /etc/niminfo +# get the name of my service node/NIM master from the /etc/niminfo file + +if (-f "/etc/niminfo") { + + $cmd = "/bin/cat /etc/niminfo | /bin/grep 'NIM_HOSTNAME'"; + &runcmd($cmd); + my $hostline = $::outref; + my $junk; + ($junk, $hostname) = split(/=/, $hostline); + $hostname =~ s/^\s*//; + chomp $hostname; + msg("Info: the hostname is $hostname"); + + $cmd = "host $hostname"; + &runcmd($cmd); + $ipaddr = $::outref; + $ipaddr =~ s/.*is\s+//; + chomp $ipaddr; + msg("Info: the ip address is $ipaddr"); + + $cmd = "/bin/cat /etc/niminfo | /bin/grep 'NIM_MASTER_HOSTNAME'"; + &runcmd($cmd); + my $SNline = $::outref; + ($junk, $servnode) = split(/=/, $SNline); + $servnode =~ s/^\s*//; + chomp $servnode; + + + my $xcatinfo="/etc/xcatinfo"; + open(XCATINFO,">",$xcatinfo); + print XCATINFO "XCATSERVER=$servnode\n"; + close(XCATINFO); +} else { + msg("Error: could not find /etc/niminfo file, exiting..."); + exit 1; +} +# Configure TCP/IP +# Get the boot nic +my $bootnic; +if (defined($ENV{'BOOTDEV'})) +{ + $bootnic = $ENV{'BOOTDEV'}; +} +if (!$bootnic) +{ + $cmd = "/usr/sbin/bootinfo -b"; + if (&runcmd($cmd) != 0) { + msg("Error: could not get the boot nic, exiting..."); + exit 1; + } + $bootnic = $::outref; + chomp $bootnic; +} + +msg("Info: bootnic is $bootnic"); +my $skiptcpip = 0; +if ($bootnic !~ /^en/) +{ + msg("Error: bootnic $bootnic is not a nic, skipping the TCP/IP configuration"); + $skiptcpip = 1; +} + +$cmd = "lsdev -C -l $bootnic"; +if (&runcmd($cmd) != 0) { + msg("Warning: could not get information for $bootnic, skipping the TCP/IP configuration"); + $skiptcpip = 1; +} +my @vir_nic = (); +$cmd = qq~lsdev -c adapter \| grep ent \| grep "Virtual I\/O Ethernet Adapter" \| awk -F ' ' '{print \$1}'~; +if (&runcmd($cmd) != 0) { + msg("Warning: could not find virtual I/O Ethernet Adapter"); + msg("Error: $::outref"); + $skiptcpip = 1; +} else { + if (!grep(/ent/, $::outref)) { + msg("Error($cmd): $::outref"); + $skiptcpip = 1; + } else { + @vir_nic = sort (split(/\n/, $::outref)); + msg("Find virtual NIC: @vir_nic"); + } +} + +my %sea_adapters = (); +if (defined($ENV{'SEA_ADAPTERS'}) and $ENV{'SEA_ADAPTERS'} =~ /bootnic/i) { + msg("Info: Environment variable SEA_ADAPTERS is $ENV{'SEA_ADAPTERS'}"); + if (scalar(@vir_nic) == 0) { + msg("Warning: No Virtual Ethernet Adapter found"); + $skiptcpip = 1; + } else { + my $xcatinfo="/etc/xcatinfo"; + open(XCATINFO,">>",$xcatinfo); + print XCATINFO "SEA_ADAPTERS=$bootnic:$vir_nic[0]:1:$ENV{'NIM_IPADDR'}:$ENV{'NIM_NETMASK'}:$hostname\n"; + close(XCATINFO); + + my $lsicmd = "/usr/sbin/lsitab bootnicsea > /dev/null 2>&1"; + if (&runcmd($lsicmd) != 0) { + my $mkicmd = '/usr/sbin/mkitab "bootnicsea:2:wait:/xcatpost/config_bootnicsea > /dev/console 2>&1"'; + if (&runcmd($mkicmd) != 0) { + msg("Warning: config_bootnicsea: Could not add config_bootnicsea to /etc/inittab.\n") + } + } + + } +} elsif (defined($ENV{'SEA_ADAPTERS'})) { + msg("Info: Environment variable SEA_ADAPTERS is $ENV{'SEA_ADAPTERS'}"); + my @sea_array = split(/\s+/, $ENV{'SEA_ADAPTERS'}); + foreach my $sea (@sea_array) + { + my ($phy, $virt, $vlan, $ip, $mask) = split(/:/, $sea); + if (!$phy || !$virt || !$vlan) + { + msg("Warning: incorrect SEA_ADAPTERS format, the syntax is physcial_adapter:virtual_adapter:vlan_id:ip_addr:netmask, where the ip_addr and netmask could be blank if you do not want to configure ip for this SEA adapter, skipping TCP/IP configuration"); + $skiptcpip = 1; + last; + } + $sea_adapters{$phy}{'phy'} = $phy; + $sea_adapters{$phy}{'virt'} = $virt; + $sea_adapters{$phy}{'vlan'} = $vlan; + $sea_adapters{$phy}{'ip'} = $ip; + $sea_adapters{$phy}{'mask'} = $mask; + } +} else { + msg("Info: The environment variable SEA_ADAPTERS is not defined"); +} + +if (!$skiptcpip) { + my $bootnicsea = 0; + my $netmask; + if (defined($ENV{'NIM_NETMASK'})) + { + $netmask = $ENV{'NIM_NETMASK'}; + } + if (!$netmask) + { + msg("Warning: NIM_NETMASK is not specified, using the default 255.255.255.0"); + $netmask = "255.255.255.0"; + } + + foreach my $phy (keys %sea_adapters) + { + my $phy = $sea_adapters{$phy}{'phy'}; + my $virt = $sea_adapters{$phy}{'virt'}; + my $vlan = $sea_adapters{$phy}{'vlan'}; + my $ip = $sea_adapters{$phy}{'ip'}; + my $mask = $sea_adapters{$phy}{'mask'}; + if ($phy eq $bootnic) + { + $bootnicsea = 1; + } + { + $cmd = "/usr/ios/cli/ioscli license -swma"; + &runcmd($cmd); + $cmd = "/usr/ios/cli/ioscli license -accept"; + &runcmd($cmd); + } + { # detach bootnic + if ($bootnicsea and $phy =~ /^ent(\d+)/) { + my $phynic_id = $1; + my $en_nic = "en".$phynic_id; + my $ent_nic = "ent".$phynic_id; + my $et_nic = "et".$phynic_id; + $cmd = "ifconfig $en_nic down; ifconfig $en_nic detach; rmdev -dl $en_nic; rmdev -dl $ent_nic; rmdev -dl $et_nic; cfgmgr;"; + if (&runcmd($cmd) != 0) { + msg("Error: could not detach bootnic:$bootnic"); + next; + } + } + + } + #$cmd = qq~su - padmin "-c ioscli license -accept; ioscli mkvdev -sea $phy -vadapter $virt -default $virt -defaultid $vlan"~; + $cmd = "/usr/ios/cli/ioscli mkvdev -sea $phy -vadapter $virt -default $virt -defaultid $vlan"; + if (&runcmd($cmd) != 0) { + msg("Error: could not create SEA with physical adapter $phy, virtual adapter $virt and vlan id $vlan"); + next; + } + my $sea_out = $::outref; + my $sea = undef; + my @out_array = split (/\n/, $sea_out); + foreach (@out_array) { + if (/(ent\d+)\s*Available/) { + $sea = $1; + $sea =~ s/t//; + } + } + unless ($sea) { + msg("Error: did not get available SEA adapter, $sea_out==="); + next; + } + msg("Info: The interface created with mkvdev is: $sea"); + #$cmd = qq~su - padmin "-c ioscli license -accept; ioscli mktcpip -hostname $hostname -inetaddr $ip -interface $sea -netmask $mask"~; + $cmd = "/usr/ios/cli/ioscli mktcpip -hostname $hostname -inetaddr $ip -interface $sea -netmask $mask"; + if (&runcmd($cmd) != 0) { + msg("Error: could not configure ip address for SEA $sea"); + } + } + + if (!$bootnicsea) + { + # ent1 -> en1 + if ($bootnic =~ /^ent/) + { + $bootnic =~ s/t//; + } + $cmd = "mktcpip -h \"$hostname\" -a $ipaddr -m $netmask -i $bootnic -A 'no' -t 'N/A' -s ''"; + if (&runcmd($cmd) != 0) { + msg("Error: could not configure IP for nic $bootnic, exiting ..."); + exit 1; + } + } +} + +# create the xcatpost dir +$cmd = "/bin/mkdir -m 755 -p /xcatpost"; +if (&runcmd($cmd) != 0) { + print "$::sdate xcataixscript: Could not make the /xcatpost directory.\n"; + print $::LOG_FILE "$::sdate xcataixscript: Could not make the /xcatpost directory.\n"; +} + +# Set a temporary root password +# - the user-provided root passwd will be set by xcataixpost +my $padmin_passwd; +if(defined($ENV{'PADMIN_PASSWD'})) +{ + $padmin_passwd = $ENV{'PADMIN_PASSWD'}; +} + +if(!$padmin_passwd) +{ + msg("Warning: padmin password is not specified, using the default password \"cluster\""); + $padmin_passwd = "cluster"; +} +my $pwcmd = qq~/bin/echo "padmin:$padmin_passwd" | /bin/chpasswd -c >/dev/null 2>&1~; +if (&runcmd($pwcmd) != 0) { + print "$::sdate xcatvio.script: Could not set password for padmin.\n"; + print $::LOG_FILE "$::sdate xcatvio.script: Could not set password for padmin.\n"; +} + +# The license accept does not work in postscript phase, +# should be done in postbootscript phase +# my $liccmd = qq~su - padmin "-c ioscli license -accept"~; +# if (&runcmd($liccmd) != 0) { +# msg("Error: failed to run license accept command"); +# } +# +# +# need fix to support INSTALLDIR !!!!! +# socket doesn't work at this point of install so need another +# way to get INSTALLDIR value!!! + +my $installdir; +if (!$installdir) { + $installdir="/install"; +} + +# get the contents of the $installdir/postscripts dir on the server +# - mount dir from server and copy files +# IPv6, should only use NFS version 4 mount + +my $mcmd; +my $snipcmd = "host $servnode"; +if (((&runcmd($snipcmd) == 0) && ($::outref =~ /:/)) || ($ENV{'USENFSV4ONAIX'} && ($ENV{'USENFSV4ONAIX'} =~ /1|Yes|yes|YES|Y|y/))) +{ + $mcmd = "mkdir -p /xcatmnt; mount -o nolock -o vers=4 $servnode:$installdir/postscripts /xcatmnt"; +} else { + $mcmd = "mkdir -p /xcatmnt; mount -o nolock $servnode:$installdir/postscripts /xcatmnt"; +} +if (&runcmd($mcmd) != 0) { + print "$::sdate xcataixscript: Could not mount $installdir/postscripts from $servnode.\n"; + print $::LOG_FILE "$::sdate xcataixscript: Could not mount $installdir/postscripts from $servnode.\n"; +} + +my $cpcmd; +if ((@ARGV==0) || ($ARGV[0] != 2)) { + $cpcmd = "/bin/cp -r /xcatmnt/* /xcatpost >/dev/null 2>&1"; +} else { +# when argv[1]=2, there is only one postscript file, +# user wants only download it to save time + $cpcmd= "/bin/cp /xcatmnt/$ARGV[1] /xcatpost >/dev/null 2>&1"; +} + +if (&runcmd($cpcmd) != 0) { + print "$::sdate xcataixscript: Could not copy postscripts to /xcatpost.\n"; + print $::LOG_FILE "$::sdate xcataixscript: Could not copy postscripts to /xcatpost.\n"; +} +# make sure all are executable + +my $chcmd = "/bin/chmod +x /xcatpost/*"; +if (&runcmd($chcmd) != 0) { + print "$::sdate xcataixscript: Could not change /xcatpost file permissions.\n"; + print $::LOG_FILE "$::sdate xcataixscript: Could not change /xcatpost file permissions.\n"; +} + +my $ucmd = "/usr/sbin/umount /xcatmnt; /bin/rmdir /xcatmnt"; +if (&runcmd($ucmd) != 0) { + print "$::sdate xcataixscript: Could not unmount $installdir.\n"; + print $::LOG_FILE "$::sdate xcataixscript: Could not unmount $installdir/postscripts.\n"; +} + +# Setup remote shell +if (-f "/xcatpost/_ssh/authorized_keys") +{ + runcmd("cat /xcatpost/_ssh/authorized_keys >> /home/padmin/.ssh/authorized_keys2"); +} +close($::LOG_FILE); + +exit 0; + + diff --git a/xCAT-server/xCAT-wsapi/xcatws.cgi b/xCAT-server/xCAT-wsapi/xcatws.cgi index 9fabf3bdb..0694bbc94 100755 --- a/xCAT-server/xCAT-wsapi/xcatws.cgi +++ b/xCAT-server/xCAT-wsapi/xcatws.cgi @@ -1,7 +1,7 @@ #!/usr/bin/perl use strict; use CGI qw/:standard/; -#use JSON; # require this dynamically later on so that installations that do not use xcatws.cgi do not need perl-JSON +use JSON; # require this dynamically later on so that installations that do not use xcatws.cgi do not need perl-JSON use Data::Dumper; #added the line: diff --git a/xCAT-test/autotest/testcase/installation/ubuntu_diskless_installation_vm b/xCAT-test/autotest/testcase/installation/ubuntu_diskless_installation_vm new file mode 100644 index 000000000..fcd22eb84 --- /dev/null +++ b/xCAT-test/autotest/testcase/installation/ubuntu_diskless_installation_vm @@ -0,0 +1,56 @@ +start:Ubuntu_diskless_installation_flat_x86_vm +os:Linux +cmd:makedns -n +check:rc==0 +cmd:makeconservercf $$CN +check:rc==0 +cmd:chdef $$CN servicenode= xcatmaster= +cmd:cat /etc/conserver.cf | grep $$CN +check:output=~$$CN +cmd:sleep 60 +cmd:makedhcp -n +check:rc==0 +cmd:makedhcp -a +check:rc==0 +cmd:if [ ! -d /install/custom/netboot/ubuntu ]; then mkdir -p /install/custom/netboot/ubuntu; fi +check:rc==0 +cmd:if [ ! -e /install/custom/netboot/ubuntu/compute.synclist ]; then echo "/etc/resolv.conf -> /etc/resolv.conf" > /install/custom/netboot/ubuntu/compute.synclist; fi +check:rc==0 +cmd:chdef -t osimage -o __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute synclists=/install/custom/netboot/ubuntu/compute.synclist +cmd:rm -rf /install/netboot/__GETNODEATTR($$CN,os)__/x86_64/compute +check:rc==0 +cmd:genimage __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute +check:rc==0 +cmd:packimage __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute +check:rc==0 +cmd:nodeset $$CN osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-netboot-compute +check:rc==0 +cmd:rpower $$CN reset +check:rc==0 +cmd:sleep 200 +cmd:lsdef -l $$CN | grep status +check:output=~booted +cmd:xdsh $$CN date +check:rc==0 +check:output=~\d\d:\d\d:\d\d +cmd:nodeset $$CN osimage +check:rc==0 +cmd:rpower $$CN reset +check:rc==0 +cmd:sleep 200 +cmd:lsdef -l $$CN | grep status +check:output=~booted +cmd:xdsh $$CN date +check:rc==0 +check:output=~\d\d:\d\d:\d\d +cmd:nodeset $$CN netboot +check:rc==0 +cmd:rpower $$CN reset +check:rc==0 +cmd:sleep 200 +cmd:lsdef -l $$CN | grep status +check:output=~booted +cmd:xdsh $$CN date +check:rc==0 +check:output=~\d\d:\d\d:\d\d +end diff --git a/xCAT-test/autotest/testcase/installation/ubuntu_full_installation_vm b/xCAT-test/autotest/testcase/installation/ubuntu_full_installation_vm new file mode 100644 index 000000000..bf29b8f61 --- /dev/null +++ b/xCAT-test/autotest/testcase/installation/ubuntu_full_installation_vm @@ -0,0 +1,45 @@ +start:Ubuntu_full_installation_flat_x86_vm +os:Linux +cmd:makedns +check:rc==0 +cmd:service named restart +check:rc==0 +cmd:chdef $$CN servicenode= xcatmaster= +cmd:makeconservercf $$CN +check:rc==0 +cmd:cat /etc/conserver.cf | grep $$CN +check:output=~$$CN +cmd:sleep 60 +cmd:makedhcp -n +check:rc==0 +cmd:makedhcp -a +check:rc==0 +cmd:if [ ! -e /install/custom/netboot/ubuntu/compute.synclist ]; then echo "/etc/resolv.conf -> /etc/resolv.conf" > /install/custom/netboot/ubuntu/compute.synclist; fi +check:rc==0 +cmd:chdef -t osimage __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-compute synclists=/install/custom/install/ubuntu/compute.synclist +check:rc==0 +cmd:nodeset $$CN osimage=__GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-install-compute +check:rc==0 +cmd:rpower $$CN reset +check:rc==0 +cmd:sleep 2000 +cmd:ping $$CN -c 3 +check:output=~64 bytes from $$CN +cmd:lsdef -l $$CN | grep status +check:output=~booted +cmd:xdsh $$CN date +check:rc==0 +check:output=~\d\d:\d\d:\d\d +cmd:nodeset $$CN osimage +check:rc==0 +cmd:rpower $$CN reset +check:rc==0 +cmd:sleep 2000 +cmd:ping $$CN -c 3 +check:output=~64 bytes from $$CN +cmd:lsdef -l $$CN | grep status +check:output=~booted +cmd:xdsh $$CN date +check:rc==0 +check:output=~\d\d:\d\d:\d\d +end diff --git a/xCAT/debian/install b/xCAT/debian/install index b6975959d..edd37eb13 100644 --- a/xCAT/debian/install +++ b/xCAT/debian/install @@ -1,4 +1,5 @@ xcat.conf etc/apache2/conf.d/ +xcat.conf.apach24 etc/apache2/conf.d/ LICENSE.html opt/xcat/share/doc/packages/xCAT postscripts/* install/postscripts/ prescripts/* install/prescripts/ diff --git a/xCAT/debian/postinst b/xCAT/debian/postinst index 68a15f6a8..9215ea63b 100644 --- a/xCAT/debian/postinst +++ b/xCAT/debian/postinst @@ -40,6 +40,13 @@ case "$1" in else xcatconfig -i -d -s fi + ver=$(cat /etc/issue |awk '{print $2}') + num=${ver%.*} + file="xcat.conf.apach24" + if [ $num -gt 12 ];then + mv /etc/apache2/conf.d/xcat.conf.apach24 /etc/apache2/conf-enabled/ + fi + /etc/init.d/apache2 restart ;; diff --git a/xCAT/postscripts/config_bootnicsea b/xCAT/postscripts/config_bootnicsea new file mode 100644 index 000000000..45ae983b2 --- /dev/null +++ b/xCAT/postscripts/config_bootnicsea @@ -0,0 +1,143 @@ +#!/usr/bin/env perl -w + + +if ($^O =~ /^aix/i) { + unshift(@INC, qw(/usr/opt/perl5/lib/5.8.2/aix-thread-multi /usr/opt/perl5/lib/5.8.2 /usr/opt/perl5/lib/site_perl/5.8.2/aix-thread-multi /usr/opt/perl5/lib/site_perl/5.8.2)); +} + +use strict; +use File::Path; +use Getopt::Long; +# script file name +$::script = $0; +$::script =~ s/.*\///; +##################################################### +# +# run the command +# +##################################################### + +sub runcmd +{ + my ($cmd) = @_; + my $rc=0; + $cmd .= ' 2>&1' ; + msg("Running command $cmd"); + $::outref = `$cmd`; + if ($?) + { + $rc = $? >> 8; + if ($rc > 0) + { + print "$::sdate $0: $::outref\n"; + print $::LOG_FILE "$::sdate $0: $::outref\n"; + } + } + return $rc; +} + +sub msg +{ + my $str = shift; + $::sdate = `/bin/date`; + chomp $::sdate; + #print "$::sdate $::script $str\n"; + print $::LOG_FILE "$::sdate $::script $str\n"; +} + +my $cmd; + +my $logdir = "/var/log/xcat"; + +if (!-d $logdir) { + mkpath($logdir); +} + +my $logfile = $logdir . "/xcat.log"; +# this log should not contain much so it might be ok to let it grow? +# at least we'll have the errors preserved +open(LOGFILE,">>",$logfile); +$::LOG_FILE = \*LOGFILE; + +my $xcatinfo; +open($xcatinfo,"<","/etc/xcatinfo"); +my @sea_info = <$xcatinfo>; +close($xcatinfo); +my ($phy,$vir,$vlan,$ip,$mask,$host); +foreach my $sea_line (@sea_info) { + if ($sea_line =~ /SEA_ADAPTERS=(.*)$/) { + ($phy,$vir,$vlan,$ip,$mask,$host) = split (/:/,$1); + last; + } +} + +if (!$phy || !$vir || !$vlan) { + msg("Warning: incorrect SEA_ADAPTERS format, the syntax is physcial_adapter:virtual_adapter:vlan_id:ip_addr:netmask, where the ip_addr and netmask could be blank if you do not want to configure ip for this SEA adapter, skipping TCP/IP configuration"); + exit 1; +} else { + msg("Info: phy:$phy,vir:$vir,vlan:$vlan,ip:$ip-$mask, hostname:$host"); +} + +unless($mask) { + $mask = "255.255.255.0"; +} + +{ + #$cmd = "/usr/ios/cli/ioscli license -swma"; + #&runcmd($cmd); + $cmd = "/usr/ios/cli/ioscli license -accept"; + &runcmd($cmd); +} +{ # detach bootnic + if ($phy =~ /^ent(\d+)/) { + my $phynic_id = $1; + my $en_nic = "en".$phynic_id; + my $ent_nic = "ent".$phynic_id; + my $et_nic = "et".$phynic_id; + $cmd = "ifconfig $en_nic down; ifconfig $en_nic detach; rmdev -dl $en_nic; rmdev -dl $ent_nic; rmdev -dl $et_nic; cfgmgr;"; + if (&runcmd($cmd) != 0) { + msg("Error: could not detach nic:$phy"); + exit 1; + } + } +} +{ # create sea adapter and config it + #$cmd = qq~su - padmin "-c ioscli license -accept; ioscli mkvdev -sea $phy -vadapter $virt -default $virt -defaultid $vlan"~; + $cmd = "/usr/ios/cli/ioscli mkvdev -sea $phy -vadapter $vir -default $vir -defaultid $vlan"; + if (&runcmd($cmd) != 0) { + msg("Error: could not create SEA with physical adapter $phy, virtual adapter $vir and vlan id $vlan"); + exit 1; + } + my $sea_out = $::outref; + my $sea = undef; + my @out_array = split (/\n/, $sea_out); + foreach (@out_array) { + if (/(ent\d+)\s*Available/) { + $sea = $1; + $sea =~ s/t//; + } + } + unless ($sea) { + msg("Error: did not get available SEA adapter, $sea_out==="); + exit 1; + } + msg("Info: The interface created with mkvdev is: $sea"); + #$cmd = qq~su - padmin "-c ioscli license -accept; ioscli mktcpip -host $host -inetaddr $ip -interface $sea -netmask $mask"~; + $cmd = "/usr/ios/cli/ioscli mktcpip -hostname $host -inetaddr $ip -interface $sea -netmask $mask"; + if (&runcmd($cmd) != 0) { + msg("Error: could not configure ip address for SEA $sea"); + } +} + +{ + my $lsicmd = "/usr/sbin/lsitab bootnicsea > /dev/null 2>&1"; + if (&runcmd($lsicmd) == 0) { + my $rmicmd = 'rmitab "bootnicsea" > /dev/null 2>&1'; + if (&runcmd($rmicmd) != 0) { + msg("Warning: config_bootnicsea: Could not remove config_bootnicsea from /etc/inittab.\n") + } + } +} +close($::LOG_FILE); + +exit 0; diff --git a/xCAT/postscripts/confignics b/xCAT/postscripts/confignics index 0b2d607dd..79f88d867 100755 --- a/xCAT/postscripts/confignics +++ b/xCAT/postscripts/confignics @@ -282,7 +282,7 @@ do else if [ `echo $key | grep -E '(eth|en)[0-9]+'` ];then str_nic_type="ethernet" - elif [ `echo $KEY | grep -E 'ib[0-9]+'` ];then + elif [ `echo $key | grep -E 'ib[0-9]+'` ];then str_nic_type="infiniband" else logger -t xcat -p local4.info "confignics: unknown nic type for $key: $str_value ." diff --git a/xCAT/xcat.conf.apach24 b/xCAT/xcat.conf.apach24 new file mode 100644 index 000000000..d4e83370c --- /dev/null +++ b/xCAT/xcat.conf.apach24 @@ -0,0 +1,27 @@ +# +# This configuration file allows a diskfull install to access the install images +# via http. It also allows the xCAT documentation to be accessed via +# http://localhost/xcat-doc/ +# Updates to xCAT/xcat.conf should also be made to xCATsn/xcat.conf +# +AliasMatch ^/install/(.*)$ "/install/$1" +AliasMatch ^/tftpboot/(.*)$ "/tftpboot/$1" + + + Options Indexes FollowSymLinks Includes MultiViews + AllowOverride None + Require all granted + + + Options Indexes FollowSymLinks Includes MultiViews + AllowOverride None + Require all granted + + +Alias /xcat-doc "/opt/xcat/share/doc" + + Options Indexes + AllowOverride None + Require all granted + + diff --git a/xCATsn/debian/install b/xCATsn/debian/install index 9132f94f5..80345cbb2 100644 --- a/xCATsn/debian/install +++ b/xCATsn/debian/install @@ -1,3 +1,4 @@ LICENSE.html opt/xcat/share/doc/packages/xCAT xCATSN etc xcat.conf etc/apache2/conf.d +xcat.conf.apach24 etc/apache2/conf.d/ diff --git a/xCATsn/debian/postinst b/xCATsn/debian/postinst index ac91a1517..d90483185 100644 --- a/xCATsn/debian/postinst +++ b/xCATsn/debian/postinst @@ -28,6 +28,14 @@ case "$1" in rm /etc/xCATMN fi + ver=$(cat /etc/issue |awk '{print $2}') + num=${ver%.*} + file="xcat.conf.apach24" + if [ $num -gt 12 ];then + mv /etc/apache2/conf.d/xcat.conf.apach24 /etc/apache2/conf-enabled/ + fi + + apachedaemon='apache2' update-rc.d $apachedaemon enable diff --git a/xCATsn/xcat.conf.apach24 b/xCATsn/xcat.conf.apach24 new file mode 100644 index 000000000..d4e83370c --- /dev/null +++ b/xCATsn/xcat.conf.apach24 @@ -0,0 +1,27 @@ +# +# This configuration file allows a diskfull install to access the install images +# via http. It also allows the xCAT documentation to be accessed via +# http://localhost/xcat-doc/ +# Updates to xCAT/xcat.conf should also be made to xCATsn/xcat.conf +# +AliasMatch ^/install/(.*)$ "/install/$1" +AliasMatch ^/tftpboot/(.*)$ "/tftpboot/$1" + + + Options Indexes FollowSymLinks Includes MultiViews + AllowOverride None + Require all granted + + + Options Indexes FollowSymLinks Includes MultiViews + AllowOverride None + Require all granted + + +Alias /xcat-doc "/opt/xcat/share/doc" + + Options Indexes + AllowOverride None + Require all granted + +