source: trunk/ddt/ddt @ 352

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