pf-tools/pf-tools: 30 new changesets
parmelan-guest at users.alioth.debian.org
parmelan-guest at users.alioth.debian.org
Thu Dec 2 17:47:41 UTC 2010
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/ada57136eed1
changeset: 1083:ada57136eed1
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Thu Nov 25 08:15:32 2010 +0100
description:
Remove spurious whitespace in s{}{} replacement string
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/89b3e60f4950
changeset: 1084:89b3e60f4950
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Thu Nov 25 08:26:54 2010 +0100
description:
Style
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/ffe648379649
changeset: 1085:ffe648379649
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Thu Nov 25 08:27:43 2010 +0100
description:
Drop unused function __get_key_value_from_context_key()
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/5f4c893f7a1e
changeset: 1086:5f4c893f7a1e
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Thu Nov 25 08:34:51 2010 +0100
description:
Style
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/505d01e5d95b
changeset: 1087:505d01e5d95b
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Thu Nov 25 08:38:38 2010 +0100
description:
Style
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/819971d8052e
changeset: 1088:819971d8052e
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Thu Nov 25 08:43:36 2010 +0100
description:
Style
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/aa439d6194db
changeset: 1089:aa439d6194db
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Thu Nov 25 10:25:13 2010 +0100
description:
Style
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/92304c0e5933
changeset: 1090:92304c0e5933
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Thu Nov 25 10:29:12 2010 +0100
description:
Style
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/1afc45fcf886
changeset: 1091:1afc45fcf886
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Thu Nov 25 19:35:11 2010 +0100
description:
Style
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/7d84e1ba22ba
changeset: 1092:7d84e1ba22ba
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Thu Nov 25 19:40:44 2010 +0100
description:
Indent
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/8afd9ea3660e
changeset: 1093:8afd9ea3660e
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Thu Nov 25 19:46:51 2010 +0100
description:
get_suffix_from_ip_type(): use ipv4 as a default
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/64b749384fd1
changeset: 1094:64b749384fd1
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Thu Nov 25 19:53:11 2010 +0100
description:
Style
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/fc5ca5dc047f
changeset: 1095:fc5ca5dc047f
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Thu Nov 25 20:02:12 2010 +0100
description:
Rename t/20.zone.t to t/20.files.t, to better match what it tests
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/f59618e833c8
changeset: 1096:f59618e833c8
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Fri Nov 26 18:12:55 2010 +0100
description:
get_cmdline_from_host_ref(): return an empty string rather than undef for $bond_cmdline
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/59737c58a539
changeset: 1097:59737c58a539
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Sat Nov 27 16:25:34 2010 +0100
description:
Mk_PXE_bootfile() replaced by make_preseed_file(), make_pxe_boot_and_preseed_files(), __build_pxe_boot() and __build_preseed().
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/b646fa23c17b
changeset: 1098:b646fa23c17b
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Sat Nov 27 16:49:10 2010 +0100
description:
Update mk_pxelinuxcfg to use the new functions
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/08d9608bb13d
changeset: 1099:08d9608bb13d
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Mon Nov 29 14:10:21 2010 +0100
description:
Documentation for make_preseed_file()
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/a36675475568
changeset: 1100:a36675475568
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Mon Nov 29 14:40:33 2010 +0100
description:
Use make_path() in __make_file(), add documentation for make_boot_and_preseed_files() and __build_pxe_boot()
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/61fe344e9e64
changeset: 1101:61fe344e9e64
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Mon Nov 29 18:54:04 2010 +0100
description:
New function: __read_and_process_template() + use it in __build_preseed()
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/6bace28fd417
changeset: 1102:6bace28fd417
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Mon Nov 29 19:16:30 2010 +0100
description:
__build_pxe_boot(): move the initrd special handline to the template
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/a36ea10e7b1f
changeset: 1103:a36ea10e7b1f
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Mon Nov 29 19:17:57 2010 +0100
description:
__build_pxe_boot(): use __read_and_process_template()
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/90601f4b51e1
changeset: 1104:90601f4b51e1
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Mon Nov 29 19:19:00 2010 +0100
description:
Style
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/c2c695a1fd0b
changeset: 1105:c2c695a1fd0b
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Mon Nov 29 23:05:12 2010 +0100
description:
__build_sources_list(): use __read_and_process_template()
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/a5efaf148dc2
changeset: 1106:a5efaf148dc2
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Mon Nov 29 23:31:20 2010 +0100
description:
Flush2disk_GLOBAL() -> store_global_config(), Retrieve_GLOBAL() -> retrieve_global_config()
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/974f85fabf93
changeset: 1107:974f85fabf93
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Tue Nov 30 07:54:55 2010 +0100
description:
Also test __build_sources_list() with backports = 1
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/b356965676de
changeset: 1108:b356965676de
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Tue Nov 30 08:24:55 2010 +0100
description:
mk_pxelinuxcfg: specify what we want to import from PFTools::Utils
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/3aa93028f1b3
changeset: 1109:3aa93028f1b3
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Tue Nov 30 08:45:48 2010 +0100
description:
Fix_hosts() -> fix_etc_hosts() + first tests
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/f52f6b324182
changeset: 1110:f52f6b324182
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Wed Dec 01 08:10:54 2010 +0100
description:
New check_args(), check_args_type() and check_true_args() functions
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/8f81e261c500
changeset: 1111:8f81e261c500
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Wed Dec 01 08:12:29 2010 +0100
description:
Args tests in get_site_list_from_hostname()
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/de2d381543f5
changeset: 1112:de2d381543f5
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Wed Dec 01 08:25:18 2010 +0100
description:
fix_etc_hosts() / __fix_etc_hosts() separation, improvements and tests
diffstat:
14 files changed, 650 insertions(+), 423 deletions(-)
lib/PFTools.pm | 43 ++
lib/PFTools/Conf.pm | 1
lib/PFTools/Conf/Host.pm | 2
lib/PFTools/Conf/Network.pm | 2
lib/PFTools/Conf/Syntax.pm | 3
lib/PFTools/Structqueries.pm | 2
lib/PFTools/Utils.pm | 2
sbin/mk_pxelinuxcfg | 2
t/12.storable.t | 6
t/20.files.t | 599 +++++++++++++++++++++++++++++++++++++++++
t/20.zone.t | 407 ---------------------------
templates/standard-installer | 1
templates/ubuntu-installer | 1
templates/ubuntu-sources.list | 2
diffs (4233 lines):
diff -r 9e79004112bc -r de2d381543f5 lib/PFTools.pm
--- a/lib/PFTools.pm Wed Nov 24 19:39:32 2010 +0100
+++ b/lib/PFTools.pm Wed Dec 01 08:25:18 2010 +0100
@@ -22,12 +22,104 @@
use warnings;
use base qw( Exporter);
+use Carp;
use English qw( -no_match_vars ); # Avoids regex performance penalty
-#our @EXPORT = qw();
+our @EXPORT = qw(
+ check_args_type
+ check_args
+ check_true_args
+);
+
#our @EXPORT_OK = qw();
our $VERSION = '1.0.1-WIP';
+
+my %type_string = (
+ q{} => 'scalar',
+ 'ARRAY' => 'arrayref',
+ 'HASH' => 'hashref',
+);
+
+=head2 FIXME
+=head2 check_hashref_args( $args_ref, $names_ref )
+
+Checks that the %{$args_ref} keys listed in @{$names_ref} all have a hashref
+value.
+
+=cut
+
+sub check_args_type {
+ my ($args_ref, $type, @keys) = @_;
+
+ if ( ref $args_ref ne 'HASH' or ref $type or not @keys ) {
+ confess q{ERROR: BUG: invalid args};
+ }
+
+ if ( $type eq 'SCALAR' ) {
+ $type = q{};
+ }
+
+ if ( not $type_string{$type} ) {
+ confess qq{ERROR: Unknown argument type '$type'};
+ }
+
+ foreach my $key (@keys) {
+ if ( not exists $args_ref->{$key} ) {
+ croak qq{ERROR: Mandatory argument $key not found};
+ }
+ if ( ref $args_ref->{$key} ne $type ) {
+ croak qq{ERROR: Invalid non-$type_string{$type} $key};
+ }
+ }
+
+ return 1;
+
+}
+
+=head2 check_args( $function_ref, $args_ref, @keys)
+
+Runs $function_ref->($args_ref, $key) for each key listed in @keys.
+
+This function is prototyped to allow a nice block syntax just as map, grep,
+and others:
+
+ check_args { some_code_here() } $args_ref, @keys;
+
+=cut
+
+sub check_args (&@$@) {
+ my ($function_ref, $args_ref, @keys) = @_;
+
+ foreach my $key (@keys) {
+ $function_ref->($args_ref, $key);
+ }
+
+ return 1;
+}
+
+=head2 check_true_args( $args_ref, $names_ref )
+
+Checks that all the %{$args_ref} keys listed in @{$names_ref} all have a true
+value. NOTE: this is therefor NOT suitable for 0, q{0}, etc.
+
+=cut
+
+sub check_true_args {
+ my ($args_ref, @keys) = @_;
+
+ check_args {
+ my ($args_ref, $key) = @_;
+
+ if ( not $args_ref->{$key} ) {
+ croak qq{ERROR: Invalid empty $key};
+ }
+ }
+ $args_ref, @keys;
+
+ return 1;
+}
+
1; # Magic true value required at end of module
diff -r 9e79004112bc -r de2d381543f5 lib/PFTools/Conf.pm
--- a/lib/PFTools/Conf.pm Wed Nov 24 19:39:32 2010 +0100
+++ b/lib/PFTools/Conf.pm Wed Dec 01 08:25:18 2010 +0100
@@ -48,8 +48,8 @@
Init_PF_CONFIG
Init_GLOBAL_NETCONFIG
Load_conf
- Flush2disk_GLOBAL
- Retrieve_GLOBAL
+ store_global_config
+ retrieve_global_config
Get_source
Get_config_for_hostname_on_site
get_default_pf_config
@@ -538,7 +538,7 @@
return $GLOBAL;
}
-=head2 Flush2disk_GLOBAL( $global_config, $pf_config, $flush_file )
+=head2 store_global_config( $global_config, $pf_config, $flush_file )
Stores $global_config on disk in $flush_file (defaults to
$pf_config->{'path'}->{'global_struct'}).
@@ -547,7 +547,7 @@
=cut
-sub Flush2disk_GLOBAL {
+sub store_global_config {
my ( $global_config, $pf_config, $flush_file ) = @_;
if ( ref $global_config ne 'HASH' ) {
@@ -574,13 +574,13 @@
return 1;
}
-=head2 Retrieve_GLOBAL($path_global_file)
+=head2 retrieve_global_config( $path_global_file )
Retrieves from $path_global_file and returns the stored $global_config.
=cut
-sub Retrieve_GLOBAL {
+sub retrieve_global_config {
my ($path_global_file) = @_;
if ( ref $path_global_file ) {
diff -r 9e79004112bc -r de2d381543f5 lib/PFTools/Conf/Host.pm
--- a/lib/PFTools/Conf/Host.pm Wed Nov 24 19:39:32 2010 +0100
+++ b/lib/PFTools/Conf/Host.pm Wed Dec 01 08:25:18 2010 +0100
@@ -1130,12 +1130,11 @@
( is_private_vlan ($vlan, $global_config, $site) )
? $zone_part_ref->{'BY_SITE'}->{$site}
: $zone_part_ref->{'ALL_SITES'};
- my $added_hostclass = grep { m{ \A $hostclass \z }xms }
- @{ $zone_entry->{'__hostclass_order'} };
- if ( not defined $zone_entry->{$hostclass} and
- not $added_hostclass
- ) {
+ my $hostclass_already_added
+ = any { $_ eq $hostclass } @{ $zone_entry->{'__hostclass_order'} };
+
+ if ( not $zone_entry->{$hostclass} and not $hostclass_already_added ) {
push @{ $zone_entry->{'__hostclass_order'} },
$hostclass;
}
diff -r 9e79004112bc -r de2d381543f5 lib/PFTools/Conf/Network.pm
--- a/lib/PFTools/Conf/Network.pm Wed Nov 24 19:39:32 2010 +0100
+++ b/lib/PFTools/Conf/Network.pm Wed Dec 01 08:25:18 2010 +0100
@@ -98,9 +98,9 @@
}
$zone_part->{$section_name} = {
- 'SOA' => $section_ref,
- 'BY_SITE' => {},
- 'ALL_SITES' => {},
+ 'SOA' => $section_ref,
+ 'BY_SITE' => {},
+ 'ALL_SITES' => {},
};
}
@@ -188,7 +188,7 @@
foreach my $ip_type (qw( ipv4 ipv6 )) {
next if not $pf_config->{'features'}->{$ip_type};
- my $suffix = get_suffix_from_ip_type( $ip_type );
+ my $suffix = get_suffix_from_ip_type($ip_type);
my $zone_part = $global_config->{"ZONE$suffix"};
my $dhcp_part = $global_config->{"DHCP$suffix"};
my $addr_key = "BY_ADDR$suffix";
@@ -258,8 +258,9 @@
my $net2add = {
scope => $section_ref->{'scope'},
};
- if ( $section_ref->{'comment'} )
- { $net2add->{'comment'} = $section_ref->{'comment'}; }
+ if ( $section_ref->{'comment'} ) {
+ $net2add->{'comment'} = $section_ref->{'comment'};
+ }
# Check TAG
my $tag = $section_ref->{'tag'};
@@ -272,7 +273,7 @@
foreach my $ip_type (qw( ipv4 ipv6 )) {
next if not $pf_config->{'features'}->{$ip_type};
- my $suffix = get_suffix_from_ip_type( $ip_type );
+ my $suffix = get_suffix_from_ip_type($ip_type);
my $subnet_ref = get_subnet_from_vlan( $ip_type, $section_ref );
my $zone_key = qq{ZONE$suffix};
my $dhcp_key = qq{DHCP$suffix};
@@ -332,14 +333,14 @@
# Adding entries for network, netmask, broadcast etc. into the
# DNS zone
my $add_args = {
- 'ref_net' => $net2add,
+ 'net_name' => $section_name,
+ 'net_ref' => $net2add,
'subnet_ref' => $subnet_ref,
- 'site' => $site,
+ 'site_name' => $site,
'ip_type' => $ip_type,
- 'net_name' => $section_name,
'global_config' => $global_config,
};
- __add_network_in_zone_part( $add_args );
+ __add_network_in_zone_part($add_args);
my $dhcp_part = $global_config->{$dhcp_key}->{'BY_SITE'}->{$site}
->{$section_name};
@@ -363,7 +364,7 @@
=over
-=item I<ref_net>
+=item I<net_ref>
Reference to a hash containing the network to add
@@ -371,7 +372,7 @@
NetAddr::IP object for the specified network
-=item I<site>
+=item I<site_name>
String containing the site name of the specified network
@@ -390,34 +391,33 @@
sub __add_network_in_zone_part {
my ($args) = @_;
- my ($ref_net, $subnet_ref, $site, $ip_type, $net_name, $global_config)
+ my ( $net_ref, $subnet_ref, $site_name, $ip_type, $net_name, $global_config )
= @{$args}{
- qw( ref_net subnet_ref site ip_type net_name global_config )
+ qw( net_ref subnet_ref site_name ip_type net_name global_config )
};
# Adding entries for network, netmask, broadcast etc. into the DNS zone
- my $zone = $global_config->{'SITE'}->{'BY_NAME'}->{$site}->{'zone'};
- my $suffix = get_suffix_from_ip_type( $ip_type );
+ my $zone = $global_config->{'SITE'}->{'BY_NAME'}->{$site_name}->{'zone'};
+ my $suffix = get_suffix_from_ip_type($ip_type);
my $zone_key = qq{ZONE$suffix};
my $zone_part = $global_config->{$zone_key}->{'BY_NAME'}->{$zone};
my $zone_ref = {};
- $zone_ref->{'network'} = qq{A\t} . $ref_net->{"network$suffix"};
- $zone_ref->{'netmask'} = qq{A\t} . $ref_net->{"netmask$suffix"};
+ $zone_ref->{'network'} = qq{A\t} . $net_ref->{"network$suffix"};
+ $zone_ref->{'netmask'} = qq{A\t} . $net_ref->{"netmask$suffix"};
- my $broadcast = $subnet_ref->broadcast();
- $broadcast =~ s{ [/].* \z }{}xms; # remove /prefix
+ my $broadcast = $subnet_ref->broadcast()->addr();
$zone_ref->{'broadcast'} = qq{A\t} . $broadcast;
- if ( $ref_net->{"gateway$suffix"} ) {
- $zone_ref->{'gateway'} = qq{A\t} . $ref_net->{"gateway$suffix"};
+ if ( $net_ref->{"gateway$suffix"} ) {
+ $zone_ref->{'gateway'} = qq{A\t} . $net_ref->{"gateway$suffix"};
}
- if ( is_private_vlan ($net_name, $global_config, $site) ) {
+ if ( is_private_vlan( $net_name, $global_config, $site_name ) ) {
push
- @{ $zone_part->{'BY_SITE'}->{$site}->{'__network_order'} },
+ @{ $zone_part->{'BY_SITE'}->{$site_name}->{'__network_order'} },
$net_name;
- $zone_part->{'BY_SITE'}->{$site}->{$net_name} = $zone_ref;
+ $zone_part->{'BY_SITE'}->{$site_name}->{$net_name} = $zone_ref;
}
else {
$zone_part->{'ALL_SITES'}->{$net_name} = $zone_ref;
@@ -427,5 +427,6 @@
return 1;
}
+
1; # Magic true value required at end of module
diff -r 9e79004112bc -r de2d381543f5 lib/PFTools/Conf/Syntax.pm
--- a/lib/PFTools/Conf/Syntax.pm Wed Nov 24 19:39:32 2010 +0100
+++ b/lib/PFTools/Conf/Syntax.pm Wed Dec 01 08:25:18 2010 +0100
@@ -227,10 +227,10 @@
'site' => '(ALL|[\w\-]+(\s*,\s*[\w\-]+)*)',
'number' => '\d+',
'order' => '\d+',
- 'ipv4' => '(\d{1,3})((\.\d{1,3}){1,3})?',
- 'ipv6' => 'undefined',
- 'alias' => '[a-z][a-z0-9\-]+[a-z0-9]',
- 'shortname' => '[a-z][a-z0-9\-]+[a-z0-9]',
+ 'ipv4' => '(\d{1,3})((\.\d{1,3}){1,3})?',
+ 'ipv6' => 'undefined',
+ 'alias' => '[a-z][a-z0-9\-]+[a-z0-9]',
+ 'shortname' => '[a-z][a-z0-9\-]+[a-z0-9]',
},
'service' => {
'MANDATORY_KEYS' => [ 'site', '@host' ],
@@ -289,9 +289,9 @@
'MANDATORY_KEYS' => [ 'source', 'fstype', 'options' ],
'depends' => 'undefined',
'source' => 'undefined',
- 'fstype' => '(nfs|ext[2-4]|btrfs|cifs)',
- 'options' => 'undefined',
- 'mode' => '[0-7]?[0-7]{3}',
+ 'fstype' => '(nfs|ext[2-4]|btrfs|cifs)',
+ 'options' => 'undefined',
+ 'mode' => '[0-7]?[0-7]{3}',
},
'installpkg' => {
'depends' => 'undefined',
@@ -344,13 +344,12 @@
croak qq{ERROR: Invalid section type $section_type};
}
- my $definition = $DEF_SECTIONS->{$int_context}->{$section_type};
- my $parsed_keys_list = {};
- my $check_mandatory = 1;
+ my $definition = $DEF_SECTIONS->{$int_context}->{$section_type};
+ my $parsed_keys_list = {};
+ my $check_mandatory_keys = 1;
- my $iface_type;
if ( $section_type eq 'interface' ) {
- ( $iface_type = $section_name )
+ ( my $iface_type = $section_name )
=~ s{
\A
\Q$section_type\E
@@ -366,21 +365,23 @@
)?
\z
}
- {
- $LAST_PAREN_MATCH{'iftype'}
- }xms;
- # FIXME : arbitrary set $parsed_keys_list->{'slaves'} to 1
- # due to 'slaves' is a mandatory key on interface sections
- if ( $iface_type eq 'eth' ) { $parsed_keys_list->{'slaves'} = 1 };
+ {$LAST_PAREN_MATCH{'iftype'}}xms;
+
+ # FIXME arbitrary set $parsed_keys_list->{'slaves'} to 1
+ # due to 'slaves' is a mandatory key on interface sections
+ if ( $iface_type eq 'eth' ) {
+ $parsed_keys_list->{'slaves'} = 1
+ }
}
if ( $context eq 'model' ) {
if ( $section_type eq 'hostgroup' ) {
- $check_mandatory = 0;
+ $check_mandatory_keys = 0;
}
+
+ # FIXME arbitrary set ipv4 and ipv6 to 1 when context is model
+ # due to ipv4 is mandatory in interface sections
if ( $section_type eq 'interface' ) {
- # FIXME : arbitrary set ipv4 and ipv6 to 1 when context is model
- # due to ipv4 is mandatory in interface sections
$parsed_keys_list->{'ipv4'} = 1;
}
}
@@ -388,35 +389,36 @@
my $master_key = ( $context eq 'config' ) ? 'action' : 'type';
foreach my $key ( keys %{$section_hash} ) {
( my $new = $key ) =~ s{ \A ([^.]+) (?: [.] .*)? \z }{$1}xmso;
- my $def_key =
- ( $int_context eq 'host'
+ my $def_key = (
+ $int_context eq 'host'
or $context eq 'network' and $section_type eq 'server'
)
? $new
: $key;
$parsed_keys_list->{$def_key} = 1;
-
+
# Next if useless checks
next
if $key eq $master_key
or $definition->{$def_key} eq 'undefined';
- # Checking if key exits
+ # Check if key exists
if ( not defined $definition->{$def_key} ) {
- croak qq{ERROR: file $file, section $section_name: unknown key $key}
+ croak
+ qq{ERROR: file $file, section $section_name: unknown key $key}
}
my $value = ( ref $section_hash->{$key} eq 'ARRAY' )
? $section_hash->{$key}
: [ $section_hash->{$key} ];
- __check_key_value_from_definition (
+ __check_key_value_from_definition(
$key, $value, $definition->{$def_key}, $section_name, $file
);
}
- if ( $check_mandatory ) {
+ if ($check_mandatory_keys) {
foreach my $key ( @{ $definition->{'MANDATORY_KEYS'} } ) {
if ( not defined $parsed_keys_list ) {
croak
@@ -428,53 +430,38 @@
return 1;
}
-=head2 __get_key_value_from_context_key( $section, $context, $parsed_pkey )
+=head2 __check_key_value_from_definition( $key_name, $values_ref, $regexp, $section_name, $file_name )
-Retrieve key_name and values for checking on hash defintion structure.
-Returns a pair with key_name and tab_values
+Checks values for a specified key. Returns true value on success or croaks
+on errors. The parameters are:
-=cut
+=over
-sub __get_key_value_from_context_key {
- my ( $section, $context, $parsed_key ) = @_;
+=item I<key_name> the key name
- my ( $tab_values, $key_name );
- if ( $context eq 'host' ) {
- $tab_values
- = ( $parsed_key !~ m{ \A [@] }xms )
- ? [ $section->{$parsed_key}->{'VALUE'} ]
- : $section->{$parsed_key}->{'VALUE'};
- $key_name = $section->{$parsed_key}->{'ORIG_NAME'};
- }
- else {
- $tab_values
- = ( $parsed_key !~ m{ \A [@] }xms )
- ? [ $section->{$parsed_key} ]
- : $section->{$parsed_key};
- $key_name = $parsed_key;
- }
+=item I<values_ref> a reference to the values list
- return ( $key_name, $tab_values );
-}
-
-=head2 __check_key_value_from_definition( $key_name, $tab_values, $regexp, $sect_name, $file )
+=item I<regexp> the regexp agains which each value will be checked
-Check values for a specified key_name. Returns true value on success or croaks
-on errors
+=item I<section_name> the section name (for error messages)
+
+=item I<file_name> the file name (for error messages)
+
+=back
=cut
sub __check_key_value_from_definition {
- my ( $key_name, $tab_values, $regexp, $sect_name, $file ) = @_;
+ my ( $key_name, $values_ref, $regexp, $section_name, $file_name ) = @_;
- foreach my $value ( @{$tab_values} ) {
+ foreach my $value ( @{$values_ref} ) {
# Remove surrounding whitespace
$value =~ s{ \A \s* (\S*) \s* \z }{$1}xms;
if ( $value !~ m{ \A $regexp \z }xms ) {
croak
- qq{Value '$value' for key $key_name in section $sect_name file $file doesn't match $regexp};
+ qq{ERROR: file $file_name, section $section_name, key $key_name: value '$value' doesn't match $regexp};
}
}
diff -r 9e79004112bc -r de2d381543f5 lib/PFTools/Structqueries.pm
--- a/lib/PFTools/Structqueries.pm Wed Nov 24 19:39:32 2010 +0100
+++ b/lib/PFTools/Structqueries.pm Wed Dec 01 08:25:18 2010 +0100
@@ -55,12 +55,14 @@
=head2 get_suffix_from_ip_type ( $ip_type )
This function returns the suffix according to an IP type on the global
-structure.
+structure. If not specified, I<$ip_type> defaults to 'ipv4'.
=cut
sub get_suffix_from_ip_type {
- my ( $ip_type ) = @_;
+ my ($ip_type) = @_;
+
+ $ip_type ||= q{ipv4}; # default value
my $suffix
= $ip_type eq 'ipv6'
@@ -80,10 +82,10 @@
my ( $hostname, $global_config ) = @_;
my $list_ref = get_site_list_from_hostname( $hostname, $global_config );
- unless ($list_ref) {
+ if ( not $list_ref) {
croak qq{ERROR: Uknown host $hostname};
}
- if ( scalar @{$list_ref} > 1 ) {
+ if ( @{$list_ref} > 1 ) {
croak qq{ERROR: Multiple sites for hostname $hostname};
}
@@ -151,7 +153,8 @@
}
}
- croak qq{ERROR: Unknown hostname $hostname} . ( $site ? qq{ on site $site} : q{} );
+ croak qq{ERROR: Unknown hostname $hostname}
+ . ( $site ? qq{ on site $site} : q{} );
}
=head2 get_iface_vlan_from_hostname( $vlan, $host_ref )
@@ -180,6 +183,17 @@
sub get_site_list_from_hostname {
my ( $hostname, $global_config ) = @_;
+
+ if ( not $hostname ) {
+ croak q{ERROR: Invalid empty hostname};
+ }
+ if ( ref $hostname ) {
+ croak q{ERROR: Invalid non-scalar hostname};
+ }
+
+ if ( ref $global_config ne 'HASH' ) {
+ croak q{ERROR: Invalid non-hashref global_config};
+ }
my @site_list = ();
foreach my $site ( @{ $global_config->{'SITE'}->{'__site_list'} } ) {
@@ -242,7 +256,7 @@
=head2 get_host_config( $hostname, $global_config, $site_name )
-This function returns a reference to the host config hash for I<$hostname.
+This function returns a reference to the host config hash for I<$hostname>.
I<$site_name> is optional.
=cut
@@ -257,7 +271,7 @@
my $site_part = $global_config->{'SITE'}->{'BY_NAME'}->{$site_name};
my $zone = $site_part->{'zone'};
- my ( $hostshort )
+ my ($hostshort)
= $hostname =~ m{
\A
( # -> $hostshort
@@ -351,7 +365,7 @@
sub get_pkgtype_from_hostname {
my ( $hostname, $global_config, $site_name ) = @_;
- my $host_props = get_host_config( $hostname, $global_config, $site_name);
+ my $host_props = get_host_config( $hostname, $global_config, $site_name );
my %pkgtype_for = (
debian => q{deb},
@@ -359,7 +373,7 @@
);
my $mode = $host_props->{'deployment'}->{'mode'};
- if (not exists $pkgtype_for{$mode}) {
+ if ( not exists $pkgtype_for{$mode} ) {
croak qq{ERROR: Unknown/not implemented deployment mode $mode};
}
@@ -377,14 +391,16 @@
my ($host_ref) = @_;
my $cmdline = $host_ref->{'boot'}->{'cmdline'} || q{};
- my $bond_cmdline;
+ my $bond_cmdline = q{};
foreach my $iface ( sort keys %{ $host_ref->{'interfaces'} } ) {
next if $iface !~ m{\A bond }xms;
$bond_cmdline
= qq/bonding.mode=$host_ref->{'interfaces'}->{$iface}->{'mode'}/;
- foreach my $opt ( split qr{ \s* [,] \s* }xms,
- $host_ref->{'interfaces'}->{$iface}->{'options'} )
+ foreach my $opt (
+ split qr{ \s* [,] \s* }xms,
+ $host_ref->{'interfaces'}->{$iface}->{'options'}
+ )
{
$bond_cmdline .= qq{ bonding.$opt};
}
@@ -480,13 +496,13 @@
my $zone_key = $ip_type eq 'ipv6' ? 'ZONE6' : 'ZONE';
my $zone_ref = $global_config->{$zone_key}->{'BY_NAME'}->{$zone_name};
my $zone_search;
- if ( $hostvlan ) {
+ if ($hostvlan) {
my $zone_part =
- ( is_private_vlan ($hostvlan, $global_config, $site_name) )
+ ( is_private_vlan( $hostvlan, $global_config, $site_name ) )
? $zone_ref->{'BY_SITE'}->{$site_name}
: $zone_ref->{'ALL_SITES'};
return if ( not defined $zone_part->{$hostvlan} );
- $zone_search = [ $zone_part ];
+ $zone_search = [$zone_part];
}
else {
$zone_search = [
@@ -495,7 +511,7 @@
}
my @fields;
- foreach my $zone_part ( @{ $zone_search } ) {
+ foreach my $zone_part ( @{$zone_search} ) {
if ( $hostname =~ m{\A (network|netmask|broadcast|gateway) }xms ) {
if ( $hostvlan and not $zone_part->{$hostvlan} ) {
return;
diff -r 9e79004112bc -r de2d381543f5 lib/PFTools/Utils.pm
--- a/lib/PFTools/Utils.pm Wed Nov 24 19:39:32 2010 +0100
+++ b/lib/PFTools/Utils.pm Wed Dec 01 08:25:18 2010 +0100
@@ -27,13 +27,18 @@
use Carp;
use Digest::MD5;
use English qw( -no_match_vars ); # Avoids regex performance penalty
+use File::Basename;
use File::Compare;
use File::Copy;
+use File::Path qw( make_path );
use File::Temp;
use Hash::Merge::Simple qw( merge );
use IO::File;
+use List::MoreUtils qw( uniq );
+use NetAddr::IP;
use Template::Tiny;
+use PFTools;
use PFTools::Conf;
use PFTools::Logger;
use PFTools::Net;
@@ -41,20 +46,23 @@
use PFTools::Update;
use PFTools::VCS;
+our @CARP_NOT = qw( PFTools );
+
our @EXPORT = qw(
Init_TOOLS
Do_update_from_GLOBAL
- Fix_hosts
Mk_dhcp
- Mk_PXE_bootfile
Change_kopt_for_hostname
Search_and_replace
);
our @EXPORT_OK = qw(
+ fix_etc_hosts
make_interfaces_file
+ make_preseed_file
+ make_pxe_boot_and_preseed_files
make_resolv_conf_file
make_sources_list_file
make_zone_file
@@ -68,7 +76,7 @@
my ( $hostname, $pf_config_file, $global_store_file, $reload ) = @_;
my $default_pf_config_file = q{/etc/pf-tools.conf};
- if (not $pf_config_file and -e $default_pf_config_file) {
+ if ( not $pf_config_file and -e $default_pf_config_file ) {
$pf_config_file = $default_pf_config_file;
}
@@ -90,91 +98,178 @@
}
my $source
- = Get_source( "COMMON:/$pf_config->{'path'}->{'start_file'}",
- $hostname, {}, $pf_config );
+ = Get_source(
+ "COMMON:/$pf_config->{'path'}->{'start_file'}",
+ $hostname, {}, $pf_config
+ );
$global_struct = Init_GLOBAL_NETCONFIG( $source, {}, $pf_config );
- Flush2disk_GLOBAL( $global_struct, $pf_config );
+ store_global_config( $global_struct, $pf_config );
}
else {
- $global_struct = Retrieve_GLOBAL($global_store_file);
+ $global_struct = retrieve_global_config( $global_store_file );
}
return ( $pf_config, $global_struct );
}
-# FIXME convert to __make_file()
-# builds both the preseed and PXE files
-sub Mk_PXE_bootfile {
- my ( $hostname, $host_ref, $pxe_template_filename, $preseed_template,
- $default_preseed, $pf_script, $pf_config )
- = @_;
+=head2 make_preseed_file($arguments_ref)
- my $iface = get_iface_vlan_from_hostname(
- $host_ref->{'deployment'}->{'dhcpvlan'}, $host_ref );
- my $mac = $host_ref->{'interfaces'}->{$iface}->{'mac'};
- ( my $pxe_boot_file = $mac ) =~ s{ [:] }{-}xmsg;
+Creates a preseed file for a given host. The preseed file is named
+"preseed_I<hostname>" and lies in the I<preseed_dir> directory as specified in
+the pf-tools configuration. This function returns the name (basename, not the
+complete path) of the written preseed file. It takes the following named
+arguments in %{$arguments_ref}:
- my $pxe_template_content = __read_file_in_scalar($pxe_template_filename);
+=over
- my $preseed_filename = __build_preseed_file(
+=item I<hostname> the hostname
+
+=item I<site_name> the site name
+
+=item I<global_config> a reference to the global configuration hash
+
+=item I<pf_config> a reference to the pf-tools configuration hash
+
+=item I<host_ref> a reference to the host configuration hash (optional:
+get_host_config() will be used if it is not specified)
+
+=item I<template_filename> the name of the preseed template file (optional,
+the default is computed from the host deployment mode and the pf-tools
+configuration)
+
+=back
+
+=cut
+
+sub make_preseed_file {
+ my ($arguments_ref) = @_;
+
+ if ( ref $arguments_ref ne 'HASH' ) {
+ croak q{ERROR: Invalid $arguments_ref};
+ }
+
+ my ($hostname, $site_name, $global_config,
+ $pf_config, $template_filename, $host_ref
+ )
+ = @{$arguments_ref}{
+ qw( hostname site_name global_config
+ pf_config template_filename host_ref )
+ };
+
+ $template_filename ||= $arguments_ref->{'preseed_template_filename'};
+
+ if ( not $hostname ) {
+ croak q{ERROR: Invalid empty $hostname};
+ }
+ if ( ref $hostname ) {
+ croak q{ERROR: Invalid non-scalar $hostname};
+ }
+
+ if ( ref $pf_config ne 'HASH' ) {
+ croak q{ERROR: Invalid non-hashref $pf_config};
+ }
+ if ( not $pf_config->{'path'}->{'preseed_dir'} ) {
+ croak q{ERROR: Invalid hashref $pf_config: no ->path->preseed_dir};
+ }
+
+ $host_ref ||= get_host_config( $hostname, $global_config, $site_name );
+
+ my $mode = $host_ref->{'deployment'}->{'mode'};
+ my $templates_dirname = $pf_config->{'path'}->{'templates_dir'};
+
+ $template_filename ||= join q{/}, $templates_dirname,
+ (
+ $host_ref->{'deployment'}->{'preseed'} || $pf_config->{$mode}->{'preseed'}
+ );
+
+ my $basename = qq{preseed_$hostname};
+ my $filename = join q{/}, $pf_config->{'path'}->{'preseed_dir'},
+ $basename;
+
+ __make_file(
{
- hostname => $hostname,
- host_ref => $host_ref,
- preseed_template => $preseed_template,
- default_preseed => $default_preseed, # FIXME unused
- pf_script => $pf_script,
- pf_config => $pf_config,
+ %{$arguments_ref},
+ file_type => q{preseed},
+ filename => $filename,
+ template_filename => $template_filename,
+ host_ref => $host_ref,
}
);
- my $preseed_md5 = __get_md5sum_for_preseedfile( $preseed_filename, $pf_config );
+ return $basename;
+}
- my $cmdline = join q{ }, get_cmdline_from_host_ref($host_ref);
- $cmdline =~ s{ \A \s* }{}xms; # Remove leading white space
+=head2 make_boot_and_preseed_files($arguments_ref)
- my $pxe_subst = {
- 'iface' => $iface,
- 'mode' => $host_ref->{'deployment'}->{'mode'} . '-installer',
- 'arch' => $host_ref->{'deployment'}->{'arch'},
- 'distrib' => $host_ref->{'deployment'}->{'distrib'},
- 'serial_speed' => '115200',
- 'preseed_url' => $preseed_filename,
- 'preseed_md5' => $preseed_md5,
- 'console' => $host_ref->{'boot'}->{'console'},
- 'install_cmdline' => $host_ref->{'boot'}->{'cmdline'},
- 'cmdline' => $cmdline,
- 'kernel' => $host_ref->{'boot'}->{'kernel'}
- };
+Creates a preseed file and a pxe boot file for a given host. The preseed
+file's name and MD5 hash are needed for the PXE boot file. The preseed file is
+created by calling make_preseed_file(), so its mandatory arguments are needed
+here too.
- if ( $host_ref->{'boot'}->{'initrd'} ) {
- $pxe_subst->{'initrd'} = $host_ref->{'boot'}->{'initrd'};
- }
- else {
- $pxe_template_content =~ s{
- initrd=
- (
- (
- [^/]+
- [/]
- )+
- )?
- \[% \s* initrd \s* %\]
- }{}xmsg;
+make_boot_and_preseed_files() returns a true value on success. It takes the
+following named arguments in %{$arguments_ref}:
+
+=over
+
+=item I<hostname> the hostname
+
+=item I<site_name> the site name
+
+=item I<global_config> a reference to the global configuration hash
+
+=item I<pf_config> a reference to the pf-tools configuration hash
+
+=item I<preseed_template_filename> the name of the preseed template file
+(optional, the default is computed from the host deployment mode and the
+pf-tools configuration)
+
+=item I<pxe_template_filename> the name of the pxe template file (optional,
+the default is computed from the host deployment mode and the pf-tools
+configuration)
+
+=back
+
+=cut
+
+sub make_pxe_boot_and_preseed_files {
+ my ($arguments_ref) = @_;
+
+ if ( ref $arguments_ref ne 'HASH' ) {
+ croak q{ERROR: Invalid $arguments_ref};
}
- my $tpl = Template::Tiny->new( TRIM => 1 );
- my $pxe_content = q{};
- $tpl->process( \$pxe_template_content, $pxe_subst, \$pxe_content );
+ my ( $hostname, $site_name, $global_config, $pf_config )
+ = @{$arguments_ref}{qw( hostname site_name global_config pf_config)};
- my $tmp_fh = File::Temp->new( unlink => 0 );
- my $tmp_fn = $tmp_fh->filename();
- __write_scalar_to_filehandle($tmp_fh, $tmp_fn, $pxe_content);
+ $site_name ||= get_uniq_site_from_hostname( $hostname, $global_config, $pf_config );
- my $dst = join q{/}, $pf_config->{'path'}->{'pxefiles_dir'}, $pxe_boot_file;
- __move_if_different( $tmp_fn, $dst );
+ my $host_ref = get_host_config( $hostname, $global_config, $site_name );
- return $pxe_boot_file;
+ my $preseed_filename = make_preseed_file(
+ {
+ %{$arguments_ref},
+ host_ref => $host_ref,
+ }
+ );
+
+ my $iface = get_iface_vlan_from_hostname(
+ $host_ref->{'deployment'}->{'dhcpvlan'}, $host_ref
+ );
+ ( my $mac = $host_ref->{'interfaces'}->{$iface}->{'mac'} ) =~ s{ [:] }{-}xmsg;
+ my $pxe_boot_file = join q{/}, $pf_config->{'path'}->{'pxefiles_dir'}, $mac;
+
+ __make_file(
+ {
+ %{$arguments_ref},
+ file_type => q{pxe_boot},
+ filename => $pxe_boot_file,
+ site_name => $site_name,
+ preseed_filename => $preseed_filename,
+ }
+ );
+
+ return 1;
}
=head2 make_zone_file($arguments_ref)
@@ -201,7 +296,7 @@
croak q{ERROR: Invalid $arguments_ref};
}
- __make_file( { file_type => q{zone}, %{ $arguments_ref } } );
+ __make_file( { %{$arguments_ref}, file_type => q{zone} } );
return 1;
}
@@ -221,14 +316,15 @@
croak q{ERROR: Invalid $arguments_ref};
}
- __make_file( { file_type => q{resolv.conf}, %{ $arguments_ref } } );
+ __make_file( { %{$arguments_ref}, file_type => q{resolv.conf} } );
return 1;
}
sub Resolv {
- my ( $type_resolve, $ip_type, $hostname, $global_config, $site_name,
- $hosttype )
+ my ($type_resolve, $ip_type, $hostname, $global_config, $site_name,
+ $hosttype
+ )
= @_;
if ( $ip_type ne q{ipv4} and $ip_type ne q{ipv6} ) {
@@ -249,7 +345,8 @@
# $type_resolve eq q{cnf}
$site_name ||= get_uniq_site_from_hostname( $hostname, $global_config );
- my $zone = get_zone_from_hostname( $hostname, $global_config, $site_name );
+ my $zone
+ = get_zone_from_hostname( $hostname, $global_config, $site_name );
$hostname =~ s{ [.] $zone \z}{}xms;
# FIXME this regexp is also used in
@@ -268,16 +365,20 @@
\z
}xms;
- if ( not defined $hosttype
+ if (not defined $hosttype
and $hostshort
- !~ m{\A (network|netmask|broadcast|gateway|prefix)}xms )
+ !~ m{\A (network|netmask|broadcast|gateway|prefix)}xms
+ )
{
$hosttype
- = get_hosttype_from_hostname( $hostshort, $global_config,
- $site_name );
+ = get_hosttype_from_hostname(
+ $hostshort, $global_config,
+ $site_name
+ );
}
elsif ( $hostshort eq q{prefix} ) {
- my $vlan_def = get_vlan_config( $hostvlan, $global_config, $site_name );
+ my $vlan_def
+ = get_vlan_config( $hostvlan, $global_config, $site_name );
my $subnet_ref = get_subnet_from_vlan( $ip_type, $vlan_def );
my $prefix = $subnet_ref->masklen();
@@ -297,10 +398,10 @@
}
sub Search_and_replace {
- my ($hostname, $site_name, $input_file, $type_replace, $pf_config, $separator,
+ my ($hostname, $site_name, $input_file,
+ $type_replace, $pf_config, $separator,
$global_config, $type_resolve, $ip_type
- )
- = @_;
+ ) = @_;
if ( $type_resolve && $type_resolve eq 'cnf' && !defined $global_config )
{
@@ -318,8 +419,10 @@
foreach my $line ( @{$src} ) {
if ( $type_replace eq 'resolver' ) {
$line
- = __search_and_resolve_ip( $hostname, $ip_type, $site_name, $line,
- $separator, $type_resolve, $subst, $global_config );
+ = __search_and_resolve_ip(
+ $hostname, $ip_type, $site_name, $line,
+ $separator, $type_resolve, $subst, $global_config
+ );
}
elsif ( $type_replace eq 'iface' ) {
$line = __search_and_resolve_iface( $line, $host_props, $subst );
@@ -337,36 +440,138 @@
return \@result;
}
-sub Fix_hosts {
- my ( $hostname, $input_file, $site_name, $ip_type, $global_config, $pf_config )
- = @_;
+=head2 fix_etc_hosts($arguments_ref)
+Fixes the IP address listed in an /etc/hosts-like file for a given hostname.
+This is useful when debian-installer puts there a localnet address, to replace
+it with the IP address of the host in the dhcp deployment subnet.
+
+The named arguments are:
+
+=over
+
+=item I<hostname> the host name
+
+=item I<site_name> (optional) the site name
+
+=item I<input_file> the file to read from (usually I</etc/hosts>)
+
+=item I<output_file> the file to write to (usually I</etc/hosts> too)
+
+=item I<ip_type> I<ipv4> or I<ipv6> (but only I<ipv4> is currently supported)
+
+=item I<global_config> a reference to the global configuration hash
+
+=item I<pf_config> a reference to the pf-tools configuration hash
+
+=back
+
+=cut
+
+sub fix_etc_hosts {
+ my ($arguments_ref) = @_;
+
+ unless ( ref $arguments_ref eq 'HASH' ) {
+ croak q{ERROR: Invalid $arguments_ref};
+ }
+
+ check_args_type( $arguments_ref, q{},
+ qw( input_filename output_filename ) );
+
+ check_true_args( $arguments_ref,
+ qw( input_filename output_filename ) );
+
+ __make_file(
+ {
+ %{$arguments_ref},
+ file_type => q{etc_hosts},
+ filename => $arguments_ref->{'output_filename'},
+ }
+ );
+
+ return 1;
+}
+
+=head2 __fix_etc_hosts($arguments_ref)
+
+Reads an /etc/hosts-type file, fixes the IP address for a given hostname,
+returns a reference to the list of lines. THe named arguments are:
+
+=over
+
+=item I<hostname> the host name
+
+=item I<site_name> (optional) the site name
+
+=item I<input_file> the file to read from (usually I</etc/hosts>)
+
+=item I<ip_type> I<ipv4> or I<ipv6> (but only I<ipv4> is currently supported)
+
+=item I<global_config> a reference to the global configuration hash
+
+=item I<pf_config> a reference to the pf-tools configuration hash
+
+=back
+
+=cut
+
+# FIXME: move to end of file
+# FIXME: what is the problem exactly, is this really necessary?
+
+sub __fix_etc_hosts {
+ my ($arguments_ref) = @_;
+
+ my ($hostname, $site_name, $input_filename,
+ $ip_type, $global_config, $pf_config
+ )
+ = @{$arguments_ref}
+ {qw( hostname site_name input_filename
+ ip_type global_config pf_config )};
+
+ # $hostname, $site_name and $global_config will be checked by
+ # get_host_config()
+
+ # input_filename will be checked by __read_file_in_array()
+
+ # FIXME pf_config is not used for the moment
+
+ if ( not $ip_type ) {
+ croak q{ERROR: Invalid empty ip_type};
+ }
+ if ( ref $ip_type ) {
+ croak q{ERROR: Invalid non-scalar ip_type};
+ }
if ( $ip_type ne q{ipv4} ) {
- croak qq{ERROR: $ip_type is not implemented for fixing $input_file};
+ croak qq{ERROR: __fix_etc_hosts: ip_type '$ip_type' not implemented};
}
my $host_ref = get_host_config( $hostname, $global_config, $site_name );
my $dhcp_iface = get_iface_vlan_from_hostname(
- $host_ref->{'deployment'}->{'dhcpvlan'}, $host_ref );
+ $host_ref->{'deployment'}->{'dhcpvlan'}, $host_ref
+ );
- ( my $ip_deploy = $host_ref->{'interfaces'}->{$dhcp_iface}->{'ipv4'} )
- =~ s{ [/] [\d]+ \z }{}xms; # remove CIDR prefix size
+ # This should work for IPv6 too...
+ my $ip_and_prefix = $host_ref->{'interfaces'}->{$dhcp_iface}->{$ip_type};
+ my $ip_deploy = NetAddr::IP->new($ip_and_prefix)->addr();
- my $tmp_hosts = __read_file_in_array( $input_file, 0 );
+ my $lines_ref = __read_file_in_array( $input_filename, 1 );
- foreach my $line ( @{$tmp_hosts} ) {
+ foreach my $line ( @{$lines_ref} ) {
next unless $line =~ m{ $hostname }xms;
+
$line =~ s{ \A 127 [.] 0 [.] [\d]{1,3} [.] [\d]{1,3} }{$ip_deploy}xms;
}
- return $tmp_hosts;
+ return $lines_ref;
}
+# FIXME convert to __make_file()
sub Mk_dhcp {
my ( $header_file, $site_part ) = @_;
- my @dhcp_hosts = ();
+ my @dhcp_hosts = ();
- my $dhcp_headers = $header_file ? __read_file_in_array($header_file, 1) : [];
+ my $dhcp_headers
+ = $header_file ? __read_file_in_array( $header_file, 1 ) : [];
my @dhcp_subnets = ();
foreach my $vlan ( keys %{$site_part} ) {
@@ -375,7 +580,7 @@
foreach my $hostclass ( keys %{ $site_part->{$vlan} } ) {
next
- if $hostclass eq q{subnet}
+ if $hostclass eq q{subnet}
or $hostclass eq q{netmask}
or $hostclass eq q{routers};
@@ -428,7 +633,7 @@
croak q{ERROR: Invalid $arguments_ref};
}
- __make_file( { file_type => q{sources.list}, %{ $arguments_ref } } );
+ __make_file( { %{$arguments_ref}, file_type => q{sources.list} } );
return 1;
}
@@ -452,7 +657,7 @@
my $lines_ref = __read_file_in_array( $grub_src, 1 );
foreach my $line ( @{$lines_ref} ) {
- if ( $grub_version == 1
+ if ($grub_version == 1
and $line =~ m{ \A [#] kopt=.* \z }xms
or $grub_version == 2
and $line =~ m{ \A GRUB_CMDLINE_LINUX_DEFAULT=".*" \z }xms
@@ -467,7 +672,7 @@
}
# Either STDOUT or a tempfile...
- my ($dst_fh, $dst_fn);
+ my ( $dst_fh, $dst_fn );
if ( $dst eq q{-} ) {
$dst_fh = IO::File->new();
unless ( $dst_fh->fdopen( fileno(STDOUT), q{>} ) ) {
@@ -517,7 +722,7 @@
croak q{ERROR: Invalid $arguments_ref};
}
- __make_file( { file_type => q{interfaces}, %{ $arguments_ref } } );
+ __make_file( { %{$arguments_ref}, file_type => q{interfaces} } );
return 1;
}
@@ -548,13 +753,17 @@
$hash_subst->{'DISTRIB'} = get_distrib_from_host_ref($host_props);
$hash_subst->{'MODE'} = get_mode_from_host_ref($host_props);
$options->{'pkg_type'}
- ||= get_pkgtype_from_hostname( $hostname, $global_config, $site_name );
+ ||= get_pkgtype_from_hostname(
+ $hostname, $global_config,
+ $site_name
+ );
my $host_config = Get_config_for_hostname_on_site(
$hostname, $site_name, $hash_subst, $global_config, $pf_config
);
unless ($host_config) {
- croak qq{ERROR: Problem when parsing config for $hostname on $site_name};
+ croak
+ qq{ERROR: Problem when parsing config for $hostname on $site_name};
}
if ( !$pf_config->{'features'}->{'update'} ) {
@@ -564,7 +773,7 @@
my @sortedkeys = sort { Sort_config_sections( $host_config, $a, $b ) }
@{ $host_config->{'__sections_order'} };
- $| = 1;
+ $| = 1;
my $errorcount = __do_updateloop(
$host_config, $options, $hash_subst, $global_config, \@sortedkeys
);
@@ -614,8 +823,9 @@
next;
}
- if ( $host_config->{$depend}->{'action'} eq
- 'addmount' )
+ if ($host_config->{$depend}->{'action'} eq
+ 'addmount'
+ )
{
carp
qq{WARN: [$section] depends on addmount [$depend], it may not work during install!};
@@ -630,7 +840,7 @@
print qq{<$section>} . join q{ }, @depends;
}
$errorcount += __do_updateloop(
- $host_config, $options, $hash_subst,
+ $host_config, $options, $hash_subst,
$global_config, \@depends
);
}
@@ -695,11 +905,11 @@
}xmso
)
{
- my $before = $1;
- my $back = $3;
- my $match = $2 . $3 . $4;
- my $matchback = $2 . $4;
- my $after = $5;
+ my $before = $1;
+ my $back = $3;
+ my $match = $2 . $3 . $4;
+ my $matchback = $2 . $4;
+ my $after = $5;
my $lengthbefore = defined $before ? length $before : 0;
@@ -713,7 +923,11 @@
$match2 =~ s{ HOSTNAME }{$hostname}xmsg;
$match2 =~ s{ POPNAME }{$hash_subst->{'POPNAME'}}xmsg;
- my $resolved = Resolv( $type_resolve, $ip_type, $match2, $global_config, $site_name);
+ my $resolved
+ = Resolv(
+ $type_resolve, $ip_type, $match2, $global_config,
+ $site_name
+ );
if ( @{$resolved} ) {
if ( $separator eq q{DUPLICATE} ) {
my $templine = q{};
@@ -727,7 +941,7 @@
}
else {
my $replacement = join $separator, @{$resolved};
- substr( $line, $lengthbefore, length $match, $replacement);
+ substr( $line, $lengthbefore, length $match, $replacement );
}
}
@@ -774,7 +988,8 @@
my $lengthbefore = defined $before ? length $before : 0;
- ( my $real_vlan = $vlan ) =~ s{ POPNAME }{$hash_subst->{'POPNAME'}}xms;
+ ( my $real_vlan = $vlan )
+ =~ s{ POPNAME }{$hash_subst->{'POPNAME'}}xms;
my $eth = get_iface_vlan_from_hostname( $real_vlan, $host_props );
if ( defined $eth ) {
@@ -797,9 +1012,9 @@
return $line;
}
-=head2 __build_preseed_file($arguments_ref)
+=head2 __build_preseed($arguments_ref)
-Builds the preseed file for a host, returns the filename.
+Builds the preseed file content for a host.
I<$arguments_ref> is a reference to a hash of named parameters:
=over
@@ -808,11 +1023,93 @@
=item I<host_ref> a reference to the host configuration hash
-=item I<preseed_template> the template file name
-
-=item I<default_preseed> FIXME unused?
+=item I<preseed_template_filename> the template file name. This argument can
+be passed as I<template_filename> for simplicity.
=item I<pf_script> FIXME ???
+
+=item I<pf_config> a reference to the pf-tools configuration hash
+
+=item I<global_config> a reference to the global configuration hash
+
+=back
+
+=cut
+
+sub __build_preseed {
+ my ($arguments_ref) = @_;
+
+ my ($hostname, $host_ref, $template_filename,
+ $pf_script
+ )
+ = @{$arguments_ref}{
+ qw( hostname host_ref template_filename
+ pf_script
+ )
+ };
+
+ $template_filename ||= $arguments_ref->{'preseed_template_filename'};
+
+ if ( not $hostname ) {
+ croak q{ERROR: Invalid empty hostname};
+ }
+ if ( ref $hostname ) {
+ croak q{ERROR: Invalid non-scalar hostname};
+ }
+
+ if ( ref $host_ref ne 'HASH' ) {
+ croak q{ERROR: Invalid non-hashref host_ref};
+ }
+
+ if ( not $template_filename ) {
+ croak q{ERROR: Invalid empty template_filename};
+ }
+ if ( ref $template_filename ) {
+ croak q{ERROR: Invalid non-scalar template_filename};
+ }
+
+ if ( not $pf_script ) {
+ croak q{ERROR: Invalid empty pf_script};
+ }
+ if ( ref $pf_script ) {
+ croak q{ERROR: Invalid non-scalar pf_script};
+ }
+
+ my $kernel_pkg = __get_kpkg_from_kernel(
+ $host_ref->{'boot'}->{'kernel'},
+ $host_ref->{'deployment'}->{'mode'},
+ );
+
+ my $vars_ref = {
+ 'kernelpkg' => $kernel_pkg,
+ 'mode' => $host_ref->{'deployment'}->{'mode'},
+ 'distrib' => $host_ref->{'deployment'}->{'distrib'},
+ 'config_script' => $pf_script,
+ };
+
+ my $content = __read_and_process_template( $template_filename, $vars_ref );
+
+ return [$content];
+}
+
+=head2 __build_pxe_boot($arguments_ref)
+
+Builds the PXE boot file content for a host and returns a reference to the
+array of lines. I<$arguments_ref> is a reference to a hash of named
+parameters:
+
+=over
+
+=item I<hostname> the host name
+
+=item I<site_name> the site name
+
+=item I<preseed_filename> the preseed file name
+
+=item I<pxe_template_filename> the pxe template file name. This argument can
+be passed as I<template_filename> for simplicity.
+
+=item I<global_config> a reference to the global configuration hash
=item I<pf_config> a reference to the pf-tools configuration hash
@@ -820,44 +1117,108 @@
=cut
-sub __build_preseed_file {
+sub __build_pxe_boot {
my ($arguments_ref) = @_;
- my ($hostname, $host_ref, $preseed_template,
- $default_preseed, $pf_script, $pf_config
- ) = @{$arguments_ref}{
+ my ($hostname, $site_name, $global_config,
+ $pf_config, $preseed_filename, $template_filename
+ )
+ = @{$arguments_ref}{
qw(
- hostname host_ref preseed_template
- default_preseed pf_script pf_config
- )
+ hostname site_name global_config
+ pf_config preseed_filename template_filename
+ )
};
- my $preseed_template_content = __read_file_in_scalar($preseed_template);
+ $template_filename = $arguments_ref->{'pxe_template_filename'};
- my $kernel_pkg = __get_kpkg_from_kernel(
- $host_ref->{'boot'}->{'kernel'},
- $host_ref->{'deployment'}->{'mode'},
+ if ( not $hostname ) {
+ croak q{ERROR: Invalid empty $hostname};
+ }
+ if ( ref $hostname ) {
+ croak q{ERROR: Invalid non-scalar $hostname};
+ }
+
+ if ( not $site_name ) {
+ croak q{ERROR: Invalid empty $site_name};
+ }
+ if ( ref $site_name ) {
+ croak q{ERROR: Invalid non-scalar $site_name};
+ }
+
+ if ( not $global_config ) {
+ croak q{ERROR: Invalid empty $global_config};
+ }
+ if ( ref $global_config ne 'HASH' ) {
+ croak q{ERROR: Invalid non-hashref $global_config};
+ }
+
+ # This is not a complete check but it will catch obvious errors,
+ # like $global_config referencing a non-config hash
+ if ( not exists $global_config->{'ZONE'} ) {
+ croak q{ERROR: Invalid $global_config hashref: no 'ZONE' key found};
+ }
+
+ if ( not $pf_config ) {
+ croak q{ERROR: Invalid empty $pf_config};
+ }
+ if ( ref $pf_config ne 'HASH' ) {
+ croak q{ERROR: Invalid non-hashref $pf_config};
+ }
+
+ # This is not a complete check but it will catch obvious errors,
+ # like $pf_config referencing a non-config hash
+ if ( not exists $pf_config->{'vcs'} ) {
+ croak q{ERROR: Invalid $pf_config hashref: no 'vcs' key found};
+ }
+
+ if ( not $preseed_filename ) {
+ croak q{ERROR: Invalid empty $preseed_filename};
+ }
+ if ( ref $preseed_filename ) {
+ croak q{ERROR: Invalid non-scalar $preseed_filename};
+ }
+
+ if ( ref $template_filename ) {
+ croak q{ERROR: Invalid non-scalar $template_filename};
+ }
+
+ my $host_ref = get_host_config( $hostname, $global_config, $site_name );
+ my $mode = $host_ref->{'deployment'}->{'mode'};
+ my $templates_dirname = $pf_config->{'path'}->{'templates_dir'};
+
+ $template_filename ||= join q{/}, $templates_dirname, $pf_config->{$mode}->{'pxe'};
+
+ my $preseed_md5
+ = __get_md5sum_for_preseedfile( $preseed_filename, $pf_config );
+
+ my $iface = get_iface_vlan_from_hostname(
+ $host_ref->{'deployment'}->{'dhcpvlan'}, $host_ref
);
- my $preseed_subst = {
- 'kernelpkg' => $kernel_pkg,
- 'mode' => $host_ref->{'deployment'}->{'mode'},
- 'distrib' => $host_ref->{'deployment'}->{'distrib'},
- 'config_script' => $pf_script,
+ # Get cmdline, remove leading and trailing whitespace
+ ( my $cmdline = join q{ }, get_cmdline_from_host_ref($host_ref) )
+ =~ s{ \A \s* (\S*) \s* \z}{$1}xms;
+
+ my $vars_ref = {
+ 'iface' => $iface,
+ 'mode' => $host_ref->{'deployment'}->{'mode'} . '-installer',
+ 'arch' => $host_ref->{'deployment'}->{'arch'},
+ 'distrib' => $host_ref->{'deployment'}->{'distrib'},
+ 'serial_speed' => '115200',
+ 'preseed_url' => $preseed_filename,
+ 'preseed_md5' => $preseed_md5,
+ 'console' => $host_ref->{'boot'}->{'console'},
+ 'install_cmdline' => $host_ref->{'boot'}->{'cmdline'},
+ 'cmdline' => $cmdline,
+ 'kernel' => $host_ref->{'boot'}->{'kernel'},
+ 'initrd' => $host_ref->{'boot'}->{'initrd'},
};
- my $preseed_content = q{};
- my $tpl = Template::Tiny->new( TRIM => 1 );
- $tpl->process( \$preseed_template_content, $preseed_subst, \$preseed_content );
- my $tmp_fh = File::Temp->new( unlink => 0 );
- my $tmp_fn = $tmp_fh->filename();
- __write_scalar_to_filehandle($tmp_fh, $tmp_fn, $preseed_content);
+ my $content
+ = __read_and_process_template( $template_filename, $vars_ref );
- my $preseed_filename = qq{preseed_$hostname};
- my $dst = join q{/}, $pf_config->{'path'}->{'preseed_dir'}, $preseed_filename;
- __move_if_different( $tmp_fn, $dst );
-
- return $preseed_filename;
+ return [$content];
}
=head2 __build_interfaces($arguments_ref)
@@ -916,15 +1277,17 @@
croak q{ERROR: Invalid non-scalar $site_name};
}
- my $host_ref = get_host_config( $hostname, $global_config, $site_name );
+ my $host_ref = get_host_config( $hostname, $global_config, $site_name );
my $interfaces = {};
my $routes = {};
foreach my $iface ( 'lo', sort keys %{ $host_ref->{'interfaces'} } ) {
push @{ $interfaces->{'__order'} }, $iface;
$interfaces->{$iface}
- = __build_interface_lines_ref( $iface, $routes, $host_ref,
- $pf_config );
+ = __build_interface_lines_ref(
+ $iface, $routes, $host_ref,
+ $pf_config
+ );
}
DESTINATION:
@@ -972,7 +1335,7 @@
q{},
);
- foreach my $iface ( @{ $interfaces->{'__order' } } ) {
+ foreach my $iface ( @{ $interfaces->{'__order'} } ) {
push @lines, @{ $interfaces->{$iface} }, q{};
}
@@ -987,21 +1350,23 @@
=cut
sub __build_interface_lines_ref {
- my ($iface, $routes, $host_ref, $pf_config) = @_;
+ my ( $iface, $routes, $host_ref, $pf_config ) = @_;
my @iface_lines;
my $if_part = $host_ref->{'interfaces'}->{$iface};
my $if_method
- = $if_part->{'method'} ? $if_part->{'method'}
- : $iface eq 'lo' ? q{loopback}
- : q{static};
+ = $if_part->{'method'}
+ ? $if_part->{'method'}
+ : $iface eq 'lo' ? q{loopback}
+ : q{static};
push @iface_lines,
qq{auto $iface},
qq{iface $iface inet $if_method};
- if ( ( $if_part->{'method'} and $if_part->{'method'} eq 'dhcp' )
- or $iface eq 'lo' )
+ if (( $if_part->{'method'} and $if_part->{'method'} eq 'dhcp' )
+ or $iface eq 'lo'
+ )
{
return \@iface_lines;
}
@@ -1036,8 +1401,9 @@
push @iface_lines, qq{\tvlan_raw_device\t$raw_device};
# Set MTU to 1496 unless told otherwise
- if ( $if_part->{'iface_opt'}
- and $if_part->{'iface_opt'} !~ m{ mtu }xms )
+ if ($if_part->{'iface_opt'}
+ and $if_part->{'iface_opt'} !~ m{ mtu }xms
+ )
{
$if_part->{'iface_opt'} .= q{, mtu 1496};
}
@@ -1048,8 +1414,10 @@
# Options
if ( $if_part->{'iface_opt'} ) {
- foreach my $option ( split qr{ \s* [,] \s* }xms,
- $if_part->{'iface_opt'} )
+ foreach my $option (
+ split qr{ \s* [,] \s* }xms,
+ $if_part->{'iface_opt'}
+ )
{
push @iface_lines,
qq{\tup\t\t/sbin/ip link set $iface $option};
@@ -1103,7 +1471,8 @@
}
my $host_props = get_host_config( $hostname, $global_config, $site_name );
- my $domain = get_zone_from_hostname( $hostname, $global_config, $site_name );
+ my $domain
+ = get_zone_from_hostname( $hostname, $global_config, $site_name );
my @dns = split qr{ \s* [,] \s* }xms, $host_props->{'dns'}->{'resolver'};
@@ -1116,9 +1485,12 @@
q{},
);
- foreach my $ip_type ( qw( ipv4 ipv6 ) ) {
+ foreach my $ip_type (qw( ipv4 ipv6 )) {
foreach my $dns (@dns) {
- my $resolved = Resolv( q{cnf}, $ip_type, $dns, $global_config, $site_name );
+ my $resolved = Resolv(
+ q{cnf}, $ip_type, $dns, $global_config,
+ $site_name
+ );
foreach my $ip ( @{$resolved} ) {
push @lines, qq{nameserver $ip};
}
@@ -1200,7 +1572,7 @@
my @network_order = @{ $zone_part->{'__network_order'} };
push @network_order,
@{ $zone_ref->{'ALL_SITES'}->{'__network_order'} };
- foreach my $network ( @network_order ) {
+ foreach my $network (@network_order) {
my $head = qq{; $network};
if ( $merged_zone_ref->{$network}->{'comment'} ) {
$head .= ": $merged_zone_ref->{$network}->{'comment'}";
@@ -1230,16 +1602,13 @@
q{;;============================================================================},
q{};
- my @hostclass_order =
- @{ $zone_ref->{'BY_SITE'}->{$site_name}->{'__hostclass_order'} };
- foreach my $hc ( @{ $zone_ref->{'ALL_SITES'}->{'__hostclass_roder'} } ) {
- my $exist = grep m{ \A $hc \z }xms, @hostclass_order;
- if ( not $exist ) {
- push @hostclass_order, $hc;
- }
- }
+ my @hostclass_order
+ = uniq(
+ @{ $zone_ref->{'BY_SITE'}->{$site_name}->{'__hostclass_order'} },
+ @{ $zone_ref->{'ALL_SITES'}->{'__hostclass_order'} },
+ );
- foreach my $server ( @hostclass_order ) {
+ foreach my $server (@hostclass_order) {
my $head = qq{; $server};
if ( $merged_zone_ref->{$server}->{'comment'} ) {
@@ -1339,7 +1708,7 @@
my @sections = ();
foreach my $section ( @{$sections_ref} ) {
- # Remove leading and trailink whitespace
+ # Remove leading and trailing whitespace
$section =~ s{ \A \s* (\S*) \s* \z }{$1}xms;
if ( not $section ) {
croak
@@ -1370,34 +1739,18 @@
$template ||= join q{/}, $pf_config->{'path'}->{'templates_dir'},
$pf_config->{$deployment_mode}->{'sources_list'};
- my $tpl = Template::Tiny->new( TRIM => 1 );
- my $sources_template = __read_file_in_scalar($template);
- my $sources_subst = {
- 'mode' => $deployment_mode,
- 'distrib' => $host_ref->{'deployment'}->{'distrib'},
- 'default_sections' =>
+ my $vars_ref = {
+ mode => $deployment_mode,
+ distrib => $host_ref->{'deployment'}->{'distrib'},
+ default_sections =>
$pf_config->{$deployment_mode}->{'default_sections'},
- 'custom_sections' => $sections,
+ custom_sections => $sections,
+ backports => $backports,
};
- my $sources_content = q{};
- $tpl->process( \$sources_template, $sources_subst, \$sources_content );
- # FIXME why not in the template?
- if ($backports) {
- my $dash_backports
- = $deployment_mode eq q{debian} ? q{-backports} : q{};
- my $back_src = $deployment_mode . $dash_backports;
- $sources_content .= <<"BACKPORTS_TEXT";
+ my $content = __read_and_process_template( $template, $vars_ref );
-deb http://mirrors.private/$back_src $host_ref->{'deployment'}->{'distrib'}-backports $pf_config->{$deployment_mode}->{'default_sections'}
-
-BACKPORTS_TEXT
- }
-
- # This cannot be in the template because of the TRIM option
- $sources_content .= qq{\n};
-
- return [$sources_content];
+ return [$content];
}
=head2 __get_kpkg_from_kernel( $pxefilename, $deploymode )
@@ -1451,8 +1804,20 @@
sub __get_md5sum_for_preseedfile {
my ( $filename, $pf_config ) = @_;
- my $file_path = join q{/}, $pf_config->{'path'}->{'preseed_dir'},
- $filename;
+ if ( not $filename ) {
+ croak q{ERROR: Invalid empty filename};
+ }
+ if ( ref $pf_config ne 'HASH' ) {
+ croak q{ERROR: Invalid non-hashref pf_config};
+ }
+ if ( not $pf_config->{'path'}->{'preseed_dir'} ) {
+ croak q{ERROR: Invalid empty preseed_dir};
+ }
+ if ( ref $pf_config->{'path'}->{'preseed_dir'} ) {
+ croak q{ERROR: Invalid non-scalar preseed_dir};
+ }
+
+ my $file_path = join q{/}, $pf_config->{'path'}->{'preseed_dir'}, $filename;
my $fh = IO::File->new( $file_path, q{<} );
unless ($fh) {
@@ -1556,7 +1921,7 @@
=cut
sub __move_if_different {
- my ($source, $destination) = @_;
+ my ( $source, $destination ) = @_;
if ( compare( $source, $destination ) ) {
unless ( move( $source, $destination ) ) {
@@ -1583,6 +1948,14 @@
sub __read_file_in_scalar {
my ($filename) = @_;
+ if ( not $filename ) {
+ croak q{ERROR: Invalid empty $filename};
+ }
+
+ if ( ref $filename ) {
+ croak q{ERROR: Invalid non-scalar $filename};
+ }
+
my $fh = IO::File->new( $filename, q{<} );
unless ($fh) {
croak qq{ERROR: open $filename: $OS_ERROR};
@@ -1607,9 +1980,16 @@
=cut
sub __read_file_in_array {
- my ($filename, $chomp_wanted) = @_;
+ my ( $filename, $chomp_wanted ) = @_;
$chomp_wanted = 1 unless defined $chomp_wanted;
+
+ if ( not $filename ) {
+ croak q{ERROR: Invalid empty filename};
+ }
+ if ( ref $filename ) {
+ croak q{ERROR: Invalid non-scalar filename};
+ }
my $fh = IO::File->new( $filename, q{<} );
unless ($fh) {
@@ -1617,7 +1997,7 @@
}
my @lines = ();
- while ( defined ( my $line = $fh->getline() ) ) {
+ while ( defined( my $line = $fh->getline() ) ) {
if ($chomp_wanted) {
chomp $line;
}
@@ -1639,10 +2019,9 @@
=cut
sub __write_scalar_to_filehandle {
- my ($fh, $filename, $scalar) = @_;
+ my ( $fh, $filename, $scalar ) = @_;
- # FIXME should be q{}, but wait for proper tests to really correct it
- __write_array_to_filehandle( $fh, $filename, [$scalar], qq{\n} );
+ __write_array_to_filehandle( $fh, $filename, [$scalar], q{} );
return 1;
}
@@ -1666,7 +2045,10 @@
# IO::File does not implement filename()
#my $filename = $fh->filename();
- unless ( $fh->print( join( $line_separator, @{$array_ref}), $line_separator ) ) {
+ unless (
+ $fh->print( join( $line_separator, @{$array_ref} ), $line_separator )
+ )
+ {
croak qq{ERROR: print $filename: $OS_ERROR};
}
@@ -1694,13 +2076,18 @@
is different from the original content. STDOUT is also supported (if
I<filename> is '-').
+The path to I<filename> is automagically created via make_path() if needed.
+
=cut
sub __make_file {
my ($arguments_ref) = @_;
my %build_content_for = (
+ etc_hosts => \&__fix_etc_hosts,
interfaces => \&__build_interfaces,
+ preseed => \&__build_preseed,
+ pxe_boot => \&__build_pxe_boot,
q{resolv.conf} => \&__build_resolv_conf,
q{sources.list} => \&__build_sources_list,
zone => \&__build_zone,
@@ -1732,7 +2119,7 @@
my $lines_ref = $build_content_for{$file_type}->($arguments_ref);
# Either STDOUT or a tempfile...
- my ($out_fh, $out_fn);
+ my ( $out_fh, $out_fn );
if ( $filename eq q{-} ) {
$out_fh = IO::File->new();
unless ( $out_fh->fdopen( fileno(STDOUT), q{>} ) ) {
@@ -1748,11 +2135,38 @@
__write_array_to_filehandle( $out_fh, $out_fn, $lines_ref, qq{\n} );
if ( $filename ne q{-} ) {
+ make_path( dirname($filename) );
__move_if_different( $out_fn, $filename );
}
return 1;
}
+=head2 __read_and_process_template( $template_filename, $vars_ref )
+
+Reads I<$template_filename> as a Template::Tiny template and process it with
+I<$vars_ref>. Returns the processed content.
+
+=cut
+
+sub __read_and_process_template {
+ my ( $template_filename, $vars_ref ) = @_;
+
+ # __read_file_in_scalar() will take care of the $template_filename checks
+
+ if ( ref $vars_ref ne 'HASH' ) {
+ croak q{ERROR: Invalid non-hashref vars_ref};
+ }
+
+ my $template_content = __read_file_in_scalar($template_filename);
+
+ my $content = q{};
+ my $template = Template::Tiny->new();
+ $template->process( \$template_content, $vars_ref, \$content );
+
+ return $content;
+}
+
+
1; # Magic true value required at end of module
diff -r 9e79004112bc -r de2d381543f5 sbin/fix_hosts
--- a/sbin/fix_hosts Wed Nov 24 19:39:32 2010 +0100
+++ b/sbin/fix_hosts Wed Dec 01 08:25:18 2010 +0100
@@ -28,7 +28,7 @@
use Sys::Hostname;
use PFTools::Structqueries;
-use PFTools::Utils;
+use PFTools::Utils qw( Init_TOOLS fix_etc_hosts );
#################################
# VARS
@@ -103,19 +103,17 @@
|| get_uniq_site_from_hostname( $options->{'host'}, $GLOBAL_STRUCT );
}
-my $fixed_input = Fix_hosts(
- $options->{'host'}, $options->{'input'},
- $options->{'site'}, $options->{'type'}, $GLOBAL_STRUCT,
- $PF_CONFIG );
-unless( $fixed_input ) {
- die "An error occured during fixing file $options->{'input'}";
-}
+fix_etc_hosts(
+ {
+ hostname => $options->{'host'},
+ site_name => $options->{'site'},
+ input_filename => $options->{'input'},
+ ouput_filename => $options->{'output'},
+ ip_type => $options->{'type'},
+ global_config => $GLOBAL_STRUCT,
+ pf_config => $PF_CONFIG,
+ }
+);
-my $output_fh = IO::File->new(">$options->{'output'}")
- or die "Unable to open destination $options->{'output'} : $OS_ERROR";
-$output_fh->print ( join '', @{$fixed_input} )
- or die "Unable to write to destination $options->{'output'} : $OS_ERROR";
-$output_fh->close()
- or die "Unable to close destination $options->{'output'} : $OS_ERROR";
exit 0;
diff -r 9e79004112bc -r de2d381543f5 sbin/mk_pxelinuxcfg
--- a/sbin/mk_pxelinuxcfg Wed Nov 24 19:39:32 2010 +0100
+++ b/sbin/mk_pxelinuxcfg Wed Dec 01 08:25:18 2010 +0100
@@ -28,16 +28,16 @@
use Getopt::Long qw( :config ignore_case_always bundling );
use File::Path qw( make_path );
-use PFTools::Utils;
+use PFTools::Utils qw( Init_TOOLS make_pxe_boot_and_preseed_files );
############################################
# Vars
my @options_specs = (
- 'help',
+ 'config|c=s',
+ 'help|h',
'script=s',
'site|s=s',
- 'config|c=s',
'store=s',
);
@@ -106,25 +106,35 @@
die "Unknown site $options->{'site'}";
}
+=for FIXME
+
+provide an iterator for all hostclasses on a site
+provide an iterator for all hosts in a hostclass on a site
+provide an iterator for all hosts on a site
+
+=> pseudo-code:
+
+my $host_iterator = get_iteror_for_hosts( $options->{'site'} );
+foreach my $host ( $host_iterator->get_next() ) {
+ make_pxe_boot_and_preseed_files( ... );
+}
+
+=cut
+
my $site_part = $GLOBAL_STRUCT->{'SITE'}->{'BY_NAME'}->{$options->{'site'}};
my $host_part = $site_part->{'HOST'}->{'BY_NAME'};
foreach my $hostclass ( @{ $site_part->{'HOST'}->{'__hostclass_pxe'} } ) {
foreach my $host ( keys %{ $host_part->{$hostclass} } ) {
next if ( ref $host_part->{$hostclass}->{$host} ne 'HASH' );
- my $mode
- = $host_part->{$hostclass}->{$host}->{'deployment'}->{'mode'};
- my $pxe_template = $PF_CONFIG->{'path'}->{'templates_dir'} . '/'
- . $PF_CONFIG->{$mode}->{'pxe'};
- my $preseed_file =
- $host_part->{$hostclass}->{$host}->{'deployment'}->{'preseed'}
- || $PF_CONFIG->{$mode}->{'preseed'};
- my $preseed_tpl = $PF_CONFIG->{'path'}->{'templates_dir'} . '/'
- . $preseed_file;
- my $pxe_file = Mk_PXE_bootfile(
- $host, $host_part->{$hostclass}->{$host},
- $pxe_template, $preseed_tpl,
- $DEFAULT_PRESEED, $options->{'script'}, $PF_CONFIG
- );
+
+ my $args_ref = {
+ hostname => $host,
+ site_name => $options->{'site'},
+ global_config => $GLOBAL_STRUCT,
+ pf_config => $PF_CONFIG,
+ pf_script => $options->{'script'},
+ };
+ make_pxe_boot_and_preseed_files($args_ref);
}
}
diff -r 9e79004112bc -r de2d381543f5 t/12.storable.t
--- a/t/12.storable.t Wed Nov 24 19:39:32 2010 +0100
+++ b/t/12.storable.t Wed Dec 01 08:25:18 2010 +0100
@@ -6,21 +6,21 @@
use Test::Exception;
use Test::More qw( no_plan );
-use PFTools::Conf qw( Flush2disk_GLOBAL Retrieve_GLOBAL );
+use PFTools::Conf qw( store_global_config retrieve_global_config );
-can_ok( 'PFTools::Conf', qw( Flush2disk_GLOBAL Retrieve_GLOBAL ) );
+can_ok( 'PFTools::Conf', qw( store_global_config retrieve_global_config ) );
-note('Testing PFTools::Conf::Flush2disk_GLOBAL');
+note('Testing PFTools::Conf::store_global_config');
-throws_ok { Flush2disk_GLOBAL() }
+throws_ok { store_global_config() }
qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] [\$] global_config }xms
=> q{Dies on non-hashref global_config};
-throws_ok { Flush2disk_GLOBAL( {} ) }
+throws_ok { store_global_config( {} ) }
qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] [\$] pf_config }xms
=> q{Dies on non-hashref pf_config};
-throws_ok { Flush2disk_GLOBAL( {}, {}, {} ) }
+throws_ok { store_global_config( {}, {}, {} ) }
qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] flush_file }xms
=> q{Dies on non-scalar flush_file};
@@ -35,7 +35,7 @@
};
my $pf_config = {};
-throws_ok { Flush2disk_GLOBAL( $global_config, $pf_config ) }
+throws_ok { store_global_config( $global_config, $pf_config ) }
qr{\A ERROR: }xms
=> 'Dies with error message if empty $pf_config and empty $flush_file';
@@ -50,45 +50,45 @@
},
};
-my $result = Flush2disk_GLOBAL($global_config, $pf_config);
+my $result = store_global_config( $global_config, $pf_config );
ok $result && -s $store1
=> 'Stores something in default path';
-$result = Flush2disk_GLOBAL($global_config, $pf_config, $store2);
+$result = store_global_config( $global_config, $pf_config, $store2 );
ok $result && -s $store2
=> 'Stores something in explicit path';
unlink $store2;
-$result = Flush2disk_GLOBAL($global_config, {}, $store2);
+$result = store_global_config( $global_config, {}, $store2 );
ok $result && -s $store2
=> 'Stores something in explicit path even if empty $pf_config';
-throws_ok { Flush2disk_GLOBAL($global_config, $pf_config, $store3) }
+throws_ok { store_global_config( $global_config, $pf_config, $store3 ) }
# "Can't" case differs for some versions of Perl
qr{\A ERROR: [ ] [Cc]an't [ ] create }xms
=> 'Dies if cannot create';
-note('Testing PFTools::Conf::Retrieve_GLOBAL');
+note('Testing PFTools::Conf::retrieve_global_config');
-throws_ok { Retrieve_GLOBAL( {} ) }
+throws_ok { retrieve_global_config( {} ) }
qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] path_global_file }xms
=> q{Dies on non-scalar flush_file};
-throws_ok { Retrieve_GLOBAL() }
+throws_ok { retrieve_global_config() }
qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] path_global_file }xms
=> q{Dies on empty flush_file};
-throws_ok { Retrieve_GLOBAL($store3) }
+throws_ok { retrieve_global_config($store3) }
qr{\A ERROR: }xms
=> 'Dies on inexistent file';
-$result = Retrieve_GLOBAL($store1);
+$result = retrieve_global_config($store1);
is_deeply $result, $global_config
=> 'Store1 retrieval';
unlink $store1;
-$result = Retrieve_GLOBAL($store2);
+$result = retrieve_global_config($store2);
is_deeply $result, $global_config
=> 'Store2 retrieval';
unlink $store2;
diff -r 9e79004112bc -r de2d381543f5 t/20.files.t
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/t/20.files.t Wed Dec 01 08:25:18 2010 +0100
@@ -0,0 +1,1198 @@
+#!perl
+
+use strict;
+use warnings;
+
+use Cwd;
+use English qw( -no_match_vars ); # Avoids regex performance penalty
+use File::Basename;
+use File::Copy;
+use Sys::Hostname;
+use Test::Exception;
+use Test::More qw( no_plan );
+
+use PFTools::Conf;
+use PFTools::Structqueries qw( get_host_config );
+use PFTools::Utils qw( /^./ ); # import @EXPORT and @EXPORT_OK
+
+# Let's go back to our test configuration
+# FIXME: this depends on t/13.conf.t, but it probably should not.
+my $config_file = 't/13.conf.cfg1/etc/pf-tools.1.conf';
+my $pf_config = Init_PF_CONFIG($config_file); # already tested OK in 13.conf.t
+
+my $hostname = hostname;
+my $hash_subst = Init_SUBST( $hostname, undef, $pf_config, 'private' );
+
+my $global_config = Init_GLOBAL_NETCONFIG( q{COMMON:private-network}, $hash_subst );
+
+########################################################################
+note('Testing PFTools::Utils::__make_zone_header');
+can_ok( 'PFTools::Utils', qw( __make_zone_header ) );
+
+throws_ok { PFTools::Utils::__make_zone_header(); }
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] zone_name }xms
+ => q{Dies if empty $zone_name};
+
+throws_ok { PFTools::Utils::__make_zone_header( {} ); }
+qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] zone_name }xms
+ => q{Dies if non-scalar $zone_name};
+
+throws_ok { PFTools::Utils::__make_zone_header( q{name} ); }
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] site_name }xms
+ => q{Dies if empty $site_name};
+
+throws_ok { PFTools::Utils::__make_zone_header( q{name}, {} ); }
+qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] site_name }xms
+ => q{Dies if non-scalar $site_name};
+
+throws_ok { PFTools::Utils::__make_zone_header( q{name}, q{site} ); }
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] zone_ref }xms
+ => q{Dies if empty $zone_ref};
+
+throws_ok { PFTools::Utils::__make_zone_header( q{name}, q{site}, q{ref} ); }
+qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] [\$] zone_ref }xms
+ => q{Dies if non-hashref $zone_ref};
+
+throws_ok { PFTools::Utils::__make_zone_header( q{name}, q{site}, {} ); }
+qr{ \A ERROR: [ ] Invalid [ ] [\$] zone_ref [ ] hashref:
+ [ ] no [ ] 'SOA' [ ] key [ ] found }xms
+ => q{Dies if non-zone hashref $zone_ref};
+
+
+my $zone_ref = $global_config->{'ZONE'}->{'BY_NAME'}->{'private'};
+$zone_ref->{'SOA'}->{'serial'} = '1289575205';
+my $result = PFTools::Utils::__make_zone_header( 'private', 'cbv4-pfds', $zone_ref );
+my $expected_result = [
+ ';;',
+ ';; BIND configuration file for zone: private',
+ ';; Site: cbv4-pfds',
+ ';;',
+ ';; Internal management zone',
+ ';;============================================================================',
+ '',
+ '$TTL 1D ; TTL (1 day)',
+ '@ IN SOA' . qq{\t} . 'Deploy00.private. dnsmaster at private (',
+ ' 1289575205' . qq{\t} . '; Serial',
+ ' 6H ; Refresh (6 hours)',
+ ' 1H ; Retry (1 hour)',
+ ' 7D ; Expire (7 days)',
+ ' 1H ; Negative TTL (1 hours)',
+ ' )',
+ '',
+ ' IN NS' . qq{\t} . 'deploy00.vlan-systeme.private.',
+ ' IN NS' . qq{\t} . 'deploy01.vlan-systeme.private.',
+ '',
+ ' IN MX' . qq{\t} . '1 mf.private.',
+ ' IN MX' . qq{\t} . '2 mf00.private.',
+ ' IN MX' . qq{\t} . '2 mf01.private.',
+ '',
+ '',
+];
+
+is_deeply $result, $expected_result
+ => q{Returns the expected result for zone 'private'}
+ or note explain $result;
+
+
+########################################################################
+note('Testing PFTools::Utils::__build_zone');
+can_ok( 'PFTools::Utils', qw( __build_zone ) );
+
+throws_ok { PFTools::Utils::__build_zone(); }
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] zone_name }xms
+ => q{Dies if empty $zone_name};
+
+throws_ok { PFTools::Utils::__build_zone( { zone_name => {} } ); }
+qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] zone_name }xms
+ => q{Dies if non-scalar $zone_name};
+
+throws_ok { PFTools::Utils::__build_zone( { zone_name => q{name} } ); }
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] site_name }xms
+ => q{Dies if empty $site_name};
+
+throws_ok {
+ PFTools::Utils::__build_zone(
+ {
+ zone_name => q{name},
+ site_name => {},
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] site_name }xms
+ => q{Dies if non-scalar $site_name};
+
+throws_ok {
+ PFTools::Utils::__build_zone(
+ {
+ zone_name => q{name},
+ site_name => q{site},
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] global_config }xms
+ => q{Dies if empty $global_config};
+
+throws_ok {
+ PFTools::Utils::__build_zone(
+ {
+ zone_name => q{name},
+ site_name => q{site},
+ global_config => q{ref},
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] [\$] global_config }xms
+ => q{Dies if non-hashref $global_config};
+
+throws_ok {
+ PFTools::Utils::__build_zone(
+ {
+ zone_name => q{name},
+ site_name => q{site},
+ global_config => {},
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] [\$] global_config [ ] hashref:
+ [ ] no [ ] 'ZONE' [ ] key [ ] found }xms
+ => q{Dies if non-config hashref $global_config};
+
+throws_ok {
+ PFTools::Utils::__build_zone(
+ {
+ zone_name => q{name},
+ site_name => q{site},
+ global_config => $global_config,
+ }
+ );
+}
+qr{ \A ERROR: [ ] Unknown [ ] zone_name: [ ] }xms
+ => q{Dies if unknown zone_name};
+
+throws_ok {
+ PFTools::Utils::__build_zone(
+ {
+ zone_name => q{private},
+ site_name => q{site},
+ global_config => $global_config
+ }
+ );
+}
+qr{ \A ERROR: [ ] Unknown [ ] site_name: [ ] }xms
+ => q{Dies if unknown site_name};
+
+$result = PFTools::Utils::__build_zone(
+ {
+ zone_name => q{private},
+ site_name => q{cbv4-pfds},
+ global_config => $global_config,
+ }
+);
+$expected_result = [
+ ';;',
+ ';; BIND configuration file for zone: private',
+ ';; Site: cbv4-pfds',
+ ';;',
+ ';; Internal management zone',
+ ';;============================================================================',
+ '',
+ '$TTL 1D ; TTL (1 day)',
+ '@ IN SOA Deploy00.private. dnsmaster at private (',
+ ' 1289575205 ; Serial',
+ ' 6H ; Refresh (6 hours)',
+ ' 1H ; Retry (1 hour)',
+ ' 7D ; Expire (7 days)',
+ ' 1H ; Negative TTL (1 hours)',
+ ' )',
+ '',
+ ' IN NS deploy00.vlan-systeme.private.',
+ ' IN NS deploy01.vlan-systeme.private.',
+ '',
+ ' IN MX 1 mf.private.',
+ ' IN MX 2 mf00.private.',
+ ' IN MX 2 mf01.private.',
+ '',
+ '',
+ ';;',
+ ';; Networks',
+ ';;============================================================================',
+ '',
+ '; vlan-systeme',
+ ';----------------------------------------------------------------------------',
+ 'network.vlan-systeme IN A 10.1.0.0',
+ 'netmask.vlan-systeme IN A 255.255.0.0',
+ 'broadcast.vlan-systeme IN A 10.1.255.255',
+ '',
+ '; vlan-pfds-int',
+ ';----------------------------------------------------------------------------',
+ 'network.vlan-pfds-int IN A 10.2.0.0',
+ 'netmask.vlan-pfds-int IN A 255.255.0.0',
+ 'broadcast.vlan-pfds-int IN A 10.2.255.255',
+ '',
+ '; vlan-admindsi',
+ ';----------------------------------------------------------------------------',
+ 'network.vlan-admindsi IN A 10.3.1.0',
+ 'netmask.vlan-admindsi IN A 255.255.255.0',
+ 'broadcast.vlan-admindsi IN A 10.3.1.255',
+ 'gateway.vlan-admindsi IN A 10.3.1.254',
+ '',
+ '; vlan-middledsi',
+ ';----------------------------------------------------------------------------',
+ 'network.vlan-middledsi IN A 10.3.2.0',
+ 'netmask.vlan-middledsi IN A 255.255.255.0',
+ 'broadcast.vlan-middledsi IN A 10.3.2.255',
+ 'gateway.vlan-middledsi IN A 10.3.2.254',
+ '',
+ '; vlan-pfds-ext',
+ ';----------------------------------------------------------------------------',
+ 'network.vlan-pfds-ext IN A 192.168.1.0',
+ 'netmask.vlan-pfds-ext IN A 255.255.255.0',
+ 'broadcast.vlan-pfds-ext IN A 192.168.1.255',
+ 'gateway.vlan-pfds-ext IN A 192.168.1.254',
+ '',
+ '',
+ '',
+ ';;',
+ ';; Servers',
+ ';;============================================================================',
+ '',
+ '; vip-spawn',
+ ';----------------------------------------------------------------------------',
+ 'cvs IN CNAME vip-spawn.vlan-systeme',
+ 'mf IN CNAME vip-spawn.vlan-systeme',
+ 'mirrors IN CNAME vip-spawn.vlan-systeme',
+ 'nscache IN CNAME vip-spawn.vlan-systeme',
+ 'nsprivate IN CNAME vip-spawn.vlan-systeme',
+ 'vip-deploy IN CNAME vip-spawn.vlan-systeme',
+ 'vip-spawn.vlan-pfds-ext IN A 192.168.1.99',
+ 'vip-spawn.vlan-systeme IN A 10.1.1.254',
+ '',
+ '; cbv4-pfds-filer',
+ ';----------------------------------------------------------------------------',
+ 'cbv4-pfds-filer00.vlan-systeme IN A 10.1.2.0',
+ 'cbv4-pfds-filer01.vlan-systeme IN A 10.1.2.1',
+ '',
+ '; cbv4-spawn',
+ ';----------------------------------------------------------------------------',
+ 'cbv4-spawn IN CNAME cbv4-spawn.vlan-systeme',
+ 'cbv4-spawn.vlan-systeme IN A 10.1.167.0',
+ 'cbv4-spawn.vlan-systeme IN A 10.1.167.1',
+ 'cbv4-spawn00.vlan-admindsi IN A 10.3.1.41',
+ 'cbv4-spawn00.vlan-middledsi IN A 10.3.2.41',
+ 'cbv4-spawn00.vlan-pfds-ext IN A 192.168.1.97',
+ 'cbv4-spawn00.vlan-pfds-int IN A 10.2.167.0',
+ 'cbv4-spawn00.vlan-systeme IN A 10.1.167.0',
+ 'cbv4-spawn01.vlan-admindsi IN A 10.3.1.42',
+ 'cbv4-spawn01.vlan-middledsi IN A 10.3.2.42',
+ 'cbv4-spawn01.vlan-pfds-ext IN A 192.168.1.98',
+ 'cbv4-spawn01.vlan-pfds-int IN A 10.2.167.1',
+ 'cbv4-spawn01.vlan-systeme IN A 10.1.167.1',
+ 'ntp IN CNAME cbv4-spawn.vlan-systeme',
+ 'ntp00 IN CNAME cbv4-spawn00.vlan-systeme',
+ 'ntp01 IN CNAME cbv4-spawn01.vlan-systeme',
+ 'spawn IN CNAME cbv4-spawn.vlan-systeme',
+ 'spawn00 IN CNAME cbv4-spawn00.vlan-systeme',
+ 'spawn01 IN CNAME cbv4-spawn01.vlan-systeme',
+ ''
+];
+
+is_deeply $result, $expected_result
+ => q{Returns the expected result for zone 'private'}
+ or note explain $result;
+
+
+########################################################################
+note('Testing PFTools::Utils::make_zone_file');
+can_ok( 'PFTools::Utils', qw( make_zone_file ) );
+
+throws_ok { make_zone_file(); }
+qr{ \A ERROR: [ ] Invalid [ ] [\$] arguments_ref }xms
+ => q{Dies if no args};
+
+my $test_output_file = q{test.zone};
+$result = make_zone_file(
+ {
+ zone_name => q{private},
+ site_name => q{cbv4-pfds},
+ filename => $test_output_file,
+ global_config => $global_config,
+ }
+);
+ok $result => q{Returns true on success};
+
+$result = PFTools::Utils::__read_file_in_array( $test_output_file, 1 );
+
+is_deeply $result, $expected_result
+ => q{Returns the expected result for host cbv4-rdeploy01 site cbv4'}
+ or note explain $result;
+
+ok unlink($test_output_file)
+ => q{Removed the test-generated zone file};
+
+
+########################################################################
+note('Testing PFTools::Utils::make_resolv_conf_file');
+can_ok( 'PFTools::Utils', qw( make_resolv_conf_file ) );
+
+throws_ok { make_resolv_conf_file(); }
+qr{ \A ERROR: [ ] Invalid [ ] [\$] arguments_ref }xms
+ => q{Dies if no args};
+
+throws_ok { make_resolv_conf_file( {} ); }
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] filename }xms
+ => q{Dies if empty $filename};
+
+throws_ok { make_resolv_conf_file( { filename => {} } ); }
+qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] filename }xms
+ => q{Dies if non-scalar $filename};
+
+throws_ok { make_resolv_conf_file( { filename => q{filename} } ); }
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] hostname }xms
+ => q{Dies if empty $hostname};
+
+throws_ok {
+ make_resolv_conf_file(
+ {
+ filename => q{filename},
+ hostname => {},
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] hostname }xms
+ => q{Dies if non-scalar $hostname};
+
+throws_ok {
+ make_resolv_conf_file(
+ {
+ filename => q{filename},
+ hostname => q{name},
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] global_config}xms
+ => q{Dies if empty $global_config};
+
+throws_ok {
+ make_resolv_conf_file(
+ {
+ filename => q{filename},
+ hostname => q{name},
+ global_config => q{global_config},
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] [\$] global_config [ ]}xms
+ => q{Dies if non-hashref $global_config};
+
+throws_ok {
+ make_resolv_conf_file(
+ {
+ filename => q{filename},
+ hostname => q{name},
+ global_config => {},
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] [\$] global_config [ ] hashref:
+ [ ] no [ ] 'ZONE' [ ] key [ ] found }xms
+ => q{Dies if non-config hashref $global_config};
+
+throws_ok {
+ make_resolv_conf_file(
+ {
+ filename => q{filename},
+ hostname => q{hostname},
+ global_config => $global_config,
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] site_name }xms
+ => q{Dies if empty $site_name};
+
+throws_ok {
+ make_resolv_conf_file(
+ {
+ filename => q{filename},
+ hostname => q{name},
+ global_config => $global_config,
+ site_name => {},
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] site_name }xms
+ => q{Dies if non-scalar $site_name};
+
+$test_output_file = q{test.resolv.conf};
+$result = make_resolv_conf_file(
+ {
+ hostname => q{cbv4-rdeploy01},
+ global_config => $global_config,
+ site_name => q{cbv4},
+ filename => $test_output_file,
+ }
+);
+ok $result => q{Returns true on success};
+
+$result = PFTools::Utils::__read_file_in_array( $test_output_file, 1 );
+$expected_result = [
+ q{#},
+ q{# This file was auto-generated by mk_resolvconf -- DO NOT EDIT!},
+ q{#},
+ q{},
+ q{search private},
+ q{},
+ q{nameserver 10.1.167.0},
+ q{nameserver 10.1.167.1},
+ q{},
+];
+
+is_deeply $result, $expected_result
+ => q{Returns the expected result for host cbv4-rdeploy01 site cbv4'}
+ or note explain $result;
+
+ok unlink($test_output_file)
+ => q{Removed the test-generated resolv.conf file};
+
+
+########################################################################
+note('Testing PFTools::Utils::__build_interfaces');
+can_ok( 'PFTools::Utils', qw( __build_interfaces ) );
+
+throws_ok { PFTools::Utils::__build_interfaces(); }
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] hostname }xms
+ => q{Dies if empty $hostname};
+
+throws_ok { PFTools::Utils::__build_interfaces( { hostname => {} } ); }
+qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] hostname }xms
+ => q{Dies if non-scalar $hostname};
+
+throws_ok {
+ PFTools::Utils::__build_interfaces( { hostname => q{hostname} } );
+}
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] global_config }xms
+ => q{Dies if empty $global_config};
+
+throws_ok {
+ PFTools::Utils::__build_interfaces(
+ {
+ hostname => q{hostname},
+ global_config => q{global_config},
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] [\$] global_config }xms
+ => q{Dies if non-hashref $global_config};
+
+throws_ok {
+ PFTools::Utils::__build_interfaces(
+ {
+ hostname => q{name},
+ global_config => {},
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] [\$] global_config [ ] hashref:
+ [ ] no [ ] 'ZONE' [ ] key [ ] found }xms
+ => q{Dies if non-config hashref $global_config};
+
+throws_ok {
+ PFTools::Utils::__build_interfaces(
+ {
+ hostname => q{hostname},
+ global_config => $global_config,
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] pf_config }xms
+ => q{Dies if empty $pf_config};
+
+throws_ok {
+ PFTools::Utils::__build_interfaces(
+ {
+ hostname => q{hostname},
+ global_config => $global_config,
+ pf_config => q{pf_config},
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] [\$] pf_config }xms
+ => q{Dies if non-hashref $pf_config};
+
+throws_ok {
+ PFTools::Utils::__build_interfaces(
+ {
+ hostname => q{hostname},
+ global_config => $global_config,
+ pf_config => {},
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] [\$] pf_config [ ] hashref:
+ [ ] no [ ] 'vcs' [ ] key [ ] found }xms
+ => q{Dies if non-config hashref $pf_config};
+
+throws_ok {
+ PFTools::Utils::__build_interfaces(
+ {
+ hostname => q{hostname},
+ global_config => $global_config,
+ pf_config => $pf_config,
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] site_name }xms
+ => q{Dies if empty $site_name};
+
+throws_ok {
+ PFTools::Utils::__build_interfaces(
+ {
+ hostname => q{hostname},
+ global_config => $global_config,
+ pf_config => $pf_config,
+ site_name => {},
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] site_name }xms
+ => q{Dies if non-scalar $site_name};
+
+$result = PFTools::Utils::__build_interfaces(
+ {
+ hostname => q{cbv4-spawn01},
+ global_config => $global_config,
+ pf_config => $pf_config,
+ site_name => q{cbv4-pfds},
+ }
+);
+$expected_result = [
+ qq{#},
+ qq{# This file was auto-generated by mk_interfaces -- DO NOT EDIT!},
+ qq{#},
+ qq{},
+ qq{auto lo},
+ qq{iface lo inet loopback},
+ qq{},
+ qq{auto bond0},
+ qq{iface bond0 inet static},
+ qq{\tslaves\t\teth2 eth3},
+ qq{\taddress\t\t192.168.1.98},
+ qq{\tnetmask\t\t255.255.255.0},
+ qq{\tnetwork\t\t192.168.1.0},
+ qq{\tbroadcast\t192.168.1.255},
+ qq{},
+ qq{auto eth0},
+ qq{iface eth0 inet static},
+ qq{\taddress\t\t10.1.167.1},
+ qq{\tnetmask\t\t255.255.0.0},
+ qq{\tnetwork\t\t10.1.0.0},
+ qq{\tbroadcast\t10.1.255.255},
+ qq{},
+ qq{auto eth0.39},
+ qq{iface eth0.39 inet static},
+ qq{\taddress\t\t10.2.167.1},
+ qq{\tnetmask\t\t255.255.0.0},
+ qq{\tnetwork\t\t10.2.0.0},
+ qq{\tbroadcast\t10.2.255.255},
+ qq{\tvlan_raw_device\teth0},
+ qq{\tup\t\t/sbin/ip link set eth0.39 mtu 1496},
+ qq{},
+ qq{auto eth4},
+ qq{iface eth4 inet static},
+ qq{\taddress\t\t10.3.1.42},
+ qq{\tnetmask\t\t255.255.255.0},
+ qq{\tnetwork\t\t10.3.1.0},
+ qq{\tbroadcast\t10.3.1.255},
+ qq{},
+ qq{auto eth5},
+ qq{iface eth5 inet static},
+ qq{\taddress\t\t10.3.2.42},
+ qq{\tnetmask\t\t255.255.255.0},
+ qq{\tnetwork\t\t10.3.2.0},
+ qq{\tbroadcast\t10.3.2.255},
+ qq{},
+];
+
+is_deeply $result, $expected_result
+ => q{Returns the expected result for host cbv4-spawn01 site cbv4-pfds'}
+ or note explain $result;
+
+########################################################################
+note('Testing PFTools::Utils::make_interfaces_file');
+can_ok( 'PFTools::Utils', qw( make_interfaces_file ) );
+
+throws_ok { make_interfaces_file(); }
+qr{ \A ERROR: [ ] Invalid [ ] [\$] arguments_ref }xms
+ => q{Dies if no args};
+
+$test_output_file = q{test.interfaces};
+$result = make_interfaces_file(
+ {
+ hostname => q{cbv4-spawn01},
+ global_config => $global_config,
+ pf_config => $pf_config,
+ site_name => q{cbv4-pfds},
+ filename => $test_output_file,
+ }
+);
+ok $result => q{Returns true on success};
+
+$result = PFTools::Utils::__read_file_in_array( $test_output_file, 1 );
+
+is_deeply $result, $expected_result
+ => q{Returns the expected result for host cbv4-spawn01 site cbv4-pfds'}
+ or note explain $result;
+
+ok unlink($test_output_file)
+ => q{Removed the test-generated interfaces file};
+
+########################################################################
+note('Testing PFTools::Utils::__build_sources_list');
+can_ok( 'PFTools::Utils', qw( __build_sources_list ) );
+
+throws_ok { PFTools::Utils::__build_sources_list(); }
+qr{ \A ERROR: }xms
+ => q{Dies if no $arguments_ref};
+
+throws_ok { PFTools::Utils::__build_sources_list( {} ); }
+qr{ \A ERROR: }xms
+ => q{Dies if empty $arguments_ref};
+
+throws_ok { PFTools::Utils::__build_sources_list( { template => q{} } ); }
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] template }xms
+ => q{Dies if empty $template};
+
+throws_ok { PFTools::Utils::__build_sources_list( { template => {} } ); }
+qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] template }xms
+ => q{Dies if non-scalar $template};
+
+throws_ok {
+ PFTools::Utils::__build_sources_list(
+ { template => q{template}, hostname => q{}, sections_ref => q{} }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] sections_ref }xms
+ => q{Dies if empty $sections_ref};
+
+throws_ok {
+ PFTools::Utils::__build_sources_list(
+ { template => q{template}, hostname => q{}, sections_ref => {} }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] non-array-ref [ ] [\$] sections_ref }xms
+ => q{Dies if non-array-ref $sections_ref};
+
+throws_ok {
+ PFTools::Utils::__build_sources_list(
+ { template => q{template}, hostname => q{}, sections_ref => [] }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] empty-array-ref [ ] [\$] sections_ref }xms
+ => q{Dies if empty-array-ref $sections_ref};
+
+throws_ok {
+ PFTools::Utils::__build_sources_list(
+ { template => q{template}, hostname => q{}, sections_ref => [q{}] }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] or [ ] blank [ ] section [ ] in [ ] array-ref [ ] [\$] sections_ref }xms
+ => q{Dies if empty section in array-ref $sections_ref};
+
+throws_ok {
+ PFTools::Utils::__build_sources_list(
+ { template => q{template}, hostname => q{}, sections_ref => [q{ }] }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] or [ ] blank [ ] section [ ] in [ ] array-ref [ ] [\$] sections_ref }xms
+ => q{Dies if blank section in array-ref $sections_ref};
+
+throws_ok {
+ PFTools::Utils::__build_sources_list(
+ {
+ template => q{template},
+ sections_ref => [q{section}],
+ backports => {}
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] backports }xms
+ => q{Dies if non-scalar $backports};
+
+throws_ok {
+ PFTools::Utils::__build_sources_list(
+ {
+ template => q{template},
+ sections_ref => [q{section}],
+ hostname => q{hostname},
+ global_config => q{foo},
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] [\$] global_config }xms
+ => q{Dies if non-hashref $global_config};
+
+throws_ok {
+ PFTools::Utils::__build_sources_list(
+ {
+ template => q{template},
+ sections_ref => [q{section}],
+ hostname => q{hostname},
+ global_config => {},
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] [\$] global_config [ ] hashref: }xms
+ => q{Dies if non-config hashref $global_config};
+
+throws_ok {
+ PFTools::Utils::__build_sources_list(
+ {
+ template => q{template},
+ sections_ref => [q{section}],
+ global_config => $global_config,
+ hostname => q{},
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] hostname }xms
+ => q{Dies if empty $hostname};
+
+throws_ok {
+ PFTools::Utils::__build_sources_list(
+ {
+ template => q{template},
+ sections_ref => [q{section}],
+ global_config => $global_config,
+ hostname => {},
+ }
+ );
+}
+qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] hostname }xms
+ => q{Dies if non-scalar $hostname};
+
+my $test_sections_ref = [qw(common uncommon)];
+my $args_ref = {
+ hostname => q{cbv4-rdeploy01},
+ site_name => q{cbv4},
+ sections_ref => $test_sections_ref,
+ template => q{templates/sources.list},
+ global_config => $global_config,
+ pf_config => $pf_config,
+};
+$result = PFTools::Utils::__build_sources_list( $args_ref );
+
+my $expected_sources_list = <<'EOT';
+#
+# Generated by mk_sourceslist -- DO NOT EDIT!
+#
+
+deb http://mirrors.private/debian lenny main contrib non-free
+deb http://mirrors.private/debian-custom lenny-custom common uncommon
+deb http://mirrors.private/debian-security lenny/updates main contrib non-free
+
+EOT
+
+$expected_result = [$expected_sources_list];
+
+is_deeply $result, $expected_result
+ => q{Returns the expected content for host cbv4-rdeploy01 site cbv4'}
+ or note explain $result;
+
+$args_ref->{'backports'} = 1;
+$result = PFTools::Utils::__build_sources_list( $args_ref );
+$expected_sources_list .= <<'EOT';
+deb http://mirrors.private/debian-backports lenny-backports main contrib non-free
+
+EOT
+$expected_result = [$expected_sources_list];
+
+is_deeply $result, $expected_result
+ => q{Returns the expected content for host cbv4-rdeploy01 site cbv4 and backports'}
+ or note explain $result;
+
+########################################################################
+note('Testing PFTools::Utils::make_sources_list_file');
+can_ok( 'PFTools::Utils', qw( make_sources_list_file ) );
+
+throws_ok { make_sources_list_file(); }
+qr{ \A ERROR: [ ] Invalid [ ] [\$] arguments_ref }xms
+ => q{Dies if no args};
+
+$expected_result = [ split qr{ \n }xms, $expected_sources_list, -1 ];
+
+$test_output_file = q{test.sources.list};
+$result = make_sources_list_file(
+ {
+ filename => $test_output_file,
+ %{$args_ref},
+ }
+);
+ok $result => q{Returns true on success};
+
+$result = PFTools::Utils::__read_file_in_array( $test_output_file );
+
+is_deeply $result, $expected_result
+ => q{Returns the expected result for host cbv4-rdeploy01 site cbv4'}
+ or note explain $result;
+
+ok unlink($test_output_file)
+ => q{Removed the test-generated interfaces file};
+
+
+########################################################################
+note('Testing PFTools::Utils::make_preseed_file');
+can_ok( 'PFTools::Utils', qw( make_preseed_file ) );
+
+$hostname = q{cbv4-rdeploy01};
+my $site_name = q{cbv4};
+
+$expected_result = [ split qr{ \n }xms, <<'EOT', -1 ];
+#### Contents of the preconfiguration file
+d-i debconf/priority select critical
+
+### Localization
+# Locale sets language and country.
+d-i debian-installer/locale string en_US
+
+# Keyboard selection.
+d-i console-keymaps-at/keymap select fr
+
+### Network configuration
+#d-i netcfg/choose_interface select auto
+#d-i interface select eth0
+d-i interface string eth0
+d-i interface seen false
+d-i netcfg/get_hostname string unassigned-hostname
+d-i netcfg/get_domain string unassigned-domain
+d-i netcfg/no_default_route boolean true
+# Disable that annoying WEP key dialog.
+d-i netcfg/wireless_wep string
+
+### Mirror settings
+d-i mirror/protocol string http
+d-i mirror/country string enter information manually
+d-i mirror/http/hostname string mirrors.private
+d-i mirror/http/directory string /debian
+d-i mirror/http/proxy string
+
+# Suite to install.
+d-i mirror/suite string lenny
+
+### Clock and time zone setup
+d-i clock-setup/utc boolean false
+d-i time/zone string Europe/Paris
+d-i clock-setup/ntp boolean false
+d-i clock-setup/ntp-server string fwadmin.vlan-systeme.private
+
+### Partitioning
+d-i partman-auto/disk string /dev/sda
+d-i partman-auto/method string regular
+d-i partman-auto/purge_lvm_from_device boolean true
+d-i partman-lvm/confirm boolean true
+#d-i partman-auto/choose_recipe \
+# select All files in one partition (recommended for new users)
+d-i partman-auto/expert_recipe string \
+ boot-root :: \
+ 64 72 80 ext3 \
+ $primary{ } $bootable{ } \
+ method{ format } format{ } \
+ use_filesystem{ } filesystem{ ext3 } \
+ mountpoint{ /boot } \
+ . \
+ 500 10000 1000000000 ext3 \
+ $primary{ } \
+ method{ format } format{ } \
+ use_filesystem{ } filesystem{ ext3 } \
+ mountpoint{ / } \
+ . \
+ 64 512 100% linux-swap \
+ method{ swap } format{ } \
+ .
+
+d-i partman/confirm_write_new_label boolean true
+d-i partman/choose_partition \
+ select Finish partitioning and write changes to disk
+d-i partman/confirm boolean true
+
+### Base system installation
+d-i base-installer/kernel/image string linux-image-2.6.26.5-universal-grm2.1.12-grsec
+
+### Account setup
+d-i passwd/root-login boolean false
+d-i passwd/user-fullname string Auto Installer
+d-i passwd/username string auto
+d-i passwd/user-password password auto
+d-i passwd/user-password-again password auto
+#d-i passwd/user-password-crypted password [MD5 hash]
+
+### Apt setup
+d-i apt-setup/non-free boolean true
+d-i apt-setup/contrib boolean true
+d-i apt-setup/services-select string multi-select security
+d-i apt-setup/security_host string mirrors.private/debian-security
+#d-i apt-setup/volatile_host string volatile.debian.org
+# Additional repositories, local[0-9] available
+d-i apt-setup/local0/repository string \
+ http://mirrors.private/debian-custom lenny-custom common
+#d-i apt-setup/local0/key string http://local.server/key
+# By default the installer requires that repositories be authenticated
+# using a known gpg key. This setting can be used to disable that
+# authentication. Warning: Insecure, not recommended.
+d-i debian-installer/allow_unauthenticated string true
+
+### Package selection
+tasksel tasksel/first string multiselect standard
+# Individual additional packages to install
+#d-i pkgsel/include string openssh-server
+#d-i pkgsel/include string pf-tools
+popularity-contest popularity-contest/participate boolean false
+
+### Boot loader installation
+# Grub is the default boot loader (for x86). If you want lilo installed
+# instead, uncomment this:
+#d-i grub-installer/skip boolean true
+# To also skip installing lilo, and install no bootloader, uncomment this
+# too:
+#d-i lilo-installer/skip boolean true
+# This is fairly safe to set, it makes grub install automatically to the MBR
+# if no other operating system is detected on the machine.
+#d-i grub-installer/only_debian boolean true
+# This one makes grub-installer install to the MBR if it also finds some other
+# OS, which is less safe as it might not be able to boot that other OS.
+#d-i grub-installer/with_other_os boolean false
+# Alternatively, if you want to install to a location other than the mbr,
+# uncomment and edit these lines:
+#d-i grub-installer/only_debian boolean false
+#d-i grub-installer/with_other_os boolean false
+#d-i grub-installer/bootdev string (hd0,0)
+# To install grub to multiple disks:
+#d-i grub-installer/bootdev string (hd0,0) (hd1,0) (hd2,0)
+
+### Post-install command before reboot
+d-i preseed/late_command string apt-install linux-image-2.6.26.5-universal-grm2.1.12-grsec ; apt-install nfs-common ; apt-install pf-tools ; in-target wget http://mirrors.private//path/to/some/script -O /tmp//path/to/some/script ; in-target sh /tmp//path/to/some/script
+
+### Finishing up the installation
+# Avoid that last message about the install being complete.
+d-i finish-install/reboot_in_progress note
+
+#### Advanced options
+### Running custom commands during the installation
+# d-i preseeding is inherently not secure. Nothing in the installer checks
+# for attempts at buffer overflows or other exploits of the values of a
+# preconfiguration file like this one. Only use preconfiguration files from
+# trusted locations! To drive that home, and because it's generally useful,
+# here's a way to run any shell command you'd like inside the installer,
+# automatically.
+
+# This first command is run as early as possible, just after
+# preseeding is read.
+#d-i preseed/early_command string anna-install some-udeb
+
+# This command is run just before the install finishes, but when there is
+# still a usable /target directory. You can chroot to /target and use it
+# directly, or use the apt-install and in-target commands to easily install
+# packages and run commands in the target system.
+#d-i preseed/late_command string apt-install zsh; in-target chsh -s /bin/zsh
+#d-i preseed/late_command string apt-install pf-tools; in-target update-config
+
+EOT
+
+$test_output_file = q{/tmp/pf-test/var/www/preseed/preseed_cbv4-rdeploy01};
+
+my $host_ref = get_host_config( $hostname, $global_config, $site_name );
+
+my $preseed_file = make_preseed_file(
+ {
+ hostname => $hostname,
+ host_ref => $host_ref,
+ site_name => $site_name,
+ preseed_template_filename => q{templates/standard-preseed},
+ pf_config => $pf_config,
+ pf_script => q{/path/to/some/script},
+ }
+);
+is $preseed_file, basename($test_output_file)
+ => q{Returns the correct preseed filename};
+
+$result = PFTools::Utils::__read_file_in_array( $test_output_file );
+
+is_deeply $result, $expected_result
+ => q{Returns the expected preseed content for host cbv4-rdeploy01 site cbv4}
+ or note explain $result;
+
+########################################################################
+note('Testing PFTools::Utils::make_pxe_boot_and_preseed_files');
+can_ok( 'PFTools::Utils', qw( make_pxe_boot_and_preseed_files ) );
+
+ok make_pxe_boot_and_preseed_files(
+ {
+ hostname => $hostname,
+ site_name => $site_name,
+ global_config => $global_config,
+ pf_config => $pf_config,
+ pf_script => q{/path/to/some/script},
+ preseed_template_filename => q{templates/standard-preseed},
+ pxe_template_filename => q{templates/standard-installer},
+ }
+ )
+ => q{Returns success};
+
+$result = PFTools::Utils::__read_file_in_array( $test_output_file );
+is_deeply $result, $expected_result
+ => q{Returns the expected preseed result for host cbv4-rdeploy01 site cbv4}
+ or note explain $result;
+
+$expected_result = [ split qr{ \n }xms, <<"EOT", -1 ];
+SERIAL 0 115200 2
+DISPLAY debian-installer/lenny/amd64/boot-screens/myboot.txt
+
+DEFAULT linux
+
+LABEL install
+\tkernel debian-installer/lenny/amd64/linux
+\tappend DEBCONF_PRIORITY=critical vga=normal auto=true initrd=debian-installer/lenny/amd64/initrd.gz interface=eth0 netcfg/no_default_route=true url=http://vip-deploy.vlan-systeme.private/preseed_cbv4-rdeploy01 url/checksum=aa03e0e1599f6da3149aa94027d116a0 -- default
+
+LABEL linux
+\tkernel vmlinuz-2.6.26.5-universal-grm2.1.12
+\tappend vga=normal root=/dev/sda2 -- default
+
+PROMPT 1
+TIMEOUT 100
+
+EOT
+
+$result = PFTools::Utils::__read_file_in_array(
+ q{/tmp/pf-test/distrib/tftpboot/pxelinux.cfg/00-1e-c9-ff-42-0b}
+);
+is_deeply $result, $expected_result
+ => q{Builds the expected pxe_boot_file content for host cbv4-rdeploy01 site cbv4'}
+ or note explain $result;
+
+########################################################################
+note('Testing PFTools::Utils::__fix_etc_hosts');
+can_ok( 'PFTools::Utils', qw( __fix_etc_hosts ) );
+
+throws_ok { PFTools::Utils::__fix_etc_hosts(); }
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] ip_type }xms
+ => q{Dies if empty iptype};
+
+throws_ok { PFTools::Utils::__fix_etc_hosts( { ip_type => {} } ); }
+qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] ip_type }xms
+ => q{Dies if non-scalar iptype};
+
+$args_ref = {
+ ip_type => q{ipv6},
+};
+throws_ok { PFTools::Utils::__fix_etc_hosts($args_ref); }
+qr{ \A ERROR: [ ] __fix_etc_hosts: [ ] ip_type [ ] 'ipv6' [ ] not [ ] implemented [ ] }xms
+ => q{Dies if iptype eq 'ipv6'};
+
+$args_ref = {
+ ip_type => q{ipv4},
+};
+throws_ok { PFTools::Utils::__fix_etc_hosts($args_ref); }
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] hostname }xms
+ => q{Dies if empty hostname};
+
+$args_ref->{'hostname'} = {};
+throws_ok { PFTools::Utils::__fix_etc_hosts($args_ref); }
+qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] hostname }xms
+ => q{Dies if non-scalar hostname};
+
+$args_ref->{'hostname'} = q{cbv4-rdeploy01};
+throws_ok { PFTools::Utils::__fix_etc_hosts($args_ref); }
+qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] global_config }xms
+ => q{Dies if empty global_config};
+
+$args_ref->{'global_config'} = q{global_config};
+throws_ok { PFTools::Utils::__fix_etc_hosts($args_ref); }
+qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] global_config }xms
+ => q{Dies if non-hashref global_config};
+
+$args_ref->{'global_config'} = $global_config;
+throws_ok { PFTools::Utils::__fix_etc_hosts($args_ref); }
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] filename }xms
+ => q{Dies if empty input_filename};
+
+$args_ref->{'input_filename'} = {};
+throws_ok { PFTools::Utils::__fix_etc_hosts($args_ref); }
+qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] filename }xms
+ => q{Dies if non-scalar input_filename};
+
+my $input_filename = q{t/20.files.etc.hosts.input};
+$args_ref->{'input_filename'} = $input_filename;
+
+# site_name is optional
+
+$result = PFTools::Utils::__fix_etc_hosts($args_ref);
+$expected_result = [qq{10.1.167.1\tcbv4-rdeploy01}];
+
+is_deeply $result, $expected_result
+ => q{Correctly fixes /etc/hosts content for host cbv4-rdeploy01 site cbv4'}
+ or note explain $result;
+
+########################################################################
+note('Testing PFTools::Utils::fix_etc_hosts');
+can_ok( 'PFTools::Utils', qw( fix_etc_hosts ) );
+
+my $output_filename = q{t/20.files.etc.hosts.output};
+
+$args_ref = {
+ hostname => q{cbv4-rdeploy01},
+ site_name => q{cbv4},
+ ip_type => q{ipv4},
+ global_config => $global_config,
+ pf_config => $pf_config,
+};
+
+$args_ref->{'input_filename'} = undef;
+$args_ref->{'output_filename'} = undef;
+throws_ok { fix_etc_hosts($args_ref); }
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] input_filename }xms
+ => q{Dies if undefined input_filename};
+
+$args_ref->{'input_filename'} = {};
+throws_ok { fix_etc_hosts($args_ref); }
+qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] input_filename }xms
+ => q{Dies if non-scalar input_filename};
+
+$args_ref->{'input_filename'} = $input_filename;
+
+throws_ok { fix_etc_hosts($args_ref); }
+qr{ \A ERROR: [ ] Invalid [ ] empty [ ] output_filename }xms
+ => q{Dies if empty output_filename};
+
+$args_ref->{'output_filename'} = {};
+throws_ok { fix_etc_hosts($args_ref); }
+qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] output_filename }xms
+ => q{Dies if non-scalar output_filename};
+
+$args_ref->{'output_filename'} = $output_filename;
+
+ok fix_etc_hosts($args_ref)
+ => q{Returns a true value};
+
+$result = PFTools::Utils::__read_file_in_array($output_filename, 1);
+is_deeply $result, $expected_result
+ => q{Correctly fixes /etc/hosts file for host cbv4-rdeploy01 site cbv4'}
+ or note explain $result;
+
+ok unlink $output_filename
+ => q{Removed test output file};
+
+ok copy($input_filename, $output_filename)
+ => q{Copied the test input file for the next test};
+
+$args_ref->{'input_filename'} = $output_filename;
+
+ok fix_etc_hosts($args_ref)
+ => q{Returns a true value};
+
+$result = PFTools::Utils::__read_file_in_array($output_filename, 1);
+is_deeply $result, $expected_result
+ => q{Correctly fixes /etc/hosts file for host cbv4-rdeploy01 site cbv4,
+ even if input and output are the same file'}
+ or note explain $result;
+
+ok unlink $output_filename
+ => q{Removed test output file};
+
diff -r 9e79004112bc -r de2d381543f5 t/20.zone.t
--- a/t/20.zone.t Wed Nov 24 19:39:32 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,814 +0,0 @@
-#!perl
-
-use strict;
-use warnings;
-
-use Cwd;
-use English qw( -no_match_vars ); # Avoids regex performance penalty
-use Sys::Hostname;
-use Test::Exception;
-use Test::More qw( no_plan );
-
-use PFTools::Conf;
-use PFTools::Utils qw( /^./ ); # import @EXPORT and @EXPORT_OK
-
-# Let's go back to our test configuration
-# FIXME: this depends on t/13.conf.t, but it probably should not.
-my $config_file = 't/13.conf.cfg1/etc/pf-tools.1.conf';
-my $pf_config = Init_PF_CONFIG($config_file); # already tested OK in 13.conf.t
-
-my $hostname = hostname;
-my $hash_subst = Init_SUBST( $hostname, undef, $pf_config, 'private' );
-
-my $global_config = Init_GLOBAL_NETCONFIG( q{COMMON:private-network}, $hash_subst );
-
-########################################################################
-note('Testing PFTools::Utils::__make_zone_header');
-can_ok( 'PFTools::Utils', qw( __make_zone_header ) );
-
-throws_ok { PFTools::Utils::__make_zone_header(); }
-qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] zone_name }xms
- => q{Dies if empty $zone_name};
-
-throws_ok { PFTools::Utils::__make_zone_header( {} ); }
-qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] zone_name }xms
- => q{Dies if non-scalar $zone_name};
-
-throws_ok { PFTools::Utils::__make_zone_header( q{name} ); }
-qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] site_name }xms
- => q{Dies if empty $site_name};
-
-throws_ok { PFTools::Utils::__make_zone_header( q{name}, {} ); }
-qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] site_name }xms
- => q{Dies if non-scalar $site_name};
-
-throws_ok { PFTools::Utils::__make_zone_header( q{name}, q{site} ); }
-qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] zone_ref }xms
- => q{Dies if empty $zone_ref};
-
-throws_ok { PFTools::Utils::__make_zone_header( q{name}, q{site}, q{ref} ); }
-qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] [\$] zone_ref }xms
- => q{Dies if non-hashref $zone_ref};
-
-throws_ok { PFTools::Utils::__make_zone_header( q{name}, q{site}, {} ); }
-qr{ \A ERROR: [ ] Invalid [ ] [\$] zone_ref [ ] hashref:
- [ ] no [ ] 'SOA' [ ] key [ ] found }xms
- => q{Dies if non-zone hashref $zone_ref};
-
-
-my $zone_ref = $global_config->{'ZONE'}->{'BY_NAME'}->{'private'};
-$zone_ref->{'SOA'}->{'serial'} = '1289575205';
-my $result = PFTools::Utils::__make_zone_header( 'private', 'cbv4-pfds', $zone_ref );
-my $expected_result = [
- ';;',
- ';; BIND configuration file for zone: private',
- ';; Site: cbv4-pfds',
- ';;',
- ';; Internal management zone',
- ';;============================================================================',
- '',
- '$TTL 1D ; TTL (1 day)',
- '@ IN SOA' . qq{\t} . 'Deploy00.private. dnsmaster at private (',
- ' 1289575205' . qq{\t} . '; Serial',
- ' 6H ; Refresh (6 hours)',
- ' 1H ; Retry (1 hour)',
- ' 7D ; Expire (7 days)',
- ' 1H ; Negative TTL (1 hours)',
- ' )',
- '',
- ' IN NS' . qq{\t} . 'deploy00.vlan-systeme.private.',
- ' IN NS' . qq{\t} . 'deploy01.vlan-systeme.private.',
- '',
- ' IN MX' . qq{\t} . '1 mf.private.',
- ' IN MX' . qq{\t} . '2 mf00.private.',
- ' IN MX' . qq{\t} . '2 mf01.private.',
- '',
- '',
-];
-
-is_deeply $result, $expected_result
- => q{Returns the expected result for zone 'private'}
- or note explain $result;
-
-
-########################################################################
-note('Testing PFTools::Utils::__build_zone');
-can_ok( 'PFTools::Utils', qw( __build_zone ) );
-
-throws_ok { PFTools::Utils::__build_zone(); }
-qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] zone_name }xms
- => q{Dies if empty $zone_name};
-
-throws_ok { PFTools::Utils::__build_zone( { zone_name => {} } ); }
-qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] zone_name }xms
- => q{Dies if non-scalar $zone_name};
-
-throws_ok { PFTools::Utils::__build_zone( { zone_name => q{name} } ); }
-qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] site_name }xms
- => q{Dies if empty $site_name};
-
-throws_ok {
- PFTools::Utils::__build_zone(
- {
- zone_name => q{name},
- site_name => {},
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] site_name }xms
- => q{Dies if non-scalar $site_name};
-
-throws_ok {
- PFTools::Utils::__build_zone(
- {
- zone_name => q{name},
- site_name => q{site},
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] global_config }xms
- => q{Dies if empty $global_config};
-
-throws_ok {
- PFTools::Utils::__build_zone(
- {
- zone_name => q{name},
- site_name => q{site},
- global_config => q{ref},
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] [\$] global_config }xms
- => q{Dies if non-hashref $global_config};
-
-throws_ok {
- PFTools::Utils::__build_zone(
- {
- zone_name => q{name},
- site_name => q{site},
- global_config => {},
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] [\$] global_config [ ] hashref:
- [ ] no [ ] 'ZONE' [ ] key [ ] found }xms
- => q{Dies if non-config hashref $global_config};
-
-throws_ok {
- PFTools::Utils::__build_zone(
- {
- zone_name => q{name},
- site_name => q{site},
- global_config => $global_config,
- }
- );
-}
-qr{ \A ERROR: [ ] Unknown [ ] zone_name: [ ] }xms
- => q{Dies if unknown zone_name};
-
-throws_ok {
- PFTools::Utils::__build_zone(
- {
- zone_name => q{private},
- site_name => q{site},
- global_config => $global_config
- }
- );
-}
-qr{ \A ERROR: [ ] Unknown [ ] site_name: [ ] }xms
- => q{Dies if unknown site_name};
-
-$result = PFTools::Utils::__build_zone(
- {
- zone_name => q{private},
- site_name => q{cbv4-pfds},
- global_config => $global_config,
- }
-);
-$expected_result = [
- ';;',
- ';; BIND configuration file for zone: private',
- ';; Site: cbv4-pfds',
- ';;',
- ';; Internal management zone',
- ';;============================================================================',
- '',
- '$TTL 1D ; TTL (1 day)',
- '@ IN SOA Deploy00.private. dnsmaster at private (',
- ' 1289575205 ; Serial',
- ' 6H ; Refresh (6 hours)',
- ' 1H ; Retry (1 hour)',
- ' 7D ; Expire (7 days)',
- ' 1H ; Negative TTL (1 hours)',
- ' )',
- '',
- ' IN NS deploy00.vlan-systeme.private.',
- ' IN NS deploy01.vlan-systeme.private.',
- '',
- ' IN MX 1 mf.private.',
- ' IN MX 2 mf00.private.',
- ' IN MX 2 mf01.private.',
- '',
- '',
- ';;',
- ';; Networks',
- ';;============================================================================',
- '',
- '; vlan-systeme',
- ';----------------------------------------------------------------------------',
- 'network.vlan-systeme IN A 10.1.0.0',
- 'netmask.vlan-systeme IN A 255.255.0.0',
- 'broadcast.vlan-systeme IN A 10.1.255.255',
- '',
- '; vlan-pfds-int',
- ';----------------------------------------------------------------------------',
- 'network.vlan-pfds-int IN A 10.2.0.0',
- 'netmask.vlan-pfds-int IN A 255.255.0.0',
- 'broadcast.vlan-pfds-int IN A 10.2.255.255',
- '',
- '; vlan-admindsi',
- ';----------------------------------------------------------------------------',
- 'network.vlan-admindsi IN A 10.3.1.0',
- 'netmask.vlan-admindsi IN A 255.255.255.0',
- 'broadcast.vlan-admindsi IN A 10.3.1.255',
- 'gateway.vlan-admindsi IN A 10.3.1.254',
- '',
- '; vlan-middledsi',
- ';----------------------------------------------------------------------------',
- 'network.vlan-middledsi IN A 10.3.2.0',
- 'netmask.vlan-middledsi IN A 255.255.255.0',
- 'broadcast.vlan-middledsi IN A 10.3.2.255',
- 'gateway.vlan-middledsi IN A 10.3.2.254',
- '',
- '; vlan-pfds-ext',
- ';----------------------------------------------------------------------------',
- 'network.vlan-pfds-ext IN A 192.168.1.0',
- 'netmask.vlan-pfds-ext IN A 255.255.255.0',
- 'broadcast.vlan-pfds-ext IN A 192.168.1.255',
- 'gateway.vlan-pfds-ext IN A 192.168.1.254',
- '',
- '',
- '',
- ';;',
- ';; Servers',
- ';;============================================================================',
- '',
- '; vip-spawn',
- ';----------------------------------------------------------------------------',
- 'cvs IN CNAME vip-spawn.vlan-systeme',
- 'mf IN CNAME vip-spawn.vlan-systeme',
- 'mirrors IN CNAME vip-spawn.vlan-systeme',
- 'nscache IN CNAME vip-spawn.vlan-systeme',
- 'nsprivate IN CNAME vip-spawn.vlan-systeme',
- 'vip-deploy IN CNAME vip-spawn.vlan-systeme',
- 'vip-spawn.vlan-pfds-ext IN A 192.168.1.99',
- 'vip-spawn.vlan-systeme IN A 10.1.1.254',
- '',
- '; cbv4-pfds-filer',
- ';----------------------------------------------------------------------------',
- 'cbv4-pfds-filer00.vlan-systeme IN A 10.1.2.0',
- 'cbv4-pfds-filer01.vlan-systeme IN A 10.1.2.1',
- '',
- '; cbv4-spawn',
- ';----------------------------------------------------------------------------',
- 'cbv4-spawn IN CNAME cbv4-spawn.vlan-systeme',
- 'cbv4-spawn.vlan-systeme IN A 10.1.167.0',
- 'cbv4-spawn.vlan-systeme IN A 10.1.167.1',
- 'cbv4-spawn00.vlan-admindsi IN A 10.3.1.41',
- 'cbv4-spawn00.vlan-middledsi IN A 10.3.2.41',
- 'cbv4-spawn00.vlan-pfds-ext IN A 192.168.1.97',
- 'cbv4-spawn00.vlan-pfds-int IN A 10.2.167.0',
- 'cbv4-spawn00.vlan-systeme IN A 10.1.167.0',
- 'cbv4-spawn01.vlan-admindsi IN A 10.3.1.42',
- 'cbv4-spawn01.vlan-middledsi IN A 10.3.2.42',
- 'cbv4-spawn01.vlan-pfds-ext IN A 192.168.1.98',
- 'cbv4-spawn01.vlan-pfds-int IN A 10.2.167.1',
- 'cbv4-spawn01.vlan-systeme IN A 10.1.167.1',
- 'ntp IN CNAME cbv4-spawn.vlan-systeme',
- 'ntp00 IN CNAME cbv4-spawn00.vlan-systeme',
- 'ntp01 IN CNAME cbv4-spawn01.vlan-systeme',
- 'spawn IN CNAME cbv4-spawn.vlan-systeme',
- 'spawn00 IN CNAME cbv4-spawn00.vlan-systeme',
- 'spawn01 IN CNAME cbv4-spawn01.vlan-systeme',
- ''
-];
-
-is_deeply $result, $expected_result
- => q{Returns the expected result for zone 'private'}
- or note explain $result;
-
-
-########################################################################
-note('Testing PFTools::Utils::make_zone_file');
-can_ok( 'PFTools::Utils', qw( make_zone_file ) );
-
-throws_ok { make_zone_file(); }
-qr{ \A ERROR: [ ] Invalid [ ] [\$] arguments_ref }xms
- => q{Dies if no args};
-
-my $test_output_file = q{test.zone};
-$result = make_zone_file(
- {
- zone_name => q{private},
- site_name => q{cbv4-pfds},
- filename => $test_output_file,
- global_config => $global_config,
- }
-);
-ok $result => q{Returns true on success};
-
-$result = PFTools::Utils::__read_file_in_array( $test_output_file, 1 );
-
-is_deeply $result, $expected_result
- => q{Returns the expected result for host cbv4-rdeploy01 site cbv4'}
- or note explain $result;
-
-ok unlink($test_output_file)
- => q{Removed the test-generated zone file};
-
-
-########################################################################
-note('Testing PFTools::Utils::make_resolv_conf_file');
-can_ok( 'PFTools::Utils', qw( make_resolv_conf_file ) );
-
-throws_ok { make_resolv_conf_file(); }
-qr{ \A ERROR: [ ] Invalid [ ] [\$] arguments_ref }xms
- => q{Dies if no args};
-
-throws_ok { make_resolv_conf_file( {} ); }
-qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] filename }xms
- => q{Dies if empty $filename};
-
-throws_ok { make_resolv_conf_file( { filename => {} } ); }
-qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] filename }xms
- => q{Dies if non-scalar $filename};
-
-throws_ok { make_resolv_conf_file( { filename => q{filename} } ); }
-qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] hostname }xms
- => q{Dies if empty $hostname};
-
-throws_ok {
- make_resolv_conf_file(
- {
- filename => q{filename},
- hostname => {},
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] hostname }xms
- => q{Dies if non-scalar $hostname};
-
-throws_ok {
- make_resolv_conf_file(
- {
- filename => q{filename},
- hostname => q{name},
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] global_config}xms
- => q{Dies if empty $global_config};
-
-throws_ok {
- make_resolv_conf_file(
- {
- filename => q{filename},
- hostname => q{name},
- global_config => q{global_config},
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] [\$] global_config [ ]}xms
- => q{Dies if non-hashref $global_config};
-
-throws_ok {
- make_resolv_conf_file(
- {
- filename => q{filename},
- hostname => q{name},
- global_config => {},
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] [\$] global_config [ ] hashref:
- [ ] no [ ] 'ZONE' [ ] key [ ] found }xms
- => q{Dies if non-config hashref $global_config};
-
-throws_ok {
- make_resolv_conf_file(
- {
- filename => q{filename},
- hostname => q{hostname},
- global_config => $global_config,
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] site_name }xms
- => q{Dies if empty $site_name};
-
-throws_ok {
- make_resolv_conf_file(
- {
- filename => q{filename},
- hostname => q{name},
- global_config => $global_config,
- site_name => {},
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] site_name }xms
- => q{Dies if non-scalar $site_name};
-
-$test_output_file = q{test.resolv.conf};
-$result = make_resolv_conf_file(
- {
- hostname => q{cbv4-rdeploy01},
- global_config => $global_config,
- site_name => q{cbv4},
- filename => $test_output_file,
- }
-);
-ok $result => q{Returns true on success};
-
-$result = PFTools::Utils::__read_file_in_array( $test_output_file, 1 );
-$expected_result = [
- q{#},
- q{# This file was auto-generated by mk_resolvconf -- DO NOT EDIT!},
- q{#},
- q{},
- q{search private},
- q{},
- q{nameserver 10.1.167.0},
- q{nameserver 10.1.167.1},
- q{},
-];
-
-is_deeply $result, $expected_result
- => q{Returns the expected result for host cbv4-rdeploy01 site cbv4'}
- or note explain $result;
-
-ok unlink($test_output_file)
- => q{Removed the test-generated resolv.conf file};
-
-
-########################################################################
-note('Testing PFTools::Utils::__build_interfaces');
-can_ok( 'PFTools::Utils', qw( __build_interfaces ) );
-
-throws_ok { PFTools::Utils::__build_interfaces(); }
-qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] hostname }xms
- => q{Dies if empty $hostname};
-
-throws_ok { PFTools::Utils::__build_interfaces( { hostname => {} } ); }
-qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] hostname }xms
- => q{Dies if non-scalar $hostname};
-
-throws_ok {
- PFTools::Utils::__build_interfaces( { hostname => q{hostname} } );
-}
-qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] global_config }xms
- => q{Dies if empty $global_config};
-
-throws_ok {
- PFTools::Utils::__build_interfaces(
- {
- hostname => q{hostname},
- global_config => q{global_config},
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] [\$] global_config }xms
- => q{Dies if non-hashref $global_config};
-
-throws_ok {
- PFTools::Utils::__build_interfaces(
- {
- hostname => q{name},
- global_config => {},
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] [\$] global_config [ ] hashref:
- [ ] no [ ] 'ZONE' [ ] key [ ] found }xms
- => q{Dies if non-config hashref $global_config};
-
-throws_ok {
- PFTools::Utils::__build_interfaces(
- {
- hostname => q{hostname},
- global_config => $global_config,
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] pf_config }xms
- => q{Dies if empty $pf_config};
-
-throws_ok {
- PFTools::Utils::__build_interfaces(
- {
- hostname => q{hostname},
- global_config => $global_config,
- pf_config => q{pf_config},
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] [\$] pf_config }xms
- => q{Dies if non-hashref $pf_config};
-
-throws_ok {
- PFTools::Utils::__build_interfaces(
- {
- hostname => q{hostname},
- global_config => $global_config,
- pf_config => {},
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] [\$] pf_config [ ] hashref:
- [ ] no [ ] 'vcs' [ ] key [ ] found }xms
- => q{Dies if non-config hashref $pf_config};
-
-throws_ok {
- PFTools::Utils::__build_interfaces(
- {
- hostname => q{hostname},
- global_config => $global_config,
- pf_config => $pf_config,
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] site_name }xms
- => q{Dies if empty $site_name};
-
-throws_ok {
- PFTools::Utils::__build_interfaces(
- {
- hostname => q{hostname},
- global_config => $global_config,
- pf_config => $pf_config,
- site_name => {},
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] site_name }xms
- => q{Dies if non-scalar $site_name};
-
-$result = PFTools::Utils::__build_interfaces(
- {
- hostname => q{cbv4-spawn01},
- global_config => $global_config,
- pf_config => $pf_config,
- site_name => q{cbv4-pfds},
- }
-);
-$expected_result = [
- qq{#},
- qq{# This file was auto-generated by mk_interfaces -- DO NOT EDIT!},
- qq{#},
- qq{},
- qq{auto lo},
- qq{iface lo inet loopback},
- qq{},
- qq{auto bond0},
- qq{iface bond0 inet static},
- qq{\tslaves\t\teth2 eth3},
- qq{\taddress\t\t192.168.1.98},
- qq{\tnetmask\t\t255.255.255.0},
- qq{\tnetwork\t\t192.168.1.0},
- qq{\tbroadcast\t192.168.1.255},
- qq{},
- qq{auto eth0},
- qq{iface eth0 inet static},
- qq{\taddress\t\t10.1.167.1},
- qq{\tnetmask\t\t255.255.0.0},
- qq{\tnetwork\t\t10.1.0.0},
- qq{\tbroadcast\t10.1.255.255},
- qq{},
- qq{auto eth0.39},
- qq{iface eth0.39 inet static},
- qq{\taddress\t\t10.2.167.1},
- qq{\tnetmask\t\t255.255.0.0},
- qq{\tnetwork\t\t10.2.0.0},
- qq{\tbroadcast\t10.2.255.255},
- qq{\tvlan_raw_device\teth0},
- qq{\tup\t\t/sbin/ip link set eth0.39 mtu 1496},
- qq{},
- qq{auto eth4},
- qq{iface eth4 inet static},
- qq{\taddress\t\t10.3.1.42},
- qq{\tnetmask\t\t255.255.255.0},
- qq{\tnetwork\t\t10.3.1.0},
- qq{\tbroadcast\t10.3.1.255},
- qq{},
- qq{auto eth5},
- qq{iface eth5 inet static},
- qq{\taddress\t\t10.3.2.42},
- qq{\tnetmask\t\t255.255.255.0},
- qq{\tnetwork\t\t10.3.2.0},
- qq{\tbroadcast\t10.3.2.255},
- qq{},
-];
-
-is_deeply $result, $expected_result
- => q{Returns the expected result for host cbv4-spawn01 site cbv4-pfds'}
- or note explain $result;
-
-########################################################################
-note('Testing PFTools::Utils::make_interfaces_file');
-can_ok( 'PFTools::Utils', qw( make_interfaces_file ) );
-
-throws_ok { make_interfaces_file(); }
-qr{ \A ERROR: [ ] Invalid [ ] [\$] arguments_ref }xms
- => q{Dies if no args};
-
-$test_output_file = q{test.interfaces};
-$result = make_interfaces_file(
- {
- hostname => q{cbv4-spawn01},
- global_config => $global_config,
- pf_config => $pf_config,
- site_name => q{cbv4-pfds},
- filename => $test_output_file,
- }
-);
-ok $result => q{Returns true on success};
-
-$result = PFTools::Utils::__read_file_in_array( $test_output_file, 1 );
-
-is_deeply $result, $expected_result
- => q{Returns the expected result for host cbv4-spawn01 site cbv4-pfds'}
- or note explain $result;
-
-ok unlink($test_output_file)
- => q{Removed the test-generated interfaces file};
-
-########################################################################
-note('Testing PFTools::Utils::__build_sources_list');
-can_ok( 'PFTools::Utils', qw( __build_sources_list ) );
-
-throws_ok { PFTools::Utils::__build_sources_list(); }
-qr{ \A ERROR: }xms
- => q{Dies if no $arguments_ref};
-
-throws_ok { PFTools::Utils::__build_sources_list( {} ); }
-qr{ \A ERROR: }xms
- => q{Dies if empty $arguments_ref};
-
-throws_ok { PFTools::Utils::__build_sources_list( { template => q{} } ); }
-qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] template }xms
- => q{Dies if empty $template};
-
-throws_ok { PFTools::Utils::__build_sources_list( { template => {} } ); }
-qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] template }xms
- => q{Dies if non-scalar $template};
-
-throws_ok {
- PFTools::Utils::__build_sources_list(
- { template => q{template}, hostname => q{}, sections_ref => q{} }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] sections_ref }xms
- => q{Dies if empty $sections_ref};
-
-throws_ok {
- PFTools::Utils::__build_sources_list(
- { template => q{template}, hostname => q{}, sections_ref => {} }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] non-array-ref [ ] [\$] sections_ref }xms
- => q{Dies if non-array-ref $sections_ref};
-
-throws_ok {
- PFTools::Utils::__build_sources_list(
- { template => q{template}, hostname => q{}, sections_ref => [] }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] empty-array-ref [ ] [\$] sections_ref }xms
- => q{Dies if empty-array-ref $sections_ref};
-
-throws_ok {
- PFTools::Utils::__build_sources_list(
- { template => q{template}, hostname => q{}, sections_ref => [q{}] }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] empty [ ] or [ ] blank [ ] section [ ] in [ ] array-ref [ ] [\$] sections_ref }xms
- => q{Dies if empty section in array-ref $sections_ref};
-
-throws_ok {
- PFTools::Utils::__build_sources_list(
- { template => q{template}, hostname => q{}, sections_ref => [q{ }] }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] empty [ ] or [ ] blank [ ] section [ ] in [ ] array-ref [ ] [\$] sections_ref }xms
- => q{Dies if blank section in array-ref $sections_ref};
-
-throws_ok {
- PFTools::Utils::__build_sources_list(
- {
- template => q{template},
- sections_ref => [q{section}],
- backports => {}
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] backports }xms
- => q{Dies if non-scalar $backports};
-
-throws_ok {
- PFTools::Utils::__build_sources_list(
- {
- template => q{template},
- sections_ref => [q{section}],
- hostname => q{hostname},
- global_config => q{foo},
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] [\$] global_config }xms
- => q{Dies if non-hashref $global_config};
-
-throws_ok {
- PFTools::Utils::__build_sources_list(
- {
- template => q{template},
- sections_ref => [q{section}],
- hostname => q{hostname},
- global_config => {},
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] [\$] global_config [ ] hashref: }xms
- => q{Dies if non-config hashref $global_config};
-
-throws_ok {
- PFTools::Utils::__build_sources_list(
- {
- template => q{template},
- sections_ref => [q{section}],
- hostname => q{hostname},
- global_config => $global_config,
- hostname => q{},
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] empty [ ] [\$] hostname }xms
- => q{Dies if empty $hostname};
-
-throws_ok {
- PFTools::Utils::__build_sources_list(
- {
- template => q{template},
- sections_ref => [q{section}],
- hostname => q{hostname},
- global_config => $global_config,
- hostname => {},
- }
- );
-}
-qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] hostname }xms
- => q{Dies if non-scalar $hostname};
-
-my $test_sections_ref = [qw(common uncommon)];
-
-$expected_result = <<'EOT';
-#
-# Generated by mk_sourceslist -- DO NOT EDIT!
-#
-
-deb http://mirrors.private/debian lenny main contrib non-free
-deb http://mirrors.private/debian-custom lenny-custom common uncommon
-deb http://mirrors.private/debian-security lenny/updates main contrib non-free
-
-EOT
-
-########################################################################
-note('Testing PFTools::Utils::make_sources_list_file');
-can_ok( 'PFTools::Utils', qw( make_sources_list_file ) );
-
-throws_ok { make_sources_list_file(); }
-qr{ \A ERROR: [ ] Invalid [ ] [\$] arguments_ref }xms
- => q{Dies if no args};
-
-$test_output_file = q{test.sources.list};
-$result = make_sources_list_file(
- {
- hostname => q{cbv4-rdeploy01},
- site_name => q{cbv4},
- filename => $test_output_file,
- sections_ref => $test_sections_ref,
- template => q{templates/sources.list},
- global_config => $global_config,
- pf_config => $pf_config,
- }
-);
-ok $result => q{Returns true on success};
-
-$result = PFTools::Utils::__read_file_in_scalar( $test_output_file );
-
-is_deeply $result, $expected_result
- => q{Returns the expected result for host cbv4-rdeploy01 site cbv4'}
- or note explain $result;
-
-ok unlink($test_output_file)
- => q{Removed the test-generated interfaces file};
-
diff -r 9e79004112bc -r de2d381543f5 templates/sources.list
--- a/templates/sources.list Wed Nov 24 19:39:32 2010 +0100
+++ b/templates/sources.list Wed Dec 01 08:25:18 2010 +0100
@@ -6,3 +6,7 @@
deb http://mirrors.private/[% mode %]-custom [% distrib %]-custom [% custom_sections %]
deb http://mirrors.private/[% mode %]-security [% distrib %]/updates [% default_sections %]
+[% IF backports -%]
+deb http://mirrors.private/[% mode %]-backports [% distrib %]-backports [% default_sections %]
+
+[% END -%]
diff -r 9e79004112bc -r de2d381543f5 templates/standard-installer
--- a/templates/standard-installer Wed Nov 24 19:39:32 2010 +0100
+++ b/templates/standard-installer Wed Dec 01 08:25:18 2010 +0100
@@ -9,7 +9,8 @@
LABEL linux
kernel [% kernel %]
- append vga=normal root=/dev/sda2 initrd=[% arch %]/[% initrd %] -- [% console %] [% cmdline %]
+ append vga=normal root=/dev/sda2 [% IF initrd %]initrd=[% arch %]/[% initrd %] [% END %]-- [% console %] [% cmdline %]
PROMPT 1
TIMEOUT 100
+
diff -r 9e79004112bc -r de2d381543f5 templates/standard-preseed-squeeze.tpl
--- a/templates/standard-preseed-squeeze.tpl Wed Nov 24 19:39:32 2010 +0100
+++ b/templates/standard-preseed-squeeze.tpl Wed Dec 01 08:25:18 2010 +0100
@@ -215,4 +215,3 @@
# packages and run commands in the target system.
#d-i preseed/late_command string apt-install zsh; in-target chsh -s /bin/zsh
-
diff -r 9e79004112bc -r de2d381543f5 templates/ubuntu-installer
--- a/templates/ubuntu-installer Wed Nov 24 19:39:32 2010 +0100
+++ b/templates/ubuntu-installer Wed Dec 01 08:25:18 2010 +0100
@@ -9,7 +9,8 @@
LABEL linux
kernel [% kernel %]
- append vga=normal root=/dev/sda2 initrd=[% initrd %] -- [% console %] [% cmdline %]
+ append vga=normal root=/dev/sda2 [% IF initrd %]initrd=[% arch %]/[% initrd %] [% END %]-- [% console %] [% cmdline %]
PROMPT 1
TIMEOUT 100
+
diff -r 9e79004112bc -r de2d381543f5 templates/ubuntu-sources.list
--- a/templates/ubuntu-sources.list Wed Nov 24 19:39:32 2010 +0100
+++ b/templates/ubuntu-sources.list Wed Dec 01 08:25:18 2010 +0100
@@ -2,7 +2,10 @@
# Except if you know what you're doing
deb http://mirrors.private/[% mode %] [% distrib %] [% default_sections %]
+deb http://mirrors.private/[% mode %] [% distrib %]-security [% default_sections %]
+deb http://mirrors.private/[% mode %]-custom [% distrib %]-custom [% custom_sections %]
-deb http://mirrors.private/[% mode %] [% distrib %]-security [% default_sections %]
+[% IF backports -%]
+deb http://mirrors.private/[% mode %] [% distrib %]-backports [% default_sections %]
+[% END -%]
-deb http://mirrors.private/[% mode %]-custom [% distrib %]-custom [% custom_sections %]
More information about the pf-tools-commits
mailing list