pf-tools/pf-tools: 41 new changesets

parmelan-guest at users.alioth.debian.org parmelan-guest at users.alioth.debian.org
Tue Apr 1 15:58:01 UTC 2014


details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/c19b61de4b1e
changeset: 1206:c19b61de4b1e
user:      shad
date:      Fri Feb 07 14:43:39 2014 +0100
description:
fix pod, tidy, critic, typo

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/54b46d1821c2
changeset: 1207:54b46d1821c2
user:      shad
date:      Fri Feb 07 18:19:14 2014 +0100
description:
pod tidy et critic

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/b6f4c476c3af
changeset: 1208:b6f4c476c3af
user:      shad
date:      Mon Feb 10 18:16:34 2014 +0100
description:
Lintian et chemins

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/10c482a40c39
changeset: 1209:10c482a40c39
user:      shad
date:      Mon Feb 10 18:17:24 2014 +0100
description:
tidy, critic et typo

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/05a1bc6e3244
changeset: 1210:05a1bc6e3244
user:      shad
date:      Thu Feb 13 18:17:16 2014 +0100
description:
dependance

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/96e6b4d20254
changeset: 1211:96e6b4d20254
user:      shad
date:      Thu Feb 13 18:19:17 2014 +0100
description:
tidy, critic, erreur passé en warn en mode verbeux uniquement

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/ccbd331dae8a
changeset: 1212:ccbd331dae8a
user:      shad
date:      Thu Feb 13 18:19:57 2014 +0100
description:
tidy critic, fix warning

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/8926185f4338
changeset: 1213:8926185f4338
user:      shad
date:      Fri Feb 14 14:14:04 2014 +0100
description:
un peu de couleur mais pas trop

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/c2bbd6bc2df7
changeset: 1214:c2bbd6bc2df7
user:      shad
date:      Wed Feb 19 14:09:15 2014 +0100
description:
tidy, critic, fix test, add test for chown/chmod

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/72eb64393e43
changeset: 1215:72eb64393e43
user:      shad
date:      Wed Feb 19 15:32:48 2014 +0100
description:
sans les quotes dhcp de démarre pas

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/48293f783dd5
changeset: 1216:48293f783dd5
user:      shad
date:      Wed Feb 19 18:12:09 2014 +0100
description:
fix et test en plus sur le bind

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/93e23dbdcf03
changeset: 1217:93e23dbdcf03
user:      shad
date:      Thu Feb 20 11:43:17 2014 +0100
description:
fix sur les escapes

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/a77e8c806abf
changeset: 1218:a77e8c806abf
user:      shad
date:      Thu Feb 20 16:34:13 2014 +0100
description:
tidy, critic, sort des sections

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/46406cdca342
changeset: 1219:46406cdca342
user:      shad
date:      Fri Feb 21 18:05:09 2014 +0100
description:
critic et doc

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/ef8a693905c7
changeset: 1220:ef8a693905c7
user:      shad
date:      Mon Feb 24 19:24:33 2014 +0100
description:
test en anglais et message sur le faut faire un sudo

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/3f757485cf91
changeset: 1221:3f757485cf91
user:      shad
date:      Mon Feb 24 19:27:15 2014 +0100
description:
plus d'homogeneité entre les scripts, mk_dhcp et mk_sitezone prennent un template par defaut pour pas avoir a le mettre dans la conf pf-tools

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/52195e46f971
changeset: 1222:52195e46f971
user:      shad
date:      Tue Feb 25 10:39:38 2014 +0100
description:
mise a jour test et doc

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/cc2c5f20caf8
changeset: 1223:cc2c5f20caf8
user:      shad
date:      Tue Feb 25 14:04:24 2014 +0100
description:
tidy, critic, doc, __add_dhcp_entry ne retourne plus de la mise en forme dans un tableau mais juste des clefs=>valeurs, la mise en forme est mise dans le template

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/16cba303d630
changeset: 1224:16cba303d630
user:      shad
date:      Tue Feb 25 15:57:26 2014 +0100
description:
erreur de traduction

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/505c3119a6fb
changeset: 1225:505c3119a6fb
user:      shad
date:      Tue Feb 25 17:16:06 2014 +0100
description:
fix sur le mk_sourceslist et ajout du fix_hosts

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/593820343d2b
changeset: 1226:593820343d2b
user:      shad
date:      Tue Feb 25 17:56:31 2014 +0100
description:
ouput -> output + homogeneisation noms de variable des scripts

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/36f7b65a178d
changeset: 1227:36f7b65a178d
user:      shad
date:      Wed Feb 26 14:40:04 2014 +0100
description:
moins d'erreur et de warning sur la traduction de vieux fichier de conf

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/35b206b1fa5f
changeset: 1228:35b206b1fa5f
user:      shad
date:      Wed Feb 26 15:42:17 2014 +0100
description:
on garde l'ordre originel des sections

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/2b500e0e64b0
changeset: 1229:2b500e0e64b0
user:      shad
date:      Wed Feb 26 15:51:13 2014 +0100
description:
plus propre

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/ccb4530a06ab
changeset: 1230:ccb4530a06ab
user:      shad
date:      Mon Mar 03 17:58:08 2014 +0100
description:
script de traduction : interface -> link

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/167759fa2483
changeset: 1231:167759fa2483
user:      shad
date:      Fri Mar 14 17:49:06 2014 +0100
description:
dependance

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/f8ca2df81da4
changeset: 1232:f8ca2df81da4
user:      shad
date:      Fri Mar 14 17:56:06 2014 +0100
description:
prise en compte de nouvelles clef pour les traductions

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/0f1476d9adaa
changeset: 1233:0f1476d9adaa
user:      shad
date:      Fri Mar 14 17:57:43 2014 +0100
description:
NetAddr::IP->prefix() peut retourner des chaine du genre 192.168.1.98-227 dans certain cas

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/56c6f886ff1e
changeset: 1234:56c6f886ff1e
user:      shad
date:      Fri Mar 14 17:58:31 2014 +0100
description:
plus de croak

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/8a0f8e66f055
changeset: 1235:8a0f8e66f055
user:      shad
date:      Fri Mar 14 18:05:33 2014 +0100
description:
clarification messages, tidy, critic, podchecker

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/b317046c51f4
changeset: 1236:b317046c51f4
user:      shad
date:      Mon Mar 17 19:42:13 2014 +0100
description:
rajout du 'ignore' dans les definition, prise en compte d'un template par defaut pour le sources.list, tidy, critic

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/fe75c51fa48c
changeset: 1237:fe75c51fa48c
user:      shad
date:      Tue Mar 18 17:15:13 2014 +0100
description:
pf_config oublié et message d'erreurs plus clair

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/44a94986381d
changeset: 1238:44a94986381d
user:      shad
date:      Tue Mar 18 17:16:15 2014 +0100
description:
sinon les grub2opt ne sont pas traduits

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/c0e33dc4dbf3
changeset: 1239:c0e33dc4dbf3
user:      shad
date:      Tue Mar 18 17:17:18 2014 +0100
description:
NetAddr::IP->prefix()  avec ses ranges frappe encore + tidy+critic+podchecker

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/a3beb5e317c1
changeset: 1240:a3beb5e317c1
user:      shad
date:      Wed Mar 19 15:33:12 2014 +0100
description:
les --sep des filter_privateresoleve

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/a9354ce33bed
changeset: 1241:a9354ce33bed
user:      shad
date:      Wed Mar 19 16:05:53 2014 +0100
description:
ne meurt pas lors qu'un privateresolve ne resoud pas un nom

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/9a95596e1909
changeset: 1242:9a95596e1909
user:      shad
date:      Wed Mar 19 16:58:23 2014 +0100
description:
rajout d'un hash PUBLIC_NETWORK pour resoudre les host des machine de pop voisins avec une patte sur le public

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/5b8295127534
changeset: 1243:5b8295127534
user:      shad
date:      Wed Mar 19 17:14:36 2014 +0100
description:
le test qui va avec

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/0dbdaaa2d33c
changeset: 1244:0dbdaaa2d33c
user:      shad
date:      Thu Mar 20 10:14:18 2014 +0100
description:
coherence test

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/f64dbca5935a
changeset: 1245:f64dbca5935a
user:      shad
date:      Thu Mar 20 11:45:01 2014 +0100
description:
IGNORE traité comme les autre et warning si une interface n'est pas resolue dans un vlan

details:   http://hg.debian.org/hg/pf-tools/pf-tools/rev/db767ed9f51f
changeset: 1246:db767ed9f51f
user:      shad
date:      Tue Apr 01 17:50:29 2014 +0200
description:
ecriture plus correct des hostfile et des machine uniquement déclarée pour leurs ip

diffstat:

 Makefile                               |    11 +-
 debian/changelog                       |     2 +-
 debian/control                         |     2 +-
 debian/dirs                            |     5 -
 debian/pf-host.conffiles               |     1 -
 doc/hostfile-syntax                    |    37 -
 filters/filter_distrib                 |     4 +-
 filters/filter_privateresolve          |     4 +-
 filters/filter_vlan2if                 |     4 +-
 lib/PFTools.pm                         |   100 +-
 lib/PFTools/Compat/Translation.pm      |   451 +++++++++----
 lib/PFTools/Conf.pm                    |   117 +-
 lib/PFTools/Conf/Host.pm               |   375 ++++++----
 lib/PFTools/Conf/Network.pm            |   222 ++---
 lib/PFTools/Conf/Syntax.pm             |    80 +-
 lib/PFTools/Packages/DEB.pm            |     2 +-
 lib/PFTools/Structqueries.pm           |   150 ++-
 lib/PFTools/Update.pm                  |    11 +-
 lib/PFTools/Update/ADDFILE.pm          |    41 +-
 lib/PFTools/Update/ADDLINK.pm          |     3 +-
 lib/PFTools/Update/ADDMOUNT.pm         |   145 ++--
 lib/PFTools/Update/CREATEFILE.pm       |     3 +-
 lib/PFTools/Update/Common.pm           |   141 ++--
 lib/PFTools/Update/IGNORE.pm           |    53 +
 lib/PFTools/Update/INSTALLPKG.pm       |    76 +-
 lib/PFTools/Update/MKDIR.pm            |     3 +-
 lib/PFTools/Update/PURGEPKG.pm         |     3 +-
 lib/PFTools/Update/REMOVEDIR.pm        |     3 +-
 lib/PFTools/Update/REMOVEFILE.pm       |     3 +-
 lib/PFTools/Utils.pm                   |  1082 +++++++++++++++----------------
 lib/PFTools/VCS.pm                     |     8 +-
 lib/PFTools/VCS/CVS.pm                 |    54 +-
 lib/PFTools/VCS/HG.pm                  |    27 +-
 lib/PFTools/VCS/SVN.pm                 |    33 +-
 sbin/fix_hosts                         |    78 +-
 sbin/mk_dhcp                           |    81 +-
 sbin/mk_grubopt                        |    60 +-
 sbin/mk_interfaces                     |    71 +-
 sbin/mk_pxelinuxcfg                    |   114 +-
 sbin/mk_resolvconf                     |    65 +-
 sbin/mk_sitezone                       |    58 +-
 sbin/mk_sourceslist                    |    63 +-
 sbin/update-config                     |    60 +-
 t/13.conf.t                            |    81 +-
 t/20.files.search_and_replace.input.ip |     2 +
 t/20.files.t                           |   128 ++-
 templates/dhcpd.conf.tpl               |     7 +-
 tools/Display_IP_config                |     2 +-
 tools/Translate_old_config             |   224 +++++-
 tools/pflaunch                         |     2 +-
 50 files changed, 2394 insertions(+), 1958 deletions(-)

diffs (8183 lines):

diff -r 02ed6fbcae72 -r db767ed9f51f Makefile
--- a/Makefile	Wed Oct 02 13:48:39 2013 +0200
+++ b/Makefile	Tue Apr 01 17:50:29 2014 +0200
@@ -1,6 +1,7 @@
 #! /usr/bin/make -f
 
-LIB_DIR=$(DESTDIR)/usr/share/perl5/PFTools
+PERL_DIR=$(DESTDIR)/usr/share/perl5
+LIB_DIR=$(PERL_DIR)/PFTools
 SBIN_DIR=$(DESTDIR)/usr/sbin
 FILTERS_DIR=$(DESTDIR)/usr/sbin
 CONF_DIR=$(DESTDIR)/etc
@@ -9,6 +10,7 @@
 SBIN=sbin/*
 FILTERS=filters/*
 LIB=lib/PFTools/*
+MAINLIB=lib/PFTools.pm
 TOOLS=tools/*
 CONF=conf/*
 TPL=templates/*
@@ -32,6 +34,12 @@
 
 test:
 	prove -lr
+	@echo "if you want to run all test, you must either use 'sudo make test'"
+	@echo "or 'make alltest' which will require you to be in sudoers"
+	@echo "this is used to realize chown/chmod test"
+
+alltest:
+	sudo prove -lr
 
 install: install_tools install_host
 
@@ -40,6 +48,7 @@
 	mkdir -p $(LIB_DIR)
 	cp -r $(LIB) $(LIB_DIR)
 	find $(LIB_DIR) -name "*.pm" -exec chmod 0644 {} \;
+	install --owner=root --group=root --mode=0644  $(MAINLIB) $(PERL_DIR)
 	
 	# PFTools utils
 	mkdir -p $(SBIN_DIR)
diff -r 02ed6fbcae72 -r db767ed9f51f debian/changelog
--- a/debian/changelog	Wed Oct 02 13:48:39 2013 +0200
+++ b/debian/changelog	Tue Apr 01 17:50:29 2014 +0200
@@ -1,4 +1,4 @@
-pf-tools (1.0.1~WIP) unstable; urgency=low
+pf-tools (1.0.1-0~WIP) UNRELEASED; urgency=low
 
   * WORK IN PROGRESS, DO NOT RELEASE!
 
diff -r 02ed6fbcae72 -r db767ed9f51f debian/control
--- a/debian/control	Wed Oct 02 13:48:39 2013 +0200
+++ b/debian/control	Tue Apr 01 17:50:29 2014 +0200
@@ -8,7 +8,7 @@
 
 Package: pf-tools
 Architecture: all
-Depends: perl, perl (>= 5.10.0) | libmd5-perl, libclone-perl, libconfig-inifiles-perl, liblist-moreutils-perl, libmodule-runtime-perl, libnetaddr-ip-perl, libnet-dns-perl, libproc-reliable-perl, libreadonly-xs-perl, libtemplate-tiny-perl, libtext-diff-perl, cvs, ssh, iproute, debconf, psmisc
+Depends: perl, perl (>= 5.10.0) | libmd5-perl, libclone-perl, libconfig-inifiles-perl, liblist-moreutils-perl, libhash-merge-simple-perl, libmodule-runtime-perl, libnetaddr-ip-perl, libnet-dns-perl, libproc-reliable-perl, libreadonly-xs-perl, libreadonly-xs-perl, libtemplate-tiny-perl, libtext-diff-perl, cvs, ssh, iproute, debconf, psmisc
 Description: Outils de gestion de la plateforme
  Mise a jour automatique et generation de conf.
  Deploiement de machines.
diff -r 02ed6fbcae72 -r db767ed9f51f debian/dirs
--- a/debian/dirs	Wed Oct 02 13:48:39 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-usr/local/bin
-usr/local/sbin
-usr/local/lib/site_perl
-usr/local/share/pf-tools
-etc
diff -r 02ed6fbcae72 -r db767ed9f51f debian/pf-host.conffiles
--- a/debian/pf-host.conffiles	Wed Oct 02 13:48:39 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-/etc/init.d/pf-host
diff -r 02ed6fbcae72 -r db767ed9f51f doc/hostfile-syntax
--- a/doc/hostfile-syntax	Wed Oct 02 13:48:39 2013 +0200
+++ b/doc/hostfile-syntax	Tue Apr 01 17:50:29 2014 +0200
@@ -10,43 +10,6 @@
 	? iface_opt[%HOSTNUM%]		::= <IFACE_OPT> define here iface options (ip link syntax)
 	? @route[.default|%HOSTNUM%]	::= <SUBNET>/<NETMASK> [via <GATEWAY>] (ip route syntax)
 	? @route6[.default|%HOSTNUM%]	::= <SUBNET>/<NETMASK> [via <GATEWAY>] (ip route syntax)
-	
-
-[interface::ethX]
-	? mac[.%HOSTNUM%]				::= <MAC_ADDR> WARNING this directive MUST BE defined for interface which is used for deployment
-	! vlan[.%HOSTNUM%]				::= <NETWORK_NAME> as defined in network configurations part in PF-TOOLS
-	! ipv4[.%HOSTNUM%]				::= <IPV4_ADDR> if default is used then act as old ipstart directive
-	? ipv6[.%HOSTNUM%]				::= <IPV6_ADDR> if default is used then act as old ipstart directive
-	? iface_opt[.%HOSTNUM%]			::= <IFACE_OPT> define here iface options (ip link syntax)
-	? @route[.default|%HOSTNUM%]	::= <SUBNET>/<NETMASK> [via <GATEWAY>] (ip route syntax)
-	? @route6[.default|%HOSTNUM%]	::= <SUBNET>/<NETMASK> [via <GATEWAY>] (ip route syntax)
-
-[interface::ethX.TAGY]
-	! vlan[.%HOSTNUM%]		::= <NETWORK_NAME> as defined in network configurations part in PF-TOOLS
-	! ipv4[.%HOSTNUM%]		::= <IPV4_ADDR> if default is used then act as old ipstart directive
-	? ipv6[.%HOSTNUM%]		::= <IPV6_ADDR> if default is used then act as old ipstart directive
-	? iface_opt[%HOSTNUM%]	::= <IFACE_OPT> define here iface options (ip link syntax)
-	? @route[.%HOSTNUM%]	::= <SUBNET>/<NETMASK> [via <GATEWAY>] (ip route syntax)
-	? @route6[.%HOSTNUM%]	::= <SUBNET>/<NETMASK> [via <GATEWAY>] (ip route syntax)
-
-[interface::bondX]
-	! slaves[.%HOSTNUM%]	::= <IFACE>,<IFACE>,... abort parsing if one <IFACE> is defined into [interface::<IFACE>] section
-	? mode[.%HOSTNUM%]		::= active-backup|802.3ad ... see kernel Docs for different modes default value is active-backup
-	? options[.%HOSTNUM%]	::= see kernel docs for misc options like xmit_hash_policy (space separated list)
-	! vlan[.%HOSTNUM%]		::= <NETWORK_NAME> as defined in network configurations part in PF-TOOLS
-	! ipv4[.%HOSTNUM%]		::= <IPV4_ADDR> if default is used then act as old ipstart directive
-	? ipv6[.%HOSTNUM%]		::= <IPV6_ADDR> if default is used then act as old ipstart directive
-	? iface_opt[.%HOSTNUM%]	::= <IFACE_OPT> define here iface options (ip link syntax and comma separated list)
-	? @route[.%HOSTNUM%]	::= <SUBNET>/<NETMASK> [via <GATEWAY>] (ip route syntax)
-	? @route6[.%HOSTNUM%]	::= <SUBNET>/<NETMASK> [via <GATEWAY>] (ip route syntax)
-
-[interface::bondX.TAGY]
-	! vlan[.%HOSTNUM%]		::= <NETWORK_NAME> as defined in network configurations part in PF-TOOLS
-	! ipv4[.%HOSTNUM%]		::= <IPV4_ADDR> if default is used then act as old ipstart directive
-	? ipv6[.%HOSTNUM%]		::= <IPV6_ADDR> if default is used then act as old ipstart directive
-	? iface_opt[.%HOSTNUM%]	::= <IFACE_OPT> define here iface options (ip link syntax)
-	? @route[.%HOSTNUM%]	::= <SUBNET>/<NETMASK> [via <GATEWAY>] (ip route syntax)
-	? @route6[.%HOSTNUM%]	::= <SUBNET>/<NETMASK> [via <GATEWAY>] (ip route syntax)
 
 [deployment]
 	? os_type				::= redhat|debian|centos ...
diff -r 02ed6fbcae72 -r db767ed9f51f filters/filter_distrib
--- a/filters/filter_distrib	Wed Oct 02 13:48:39 2013 +0200
+++ b/filters/filter_distrib	Tue Apr 01 17:50:29 2014 +0200
@@ -27,7 +27,7 @@
 use Sys::Hostname;
 
 use PFTools::Structqueries;
-use PFTools::Utils qw( Init_TOOLS search_and_replace );
+use PFTools::Utils qw( init_tools search_and_replace );
 
 my @options_specs = (
     'config|c=s',
@@ -57,7 +57,7 @@
 }
 
 my ( $pf_config, $global_config )
-    = Init_TOOLS(
+    = init_tools(
     $options->{'host'}, $options->{'config'},
     $options->{'store'}
     );
diff -r 02ed6fbcae72 -r db767ed9f51f filters/filter_privateresolve
--- a/filters/filter_privateresolve	Wed Oct 02 13:48:39 2013 +0200
+++ b/filters/filter_privateresolve	Tue Apr 01 17:50:29 2014 +0200
@@ -29,7 +29,7 @@
 use Sys::Hostname;
 
 use PFTools::Structqueries;
-use PFTools::Utils qw( Init_TOOLS search_and_replace );
+use PFTools::Utils qw( init_tools search_and_replace );
 
 my @options_specifications = (
     'config|c=s',
@@ -70,7 +70,7 @@
     die q{ERROR: --input and --output are mandatory};
 }
 
-my ( $pf_config, $global_config ) = Init_TOOLS(
+my ( $pf_config, $global_config ) = init_tools(
     $options->{'host'},
     $options->{'config'},
     $options->{'store'}
diff -r 02ed6fbcae72 -r db767ed9f51f filters/filter_vlan2if
--- a/filters/filter_vlan2if	Wed Oct 02 13:48:39 2013 +0200
+++ b/filters/filter_vlan2if	Tue Apr 01 17:50:29 2014 +0200
@@ -33,7 +33,7 @@
 use Sys::Hostname;
 
 use PFTools::Structqueries;
-use PFTools::Utils qw( Init_TOOLS search_and_replace );
+use PFTools::Utils qw( init_tools search_and_replace );
 
 my $program = basename $PROGRAM_NAME;
 
@@ -66,7 +66,7 @@
     die q{ERROR: --input and --output are mandatory};
 }
 
-my ( $pf_config, $global_config ) = Init_TOOLS(
+my ( $pf_config, $global_config ) = init_tools(
     $options->{'host'},
     $options->{'config'},
     $options->{'store'}
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools.pm
--- a/lib/PFTools.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -1,22 +1,30 @@
 package PFTools;
 
-#
-#  Copyright (C) 2010 Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
-#
-#  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
-#
+=head1 NAME
+
+PFTools - deploy and manage a platform
+
+=head1 LICENSE AND COPYRIGHT
+
+ Copyright (C) 2010 Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
+
+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
+
+=head1 SUBROUTINES/METHODS
+
+=cut
 
 use strict;
 use warnings;
@@ -39,7 +47,6 @@
 
 our $VERSION = '1.0.1-WIP';
 
-
 =head2 check_args_type($args_ref)
 
 Takes the following named arguments:
@@ -82,7 +89,8 @@
     }
 
     my ( $args_ref, $type, $mandatory, $must_be_true, $keys_ref )
-        = @{$my_args_ref}{qw( args_ref type mandatory must_be_true keys_ref )};
+        = @{$my_args_ref}
+        {qw( args_ref type mandatory must_be_true keys_ref )};
 
     if ( ref $args_ref ne 'HASH' ) {
         croak q{ERROR: Invalid non-hash reference args_ref};
@@ -93,16 +101,21 @@
     }
     my @keys = @{$keys_ref};
 
-    if ( ref $type or ref $mandatory or ref $must_be_true or not defined $type or not @keys ) {
+    if (   ref $type
+        or ref $mandatory
+        or ref $must_be_true
+        or not defined $type
+        or not @keys )
+    {
         confess q{ERROR: BUG: invalid args};
     }
 
     my $type_string
-        = $type ? ( qq{non-} . lc($type) . q{ reference} ) : q{non-scalar};
+        = $type ? ( q{non-} . lc($type) . q{ reference} ) : q{non-scalar};
 
     foreach my $key (@keys) {
-        if (not defined $key) {
-            carp qq{WARNING: PROBABLE BUG: undefined key in check_args_type()};
+        if ( not defined $key ) {
+            carp q{WARNING: PROBABLE BUG: undefined key in check_args_type()};
             next;
         }
 
@@ -126,17 +139,16 @@
 
 =head2 check_mandatory_args_type( $args_ref, $type, @keys )
 
-Checks the arguments, treating them as mandatory (see I<check_args_type() for
+Checks the arguments, treating them as mandatory (see I<check_args_type()> for
 details).
 
 =cut
 
 sub check_mandatory_args_type {
-    my ($args_ref, $type, @keys) = @_;
+    my ( $args_ref, $type, @keys ) = @_;
 
     return check_args_type(
-        {
-            args_ref  => $args_ref,
+        {   args_ref  => $args_ref,
             type      => $type,
             keys_ref  => \@keys,
             mandatory => 1,
@@ -146,19 +158,18 @@
 
 =head2 check_optional_args_type( $args_ref, $type, @keys )
 
-Checks the arguments, treating them as optional (see I<check_args_type() for
+Checks the arguments, treating them as optional (see I<check_args_type()> for
 details).
 
 =cut
 
 sub check_optional_args_type {
-    my ($args_ref, $type, @keys) = @_;
+    my ( $args_ref, $type, @keys ) = @_;
 
     return check_args_type(
-        {
-            args_ref  => $args_ref,
-            type      => $type,
-            keys_ref  => \@keys,
+        {   args_ref => $args_ref,
+            type     => $type,
+            keys_ref => \@keys,
         }
     );
 }
@@ -166,16 +177,15 @@
 =head2 check_mandatory_true_args_type( $args_ref, $type, @keys )
 
 Checks the arguments, treating them as mandatory and must_be_true (see
-I<check_args_type() for details).
+I<check_args_type()> for details).
 
 =cut
 
 sub check_mandatory_true_args_type {
-    my ($args_ref, $type, @keys) = @_;
+    my ( $args_ref, $type, @keys ) = @_;
 
     return check_args_type(
-        {
-            args_ref     => $args_ref,
+        {   args_ref     => $args_ref,
             type         => $type,
             keys_ref     => \@keys,
             mandatory    => 1,
@@ -195,11 +205,11 @@
 
 =cut
 
-sub check_args (&$@) {
-    my ($function_ref, $args_ref, @keys) = @_;
+sub check_args (&$@) {    ## no critic (ProhibitSubroutinePrototypes);
+    my ( $function_ref, $args_ref, @keys ) = @_;
 
     foreach my $key (@keys) {
-        $function_ref->($args_ref, $key);
+        $function_ref->( $args_ref, $key );
     }
 
     return 1;
@@ -208,15 +218,15 @@
 =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{}, etc.
+value. NOTE: this is therefore NOT suitable for 0, q{}, etc.
 
 =cut
 
 sub check_true_args {
-    my ($args_ref, @keys) = @_;
+    my ( $args_ref, @keys ) = @_;
 
     check_args {
-        my ($args_ref, $key) = @_;
+        my ( $args_ref, $key ) = @_;
 
         if ( not $args_ref->{$key} ) {
             croak qq{ERROR: Invalid empty $key};
@@ -229,7 +239,7 @@
 
 =head2 trim_surrounding_whitespace($string)
 
-Just like the name suggets!
+Just like the name suggest!
 
 =cut
 
@@ -240,7 +250,7 @@
         croak q{ERROR: Invalid non-scalar string};
     }
 
-    return unless defined $string;
+    return if !defined $string;
 
     $string =~ s{
         \A
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/Compat/Translation.pm
--- a/lib/PFTools/Compat/Translation.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/Compat/Translation.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -28,6 +28,7 @@
 
 our @EXPORT = qw (
     Translate_old2new_host
+    Translate_old2new_vhost
     Translate_old2new_network
     Translate_old2new_config
 );
@@ -40,14 +41,23 @@
     my $new_conf = $conf_parsed;
     foreach my $section ( keys %{$new_conf} ) {
         if ( $section =~ /^@(.*)$/ ) {
-            $new_conf->{$1} = { 'type' => 'include' };
+            $new_conf->{$1} = { 'action' => 'include' };
+            delete $new_conf->{$section};
             next;
         }
         foreach my $key ( keys %{ $new_conf->{$section} } ) {
 
             # Filter substitution
-            $new_conf->{$section}->{$key}
-                =~ s/(filter_(\S+)) (\S+) (\S+) (\S+)/$1 -i $3 -h $4 -o $5/g;
+            if ( $new_conf->{$section}->{$key}
+                =~ m{(filter_(\S+)) (\S+) (\S+) (\S+) ([^|]+)} )
+            {
+                $new_conf->{$section}->{$key}
+                    =~ s/(filter_(\S+)) (\S+) (\S+) (\S+) ([^|]+)/$1 -i $3 -h $4 -o $5 --sep $6/g;
+            }
+            else {
+                $new_conf->{$section}->{$key}
+                    =~ s/(filter_(\S+)) (\S+) (\S+) (\S+)/$1 -i $3 -h $4 -o $5/g;
+            }
             $new_conf->{$section}->{$key} =~ s/^apt-get$/installpkg/;
             $new_conf->{$section}->{$key} =~ s/^dpkg-purge$/purgepkg/;
             if ( $new_conf->{$section}->{$key} =~ /mk_pxelinuxcfg/ ) {
@@ -60,7 +70,7 @@
             }
             elsif ( $new_conf->{$section}->{$key} =~ /mk_grub2opt/ ) {
                 $new_conf->{$section}->{$key}
-                    =~ s/mk_grubopt -d (\S+) --host (\S+)/mk_grubopt -h $2 -o $1/;
+                    =~ s/mk_grub2opt -d (\S+) --host (\S+)/mk_grubopt -h $2 -o $1/;
             }
             elsif ( $new_conf->{$section}->{$key} =~ /mk_resolvconf/ ) {
                 $new_conf->{$section}->{$key}
@@ -80,7 +90,13 @@
             }
             elsif ( $new_conf->{$section}->{$key} =~ /mk_sourceslist/ ) {
                 $new_conf->{$section}->{$key}
-                    =~ s/mk_sourceslist -s (\S+) -d (\S+)--host (\S+)/mk_sourceslist -h $2 -o $1/;
+                    =~ s/mk_sourceslist -s (\S+) -d (\S+) --host (\S+)(.*)/mk_sourceslist -h $3 -o $2/;
+                $new_conf->{$section}->{$key} .= join q{ -a },
+                    split( / /, $4 );
+            }
+            elsif ( $new_conf->{$section}->{$key} =~ /fix_hosts/ ) {
+                $new_conf->{$section}->{$key}
+                    =~ s/fix_hosts -d (\S+) --host (\S+)/fix_hosts -h $2 -o $1/;
             }
         }
     }
@@ -93,7 +109,7 @@
 
     if ( $network_parsed->{'type'} ne 'network' ) {
         Warn( $CODE->{'INVALID_CONTEXT'},
-            "Unable to translate into new format a section which is not a network declaration"
+            q{Unable to translate into new format a section which is not a network declaration}
         );
         return;
     }
@@ -101,16 +117,17 @@
         $network_parsed->{'netmask'} );
     if ( !defined $net ) {
         Warn( $CODE->{'INVALID_VALUE'},
-            "Invalid network definition for network name " . $network_name );
+            q{Invalid network definition for network name } . $network_name );
         return;
     }
+
     $new_network = {
         'type'    => 'network',
         'comment' => $network_parsed->{'comment'},
         'network' => $net->cidr(),
         'tag'     => $network_parsed->{'tag'},
         'site'    => 'UNDEFINED',
-        'scope'   => ( $network_parsed->{'network_parsed'} =~ /^10\./ )
+        'scope'   => ( $network_parsed->{'network'} =~ /^10[.]/ )
         ? 'private'
         : 'public'
     };
@@ -123,179 +140,107 @@
 
     if ( $host_parsed->{'type'} !~ /-server$/ ) {
         Warn( $CODE->{'INVALID_CONTEXT'},
-            "Unable to translate into new format a section which is not a host declaration"
+            q{Unable to translate into new format a section which is not a host declaration}
         );
         return;
     }
 
+    #use Data::Dumper;
+    #print Dumper $host_parsed;
     $new_host->{'hostgroup'}->{'hostname'} = $hostname;
-    $new_host->{'hostgroup'}->{'comment'} = $host_parsed->{'comment'} || "";
+    $new_host->{'hostgroup'}->{'comment'} = $host_parsed->{'comment'} || q{};
     foreach my $key ( keys %{$host_parsed} ) {
         if ( $key eq 'shortname' ) {
             $new_host->{'dns'}->{'shortname'} = $host_parsed->{'shortname'};
         }
         elsif ( $key eq 'ether' ) {
             foreach my $num ( sort keys %{ $host_parsed->{'ether'} } ) {
-                $new_host->{'interface::eth0'}->{ 'mac.' . $num }
-                    = $host_parsed->{$key}->{$num};
+                $new_host->{'link::vlan-systeme'}->{ 'mac.' . $num }
+                    = lc $host_parsed->{$key}->{$num};
             }
         }
-        elsif ( $key =~ /^arch|distrib|deploymode$/ ) {
-            my $new_key = ( $key eq 'deploymode' ) ? 'mode' : $key;
+        elsif ( $key =~ /^deploymode$/ ) {
+            my $new_key = 'mode';
             if ( ref $host_parsed->{$key} eq 'HASH' ) {
                 foreach my $subkey ( keys %{ $host_parsed->{$key} } ) {
                     if ( $subkey eq 'default' ) {
                         $new_host->{'deployment'}->{$new_key}
                             = $host_parsed->{$key}->{$subkey};
+                        $new_host->{'deployment'}->{$new_key}
+                            =~ s{ -installer \z}{}xms;
                     }
                     else {
                         $new_host->{'deployment'}
                             ->{ $new_key . '.' . $subkey }
                             = $host_parsed->{$key}->{$subkey};
+                        $new_host->{'deployment'}
+                            ->{ $new_key . '.' . $subkey }
+                            =~ s{ -installer \z}{}xms;
                     }
                 }
             }
             else {
                 $new_host->{'deployment'}->{$new_key} = $host_parsed->{$key};
+                $new_host->{'deployment'}->{$new_key}
+                    =~ s{ -installer \z}{}xms;
+            }
+        }
+        elsif ( $key =~ /^arch|distrib$/ ) {
+            if ( ref $host_parsed->{$key} eq 'HASH' ) {
+                foreach my $subkey ( keys %{ $host_parsed->{$key} } ) {
+                    if ( $subkey eq 'default' ) {
+                        $new_host->{'deployment'}->{$key}
+                            = $host_parsed->{$key}->{$subkey};
+                    }
+                    else {
+                        $new_host->{'deployment'}->{ $key . '.' . $subkey }
+                            = $host_parsed->{$key}->{$subkey};
+                    }
+                }
+            }
+            else {
+                $new_host->{'deployment'}->{$key} = $host_parsed->{$key};
             }
         }
         elsif ( $key =~ /^order|number$/ ) {
             $new_host->{'hostgroup'}->{$key} = $host_parsed->{$key};
         }
         elsif ( $key eq 'interface' ) {
+            my $ifacedone;
             foreach my $iface ( keys %{ $host_parsed->{$key} } ) {
-                my $vlan = $host_parsed->{$key}->{$iface};
-                $new_host->{ 'interface::' . $iface }->{'vlan'} = $vlan;
-                if ( defined $host_parsed->{'ipstart'}->{$vlan} ) {
-                    $new_host->{ 'interface::' . $iface }->{'ipv4'}
-                        = $host_parsed->{'ipstart'}->{$vlan};
+                my $vlan;
+                if ( ref $host_parsed->{$key}->{$iface} eq q{} ) {
+                    $vlan = $host_parsed->{$key}->{$iface};
+                    $new_host->{ 'link::' . $vlan }->{'dev'} = $iface;
+                    __addlinksection( $host_parsed, $new_host, $vlan,
+                        $iface );
+                    if ( !$ifacedone->{$iface} ) {
+                        __addroutetolink( $host_parsed, $new_host, $vlan,
+                            $iface );
+                        __addbondtolink( $host_parsed, $new_host, $vlan,
+                            $iface );
+                        $ifacedone->{$iface} = 1;
+                    }
                 }
-                elsif ( defined $host_parsed->{'ip'}->{$vlan} ) {
-                    foreach
-                        my $subkey ( keys %{ $host_parsed->{'ip'}->{$vlan} } )
+                else {
+                    foreach my $hostnum (
+                        keys %{ $host_parsed->{$key}->{$iface} } )
                     {
-                        if ( $subkey eq 'default'
-                            && !
-                            defined $new_host->{ 'interface::' . $iface }
-                            ->{'ipv4'} )
-                        {
-                            $new_host->{ 'interface::' . $iface }->{'ipv4'}
-                                = $host_parsed->{'ip'}->{$vlan}->{$subkey};
-                        }
-                        else {
-                            $new_host->{ 'interface::' . $iface }
-                                ->{ 'ipv4.' . $subkey }
-                                = $host_parsed->{'ip'}->{$vlan}->{$subkey};
+                        $vlan = $host_parsed->{$key}->{$iface}->{$hostnum};
+                        $new_host->{ 'link::' . $vlan }
+                            ->{ 'dev' . qq{.$hostnum} } = $iface;
+                        __addlinksection( $host_parsed, $new_host, $vlan,
+                            $iface );
+                        if ( !$ifacedone->{$iface} ) {
+                            __addroutetolink( $host_parsed, $new_host, $vlan,
+                                $iface );
+                            __addbondtolink( $host_parsed, $new_host, $vlan,
+                                $iface );
+                            $ifacedone->{$iface} = 1;
                         }
                     }
                 }
-                else {
-                    $new_host->{ 'interface::' . $iface }->{'ipv4'}
-                        = $host_parsed->{'ipstart'}->{'default'};
-                }
                 if ( defined $host_parsed->{$iface} ) {
-                    foreach my $route ( keys %{ $host_parsed->{$iface} } ) {
-                        if ( ref $host_parsed->{$iface}->{$route} eq 'HASH' )
-                        {
-                            foreach my $subkey (
-                                keys %{ $host_parsed->{$iface}->{$route} } )
-                            {
-                                if ( $subkey eq 'default' ) {
-                                    push(
-                                        @{  $new_host->{ 'interface::'
-                                                    . $iface }->{'@route'}
-                                            },
-                                        $host_parsed->{$iface}->{$route}
-                                            ->{$subkey}
-                                    );
-                                }
-                                else {
-                                    push(
-                                        @{  $new_host->{ 'interface::'
-                                                    . $iface }
-                                                ->{ '@route.' . $subkey }
-                                            },
-                                        $host_parsed->{$iface}->{$route}
-                                            ->{$subkey}
-                                    );
-                                }
-                            }
-                        }
-                    }
-                    if ( $iface =~ /^bond/ ) {
-                        if (ref $host_parsed->{'bonding'}->{$iface} eq
-                            'HASH' )
-                        {
-                            foreach my $subkey (
-                                keys %{ $host_parsed->{'bonding'}->{$iface} }
-                                )
-                            {
-                                if ( $subkey eq 'default' ) {
-                                    $new_host->{ 'interface::' . $iface }
-                                        ->{'slaves'}
-                                        = $host_parsed->{'bonding'}->{$iface}
-                                        ->{$subkey};
-                                }
-                                else {
-                                    $new_host->{ 'interface::' . $iface }
-                                        ->{ 'slaves.' . $subkey }
-                                        = $host_parsed->{'bonding'}->{$iface}
-                                        ->{$subkey};
-                                }
-                            }
-                        }
-                        else {
-                            $new_host->{ 'interface::' . $iface }->{'slaves'}
-                                = $host_parsed->{'bonding'}->{$iface};
-                        }
-                        my $ref_cmdline = {};
-                        if ( ref $host_parsed->{'cmdline'} eq 'HASH' ) {
-                            $ref_cmdline = $host_parsed->{'cmdline'};
-                        }
-                        else {
-                            $ref_cmdline->{'default'}
-                                = $host_parsed->{'cmdline'};
-                        }
-                        foreach my $cmdline ( keys %{$ref_cmdline} ) {
-                            my $newcmd_key
-                                = ( $cmdline eq 'default' )
-                                ? 'cmdline'
-                                : 'cmdline.' . $cmdline;
-                            my $newopt_key
-                                = ( $cmdline eq 'default' )
-                                ? 'options'
-                                : 'options.' . $cmdline;
-                            my $newmode_key
-                                = ( $cmdline eq 'default' )
-                                ? 'mode'
-                                : 'mode.' . $cmdline;
-                            foreach my $cmd (
-                                split( / /, $ref_cmdline->{$cmdline} ) )
-                            {
-                                if ( $cmd =~ /^bonding\.(.+)$/ ) {
-                                    my ( $opt, $val ) = split( /=/, $1 );
-                                    my $new_opt;
-                                    if ( $opt eq 'mode' ) {
-                                        $new_host->{ 'interface::' . $iface }
-                                            ->{$newmode_key} = $val;
-                                    }
-                                    else {
-                                        $new_host->{ 'interface::' . $iface }
-                                            ->{$newopt_key}
-                                            = $opt . '=' . $val . ' ';
-                                    }
-                                }
-                                else {
-                                    $new_host->{'boot'}->{$newcmd_key}
-                                        .= $cmd . " ";
-                                }
-                            }
-                            $new_host->{ 'interface::' . $iface }
-                                ->{$newopt_key} =~ s/\s*$//;
-                            $new_host->{'boot'}->{$newcmd_key} =~ s/\s*$//
-                                if ( $new_host->{'boot'}->{$newcmd_key} );
-                        }
-                    }
                 }
             }
         }
@@ -320,7 +265,8 @@
                 $new_host->{'dns'}->{'resolver'} = $host_parsed->{$key};
             }
         }
-        elsif ( $key =~ /^console|(pxe|uml)?filename$/ ) {
+        elsif ( $key =~ /^initrd|pxetemplate|console|(pxe|uml)?filename$/xms )
+        {
             my $new_key;
             if ( defined $1 ) {
                 $new_key = ( $1 eq 'uml' ) ? 'kerneluml' : 'kernel';
@@ -336,7 +282,7 @@
                     my $newsub_key
                         = ( $subkey eq 'default' )
                         ? $new_key
-                        : $new_key . '.' . $subkey;
+                        : $new_key . q{.} . $subkey;
                     $new_host->{'boot'}->{$newsub_key}
                         = $host_parsed->{$key}->{$subkey};
                 }
@@ -349,4 +295,225 @@
     return $new_host;
 }
 
+sub Translate_old2new_vhost ($$) {
+    my ( $host_parsed, $hostname ) = @_;
+    my $new_host = {};
+
+    if ( $host_parsed->{'type'} !~ /-server$/ ) {
+        Warn( $CODE->{'INVALID_CONTEXT'},
+            q{Unable to translate into new format a section which is not a host declaration}
+        );
+        return;
+    }
+
+    #use Data::Dumper;
+    #print Dumper $host_parsed;
+    $new_host->{'type'} = q{server};
+    $new_host->{'site'} = q{UNDEFINED};
+    $new_host->{'comment'} = $host_parsed->{'comment'} || q{};
+    foreach my $key ( keys %{$host_parsed} ) {
+        if ( $key eq 'shortname' ) {
+            $new_host->{'shortname'} = $host_parsed->{'shortname'};
+        }
+        elsif ( $key =~ /^order|number$/ ) {
+            $new_host->{$key} = $host_parsed->{$key};
+        }
+        elsif ( $key eq 'interface' ) {
+            my $ifacedone;
+            foreach my $iface ( keys %{ $host_parsed->{$key} } ) {
+                my $vlan;
+                if ( ref $host_parsed->{$key}->{$iface} eq q{} ) {
+                    $vlan = $host_parsed->{$key}->{$iface};
+                    #$new_host->{ 'link::' . $vlan }->{'dev'} = $iface;
+                    __addvlinksection( $host_parsed, $new_host, $vlan,
+                        $iface );
+                    if ( !$ifacedone->{$iface} ) {
+                        __addroutetolink( $host_parsed, $new_host, $vlan,
+                            $iface );
+                        __addbondtolink( $host_parsed, $new_host, $vlan,
+                            $iface );
+                        $ifacedone->{$iface} = 1;
+                    }
+                }
+                else {
+                    foreach my $hostnum (
+                        keys %{ $host_parsed->{$key}->{$iface} } )
+                    {
+                        $vlan = $host_parsed->{$key}->{$iface}->{$hostnum};
+                        #$new_host->{ 'link::' . $vlan }
+                        #    ->{ 'dev' . qq{.$hostnum} } = $iface;
+                        __addvlinksection( $host_parsed, $new_host, $vlan,
+                            $iface );
+                        if ( !$ifacedone->{$iface} ) {
+                            __addroutetolink( $host_parsed, $new_host, $vlan,
+                                $iface );
+                            __addbondtolink( $host_parsed, $new_host, $vlan,
+                                $iface );
+                            $ifacedone->{$iface} = 1;
+                        }
+                    }
+                }
+                if ( defined $host_parsed->{$iface} ) {
+                }
+            }
+        }
+        elsif ( $key eq 'alias' ) {
+            foreach my $alias ( keys %{ $host_parsed->{$key} } ) {
+                $new_host->{ 'alias.' . $alias }
+                    = $host_parsed->{$key}->{$alias};
+            }
+        }
+    }
+    return $new_host;
+}
+sub __addvlinksection {
+    my ( $host_parsed, $new_host, $vlan, $iface ) = @_;
+
+    if ( defined $host_parsed->{'ipstart'}->{$vlan} ) {
+        $new_host->{ 'ipv4.' . $vlan }
+            = $host_parsed->{'ipstart'}->{$vlan};
+    }
+    elsif ( defined $host_parsed->{'ip'}->{$vlan} ) {
+        foreach my $subkey ( keys %{ $host_parsed->{'ip'}->{$vlan} } ) {
+            if ( $subkey eq 'default'
+                && !defined $new_host->{ 'ipv4.' . $vlan } )
+            {
+                $new_host->{ 'ipv4.' . $vlan }
+                    = $host_parsed->{'ip'}->{$vlan}->{$subkey};
+            }
+            else {
+                $new_host->{ 'ipv4.' . $vlan . q{.} . $subkey}
+                    = $host_parsed->{'ip'}->{$vlan}->{$subkey};
+            }
+        }
+    }
+    else {
+        $new_host->{ 'ipv4.' . $vlan }
+            = $host_parsed->{'ipstart'}->{'default'};
+    }
+    return;
+}
+
+
+sub __addlinksection {
+    my ( $host_parsed, $new_host, $vlan, $iface ) = @_;
+
+    if ( defined $host_parsed->{'ipstart'}->{$vlan} ) {
+        $new_host->{ 'link::' . $vlan }->{'ipv4'}
+            = $host_parsed->{'ipstart'}->{$vlan};
+    }
+    elsif ( defined $host_parsed->{'ip'}->{$vlan} ) {
+        foreach my $subkey ( keys %{ $host_parsed->{'ip'}->{$vlan} } ) {
+            if ( $subkey eq 'default'
+                && !defined $new_host->{ 'link::' . $vlan }->{'ipv4'} )
+            {
+                $new_host->{ 'link::' . $vlan }->{'ipv4'}
+                    = $host_parsed->{'ip'}->{$vlan}->{$subkey};
+            }
+            else {
+                $new_host->{ 'link::' . $vlan }->{ 'ipv4.' . $subkey }
+                    = $host_parsed->{'ip'}->{$vlan}->{$subkey};
+            }
+        }
+    }
+    else {
+        $new_host->{ 'link::' . $vlan }->{'ipv4'}
+            = $host_parsed->{'ipstart'}->{'default'};
+    }
+    return;
+}
+
+sub __addroutetolink {
+    my ( $host_parsed, $new_host, $vlan, $iface ) = @_;
+
+    if ( defined $host_parsed->{$iface} ) {
+        foreach my $route ( keys %{ $host_parsed->{$iface} } ) {
+
+            # if no hash => default gateway ???
+            if ( ref $host_parsed->{$iface}->{$route} eq 'HASH' ) {
+                foreach
+                    my $subkey ( keys %{ $host_parsed->{$iface}->{$route} } )
+                {
+                    if ( $subkey eq 'default' ) {
+                        push @{ $new_host->{ 'link::' . $vlan }->{'@route'} },
+                            $host_parsed->{$iface}->{$route}->{$subkey};
+                    }
+                    else {
+                        push @{ $new_host->{ 'link::' . $vlan }
+                                ->{ '@route.' . $subkey } },
+                            $host_parsed->{$iface}->{$route}->{$subkey};
+                    }
+                }
+            }
+        }
+    }
+    return;
+}
+
+sub __addbondtolink {
+    my ( $host_parsed, $new_host, $vlan, $iface ) = @_;
+    if ( $iface =~ /\A bond/xms ) {
+        if ( ref $host_parsed->{'bonding'}->{$iface} eq 'HASH' ) {
+            foreach
+                my $subkey ( keys %{ $host_parsed->{'bonding'}->{$iface} } )
+            {
+                if ( $subkey eq 'default' ) {
+                    $new_host->{ 'link::' . $vlan }->{'slaves'}
+                        = $host_parsed->{'bonding'}->{$iface}->{$subkey};
+                }
+                else {
+                    $new_host->{ 'link::' . $vlan }->{ 'slaves.' . $subkey }
+                        = $host_parsed->{'bonding'}->{$iface}->{$subkey};
+                }
+            }
+        }
+        else {
+            $new_host->{ 'link::' . $vlan }->{'slaves'}
+                = $host_parsed->{'bonding'}->{$iface};
+        }
+        my $ref_cmdline = {};
+        if ( ref $host_parsed->{'cmdline'} eq 'HASH' ) {
+            $ref_cmdline = $host_parsed->{'cmdline'};
+        }
+        else {
+            $ref_cmdline->{'default'} = $host_parsed->{'cmdline'};
+        }
+        foreach my $cmdline ( keys %{$ref_cmdline} ) {
+            my $newcmd_key
+                = ( $cmdline eq 'default' )
+                ? 'cmdline'
+                : 'cmdline.' . $cmdline;
+            my $newopt_key
+                = ( $cmdline eq 'default' )
+                ? 'options'
+                : 'options.' . $cmdline;
+            my $newmode_key
+                = ( $cmdline eq 'default' )
+                ? 'mode'
+                : 'mode.' . $cmdline;
+            foreach my $cmd ( split /[ ]/xms, $ref_cmdline->{$cmdline} ) {
+                if ( $cmd =~ /\A bonding[.](.+) \z/xms ) {
+                    my ( $opt, $val ) = split /=/xms, $1;
+                    if ( $opt eq 'mode' ) {
+                        $new_host->{ 'link::' . $vlan }->{$newmode_key}
+                            = $val;
+                    }
+                    else {
+                        $new_host->{ 'link::' . $vlan }->{$newopt_key}
+                            = $opt . q{=} . $val . q{ };
+                    }
+                }
+                else {
+                    $new_host->{'boot'}->{$newcmd_key} .= $cmd . q{ };
+                }
+            }
+            $new_host->{ 'link::' . $vlan }->{$newopt_key} =~ s/\s*$//;
+            if ( $new_host->{'boot'}->{$newcmd_key} ) {
+                $new_host->{'boot'}->{$newcmd_key} =~ s/\s*$//;
+            }
+        }
+    }
+    return;
+}
+
 1;
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/Conf.pm
--- a/lib/PFTools/Conf.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/Conf.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -1,25 +1,36 @@
 package PFTools::Conf;
 
-#
-#  Copyright (C) 2007-2010 Christophe Caillet <quadchris at free.fr>
-#  Copyright (C) 2005-2007 Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
-#  Copyright (C) 2003-2005 Damien Clermonte <damien at sitadelle.com>
-#  Copyright (C) 2001-2003 Olivier Molteni <olivier at molteni.net>
-#
-#  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
-#
+=head1 NAME
+
+PFTools::Conf - PF-Tools Configuration handling
+
+=head1 DESCRIPTION
+
+This module exports functions handling the reading and parsing of the
+configuration files.
+
+=head1 LICENSE AND COPYRIGHT
+
+ Copyright (C) 2007-2010 Christophe Caillet <quadchris at free.fr>
+ Copyright (C) 2005-2007 Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
+ Copyright (C) 2003-2005 Damien Clermonte <damien at sitadelle.com>
+ Copyright (C) 2001-2003 Olivier Molteni <olivier at molteni.net>
+
+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
+
+=cut
 
 use strict;
 use warnings;
@@ -59,16 +70,7 @@
 
 our @EXPORT_OK = qw();
 
-=head1 NAME
-
-PFTools::Conf - PF-Tools Configuration handling
-
-=head1 DESCRIPTION
-
-This module exports functions handling the reading and parsing of the
-configuration files.
-
-=head1 INTERFACE
+=head1 SUBROUTINES/METHODS
 
 This module defines the following functions:
 
@@ -98,7 +100,7 @@
         'user'     => 'cvsguest',
         'password' => q{},
         'method'   => 'rsh',
-        'rsh'      => '/usr/local/sbin/cvs_rsh',
+        'rsh'      => '/usr/sbin/cvs_rsh',
         'server'   => 'cvs.private',
         'vcsroot'  => '/var/lib/cvs/repository',
         'module'   => 'config',
@@ -362,8 +364,7 @@
     $result =~ s{ \A SITE [:] }{$vcs_work_dir/$module/SITE/}xms;
     $result
         =~ s{ \A HOSTSITE_([^:]+) [:] }{$vcs_work_dir/$module/SITE/$1/%HOSTTYPE%/}xms;
-    $result
-        =~ s{ \A HOST [:] }{$vcs_work_dir/$module/%HOSTTYPE%/}xms;
+    $result =~ s{ \A HOST [:] }{$vcs_work_dir/$module/%HOSTTYPE%/}xms;
     $result =~ s{ \A COMMON [:] }{$vcs_work_dir/$module/COMMON/}xms;
     $result =~ s{ \A CONFIG [:] }{$vcs_work_dir/$module/}xms;
     $result =~ s{ \A CVS [:] }{$vcs_work_dir/}xms;
@@ -442,15 +443,13 @@
             my $section_type = $parsed->{$section}->{$action_or_type};
             unless ($section_type) {
                 croak
-                    qq{Key $action_or_type must be defined in file $file section $section};
+                    qq{ERROR: Key '$action_or_type' must be defined in file '$file' section [$section]};
             }
 
             if ( $section_type eq 'include' ) {
                 $parsed->{$section}->{'__content'}
-                    = Load_conf(
-                    $section, $hash_subst, $context,
-                    $pf_config
-                    );
+                    = Load_conf( $section, $hash_subst, $context,
+                    $pf_config );
             }
         }
     }
@@ -504,8 +503,7 @@
 
     my $net_parsed
         = Load_conf( $start_file, $hash_subst, 'network', $pf_config );
-    my @sortnetkeys
-        = sort { __sort_net_section( $net_parsed, $a, $b ) }
+    my @sortnetkeys = sort { __sort_net_section( $net_parsed, $a, $b ) }
         @{ $net_parsed->{'__sections_order'} };
 
     my %add_function_for = (
@@ -638,12 +636,9 @@
     }
 
     # Common configuration file e.g. update-common
-    my $global_host_conf = Load_conf(
-        'COMMON:/' . $pf_config->{'path'}->{'common_config'},
-        $hash_subst,
-        'config',
-        $pf_config
-    );
+    my $global_host_conf
+        = Load_conf( 'COMMON:/' . $pf_config->{'path'}->{'common_config'},
+        $hash_subst, 'config', $pf_config );
     my $hosttype
         = get_hosttype_from_hostname( $hostname, $global_config, $site );
 
@@ -799,25 +794,21 @@
         my $tmp_merged
             = __Merge_conf_includes(
             $hash_to_merge->{$section}->{'__content'},
-            $hash_subst, $context
-            );
+            $hash_subst, $context );
         foreach my $tomerge_section ( @{ $tmp_merged->{'__sections_order'} } )
         {
             if ( defined $global_parsed->{$tomerge_section} ) {
-                if (!defined $tmp_merged->{$tomerge_section}->{'override'}
+                if ( !defined $tmp_merged->{$tomerge_section}->{'override'}
                     || $tmp_merged->{$tomerge_section}->{'override'} ne
-                    'replace'
-                    )
+                    'replace' )
                 {
-                    Warn(
-                        $CODE->{'WARNING'},
+                    Warn( $CODE->{'WARNING'},
                         "Section $tomerge_section from file $section already defined ... skipping it\n"
                     );
                     next;
                 }
                 else {
-                    Warn(
-                        $CODE->{'WARNING'},
+                    Warn( $CODE->{'WARNING'},
                         "Section $tomerge_section already defined but override is set to replace ... overriding it\n"
                     );
 
@@ -866,7 +857,7 @@
 
 =head2 __add_service($args)
 
-This function does the necessary magic (including calling C<add_host()>) for each
+This function does the necessary magic (including calling L<add_host()>) for each
 host composing a service. I<$args> is a reference to a hash containing the
 following named parameters :
 
@@ -906,7 +897,8 @@
         qw( start_file section_name section_ref global_config pf_config hash_subst )
         };
 
-    my $site_list = get_site_list_from_section( $section_ref, $global_config );
+    my $site_list
+        = get_site_list_from_section( $section_ref, $global_config );
     foreach my $site ( @{$site_list} ) {
         my $site_ref = get_site_config( $site, $global_config );
         my $service_part = $site_ref->{'SERVICE'}->{'BY_NAME'};
@@ -916,8 +908,7 @@
             my $host_parsed
                 = Load_conf( $hostfile, $hash_subst, q{host}, $pf_config );
             add_host(
-                {
-                    start_file    => $hostfile,
+                {   start_file    => $hostfile,
                     host_type     => q{host},
                     host_ref      => $host_parsed,
                     global_config => $global_config,
@@ -958,15 +949,13 @@
             $section_type = $parsed->{$section}->{$action_or_type};
             unless ($section_type) {
                 croak
-                    qq{Key $action_or_type must be defined in file $file section $section};
+                    qq{ERROR: Key '$action_or_type' must be defined in file '$file' section [$section]};
             }
         }
 
         # Run the real checks
-        check_section_structure(
-            $section, $section_type, $parsed->{$section},
-            $context, $file
-        );
+        check_section_structure( $section, $section_type, $parsed->{$section},
+            $context, $file );
     }
 
     return;
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/Conf/Host.pm
--- a/lib/PFTools/Conf/Host.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/Conf/Host.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -1,23 +1,31 @@
 package PFTools::Conf::Host;
 
-#
-#  Copyright (C) 2013 Richard Phan <richard.phan.prestataire at sfr.fr>
-#  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
-#
+=head1 NAME
+
+PFTools::Conf::Host - FIXME
+
+=head1 LICENSE AND COPYRIGHT
+
+ Copyright (C) 2013 Richard Phan <richard.phan.prestataire at sfr.fr>
+ 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
+
+=head1 SUBROUTINES/METHODS
+
+=cut
 
 use strict;
 use warnings;
@@ -47,32 +55,22 @@
 Readonly::Scalar my $ALPHANUM_CARDINAL => 26;
 Readonly::Scalar my $DIGITS_CARDINAL   => 10;
 
-=head2 add_host($args)
+=head2 add_host()
 
-This function adds a host to the global configuration. $args is a reference to
-a hash containing the following named parameters:
+This function adds a host to the global configuration.
+It takes the following named arguments:
 
 =over
 
-=item I<start_file>
+=item I<start_file> Filename containing the host definition
 
-Filename containing the host definition
+=item I<section_name> The host name
 
-=item I<section_name>
+=item I<section_ref> Reference to a hash containing the parsed host
 
-The host name
+=item I<global_config> Reference to the global configuration hash (the host will be added in this hash)
 
-=item I<section_ref>
-
-Reference to a hash containing the parsed host
-
-=item I<global_config>
-
-Reference to the global configuration hash (the host will be added in this hash)
-
-=item I<pf_config>
-
-Reference to the pf-tools configuration hash
+=item I<pf_config> Reference to the pf-tools configuration hash
 
 =back
 
@@ -91,8 +89,8 @@
     my $dep_def  = $DEF_SECTIONS->{'host'}->{'deployment'};
 
     my $hostname_model = $host_ref->{'hostgroup'}->{'hostname'};
-    unless ( $hostname_model
-        =~ m{ \A $pf_config->{'regex'}->{'hostname_model'} \z }xms )
+    if ( $hostname_model
+        !~ m{ \A $pf_config->{'regex'}->{'hostname_model'} \z }xms )
     {
         croak qq{Invalid hostname model name $hostname_model};
     }
@@ -107,7 +105,7 @@
     foreach my $site ( @{$site_list} ) {
         my $site_part_ref = get_site_config( $site, $global_config );
 
-        unless ( $site_part_ref->{'HOST'}->{'BY_NAME'}->{$hostclass} ) {
+        if ( !$site_part_ref->{'HOST'}->{'BY_NAME'}->{$hostclass} ) {
             $site_part_ref->{'HOST'}->{'BY_NAME'}->{$hostclass} = {};
             if ( $host_type eq 'host' ) {
                 push @{ $site_part_ref->{'HOST'}->{'__hostclass_pxe'} },
@@ -128,7 +126,7 @@
             }
         );
         my @link_list = __get_host_links($host_ref);
-        
+
         foreach my $hostname ( sort keys %{$host_list} ) {
             my $host_number = $host_list->{$hostname}->{'host_number'};
             my $index       = $host_list->{$hostname}->{'index'};
@@ -139,7 +137,7 @@
                 || $host_ref->{'deployment'}->{'dhcpvlan'}
                 || $site_part_ref->{'dhcpvlan'};
 
-            unless ( $site_part_ref->{'NETWORK'}->{'BY_NAME'}->{$dhcpvlan} ) {
+            if ( !$site_part_ref->{'NETWORK'}->{'BY_NAME'}->{$dhcpvlan} ) {
                 croak qq{ERROR: Unknown DHCP vlan $dhcpvlan for $hostname};
             }
 
@@ -161,7 +159,7 @@
             }
 
             # Check interfaces
-            
+
             foreach my $link (@link_list) {
                 my $new_iface_ref = __build_iface_entry(
                     {   link_name     => $link,
@@ -183,7 +181,7 @@
                         \A
                             (
                                 (eth|bond)[\d]+)
-                                (\.(TAG[\d]+)
+                                ([.](TAG[\d]+)
                             )
                 
                         \z
@@ -270,6 +268,13 @@
                             }
                         );
                     }
+                    if (defined $global_config->{'PUBLIC_NETWORK'}
+                        ->{ $new_iface_ref->{'vlan'} } )
+                    {
+                        $global_config->{'PUBLIC_NETWORK'}
+                            ->{ $new_iface_ref->{'vlan'} }->{$hostname}
+                            = $site;
+                    }
                 }
             }
         }
@@ -278,33 +283,22 @@
     return;
 }
 
-=head2 add_server($arguments_ref)
+=head2 add_server()
 
-Build a host definition from a server definition, then call C<add_host()>.
-I<$arguments_ref> is a reference to a hash containing the following named
-parameters :
+Build a host definition from a server definition, then call L</add_host()>.
+It takes the following named arguments:
 
 =over
 
-=item I<start_file>
+=item I<start_file> Filename containing the server definition
 
-Filename containing the server definition
+=item I<section_name> The server name
 
-=item I<section_name>
+=item I<section_ref> Reference to a hash containing the parsed server
 
-The server name
+=item I<global_config> Reference to the global configuration hash (the server will be added in this hash)
 
-=item I<section_ref>
-
-Reference to a hash containing the parsed server
-
-=item I<global_config>
-
-Reference to the global configuration hash (the server will be added in this hash)
-
-=item I<pf_config>
-
-Reference to the pf-tools configuration hash
+=item I<pf_config> Reference to the pf-tools configuration hash
 
 =back
 
@@ -317,7 +311,7 @@
         $global_config, $pf_config
         )
         = @{$arguments_ref}
-        { qw( start_file section_name section_ref global_config pf_config ) };
+        {qw( start_file section_name section_ref global_config pf_config )};
 
     my $host_ref = __build_host_from_server( $section_name, $section_ref );
 
@@ -332,6 +326,10 @@
     return add_host($add_host_args_ref);
 }
 
+=head1 INTERNAL INTERFACE
+
+This module defines the following internal (not exported) functions:
+
 =head2 __get_site_prefix ( $site_name, $site_ref )
 
 This function returns the site's prefix value, or an empty string.
@@ -373,12 +371,14 @@
 
 =item I<$hostname_model> is the host model name
 
+=back
+
 =cut
 
 sub __get_host_indexes {
     my ( $hostgroup_ref, $hostname_model ) = @_;
 
-    unless ( $hostgroup_ref and $hostname_model ) {
+    if ( !$hostgroup_ref || !$hostname_model ) {
         croak q{ERROR: $hostgroup_ref and $hostname_model are mandatory};
     }
     if ( ref $hostgroup_ref ne 'HASH' ) {
@@ -506,9 +506,9 @@
             \A
             link::
             (
-                (?:		# name
-		    [^\s:]+
-		)
+                (?:     # name
+                    [^\s:]+
+                )
             )
             \z
         }xms;
@@ -539,12 +539,11 @@
     return @if_list;
 }
 
-=head2 __get_host_ip($arguments_ref)
+=head2 __get_host_ip()
 
 This function returns a NetAddr::IP object representing the host IP address
 for a given number and node.
-
-I<$arguments_ref> is a reference to a hash of named parameters:
+It takes the following named arguments:
 
 =over
 
@@ -564,6 +563,8 @@
 
 =item I<site_ref> a reference to the site definition hash
 
+=back
+
 =cut
 
 sub __get_host_ip {
@@ -577,14 +578,18 @@
         $hostnode, $nodes,      $site_name, $site_ref
     ) = @{$arguments_ref}{@argument_names};
 
-    unless ( ref $subnet_ref eq 'NetAddr::IP' ) {
-        croak q{ERROR: Invalid $subnet_ref object};
+    if ( ref $subnet_ref ne 'NetAddr::IP' ) {
+        croak q{ERROR: Invalid subnet_ref object};
     }
 
-    my $ip_address = NetAddr::IP->new( $subnet_ref->prefix() . $ipstart,
-        $subnet_ref->mask() );
-    unless ($ip_address) {
-        croak qq{ERROR: Invalid IP with $subnet_ref->prefix() and $ipstart};
+    # for some network, NetAddr::IP->prefix() return a range
+    # something like '109.3.20.225-255'
+    my $prefix = $subnet_ref->prefix();
+    $prefix =~ s{ \d+-[\d.]+ }{}xms;
+    my $ip_address
+        = NetAddr::IP->new( $prefix . $ipstart, $subnet_ref->mask() );
+    if ( !$ip_address ) {
+        croak qq{ERROR: Invalid IP with $prefix and $ipstart};
     }
 
     if ($hostnum) {
@@ -594,12 +599,15 @@
 
     my $host_addr_site = $site_ref->{'HOST'}->{'BY_ADDR'};
     if ( defined $host_addr_site->{ $ip_address->cidr() } ) {
-        croak
-            qq{ERROR: $ip_address->addr() already defined on site $site_name};
+        croak q{ERROR: }
+            . $ip_address->addr()
+            . qq{ already defined on site $site_name};
     }
-    unless ( $subnet_ref->contains($ip_address) ) {
-        croak
-            qq{ERROR: $ip_address->addr() is out of range $subnet_ref->cidr()};
+    if ( !$subnet_ref->contains($ip_address) ) {
+        croak q{ERROR: }
+            . $ip_address->addr()
+            . q{ is out of range }
+            . $subnet_ref->cidr();
     }
 
     return $ip_address;
@@ -636,11 +644,11 @@
 
     my $result = { hostgroup => { hostname => $server_name, }, };
     my $constant_keys = {
-        'comment'   => 1,
-        'order'     => 1,
-        'number'    => 1,
-        'nodes'     => 1,
-        'site'      => 1,
+        'comment' => 1,
+        'order'   => 1,
+        'number'  => 1,
+        'nodes'   => 1,
+        'site'    => 1,
     };
 
     my $iface_index = 0;
@@ -678,10 +686,10 @@
     return $result;
 }
 
-=head2 __build_iface_entry($arguments_ref)
+=head2 __build_iface_entry()
 
 This functions builds the configuration structure for a given host interface.
-I<$arguments_ref> references a hash of named arguments:
+It takes the following named arguments:
 
 =over
 
@@ -703,6 +711,8 @@
 
 =item I<pf_config> a reference to the global pf-tools configuration hash
 
+=back
+
 =cut
 
 sub __build_iface_entry {
@@ -713,9 +723,9 @@
         hostnode    host_ref   link_list_ref
         site_name   site_ref   pf_config
     );
-    my ($link_name,   $hostname,   $hostnum,
-        $hostnode,    $host_ref,   $link_list_ref,
-        $site_name,   $site_ref,   $pf_config
+    my ($link_name, $hostname, $hostnum,
+        $hostnode,  $host_ref, $link_list_ref,
+        $site_name, $site_ref, $pf_config
     ) = @{$arguments_ref}{@argument_names};
 
     my $net_site_ref      = $site_ref->{'NETWORK'}->{'BY_NAME'};
@@ -728,17 +738,16 @@
 
     # Check vlan
     my $vlan_name = $link_name;
-    my $vlan_ref = $net_site_ref->{$vlan_name};
-    unless ($vlan_ref) {
+    my $vlan_ref  = $net_site_ref->{$vlan_name};
+    if ( !$vlan_ref ) {
         croak
-            qq{ERROR: site $site_name host $hostname: unknown $vlan_name for $link_name};
+            qq{ERROR: site '$site_name' host '$hostname': unknown vlan '$vlan_name' for link '$link_name'};
     }
 
     my $result = { 'vlan' => $vlan_name, };
 
     # Links option(s)
-    if ( my $link_options
-         = $link_section_ref->{ 'options.' . $host_number }
+    if ( my $link_options = $link_section_ref->{ 'options.' . $host_number }
         || $link_section_ref->{'options'} )
     {
         $result->{'options'} = $link_options;
@@ -781,7 +790,7 @@
             qq{ERROR: $iface_tag for $link_section_name differs from $vlan_name def};
     }
 
-    # Bondig "master interface"?
+    # Bonding "master interface"?
     if ( $iface_name =~ m{ \A bond }xms and not $iface_tag ) {
 
         # Check if slaves are not in use
@@ -852,6 +861,35 @@
     return $result;
 }
 
+=head2 __get_host_real_ip()
+
+This functions return the real ip of the host by calling L</__get_host_ip()>.
+It takes the following named arguments:
+
+=over
+
+=item I<ip_type> ipv4 or ipv6
+
+=item I<host_number> FIXME
+
+=item I<link_section_ref> FIXME
+
+=item I<hostnum> the host number
+
+=item I<hostnode> the host node
+
+=item I<nodes> number of nodes for this hostclass
+
+=item I<subnet_ref> NetAddr::IP object representing the subnet
+
+=item I<site_name> the site name
+
+=item I<site_ref> a reference to the I<site> configuration hash
+
+=back
+
+=cut
+
 sub __get_host_real_ip {
     my ($arguments_ref) = @_;
 
@@ -890,10 +928,10 @@
     return $real_ip->cidr();
 }
 
-=head2 __get_route($arguments_ref)
+=head2 __get_route()
 
 This function builds the translated route string.
-Its named arguments are:
+It takes the following named arguments:
 
 =over
 
@@ -914,6 +952,8 @@
 =item I<subnet_ref> a NetAddr::IP object representing the IP range associated
 to the I<vlan_name> vlan
 
+=back
+
 =cut
 
 sub __get_route {
@@ -977,7 +1017,7 @@
     }
 
     # $destination is clearly not an IP address or address/prefix
-    if ( $destination =~ m{ [a-zA-Z]+ }xms ) {
+    if ( $destination =~ m{ [[:alpha:]]+ }xms ) {
 
         # $destination is a known network, translate it to CIDR notation
         if ( $net_site_ref->{$destination} ) {
@@ -995,19 +1035,18 @@
 
     # $destination must be an IP address or address/prefix
     my $ip_dest = NetAddr::IP->new($destination);
-    unless ($ip_dest) {
+    if ( !$ip_dest ) {
         croak qq{ERROR: host $hostname: bad route destination $destination};
     }
 
     return $ip_dest->cidr();
 }
 
-=head2 __build_route_gateway($arguments_ref)
+=head2 __build_route_gateway()
 
 This functions verifies the gateway I<$via> and possibly translates it to an
 IP address.
-
-The named arguments are:
+It takes the following named arguments:
 
 =over
 
@@ -1043,7 +1082,7 @@
     # 'GATEWAY' means "the known gateway for this vlan"
     if ( $via eq 'GATEWAY' ) {
         my $gateway = $net_site_ref->{$vlan_name}->{$gw_key};
-        unless ($gateway) {
+        if ( !$gateway ) {
             croak qq{ERROR: Host $hostname: unknown gateway for $vlan_name};
         }
 
@@ -1051,16 +1090,16 @@
     }
 
     # $via is clearly not an IP address, leave it as-is
-    if ( $via =~ m{ [a-zA-Z]+ }xms ) {
+    if ( $via =~ m{ [[:alpha:]]+ }xms ) {
         return $via;
     }
 
     # $via must be an IP address
     my $ip_via = NetAddr::IP->new($via);
-    unless ($ip_via) {
+    if ( !$ip_via ) {
         croak qq{ERROR: host $hostname: bad route gateway $via};
     }
-    unless ( $subnet_ref->contains($ip_via) ) {
+    if ( !$subnet_ref->contains($ip_via) ) {
         croak
             qq{ERROR: host $hostname: gateway $ip_via is not in $subnet_ref->cidr()};
     }
@@ -1068,9 +1107,32 @@
     return $ip_via->addr();
 }
 
-=head2 __add_dhcp_entry( $arguments_ref )
+=head2 __add_dhcp_entry()
 
 This function adds the DHCP configuration for a host.
+It takes the following named arguments:
+
+=over
+
+=item I<dhcp_part_ref> FIXME
+
+=item I<dhcp_vlan> FIXME
+
+=item I<resolver> FIXME
+
+=item I<hostname> the host name
+
+=item I<hostclass> FIXME
+
+=item I<ip_type> ipv4 or ipv6
+
+=item I<vlan_def_ref> FIXME
+
+=item I<iface_def_ref> FIXME
+
+=item I<pxefilename> FIXME
+
+=back
 
 =cut
 
@@ -1088,7 +1150,7 @@
     ) = @{$arguments_ref}{@argument_names};
 
     my $ip_type_suffix = get_suffix_from_ip_type($ip_type);
-    unless ( $dhcp_part_ref->{$dhcp_vlan} ) {
+    if ( !$dhcp_part_ref->{$dhcp_vlan} ) {
         $dhcp_part_ref->{$dhcp_vlan} = {
             'subnet'  => $vlan_def_ref->{"network$ip_type_suffix"},
             'netmask' => $vlan_def_ref->{"netmask$ip_type_suffix"},
@@ -1097,21 +1159,55 @@
     }
 
     ( my $fixed_addr = $iface_def_ref->{$ip_type} )
-        =~ s{ [/] [\d]+ \z }{}xms;    # remove CIDE prefix size
+        =~ s{ [/] [\d]+ \z }{}xms;    # remove CIDR prefix size
 
-    $dhcp_part_ref->{$dhcp_vlan}->{$hostclass}->{$hostname} = [
-        qq/hardware ethernet $iface_def_ref->{'mac'};/,
-        qq/fixed-address $fixed_addr;/,
-        qq/filename $pxefilename;/,
-        qq/option domain-name-servers $resolver;/,
-    ];
+    $dhcp_part_ref->{$dhcp_vlan}->{$hostclass}->{$hostname} = {
+        hardware    => $iface_def_ref->{'mac'},
+        fixed_addr  => $fixed_addr,
+        pxefilename => $pxefilename,
+        resolver    => $resolver,
+    };
 
     return;
 }
 
-=head2 __add_zone_entry($arguments_ref)
+=head2 __add_zone_entry()
 
 This function adds the host information to the zone hash.
+It takes the following named arguments:
+
+=over
+
+=item I<hostname> the host name
+
+=item I<hostclass> FIXME
+
+=item I<host_number> FIXME
+
+=item I<host_part_ref> a reference to the host part in the global
+configuration structure
+
+=item I<iface_def> FIXME
+
+=item I<zone_part_ref> FIXME
+
+=item I<dns_def_ref> FIXME
+
+=item I<ip_type> ipv4 or ipv6
+
+=item I<zone_name> FIXME
+
+=item I<shortname> FIXME
+
+=item I<site> FIXME
+
+=item I<global_config> Reference to the global configuration hash
+
+=item I<index> FIXME
+
+
+=back
+
 
 =cut
 
@@ -1130,11 +1226,11 @@
         $index
     ) = @{$arguments_ref}{@argument_names};
 
-    unless ($hostname) {
-        croak q{ERROR: $hostname is mandatory};
+    if ( !$hostname ) {
+        croak q{ERROR: hostname is mandatory};
     }
-    unless ($hostclass) {
-        croak q{ERROR: $hostclass is mandatory};
+    if ( !$hostclass ) {
+        croak q{ERROR: hostclass is mandatory};
     }
 
     ( my $zone_ip = $iface_def->{$ip_type} )
@@ -1142,9 +1238,9 @@
 
     my $zone_key = ( $ip_type eq 'ipv6' ) ? 'ZONE6' : 'ZONE';
 
-    my $vlan        = $iface_def->{'vlan'};
-    my $zone_entry  = 
-        ( is_private_vlan ($vlan, $global_config, $site) )
+    my $vlan = $iface_def->{'vlan'};
+    my $zone_entry
+        = ( is_private_vlan( $vlan, $global_config, $site ) )
         ? $zone_part_ref->{'BY_SITE'}->{$site}
         : $zone_part_ref->{'ALL_SITES'};
 
@@ -1152,15 +1248,14 @@
         = any { $_ eq $hostclass } @{ $zone_entry->{'__hostclass_order'} };
 
     if ( not $zone_entry->{$hostclass} and not $hostclass_already_added ) {
-        push @{ $zone_entry->{'__hostclass_order'} },
-            $hostclass;
+        push @{ $zone_entry->{'__hostclass_order'} }, $hostclass;
     }
 
     $zone_entry->{$hostclass}->{"$hostname\.$vlan"} = "A\t$zone_ip";
 
     my $shortname_vlan = $dns_def_ref->{"shortname\.$host_number"}
         || $dns_def_ref->{'shortname'};
-    unless ($shortname_vlan) {
+    if ( !$shortname_vlan ) {
         croak qq{ERROR: hostname $hostname: shortname is mandatory};
     }
 
@@ -1169,7 +1264,8 @@
             $zone_entry->{$hostclass}->{"$shortname\.$vlan"}
                 = [ "A\t$zone_ip", ];
 
-            $zone_entry->{$hostclass}->{"$hostname"} = qq{CNAME\t$hostname.$vlan};
+            $zone_entry->{$hostclass}->{"$hostname"}
+                = qq{CNAME\t$hostname.$vlan};
         }
         else {
             push @{ $zone_entry->{$hostclass}->{"$shortname\.$vlan"} },
@@ -1177,7 +1273,8 @@
             $zone_entry->{$hostclass}->{$shortname}
                 = qq{CNAME\t$shortname.$vlan};
 
-            $zone_entry->{$hostclass}->{"$hostname"} = qq{CNAME\t$hostname.$vlan};
+            $zone_entry->{$hostclass}->{"$hostname"}
+                = qq{CNAME\t$hostname.$vlan};
         }
     }
 
@@ -1213,10 +1310,10 @@
     my $result = {};
 
     # Checking path for PXE elements kernel, initrd ...
-    my $boot_def = $DEF_SECTIONS->{'host'}->{'boot'};
+    my $boot_def      = $DEF_SECTIONS->{'host'}->{'boot'};
     my $excluded_keys = {
-        'console'   => 1,
-        'cmdline'   => 1,
+        'console' => 1,
+        'cmdline' => 1,
     };
 
 BOOT_KEY:
@@ -1235,7 +1332,7 @@
 
         # This check should be done only on the deploy hosts
         if ($hostname =~ m{ \A $pf_config->{'regex'}->{'deploy_hosts'} \z }xms
-            and $excluded_keys->{$key})
+            and $excluded_keys->{$key} )
         {
             my $filename = "$pf_config->{'path'}->{'tftp_dir'}/$value";
             carp qq{WARNING: host $hostname: $filename doesn't exist};
@@ -1256,13 +1353,13 @@
 sub __build_deployment_entry_for_host {
     my ( $type, $host_part_ref, $hostclass, $host_number, $dhcpvlan ) = @_;
 
-    unless ( $type and $host_part_ref and $hostclass ) {
+    if ( !$type || !$host_part_ref || !$hostclass ) {
         croak q{ERROR: one or more parameter is not defined};
     }
     if ( ref $type or ref $hostclass ) {
         croak q{ERROR: $type and/or $hostclass MUST BE a string};
     }
-    unless ( ref $host_part_ref eq 'HASH' ) {
+    if ( ref $host_part_ref ne 'HASH' ) {
         croak q{ERROR: non-hashref $host_part_ref};
     }
 
@@ -1287,11 +1384,10 @@
     return $result;
 }
 
-=head2 __build_host_list($arguments_ref)
+=head2 __build_host_list()
 
 Builds a hash of hosts for a given model, returns a reference to this hash.
-$arguments_ref is a reference to a hash structure containing the following
-keys:
+It takes the following named arguments:
 
 =over
 
@@ -1351,4 +1447,3 @@
 }
 
 1;    # Magic true value required at end of module
-
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/Conf/Network.pm
--- a/lib/PFTools/Conf/Network.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/Conf/Network.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -1,25 +1,33 @@
 package PFTools::Conf::Network;
 
-#
-#  Copyright (C) 2007-2009 Christophe Caillet <quadchris at free.fr>
-#  Copyright (C) 2005-2007 Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
-#  Copyright (C) 2003-2005 Damien Clermonte <damien at sitadelle.com>
-#  Copyright (C) 2001-2003 Olivier Molteni <olivier at molteni.net>
-#
-#  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
-#
+=head1 NAME
+
+PFTools::Conf::Network - FIXME
+
+=head1 LICENSE AND COPYRIGHT
+
+ Copyright (C) 2007-2009 Christophe Caillet <quadchris at free.fr>
+ Copyright (C) 2005-2007 Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
+ Copyright (C) 2003-2005 Damien Clermonte <damien at sitadelle.com>
+ Copyright (C) 2001-2003 Olivier Molteni <olivier at molteni.net>
+
+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
+
+=head1 SUBROUTINES/METHODS
+
+=cut
 
 use strict;
 use warnings;
@@ -46,32 +54,22 @@
 
 Readonly::Scalar my $VLAN_MAXVALUE => 4095;
 
-=head2 add_zone($args)
+=head2 add_zone()
 
-This function adds a zone to the global configuration. $args is a reference to
-a hash containing the following named parameters:
+This function adds a zone to the global configuration.
+It takes the following named arguments:
 
 =over
 
-=item I<start_file>
+=item I<start_file> Filename containing the zone definition
 
-Filename containing the zone definition
+=item I<section_name> The zone name
 
-=item I<section_name>
+=item I<section_ref> Reference to a hash containing the parsed zone
 
-The zone name
+=item I<global_config> Reference to the global configuration hash (the zone will be added in this hash)
 
-=item I<section_ref>
-
-Reference to a hash containing the parsed zone
-
-=item I<global_config>
-
-Reference to the global configuration hash (the zone will be added in this hash)
-
-=item I<pf_config>
-
-Reference to the pf-tools configuration hash
+=item I<pf_config> Reference to the pf-tools configuration hash
 
 =back
 
@@ -80,12 +78,11 @@
 sub add_zone {
     my ($args) = @_;
 
-    my ($start_file, $section_name, $section_ref,
+    my ($start_file,    $section_name, $section_ref,
         $global_config, $pf_config
         )
-        = @{$args}{
-        qw( start_file section_name section_ref global_config pf_config )
-        };
+        = @{$args}
+        {qw( start_file section_name section_ref global_config pf_config )};
 
     foreach my $ip_type (qw( ipv4 ipv6 )) {
         next if not $pf_config->{'features'}->{$ip_type};
@@ -107,32 +104,22 @@
     return;
 }
 
-=head2 add_site($args)
+=head2 add_site()
 
-This function adds a site to the global configuration. $args is a reference to
-a hash containing the following named parameters:
+This function adds a site to the global configuration.
+It takes the following named arguments:
 
 =over
 
-=item I<start_file>
+=item I<start_file> Filename containing the site definition
 
-Filename containing the site definition
+=item I<section_name> The site name
 
-=item I<section_name>
+=item I<section_ref> Reference to a hash containing the parsed site
 
-The site name
+=item I<global_config> Reference to the global configuration hash (the site will be added in this hash)
 
-=item I<section_ref>
-
-Reference to a hash containing the parsed site
-
-=item I<global_config>
-
-Reference to the global configuration hash (the site will be added in this hash)
-
-=item I<pf_config>
-
-Reference to the pf-tools configuration hash
+=item I<pf_config> Reference to the pf-tools configuration hash
 
 =back
 
@@ -141,12 +128,11 @@
 sub add_site {
     my ($args) = @_;
 
-    my ($start_file, $section_name, $section_ref,
+    my ($start_file,    $section_name, $section_ref,
         $global_config, $pf_config
         )
-        = @{$args}{
-        qw( start_file section_name section_ref global_config pf_config )
-        };
+        = @{$args}
+        {qw( start_file section_name section_ref global_config pf_config )};
 
     if ( defined $global_config->{'SITE'}->{'BY_NAME'}->{$section_name} ) {
         carp qq{WARN: $section_name from $start_file already defined};
@@ -177,9 +163,7 @@
         'BY_NAME' => {},
         'BY_MAC'  => {},
     };
-    $site_part->{$section_name}->{'SERVICE'} = {
-        'BY_NAME' => {},
-    };
+    $site_part->{$section_name}->{'SERVICE'} = { 'BY_NAME' => {}, };
 
     push @{ $global_config->{'SITE'}->{'__site_list'} }, $section_name;
 
@@ -192,7 +176,7 @@
         my $zone_part = $global_config->{"ZONE$suffix"};
         my $dhcp_part = $global_config->{"DHCP$suffix"};
         my $addr_key  = "BY_ADDR$suffix";
-        unless ( $zone_part->{'BY_NAME'}->{$zone} ) {
+        if ( !$zone_part->{'BY_NAME'}->{$zone} ) {
             croak qq{ERROR: Unknown $zone from $start_file};
         }
 
@@ -211,32 +195,22 @@
     return;
 }
 
-=head2 add_network($args)
+=head2 add_network()
 
-This function adds a network to the global configuration. $args is a reference to
-a hash containing the following named parameters:
+This function adds a network to the global configuration.
+It takes the following named arguments:
 
 =over
 
-=item I<start_file>
+=item I<start_file> Filename containing the network definition
 
-Filename containing the network definition
+=item I<section_name> The network name
 
-=item I<section_name>
+=item I<section_ref> Reference to a hash containing the parsed network
 
-The network name
+=item I<global_config> Reference to the global configuration hash (the network will be added in this hash)
 
-=item I<section_ref>
-
-Reference to a hash containing the parsed network
-
-=item I<global_config>
-
-Reference to the global configuration hash (the network will be added in this hash)
-
-=item I<pf_config>
-
-Reference to the pf-tools configuration hash
+=item I<pf_config> Reference to the pf-tools configuration hash
 
 =back
 
@@ -245,19 +219,21 @@
 sub add_network {
     my ($args) = @_;
 
-    my ($start_file, $section_name, $section_ref,
+    my ($start_file,    $section_name, $section_ref,
         $global_config, $pf_config
         )
-        = @{$args}{
-        qw( start_file section_name section_ref global_config pf_config )
-        };
+        = @{$args}
+        {qw( start_file section_name section_ref global_config pf_config )};
 
     my $site_part = $global_config->{'SITE'};
     my $site_list
         = get_site_list_from_section( $section_ref, $global_config );
-    my $net2add = {
-        scope => $section_ref->{'scope'},
-    };
+
+    my $all_site_list = $global_config->{'SITE'}->{'__site_list'};
+    if ( $section_ref->{'scope'} eq q{public} ) {
+        $global_config->{'PUBLIC_NETWORK'}->{$section_name} = {};
+    }
+    my $net2add = { scope => $section_ref->{'scope'}, };
     if ( $section_ref->{'comment'} ) {
         $net2add->{'comment'} = $section_ref->{'comment'};
     }
@@ -283,15 +259,18 @@
         $net2add->{"netmask$suffix"} = $subnet_ref->mask();
 
         if ( my $gateway = $section_ref->{$gw_key} ) {
-            my $ip_gw = NetAddr::IP->new(
-                $subnet_ref->prefix() . $gateway,
-                $subnet_ref->mask()
-            );
-            unless ($ip_gw) {
+
+            # for some network, NetAddr::IP->prefix() return a range
+            # something like '109.3.20.225-255'
+            my $prefix = $subnet_ref->prefix();
+            $prefix =~ s{ \d+-[\d.]+ }{}xms;
+            my $ip_gw
+                = NetAddr::IP->new( $prefix . $gateway, $subnet_ref->mask() );
+            if ( !$ip_gw ) {
                 croak
                     qq{ERROR: Invalid $ip_type gateway $gateway in $section_name};
             }
-            unless ( $subnet_ref->contains($ip_gw) ) {
+            if ( !$subnet_ref->contains($ip_gw) ) {
                 croak qq{ERROR: $ip_gw->addr() is not in $subnet_ref->cidr()};
             }
             $net2add->{$gw_key} = $ip_gw->addr();
@@ -309,8 +288,7 @@
                 next;
             }
 
-            if ( $tag and $net_part->{'BY_TAG'}->{$tag} )
-            {
+            if ( $tag and $net_part->{'BY_TAG'}->{$tag} ) {
                 croak
                     qq{ERROR: File $start_file section $section_name: duplicate tag $tag};
             }
@@ -357,32 +335,26 @@
     return;
 }
 
-=head2 __add_network_in_zone_part($args)
+=head1 INTERNAL INTERFACE
+
+This module defines the following internal (not exported) functions:
+
+=head2 __add_network_in_zone_part()
 
 This function adds a network into the zone part of global configuration.
-$args is a reference to a hash containing the following named parameters:
+It takes the following named arguments:
 
 =over
 
-=item I<net_ref>
+=item I<net_ref> Reference to a hash containing the network to add
 
-Reference to a hash containing the network to add
+=item I<subnet_ref> NetAddr::IP object for the specified network
 
-=item I<subnet_ref>
+=item I<site_name> String containing the site name of the specified network
 
-NetAddr::IP object for the specified network
+=item I<net_name> String containing the network name of the specified network
 
-=item I<site_name>
-
-String containing the site name of the specified network
-
-=item I<net_name>
-
-String containing the network name of the specified network
-
-=item I<global_config>
-
-Reference to the global configuration hash (the network will be added in this hash)
+=item I<global_config> Reference to the global configuration hash (the network will be added in this hash)
 
 =back
 
@@ -391,10 +363,11 @@
 sub __add_network_in_zone_part {
     my ($args) = @_;
 
-    my ( $net_ref, $subnet_ref, $site_name, $ip_type, $net_name, $global_config )
-        = @{$args}{
-        qw( net_ref subnet_ref site_name ip_type net_name global_config )
-        };
+    my ($net_ref, $subnet_ref, $site_name,
+        $ip_type, $net_name,   $global_config
+        )
+        = @{$args}
+        {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 $site_ref  = get_site_config( $site_name, $global_config );
@@ -415,8 +388,7 @@
     }
 
     if ( is_private_vlan( $net_name, $global_config, $site_name ) ) {
-        push
-            @{ $zone_part->{'BY_SITE'}->{$site_name}->{'__network_order'} },
+        push @{ $zone_part->{'BY_SITE'}->{$site_name}->{'__network_order'} },
             $net_name;
         $zone_part->{'BY_SITE'}->{$site_name}->{$net_name} = $zone_ref;
     }
@@ -428,6 +400,4 @@
     return 1;
 }
 
-
 1;    # Magic true value required at end of module
-
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/Conf/Syntax.pm
--- a/lib/PFTools/Conf/Syntax.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/Conf/Syntax.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -1,23 +1,32 @@
 package PFTools::Conf::Syntax;
 
-#
-#  Copyright (C) 2013 Richard Phan <richard.phan.prestataire at sfr.fr>
-#  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
-#
+=head1 NAME
+
+PFTools::Conf::Syntax - FIXME
+
+=head1 LICENSE AND COPYRIGHT
+
+ Copyright (C) 2013 Richard Phan <richard.phan.prestataire at sfr.fr>
+ 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
+
+
+u=head1 SUBROUTINES/METHODS
+
+=cut
 
 use strict;
 use warnings;
@@ -135,8 +144,8 @@
     'host' => {
         'link' => {
             'MANDATORY_KEYS' => [ 'type', 'dev' ],
-            'type'	=> 'ether|bond|bridge|tun|tap',
-            'dev'	=> '((eth|bond|br|tun|tap)[\d]+(\.TAG\d+)?|NONE)',
+            'type'           => 'ether|bond|bridge|tun|tap',
+            'dev'       => '((eth|bond|br|tun|tap)[\d]+(\.TAG\d+)?|NONE)',
             'mac'       => '([0-9a-f]{2}:){5}[0-9a-f]{2}',
             'options'   => 'undefined',
             'ipv4'      => '(\d{1,3})((\.\d{1,3}){1,3})?',
@@ -281,6 +290,7 @@
             'after_change'  => 'undefined',
         },
         'removefile' => {},
+        'ignore'     => {},
         'mkdir'      => {
             'depends'       => 'undefined',
             'owner'         => '(\d+|[a-z\d-]+)',
@@ -341,9 +351,7 @@
 $DEF_SECTIONS->{'config'}->{'dpkg-purge'}
     = $DEF_SECTIONS->{'config'}->{'purgepkg'};
 
-=head2
-
-check_section_structure( $section_name, $section_type, $section_hash, $context, $file )
+=head2 check_section_structure($section_name,$section_type,$section_hash,$context, $file)
 
 Check $section_hash validity against $DEF_SECTIONS. Returns a true value on
 success, or croaks on errors.
@@ -364,8 +372,7 @@
     my $check_mandatory_keys = 1;
 
     if ( $section_type eq 'interface' ) {
-        ( my $iface_type = $section_name )
-            =~ s{
+        ( my $iface_type = $section_name ) =~ s{
                 \A
                     \Q$section_type\E
                     (?:
@@ -385,7 +392,7 @@
         # 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
+            $parsed_keys_list->{'slaves'} = 1;
         }
     }
 
@@ -404,8 +411,9 @@
     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
@@ -416,21 +424,22 @@
         # Next if useless checks
         next
             if $key eq $master_key
-                or $definition->{$def_key} eq 'undefined';
+            or $definition->{$def_key} eq 'undefined';
 
         # Check if key exists
         if ( not defined $definition->{$def_key} ) {
             croak
-                qq{ERROR: file $file, section $section_name: unknown key $key}
+                qq{ERROR: file '$file', section '$section_name': unknown key '$key'};
         }
 
-        my $value = ( ref $section_hash->{$key} eq 'ARRAY' )
+        my $value
+            = ( ref $section_hash->{$key} eq 'ARRAY' )
             ? $section_hash->{$key}
             : [ $section_hash->{$key} ];
 
-        __check_key_value_from_definition(
-            $key, $value, $definition->{$def_key}, $section_name, $file
-        );
+        __check_key_value_from_definition( $key, $value,
+            $definition->{$def_key},
+            $section_name, $file );
     }
 
     if ($check_mandatory_keys) {
@@ -445,7 +454,7 @@
     return 1;
 }
 
-=head2 __check_key_value_from_definition( $key_name, $values_ref, $regexp, $section_name, $file_name )
+=head2 __check_key_value_from_definition($key_name,$values_ref,$regexp,$section_name,$file_name)
 
 Checks values for a specified key. Returns true value on success or croaks
 on errors. The parameters are:
@@ -483,6 +492,5 @@
     return 1;
 }
 
-
 1;    # Magic true value required at end of module
 
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/Packages/DEB.pm
--- a/lib/PFTools/Packages/DEB.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/Packages/DEB.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -127,7 +127,7 @@
 
     return unless $pkg_name;
 
-    my $dep_list;
+    my $dep_list = q{};
     my $output_fh;
     unless (
         $output_fh = IO::File->new(
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/Structqueries.pm
--- a/lib/PFTools/Structqueries.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/Structqueries.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -1,26 +1,34 @@
 package PFTools::Structqueries;
 
-#
-#  Copyright (C) 2013 Richard Phan <richard.phan.prestataire at sfr.com>
-#  Copyright (C) 2007-2010 Christophe Caillet <quadchris at free.fr>
-#  Copyright (C) 2005-2007 Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
-#  Copyright (C) 2003-2005 Damien Clermonte <damien at sitadelle.com>
-#  Copyright (C) 2001-2003 Olivier Molteni <olivier at molteni.net>
-#
-#  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
-#
+=head1 NAME
+
+PFTools::Structqueries - Structqueries module for PFTools
+
+=head1 LICENSE AND COPYRIGHT
+
+ Copyright (C) 2013 Richard Phan <richard.phan.prestataire at sfr.com>
+ Copyright (C) 2007-2010 Christophe Caillet <quadchris at free.fr>
+ Copyright (C) 2005-2007 Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
+ Copyright (C) 2003-2005 Damien Clermonte <damien at sitadelle.com>
+ Copyright (C) 2001-2003 Olivier Molteni <olivier at molteni.net>
+
+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
+
+=head1 SUBROUTINES/METHODS
+
+=cut
 
 use strict;
 use warnings;
@@ -29,6 +37,7 @@
 use Carp;
 use English qw( -no_match_vars );    # Avoids regex performance penalty
 use List::MoreUtils qw( uniq );
+use Term::ANSIColor;
 
 use PFTools;
 
@@ -73,17 +82,15 @@
         croak q{ERROR: Invalid non-hash reference host_ref};
     }
 
-    my $cmdline = $host_ref->{'boot'}->{'cmdline'} || q{};
+    my $cmdline      = $host_ref->{'boot'}->{'cmdline'} || q{};
     my $bond_cmdline = q{};
-    my $bond_mode = q{};
+    my $bond_mode    = q{};
 
     foreach my $iface ( sort keys %{ $host_ref->{'interfaces'} } ) {
         next if $iface !~ m{\A bond }xms;
 
-        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'} )
         {
             if ( $opt !~ m{\A mode }xms ) {
                 $bond_cmdline .= qq{ bonding.$opt};
@@ -103,7 +110,7 @@
 
 =head2 get_complete_cmdline_from_host_ref($host_ref)
 
-Builds the complete cmdline with get_cmdline_from_host_ref() and removes both
+Builds the complete cmdline with L</get_cmdline_from_host_ref($host_ref)> and removes both
 leading and trailing whitespace. Returns the complete cmdline.
 
 =cut
@@ -152,19 +159,19 @@
     my ($hostshort)
         = get_hostshort_hostvlan_zone_from_fqdn( $hostname, $zone );
     if ( not $hostshort ) {
-        croak
-            qq{ERROR: Unable to get hostshort from hostname $hostname};
+        croak qq{ERROR: Unable to get hostshort from hostname $hostname};
     }
 
     my $host_config
         = $site_ref->{'HOST'}->{'BY_NAME'}->{$hosttype}->{$hostshort};
 
-    unless ($host_config) {
+    if ( !$host_config ) {
         croak qq{ERROR: hostname $hostname: no configuration found};
     }
 
-    unless ( ref $host_config eq q{HASH} ) {
-        croak qq{ERROR: host_config for hostname $hostname is not an array reference (BUG?)};
+    if ( ref $host_config ne q{HASH} ) {
+        croak
+            qq{ERROR: host_config for hostname $hostname is not an array reference (BUG?)};
     }
 
     return $host_config;
@@ -185,7 +192,7 @@
 =cut
 
 sub get_hostshort_hostvlan_zone_from_fqdn {
-    my ($fqdn, $zone) = @_;
+    my ( $fqdn, $zone ) = @_;
 
     if ( not $fqdn ) {
         croak q{ERROR: Invalid false fqdn};
@@ -204,8 +211,7 @@
         ? qr{ \Q$zone\E }xms
         : qr{ [^.]+ }xms;    # or just .+ to allow subzones?
 
-    my @return
-        = $fqdn =~ m{
+    my @return = $fqdn =~ m{
             \A
                 (               # -> $hostshort
                     [^.]+
@@ -228,9 +234,7 @@
     return @return;
 }
 
-=head2
-
-get_hosttype_from_hostname ( $hostname, $global_config, $site_name )
+=head2 get_hosttype_from_hostname ( $hostname, $global_config, $site_name )
 
 Returns the hosttype.
 
@@ -254,10 +258,20 @@
         croak q{ERROR: Invalid non-scalar site_name};
     }
 
-    my $site_list = ($site_name)
+    my $site_list
+        = ($site_name)
         ? [$site_name]
         : $global_config->{'SITE'}->{'__site_list'};
 
+    # adding site where this host have a public network
+    my $public_networks = $global_config->{'PUBLIC_NETWORK'};
+    foreach my $vlan ( keys %{$public_networks} ) {
+
+        #print " into $vlan\n";
+        if ( defined $public_networks->{$vlan}->{$hostname} ) {
+            push @{$site_list}, $public_networks->{$vlan}->{$hostname};
+        }
+    }
     foreach my $site ( @{$site_list} ) {
         my $site_ref = get_site_config( $site, $global_config );
         my $host_part = $site_ref->{'HOST'}->{'BY_NAME'};
@@ -289,6 +303,7 @@
         }
     }
 
+    croak qq{ERROR: Host have no interface in vlan '$vlan'};
     return;
 }
 
@@ -347,9 +362,8 @@
         croak q{ERROR: Invalid site_name};
     }
 
-    if (ref $global_config ne 'HASH'
-        or not exists $global_config->{'SITE'}->{'BY_NAME'}
-        )
+    if ( ref $global_config ne 'HASH'
+        or not exists $global_config->{'SITE'}->{'BY_NAME'} )
     {
         croak q{ERROR: Invalid global_config};
     }
@@ -377,9 +391,8 @@
         croak q{ERROR: Invalid site_name};
     }
 
-    if (ref $global_config ne 'HASH'
-        or not exists $global_config->{'DHCP'}->{'BY_SITE'}
-        )
+    if ( ref $global_config ne 'HASH'
+        or not exists $global_config->{'DHCP'}->{'BY_SITE'} )
     {
         croak q{ERROR: Invalid global_config};
     }
@@ -450,7 +463,9 @@
 
 sub get_site_list_from_section {
     my ( $section_ref, $global_config ) = @_;
-
+    if ( !defined $section_ref->{'site'} ) {
+        croak qq{no defined site for section $section_ref->{'hostname'}'};
+    }
     if ( $section_ref->{'site'} eq 'ALL' ) {
         return $global_config->{'SITE'}->{'__site_list'};
     }
@@ -493,7 +508,7 @@
 sub get_vlan_config {
     my ( $vlan_name, $global_config, $site_name ) = @_;
 
-    unless ($site_name) {
+    if ( !$site_name ) {
         croak q{ERROR: $site MUST BE defined};
     }
 
@@ -513,7 +528,7 @@
 
     my $list_ref = get_site_list_from_hostname( $hostname, $global_config );
     if ( not $list_ref ) {
-        croak qq{ERROR: Uknown host $hostname};
+        croak qq{ERROR: Unknown host $hostname};
     }
     if ( @{$list_ref} > 1 ) {
         croak qq{ERROR: Multiple sites for hostname $hostname};
@@ -572,9 +587,17 @@
     my $site_ref = get_site_config( $site_name, $global_config );
 
     # We really don't want to croak() here
-    unless ( $site_ref->{'NETWORK'}->{'BY_NAME'}->{$vlan_name} ) {
-        carp qq{WARNING: unknown vlan $vlan_name on site $site_name};
-        return;
+    if ( !$site_ref->{'NETWORK'}->{'BY_NAME'}->{$vlan_name} ) {
+        if ( !$global_config->{PUBLIC_NETWORK}->{$vlan_name} ) {
+            carp colored(
+                qq{WARNING: unknown vlan $vlan_name on site $site_name and as a public vlan},
+                q{bold yellow on_white}
+            );
+            return;
+        }
+        else {
+            return 0;
+        }
     }
 
     my $scope = $site_ref->{'NETWORK'}->{'BY_NAME'}->{$vlan_name}->{'scope'};
@@ -618,27 +641,26 @@
 
     my ($hostname,  $ip_type,   $global_config,
         $site_name, $zone_name, $hosttype
-        )
-        = @{$arguments_ref}{@argument_names};
+    ) = @{$arguments_ref}{@argument_names};
 
     my ( $hostshort, $hostvlan )
         = get_hostshort_hostvlan_zone_from_fqdn($hostname);
 
-    my $zone_key = $ip_type eq 'ipv6' ? 'ZONE6' : 'ZONE';
+    my $zone_key
+        = ( defined $ip_type and $ip_type eq 'ipv6' ) ? 'ZONE6' : 'ZONE';
     my $zone_ref = $global_config->{$zone_key}->{'BY_NAME'}->{$zone_name};
     my $zone_search;
     if ($hostvlan) {
-        my $zone_part =
-            ( is_private_vlan( $hostvlan, $global_config, $site_name ) )
+        my $zone_part
+            = ( 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];
     }
     else {
-        $zone_search = [
-            $zone_ref->{'BY_SITE'}->{$site_name}, $zone_ref->{'ALL_SITES'}
-        ];
+        $zone_search = [ $zone_ref->{'BY_SITE'}->{$site_name},
+            $zone_ref->{'ALL_SITES'} ];
     }
 
     my @fields;
@@ -673,17 +695,15 @@
         }
 
         if ( $type eq 'CNAME' ) {
-            my $cname_resolved
-                = resolve_hostname_from_global_config(
-                {
-                    hostname      => $field,
+            my $cname_resolved = resolve_hostname_from_global_config(
+                {   hostname      => $field,
                     ip_type       => $ip_type,
                     global_config => $global_config,
                     site_name     => $site_name,
                     zone_name     => $zone_name,
                     hosttype      => $hosttype,
                 }
-                );
+            );
             push @result, @{$cname_resolved};
             next LINE;
         }
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/Update.pm
--- a/lib/PFTools/Update.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/Update.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -54,7 +54,7 @@
 #   - Action_depends    : for building potentially implicit depend(s)
 #   - Action_exec       : the action itself
 #
-# Action_depends is a VOID funtion with 3 parameters
+# Action_depends is a VOID function with 3 parameters
 #   - $ref_section  : HASHREF where parsed section is stored
 #   - $dest         : parsed section name
 #   - $options      : HASHREF with update-config options
@@ -67,7 +67,6 @@
 #   - $global_config: HASHREF with parsed "network and host" configuration
 #
 
-
 ###########################################
 # Global vars
 
@@ -86,7 +85,6 @@
         print "$EVAL_ERROR\n";
         croak
             qq{ERROR: Unable to init action engine $module_name for $action};
-        return;
     }
     $module->import();
     return 1;
@@ -112,6 +110,7 @@
     }
 
     Action_depends( $ref_section, $dest, $options );
+    return;
 }
 
 sub Exec_action ($$$$$$) {
@@ -122,7 +121,6 @@
 
     # Adding some commons entries into substitution hash : $hash_subst
     $hash_subst->{'SECTIONNAME'} = $dest;
-    return 1 if ( $action eq "ignore" );
     if ( $action eq "apt-get" || $action eq "installpkg" ) {
         if ($APT_UPDATE) {
             if ( !Update_pkg_repository( $options->{'pkg_type'} ) ) {
@@ -132,9 +130,8 @@
             $APT_UPDATE = 0;
         }
     }
-    return Action_exec(
-        $ref_section, $dest, $options, $hash_subst, $global_config
-    );
+    return Action_exec( $ref_section, $dest, $options, $hash_subst,
+        $global_config );
 }
 
 sub __Sort_depends_prio ($$) {
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/Update/ADDFILE.pm
--- a/lib/PFTools/Update/ADDFILE.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/Update/ADDFILE.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -26,6 +26,7 @@
 use English qw( -no_match_vars );    # Avoids regex performance penalty
 use File::Compare;
 use File::Copy;
+use Term::ANSIColor;
 use Text::Diff;
 
 use PFTools::Conf;
@@ -62,17 +63,13 @@
     $ref_section->{'source'} =~ s{\A\s*}{};
     $ref_section->{'source'} =~ s{\s*\z}{};
     if ( $ref_section->{'source'} =~ m{\s} ) {
-        $source = Get_tmp_dest($dest) . ".merged";
+        $source = Get_tmp_dest($dest) . q{.merged};
         unlink($source);
-        my $splitsource;
-        foreach $splitsource ( split( ' ', $ref_section->{'source'} ) ) {
-            $splitsource = Get_source(
-                $splitsource,
-                $options->{'host'},
-                $hash_subst
-            );
+        foreach my $splitsource ( split( ' ', $ref_section->{'source'} ) ) {
+            $splitsource
+                = Get_source( $splitsource, $options->{'host'}, $hash_subst );
             if ( !-f $splitsource ) {
-                carp qq{ERROR: $splitsource no such file or directory};
+                carp colored( qq{ERROR: $splitsource no such file or directory}, q{bold red on_white} );
                 return;
             }
             if (deferredlogsystem(
@@ -86,13 +83,12 @@
         }
     }
     else {
-        $source = Get_source(
-            $ref_section->{'source'}, $options->{'host'}, $hash_subst
-        );
+        $source = Get_source( $ref_section->{'source'},
+            $options->{'host'}, $hash_subst );
     }
 
     if ( !-e $source ) {
-        carp qq{ERROR: $source no such file or directory};
+        carp colored( qq{ERROR: $source no such file or directory}, q{bold red on_white} );
         return;
     }
     $hash_subst->{'SOURCE'}      = $source;
@@ -119,17 +115,19 @@
     if ( compare( $tmp, $dest ) ) {
         $diff = 1;
         if ( $options->{'verbose'} || $options->{'simul'} ) {
-            Log("(action needed)");
+            Log( colored( q{(action needed)}, q{bold red} ) );
         }
         if ( $options->{'diff'} ) {
             my @diff;
             if ( !-e $dest ) {
-                @diff = split qq{\n}, diff( [], $tmp, {STYLE => "Unified"} );
-                print_diff_color( @diff );
+                @diff = split qq{\n},
+                    diff( [], $tmp, { STYLE => 'Unified' } );
+                print_diff_color(@diff);
             }
             else {
-                @diff = split qq{\n}, diff( $dest, $tmp, {STYLE => "Unified"} );
-                print_diff_color( @diff );
+                @diff = split qq{\n},
+                    diff( $dest, $tmp, { STYLE => 'Unified' } );
+                print_diff_color(@diff);
             }
         }
         print "on_config ...\n";
@@ -139,16 +137,15 @@
         if ( !$options->{'simul'} ) {
 
             # Fuck dpkg conffiles
-            if ($options->{'noaction'}
+            if (   $options->{'noaction'}
                 && -e $dest
-                && !-e $dest . '.dpkg-dist'
-                )
+                && !-e $dest . '.dpkg-dist' )
             {
                 copy( $dest, $dest . '.dpkg-dist' );
             }
             Do_moveold( $dest, $options );
             if ( !Mk_dest_dir($dest) || !copy( $tmp, $dest ) ) {
-                carp qq{ERROR: Unable to copy file $tmp to $dest};
+                carp colored( qq{ERROR: Unable to copy file $tmp to $dest}, q{bold red on_white} );
                 return;
             }
             Do_chownmod( $ref_section, $dest, $options );
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/Update/ADDLINK.pm
--- a/lib/PFTools/Update/ADDLINK.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/Update/ADDLINK.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -24,6 +24,7 @@
 use base qw( Exporter );
 use Carp;
 use English qw( -no_match_vars );    # Avoids regex performance penalty
+use Term::ANSIColor;
 
 use PFTools::Conf;
 use PFTools::Logger;
@@ -59,7 +60,7 @@
     }
     if ( !-l $dest || ( -l $dest && readlink($dest) ne $source ) ) {
         if ( $options->{'verbose'} || $options->{'simul'} ) {
-            Log("(action needed)");
+            Log(colored(q{(action needed)}, q{bold red}));
         }
         if ( $options->{'diff'} ) {
             if ( -l $dest ) {
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/Update/ADDMOUNT.pm
--- a/lib/PFTools/Update/ADDMOUNT.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/Update/ADDMOUNT.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -27,6 +27,7 @@
 use IO::File;
 use File::Copy;
 use File::Path qw( make_path );
+use Term::ANSIColor;
 use Text::Diff;
 
 use PFTools::Conf;
@@ -61,8 +62,8 @@
 sub Action_depends {
     my ( $ref_section, $dest, $options ) = @_;
 
-    while ( $dest ne "/" && $dest ne "." ) {
-        $ref_section->{'depends'} .= " " . dirname($dest);
+    while ( $dest ne q{/} && $dest ne q{.} ) {
+        $ref_section->{'depends'} .= q{ } . dirname($dest);
         $dest = dirname($dest);
     }
 }
@@ -71,10 +72,10 @@
     my ( $host, $global_config ) = @_;
 
     my $ip = $host;
-    $host =~ m{\A ([^\.]+)(\..*)? \z}xms;
+    $host =~ m{\A ([^\.]+)([.].*)? \z}xms;
     my $zone = get_zone_from_hostname( $1, $global_config );
-    $ip =~ s{\.$zone \z}{}xms;
-    $ip =~ m{\A ([^.]+)(\.([^.]+))? \z}xms;
+    $ip =~ s{[.]$zone \z}{}xms;
+    $ip =~ m{\A ([^.]+)([.]([^.]+))? \z}xms;
     my ( $hostshort, $hostvlan ) = ( $1, $3 );
     my $hosttype = get_hosttype_from_hostname( $hostshort, $global_config );
     my $site_list = get_site_list_from_hostname( $hostshort, $global_config );
@@ -89,8 +90,7 @@
     }
     if ( !isipaddr($ip) ) {
         my $resolved = resolve_hostname_from_global_config(
-            {
-                hostname      => $ip,
+            {   hostname      => $ip,
                 global_config => $global_config,
                 site_name     => $site,
                 zone_name     => $zone,
@@ -115,9 +115,8 @@
 
     my $pf_config = Init_PF_CONFIG();
     my $fs_entry  = $param->{'fs_entry'};
-    if ($fs_entry->{'fstype'}
-        =~ m{\A $pf_config->{'regex'}->{'network_fstype'} \z}xms
-        )
+    if ( $fs_entry->{'fstype'}
+        =~ m{\A $pf_config->{'regex'}->{'network_fstype'} \z}xms )
     {
         foreach my $key ( 'source', 'options' ) {
             my $value
@@ -132,11 +131,9 @@
             $val_addr =~ s{$regex}{$+{ip}};
 
             if ( defined $val_addr && $val_addr ne $value ) {
-                my $val_ip = __Get_ip_host_from_GLOBAL(
-                    $val_addr,
-                    $param->{'global_config'}
-                );
-                return unless ($val_ip);
+                my $val_ip = __Get_ip_host_from_GLOBAL( $val_addr,
+                    $param->{'global_config'} );
+                return if ( !$val_ip );
                 $regex
                     = ( $key eq 'options' )
                     ? '^(?<pre>(.*,)?(ip=)?)(?<ip>[^,]+)?(?<suf>,.*)?$'
@@ -159,8 +156,8 @@
             = Subst_vars( $fs_entry->{$key}, $param->{'subst'} );
     }
 
-    $fs_entry->{'options'} =
-        join( ',', sort split ',', $fs_entry->{'options'} );
+    $fs_entry->{'options'}
+        = join( q{,}, sort split /,/, $fs_entry->{'options'} );
 
     my $resolve_param = {
         'fs_entry'      => $fs_entry,
@@ -185,22 +182,22 @@
             'ref_section'   => $ref_section
         }
     );
-    unless ($add_mount) {
+    if ( !$add_mount ) {
         carp qq{ERROR: Unable to build addmount entry $dest};
         return;
     }
     $hash_subst->{'SOURCE'} = $add_mount->{'source'};
     $hash_subst->{'OPTIONS'}
-        = join( ',', sort split( ',', $add_mount->{'options'} ) );
+        = join( q{,}, sort split( /,/, $add_mount->{'options'} ) );
     $hash_subst->{'FSTYPE'} = $ref_section->{'fstype'} || $DEFAULT_FSTYPE;
 
-    my $current_fstab = Build_structure_from_fstab("/etc/fstab");
-    unless ($current_fstab) {
+    my $current_fstab = Build_structure_from_fstab(q{/etc/fstab});
+    if ( !$current_fstab ) {
         carp q{ERROR: Unable to build fstab structure from file /etc/fstab};
         return;
     }
-    my $current_proc = Build_structure_from_fstab("/proc/mounts");
-    unless ($current_fstab) {
+    my $current_proc = Build_structure_from_fstab(q{/proc/mounts});
+    if ( !$current_fstab ) {
         carp q{ERROR: Unable to build fstab structure from file /proc/mounts};
         return;
     }
@@ -211,7 +208,7 @@
         {
             $current_fstab->{$dest}->{$key} = $add_mount->{$key} || 0;
         }
-        push( @{ $current_fstab->{'__mnt_order'} }, $dest );
+        push @{ $current_fstab->{'__mnt_order'} }, $dest;
         $addfstab = 1;
     }
     else {
@@ -231,58 +228,60 @@
         my $fs_proc = $current_proc->{$dest};
         foreach my $key ( 'source', 'dest', 'fstype', 'options' ) {
             if ( $key eq 'options' ) {
-                $addproc = 1
-                    if (
-                    $add_mount->{$key} ne $current_fstab->{$dest}->{$key}
-                    );
+                if ( $add_mount->{$key} ne $current_fstab->{$dest}->{$key} ) {
+                    $addproc = 1;
+                }
             }
             else {
-                $addproc = 1
-                    if (
-                    $add_mount->{$key} ne $current_proc->{$dest}->{$key}
-                    );
+                if ( $add_mount->{$key} ne $current_proc->{$dest}->{$key} ) {
+                    $addproc = 1;
+                }
             }
         }
     }
 
     if ( $addfstab || $addproc || !-d $dest ) {
         if ( $options->{'verbose'} || $options->{'simul'} ) {
-            Log("(action needed)");
+            Log( colored( q{(action needed)}, q{bold red} ) );
         }
         Do_on_config( $ref_section, $options, $hash_subst ) or return;
         Do_before_change( $ref_section, $options, $hash_subst ) or return;
         if ( !-d $dest && $dest ne 'none' ) {
-            unless ( make_path($dest) ) {
+            if ( !make_path($dest) ) {
                 carp qq{ERROR: while creating mountpoints $dest};
                 return;
             }
         }
         if ($addfstab) {
-            my $tmp = Get_tmp_dest("/etc/fstab");
+            my $fstabfile = q{/etc/fstab};
+            my $tmp       = Get_tmp_dest($fstabfile);
             my $output_fh;
             my @diff;
 
-            unless ( $output_fh = IO::File->new( '>' . $tmp ) ) {
+            $output_fh = IO::File->new( '>' . $tmp );
+            if ( !$output_fh ) {
                 carp qq{ERROR: Unable to create tmp $tmp : $OS_ERROR};
                 return;
             }
             my $new_fstab = Build_fstab_from_structure($current_fstab);
-            unless ( print $output_fh join "\n", @{$new_fstab} ) {
+            if ( !print {$output_fh} join "\n", @{$new_fstab} ) {
                 carp qq{ERROR: Unable to write on tmp $tmp : $OS_ERROR"};
                 return;
             }
-            unless ( $output_fh->close() ) {
+            if ( !$output_fh->close() ) {
                 carp qq{ERROR: Unable to close tmp $tmp : $OS_ERROR"};
                 return;
             }
             if ( $options->{'diff'} ) {
-                #print diff ( '/etc/fstab', $tmp, { STYLE => 'Unified' } );
-                @diff = split qq{\n}, diff( $dest, $tmp, {STYLE => "Unified"} );
-                print_diff_color( @diff );
+
+                #print diff ( $fstabfile, $tmp, { STYLE => 'Unified' } );
+                @diff = split qq{\n},
+                    diff( $fstabfile, $tmp, { STYLE => q{Unified} } );
+                print_diff_color(@diff);
             }
             if ( !$options->{'simul'} ) {
-                if ( !move( $tmp, "/etc/fstab" ) ) {
-                    carp qq{ERROR: Unable to move $tmp to /etc/fstab};
+                if ( !move( $tmp, $fstabfile ) ) {
+                    carp qq{ERROR: Unable to move $tmp to $fstabfile};
                     return;
                 }
             }
@@ -291,42 +290,40 @@
             my $remount = 1;
             if ( defined $current_proc->{$dest} ) {
                 foreach my $key ( 'source', 'dest', 'fstype' ) {
-                    $remount = 0
-                        if (
-                        $add_mount->{$key} ne
-                        $current_proc->{$dest}->{$key}
-                        );
+                    if ($add_mount->{$key} ne $current_proc->{$dest}->{$key} )
+                    {
+                        $remount = 0;
+                    }
                 }
             }
             if ( $options->{'diff'} ) {
                 foreach my $key ( 'source', 'dest', 'fstype', 'options' ) {
-                    my $value = $current_proc->{$dest}->{$key} || '?';
+                    my $value = $current_proc->{$dest}->{$key} || q{?};
                     if ( $key eq 'options' ) {
-                        Log($key . " "
-                                . $value . " -> "
-                                . $add_mount->{$key}
-                            )
-                            if (
-                            $current_fstab->{$dest}->{$key} ne
+                        if ( $current_fstab->{$dest}->{$key} ne
                             $add_mount->{$key}
-                            || !defined $current_proc->{$dest}->{$key}
-                            );
+                            || !defined $current_proc->{$dest}->{$key} )
+                        {
+                            Log(      $key . q{ }
+                                    . $value . q{ -> }
+                                    . $add_mount->{$key} );
+                        }
                     }
                     else {
-                        Log($key . " "
-                                . $value . " -> "
-                                . $add_mount->{$key}
-                            )
-                            if ( $value ne $add_mount->{$key} );
+                        if ( $value ne $add_mount->{$key} ) {
+                            Log(      $key . q{ }
+                                    . $value . q{ -> }
+                                    . $add_mount->{$key} );
+                        }
                     }
                 }
             }
             if ( !$options->{'simul'} && !$options->{'noaction'} ) {
                 if ($remount) {
                     my $cmd
-                        = "mount -o 'remount,"
-                        . $add_mount->{'options'} . "' '"
-                        . $dest . "'";
+                        = q{mount -o 'remount,}
+                        . $add_mount->{'options'} . q{' '}
+                        . $dest . q{'};
                     if ( deferredlogsystem($cmd) ) {
                         carp qq{ERROR: while remounting $dest with
                             $add_mount->{'options'}
@@ -336,23 +333,21 @@
                 }
                 else {
                     my $umount
-                        = (
-                        $add_mount->{'source'} ne
-                            $current_proc->{$dest}->{'source'}
-                        )
+                        = ( $add_mount->{'source'} ne
+                            $current_proc->{$dest}->{'source'} )
                         ? $current_proc->{$dest}->{'source'}
                         : $add_mount->{'source'};
-                    if ( deferredlogsystem( "umount '" . $umount . "'" ) ) {
+                    if ( deferredlogsystem( q{umount '} . $umount . q{'} ) ) {
                         carp qq{ERROR: Unable to unmount $umount};
                         return;
                     }
                     my $mount_cmd
-                        = "mount -t '"
+                        = q{mount -t '}
                         . $add_mount->{'fstype'}
-                        . "' -o '"
-                        . $add_mount->{'options'} . "' '"
-                        . $add_mount->{'source'} . "' '"
-                        . $add_mount->{'dest'} . "'";
+                        . q{' -o '}
+                        . $add_mount->{'options'} . q{' '}
+                        . $add_mount->{'source'} . q{' '}
+                        . $add_mount->{'dest'} . q{'};
 
                     if ( deferredlogsystem($mount_cmd) ) {
                         carp qq{ERROR: while mounting $dest with $mount_cmd};
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/Update/CREATEFILE.pm
--- a/lib/PFTools/Update/CREATEFILE.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/Update/CREATEFILE.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -25,6 +25,7 @@
 use Carp;
 use English qw( -no_match_vars );    # Avoids regex performance penalty
 use File::Copy;
+use Term::ANSIColor;
 
 use PFTools::Conf;
 use PFTools::Logger;
@@ -54,7 +55,7 @@
     $hash_subst->{'DESTINATION'} = $tmp;
     unless ( -f $dest ) {
         if ( $options->{'verbose'} || $options->{'simul'} ) {
-            Log("(action needed)");
+            Log(colored(q{(action needed)}, q{bold red}));
         }
         if ( !defined $ref_section->{'source'} ) {
 
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/Update/Common.pm
--- a/lib/PFTools/Update/Common.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/Update/Common.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -57,7 +57,7 @@
 my $DEFAULT_DIRMODE = '0750';
 my $DEFAULT_OWNER   = 'root';
 my $DEFAULT_GROUP   = 'root';
-my $STARTTIME       = time();
+my $STARTTIME       = time;
 
 ##############################################
 ###
@@ -65,7 +65,7 @@
 sub isipaddr {
     my ($ip) = @_;
 
-    my @sub = split( m{\.}, $ip );
+    my @sub = split m{[.]}xms, $ip;
     return if ( $#sub != 3 );
 
     foreach my $octet ( 0 .. 3 ) {
@@ -78,28 +78,37 @@
     my ( $type, $dest, $options, $right1, $right2 ) = @_;
 
     if ( $options->{'verbose'} || $options->{'simul'} ) {
-        Log("(chown needed)");
+        Log( colored( qq{($type needed)}, q{bold red} ) );
     }
     return 1 if ( $options->{'simul'} );
-    my ( $dev, $ino, $mode, $nlink, $uid, $gid, @others ) = stat($dest);
+    my ( $dev, $ino, $mode, $nlink, $uid, $gid, @others ) = stat $dest;
     if ( $type eq 'chown' ) {
-        my $newuid = getpwnam($right1);
-        my $newgid = getgrnam($right2);
-        if (( $uid && $uid == $newuid )
-            && ( $gid && $gid == $newgid )
-            )
-        {
-            print "Useless $type for $dest" if ( $options->{'verbose'} );
+        my $newuid = getpwnam $right1;
+        my $newgid = getgrnam $right2;
+        if ( !defined $newuid ) {
+            carp colored( qq{ERROR: user '$right1' not in /etc/passwd},
+                q{bold red on_white} );
             return 1;
         }
-        return chown( $newuid, $newgid, $dest );
+        if ( !defined $newgid ) {
+            carp colored( qq{ERROR: group '$right2' not in /etc/group},
+                q{bold red on_white} );
+            return 1;
+        }
+        if (   ( $uid && $uid == $newuid )
+            && ( $gid && $gid == $newgid ) )
+        {
+            print qq{Useless $type for $dest\n} if ( $options->{'verbose'} );
+            return 1;
+        }
+        return chown $newuid, $newgid, $dest;
     }
     elsif ( $type eq 'chmod' ) {
-        if ( $mode && ( $mode & 07777 ) == $right1 ) {
-            print "Useless $type for $dest" if ( $options->{'verbose'} );
+        if ( $mode && ( $mode & oct 7777 ) == $right1 ) {
+            print qq{Useless $type for $dest\n} if ( $options->{'verbose'} );
             return 1;
         }
-        return chmod( $right1, $dest );
+        return chmod $right1, $dest;
     }
     else {
         carp q{ERROR: invalid $type parameter};
@@ -123,22 +132,22 @@
 sub ln_sfn {
     my ( $source, $dest ) = @_;
 
-    unlink($dest);
-    rmdir($dest);
-    return symlink( $source, $dest );
+    unlink $dest;
+    rmdir $dest;
+    return symlink $source, $dest;
 }
 
 sub dirname {
     my ($file) = @_;
 
-    $file =~ s{//}{/}g;
+    $file =~ s{//}{/}gxms;
 
-    if ( $file =~ m{/} ) {
+    if ( $file =~ m{/}xms ) {
         $file =~ s{\A (.*)/[^/]+/? \z}{$1}xms;
-        $file = "." if ( $file =~ m{\A \s* \z}xms );
+        $file = q{.} if ( $file =~ m{\A \s* \z}xms );
     }
     else {
-        $file = '.';
+        $file = q{.};
     }
 
     return $file;
@@ -150,10 +159,11 @@
     my $pf_config = Init_PF_CONFIG();
     if ( -e $dest ) {
         my $old
-            = $pf_config->{'path'}->{'checkout_dir'} . "/old/"
-            . $dest . "."
+            = $pf_config->{'path'}->{'checkout_dir'}
+            . q{/old/}
+            . $dest . q{.}
             . $STARTTIME;
-        Log( "(moving old to " . $old . ")" ) if ( $options->{'verbose'} );
+        Log(qq{(moving old to $old)}) if ( $options->{'verbose'} );
         unless ( $options->{'simul'} ) {
             Mk_dest_dir($old);
             return move( $old, $dest );
@@ -173,8 +183,10 @@
         return;
     }
 
-    my $mode = $ref_section->{'mode'}
-        || ( -d $dest ) ? $DEFAULT_DIRMODE : $DEFAULT_MODE;
+    my $mode
+        = defined( $ref_section->{'mode'} ) ? $ref_section->{'mode'}
+        : ( -d $dest )                      ? $DEFAULT_DIRMODE
+        :                                     $DEFAULT_MODE;
     $mode =~ s{\A [^0]}{0$&}xms;
 
     unless ( fullchmod( eval($mode), $dest, $options ) ) {
@@ -198,17 +210,15 @@
     my ( $ref_section, $options, $hash_subst ) = @_;
 
     if ( $ref_section->{'actiongroup'} ) {
-        Log( "Triggering actiongroup " . $ref_section->{'actiongroup'} )
+        Log( q{Triggering actiongroup } . $ref_section->{'actiongroup'} )
             if ( $options->{'verbose'} );
         return 1;
     }
-    if (!$options->{'simul'}
-        && defined( $ref_section->{'on_config'} )
-        )
+    if ( !$options->{'simul'}
+        && defined( $ref_section->{'on_config'} ) )
     {
         return Exec_cmd(
-            Subst_vars( $ref_section->{'on_config'}, $hash_subst )
-        );
+            Subst_vars( $ref_section->{'on_config'}, $hash_subst ) );
     }
     return 1;
 }
@@ -217,18 +227,16 @@
     my ( $ref_section, $options, $hash_subst ) = @_;
 
     if ( $ref_section->{'actiongroup'} ) {
-        Log( "Triggering actiongroup " . $ref_section->{'actiongroup'} )
+        Log( q{Triggering actiongroup } . $ref_section->{'actiongroup'} )
             if ( $options->{'verbose'} );
         return 1;
     }
-    if (!$options->{'simul'}
+    if (   !$options->{'simul'}
         && !$options->{'noaction'}
-        && defined( $ref_section->{'before_change'} )
-        )
+        && defined( $ref_section->{'before_change'} ) )
     {
         return Exec_cmd(
-            Subst_vars( $ref_section->{'before_change'}, $hash_subst )
-        );
+            Subst_vars( $ref_section->{'before_change'}, $hash_subst ) );
     }
     return 1;
 }
@@ -237,18 +245,16 @@
     my ( $ref_section, $options, $hash_subst ) = @_;
 
     if ( $ref_section->{'actiongroup'} ) {
-        Log( "Triggering actiongroup " . $ref_section->{'actiongroup'} )
+        Log( q{Triggering actiongroup } . $ref_section->{'actiongroup'} )
             if ( $options->{'verbose'} );
         return 1;
     }
-    if (!$options->{'simul'}
+    if (   !$options->{'simul'}
         && defined( $ref_section->{'after_change'} )
-        && !$options->{'noaction'}
-        )
+        && !$options->{'noaction'} )
     {
         return Exec_cmd(
-            Subst_vars( $ref_section->{'after_change'}, $hash_subst )
-        );
+            Subst_vars( $ref_section->{'after_change'}, $hash_subst ) );
     }
     return 1;
 }
@@ -257,18 +263,16 @@
     my ( $ref_section, $options, $hash_subst ) = @_;
 
     if ( $ref_section->{'actiongroup'} ) {
-        Log( "Triggering actiongroup " . $ref_section->{'actiongroup'} )
+        Log( q{Triggering actiongroup } . $ref_section->{'actiongroup'} )
             if ( $options->{'verbose'} );
         return 1;
     }
-    if (!$options->{'simul'}
+    if (   !$options->{'simul'}
         && defined( $ref_section->{'on_noaction'} )
-        && $options->{'noaction'}
-        )
+        && $options->{'noaction'} )
     {
         return Exec_cmd(
-            Subst_vars( $ref_section->{'on_noaction'}, $hash_subst )
-        );
+            Subst_vars( $ref_section->{'on_noaction'}, $hash_subst ) );
     }
     return 1;
 }
@@ -282,14 +286,14 @@
     return unless $dir;
 
     # FIXME rewrite this part, it's really unreadable!!
-    $dir =~ s{//}{/}g;             # supprimer // sinon ca marche moins bien
+    $dir =~ s{//}{/}gxms;          # supprimer // sinon ca marche moins bien
     $dir =~ s{/[^/]+/* \z}{}xms;
     my $dir2 = $dir;
-    while ( $dir2 ne "" && !-e $dir2 ) {
+    while ( $dir2 ne q{} && !-e $dir2 ) {
         $dir2 =~ s{/[^/]+/* \z}{}xms;
     }
-    if ( $dir2 ne "" && -e $dir2 && !-d $dir2 ) {
-        unlink($dir2);
+    if ( $dir2 ne q{} && -e $dir2 && !-d $dir2 ) {
+        unlink $dir2;
     }
 
     eval { make_path($dir); };
@@ -305,13 +309,13 @@
     my ($dest) = @_;
 
     my $pf_config = Init_PF_CONFIG();
-    my $tmp       = $pf_config->{'path'}->{'checkout_dir'} . "/tmp/" . $dest;
+    my $tmp       = $pf_config->{'path'}->{'checkout_dir'} . q{/tmp/} . $dest;
     Mk_dest_dir($tmp);
     if ( -d $tmp ) {
-        rmdir($tmp);
+        rmdir $tmp;
     }
     elsif ( -e $tmp ) {
-        unlink($tmp);
+        unlink $tmp;
     }
     return $tmp;
 }
@@ -319,26 +323,21 @@
 sub print_diff_color {
     my (@diff) = @_;
 
-    foreach my $line ( @diff ) {
-        if ( $line =~ m/^\+/ ) {
-            print color q{green};
-            print qq{$line\n};
-            print color q{reset};
+    foreach my $line (@diff) {
+        if ( $line =~ m{\A[+]}xms ) {
+            print colored( qq{$line\n}, q{green} );
         }
-        elsif ( $line =~ m/^-/ ) {
-            print color q{red};
-            print qq{$line\n};
-            print color q{reset};
+        elsif ( $line =~ m{\A-}xms ) {
+            print colored( qq{$line\n}, q{red} );
         }
-        elsif ( $line =~ m/^@@ / ) {
-            print color q{bold yellow};
-            print qq{$line\n};
-            print color q{reset};
+        elsif ( $line =~ m{\A@@ }xms ) {
+            print colored( qq{$line\n}, q{magenta} );
         }
         else {
             print qq{$line\n};
         }
     }
+    return;
 }
 
 1;
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/Update/IGNORE.pm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/PFTools/Update/IGNORE.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -0,0 +1,53 @@
+package PFTools::Update::IGNORE;
+
+#
+#  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 base qw( Exporter );
+use Carp;
+use English qw( -no_match_vars );    # Avoids regex performance penalty
+use Term::ANSIColor;
+
+use PFTools::Conf;
+use PFTools::Logger;
+use PFTools::Update::Common;
+
+our @EXPORT = qw(
+    Action_depends
+    Action_exec
+);
+
+our @EXPORT_OK = qw();
+
+sub Action_depends {
+    return 1;
+}
+
+sub Action_exec {
+    my ( $ref_section, $dest, $options, $hash_subst, $global_config ) = @_;
+
+    if ( $options->{'verbose'} || $options->{'simul'} ) {
+        Log( colored( q{(action ignored)}, q{bold red} ) );
+    }
+    return 1;
+}
+
+1;
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/Update/INSTALLPKG.pm
--- a/lib/PFTools/Update/INSTALLPKG.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/Update/INSTALLPKG.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -27,6 +27,7 @@
 use Debconf::Db;
 use Debconf::Template;
 use English qw( -no_match_vars );    # Avoids regex performance penalty
+use Term::ANSIColor;
 
 use PFTools::Conf;
 use PFTools::Logger;
@@ -41,18 +42,20 @@
 our @EXPORT_OK = qw();
 
 ###########################################
-### Environement vars
-$ENV{'PATH'}            = $ENV{'PATH'} . ":/usr/local/sbin:/usr/local/bin";
-$ENV{'DEBIAN_FRONTEND'} = "noninteractive";
-$ENV{'DEBIAN_PRIORITY'} = "critical";
+### Environment vars
+$ENV{'PATH'}            = $ENV{'PATH'} . ':/usr/local/sbin:/usr/local/bin';
+$ENV{'DEBIAN_FRONTEND'} = 'noninteractive';
+$ENV{'DEBIAN_PRIORITY'} = 'critical';
 
 sub Action_depends {
     my ( $ref_section, $dest, $options ) = @_;
 
     $options->{'pkg_type'} = 'deb' unless ( $options->{'pkg_type'} );
     my $deps = Get_pkg_depends( $options->{'pkg_type'}, $dest );
-    unless ($deps) {
-        carp qq{ERROR: Unable to get depends for $dest};
+    if ( !$deps ) {
+        if ( $options->{'verbose'} ) {
+            carp colored( qq{WARN: Unable to get or no dependency for $dest}, q{bold yellow on_white} );
+        }
         return;
     }
     if ( $ref_section->{'depends'} ) {
@@ -61,6 +64,7 @@
     else {
         $ref_section->{'depends'} = $deps;
     }
+    return;
 }
 
 sub Action_exec {
@@ -74,9 +78,8 @@
 
     my $name_filter = $ref_section->{'name_filter'};
     if ($name_filter) {
-        my $newdest = deferredlogpipe(
-            Subst_vars( $name_filter, $hash_subst )
-        );
+        my $newdest
+            = deferredlogpipe( Subst_vars( $name_filter, $hash_subst ) );
         unless ( defined $newdest ) {
             carp qq{ERROR: Unable to apply name_filter $name_filter};
             return;
@@ -89,9 +92,8 @@
     }
     $hash_subst->{'SECTIONNAME'} = $dest;
     ( $installed_version, $available_version, $specified_version )
-        = Get_pkg_policy(
-        $options->{'pkg_type'}, $dest, $ref_section->{'version'}
-        );
+        = Get_pkg_policy( $options->{'pkg_type'},
+        $dest, $ref_section->{'version'} );
     unless ($available_version) {
         carp qq{ERROR: Package $dest is unavailable};
         return;
@@ -104,35 +106,33 @@
         $install++;
     }
     else {
-        my $compare = Cmp_pkg_version(
-            $options->{'pkg_type'}, $dest,
-            $installed_version, $available_version
-        );
+        my $compare = Cmp_pkg_version( $options->{'pkg_type'},
+            $dest, $installed_version, $available_version );
         $install++ if ( defined $compare && $compare < 0 );
     }
     if ($install) {
         if ( $options->{'verbose'} || $options->{'simul'} ) {
-            Log("(action needed)");
+            Log(colored(q{(action needed)}, q{bold red}));
         }
         if ( $options->{'diff'} ) {
-            Log("(inst = "
+            Log(q{(inst = }
                     . (
-                    defined($installed_version) ? $installed_version : '?'
+                    defined($installed_version) ? $installed_version : q{?}
                     )
-                    . ", avail = "
+                    . q{, avail = }
                     . (
-                    defined($available_version) ? $available_version : '?'
+                    defined($available_version) ? $available_version : q{?}
                     )
-                    . ", target = "
+                    . q{, target = }
                     . (
-                    defined($available_version) ? $available_version : '?'
+                    defined($available_version) ? $available_version : q{?}
                     )
-                    . ")"
+                    . q{)}
             );
         }
         if ( defined( $ref_section->{'delay'} ) && !$options->{'noaction'} ) {
             $hash_subst->{'HOSTNAME'} =~ m{\d+ \z}xms;
-            if ( $& ne "" ) {
+            if ( $& ne q{} ) {
                 sleep( 120 * $& );
             }
         }
@@ -146,25 +146,22 @@
                 $debconf_vars->{$1} = $ref_section->{$key};
             }
             if ($debconf) {
-                my ( $DEB, $conf, $pkg );
+                my ( $DEB, $pkg );
                 my $pf_config = Init_PF_CONFIG();
                 my $vcs_tpl_dir
                     = $pf_config->{'path'}->{'checkout_dir'} . '/TEMPLATES';
                 Debconf::Db->load;
-                foreach $conf ( keys %{ $ref_section->{'debconf'} } ) {
-                    ($pkg) = split( m{/}, $conf );
+                foreach my $conf ( keys %{ $ref_section->{'debconf'} } ) {
+                    ($pkg) = split m{/}, $conf;
                     if ( !$DEB->{$pkg} ) {
                         $DEB->{$pkg} = 1;
-                        Debconf::Template->load(
-                            $vcs_tpl_dir . "/" . $pkg, $pkg
-                        );
+                        Debconf::Template->load( $vcs_tpl_dir . q{/} . $pkg,
+                            $pkg );
                     }
-                    Debconf::ConfModule->command_set(
-                        $conf, $ref_section->{'debconf'}->{$conf}
-                    );
-                    Debconf::ConfModule->command_fset(
-                        $conf, "seen", "true"
-                    );
+                    Debconf::ConfModule->command_set( $conf,
+                        $ref_section->{'debconf'}->{$conf} );
+                    Debconf::ConfModule->command_fset( $conf, 'seen',
+                        'true' );
                 }
                 Debconf::Db->save;
             }
@@ -176,11 +173,10 @@
             eval "\$install = sprintf (\"echo '$install' |\")";
         }
         else {
-            $install = '';
+            $install = q{};
         }
         if ( !$options->{'simul'} ) {
-            if (
-                !Install_pkg(
+            if (!Install_pkg(
                     $options->{'pkg_type'}, $dest,
                     $ref_section->{'version'}
                 )
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/Update/MKDIR.pm
--- a/lib/PFTools/Update/MKDIR.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/Update/MKDIR.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -25,6 +25,7 @@
 use Carp;
 use English qw( -no_match_vars );    # Avoids regex performance penalty
 use File::Path qw( make_path );
+use Term::ANSIColor;
 
 use PFTools::Conf;
 use PFTools::Logger;
@@ -57,7 +58,7 @@
     unless ( -d $dest ) {
         $cmp = 1;
         if ( $options->{'verbose'} || $options->{'simul'} ) {
-            Log("(action needed)");
+            Log(colored(q{(action needed)}, q{bold red}));
         }
         Do_on_config( $ref_section, $options, $hash_subst ) or return;
         Do_before_change( $ref_section, $options, $hash_subst ) or return;
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/Update/PURGEPKG.pm
--- a/lib/PFTools/Update/PURGEPKG.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/Update/PURGEPKG.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -24,6 +24,7 @@
 use base qw( Exporter );
 use Carp;
 use English qw( -no_match_vars );    # Avoids regex performance penalty
+use Term::ANSIColor;
 
 use PFTools::Conf;
 use PFTools::Logger;
@@ -72,7 +73,7 @@
 
     if ( $status->{'installed'} ) {
         if ( $options->{'verbose'} || $options->{'simul'} ) {
-            Log("(action needed)");
+            Log(colored(q{(action needed)}, q{bold red}));
         }
         Do_on_config( $ref_section, $options, $hash_subst ) or return;
         Do_before_change( $ref_section, $options, $hash_subst ) or return;
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/Update/REMOVEDIR.pm
--- a/lib/PFTools/Update/REMOVEDIR.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/Update/REMOVEDIR.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -24,6 +24,7 @@
 use base qw( Exporter );
 use Carp;
 use English qw( -no_match_vars );    # Avoids regex performance penalty
+use Term::ANSIColor;
 
 use PFTools::Conf;
 use PFTools::Logger;
@@ -49,7 +50,7 @@
         return;
     }
     if ( $options->{'verbose'} || $options->{'simul'} ) {
-        Log("(action needed)");
+        Log(colored(q{(action needed)}, q{bold red}));
     }
     Do_on_config( $ref_section, $options, $hash_subst ) or return;
     Do_before_change( $ref_section, $options, $hash_subst ) or return;
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/Update/REMOVEFILE.pm
--- a/lib/PFTools/Update/REMOVEFILE.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/Update/REMOVEFILE.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -24,6 +24,7 @@
 use base qw( Exporter );
 use Carp;
 use English qw( -no_match_vars );    # Avoids regex performance penalty
+use Term::ANSIColor;
 
 use PFTools::Conf;
 use PFTools::Logger;
@@ -49,7 +50,7 @@
         return;
     }
     if ( $options->{'verbose'} || $options->{'simul'} ) {
-        Log("(action needed)");
+        Log(colored(q{(action needed)}, q{bold red}));
     }
     Do_on_config( $ref_section, $options, $hash_subst ) or return;
     Do_before_change( $ref_section, $options, $hash_subst ) or return;
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/Utils.pm
--- a/lib/PFTools/Utils.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/Utils.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -1,22 +1,30 @@
 package PFTools::Utils;
 
-#
-#  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
-#
+=head1 NAME
+
+PFTools::Utils - Utils module for PFTools
+
+=head1 LICENSE AND COPYRIGHT
+
+ 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
+
+=head1 SUBROUTINES/METHODS
+
+=cut
 
 use strict;
 use warnings;
@@ -36,6 +44,7 @@
 use List::MoreUtils qw( uniq );
 use NetAddr::IP;
 use Template::Tiny;
+use Term::ANSIColor;
 
 use PFTools;
 use PFTools::Conf;
@@ -48,7 +57,7 @@
 our @CARP_NOT = qw( PFTools );
 
 our @EXPORT = qw(
-    Init_TOOLS
+    init_tools
 
     Do_update_from_GLOBAL
 );
@@ -66,11 +75,31 @@
     search_and_replace
 );
 
-########################################################################
-# Exported functions
-
-# FIXME documentation + named arguments
-sub Init_TOOLS {
+=head2 init_tools($hostname,$pf_config_file,$global_store_file,$reload)
+
+Load the configuration file and either use the cached global configuration hash
+or create it from a VCS checkout.
+It takes the following arguments:
+
+=over
+
+=item I<hostname> the hostname
+
+=item I<pf_config_file> the pf-tools configuration file
+
+=item I<global_store_file> the file where the global configuration hash will be
+saved
+
+=item I<reload> don't use the stored structure, recreate it from the VSC
+(useful when changing a network configuration)
+
+=back
+
+FIXME named arguments
+
+=cut
+
+sub init_tools {
     my ( $hostname, $pf_config_file, $global_store_file, $reload ) = @_;
 
     my $default_pf_config_file = q{/etc/pf-tools.conf};
@@ -80,26 +109,24 @@
 
     my $pf_config = Init_PF_CONFIG($pf_config_file);
 
-    unless ($global_store_file) {
+    if ( !$global_store_file ) {
         $global_store_file = $pf_config->{'path'}->{'global_struct'};
     }
-    unless ( -e $global_store_file ) {
+    if ( !-e $global_store_file ) {
         $reload = 1;
     }
 
     my $global_struct;
     if ($reload) {
 
-        # FIXME VCS_checkout should croak by itself
-        if ( !VCS_checkout( $hostname, $pf_config, {} ) ) {
+        # FIXME vcs_checkout should croak by itself
+        if ( !vcs_checkout( $hostname, $pf_config, {} ) ) {
             croak q{ERROR: Unable to checkout configuration from VCS system};
         }
 
         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 );
         store_global_config( $global_struct, $pf_config );
@@ -111,13 +138,13 @@
     return ( $pf_config, $global_struct );
 }
 
-=head2 make_preseed_file($args_ref)
+=head2 make_preseed_file()
 
 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 %{$args_ref}:
+complete path) of the written preseed file.
+It takes the following named arguments:
 
 =over
 
@@ -130,7 +157,7 @@
 =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)
+L<PFTools::Structqueries/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
@@ -143,20 +170,14 @@
 sub make_preseed_file {
     my ($args_ref) = @_;
 
-    check_mandatory_true_args_type(
-        $args_ref, q{},
-        qw( hostname site_name template_filename )
-    );
-
-    check_mandatory_args_type(
-        $args_ref, q{HASH},
-        qw( global_config pf_config )
-    );
-
-    check_optional_args_type(
-        $args_ref, q{HASH},
-        qw( host_ref)
-    );
+    check_mandatory_true_args_type( $args_ref, q{},
+        qw( hostname site_name ) );
+
+    check_mandatory_args_type( $args_ref, q{HASH},
+        qw( global_config pf_config ) );
+
+    check_optional_args_type( $args_ref, q{HASH}, qw( host_ref) );
+    check_optional_args_type( $args_ref, q{},     qw( template_filename ) );
 
     my ($hostname,  $site_name,         $global_config,
         $pf_config, $template_filename, $host_ref
@@ -167,7 +188,7 @@
         };
 
     if ( not $pf_config->{'path'}->{'preseed_dir'} ) {
-        croak q{ERROR: Invalid hashref $pf_config: no ->path->preseed_dir};
+        croak q{ERROR: Invalid hashref pf_config: no ->path->preseed_dir};
     }
 
     $host_ref ||= get_host_config( $hostname, $global_config, $site_name );
@@ -176,37 +197,34 @@
     my $templates_dirname = $pf_config->{'path'}->{'templates_dir'};
 
     $template_filename ||= join q{/}, $templates_dirname,
-        (
-        $host_ref->{'deployment'}->{'preseed'}
-            || $pf_config->{$mode}->{'preseed'}
-        );
+        (      $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(
-        {
-            %{$args_ref},
-            file_type         => q{preseed},
+        {   file_type         => q{preseed},
             filename          => $filename,
             template_filename => $template_filename,
             host_ref          => $host_ref,
+            %{$args_ref},
         }
     );
 
     return $basename;
 }
 
-=head2 make_pxe_boot_and_preseed_files($args_ref)
+=head2 make_pxe_boot_and_preseed_files()
 
 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.
-
-make_boot_and_preseed_files() returns a true value on success. It takes the
-following named arguments in %{$args_ref}:
+created by calling L</make_preseed_file()>, so its mandatory arguments
+are needed here too.
+
+Returns a true value on success.
+It takes the following named arguments:
 
 =over
 
@@ -233,19 +251,16 @@
 sub make_pxe_boot_and_preseed_files {
     my ($args_ref) = @_;
 
-    check_mandatory_true_args_type(
-        $args_ref, q{},
-        qw( hostname site_name preseed_template_filename pxe_template_filename )
-    );
-
-    check_mandatory_args_type(
-        $args_ref, q{HASH},
-        qw( global_config pf_config )
-    );
-
-    my ($hostname,              $site_name,     $preseed_template_filename,
-        $pxe_template_filename, $global_config, $pf_config
-        )
+    check_mandatory_true_args_type( $args_ref, q{},
+        qw( hostname site_name ) );
+
+    check_mandatory_args_type( $args_ref, q{HASH},
+        qw( global_config pf_config ) );
+    check_optional_args_type( $args_ref, q{},
+        qw( preseed_template_filename pxe_template_filename ) );
+
+    my ( $hostname, $site_name, $preseed_template_filename,
+        $pxe_template_filename, $global_config, $pf_config )
         = @{$args_ref}{
         qw( hostname              site_name      preseed_template_filename
             pxe_template_filename global_config  pf_config
@@ -258,39 +273,36 @@
     my $host_ref = get_host_config( $hostname, $global_config, $site_name );
 
     my $preseed_filename = make_preseed_file(
-        {
+        {   template_filename => $preseed_template_filename,
+            host_ref          => $host_ref,
             %{$args_ref},
-            template_filename => $preseed_template_filename,
-            host_ref          => $host_ref,
         }
     );
 
     my $iface = get_iface_vlan_from_hostname(
-        $host_ref->{'deployment'}->{'dhcpvlan'}, $host_ref
-    );
+        $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(
-        {
-            %{$args_ref},
-            file_type         => q{pxe_boot},
+        {   file_type         => q{pxe_boot},
             filename          => $pxe_boot_file,
             site_name         => $site_name,
             template_filename => $pxe_template_filename,
             preseed_filename  => $preseed_filename,
+            %{$args_ref},
         }
     );
 
     return 1;
 }
 
-=head2 make_zone_file($args_ref)
-
-This function creates a zone file. It takes the
-following named arguments in %{$args_ref}:
+=head2 make_zone_file()
+
+This function creates a zone file.
+It takes the following named arguments:
 
 =over
 
@@ -302,45 +314,61 @@
 
 =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 make_zone_file {
     my ($args_ref) = @_;
 
-    unless ( ref $args_ref eq 'HASH' ) {
+    if ( ref $args_ref ne 'HASH' ) {
         croak q{ERROR: Invalid non-hash reference args_ref};
     }
 
-    __make_file( { %{$args_ref}, file_type => q{zone} } );
+    __make_file( { file_type => q{zone}, %{$args_ref} } );
 
     return 1;
 }
 
-=head2 make_resolv_conf_file( $hostname, $global_config, $site_name, $filename );
-
-Writes the I<resolv.conf> configuration for I<$hostname> at I<$site_name> to
-I<$filename>. I<$global_config> is a reference to the global configuration
-hash.
+=head2 make_resolv_conf_file()
+
+This function writes the F<resolv.conf> configuration file.
+It takes the following named arguments:
+
+=over
+
+=item I<hostname> the host name
+
+=item I<site_name> the site name
+
+=item I<filename> the output file name
+
+=item I<global_config> a reference to the global configuration hash
+
+=back
 
 =cut
 
 sub make_resolv_conf_file {
     my ($args_ref) = @_;
 
-    unless ( ref $args_ref eq 'HASH' ) {
+    if ( ref $args_ref ne 'HASH' ) {
         croak q{ERROR: Invalid non-hash reference args_ref};
     }
 
-    __make_file( { %{$args_ref}, file_type => q{resolv.conf} } );
+    __make_file( { file_type => q{resolv.conf}, %{$args_ref} } );
 
     return 1;
 }
 
-=head2 search_and_replace($args_ref)
+=head2 search_and_replace()
 
 Reads a file, replaces some special keywords in its content and writes the
 result in (possibly another) file (this is the function behind the scene for
-the filter_* programs). It takes the following named arguments:
+the filter_* programs).
+It takes the following named arguments:
 
 =over
 
@@ -357,13 +385,13 @@
 =over
 
 =item I<distrib>: replace %DISTRIB% and %DISTSRC% (see the
-__search_and_replace_distrib() documentation for details)
+L</__search_and_replace_distrib()> documentation for details)
 
 =item I<iface>: resolve network names to interface names (see the
-__search_and_replace_iface() documentation for details)
+L</__search_and_replace_iface()> documentation for details)
 
 =item I<ip>: resolve host names to IP addresses (see the
-__search_and_replace_ip() documentation for details)
+L</__search_and_replace_ip()> documentation for details)
 
 =back
 
@@ -373,9 +401,9 @@
 
 =item I<separator> (optional, for the I<ip> filter only)
 
-=item I<global_config> as usual
-
-=item I<pf_config> as usual
+=item I<global_config> a reference to the global configuration hash
+
+=item I<pf_config> a reference to the pf-tools configuration hash
 
 =back
 
@@ -390,25 +418,18 @@
 sub search_and_replace {
     my ($args_ref) = @_;
 
-    check_mandatory_true_args_type(
-        $args_ref, q{},
-        qw( hostname site_name input_filename output_filename filter_type )
-    );
+    check_mandatory_true_args_type( $args_ref, q{},
+        qw( hostname site_name input_filename output_filename filter_type ) );
 
     # Only check these in __search_and_replace_ip()?
-    check_optional_args_type(
-        $args_ref, q{},
-        qw( ip_type resolution_type separator )
-    );
-
-    check_mandatory_args_type(
-        $args_ref, q{HASH},
-        qw( global_config pf_config )
-    );
-
-    my ($hostname, $site_name, $input_filename, $output_filename,
-        $filter_type, $global_config, $pf_config
-        )
+    check_optional_args_type( $args_ref, q{},
+        qw( ip_type resolution_type separator ) );
+
+    check_mandatory_args_type( $args_ref, q{HASH},
+        qw( global_config pf_config ) );
+
+    my ( $hostname, $site_name, $input_filename, $output_filename,
+        $filter_type, $global_config, $pf_config )
         = @{$args_ref}{
         qw( hostname    site_name     input_filename   output_filename
             filter_type global_config pf_config )
@@ -444,13 +465,12 @@
     return __write_array_to_file( $output_filename, \@lines, qq{\n} );
 }
 
-=head2 fix_etc_hosts($args_ref)
+=head2 fix_etc_hosts()
 
 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:
+It takes the following named arguments:
 
 =over
 
@@ -458,9 +478,9 @@
 
 =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<input_file> the file to read from (usually F</etc/hosts>)
+
+=item I<output_file> the file to write to (usually F</etc/hosts> too)
 
 =item I<ip_type> I<ipv4> or I<ipv6> (but only I<ipv4> is currently supported)
 
@@ -475,26 +495,22 @@
 sub fix_etc_hosts {
     my ($args_ref) = @_;
 
-    check_mandatory_true_args_type(
-        $args_ref, q{},
-        qw( output_filename )
-    );
+    check_mandatory_true_args_type( $args_ref, q{}, qw( output_filename ) );
 
     __make_file(
-        {
+        {   file_type => q{etc_hosts},
+            filename  => $args_ref->{'output_filename'},
             %{$args_ref},
-            file_type => q{etc_hosts},
-            filename  => $args_ref->{'output_filename'},
         }
     );
 
     return 1;
 }
 
-=head2 make_sources_list_file($args_ref)
-
-This function creates the I<sources.list> file. It takes the following named
-arguments in I<%{$args_ref}: 
+=head2 make_sources_list_file()
+
+This function creates the F<sources.list> file.
+It takes the following named arguments:
 
 =over
 
@@ -505,7 +521,7 @@
 =item I<sections> a whitespace-separated list of repository sections (ie:
 q{common} or q{common foo1 foo2})
 
-=item I<template> the filename of the sources.list template
+=item I<template_filename> the filename of the sources.list template
 
 =item I<backports> whether to add an entry for backports (used as a boolean)
 
@@ -520,46 +536,43 @@
 sub make_sources_list_file {
     my ($args_ref) = @_;
 
-    unless ( ref $args_ref eq 'HASH' ) {
+    if ( ref $args_ref ne 'HASH' ) {
         croak q{ERROR: Invalid non-hash reference args_ref};
     }
 
-    __make_file( { %{$args_ref}, file_type => q{sources.list} } );
+    __make_file( { file_type => q{sources.list}, %{$args_ref} } );
 
     return 1;
 }
 
-=head2 fix_grub_kopt($args_ref)
+=head2 fix_grub_kopt()
 
 Reads a GRUB configuration file, fixes the kopt configuration, and writes the
-resulting GRUB configuration file. See C<__fix_grub_kopt()> documentation for
-details.
+resulting GRUB configuration file. See L</__fix_grub_kopt()> documentation
+for details.
+It takes the following named arguments:
 
 =cut
 
 sub fix_grub_kopt {
     my ($args_ref) = @_;
 
-    check_mandatory_true_args_type(
-        $args_ref, q{},
-        qw( output_filename )
-    );
+    check_mandatory_true_args_type( $args_ref, q{}, qw( output_filename ) );
 
     __make_file(
-        {
+        {   file_type => q{grub_config},
+            filename  => $args_ref->{'output_filename'},
             %{$args_ref},
-            file_type => q{grub_config},
-            filename  => $args_ref->{'output_filename'},
         }
     );
 
     return 1;
 }
 
-=head2 make_interfaces_file($args_ref)
-
-This function writes the I<interfaces> configuration file. It takes the
-following named arguments in %{$args_ref}:
+=head2 make_interfaces_file()
+
+This function writes the F<interfaces> configuration file.
+It takes the following named arguments:
 
 =over
 
@@ -580,19 +593,19 @@
 sub make_interfaces_file {
     my ($args_ref) = @_;
 
-    unless ( ref $args_ref eq 'HASH' ) {
+    if ( ref $args_ref ne 'HASH' ) {
         croak q{ERROR: Invalid non-hash reference args_ref};
     }
 
-    __make_file( { %{$args_ref}, file_type => q{interfaces} } );
+    __make_file( { file_type => q{interfaces}, %{$args_ref} } );
 
     return 1;
 }
 
-=head2 make_dhcpd_conf_file($arg_ref)
-
-This function writes the I<dhcpd.conf> configuration file for a given site. It
-takes the following named arguments in %{$arg_ref}:
+=head2 make_dhcpd_conf_file()
+
+This function writes the F<dhcpd.conf> configuration file for a given site.
+It takes the following named arguments:
 
 =over
 
@@ -602,6 +615,8 @@
 
 =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<filename> the output file name
 
 =back
@@ -611,11 +626,11 @@
 sub make_dhcpd_conf_file {
     my ($args_ref) = @_;
 
-    unless ( ref $args_ref eq 'HASH' ) {
+    if ( ref $args_ref ne 'HASH' ) {
         croak q{ERROR: Invalid non-hash reference args_ref};
     }
 
-    __make_file( { %{$args_ref}, file_type => q{dhcpd.conf} } );
+    __make_file( { file_type => q{dhcpd.conf}, %{$args_ref} } );
 
     return 1;
 }
@@ -626,16 +641,16 @@
     my ( $options, $global_config, $pf_config ) = @_;
 
     my $hostname = $options->{'host'};
-    unless ($hostname) {
+    if ( !$hostname ) {
         croak q{ERROR: undefined option host};
     }
 
     my $site_name = $options->{'site'};
-    unless ($site_name) {
+    if ( !$site_name ) {
         croak q{ERROR: undefined option site};
     }
 
-    if ( !VCS_checkout( $hostname, $pf_config, $options ) ) {
+    if ( !vcs_checkout( $hostname, $pf_config, $options ) ) {
         croak q{ERROR: "Unable to checkout configuration from VCS system"};
     }
 
@@ -647,15 +662,13 @@
     $subst_ref->{'DISTRIB'} = get_distrib_from_host_ref($host_ref);
     $subst_ref->{'MODE'}    = get_mode_from_host_ref($host_ref);
     $options->{'pkg_type'}
-        ||= get_pkgtype_from_hostname(
-        $hostname, $global_config,
-        $site_name
-        );
-
-    my $host_config = Get_config_for_hostname_on_site(
-        $hostname, $site_name, $subst_ref, $global_config, $pf_config
-    );
-    unless ($host_config) {
+        ||= get_pkgtype_from_hostname( $hostname, $global_config,
+        $site_name );
+
+    my $host_config
+        = Get_config_for_hostname_on_site( $hostname, $site_name, $subst_ref,
+        $global_config, $pf_config );
+    if ( !$host_config ) {
         croak
             qq{ERROR: Problem when parsing config for $hostname on $site_name};
     }
@@ -667,26 +680,26 @@
     my @sortedkeys = sort { Sort_config_sections( $host_config, $a, $b ) }
         @{ $host_config->{'__sections_order'} };
 
-    $| = 1;
-    my $errorcount = __do_updateloop(
-        $host_config, $options, $subst_ref, $global_config, \@sortedkeys
-    );
+    local $OUTPUT_AUTOFLUSH = 1;
+    my $errorcount
+        = __do_updateloop( $host_config, $options, $subst_ref, $global_config,
+        \@sortedkeys );
 
     print qq{$errorcount error(s) detected.\n};
 
     return;
 }
 
-########################################################################
-#
-# Only "private" functions after this line
-#
-
-=head2 __resolve_hostname($args_ref)
-
-Wrapper around resolve_hostname_from_dns($hostname) and
-resolve_hostname_from_global_config(). Returns a reference to an array
-containing the resolved IP addresses. Takes the following named arguments:
+=head1 INTERNAL INTERFACE
+
+This module defines the following internal (not exported) functions:
+
+=head2 __resolve_hostname()
+
+Wrapper around L<PFTools::Net/resolve_hostname_from_dns($hostname)> and
+L<PFTools::Structqueries/resolve_hostname_from_global_config()>. Returns a
+reference to an array containing the resolved IP addresses.
+It takes the following named arguments:
 
 =over
 
@@ -703,7 +716,7 @@
 =item I<ip_type> either I<ipv4> or I<ipv6> (only needed if I<resolution_type>
 is I<cnf>)
 
-=item I<global_config> as usual
+=item I<global_config> a reference to the global configuration hash
 
 =back
 
@@ -712,24 +725,17 @@
 sub __resolve_hostname {
     my ($args_ref) = @_;
 
-    check_mandatory_true_args_type(
-        $args_ref, q{},
-        qw( hostname )
-    );
-
-    check_optional_args_type(
-        $args_ref, q{},
-        qw( resolution_type site_name hosttype ip_type )
-    );
-
-    check_mandatory_args_type(
-        $args_ref, q{HASH},
-        qw( global_config )
-    );
+    check_mandatory_true_args_type( $args_ref, q{}, qw( hostname ) );
+
+    check_optional_args_type( $args_ref, q{},
+        qw( resolution_type site_name hosttype ip_type ) );
+
+    check_mandatory_args_type( $args_ref, q{HASH}, qw( global_config ) );
 
     my ($hostname, $resolution_type, $site_name,
         $hosttype, $ip_type,         $global_config
-        ) = @{$args_ref}{
+        )
+        = @{$args_ref}{
         qw( hostname resolution_type site_name
             hosttype ip_type         global_config )
         };
@@ -758,13 +764,11 @@
 
     if (not defined $hosttype
         and $hostshort
-        !~ m{\A (network|netmask|broadcast|gateway|prefix) }xms    # \z ?
+        !~ m{\A (?:network|netmask|broadcast|gateway|prefix) }xms    # \z ?
         )
     {
-        $hosttype = get_hosttype_from_hostname(
-            $hostshort, $global_config,
-            $site_name
-        );
+        $hosttype = get_hosttype_from_hostname( $hostshort, $global_config,
+            $site_name );
     }
 
     if ( $hostshort eq q{prefix} ) {
@@ -777,8 +781,7 @@
     }
 
     return resolve_hostname_from_global_config(
-        {
-            hostname      => $hostname,
+        {   hostname      => $hostname,
             ip_type       => $ip_type,
             global_config => $global_config,
             site_name     => $site_name,
@@ -799,9 +802,8 @@
     foreach my $section ( @{$sortedkeys} ) {
         next if $host_config->{$section}->{'action'} eq 'actiongroup';
 
-        if (not defined $host_config->{$section}->{'doing'}
-            and not defined $host_config->{$section}->{'done'}
-            )
+        if (    not defined $host_config->{$section}->{'doing'}
+            and not defined $host_config->{$section}->{'done'} )
         {
             $host_config->{$section}->{'doing'} = 1;
             Get_depends_for_action(
@@ -809,9 +811,8 @@
                 $host_config->{$section},
                 $section, $options
             );
-            if (defined $host_config->{$section}->{'depends'}
-                and $host_config->{$section}->{'depends'} =~ m{ \S+ }xms
-                )
+            if ( defined $host_config->{$section}->{'depends'}
+                and $host_config->{$section}->{'depends'} =~ m{ \S+ }xms )
             {
                 my @depends    = ();
                 my @dependsraw = split qr{ \s+ }xms,
@@ -824,12 +825,13 @@
                             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!};
+                            carp colored(
+                                qq{WARN: [$section] depends on addmount [$depend], it may not work during install!},
+                                q{bold yellow on_white}
+                            );
                         }
 
                         push @depends, $depend;
@@ -837,27 +839,23 @@
                 }
 
                 if (@depends) {
-                    unless ( $options->{'quiet'} ) {
-                        print qq{<$section>} . join q{ }, @depends;
+                    if ( !$options->{'quiet'} ) {
+                        print colored( qq{<$section> }, q{cyan} )
+                            . join( q{ }, @depends ) . qq{\n};
                     }
-                    $errorcount += __do_updateloop(
-                        $host_config, $options, $subst_ref,
-                        $global_config, \@depends
-                    );
+                    $errorcount += __do_updateloop( $host_config, $options,
+                        $subst_ref, $global_config, \@depends );
                 }
             }
 
-            unless ( $options->{'quiet'} ) {
-                print qq{[$section]\n};
+            if ( !$options->{'quiet'} ) {
+                print colored( qq{[$section]\n}, q{white} );
             }
 
             if (!Exec_action(
                     $host_config->{$section}->{'action'},
                     $host_config->{$section},
-                    $section,
-                    $options,
-                    $subst_ref,
-                    $global_config
+                    $section, $options, $subst_ref, $global_config
                 )
                 )
             {
@@ -871,9 +869,10 @@
     return $errorcount;
 }
 
-=head2 __search_and_replace_distrib($args_ref)
-
-Replace %DISTRIB% and %DISTSRC%. Take the following named arguments:
+=head2 __search_and_replace_distrib()
+
+Replace %DISTRIB% and %DISTSRC%.
+It takes the following named arguments:
 
 =over
 
@@ -890,19 +889,13 @@
 sub __search_and_replace_distrib {
     my ($args_ref) = @_;
 
-    check_mandatory_args_type(
-        $args_ref, q{},
-        qw( line )
-    );
-
-    check_mandatory_args_type(
-        $args_ref, q{HASH},
-        qw( host_ref )
-    );
+    check_mandatory_args_type( $args_ref, q{}, qw( line ) );
+
+    check_mandatory_args_type( $args_ref, q{HASH}, qw( host_ref ) );
 
     my ( $line, $host_ref ) = @{$args_ref}{qw( line host_ref )};
 
-    return $line unless $line;    # no warnings if undef
+    return $line if !$line;    # no warnings if undef
 
     $line =~ s{ %DISTSRC% }{$host_ref->{'deployment'}->{'mode'}}xmsg;
     $line =~ s{ %DISTRIB% }{$host_ref->{'deployment'}->{'distrib'}}xmsg;
@@ -910,7 +903,7 @@
     return $line;
 }
 
-=head2 __search_and_replace_ip($args_ref)
+=head2 __search_and_replace_ip()
 
 Replace hostname specs by IP addresses in a given string:
 
@@ -919,7 +912,7 @@
 
 FIXME more documentation and usage samples here
 
-Take the following named arguments:
+It takes the following named arguments:
 
 =over
 
@@ -931,7 +924,7 @@
 
 =item I<ip_type> the IP type: ipv4 or ipv6
 
-=item I<resolution_type> (optional, see the __resolve_hostname() documentation)
+=item I<resolution_type> (optional, see the L</__resolve_hostname()> documentation)
 
 =item I<separator> (optional) the separator to use when something resolves to
 multiple IP addresses. If undefined, a space will be used. The special value
@@ -952,35 +945,27 @@
 sub __search_and_replace_ip {
     my ($args_ref) = @_;
 
-    check_mandatory_args_type(
-        $args_ref, q{},
-        qw( line )
-    );
-
-    check_mandatory_true_args_type(
-        $args_ref, q{},
-        qw( hostname site_name ip_type )
-    );
-
-    check_optional_args_type(
-        $args_ref, q{},
-        qw( separator resolution_type )
-    );
-
-    check_mandatory_args_type(
-        $args_ref, q{HASH},
-        qw( host_ref site_ref subst_ref global_config )
-    );
-
-    my ($line, $hostname, $site_name, $ip_type, $separator, $resolution_type,
-        $host_ref, $site_ref, $subst_ref, $global_config
+    check_mandatory_args_type( $args_ref, q{}, qw( line ) );
+
+    check_mandatory_true_args_type( $args_ref, q{},
+        qw( hostname site_name ip_type ) );
+
+    check_optional_args_type( $args_ref, q{},
+        qw( separator resolution_type ) );
+
+    check_mandatory_args_type( $args_ref, q{HASH},
+        qw( host_ref site_ref subst_ref global_config ) );
+
+    my ($line,      $hostname,        $site_name, $ip_type,
+        $separator, $resolution_type, $host_ref,  $site_ref,
+        $subst_ref, $global_config
         )
         = @{$args_ref}{
         qw( line hostname site_name ip_type separator resolution_type
             host_ref site_ref subst_ref global_config )
         };
 
-    return $line unless $line;    # no warnings if undef
+    return $line if !$line;    # no warnings if undef
 
     # $separator //= q{ };
     if ( not defined $separator ) {
@@ -1026,7 +1011,7 @@
 
         my $lengthbefore = defined $before ? length $before : 0;
 
-        if ( $back eq "\\\\" ) {
+        if ( $back eq q{\\} ) {
             substr( $line, $lengthbefore, length $match, $matchback );
             $pos = $lengthbefore;
             next;
@@ -1036,16 +1021,22 @@
         $match2 =~ s{ HOSTNAME }{$hostname}xmsg;
         $match2 =~ s{ POPNAME }{$subst_ref->{'POPNAME'}}xmsg;
 
-        my $resolved_ref = __resolve_hostname(
-            {
-                hostname        => $match2,
-                resolution_type => $resolution_type,
-                ip_type         => $ip_type,
-                site_name       => $site_name,
-                global_config   => $global_config,
-            }
-        );
-        if ( @{$resolved_ref} ) {
+        my $resolved_ref;
+        eval {
+            $resolved_ref = __resolve_hostname(
+                {   hostname        => $match2,
+                    resolution_type => $resolution_type,
+                    ip_type         => $ip_type,
+                    site_name       => $site_name,
+                    global_config   => $global_config,
+                }
+            );
+        };
+        if ( $EVAL_ERROR || !$resolved_ref ) {
+            carp colored( qq{WARNING: Unable to resolve $match2},
+                q{bold yellow on_white} );
+        }
+        elsif ( @{$resolved_ref} ) {
             if ( $separator eq q{DUPLICATE} ) {
                 foreach my $res ( @{$resolved_ref} ) {
                     my $templine2 = $line;
@@ -1069,14 +1060,14 @@
     return @lines;
 }
 
-=head2 __search_and_replace_iface($args_ref)
+=head2 __search_and_replace_iface()
 
 Replace iface specs by iface names in a given string:
 
   eth.vlan-systeme.private => eth0
   eth.vlan-foo-8021q.private => eth2.42
 
-Take the following named arguments:
+It takes the following named arguments:
 
 =over
 
@@ -1095,20 +1086,14 @@
 sub __search_and_replace_iface {
     my ($args_ref) = @_;
 
-    check_mandatory_args_type(
-        $args_ref, q{},
-        qw( line )
-    );
-
-    check_mandatory_args_type(
-        $args_ref, q{HASH},
-        qw( host_ref subst_ref )
-    );
+    check_mandatory_args_type( $args_ref, q{}, qw( line ) );
+
+    check_mandatory_args_type( $args_ref, q{HASH}, qw( host_ref subst_ref ) );
 
     my ( $line, $host_ref, $subst_ref )
         = @{$args_ref}{qw( line host_ref subst_ref )};
 
-    return $line unless $line;    # no warnings if undef
+    return $line if !$line;    # no warnings if undef
 
     my $pos = length $line;
     while (
@@ -1144,10 +1129,17 @@
 
         my $lengthbefore = defined $before ? length $before : 0;
 
-        ( my $real_vlan = $vlan )
-            =~ s{ POPNAME }{$subst_ref->{'POPNAME'}}xms;
-
-        my $eth = get_iface_vlan_from_hostname( $real_vlan, $host_ref );
+        ( my $real_vlan = $vlan ) =~ s{ POPNAME }{$subst_ref->{'POPNAME'}}xms;
+
+        my $eth;
+        eval {
+            $eth = get_iface_vlan_from_hostname( $real_vlan, $host_ref ); };
+        if ($EVAL_ERROR) {
+            carp colored(
+                qq{WARNING: Unable to find interface for host in vlan '$real_vlan'},
+                q{bold yellow on_white}
+            );
+        }
         if ( defined $eth ) {
             my $neweth = $eth;
             if ( $type eq q{.} ) {
@@ -1168,10 +1160,10 @@
     return $line;
 }
 
-=head2 __build_preseed($args_ref)
+=head2 __build_preseed()
 
 Builds the preseed file content for a host.
-I<$args_ref> is a reference to a hash of named parameters:
+It takes the following named arguments:
 
 =over
 
@@ -1181,7 +1173,7 @@
 
 =item I<template_filename> the template file name.
 
-=item I<pf_script> FIXME ???
+=item I<pf_script> the configuration script
 
 =back
 
@@ -1190,15 +1182,10 @@
 sub __build_preseed {
     my ($args_ref) = @_;
 
-    check_mandatory_true_args_type(
-        $args_ref, q{},
-        qw( hostname template_filename pf_script )
-    );
-
-    check_mandatory_args_type(
-        $args_ref, q{HASH},
-        qw( host_ref )
-    );
+    check_mandatory_true_args_type( $args_ref, q{},
+        qw( hostname template_filename pf_script ) );
+
+    check_mandatory_args_type( $args_ref, q{HASH}, qw( host_ref ) );
 
     my ( $hostname, $template_filename, $pf_script, $host_ref )
         = @{$args_ref}{qw( hostname template_filename pf_script host_ref )};
@@ -1221,11 +1208,11 @@
     return [$content];
 }
 
-=head2 __build_pxe_boot($args_ref)
+=head2 __build_pxe_boot()
 
 Builds the PXE boot file content for a host and returns a reference to the
-array of lines. I<$args_ref> is a reference to a hash of named
-parameters:
+array of lines.
+It takes the following named arguments:
 
 =over
 
@@ -1248,24 +1235,16 @@
 sub __build_pxe_boot {
     my ($args_ref) = @_;
 
-    check_mandatory_true_args_type(
-        $args_ref, q{},
-        qw( hostname site_name preseed_filename )
-    );
-
-    check_optional_args_type(
-        $args_ref, q{},
-        qw( template_filename )
-    );
-
-    check_mandatory_args_type(
-        $args_ref, q{HASH},
-        qw( global_config pf_config )
-    );
-
-    my ($hostname, $site_name, $preseed_filename, $template_filename,
-        $global_config, $pf_config
-        )
+    check_mandatory_true_args_type( $args_ref, q{},
+        qw( hostname site_name preseed_filename ) );
+
+    check_optional_args_type( $args_ref, q{}, qw( template_filename ) );
+
+    check_mandatory_args_type( $args_ref, q{HASH},
+        qw( global_config pf_config ) );
+
+    my ( $hostname, $site_name, $preseed_filename, $template_filename,
+        $global_config, $pf_config )
         = @{$args_ref}{
         qw(
             hostname site_name preseed_filename template_filename
@@ -1276,13 +1255,13 @@
     # 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};
+        croak q{ERROR: Invalid global_config hashref: no 'ZONE' key found};
     }
 
     # 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};
+        croak q{ERROR: Invalid pf_config hashref: no 'vcs' key found};
     }
 
     my $host_ref = get_host_config( $hostname, $global_config, $site_name );
@@ -1296,8 +1275,7 @@
         = __get_md5sum_for_preseedfile( $preseed_filename, $pf_config );
 
     my $iface = get_iface_vlan_from_hostname(
-        $host_ref->{'deployment'}->{'dhcpvlan'}, $host_ref
-    );
+        $host_ref->{'deployment'}->{'dhcpvlan'}, $host_ref );
 
     # Get cmdline, remove leading and trailing whitespace
     my $cmdline = get_complete_cmdline_from_host_ref($host_ref);
@@ -1323,13 +1301,24 @@
     return [$content];
 }
 
-=head2 __build_interfaces($args_ref)
-
-Builds the content for the I<interfaces> configuration file for I<hostname> at
-I<site_name>. I<global_config> is a reference to the global configuration
-hash. I<pf_config> is a referenfe to the pf-tools configuration hash. This
-function takes named arguments in I<%{$args_ref}> and returns a reference
+=head2 __build_interfaces()
+
+Builds the content for the F<interfaces> configuration file and returns a reference
 to an array of lines.
+It takes the following named arguments:
+
+=over
+
+=item I<hostname> the host name
+
+=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
+
+=back
+
 
 =cut
 
@@ -1337,15 +1326,11 @@
 sub __build_interfaces {
     my ($args_ref) = @_;
 
-    check_mandatory_true_args_type(
-        $args_ref, q{},
-        qw( hostname site_name )
-    );
-
-    check_mandatory_args_type(
-        $args_ref, q{HASH},
-        qw( global_config pf_config )
-    );
+    check_mandatory_true_args_type( $args_ref, q{},
+        qw( hostname site_name ) );
+
+    check_mandatory_args_type( $args_ref, q{HASH},
+        qw( global_config pf_config ) );
 
     my ( $hostname, $global_config, $pf_config, $site_name )
         = @{$args_ref}{qw( hostname global_config pf_config site_name )};
@@ -1353,13 +1338,13 @@
     # 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};
+        croak q{ERROR: Invalid global_config hashref: no 'ZONE' key found};
     }
 
     # 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};
+        croak q{ERROR: Invalid pf_config hashref: no 'vcs' key found};
     }
 
     my $host_ref = get_host_config( $hostname, $global_config, $site_name );
@@ -1369,10 +1354,8 @@
     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:
@@ -1382,7 +1365,7 @@
         if ( scalar @{ $routes->{$dest} } > 1 ) {
             foreach my $entry ( @{ $routes->{$dest} } ) {
                 my ( $if, $dst, $via, $gw ) = split qr{ \s+ }xms, $entry;
-                unless ( defined $gw ) {
+                if ( !defined $gw ) {
                     croak
                         qq{ERROR: host $hostname: route to $dest needs a gateway};
                 }
@@ -1399,7 +1382,7 @@
 
         # ... default route
         if ( $dst eq 'default' ) {
-            unless ( defined $gw ) {
+            if ( !defined $gw ) {
                 croak
                     qq{ERROR: host $hostname: default route needs a gateway};
             }
@@ -1416,8 +1399,7 @@
     my @lines = (
         q{#},
         q{# This file was auto-generated by mk_interfaces -- DO NOT EDIT!},
-        q{#},
-        q{},
+        q{#}, q{},
     );
 
     foreach my $iface ( @{ $interfaces->{'__order'} } ) {
@@ -1427,10 +1409,10 @@
     return \@lines;
 }
 
-=head2 __build_interface_lines_ref( $iface, $routes, $host_ref, $pf_config )
+=head2 __build_interface_lines_ref($iface,$routes,$host_ref,$pf_config)
 
 Builds a list of configuration lines for an interface and returns a reference
-to it. Also, fill %{$routes}.
+to it. Also, fill I<%{$routes}>.
 
 =cut
 
@@ -1441,17 +1423,13 @@
 
     my $if_part = $host_ref->{'interfaces'}->{$iface};
     my $if_method
-        = $if_part->{'method'}
-        ? $if_part->{'method'}
+        = $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'
-        )
+    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' )
     {
         return \@iface_lines;
     }
@@ -1473,8 +1451,10 @@
         # Routes
         # FIXME add test cases in t/* for non-default routes
         my $suffix = get_suffix_from_ip_type($ip_type);
-        foreach my $route ( @{ $if_part->{ '@route' . $suffix } } ) {
-            if ( $route =~ m{ \A \s* (\S+) \s* (?: via \s* \S+ )? \s* \z }xms ) {
+        foreach my $route ( @{ $if_part->{ '@route' . $suffix } } )
+        {    ## no critic(RequireInterpolationOfMetachars);
+            if ($route =~ m{ \A \s* (\S+) \s* (?: via \s* \S+ )? \s* \z }xms )
+            {
                 my $destination = $1;
                 push @{ $routes->{$destination} }, qq{$iface $route};
             }
@@ -1486,9 +1466,8 @@
             push @iface_lines, qq{\tvlan_raw_device\t$raw_device};
 
             # Set MTU to 1496 unless told otherwise
-            if ($if_part->{'options'}
-                and $if_part->{'options'} !~ m{ mtu }xms
-                )
+            if (    $if_part->{'options'}
+                and $if_part->{'options'} !~ m{ mtu }xms )
             {
                 $if_part->{'options'} .= q{, mtu 1496};
             }
@@ -1499,10 +1478,8 @@
 
         # Options
         if ( $if_part->{'options'} ) {
-            foreach my $option (
-                split qr{ \s* [,] \s* }xms,
-                $if_part->{'options'}
-                )
+            foreach my $option ( split qr{ \s* [,] \s* }xms,
+                $if_part->{'options'} )
             {
                 push @iface_lines,
                     qq{\tup\t\t/sbin/ip link set $iface $option};
@@ -1513,22 +1490,31 @@
     return \@iface_lines;
 }
 
-=head2 __build_resolv_conf($args_ref)
-
-Writes the I<resolv.conf> configuration for I<hostname> at I<site_name>.
-I<global_config> is a reference to the global configuration hash.  This
-function takes named arguments in I<%{$args_ref}> and returns a reference
-to an array of lines.
+=head2 __build_resolv_conf()
+
+Writes the F<resolv.conf> configuration and returns a reference to an array of lines.
+It takes the following named arguments:
+
+=over
+
+=item I<template_filename> the name of file containing the template to use
+
+=item I<hostname> the host name
+
+=item I<site_name> the site name
+
+=item I<global_config> a reference to the global configuration hash
+
+=back
+
 
 =cut
 
 sub __build_resolv_conf {
     my ($args_ref) = @_;
 
-    check_mandatory_true_args_type(
-        $args_ref, q{},
-        qw( hostname site_name template_filename )
-    );
+    check_mandatory_true_args_type( $args_ref, q{},
+        qw( hostname site_name template_filename ) );
 
     check_mandatory_args_type( $args_ref, q{HASH}, qw( global_config ) );
 
@@ -1539,7 +1525,7 @@
     # 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};
+        croak q{ERROR: Invalid global_config hashref: no 'ZONE' key found};
     }
 
     my $host_ref = get_host_config( $hostname, $global_config, $site_name );
@@ -1552,8 +1538,7 @@
     foreach my $ip_type (qw( ipv4 ipv6 )) {
         foreach my $dns (@dns) {
             my $resolved_ref = __resolve_hostname(
-                {
-                    hostname        => $dns,
+                {   hostname        => $dns,
                     resolution_type => q{cnf},
                     ip_type         => $ip_type,
                     site_name       => $site_name,
@@ -1576,10 +1561,11 @@
     return $lines_ref;
 }
 
-=head2 __build_zone($args_ref)
+=head2 __build_zone()
 
 This function creates the zone file content for a given site. It returns a
-reference to the list of generated lines. The named arguments are:
+reference to the list of generated lines.
+It takes the following named arguments:
 
 =over
 
@@ -1590,6 +1576,9 @@
 =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
+
 =back
 
 =cut
@@ -1597,10 +1586,9 @@
 sub __build_zone {
     my ($args_ref) = @_;
 
-    check_mandatory_true_args_type(
-        $args_ref, q{},
-        qw( site_name zone_name template_filename )
-    );
+    check_mandatory_true_args_type( $args_ref, q{},
+        qw( site_name zone_name ) );
+    check_optional_args_type( $args_ref, q{}, qw( template_filename ) );
 
     check_mandatory_args_type( $args_ref, q{HASH}, qw( global_config ) );
 
@@ -1611,7 +1599,7 @@
     # 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};
+        croak q{ERROR: Invalid global_config hashref: no 'ZONE' key found};
     }
 
     my $zone_ref = $global_config->{'ZONE'}->{'BY_NAME'}->{$zone_name};
@@ -1628,9 +1616,13 @@
     my $new_soa = clone($soa);
     $new_soa->{'serial'}
         = $soa->{'serial'} eq 'AUTO' ? time : $soa->{'serial'};
+
+    ## no critic(RequireInterpolationOfMetachars);
     $new_soa->{'ns_list'} = $new_soa->{'@ns'};
     $new_soa->{'mx_list'} = $new_soa->{'@mx'};
 
+    ## use critic
+
     # Merge private and public parts for a given zone_name
     my $merged_zone_ref = merge( $zone_part, $zone_ref->{'ALL_SITES'} );
 
@@ -1638,8 +1630,7 @@
     my @networks = ();
 
     my @network_order = @{ $zone_part->{'__network_order'} };
-    push @network_order,
-        @{ $zone_ref->{'ALL_SITES'}->{'__network_order'} };
+    push @network_order, @{ $zone_ref->{'ALL_SITES'}->{'__network_order'} };
 
     foreach my $network (@network_order) {
         my $network_ref = {
@@ -1650,12 +1641,13 @@
         my @records = ();
         foreach my $spec (qw( network netmask broadcast gateway )) {
             my $value = $merged_zone_ref->{$network}->{$spec};
-            next unless defined $value;
-
-            push @records, {
+            next if !defined $value;
+
+            push @records,
+                {
                 name  => qq{$spec.$network},
                 value => $value,
-            };
+                };
         }
         $network_ref->{'records'} = \@records;
 
@@ -1665,11 +1657,10 @@
     # Servers
     my @servers = ();
 
-    my @hostclass_order
-        = uniq(
+    my @hostclass_order = uniq(
         @{ $zone_ref->{'BY_SITE'}->{$site_name}->{'__hostclass_order'} },
         @{ $zone_ref->{'ALL_SITES'}->{'__hostclass_order'} },
-        );
+    );
 
     foreach my $server (@hostclass_order) {
         my $server_ref = {
@@ -1688,10 +1679,11 @@
                 }
             }
             else {
-                push @records, {
+                push @records,
+                    {
                     name  => $field,
                     value => $merged_zone_ref->{$server}->{$field},
-                };
+                    };
             }
         }
         $server_ref->{'records'} = \@records;
@@ -1700,6 +1692,11 @@
 
     }
 
+    my $templates_dirname
+        = $args_ref->{'pf_config'}->{'path'}->{'templates_dir'};
+
+    $template_filename ||= join q{/}, $templates_dirname, q{zone.tpl};
+
     my $vars_ref = {
         zone_name => $zone_name,
         site_name => $site_name,
@@ -1715,11 +1712,11 @@
     return $lines_ref;
 }
 
-=head2 __build_sources_list($args_ref)
-
-This function creates the I<sources.list> file content and returns a reference
-to the array of lines. It takes the following named arguments in
-I<%{$args_ref}: 
+=head2 __build_sources_list()
+
+This function creates the F<sources.list> file content and returns a reference
+to the array of lines.
+It takes the following named arguments:
 
 =over
 
@@ -1744,32 +1741,22 @@
 sub __build_sources_list {
     my ($args_ref) = @_;
 
-    check_mandatory_true_args_type(
-        $args_ref, q{},
-        qw( hostname site_name template )
-    );
-
-    check_mandatory_args_type(
-        $args_ref, q{HASH},
-        qw( global_config pf_config)
-    );
-
-    check_mandatory_args_type(
-        $args_ref, q{ARRAY},
-        qw( sections_ref )
-    );
-
-    check_optional_args_type(
-        $args_ref, q{},
-        qw( backports )
-    );
-
-    my ($hostname, $site_name, $sections_ref, $template, $backports,
-        $global_config, $pf_config
-        )
+    check_mandatory_true_args_type( $args_ref, q{},
+        qw( hostname site_name ) );
+
+    check_mandatory_args_type( $args_ref, q{HASH},
+        qw( global_config pf_config) );
+
+    check_optional_args_type( $args_ref, q{ARRAY}, qw( sections_ref ) );
+
+    check_optional_args_type( $args_ref, q{},
+        qw( backports template_filename ) );
+
+    my ( $hostname, $site_name, $sections_ref, $template_filename, $backports,
+        $global_config, $pf_config )
         = @{$args_ref}{
         qw(
-            hostname site_name sections_ref template backports
+            hostname site_name sections_ref template_filename backports
             global_config pf_config
             )
         };
@@ -1777,7 +1764,7 @@
     # 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};
+        croak q{ERROR: Invalid global_config hashref: no 'ZONE' key found};
     }
 
     if ( not @{$sections_ref} ) {
@@ -1790,8 +1777,7 @@
         # Remove leading and trailing whitespace
         $section =~ s{ \A \s* (\S*) \s* \z }{$1}xms;
         if ( not $section ) {
-            croak
-                q{ERROR: Invalid empty or blank section in sections_ref};
+            croak q{ERROR: Invalid empty or blank section in sections_ref};
         }
         push @sections, $section;
     }
@@ -1800,8 +1786,8 @@
     my $host_ref = get_host_config( $hostname, $global_config, $site_name );
     my $deployment_mode = $host_ref->{'deployment'}->{'mode'};
 
-    $template ||= join q{/}, $pf_config->{'path'}->{'templates_dir'},
-        $pf_config->{$deployment_mode}->{'sources_list'};
+    $template_filename ||= join q{/}, $pf_config->{'path'}->{'templates_dir'},
+        $pf_config->{$deployment_mode}->{'sources_list'} . q{.tpl};
 
     my $vars_ref = {
         mode    => $deployment_mode,
@@ -1812,15 +1798,17 @@
         backports       => $backports,
     };
 
-    my $content = __read_and_process_template( $template, $vars_ref );
+    my $content
+        = __read_and_process_template( $template_filename, $vars_ref );
 
     return [$content];
 }
 
-=head2 __fix_etc_hosts($args_ref)
+=head2 __fix_etc_hosts()
 
 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:
+returns a reference to the list of lines.
+It takes the following named arguments:
 
 =over
 
@@ -1828,7 +1816,7 @@
 
 =item I<site_name> (optional) the site name
 
-=item I<input_filename> the file to read from (usually I</etc/hosts>)
+=item I<input_filename> the file to read from (usually F</etc/hosts>)
 
 =item I<ip_type> I<ipv4> or I<ipv6> (but only I<ipv4> is currently supported)
 
@@ -1845,27 +1833,19 @@
 sub __fix_etc_hosts {
     my ($args_ref) = @_;
 
-    check_mandatory_true_args_type(
-        $args_ref, q{},
-        qw( hostname input_filename ip_type )
-    );
-
-    check_optional_args_type(
-        $args_ref, q{},
-        qw( site_name )
-    );
+    check_mandatory_true_args_type( $args_ref, q{},
+        qw( hostname input_filename ip_type ) );
+
+    check_optional_args_type( $args_ref, q{}, qw( site_name ) );
 
     # FIXME pf_config is not actually used
-    check_mandatory_args_type(
-        $args_ref, q{HASH},
-        qw( global_config pf_config )
-    );
+    check_mandatory_args_type( $args_ref, q{HASH},
+        qw( global_config pf_config ) );
 
     my ($hostname, $site_name,     $input_filename,
         $ip_type,  $global_config, $pf_config
         )
-        = @{$args_ref}
-        {
+        = @{$args_ref}{
         qw( hostname site_name input_filename
             ip_type global_config pf_config )
         };
@@ -1876,8 +1856,7 @@
 
     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 );
 
     # This should work for IPv6 too...
     my $ip_and_prefix = $host_ref->{'interfaces'}->{$dhcp_iface}->{$ip_type};
@@ -1886,7 +1865,7 @@
     my $lines_ref = __read_file_in_array( $input_filename, 1 );
 
     foreach my $line ( @{$lines_ref} ) {
-        next unless $line =~ m{ $hostname }xms;
+        next if $line !~ m{ $hostname }xms;
 
         $line =~ s{ \A 127 [.] 0 [.] [\d]{1,3} [.] [\d]{1,3} }{$ip_deploy}xms;
     }
@@ -1894,11 +1873,11 @@
     return $lines_ref;
 }
 
-=head2 __fix_grub_kopt($args_ref)
+=head2 __fix_grub_kopt()
 
 Reads a GRUB configuration file, fixes the kopt configuration, and returns a
-reference to the list of (possibly updated) lines. Takes the following named
-arguments:
+reference to the list of (possibly updated) lines.
+It takes the following named arguments:
 
 =over
 
@@ -1922,25 +1901,21 @@
 sub __fix_grub_kopt {
     my ($args_ref) = @_;
 
-    check_mandatory_true_args_type(
-        $args_ref, q{},
-        qw( hostname grub_version )
-    );
-
-    check_optional_args_type(
-        $args_ref, q{},
-        qw( site_name input_filename )
-    );
-
-    check_mandatory_args_type(
-        $args_ref, q{HASH},
-        qw( global_config pf_config )
-    );
-
-    my ($hostname, $site_name, $input_filename, $grub_version, $global_config,
-        $pf_config
+    check_mandatory_true_args_type( $args_ref, q{},
+        qw( hostname grub_version ) );
+
+    check_optional_args_type( $args_ref, q{},
+        qw( site_name input_filename ) );
+
+    check_mandatory_args_type( $args_ref, q{HASH},
+        qw( global_config pf_config ) );
+
+    my ($hostname,     $site_name,     $input_filename,
+        $grub_version, $global_config, $pf_config
         )
-        = @{$args_ref}{qw( hostname site_name input_filename grub_version global_config )};
+        = @{$args_ref}{
+        qw( hostname site_name input_filename grub_version global_config pf_config )
+        };
 
     if ( $grub_version != 1 and $grub_version != 2 ) {
         croak qq{ERROR: Invalid grub_version '$grub_version'};
@@ -1992,10 +1967,11 @@
     return $lines_ref;
 }
 
-=head2 __build_dhcpd_conf($args_ref)
-
-Builds the I<dhcpd.conf> content for a given site. Returns a reference to the
-list of generated lines. The named arguments are:
+=head2 __build_dhcpd_conf()
+
+Builds the F<dhcpd.conf> content for a given site. Returns a reference to the
+list of generated lines.
+It takes the following named arguments:
 
 =over
 
@@ -2004,6 +1980,9 @@
 =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
+
 =back
 
 =cut
@@ -2011,10 +1990,8 @@
 sub __build_dhcpd_conf {
     my ($args_ref) = @_;
 
-    check_mandatory_true_args_type(
-        $args_ref, q{},
-        qw( site_name template_filename )
-    );
+    check_mandatory_true_args_type( $args_ref, q{}, qw( site_name ) );
+    check_optional_args_type( $args_ref, q{}, qw( template_filename ) );
     check_mandatory_args_type( $args_ref, q{HASH}, qw( global_config ) );
 
     my $site_ref = get_site_dhcp_config(
@@ -2030,21 +2007,28 @@
         foreach my $hostclass ( keys %{ $site_ref->{$vlan} } ) {
             next
                 if $hostclass eq q{subnet}
-                    or $hostclass eq q{netmask}
-                    or $hostclass eq q{routers};
+                or $hostclass eq q{netmask}
+                or $hostclass eq q{routers};
 
             my $host_ref = $site_ref->{$vlan}->{$hostclass};
             foreach my $hostname ( keys %{$host_ref} ) {
-                push @hosts, {
+                push @hosts,
+                    {
                     hostname    => $hostname,
                     definitions => $host_ref->{$hostname},
-                };
+                    };
             }
         }
     }
 
-    my $template_filename = $args_ref->{'template_filename'};
-    my $vars_ref          = {
+    my $templates_dirname
+        = $args_ref->{'pf_config'}->{'path'}->{'templates_dir'};
+
+    my $template_filename = $args_ref->{'template_filename'} ||= join q{/},
+        $templates_dirname,
+        q{dhcpd.conf.tpl};
+
+    my $vars_ref = {
         hosts   => \@hosts,
         subnets => \@subnets,
     };
@@ -2056,7 +2040,7 @@
     return $lines_ref;
 }
 
-=head2 __get_kpkg_from_kernel( $pxefilename, $deploymode )
+=head2 __get_kpkg_from_kernel($pxefilename,$deploymode)
 
 This functions computes the name of the kernel package to install, based on the
 I<$pxefilename> and I<$deploymode> values.
@@ -2079,7 +2063,7 @@
     return $package_name;
 }
 
-=head2 __get_md5sum_for_preseedfile( $filename, $pf_config )
+=head2 __get_md5sum_for_preseedfile($filename,$pf_config)
 
 This function computes and returns the MD5 digest for the preseedfile named
 I<$filename>.
@@ -2106,7 +2090,7 @@
         $filename;
 
     my $fh = IO::File->new( $file_path, q{<} );
-    unless ($fh) {
+    if ( !$fh ) {
         croak qq{ERROR: $file_path: $OS_ERROR};
     }
 
@@ -2118,7 +2102,7 @@
     return $md5sum;
 }
 
-=head2 __move_if_different( $source, $destination )
+=head2 __move_if_different($source,$destination)
 
 Compares I<$source> and I<$destination>. If they differ, moves I<$source> to
 I<$destination>. If they are equal, unlink I<$source>.
@@ -2129,14 +2113,14 @@
     my ( $source, $destination ) = @_;
 
     if ( compare( $source, $destination ) ) {
-        unless ( move( $source, $destination ) ) {
+        if ( !move( $source, $destination ) ) {
             croak qq{ERROR: move( $source, $destination ): $OS_ERROR};
         }
 
         return 1;
     }
 
-    unless ( unlink($source) ) {
+    if ( !unlink $source ) {
         carp qq{WARNING: unlink $source: $OS_ERROR};
     }
 
@@ -2153,6 +2137,7 @@
 sub __read_file_in_scalar {
     my ($filename) = @_;
 
+    ## no critic(RequireInterpolationOfMetachars);
     if ( not $filename ) {
         croak q{ERROR: Invalid empty $filename};
     }
@@ -2161,22 +2146,24 @@
         croak q{ERROR: Invalid non-scalar $filename};
     }
 
+    ## use critic
+
     my $fh = IO::File->new( $filename, q{<} );
-    unless ($fh) {
+    if ( !$fh ) {
         croak qq{ERROR: open $filename: $OS_ERROR};
     }
 
     # FIXME use File::Slurp instead?
     my $content = do { local $INPUT_RECORD_SEPARATOR = undef; <$fh> };
 
-    unless ( $fh->close() ) {
+    if ( !$fh->close() ) {
         croak qq{ERROR: close $filename: $OS_ERROR};
     }
 
     return $content;
 }
 
-=head2 __read_file_in_array( $filename, $chomp_wanted )
+=head2 __read_file_in_array($filename,$chomp_wanted)
 
 Reads I<$filename> as an array of lines. Each line is chomped unless
 I<$chomp_wanted> is 0 (the default is 1). Returns a reference to the array of
@@ -2187,13 +2174,13 @@
 sub __read_file_in_array {
     my ( $filename, $chomp_wanted ) = @_;
 
-    $chomp_wanted = 1 unless defined $chomp_wanted;
+    $chomp_wanted = 1 if !defined $chomp_wanted;
 
     if ( not $filename ) {
-        croak q{ERROR: Invalid empty filename};
+        croak q{ERROR: Invalid empty $filename};
     }
     if ( ref $filename ) {
-        croak q{ERROR: Invalid non-scalar filename};
+        croak q{ERROR: Invalid non-scalar $filename};
     }
 
     # Correctly handle q{-} for STDIN
@@ -2202,7 +2189,7 @@
         push @open_args, q{<};
     }
     my $fh = IO::File->new(@open_args);
-    unless ($fh) {
+    if ( !$fh ) {
         croak qq{ERROR: open $filename: $OS_ERROR};
     }
 
@@ -2215,14 +2202,14 @@
         push @lines, $line;
     }
 
-    unless ( $fh->close() ) {
+    if ( !$fh->close() ) {
         croak qq{ERROR: close $filename: $OS_ERROR};
     }
 
     return \@lines;
 }
 
-=head2 __write_scalar_to_filehandle( $fh, $filename, $scalar )
+=head2 __write_scalar_to_filehandle($fh,$filename,$scalar)
 
 This functions writes I<$scalar> to the I<$fh> filehandle, then closes it.
 
@@ -2236,11 +2223,11 @@
     return 1;
 }
 
-=head2 __write_array_to_filehandle( $fh, $filename, $array_ref, $line_separator )
+=head2 __write_array_to_filehandle($fh,$filename,$array_ref,$line_separator)
 
 This functions writes the list of lines referenced by I<$array_ref> to the
 I<$fh> filehandle, then closes it. I<$line_separator> is written between each
-line (the default is the empty string, but a useful value is qq{\n}).
+line (the default is the empty string, but a useful value is C<qq{\n}>).
 
 =cut
 
@@ -2248,29 +2235,30 @@
     my ( $fh, $filename, $array_ref, $line_separator ) = @_;
 
     # $line_separator //= q{};
-    unless ( defined $line_separator ) {
+    if ( !defined $line_separator ) {
         $line_separator = q{};
     }
 
     # IO::File does not implement filename()
     #my $filename = $fh->filename();
 
-    unless (
-        $fh->print( join( $line_separator, @{$array_ref} ), $line_separator )
+    if (!$fh->print(
+            join( $line_separator, @{$array_ref} ), $line_separator
+        )
         )
     {
         croak qq{ERROR: print $filename: $OS_ERROR};
     }
 
-    unless ( $fh->close() ) {
+    if ( !$fh->close() ) {
         croak qq{ERROR: close $filename: $OS_ERROR};
     }
 }
 
-=head2 __write_array_to_file( $filename, $lines_ref, $line_separator )
+=head2 __write_array_to_file($filename,$lines_ref,$line_separator)
 
 Open a temporary output file (or STDOUT if $filename is '-'), call
-__write_array_to_filehandle(), and move to the real destination if the content
+L</__write_array_to_filehandle($fh,$filename,$array_ref,$line_separator)>, and move to the real destination if the content
 has changed.
 
 =cut
@@ -2294,7 +2282,7 @@
     my ( $out_fh, $out_fn );
     if ( $filename eq q{-} ) {
         $out_fh = IO::File->new();
-        unless ( $out_fh->fdopen( fileno(STDOUT), q{>} ) ) {
+        if ( !$out_fh->fdopen( fileno(STDOUT), q{>} ) ) {
             croak qq{ERROR: fdopen STDOUT: $OS_ERROR};
         }
         $out_fn = $filename;
@@ -2315,18 +2303,28 @@
     return 1;
 }
 
-=head2 __make_file($args_ref)
-
-This function creates a specific file. It takes the
-following named arguments in %{$args_ref}:
+=head2 __make_file()
+
+This function creates a specific file.
+It takes the following named arguments:
 
 =over
 
 =item I<file_type> the type of file to create. The allowed types are
-I<interfaces>, I<resolv.conf> and I<zone>.
+I<dhcpd.conf>,
+I<etc_hosts>,
+I<grub_config>,
+I<interfaces>,
+I<preseed>,
+I<pxe_boot>,
+I<resolv.conf>,
+I<sources.list>,
+I<zone>.
 
 =item I<filename> the output file name
 
+=back
+
 All other named arguments are passed to the specialized function to which the
 content creation for this I<file_type> is delegated.
 
@@ -2356,13 +2354,10 @@
     # NOTE: all other parameters are properly checked by
     # __build_FOO() => no need to check them here
 
-    check_mandatory_true_args_type(
-        $args_ref, q{},
-        qw( file_type filename )
-    );
-
-    my ( $file_type, $filename )
-        = @{$args_ref}{qw( file_type filename )};
+    check_mandatory_true_args_type( $args_ref, q{},
+        qw( file_type filename ) );
+
+    my ( $file_type, $filename ) = @{$args_ref}{qw( file_type filename )};
 
     if ( not exists $build_content_for{$file_type} ) {
         croak qq{ERROR: Unknown file_type $file_type};
@@ -2375,7 +2370,7 @@
     return 1;
 }
 
-=head2 __read_and_process_template( $template_filename, $vars_ref )
+=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.
@@ -2400,6 +2395,5 @@
     return $content;
 }
 
-
 1;    # Magic true value required at end of module
 
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/VCS.pm
--- a/lib/PFTools/VCS.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/VCS.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -29,15 +29,15 @@
 use PFTools::Logger;
 
 our @EXPORT = qw(
-    VCS_checkout
+    vcs_checkout
 );
 
 our @EXPORT_OK = qw();
 
-sub VCS_checkout ($$$) {
+sub vcs_checkout {
     my ( $hostname, $pf_config, $options ) = @_;
 
-    unless ($pf_config) {
+    if ( !$pf_config ) {
         carp q{ERROR: $pf_config is invalid};
         return;
     }
@@ -49,7 +49,7 @@
     $module->import();
 
     if ( !checkout( $hostname, $pf_config, $options ) ) {
-        return 0
+        return 0;
     }
     return 1;
 }
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/VCS/CVS.pm
--- a/lib/PFTools/VCS/CVS.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/VCS/CVS.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -51,45 +51,48 @@
         return;
     }
 
-    if ( defined $options->{'branch'} && $options->{'branch'} ne '' ) {
-        if ( $cvs_cmd ne '' ) {
-            carp
-                qq{WARN: ingnoring $cvs_cmd with branch $options->{'branch'}};
+    if ( defined $options->{'branch'} && $options->{'branch'} ne q{} ) {
+        if ( $cvs_cmd ne q{} ) {
+            carp qq{WARN: Ignoring $cvs_cmd with branch $options->{'branch'}};
         }
     }
     elsif ( $pf_config->{'vcs'}->{'branch'} ) {
         $options->{'branch'} = $pf_config->{'vcs'}->{'branch'};
     }
     else {
-        $options->{'branch'} = "";
+        $options->{'branch'} = q{};
     }
 
-    my $ret;
     my $umask = umask( oct( $pf_config->{'vcs'}->{'umask'} ) );
 
-    $ENV{'CVS_RSH'} = $pf_config->{'vcs'}->{'rsh'}
-        if ( $pf_config->{'vcs'}->{'method'} eq 'rsh' );
+    if ( $pf_config->{'vcs'}->{'method'} eq 'rsh' ) {
+        $ENV{'CVS_RSH'} = $pf_config->{'vcs'}->{'rsh'};
+    }
 
-    if ( $cvs_cmd eq "" ) {
+    if ( !$cvs_cmd ) {
         if ( $hostname =~ /^$pf_config->{'regex'}->{'deploy_hosts'}/ ) {
-            $cvs_cmd = "/usr/bin/cvs -R -d '";
+            $cvs_cmd = q{/usr/bin/cvs -R -d '};
         }
         else {
-            print $hostname
-                . " doesn't match "
-                . $pf_config->{'regex'}->{'deploy_hosts'} . "\n"
-                if ( $options->{'verbose'} );
+            if ( $options->{'verbose'} ) {
+                print $hostname ## no critic(RequireBracedFileHandleWithPrint);
+                    . q{ doesn't match }
+                    . $pf_config->{'regex'}->{'deploy_hosts'} . "\n";
+            }
             $cvs_cmd
-                = "/usr/bin/cvs -d ':ext:"
-                . $pf_config->{'vcs'}->{'user'} . '@'
+                = q{/usr/bin/cvs -d ':ext:}
+                . $pf_config->{'vcs'}->{'user'} . q{@}
                 . $pf_config->{'vcs'}->{'server'};
         }
-        $cvs_cmd .= $pf_config->{'vcs'}->{'vcsroot'} . "' checkout ";
-        $cvs_cmd .= ' -r ' . $options->{'branch'}
-            if ( $options->{'branch'} ne "" );
+        $cvs_cmd .= $pf_config->{'vcs'}->{'vcsroot'} . q{' checkout };
+        if ( $options->{'branch'} ne q{} ) {
+            $cvs_cmd .= ' -r ' . $options->{'branch'};
+        }
         $cvs_cmd .= $pf_config->{'vcs'}->{'module'};
     }
-    print $cvs_cmd. "\n" if ( $options->{'debug'} || $options->{'verbose'} );
+    if ( $options->{'debug'} || $options->{'verbose'} ) {
+        print $cvs_cmd. "\n";
+    }
 
     my $co_dir = $pf_config->{'path'}->{'checkout_dir'};
     if ( -e $co_dir ) {
@@ -100,15 +103,16 @@
         or croak qq{ERROR: Unable to create $co_dir : $OS_ERROR};
 
     my $exec = Proc::Reliable->new();
-    my ( $stdout, $stderr, $status, $msg ) = $exec->run(
-        "cd '" . $co_dir . "';" . $cvs_cmd
-    );
-    print $stdout if ( $options->{'verbose'} );
+    my ( $stdout, $stderr, $status, $msg )
+        = $exec->run( q{cd '} . $co_dir . q{';} . $cvs_cmd );
+    if ( $options->{'verbose'} ) {
+        print $stdout;
+    }
     if ($status) {
         carp qq{ERROR: unable to checkout : $stderr};
         return;
     }
-    umask($umask);
+    umask $umask;
     return 1;
 }
 
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/VCS/HG.pm
--- a/lib/PFTools/VCS/HG.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/VCS/HG.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -57,8 +57,8 @@
 
     my $hg_cmd = $pf_config->{'vcs'}->{'command'};
 
-    if ( defined $options->{'branch'} && $options->{'branch'} ne '' ) {
-        if ( $hg_cmd ne '' ) {
+    if ( defined $options->{'branch'} && $options->{'branch'} ne q{} ) {
+        if ( $hg_cmd ne q{} ) {
             carp qq{WARN: Ignoring $hg_cmd with branch $options->{'branch'}};
         }
     }
@@ -66,19 +66,21 @@
         $options->{'branch'} = $pf_config->{'vcs'}->{'branch'};
     }
     else {
-        $options->{'branch'} = "";
+        $options->{'branch'} = q{};
     }
 
     my $ret;
     my $umask = umask( oct( $pf_config->{'vcs'}->{'umask'} ) );
 
-    unless ( $hg_cmd ne "" ) {
+    if ( !$hg_cmd ) {
         $hg_cmd
-            = "hg clone "
-            . $pf_config->{'vcs'}->{'server'} . "/"
+            = q{hg clone }
+            . $pf_config->{'vcs'}->{'server'} . q{/}
             . $pf_config->{'vcs'}->{'module'};
     }
-    print $hg_cmd. "\n" if ( $options->{'debug'} || $options->{'verbose'} );
+    if ( $options->{'debug'} || $options->{'verbose'} ) {
+        print $hg_cmd. "\n";
+    }
 
     my $co_dir = $pf_config->{'path'}->{'checkout_dir'};
     if ( -e $co_dir ) {
@@ -89,16 +91,17 @@
         or croak qq{ERROR: Unable to create $co_dir : $OS_ERROR};
 
     my $exec = Proc::Reliable->new();
-    my ( $stdout, $stderr, $status, $msg ) = $exec->run(
-        "cd '" . $co_dir . "';" . $hg_cmd
-    );
-    print $stdout if ( $options->{'verbose'} );
+    my ( $stdout, $stderr, $status, $msg )
+        = $exec->run( q{cd '} . $co_dir . q{';} . $hg_cmd );
+    if ( $options->{'verbose'} ) {
+        print $stdout;
+    }
     if ($status) {
         carp qq{ERROR: unable to checkout : $stderr};
         return;
     }
 
-    umask($umask);
+    umask $umask;
     return !$ret;
 }
 
diff -r 02ed6fbcae72 -r db767ed9f51f lib/PFTools/VCS/SVN.pm
--- a/lib/PFTools/VCS/SVN.pm	Wed Oct 02 13:48:39 2013 +0200
+++ b/lib/PFTools/VCS/SVN.pm	Tue Apr 01 17:50:29 2014 +0200
@@ -56,8 +56,8 @@
 
     my $svn_cmd = $pf_config->{'vcs'}->{'command'};
 
-    if ( defined $options->{'branch'} && $options->{'branch'} ne '' ) {
-        if ( $svn_cmd ne '' ) {
+    if ( defined $options->{'branch'} && $options->{'branch'} ne q{} ) {
+        if ( $svn_cmd ne q{} ) {
             carp qq{WARN: Ignoring $svn_cmd with branch $options->{'branch'}};
         }
     }
@@ -65,24 +65,26 @@
         $options->{'branch'} = $pf_config->{'vcs'}->{'branch'};
     }
     else {
-        $options->{'branch'} = "";
+        $options->{'branch'} = q{};
     }
 
     my $ret;
     my $umask = umask( oct( $pf_config->{'vcs'}->{'umask'} ) );
 
-    unless ( $svn_cmd ne "" ) {
+    if ( !$svn_cmd ) {
         $svn_cmd
-            = "svn checkout "
-            . $pf_config->{'vcs'}->{'method'} . "://"
-            . $pf_config->{'vcs'}->{'server'} . "/"
+            = q{svn checkout }
+            . $pf_config->{'vcs'}->{'method'} . q{://}
+            . $pf_config->{'vcs'}->{'server'} . q{/}
             . $pf_config->{'vcs'}->{'module'}
-            . " --username "
+            . q{ --username }
             . $pf_config->{'vcs'}->{'user'}
-            . " --password "
+            . q{ --password }
             . $pf_config->{'vcs'}->{'password'};
     }
-    print $svn_cmd. "\n" if ( $options->{'debug'} || $options->{'verbose'} );
+    if ( $options->{'debug'} || $options->{'verbose'} ) {
+        print $svn_cmd. "\n";
+    }
 
     my $co_dir = $pf_config->{'path'}->{'checkout_dir'};
     if ( -e $co_dir ) {
@@ -93,16 +95,17 @@
         or croak qq{ERROR: Unable to create $co_dir : $OS_ERROR};
 
     my $exec = Proc::Reliable->new();
-    my ( $stdout, $stderr, $status, $msg ) = $exec->run(
-        "cd '" . $co_dir . "';" . $svn_cmd
-    );
-    print $stdout if ( $options->{'verbose'} );
+    my ( $stdout, $stderr, $status, $msg )
+        = $exec->run( q{cd '} . $co_dir . q{';} . $svn_cmd );
+    if ( $options->{'verbose'} ) {
+        print $stdout;
+    }
     if ($status) {
         carp qq{ERROR: unable to checkout : $stderr};
         return;
     }
 
-    umask($umask);
+    umask $umask;
     return !$ret;
 }
 
diff -r 02ed6fbcae72 -r db767ed9f51f sbin/fix_hosts
--- a/sbin/fix_hosts	Wed Oct 02 13:48:39 2013 +0200
+++ b/sbin/fix_hosts	Tue Apr 01 17:50:29 2014 +0200
@@ -21,6 +21,7 @@
 use strict;
 use warnings;
 
+use Carp;
 use English qw( -no_match_vars );    # Avoids regex performance penalty
 use File::Basename;
 use Getopt::Long qw( :config ignore_case_always bundling );
@@ -28,20 +29,14 @@
 use Sys::Hostname;
 
 use PFTools::Structqueries;
-use PFTools::Utils qw( Init_TOOLS fix_etc_hosts );
+use PFTools::Utils qw( init_tools fix_etc_hosts );
 
-#################################
+############################################
 # VARS
 
 my @options_specs = (
-    'help',
-    'host|h=s',
-    'site|s=s',
-    'config|c=s',
-    'stote=s',
-    'type|t=s',
-    'input|i=s',
-    'output|o=s',
+    'config|c=s', 'help',    'input|i=s', 'output|o=s',
+    'site|s=s',   'store=s', 'host|h=s',  'type|t=s',
 );
 
 # Options default values
@@ -53,67 +48,64 @@
     'output' => '/etc/hosts',
 };
 
-my $PF_CONFIG     = {};
-my $GLOBAL_STRUCT = {};
+my $pf_config     = {};
+my $global_config = {};
 
 my $program = basename $PROGRAM_NAME;
 
-###################################
-# Funtions
+############################################
+# Functions
 
-sub Do_help {
-    print STDERR << "# ENDHELP";
+sub do_help {
+    print {*STDERR} << "ENDHELP";
 
 Usage:	$program [options]
-	--help		: print help and exit
+	--help		: print this message and exit
 	-h --host	: hostname for which we want to build interfaces file
 	-s --site	: site on which hostname is defined (optional)
-	-c --config	: file where pf-tools configuration is stored e.g. /etc/pf-tools.conf (optional)
 	--store		: file where global structure datas are in storable format (optional)
-	-t --type	: IP type to fix, allowed values are ipv4 and ipv6. Default value is ipv4
+	-c --config	: pf-tools config file (optional)
 	-i --input	: input file to fix default value is /etc/hosts
 	-o --output	: output file default value is /etc/hosts
-    
-# ENDHELP
+	-t --type	: IP type to fix, allowed values are ipv4 and ipv6. Default value is ipv4
+
+ENDHELP
+    return;
 }
 
-##################################
+############################################
 ### MAIN
 
 GetOptions( $options, @options_specs )
-    or die "Didn't grok options (see --help).\n";
+    or croak "Didn't grok options (see --help).\n";
 
 if ( $options->{'help'} ) {
-    Do_help();
+    do_help();
     exit 0;
 }
 
-( $PF_CONFIG, $GLOBAL_STRUCT ) = Init_TOOLS(
-    $options->{'host'},
-    $options->{'config'},
-    $options->{'store'}
-);
+( $pf_config, $global_config )
+    = init_tools( $options->{'host'}, $options->{'config'},
+    $options->{'store'} );
 
-if ( !$PF_CONFIG->{'features'}->{ $options->{'type'} } ) {
-    die "Aborting because $options->{'type'} is not activated in PF-Tools";
+if ( !$pf_config->{'features'}->{ $options->{'type'} } ) {
+    croak "Aborting because $options->{'type'} is not activated in PF-Tools";
 }
 
-unless ( $options->{'site'} ) {
-    $options->{'site'} = $PF_CONFIG->{'location'}->{'site'}
-        || get_uniq_site_from_hostname( $options->{'host'}, $GLOBAL_STRUCT );
+if ( !$options->{'site'} ) {
+    $options->{'site'} = $pf_config->{'location'}->{'site'}
+        || get_uniq_site_from_hostname( $options->{'host'}, $global_config );
 }
 
 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,
+    {   site_name       => $options->{'site'},
+        hostname        => $options->{'host'},
+        input_filename  => $options->{'input'},
+        output_filename => $options->{'output'},
+        ip_type         => $options->{'type'},
+        global_config   => $global_config,
+        pf_config       => $pf_config,
     }
 );
 
-
 exit 0;
diff -r 02ed6fbcae72 -r db767ed9f51f sbin/mk_dhcp
--- a/sbin/mk_dhcp	Wed Oct 02 13:48:39 2013 +0200
+++ b/sbin/mk_dhcp	Tue Apr 01 17:50:29 2014 +0200
@@ -23,80 +23,73 @@
 use strict;
 use warnings;
 
+use Carp;
 use English qw( -no_match_vars );    # Avoids regex performance penalty
 use File::Basename;
 use Getopt::Long qw( :config ignore_case_always bundling );
 use IO::File;
 
 use PFTools::Structqueries;
-use PFTools::Utils qw( Init_TOOLS make_dhcpd_conf_file );
+use PFTools::Utils qw( init_tools make_dhcpd_conf_file );
 
-#####################################
-# Vars
+############################################
+# VARS
 
 my @options_specs = (
-    'config|c=s',
-    'help|h',
-    'output|o=s',
-    'site|s=s',
-    'store=s',
-    'template|t=s',
+    'config|c=s', 'help', 'output|o=s', 'site|s=s',
+    'store=s',    'template|t=s',
 );
 
-#########################
+############################################
 # Default options value
-my $options = {
-    'output' => '-',
-};
+my $options = { 'output' => q{-}, };
 
 my $program = basename $PROGRAM_NAME;
 
-#####################################
+############################################
 # Functions
 
-sub Do_help {
-    print STDERR << "# ENDHELP";
+sub do_help {
+    print {*STDERR} << "ENDHELP";
 
 Usage:	$program [options]
-    --help		: print this message and exit
-    -t --template : template file
-    -s --site	: site on which hostname is defined
-    --store		: file where global structure datas are in storable format (optional)
-    -c --config	: pf-tools config file (optional)
-    -o --output	: output file
-    
-# ENDHELP
+	--help		: print this message and exit
+	-t --template : template file
+	-s --site	: site on which hostname is defined
+	--store		: file where global structure datas are in storable format (optional)
+	-c --config	: pf-tools config file (optional)
+	-o --output	: output file
+
+ENDHELP
+    return;
 }
 
 ############################################
 ### MAIN
 
 GetOptions( $options, @options_specs )
-    or die "Didn't grok options (see --help).\n";
+    or croak "Didn't grok options (see --help).\n";
 
 if ( $options->{'help'} ) {
-    Do_help();
+    do_help();
     exit 0;
 }
 
-my ( $pf_config, $global_config ) = Init_TOOLS(
-    q{},
-    $options->{'config'},
-    $options->{'store'}
+my ( $pf_config, $global_config )
+    = init_tools( q{}, $options->{'config'}, $options->{'store'} );
+
+$options->{'site'} ||= $pf_config->{'location'}->{'site'};
+if ( !$options->{'site'} ) {
+    croak q{ERROR: No site specified and no default site in configuration};
+}
+
+make_dhcpd_conf_file(
+    {   site_name         => $options->{'site'},
+        template_filename => $options->{'template'},
+        filename          => $options->{'output'},
+        global_config     => $global_config,
+        pf_config         => $pf_config,
+    }
 );
 
-$options->{'site'} ||= $pf_config->{'location'}->{'site'};
-unless ( $options->{'site'} ) {
-    die q{ERROR: No site specified and no default site in configuration};
-}
-
-my $args_ref = {
-    site_name         => $options->{'site'},
-    template_filename => $options->{'template'},
-    global_config     => $global_config,
-    filename          => $options->{'output'},
-};
-
-make_dhcpd_conf_file($args_ref);
-
 exit 0;
diff -r 02ed6fbcae72 -r db767ed9f51f sbin/mk_grubopt
--- a/sbin/mk_grubopt	Wed Oct 02 13:48:39 2013 +0200
+++ b/sbin/mk_grubopt	Tue Apr 01 17:50:29 2014 +0200
@@ -14,85 +14,81 @@
 #
 #  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
+#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+#  USA
 #
 
 use strict;
 use warnings;
 
+use Carp;
 use English qw( -no_match_vars );    # Avoids regex performance penalty
 use File::Basename;
 use Getopt::Long qw( :config ignore_case_always bundling );
 use Sys::Hostname;
 
 use PFTools::Structqueries;
-use PFTools::Utils qw( Init_TOOLS fix_grub_kopt );
+use PFTools::Utils qw( init_tools fix_grub_kopt );
 
-####################################################
-# Vars
+############################################
+# VARS
 
 my @options_specs = (
-    'config|c=s',
-    'grub-version|v=s',
-    'help',
-    'host|h=s',
-    'input|i=s',
-    'output|o=s',
-    'site|s=s',
-    'store=s',
+    'config|c=s', 'help',     'host|h=s', 'input|i=s',
+    'output|o=s', 'site|s=s', 'store=s',  'grub-version|v=s',
 );
 
+############################################
+# Default options value
 my $options = {
-    'grub-version'   => 2,
-    'host'   => hostname,
-    'output' => '-',
+    'grub-version' => 2,
+    'host'         => hostname,
+    'output'       => q{-},
 };
 
 my $program = basename $PROGRAM_NAME;
 
-######################################################
+############################################
 # Functions
 
-sub Do_help () {
-    print STDERR << "# ENDHELP";
+sub do_help {
+    print {*STDERR} << "ENDHELP";
 
 Usage:	$program [options]
-	-c --config	: path for accessing pf-tools.conf file
 	--help  	: print help and exit
+	-s, --site	: the site where the hostname is defined
 	-h, --host	: the hostname for which you want to build grub configuration
 	-v, --grub-version
                 : version of grub [default: 2]
 	-i, --input	: the grub configuration file to read
+	--store		: path for accessing storable file containing the global configuration
+	-c --config	: path for accessing pf-tools.conf file
 	-o, --output: the grub configuration file to write [default: STDOUT]
-	-s, --site	: the site where the hostname is defined
-	--store		: path for accessing storable file containing the global configuration
 
-# ENDHELP
+ENDHELP
+    return;
 }
 
-#######################################################""
+############################################
 ### MAIN
 
 GetOptions( $options, @options_specs )
-    or die "Didn't grok options (see --help).\n";
+    or croak "Didn't grok options (see --help).\n";
 
 if ( $options->{'help'} ) {
-    Do_help();
+    do_help();
     exit 0;
 }
 
-my ( $pf_config, $global_config ) = Init_TOOLS(
-    $options->{'host'},
-    $options->{'config'},
-    $options->{'store'}
-);
+my ( $pf_config, $global_config )
+    = init_tools( $options->{'host'}, $options->{'config'},
+    $options->{'store'} );
 
 $options->{'site'} ||= $pf_config->{'location'}->{'site'}
     || get_uniq_site_from_hostname( $options->{'host'}, $global_config );
 
 fix_grub_kopt(
-    {
-        hostname        => $options->{'host'},
+    {   hostname        => $options->{'host'},
         site_name       => $options->{'site'},
         input_filename  => $options->{'input'},
         output_filename => $options->{'output'},
diff -r 02ed6fbcae72 -r db767ed9f51f sbin/mk_interfaces
--- a/sbin/mk_interfaces	Wed Oct 02 13:48:39 2013 +0200
+++ b/sbin/mk_interfaces	Tue Apr 01 17:50:29 2014 +0200
@@ -23,6 +23,7 @@
 use strict;
 use warnings;
 
+use Carp;
 use English qw( -no_match_vars );    # Avoids regex performance penalty
 use File::Basename;
 use Getopt::Long qw( :config ignore_case_always bundling );
@@ -30,79 +31,73 @@
 use Sys::Hostname;
 
 use PFTools::Structqueries;
-use PFTools::Utils qw( Init_TOOLS make_interfaces_file );
+use PFTools::Utils qw( init_tools make_interfaces_file );
 
-#################################
+############################################
 # VARS
 
-my @options_specs = (
-    'help',
-    'host|h=s',
-    'site|s=s',
-    'config|c=s',
-    'store=s',
-    'output|o=s',
-);
+my @options_specs
+    = ( 'config|c=s', 'help', 'host|h=s', 'output|o=s', 'site|s=s',
+    'store=s', );
 
-# Default options values
+############################################
+# Default options value
 my $options = {
     'help'   => 0,
     'host'   => hostname,
-    'output' => '-',
+    'output' => q{-},
 };
 
-my $PF_CONFIG     = {};
-my $GLOBAL_STRUCT = {};
+my $pf_config     = {};
+my $global_config = {};
 
 my $program = basename $PROGRAM_NAME;
 
-###################################
-# Funtions
+############################################
+# Functions
 
-sub Do_help {
-    print STDERR << "# ENDHELP";
+sub do_help {
+    print {*STDERR} << "ENDHELP";
+
 Usage:	$program [options]
 	--help		: print help and exit
+	-s --site	: site on which hostname is defined (optional)
 	-h --host	: hostname for which we want to build interfaces file
-	-s --site	: site on which hostname is defined (optional)
+	--store		: file where global structure datas are in storable format (optional)
 	-c --config	: file where pf-tools configuration is stored e.g. /etc/pf-tools.conf (optional)
-	--store		: file where global structure datas are in storable format (optional)
 	-o --output	: output file default value is /etc/network/interfaces
-    
-# ENDHELP
+
+ENDHELP
+    return;
 }
 
-##################################
+############################################
 ### MAIN
 
 GetOptions( $options, @options_specs )
-    or die "Didn't grok options (see --help).\n";
+    or croak "Didn't grok options (see --help).\n";
 
 if ( $options->{'help'} ) {
-    Do_help();
+    do_help();
     exit 0;
 }
 
-( $PF_CONFIG, $GLOBAL_STRUCT ) = Init_TOOLS(
-    $options->{'host'},
-    $options->{'config'},
-    $options->{'store'}
-);
+( $pf_config, $global_config )
+    = init_tools( $options->{'host'}, $options->{'config'},
+    $options->{'store'} );
 
-unless ( $options->{'site'} ) {
-    $options->{'site'} = $PF_CONFIG->{'location'}->{'site'}
-        || get_uniq_site_from_hostname( $options->{'host'}, $GLOBAL_STRUCT );
+if ( !$options->{'site'} ) {
+    $options->{'site'} = $pf_config->{'location'}->{'site'}
+        || get_uniq_site_from_hostname( $options->{'host'}, $global_config );
 }
 
 make_interfaces_file(
-    {
-        hostname      => $options->{'host'},
-        global_config => $GLOBAL_STRUCT,
-        pf_config     => $PF_CONFIG,
+    {   hostname      => $options->{'host'},
+        global_config => $global_config,
         site_name     => $options->{'site'},
         filename      => $options->{'output'},
+        pf_config     => $pf_config,
     }
 );
 
 exit 0;
-
diff -r 02ed6fbcae72 -r db767ed9f51f sbin/mk_pxelinuxcfg
--- a/sbin/mk_pxelinuxcfg	Wed Oct 02 13:48:39 2013 +0200
+++ b/sbin/mk_pxelinuxcfg	Tue Apr 01 17:50:29 2014 +0200
@@ -23,41 +23,39 @@
 use strict;
 use warnings;
 
+use Carp;
 use English qw( -no_match_vars );    # Avoids regex performance penalty
 use File::Basename;
 use Getopt::Long qw( :config ignore_case_always bundling );
 use File::Path qw( make_path );
 
-use PFTools::Utils qw( Init_TOOLS make_pxe_boot_and_preseed_files );
+use PFTools::Structqueries;
+use PFTools::Utils qw( init_tools make_pxe_boot_and_preseed_files );
 
 ############################################
-# Vars
+# VARS
 
-my @options_specs = (
-    'config|c=s',
-    'help|h',
-    'script=s',
-    'site|s=s',
-    'store=s',
-);
+my @options_specs
+    = ( 'config|c=s', 'help|h', 'script=s', 'site|s=s', 'store=s', );
 
+############################################
+# Default options value
 my $options = {
     'help'   => 0,
     'script' => 'pf-tools-config.sh',
 };
 
-my $PF_CONFIG       = {};
-my $GLOBAL_STRUCT   = {};
-my $DEFAULT_PRESEED = '';
+my $pf_config       = {};
+my $global_config   = {};
+my $default_preseed = q{};
 
 my $program = basename $PROGRAM_NAME;
 
-
 ############################################
 # Functions
 
-sub Do_help {
-    print STDERR << "# ENDHELP";
+sub do_help {
+    print {*STDERR} << "ENDHELP";
 
 Usage:	$program [options]
 	--help		: print help and exit
@@ -66,59 +64,56 @@
 	--store		: file where global structure datas are in storable format (optional)
 	-c --config	: pf-tools config file (optional)
     
-# ENDHELP
+ENDHELP
+    return;
 }
 
 ############################################
 ### MAIN
 
 GetOptions( $options, @options_specs )
-    or die "Didn't grok options (see --help).\n";
+    or croak "Didn't grok options (see --help).\n";
 
 if ( $options->{'help'} ) {
-    Do_help();
+    do_help();
     exit 0;
 }
 
-( $PF_CONFIG, $GLOBAL_STRUCT ) = Init_TOOLS(
-    "",
-    $options->{'config'},
-    $options->{'store'}
-);
+( $pf_config, $global_config )
+    = init_tools( q{}, $options->{'config'}, $options->{'store'} );
 
-if ( !-e $PF_CONFIG->{'path'}->{'preseed_dir'} ) {
-    make_path( $PF_CONFIG->{'path'}->{'preseed_dir'} );
-    my ( $login, $pass, $uid, $gid ) = getpwnam('www-data');
-    chown $uid, $gid, $PF_CONFIG->{'path'}->{'preseed_dir'};
+if ( !-e $pf_config->{'path'}->{'preseed_dir'} ) {
+    make_path( $pf_config->{'path'}->{'preseed_dir'} );
+    my ( $login, $pass, $uid, $gid ) = getpwnam 'www-data';
+    chown $uid, $gid, $pf_config->{'path'}->{'preseed_dir'};
     my $mode = '2750';
-    chmod( oct($mode), $PF_CONFIG->{'path'}->{'preseed_dir'} );
+    chmod oct($mode), $pf_config->{'path'}->{'preseed_dir'};
 }
 
-#$DEFAULT_PRESEED
-#    = $PF_CONFIG->{'path'}->{'preseed_dir'} . "/default_preseed.txt";
-unless ( $options->{'site'} ) {
-    unless ( $PF_CONFIG->{'location'}->{'site'} ) {
-        die "A site MUST BE defined for building DNS zone forward";
+#$default_preseed
+#    = $pf_config->{'path'}->{'preseed_dir'} . "/default_preseed.txt";
+if ( !$options->{'site'} ) {
+    if ( !$pf_config->{'location'}->{'site'} ) {
+        croak q{A site MUST BE defined for building DNS zone forward};
     }
-    $options->{'site'} = $PF_CONFIG->{'location'}->{'site'};
+    $options->{'site'} = $pf_config->{'location'}->{'site'};
 }
 
-=for FIXME
+# 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( ... );
+# }
+#
 
-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 = get_site_config( $options->{'site'}, $GLOBAL_STRUCT );
+my $site_part = get_site_config( $options->{'site'}, $global_config );
 my $host_part = $site_part->{'HOST'}->{'BY_NAME'};
 foreach my $hostclass ( @{ $site_part->{'HOST'}->{'__hostclass_pxe'} } ) {
     foreach my $host ( keys %{ $host_part->{$hostclass} } ) {
@@ -127,19 +122,18 @@
         my $args_ref = {
             hostname      => $host,
             site_name     => $options->{'site'},
-            global_config => $GLOBAL_STRUCT,
-            pf_config     => $PF_CONFIG,
+            global_config => $global_config,
+            pf_config     => $pf_config,
             pf_script     => $options->{'script'},
         };
-        if ( $host->{'boot'}->{'pxetemplate'} ) {
-            $args_ref->{'pxe_template_file'} =
-                ( $host->{'boot'}->{'pxetemplate'} =~ m{^/} )
-                ? $host->{'boot'}->{'pxetemplate'}
-                : join (
-                    '/',
-                    $PF_CONFIG->{'path'}->{'templates_dir'},
-                    $host->{'boot'}->{'pxetemplate'}
-                );
+        my $host_ref = $host_part->{$hostclass}->{$host};
+        if ( $host_ref->{'boot'}->{'pxetemplate'} ) {
+            $args_ref->{'pxe_template_filename'}
+                = ( $host_ref->{'boot'}->{'pxetemplate'} =~ m{^/}xms )
+                ? $host_ref->{'boot'}->{'pxetemplate'}
+                : join( q{/},
+                $pf_config->{'path'}->{'templates_dir'},
+                $host_ref->{'boot'}->{'pxetemplate'} );
         }
         make_pxe_boot_and_preseed_files($args_ref);
     }
diff -r 02ed6fbcae72 -r db767ed9f51f sbin/mk_resolvconf
--- a/sbin/mk_resolvconf	Wed Oct 02 13:48:39 2013 +0200
+++ b/sbin/mk_resolvconf	Tue Apr 01 17:50:29 2014 +0200
@@ -16,75 +16,69 @@
 #
 #  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
+#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+#  USA
 #
 
 use strict;
 use warnings;
 
+use Carp;
 use English qw( -no_match_vars );    # Avoids regex performance penalty
 use File::Basename;
 use Getopt::Long qw( :config ignore_case_always bundling );
 use Sys::Hostname;
 
 use PFTools::Structqueries;
-use PFTools::Utils qw( Init_TOOLS make_resolv_conf_file );
+use PFTools::Utils qw( init_tools make_resolv_conf_file );
 
-#################################
+############################################
 # VARS
 
 my @options_specs = (
-    'help',
-    'host|h=s',
-    'site|s=s',
-    'config|c=s',
-    'store=s',
-    'output|o=s',
-    'template|t=s',
+    'config|c=s', 'help',         'output|o=s', 'site|s=s',
+    'store=s',    'template|t=s', 'host|h=s',
 );
 
-my $options = {
-    'host'     => hostname
-        'help' => 0,
-    'output' => '/etc/resolv.conf',
-};
+############################################
+# Default options value
+my $options = { 'host' => hostname 'output' => '/etc/resolv.conf', };
 
 my $program = basename $PROGRAM_NAME;
 
-###################################
-# Funtions
+############################################
+# Functions
 
-sub Do_help {
-    print STDERR << "# ENDHELP";
+sub do_help {
+    print {*STDERR} << "ENDHELP";
 
 Usage:	$program [options]
-	--help		: print help and exit
-    -t --template : template file
+	--help		: print this message and exit
+	-t --template : template file
 	-h --host	: hostname for which we want to build interfaces file
 	-s --site	: site on which hostname is defined (optional)
-	-c --config	: file where pf-tools configuration is stored e.g. /etc/pf-tools.conf (optional)
 	--store		: file where global structure datas are in storable format (optional)
+	-c --config	: pf-tools config file (optional)
 	-o --output	: output file default value is /etc/resolv.conf
-    
-# ENDHELP
+
+ENDHELP
+    return;
 }
 
-##################################
+############################################
 ### MAIN
 
 GetOptions( $options, @options_specs )
-    or die "Didn't grok options (see --help).\n";
+    or croak "Didn't grok options (see --help).\n";
 
 if ( $options->{'help'} ) {
-    Do_help();
+    do_help();
     exit 0;
 }
 
-my ( $pf_config, $global_config ) = Init_TOOLS(
-    $options->{'host'},
-    $options->{'config'},
-    $options->{'store'}
-);
+my ( $pf_config, $global_config )
+    = init_tools( $options->{'host'}, $options->{'config'},
+    $options->{'store'} );
 
 # NOTE: get_uniq_site_from_hostname() will croak if the site_name
 # cannot be determined
@@ -92,12 +86,11 @@
     || get_uniq_site_from_hostname( $options->{'host'}, $global_config );
 
 make_resolv_conf_file(
-    {
+    {   site_name         => $options->{'site'},
+        template_filename => $options->{'template'},
         hostname          => $options->{'host'},
+        filename          => $options->{'output'},
         global_config     => $global_config,
-        site_name         => $options->{'site'},
-        filename          => $options->{'output'},
-        template_filename => $options->{'template'},
     }
 );
 
diff -r 02ed6fbcae72 -r db767ed9f51f sbin/mk_sitezone
--- a/sbin/mk_sitezone	Wed Oct 02 13:48:39 2013 +0200
+++ b/sbin/mk_sitezone	Tue Apr 01 17:50:29 2014 +0200
@@ -21,82 +21,76 @@
 use strict;
 use warnings;
 
+use Carp;
 use English qw( -no_match_vars );    # Avoids regex performance penalty
 use File::Basename;
 use Getopt::Long qw( :config ignore_case_always bundling );
 use IO::File;
 
 use PFTools::Structqueries;
-use PFTools::Utils qw( Init_TOOLS make_zone_file );
+use PFTools::Utils qw( init_tools make_zone_file );
 
-#################################
+############################################
 # VARS
 
 my @options_specs = (
-    'help',
-    'site|s=s',
-    'config|c=s',
-    'store=s',
-    'output|o=s',
-    'template|t=s',
+    'config|c=s', 'help', 'output|o=s', 'site|s=s',
+    'store=s',    'template|t=s',
 );
 
-my $options = {
-    'help'   => 0,
-    'output' => '-',
-};
+############################################
+# Default options value
+my $options = { 'output' => q{-}, };
 
 my $program = basename $PROGRAM_NAME;
 
-#################################################
+############################################
 # Functions
 
-sub Do_help {
-    print STDERR << "# ENDHELP";
+sub do_help {
+    print {*STDERR} << "ENDHELP";
 
 Usage:	$program [options]
-	--help		: print help and exit
-    -t --template : template file
+	--help		: print this message and exit
+	-t --template : template file
 	-s --site	: site on which hostname is defined
 	--store		: file where global structure datas are in storable format (optional)
 	-c --config	: pf-tools config file (optional)
 	-o --output	: output file
-    
-# ENDHELP
+
+ENDHELP
+    return;
 }
 
-##########################################################""
+############################################
 ### MAIN
 
 GetOptions( $options, @options_specs )
-    or die "Didn't grok options (see --help).\n";
+    or croak "Didn't grok options (see --help).\n";
 
 if ( $options->{'help'} ) {
-    Do_help();
+    do_help();
     exit 0;
 }
 
-my ( $pf_config, $global_config ) = Init_TOOLS(
-    q{},
-    $options->{'config'},
-    $options->{'store'}
-);
+my ( $pf_config, $global_config )
+    = init_tools( q{}, $options->{'config'}, $options->{'store'} );
 
 $options->{'site'} ||= $pf_config->{'location'}->{'site'};
-unless ( $options->{'site'} ) {
-    die q{ERROR: No site specified and no default site in configuration};
+if ( !$options->{'site'} ) {
+    croak q{ERROR: No site specified and no default site in configuration};
 }
 
 # NOTE: get_site_dhcp_config() will croak if the site is unknown
-my $site_ref = get_site_dhcp_config( $options->{'site'}, $global_config );
+my $site_ref = get_site_config( $options->{'site'}, $global_config );
 
 make_zone_file(
-    {
-        zone_name         => $site_ref->{'zone'},
+    {   zone_name         => $site_ref->{'zone'},
         site_name         => $options->{'site'},
         template_filename => $options->{'template'},
         filename          => $options->{'output'},
         global_config     => $global_config,
+        pf_config         => $pf_config,
     }
 );
 
diff -r 02ed6fbcae72 -r db767ed9f51f sbin/mk_sourceslist
--- a/sbin/mk_sourceslist	Wed Oct 02 13:48:39 2013 +0200
+++ b/sbin/mk_sourceslist	Tue Apr 01 17:50:29 2014 +0200
@@ -21,34 +21,31 @@
 use strict;
 use warnings;
 
+use Carp;
 use English qw( -no_match_vars );    # Avoids regex performance penalty
 use File::Basename;
 use Getopt::Long qw( :config ignore_case_always bundling );
 use Sys::Hostname;
 
 use PFTools::Structqueries;
-use PFTools::Utils qw( Init_TOOLS make_sources_list_file );
+use PFTools::Utils qw( init_tools make_sources_list_file );
 
 ############################################
-# Vars
+# VARS
 
 my @options_specs = (
-    'help',
-    'host|h=s',
-    'site|s=s',
-    'tpl|t=s',
-    'add|a=s@',
-    'config|c=s',
-    'store=s',
+    'config|c=s', 'help',     'output|o=s',   'site|s=s',
+    'store=s',    'host|h=s', 'template|t=s', 'add|a=s@',
     'backport|b',
-    'output|o=s',
 );
 
+############################################
+# Default options value
 my $options = {
     'help'     => 0,
     'add'      => [],
     'backport' => 0,
-    'output'   => '-',
+    'output'   => q{-},
 };
 
 my $pf_config     = {};
@@ -59,12 +56,11 @@
 ############################################
 # Functions
 
-sub Do_help () {
-
-    print <<EOF
+sub do_help {
+    print {*STDERR} << "ENDHELP";
 
 Synopsis : $program [--help] [-h|--host hostname <hostname>] [-s|--site <site_name>]
-			[-o|--output <sources.list dest>] [ -t|--tpl <sources.list template>] [-b|--backports]
+			[-o|--output <sources.list dest>] [ -t|--template <sources.list template>] [-b|--backports]
 			[-a|--add <section to add>] [-c|--config <pf_tools_file>] [--store <filename>]
 
 	This tool permits to build the sources.list file according to distribution defined
@@ -79,7 +75,7 @@
 
 	-o | --output	Define here where to build the sources.list file
 
-	-t | --tpl		Define here where to find the sources.list template. If not defined
+	-t | --template		Define here where to find the sources.list template. If not defined
 				the program will use template path issued from pf-tools.conf file
 
 	-a | --add		Define here the section you want to add to the custom repository (in
@@ -103,27 +99,26 @@
 	This command generate the sources.list file on /tmp for stream-tv00 host and adds the
 	section stream to the custom packages repository
 
-EOF
+ENDHELP
+    return;
 }
 
-#############################################################
+############################################
 ### MAIN
 
 GetOptions( $options, @options_specs )
-    or die "Didn't grok options (see --help).\n";
+    or croak "Didn't grok options (see --help).\n";
 
 if ( $options->{'help'} ) {
-    Do_help();
+    do_help();
     exit 0;
 }
 
 $options->{'host'} ||= hostname;
 
-( $pf_config, $global_config ) = Init_TOOLS(
-    $options->{'host'},
-    $options->{'config'},
-    $options->{'store'}
-);
+( $pf_config, $global_config )
+    = init_tools( $options->{'host'}, $options->{'config'},
+    $options->{'store'} );
 
 $options->{'site'} ||= $pf_config->{'location'}->{'site'}
     || get_uniq_site_from_hostname( $options->{'host'}, $global_config );
@@ -132,17 +127,15 @@
 push @sections, split qr{ \s* [,] \s* }xms, join q{,}, @{ $options->{'add'} };
 
 make_sources_list_file(
-    {
-        hostname      => $options->{'host'},
-        site_name     => $options->{'site'},
-        filename      => $options->{'output'},
-        sections      => \@sections,
-        template      => $options->{'tpl'},
-        backports     => $options->{'backport'},
-        global_config => $global_config,
-        pf_config     => $pf_config,
+    {   hostname          => $options->{'host'},
+        site_name         => $options->{'site'},
+        template_filename => $options->{'template'},
+        filename          => $options->{'output'},
+        sections_ref      => \@sections,
+        backports         => $options->{'backport'},
+        global_config     => $global_config,
+        pf_config         => $pf_config,
     }
 );
 
 exit 0;
-
diff -r 02ed6fbcae72 -r db767ed9f51f sbin/update-config
--- a/sbin/update-config	Wed Oct 02 13:48:39 2013 +0200
+++ b/sbin/update-config	Tue Apr 01 17:50:29 2014 +0200
@@ -36,22 +36,11 @@
 my $program = basename $PROGRAM_NAME;
 
 my @options_specs = (
-    'branch=s',
-    'debug|d',
-    'diff|u',
-    'force-reload|f',
-    'help',
-    'install|i',
-    'noaction',
-    'noupdate',
-    'quiet|q',
-    'simul|s',
-    'pkg_type|p=s',
-    'verbose|v',
-    'config|c=s',
-    'store=s',
-    'host|h=s',
-    'site=s'
+    'branch=s',   'debug|d',   'diff|u',       'force-reload|f',
+    'help',       'install|i', 'noaction',     'noupdate',
+    'quiet|q',    'simul|s',   'pkg_type|p=s', 'verbose|v',
+    'config|c=s', 'store=s',   'host|h=s',     'site=s',
+    'forcecolor', 'nocolor',
 );
 
 my $options = {
@@ -73,14 +62,29 @@
     exit 0;
 }
 
-my ( $PF_CONFIG, $GLOBAL_STRUCT ) = Init_TOOLS(
-    $options->{'host'},
-    $options->{'config'},
-    $options->{'store'},
-    $options->{'force-reload'}
+# use color if:
+# - no 'nocolor' options is passed
+# - tts STDOUT is a tty.
+# - the value of $TERM is unknown.
+my $terminal = $ENV{'TERM'} || 'dumb';
+
+# not looking if interactive, juste if STDOUT
+## no critic(ProhibitInteractiveTest)
+if ( !$options->{'forcecolor'}
+    && ( !-t STDOUT || $terminal eq 'dumb' || $options->{'nocolor'} ) )
+{
+    $ENV{ANSI_COLORS_DISABLED}
+        = 'true';    ## no critic(RequireLocalizedPunctuationVars)
+}
+
+## use critic
+
+my ( $PF_CONFIG, $GLOBAL_STRUCT ) = init_tools(
+    $options->{'host'},  $options->{'config'},
+    $options->{'store'}, $options->{'force-reload'}
 );
 
-unless ( $PF_CONFIG->{'features'}->{'update'} ) {
+if ( !$PF_CONFIG->{'features'}->{'update'} ) {
     die qq{$program command has been desactivated in pf-tools.conf\n};
 }
 
@@ -91,13 +95,11 @@
     print qq{$program started in quiet mode...\n};
 }
 
-$options->{'simul'} = 1 if $options->{'diff'};
+if ( $options->{'diff'} ) {
+    $options->{'simul'} = 1;
+}
 
-Do_update_from_GLOBAL(
-    $options,
-    $GLOBAL_STRUCT,
-    $PF_CONFIG
-);
+Do_update_from_GLOBAL( $options, $GLOBAL_STRUCT, $PF_CONFIG );
 
 exit 0;
 
@@ -105,7 +107,7 @@
 # Funtions
 
 sub do_help {
-    print STDERR << "END_OF_HELP";
+    print {*STDERR} << "END_OF_HELP";
 
 Usage:	$program [options]
 	--help			: print help and exit
diff -r 02ed6fbcae72 -r db767ed9f51f t/13.conf.t
--- a/t/13.conf.t	Wed Oct 02 13:48:39 2013 +0200
+++ b/t/13.conf.t	Tue Apr 01 17:50:29 2014 +0200
@@ -779,18 +779,18 @@
             'cbv4-pfds' => {
                 'vlan-systeme' => {
                     'cbv4-spawn' => {
-                        'cbv4-spawn01' => [
-                            'hardware ethernet 00:1e:c9:ff:42:0a;',
-                            'fixed-address 10.1.167.1;',
-                            'filename pxelinux.0;',
-                            'option domain-name-servers nsprivate.private,spawn.private;'
-                        ],
-                        'cbv4-spawn00' => [
-                            'hardware ethernet 00:1e:c9:ff:08:e3;',
-                            'fixed-address 10.1.167.0;',
-                            'filename pxelinux.0;',
-                            'option domain-name-servers nsprivate.private,spawn.private;'
-                        ],
+                        'cbv4-spawn01' => {
+                            'hardware' => '00:1e:c9:ff:42:0a',
+                            'fixed_addr' => '10.1.167.1',
+                            'pxefilename' => 'pxelinux.0',
+                            'resolver' => 'nsprivate.private,spawn.private',
+                        },
+                        'cbv4-spawn00' => {
+                            'hardware' => '00:1e:c9:ff:08:e3',
+                            'fixed_addr' => '10.1.167.0',
+                            'pxefilename' => 'pxelinux.0',
+                            'resolver' => 'nsprivate.private,spawn.private',
+                        },
                     },
                     'netmask' => '255.255.0.0',
                     'subnet'  => '10.1.0.0',
@@ -801,18 +801,18 @@
                     'netmask'      => '255.255.0.0',
                     'subnet'       => '10.1.0.0',
                     'cbv4-rdeploy' => {
-                        'cbv4-rdeploy01' => [
-                            'hardware ethernet 00:1e:c9:ff:42:0b;',
-                            'fixed-address 10.1.167.1;',
-                            'filename pxelinux.0;',
-                            'option domain-name-servers nsprivate.private;'
-                        ],
-                        'cbv4-rdeploy00' => [
-                            'hardware ethernet 00:1e:c9:ff:08:e4;',
-                            'fixed-address 10.1.167.0;',
-                            'filename pxelinux.0;',
-                            'option domain-name-servers nsprivate.private;'
-                        ],
+                        'cbv4-rdeploy01' => {
+                            'hardware' => '00:1e:c9:ff:42:0b',
+                            'fixed_addr' => '10.1.167.1',
+                            'pxefilename' => 'pxelinux.0',
+                            'resolver' => 'nsprivate.private',
+                        },
+                        'cbv4-rdeploy00' => {
+                            'hardware' => '00:1e:c9:ff:08:e4',
+                            'fixed_addr' => '10.1.167.0',
+                            'pxefilename' => 'pxelinux.0',
+                            'resolver' => 'nsprivate.private',
+                        },
                     },
                 },
             },
@@ -1374,7 +1374,14 @@
             'cbv4-pfds' => 'private',
             'cbv4'      => 'private'
             }
-        }
+        },
+    'PUBLIC_NETWORK' => {
+        'vlan-pfds-ext' => {
+            'cbv4-spawn00' => 'cbv4-pfds',
+            'cbv4-spawn01' => 'cbv4-pfds',
+            'vip-spawn' =>    'cbv4-pfds'
+        },
+    }
 };
 $expected_configuration->{'SITE'}{'BY_NAME'}{'cbv4'}{'NETWORK'}{'BY_NAME'}
     {'vlan-systeme'}
@@ -1735,18 +1742,18 @@
         'netmask'      => '255.255.0.0',
         'subnet'       => '10.1.0.0',
         'cbv4-rdeploy' => {
-            'cbv4-rdeploy01' => [
-                'hardware ethernet 00:1e:c9:ff:42:0b;',
-                'fixed-address 10.1.167.1;',
-                'filename pxelinux.0;',
-                'option domain-name-servers nsprivate.private;'
-            ],
-            'cbv4-rdeploy00' => [
-                'hardware ethernet 00:1e:c9:ff:08:e4;',
-                'fixed-address 10.1.167.0;',
-                'filename pxelinux.0;',
-                'option domain-name-servers nsprivate.private;'
-            ],
+            'cbv4-rdeploy01' => {
+                'hardware' => '00:1e:c9:ff:42:0b',
+                'fixed_addr' => '10.1.167.1',
+                'pxefilename' => 'pxelinux.0',
+                'resolver' => 'nsprivate.private',
+            },
+            'cbv4-rdeploy00' => {
+                'hardware' => '00:1e:c9:ff:08:e4',
+                'fixed_addr' => '10.1.167.0',
+                'pxefilename' => 'pxelinux.0',
+                'resolver' => 'nsprivate.private',
+            },
         },
     },
 };
diff -r 02ed6fbcae72 -r db767ed9f51f t/20.files.search_and_replace.input.ip
--- a/t/20.files.search_and_replace.input.ip	Wed Oct 02 13:48:39 2013 +0200
+++ b/t/20.files.search_and_replace.input.ip	Tue Apr 01 17:50:29 2014 +0200
@@ -2,5 +2,7 @@
 a HOSTNAME.vlan-pfds-int.private b
 a cbv4-spawn00.vlan-systeme.private b
 a cbv4-spawn.vlan-systeme.private b
+a unresolved.vlan-systeme\.private b
+a /etc/bind/db\.private b
 # the end
 
diff -r 02ed6fbcae72 -r db767ed9f51f t/20.files.t
--- a/t/20.files.t	Wed Oct 02 13:48:39 2013 +0200
+++ b/t/20.files.t	Tue Apr 01 17:50:29 2014 +0200
@@ -14,6 +14,7 @@
 use PFTools::Conf;
 use PFTools::Structqueries qw( get_host_config );
 use PFTools::Utils qw( /^./ ); # import @EXPORT and @EXPORT_OK
+use PFTools::Update::Common;
 
 # Let's go back to our test configuration
 # FIXME: this depends on t/13.conf.t, but it probably should not.
@@ -25,7 +26,6 @@
 
 my $global_config = Init_GLOBAL_NETCONFIG( q{COMMON:private-network}, $hash_subst );
 
-
 ########################################################################
 note('Testing PFTools::Utils::__build_zone');
 can_ok( 'PFTools::Utils', qw( __build_zone ) );
@@ -36,6 +36,7 @@
     site_name => q{site_name},
     template_filename => $template_filename,
     global_config => $global_config,
+    pf_config         => $pf_config,
 };
 
 throws_ok { PFTools::Utils::__build_zone(); }
@@ -86,15 +87,15 @@
 
 $args_ref->{'global_config'} = {};
 throws_ok { PFTools::Utils::__build_zone($args_ref); }
-qr{ \A ERROR: [ ] Invalid [ ] [\$] global_config [ ] hashref:
+qr{ \A ERROR: [ ] Invalid [ ] global_config [ ] hashref:
     [ ] no [ ] 'ZONE' [ ] key [ ] found }xms
     => q{Dies if non-config hashref $global_config};
 
 $args_ref->{'global_config'} = $global_config;
 delete $args_ref->{'template_filename'};
-throws_ok { PFTools::Utils::__build_zone($args_ref); }
-qr{ \A ERROR: [ ] Mandatory [ ] argument [ ] template_filename [ ] not [ ] found }xms
-    => q{Dies if no template_filename};
+#throws_ok { PFTools::Utils::__build_zone($args_ref); }
+#qr{ \A ERROR: [ ] Mandatory [ ] argument [ ] template_filename [ ] not [ ] found }xms
+#    => q{Dies if no template_filename};
 
 $args_ref->{'template_filename'} = $template_filename;
 my $result = PFTools::Utils::__build_zone($args_ref);
@@ -258,6 +259,7 @@
     global_config     => $global_config,
     site_name         => q{cbv4},
     template_filename => $template_filename,
+    pf_config         => $pf_config,
 };
 throws_ok { make_resolv_conf_file($args_ref); }
 qr{ \A ERROR: [ ] Mandatory [ ] argument  [ ] filename [ ] not [ ] found }xms
@@ -297,7 +299,7 @@
 
 $args_ref->{'global_config'} = {};
 throws_ok { make_resolv_conf_file($args_ref); }
-qr{ \A ERROR: [ ] Invalid [ ] [\$] global_config [ ] hashref:
+qr{ \A ERROR: [ ] Invalid [ ] global_config [ ] hashref:
     [ ] no [ ] 'ZONE' [ ] key [ ] found }xms
     => q{Dies if non-config hashref $global_config};
 
@@ -313,10 +315,10 @@
     => q{Dies if non-scalar $site_name};
 
 $args_ref->{'site_name'} = q{cbv4};
-delete $args_ref->{'template_filename'};
-throws_ok { make_resolv_conf_file($args_ref); }
-qr{ \A ERROR: [ ] Mandatory [ ] argument [ ] template_filename [ ] not [ ] found }xms
-    => q{Dies if no template_filename};
+#delete $args_ref->{'template_filename'};
+#throws_ok { make_resolv_conf_file($args_ref); }
+#qr{ \A ERROR: [ ] Mandatory [ ] argument [ ] template_filename [ ] not [ ] found }xms
+#    => q{Dies if no template_filename};
 
 $test_output_file = q{test.resolv.conf};
 $args_ref->{'filename'} = $test_output_file;
@@ -382,7 +384,7 @@
 
 $args_ref->{'global_config'} = {};
 throws_ok { PFTools::Utils::__build_interfaces($args_ref); }
-qr{ \A ERROR: [ ] Invalid [ ] [\$] global_config [ ] hashref:
+qr{ \A ERROR: [ ] Invalid [ ] global_config [ ] hashref:
     [ ] no [ ] 'ZONE' [ ] key [ ] found }xms
     => q{Dies if non-config hashref $global_config};
 
@@ -399,7 +401,7 @@
 
 $args_ref->{'pf_config'} = {};
 throws_ok { PFTools::Utils::__build_interfaces($args_ref); }
-qr{ \A ERROR: [ ] Invalid [ ] [\$] pf_config [ ] hashref: [ ] no [ ] 'vcs' [ ] key [ ] found }xms
+qr{ \A ERROR: [ ] Invalid [ ] pf_config [ ] hashref: [ ] no [ ] 'vcs' [ ] key [ ] found }xms
     => q{Dies if non-config hashref $pf_config};
 
 $args_ref->{'pf_config'} = $pf_config;
@@ -417,7 +419,7 @@
 $args_ref->{'site_name'} = q{cbv4-pfds};
 throws_ok { PFTools::Utils::__build_interfaces($args_ref); }
 qr{ \A ERROR: [ ] Unknown [ ] hostname [ ] 'foo' [ ] on [ ] site [ ] 'cbv4-pfds' }xms
-    => q{Dies if unknown $site_name};
+    => q{Dies if unknown $hostname};
 
 $args_ref->{'hostname'} = q{cbv4-spawn01};
 $args_ref->{'site_name'} = q{foo};
@@ -427,8 +429,8 @@
 
 $args_ref->{'site_name'} = q{cbv4};
 throws_ok { PFTools::Utils::__build_interfaces($args_ref); }
-qr{ \A ERROR: [ ] Unknown [ ] hostname [ ] 'cbv4-spawn01' [ ] on [ ] site [ ] 'cbv4' }xms
-    => q{Dies if unknown $hostname};
+qr{ \A ERROR: [ ] hostname [ ] cbv4-spawn01: [ ] no [ ] configuration [ ] found }xms
+    => q{Dies if $hostname not in site but have public interface};
 
 $args_ref->{'site_name'} = q{cbv4-pfds};
 $result = PFTools::Utils::__build_interfaces($args_ref);
@@ -526,25 +528,20 @@
 
 my $test_sections_ref = [qw(common uncommon)];
 $args_ref = {
-    hostname      => $hostname,
-    site_name     => q{cbv4},
-    sections_ref  => $test_sections_ref,
-    template      => q{templates/sources.list.tpl},
-    global_config => $global_config,
-    pf_config     => $pf_config,
+    hostname          => $hostname,
+    site_name         => q{cbv4},
+    sections_ref      => $test_sections_ref,
+    template_filename => q{templates/sources.list.tpl},
+    global_config     => $global_config,
+    pf_config         => $pf_config,
 };
 
-$args_ref->{'template'} = q{};
+$args_ref->{'template_filename'} = {};
 throws_ok { PFTools::Utils::__build_sources_list($args_ref); }
-qr{ \A ERROR: [ ] Invalid [ ] false [ ] argument [ ] template }xms
-    => q{Dies if empty $template};
+qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] template_filename }xms
+    => q{Dies if non-scalar $template_filename};
 
-$args_ref->{'template'} = {};
-throws_ok { PFTools::Utils::__build_sources_list($args_ref); }
-qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] template }xms
-    => q{Dies if non-scalar $template};
-
-$args_ref->{'template'} = q{templates/sources.list.tpl};
+$args_ref->{'template_filename'} = q{templates/sources.list.tpl};
 $args_ref->{'hostname'} = q{};
 throws_ok { PFTools::Utils::__build_sources_list($args_ref); }
 qr{ \A ERROR: [ ] Invalid [ ] false [ ] argument [ ] hostname }xms
@@ -585,7 +582,7 @@
 
 $args_ref->{'global_config'} = { foo => q{bar} };
 throws_ok { PFTools::Utils::__build_sources_list($args_ref); }
-qr{ \A ERROR: [ ] Invalid [ ] [\$] global_config [ ] hashref: }xms
+qr{ \A ERROR: [ ] Invalid [ ] global_config [ ] hashref: }xms
     => q{Dies if non-config hashref $global_config};
 
 $args_ref->{'global_config'} = $global_config;
@@ -1071,14 +1068,14 @@
 host cbv4-spawn01 {
 \thardware ethernet 00:1e:c9:ff:42:0a;
 \tfixed-address 10.1.167.1;
-\tfilename pxelinux.0;
+\tfilename "pxelinux.0";
 \toption domain-name-servers nsprivate.private,spawn.private;
 }
 
 host cbv4-spawn00 {
 \thardware ethernet 00:1e:c9:ff:08:e3;
 \tfixed-address 10.1.167.0;
-\tfilename pxelinux.0;
+\tfilename "pxelinux.0";
 \toption domain-name-servers nsprivate.private,spawn.private;
 }
 
@@ -1211,6 +1208,8 @@
 a 10.2.167.0 b
 a 10.1.167.0 b
 a 10.1.167.0 10.1.167.1 b
+a unresolved.vlan-systeme.private b
+a /etc/bind/db.private b
 # the end
 EOT
 
@@ -1234,6 +1233,8 @@
 a 10.1.167.0 b
 a 10.1.167.0 b
 a 10.1.167.1 b
+a unresolved.vlan-systeme.private b
+a /etc/bind/db.private b
 # the end
 EOT
 
@@ -1308,3 +1309,64 @@
     => q{Correct result for GRUB version 2}
     or note explain $result;
 
+ok unlink($output_filename)
+    => q{Removed test output file};
+
+########################################################################
+SKIP: {
+    skip( q{Need root to give away ownership}, 16 ) unless ( $UID == 0 );
+
+    note('Testing PFTools::Update::Common::Do_chownmod');
+    can_ok( 'PFTools::Update::Common', qw( Do_chownmod ) );
+
+    my $ref_section = {
+        owner => 'daemon',
+        group => 'bin',
+        mode  => '0755',
+    };
+    my $dest = 'test-ownergroupmode.file';
+    open my $FILE, '>', $dest;
+    print {$FILE} 'bla';
+    close $FILE;
+    my $newuid = getpwnam $ref_section->{owner};
+    my $newgid = getgrnam $ref_section->{group};
+
+    ok PFTools::Update::Common::Do_chownmod(
+        $ref_section, $dest, $global_config
+        ),
+        q{execution of Do_chownmod};
+    my @stat = stat($dest);
+    ok $stat[4] == $newuid, q{result owner};
+    ok $stat[5] == $newgid, q{result group};
+    ok( ( $stat[2] & oct 7777 ) == eval $ref_section->{mode},
+        q{result mode} );
+    ok unlink($dest) => q{Removed the test-generated right file};
+
+    open $FILE, '>', $dest;
+    print {$FILE} 'bla';
+    close $FILE;
+    $newuid = getpwnam q{root};
+    $newgid = getgrnam q{root};
+
+    ok PFTools::Update::Common::Do_chownmod( {}, $dest, $global_config ),
+        q{execution of Do_chownmod default};
+    @stat = stat($dest);
+    ok $stat[4] == $newuid, q{result owner defaut};
+    ok $stat[5] == $newgid, q{result group défaut};
+    ok( ( $stat[2] & oct 7777 ) == eval q{0640}, q{result mode defaut} );
+    ok unlink($dest) => q{Removed the test-generated right file};
+
+    my $testdir = q{testownergroupmode.dir};
+    mkdir $testdir;
+    ok PFTools::Update::Common::Do_chownmod( {}, $testdir, $global_config ),
+        q{execution of Do_chownmod default (directory)};
+    @stat = stat($testdir);
+    ok $stat[4] == $newuid, q{result owner default (directory)};
+    ok $stat[5] == $newgid, q{result group default (directory)};
+    ok( ( $stat[2] & oct 7777 ) == eval q{0750},
+        q{result mode default (directory)}
+    );
+    ok rmdir($testdir) => q{Removed the test-generated right directory};
+
+}
+
diff -r 02ed6fbcae72 -r db767ed9f51f templates/dhcpd.conf.tpl
--- a/templates/dhcpd.conf.tpl	Wed Oct 02 13:48:39 2013 +0200
+++ b/templates/dhcpd.conf.tpl	Tue Apr 01 17:50:29 2014 +0200
@@ -8,9 +8,10 @@
 
 [%- FOREACH host IN hosts -%]
 host [% host.hostname %] {
-[% FOREACH definition IN host.definitions -%]
-	[% definition %]
-[% END -%]
+	hardware ethernet [% host.definitions.hardware %];
+	fixed-address [% host.definitions.fixed_addr %];
+	filename "[% host.definitions.pxefilename %]";
+	option domain-name-servers [% host.definitions.resolver %];
 }
 
 [% END -%]
diff -r 02ed6fbcae72 -r db767ed9f51f tools/Display_IP_config
--- a/tools/Display_IP_config	Wed Oct 02 13:48:39 2013 +0200
+++ b/tools/Display_IP_config	Tue Apr 01 17:50:29 2014 +0200
@@ -176,7 +176,7 @@
     exit 0;
 }
 
-( $PF_CONFIG, $GLOBAL_STRUCT ) = Init_TOOLS(
+( $PF_CONFIG, $GLOBAL_STRUCT ) = init_tools(
     "",
     $options->{'config'},
     $options->{'store'}
diff -r 02ed6fbcae72 -r db767ed9f51f tools/Translate_old_config
--- a/tools/Translate_old_config	Wed Oct 02 13:48:39 2013 +0200
+++ b/tools/Translate_old_config	Tue Apr 01 17:50:29 2014 +0200
@@ -24,7 +24,9 @@
 
 use strict;
 use warnings;
+use Modern::Perl;
 
+use Carp;
 use Data::Dumper;
 use File::Basename;
 use English qw( -no_match_vars );    # Avoids regex performance penalty
@@ -37,17 +39,12 @@
 #################################
 # Global vars
 
-my @options_specs = (
-    'help',
-    'type|t=s',
-    'include',
-    'input|i=s',
-    'output|o=s',
-);
+my @options_specs
+    = ( 'help', 'type|t=s', 'include', 'input|i=s', 'output|o=s', );
 
 my $options = {
     'help'    => 0,
-    'output'  => '-',
+    'output'  => q{-},
     'type'    => 'config',
     'include' => 0,
 };
@@ -57,58 +54,83 @@
 #################################
 # Functions
 
-sub Do_help () {
-    print STDERR << "# ENDHELP";
+sub do_help {
+    print {*STDERR} << "ENDHELP";
 Usage:	$program [options]
 	--help	: print help and exit
 	-t --type	: type of configuration file, allowed types are : config, network
 				- config is for update-* file
 				- network is for file like old private-network
-    --include   : parse include file if defined (default disabled)
+	--include	: parse include file if defined (default disabled)
 	-i --input	: source for old configuration file
 	-o --output	: destination for modified configuration file
-# ENDHELP
+ENDHELP
+    return;
 }
 
 #######################################################""
 ### MAIN
 
 GetOptions( $options, @options_specs )
-    or die "Didn't grok options (see --help).\n";
+    or croak "Didn't grok options (see --help).\n";
 
 if ( $options->{'help'} ) {
-    Do_help();
+    do_help();
     exit 0;
 }
 
-unless ( -e $options->{'input'} ) {
-    die "File $options->{'input'} doesn't exist";
+if ( !defined $options->{'input'} ) {
+    croak q{no input file defined};
 }
 
-my $old_parsing = Parser_pftools(
-    $options->{'input'},
-    {},
-    $options->{'include'}
-);
+if ( !-e $options->{'input'} ) {
+    croak qq{File "$options->{'input'}" doesn't exist};
+}
+
+my %sectionorder = ( __hostfile => 0 );
+my $sectionnumber = 1;
+open my $FILE, q{<}, $options->{'input'}
+    or croak qq{Can't open '$options->{'input'}': $OS_ERROR};
+while (<$FILE>) {
+    chomp;
+    if ( $_ =~ m{\A \[ ([^\]]*) \] }msx ) {
+        $sectionorder{$1} = $sectionnumber;
+        $sectionnumber++;
+    }
+    elsif ( $_ =~ m{\A \@include [ ] (.*) }msx ) {
+        $sectionorder{"include-$1"} = $sectionnumber;
+        $sectionnumber++;
+    }
+}
+close $FILE
+    or croak qq{Can't close '$options->{'input'}': $OS_ERROR};
+
+my $old_parsing
+    = Parser_pftools( $options->{'input'}, {}, $options->{'include'} );
 my $trans = {};
+#print Dumper($old_parsing);
 if ( $options->{'type'} eq 'config' ) {
     $trans = Translate_old2new_config($old_parsing);
 }
 else {
     foreach my $section ( keys %{$old_parsing} ) {
-        if ( $old_parsing->{$section}->{'type'} eq 'network' ) {
-            $trans->{$section} = Translate_old2new_network(
-                $old_parsing->{$section},
-                $section
-            );
+        if ( $section =~ m{\A @ (.*) \z}msx ) {
+            $trans->{$1} = { 'action' => 'include' };
         }
-        elsif ( $old_parsing->{$section}->{'type'} =~ /-server$/ ) {
+        elsif ( $old_parsing->{$section}->{'type'} eq 'network' ) {
+            $trans->{$section}
+                = Translate_old2new_network( $old_parsing->{$section},
+                $section );
+        }
+        elsif ( $old_parsing->{$section}->{'type'} =~ /-server\z/xms ) {
             my $pftools = 0;
 
             # Need to see if it is a "virtual pf-tools" host
             # or a "real pf-tools" host
             foreach my $key ( keys %{ $old_parsing->{$section} } ) {
-                if ( $key =~ m{\A ether\.\d+ \z}xms ) {
+
+                # seems like old_parsing translate key ether.1 as a hash
+                if ( $key =~ m{\A ether \z}xms ) {
                     $pftools++;
                     last;
                 }
@@ -116,33 +138,151 @@
             if ($pftools) {
 
                 # We need to translate into a hostfile configuration
-                $trans->{'__hostfile'} = {
-                    $section => Translate_old2new_host(
-                        $old_parsing->{$section}, $section
-                        )
-                };
+                $trans->{'__hostfile'}->{$section}
+                    = Translate_old2new_host( $old_parsing->{$section},
+                    $section );
+            } else {
+                $trans->{$section}
+                    = Translate_old2new_vhost( $old_parsing->{$section},
+                    $section );
             }
         }
     }
 }
 
-my $output_fh = IO::File->new( ">" . $options->{'output'} )
-    or die "Unable to open $options->{'output'} for translation";
+my $output_fh = IO::File->new( q{>} . $options->{'output'} )
+    or croak "Unable to open $options->{'output'} for translation";
+
+# sort items by a more logical order
+my @orderby = qw( action depends source actiongroup filter owner group
+    mode  option slaveon_config before_change on_noaction after_change
+    type comment serial soa mail refresh retry expire negttl
+    ttl @ns @mx
+    state zone location room alias confdir dhcp vlan console
+    site number node network network6 scope gateway
+    netmask tag interface ip ipstart
+    shortname dev @route );
+my %orderby = map { $orderby[$_] => $_ } 0 .. $#orderby;
+
+sub orderkeys {
+
+    # dont touch variable $a and $b or it mess everything
+    my ( $roota, $rootb ) = ( $a, $b );
+    my ( $sufa, $sufb );
+    if ( $a =~ m{\A ([^.]*) (?: [.] (\d*) )? \z}xms ) {
+        $roota = $1;
+        $sufa  = $2;
+    }
+    if ( $b =~ m{\A ([^.]*) (?: [.] (\d*) )? \z}xms ) {
+        $rootb = $1;
+        $sufb  = $2;
+    }
+    if ( !defined $orderby{$roota} ) {
+        print qq{$roota not defined in order list, put at the end\n};
+        push @orderby, $roota;
+        %orderby = map { $orderby[$_] => $_ } 0 .. $#orderby;
+    }
+    if ( !defined $orderby{$rootb} ) {
+        print qq{$rootb not defined in order list, put at the end\n};
+        push @orderby, $rootb;
+        %orderby = map { $orderby[$_] => $_ } 0 .. $#orderby;
+    }
+    if ( ( $roota eq $rootb ) && ( defined $sufa && defined $sufb ) ) {
+        return $sufa <=> $sufb;
+    }
+    else {
+        return $orderby{$roota} <=> $orderby{$rootb};
+    }
+}
 
 if ( $options->{'type'} eq 'config' ) {
-    foreach my $section ( keys %{$trans} ) {
-        next if ( $section =~ m{\A@} );
-        $output_fh->print( "[" . $section . "]\n" );
-        foreach my $key ( keys %{ $trans->{$section} } ) {
-            next if ( $key =~ m{\A__} );
+    foreach my $section (
+        sort { $sectionorder{$a} <=> $sectionorder{$b} }
+        keys %{$trans}
+        )
+    {
+        $output_fh->print(qq{[$section]\n});
+        foreach my $key ( sort orderkeys keys %{ $trans->{$section} } ) {
             $output_fh->print("\t$key\t= $trans->{$section}->{$key}\n");
         }
         $output_fh->print("\n");
     }
 }
 else {
-    print "Need to implement the output for other type " . $options->{'type'};
-    print Dumper $trans;
+    foreach my $section (
+        sort { $sectionorder{$a} <=> $sectionorder{$b} }
+        keys %{$trans}
+        )
+    {
+        if ( $section =~ m{\A__}xms ) {
+            foreach my $hostdef (
+                sort { $sectionorder{$a} <=> $sectionorder{$b} }
+                keys %{ $trans->{$section} }
+                )
+            {
+                my $cleanhostname = $hostdef;
+                $cleanhostname =~ s{%%}{}mxs;
+                my $host_output_fh
+                    = IO::File->new( q{>}
+                        . $options->{'output'}
+                        . qq{.hostfile-$cleanhostname} )
+                    or croak
+                    "Unable to open $options->{'output'}.hostfile-$cleanhostname} for translation";
+
+                foreach my $hostsection (
+                    sort keys %{ $trans->{$section}->{$hostdef} } )
+                {
+                    $host_output_fh->print(qq{[$hostsection]\n});
+                    foreach my $hostkey (
+                        sort orderkeys
+                        keys
+                        %{ $trans->{$section}->{$hostdef}->{$hostsection} } )
+                    {
+                        if ( $hostkey =~ m{\A @ }mxs ) {
+                            foreach my $subhostkey (
+                                @{  $trans->{$section}->{$hostdef}
+                                        ->{$hostsection}->{$hostkey}
+                                }
+                                )
+                            {
+                                $host_output_fh->print(
+                                    "\t$hostkey\t= $subhostkey\n");
+                            }
+                        }
+                        else {
+                            $host_output_fh->print(
+                                "\t$hostkey\t= $trans->{$section}->{$hostdef}->{$hostsection}->{$hostkey}\n"
+                            );
+                        }
+                    }
+                    $host_output_fh->print("\n");
+                }
+                $host_output_fh->close();
+                my $site = q{cbv4-pfds};
+                $output_fh->print(qq{[$cleanhostname]\n});
+                $output_fh->print("\ttype\t= service\n");
+                $output_fh->print(
+                    "\tcomment\t= $trans->{$section}->{$hostdef}->{hostgroup}->{comment}\n"
+                );
+                $output_fh->print("\tsite\t= $site\n");
+                $output_fh->print(
+                    "\t\@host\t= CONFSITE_$site:/hostfile-$cleanhostname\n");
+                $output_fh->print("\n");
+            }
+        }
+        else {
+            $output_fh->print(qq{[$section]\n});
+            foreach my $key ( sort orderkeys keys %{ $trans->{$section} } ) {
+                $output_fh->print("\t$key\t= $trans->{$section}->{$key}\n");
+            }
+            $output_fh->print("\n");
+        }
+    }
+
+    print
+        qq{Need to implement the output for other type: '$options->{'type'}'\n};
+
+    #print Dumper($trans);
 }
 
 $output_fh->close();
diff -r 02ed6fbcae72 -r db767ed9f51f tools/pflaunch
--- a/tools/pflaunch	Wed Oct 02 13:48:39 2013 +0200
+++ b/tools/pflaunch	Tue Apr 01 17:50:29 2014 +0200
@@ -48,7 +48,7 @@
 my $HOSTNAME = hostname;
 
 # paths
-my $umlaunch           = "/usr/local/sbin/umlaunch";
+my $umlaunch           = "/usr/sbin/umlaunch";
 my $cfgpath            = "/var/lib/cvsguest/$HOSTNAME/config/GLOBAL";
 my $configfile         = "$cfgpath/PF/$HOSTNAME.cfg";
 my $privatenetworkfile = "$cfgpath/private-network";



More information about the pf-tools-commits mailing list