source: trunk/ddt/ddt @ 340

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