pf-tools commit: r771 [ccaillet-guest] - in /branches/next-gen: debian/changelog doc/hostfile-syntax doc/networkfile-syntax lib/PFTools/Conf.pm lib/PFTools/Logger.pm lib/PFTools/Net.pm

parmelan-guest at users.alioth.debian.org parmelan-guest at users.alioth.debian.org
Thu Jul 8 15:30:59 UTC 2010


Author: ccaillet-guest
Date: Thu Jul  8 15:30:59 2010
New Revision: 771

URL: http://svn.debian.org/wsvn/pf-tools/?sc=1&rev=771
Log:
Commit partiel

Modified:
    branches/next-gen/debian/changelog
    branches/next-gen/doc/hostfile-syntax
    branches/next-gen/doc/networkfile-syntax
    branches/next-gen/lib/PFTools/Conf.pm
    branches/next-gen/lib/PFTools/Logger.pm
    branches/next-gen/lib/PFTools/Net.pm

Modified: branches/next-gen/debian/changelog
URL: http://svn.debian.org/wsvn/pf-tools/branches/next-gen/debian/changelog?rev=771&op=diff
==============================================================================
--- branches/next-gen/debian/changelog (original)
+++ branches/next-gen/debian/changelog Thu Jul  8 15:30:59 2010
@@ -26,12 +26,19 @@
     - better when deferredlog* functions were really imported into package
   * lib/PFTools/Net.pm
     - using new packages Parser.pm et Logger.pm
+    - adding entries in new global structure build the DNS zone for sites
+    - __Add_zone : adding zone into the new global structure
+    - __Add_site : adding sites into the new global structure
+    - __Add_network : adding network into the new global structure
+    - __Check_host_interfaces : checking interfaces for host definition
+    
   * lib/PFTools/Packages.pm
     - using new packages Parser.pm et Logger.pm
   * lib/PFTools/Update.pm
     - using new packages Parser.pm et Logger.pm
-
- -- Christophe Caillet <quadchris at free.fr>  Mon, 05 Jul 2010 12:45:16 +0200
+  * 
+
+ -- Christophe Caillet <tof at sitadelle.com>  Thu, 08 Jul 2010 17:27:37 +0200
 
 pf-tools (0.34.0-0WIP) unstable; urgency=low
 

Modified: branches/next-gen/doc/hostfile-syntax
URL: http://svn.debian.org/wsvn/pf-tools/branches/next-gen/doc/hostfile-syntax?rev=771&op=diff
==============================================================================
--- branches/next-gen/doc/hostfile-syntax (original)
+++ branches/next-gen/doc/hostfile-syntax Thu Jul  8 15:30:59 2010
@@ -39,15 +39,16 @@
 	! mode[.%HOSTNUM%]		::= debian|ubuntu|kickstart
 	! arch[.%HOSTNUM%]		::= i386|amd64
 	! distrib[.%HOSTNUM%]	::= <DISTRIB_NAME>
-	! dhcp[.%HOSTNUM%]		::= <VLAN_NAME>
+	? dhcpvlan[.%HOSTNUM%]	::= <VLAN_NAME>
 
 [hostgroup]
 	! site		::= <SITE_NAME>
 	? comment	::= <STR>
 	? model		::= <MODEL_NAME> if model is defined then <MODEL_NAME> file is parsed from model directory and hashes are merged with right precedency
 	! number	::= <INT> define here the number of hosts inside this hostgroup
+	? nodes		::= <INT> define here the number of nodes for a designated number into the hostgroup (needed for cluster definition)
 	? order		::= <INT>
-	! hostname	::= <STR>[%%]? if the string <STR> is ended by one or more % then each percent is a digit for indexing hosts
+	! hostname	::= <STR>[%%__]? if the string <STR> is ended by one or more % then each percent is a digit for indexing hosts _ indicates the nodes (clustering)
 	? hosttype	::= <STR> if defined this key is used for %HOSTTYPE% instead of the derived one from hostfile name
 
 [boot]

Modified: branches/next-gen/doc/networkfile-syntax
URL: http://svn.debian.org/wsvn/pf-tools/branches/next-gen/doc/networkfile-syntax?rev=771&op=diff
==============================================================================
--- branches/next-gen/doc/networkfile-syntax (original)
+++ branches/next-gen/doc/networkfile-syntax Thu Jul  8 15:30:59 2010
@@ -11,28 +11,30 @@
 	? ttl		::= <TTL> see bind doc for more infos
 	! @ns		::= <NS_NAME>
 	! @mx		::= <WEIGHT_MX> <MX_NAME>
-	? dhcpvlan	::= <VLAN_NAME>
-	? console	::= (default|ttyS0,115200n8)
 
 [<SITE_NAME>]
 	! type		::= site
 	! state		::= ROOT|EDGE
-	! zone_priv	::= <ZONE_NAME>
-	? zone_pub	::= <ZONE_NAME>
+	! zone		::= <ZONE_NAME>
 	? comment	::= <STR>
 	? location	::= <STR>
 	? room		::= <STR>
+	? alias		::= [a-z]{3}\d
 	? confdir	::= <PATH> define here the directory for configuration access refined by Get_source
+	! dhcpvlan	::= <VLAN_NAME>
+	? console	::= (default|ttyS0,115200n8)
 
 [<NETWORK_NAME>]
 	! type		::= network
 	? comment	::= <STR>
+	! site		::= <STR>
 	? tag		::= <INT> 802.1q tag
 	! network	::= <NETWORK> define here the prefix in IPv4 format
 	? network6	::= <NETWORK> define here the prefix in IPv6 format
 	! netmask	::= <NETMASK> define here the netmask in IPv4 format or in CIDR format e.g. /XX
 	? netmask6	::= <NETMASK> define here the netmask in IPv6 format or in CIDR format e.g. /XX
 	! scope		::= private|public, if private is defined this network will be ONLY added on zone private for site
+	? gateway	::= <IPV4>
 
 [<FILENAME>]
 	! type		::= include

Modified: branches/next-gen/lib/PFTools/Conf.pm
URL: http://svn.debian.org/wsvn/pf-tools/branches/next-gen/lib/PFTools/Conf.pm?rev=771&op=diff
==============================================================================
--- branches/next-gen/lib/PFTools/Conf.pm (original)
+++ branches/next-gen/lib/PFTools/Conf.pm Thu Jul  8 15:30:59 2010
@@ -51,6 +51,7 @@
 	$CVS_BRANCHE
 
 	Init_SUBST
+	__Translate_old2new_host
 	Load_conf
 );
 
@@ -105,6 +106,7 @@
 	'mac'				=> '([0-9a-f]{2}:){5}[0-9a-f]{2}',
 	'vlan'				=> '[a-z][a-z0-9\-]+[a-z0-9]',
 	'ipv4'				=> '([\d]{1,3})((\.[\d]{1,3}){1,3})?',
+	'slaves'			=> 'e(th)?\d+(\s*,\s*e(th)?\d+)+',
 	'ipv6'				=> 'undefined',
 	'iface_opt'			=> 'undefined',
 	'@route'			=> 'undefined',
@@ -115,14 +117,15 @@
 	'arch'				=> 'i386|amd64',
 	'mode'				=> '(debian|ubuntu)(-installer)?',
 	'distrib'			=> '[a-z]+',
-	'dhcp'				=> 'eth\d'
+	'dhcpvlan'			=> '\w+'
 };
 $DEF_SECTIONS->{'host'}->{'hostgroup'} = {
-	'MANDATORY_KEYS'	=> [ 'number','hostname','site' ],
-	'site'				=> '\w+',
+	'MANDATORY_KEYS'	=> [ 'number','hostname' ],
+	'site'				=> '(ALL|[\w\-]+(\s*,\s*[\w\-]+)*)',
 	'model'				=> 'undefined',
 	'number'			=> '[\d]+',
 	'order'				=> '[\d]+',
+	'nodes'				=> '[\d]+',
 	'hostname'			=> $HOST_CONFIG_REGEX,
 	'hosttype'			=> $HOSTTYPE_CONFIG_REGEX
 };
@@ -146,31 +149,39 @@
 	'serial'			=> '(AUTO|.+)',
 	'soa' 				=> '[\w\-\.]+',
 	'mail'				=> 'undefined',
-	'refresh' 			=> '(\d(M|H|D)|\d+)',
-	'retry'				=> '(\d(M|H|D)|\d+)',
-	'expire'			=> '(\d(M|H|D)|\d+)',
-	'negttl'			=> '(\d(M|H|D)|\d+)',
-	'ttl'				=> '(\d(M|H|D)|\d+)',
+	'refresh' 			=> '\d+(M|H|D)?(\s*;.*)?',
+	'retry'				=> '\d+(M|H|D)?(\s*;.*)?',
+	'expire'			=> '\d+(M|H|D)?(\s*;.*)?',
+	'negttl'			=> '\d+(M|H|D)?(\s*;.*)?',
+	'ttl'				=> '\d+(M|H|D)?(\s*;.*)?',
 	'@ns'				=> '[\w\-\.]+',
 	'@mx'				=> '\d+\s+[\w\-\.]+',
-	'dhcpvlan'			=> '[\w\-]+',
-	'console'			=> '(default|ttyS0,115200n8)'
 };
 $DEF_SECTIONS->{'network'}->{'site'} = {
+	'MANDATORY_KEYS'	=> [ 'state', 'zone', 'dhcpvlan' ],
 	'comment'			=> 'undefined',
 	'location'			=> 'undefined',
 	'room'				=> 'undefined',
-	'confdir'			=> 'undefined'
+	'confdir'			=> 'undefined',
+	'alias'				=> '\w+',
+	'zone'				=> '\w+',
+	'state'				=> 'ROOT|EDGE',
+	'dhcpvlan'			=> '[\w\-]+',
+	'console'			=> '(default|ttyS0,115200n8)'
+
 };
 $DEF_SECTIONS->{'network'}->{'network'} = {
-	'MANDATORY_KEYS'	=> [ 'network','netmask' ],
+	'MANDATORY_KEYS'	=> [ 'network','netmask', 'site' ],
 	'comment'			=> 'undefined',
 	'tag'				=> '\d{1,4}',
 	'network'			=> '([\d]{1,3}\.){3}[\d]{1,3}',
 	'network6'			=> 'undefined',
 	'netmask'			=> '(/\d{2}|([\d]{1,3}\.){3}[\d]{1,3})',
 	'netmask6'			=> 'undefined',
-	'scope'				=> '(private|public)'
+	'scope'				=> '(private|public)',
+	'site'				=> '(ALL|[\w\-]+(\s*,\s*[\w\-]+)*)',
+	'gateway'			=> '([\d]{1,3})((\.[\d]{1,3}){1,3})?',
+	'gateway6'			=> 'undefined'
 };
 $DEF_SECTIONS->{'network'}->{'service'} = {
 	'MANDATORY_KEYS'	=> [ '@host' ],
@@ -443,7 +454,7 @@
 			}
 		}
 	}
-	return ( $CODE->{'SECTION_OK'}, "" ) ;
+	return ( $CODE->{'OK'}, "" ) ;
 }
 
 sub __Merge_conf_new ($$$) {
@@ -486,11 +497,11 @@
 				foreach my $tomerge_section ( @{$tmp_merged->{'__sections_order'}} ) {
 					if ( defined $global_parsed->{$tomerge_section} ) {
 						if ( ! defined $tmp_merged->{$tomerge_section}->{'override'} || $tmp_merged->{$tomerge_section}->{'override'} ne 'replace' ) {
-							warn "Section ".$tomerge_section." from file ".$section." already defined ... skipping it\n";
+							Warn ( $CODE->{'WARNING'}, "Section ".$tomerge_section." from file ".$section." already defined ... skipping it\n" );
 							next;
 						}
 						else {
-							warn "Section ".$tomerge_section." already defined but override is set to replace ... overriding it\n";
+							Warn ( $CODE->{'WARNING'}, "Section ".$tomerge_section." already defined but override is set to replace ... overriding it\n" );
 							# Need to evalute if order must be changed
 							# push ( @{$global_parsed->{'__sections_order'}}, $tomerge_section );
 						}
@@ -704,7 +715,7 @@
 
 sub Load_conf ($$;$$) {
 	my ( $file, $hash_subst, $context, $syntax ) = @_;
-	my $sect_type;
+	my ( $sect_type, $iface_name );
 	my $parsed;
 
 	if ( defined $context && $context !~ /^$ALLOWED_PARSING_CONTEXT$/ ) {
@@ -727,8 +738,9 @@
 	foreach my $section ( keys %{$parsed} ) {
 		next if ( $section eq '__sections_order' );
 		if ( $context =~ /^(host|model)$/ ) {
-			$section =~ /^([^:]+)(::.+)?$/;
+			$section =~ /^([^:]+)(::(.+))?$/;
 			$sect_type = $1;
+			$iface_name = $3;
 		}
 		else {
 			my $select = ( $context eq 'config' ) ? 'action' : 'type';
@@ -743,7 +755,7 @@
 			if ( $code > 1 ) {
 				Warn ( $code, "Errors occur during parsing model from file ". $file );
 				Abort ( $code, $msg );
-			}
+			} 
 		}
 	}
 	return $parsed;

Modified: branches/next-gen/lib/PFTools/Logger.pm
URL: http://svn.debian.org/wsvn/pf-tools/branches/next-gen/lib/PFTools/Logger.pm?rev=771&op=diff
==============================================================================
--- branches/next-gen/lib/PFTools/Logger.pm (original)
+++ branches/next-gen/lib/PFTools/Logger.pm Thu Jul  8 15:30:59 2010
@@ -50,8 +50,8 @@
 our $ERR_SYNTAX = 2;
 # Error code and error messages
 our $CODE					= {};
-$CODE->{'WARNING'}			= 0;
-$CODE->{'SECTION_OK'}		= 1;
+$CODE->{'OK'}				= 0;
+$CODE->{'WARNING'}			= 1;
 $CODE->{'OPEN'}				= 2;
 $CODE->{'SYNTAX'}			= 3;
 
@@ -59,6 +59,7 @@
 $CODE->{'INVALID_SECTNAME'}	= 11;
 $CODE->{'INVALID_VALUE'}	= 12;
 $CODE->{'UNDEF_KEY'}		= 20;
+$CODE->{'DUPLICATE_VALUE'}	= 21;
 
 our $DEFERREDLOG	= 0;
 

Modified: branches/next-gen/lib/PFTools/Net.pm
URL: http://svn.debian.org/wsvn/pf-tools/branches/next-gen/lib/PFTools/Net.pm?rev=771&op=diff
==============================================================================
--- branches/next-gen/lib/PFTools/Net.pm (original)
+++ branches/next-gen/lib/PFTools/Net.pm Thu Jul  8 15:30:59 2010
@@ -54,6 +54,11 @@
     
     cmpif
     Host_class
+    
+    __Add_network
+    __Add_site
+    __Add_zone
+    __Check_host_interfaces
 );
 
 our @EXPORT_OK = qw();
@@ -64,8 +69,9 @@
 use PFTools::Conf;
 use PFTools::Logger;
 use PFTools::Parser;
-
-#use Data::Dumper;
+use NetAddr::IP;
+
+use Data::Dumper;
 #$Data::Dumper::Sortkeys = 1;
 #$Data::Dumper::Useperl = 1;
 
@@ -671,6 +677,364 @@
     return @dns;
 }
 
+#########################################################################
+### Rewrite with new syntax
+### Enhancement : creating DNS entries when adding network or hosts
+
+sub __Add_zone ($$$$) {
+	my ( $netfile, $zone_name, $zone2add, $global_config ) = @_;
+	
+	my $zone_part = $global_config->{'ZONE'}->{'BY_NAME'};
+	if ( defined $zone_part->{$zone_name} ) {
+		Warn ( $CODE->{'WARNING'}, "Zone ".$zone_name." from file ".$netfile." already exists : skipping the new definition" );
+		return;
+	}
+	$zone_part->{$zone_name} = {};
+	$zone_part->{$zone_name}->{'SOA'}		= $zone2add;
+	$zone_part->{$zone_name}->{'BY_SITE'}	= {};
+}
+
+sub __Add_site ($$$$) {
+	my ( $netfile, $site_name, $site2add, $global_config ) = @_;
+	
+	my $site_part = $global_config->{'SITE'};
+	if ( defined $site_part->{'BY_NAME'}->{$site_name} ) {
+		Warn ( $CODE->{'WARNING'}, "Site ".$site_name." from file ".$netfile." already exists : skipping the new definition" );
+		return;
+	}
+	if ( ! defined $global_config->{'ZONE'}->{'BY_NAME'}->{$site2add->{'zone'}} ) {
+		Abort ( $CODE->{'INVALID_VALUE'},
+			"Zone ".$site2add->{'zone'}." for site ".$site_name." defined into ".$netfile." doesn't exist in global configuration" );
+	}
+	if ( $site2add->{'state'} eq 'ROOT' ) {
+		if ( $site_part->{'ROOT'} ) {
+			Warn ( $CODE->{'WARNING'}, "Site ".$site_name." from file ".$netfile." cannot be defined as ROOT site : skipping the new definition" );
+		}
+		else {
+			$site_part->{'ROOT'} = $site_name;
+		}
+	} else {
+		push ( @{$site_part->{'EDGE'}}, $site_name );
+	}
+	$site_part->{'BY_NAME'}->{$site_name} = $site2add;
+	$site_part->{'BY_NAME'}->{$site_name}->{'NETWORK'} = {
+		'BY_NAME'	=> {},
+		'BY_ADDR'	=> {},
+		'BY_ADDR6'	=> {},
+		'BY_TAG'	=> {}
+	};
+	$site_part->{'BY_NAME'}->{$site_name}->{'HOST'} = {
+		'BY_NAME'	=> {},
+		'BY_ADDR'	=> {},
+		'BY_ADDR6'	=> {},
+		'BY_MAC'	=> {}
+	};
+	push ( @{$site_part->{'__site_list'}}, $site_name );
+	$global_config->{'ZONE'}->{'BY_NAME'}->{$site2add->{'zone'}}->{'BY_SITE'}->{$site_name} = {};
+	$global_config->{'ZONE'}->{'BY_SITE'}->{$site_name} = $site2add->{'zone'};
+}
+
+sub __Get_site_list ($$) {
+	my ( $sect_hash, $global_config ) = @_;
+	my $ref_list;
+	
+	if ( $sect_hash->{'site'} eq 'ALL' ) {
+		return $global_config->{'__site_list'};
+	}
+	else {
+		@{$ref_list} = split ( /\s*\,\s*/, $sect_hash->{'site'} );
+		return $ref_list;
+	}
+}
+
+sub __Get_netblock_from_vlan ($$) {
+	my ( $type, $net_hash ) = @_;
+	
+	my $suffix = ( $type eq 'ipv6' )
+		? '6'
+		: '';
+	my $block = ( $net_hash->{'netmask'.$suffix} =~/^\// )
+		? new NetAddr::IP ( $net_hash->{'network'.$suffix}.$net_hash->{'netmask'.$suffix} )
+		: new NetAddr::IP ( $net_hash->{'network'.$suffix}, $net_hash->{'netmask'.$suffix} );
+	return $block;
+}
+
+sub __Add_network ($$$$) {
+	my ( $netfile, $net_name, $net2add, $global_config ) = @_;
+	my ( $block, $block6, $site_list, $net_part );
+
+	my $site_part	= $global_config->{'SITE'};
+	$site_list = __Get_site_list ( $net2add, $global_config );
+	# Check TAG
+	if ( $net2add->{'tag'} && ( $net2add->{'tag'} < 0 || $net2add->{'tag'} > 4095 ) ) {
+		Abort ( $CODE->{'INVALID_VALUE'}, 
+		"Invalid 802.1q tag ".$net2add->{'tag'}." for file ".$netfile." into ".$net_name." definition" );
+	}
+	# Check IPv4 values
+	$block = __Get_netblock_from_vlan ( 'ipv4', $net2add );
+	if ( ! defined $block ) {
+		Abort ( $CODE->{'INVALID_VALUE'}, 
+			"Invalid IPv4 definition for network ".$net2add->{'network'}
+			." and/or ".$net2add->{'netmask'}." from file ".$netfile." into ".$net_name." definition" );
+	}
+	if ( $net2add->{'gateway'} ) {
+		my $ip_gw = new NetAddr::IP ( $block->prefix().$net2add->{'gateway'} );
+		if ( ! defined $ip_gw ) {
+			Abort ( $CODE->{'UNDEF_KEY'},
+				"Unable to check IPv4 gateway defined from ".$netfile." into ".$net_name." definition" );
+		}
+		elsif ( ! $block->contains ( $ip_gw ) ) {
+			Abort (
+				"Gateway ".$ip_gw." is out of range from network ".$net2add->{'network'}
+				." from file ".$netfile." into ".$net_name." definition" );
+		}
+	}
+	# Check IPv6 values if defined
+	if ( $net2add->{'network6'} ) {
+		$block6 = __Get_netblock_from_network ( 'ipv6', $net2add );
+		if ( ! defined $block6 ) {
+			Abort ( $CODE->{'INVALID_VALUE'},
+				"Invalid IPv6 definition for network ".$net2add->{'network6'}
+				." and/or ".$net2add->{'netmask6'}." from file ".$netfile." into ".$net_name." definition" );
+		}
+		if ( $net2add->{'gateway'} ) {
+			my $ip_gw = new NetAddr::IP ( $block->prefix().$net2add->{'gateway'} );
+			if ( ! defined $ip_gw ) {
+				Abort ( $CODE->{'UNDEF_KEY'},
+					"Unable to check IPv4 gateway defined from ".$netfile." into ".$net_name." definition" );
+			}
+			elsif ( ! $block->contains ( $ip_gw ) ) {
+				Abort (
+					"Gateway ".$ip_gw." is out of range from network ".$net2add->{'network'}
+					." from file ".$netfile." into ".$net_name." definition" );
+			}
+		}
+	}
+
+	# Already defined in sites for which it will be : by name ? by tag ? by subnet
+	foreach my $site ( @{$site_list} ) {
+		$net_part = $site_part->{'BY_NAME'}->{$site}->{'NETWORK'};
+		if ( $net_part->{'BY_NAME'}->{$net_name} ) {
+			Warn ( $CODE->{'DUPLICATE_VALUE'},
+					"Network ".$net_name." from file ".$netfile." is already defined for site ".$site." : skipping declaration" );
+		}
+		else {
+			if ( $net2add->{'tag'} &&  $net_part->{'BY_TAG'}->{$net2add->{'tag'}} ) {
+				Abort ( $CODE->{'DUPLICATE_VALUE'},
+					"802.1q tag ".$net2add->{'tag'}." for network ".$net_name." is already in use on site "
+					.$site." for network ".$net_part->{'BY_TAG'}->{$net2add->{'tag'}} );
+			}
+			elsif ( $net_part->{'BY_ADDR'}->{$block} && $net_part->{'BY_ADDR'}->{$block} ne $net_name ) {
+				Abort ( $CODE->{'DUPLICATE_VALUE'},
+					"IPv4 subnet ".$block." for network ".$net_name." from file ".$netfile
+					." is already in use in site ".$site." for network ".$net_part->{'BY_ADDR'}->{$block} );
+			}
+			elsif ( $block6 && $net_part->{'BY_ADDR6'}->{$block6} && $net_part->{'BY_ADDR6'}->{$block6} ne $net_name ) {
+				Abort ( $CODE->{'DUPLICATE_VALUE'},
+					"IPv6 subnet ".$block6." for network ".$net_name." from file ".$netfile
+					." is already in use in site ".$site." for network ".$net_part->{'BY_ADDR6'}->{$block} );
+			}
+		}
+	}
+
+	foreach my $site ( @{$site_list} ) {
+		# Adding network to the network part of the global structure
+		$net_part = $site_part->{'BY_NAME'}->{$site}->{'NETWORK'};
+		$net_part->{'BY_NAME'}->{$net_name}			= $net2add;
+		$net_part->{'BY_ADDR'}->{$block}			= $net_name;
+		$net_part->{'BY_ADDR6'}->{$block6}			= $net_name if ( $block6 );
+		$net_part->{'BY_TAG'}->{$net2add->{'tag'}}	= $net_name if ( $net2add->{'tag'} );
+		# Adding entries for network, netmask, broadcast etc. into the DNS zone
+		my $zone = $global_config->{'ZONE'}->{'BY_SITE'}->{$site};
+		my $zone_part = $global_config->{'ZONE'}->{'BY_NAME'}->{$zone};
+		$zone_part->{'__network_order'} = {} if ( ! defined $zone_part->{'__network_order'} );
+		push ( @{$zone_part->{'__network_order'}->{$site}}, $net_name );
+		# Adding IPv4 entries
+		$zone_part->{'BY_SITE'}->{$site}->{'network.'.$net_name} = "A\t".$net2add->{'network'};
+		$zone_part->{'BY_SITE'}->{$site}->{'netmask.'.$net_name} = ( $net2add->{'netmask'} =~ /^\// )
+			? "A\t".$block->mask()
+			: "A\t".$net2add->{'netmask'};
+		my $broad	= $block->broadcast(); $broad =~ s/\/.*$//;
+		$zone_part->{'BY_SITE'}->{$site}->{'broadcast.'.$net_name} = "A\t".$broad;
+		if ( $block6 ) {
+			$zone_part->{'BY_SITE'}->{$site}->{'network6.'.$net_name} = "A\t".$net2add->{'network6'};
+			$zone_part->{'BY_SITE'}->{$site}->{'netmask6.'.$net_name} = ( $net2add->{'netmask6'} =~ /^\// )
+				? "A\t".$block6->mask()
+				: "A\t".$net2add->{'netmask6'};
+			my $broad6 = $block6->broadcast(); $broad6 =~ s/\/.*$//;
+			$zone_part->{'BY_SITE'}->{$site}->{'broadcast6'.$net_name} = "A\t".$broad6;
+		}
+	}
+}
+
+sub __Get_host_indexes ($$) {
+	my ( $ref_host, $host_name ) = @_;
+	my ( $node_last, $num_last, $digits, $nodes );
+	
+	
+	$node_last	= ( $ref_host->{'nodes'} )
+		? ( $ref_host->{'nodes'} -1 )
+		: 0;
+	$num_last				= $ref_host->{'number'} - 1;
+	$ref_host->{'hostname'}	=~ /(%*)(_*)$/;
+	$digits					= length ($1) || 0;
+	$nodes					= length ($2) || 0;
+	# Checking nodes
+	if ( $node_last && ! $nodes ) {
+		Abort ( $CODE->{'INVALID_VALUE'},
+			"Unable to affect all ".$node_last." nodes : no _ defined in key hostname" );
+	}
+	elsif ( $node_last && ceil ( log($node_last) / log(26) ) > $nodes ) {
+		Warn ( $CODE->{'INVALID_VALUE'},
+			"Not enough places for indexing nodes definition for host ".$ref_host->{'hostgroup'}->{'hostname'} );
+	}
+	# Checking hostnum
+	if ( $num_last && ! $digits ) {
+		Abort ( $CODE->{'INVALID_VALUE'},
+			"Unable to affect all host number(s) : no % defined in key hostname" );
+	}
+	elsif ( $num_last && $num_last > 10**$digits ) {
+		Warn ( $CODE->{'INVALID_VALUE'},
+			"Not enough places for indexing host number(s) according to hostname ".$host_name );
+	}
+	return ( $num_last, $node_last );
+}
+
+sub __Check_host_interfaces ($$$$$) {
+	my ( $ref_host, $host_name, $host_num, $site, $network_site ) = @_;
+	my ( @if_list, $vlan );
+	
+	foreach my $section ( keys %{$ref_host} ) {
+		next if ( $section !~ /^interface/ );
+		$section =~ /^interface::(((eth|bond)[\d]+)(\.(TAG[\d]+))?)$/;
+		push ( @if_list, $2 );
+	}
+	foreach my $iface ( @if_list ) {
+		my $iface_section = 'interface::'.$iface;
+		$iface =~ /^(eth|bond[\d]+)(\.(TAG[\d]+))?$/;
+		my ( $ifraw, $iftag ) = ( $1, $3 );
+		my $vlan = $ref_host->{$iface_section}->{'vlan'};
+		# Check tag
+		if ( $iftag && $iftag =~ /^\d+$/ ) {
+			Abort ( $CODE->{'INVALID_VALUE'},
+				"Tag ".$iftag." defined on section name ".$iface_section." differs from "
+				.$ref_host->{'vlan'}." network definition" );
+		}
+		if ( $iface =~ /^bond/ && ! $iftag ) {
+			# Check if slaves not in use
+			my @slaves = ( $ref_host->{$iface_section}->{'slaves.'.$host_num} )
+				? split ( /\s*,\s*/, $ref_host->{$iface_section}->{'slaves.'.$host_num} )
+				: split ( /\s*,\s*/, $ref_host->{$iface_section}->{'slaves'} );
+			foreach my $if ( @slaves ) {
+				Abort ( $CODE->{'INVALID_VALUE'},
+					"Interface ".$if." cannot be enslaved by ".$iface." : already in use for "
+					.$host_name ) if ( grep ( /$if/, @if_list ) );
+			}
+		}
+		# Check vlan
+		if ( ! defined $network_site->{'BY_NAME'}->{$vlan} ) {
+			Abort ( $CODE->{'INVALID_VALUE'},
+				"Unknown vlan ".$vlan." on site ".$site." for interface ".$iface.
+				" defined on host ".$host_name );
+		}
+		# Check address and route values
+		foreach my $ip_type ( 'ipv4', 'ipv6' ) {
+			next if ( ! $ref_host->{$iface_section}->{$ip_type} );
+			my $netblock = __Get_netblock_from_vlan ( $ip_type, $network_site->{'BY_NAME'}->{$vlan} );
+			if ( ! defined $netblock ) {
+				Abort ( $CODE->{'INVALID_VALUE'},
+					"Unable to retrieve network block of type ".$ip_type." for vlan ".$vlan
+					." on site ".$site." for host ".$host_name );
+			}
+			my $prefix = $netblock->prefix();
+			my $realip = ( $ref_host->{$iface_section}->{$ip_type.'.'.$host_num} )
+				? new NetAddr::IP ( $prefix.$ref_host->{$iface_section}->{$ip_type.'.'.$host_num} )
+				: new NetAddr::IP ( $prefix.$ref_host->{$iface_section}->{$ip_type} );
+			if ( ! defined $realip ) {
+				Abort ( $CODE->{'INVALID_VALUE'},
+					"Unable to check ".$ip_type." realip for vlan ".$vlan
+					." for host ".$host_name." on site ".$site );
+			}
+			elsif ( ! $netblock->contains ( $realip ) ) {
+				Abort ( $CODE->{'INVALID_VALUE'},
+					"IP of type ".$ip_type." on vlan ".$vlan." is out of "
+					.$netblock." for host ".$host_name." on site ".$site );
+			}
+			my $route_key	= ( $ip_type eq 'ipv6' ) ? '@route6' : '@route';
+			my $gw_key		= ( $ip_type eq 'ipv6' ) ? 'gateway6' : 'gateway';
+			if ( defined $ref_host->{$iface_section}->{$route_key} ) {
+				foreach my $route ( @{$ref_host->{$iface_section}->{$route_key}} ) {
+					$route =~ /^(\S+)\s*(via\s*(\S+))?$/;
+					my ( $dest, $via ) = ( $1, $3 );
+					if ( $dest ne 'default' ) {
+						print "$dest, $via|\n";
+						if ( $dest =~ /[g-zG-Z]+/ && ! defined $network_site->{'BY_NAME'}->{$dest} ) {
+							Abort ( $CODE->{'INVALID_VALUE'},
+								"Unknown network ".$dest." on site ".$site );
+						}
+						else {
+							my $ip_dest = new NetAddr::IP ( $dest );
+							if ( ! defined $ip_dest ) {
+								Abort ( $CODE->{'INVALID_VALUE'},
+									"Unable to check dest IP ".$dest." of type ".$ip_type." on \@route key for interface ".$iface
+									." for host ".$host_name." on site ".$site );
+							}
+						}
+					}
+					if ( $via ) {
+						if ( $via eq 'GATEWAY' && ! defined  $network_site->{'BY_NAME'}->{$vlan}->{$gw_key} ) {
+							Abort ( $CODE->{'INVALID_VALUE'},
+								"Unable to define default route by vlan ".$vlan." : no gateway defined on this one" );
+						}
+						elsif ( $via =~ /[g-zG-Z]+/ ) {
+							# Potentially not parsed host ... skipping this case for now
+						}
+						else {
+							my $ip_via = new NetAddr::IP ( $via );
+							if ( ! defined $ip_via ) {
+								Abort ( $CODE->{'INVALID_VALUE'},
+									"Unable to check IP ".$via." of type ".$ip_type." as gateway for interface ".$iface
+									." for host ".$host_name." on site ".$site );
+							}
+							elsif ( ! $netblock->contains ( $ip_via ) ) {
+								Abort ( $CODE->{'INVALID_VALUE'},
+									"IP ".$ip_via." of type ".$ip_type." for gateway on interface ".$iface
+									." is out of ".$netblock." for host ".$host_name." on site ".$site );
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+}
+
+sub __Add_host ($$$) {
+	my ( $hostfile, $host2add, $global_config ) = @_;
+
+	my $host_name = $host2add->{'hostgroup'}->{'hostname'};
+	my $site_list = __Get_site_list ( $host2add, $global_config );
+	foreach my $site ( @{$site_list} ) {
+		my $site_part	= $global_config->{'SITE'}->{'BY_NAME'}->{$site};
+		my $host_part	= $site_part->{'HOST'};
+		my ( $host_last, $node_last ) = __Get_host_indexes ( $host2add, $host_name );
+		foreach my $hostnum ( 0 .. $host_last ) {
+			foreach my $hostnode (  0 .. $node_last ) {
+				my $dhcpvlan = ( $host2add->{'deployment'}->{'dhcpvlan'} )
+					? $host2add->{'deployment'}->{'dhcpvlan'}
+					: $site_part->{'dhcpvlan'};
+				if ( ! defined $site_part->{'NETWORK'}->{'BY_NAME'}->{$dhcpvlan} ) {
+					Abort ( $CODE->{'INVALID_VALUE'},
+						"Vlan ".$dhcpvlan." defined for ".$host_name." from file "
+						.$hostfile." doesn't exist on site ".$site );
+				}
+			}
+		}
+		$host_part->{'BY_NAME'}->{$host_name} = $host2add;
+	}
+	# Add others sections
+}
+
 #
 #	HASHREF Init_lib_net (STRING $fic_conf)
 #
@@ -695,7 +1059,7 @@
     $Z->{'ALIAS'} = {};
 
     # Chargement du fichier de configuration reseau
-    $C = Load_conf( $fic_conf, 'subst', 'network', $syntax );
+    $C = Load_conf( $fic_conf, \%SUBST, 'network', $syntax );
 
     # Calcul de la conf reseau et de la zone
     foreach $s ( keys %$C ) {




More information about the pf-tools-commits mailing list