From bfac2a196457149123c14b55fb6b8c9c8a46c769 Mon Sep 17 00:00:00 2001 From: Michel Jouvin Date: Mon, 23 Jan 2017 07:33:20 +0100 Subject: [PATCH] aii-pxelinux: create configuration files for PXELINUX and Grub2 UEFI - Configuration is built for every variant enabled - Significant code cleanup - Contributes to #216 --- .../src/main/perl/PXELINUX/constants.pm | 91 +++++ aii-pxelinux/src/main/perl/pxelinux.pm | 346 ++++++++++++------ aii-pxelinux/src/test/perl/pxelinux_hooks.t | 2 +- .../src/test/perl/pxelinux_ks_block.t | 8 +- .../src/test/perl/pxelinux_ks_bonding.t | 6 +- .../test/perl/pxelinux_ks_bonding_bridge.t | 6 +- .../src/test/perl/pxelinux_ks_el7_static_ip.t | 6 +- .../src/test/perl/pxelinux_ks_logging.t | 4 +- .../test/perl/pxelinux_ks_nologging_host.t | 4 +- .../test/perl/pxelinux_ks_special_ksdevice.t | 4 +- .../test/perl/pxelinux_ks_systemd_ksdevice.t | 4 +- .../src/test/perl/pxelinux_no_append_block.t | 8 +- .../src/test/resources/pxelinux_ks.pan | 2 +- .../src/test/resources/pxelinux_no_append.pan | 27 -- .../resources/pxelinux_no_append_block.pan | 2 +- 15 files changed, 360 insertions(+), 160 deletions(-) create mode 100644 aii-pxelinux/src/main/perl/PXELINUX/constants.pm delete mode 100644 aii-pxelinux/src/test/resources/pxelinux_no_append.pan diff --git a/aii-pxelinux/src/main/perl/PXELINUX/constants.pm b/aii-pxelinux/src/main/perl/PXELINUX/constants.pm new file mode 100644 index 00000000..ba41c473 --- /dev/null +++ b/aii-pxelinux/src/main/perl/PXELINUX/constants.pm @@ -0,0 +1,91 @@ +#${PMpre} NCM::Component::PXELINUX::constants${PMpost} + +=pod + +This aii-pxelinux submodule only defines constants used by +pxelinux module and shared with others. It allows to share +the constant definitions without bringing all the aii-pxelinux +depencies. + +=cut + +use Readonly; +use Exporter qw(import); + +# PXE commands supported +use constant CONFIGURE => undef; +use constant INSTALL => 'install'; +use constant BOOT => 'boot'; +use constant RESCUE => 'rescue'; +use constant RESCUEBOOT => 'rescueconfig'; +use constant FIRMWARE => 'firmware'; +use constant LIVECD => 'livecd'; + +# Default paths and option values related to PXE configuration +use constant OSINSTALL_DEF_ROOT_PATH => '/osinstall/nbp'; +use constant OSINSTALL_DEF_PXELINUX_DIR => '/pxelinux.cfg'; +use constant OSINSTALL_DEF_GRUB2_DIR => '/grub-efi'; +use constant LOCAL_BOOT_CONFIG_FILE => 'localboot.cfg'; +use constant GRUB2_EFI_LINUX_CMD_DEFAULT => 'linuxefi'; +use constant NBPDIR_VARIANT_DISABLED => 'none'; + +# Option names related to PXE configuration +use constant LOCALBOOT => 'bootconfig'; +use constant NBPDIR_PXELINUX => 'nbpdir'; +use constant NBPDIR_GRUB2 => 'nbpdir_grub2'; +use constant GRUB2_EFI_KERNEL_ROOT => 'grub2_efi_kernel_root'; +use constant GRUB2_EFI_LINUX_CMD => 'grub2_efi_linux_cmd'; +use constant GRUB2_EFI_INITRD_CMD => 'grub2_efi_initrd_cmd'; + +# Hooks for NBP (PXE/UEFI) plug-in +use constant HOOK_PATH => '/system/aii/hooks/'; +use constant REMOVE_HOOK_PATH => HOOK_PATH.'remove'; +use constant STATUS_HOOK_PATH => HOOK_PATH.'status'; + +# Supported PXE variants +use enum qw(PXE_VARIANT_PXELINUX PXE_VARIANT_GRUB2); + +# To ease constant export/import by tests and other modules +# Some constants are use only by unit tests +Readonly my @PXE_VARIANTS => qw( + PXE_VARIANT_PXELINUX + PXE_VARIANT_GRUB2 +); +Readonly my @PXE_CONSTANTS => qw( + LOCALBOOT + LOCAL_BOOT_CONFIG_FILE + NBPDIR_VARIANT_DISABLED + NBPDIR_PXELINUX + NBPDIR_GRUB2 + GRUB2_EFI_KERNEL_ROOT + GRUB2_EFI_INITRD_CMD + GRUB2_EFI_LINUX_CMD + GRUB2_EFI_LINUX_CMD_DEFAULT + OSINSTALL_DEF_ROOT_PATH + OSINSTALL_DEF_PXELINUX_DIR + OSINSTALL_DEF_GRUB2_DIR +); +Readonly my @PXE_COMMANDS => qw( + BOOT + CONFIGURE + FIRMWARE + INSTALL + LIVECD + RESCUE + RESCUEBOOT +); +Readonly my @PXE_HOOKS => qw( + HOOK_PATH + REMOVE_HOOK_PATH + STATUS_HOOK_PATH +); +our @EXPORT_OK; +push @EXPORT_OK, @PXE_VARIANTS, @PXE_CONSTANTS, @PXE_COMMANDS, @PXE_HOOKS; +our %EXPORT_TAGS = ( + all => \@EXPORT_OK, + pxe_commands => \@PXE_COMMANDS, + pxe_constants => \@PXE_CONSTANTS, + pxe_hooks => \@PXE_HOOKS, + pxe_variants => \@PXE_VARIANTS, +); + diff --git a/aii-pxelinux/src/main/perl/pxelinux.pm b/aii-pxelinux/src/main/perl/pxelinux.pm index 9ef925f6..0a4b2890 100755 --- a/aii-pxelinux/src/main/perl/pxelinux.pm +++ b/aii-pxelinux/src/main/perl/pxelinux.pm @@ -7,26 +7,14 @@ use NCM::Component::ks qw (ksuserhooks); use LC::Fatal qw (symlink); use File::stat; use Time::localtime; +use Readonly; + +use parent qw (NCM::Component); use constant PXEROOT => "/system/aii/nbp/pxelinux"; -use constant NBPDIR => 'nbpdir'; -use constant LOCALBOOT => 'bootconfig'; use constant HOSTNAME => "/system/network/hostname"; use constant DOMAINNAME => "/system/network/domainname"; -use constant ETH => "/system/network/interfaces"; - -use constant CONFIGURE => undef; -use constant INSTALL => 'install'; -use constant BOOT => 'boot'; -use constant RESCUE => 'rescue'; -use constant RESCUEBOOT => 'rescueconfig'; -use constant FIRMWARE => 'firmware'; -use constant LIVECD => 'livecd'; - -# Hooks for NBP plug-in -use constant HOOK_PATH => '/system/aii/hooks/'; -use constant REMOVE_HOOK_PATH => HOOK_PATH.'remove'; -use constant STATUS_HOOK_PATH => HOOK_PATH.'status'; +use constant INTERFACES => "/system/network/interfaces"; # Kickstart constants (trying to use same name as in ks.pm from aii-ks) use constant KS => "/system/aii/osinstall/ks"; @@ -37,11 +25,66 @@ use constant ANACONDA_VERSION_EL_6_0 => version->new("13.21"); use constant ANACONDA_VERSION_EL_7_0 => version->new("19.31"); use constant ANACONDA_VERSION_LOWEST => ANACONDA_VERSION_EL_5_0; -use parent qw (NCM::Component); +# Import PXE-related constants shared with other modules +use NCM::Component::PXELINUX::constants qw(:all); + +# Support PXE variants and their parameters (currently PXELINUX and Grub2) +# 'name' is a descriptive name for information/debugging messages +Readonly my %GRUB2_VARIANT_PARAMS => (name => 'Grub2', + nbpdir_opt => NBPDIR_GRUB2, + kernel_root_path => GRUB2_EFI_KERNEL_ROOT, + format_method => \&write_grub2_config); +Readonly my %PXELINUX_VARIANT_PARAMS => (name => 'PXELINUX', + nbpdir_opt => NBPDIR_PXELINUX, + kernel_root_path => '', + format_method => \&write_pxelinux_config); +# Element in @VARIANT_PARAMS must be in the same order as enum PXE_VARIANT_xxx +Readonly my @VARIANT_PARAMS => (\%PXELINUX_VARIANT_PARAMS, \%GRUB2_VARIANT_PARAMS); our $EC = LC::Exception::Context->new->will_store_all; our $this_app = $main::this_app; + +# Check if a configuration option exists +sub option_exists +{ + my ($option)= @_; + return $this_app->{CONFIG}->_exists($option); +} + +# Return a configuration option value for a given variant. +# Return the value of variant attribute. +# Attribute can be any valid key in one of the xxx_VARIANT_PARAMS +sub variant_attribute +{ + my ($attribute, $variant) = @_; + return $VARIANT_PARAMS[$variant]->{$attribute}; +} + +# Return a configuration option value for a given variant. +# First argument is a variant attribute that will be interpreted +# as a configuration option. +sub variant_option +{ + my ($attribute, $variant) = @_; + return $this_app->option (variant_attribute($attribute, $variant)); +} + +# Test if a variant is enabled +# A variant is enabled if the configuration option defined in its 'nbpdir' +# attribute is defined and is not 'none' +sub variant_enabled +{ + my ($variant) = @_; + my $nbpdir = variant_attribute('nbpdir_opt', $variant); + $this_app->debug(2, "Using option '$nbpdir' to check if variant ", variant_attribute('name',$variant), " is enabled"); + my $enabled = option_exists($nbpdir) && + ($this_app->option($nbpdir) ne NBPDIR_VARIANT_DISABLED); + return $enabled; +} + + +# Return the fqdn of the node # Return the fqdn of the node sub get_fqdn { @@ -67,23 +110,43 @@ sub get_anaconda_version return $version; } -# Returns the absolute path where the PXE file must be written. +# Retuns the IP-based PXE file name, based on the PXE variant +sub hexip_filename +{ + my ($ip, $variant) = @_; + + my $hexip_str = ''; + if ( $ip =~ m/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ ) { + $hexip_str = sprintf ("%02X%02X%02X%02X", $1, $2, $3, $4); + if ( $variant eq PXE_VARIANT_GRUB2 ) { + $hexip_str = "grub.cfg-$hexip_str"; + } elsif ( $variant ne PXE_VARIANT_PXELINUX ) { + $this_app->error("Internal error: invalid PXE variant ($variant)"); + } + } else { + $this_app->error("Invalid IPv4 address ($ip)"); + } + + return $hexip_str; +} + +# Returns the absolute path where the PXE file must be written, based on the PXE variant sub filepath { - my $cfg = shift; + my ($cfg, $variant) = @_; my $fqdn = get_fqdn($cfg); - my $dir = $this_app->option (NBPDIR); - $this_app->debug(3, "NBP directory = $dir"); + my $dir = variant_option('nbpdir_opt', $variant); + $this_app->debug(2, "NBP directory (PXE variant=", variant_attribute('name',$variant), ") = $dir"); return "$dir/$fqdn.cfg"; } -# Returns the absolute path of the PXE file to link to +# Returns the absolute path of the PXE file to link to, based on the PXE variant sub link_filepath { - my ($cfg, $cmd) = @_; + my ($cfg, $cmd, $variant) = @_; - my $dir = $this_app->option (NBPDIR); + my $dir = variant_option('nbpdir_opt', $variant); my $cfgpath = PXEROOT . "/" . $cmd; if ($cfg->elementExists ($cfgpath)) { @@ -99,13 +162,13 @@ sub link_filepath return "$dir/$1"; } else { my $fqdn = get_fqdn($cfg); - $this_app->debug(3, "No $cmd defined for $fqdn"); + $this_app->debug(2, "No $cmd defined for $fqdn"); } return undef; } -# Configure the ksdevice with static IP +# Configure the ksdevice with a static IP # (EL7+ only) sub pxe_ks_static_network { @@ -121,7 +184,7 @@ sub pxe_ks_static_network # continue with network settings on the bridge device if ($net->{bridge}) { my $brdev = $net->{bridge}; - $this_app->debug (5, "Device $dev is a bridge interface for bridge $brdev."); + $this_app->debug (2, "Device $dev is a bridge interface for bridge $brdev."); # continue with network settings for the bridge device $net = $config->getElement("/system/network/interfaces/$brdev")->getTree; # warning: $dev is changed here to the bridge device to create correct log @@ -347,13 +410,13 @@ sub pxe_append } } -# Prints the PXE configuration file. -sub pxeprint +# Write the PXELINUX configuration file. +sub write_pxelinux_config { my $cfg = shift; - my $t = $cfg->getElement (PXEROOT)->getTree; - my $fh = CAF::FileWriter->open (filepath ($cfg), - log => $this_app, mode => 0644); + my $pxe_config = $cfg->getElement (PXEROOT)->getTree; + my $fh = CAF::FileWriter->open (filepath ($cfg, PXE_VARIANT_PXELINUX), + log => $this_app, mode => 0644); my $appendtxt = ''; my @appendoptions = pxe_append($cfg); @@ -362,33 +425,74 @@ sub pxeprint $fh->print (<{label} - label $t->{label} - kernel $t->{kernel} +default Install $pxe_config->{label} + label $pxe_config->{label} + kernel $pxe_config->{kernel} $appendtxt EOF ); # TODO is ksdevice still mandatory? if not, fix schema (code is already ok) # ksdecvice=bootif is an anaconda-ism, but can serve general purpose - $fh->print (" ipappend 2\n") if ($t->{ksdevice} && $t->{ksdevice} eq 'bootif'); + $fh->print (" ipappend 2\n") if ($pxe_config->{ksdevice} && $pxe_config->{ksdevice} eq 'bootif'); $fh->close(); } -# Prints an IP address in hexadecimal. -sub hexip + +# Write the Grub2 configuration file. +# Return 1 if the file was written successfully, 0 otherwise. +# TODO: handle append options? +sub write_grub2_config { - my $ip = shift || ""; + my $cfg = shift; + my $pxe_config = $cfg->getElement (PXEROOT)->getTree; + + my $linux_cmd = $this_app->option(GRUB2_EFI_LINUX_CMD); + unless ( $linux_cmd ) { + $this_app->error("AII option ".GRUB2_EFI_LINUX_CMD." undefined"); + return 0; + }; + my $initrd_cmd = $this_app->option(GRUB2_EFI_INITRD_CMD); + unless ( $initrd_cmd ) { + $this_app->error("AII option ".GRUB2_EFI_INITRD_CMD." undefined"); + return 0; + }; + my $kernel_root = ''; + if ( option_exists(GRUB2_EFI_KERNEL_ROOT) ) { + $kernel_root = $this_app->option(GRUB2_EFI_KERNEL_ROOT); + } + my $kernel_path = "$kernel_root/$pxe_config->{kernel}"; + my $initrd_path = "$kernel_root/$pxe_config->{initrd}"; - return sprintf ("%02X%02X%02X%02X", $1, $2, $3, $4) if ($ip =~ m/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/); + my $fh = CAF::FileWriter->open (filepath ($cfg, PXE_VARIANT_GRUB2), + log => $this_app, mode => 0644); + $fh->print (<{label}" { + set root=(pxe) + $linux_cmd $kernel_path ks=$pxe_config->{kslocation} ksdevice=$pxe_config->{ksdevice} + $initrd_cmd $initrd_path + } } +EOF + ); + # TODO: add specific processing of ksdevice=bootif as for PXELINUX? + $fh->close(); + + return 1; +} + # Creates a symbolic link for PXE. This means creating a symlink named # after the node's IP in hexadecimal to a PXE file. +# Returns 1 on succes, 0 otherwise. sub pxelink { - my ($cfg, $cmd) = @_; + my ($cfg, $cmd, $variant) = @_; - my $t = $cfg->getElement (ETH)->getTree; + my $interfaces = $cfg->getElement (INTERFACES)->getTree; my $path; if (!$cmd) { $path = $this_app->option (LOCALBOOT); @@ -397,93 +501,115 @@ sub pxelink $path = $this_app->option (LOCALBOOT); unless ($path =~ m{^([-.\w]+)$}) { $this_app->error ("Unexpected BOOT configuration file"); - return -1; + return 0; } $path = $1; $this_app->debug (5, "Local booting from $path"); } elsif ($cmd eq RESCUE || $cmd eq LIVECD || $cmd eq FIRMWARE) { - $path = link_filepath($cfg, $cmd); - if (! -f $path) { + $path = link_filepath($cfg, $cmd, $variant); + # Testing file existence in unit tests may fail... and file_exists() + # ignores NoAction flag as of 16.12 + if (! CAF::Path->file_exists($path) && ! $CAF::Object::NoAction ) { my $fqdn = get_fqdn($cfg); $this_app->error("Missing $cmd config file for $fqdn: $path"); - return -1; + return 0; } $this_app->debug (5, "Using $cmd from: $path"); } elsif ($cmd eq INSTALL) { - $path = filepath ($cfg); + $path = filepath ($cfg, $variant); $this_app->debug (5, "Installing on $path"); } else { $this_app->debug (5, "Unknown command"); - return -1; + return 0; } # Set the same settings for every network interface that has a # defined IP address. - foreach my $st (values (%$t)) { + foreach my $st (values (%$interfaces)) { next unless $st->{ip}; - my $dir = $this_app->option (NBPDIR); - my $lnname = "$dir/".hexip ($st->{ip}); + my $dir = variant_option('nbpdir_opt', $variant); + my $lnname = "$dir/".hexip_filename ($st->{ip}, $variant); if ($cmd || ! -l $lnname) { if ($CAF::Object::NoAction) { $this_app->info ("Would symlink $path to $lnname"); } else { unlink ($lnname); - # This must be stripped to work with chroot'edg - # environments. + # This must be stripped to work with chroot'ed environments. $path =~ s{$dir/?}{}; symlink ($path, $lnname); } } } - return 0; + + return 1; +} + + +# Wrapper function to call ksuserhooks() from aii-ks module. +# The only role of this function is to ensure that ksuserhooks() +# is always called the same way (in particular for NoAction +# handling). Be sure to use it! +sub exec_userhooks { + my ($cfg, $hook_path) = @_; + + ksuserhooks ($cfg, $hook_path) unless $CAF::Object::NoAction; } + # Prints the status of the node. +# Display information for both PXELINUX and Grub2 variant. + sub Status { my ($self, $cfg) = @_; - my $t = $cfg->getElement (ETH)->getTree; - my $dir = $this_app->option (NBPDIR); - my $fqdn = get_fqdn($cfg); - my $boot = $this_app->option (LOCALBOOT); - my $rescue = link_filepath($cfg, RESCUE); - my $firmware = link_filepath($cfg, FIRMWARE); - my $livecd = link_filepath($cfg, LIVECD); - foreach my $s (values (%$t)) { - next unless $s->{ip}; - my $ln = hexip ($s->{ip}); - my $since = "unknown"; - my $st; - if (-l "$dir/$ln") { - $since = ctime(lstat("$dir/$ln")->ctime()); - my $name = readlink ("$dir/$ln"); - my $name_path = "$dir/$name"; - if (! -e $name_path) { - $st = "broken"; - } elsif ($name =~ m{^(?:.*/)?$fqdn\.cfg$}) { - $st = "install"; - } elsif ($name =~ m{^$boot$}) { - $st = "boot"; - } elsif ($firmware && ($name_path =~ m{$firmware})) { - $st = "firmware"; - } elsif ($livecd && ($name_path =~ m{$livecd})) { - $st = "livecd"; - } elsif ($rescue && ($name_path =~ m{$rescue})) { - $st = "rescue"; + my $interfaces = $cfg->getElement (INTERFACES)->getTree; + + foreach my $variant (PXE_VARIANT_PXELINUX, PXE_VARIANT_GRUB2) { + my $dir = variant_option('nbpdir_opt', $variant); + my $boot = $this_app->option (LOCALBOOT); + my $fqdn = get_fqdn($cfg); + my $rescue = link_filepath($cfg, RESCUE, $variant); + my $firmware = link_filepath($cfg, FIRMWARE, $variant); + my $livecd = link_filepath($cfg, LIVECD, $variant); + foreach my $interface (sort(values(%$interfaces))) { + next unless $interface->{ip}; + my $ln = hexip_filename ($interface->{ip}, $variant); + my $since = "unknown"; + my $st; + if (-l "$dir/$ln") { + $since = ctime(lstat("$dir/$ln")->ctime()); + my $name = readlink ("$dir/$ln"); + my $name_path = "$dir/$name"; + if (! -e $name_path) { + $st = "broken"; + } elsif ($name =~ m{^(?:.*/)?$fqdn\.cfg$}) { + $st = "install"; + } elsif ($name =~ m{^$boot$}) { + $st = "boot"; + } elsif ($firmware && ($name_path =~ m{$firmware})) { + $st = "firmware"; + } elsif ($livecd && ($name_path =~ m{$livecd})) { + $st = "livecd"; + } elsif ($rescue && ($name_path =~ m{$rescue})) { + $st = "rescue"; + } else { + $st = "unknown"; + } } else { - $st = "unknown"; + $st = "undefined"; } - } else { - $st = "undefined"; + $self->info(ref($self), "status for $fqdn: $interface->{ip} $st since: $since (PXE variant=", + variant_attribute('name', $variant), ")"); } - $self->info(ref($self), " status for $fqdn: $s->{ip} $st ", - "since: $since"); } - ksuserhooks ($cfg, STATUS_HOOK_PATH); + + exec_userhooks ($cfg, STATUS_HOOK_PATH); + return 1; } # Removes PXE files and symlinks for the node. To be called by --remove. +# This must be done for PXELINUX and Grub2 variants. sub Unconfigure { my ($self, $cfg) = @_; @@ -493,33 +619,43 @@ sub Unconfigure return 1; } - my $t = $cfg->getElement (ETH)->getTree; - my $path = filepath ($cfg); - my $dir = $this_app->option (NBPDIR); - # Set the same settings for every network interface. - unlink ($path); - unlink ("$dir/" . hexip ($_->{ip})) foreach values (%$t); - ksuserhooks ($cfg, REMOVE_HOOK_PATH); - return 1; + my $interfaces = $cfg->getElement (INTERFACES)->getTree; + + foreach my $variant (PXE_VARIANT_PXELINUX, PXE_VARIANT_GRUB2) { + my $path = filepath ($cfg, $variant); + my $dir = $this_app->option ($VARIANT_PARAMS[$variant]->{nbpdir_opt}); + # Set the same settings for every network interface. + unlink ($path); + unlink ("$dir/" . hexip_filename ($_->{ip}, $variant)) foreach values (%$interfaces); + exec_userhooks ($cfg, REMOVE_HOOK_PATH); + return 1; + } } no strict 'refs'; -foreach my $i (qw(configure boot rescue livecd firmware install)) { - my $name = ucfirst($i); - my $cmd = uc($i); +foreach my $operation (qw(configure boot rescue livecd firmware install)) { + my $name = ucfirst($operation); + my $cmd = uc($operation); *{$name} = sub { my ($self, $cfg) = @_; - pxeprint($cfg) if ($i eq 'configure'); + foreach my $variant (PXE_VARIANT_PXELINUX, PXE_VARIANT_GRUB2) { + if ( variant_enabled($variant) ) { + $self->verbose("Executing action '$operation' for variant ", variant_attribute('name',$variant)); + variant_attribute('format_method', $variant)->($cfg) if ($operation eq 'configure'); - unless (pxelink ($cfg, &$cmd())==0) { - my $fqdn = get_fqdn($cfg); - $self->error ("Failed to change the status of $fqdn to $i"); - return 0; + unless ( pxelink ($cfg, &$cmd(), $variant) ) { + my $fqdn = get_fqdn($cfg); + $self->error ("Failed to change the status of $fqdn to $operation"); + return 0; + } + } else { + $self->debug(1, "Variant ", variant_attribute('name',$variant), "disabled: action '$operation' not executed"); + } } - ksuserhooks ($cfg, HOOK_PATH.$i) unless $CAF::Object::NoAction; + exec_userhooks ($cfg, HOOK_PATH.$operation); return 1; }; }; diff --git a/aii-pxelinux/src/test/perl/pxelinux_hooks.t b/aii-pxelinux/src/test/perl/pxelinux_hooks.t index eb22dab7..600af16c 100644 --- a/aii-pxelinux/src/test/perl/pxelinux_hooks.t +++ b/aii-pxelinux/src/test/perl/pxelinux_hooks.t @@ -17,7 +17,7 @@ BEGIN { } my $mockpxe = Test::MockModule->new('NCM::Component::pxelinux'); -foreach my $mm (qw(pxelink pxeprint unlink get_fqdn filepath link_filepath)) { +foreach my $mm (qw(pxelink write_pxelinux_config write_grub2_config unlink get_fqdn filepath link_filepath)) { $mockpxe->mock($mm, 0); }; diff --git a/aii-pxelinux/src/test/perl/pxelinux_ks_block.t b/aii-pxelinux/src/test/perl/pxelinux_ks_block.t index 664b88be..f99699d5 100644 --- a/aii-pxelinux/src/test/perl/pxelinux_ks_block.t +++ b/aii-pxelinux/src/test/perl/pxelinux_ks_block.t @@ -11,7 +11,7 @@ use Sys::Hostname; =head1 SYNOPSIS -Tests for the C method. +Tests for the C method. =cut @@ -25,13 +25,13 @@ $mockpxe->mock('filepath', $fp); my $ks = NCM::Component::pxelinux->new('pxelinux_ks'); my $cfg = get_config_for_profile('pxelinux_ks_block'); -NCM::Component::pxelinux::pxeprint($cfg); +NCM::Component::pxelinux::write_pxelinux_config($cfg); my $fh = get_file($fp); my $hostname = hostname(); -like($fh, qr{^default\skernel\slabel}m, 'default kernel'); -like($fh, qr{^\s{4}label\skernel\slabel}m, 'label default kernel'); +like($fh, qr{^default\sInstall\sScientific\sLinux\s6x\s\(x86_64\)}m, 'default kernel'); +like($fh, qr{^\s{4}label\sScientific\sLinux\s6x\s\(x86_64\)}m, 'label default kernel'); like($fh, qr{^\s{4}kernel\smykernel}m, 'kernel mykernel'); like($fh, qr{^\s{4}append\sramdisk=32768\sinitrd=path/to/initrd(\s|$)}m, 'append ramdisk and initrd'); like($fh, qr{^\s{4}append.*?\sks=http://server/ks(\s|$)}m, 'append ks url'); diff --git a/aii-pxelinux/src/test/perl/pxelinux_ks_bonding.t b/aii-pxelinux/src/test/perl/pxelinux_ks_bonding.t index 8ffd01ad..4c9acb24 100644 --- a/aii-pxelinux/src/test/perl/pxelinux_ks_bonding.t +++ b/aii-pxelinux/src/test/perl/pxelinux_ks_bonding.t @@ -10,7 +10,7 @@ use CAF::Object; =head1 SYNOPSIS -Tests for the C method. +Tests for the C method. =cut @@ -24,7 +24,7 @@ $mockpxe->mock('filepath', $fp); my $ks = NCM::Component::pxelinux->new('pxelinux_ks'); my $cfg = get_config_for_profile('pxelinux_ks_bonding'); -NCM::Component::pxelinux::pxeprint($cfg); +NCM::Component::pxelinux::write_pxelinux_config($cfg); my $fh = get_file($fp); @@ -32,7 +32,7 @@ my $fh = get_file($fp); like($fh, qr{^\s{4}append\s.*?\sbond=bond0:eth0,eth1:(opt1=val1,opt2=val2|opt2=val2,opt1=val1)(\s|$)}m, 'append bond'); # static ip settings from bond0, also bond0 is bootdev -like($fh, qr{^\s{4}append\s.*?\sip=1.2.3.0::1.2.3.4:255.255.255.0:x.y:bond0:none(\s|$)}m, 'append static ip for bootdev bond0'); +like($fh, qr{^\s{4}append\s.*?\sip=1\.2\.3\.0::133\.2\.85\.1:255\.255\.255\.0:x.y:bond0:none(\s|$)}m, 'append static ip for bootdev bond0'); # kickstart file should be fetched via ksdevice bond0 # this is EL7, the EL6 test should be ksdevice=bond0 diff --git a/aii-pxelinux/src/test/perl/pxelinux_ks_bonding_bridge.t b/aii-pxelinux/src/test/perl/pxelinux_ks_bonding_bridge.t index b0b2bbd1..efc6d262 100644 --- a/aii-pxelinux/src/test/perl/pxelinux_ks_bonding_bridge.t +++ b/aii-pxelinux/src/test/perl/pxelinux_ks_bonding_bridge.t @@ -10,7 +10,7 @@ use CAF::Object; =head1 SYNOPSIS -Tests for the C method. +Tests for the C method. =cut @@ -24,7 +24,7 @@ $mockpxe->mock('filepath', $fp); my $ks = NCM::Component::pxelinux->new('pxelinux_ks'); my $cfg = get_config_for_profile('pxelinux_ks_bonding_bridge'); -NCM::Component::pxelinux::pxeprint($cfg); +NCM::Component::pxelinux::write_pxelinux_config($cfg); my $fh = get_file($fp); @@ -34,7 +34,7 @@ my $fh = get_file($fp); like($fh, qr{^\s{4}append\s.*?\sbond=bond0:eth0,eth1:(opt1=val1,opt2=val2|opt2=val2,opt1=val1)(\s|$)}m, 'append bond'); # static ip settings from bond0, also bond0 is bootdev -like($fh, qr{^\s{4}append\s.*?\sip=1.2.3.0::1.2.3.4:255.255.255.0:x.y:bond0:none(\s|$)}m, 'append static ip for bootdev bond0'); +like($fh, qr{^\s{4}append\s.*?\sip=1\.2\.3\.0::133\.2\.85\.1:255\.255\.255\.0:x.y:bond0:none(\s|$)}m, 'append static ip for bootdev bond0'); # kickstart file should be fetched via ksdevice bond0 # this is EL7, the EL6 test should be ksdevice=bond0 diff --git a/aii-pxelinux/src/test/perl/pxelinux_ks_el7_static_ip.t b/aii-pxelinux/src/test/perl/pxelinux_ks_el7_static_ip.t index 72cde561..7a40d5a2 100644 --- a/aii-pxelinux/src/test/perl/pxelinux_ks_el7_static_ip.t +++ b/aii-pxelinux/src/test/perl/pxelinux_ks_el7_static_ip.t @@ -10,7 +10,7 @@ use CAF::Object; =head1 SYNOPSIS -Tests for the C method. +Tests for the C method. =cut @@ -24,7 +24,7 @@ $mockpxe->mock('filepath', $fp); my $ks = NCM::Component::pxelinux->new('pxelinux_ks'); my $cfg = get_config_for_profile('pxelinux_ks_el7_static_ip'); -NCM::Component::pxelinux::pxeprint($cfg); +NCM::Component::pxelinux::write_pxelinux_config($cfg); my $fh = get_file($fp); @@ -37,7 +37,7 @@ like($fh, qr{^\s{4}append\s.*?\snameserver=nm2(\s|$)}m, 'append nameserver 2'); like($fh, qr{^\s{4}append\s.*?\sifname=eth0:00:11:22:33:44:55(\s|$)}m, 'append ifname for 1st nic'); like($fh, qr{^\s{4}append\s.*?\sifname=eth1:00:11:22:33:44:66(\s|$)}m, 'append ifname for 2nd nic'); # static ip -like($fh, qr{^\s{4}append\s.*?\sip=1.2.3.0::1.2.3.4:255.255.255.0:x.y:eth0:none(\s|$)}m, 'append static ip for bootdev'); +like($fh, qr{^\s{4}append\s.*?\sip=133\.2\.85\.234::133\.2\.85\.1:255\.255\.255\.0:x.y:eth0:none(\s|$)}m, 'append static ip for bootdev'); # enable sshd like($fh, qr{^\s{4}append\s.*?\sinst.sshd(\s|$)}m, 'append enable sshd'); # enable cmdline diff --git a/aii-pxelinux/src/test/perl/pxelinux_ks_logging.t b/aii-pxelinux/src/test/perl/pxelinux_ks_logging.t index e17c4e19..799d75bd 100644 --- a/aii-pxelinux/src/test/perl/pxelinux_ks_logging.t +++ b/aii-pxelinux/src/test/perl/pxelinux_ks_logging.t @@ -10,7 +10,7 @@ use CAF::Object; =head1 SYNOPSIS -Tests for the C method. +Tests for the C method. =cut @@ -24,7 +24,7 @@ $mockpxe->mock('filepath', $fp); my $ks = NCM::Component::pxelinux->new('pxelinux_ks'); my $cfg = get_config_for_profile('pxelinux_ks_logging'); -NCM::Component::pxelinux::pxeprint($cfg); +NCM::Component::pxelinux::write_pxelinux_config($cfg); my $fh = get_file($fp); diff --git a/aii-pxelinux/src/test/perl/pxelinux_ks_nologging_host.t b/aii-pxelinux/src/test/perl/pxelinux_ks_nologging_host.t index 00040311..8a17d517 100644 --- a/aii-pxelinux/src/test/perl/pxelinux_ks_nologging_host.t +++ b/aii-pxelinux/src/test/perl/pxelinux_ks_nologging_host.t @@ -10,7 +10,7 @@ use CAF::Object; =head1 SYNOPSIS -Tests for the C method. +Tests for the C method. =cut @@ -24,7 +24,7 @@ $mockpxe->mock('filepath', $fp); my $ks = NCM::Component::pxelinux->new('pxelinux_ks'); my $cfg = get_config_for_profile('pxelinux_ks_nologging_host'); -NCM::Component::pxelinux::pxeprint($cfg); +NCM::Component::pxelinux::write_pxelinux_config($cfg); my $fh = get_file($fp); diff --git a/aii-pxelinux/src/test/perl/pxelinux_ks_special_ksdevice.t b/aii-pxelinux/src/test/perl/pxelinux_ks_special_ksdevice.t index 3f845f76..aeac765b 100644 --- a/aii-pxelinux/src/test/perl/pxelinux_ks_special_ksdevice.t +++ b/aii-pxelinux/src/test/perl/pxelinux_ks_special_ksdevice.t @@ -10,7 +10,7 @@ use CAF::Object; =head1 SYNOPSIS -Tests for the C method. +Tests for the C method. =cut @@ -33,7 +33,7 @@ foreach my $type (("bootif", "link", "mac")) { $bond = NCM::Component::pxelinux::pxe_network_bonding($cfg, {}, $search); ok(! defined($bond), "Bonding for unsupported device $search returns undef"); - NCM::Component::pxelinux::pxeprint($cfg); + NCM::Component::pxelinux::write_pxelinux_config($cfg); $fh = get_file($fp); diff --git a/aii-pxelinux/src/test/perl/pxelinux_ks_systemd_ksdevice.t b/aii-pxelinux/src/test/perl/pxelinux_ks_systemd_ksdevice.t index 6a2c27c6..954bac8a 100644 --- a/aii-pxelinux/src/test/perl/pxelinux_ks_systemd_ksdevice.t +++ b/aii-pxelinux/src/test/perl/pxelinux_ks_systemd_ksdevice.t @@ -15,7 +15,7 @@ use CAF::Object; =head1 SYNOPSIS -Tests for the C method. +Tests for the C method. =cut @@ -39,7 +39,7 @@ foreach my $scheme (qw(1 2 3 4)) { $bond = NCM::Component::pxelinux::pxe_network_bonding($cfg, {}, $search); ok(! defined($bond), "Bonding for unsupported device $search returns undef"); - NCM::Component::pxelinux::pxeprint($cfg); + NCM::Component::pxelinux::write_pxelinux_config($cfg); $fh = get_file($fp); diff --git a/aii-pxelinux/src/test/perl/pxelinux_no_append_block.t b/aii-pxelinux/src/test/perl/pxelinux_no_append_block.t index feaa8fba..84cc7a5e 100644 --- a/aii-pxelinux/src/test/perl/pxelinux_no_append_block.t +++ b/aii-pxelinux/src/test/perl/pxelinux_no_append_block.t @@ -10,7 +10,7 @@ use CAF::Object; =head1 SYNOPSIS -Tests for the C method. +Tests for the C method. =cut @@ -24,12 +24,12 @@ $mockpxe->mock('filepath', $fp); my $ks = NCM::Component::pxelinux->new('pxelinux_no_append'); my $cfg = get_config_for_profile('pxelinux_no_append_block'); -NCM::Component::pxelinux::pxeprint($cfg); +NCM::Component::pxelinux::write_pxelinux_config($cfg); my $fh = get_file($fp); -like($fh, qr{^default\skernel\slabel}m, 'default kernel'); -like($fh, qr{^\s{4}label\skernel\slabel}m, 'label default kernel'); +like($fh, qr{^default\sInstall\sScientific\sLinux\s6x\s\(x86_64\)}m, 'default kernel'); +like($fh, qr{^\s{4}label\sScientific\sLinux\s6x\s\(x86_64\)}m, 'label default kernel'); like($fh, qr{^\s{4}kernel\smykernel}m, 'kernel mykernel'); unlike($fh, qr{^\s*append}m, 'no append line'); diff --git a/aii-pxelinux/src/test/resources/pxelinux_ks.pan b/aii-pxelinux/src/test/resources/pxelinux_ks.pan index 49fe63b2..ab3a6c2e 100644 --- a/aii-pxelinux/src/test/resources/pxelinux_ks.pan +++ b/aii-pxelinux/src/test/resources/pxelinux_ks.pan @@ -3,7 +3,7 @@ Base pxelinux_ks data @} template pxelinux_ks; -include 'pxelinux_no_append'; +include 'pxelinux_config_common'; # at least 1 ks entry to trigger ks append lines prefix "/system/aii/osinstall/ks"; diff --git a/aii-pxelinux/src/test/resources/pxelinux_no_append.pan b/aii-pxelinux/src/test/resources/pxelinux_no_append.pan deleted file mode 100644 index 89981fd8..00000000 --- a/aii-pxelinux/src/test/resources/pxelinux_no_append.pan +++ /dev/null @@ -1,27 +0,0 @@ -@{ -Base pxelinux without append data -@} -template pxelinux_no_append; - -include 'quattor/aii/pxelinux/schema'; - -bind "/system/aii/nbp/pxelinux" = structure_pxelinux_pxe_info; - -prefix "/system/network"; -"hostname" = 'x'; -"domainname" = 'y'; -"nameserver/0" = 'nm1'; -"nameserver/1" = 'nm2'; -"default_gateway" = "1.2.3.4"; -"interfaces/eth0/ip" = "1.2.3.0"; -"interfaces/eth0/netmask" = "255.255.255.0"; - -prefix "/hardware/cards/nic"; -"eth0/hwaddr" = "00:11:22:33:44:55"; -"eth1/hwaddr" = "00:11:22:33:44:66"; - - -prefix "/system/aii/nbp/pxelinux"; -"initrd" = "path/to/initrd"; -"kernel" = 'mykernel'; -"label" = "kernel label"; diff --git a/aii-pxelinux/src/test/resources/pxelinux_no_append_block.pan b/aii-pxelinux/src/test/resources/pxelinux_no_append_block.pan index 1e86e3e6..47d1fc42 100644 --- a/aii-pxelinux/src/test/resources/pxelinux_no_append_block.pan +++ b/aii-pxelinux/src/test/resources/pxelinux_no_append_block.pan @@ -1,6 +1,6 @@ object template pxelinux_no_append_block; -include 'pxelinux_no_append'; +include 'pxelinux_config_common'; prefix "/system/aii/nbp/pxelinux"; "ksdevice" = "eth0";