source: trunk/ddt/ddt @ 350

Last change on this file since 350 was 350, checked in by g7moreau, 6 years ago
  • First support for ip range in sector
  • Property svn:executable set to *
  • Property svn:keywords set to Id
File size: 114.4 KB
Line 
1#!/usr/bin/perl
2#
3# Copyright (C) 2006-2018, LEGI UMR 5519 / CNRS UGA G-INP, Grenoble, France
4# License GNU GPL version 2 or later and Perl equivalent
5#
6# apt-get install perl-base perl-modules libyaml-syck-perl libnet-netmask-perl libreadonly-perl libfile-touch-perl libtext-table-perl libnetaddr-ip-perl
7
8package DDT::RE;
9
10use strict;
11#use warnings;
12
13use Readonly;
14
15Readonly our $MAC_ADDRESS  => qr{ (?: [0-9A-F]{2} :){5} [0-9A-F]{2} }xms;
16Readonly our $IPv4_ADDRESS => qr{ [0-9]{1,3} \. [0-9]{1,3} \. [0-9]{1,3} \. [0-9]{1,3} }xms;
17
18
19package main;
20
21use strict;
22#use warnings;
23use version; our $VERSION = version->declare('0.11.4');
24
25use Getopt::Long qw(GetOptions);
26#use YAML;
27use YAML::Syck;
28use Net::Netmask;
29use File::Touch;
30use File::Copy;
31use Socket;
32use Text::Table;
33use NetAddr::IP;
34
35my $command = shift @ARGV || 'help';
36
37my %cmd_db = (
38   'add-alias'          => \&cmd_add_alias,
39   'add-dhcp'           => \&cmd_add_dhcp,
40   'add-float'          => \&cmd_add_float,
41   'add-static'         => \&cmd_add_static,
42   'add-virtual'        => \&cmd_add_virtual,
43   'change-comment'     => \&cmd_change_comment,
44   'change-sector'      => \&cmd_change_sector,
45   'change-host'        => \&cmd_change_host,
46   'change-ip'          => \&cmd_change_ip,
47   'change-mac'         => \&cmd_change_mac,
48   'change-tag'         => \&cmd_change_tag,
49   'check-dns'          => \&cmd_check_dns,
50   'create-sector'      => \&cmd_create_sector,
51   'create-pool'        => \&cmd_create_pool,
52   'create-pxe'         => \&cmd_create_pxe,
53   'create-tag'         => \&cmd_create_tag,
54   'del-pc'             => \&cmd_del_pc,
55   'del-float'          => \&cmd_del_float,
56   'disable-pc'         => \&cmd_disable_pc,
57   'disable-float'      => \&cmd_disable_float,
58   'disable-pxe'        => \&cmd_disable_pxe,
59   'enable-pc'          => \&cmd_enable_pc,
60   'enable-float'       => \&cmd_enable_float,
61   'enable-pxe'         => \&cmd_enable_pxe,
62   'gen-dhcp-file'      => \&cmd_generate_dhcp_file,
63   'gen-dns-file'       => \&cmd_generate_dns_file,
64   'help'               => \&cmd_help,
65   'load-database'      => \&cmd_load_database,
66   'remove-pxe'         => \&cmd_remove_pxe,
67   'remove-tag'         => \&cmd_remove_tag,
68   'search-mac'         => \&cmd_search_mac,
69   'show'               => \&cmd_show_host,
70   'show-sector'        => \&cmd_show_sector,
71   'show-pool'          => \&cmd_show_pool,
72   'show-pxe'           => \&cmd_show_pxe,
73   'show-tag'           => \&cmd_show_tag,
74   'upgrade-db'         => \&cmd_upgrade_db,
75   'version'            => \&cmd_version,
76   );
77
78#-------------------------------------------------------------------------------
79
80my $CONFIG;
81
82my $xdg_config_home = $ENV{'XDG_CONFIG_HOME'} || "$ENV{'HOME'}/.config";
83$CONFIG = config_load("$xdg_config_home/ddt/config.yml") if -e "$xdg_config_home/ddt/config.yml";
84
85my $COMPUTER_BASENAME   = $CONFIG->{'database'}{'basename'} || 'ddt';
86my $COMPUTER_EXT        = $CONFIG->{'database'}{'ext'}      || 'db';
87
88my $FOLDER_APP          = $CONFIG->{'database'}{'folder'}   || '/var/lib/ddt';
89my $FOLDER_BACKUP       = $CONFIG->{'database'}{'backup'}   || "$FOLDER_APP/backup";
90my $FOLDER_GEN_DHCP     = $CONFIG->{'generate'}{'dhcp'}     || "$FOLDER_APP/dhcp";
91my $FOLDER_GEN_DNS      = $CONFIG->{'generate'}{'dns'}      || "$FOLDER_APP/dns";
92my $SCRIPT_UPDATE       = $CONFIG->{'script'}{'update'}     || '/usr/share/ddt/update-dhcp-server';
93
94my $COMPUTER_YAML       = "$FOLDER_APP/$COMPUTER_BASENAME.$COMPUTER_EXT";
95
96#-------------------------------------------------------------------------------
97
98mkdir $FOLDER_APP, 0755      if not -d $FOLDER_APP;
99mkdir $FOLDER_BACKUP, 0755   if not -d $FOLDER_BACKUP;
100mkdir $FOLDER_GEN_DHCP, 0755 if not -d $FOLDER_GEN_DHCP;
101mkdir $FOLDER_GEN_DNS, 0755  if not -d $FOLDER_GEN_DNS;
102
103if (defined $cmd_db{$command}) {
104   $cmd_db{$command}->(@ARGV);
105   }
106else {
107   print {*STDERR} "ddt: command $command not found\n\n";
108   $cmd_db{'help'}->();
109   exit 1;
110   }
111
112exit;
113
114#--------------------------------------------------------------------------------
115# LOAD SAVE section
116#--------------------------------------------------------------------------------
117
118sub config_load {
119   my $config_file = shift;
120
121   my $configdb = YAML::Syck::LoadFile($config_file);
122
123   return $configdb;
124   }
125
126#---------------------------------------------------------------
127# Load computer database
128
129sub ipamdb_load {
130   my $database_yaml = shift;
131
132   touch $database_yaml if not -e $database_yaml;
133   my $computer_db = YAML::Syck::LoadFile($database_yaml);
134
135   # add database version if not exist
136   if (not exists $computer_db->{'version'}) {
137      $computer_db->{'version'} = 1;
138      }
139
140   return $computer_db;
141   }
142
143#---------------------------------------------------------------
144# Save computer database
145
146sub ipamdb_save {
147   my ($database_yaml, $computer_db) = @_;
148
149   my $dirdb = $database_yaml;
150      $dirdb =~ s{ / [^/]* $}{}xms;
151   mkdir "$dirdb", 0755 unless -d "$dirdb";
152   YAML::Syck::DumpFile($database_yaml, $computer_db);
153
154   return $computer_db;
155   }
156
157#--------------------------------------------------------------------------------
158# CONTROL section
159#--------------------------------------------------------------------------------
160
161sub control_exist_pool {
162   my ($computer_db, $pool) = @_;
163
164   return exists $computer_db->{'pool'}{$pool} ? 1 : 0;
165   }
166
167#-------------------------------------------------------------------------------
168#Nom: control_exist_sector
169#Description: controle l'existence d'un sector dans le fichier YAML
170#             return 0 (faux) ou 1 (vrai)
171
172sub control_exist_sector {
173   my ($computer_db, $sector) = @_;
174
175   return 1 if exists $computer_db->{$sector};
176
177   print {*STDERR} "Error: sector $sector not found\n";
178   return 0;
179   }
180
181#-------------------------------------------------------------------------------
182#Nom: control_exist_hostname
183#Description: controle l'existence d'un nom de machine dans le fichier YAML
184#             return 0 (si trouvé) ou 1 (si non trouvé)
185
186sub control_exist_hostname {
187   my ($computer_db, $sector, $hostname) = @_;
188
189   if ($computer_db->{$sector} eq '') {
190      return 1;
191      }
192
193   my @sectordb = @{$computer_db->{$sector}};
194
195   for my $computer (@sectordb) {
196      my ($mac_address, $attribute) = %{$computer};
197      return 0 if $attribute->{'hostname'} eq $hostname;
198      }
199   return 1;
200   }
201
202#-------------------------------------------------------------------------------
203#Nom: control_exist_mac
204#Description: controle l'existence d'une adresse MAC dans le fichier YAML
205#             return 0 (si trouvé) ou 1 (si non trouvé)
206
207sub control_exist_mac {
208   my ($computer_db, $mac) = @_;
209
210   for my $sector_current (keys %{$computer_db}) {
211      next if $sector_current eq 'dset';
212      next if $sector_current eq 'pool';
213      next if $sector_current eq 'pxe';
214      next if $sector_current eq 'tag';
215      next if $sector_current eq 'version';
216
217      my @sectordb = @{$computer_db->{$sector_current}};
218
219      LOOP_ON_COMPUTER:
220      for my $computer (@sectordb) {
221         my ($mac_address, $attribute) = %{$computer};
222         return 0 if $mac_address eq $mac;
223         }
224      }
225   return 1;
226   }
227
228#-------------------------------------------------------------------------------
229#Nom: control_exist_ip
230#Description: controle l'existence d'une adresse IP dans le fichier YAML
231#             return 0 (si trouvé) ou 1 (si non trouvé)
232
233sub control_exist_ip {
234   my ($computer_db, $ip) = @_;
235
236   for my $sector_current (keys %{$computer_db}) {
237      next if $sector_current eq 'dset';
238      next if $sector_current eq 'pool';
239      next if $sector_current eq 'pxe';
240      next if $sector_current eq 'tag';
241      next if $sector_current eq 'version';
242
243      LOOP_ON_COMPUTER:
244      for my $computer (@{$computer_db->{$sector_current}}) {
245         my ($mac_address, $attribute) = %{$computer};
246         #print "Erreur: cette adresse IP $ip existe déjà\n";
247         return 0 if $attribute->{'ip'} eq $ip;
248         }
249      }
250
251   for my $current_pool (keys %{$computer_db->{'pool'}}) {
252      #--- Cette partie pour tester les ip des pools est bonne ne plus la changer ---#
253      my @T_pool_ip = @{$computer_db->{'pool'}{$current_pool}{'ip'}};
254
255      for my $pool_ip (@T_pool_ip) {
256         #print "Erreur: cette adresse IP $ip existe déjà\n";
257         return 0 if $pool_ip eq $ip;
258         }
259      }
260
261   return 1;
262   }
263
264#-------------------------------------------------------------------------------
265
266sub control_ip_in_range {
267   my ($computer_db, $sector, $ip) = @_;
268
269   return 1 if not exists $computer_db->{'dset'}{$sector}{'ip'}; # No IP range defined for this sector
270
271   my $ip_addr = NetAddr::IP->new($ip);
272
273   LOOP_ON_IP_RANGE:
274   for my $ip_range_current (@{$computer_db->{'dset'}{$sector}{'ip'}}) {
275      my $range = NetAddr::IP->new($ip_range_current);
276      return 1 if $range->contains($ip_addr);
277      }
278
279   return 0;
280   }
281
282#-------------------------------------------------------------------------------------
283#Nom: control_syntaxe_mac
284#Description: controle la syntaxe d'une adresse MAC (juste la longueur pas les valeurs)
285#             return 0 (si trouvé) ou 1 (si non trouvé)
286
287sub control_syntax_mac_address {
288   my $mac = shift;
289
290   if (scalar(split /:/, $mac) == 6 and $mac =~ $DDT::RE::MAC_ADDRESS) {
291      return 1;
292      }
293
294   print {*STDERR} "Error: bad MAC syntax: $mac\n";
295   return 0;
296   }
297
298#-------------------------------------------------------------------------------------
299#Nom: control_syntax_ip
300#Description: controle la syntaxe d'une adresse IP (juste la longueur pas les valeurs)
301#             return 0 (si trouvé) ou 1 (si non trouvé)
302
303sub control_syntax_ip {
304   my $ip = shift;
305
306   if ($ip ne 'pool') {
307      my @ip_split = split /\./, $ip;
308
309      if ( scalar(@ip_split) != 4 ) {
310         print {*STDERR} "Error: bad IP syntax: $ip\n";
311         return 0;
312         }
313      }
314   return 1;
315   }
316
317#-------------------------------------------------------------------------------------
318
319sub control_syntax_comment {
320   my $comment = shift;
321
322   if ($comment !~ m{^20\d\d-\d\d-\d\d\s}) {
323      print {*STDERR} "Error: no date like 2014-01-10 at the beginning: $comment\n";
324      return 0;
325      }
326
327   if ($comment !~ m{\(\w+\)$}) {
328      print {*STDERR} "Error: no (SERVICE) at the end: $comment\n";
329      return 0;
330      }
331
332   if ($comment =~ m{\s\s}) {
333      print {*STDERR} "Error: double space: $comment\n";
334      return 0;
335      }
336   return 1;
337   }
338
339#--------------------------------------------------------------------------------
340# UTILITY section
341#--------------------------------------------------------------------------------
342
343sub get_cmd_name {
344   my ($pkg, $sub) = split /::/, (caller(1))[3];
345   $sub =~ s/^cmd_//;
346   $sub =~ s/_/-/g;
347   return $sub;
348   }
349
350#-------------------------------------------------------------------------------
351
352sub normalize_mac_address {
353   my $mac_address = shift;
354
355   # D07E-28D1-7AB8 or d07e28-d17ab8
356   if ($mac_address =~ m{^ (?: [0-9A-Fa-f]{4} -){2} [0-9A-Fa-f]{4} $}xms
357      or $mac_address =~ m{^ [0-9A-Fa-f]{6} - [0-9A-Fa-f]{6} $}xms) {
358      $mac_address =~ s/-//g;
359      return join q{:}, unpack('(A2)*', uc($mac_address));
360      }
361
362   return join q{:}, map { substr( uc("00$_"), -2) } split m/ [:-] /xms, $mac_address;
363   }
364
365#-------------------------------------------------------------------------------
366
367sub normalize_comment {
368   my $comment = shift;
369
370   $comment =~ s{^(20\d\d)/(\d\d)/(\d\d)\s(.*)$}{$1-$2-$3 $4};
371
372   return $comment;
373   }
374
375#--------------------------------------------------------------------------------
376
377sub get_mac_from_hostname {
378   my ($computer_db, $sector, $hostname, $mac) = @_;
379
380   return $mac if $mac ne '';
381   return ''   if $hostname eq '';
382
383   LOOP_ON_COMPUTER:
384   for my $computer (@{$computer_db->{$sector}}) {
385      my ($mac_address, $attribute) = %{$computer};
386
387      next LOOP_ON_COMPUTER if $attribute->{'hostname'} ne $hostname;
388
389      return $mac_address;
390      }
391   }
392
393#--------------------------------------------------------------------------------
394
395sub get_mac_from_ip {
396   my ($computer_db, $sector, $ip, $mac) = @_;
397
398   return $mac if $mac ne '';
399   return ''   if $ip eq '';
400
401   LOOP_ON_COMPUTER:
402   for my $computer (@{$computer_db->{$sector}}) {
403      my ($mac_address, $attribute) = %{$computer};
404
405      next LOOP_ON_COMPUTER if $attribute->{'ip'} ne $ip;
406      return $mac_address;
407      }
408   }
409
410#--------------------------------------------------------------------------------
411# return a tuple (hash computer, iostat)
412# iostat 0/ok, 1/not exist
413
414sub get_computer_from_mac {
415   my ($computer_db, $sector, $mac) = @_;
416
417   LOOP_ON_COMPUTER:
418   for my $computer (@{$computer_db->{$sector}}) {
419      my ($mac_address, $attribute) = %{$computer};
420
421      next LOOP_ON_COMPUTER if $mac_address ne $mac;
422
423      return $attribute, 0;
424      }
425   return {}, 1;
426   }
427
428#-------------------------------------------------------------------------------
429# ADD computer section
430#-------------------------------------------------------------------------------
431
432#-------------------------------------------------------------------------------
433#Nom: add_alias
434#Description: ajoute un alias pour une machine. Pour la fonctionnalité CNAME dans le DNS.
435
436sub add_alias {
437   my ($computer_db, $hostname, $sector, $alias) = @_;
438
439   control_exist_sector($computer_db, $sector) or exit;
440   control_exist_hostname($computer_db, $sector, $hostname) or die "Error: host already exist in sector $sector: $hostname\n";
441
442   my @sectordb = @{$computer_db->{$sector}};
443
444   LOOP_ON_COMPUTER:
445   for my $computer (@sectordb) {
446      my ($mac_address, $attribute) = %{$computer};
447
448      next LOOP_ON_COMPUTER if $attribute->{'hostname'} ne $hostname;
449
450      $alias .= ' ' . $attribute->{'alias'};
451      $attribute->{'alias'}       = $alias;
452      $attribute->{'modify_time'} = time;
453      ipamdb_save("$COMPUTER_YAML", $computer_db);
454      print "Info: update attribute alias to $alias for host $hostname [OK]\n";
455      exit;
456      }
457   }
458
459#-------------------------------------------------------------------------------
460#Nom: add_static
461#Description: ajoute une machine non dhcp (donc à adressage fixe dans le fichier YAML)
462
463sub add_static {
464   my ($computer_db, $hostname, $sector, $ip, $mac, $comment) = @_;
465
466   $mac = normalize_mac_address($mac);
467   $comment = normalize_comment($comment);
468   control_exist_hostname($computer_db, $sector, $hostname) or die "Error: host already exist in sector $sector: $hostname\n";
469   control_syntax_mac_address($mac)                   or exit;
470   control_exist_mac($computer_db, $mac)              or die "Error: physical MAC address already exists: $mac\n";
471   control_syntax_ip($ip)                             or exit;
472   control_exist_ip($computer_db, $ip)                or die "Error: IP address already exist in sector $sector: $ip\n";
473   control_syntax_comment($comment)                   or exit;
474   my $timestamp = time;
475   push @{$computer_db->{$sector}}, { $mac => {
476      'hostname'     => $hostname,
477      'ip'           => $ip,
478      'address_type' => 'static',
479      'enabled'      => 'yes',
480      'create_time'  => $timestamp,
481      'modify_time'  => $timestamp,
482      'comment'      => $comment,
483      'alias'        =>  '',
484      }};
485   print "Info: add the host: $hostname, IP: $ip, MAC: $mac, sector: $sector [OK]\n";
486
487   ipamdb_save("$COMPUTER_YAML", $computer_db);
488   }
489
490
491#-------------------------------------------------------------------------------
492#Nom: add_dhcp
493#Description: section à corriger pour prendre en compte l'ajout d'une machine dans un pool dhcp
494#--- usage: ddt add-dhcp -s legi-sector03 -h meolpacif -m 00:18:F3:03:6F:66 -i 194.254.66.165
495
496sub add_dhcp {
497   my ($computer_db, $hostname, $sector, $ip, $mac, $comment) = @_;
498
499   my $timestamp = time;
500   $mac = normalize_mac_address($mac);
501   $comment = normalize_comment($comment);
502   control_exist_sector($computer_db, $sector)  or exit;
503   control_exist_hostname($computer_db, $sector, $hostname) or die "Error: host already exist in sector $sector: $hostname\n";
504   control_syntax_mac_address($mac)                   or exit;
505   control_exist_mac($computer_db, $mac)              or die "Error: physical MAC address already exists: $mac\n";
506   control_syntax_ip($ip)                             or exit;
507   control_exist_ip($computer_db, $ip)                or die "Error: IP address already exist in sector $sector: $ip.\n";
508   control_ip_in_range($computer_db, $sector, $ip)    or die "Error: IP $ip is not in sector $sector IP range.\n";
509   control_syntax_comment($comment)                   or exit;
510
511   push @{$computer_db->{$sector}}, { $mac => {
512      'hostname'     => $hostname,
513      'ip'           => $ip,
514      'address_type' => 'dhcp',
515      'enabled'      => 'yes',
516      'create_time'  => $timestamp,
517      'modify_time'  => $timestamp,
518      'comment'      => $comment,
519      'alias'        => '',
520      }};
521   print "Add the computer: $hostname, IP: $ip, MAC: $mac, sector: $sector\n";
522
523   ipamdb_save("$COMPUTER_YAML", $computer_db);
524   }
525
526#-------------------------------------------------------------------------------
527#--- usage: ddt add-float -s legi-sector03 -h meolpacif -m 00:18:F3:03:6F:66 -i 194.254.66.165
528
529sub add_float {
530   my ($computer_db, $pool, $sector, $mac, $comment) = @_;
531
532   my $timestamp = time;
533   $mac = normalize_mac_address($mac);
534   $comment = normalize_comment($comment);
535   control_exist_sector($computer_db, $sector)  or exit;
536   control_syntax_mac_address($mac)                   or exit;
537   control_exist_mac($computer_db, $mac)              or die "Error: physical MAC address already exists: $mac\n";
538   control_exist_pool($computer_db, $pool)            or die "Error: the pool doesn't exists: $pool\n";
539   control_syntax_comment($comment)                   or exit;
540   push @{$computer_db->{$sector}}, { $mac => {
541      'hostname'     => $pool,
542      'ip'           => $pool,
543      'address_type' => 'pool-dhcp',
544      'enabled'      => 'yes',
545      'create_time'  => $timestamp,
546      'modify_time'  => $timestamp,
547      'comment'      => $comment,
548      }};
549   print "Info: add the computer in pool MAC: $mac, sector: $sector, Pool: $pool [OK]\n";
550
551   ipamdb_save("$COMPUTER_YAML", $computer_db);
552   }
553
554#-------------------------------------------------------------------------------
555# ADD computer section
556#-------------------------------------------------------------------------------
557
558sub cmd_add_alias {
559   local @ARGV = @_;
560
561   my $help = get_cmd_name();
562   my ($hostname, $sector, $alias);
563
564   GetOptions(
565      'hostname|h=s'    => \$hostname,
566      'sector|s|d=s'    => \$sector,
567      'alias|a=s'       => \$alias,
568      );
569
570   ($hostname, $sector) = split /\./, $hostname, 2 if $hostname =~ m/\./;
571   exit_on_error_option($help)
572      if $hostname   eq ''
573      or $sector  eq ''
574      or $alias      eq '';
575
576   my $computer_db = ipamdb_load($COMPUTER_YAML);
577   add_alias($computer_db, $hostname, $sector, $alias);
578   }
579
580#-------------------------------------------------------------------------------
581
582sub cmd_add_dhcp {
583   local @ARGV = @_;
584
585   my $help = get_cmd_name();
586   my ($hostname, $sector, $ip, $mac, $comment);
587
588   GetOptions(
589      'hostname|h=s'    => \$hostname,
590      'sector|s|d=s'    => \$sector,
591      'ip|i=s'          => \$ip,
592      'mac|m=s'         => \$mac,
593      'comment|c=s'     => \$comment,
594      );
595
596   ($hostname, $sector) = split /\./, $hostname, 2 if $hostname =~ m/\./;
597   exit_on_error_option($help)
598      if $hostname   eq ''
599      or $sector  eq ''
600      or $ip         eq ''
601      or $mac        eq ''
602      or $comment    eq '';
603
604   my $computer_db = ipamdb_load($COMPUTER_YAML);
605   add_dhcp($computer_db, $hostname, $sector, $ip, $mac, $comment);
606   }
607
608#-------------------------------------------------------------------------------
609
610sub cmd_add_float {
611   local @ARGV = @_;
612
613   my $help = get_cmd_name();
614   my ($pool, $sector, $mac, $comment);
615
616   GetOptions(
617      'pool|p=s'        => \$pool,
618      'sector|s|d=s'    => \$sector,
619      'mac|m=s'         => \$mac,
620      'comment|c=s'     => \$comment,
621      );
622
623   ($pool, $sector) = split /\./, $pool, 2 if $pool =~ m/\./;
624   exit_on_error_option($help)
625      if $pool       eq ''
626      or $sector  eq ''
627      or $mac        eq ''
628      or $comment    eq '';
629
630   my $computer_db = ipamdb_load($COMPUTER_YAML);
631   add_float($computer_db, $pool, $sector, $mac, $comment);
632   }
633
634#-------------------------------------------------------------------------------
635
636sub cmd_add_static {
637   local @ARGV = @_;
638
639   my $help = get_cmd_name();
640   my ($hostname, $sector, $ip, $mac, $comment);
641
642   GetOptions(
643      'hostname|h=s'    => \$hostname,
644      'sector|s|d=s'    => \$sector,
645      'ip|i=s'          => \$ip,
646      'mac|m=s'         => \$mac,
647      'comment|c=s'     => \$comment,
648      );
649
650   ($hostname, $sector) = split /\./, $hostname, 2 if $hostname =~ m/\./;
651   exit_on_error_option($help)
652      if $hostname   eq ''
653      or $sector  eq ''
654      or $ip         eq ''
655      or $mac        eq ''
656      or $comment    eq '';
657
658   my $computer_db = ipamdb_load($COMPUTER_YAML);
659   add_static($computer_db, $hostname, $sector, $ip, $mac, $comment);
660   }
661
662#-------------------------------------------------------------------------------
663# No real computer, just an entry A in DNS with virtual MAC
664
665sub cmd_add_virtual {
666   local @ARGV = @_;
667
668   my $help = get_cmd_name();
669   my ($hostname, $sector, $ip, $comment);
670
671   GetOptions(
672      'hostname|h=s'    => \$hostname,
673      'sector|s|d=s'    => \$sector,
674      'ip|i=s'          => \$ip,
675      'comment|c=s'     => \$comment,
676      );
677
678   ($hostname, $sector) = split /\./, $hostname, 2 if $hostname =~ m/\./;
679   exit_on_error_option($help)
680      if $hostname   eq ''
681      or $sector  eq ''
682      or $ip         eq ''
683      or $comment    eq '';
684
685   my $computer_db = ipamdb_load($COMPUTER_YAML);
686
687   $comment = normalize_comment($comment);
688   my $timestamp = time;
689
690   control_exist_sector($computer_db, $sector)           or exit;
691   control_exist_hostname($computer_db, $sector, $hostname) or die "Error: host already exist in sector $sector: $hostname\n";
692   control_syntax_ip($ip)                                      or exit;
693   control_exist_ip($computer_db, $ip)                         or die "Error: IP address already exist in sector $sector: $ip.\n";
694   control_syntax_comment($comment)                            or exit;
695
696   my $mac = join ':', 'FF', 'FF', map({sprintf("%02X", $_)} split(/\./, $ip));
697   control_syntax_mac_address($mac)             or exit;
698   control_exist_mac($computer_db, $mac)         or die "Error: virtual physical MAC address already exists: $mac\n";
699
700   push @{$computer_db->{$sector}}, { $mac => {
701      'hostname'     => $hostname,
702      'ip'           => $ip,
703      'address_type' => 'static',
704      'enabled'      => 'yes',
705      'create_time'  => $timestamp,
706      'modify_time'  => $timestamp,
707      'comment'      => $comment,
708      }};
709   print "Add the virtual computer: $hostname, IP: $ip, sector: $sector\n";
710
711   ipamdb_save("$COMPUTER_YAML", $computer_db);
712   }
713
714#-------------------------------------------------------------------------------
715# CHANGE computer section
716#-------------------------------------------------------------------------------
717
718#-------------------------------------------------------------------------------
719#Nom: change_mac
720#Description: change la mac adresse d'une machine en saisissant soit l'ip
721#             soit le nom de la mahcine et spécifiant le domaine
722#--- usage: ddt change-mac -s legi-sector03 -h meolpacif -m 00:18:F3:03:6F:66
723#--- usage: ddt change-mac -s legi-sector03 -i 194.254.66.187 -m 00:18:F3:03:6F:66
724
725sub change_mac {
726   my ($hostname, $sector, $ip, $mac) = @_;
727
728   my $computer_db = ipamdb_load($COMPUTER_YAML);
729
730   $mac = normalize_mac_address($mac);
731   control_exist_sector($computer_db, $sector)  or exit;
732   control_syntax_mac_address($mac)                   or exit;
733   control_exist_mac($computer_db, $mac)              or die "Error: physical MAC address already exists: $mac\n";
734   if ($ip ne '') {
735      control_syntax_ip($ip) or exit;
736      if ( control_exist_ip($computer_db, $ip) == 1 ) {
737         print "Error: unkown IP address: $ip\n";
738         exit;
739         }
740      my @sectordb = @{$computer_db->{$sector}};
741      LOOP_ON_COMPUTER:
742      for my $computer (@sectordb) {
743         my ($mac_address, $attribute) = %{$computer};
744         die "Error: physical MAC address $mac already exists in sector $sector\n" if $mac_address eq $mac;
745
746         next LOOP_ON_COMPUTER if $attribute->{'ip'} ne $ip;
747
748         $attribute->{'modify_time'} = time;
749         $computer->{$mac} = $attribute;     # add new mac
750         delete $computer->{$mac_address};   # remove old mac
751
752         ipamdb_save("$COMPUTER_YAML", $computer_db);
753         print "Info: update host $attribute->{'hostname'}, sector $sector, MAC $mac, IP $attribute->{'ip'} [OK]\n";
754         exit;
755         }
756      }
757   elsif ($hostname ne '') {
758      if ( control_exist_hostname($computer_db, $sector, $hostname) == 1 ) {
759         die "Error: unkown host $hostname, sector $sector\n";
760         }
761      my @sectordb = @{$computer_db->{$sector}};
762      LOOP_ON_COMPUTER:
763      for my $computer (@sectordb) {
764         my ($mac_address, $attribute) = %{$computer};
765         die "Error: physical MAC address $mac already exists in sector $sector\n" if $mac_address eq $mac;
766
767         next LOOP_ON_COMPUTER if $attribute->{'hostname'} ne $hostname;
768
769         $attribute->{'modify_time'} = time;
770         $computer->{$mac} = $attribute;     # add new mac
771         delete $computer->{$mac_address};   # remove old mac
772
773         ipamdb_save("$COMPUTER_YAML", $computer_db);
774         print "Info: update host $attribute->{'hostname'}, sector $sector, MAC $mac, IP $attribute->{'ip'} [OK]\n";
775         exit;
776         }
777      }
778   }
779
780#-------------------------------------------------------------------------------
781#Nom: change_ip
782#Description: change l'adresse IP d'une machine en saisissant le nom de la machine
783#             et le domaine
784
785sub change_ip {
786   my ($hostname, $sector, $ip) = @_;
787
788   my $computer_db = ipamdb_load($COMPUTER_YAML);
789
790   control_exist_sector($computer_db, $sector) or exit;
791   if ( control_exist_hostname($computer_db, $sector, $hostname) == 1 ) {
792      die "Error: unkown host: $hostname, in sector: $sector\n";
793      }
794   control_syntax_ip($ip) or exit;
795   control_exist_ip($computer_db, $ip) or die "Error: IP address already exist in sector $sector: $ip\n";
796
797   my @sectordb = @{$computer_db->{$sector}};
798
799   LOOP_ON_COMPUTER:
800   for my $computer (@sectordb) {
801      my ($mac_address, $attribute) = %{$computer};
802     
803      next LOOP_ON_COMPUTER if $attribute->{'hostname'} ne $hostname;
804 
805      if ($attribute->{'address_type'} eq 'pool-dhcp') {
806         die "Error: host $hostname from sector $sector belongs to a a pool [FAILED]" .
807            " ... use 'del-float' command before";
808         }
809
810      $attribute->{'modify_time'} = time;
811      $attribute->{'ip'}          = $ip;
812      ipamdb_save("$COMPUTER_YAML", $computer_db);
813      print "Info: update host $hostname MAC: $mac_address IP: $ip [OK]\n";
814      exit;
815      }
816   }
817
818#-------------------------------------------------------------------------------
819#Nom: change_host
820#Description: change le computer hostname en saisissant l'IP et le domaine
821
822sub change_host {
823   my ($hostname, $sector, $ip) = @_;
824
825   my $computer_db = ipamdb_load($COMPUTER_YAML);
826
827   control_exist_sector($computer_db, $sector) or exit;
828   control_syntax_ip($ip)   or exit;
829   if ( control_exist_ip($computer_db, $ip) == 1 ) {
830      die "Error: unkown IP address: $ip\n";
831      }
832   control_exist_hostname($computer_db, $sector, $hostname) or die "Error: host already exist in sector $sector: $hostname\n";
833
834   my @sectordb = @{$computer_db->{$sector}};
835
836   LOOP_ON_COMPUTER:
837   for my $computer (@sectordb) {
838      my ($mac_address, $attribute) = %{$computer};
839
840      next LOOP_ON_COMPUTER if $attribute->{'ip'} ne $ip;
841
842      $attribute->{'modify_time'} = time;
843      $attribute->{'hostname'}    = $hostname;
844      ipamdb_save("$COMPUTER_YAML", $computer_db);
845      print "Info: update host $hostname MAC: $mac_address IP: $ip [OK]\n";
846      exit;
847      }
848
849   die "Error: failed to update hostname $hostname [FAILED]\n" .
850      " ... no IP $ip belongs to the sector $sector\n";
851   }
852
853#--------------------------------------------------------------------------------
854
855sub cmd_change_mac {
856   local @ARGV = @_;
857
858   my $help = get_cmd_name();
859   my ($hostname, $sector, $ip, $mac);
860
861   GetOptions(
862      'hostname|h=s'    => \$hostname,
863      'sector|s|d=s'    => \$sector,
864      'ip|i=s'          => \$ip,
865      'mac|m=s'         => \$mac,
866      );
867
868   ($hostname, $sector) = split /\./, $hostname, 2 if $hostname =~ m/\./;
869   exit_on_error_option($help)
870      if $sector  eq ''
871      or $mac        eq '';
872   exit_on_error_option($help)
873      if $hostname   ne ''
874      and $ip        ne '';
875
876   change_mac($hostname, $sector, $ip, $mac);
877   }
878
879#--------------------------------------------------------------------------------
880
881sub cmd_change_ip {
882   local @ARGV = @_;
883
884   my $help = get_cmd_name();
885   my ($hostname, $sector, $ip);
886
887   GetOptions(
888      'hostname|h=s'    => \$hostname,
889      'sector|s|d=s'    => \$sector,
890      'ip|i=s'          => \$ip,
891      );
892
893   ($hostname, $sector) = split /\./, $hostname, 2 if $hostname =~ m/\./;
894   exit_on_error_option($help)
895      if $hostname   eq ''
896      or $sector  eq ''
897      or $ip         eq '';
898
899   change_ip($hostname, $sector, $ip);
900   }
901
902#--------------------------------------------------------------------------------
903
904sub cmd_change_host {
905   local @ARGV = @_;
906
907   my $help = get_cmd_name();
908   my ($hostname, $sector, $ip);
909
910   GetOptions(
911      'hostname|h=s'    => \$hostname,
912      'sector|s|d=s'    => \$sector,
913      'ip|i=s'          => \$ip,
914      );
915
916   ($hostname, $sector) = split /\./, $hostname, 2 if $hostname =~ m/\./;
917   exit_on_error_option($help)
918      if $hostname   eq ''
919      or $sector  eq ''
920      or $ip         eq '';
921
922   change_host($hostname, $sector, $ip);
923   }
924
925#--------------------------------------------------------------------------------
926
927sub cmd_change_comment {
928   local @ARGV = @_;
929
930   my $help = get_cmd_name();
931   my ($sector, $mac, $comment);
932
933   GetOptions(
934      'sector|s|d=s'    => \$sector,
935      'mac|m=s'         => \$mac,
936      'comment|c=s'     => \$comment,
937      );
938
939   exit_on_error_option($help)
940      if $sector  eq ''
941      or $mac        eq ''
942      or $comment    eq '';
943
944   $mac     = normalize_mac_address($mac);
945   $comment = normalize_comment($comment);
946
947   my $computer_db = ipamdb_load($COMPUTER_YAML);
948
949   control_exist_sector($computer_db, $sector)  or exit;
950   control_syntax_mac_address($mac)                   or exit;
951   control_syntax_comment($comment)                   or exit;
952
953   my @sectordb = @{$computer_db->{$sector}};
954
955   LOOP_ON_COMPUTER:
956   for my $computer (@sectordb) {
957      my ($mac_address, $attribute) = %{$computer};
958
959      next LOOP_ON_COMPUTER if $mac_address ne $mac;
960
961      $attribute->{'modify_time'} = time;
962      $attribute->{'comment'}     = $comment;
963      ipamdb_save("$COMPUTER_YAML", $computer_db);
964      exit;
965      }
966   die "Error : Host $mac comment [FAILED]\n" .
967      " ... No MAC: $mac belongs to the domaine set $sector.\n";
968   }
969
970#--------------------------------------------------------------------------------
971
972sub cmd_change_sector {
973   local @ARGV = @_;
974
975   my $help = get_cmd_name();
976   my ($sector, $ip, $mac);
977
978   GetOptions(
979      'sector|s|d=s'    => \$sector,
980      'ip|i=s'          => \$ip,
981      'mac|m=s'         => \$mac,
982      );
983
984   exit_on_error_option($help)
985      if $sector  eq ''
986      or $ip         eq ''
987      or $mac        eq '';
988
989   $mac = normalize_mac_address($mac);
990
991   my $computer_db = ipamdb_load($COMPUTER_YAML);
992
993   control_exist_sector($computer_db, $sector)   or exit;
994   control_syntax_ip($ip)                             or exit;
995   control_syntax_mac_address($mac)                   or exit;
996
997   LOOP_ON_SECTOR:
998   for my $sector_current (keys %{$computer_db}) {
999      next if $sector_current eq 'dset';
1000      next if $sector_current eq 'pool';
1001      next if $sector_current eq 'pxe';
1002      next if $sector_current eq 'tag';
1003      next if $sector_current eq 'version';
1004
1005      my @sectordb = @{$computer_db->{$sector_current}};
1006      my $computer_index = 0;
1007      LOOP_ON_COMPUTER:
1008      for my $computer (@sectordb) {
1009         my ($mac_address, $attribute) = %{$computer};
1010
1011         $computer_index++, next LOOP_ON_COMPUTER if $mac_address ne $mac;
1012         next LOOP_ON_SECTOR if $attribute->{'ip'} ne $ip;
1013
1014         $attribute->{'modify_time'} = time;
1015         splice(@{$computer_db->{$sector_current}}, $computer_index => 1);
1016         push @{$computer_db->{$sector}}, { $mac => $attribute };
1017
1018         ipamdb_save("$COMPUTER_YAML", $computer_db);
1019         exit;
1020         }
1021      }
1022   die "Error: update of sector $sector [FAILED]\n" .
1023      " ... MAC $mac and IP $ip don't exists in the database\n";
1024   }
1025
1026#--------------------------------------------------------------------------------
1027
1028sub cmd_change_tag {
1029   local @ARGV = @_;
1030
1031   my $help = get_cmd_name();
1032   my ($hostname, $sector, $ip, $mac, $tags);
1033
1034   GetOptions(
1035      'hostname|h=s'    => \$hostname,
1036      'sector|s|d=s'    => \$sector,
1037      'ip|i=s'          => \$ip,
1038      'mac|m=s'         => \$mac,
1039      'tag|t=s'         => \$tags,
1040      );
1041
1042   ($hostname, $sector) = split /\./, $hostname, 2 if $hostname =~ m/\./;
1043
1044   exit_on_error_option($help)
1045      if $sector  eq ''
1046      or $tags       eq '';
1047   exit_on_error_option($help)
1048      if $mac        eq ''
1049      and $hostname  eq ''
1050      and $ip        eq '';
1051
1052   $mac = normalize_mac_address($mac);
1053
1054   my $computer_db = ipamdb_load($COMPUTER_YAML);
1055
1056   if ($tags !~ m/^ (?:\w+,)* \w+ $/xms) {
1057      die "Error: bad format for tags (comma separated list): $tags\n";
1058      }
1059
1060   for my $tag (split/,/, $tags) {
1061      next if $tag eq 'universal';
1062      die "Error: TAG doesn't exist in the database. Create it before with create_tag: $tag\n" if not exists $computer_db->{'tag'}{$tag};
1063      }
1064
1065   control_exist_sector($computer_db, $sector) or exit;
1066
1067   $mac = get_mac_from_ip($computer_db, $sector, $ip, $mac)             if $ip ne '';
1068   $mac = get_mac_from_hostname($computer_db, $sector, $hostname, $mac) if $hostname ne '';
1069   control_syntax_mac_address($mac) or exit;
1070
1071   LOOP_ON_COMPUTER:
1072   for my $computer (@{$computer_db->{$sector}}) {
1073      my ($mac_address, $attribute) = %{$computer};
1074
1075      next LOOP_ON_COMPUTER if $mac_address ne $mac;
1076
1077      $attribute->{'tag'}         = $tags;
1078      $attribute->{'modify_time'} = time;
1079
1080      delete $attribute->{'tag'} if $tags eq 'universal';
1081      ipamdb_save("$COMPUTER_YAML", $computer_db);
1082      exit;
1083      }
1084   print "Mise à jour du commentaire de la machine [FAILED]\n";
1085   print "L'adresse MAC: $mac n'existe pas dans le domaine: $sector.\n";
1086   }
1087
1088#-------------------------------------------------------------------------------
1089# ACTIVATION section
1090#-------------------------------------------------------------------------------
1091
1092#-------------------------------------------------------------------------------
1093#Nom: disable_pc
1094#Description: désactive une machine (du DHCP ou en IP statique, et du DNS) (champs enabled=non)
1095
1096sub disable_pc {
1097   my ($hostname, $sector, $ip) = @_;
1098
1099   my $computer_db = ipamdb_load($COMPUTER_YAML);
1100
1101   if ($ip ne '') { # disable by IP
1102      control_syntax_ip($ip);
1103      if ( control_exist_ip($computer_db, $ip) == 1 ) {
1104         die "Error: unkown IP address: $ip [FAILED]\n";
1105         }
1106
1107      for my $sector_current (keys %{$computer_db}) {
1108         next if $sector_current eq 'dset';
1109         next if $sector_current eq 'pool';
1110         next if $sector_current eq 'pxe';
1111         next if $sector_current eq 'tag';
1112         next if $sector_current eq 'version';
1113
1114         my @sectordb = @{$computer_db->{$sector_current}};
1115         LOOP_ON_COMPUTER:
1116         for my $computer (@sectordb) {
1117            my ($mac_address, $attribute) = %{$computer};
1118
1119            next LOOP_ON_COMPUTER if $attribute->{'ip'} ne $ip;
1120
1121            if ($attribute->{'enabled'} eq 'no') {
1122               print "Info: IP $ip from sector $sector_current is already disable [OK]" .
1123                  " ... Status: $attribute->{'enabled'}\n";
1124               exit;
1125               }
1126
1127            my $timestamp = time;
1128            $attribute->{'modify_time'} = $timestamp;
1129            $attribute->{'enabled'}     = 'no';
1130            ipamdb_save("$COMPUTER_YAML", $computer_db);
1131            print "Info: disabling IP $ip from sector $sector_current [OK]" .
1132               " ... Status: $attribute->{'enabled'}\n";
1133            exit;
1134            }
1135         }
1136      }
1137   else { # disable by Hostname
1138      control_exist_sector($computer_db, $sector);
1139      if ( control_exist_hostname($computer_db, $sector, $hostname) == 1 ) {
1140         die "Error: unkown host: $hostname, in sector: $sector [FAILED]\n";
1141         }
1142
1143      LOOP_ON_COMPUTER:
1144      for my  $computer (@{$computer_db->{$sector}}) {
1145         my ($mac_address, $attribute) = %{$computer};
1146
1147         next LOOP_ON_COMPUTER if $attribute->{'hostname'} ne $hostname;
1148
1149         if ($attribute->{'address_type'} eq 'pool-dhcp') {
1150            die "Error: host $hostname from sector $sector belongs to a a pool [FAILED]" .
1151               " ... use 'disable-float' command instead";
1152            }
1153
1154         if ($attribute->{'enabled'} eq 'no') {
1155            print "Info: host $hostname from sector $sector is already disable [OK]" .
1156               " ... Status: $attribute->{'enabled'}\n";
1157            exit;
1158            }
1159
1160         my $timestamp = time;
1161         $attribute->{'modify_time'} = $timestamp;
1162         $attribute->{'enabled'}     = 'no';
1163         ipamdb_save("$COMPUTER_YAML", $computer_db);
1164         print "Info: disabling host $hostname from sector $sector [OK]" .
1165            " ... Status: $attribute->{'enabled'}\n";
1166         exit;
1167         }
1168      }
1169   }
1170
1171#-------------------------------------------------------------------------------
1172
1173sub disable_float {
1174   my ($pool, $mac) = @_;
1175
1176   my $computer_db = ipamdb_load($COMPUTER_YAML);
1177
1178   if ( control_exist_mac($computer_db, $mac) == 1 ) {
1179      die "Error: unkown physical MAC address: $mac [FAILED]\n";
1180      }
1181
1182   for my $sector_current (keys %{$computer_db}) {
1183      next if $sector_current eq 'dset';
1184      next if $sector_current eq 'pool';
1185      next if $sector_current eq 'pxe';
1186      next if $sector_current eq 'tag';
1187      next if $sector_current eq 'version';
1188
1189      my @sectordb = @{$computer_db->{$sector_current}};
1190
1191      LOOP_ON_COMPUTER:
1192      for my $computer (@sectordb) {
1193         my ($mac_address, $attribute) = %{$computer};
1194         next LOOP_ON_COMPUTER if $mac_address ne $mac;
1195
1196         if ($attribute->{'ip'} eq $pool) {
1197            if ($attribute->{'enabled'} eq 'no') {
1198               print "Info: host $mac from pool $pool is already disable [OK]" .
1199                  " ... Status: $attribute->{'enabled'}\n";
1200               exit;
1201               }
1202            my $timestamp = time;
1203            $attribute->{'modify_time'} = $timestamp;
1204            $attribute->{'enabled'}     = 'no';
1205            ipamdb_save("$COMPUTER_YAML", $computer_db);
1206            print "Info: disabling host $mac from pool $pool [OK]" .
1207               " ... Status: $attribute->{'enabled'}\n";
1208            exit;
1209            }
1210         else {
1211            die "Error: host disable $mac [FAILED]" .
1212               " ... The host $mac does not belong to the $pool pool.\n";
1213            }
1214         }
1215      }
1216   }
1217
1218#-------------------------------------------------------------------------------
1219#Nom: enable_pc
1220#Description: active une machine désactivée(du DHCP ou en IP statique, et du DNS) (champs enabled=non)
1221
1222sub enable_pc {
1223   my ($hostname, $sector, $ip) = @_;
1224
1225   my $computer_db = ipamdb_load($COMPUTER_YAML);
1226
1227   control_exist_sector($computer_db, $sector) or exit;
1228
1229   if ($ip ne '') { # enable by IP
1230      control_syntax_ip($ip);
1231      if ( control_exist_ip($computer_db, $ip) == 1 ) {
1232         print "Error: unkown IP address: $ip\n";
1233         exit;
1234         }
1235
1236      for my $sector_current (keys %{$computer_db}) {
1237         next if $sector_current eq 'dset';
1238         next if $sector_current eq 'pool';
1239         next if $sector_current eq 'pxe';
1240         next if $sector_current eq 'tag';
1241         next if $sector_current eq 'version';
1242
1243         my @sectordb = @{$computer_db->{$sector_current}};
1244
1245         LOOP_ON_COMPUTER:
1246         for my $computer (@sectordb) {
1247            my ($mac_address, $attribute) = %{$computer};
1248            if ($attribute->{'ip'} eq $ip) {
1249
1250               if ($attribute->{'enabled'} eq 'yes') {
1251                  print "Info: IP $ip belongs to sector $sector is already enable [OK]" .
1252                     " ... Status: $attribute->{'enabled'}\n";
1253                  exit;
1254                  }
1255
1256               my $timestamp = time;
1257               $attribute->{'modify_time'} = $timestamp;
1258               $attribute->{'enabled'}     = 'yes';
1259               ipamdb_save("$COMPUTER_YAML", $computer_db);
1260               print "Info: IP $ip is now enable [OK]" .
1261                  " ... Status: $attribute->{'enabled'}\n";
1262               exit;
1263               }
1264            }
1265         }
1266      }
1267   else { # enable by Hostname
1268      if ( control_exist_hostname($computer_db, $sector, $hostname) == 1 ) {
1269         die "Error: unkown host: $hostname, in sector: $sector\n";
1270         }
1271
1272      LOOP_ON_COMPUTER:
1273      for my $computer (@{$computer_db->{$sector}}) {
1274         my ($mac_address, $attribute) = %{$computer};
1275         next LOOP_ON_COMPUTER if $attribute->{'hostname'} ne $hostname;
1276
1277         if ($attribute->{'address_type'} eq 'pool-dhcp') {
1278            die "Error: host $hostname from sector $sector belongs to a a pool [FAILED]" .
1279               " ... use 'enable-float' command instead";
1280            }
1281
1282         if ($attribute->{'enabled'} eq 'yes') {
1283            print "Info: host $hostname belongs to sector $sector is already enable [OK]" .
1284               " ... Status: $attribute->{'enabled'}\n";
1285            exit;
1286            }
1287
1288         my $timestamp = time;
1289         $attribute->{'modify_time'} = $timestamp;
1290         $attribute->{'enabled'}     = 'yes';
1291         ipamdb_save("$COMPUTER_YAML", $computer_db);
1292         print "Info: host $hostname is now enable [OK]" .
1293            " ... Status: $attribute->{'enabled'}\n";
1294         exit;
1295         }
1296      }
1297   }
1298
1299#-------------------------------------------------------------------------------
1300
1301sub enable_float {
1302   my ($pool, $mac) = @_;
1303
1304   my $computer_db = ipamdb_load($COMPUTER_YAML);
1305
1306   if ( control_exist_mac($computer_db, $mac) == 1 ) {
1307      die "Error: unkown physical MAC address: $mac [FAILED]\n";
1308      }
1309
1310   for my $sector_current (keys %{$computer_db}) {
1311      next if $sector_current eq 'dset';
1312      next if $sector_current eq 'pool';
1313      next if $sector_current eq 'pxe';
1314      next if $sector_current eq 'tag';
1315      next if $sector_current eq 'version';
1316
1317      my @sectordb = @{$computer_db->{$sector_current}};
1318
1319      LOOP_ON_COMPUTER:
1320      for my $computer (@sectordb) {
1321         my ($mac_address, $attribute) = %{$computer};
1322         next LOOP_ON_COMPUTER if $mac_address ne $mac;
1323
1324         if ($attribute->{'ip'} ne $pool) {
1325            die "Error: host enable $mac [FAILED]" .
1326               " ... The host $mac does not belong to the $pool pool.\n";
1327            }
1328
1329         if ($attribute->{'enabled'} eq 'yes') {
1330            print "Info: host $mac from pool $pool is already enable [OK]" .
1331               " ... Status: $attribute->{'enabled'}\n";
1332            exit;
1333            }
1334
1335         my $timestamp = time;
1336         $attribute->{'modify_time'} = $timestamp;
1337         $attribute->{'enabled'}     = 'yes';
1338         ipamdb_save("$COMPUTER_YAML", $computer_db);
1339         print "Info: enabling host $mac from pool $pool [OK]" .
1340            " ... Status: $attribute->{'enabled'}\n";
1341         exit;
1342         }
1343      }
1344   }
1345
1346#-------------------------------------------------------------------------------
1347
1348sub cmd_enable_pc {
1349   local @ARGV = @_;
1350
1351   my $help = get_cmd_name();
1352   my ($hostname, $sector, $ip);
1353
1354   GetOptions(
1355      'hostname|h=s'    => \$hostname,
1356      'sector|s|d=s'    => \$sector,
1357      'ip|i=s'          => \$ip,
1358      );
1359
1360   ($hostname, $sector) = split /\./, $hostname, 2 if $hostname =~ m/\./;
1361   exit_on_error_option($help)
1362      if $sector  eq '';
1363   exit_on_error_option($help)
1364      if $hostname   eq ''
1365      and $ip        eq '';
1366   exit_on_error_option($help)
1367      if $hostname   ne ''
1368      and $ip        ne '';
1369
1370   enable_pc($hostname, $sector, $ip);
1371   }
1372
1373#-------------------------------------------------------------------------------
1374
1375sub cmd_disable_pc {
1376   local @ARGV = @_;
1377
1378   my $help = get_cmd_name();
1379   my ($hostname, $sector, $ip);
1380
1381   GetOptions(
1382      'hostname|h=s'    => \$hostname,
1383      'sector|s|d=s'    => \$sector,
1384      'ip|i=s'          => \$ip,
1385      );
1386
1387   ($hostname, $sector) = split /\./, $hostname, 2 if $hostname =~ m/\./;
1388   exit_on_error_option($help)
1389      if $sector  eq '';
1390   exit_on_error_option($help)
1391      if $hostname   eq ''
1392      and $ip        eq '';
1393   exit_on_error_option($help)
1394      if $hostname   ne ''
1395      and $ip        ne '';
1396
1397   disable_pc($hostname, $sector, $ip);
1398   }
1399
1400#-------------------------------------------------------------------------------
1401
1402sub cmd_disable_float {
1403   local @ARGV = @_;
1404
1405   my $help = get_cmd_name();
1406   my ($pool, $mac);
1407
1408   GetOptions(
1409      'pool|p=s'  => \$pool,
1410      'mac|m=s'   => \$mac,
1411      );
1412
1413   ($pool) = split /\./, $pool, 2 if $pool =~ m/\./;
1414   exit_on_error_option($help)
1415      if $pool eq ''
1416      or $mac  eq '';
1417
1418   disable_float($pool, $mac);
1419   }
1420
1421#-------------------------------------------------------------------------------
1422
1423sub cmd_enable_float {
1424   local @ARGV = @_;
1425
1426   my $help = get_cmd_name();
1427   my ($pool, $mac);
1428
1429   GetOptions(
1430      'pool|p=s'  => \$pool,
1431      'mac|m=s'   => \$mac,
1432      );
1433
1434   ($pool) = split /\./, $pool, 2 if $pool =~ m/\./;
1435   exit_on_error_option($help)
1436      if $pool eq ''
1437      or $mac  eq '';
1438
1439   enable_float($pool, $mac);
1440   }
1441
1442#-------------------------------------------------------------------------------
1443# DELETE section
1444#-------------------------------------------------------------------------------
1445
1446#-------------------------------------------------------------------------------
1447#Nom: del_pc
1448#Description: supprime une machine en DHCP ou en IP statique.
1449
1450sub del_pc {
1451   my ($hostname, $sector, $ip) = @_;
1452
1453   my $computer_db = ipamdb_load($COMPUTER_YAML);
1454
1455   control_exist_sector($computer_db, $sector) or exit;
1456   if ($ip ne '') { # delete by IP
1457      if ( control_exist_ip($computer_db, $ip) == 1 ) {
1458         die "Error: unkown IP address: $ip\n";
1459         }
1460
1461      my $computer_index = 0;
1462
1463      LOOP_ON_COMPUTER:
1464      for my $computer (@{$computer_db->{$sector}}) {
1465         my ($mac_address, $attribute) = %{$computer};
1466
1467         $computer_index++, next LOOP_ON_COMPUTER if $attribute->{'ip'} ne $ip;
1468         
1469         splice(@{$computer_db->{$sector}}, $computer_index => 1);
1470         ipamdb_save("$COMPUTER_YAML", $computer_db);
1471         print "Info: host $ip has been removed from the sector $sector [OK]\n";
1472         exit;
1473         }
1474      }
1475   else {
1476      if ( control_exist_hostname($computer_db, $sector, $hostname) == 1 ) {
1477         die "Error: unkown host: $hostname, in sector: $sector\n";
1478         }
1479
1480      my $computer_index = 0;
1481
1482      LOOP_ON_COMPUTER:
1483      for my $computer (@{$computer_db->{$sector}}) {
1484         my ($mac_address, $attribute) = %{$computer};
1485
1486         $computer_index++, next LOOP_ON_COMPUTER if $attribute->{'hostname'} ne $hostname;
1487
1488         if ($attribute->{'address_type'} eq 'pool-dhcp') {
1489            die "Error: host remove $hostname from the sector $sector [FAILED]" .
1490               " ... The host $hostname belongs to a DHCP pool.\n";
1491            }
1492
1493         splice(@{$computer_db->{$sector}}, $computer_index => 1);
1494         ipamdb_save("$COMPUTER_YAML", $computer_db);
1495         print "Info: host $hostname has been removed from the sector $sector [OK]\n";
1496         exit;
1497         }
1498      }
1499   }
1500
1501#-------------------------------------------------------------------------------
1502#Nom: del_float
1503#Description: supprime une machine d'un pool DHCP
1504
1505sub del_float {
1506   my ($pool, $mac) = @_;
1507
1508   my $computer_db = ipamdb_load($COMPUTER_YAML);
1509
1510   if ( control_exist_mac($computer_db, $mac) == 1 ) {
1511      print "Adresse MAC $mac non trouvée.\n";
1512      exit;
1513      }
1514
1515   for my $sector_current (keys %{$computer_db}) {
1516      next if $sector_current eq 'dset';
1517      next if $sector_current eq 'pool';
1518      next if $sector_current eq 'pxe';
1519      next if $sector_current eq 'tag';
1520      next if $sector_current eq 'version';
1521
1522      my @sectordb = @{$computer_db->{$sector_current}};
1523
1524      my $computer_index = 0;
1525
1526      LOOP_ON_COMPUTER:
1527      for my $computer (@sectordb) {
1528         my ($mac_address, $attribute) = %{$computer};
1529
1530         $computer_index++, next LOOP_ON_COMPUTER if $mac_address ne $mac;
1531
1532         if ($attribute->{'ip'} ne $pool) {
1533            die "Error: host remove $mac [FAILED]" .
1534               " ... The host $mac does not belong to the $pool pool.\n";
1535            }
1536
1537         splice(@{$computer_db->{$sector_current}}, $computer_index => 1);
1538         ipamdb_save("$COMPUTER_YAML", $computer_db);
1539         print "Info: remove host $mac from the pool $pool [OK]\n";
1540         exit;
1541         }
1542      }
1543   }
1544
1545#-------------------------------------------------------------------------------
1546
1547sub cmd_del_pc {
1548   local @ARGV = @_;
1549
1550   my $help = get_cmd_name();
1551   my ($hostname, $sector, $ip);
1552
1553   GetOptions(
1554      'hostname|h=s'    => \$hostname,
1555      'sector|s|d=s'    => \$sector,
1556      'ip|i=s'          => \$ip,
1557      );
1558
1559   ($hostname, $sector) = split /\./, $hostname, 2 if $hostname =~ m/\./;
1560   exit_on_error_option($help)
1561      if $sector  eq '';
1562   exit_on_error_option($help)
1563      if $hostname   eq ''
1564      and $ip        eq '';
1565   exit_on_error_option($help)
1566      if $hostname   ne ''
1567      and $ip        ne '';
1568
1569   del_pc($hostname, $sector, $ip);
1570   }
1571
1572#-------------------------------------------------------------------------------
1573
1574sub cmd_del_float {
1575   local @ARGV = @_;
1576
1577   my $help = get_cmd_name();
1578   my ($pool, $mac);
1579
1580   GetOptions(
1581      'pool|p=s'        => \$pool,
1582      'mac|m=s'         => \$mac,
1583      );
1584
1585   ($pool) = split /\./, $pool, 2 if $pool =~ m/\./;
1586   exit_on_error_option($help)
1587      if $pool eq ''
1588      or $mac  eq '';
1589
1590   del_float($pool, $mac);
1591   }
1592
1593#-------------------------------------------------------------------------------
1594# SECTOR section
1595#-------------------------------------------------------------------------------
1596
1597sub cmd_create_sector {
1598   local @ARGV = @_;
1599
1600   my $help = get_cmd_name();
1601   my ($sector, $dns_extension, $comment);
1602
1603   GetOptions(
1604      'sector|s|d=s'      => \$sector,
1605      'dns-extension|e=s'  => \$dns_extension,
1606      'comment|c=s'        => \$comment,
1607      );
1608
1609   exit_on_error_option($help)
1610      if $sector     eq ''
1611      or $dns_extension eq ''
1612      or $comment       eq '';
1613
1614   $comment = normalize_comment($comment);
1615
1616   my $computer_db = ipamdb_load($COMPUTER_YAML);
1617
1618   $computer_db->{'dset'} ||= {};
1619   die "Error: sector already exists: $sector\n" if exists $computer_db->{'dset'}{$sector};
1620
1621   control_syntax_comment($comment)    or exit;
1622
1623   my $timestamp = time;
1624   $computer_db->{'dset'}{$sector} = {
1625      'dns_extension'   => $dns_extension,
1626      'comment'         => $comment,
1627      'create_time'     => $timestamp,
1628      'modify_time'     => $timestamp,
1629      };
1630   $computer_db->{$sector} ||= []; # Create empty sector computer list by default
1631   ipamdb_save("$COMPUTER_YAML", $computer_db);
1632   }
1633
1634#-------------------------------------------------------------------------------
1635# POOL section
1636#-------------------------------------------------------------------------------
1637
1638#-------------------------------------------------------------------------------
1639#Nom: create_pool
1640#Description: crée un pool dans le fichier de données YAML et dans le DHCP.
1641#
1642#Commentaires: il y a un petit bug si jamais on rentre que des adresses ip qui existent déjà.
1643#              Le pool est créé mais sans adresses ip.
1644
1645sub cmd_create_pool {
1646   local @ARGV = @_;
1647
1648   my $help = get_cmd_name();
1649   my ($pool, $sector, $file_pool, $ipaddress_pool);
1650
1651   GetOptions(
1652      'pool|p=s'           => \$pool,
1653      'sector|s|d=s'      => \$sector,
1654      'file-pool|f=s'      => \$file_pool,
1655      'ipaddress-pool|i=s' => \$ipaddress_pool,
1656      );
1657
1658   exit_on_error_option($help)
1659      if $pool             eq ''
1660      or $sector        eq ''
1661      or $file_pool        eq ''
1662      or $ipaddress_pool   eq '';
1663
1664   my $computer_db = ipamdb_load($COMPUTER_YAML);
1665
1666   if ($computer_db->{'pool'}) {
1667      die "Error: pool already exists: $pool\n" if exists $computer_db->{'pool'}{$pool};
1668      }
1669
1670   #--- control if the domain's pool exist ---#
1671   control_exist_sector($computer_db, $sector) or exit;
1672
1673   my @ip_list = ();
1674   #---control if address exist ---#
1675   if ($ipaddress_pool =~ /,/) {
1676      for my $ip (split /,/, $ipaddress_pool) {
1677         if ($ip =~ /-/) {
1678            my ($ip1, $ip2, $ip3, $range) = split /\./, $ip;
1679            my ($first, $last) = split /-/, $range;
1680            for (my $cpt = $first; $cpt <= $last; $cpt++) {
1681               my $ip_loc = "$ip1.$ip2.$ip3.$cpt";
1682               control_syntax_ip($ip_loc) or die "Error: bad IP syntax: $ip_loc\n";
1683               control_exist_ip($computer_db, $ip_loc) or die "Error: IP address already exists: $ip_loc\n";
1684               push @ip_list, $ip_loc;
1685               }
1686            }
1687         else {
1688            control_syntax_ip($ip) or next;
1689            if ( control_exist_ip($computer_db, $ip) == 0 ) {
1690               print "L'adresse IP $ip existe déjà\n";
1691               next;
1692               }
1693            push @ip_list, $ip;
1694            }
1695         }
1696      }
1697
1698   my $timestamp = time;
1699   $computer_db->{'pool'}{$pool} = {
1700      'ip'          => [@ip_list],
1701      'enabled'     => 'yes',
1702      'create_time' => $timestamp,
1703      'modify_time' => $timestamp,
1704      'file'        => $file_pool,
1705      'domain'      => $sector,
1706      };
1707   ipamdb_save("$COMPUTER_YAML", $computer_db);
1708   }
1709
1710#-------------------------------------------------------------------------------
1711
1712sub cmd_show_pool {
1713   local @ARGV = @_;
1714
1715   my ($no_header);
1716
1717   GetOptions(
1718      'no-header|H' => \$no_header,
1719      );
1720
1721   my $computer_db = ipamdb_load($COMPUTER_YAML);
1722
1723   printf "%-17s %-17s %s\n", 'Pool', 'File', 'DNS-Domain' if not $no_header;
1724   LOOP_ON_PXE:
1725   for my $pool ( keys %{$computer_db->{'pool'}} ) {
1726
1727      printf "%-17s %-17s %s\n",
1728         $pool,
1729         $computer_db->{'pool'}{$pool}{'file'},
1730         $computer_db->{'pool'}{$pool}{'domain'},
1731      }
1732   }
1733
1734#-------------------------------------------------------------------------------
1735# PXE section
1736#-------------------------------------------------------------------------------
1737
1738sub cmd_create_pxe {
1739   local @ARGV = @_;
1740
1741   my $help = get_cmd_name();
1742   my ($pxe_config, $ip_next_server, $filename, $comment);
1743
1744   GetOptions(
1745      'bootp|b=s'       => \$pxe_config,
1746      'next-server|n=s' => \$ip_next_server,
1747      'filename|f=s'    => \$filename,
1748      'comment|c=s'     => \$comment,
1749      );
1750
1751   exit_on_error_option($help)
1752      if $pxe_config       eq ''
1753      or $ip_next_server   eq ''
1754      or $filename         eq ''
1755      or $comment          eq '';
1756
1757   my $computer_db = ipamdb_load($COMPUTER_YAML);
1758
1759   $comment = normalize_comment($comment);
1760
1761   $computer_db->{'pxe'} ||= {};
1762   die "Error: PXE config already exists: $pxe_config\n" if exists $computer_db->{'pxe'}{$pxe_config};
1763
1764   control_syntax_ip($ip_next_server)  or die "Error: bad IP syntax: $ip_next_server\n";
1765   control_syntax_comment($comment)    or exit;
1766
1767   my $timestamp = time;
1768   $computer_db->{'pxe'}{$pxe_config} = {
1769      'ip_next_server'  => $ip_next_server,
1770      'filename'        => $filename,
1771      'comment'         => $comment,
1772      'create_time'     => $timestamp,
1773      'modify_time'     => $timestamp,
1774      };
1775   ipamdb_save("$COMPUTER_YAML", $computer_db);
1776   }
1777
1778#-------------------------------------------------------------------------------
1779
1780sub cmd_remove_pxe {
1781   local @ARGV = @_;
1782
1783   my $help = get_cmd_name();
1784   my ($pxe_config);
1785
1786   GetOptions(
1787      'bootp|b=s' => \$pxe_config,
1788      );
1789
1790   exit_on_error_option($help)
1791      if $pxe_config eq '';
1792
1793   my $computer_db = ipamdb_load($COMPUTER_YAML);
1794
1795   $computer_db->{'pxe'} ||= {};
1796   die "Error: PXE config does not exist: $pxe_config\n" if not exists $computer_db->{'pxe'}{$pxe_config};
1797
1798   # Test if some computer use this config
1799   LOOP_ON_SECTOR:
1800   for my $sector_current (keys %{$computer_db}) {
1801      next if $sector_current eq 'dset';
1802      next if $sector_current eq 'pool';
1803      next if $sector_current eq 'pxe';
1804      next if $sector_current eq 'tag';
1805      next if $sector_current eq 'version';
1806
1807      LOOP_ON_COMPUTER:
1808      for my $computer (@{$computer_db->{$sector_current}}) {
1809         my ($mac_address, $attribute) = %{$computer};
1810
1811         if (exists $attribute->{'pxe_config'}) {
1812            my $hostname = $attribute->{'hostname'};
1813            die "Error: computer still use this PXE config: $hostname.$sector_current $mac_address\n" if $pxe_config eq $attribute->{'pxe_config'};
1814            }
1815         }
1816      }
1817
1818   delete $computer_db->{'pxe'}{$pxe_config};
1819   ipamdb_save("$COMPUTER_YAML", $computer_db);
1820   }
1821
1822#--------------------------------------------------------------------------------
1823
1824sub cmd_show_pxe {
1825   local @ARGV = @_;
1826
1827   my ($no_header);
1828
1829   GetOptions(
1830      'no-header|H' => \$no_header,
1831      );
1832
1833   my $computer_db = ipamdb_load($COMPUTER_YAML);
1834
1835   printf "%-12s %-13s %-30s %s\n", 'PXE-Config', 'Next-Server', 'Filename', 'Comment' if not $no_header;
1836   LOOP_ON_PXE:
1837   for my $pxe_config ( keys %{$computer_db->{'pxe'}} ) {
1838      my $ip_next_server = $computer_db->{'pxe'}{$pxe_config}{'ip_next_server'};
1839      my $filename       = $computer_db->{'pxe'}{$pxe_config}{'filename'};
1840      my $comment        = $computer_db->{'pxe'}{$pxe_config}{'comment'};
1841
1842      printf "%-12s %-13s %-30s %s\n", $pxe_config, $ip_next_server, $filename, $comment;
1843      }
1844   }
1845
1846#-------------------------------------------------------------------------------
1847
1848sub cmd_enable_pxe {
1849   local @ARGV = @_;
1850
1851   my $help = get_cmd_name();
1852   my ($hostname, $sector, $ip, $pxe_config);
1853
1854   GetOptions(
1855      'hostname|h=s'    => \$hostname,
1856      'sector|s|d=s'    => \$sector,
1857      'ip|i=s'          => \$ip,
1858      'bootp|b=s'       => \$pxe_config,
1859      );
1860
1861   ($hostname, $sector) = split /\./, $hostname, 2 if $hostname =~ m/\./;
1862   exit_on_error_option($help)
1863      if $sector  eq ''
1864      or $pxe_config eq '';
1865   exit_on_error_option($help)
1866      if $hostname   eq ''
1867      and $ip        eq '';
1868   exit_on_error_option($help)
1869      if $hostname   ne ''
1870      and $ip        ne '';
1871
1872   my $computer_db = ipamdb_load($COMPUTER_YAML);
1873
1874   die "Error: PXE config not exists: $pxe_config\n" if not exists $computer_db->{'pxe'}{$pxe_config};
1875
1876   control_exist_sector($computer_db, $sector) or exit;
1877   if ($ip ne '') {
1878      control_syntax_ip($ip);
1879      if ( control_exist_ip($computer_db, $ip) == 1 ) {
1880         die "Error: unkown IP address: $ip\n";
1881         }
1882
1883      for my $sector_current (keys %{$computer_db}) {
1884         next if $sector_current eq 'dset';
1885         next if $sector_current eq 'pool';
1886         next if $sector_current eq 'pxe';
1887         next if $sector_current eq 'tag';
1888         next if $sector_current eq 'version';
1889
1890         LOOP_ON_COMPUTER:
1891         for my $computer (@{$computer_db->{$sector_current}}) {
1892            my ($mac_address, $attribute) = %{$computer};
1893            next LOOP_ON_COMPUTER if $attribute->{'ip'} ne $ip;
1894
1895            $attribute->{'modify_time'} = time;
1896            $attribute->{'pxe_config'}  = $pxe_config;
1897            ipamdb_save("$COMPUTER_YAML", $computer_db);
1898            print "Info: host $attribute->{'hostname'} ($sector_current), IP $ip, PXE enabled: $pxe_config\n";
1899            exit;
1900            }
1901         }
1902      }
1903   else {
1904      if ( control_exist_hostname($computer_db, $sector, $hostname) == 1 ) {
1905         die "Error: unkown host: $hostname, in sector: $sector\n";
1906         }
1907
1908      LOOP_ON_COMPUTER:
1909      for my $computer (@{$computer_db->{$sector}}) {
1910         my ($mac_address, $attribute) = %{$computer};
1911         next LOOP_ON_COMPUTER if $attribute->{'hostname'} ne $hostname;
1912         
1913         if ($attribute->{'address_type'} eq 'pool-dhcp') {
1914            die "Error. Host $hostname ($sector) in a pool. No PXE possible [FAILED]\n";
1915            }
1916
1917         $attribute->{'modify_time'} = time;
1918         $attribute->{'pxe_config'}  = $pxe_config;
1919         ipamdb_save("$COMPUTER_YAML", $computer_db);
1920         print "Info: host $hostname ($sector), IP $attribute->{'ip'}, PXE enabled: $pxe_config [OK]\n";
1921         exit;
1922         }
1923      }
1924   }
1925
1926#-------------------------------------------------------------------------------
1927
1928sub cmd_disable_pxe {
1929   local @ARGV = @_;
1930
1931   my $help = get_cmd_name();
1932   my ($hostname, $sector, $ip);
1933
1934   GetOptions(
1935      'hostname|h=s'    => \$hostname,
1936      'sector|s|d=s'    => \$sector,
1937      'ip|i=s'          => \$ip,
1938      );
1939
1940   ($hostname, $sector) = split /\./, $hostname, 2 if $hostname =~ m/\./;
1941   exit_on_error_option($help)
1942      if $sector  eq '';
1943   exit_on_error_option($help)
1944      if $hostname   eq ''
1945      and $ip        eq '';
1946   exit_on_error_option($help)
1947      if $hostname   ne ''
1948      and $ip        ne '';
1949
1950   my $computer_db = ipamdb_load($COMPUTER_YAML);
1951
1952   control_exist_sector($computer_db, $sector) or exit;
1953   if ($ip ne '') {
1954      control_syntax_ip($ip);
1955      if ( control_exist_ip($computer_db, $ip) == 1 ) {
1956         die "Error: unkown IP address: $ip\n";
1957         }
1958
1959      for my $sector_current (keys %{$computer_db}) {
1960         next if $sector_current eq 'dset';
1961         next if $sector_current eq 'pool';
1962         next if $sector_current eq 'pxe';
1963         next if $sector_current eq 'tag';
1964         next if $sector_current eq 'version';
1965
1966         LOOP_ON_COMPUTER:
1967         for my $computer (@{$computer_db->{$sector_current}}) {
1968            my ($mac_address, $attribute) = %{$computer};
1969           
1970            next LOOP_ON_COMPUTER if $attribute->{'ip'} ne $ip;
1971            next LOOP_ON_COMPUTER if not exists $attribute->{'pxe_config'};
1972
1973            my $pxe_config = $attribute->{'pxe_config'};
1974            $attribute->{'modify_time'} = time;
1975            delete $attribute->{'pxe_config'};
1976            ipamdb_save("$COMPUTER_YAML", $computer_db);
1977            print "Info: IP address: $ip, PXE disable from config: $pxe_config [OK]\n";
1978            exit;
1979            }
1980         }
1981      }
1982   else {
1983      if ( control_exist_hostname($computer_db, $sector, $hostname) == 1 ) {
1984         die "Error: unkown host: $hostname, in sector: $sector\n";
1985         }
1986
1987      LOOP_ON_COMPUTER:
1988      for my $computer (@{$computer_db->{$sector}}) {
1989         my ($mac_address, $attribute) = %{$computer};
1990
1991         next LOOP_ON_COMPUTER if $attribute->{'hostname'} eq $hostname;
1992
1993         if ($attribute->{'address_type'} eq 'pool-dhcp') {
1994            die "Error: host $hostname ($sector) in a pool. No PXE possible [FAILED]\n";
1995            }
1996
1997         next LOOP_ON_COMPUTER if not exists $attribute->{'pxe_config'};
1998
1999         my $pxe_config = $attribute->{'pxe_config'};
2000         $attribute->{'modify_time'} = time;
2001         delete $attribute->{'pxe_config'};
2002         ipamdb_save("$COMPUTER_YAML", $computer_db);
2003         print "Info: host $hostname ($sector), PXE disable from config: $pxe_config [OK]\n";
2004         exit;
2005         }
2006      }
2007   }
2008
2009#-------------------------------------------------------------------------------
2010# TAG section
2011#-------------------------------------------------------------------------------
2012
2013sub cmd_create_tag {
2014   local @ARGV = @_;
2015
2016   my $help = get_cmd_name();
2017   my ($tag, $comment);
2018
2019   GetOptions(
2020      'tag|t=s'      => \$tag,
2021      'comment|c=s'  => \$comment,
2022      );
2023
2024   exit_on_error_option($help)
2025      if $tag     eq ''
2026      or $comment eq '';
2027
2028   my $computer_db = ipamdb_load($COMPUTER_YAML);
2029
2030   $comment = normalize_comment($comment);
2031
2032   $computer_db->{'tag'} ||= {};
2033   die "Error: TAG already exists: $tag\n" if exists $computer_db->{'tag'}{$tag};
2034
2035   die "Error: TAG 'universal' is intrinsic. It's not possible to create it.\n" if $tag eq 'universal';
2036
2037   if ($tag !~ m/^ \w+ $/xms) {
2038      die "Error: bad format for TAG (alphanumeric string): $tag\n";
2039      }
2040
2041   control_syntax_comment($comment) or exit;
2042
2043   my $timestamp = time;
2044   $computer_db->{'tag'}{$tag} = {
2045      'comment'         => $comment,
2046      'create_time'     => $timestamp,
2047      'modify_time'     => $timestamp,
2048      };
2049   ipamdb_save("$COMPUTER_YAML", $computer_db);
2050   }
2051
2052#-------------------------------------------------------------------------------
2053
2054sub cmd_remove_tag {
2055   local @ARGV = @_;
2056
2057   my $help = get_cmd_name();
2058   my ($tag);
2059
2060   GetOptions(
2061      'tag|t=s' => \$tag,
2062      );
2063
2064   exit_on_error_option($help)
2065      if $tag eq '';
2066
2067   my $computer_db = ipamdb_load($COMPUTER_YAML);
2068
2069   $computer_db->{'tag'} ||= {};
2070   die "Error: TAG does not exist: $tag\n" if not exists $computer_db->{'tag'}{$tag};
2071
2072   # Test if some computer use this config
2073   LOOP_ON_SECTOR:
2074   for my $sector_current (keys %{$computer_db}) {
2075      next if $sector_current eq 'dset';
2076      next if $sector_current eq 'pool';
2077      next if $sector_current eq 'pxe';
2078      next if $sector_current eq 'tag';
2079      next if $sector_current eq 'version';
2080
2081      LOOP_ON_COMPUTER:
2082      for my $computer (@{$computer_db->{$sector_current}}) {
2083         my ($mac_address, $attribute) = %{$computer};
2084
2085         if (exists $attribute->{'tag'}) {
2086            my $hostname = $attribute->{'hostname'};
2087            die "Error: computer still use this TAG: $hostname.$sector_current $mac_address\n" if $tag eq $attribute->{'tag'};
2088            }
2089         }
2090      }
2091
2092   delete $computer_db->{'tag'}{$tag};
2093   ipamdb_save("$COMPUTER_YAML", $computer_db);
2094   }
2095
2096#--------------------------------------------------------------------------------
2097
2098sub cmd_show_tag {
2099   local @ARGV = @_;
2100
2101   my ($no_header);
2102
2103   GetOptions(
2104      'no-header|H' => \$no_header,
2105      );
2106
2107   my $computer_db = ipamdb_load($COMPUTER_YAML);
2108
2109   printf "%-12s %s\n", 'TAG', 'Comment' if not $no_header;
2110   LOOP_ON_TAG:
2111   for my $tag ( keys %{$computer_db->{'tag'}} ) {
2112      my $comment = $computer_db->{'tag'}{$tag}{'comment'};
2113
2114      printf "%-12s %s\n", $tag, $comment;
2115      }
2116   }
2117
2118#--------------------------------------------------------------------------------
2119# GLOBAL section
2120#--------------------------------------------------------------------------------
2121
2122sub cmd_upgrade_db {
2123   my $flag_change;
2124
2125   my $computer_db = ipamdb_load($COMPUTER_YAML);
2126
2127   LOOP_ON_SECTOR:
2128   for my $sector_current (keys %{$computer_db}) {
2129      next if $sector_current eq 'dset';
2130      next if $sector_current eq 'pool';
2131      next if $sector_current eq 'pxe';
2132      next if $sector_current eq 'tag';
2133      next if $sector_current eq 'version';
2134
2135      my @sectordb = @{$computer_db->{$sector_current}};
2136
2137      LOOP_ON_COMPUTER:
2138      for my $computer (@sectordb) {
2139         my ($mac_address, $attribute) = %{$computer};
2140         my $new_mac = normalize_mac_address($mac_address);
2141         print "perl -pi -e 's/$mac_address:/$new_mac:/' $COMPUTER_YAML\n" if "$mac_address" ne "$new_mac";
2142
2143         my $comment = $attribute->{'comment'};
2144         $comment =~ s/\s\s+/ /g and $flag_change++;
2145         $comment =~ s/^\s+\S//  and $flag_change++;
2146         $comment =~ s/\S\s+$//  and $flag_change++;
2147         $comment =~ s{^(\d\d\d\d)\/O(\d\/\d\d)}{$1/0$2} and $flag_change++;
2148         $comment =~ s{^(\d\d\d\d\/\d\d\/)O(\d)}{$1/0$2} and $flag_change++;
2149         $comment =~ s{^(\d\d\d\d)\/(\d\d)\/(\d\d)}{$1-$2-$3} and $flag_change++;
2150         if ($comment !~ m/^\d\d\d\d-\d\d-\d\d/) {
2151            print "# no date at beginning of comment $mac_address\n";
2152            }
2153
2154         $attribute->{'comment'} = $comment;
2155         }
2156      }
2157   print "# FLAG :$flag_change\n";
2158
2159   ipamdb_save("$COMPUTER_YAML", $computer_db) if $flag_change;
2160   }
2161
2162#--------------------------------------------------------------------------------
2163
2164sub cmd_show_sector {
2165   local @ARGV = @_;
2166
2167   my ($no_header);
2168
2169   GetOptions(
2170      'no-header|H' => \$no_header,
2171      );
2172
2173   my $computer_db = ipamdb_load($COMPUTER_YAML);
2174
2175   my $tb_computer = Text::Table->new(
2176     {align  => 'left',   align_title => 'left',   title => 'Sector'},
2177     {is_sep => 1,        body        => '  '},
2178     {align  => 'left',   align_title => 'left',   title => 'DNS-Extension:'},
2179     {is_sep => 1,        body        => '  '},
2180     {align  => 'left',   align_title => 'left',   title => 'Date'},
2181     {align  => 'left',   align_title => 'left',   title => 'Comment'},
2182     {align  => 'left',   align_title => 'left',   title => 'Category'},
2183     );
2184
2185   LOOP_ON_SECTOR:
2186   for my $sector_current (sort keys %{$computer_db}) {
2187      next if $sector_current eq 'dset';
2188      next if $sector_current eq 'pool';
2189      next if $sector_current eq 'pxe';
2190      next if $sector_current eq 'tag';
2191      next if $sector_current eq 'version';
2192
2193      $tb_computer->add($sector_current), next LOOP_ON_SECTOR if not exists $computer_db->{'dset'}{$sector_current};
2194
2195      my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime $computer_db->{'dset'}{$sector_current}{'modify_time'};
2196      $year += 1900;
2197      $mon++;
2198      my $date = sprintf '%04i-%02i-%02i', $year, $mon, $mday;
2199
2200      my $category;
2201      my $comment = $computer_db->{'dset'}{$sector_current}{'comment'};
2202      $comment =~ s/^\d\d\d\d-\d\d-\d\d\s//;
2203      $comment =~ s/\s+(\(\w+\))$// and $category = $1;
2204
2205      $tb_computer->add($sector_current,
2206         $computer_db->{'dset'}{$sector_current}{'dns_extension'},
2207         $date,
2208         $comment,
2209         $category,
2210         );
2211      }
2212
2213   print $tb_computer->title(),
2214         $tb_computer->rule('-') if not $no_header;
2215   print $tb_computer->body();
2216   }
2217
2218#--------------------------------------------------------------------------------
2219
2220sub cmd_search_mac {
2221   local @ARGV = @_;
2222
2223   my $help = get_cmd_name();
2224   my ($mac);
2225
2226   GetOptions(
2227      'mac|m=s' => \$mac,
2228      );
2229
2230   exit_on_error_option($help)
2231      if $mac eq '';
2232
2233   $mac = normalize_mac_address($mac);
2234
2235   my $computer_db = ipamdb_load($COMPUTER_YAML);
2236
2237   control_syntax_mac_address($mac) or exit;
2238
2239   LOOP_ON_SECTOR:
2240   for my $sector_current (keys %{$computer_db}) {
2241      next if $sector_current eq 'dset';
2242      next if $sector_current eq 'pool';
2243      next if $sector_current eq 'pxe';
2244      next if $sector_current eq 'tag';
2245      next if $sector_current eq 'version';
2246
2247      my @sectordb = @{$computer_db->{$sector_current}};
2248
2249      LOOP_ON_COMPUTER:
2250      for my $computer (@sectordb) {
2251         my ($mac_address, $attribute) = %{$computer};
2252
2253         next LOOP_ON_COMPUTER if $mac_address ne $mac;
2254
2255         my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime $attribute->{'modify_time'};
2256         $year += 1900;
2257         $mon++;
2258         my $date = sprintf '%04i-%02i-%02i', $year, $mon, $mday;
2259
2260         my $comment = $attribute->{'comment'};
2261         $comment =~ s/^\d\d\d\d-\d\d-\d\d\s//;
2262
2263         my $enable = $attribute->{'enabled'};
2264         if (exists $attribute->{'pxe_config'}) {
2265            $enable .= '/' . $attribute->{'pxe_config'};
2266            }
2267         if (exists $attribute->{'tag'}) {
2268            $enable .= ':' . $attribute->{'tag'};
2269            }
2270
2271         printf "%-30s  %-20s %17s %9s %3s %10s %s\n",
2272            $attribute->{'hostname'} . '.' . $sector_current,
2273            $attribute->{'ip'},
2274            $mac_address,
2275            $attribute->{'address_type'},
2276            $enable,
2277            $date,
2278            $comment;
2279         }
2280      }
2281   }
2282
2283#--------------------------------------------------------------------------------
2284#Nom: show
2285#Description: liste les machines à partir du fichier YAML par nom de domaine.
2286
2287sub cmd_show_host {
2288   my %ipdb = ();
2289
2290   my $computer_db = ipamdb_load($COMPUTER_YAML);
2291
2292   my $tb_computer = Text::Table->new(
2293     {align  => 'left',   align_title => 'left',   title => 'Hostname.Sector'},
2294     {is_sep => 1,        body        => '  '},
2295     {align  => 'left',   align_title => 'left',   title => 'IPv4-Address'},
2296     {is_sep => 1,        body        => '  '},
2297     {align  => 'center', align_title => 'center', title => 'MAC-Address'},
2298     {is_sep => 1,        body        => '  '},
2299     {align  => 'right',  align_title => 'right',  title => 'Type'},
2300     {align  => 'right',  align_title => 'right',  title => 'Status'},
2301     {is_sep => 1,        body        => '  '},
2302     {align  => 'left',   align_title => 'left',   title => 'Date'},
2303     {align  => 'left',   align_title => 'left',   title => 'Comment'},
2304     );
2305
2306  LOOP_ON_SECTOR:
2307   for my $sector_current (sort keys %{$computer_db}) {
2308      next if $sector_current eq 'dset';
2309      next if $sector_current eq 'pool';
2310      next if $sector_current eq 'pxe';
2311      next if $sector_current eq 'tag';
2312      next if $sector_current eq 'version';
2313
2314      my @sectordb = @{$computer_db->{$sector_current}};
2315
2316      LOOP_ON_COMPUTER:
2317      for my $computer (@sectordb) {
2318         my ($mac_address, $attribute) = %{$computer};
2319         my $ip = $attribute->{'ip'};
2320
2321         if ($ip =~ m/$DDT::RE::IPv4_ADDRESS/xms) {
2322            if ( not exists $ipdb{$ip} ) {
2323               $ipdb{$ip} = {
2324                  'mac_address'  => $mac_address,
2325                  %{$attribute},
2326                  'sector'    => $sector_current,
2327                  };
2328               }
2329            else {
2330               print {*STDERR} "# Warning: $ip already exists in the database with MAC $mac_address!\n";
2331               }
2332            next LOOP_ON_COMPUTER;
2333            }
2334
2335         my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime $attribute->{'modify_time'};
2336         $year += 1900;
2337         $mon++;
2338         my $date = sprintf '%04i-%02i-%02i', $year, $mon, $mday;
2339
2340         my $comment = normalize_comment($attribute->{'comment'});
2341         $comment =~ s/^\d\d\d\d-\d\d-\d\d\s//;
2342
2343         my $enable = $attribute->{'enabled'};
2344         if (exists $attribute->{'pxe_config'}) {
2345            $enable .= '/' . $attribute->{'pxe_config'};
2346            }
2347         if (exists $attribute->{'tag'}) {
2348            $enable .= ':' . $attribute->{'tag'};
2349            }
2350
2351         #printf "%-30s  %-20s %17s %9s %3s %10s %s\n",
2352         $tb_computer->add(
2353            $attribute->{'hostname'} . '.' . $sector_current,
2354            $ip,
2355            $mac_address,
2356            $attribute->{'address_type'},
2357            $enable,
2358            $date,
2359            $comment,
2360            );
2361         }
2362      #print "\n# *** List of pool computers in the sector: $sector_current ***\n";
2363      }
2364
2365   #print "\n# *** List of computers ordered by IP and sector ***\n";
2366   LOOP_ON_IP_ADDRESS:
2367   foreach my $ip (Net::Netmask::sort_by_ip_address(keys %ipdb)) {
2368      my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime $ipdb{$ip}->{'modify_time'};
2369      $year += 1900;
2370      $mon++;
2371      my $date = sprintf '%04i-%02i-%02i', $year, $mon, $mday;
2372
2373      my $comment =$ipdb{$ip}->{'comment'};
2374      $comment =~ s/^\d\d\d\d-\d\d-\d\d\s//;
2375
2376      my $enable = $ipdb{$ip}->{'enabled'};
2377      if (exists $ipdb{$ip}->{'pxe_config'}) {
2378         $enable .= '/' . $ipdb{$ip}->{'pxe_config'};
2379         }
2380      if (exists $ipdb{$ip}->{'tag'}) {
2381         $enable .= ':' . $ipdb{$ip}->{'tag'};
2382         }
2383
2384      #printf "%-30s %-20s %17s %9s %3s %10s %s\n",
2385      $tb_computer->add(
2386         $ipdb{$ip}->{'hostname'} . '.' . $ipdb{$ip}->{'sector'},
2387         $ip,
2388         normalize_mac_address($ipdb{$ip}->{'mac_address'}),
2389         $ipdb{$ip}->{'address_type'},
2390         $enable,
2391         $date,
2392         $comment
2393         );
2394      }
2395
2396   print $tb_computer->title();
2397   print $tb_computer->rule('-');
2398   print $tb_computer->body();
2399   }
2400
2401#-------------------------------------------------------------------------------
2402#Nom: cmd_generate_dhcp_file
2403#Description: génère les fichiers de configuration des machines et des pools du dhcp
2404
2405sub cmd_generate_dhcp_file {
2406   backup_database();
2407
2408   my $computer_db = ipamdb_load($COMPUTER_YAML);
2409
2410   my %file_pool;
2411
2412   for my $sector_current (keys %{$computer_db}) {
2413      next if $sector_current eq 'dset';
2414      next if $sector_current eq 'pool';
2415      next if $sector_current eq 'pxe';
2416      next if $sector_current eq 'tag';
2417      next if $sector_current eq 'version';
2418
2419      open FILE_VLAN, '>', "$FOLDER_GEN_DHCP/$sector_current";
2420      my @sectordb = @{$computer_db->{$sector_current}};
2421      for my $value (@sectordb) {
2422         ALL_MAC_ADDRESS:
2423         for my $mac_addres (keys %{$value}) {
2424            #host pcdavoust {  deny-unknown-clients;
2425            #hardware ethernet 0:6:5b:b8:13:d1;
2426            #fixed-address 194.254.66.72;
2427            #}
2428
2429            my $hostname     = $value->{$mac_addres}{'hostname'};
2430            my $ip           = $value->{$mac_addres}{'ip'};
2431            my $comment      = $value->{$mac_addres}{'comment'};
2432            my $address_type = $value->{$mac_addres}{'address_type'};
2433            my $enabled      = $value->{$mac_addres}{'enabled'};
2434            my $tags         = $value->{$mac_addres}{'tag'} || 'universal';
2435
2436            my $buffer;
2437            if ($address_type eq 'dhcp') {
2438               if ($enabled eq 'yes') {
2439                  $buffer  = "host $hostname {\n"; # deny-unknown-clients;
2440                  $buffer .= "   hardware ethernet $mac_addres;\n";
2441                  $buffer .= "   fixed-address $ip;\n";
2442
2443                  if (exists $value->{$mac_addres}{'pxe_config'}) {
2444                     my $pxe_config     = $value->{$mac_addres}{'pxe_config'};
2445                     my $ip_next_server = $computer_db->{'pxe'}{$pxe_config}{'ip_next_server'};
2446                     my $filename       = $computer_db->{'pxe'}{$pxe_config}{'filename'};
2447                     $buffer .= "   next-server $ip_next_server;\n";
2448                     $buffer .= "   filename \"$filename\";\n";
2449                     }
2450                  $buffer .= "   #comment: $comment\n";
2451                  $buffer .= "   }\n";
2452                  $buffer .= "\n";
2453
2454                  for my $tag (split/,/, $tags) {
2455                     $file_pool{"tag-$tag"} ||= [];
2456                     push @{$file_pool{"tag-$tag"}}, "subclass \"tag-$tag\" 1:$mac_addres; # $comment\n";
2457                     }
2458                  }
2459               else {
2460                  $buffer  = "#host $hostname {\n"; # deny-unknown-clients;
2461                  $buffer .= "#   hardware ethernet $mac_addres;\n";
2462                  $buffer .= "#   fixed-address $ip;\n";
2463                  $buffer .= "#   comment: $comment \n";
2464                  $buffer .= "#   }\n";
2465                  $buffer .= "\n";
2466                  }
2467               print FILE_VLAN $buffer;
2468               }
2469            elsif ($address_type eq 'pool-dhcp') {
2470               #--- Génère les fichiers pool dhcp ---#
2471               for my $current_pool (keys %{$computer_db->{'pool'}}) {
2472                  next if $current_pool ne $ip;
2473
2474                  if ($enabled eq 'yes') {
2475                     $buffer = "subclass \"$current_pool\" 1:$mac_addres; # $comment\n";
2476
2477                     for my $tag (split/,/, $tags) {
2478                        $file_pool{"tag-$tag"} ||= [];
2479                        push @{$file_pool{"tag-$tag"}}, "subclass \"tag-$tag\" 1:$mac_addres; # $comment\n";
2480                        }
2481                     }
2482                  else {
2483                     $buffer = "#subclass \"$current_pool\" 1:$mac_addres; # $comment\n";
2484                     }
2485
2486                  my $current_pool_file_name = $computer_db->{'pool'}{$current_pool}{'file'};
2487
2488                  $file_pool{$current_pool_file_name} ||= [];
2489                  push @{$file_pool{$current_pool_file_name}}, $buffer;
2490                  }
2491               }
2492            }
2493         }
2494
2495      close FILE_VLAN;
2496
2497      for my $file_name (keys %file_pool) {
2498         open FILE_POOL, '>', "$FOLDER_GEN_DHCP/$file_name";
2499         print FILE_POOL @{$file_pool{$file_name}};
2500         close FILE_POOL;
2501         }
2502      }
2503      print "Copy DHCP files from $FOLDER_GEN_DHCP to /etc/dhcp/include/\n";
2504      exec $SCRIPT_UPDATE;
2505   }
2506
2507#-------------------------------------------------------------------------------
2508#Nom: cmd_generate_dns_file
2509#Description: génère les fichiers d'enregistrements DNS
2510
2511sub cmd_generate_dns_file {
2512   local @ARGV = @_;
2513
2514   my $help = get_cmd_name();
2515   my ($verbose);
2516
2517   GetOptions(
2518      'verbose|v' => \$verbose,
2519      );
2520
2521   my $buffer_fwd;
2522   my $buffer_rev;
2523   my $pool_domain;
2524
2525   my $computer_db = ipamdb_load($COMPUTER_YAML);
2526
2527   for my $sector_current (keys %{$computer_db}) {
2528      next if $sector_current eq 'dset';
2529      next if $sector_current eq 'pool';
2530      next if $sector_current eq 'pxe';
2531      next if $sector_current eq 'tag';
2532      next if $sector_current eq 'version';
2533
2534      if ($sector_current eq 'pool') {
2535         LOOP_ON_COMPUTER:
2536         for my $computer (@{$computer_db->{$sector_current}}) {
2537            for my $pool_name (keys %{$computer}) {
2538               $pool_domain = $computer->{$pool_name}->{'domain'}."\n";
2539               #print $computer->{$pool_name}->{'file'};
2540               chomp $pool_domain;
2541               open FILE_FORWARD_DNS, '>>', "$FOLDER_GEN_DNS/db.$pool_domain.fwd";
2542               open FILE_REVERSE_DNS, '>>', "$FOLDER_GEN_DNS/db.$pool_domain.rev";
2543               my @T_pool_ip = @{$computer->{$pool_name}->{'ip'}};
2544               for my $pool_ip (@T_pool_ip) {
2545                  my @T_split = split(/\./ , $pool_ip);
2546                  $buffer_fwd = sprintf "%-24s IN  A  %-15s ;\n", "$pool_name$T_split[3]", $pool_ip;
2547                  $buffer_rev = "$T_split[3]   IN PTR   $pool_name$T_split[3].$pool_domain.\n";
2548                  print FILE_FORWARD_DNS $buffer_fwd;
2549                  print FILE_REVERSE_DNS $buffer_rev;
2550                  }
2551               close FILE_FORWARD_DNS;
2552               close FILE_REVERSE_DNS;
2553               }
2554            }
2555         }
2556
2557      else {
2558         #--- Création du fichier non-reverse ---#
2559         open FILE_FORWARD_DNS, ">> $FOLDER_GEN_DNS/db.$sector_current.fwd";
2560         open FILE_REVERSE_DNS, ">> $FOLDER_GEN_DNS/db.$sector_current.rev";
2561
2562         my @sectordb = @{$computer_db->{$sector_current}};
2563
2564         LOOP_ON_COMPUTER:
2565         for my $computer (@sectordb) {
2566            my ($mac_address, $attribute) = %{$computer};
2567
2568            #host pcdavoust {  deny-unknown-clients;
2569            #hardware ethernet 0:6:5b:b8:13:d1;
2570            #fixed-address 194.254.66.72;
2571            #}
2572
2573            my $hostname     = $attribute->{'hostname'};
2574            my $ip           = $attribute->{'ip'};
2575            my $comment      = $attribute->{'comment'};
2576            my $address_type = $attribute->{'address_type'};
2577            my $enabled      = $attribute->{'enabled'};
2578
2579            next LOOP_ON_COMPUTER if not (($address_type eq 'dhcp') or ($address_type eq 'static'));
2580
2581            my $dns_domain = $sector_current;
2582            if (exists $computer_db->{'dset'}{$sector_current}) {
2583               $dns_domain = $computer_db->{'dset'}{$sector_current}{'dns_extension'};
2584               }
2585
2586            my @ip_split = split /\./, $ip;
2587            if ($enabled eq 'yes') {
2588               if (exists $attribute->{'dns_extension'}
2589                     and "$attribute->{'dns_extension'}" != "$dns_domain") {
2590                  print "A FAIRE\n";
2591                  }
2592               $buffer_fwd = sprintf "%-24s  IN A   %-15s ; %s\n", $hostname, $ip, $comment;
2593               $buffer_rev = sprintf "%3i    IN PTR %-15s\n", $ip_split[3], "$hostname.$dns_domain.";
2594               }
2595
2596            else {
2597               $buffer_fwd = sprintf ";%-24s IN A   %-15s ; %s\n", $hostname, $ip, $comment;
2598               $buffer_rev = sprintf ";%3i   IN PTR %-15s\n", $ip_split[3], "$hostname.$dns_domain.";
2599               }
2600            print FILE_REVERSE_DNS $buffer_rev;
2601            print FILE_FORWARD_DNS $buffer_fwd;
2602            }
2603         close FILE_REVERSE_DNS;
2604         close FILE_FORWARD_DNS;
2605         print "- DNS: db.$sector_current.fwd db.$sector_current.rev [CREATE].\n" if $verbose;
2606         print "  Ex : sort -k 4n -t . $FOLDER_GEN_DNS/db.$sector_current.fwd\n"     if $verbose;
2607         }
2608      }
2609   }
2610
2611#--------------------------------------------------------------------------------
2612
2613sub shell_command {
2614   my $cmd = shift;
2615
2616   require FileHandle;
2617   my $fh     = new FileHandle;
2618   my @result = ();
2619   open $fh, q{-|}, "LANG=C $cmd" or die "Can't exec $cmd\n";
2620   @result = <$fh>;
2621   close $fh;
2622   chomp @result;
2623   return @result;
2624   }
2625
2626#--------------------------------------------------------------------------------
2627
2628sub cmd_check_dns {
2629   local @ARGV = @_;
2630
2631   my $help = get_cmd_name();
2632   my ($opt_direct, $opt_reverse);
2633
2634   GetOptions(
2635      'direct|d'  => \$opt_direct,
2636      'reverse|r' => \$opt_reverse,
2637      );
2638
2639   my $computer_db = ipamdb_load($COMPUTER_YAML);
2640
2641   if ($opt_direct or not $opt_reverse) { # DDT to DNS check
2642      LOOP_ON_SECTOR:
2643      for my $sector_current (keys %{$computer_db}) {
2644         next if $sector_current eq 'dset';
2645         next if $sector_current eq 'pool';
2646         next if $sector_current eq 'pxe';
2647         next if $sector_current eq 'tag';
2648         next if $sector_current eq 'version';
2649
2650         my @sectordb = @{$computer_db->{$sector_current}};
2651
2652         LOOP_ON_COMPUTER:
2653         for my $computer (@sectordb) {
2654            my ($mac_address, $attribute) = %{$computer};
2655            #my $new_mac = normalize_mac_address($mac_address);
2656            my $ip = $attribute->{'ip'};
2657            next LOOP_ON_COMPUTER if not $ip =~ m/$DDT::RE::IPv4_ADDRESS/xms;
2658            next LOOP_ON_COMPUTER if $attribute->{'enabled'} eq 'no';
2659
2660            my $dns_hostname_fq = scalar gethostbyaddr(inet_aton($ip), AF_INET);
2661            my ($dns_hostname) = split /\./, $dns_hostname_fq;
2662
2663            if ($attribute->{'hostname'} ne $dns_hostname) {
2664               print "$mac_address ($sector_current) $ip - $dns_hostname / $attribute->{'hostname'} # $attribute->{'comment'}\n";
2665               next LOOP_ON_COMPUTER;
2666               }
2667
2668            my $packed_ip = scalar gethostbyname($dns_hostname_fq);
2669            if (defined $packed_ip) {
2670               my $ip_address = inet_ntoa($packed_ip);
2671               if ($ip ne $ip_address) {
2672                  print "Error: bad IP for reverse DNS on $dns_hostname_fq / $ip\n";
2673                  next LOOP_ON_COMPUTER;
2674                  }
2675               }
2676            }
2677         }
2678      }
2679
2680   if ($opt_reverse) {  # DNS to DDT check
2681      my %saw; # count for unique member
2682      my @dns_domain_list = sort grep !$saw{$_}++,
2683         map $computer_db->{'dset'}{$_}{'dns_extension'},
2684         grep exists($computer_db->{'dset'}{$_}{'dns_extension'}),
2685         keys $computer_db->{'dset'};
2686      LOOP_ON_DNS:
2687      for my $dns (@dns_domain_list) {
2688         LOOP_ON_IP:
2689         for (shell_command("host -t A -l $dns")) {
2690            # smtp2.legi.grenoble-inp.fr has address 194.254.67.37
2691            next if not m/has address/;
2692            next if not m/^(\w[\w-_\.]+\w)\s+has\saddress\s+(\d[\d\.]+\d)$/;
2693            my ($hostname_fq, $ip) = ($1, $2);
2694            control_syntax_ip($ip) or next LOOP_ON_IP;
2695            if (control_exist_ip($computer_db, $ip) == 1) {
2696               printf "Unkown IP: %-15s / %s\n", $ip, $hostname_fq;
2697               next LOOP_ON_IP;
2698               }
2699            }
2700         }
2701      }
2702   }
2703
2704#-------------------------------------------------------------------------------
2705#Nom: load_data_dhcp
2706#Description: permet de charger le fichier de données YAML via les fichiers de configuration
2707#             machines.
2708#            ATTENTION: LES COMMENTAIRES DU FICHIER DISPARAITRONT.
2709
2710sub load_data_dhcp {
2711   my ($sector, $input_file) = @_;
2712
2713   my $computer_db = ipamdb_load($COMPUTER_YAML);
2714
2715   my @T_mac;
2716   my @T_host;
2717   my @T_ip;
2718   my $cpt;
2719   open (FILE, "<$input_file");
2720   my @buffer = <FILE>;
2721   close(FILE);
2722
2723   for my $ligne (@buffer) {
2724      #--
2725      $ligne =~ s/#.*$//;
2726      $ligne =~ s/\s+/ /;
2727      $ligne =~ s/^\s+//;
2728      next if $ligne eq '';
2729
2730      if ($ligne =~ /^host /) {
2731         $cpt=0;
2732         my @T_split = split(/host\s+/, $ligne);
2733         @T_host = split(/ /, $T_split[1]);
2734         chomp($T_host[0]);
2735
2736         $cpt++;
2737         }
2738
2739      if ($ligne =~ /^*ethernet /) {
2740         $ligne =~ s/;//g;
2741         @T_mac = split(/ethernet\s+/, $ligne);
2742         chomp($T_mac[1]);
2743         $cpt++;
2744         }
2745
2746      if ($ligne =~ /^*address /) {
2747         $ligne =~ s/;//g;
2748         @T_ip = split(/address\s+/, $ligne);
2749         chomp($T_ip[1]);
2750
2751         $cpt++;
2752         }
2753
2754      if ($cpt == 3) {
2755         #   print "MAC $T_mac[1] HOST $T_host[0] IP $T_ip[1].\n";
2756         my $mac = $T_mac[1];
2757         my $hostname = $T_host[0];
2758         my $ip = $T_ip[1];
2759         $cpt = 0;
2760
2761         if ( control_exist_hostname($computer_db, $sector, $hostname) == 0 ) {
2762            print "Error: host already exist in sector $sector: $hostname\n";
2763            next;
2764            }
2765         control_syntax_mac_address($mac) or next;
2766         if ( control_exist_mac($computer_db, $mac) == 0) {
2767            print "Error: physical MAC address already exists: $mac\n";
2768            next;
2769            }
2770
2771         control_syntax_ip($ip) or next;
2772         if ( control_exist_ip($computer_db, $ip) == 0 ) {
2773            print "Error: IP address already exists: $ip\n";
2774            next;
2775            }
2776         my $timestamp = time;
2777         push @{$computer_db->{$sector}}, { $mac => {
2778            'hostname'     => $hostname,
2779            'ip'           => $ip,
2780            'address_type' => 'dhcp',
2781            'enabled'      => 'yes',
2782            'create_time'  => $timestamp,
2783            'modify_time'  => $timestamp,
2784            'alias'        =>  '',
2785            }};
2786         }
2787      }
2788   }
2789
2790#-------------------------------------------------------------------------------
2791#Nom: load_data_pool
2792#Description: permet de charger le fichier YAML via les fichiers de conf 'pool' du dhcp.
2793
2794sub load_data_pool {
2795   my ($sector, $input_file) = @_;
2796
2797   my @T_mac;
2798
2799   open (FILE, "<$input_file");
2800   my @buffer = <FILE>;
2801   close(FILE);
2802
2803   my $computer_db = ipamdb_load($COMPUTER_YAML);
2804
2805   for my $ligne (@buffer) {
2806      #--
2807      $ligne =~ s/#.*$//;
2808      $ligne =~ s/\s+/ /;
2809      $ligne =~ s/^\s+//;
2810      $ligne =~ s/;//g;
2811      $ligne =~ s/"//g;
2812      next if $ligne eq '';
2813
2814      if (($ligne =~ /^subclass/)) {
2815         my @T_split = split(/ / ,$ligne);
2816         my $pool = $T_split[1];
2817
2818         @T_mac = split(/:/ , $T_split[2]);
2819         my $mac = $T_mac[1].":".$T_mac[2].":".$T_mac[3].":".$T_mac[4].":".$T_mac[5].":".$T_mac[6];
2820         control_syntax_mac_address($mac) or next;
2821         if (control_exist_mac($computer_db, $mac) == 0) {
2822            print "Error: physical MAC address already exists: $mac\n";
2823            next;
2824            }
2825
2826         #--- cette partie teste si le pool existe.
2827         if (not exists $computer_db->{'pool'}{$pool}) {
2828            print "Error: create pool with create_pool command before load database: $pool\n";
2829            exit;
2830            }
2831
2832         if ($computer_db->{'pool'}{'domain'} eq $sector) {
2833            my $timestamp = time;
2834            push @{$computer_db->{$sector}}, { $mac => {
2835               'hostname'     => $pool,
2836               'ip'           => $pool,
2837               'address_type' => 'pool-dhcp',
2838               'enabled'      => 'yes',
2839               'create_time'  => $timestamp,
2840               'modify_time'  => $timestamp,
2841               }};
2842            }
2843         else {
2844            print "Ajout de la machine $mac [FAILED]\n";
2845            print "Error: the pool doesn't exists: $pool, for the domain: $sector\n";
2846            }
2847         }
2848      }
2849   }
2850
2851#-------------------------------------------------------------------------------
2852
2853sub load_data_file {
2854   my ($sector, $input_file, $type_file) = @_;
2855
2856   my $computer_db = ipamdb_load($COMPUTER_YAML);
2857
2858   #$computer_db
2859   if ($type_file eq 'dhcp') {
2860      load_data_dhcp($sector, $input_file);
2861      }
2862
2863   elsif ($type_file eq 'pool-dhcp') {
2864      load_data_pool($sector, $input_file);
2865      }
2866
2867   ipamdb_save("$COMPUTER_YAML", $computer_db);
2868   }
2869
2870#-------------------------------------------------------------------------------
2871
2872sub cmd_load_database {
2873   local @ARGV = @_;
2874
2875   my $help = get_cmd_name();
2876   my ($sector, $input_file, $type_file);
2877
2878   GetOptions(
2879      'sector|s|d=s'    => \$sector,
2880      'filename|f=s'    => \$input_file,
2881      'kind|k=s'        => \$type_file,
2882      );
2883
2884   exit_on_error_option($help)
2885      if $sector  eq ''
2886      or $input_file eq ''
2887      or $type_file  eq '';
2888
2889   load_data_file($sector, $input_file, $type_file);
2890   }
2891
2892#-------------------------------------------------------------------------------
2893#Nom: backup_database
2894#Description: sauvegarde et réinitialise les fichiers d'enregistrements DHCP.
2895
2896sub backup_database {
2897   my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime time;
2898   $year += 1900;
2899   $mon++;
2900   my $date = sprintf '%04i-%02i-%02i-%02i-%02i-%02i', $year, $mon, $mday, $hour, $min, $sec;
2901
2902   copy($COMPUTER_YAML, "$FOLDER_BACKUP/$COMPUTER_BASENAME-$date.conf") or die "Error: database copy backup failed: $!\n";
2903   }
2904
2905#-------------------------------------------------------------------------------
2906# HELP section
2907#-------------------------------------------------------------------------------
2908
2909#-------------------------------------------------------------------------------
2910#Nom: exit_on_error_option
2911#Description: messages d'aide des options pour les différentes commandes
2912
2913sub exit_on_error_option {
2914  my ($command) = @_;
2915
2916   if ($command eq 'add-dhcp') {
2917      print "List of options for command: $command\n";
2918      print " -s : sector attachment (mandatory). Example: -s legi-sector03\n";
2919      print " -h : computer hostname (mandatory if option -i != 'pool'). Example: -h info8pc154\n";
2920      print " -m : physical MAC address (mandatory). Example: -m 0F:58:AB:2A\n";
2921      print " -i : internet IP address (mandatory). Possible value: classical IP address or the keyword 'pool'\n";
2922      print " -p : name of the DHCP pool to which the machine belongs (mandatory if option -i == 'pool')\n";
2923      print " -c : comment (mandatory). Example: 2014-04-07 DELL Laptop 6400 - Olivier Toto (INFO)\n";
2924      print "Example:\n";
2925      print " ddt add-dhcp -h most1mc130 -s legi-sector03 -i 194.254.66.130 -m 00:17:F2:D3:2B:FF -c '2008-07-03 Mac Book Guillaume Balleyrac (MOST)\n";
2926      }
2927
2928   elsif ($command eq 'add-float') {
2929      print "List of options for command: $command\n";
2930      print " -s : sector attachment (mandatory)\n";
2931      print " -p : name of the DHCP pool to which the machine belongs (mandatory)\n";
2932      print " -m : physical MAC address (mandatory)\n";
2933      print " -c : comment (mandatory). Example: 2014-04-07 DELL Laptop 6400 - Olivier Toto (INFO)\n";
2934      print "Example:\n";
2935      print " ddt add-float -p pool-stagiaire -s legi-pool -i 192.168.10.1 -m 00:AB:1B:CC:AA:2F -c '2013-09-25 Dell OptiPlex 745 - Eric Goncalves (NRJ)\n";
2936      }
2937
2938   elsif ($command eq 'add-static') {
2939      print "List of options for command: $command\n";
2940      print " -s : sector attachment (mandatory)\n";
2941      print " -i : internet IP address (mandatory)\n";
2942      print " -h : computer hostname (mandatory)\n";
2943      print " -m : physical MAC address (mandatory)\n";
2944      print " -c : comment (mandatory). Example: 2014-04-07 DELL Laptop 6400 - Olivier Toto (INFO)\n";
2945      print "Example:\n";
2946      print " ddt add-static -h legipc1 -s legi-sector03 -i 192.168.10.1 -m 00:AB:1B:CC:AA:2F -c '2013-09-25 Dell OptiPlex 745 - Eric Goncalves (NRJ)\n";
2947      }
2948
2949   elsif ($command eq 'add-virtual') {
2950      print "List of options for command: $command\n";
2951      print " -s : sector attachment (mandatory)\n";
2952      print " -i : internet IP address (mandatory)\n";
2953      print " -h : computer hostname (mandatory)\n";
2954      print " -c : comment (mandatory). Example: 2014-04-07 DELL Laptop 6400 - Olivier Toto (INFO)\n";
2955      print "Example:\n";
2956      print " ddt add-virtual -h legipc1 -s legi-sector03 -i 192.168.10.1 -c '2013-09-25 Dell OptiPlex 745 - Eric Goncalves (NRJ)\n";
2957      }
2958
2959   elsif ($command eq 'add-alias') {
2960      print "List of options for command: $command\n";
2961      print " -s : sector attachment (mandatory)\n";
2962      print " -h : computer hostname (mandatory)\n";
2963      print " -a : computer alias name (mandatory)\n";
2964      }
2965
2966   elsif ($command eq 'create-sector') {
2967      print "List of options for command: $command\n";
2968      print " -s : new sector (mandatory)\n";
2969      print " -e : DNS domain name extension( mandatory). Example legi.grenoble-inp.fr\n";
2970      print " -c : comment (mandatory). Example: 2016-08-22 VLAN legi-261 (INFO)\n";
2971      print "Examples:\n";
2972      print " ddt create-sector -s legi-sector03 -e legi.grenoble-inp.fr -c '2016-08-22 VLAN legi-261 (INFO)'\n";
2973      }
2974
2975   elsif ($command eq 'create-pool') {
2976      print "List of options for command: $command\n";
2977      print " -p : name of the DHCP pool. Example: pool-legi-priv\n";
2978      print " -s : sector attachment for the pool. (sector attachment must exist in file $COMPUTER_BASENAME.conf). Example: legi-sector03\n";
2979      print " -f : configuration filename on the DHCP server for the pool\n";
2980      print " -i : adresse(s) IP ou plage d'IP. Séparateur d'adresses IP: ','. Séparateur de plage '-'\n";
2981      print "Examples:\n";
2982      print " ddt create-pool -p legi-pool1 -s legi-sector03 -f legi-pool-private -i 192.168.10.1,192.168.10.2,192.168.10.3\n";
2983      print " ddt create-pool -p legi-pool2 -s legi-sector03 -f legi-pool-public  -i 192.168.10.1-192.168.10.4\n";
2984      }
2985
2986   elsif ($command eq 'create-pxe') {
2987      print "List of options for command: $command\n";
2988      print " -b : name of the PXE/BOOTP configuration. Example: most\n";
2989      print " -n : internet IP address for the DHCP next-server.\n";
2990      print " -f : filename on TFTP server to load at boot\n";
2991      print " -c : comment (mandatory). Example: 2014-04-07 PXE Boot for CentOS (MOST)\n";
2992      }
2993
2994   elsif ($command eq 'remove-pxe') {
2995      print "List of options for command: $command\n";
2996      print " -b : name of the PXE/BOOTP configuration. Example: most\n";
2997      }
2998
2999   elsif ($command eq 'enable-pxe') {
3000      print "List of options for command: $command\n";
3001      print " -h : computer hostname (mandatory unless option -i)\n";
3002      print " -i : internet IP address (mandatory unless option -h)\n";
3003      print " -s : sector attachment (mandatory if option -h)\n";
3004      print " -b : name of the PXE/BOOTP configuration. Example: most\n";
3005      }
3006
3007   elsif ($command eq 'disable-pxe') {
3008      print "List of options for command: $command\n";
3009      print " -h : computer hostname (mandatory unless option -i)\n";
3010      print " -i : internet IP address (mandatory unless option -h)\n";
3011      print " -s : sector attachment (mandatory if option -h)\n";
3012      }
3013
3014   elsif ($command eq 'create-tag') {
3015      print "List of options for command: $command\n";
3016      print " -t : name of the TAG (mandatory). Example: restricted\n";
3017      print " -c : comment (mandatory). Example: 2014-04-07 tag restricted (INFO)\n";
3018      print "tag 'universal' is intrinsic\n";
3019      }
3020
3021   elsif ($command eq 'remove-tag') {
3022      print "List of options for command: $command\n";
3023      print " -b : name of the TAG. Example: restricted\n";
3024      }
3025
3026   elsif ($command eq 'change-mac') {
3027      print "List of options for command: $command\n";
3028      print " -s : sector attachment (mandatory). Example: -s legi-sector03\n";
3029      print " -h : computer hostname (mandatory unless option -i)\n";
3030      print " -i : internet IP address (mandatory unless option -h). Possible value: classical IP address or the keyword 'pool'\n";
3031      print " -m : physical MAC address (mandatory). Example: -m 0F:58:AB:2A:22:11\n";
3032      }
3033
3034   elsif ($command eq 'change-ip') {
3035      print "List of options for command: $command\n";
3036      print " -s : sector attachment (mandatory). Example: -s legi-sector03\n";
3037      print " -h : computer hostname (mandatory)\n";
3038      print " -i : new internet IP address (mandatory). Possible value: classical IP address\n";
3039      }
3040
3041   elsif ($command eq 'change-host') {
3042      print "List of options for command: $command\n";
3043      print " -s : sector attachment (mandatory). Example: -s legi-sector03\n";
3044      print " -i : internet IP address (mandatory). Possible value: classical IP address\n";
3045      print " -h : new computer hostname (mandatory)\n";
3046      print "It's not possible to change hostname for computer that belongs to a pool\n";
3047      }
3048
3049   elsif ($command eq 'change-comment') {
3050      print "List of options for command: $command\n";
3051      print " -s : sector attachment (mandatory). Example: -s legi-sector03\n";
3052      print " -m : physical MAC address (mandatory). Example: -m 0F:58:AB:2A:22:11\n";
3053      print " -c : new comment (mandatory)\n";
3054      }
3055
3056   elsif ($command eq 'change-sector') {
3057      print "List of options for command: $command\n";
3058      print " -s : new sector attachment (mandatory). Example: -s legi-sector03\n";
3059      print " -m : physical MAC address (mandatory). Example: -m 0F:58:AB:2A:22:11\n";
3060      print " -i : internet IP address (mandatory)\n";
3061      }
3062
3063   elsif ($command eq 'change-tag') {
3064      print "List of options for command: $command\n";
3065      print " -h : computer hostname (mandatory unless option -i or -m)\n";
3066      print " -s : sector attachment (mandatory). Example: -s legi-sector03\n";
3067      print " -i : internet IP address (mandatory unless option -h or -m)\n";
3068      print " -m : physical MAC address (mandatory unless option -h or -i, priority). Example: -m 0F:58:AB:2A:22:11\n";
3069      print " -t : list of tags separated by comma (mandatory). Example: -t internal,windows\n";
3070      }
3071
3072   elsif ($command eq 'load-database') {
3073      print "List of options for command: $command\n";
3074      print " -s : sector attachment\n";
3075      print " -f : input file in DHCP format\n";
3076      print " -k : possible cases (kind): dhcp, pool-dhcp, fix-address\n";
3077      }
3078
3079   elsif ($command eq 'enable-pc') {
3080      print "List of options for command: $command\n";
3081      print " -h : computer hostname (mandatory unless option -i)\n";
3082      print " -i : internet IP address (mandatory unless option -h)\n";
3083      print " -s : sector attachment (mandatory if option -h)\n";
3084      print "Examples:\n";
3085      print " ddt enable-pc -i 192.168.10.1\n";
3086      print " ddt enable-pc -s legi-sector03 -h kevinpc\n";
3087      }
3088
3089   elsif ($command eq 'enable-float') {
3090      print "List of options for command: $command\n";
3091      print " -m : physical MAC address (mandatory)\n";
3092      print " -p : name of the DHCP pool (mandatory)\n";
3093      }
3094
3095   elsif ($command eq 'disable-float') {
3096      print "List of options for command: $command\n";
3097      print " -m : physical MAC address (mandatory)\n";
3098      print " -p : name of the DHCP pool (mandatory)\n";
3099      }
3100
3101   elsif ($command eq 'disable-pc') {
3102      print "List of options for command: $command\n";
3103      print " -h : computer hostname (mandatory unless option -i)\n";
3104      print " -i : internet IP address (mandatory unless option -h)\n";
3105      print " -s : sector attachment (mandatory if option -h)\n";
3106      print "Examples:\n";
3107      print " ddt disable-pc -i 192.168.10.1\n";
3108      print " ddt disable-pc -s legi-sector03 -h kevinpc\n";
3109      }
3110
3111   elsif ($command eq 'del-pc') {
3112      print "List of options for command: $command\n";
3113      print " -s : sector attachment (mandatory)\n";
3114      print " -h : computer hostname (mandatory unless option -i)\n";
3115      print " -i : internet IP address (mandatory unless option -h)\n";
3116      }
3117
3118   elsif ($command eq 'del-float') {
3119      print "List of options for command: $command\n";
3120      print " -m : physical MAC address (mandatory)l\n";
3121      print " -p : name of the DHCP pool\n";
3122      }
3123
3124   elsif ($command eq 'search-mac') {
3125      print "List of options for command: $command\n";
3126      print " -m : physical MAC address (mandatory). Example: -m 0F:58:AB:2A:22:11\n";
3127      }
3128
3129   else {
3130      print "No help for command: $command\n";
3131      }
3132   exit;
3133   }
3134
3135#-------------------------------------------------------------------------------
3136
3137sub cmd_version {
3138
3139   print <<'END';
3140ddt - management of computer names and IP addresses
3141Copyright (C) 2006-2018, LEGI UMR 5519 / CNRS UGA G-INP, Grenoble, France
3142Main author Gabriel Moreau <Gabriel.Moreau(A)univ-grenoble-alpes.fr>
3143License GNU GPL version 2 or later and Perl equivalent
3144END
3145
3146   print "Database Version 1\n";
3147   print "Version $VERSION\n\n";
3148   print ' $Id: ddt 350 2018-09-13 15:49:24Z g7moreau $'."\n";
3149   return;
3150   }
3151
3152#-------------------------------------------------------------------------------
3153#Nom: usage
3154#Description: message d'aide sur les commandes du script
3155
3156sub cmd_help {
3157   print <<END;
3158ddt - management of computer names and IP addresses
3159
3160 ddt add-alias [--hostname|-h hostname] [--sector|-s|-d sector] [--alias|-a alias]
3161 ddt add-dhcp [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip] [--mac|-m mac] [--comment|-c comment]
3162 ddt add-float [--pool|-p pool] [--sector|-s|-d sector] [--mac|-m mac] [--comment|-c comment]
3163 ddt add-static [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip] [--mac|-m mac] [--comment|-c comment]
3164 ddt add-virtual [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip] [--comment|-c comment]
3165 ddt change-comment [--sector|-s|-d sector] [--mac|-m mac] [--comment|-c comment]
3166 ddt change-sector [--sector|-s|-d sector] [--ip|-i ip] [--mac|-m mac]
3167 ddt change-host [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip]
3168 ddt change-ip [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip]
3169 ddt change-mac [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip] [--mac|-m mac]
3170 ddt change-tag [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip] [--mac|-m mac] [--tag|-t tag]
3171 ddt check-dns [--direct] [--reverse]
3172 ddt create-sector [--sector|-s|-d sector] [--dns-extension|-e dns_extension] [--comment|-c comment]
3173 ddt create-pool [--pool|-p pool] [--sector|-s|-d sector] [--file-pool|-f file_pool] [--ipaddress-pool|-i ipaddress_pool]
3174 ddt create-pxe [--bootp|-b pxe_config] [--next-server|-n next_server] [--filename|-f filename] [--comment|-c comment]
3175 ddt create-tag [--tag|-t tag] [--comment|-c comment]
3176 ddt del-float [--pool|-p pool] [--mac|-m mac]
3177 ddt del-pc [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip]
3178 ddt disable-pc [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip]
3179 ddt disable-float [--pool|-p pool] [--mac|-m mac]
3180 ddt disable-pxe [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip]
3181 ddt enable-float [--pool|-p pool] [--mac|-m mac]
3182 ddt enable-pc [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip]
3183 ddt enable-pxe [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip] [--bootp|-b pxe_config]
3184 ddt gen-dhcp-file
3185 ddt gen-dns-file [--verbose]
3186 ddt help
3187 ddt load-database [--sector|-s|-d sector] [--filename|-f filename] [--kind|-k kind]
3188 ddt remove-pxe [--bootp|-b pxe_config]
3189 ddt remove-tag [--tag|-t tag]
3190 ddt search-mac [--mac|-m mac]
3191 ddt show-sector [--no-header|-H]
3192 ddt show
3193 ddt show-pool [--no-header|-H]
3194 ddt show-pxe [--no-header|-H]
3195 ddt show-tag [--no-header|-H]
3196 ddt version
3197
3198COMMANDS
3199
3200 * add-alias        : add an alias for a computer (like CNAME for the DNS)
3201 * add-dhcp         : add a computer with a fix DHCP IP or in a DHCP pool
3202 * add-float        : add a computer with an IP in a DHCP pool
3203 * add-static       : add a computer with a static IP
3204 * add-virtual      : add a virtual computer with a static IP but a virtual MAC (useful to declare float computer in DNS)
3205 * change-comment   : change the computer comment
3206 * change-sector : change the sector attachment for a computer
3207 * change-host      : change the computer hostname
3208 * change-ip        : change the computer IP address
3209 * change-mac       : change the computer physical MAC address
3210 * change-tag       : change the list of TAGs associated to a computer
3211 * check-dns        : check the DNS table for base IPs
3212 * create-sector : create a new sector
3213 * create-pool      : create a new pool for DHCP records
3214 * create-pxe       : create a new PXE/BOOTP configuration
3215 * create-tag       : create a new TAG
3216 * del-float        : remove a computer from a DHCP pool
3217 * del-pc           : remove a computer (DHCP or static IP) from the YAML database
3218 * disable-pc       : disable a computer (DHCP and/or DNS) (but keep it in the database)
3219 * disable-float    : disable a computer from a DHCP pool (but keep it in the database)
3220 * disable-pxe      : remove PXE/BOOTP configuration on a computer
3221 * enable-float     : enable a previous disable computer (DHCP and/or DNS)
3222 * enable-pc        : enable a previous disable computer (DHCP and/or DNS)
3223 * enable-pxe       : enable PXE/BOOTP configuration on a computer
3224 * gen-dhcp-file    : generate DHCP files for the isc DHCP server
3225 * gen-dns-file     : generate DNS files for the bind domain server
3226 * help             : this help
3227 * load-database    : load the YAML database (be careful)
3228 * remove-pxe       : remove a PXE/BOOTP configuration
3229 * remove-tag       : remove a TAG
3230 * search-mac       : search physical MAC address computer
3231 * show-sector   : list all sector group of computer
3232 * show             : list all computers
3233 * show-pool        : list all pool
3234 * show-pxe         : list PXE/BOOTP configuration
3235 * show-tag         : list all TAGs
3236 * version          : return program version
3237END
3238   return;
3239   }
3240
3241################################################################
3242# documentation
3243################################################################
3244
3245__END__
3246
3247=head1 NAME
3248
3249ddt - management of computer names and IP addresses
3250
3251
3252=head1 USAGE
3253
3254 ddt add-alias [--hostname|-h hostname] [--sector|-s|-d sector] [--alias|-a alias]
3255 ddt add-dhcp [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip] [--mac|-m mac] [--comment|-c comment]
3256 ddt add-float [--pool|-p pool] [--sector|-s|-d sector] [--mac|-m mac] [--comment|-c comment]
3257 ddt add-static [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip] [--mac|-m mac] [--comment|-c comment]
3258 ddt add-virtual [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip] [--comment|-c comment]
3259 ddt change-comment [--sector|-s|-d sector] [--mac|-m mac] [--comment|-c comment]
3260 ddt change-sector [--sector|-s|-d sector] [--ip|-i ip] [--mac|-m mac]
3261 ddt change-host [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip]
3262 ddt change-ip [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip]
3263 ddt change-mac [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip] [--mac|-m mac]
3264 ddt change-tag [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip] [--mac|-m mac] [--tag|-t tag]
3265 ddt check-dns [--direct] [--reverse]
3266 ddt create-sector [--sector|-s|-d sector] [--dns-extension|-e dns_extension] [--comment|-c comment]
3267 ddt create-pool [--pool|-p pool] [--sector|-s|-d sector] [--file-pool|-f file_pool] [--ipaddress-pool|-i ipaddress_pool]
3268 ddt create-pxe [--bootp|-b pxe_config] [--next-server|-n next_server] [--filename|-f filename] [--comment|-c comment]
3269 ddt create-tag [--tag|-t tag] [--comment|-c comment]
3270 ddt del-float [--pool|-p pool] [--mac|-m mac]
3271 ddt del-pc [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip]
3272 ddt disable-pc [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip]
3273 ddt disable-float [--pool|-p pool] [--mac|-m mac]
3274 ddt disable-pxe [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip]
3275 ddt enable-float [--pool|-p pool] [--mac|-m mac]
3276 ddt enable-pc [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip]
3277 ddt enable-pxe [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip] [--bootp|-b pxe_config]
3278 ddt gen-dhcp-file
3279 ddt gen-dns-file [--verbose]
3280 ddt help
3281 ddt load-database [--sector|-s|-d sector] [--filename|-f filename] [--kind|-k kind]
3282 ddt remove-pxe [--bootp|-b pxe_config]
3283 ddt remove-tag [--tag|-t tag]
3284 ddt search-mac [--mac|-m mac]
3285 ddt show-sector [--no-header|-H]
3286 ddt show
3287 ddt show-pool [--no-header|-H]
3288 ddt show-pxe [--no-header|-H]
3289 ddt show-tag [--no-header|-H]
3290 ddt version
3291
3292
3293=head1 DESCRIPTION
3294
3295DDT is an acronym for DHCP-DNS-Tools.
3296The previous command name was not C<ddt> but just C<dhcp-dns-tools>...
3297In practise, DDT is an IP Address Management (IPAM) service.
3298It has been used in the LEGI laboratory for over 10 years.
3299
3300The tool is quite effective and tries to keep things simple
3301but easily configurable for your site like a swiss army knife.
3302Everything is saved in a YAML database
3303and entries could be added, deleted, or modified by the command line.
3304
3305
3306=head1 COMMANDS
3307
3308=head2 add-alias
3309
3310 ddt add-alias [--hostname|-h hostname] [--sector|-s|-d sector] [--alias|-a alias]
3311
3312=head2 add-dhcp
3313
3314 ddt add-dhcp [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip] [--mac|-m mac] [--comment|-c comment]
3315
3316=head2 add-float
3317
3318 ddt add-float [--pool|-p pool] [--sector|-s|-d sector] [--mac|-m mac] [--comment|-c comment]
3319
3320=head2 add-static
3321
3322 ddt add-static [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip] [--mac|-m mac] [--comment|-c comment]
3323
3324=head2 add-virtual
3325
3326 ddt add-virtual [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip] [--comment|-c comment]
3327
3328=head2 change-comment
3329
3330 ddt change-comment [--sector|-s|-d sector] [--mac|-m mac] [--comment|-c comment]
3331
3332=head2 change-sector
3333
3334 ddt change-sector [--sector|-s|-d sector] [--ip|-i ip] [--mac|-m mac]
3335
3336=head2 change-host
3337
3338 ddt change-host [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip]
3339
3340=head2 change-ip
3341
3342 ddt change-ip [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip]
3343
3344=head2 change-mac
3345
3346 ddt change-mac [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip] [--mac|-m mac]
3347
3348=head2 change-tag
3349
3350 ddt change-tag [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip] [--mac|-m mac] [--tag|-t tag]
3351
3352=head2 check-dns
3353
3354 ddt check-dns [--direct] [--reverse]
3355
3356=head2 create-sector
3357
3358 ddt create-sector [--sector|-s|-d sector] [--dns-extension|-e dns_extension] [--comment|-c comment]
3359
3360=head2 create-pool
3361
3362 ddt create-pool [--pool|-p pool] [--sector|-s|-d sector] [--file-pool|-f file_pool] [--ipaddress-pool|-i ipaddress_pool]
3363
3364=head2 create-pxe
3365
3366 ddt create-pxe [--bootp|-b pxe_config] [--next-server|-n next_server] [--filename|-f filename] [--comment|-c comment]
3367
3368=head2 create-tag
3369
3370 ddt create-tag [--tag|-t tag] [--comment|-c comment]
3371
3372=head2 del-float
3373
3374 ddt del-float [--pool|-p pool] [--mac|-m mac]
3375
3376=head2 del-pc
3377
3378 ddt del-pc [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip]
3379
3380=head2 disable-pc
3381
3382 ddt disable-pc [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip]
3383
3384=head2 disable-float
3385
3386 ddt disable-float [--pool|-p pool] [--mac|-m mac]
3387
3388=head2 disable-pxe
3389
3390 ddt disable-pxe [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip]
3391
3392=head2 enable-float
3393
3394 ddt enable-float [--pool|-p pool] [--mac|-m mac]
3395
3396=head2 enable-pc
3397
3398 ddt enable-pc [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip]
3399
3400=head2 enable-pxe
3401
3402 ddt enable-pxe [--hostname|-h hostname] [--sector|-s|-d sector] [--ip|-i ip] [--bootp|-b pxe_config]
3403
3404=head2 gen-dhcp-file
3405
3406 ddt gen-dhcp-file
3407
3408=head2 gen-dns-file
3409
3410 ddt gen-dns-file [--verbose]
3411
3412=head2 help
3413
3414 ddt help
3415
3416=head2 load-database
3417
3418 ddt load-database [--sector|-s|-d sector] [--filename|-f filename] [--kind|-k kind]
3419
3420=head2 remove-pxe
3421
3422 ddt remove-pxe [--bootp|-b pxe_config]
3423
3424=head2 remove-tag
3425
3426 ddt remove-tag [--tag|-t tag]
3427
3428=head2 search-mac
3429
3430 ddt search-mac [--mac|-m mac]
3431
3432=head2 show-sector
3433
3434 ddt show-sector [--no-header|-H]
3435
3436=head2 show
3437
3438 ddt show
3439
3440=head2 show-pool
3441
3442 ddt show-pool [--no-header|-H]
3443
3444=head2 show-pxe
3445
3446 ddt show-pxe [--no-header|-H]
3447
3448=head2 show-tag
3449
3450 ddt show-tag [--no-header|-H]
3451
3452=head2 version
3453
3454 ddt version
3455
3456
3457=head1 AUTHORS
3458
3459Written by Gabriel Moreau <Gabriel.Moreau(A)univ-grenoble-alpes.fr>, Kevin Reverchon, Olivier De-Marchi - Grenoble - France
3460
3461
3462=head1 LICENSE AND COPYRIGHT
3463
3464License GNU GPL version 2 or later and Perl equivalent
3465
3466Copyright (C) 2006-2018, LEGI UMR 5519 / CNRS UGA G-INP, Grenoble, France
Note: See TracBrowser for help on using the repository browser.