From 883549fea2f51b9d3df989b41cce38dec1b35865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Tue, 13 Oct 2026 15:29:21 -0300 Subject: [PATCH] feat(statelite): publish the liteimg ramdisk archive with its checksum liteimg deleted rootimg-statelite.gz before it packed a statelite ramdisk image, and wrote the new archive in place. It ignored a failed pack, so nodes could get no image or a partial one. It took no image lock. --tracker took no value, so the metainfo named the tracker 1, and it described rootimg.gz instead of the new archive. liteimg now takes the image lock and packs into the temporary directory that packimage uses. It fails when a command of the pack fails. It writes the SHA-256 checksum, and publishes it with the archive through publish_rootimg. --tracker takes the tracker URL, as it does for packimage, and the metainfo describes the new archive. Nodes keep downloading the previous archive until the new one replaces it. --- xCAT-server/lib/xcat/plugins/statelite.pm | 65 ++++++++++++++--------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/statelite.pm b/xCAT-server/lib/xcat/plugins/statelite.pm index 1fbdbc734..f73d9eb68 100644 --- a/xCAT-server/lib/xcat/plugins/statelite.pm +++ b/xCAT-server/lib/xcat/plugins/statelite.pm @@ -79,7 +79,7 @@ sub process_request { "arch|a=s" => \$arch, "osver|o=s" => \$osver, "help|h" => \$help, - "tracker" => \$dotorrent, + "tracker=s" => \$dotorrent, "version|v" => \$version, "verbose|V" => \$verbose ); @@ -164,6 +164,13 @@ sub process_request { $destdir = "$installroot/netboot/$osver/$arch/$profile"; $rootimg_dir = "$destdir/rootimg"; } + + # genimage, packimage, imgimport and rmimage take this lock before they change the image. + my ($lock_error, $lock) = xCAT::Utils->acquire_lock_imageop($rootimg_dir); + if ($lock_error) { + $callback->({ error => [$lock], errorcode => [1] }); + return; + } my $oldpath = cwd(); # now we have all the info we need: @@ -549,11 +556,7 @@ sub process_request { `echo TIMESTAMP="'$timestamp'" >> $rootimg_dir/opt/xcat/xcatinfo`; my $verb = "Packing"; - - my $temppath; - my $oldmask; $callback->({ data => ["$verb contents of $rootimg_dir ..."] }); - unlink("$destdir/rootimg-statelite.gz"); my $compress = "gzip"; @@ -565,31 +568,43 @@ sub process_request { $callback->({ info => ["compress method: $compress"] }); - if ($exlistloc) { - chdir("$rootimg_dir"); - system("$excludestr >> $xcat_packimg_tmpfile"); - if ($includestr) { - system("$includestr >> $xcat_packimg_tmpfile"); - } - $excludestr = "cat $xcat_packimg_tmpfile |cpio -H newc -o | $compress -c - > ../rootimg-statelite.gz"; - } else { - $excludestr = "find . |cpio -H newc -o | $compress -c - > ../rootimg-statelite.gz"; + # Nodes keep downloading the previous archive until the new one is complete and replaces it. + my ($stage, $stage_error) = xCAT::SvrUtils->rootimg_stage($destdir); + unless ($stage) { + $callback->({ error => [$stage_error], errorcode => [1] }); + chdir($oldpath); + return; } - $oldmask = umask 0077; + my $archive = "$stage/rootimg-statelite.gz"; chdir("$rootimg_dir"); - xCAT::Utils->runcmd("$excludestr"); - chmod 0644, "$destdir/rootimg-statelite.gz"; - if ($dotorrent) { - my $currdir = getcwd; - chdir($destdir); - unlink("rootimg-statelite.gz.metainfo"); - system("ctorrent -t -u $dotorrent -l 1048576 -s rootimg-statelite.gz.metainfo rootimg.gz"); - chmod 0644, "rootimg-statelite.gz.metainfo"; - chdir($currdir); + my @pack; + if ($exlistloc) { + push @pack, "$excludestr >> $xcat_packimg_tmpfile"; + push @pack, "$includestr >> $xcat_packimg_tmpfile" if $includestr; + push @pack, "cat $xcat_packimg_tmpfile |cpio -H newc -o | $compress -c - > '$archive'"; + } else { + push @pack, "find . |cpio -H newc -o | $compress -c - > '$archive'"; + } + my $oldmask = umask 0077; + my $error; + foreach my $command (@pack) { + next unless system('/bin/bash', '-o', 'pipefail', '-c', $command); + $error = "liteimg failed while running: $command"; + last; } umask $oldmask; - system("rm -f $xcat_packimg_tmpfile"); + if ($dotorrent && !$error) { + my $made = chdir($stage) && !system("ctorrent -t -u $dotorrent -l 1048576 -s rootimg-statelite.gz.metainfo rootimg-statelite.gz"); + $error = "ctorrent cannot create the metainfo of $destdir/rootimg-statelite.gz" unless $made; + } + $error ||= xCAT::SvrUtils->write_rootimg_checksum($archive); + $error ||= xCAT::SvrUtils->publish_rootimg($archive, "$destdir/rootimg-statelite.gz"); + chdir($oldpath); + if ($error) { + $callback->({ error => [$error], errorcode => [1] }); + return; + } $callback->({ data => ["$verb contents of $rootimg_dir done."] }); } chdir($oldpath);