diff --git a/xCAT-server/lib/xcat/plugins/mknb.pm b/xCAT-server/lib/xcat/plugins/mknb.pm index b385f0698..37bc7115d 100644 --- a/xCAT-server/lib/xcat/plugins/mknb.pm +++ b/xCAT-server/lib/xcat/plugins/mknb.pm @@ -9,6 +9,8 @@ use File::Path; use File::Copy; my $GENESIS_EXPORT_MANIFEST = 'xcat-genesis.manifest'; +my %GENESIS_ARCHITECTURES = map { $_ => 1 } + qw(x86 x86_64 ppc64 ppc64le armv7hf aarch64 riscv64); sub handled_commands { return { @@ -38,6 +40,28 @@ sub _select_network_addresses { return (\%legacy, \%selected); } +sub _select_genesis_source { + my ($xcatroot, $requested_arch) = @_; + return unless defined($requested_arch); + + my $arch = $requested_arch eq 'ppc64el' ? 'ppc64le' : $requested_arch; + return unless $GENESIS_ARCHITECTURES{$arch}; + + my $netboot = "$xcatroot/share/xcat/netboot"; + my $openembedded = "$netboot/genesis-openembedded/$arch"; + return ($openembedded, $arch, 'openembedded') + if -e $openembedded || -l $openembedded; + + my $legacy_arch = $arch eq 'ppc64le' ? 'ppc64' : $arch; + my $legacy = "$netboot/genesis/$legacy_arch"; + return ($legacy, $legacy_arch, 'legacy') if -e $legacy || -l $legacy; + + my $classic = "$netboot/$legacy_arch"; + return ($classic, $legacy_arch, 'classic') if -e $classic || -l $classic; + + return; +} + sub _genesis_export_manifest_present { my ($directory) = @_; my $manifest = "$directory/$GENESIS_EXPORT_MANIFEST"; @@ -341,21 +365,25 @@ sub process_request { } my $tftpdir = xCAT::TableUtils->getTftpDir(); - my $arch = $request->{arg}->[0]; - if (!$arch) { - $callback->({ error => "Need to specify architecture (x86, x86_64 or ppc64)" }, { errorcode => [1] }); + my $requested_arch = $request->{arg}->[0]; + if (!$requested_arch) { + $callback->({ error => "Need to specify architecture (x86, x86_64, ppc64, ppc64le, armv7hf, aarch64 or riscv64)" }, { errorcode => [1] }); return; - } elsif ($arch eq "ppc64le" or $arch eq "ppc64el") { - $callback->({ data => "The arch:$arch is not supported, using \"ppc64\" instead" }); - $arch = 'ppc64'; - $request->{arg}->[0] = $arch; } - my $genesis_dir = "$::XCATROOT/share/xcat/netboot/genesis/$arch"; - unless (-d "$::XCATROOT/share/xcat/netboot/$arch" or -d $genesis_dir) { - $callback->({ error => "Unable to find directory $::XCATROOT/share/xcat/netboot/$arch or $::XCATROOT/share/xcat/netboot/genesis/$arch", errorcode => [1] }); + my ($genesis_dir, $arch, $genesis_type) = + _select_genesis_source($::XCATROOT, $requested_arch); + unless (defined($genesis_dir) && -d $genesis_dir && !-l $genesis_dir) { + $callback->({ error => "Unable to find a Genesis image for architecture $requested_arch", errorcode => [1] }); return; } + if ($requested_arch eq 'ppc64el') { + $callback->({ data => 'Using the canonical architecture name ppc64le' }); + } elsif ($requested_arch eq 'ppc64le' && $arch eq 'ppc64') { + $callback->({ data => 'OpenEmbedded ppc64le is not installed, using the legacy ppc64 image' }); + } + $request->{arg}->[0] = $arch; + my $configfileonly = $request->{arg}->[1]; if ($configfileonly and $configfileonly ne "-c" and $configfileonly ne "--configfileonly") { $callback->({ error => "The option $configfileonly is not supported", errorcode => [1] }); @@ -364,7 +392,10 @@ sub process_request { goto CREAT_CONF_FILE; } if (_prebuilt_genesis_requested($genesis_dir)) { - $callback->({ data => ["Installing exported Genesis image for $arch"] }); + my $image_name = $genesis_type eq 'openembedded' + ? 'OpenEmbedded Genesis' + : 'exported Genesis'; + $callback->({ data => ["Installing $image_name image for $arch"] }); my ($installed_initrd, $install_error) = _install_prebuilt_genesis($genesis_dir, $tftpdir, $arch); if ($install_error) { @@ -375,7 +406,8 @@ sub process_request { $invisibletouch = 1; goto CREAT_CONF_FILE; } - if (_genesis_export_manifest_present($genesis_dir)) { + if ($genesis_type eq 'openembedded' + || _genesis_export_manifest_present($genesis_dir)) { $callback->({ error => ["Incomplete Genesis export: $genesis_dir"], errorcode => [1], @@ -441,19 +473,19 @@ sub process_request { mkpath("$tftpdir/xcat"); } my $rc; - if (-e "$::XCATROOT/share/xcat/netboot/genesis/$arch") { - $rc = system("shopt -s dotglob; GLOBIGNORE=\".:..\" cp -a $::XCATROOT/share/xcat/netboot/genesis/$arch/fs/* $tempdir"); - $rc = system("cp -a $::XCATROOT/share/xcat/netboot/genesis/$arch/kernel $tftpdir/xcat/genesis.kernel.$arch"); + if ($genesis_type eq 'legacy') { + $rc = system("shopt -s dotglob; GLOBIGNORE=\".:..\" cp -a $genesis_dir/fs/* $tempdir"); + $rc = system("cp -a $genesis_dir/kernel $tftpdir/xcat/genesis.kernel.$arch"); $invisibletouch = 1; } else { - $rc = system("cp -a $::XCATROOT/share/xcat/netboot/$arch/nbroot/* $tempdir"); + $rc = system("cp -a $genesis_dir/nbroot/* $tempdir"); } if ($rc) { system("rm -rf $tempdir"); if ($invisibletouch) { - $callback->({ error => ["Failed to copy $::XCATROOT/share/xcat/netboot/genesis/$arch/fs contents"], errorcode => [1] }); + $callback->({ error => ["Failed to copy $genesis_dir/fs contents"], errorcode => [1] }); } else { - $callback->({ error => ["Failed to copy $::XCATROOT/share/xcat/netboot/$arch/nbroot/ contents"], errorcode => [1] }); + $callback->({ error => ["Failed to copy $genesis_dir/nbroot contents"], errorcode => [1] }); } return; } diff --git a/xCAT-server/sbin/xcatconfig b/xCAT-server/sbin/xcatconfig index 829116d93..e3cdd2291 100755 --- a/xCAT-server/sbin/xcatconfig +++ b/xCAT-server/sbin/xcatconfig @@ -1991,10 +1991,36 @@ sub setupLinuxexports =head3 mknb Creates a network boot root image on Linux - Run mknb for each installed xCAT-genesis-scripts/xCAT-genesis-base architecture and place the result in /tftpboot + Run mknb for each installed Genesis architecture and place the result in /tftpboot =cut #----------------------------------------------------------------------------- +sub _installed_genesis_architectures +{ + my ($xcatroot) = @_; + my @supported = qw(aarch64 armv7hf ppc64 ppc64le riscv64 x86 x86_64); + my %supported = map { $_ => 1 } @supported; + my %installed; + + my $openembedded = "$xcatroot/share/xcat/netboot/genesis-openembedded"; + if (opendir(my $dh, $openembedded)) { + while (my $entry = readdir($dh)) { + next unless $supported{$entry}; + my $path = "$openembedded/$entry"; + $installed{$entry} = 1 if -d $path && !-l $path; + } + closedir($dh); + } + + my $legacy = "$xcatroot/share/xcat/netboot/genesis"; + foreach my $arch (@supported) { + my $path = "$legacy/$arch"; + $installed{$arch} = 1 if -d $path && !-l $path; + } + + return grep { $installed{$_} } @supported; +} + sub mknb { # The xCAT-genesis-scripts.spec file touches /etc/xcat/genesis-scripts-updated or @@ -2014,20 +2040,25 @@ sub mknb xCAT::MsgUtils->message('I', "Running '$cmd', triggered by the installation/update of xCAT-genesis-base ..."); } } + my @architectures = _installed_genesis_architectures($::XCATROOT); + my @openembedded = grep { + -d "$::XCATROOT/share/xcat/netboot/genesis-openembedded/$_" + } @architectures; + if (@openembedded) { + unless ($run_mknb) { + xCAT::MsgUtils->message('I', "Running '$cmd' for installed OpenEmbedded Genesis images ..."); + } + $run_mknb = 1; + } if ($run_mknb) { - foreach (qw(ppc64 x86_64)) { - my $genesis_base_pkg = "xCAT-genesis-base-$_"; - if (system("rpm -q $genesis_base_pkg >/dev/null 2>&1") != 0) { - xCAT::MsgUtils->message('I', "Skipping '$cmd $_' because $genesis_base_pkg is not installed."); - next; - } - system("$cmd $_"); + foreach my $arch (@architectures) { + system("$cmd $arch"); if ($? != 0) { my $rc = $? >> 8; - xCAT::MsgUtils->message('E', "The 'mknb $_' command returned error code: $rc."); + xCAT::MsgUtils->message('E', "The 'mknb $arch' command returned error code: $rc."); } else { - xCAT::MsgUtils->message('I', "The 'mknb $_' command completed successfully."); + xCAT::MsgUtils->message('I', "The 'mknb $arch' command completed successfully."); } } }