diff --git a/xCAT-server/lib/xcat/plugins/genimage.pm b/xCAT-server/lib/xcat/plugins/genimage.pm index d2a5e7bee..95b7e8d89 100644 --- a/xCAT-server/lib/xcat/plugins/genimage.pm +++ b/xCAT-server/lib/xcat/plugins/genimage.pm @@ -400,6 +400,10 @@ sub process_request { # print FILE "\n"; #} #close FILE; + if ($::RUNCMD_RC != 0) { + $callback->({ error => ["genimage command failed with rc $::RUNCMD_RC."], errorcode => [$::RUNCMD_RC] }); + return $::RUNCMD_RC; + } # update the generated initrd to /tftpboot/xcat so that don't need to rerun nodeset to update them if (($::RUNCMD_RC == 0) && $imagename) { diff --git a/xCAT-server/lib/xcat/plugins/sles.pm b/xCAT-server/lib/xcat/plugins/sles.pm index cd852c63d..24cadae36 100644 --- a/xCAT-server/lib/xcat/plugins/sles.pm +++ b/xCAT-server/lib/xcat/plugins/sles.pm @@ -44,6 +44,19 @@ sub handled_commands }; } +sub precreate_sles11_mypostscript +{ + my ($node, $osver, $callback) = @_; + + return unless ($osver =~ /^sles11/); + + require xCAT::Postage; + + # SLES 11 clients rely on the precreated HTTP mypostscript path more + # reliably than the dynamic getpostscript request. + xCAT::Postage::makescript([$node], undef, $callback, 1, 0); +} + sub mknetboot { my $req = shift; @@ -289,6 +302,8 @@ sub mknetboot next; } + precreate_sles11_mypostscript($node, $osver, $callback); + #print"osvr=$osver, arch=$arch, profile=$profile, imgdir=$rootimgdir\n"; my $platform; if ($osver =~ /sles.*/) @@ -968,6 +983,8 @@ sub mkinstall next; } + precreate_sles11_mypostscript($node, $os, $callback); + # create the node-specific post script DEPRECATED, don't do #mkpath "/install/postscripts/"; diff --git a/xCAT-server/lib/xcat/plugins/xnba.pm b/xCAT-server/lib/xcat/plugins/xnba.pm index 6092543c7..c59e6a2f4 100644 --- a/xCAT-server/lib/xcat/plugins/xnba.pm +++ b/xCAT-server/lib/xcat/plugins/xnba.pm @@ -110,6 +110,23 @@ sub has_efistub { return 0; } } + +sub _use_efistub_for_uefi { + my $kern = shift; + return 0 unless has_efistub($kern->{kernel}); + + my $kernel_path = $kern->{kernel} || ''; + my $initrd_path = $kern->{initrd} || ''; + my $cmdline = $kern->{kcmdline} || ''; + + # SLES 11 kernels advertise an EFI stub, but live UEFI xNBA boot corrupts + # the initrd/root image path. Keep SLES 11 on the existing elilo path. + if ("$kernel_path $initrd_path $cmdline" =~ m{(?:^|[=/\s_-])sles?11(?:[.\s/_-]|$)}i) { + return 0; + } + + return 1; +} sub setstate { =pod @@ -330,7 +347,7 @@ sub setstate { if ($kern->{kcmdline} and $kern->{initrd}) { #only a linux kernel/initrd pair should land here, write elilo config and uefi variant of xnba config file my $ucfg; open($ucfg, '>', $tftpdir . "/xcat/xnba/nodes/" . $node . ".uefi"); - if (has_efistub($kern->{kernel}, $node)) { + if (_use_efistub_for_uefi($kern)) { print $ucfg "#!gpxe\n"; print $ucfg "imgfetch -n kernel http://" . '${next-server}:' . $httpport.'/tftpboot/' . $kern->{kernel} . "\n"; print $ucfg "imgload kernel\n"; diff --git a/xCAT-server/sbin/makenamed.conf b/xCAT-server/sbin/makenamed.conf index eaf197932..f63c0f480 100755 --- a/xCAT-server/sbin/makenamed.conf +++ b/xCAT-server/sbin/makenamed.conf @@ -65,19 +65,22 @@ done >>$FILE echo " };" >>$FILE # Natural version compare against version of bind. -# If version 9.16.6 or higher, turn off DNSSEC +version_ge() +{ + if [ -z "$1" ] || [ -z "$2" ]; then + return 1 + fi + + # "sort --version-sort" sorts versions in ascending order. + [ "$(printf '%s\n' "$1" "$2" | sort --version-sort | tail -n1)" = "$1" ] +} + BIND_VERSION=$(/usr/sbin/named -v | cut -d" " -f2 | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+' | head -n1) -CONTROL_BIND_VERSION="9.16.6" -# "sort --version-sort" takes lines of version strings and sorts them. -# Output is lines of versions in sorted order, last line is highest version number -LAST_IN_COMPARE=`printf '%s\n' $BIND_VERSION $CONTROL_BIND_VERSION | sort --version-sort | tail -n1` - -if [ $BIND_VERSION = $LAST_IN_COMPARE ]; then - # current version of BIND was last in sorted order, - # therefor it is higher than CONTROL_BIND_VERSION - echo " dnssec-enable no; - dnssec-validation no;" >>$FILE +if version_ge "$BIND_VERSION" "9.16.6"; then + if ! version_ge "$BIND_VERSION" "9.18.0"; then + echo " dnssec-enable no;" >>$FILE + fi + echo " dnssec-validation no;" >>$FILE fi echo "};" >>$FILE - diff --git a/xCAT-server/share/xcat/install/scripts/post.xcat b/xCAT-server/share/xcat/install/scripts/post.xcat index 060dd6709..ad53a5c60 100755 --- a/xCAT-server/share/xcat/install/scripts/post.xcat +++ b/xCAT-server/share/xcat/install/scripts/post.xcat @@ -164,6 +164,12 @@ if [ ! -x /xcatpost/mypostscript ]; then MYCONT=`grep ^MASTER= /xcatpost/mypostscript` done + + if [ -z "$MYCONT" ]; then + msgutil_r "$MASTER_IP" "error" "failed to get mypostscript from $MASTER_IP, halt ..." "/var/log/xcat/xcat.log" "$log_label" + /tmp/updateflag $MASTER $XCATIPORT "installstatus failed" + sleep 36500d + fi fi TMP=`sed "/^#\s*postscripts-start-here/,/^#\s*postscripts-end-here/ s/\(.*\)/run_ps postscript \1/;s/run_ps postscript\s*#/#/;s/run_ps postscript\s*$//" /xcatpost/mypostscript` diff --git a/xCAT-server/share/xcat/install/scripts/pre.sles b/xCAT-server/share/xcat/install/scripts/pre.sles index e1ec0409e..292b4c6b7 100644 --- a/xCAT-server/share/xcat/install/scripts/pre.sles +++ b/xCAT-server/share/xcat/install/scripts/pre.sles @@ -191,8 +191,21 @@ if [ -e "/tmp/xcat.install_disk" ]; then fi msgutil_r "$MASTER_IP" "info" "Found $instdisk, generate partition file..." "/var/log/xcat/xcat.log" "$log_label" +set_sles11_uefi_bootloader() +{ + if grep -E 'install=.*sles11' /proc/cmdline >/dev/null 2>&1; then + # SLES 11 AutoYaST keeps the template's legacy MBR bootloader + # location unless the UEFI path explicitly selects elilo. + sed -i -e '/mbr!elilo!' \ + /tmp/profile/modified.xml + fi +} + if [ -d /sys/firmware/efi ]; then sed -e 's!XCATPARTITIONHOOK!'$instdisk'vfat/boot/efi128mbswapauto/auto!' /tmp/profile/autoinst.xml > /tmp/profile/modified.xml + set_sles11_uefi_bootloader else sed -e 's!XCATPARTITIONHOOK!'$instdisk'xfs/autoswapauto!' /tmp/profile/autoinst.xml > /tmp/profile/modified.xml fi @@ -207,6 +220,9 @@ if [ -r "/tmp/partitionfile" ]; then con=${con// /xcattempspace} sed -e '//{N;N;s!.*!'$con'!}' /tmp/profile/autoinst.xml > /tmp/profile/modified1.xml sed -e 's!xcattempspace! !g' /tmp/profile/modified1.xml > /tmp/profile/modified.xml + if [ -d /sys/firmware/efi ]; then + set_sles11_uefi_bootloader + fi fi msgutil_r "$MASTER_IP" "info" "Generate the repository for the installation" "/var/log/xcat/xcat.log" "$log_label" export nextserver=`cat /proc/cmdline | grep http | awk -F'autoyast=http://' {'print \$2'} | awk -F':' {'print \$1'}` diff --git a/xCAT-server/share/xcat/netboot/sles/compute.sles12.ppc64le.pkglist b/xCAT-server/share/xcat/netboot/sles/compute.sles12.ppc64le.pkglist index d0b4c3a0e..a60e36c20 100644 --- a/xCAT-server/share/xcat/netboot/sles/compute.sles12.ppc64le.pkglist +++ b/xCAT-server/share/xcat/netboot/sles/compute.sles12.ppc64le.pkglist @@ -19,6 +19,7 @@ bc ntp gzip e2fsprogs +xfsprogs parted binutils tar diff --git a/xCAT-server/share/xcat/netboot/sles/compute.sles12.x86_64.pkglist b/xCAT-server/share/xcat/netboot/sles/compute.sles12.x86_64.pkglist index d0b4c3a0e..a60e36c20 100644 --- a/xCAT-server/share/xcat/netboot/sles/compute.sles12.x86_64.pkglist +++ b/xCAT-server/share/xcat/netboot/sles/compute.sles12.x86_64.pkglist @@ -19,6 +19,7 @@ bc ntp gzip e2fsprogs +xfsprogs parted binutils tar diff --git a/xCAT-server/share/xcat/netboot/sles/genimage b/xCAT-server/share/xcat/netboot/sles/genimage index 9eed0bbed..e144f72a2 100755 --- a/xCAT-server/share/xcat/netboot/sles/genimage +++ b/xCAT-server/share/xcat/netboot/sles/genimage @@ -94,7 +94,9 @@ sub umount { # Make sure we clean up all mounts everytime END { + my $exitstatus = $?; umount(); + $? = $exitstatus; } #-- fetch current version form CVS (overwrite locally changed versions) @@ -2091,9 +2093,11 @@ sub generic_post { # This function is meant to leave the image in a state approx print $cfgfile "if [ -n \"\$VERS\" ]; then\n"; print $cfgfile " VERNUM=`echo \$VERS|awk -F= \'{print \$2}\'|awk -F- \'{print \$1}\'|sed -e \'s/ //g\'|sed -e \'s/\"//g\'`\n"; print $cfgfile "fi\n"; - print $cfgfile "if [ \"\$VERNUM\" -gt 10 ]; then\n"; - print $cfgfile " exit\n"; - print $cfgfile "fi\n"; + print $cfgfile "VERMAJOR=`echo \$VERNUM|sed -e 's/\\..*//'`\n"; + print $cfgfile "case \"\$VERMAJOR\" in\n"; + print $cfgfile " ''|*[!0-9]*) ;;\n"; + print $cfgfile " *) if [ \"\$VERMAJOR\" -gt 10 ]; then exit; fi ;;\n"; + print $cfgfile "esac\n"; print $cfgfile "\n"; print $cfgfile "for i in `cat /proc/cmdline`; do\n"; print $cfgfile ' KEY=`echo $i|cut -d= -f 1`' . "\n"; @@ -2117,7 +2121,12 @@ sub generic_post { # This function is meant to leave the image in a state approx system("mkdir -p $rootimg_dir/opt/xcat"); copy("$installroot/postscripts/xcatpostinit", "$rootimg_dir/opt/xcat/xcatpostinit"); chmod(0755, "$rootimg_dir/opt/xcat/xcatpostinit"); - copy("$installroot/postscripts/xcatpostinit.service", "$rootimg_dir/usr/lib/systemd/system/xcatpostinit.service"); + if (-d "$rootimg_dir/usr/lib/systemd/system") { + copy("$installroot/postscripts/xcatpostinit.service", "$rootimg_dir/usr/lib/systemd/system/xcatpostinit.service"); + } elsif (-d "$rootimg_dir/etc/init.d") { + copy("$installroot/postscripts/xcatpostinit", "$rootimg_dir/etc/init.d/xcatpostinit"); + chmod(0755, "$rootimg_dir/etc/init.d/xcatpostinit"); + } # # set certain system services to start on boot, if the file exists in /etc/init.d as a script, diff --git a/xCAT-test/unit/sles_pre_script.t b/xCAT-test/unit/sles_pre_script.t new file mode 100644 index 000000000..1ffa01eea --- /dev/null +++ b/xCAT-test/unit/sles_pre_script.t @@ -0,0 +1,20 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use Test::More; + +my $pre_sles_path = defined $ENV{XCATROOT} ? "$ENV{XCATROOT}/share/xcat/install/scripts/pre.sles" : ''; +$pre_sles_path = "xCAT-server/share/xcat/install/scripts/pre.sles" + unless -f $pre_sles_path; + +plan skip_all => "pre.sles not found" unless -f $pre_sles_path; + +my $src = do { local $/; open my $fh, '<', $pre_sles_path or die $!; <$fh> }; + +like($src, qr/sub set_sles11_uefi_bootloader\b|set_sles11_uefi_bootloader\(\)/, 'SLES UEFI bootloader helper exists'); +like($src, qr/install=\.\*sles11/, 'SLES 11 UEFI bootloader change is scoped to SLES 11 install media'); +like($src, qr/elilo<\/loader_type>/, 'SLES 11 UEFI install selects elilo'); +like($src, qr/mbr<\/location>/, 'legacy MBR template value is replaced at install time'); +like($src, qr/if \[ -d \/sys\/firmware\/efi \]; then\s+sed .*?set_sles11_uefi_bootloader/s, 'UEFI default partitioning applies bootloader helper'); + +done_testing(); diff --git a/xCAT-test/unit/xnba_semicolon.t b/xCAT-test/unit/xnba_semicolon.t index ea07dedcc..fdf998526 100644 --- a/xCAT-test/unit/xnba_semicolon.t +++ b/xCAT-test/unit/xnba_semicolon.t @@ -28,4 +28,10 @@ like($src, qr/sub _write_uefi_exit_script\b/, 'UEFI local boot helper exists'); like($src, qr/_write_uefi_exit_script\(\$bootloader_root, \$node, \$cref->\{currstate\}\);/, 'boot/local states rewrite UEFI xNBA script'); like($src, qr/print \$ucfg "exit\\n";/, 'UEFI local boot script exits iPXE to firmware'); +# SLES 11 advertises EFI stub support, but the live UEFI xNBA path corrupts +# the legacy initrd/root image handoff. It must keep using elilo. +like($src, qr/sub _use_efistub_for_uefi\b/, 'UEFI EFI-stub selection helper exists'); +like($src, qr/sles\?11/, 'SLES 11 UEFI compatibility rule matches sle11 and sles11 images'); +like($src, qr/if \(_use_efistub_for_uefi\(\$kern\)\)/, 'UEFI boot path uses compatibility helper before direct EFI-stub boot'); + done_testing(); diff --git a/xCAT/postscripts/getcredentials.awk b/xCAT/postscripts/getcredentials.awk index 0cbf2fdfb..ef91541e4 100755 --- a/xCAT/postscripts/getcredentials.awk +++ b/xCAT/postscripts/getcredentials.awk @@ -5,7 +5,7 @@ BEGIN { } else { randombytes = "" } - if (!system("test -f openssl")) { + if (system("command -v openssl >/dev/null 2>&1")) { print "Error: openssl utility missing" exit 1 } diff --git a/xCAT/postscripts/getpostscript.awk b/xCAT/postscripts/getpostscript.awk index e4ffd3006..6ccfc3840 100755 --- a/xCAT/postscripts/getpostscript.awk +++ b/xCAT/postscripts/getpostscript.awk @@ -5,7 +5,7 @@ BEGIN { } else { randombytes = "" } - if (!system("test -f openssl")) { + if (system("command -v openssl >/dev/null 2>&1")) { print "Error: openssl utility missing" exit 1 } diff --git a/xCAT/postscripts/startsyncfiles.awk b/xCAT/postscripts/startsyncfiles.awk index 0c85ae262..5b385325c 100755 --- a/xCAT/postscripts/startsyncfiles.awk +++ b/xCAT/postscripts/startsyncfiles.awk @@ -5,9 +5,9 @@ BEGIN { } else { randombytes = "" } - if (!system("test -f openssl")) { - print "Error: openssl utility missing" - exit 1 + if (system("command -v openssl >/dev/null 2>&1")) { + print "Error: openssl utility missing" + exit 1 } if (ENVIRON["USEOPENSSLFORXCAT"]) { diff --git a/xCAT/postscripts/xcatdsklspost b/xCAT/postscripts/xcatdsklspost index 988fc8c2e..b0bc6d248 100755 --- a/xCAT/postscripts/xcatdsklspost +++ b/xCAT/postscripts/xcatdsklspost @@ -681,6 +681,10 @@ fi if [ ! -x /$xcatpost/mypostscript ]; then echolog "debug" "no pre-generated mypostscript., trying to get it with getpostscript.awk..." + GETPOSTSCRIPT_ARGS="" + if [ -n "$node_short" ]; then + GETPOSTSCRIPT_ARGS="$node_short" + fi if [ $useflowcontrol = "1" ]; then # first contact daemon xcatflowrequest 3001 #logger -t xCAT -p local4.info "xcatdsklspost:sending xcatflowrequest $SIP 3001" @@ -695,7 +699,7 @@ if [ ! -x /$xcatpost/mypostscript ]; then useflowcontrol=0 fi fi - /$xcatpost/getpostscript.awk | egrep '' | sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' | sed -e 's/<//g' -e 's/&/\&/g' -e 's/"/"/g' -e "s/'/'/g" > /$xcatpost/mypostscript; + /$xcatpost/getpostscript.awk $GETPOSTSCRIPT_ARGS | egrep '' | sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' | sed -e 's/<//g' -e 's/&/\&/g' -e 's/"/"/g' -e "s/'/'/g" > /$xcatpost/mypostscript; MYCONT=`grep MASTER /$xcatpost/mypostscript` @@ -729,12 +733,16 @@ if [ ! -x /$xcatpost/mypostscript ]; then useflowcontrol=0 fi fi - /$xcatpost/getpostscript.awk | egrep '' | sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' | sed -e 's/<//g' -e 's/&/\&/g' -e 's/"/"/g' -e "s/'/'/g" > /$xcatpost/mypostscript; + /$xcatpost/getpostscript.awk $GETPOSTSCRIPT_ARGS | egrep '' | sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' | sed -e 's/<//g' -e 's/&/\&/g' -e 's/"/"/g' -e "s/'/'/g" > /$xcatpost/mypostscript; MYCONT=`grep MASTER /$xcatpost/mypostscript` if [ ! -z "$MYCONT" ]; then break; fi done + if [ -z "$MYCONT" ]; then + echolog "err" "failed to get mypostscript from $SIP" + exit 1 + fi fi #save the MASTER into the xcatinfo file for node deployment case, diff --git a/xCAT/postscripts/xcatinstallpost b/xCAT/postscripts/xcatinstallpost index 367bdc8d0..d840d77a8 100755 --- a/xCAT/postscripts/xcatinstallpost +++ b/xCAT/postscripts/xcatinstallpost @@ -25,6 +25,15 @@ SLI=$(awk 'BEGIN{srand(); printf("%d\n",rand()*10)}') sleep $SLI XCATINFOFILE=/opt/xcat/xcatinfo +if [ -z "$MASTER_IP" ] && [ -f "$XCATINFOFILE" ]; then + MASTER_IP=`grep '^XCATSERVER=' "$XCATINFOFILE" | head -n 1 | cut -d= -f2 | cut -d: -f1 | tr -d \'\"` +fi + +if [ -z "$MASTER_IP" ]; then + msgutil_r "" "error" "Unable to determine the xCAT master for postboot scripts." "/var/log/xcat/xcat.log" "$log_label" + exit 1 +fi + MACADDR=`grep MACADDRESS= /xcatpost/mypostscript.post | awk -F = '{ print $2 }'| sed "s/\'//g"` INSTALLNIC=`ip -o link | grep -i "$MACADDR" | awk '{ print $2 }' | sed "s/://"` @@ -34,7 +43,7 @@ INSTALLNIC=`ip -o link | grep -i "$MACADDR" | awk '{ print $2 }' | sed "s/://"` RETRY=0 while true; do #check whether the network access between MN/CN and the node is ready - ping $MASTER_IP -c 1 >/dev/null && break + ping -c 1 $MASTER_IP >/dev/null && break RETRY=$[ $RETRY + 1 ]