mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-07-31 18:19:40 +00:00
Merge pull request #7588 from VersatusHPC/fix/issue-6495-nfs-root-options
feat: add configurable NFS root options for statelite images
This commit is contained in:
+13
@@ -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.
|
||||
|
||||
@@ -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)**\
|
||||
|
||||
|
||||
@@ -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*\ , \ *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)
|
||||
|
||||
|
||||
@@ -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/<osimage name>/cfmdir by PCM. ',
|
||||
@@ -3217,6 +3218,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',
|
||||
|
||||
@@ -2415,6 +2415,54 @@ sub getplatform {
|
||||
return $platform;
|
||||
}
|
||||
|
||||
# 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;
|
||||
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 (\@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);
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------------------------------------
|
||||
#searchcompressedrootimg:
|
||||
#description: search the compressed rootimage for diskless or statelite osimage under specified directory
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -261,6 +261,7 @@ sub mknetboot
|
||||
my $dump; # for kdump, its format is "nfs://<nfs_server_ip>/<kdump_path>"
|
||||
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}->{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=";
|
||||
}
|
||||
|
||||
@@ -1163,6 +1163,7 @@ sub mknetboot
|
||||
my $dump; # for kdump, its format is "nfs://<nfs_server_ip>/<kdump_path>"
|
||||
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}->{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=";
|
||||
}
|
||||
|
||||
@@ -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,13 +148,14 @@ 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}->{provmethod} = $ref->{'provmethod'};
|
||||
$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=";
|
||||
}
|
||||
|
||||
@@ -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: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
|
||||
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
|
||||
|
||||
|
||||
+12
-1
@@ -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
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
#!/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");
|
||||
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'
|
||||
);
|
||||
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();
|
||||
Reference in New Issue
Block a user