pf-tools commit: r853 [ccaillet-guest] - in /branches/next-gen: debian/changelog lib/PFTools/Conf.pm lib/PFTools/Conf/ lib/PFTools/Conf/Syntax.pm

parmelan-guest at users.alioth.debian.org parmelan-guest at users.alioth.debian.org
Fri Aug 27 13:30:22 UTC 2010


Author: ccaillet-guest
Date: Fri Aug 27 13:30:20 2010
New Revision: 853

URL: http://svn.debian.org/wsvn/pf-tools/?sc=1&rev=853
Log:
* lib/PFTools/Conf/Syntax.pm
  - extracting syntax checks from PFTools::Conf to PFTools::Conf::Syntax
  which is more flexible for future evolutions

Added:
    branches/next-gen/lib/PFTools/Conf/
    branches/next-gen/lib/PFTools/Conf/Syntax.pm   (with props)
Modified:
    branches/next-gen/debian/changelog
    branches/next-gen/lib/PFTools/Conf.pm

Modified: branches/next-gen/debian/changelog
URL: http://svn.debian.org/wsvn/pf-tools/branches/next-gen/debian/changelog?rev=853&op=diff
==============================================================================
--- branches/next-gen/debian/changelog (original)
+++ branches/next-gen/debian/changelog Fri Aug 27 13:30:20 2010
@@ -18,6 +18,9 @@
     - small fixes on Get_source for order and substitution regex
     - rollback for CONFIG: alias with the 0.33-stable substitution value
     - optims : sorting sections according to the types in Init_GLOBAL_NETCONFIG
+  * lib/PFTools/Conf/Syntax.pm
+    - extracting syntax checks from PFTools::Conf to PFTools::Conf::Syntax
+    which is more flexible for future evolutions
   * lib/PFTools/Utils.pm
     - fix on Ini_TOOLS : if storable file doesn't exist we need to parse
     - cosmetic for building zone in __Mk_zoneheader and Mk_zone_for_site
@@ -60,7 +63,7 @@
   * TODO
     - adding more TODOs :)
 
- -- Christophe Caillet <quadchris at free.fr>  Fri, 27 Aug 2010 11:21:09 +0200
+ -- Christophe Caillet <quadchris at free.fr>  Fri, 27 Aug 2010 15:28:30 +0200
 
 pf-tools (0.99.98-1) unstable; urgency=low
 

Modified: branches/next-gen/lib/PFTools/Conf.pm
URL: http://svn.debian.org/wsvn/pf-tools/branches/next-gen/lib/PFTools/Conf.pm?rev=853&op=diff
==============================================================================
--- branches/next-gen/lib/PFTools/Conf.pm (original)
+++ branches/next-gen/lib/PFTools/Conf.pm Fri Aug 27 13:30:20 2010
@@ -31,8 +31,8 @@
 use PFTools::Parser;
 use PFTools::Logger;
 use PFTools::Structqueries;
+use PFTools::Conf::Syntax;
 use Sys::Hostname;
-# use NetAddr::IP;
 use Fcntl ':mode';
 use Data::Dumper;
 use Storable;
@@ -61,256 +61,7 @@
 #################################
 ### Constants
 
-my $CVS_CHECKOUT    = "/var/lib/cvsguest";
-
-# Syntax definitions
-my $ALLOWED_PARSING_CONTEXT = '(host|network|config|model)';
-my $MODEL_CONFIG_REGEX = qr{
-	\A
-	(				# HOSTTYPE
-	(
-		(			# POPNAME (optional)
-		[a-z]{3}\d{1}
-		)
-		-
-	)?
-	(
-		[a-z0-9-]+[a-z-]	# host type (without the POP name)
-	)
-	)
-	%*			# HOSTDIGITS MARK (optional)
-	_*			# HOSTNODEINDEX MARK (optional)
-	\z
-}xms;
-my $HOST_CONFIG_REGEX = qr{
-	\A
-	(				# HOSTTYPE
-	(
-		(			# POPNAME (optional)
-		[a-z]{3}\d{1}
-		)
-		-
-	)?
-	(
-		[a-z0-9-]+[a-z-]	# host type (without the POP name)
-	)
-	)
-	(\d*)                       # HOSTDIGITS (optional)
-	([a-z]*)                    # HOSTNODEINDEX (optional)
-	\z
-}xms;
-my $HOSTTYPE_CONFIG_REGEX = qr{
-	\A
-	(				# HOSTTYPE
-	(
-	    (			# POPNAME (optional)
-		[a-z]{3}\d{1}
-	    )
-	    -
-	)?
-	(
-	    [a-z0-9-]+[a-z-]	# host type (without the POP name)
-	)
-    )
-    \z
-}xms;
-my $DEPLOY_CONFIG_REGEX = '((?:\w{3}\d-r)?deploy|(\w{3}\d-)?spawn)';
-
-my $DEF_SECTIONS = {};
-$DEF_SECTIONS->{'host'}->{'interface'} = {
-	'MANDATORY_KEYS'	=> [ 'vlan','ipv4','slaves' ],
-	'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',
-	'@route6'			=> 'undefined'
-};
-$DEF_SECTIONS->{'host'}->{'deployment'} = {
-	'MANDATORY_KEYS'	=> [ 'arch','mode','distrib' ],
-	'arch'				=> 'i386|amd64',
-	'mode'				=> '(debian|ubuntu)',
-	'distrib'			=> '[a-z]+',
-	'dhcpvlan'			=> '\w+'
-};
-$DEF_SECTIONS->{'host'}->{'hostgroup'} = {
-	'MANDATORY_KEYS'	=> [ 'number','hostname' ],
-	'site'				=> '(ALL|[\w\-]+(\s*,\s*[\w\-]+)*)',
-	'model'				=> 'undefined',
-	'number'			=> '[\d]+',
-	'order'				=> '[\d]+',
-	'nodes'				=> '[\d]+',
-	'prefix'			=> '(true|false)',
-	'hostname'			=> $MODEL_CONFIG_REGEX,
-	'hosttype'			=> $HOSTTYPE_CONFIG_REGEX
-};
-$DEF_SECTIONS->{'host'}->{'boot'} = {
-	'MANDATORY_KEYS'	=> [ 'kernel' ],
-	'pxefilename'		=> 'undefined',
-	'kernel'			=> 'undefined',
-	'initrd'			=> 'undefined',
-	'cmdline'			=> 'undefined',
-	'console'			=> '(default|ttyS0,115200n8)'
-};
-$DEF_SECTIONS->{'host'}->{'dns'} = {
-	'MANDATORY_KEYS'	=> [ 'resolver' ],
-	'resolver'			=> 'undefined',
-	'shortname'			=> 'undefined',
-	'alias'				=> 'undefined'
-};
-$DEF_SECTIONS->{'network'}->{'zone'} = {
-	'MANDATORY_KEYS'	=> [ 'serial','soa','mail','@ns','@mx' ],
-	'comment'			=> 'undefined',
-	'serial'			=> '(AUTO|.+)',
-	'soa' 				=> '[\w\-\.]+',
-	'mail'				=> 'undefined',
-	'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\-\.]+',
-};
-$DEF_SECTIONS->{'network'}->{'site'} = {
-	'MANDATORY_KEYS'	=> [ 'state', 'zone', 'dhcpvlan', 'console' ],
-	'comment'			=> 'undefined',
-	'location'			=> 'undefined',
-	'room'				=> 'undefined',
-	'confdir'			=> 'undefined',
-	'alias'				=> '\w+',
-	'zone'				=> '\w+',
-	'state'				=> 'ROOT|EDGE',
-	'dhcpvlan'			=> '[\w\-]+',
-	'prefix'			=> '\w+',
-	'console'			=> '(default|ttyS0,115200n8)'
-
-};
-$DEF_SECTIONS->{'network'}->{'network'} = {
-	'MANDATORY_KEYS'	=> [ 'network', 'site' ],
-	'comment'			=> 'undefined',
-	'tag'				=> '\d{1,4}',
-	'network'			=> '([\d]{1,3}\.){3}[\d]{1,3}(\/\d+)?',
-	'network6'			=> 'undefined',
-	'netmask'			=> '(/\d{2}|([\d]{1,3}\.){3}[\d]{1,3})',
-	'netmask6'			=> 'undefined',
-	'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'	=> [ 'site','@host' ],
-	'comment'			=> 'undefined',
-	'@host'				=> '[\w\-\:\/]+'
-};
-$DEF_SECTIONS->{'network'}->{'server'} = {
-	'MANDATORY_KEYS'	=> [ 'site', 'number', ],
-	'comment'			=> 'undefined',
-	'site'				=> '(ALL|[\w\-]+(\s*,\s*[\w\-]+)*)',
-	'number'			=> '\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]'
-};
-$DEF_SECTIONS->{'config'}->{'addfile'} = {
-	'MANDATORY_KEYS'	=> [ 'source' ],
-	'depends'			=> 'undefined',
-	'source'			=> 'undefined',
-	'filter'			=> 'undefined',
-	'owner'				=> '([\d]+|[a-z\d\-]+)',
-	'group'				=> '([\d]+|[a-z\d\-]+)',
-	'mode'				=> '[0-7]?[0-7]{3}',
-	'on_config'			=> 'undefined',
-	'before_change'		=> 'undefined',
-	'on_noaction'		=> 'undefined',
-	'after_change'		=> 'undefined'
-};
-$DEF_SECTIONS->{'config'}->{'createfile'} = {
-	'depends'		=> 'undefined',
-	'source'		=> 'undefined',
-	'filter'		=> 'undefined',
-	'owner'			=> '([\d]+|[a-z\d\-]+)',
-	'group'			=> '([\d]+|[a-z\d\-]+)',
-	'mode'			=> '[0-7]?[0-7]{3}',
-	'on_config'		=> 'undefined',
-	'before_change'	=> 'undefined',
-	'on_noaction'	=> 'undefined',
-	'after_change'	=> 'undefined'
-};
-$DEF_SECTIONS->{'config'}->{'removefile'} = {
-
-};
-$DEF_SECTIONS->{'config'}->{'mkdir'} = {
-	'owner'			=> '([\d]+|[a-z\d\-]+)',
-	'group'			=> '([\d]+|[a-z\d\-]+)',
-	'mode'			=> '0?[0-7]{3}',
-	'on_config'		=> 'undefined',
-	'before_change'	=> 'undefined',
-	'on_noaction'	=> 'undefined',
-	'after_change'	=> 'undefined'
-};
-$DEF_SECTIONS->{'config'}->{'addlink'} = {
-	'MANDATORY_KEYS'	=> [ 'source' ],
-	'source'			=> 'undefined',
-	'on_config'			=> 'undefined',
-	'before_change'		=> 'undefined',
-	'on_noaction'		=> 'undefined',
-	'after_change'		=> 'undefined'
-};
-$DEF_SECTIONS->{'config'}->{'addmount'} = {
-	'MANDATORY_KEYS'	=> [ 'source','fstype','options' ],
-	'depends'			=> 'undefined',
-	'source'			=> 'undefined',
-	'fstype'			=> '(nfs|ext[2-4]|btrfs|cifs)',
-	'options'			=> 'undefined',
-	'mode'				=> '0?[0-7]{3}'
-};
-$DEF_SECTIONS->{'config'}->{'apt-get'} = {
-	'on_config'		=> 'undefined',
-	'before_change'	=> 'undefined',
-	'on_noaction'	=> 'undefined',
-	'after_change'	=> 'undefined'
-};
-$DEF_SECTIONS->{'config'}->{'installpkg'} = $DEF_SECTIONS->{'config'}->{'apt-get'};
-$DEF_SECTIONS->{'config'}->{'dpkg-purge'} = $DEF_SECTIONS->{'config'}->{'apt-get'};
-$DEF_SECTIONS->{'config'}->{'filter-model'} = {
-	'MANDATORY_KEYS'	=> [ 'filter' ],
-	'filter'			=> 'undefined'
-};
-$DEF_SECTIONS->{'config'}->{'group'} = {
-	'on_config'		=> 'undefined',
-	'before_change'	=> 'undefined',
-	'on_noaction'	=> 'undefined',
-	'after_change'	=> 'undefined'
-};
-
 my $DEBUG	= 0 ;
-
-# Global hash for substitution
-# our %SUBST;
-
-my $FAKEHOSTNAME;
-my $FAKEDOMAINNAME;
-our $DEFERREDLOG = 0;
-
-#####################################################################
-### Default value for PF-TOOLS configuration with old configuration
-our $PFTOOLSCONF	= "/etc/pf-tools.conf";
-
-our $PF_STATUS_DIR	= "/var/lib/pftools";
-
-our $CVS_USER		= "cvsguest";
-our $CVS_RSH		= "/usr/local/sbin/cvs_rsh";
-our $CVS_SERVER		= "cvs.private";
-our $CVS_ROOT		= "/var/lib/cvs";
-our $CVS_REPOSITORY	= $CVS_ROOT . "/repository";
-our $CVS_CONFIG		= "config";
-our $CVS_COMMAND	= "";
-our $CVS_BRANCHE	= "";
 
 #############################################################
 ### Default value for configuration with new method
@@ -381,7 +132,7 @@
 		Abort ( $CODE->{'UNDEF_KEY'},
 			"Unable to proceed with configuration file ".$config_file." : no such file or directory" );
 	}
-	elsif ( -r $config_file ) {
+	if ( -r $config_file ) {
 		my ( $dev, $ino, $mode, $nlink, $uid, $gid, @lstat_vars ) = lstat($config_file);
 # 		unless ( $uid == 0 && $gid == 0 && S_IMODE($mode) == 0600 && S_ISREG($mode) ) {
 		unless ( S_IMODE($mode) == 0600 && S_ISREG($mode) ) {
@@ -403,7 +154,7 @@
 	return $PF_CONFIG;
 }
 
-sub Init_SUBST ($;$$) {
+sub Init_SUBST (;$$$) {
 	my ( $host, $pf_config, $domain ) = @_ ;
 	my $host_regex; my $ref_subst = {};
 
@@ -416,20 +167,14 @@
 			"Unable to init substitution hash for hostname ".$host."\n" );
 		return ;
 	}
-	elsif ( defined $host ) {
-		$ref_subst->{'HOSTNAME'}	= ( $host ne "" ) ? $host : hostname ;
-		$ref_subst->{'DOMAINNAME'}	= $domain || $pf_config->{'location'}->{'zone'} || "";
-	}
-	else {
-		chomp ( $ref_subst->{'HOSTNAME'} = `/bin/hostname -s 2>>/dev/null` ) ;
+	$ref_subst->{'HOSTNAME'}	= ( $host ne "" ) ? $host : hostname;
+	$ref_subst->{'DOMAINNAME'}	= $domain || $pf_config->{'location'}->{'zone'} || "";
+	if ( $ref_subst->{'DOMAINNAME'} eq "" ) {
 		if ( -x "/bin/domainname" ) {
 			chomp( $ref_subst->{'DOMAINNAME'} = `/bin/domainname 2>>/dev/null` );
 		}
 		elsif ( -x "/bin/dnsdomainname" ) {
 			chomp( $ref_subst->{'DOMAINNAME'} = `/bin/dnsdomainname 2>>/dev/null` );
-		}
-		else {
-			$ref_subst->{'DOMAINNAME'} = "";
 		}
 	}
 	chomp ( $ref_subst->{'OS_RELEASE'} = `/bin/uname -r` ) ;
@@ -463,7 +208,7 @@
 	if ( ! defined $hash_subst ) {
 		$hash_subst = Init_SUBST ( $hostname, $pf_config ) ;
 	}
-	elsif ( ! defined $pf_config ) {
+	if ( ! defined $pf_config ) {
 		$pf_config = $PF_CONFIG;
 	}
 	my $vcs_work_dir	= $pf_config->{'path'}->{'checkout_dir'};
@@ -489,75 +234,6 @@
 	my $default_conf_file = Get_source ( 'CONFIG:/update-'.$hostvalue, $hostvalue, {}, $pf_config );
 	return $default_conf_file if ( -e $default_conf_file );
 	return undef;
-}
-
-sub __Chk_section_struct ($$$$) {
-	my ( $sect_name, $sect_type, $sect_hash, $context ) = @_;
-	my ( $iface_type, $definition, $int_context, $sect_tmp );
-
-	$int_context = ( $context eq 'model') ? 'host' : $context;
-
-	if ( ! defined $DEF_SECTIONS->{$int_context}->{$sect_type} ) {
-		return ( $CODE->{'INVALID_SECTNAME'}, "Invalid section type ".$sect_type );
-	}
-
-	if ( $context =~ /^(host|model)$/ ) {
-		if ( $sect_name =~ /^\Q$sect_type\E(::((eth|bond)[\d]+(\.TAG[\d]+)?))?$/ ) {
-			$iface_type = $3;
-		}
-		else {
-			return ( $CODE->{'INVALID_SECTNAME'}, "Invalid section name ".$sect_name )
-		}
-		# Cleaning key name by removing .default or .%HOSTNUM% suffix
-		foreach my $key ( keys %{$sect_hash} ) {
-			my $new = $key;
-			$new =~ s/\..*$//;
-			$sect_tmp->{$new}->{'ORIG_NAME'} = $key;
-			$sect_tmp->{$new}->{'VALUE'} = $sect_hash->{$key};
-		}
-	}
-	else {
-		$sect_tmp = $sect_hash;
-	}
-	$definition = $DEF_SECTIONS->{$int_context}->{$sect_type};
-
-	# Checking mandatory keys
-	foreach my $key ( @{$definition->{'MANDATORY_KEYS'}} ) {
-		if ( $sect_type eq 'interface' ) {
-			next if ( $iface_type eq 'eth' && $key eq 'slaves' );
-			next if ( $key =~ /^ipv/ && $context eq 'model' );
-		}
-		return ( $CODE->{'UNDEF_KEY'}, 
-			"Mandatory key ".$key." MUST BE defined on section "
-			.$sect_name." in context ".$context ) if ( ! defined ( $sect_tmp->{$key} ) );
-	}
-	# Checking all keys defined
-	foreach my $key ( keys %{$definition} ) {
-		next if ( $key eq 'MANDATORY_KEYS'
-			|| $key =~ /^__/
-			|| $definition->{$key} eq 'undefined'
-			|| ! defined $sect_tmp->{$key} );
-		my $tab_values = [];
-		my $key_name;
-		if ( $int_context eq 'host' ) {
-			$tab_values = ( $key !~ /^@/ ) ? [ $sect_tmp->{$key}->{'VALUE'} ] : $sect_tmp->{$key}->{'VALUE'};
-			$key_name = $sect_tmp->{$key}->{'ORIG_NAME'};
-		}
-		else {
-			$tab_values = ( $key !~ /^@/ ) ? [ $sect_tmp->{$key} ] : $sect_tmp->{$key};
-			$key_name = $key;
-		}
-		foreach my $value ( @{$tab_values} ) {
-			# Removing trailing space
-			$value =~ s/^\s*//; $value =~ s/\s*$//;
-			if ( "$value" !~ /^$definition->{$key}$/ ) {
-				return ( $CODE->{'INVALID_VALUE'},
-					"Value |".$value."| for key ".$key_name
-					." on section ".$sect_name." doesn't match ".$definition->{$key} );
-			}
-		}
-	}
-	return ( $CODE->{'OK'}, "" ) ;
 }
 
 sub __Merge_conf_includes ($$$) {
@@ -691,7 +367,8 @@
 			$sect_type = $parsed->{$section}->{$select};
 		}
 		if ( $sect_type ne 'include' ) {
-			my ( $code, $msg ) = __Chk_section_struct ( $section, $sect_type, $parsed->{$section}, $context );
+# 			my ( $code, $msg ) = __Chk_section_struct ( $section, $sect_type, $parsed->{$section}, $context );
+			my ( $code, $msg ) = Chk_section_struct ( $section, $sect_type, $parsed->{$section}, $context );
 			if ( $code > 1 ) {
 				Warn ( $code, "Errors occur during parsing model from file ". $file );
 				Abort ( $code, $msg );

Added: branches/next-gen/lib/PFTools/Conf/Syntax.pm
URL: http://svn.debian.org/wsvn/pf-tools/branches/next-gen/lib/PFTools/Conf/Syntax.pm?rev=853&op=file
==============================================================================
--- branches/next-gen/lib/PFTools/Conf/Syntax.pm (added)
+++ branches/next-gen/lib/PFTools/Conf/Syntax.pm Fri Aug 27 13:30:20 2010
@@ -1,0 +1,363 @@
+package PFTools::Conf::Syntax;
+##
+##  $Id$
+##
+##  Copyright (C) 2010 Christophe Caillet <quadchris at free.fr>
+##
+##  This program is free software; you can redistribute it and/or
+##  modify it under the terms of the GNU General Public License
+##  as published by the Free Software Foundation; either version 2
+##  of the License, or (at your option) any later version.
+##
+##  This program is distributed in the hope that it will be useful,
+##  but WITHOUT ANY WARRANTY; without even the implied warranty of
+##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+##  GNU General Public License for more details.
+##
+##  You should have received a copy of the GNU General Public License
+##  along with this program; if not, write to the Free Software
+##  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+##
+
+use strict;
+use warnings;
+
+use Exporter;
+
+our @ISA = ('Exporter');
+
+our @EXPORT = qw(
+	$ALLOWED_PARSING_CONTEXT
+	$HOST_CONFIG_REGEX
+	$HOSTTYPE_CONFIG_REGEX
+	$MODEL_CONFIG_REGEX
+	$DEPLOY_CONFIG_REGEX
+
+	Chk_section_struct
+);
+
+our @EXPORT_OK = qw();
+
+use PFTools::Logger;
+
+# Syntax definitions
+our $ALLOWED_PARSING_CONTEXT = '(host|network|config|model)';
+our $HOSTTYPE_CONFIG_REGEX = qr{
+	\A
+	(				# HOSTTYPE
+	(
+	    (			# POPNAME (optional)
+		[a-z]{3}\d{1}
+	    )
+	    -
+	)?
+	(
+	    [a-z0-9-]+[a-z-]	# host type (without the POP name)
+	)
+    )
+    \z
+}xms;
+our $MODEL_CONFIG_REGEX = qr{
+	\A
+	(				# HOSTTYPE
+	(
+	    (			# POPNAME (optional)
+		[a-z]{3}\d{1}
+	    )
+	    -
+	)?
+	(
+	    [a-z0-9-]+[a-z-]	# host type (without the POP name)
+	)
+    )
+	%*			# HOSTDIGITS MARK (optional)
+	_*			# HOSTNODEINDEX MARK (optional)
+	\z
+}xms;
+our $HOST_CONFIG_REGEX = qr{
+	\A
+	(				# HOSTTYPE
+	(
+	    (			# POPNAME (optional)
+		[a-z]{3}\d{1}
+	    )
+	    -
+	)?
+	(
+	    [a-z0-9-]+[a-z-]	# host type (without the POP name)
+	)
+    )(\d*)                       # HOSTDIGITS (optional)
+	([a-z]*)                    # HOSTNODEINDEX (optional)
+	\z
+}xms;
+our $DEPLOY_CONFIG_REGEX = '((?:\w{3}\d-r)?deploy|(\w{3}\d-)?spawn)';
+
+#####################################
+# Sturcture for the hash below :
+# {
+#	<context> = {
+#		<section> = {
+#			'MANDATORY_KEYS' => ARRAYREF containing mandatory keys
+#			<key1> => <REGEX> or 'undefined', if value is not 'undefined', then
+#					use <REGEX>
+#			...
+#			<keyn> => <REGEX> or 'undefined', if value is not 'undefined', then
+#					use <REGEX>
+#		}
+#	}
+# }
+my $DEF_SECTIONS = {
+	'host'	=> {
+		'interface' => {
+			'MANDATORY_KEYS'	=> [ 'vlan','ipv4','slaves' ],
+			'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',
+			'@route6'			=> 'undefined'
+		},
+		'deployment' => {
+			'MANDATORY_KEYS'	=> [ 'arch','mode','distrib' ],
+			'arch'				=> 'i386|amd64',
+			'mode'				=> '(debian|ubuntu)',
+			'distrib'			=> '[a-z]+',
+			'dhcpvlan'			=> '\w+'
+		},
+		'hostgroup' => {
+			'MANDATORY_KEYS'	=> [ 'number','hostname' ],
+			'site'				=> '(ALL|[\w\-]+(\s*,\s*[\w\-]+)*)',
+			'model'				=> 'undefined',
+			'number'			=> '[\d]+',
+			'order'				=> '[\d]+',
+			'nodes'				=> '[\d]+',
+			'prefix'			=> '(true|false)',
+			'hostname'			=> $MODEL_CONFIG_REGEX,
+			'hosttype'			=> $HOSTTYPE_CONFIG_REGEX
+		},
+		'boot' => {
+			'MANDATORY_KEYS'	=> [ 'kernel' ],
+			'pxefilename'		=> 'undefined',
+			'kernel'			=> 'undefined',
+			'initrd'			=> 'undefined',
+			'cmdline'			=> 'undefined',
+			'console'			=> '(default|ttyS0,115200n8)'
+		},
+		'dns' => {
+			'MANDATORY_KEYS'	=> [ 'resolver' ],
+			'resolver'			=> 'undefined',
+			'shortname'			=> 'undefined',
+			'alias'				=> 'undefined'
+		}
+	},
+	'network' => {
+		'zone' => {
+			'MANDATORY_KEYS'	=> [ 'serial','soa','mail','@ns','@mx' ],
+			'comment'			=> 'undefined',
+			'serial'			=> '(AUTO|.+)',
+			'soa' 				=> '[\w\-\.]+',
+			'mail'				=> 'undefined',
+			'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\-\.]+',
+		},
+		'site' => {
+			'MANDATORY_KEYS'	=> [ 'state', 'zone', 'dhcpvlan', 'console' ],
+			'comment'			=> 'undefined',
+			'location'			=> 'undefined',
+			'room'				=> 'undefined',
+			'confdir'			=> 'undefined',
+			'alias'				=> '\w+',
+			'zone'				=> '\w+',
+			'state'				=> 'ROOT|EDGE',
+			'dhcpvlan'			=> '[\w\-]+',
+			'prefix'			=> '\w+',
+			'console'			=> '(default|ttyS0,115200n8)'
+		},
+		'network' => {
+			'MANDATORY_KEYS'	=> [ 'network', 'site' ],
+			'comment'			=> 'undefined',
+			'tag'				=> '\d{1,4}',
+			'network'			=> '([\d]{1,3}\.){3}[\d]{1,3}(\/\d+)?',
+			'network6'			=> 'undefined',
+			'netmask'			=> '(/\d{2}|([\d]{1,3}\.){3}[\d]{1,3})',
+			'netmask6'			=> 'undefined',
+			'scope'				=> '(private|public)',
+			'site'				=> '(ALL|[\w\-]+(\s*,\s*[\w\-]+)*)',
+			'gateway'			=> '([\d]{1,3})((\.[\d]{1,3}){1,3})?',
+			'gateway6'			=> 'undefined'
+		},
+		'server' => {
+			'MANDATORY_KEYS'	=> [ 'site', 'number', ],
+			'comment'			=> 'undefined',
+			'site'				=> '(ALL|[\w\-]+(\s*,\s*[\w\-]+)*)',
+			'number'			=> '\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]'
+		},
+		'service' => {
+			'MANDATORY_KEYS'	=> [ 'site','@host' ],
+			'comment'			=> 'undefined',
+			'@host'				=> '[\w\-\:\/]+'
+		}
+	},
+	'config' => {
+		'addfile' => {
+			'MANDATORY_KEYS'	=> [ 'source' ],
+			'depends'			=> 'undefined',
+			'source'			=> 'undefined',
+			'filter'			=> 'undefined',
+			'owner'				=> '([\d]+|[a-z\d\-]+)',
+			'group'				=> '([\d]+|[a-z\d\-]+)',
+			'mode'				=> '[0-7]?[0-7]{3}',
+			'on_config'			=> 'undefined',
+			'before_change'		=> 'undefined',
+			'on_noaction'		=> 'undefined',
+			'after_change'		=> 'undefined'
+		},
+		'createfile' => {
+			'depends'		=> 'undefined',
+			'source'		=> 'undefined',
+			'filter'		=> 'undefined',
+			'owner'			=> '([\d]+|[a-z\d\-]+)',
+			'group'			=> '([\d]+|[a-z\d\-]+)',
+			'mode'			=> '[0-7]?[0-7]{3}',
+			'on_config'		=> 'undefined',
+			'before_change'	=> 'undefined',
+			'on_noaction'	=> 'undefined',
+			'after_change'	=> 'undefined'
+		},
+		'removefile' => {
+		},
+		'mkdir' => {
+			'owner'			=> '([\d]+|[a-z\d\-]+)',
+			'group'			=> '([\d]+|[a-z\d\-]+)',
+			'mode'			=> '0?[0-7]{3}',
+			'on_config'		=> 'undefined',
+			'before_change'	=> 'undefined',
+			'on_noaction'	=> 'undefined',
+			'after_change'	=> 'undefined'
+		},
+		'addlink' => {
+			'MANDATORY_KEYS'	=> [ 'source' ],
+			'source'			=> 'undefined',
+			'on_config'			=> 'undefined',
+			'before_change'		=> 'undefined',
+			'on_noaction'		=> 'undefined',
+			'after_change'		=> 'undefined'
+		},
+		'addmount' => {
+			'MANDATORY_KEYS'	=> [ 'source','fstype','options' ],
+			'depends'			=> 'undefined',
+			'source'			=> 'undefined',
+			'fstype'			=> '(nfs|ext[2-4]|btrfs|cifs)',
+			'options'			=> 'undefined',
+			'mode'				=> '0?[0-7]{3}'
+		},
+		'installpkg' => {
+			'version'		=> 'undefined',
+			'on_config'		=> 'undefined',
+			'before_change'	=> 'undefined',
+			'on_noaction'	=> 'undefined',
+			'after_change'	=> 'undefined'
+		},
+		'purgepkg' => {
+			'version'		=> 'undefined',
+			'on_config'		=> 'undefined',
+			'before_change'	=> 'undefined',
+			'on_noaction'	=> 'undefined',
+			'after_change'	=> 'undefined'
+		},
+		'filter-model' => {
+			'MANDATORY_KEYS'	=> [ 'filter' ],
+			'filter'			=> 'undefined'
+		},
+		'group' => {
+			'on_config'		=> 'undefined',
+			'before_change'	=> 'undefined',
+			'on_noaction'	=> 'undefined',
+			'after_change'	=> 'undefined'
+		}
+	}
+};
+$DEF_SECTIONS->{'config'}->{'apt-get'}		= $DEF_SECTIONS->{'config'}->{'installpkg'};
+$DEF_SECTIONS->{'config'}->{'dpkg-purge'}	= $DEF_SECTIONS->{'config'}->{'purgepkg'};
+
+sub Chk_section_struct ($$$$) {
+	my ( $sect_name, $sect_type, $sect_hash, $context ) = @_;
+	my ( $iface_type, $definition, $int_context, $sect_tmp );
+
+	$int_context = ( $context eq 'model') ? 'host' : $context;
+
+	if ( ! defined $DEF_SECTIONS->{$int_context}->{$sect_type} ) {
+		return ( $CODE->{'INVALID_SECTNAME'}, "Invalid section type ".$sect_type );
+	}
+
+	if ( $context =~ /^(host|model)$/ ) {
+		if ( $sect_name =~ /^\Q$sect_type\E(::((eth|bond)[\d]+(\.TAG[\d]+)?))?$/ ) {
+			$iface_type = $3;
+		}
+		else {
+			return ( $CODE->{'INVALID_SECTNAME'}, "Invalid section name ".$sect_name )
+		}
+		# Cleaning key name by removing .default or .%HOSTNUM% suffix
+		foreach my $key ( keys %{$sect_hash} ) {
+			my $new = $key;
+			$new =~ s/\..*$//;
+			$sect_tmp->{$new}->{'ORIG_NAME'} = $key;
+			$sect_tmp->{$new}->{'VALUE'} = $sect_hash->{$key};
+		}
+	}
+	else {
+		$sect_tmp = $sect_hash;
+	}
+	$definition = $DEF_SECTIONS->{$int_context}->{$sect_type};
+
+	# Checking mandatory keys
+	foreach my $key ( @{$definition->{'MANDATORY_KEYS'}} ) {
+		if ( $sect_type eq 'interface' ) {
+			next if ( $iface_type eq 'eth' && $key eq 'slaves' );
+			next if ( $key =~ /^ipv/ && $context eq 'model' );
+		}
+		return ( $CODE->{'UNDEF_KEY'}, 
+			"Mandatory key ".$key." MUST BE defined on section "
+			.$sect_name." in context ".$context ) if ( ! defined ( $sect_tmp->{$key} ) );
+	}
+	# Checking all keys defined
+	foreach my $key ( keys %{$definition} ) {
+		next if ( $key eq 'MANDATORY_KEYS'
+			|| $key =~ /^__/
+			|| $definition->{$key} eq 'undefined'
+			|| ! defined $sect_tmp->{$key} );
+		my $tab_values = [];
+		my $key_name;
+		if ( $int_context eq 'host' ) {
+			$tab_values = ( $key !~ /^@/ ) ? [ $sect_tmp->{$key}->{'VALUE'} ] : $sect_tmp->{$key}->{'VALUE'};
+			$key_name = $sect_tmp->{$key}->{'ORIG_NAME'};
+		}
+		else {
+			$tab_values = ( $key !~ /^@/ ) ? [ $sect_tmp->{$key} ] : $sect_tmp->{$key};
+			$key_name = $key;
+		}
+		foreach my $value ( @{$tab_values} ) {
+			# Removing trailing space
+			$value =~ s/^\s*//; $value =~ s/\s*$//;
+			if ( "$value" !~ /^$definition->{$key}$/ ) {
+				return ( $CODE->{'INVALID_VALUE'},
+					"Value |".$value."| for key ".$key_name
+					." on section ".$sect_name." doesn't match ".$definition->{$key} );
+			}
+		}
+	}
+	return ( $CODE->{'OK'}, "" ) ;
+}
+
+1;

Propchange: branches/next-gen/lib/PFTools/Conf/Syntax.pm
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Fri Aug 27 13:30:20 2010
@@ -1,0 +1,2 @@
+Id
+Revision




More information about the pf-tools-commits mailing list