From aa086a1bc99b2dfd4c41a42c350a012886644b99 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, 14 Jul 2026 18:26:39 -0300 Subject: [PATCH 1/6] feat(statelite): support NFS root mount options --- .../ppc64le/statelite/config_statelite.rst | 13 ++++ .../references/man5/osimage.5.rst | 8 ++- perl-xCAT/xCAT/Schema.pm | 8 ++- xCAT-server/lib/perl/xCAT/SvrUtils.pm | 26 ++++++++ xCAT-server/lib/xcat/plugins/anaconda.pm | 19 ++++-- xCAT-server/lib/xcat/plugins/debian.pm | 19 ++++-- xCAT-server/lib/xcat/plugins/sles.pm | 19 ++++-- xCAT-test/unit/nfs_root_options.t | 62 +++++++++++++++++++ 8 files changed, 156 insertions(+), 18 deletions(-) create mode 100644 xCAT-test/unit/nfs_root_options.t diff --git a/docs/source/guides/admin-guides/manage_clusters/ppc64le/statelite/config_statelite.rst b/docs/source/guides/admin-guides/manage_clusters/ppc64le/statelite/config_statelite.rst index 2c8a02d28..dcad14a7b 100644 --- a/docs/source/guides/admin-guides/manage_clusters/ppc64le/statelite/config_statelite.rst +++ b/docs/source/guides/admin-guides/manage_clusters/ppc64le/statelite/config_statelite.rst @@ -136,3 +136,16 @@ noderes ``noderes.nfsdir`` can be set. If this is not set, the default is ``/install`` +NFS root mount options +---------------------- + +For dracut-based NFS statelite images, additional NFS root mount options can +be set on the osimage. For example, to disable attribute caching:: + + chdef -t osimage -o rhels9-ppc64le-statelite-compute nfsrootopts=noac + nodeset compute osimage=rhels9-ppc64le-statelite-compute + +The value is a comma-separated list, such as ``noac,actimeo=0``. xCAT always +includes ``ro`` and does not accept ``rw`` or ``defaults`` because the shared +statelite root filesystem must remain read-only. The ``statelite.mntopts`` +attribute continues to control only the separate persistent directory. diff --git a/docs/source/guides/admin-guides/references/man5/osimage.5.rst b/docs/source/guides/admin-guides/references/man5/osimage.5.rst index b5bf84f82..510ad917c 100644 --- a/docs/source/guides/admin-guides/references/man5/osimage.5.rst +++ b/docs/source/guides/admin-guides/references/man5/osimage.5.rst @@ -19,7 +19,7 @@ SYNOPSIS ******** -\ **osimage Attributes:**\ \ *imagename*\ , \ *groups*\ , \ *profile*\ , \ *imagetype*\ , \ *description*\ , \ *provmethod*\ , \ *rootfstype*\ , \ *osdistroname*\ , \ *osupdatename*\ , \ *cfmdir*\ , \ *osname*\ , \ *osvers*\ , \ *osarch*\ , \ *synclists*\ , \ *postscripts*\ , \ *postbootscripts*\ , \ *serverrole*\ , \ *isdeletable*\ , \ *kitcomponents*\ , \ *environvar*\ , \ *comments*\ , \ *disable*\ +\ **osimage Attributes:**\ \ *imagename*\ , \ *groups*\ , \ *profile*\ , \ *imagetype*\ , \ *description*\ , \ *provmethod*\ , \ *rootfstype*\ , \ *nfsrootopts*\ , \ *osdistroname*\ , \ *osupdatename*\ , \ *cfmdir*\ , \ *osname*\ , \ *osvers*\ , \ *osarch*\ , \ *synclists*\ , \ *postscripts*\ , \ *postbootscripts*\ , \ *serverrole*\ , \ *isdeletable*\ , \ *kitcomponents*\ , \ *environvar*\ , \ *comments*\ , \ *disable* *********** @@ -78,6 +78,11 @@ osimage Attributes: +**nfsrootopts** + +A comma-separated list of additional NFS mount options for the root filesystem of a dracut-based statelite image. The root filesystem is always mounted read-only; rw and defaults are not allowed. + + \ **osdistroname**\ The name of the OS distro definition. This attribute can be used to specify which OS distro to use, instead of using the osname,osvers,and osarch attributes. For \*kit commands, the attribute will be used to read the osdistro table for the osname, osvers, and osarch attributes. If defined, the osname, osvers, and osarch attributes defined in the osimage table will be ignored. @@ -175,4 +180,3 @@ SEE ALSO \ **nodels(1)**\ , \ **chtab(8)**\ , \ **tabdump(8)**\ , \ **tabedit(8)**\ - diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index cca78aa90..63696e815 100644 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -773,7 +773,7 @@ passed as argument rather than by table value', }, }, osimage => { - cols => [qw(imagename groups profile imagetype description provmethod rootfstype osdistroname osupdatename cfmdir osname osvers osarch synclists postscripts postbootscripts serverrole isdeletable kitcomponents environvar comments disable)], + cols => [qw(imagename groups profile imagetype description provmethod rootfstype nfsrootopts osdistroname osupdatename cfmdir osname osvers osarch synclists postscripts postbootscripts serverrole isdeletable kitcomponents environvar comments disable)], keys => [qw(imagename)], tablespace => 'XCATTBS32K', table_desc => 'Basic information about an operating system image that can be used to deploy cluster nodes.', @@ -787,6 +787,7 @@ passed as argument rather than by table value', description => 'OS Image Description', provmethod => 'The provisioning method for node deployment. The valid values are install, netboot,statelite,boottarget,dualboot,sysclone. If boottarget is set, you must set linuximage.boottarget to the name of the boottarget definition. It is not used by AIX.', rootfstype => 'The filesystem type for the rootfs is used when the provmethod is statelite. The valid values are nfs or ramdisk. The default value is nfs', + nfsrootopts => 'A comma-separated list of additional NFS mount options for the root filesystem of a dracut-based statelite image. The root filesystem is always mounted read-only; rw and defaults are not allowed.', osdistroname => 'The name of the OS distro definition. This attribute can be used to specify which OS distro to use, instead of using the osname,osvers,and osarch attributes. For *kit commands, the attribute will be used to read the osdistro table for the osname, osvers, and osarch attributes. If defined, the osname, osvers, and osarch attributes defined in the osimage table will be ignored.', osupdatename => 'A comma-separated list of OS distro updates to apply to this osimage.', cfmdir => 'CFM directory name for PCM. Set to /install/osimages//cfmdir by PCM. ', @@ -3207,6 +3208,11 @@ push(@{ $defspec{node}->{'attrs'} }, @nodeattrs); tabentry => 'osimage.rootfstype', access_tabentry => 'osimage.imagename=attr:imagename', }, + { attr_name => 'nfsrootopts', + only_if => 'imagetype=linux', + tabentry => 'osimage.nfsrootopts', + access_tabentry => 'osimage.imagename=attr:imagename', + }, { attr_name => 'profile', tabentry => 'osimage.profile', access_tabentry => 'osimage.imagename=attr:imagename', diff --git a/xCAT-server/lib/perl/xCAT/SvrUtils.pm b/xCAT-server/lib/perl/xCAT/SvrUtils.pm index 92e615543..04b7305c8 100644 --- a/xCAT-server/lib/perl/xCAT/SvrUtils.pm +++ b/xCAT-server/lib/perl/xCAT/SvrUtils.pm @@ -2415,6 +2415,32 @@ sub getplatform { return $platform; } +# Build the dracut root=nfs parameter while preserving statelite's read-only +# root filesystem contract. +sub build_statelite_nfsroot_parameter { + shift if @_ && defined($_[0]) && $_[0] eq __PACKAGE__; + my ($server, $rootdir, $additional_options) = @_; + + my @mount_options = ('ro'); + if (defined($additional_options) && $additional_options ne '') { + foreach my $option (split(/,/, $additional_options, -1)) { + if ($option eq '' || $option =~ /\s/) { + return (undef, 'nfsrootopts must be a comma-separated list without whitespace or empty options'); + } + + my ($name) = split(/=/, $option, 2); + $name = lc($name); + if ($name eq 'rw' || $name eq 'defaults') { + return (undef, "nfsrootopts cannot contain '$name'; statelite NFS roots are always read-only"); + } + next if lc($option) eq 'ro'; + push @mount_options, $option; + } + } + + return ('root=nfs:' . $server . ':' . $rootdir . ':' . join(',', @mount_options), undef); +} + #-------------------------------------------------------------------------------------------------------- #searchcompressedrootimg: #description: search the compressed rootimage for diskless or statelite osimage under specified directory diff --git a/xCAT-server/lib/xcat/plugins/anaconda.pm b/xCAT-server/lib/xcat/plugins/anaconda.pm index 7a4c0f7f5..0187aef47 100644 --- a/xCAT-server/lib/xcat/plugins/anaconda.pm +++ b/xCAT-server/lib/xcat/plugins/anaconda.pm @@ -261,6 +261,7 @@ sub mknetboot my $dump; # for kdump, its format is "nfs:///" my $crashkernelsize; my $rootfstype; + my $nfsrootopts; my $tftpdir; my $cfgpart; my $imagename; # set it if running of 'nodeset osimage=xxx' @@ -283,13 +284,14 @@ sub mknetboot if (!$osimagetab) { $osimagetab = xCAT::Table->new('osimage', -create => 1); } - (my $ref) = $osimagetab->getAttribs({ imagename => $imagename }, 'osvers', 'osarch', 'profile', 'provmethod', 'rootfstype'); + (my $ref) = $osimagetab->getAttribs({ imagename => $imagename }, 'osvers', 'osarch', 'profile', 'provmethod', 'rootfstype', 'nfsrootopts'); if ($ref) { $img_hash{$imagename}->{osver} = $ref->{'osvers'}; $img_hash{$imagename}->{osarch} = $ref->{'osarch'}; $img_hash{$imagename}->{profile} = $ref->{'profile'}; $img_hash{$imagename}->{provmethod} = $ref->{'provmethod'}; $img_hash{$imagename}->{rootfstype} = $ref->{rootfstype}; + $img_hash{$imagename}->{nfsrootopts} = $ref->{nfsrootopts}; if (!$linuximagetab) { $linuximagetab = xCAT::Table->new('linuximage', -create => 1); } @@ -343,6 +345,7 @@ sub mknetboot $profile = $ph->{profile}; $rootfstype = $ph->{rootfstype}; + $nfsrootopts = $ph->{nfsrootopts}; $rootimgdir = $ph->{rootimgdir}; unless ($rootimgdir) { $rootimgdir = "$installroot/netboot/$osver/$arch/$profile"; @@ -382,9 +385,10 @@ sub mknetboot } if ($osimagetab) { - my ($ref1) = $osimagetab->getAttribs({ imagename => $imgname }, 'rootfstype'); - if (($ref1) && ($ref1->{'rootfstype'})) { - $rootfstype = $ref1->{'rootfstype'}; + my ($ref1) = $osimagetab->getAttribs({ imagename => $imgname }, 'rootfstype', 'nfsrootopts'); + if ($ref1) { + $rootfstype = $ref1->{'rootfstype'} if $ref1->{'rootfstype'}; + $nfsrootopts = $ref1->{'nfsrootopts'}; } } else { xCAT::MsgUtils->report_node_error($callback, $node, @@ -634,7 +638,12 @@ sub mknetboot # special case for redhat6, fedora12/13/14 if (&using_dracut($osver)) { - $kcmdline = "root=nfs:$nfssrv:$nfsdir/rootimg:ro STATEMNT="; + my ($nfsroot, $error) = xCAT::SvrUtils->build_statelite_nfsroot_parameter($nfssrv, "$nfsdir/rootimg", $nfsrootopts); + if ($error) { + xCAT::MsgUtils->report_node_error($callback, $node, $error); + next; + } + $kcmdline = "$nfsroot STATEMNT="; } else { $kcmdline = "NFSROOT=$nfssrv:$nfsdir STATEMNT="; } diff --git a/xCAT-server/lib/xcat/plugins/debian.pm b/xCAT-server/lib/xcat/plugins/debian.pm index 523cbfa9e..113414b85 100644 --- a/xCAT-server/lib/xcat/plugins/debian.pm +++ b/xCAT-server/lib/xcat/plugins/debian.pm @@ -1163,6 +1163,7 @@ sub mknetboot my $dump; # for kdump, its format is "nfs:///" my $crashkernelsize; my $rootfstype; + my $nfsrootopts; my $tftpdir; my $imagename; # set it if running of 'nodeset osimage=xxx' @@ -1179,13 +1180,14 @@ sub mknetboot if (!$osimagetab) { $osimagetab = xCAT::Table->new('osimage', -create => 1); } - (my $ref) = $osimagetab->getAttribs({ imagename => $imagename }, 'osvers', 'osarch', 'profile', 'provmethod', 'rootfstype'); + (my $ref) = $osimagetab->getAttribs({ imagename => $imagename }, 'osvers', 'osarch', 'profile', 'provmethod', 'rootfstype', 'nfsrootopts'); if ($ref) { $img_hash{$imagename}->{osver} = $ref->{'osvers'}; $img_hash{$imagename}->{osarch} = $ref->{'osarch'}; $img_hash{$imagename}->{profile} = $ref->{'profile'}; $img_hash{$imagename}->{provmethod} = $ref->{'provmethod'}; $img_hash{$imagename}->{rootfstype} = $ref->{'rootfstype'}; + $img_hash{$imagename}->{nfsrootopts} = $ref->{'nfsrootopts'}; if (!$linuximagetab) { $linuximagetab = xCAT::Table->new('linuximage', -create => 1); } @@ -1215,6 +1217,7 @@ sub mknetboot $profile = $ph->{profile}; $rootfstype = $ph->{rootfstype}; + $nfsrootopts = $ph->{nfsrootopts}; $rootimgdir = $ph->{rootimgdir}; unless ($rootimgdir) { @@ -1249,9 +1252,10 @@ sub mknetboot } if ($osimagetab) { - my ($ref1) = $osimagetab->getAttribs({ imagename => $imgname }, 'rootfstype'); - if (($ref1) && ($ref1->{'rootfstype'})) { - $rootfstype = $ref1->{'rootfstype'}; + my ($ref1) = $osimagetab->getAttribs({ imagename => $imgname }, 'rootfstype', 'nfsrootopts'); + if ($ref1) { + $rootfstype = $ref1->{'rootfstype'} if $ref1->{'rootfstype'}; + $nfsrootopts = $ref1->{'nfsrootopts'}; } } else { xCAT::MsgUtils->report_node_error($callback, $node, @@ -1456,7 +1460,12 @@ sub mknetboot # special case for redhat6, fedora12/13/14 if (&using_dracut($osver)) { - $kcmdline = "root=nfs:$nfssrv:$nfsdir/rootimg:ro STATEMNT="; + my ($nfsroot, $error) = xCAT::SvrUtils->build_statelite_nfsroot_parameter($nfssrv, "$nfsdir/rootimg", $nfsrootopts); + if ($error) { + xCAT::MsgUtils->report_node_error($callback, $node, $error); + next; + } + $kcmdline = "$nfsroot STATEMNT="; } else { $kcmdline = "NFSROOT=$nfssrv:$nfsdir STATEMNT="; } diff --git a/xCAT-server/lib/xcat/plugins/sles.pm b/xCAT-server/lib/xcat/plugins/sles.pm index 24cadae36..e2ac19691 100644 --- a/xCAT-server/lib/xcat/plugins/sles.pm +++ b/xCAT-server/lib/xcat/plugins/sles.pm @@ -137,6 +137,7 @@ sub mknetboot my $dump; #for kdump my $crashkernelsize; my $rootfstype; + my $nfsrootopts; my $cfgpart; my $imagename; # set it if running of 'nodeset osimage=xxx' @@ -147,12 +148,13 @@ sub mknetboot if (!$osimagetab) { $osimagetab = xCAT::Table->new('osimage', -create => 1); } - (my $ref) = $osimagetab->getAttribs({ imagename => $imagename }, 'osvers', 'osarch', 'profile', 'rootfstype', 'provmethod'); + (my $ref) = $osimagetab->getAttribs({ imagename => $imagename }, 'osvers', 'osarch', 'profile', 'rootfstype', 'nfsrootopts', 'provmethod'); if ($ref) { $img_hash{$imagename}->{osver} = $ref->{'osvers'}; $img_hash{$imagename}->{osarch} = $ref->{'osarch'}; $img_hash{$imagename}->{profile} = $ref->{'profile'}; $img_hash{$imagename}->{rootfstype} = $ref->{'rootfstype'}; + $img_hash{$imagename}->{nfsrootopts} = $ref->{'nfsrootopts'}; $img_hash{$imagename}->{provmethod} = $ref->{'provmethod'}; if (!$linuximagetab) { $linuximagetab = xCAT::Table->new('linuximage', -create => 1); @@ -204,6 +206,7 @@ sub mknetboot $arch = $ph->{osarch}; $profile = $ph->{profile}; $rootfstype = $ph->{rootfstype}; + $nfsrootopts = $ph->{nfsrootopts}; $nodebootif = $ph->{nodebootif}; $provmethod = $ph->{provmethod}; $dump = $ph->{dump}; @@ -242,9 +245,10 @@ sub mknetboot } if ($osimagetab) { - my ($ref1) = $osimagetab->getAttribs({ imagename => $imgname }, 'rootfstype'); - if (($ref1) && ($ref1->{'rootfstype'})) { - $rootfstype = $ref1->{'rootfstype'}; + my ($ref1) = $osimagetab->getAttribs({ imagename => $imgname }, 'rootfstype', 'nfsrootopts'); + if ($ref1) { + $rootfstype = $ref1->{'rootfstype'} if $ref1->{'rootfstype'}; + $nfsrootopts = $ref1->{'nfsrootopts'}; } } else { xCAT::MsgUtils->report_node_error($callback, $node, @@ -469,7 +473,12 @@ sub mknetboot $nfsdir = $ient->{nfsdir} . "/netboot/$osver/$arch/$profile"; } if (&using_dracut($rootimgdir)) { - $kcmdline = "root=nfs:$nfssrv:$nfsdir/rootimg:ro STATEMNT="; + my ($nfsroot, $error) = xCAT::SvrUtils->build_statelite_nfsroot_parameter($nfssrv, "$nfsdir/rootimg", $nfsrootopts); + if ($error) { + xCAT::MsgUtils->report_node_error($callback, $node, $error); + next; + } + $kcmdline = "$nfsroot STATEMNT="; } else { $kcmdline = "NFSROOT=$nfssrv:$nfsdir STATEMNT="; } diff --git a/xCAT-test/unit/nfs_root_options.t b/xCAT-test/unit/nfs_root_options.t new file mode 100644 index 000000000..99391f85b --- /dev/null +++ b/xCAT-test/unit/nfs_root_options.t @@ -0,0 +1,62 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use FindBin; +use lib "$FindBin::Bin/../../xCAT-server/lib/perl"; +use lib "$FindBin::Bin/../../perl-xCAT"; + +use Test::More; +use xCAT::Schema; +use xCAT::SvrUtils; + +sub build_nfsroot { + return xCAT::SvrUtils->build_statelite_nfsroot_parameter('192.0.2.1', '/install/netboot/test/rootimg', shift); +} + +my ($parameter, $error) = build_nfsroot(undef); +is($parameter, 'root=nfs:192.0.2.1:/install/netboot/test/rootimg:ro', 'unset options preserve the read-only default'); +is($error, undef, 'unset options are valid'); + +($parameter, $error) = build_nfsroot(''); +is($parameter, 'root=nfs:192.0.2.1:/install/netboot/test/rootimg:ro', 'empty options preserve the read-only default'); +is($error, undef, 'empty options are valid'); + +($parameter, $error) = build_nfsroot('noac,actimeo=0'); +is($parameter, 'root=nfs:192.0.2.1:/install/netboot/test/rootimg:ro,noac,actimeo=0', 'additional options follow the mandatory read-only option'); +is($error, undef, 'valid additional options are accepted'); + +($parameter, $error) = build_nfsroot('ro,nfsvers=4.1'); +is($parameter, 'root=nfs:192.0.2.1:/install/netboot/test/rootimg:ro,nfsvers=4.1', 'a redundant read-only option is normalized'); +is($error, undef, 'a redundant read-only option is valid'); + +($parameter, $error) = build_nfsroot('clientaddr=2001:db8::1'); +is($parameter, 'root=nfs:192.0.2.1:/install/netboot/test/rootimg:ro,clientaddr=2001:db8::1', 'option values may contain colons'); +is($error, undef, 'an option value containing colons is valid'); + +foreach my $invalid ('rw', 'RW', 'noac,rw', 'defaults', 'noac, actimeo=0', 'noac,,actimeo=0') { + ($parameter, $error) = build_nfsroot($invalid); + is($parameter, undef, "invalid option list '$invalid' is rejected"); + like($error, qr/^nfsrootopts /, "invalid option list '$invalid' reports the attribute name"); +} + +ok( + scalar(grep { $_ eq 'nfsrootopts' } @{ $xCAT::Schema::tabspec{osimage}->{cols} }), + 'osimage table includes nfsrootopts' +); +is( + $xCAT::Schema::defspec{osimage}->{attrhash}->{nfsrootopts}->{tabentry}, + 'osimage.nfsrootopts', + 'osimage object exposes nfsrootopts' +); + +foreach my $plugin (qw(anaconda debian sles)) { + my $path = "$FindBin::Bin/../../xCAT-server/lib/xcat/plugins/$plugin.pm"; + open(my $fh, '<', $path) or die "Unable to read $path: $!"; + my $source = do { local $/; <$fh> }; + close($fh); + like($source, qr/build_statelite_nfsroot_parameter/, "$plugin statelite renderer uses the shared NFS-root builder"); + like($source, qr/'rootfstype',\s*'nfsrootopts'/, "$plugin reads nfsrootopts with the statelite root type"); +} + +done_testing(); From 24e2c989570467fc47b219b6f0ae977b9305d5bf 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, 14 Jul 2026 19:11:28 -0300 Subject: [PATCH 2/6] style(statelite): align image cache assignments --- xCAT-server/lib/xcat/plugins/anaconda.pm | 10 +++++----- xCAT-server/lib/xcat/plugins/debian.pm | 10 +++++----- xCAT-server/lib/xcat/plugins/sles.pm | 10 +++++----- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/anaconda.pm b/xCAT-server/lib/xcat/plugins/anaconda.pm index 0187aef47..6ad77d3b3 100644 --- a/xCAT-server/lib/xcat/plugins/anaconda.pm +++ b/xCAT-server/lib/xcat/plugins/anaconda.pm @@ -286,11 +286,11 @@ sub mknetboot } (my $ref) = $osimagetab->getAttribs({ imagename => $imagename }, 'osvers', 'osarch', 'profile', 'provmethod', 'rootfstype', 'nfsrootopts'); if ($ref) { - $img_hash{$imagename}->{osver} = $ref->{'osvers'}; - $img_hash{$imagename}->{osarch} = $ref->{'osarch'}; - $img_hash{$imagename}->{profile} = $ref->{'profile'}; - $img_hash{$imagename}->{provmethod} = $ref->{'provmethod'}; - $img_hash{$imagename}->{rootfstype} = $ref->{rootfstype}; + $img_hash{$imagename}->{osver} = $ref->{'osvers'}; + $img_hash{$imagename}->{osarch} = $ref->{'osarch'}; + $img_hash{$imagename}->{profile} = $ref->{'profile'}; + $img_hash{$imagename}->{provmethod} = $ref->{'provmethod'}; + $img_hash{$imagename}->{rootfstype} = $ref->{rootfstype}; $img_hash{$imagename}->{nfsrootopts} = $ref->{nfsrootopts}; if (!$linuximagetab) { $linuximagetab = xCAT::Table->new('linuximage', -create => 1); diff --git a/xCAT-server/lib/xcat/plugins/debian.pm b/xCAT-server/lib/xcat/plugins/debian.pm index 113414b85..4051ca18e 100644 --- a/xCAT-server/lib/xcat/plugins/debian.pm +++ b/xCAT-server/lib/xcat/plugins/debian.pm @@ -1182,11 +1182,11 @@ sub mknetboot } (my $ref) = $osimagetab->getAttribs({ imagename => $imagename }, 'osvers', 'osarch', 'profile', 'provmethod', 'rootfstype', 'nfsrootopts'); if ($ref) { - $img_hash{$imagename}->{osver} = $ref->{'osvers'}; - $img_hash{$imagename}->{osarch} = $ref->{'osarch'}; - $img_hash{$imagename}->{profile} = $ref->{'profile'}; - $img_hash{$imagename}->{provmethod} = $ref->{'provmethod'}; - $img_hash{$imagename}->{rootfstype} = $ref->{'rootfstype'}; + $img_hash{$imagename}->{osver} = $ref->{'osvers'}; + $img_hash{$imagename}->{osarch} = $ref->{'osarch'}; + $img_hash{$imagename}->{profile} = $ref->{'profile'}; + $img_hash{$imagename}->{provmethod} = $ref->{'provmethod'}; + $img_hash{$imagename}->{rootfstype} = $ref->{'rootfstype'}; $img_hash{$imagename}->{nfsrootopts} = $ref->{'nfsrootopts'}; if (!$linuximagetab) { $linuximagetab = xCAT::Table->new('linuximage', -create => 1); diff --git a/xCAT-server/lib/xcat/plugins/sles.pm b/xCAT-server/lib/xcat/plugins/sles.pm index e2ac19691..4e42a9b02 100644 --- a/xCAT-server/lib/xcat/plugins/sles.pm +++ b/xCAT-server/lib/xcat/plugins/sles.pm @@ -150,12 +150,12 @@ sub mknetboot } (my $ref) = $osimagetab->getAttribs({ imagename => $imagename }, 'osvers', 'osarch', 'profile', 'rootfstype', 'nfsrootopts', 'provmethod'); if ($ref) { - $img_hash{$imagename}->{osver} = $ref->{'osvers'}; - $img_hash{$imagename}->{osarch} = $ref->{'osarch'}; - $img_hash{$imagename}->{profile} = $ref->{'profile'}; - $img_hash{$imagename}->{rootfstype} = $ref->{'rootfstype'}; + $img_hash{$imagename}->{osver} = $ref->{'osvers'}; + $img_hash{$imagename}->{osarch} = $ref->{'osarch'}; + $img_hash{$imagename}->{profile} = $ref->{'profile'}; + $img_hash{$imagename}->{rootfstype} = $ref->{'rootfstype'}; $img_hash{$imagename}->{nfsrootopts} = $ref->{'nfsrootopts'}; - $img_hash{$imagename}->{provmethod} = $ref->{'provmethod'}; + $img_hash{$imagename}->{provmethod} = $ref->{'provmethod'}; if (!$linuximagetab) { $linuximagetab = xCAT::Table->new('linuximage', -create => 1); } From 68a4855c7fa595193f1932c3fd0334ba41a68aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Fri, 17 Jul 2026 20:36:51 -0300 Subject: [PATCH 3/6] fix(statelite): reject invalid NFS root options early --- xCAT-server/lib/perl/xCAT/SvrUtils.pm | 34 ++++++++++++++++---- xCAT-server/lib/xcat/plugins/DBobjectdefs.pm | 27 ++++++++++++++++ xCAT-test/autotest/testcase/chdef/cases0 | 27 +++++++++++++++- xCAT-test/unit/nfs_root_options.t | 9 ++++++ 4 files changed, 90 insertions(+), 7 deletions(-) diff --git a/xCAT-server/lib/perl/xCAT/SvrUtils.pm b/xCAT-server/lib/perl/xCAT/SvrUtils.pm index 04b7305c8..e1a8df247 100644 --- a/xCAT-server/lib/perl/xCAT/SvrUtils.pm +++ b/xCAT-server/lib/perl/xCAT/SvrUtils.pm @@ -2415,13 +2415,12 @@ sub getplatform { return $platform; } -# Build the dracut root=nfs parameter while preserving statelite's read-only -# root filesystem contract. -sub build_statelite_nfsroot_parameter { - shift if @_ && defined($_[0]) && $_[0] eq __PACKAGE__; - my ($server, $rootdir, $additional_options) = @_; +# Parse statelite NFS root options once so command-time validation and the +# dracut root=nfs renderer enforce the same rules. +sub _parse_statelite_nfsroot_options { + my ($additional_options) = @_; - my @mount_options = ('ro'); + my @mount_options; if (defined($additional_options) && $additional_options ne '') { foreach my $option (split(/,/, $additional_options, -1)) { if ($option eq '' || $option =~ /\s/) { @@ -2438,6 +2437,29 @@ sub build_statelite_nfsroot_parameter { } } + return (\@mount_options, undef); +} + +# Return an error message when statelite NFS root options violate the +# read-only root filesystem contract. +sub validate_statelite_nfsroot_options { + shift if @_ && defined($_[0]) && $_[0] eq __PACKAGE__; + my ($additional_options) = @_; + + my ($mount_options, $error) = _parse_statelite_nfsroot_options($additional_options); + return $error; +} + +# Build the dracut root=nfs parameter while preserving statelite's read-only +# root filesystem contract. +sub build_statelite_nfsroot_parameter { + shift if @_ && defined($_[0]) && $_[0] eq __PACKAGE__; + my ($server, $rootdir, $additional_options) = @_; + + my ($additional_mount_options, $error) = _parse_statelite_nfsroot_options($additional_options); + return (undef, $error) if $error; + + my @mount_options = ('ro', @{$additional_mount_options}); return ('root=nfs:' . $server . ':' . $rootdir . ':' . join(',', @mount_options), undef); } diff --git a/xCAT-server/lib/xcat/plugins/DBobjectdefs.pm b/xCAT-server/lib/xcat/plugins/DBobjectdefs.pm index c9c41cb31..6c154768a 100644 --- a/xCAT-server/lib/xcat/plugins/DBobjectdefs.pm +++ b/xCAT-server/lib/xcat/plugins/DBobjectdefs.pm @@ -369,6 +369,19 @@ sub parse_attr_for_osimage { return 0; } +sub validate_osimage_nfsrootopts { + my $attr_hash = shift; + return 0 unless exists($attr_hash->{nfsrootopts}); + + my $validation_error = xCAT::SvrUtils->validate_statelite_nfsroot_options($attr_hash->{nfsrootopts}); + return 0 unless $validation_error; + + my $rsp; + $rsp->{data}->[0] = $validation_error; + xCAT::MsgUtils->message("E", $rsp, $::callback); + return 1; +} + #---------------------------------------------------------------------------- =head3 processArgs @@ -1886,6 +1899,13 @@ sub defmk next; } + if (($type eq 'osimage') && validate_osimage_nfsrootopts($::FINALATTRS{$obj})) + { + $error = 1; + delete $::FINALATTRS{$obj}; + next; + } + if ($object_exists && $::opt_f) { # remove the old object after the replacement definition is known valid @@ -2531,6 +2551,13 @@ sub defch $isDefined = 1; } + if (($type eq 'osimage') && !$::opt_m && validate_osimage_nfsrootopts($::FINALATTRS{$obj})) + { + $error = 1; + delete($::FINALATTRS{$obj}); + next; + } + if ($type eq 'network') { my $isInvalid = 0; diff --git a/xCAT-test/autotest/testcase/chdef/cases0 b/xCAT-test/autotest/testcase/chdef/cases0 index dc84f1e40..619f70428 100644 --- a/xCAT-test/autotest/testcase/chdef/cases0 +++ b/xCAT-test/autotest/testcase/chdef/cases0 @@ -34,6 +34,32 @@ cmd:rmdef -t node testnode check:rc==0 end +start:chdef_osimage_nfsrootopts_validation +description:Reject invalid statelite NFS root options before provisioning without changing the osimage +label:mn_only,ci_test,db,statelite,nfsrootopts +cmd:rmdef -t node -o xcatnfsoptscinode >/dev/null 2>&1; rmdef -t osimage -o xcatnfsoptsciimage >/dev/null 2>&1; rm -rf /tmp/xcat-nfsrootopts-ci-root /tftpboot/xcat/osimage/xcatnfsoptsciimage; rm -f /tftpboot/xcat/xnba/nodes/xcatnfsoptscinode* +cmd:mkdir -p /tmp/xcat-nfsrootopts-ci-root; touch /tmp/xcat-nfsrootopts-ci-root/kernel /tmp/xcat-nfsrootopts-ci-root/initrd-statelite.gz +check:rc==0 +cmd:mkdef -t osimage -o xcatnfsoptsciimage imagetype=linux provmethod=statelite profile=compute osname=Linux osvers=rhels6.99 osarch=x86_64 rootfstype=nfs rootimgdir=/tmp/xcat-nfsrootopts-ci-root nfsrootopts=noac +check:rc==0 +cmd:mkdef -t node -o xcatnfsoptscinode groups=all arch=x86_64 netboot=xnba os=rhels6.99 profile=compute ip=192.0.2.100 mac=02:00:00:00:00:01 +check:rc==0 +cmd:chdef -t osimage -o xcatnfsoptsciimage nfsrootopts=rw +check:rc!=0 +check:output=~nfsrootopts cannot contain 'rw'; statelite NFS roots are always read-only +cmd:lsdef -t osimage -o xcatnfsoptsciimage -i nfsrootopts +check:rc==0 +check:output=~nfsrootopts=noac +check:output!~nfsrootopts=rw +cmd:nodeset xcatnfsoptscinode osimage=xcatnfsoptsciimage +check:rc==0 +check:output!~nfsrootopts +cmd:grep 'root=nfs:.*:ro,noac' /tftpboot/xcat/xnba/nodes/xcatnfsoptscinode +check:rc==0 +cmd:rmdef -t node -o xcatnfsoptscinode; rmdef -t osimage -o xcatnfsoptsciimage; rm -rf /tmp/xcat-nfsrootopts-ci-root /tftpboot/xcat/osimage/xcatnfsoptsciimage; rm -f /tftpboot/xcat/xnba/nodes/xcatnfsoptscinode* +check:rc==0 +end + start:chdef_t_network description:chdef -t network label:mn_only,ci_test,db @@ -324,4 +350,3 @@ cmd:rmdef -t network -o aaaaa_not_exist check:rc==0 cmd:rm -rf /tmp/bbbbb_not_exist.def end - diff --git a/xCAT-test/unit/nfs_root_options.t b/xCAT-test/unit/nfs_root_options.t index 99391f85b..bc721adc0 100644 --- a/xCAT-test/unit/nfs_root_options.t +++ b/xCAT-test/unit/nfs_root_options.t @@ -38,8 +38,17 @@ foreach my $invalid ('rw', 'RW', 'noac,rw', 'defaults', 'noac, actimeo=0', 'noac ($parameter, $error) = build_nfsroot($invalid); is($parameter, undef, "invalid option list '$invalid' is rejected"); like($error, qr/^nfsrootopts /, "invalid option list '$invalid' reports the attribute name"); + like( + xCAT::SvrUtils->validate_statelite_nfsroot_options($invalid), + qr/^nfsrootopts /, + "command-time validation rejects '$invalid'" + ); } +is(xCAT::SvrUtils->validate_statelite_nfsroot_options(undef), undef, 'command-time validation accepts an unset value'); +is(xCAT::SvrUtils->validate_statelite_nfsroot_options(''), undef, 'command-time validation accepts an empty value'); +is(xCAT::SvrUtils->validate_statelite_nfsroot_options('noac,actimeo=0'), undef, 'command-time validation accepts valid options'); + ok( scalar(grep { $_ eq 'nfsrootopts' } @{ $xCAT::Schema::tabspec{osimage}->{cols} }), 'osimage table includes nfsrootopts' From b6993e2d6369d6f22ef74416ad1dc498ab530d82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Fri, 17 Jul 2026 20:38:23 -0300 Subject: [PATCH 4/6] test(statelite): cover NFS root options in provisioning --- ...eg_linux_statelite_installation_hierarchy_by_nfs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/xCAT-test/autotest/testcase/installation/reg_linux_statelite_installation_hierarchy_by_nfs b/xCAT-test/autotest/testcase/installation/reg_linux_statelite_installation_hierarchy_by_nfs index 637386df4..c73fd3e30 100644 --- a/xCAT-test/autotest/testcase/installation/reg_linux_statelite_installation_hierarchy_by_nfs +++ b/xCAT-test/autotest/testcase/installation/reg_linux_statelite_installation_hierarchy_by_nfs @@ -65,8 +65,15 @@ check:rc==0 cmd:lsdef -t osimage -o __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-statelite-compute check:rc==0 -cmd:chdef -t osimage -o __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-statelite-compute rootfstype=nfs +cmd:chdef -t osimage -o __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-statelite-compute rootfstype=nfs nfsrootopts=noac check:rc==0 +cmd:chdef -t osimage -o __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-statelite-compute nfsrootopts=rw +check:rc!=0 +check:output=~nfsrootopts cannot contain 'rw'; statelite NFS roots are always read-only +cmd:lsdef -t osimage -o __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-statelite-compute -i nfsrootopts +check:rc==0 +check:output=~nfsrootopts=noac +check:output!~nfsrootopts=rw cmd:genimage __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-statelite-compute check:rc==0 @@ -99,6 +106,8 @@ cmd:xdsh $$CN mount check:rc==0 check:output=~/nodedata/$$CN on /.statelite/persistent check:output=~compute/rootimg on / type nfs +cmd:rootimgdir=`lsdef -t osimage __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-statelite-compute|grep rootimgdir|awk -F'=' '{print $2}'`; if [[ "__GETNODEATTR($$CN,os)__" =~ ^(rhels|rhel|centos|alma|rocky|ol)([6-9]|10) ]] || [[ "__GETNODEATTR($$CN,os)__" =~ ^fedora(1[2-9]|[2-9][0-9]) ]] || [[ "__GETNODEATTR($$CN,os)__" =~ ^SL([6-9]|10) ]] || [ -f "$rootimgdir/rootimg/etc/dracut.conf" ]; then xdsh $$CN mount | grep 'compute/rootimg on / type nfs' | grep 'noac'; fi +check:rc==0 cmd:xdsh $$CN hostname check:rc==0 check:output=~$$CN: $$CN @@ -112,6 +121,8 @@ check:output=~No load hostkey warning cmd:if [ -x /usr/bin/goconserver ]; then makegocons -d $$CN; else makeconservercf -d $$CN; fi cmd:output=$(xdsh $$CN ls -al / |grep test.statelite);if [[ $? -eq 0 ]];then xdsh $$CN rm -rf /test.statelite;fi +cmd:chdef -t osimage -o __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-statelite-compute nfsrootopts= +check:rc==0 cmd:rootimgdir=`lsdef -t osimage __GETNODEATTR($$CN,os)__-__GETNODEATTR($$CN,arch)__-statelite-compute|grep rootimgdir|awk -F'=' '{print $2}'`; if [ -d $rootimgdir ]; then rm -rf $rootimgdir;fi check:rc==0 end From 95144c2685bb8df9d611b0f38ab7b4c786320d38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Fri, 17 Jul 2026 21:31:01 -0300 Subject: [PATCH 5/6] docs(osimage): document NFS root options attribute --- .../guides/admin-guides/references/man7/osimage.7.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/source/guides/admin-guides/references/man7/osimage.7.rst b/docs/source/guides/admin-guides/references/man7/osimage.7.rst index 1171e280f..ba5101245 100644 --- a/docs/source/guides/admin-guides/references/man7/osimage.7.rst +++ b/docs/source/guides/admin-guides/references/man7/osimage.7.rst @@ -19,7 +19,7 @@ SYNOPSIS ******** -\ **osimage Attributes:**\ \ *addkcmdline*\ , \ *boottarget*\ , \ *bosinst_data*\ , \ *cfmdir*\ , \ *configdump*\ , \ *crashkernelsize*\ , \ *description*\ , \ *driverupdatesrc*\ , \ *dump*\ , \ *environvar*\ , \ *exlist*\ , \ *fb_script*\ , \ *groups*\ , \ *home*\ , \ *image_data*\ , \ *imagename*\ , \ *imagetype*\ , \ *installp_bundle*\ , \ *installto*\ , \ *isdeletable*\ , \ *kerneldir*\ , \ *kernelver*\ , \ *kitcomponents*\ , \ *krpmver*\ , \ *lpp_source*\ , \ *mksysb*\ , \ *netdrivers*\ , \ *nimmethod*\ , \ *nimtype*\ , \ *nodebootif*\ , \ *osarch*\ , \ *osdistroname*\ , \ *osname*\ , \ *osupdatename*\ , \ *osvers*\ , \ *otherifce*\ , \ *otherpkgdir*\ , \ *otherpkglist*\ , \ *otherpkgs*\ , \ *paging*\ , \ *partitionfile*\ , \ *permission*\ , \ *pkgdir*\ , \ *pkglist*\ , \ *postbootscripts*\ , \ *postinstall*\ , \ *postscripts*\ , \ *profile*\ , \ *provmethod*\ , \ *resolv_conf*\ , \ *root*\ , \ *rootfstype*\ , \ *rootimgdir*\ , \ *script*\ , \ *serverrole*\ , \ *shared_home*\ , \ *shared_root*\ , \ *spot*\ , \ *synclists*\ , \ *template*\ , \ *tmp*\ , \ *usercomment*\ , \ *winpepath*\ +\ **osimage Attributes:**\ \ *addkcmdline*\ , \ *boottarget*\ , \ *bosinst_data*\ , \ *cfmdir*\ , \ *configdump*\ , \ *crashkernelsize*\ , \ *description*\ , \ *driverupdatesrc*\ , \ *dump*\ , \ *environvar*\ , \ *exlist*\ , \ *fb_script*\ , \ *groups*\ , \ *home*\ , \ *image_data*\ , \ *imagename*\ , \ *imagetype*\ , \ *installp_bundle*\ , \ *installto*\ , \ *isdeletable*\ , \ *kerneldir*\ , \ *kernelver*\ , \ *kitcomponents*\ , \ *krpmver*\ , \ *lpp_source*\ , \ *mksysb*\ , \ *netdrivers*\ , \ *nimmethod*\ , \ *nimtype*\ , \ *nfsrootopts*\ , \ *nodebootif*\ , \ *osarch*\ , \ *osdistroname*\ , \ *osname*\ , \ *osupdatename*\ , \ *osvers*\ , \ *otherifce*\ , \ *otherpkgdir*\ , \ *otherpkglist*\ , \ *otherpkgs*\ , \ *paging*\ , \ *partitionfile*\ , \ *permission*\ , \ *pkgdir*\ , \ *pkglist*\ , \ *postbootscripts*\ , \ *postinstall*\ , \ *postscripts*\ , \ *profile*\ , \ *provmethod*\ , \ *resolv_conf*\ , \ *root*\ , \ *rootfstype*\ , \ *rootimgdir*\ , \ *script*\ , \ *serverrole*\ , \ *shared_home*\ , \ *shared_root*\ , \ *spot*\ , \ *synclists*\ , \ *template*\ , \ *tmp*\ , \ *usercomment*\ , \ *winpepath* *********** @@ -217,6 +217,12 @@ osimage Attributes: +\ **nfsrootopts**\ (osimage.nfsrootopts) + + A comma-separated list of additional NFS mount options for the root filesystem of a dracut-based statelite image. The root filesystem is always mounted read-only; rw and defaults are not allowed. + + + \ **nodebootif**\ (linuximage.nodebootif) The network interface the stateless/statelite node will boot over (e.g. eth0) From 4d75fd5461a5e17c8449ea3d12a097c54ce89900 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Fri, 17 Jul 2026 21:55:48 -0300 Subject: [PATCH 6/6] test(statelite): stabilize NFS root options validation --- .../admin-guides/references/man5/osimage.5.rst | 4 ++-- .../admin-guides/references/man7/osimage.7.rst | 13 ++++++------- xCAT-test/autotest/testcase/chdef/cases0 | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/docs/source/guides/admin-guides/references/man5/osimage.5.rst b/docs/source/guides/admin-guides/references/man5/osimage.5.rst index 510ad917c..5ec6a150e 100644 --- a/docs/source/guides/admin-guides/references/man5/osimage.5.rst +++ b/docs/source/guides/admin-guides/references/man5/osimage.5.rst @@ -78,9 +78,9 @@ osimage Attributes: -**nfsrootopts** +\ **nfsrootopts** -A comma-separated list of additional NFS mount options for the root filesystem of a dracut-based statelite image. The root filesystem is always mounted read-only; rw and defaults are not allowed. + A comma-separated list of additional NFS mount options for the root filesystem of a dracut-based statelite image. The root filesystem is always mounted read-only; rw and defaults are not allowed. \ **osdistroname**\ diff --git a/docs/source/guides/admin-guides/references/man7/osimage.7.rst b/docs/source/guides/admin-guides/references/man7/osimage.7.rst index ba5101245..cb31b767e 100644 --- a/docs/source/guides/admin-guides/references/man7/osimage.7.rst +++ b/docs/source/guides/admin-guides/references/man7/osimage.7.rst @@ -19,7 +19,7 @@ SYNOPSIS ******** -\ **osimage Attributes:**\ \ *addkcmdline*\ , \ *boottarget*\ , \ *bosinst_data*\ , \ *cfmdir*\ , \ *configdump*\ , \ *crashkernelsize*\ , \ *description*\ , \ *driverupdatesrc*\ , \ *dump*\ , \ *environvar*\ , \ *exlist*\ , \ *fb_script*\ , \ *groups*\ , \ *home*\ , \ *image_data*\ , \ *imagename*\ , \ *imagetype*\ , \ *installp_bundle*\ , \ *installto*\ , \ *isdeletable*\ , \ *kerneldir*\ , \ *kernelver*\ , \ *kitcomponents*\ , \ *krpmver*\ , \ *lpp_source*\ , \ *mksysb*\ , \ *netdrivers*\ , \ *nimmethod*\ , \ *nimtype*\ , \ *nfsrootopts*\ , \ *nodebootif*\ , \ *osarch*\ , \ *osdistroname*\ , \ *osname*\ , \ *osupdatename*\ , \ *osvers*\ , \ *otherifce*\ , \ *otherpkgdir*\ , \ *otherpkglist*\ , \ *otherpkgs*\ , \ *paging*\ , \ *partitionfile*\ , \ *permission*\ , \ *pkgdir*\ , \ *pkglist*\ , \ *postbootscripts*\ , \ *postinstall*\ , \ *postscripts*\ , \ *profile*\ , \ *provmethod*\ , \ *resolv_conf*\ , \ *root*\ , \ *rootfstype*\ , \ *rootimgdir*\ , \ *script*\ , \ *serverrole*\ , \ *shared_home*\ , \ *shared_root*\ , \ *spot*\ , \ *synclists*\ , \ *template*\ , \ *tmp*\ , \ *usercomment*\ , \ *winpepath* +\ **osimage Attributes:**\ \ *addkcmdline*\ , \ *boottarget*\ , \ *bosinst_data*\ , \ *cfmdir*\ , \ *configdump*\ , \ *crashkernelsize*\ , \ *description*\ , \ *driverupdatesrc*\ , \ *dump*\ , \ *environvar*\ , \ *exlist*\ , \ *fb_script*\ , \ *groups*\ , \ *home*\ , \ *image_data*\ , \ *imagename*\ , \ *imagetype*\ , \ *installp_bundle*\ , \ *installto*\ , \ *isdeletable*\ , \ *kerneldir*\ , \ *kernelver*\ , \ *kitcomponents*\ , \ *krpmver*\ , \ *lpp_source*\ , \ *mksysb*\ , \ *netdrivers*\ , \ *nfsrootopts*\ , \ *nimmethod*\ , \ *nimtype*\ , \ *nodebootif*\ , \ *osarch*\ , \ *osdistroname*\ , \ *osname*\ , \ *osupdatename*\ , \ *osvers*\ , \ *otherifce*\ , \ *otherpkgdir*\ , \ *otherpkglist*\ , \ *otherpkgs*\ , \ *paging*\ , \ *partitionfile*\ , \ *permission*\ , \ *pkgdir*\ , \ *pkglist*\ , \ *postbootscripts*\ , \ *postinstall*\ , \ *postscripts*\ , \ *profile*\ , \ *provmethod*\ , \ *resolv_conf*\ , \ *root*\ , \ *rootfstype*\ , \ *rootimgdir*\ , \ *script*\ , \ *serverrole*\ , \ *shared_home*\ , \ *shared_root*\ , \ *spot*\ , \ *synclists*\ , \ *template*\ , \ *tmp*\ , \ *usercomment*\ , \ *winpepath* *********** @@ -204,6 +204,11 @@ osimage Attributes: The ethernet device drivers of the nodes which will use this linux image, at least the device driver for the nodes' installnic should be included +\ **nfsrootopts**\ (osimage.nfsrootopts) + + A comma-separated list of additional NFS mount options for the root filesystem of a dracut-based statelite image. The root filesystem is always mounted read-only; rw and defaults are not allowed. + + \ **nimmethod**\ (nimimage.nimmethod) @@ -217,12 +222,6 @@ osimage Attributes: -\ **nfsrootopts**\ (osimage.nfsrootopts) - - A comma-separated list of additional NFS mount options for the root filesystem of a dracut-based statelite image. The root filesystem is always mounted read-only; rw and defaults are not allowed. - - - \ **nodebootif**\ (linuximage.nodebootif) The network interface the stateless/statelite node will boot over (e.g. eth0) diff --git a/xCAT-test/autotest/testcase/chdef/cases0 b/xCAT-test/autotest/testcase/chdef/cases0 index 619f70428..e2456c164 100644 --- a/xCAT-test/autotest/testcase/chdef/cases0 +++ b/xCAT-test/autotest/testcase/chdef/cases0 @@ -51,7 +51,7 @@ cmd:lsdef -t osimage -o xcatnfsoptsciimage -i nfsrootopts check:rc==0 check:output=~nfsrootopts=noac check:output!~nfsrootopts=rw -cmd:nodeset xcatnfsoptscinode osimage=xcatnfsoptsciimage +cmd:old=`lsdef -t site clustersite -i dhcpsetup | grep 'dhcpsetup=' | awk -F= '{print $2}'`; trap 'chdef -t site clustersite dhcpsetup="$old" >/dev/null 2>&1' EXIT; chdef -t site clustersite dhcpsetup=n >/dev/null 2>&1 && nodeset xcatnfsoptscinode osimage=xcatnfsoptsciimage check:rc==0 check:output!~nfsrootopts cmd:grep 'root=nfs:.*:ro,noac' /tftpboot/xcat/xnba/nodes/xcatnfsoptscinode