source: trunk/ddt/ddt @ 329

Last change on this file since 329 was 329, checked in by g7moreau, 6 years ago
  • Change and operator (to strong) to comma ,
  • Property svn:executable set to *
  • Property svn:keywords set to Id
File size: 114.5 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.1');
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} "Syntax 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} "Syntax Error: No (SERVICE) at the end: $comment\n";
310      return 0;
311      }
312
313   if ($comment =~ m{\s\s}) {
314      print {*STDERR} "Syntax 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: Hostname already exist in domain set attachement $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: Hostname already exist in domain set attachement $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 attachement $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: Hostname already exist in domain set attachement $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 attachement $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: Hostname already exist in domain set attachement $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 attachement $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      my $computer_index = 0;
722      LOOP_ON_COMPUTER:
723      for my $computer (@domainsetdb) {
724         my ($mac_address, $attribute) = %{$computer};
725
726         $computer_index++, next LOOP_ON_COMPUTER if $attribute->{'ip'} ne $ip;
727
728         $attribute->{'modify_time'} = time;
729         $computer_db->{$domainset}[$computer_index] = { $mac => $attribute };
730         ipamdb_save("$COMPUTER_YAML", $computer_db);
731         print "Info: Update host $hostname MAC: $mac IP: $ip [OK]\n";
732         exit;
733         }
734      }
735   elsif ($hostname ne '') {
736      if ( control_exist_hostname($computer_db, $domainset, $hostname) == 1 ) {
737         die "Error: Unkown host: $hostname, in domain set: $domainset\n";
738         }
739      my @domainsetdb = @{$computer_db->{$domainset}};
740      my $computer_index = 0;
741      LOOP_ON_COMPUTER:
742      for my $computer (@domainsetdb) {
743         my ($mac_address, $attribute) = %{$computer};
744
745         $computer_index++, next LOOP_ON_COMPUTER if $attribute->{'hostname'} ne $hostname;
746
747         $attribute->{'modify_time'} = time;
748         $computer_db->{$domainset}[$computer_index] = { $mac => $attribute };
749         ipamdb_save("$COMPUTER_YAML", $computer_db);
750         print "Info: Update HOST: $hostname DOMAINSET: $domainset MAC: $mac IP: $attribute->{'ip'} [OK]\n";
751         exit;
752         }
753      }
754   }
755
756#-------------------------------------------------------------------------------
757#Nom: change_ip
758#Description: change l'adresse IP d'une machine en saisissant le nom de la machine
759#             et le domaine
760
761sub change_ip {
762   my ($hostname, $domainset, $ip) = @_;
763
764   my $computer_db = ipamdb_load($COMPUTER_YAML);
765
766   control_exist_domainset($computer_db, $domainset) or exit;
767   if ( control_exist_hostname($computer_db, $domainset, $hostname) == 1 ) {
768      die "Error: Unkown host: $hostname, in domain set: $domainset\n";
769      }
770   control_syntax_ip($ip) or exit;
771   control_exist_ip($computer_db, $ip) or die "Error: IP address already exist in domain set attachement $domainset: $ip\n";
772
773   my @domainsetdb = @{$computer_db->{$domainset}};
774
775   LOOP_ON_COMPUTER:
776   for my $computer (@domainsetdb) {
777      my ($mac_address, $attribute) = %{$computer};
778     
779      next LOOP_ON_COMPUTER if $attribute->{'hostname'} ne $hostname;
780 
781      if ($attribute->{'address_type'} eq 'pool-dhcp') {
782         die "Error: Host $hostname from domain set $domainset belongs to a a pool [FAILED]" .
783            " ... use 'del-float' command before";
784         }
785
786      $attribute->{'modify_time'} = time;
787      $attribute->{'ip'}          = $ip;
788      ipamdb_save("$COMPUTER_YAML", $computer_db);
789      print "Info: Update host $hostname MAC: $mac_address IP: $ip [OK]\n";
790      exit;
791      }
792   }
793
794#-------------------------------------------------------------------------------
795#Nom: change_host
796#Description: change le computer hostname en saisissant l'IP et le domaine
797
798sub change_host {
799   my ($hostname, $domainset, $ip) = @_;
800
801   my $computer_db = ipamdb_load($COMPUTER_YAML);
802
803   control_exist_domainset($computer_db, $domainset) or exit;
804   control_syntax_ip($ip)   or exit;
805   if ( control_exist_ip($computer_db, $ip) == 1 ) {
806      die "Error: Unkown IP address: $ip\n";
807      }
808   control_exist_hostname($computer_db, $domainset, $hostname) or die "Error: Hostname already exist in domain set attachement $domainset: $hostname\n";
809
810   my @domainsetdb = @{$computer_db->{$domainset}};
811
812   LOOP_ON_COMPUTER:
813   for my $computer (@domainsetdb) {
814      my ($mac_address, $attribute) = %{$computer};
815
816      next LOOP_ON_COMPUTER if $attribute->{'ip'} ne $ip;
817
818      $attribute->{'modify_time'} = time;
819      $attribute->{'hostname'}    = $hostname;
820      ipamdb_save("$COMPUTER_YAML", $computer_db);
821      print "Info: Update host $hostname MAC: $mac_address IP: $ip [OK]\n";
822      exit;
823      }
824
825   die "Error: Failed to update hostname $hostname [FAILED]\n" .
826      " ... no IP $ip belongs to the domain set $domainset\n";
827   }
828
829#--------------------------------------------------------------------------------
830
831sub cmd_change_mac {
832   local @ARGV = @_;
833
834   my $help = get_cmd_name();
835   my ($hostname, $domainset, $ip, $mac);
836
837   GetOptions(
838      'hostname|h=s'    => \$hostname,
839      'domainset|d=s'   => \$domainset,
840      'ip|i=s'          => \$ip,
841      'mac|m=s'         => \$mac,
842      );
843
844   ($hostname, $domainset) = split /\./, $hostname, 2 if $hostname =~ m/\./;
845   exit_on_error_option($help)
846      if $domainset  eq ''
847      or $mac        eq '';
848   exit_on_error_option($help)
849      if $hostname   ne ''
850      and $ip        ne '';
851
852   change_mac($hostname, $domainset, $ip, $mac);
853   }
854
855#--------------------------------------------------------------------------------
856
857sub cmd_change_ip {
858   local @ARGV = @_;
859
860   my $help = get_cmd_name();
861   my ($hostname, $domainset, $ip);
862
863   GetOptions(
864      'hostname|h=s'    => \$hostname,
865      'domainset|d=s'   => \$domainset,
866      'ip|i=s'          => \$ip,
867      );
868
869   ($hostname, $domainset) = split /\./, $hostname, 2 if $hostname =~ m/\./;
870   exit_on_error_option($help)
871      if $hostname   eq ''
872      or $domainset  eq ''
873      or $ip         eq '';
874
875   change_ip($hostname, $domainset, $ip);
876   }
877
878#--------------------------------------------------------------------------------
879
880sub cmd_change_host {
881   local @ARGV = @_;
882
883   my $help = get_cmd_name();
884   my ($hostname, $domainset, $ip);
885
886   GetOptions(
887      'hostname|h=s'    => \$hostname,
888      'domainset|d=s'   => \$domainset,
889      'ip|i=s'          => \$ip,
890      );
891
892   ($hostname, $domainset) = split /\./, $hostname, 2 if $hostname =~ m/\./;
893   exit_on_error_option($help)
894      if $hostname   eq ''
895      or $domainset  eq ''
896      or $ip         eq '';
897
898   change_host($hostname, $domainset, $ip);
899   }
900
901#--------------------------------------------------------------------------------
902
903sub cmd_change_comment {
904   local @ARGV = @_;
905
906   my $help = get_cmd_name();
907   my ($domainset, $mac, $comment);
908
909   GetOptions(
910      'domainset|d=s'   => \$domainset,
911      'mac|m=s'         => \$mac,
912      'comment|c=s'     => \$comment,
913      );
914
915   exit_on_error_option($help)
916      if $domainset  eq ''
917      or $mac        eq ''
918      or $comment    eq '';
919
920   $mac     = normalize_mac_address($mac);
921   $comment = normalize_comment($comment);
922
923   my $computer_db = ipamdb_load($COMPUTER_YAML);
924
925   control_exist_domainset($computer_db, $domainset)  or exit;
926   control_syntax_mac_address($mac)                   or exit;
927   control_syntax_comment($comment)                   or exit;
928
929   my @domainsetdb = @{$computer_db->{$domainset}};
930
931   LOOP_ON_COMPUTER:
932   for my $computer (@domainsetdb) {
933      my ($mac_address, $attribute) = %{$computer};
934
935      next LOOP_ON_COMPUTER if $mac_address ne $mac;
936
937      $attribute->{'modify_time'} = time;
938      $attribute->{'comment'}     = $comment;
939      ipamdb_save("$COMPUTER_YAML", $computer_db);
940      exit;
941      }
942   die "Error : Host $mac comment [FAILED]\n" .
943      " ... No MAC: $mac belongs to the domaine set $domainset.\n";
944   }
945
946#--------------------------------------------------------------------------------
947
948sub cmd_change_domainset {
949   local @ARGV = @_;
950
951   my $help = get_cmd_name();
952   my ($domainset, $ip, $mac);
953
954   GetOptions(
955      'domainset|d=s'   => \$domainset,
956      'ip|i=s'          => \$ip,
957      'mac|m=s'         => \$mac,
958      );
959
960   exit_on_error_option($help)
961      if $domainset  eq ''
962      or $ip         eq ''
963      or $mac        eq '';
964
965   $mac = normalize_mac_address($mac);
966
967   my $computer_db = ipamdb_load($COMPUTER_YAML);
968
969   control_exist_domainset($computer_db, $domainset)   or exit;
970   control_syntax_ip($ip)                             or exit;
971   control_syntax_mac_address($mac)                   or exit;
972
973   LOOP_ON_DOMAINSET:
974   for my $domainset_current (keys %{$computer_db}) {
975      next if $domainset_current eq 'dset';
976      next if $domainset_current eq 'pool';
977      next if $domainset_current eq 'pxe';
978      next if $domainset_current eq 'tag';
979      next if $domainset_current eq 'version';
980
981      my @domainsetdb = @{$computer_db->{$domainset_current}};
982      my $computer_index = 0;
983      LOOP_ON_COMPUTER:
984      for my $computer (@domainsetdb) {
985         my ($mac_address, $attribute) = %{$computer};
986
987         $computer_index++, next LOOP_ON_COMPUTER if $mac_address ne $mac;
988         next LOOP_ON_DOMAINSET if $attribute->{'ip'} ne $ip;
989
990         $attribute->{'modify_time'} = time;
991         splice(@{$computer_db->{$domainset_current}}, $computer_index => 1);
992         push @{$computer_db->{$domainset}}, { $mac => $attribute };
993
994         ipamdb_save("$COMPUTER_YAML", $computer_db);
995         exit;
996         }
997      }
998   die "Error: Update of domain set $domainset [FAILED]\n" .
999      " ... MAC $mac and IP $ip don't exists in the database\n";
1000   }
1001
1002#--------------------------------------------------------------------------------
1003
1004sub cmd_change_tag {
1005   local @ARGV = @_;
1006
1007   my $help = get_cmd_name();
1008   my ($hostname, $domainset, $ip, $mac, $tags);
1009
1010   GetOptions(
1011      'hostname|h=s'    => \$hostname,
1012      'domainset|d=s'   => \$domainset,
1013      'ip|i=s'          => \$ip,
1014      'mac|m=s'         => \$mac,
1015      'tag|t=s'         => \$tags,
1016      );
1017
1018   ($hostname, $domainset) = split /\./, $hostname, 2 if $hostname =~ m/\./;
1019
1020   exit_on_error_option($help)
1021      if $domainset  eq ''
1022      or $tags       eq '';
1023   exit_on_error_option($help)
1024      if $mac        eq ''
1025      and $hostname  eq ''
1026      and $ip        eq '';
1027
1028   $mac = normalize_mac_address($mac);
1029
1030   my $computer_db = ipamdb_load($COMPUTER_YAML);
1031
1032   if ($tags !~ m/^ (?:\w+,)* \w+ $/xms) {
1033      die "Error: Bad format for tags (comma separated list): $tags\n";
1034      }
1035
1036   for my $tag (split/,/, $tags) {
1037      next if $tag eq 'universal';
1038      die "Error: TAG doesn't exist in the database. Create it before with create_tag: $tag\n" if not exists $computer_db->{'tag'}{$tag};
1039      }
1040
1041   control_exist_domainset($computer_db, $domainset) or exit;
1042
1043   $mac = get_mac_from_ip($computer_db, $domainset, $ip, $mac)             if $ip ne '';
1044   $mac = get_mac_from_hostname($computer_db, $domainset, $hostname, $mac) if $hostname ne '';
1045   control_syntax_mac_address($mac) or exit;
1046
1047   LOOP_ON_COMPUTER:
1048   for my $computer (@{$computer_db->{$domainset}}) {
1049      my ($mac_address, $attribute) = %{$computer};
1050
1051      next LOOP_ON_COMPUTER if $mac_address ne $mac;
1052
1053      $attribute->{'tag'}         = $tags;
1054      $attribute->{'modify_time'} = time;
1055
1056      delete $attribute->{'tag'} if $tags eq 'universal';
1057      ipamdb_save("$COMPUTER_YAML", $computer_db);
1058      exit;
1059      }
1060   print "Mise à jour du commentaire de la machine [FAILED]\n";
1061   print "L'adresse MAC: $mac n'existe pas dans le domaine: $domainset.\n";
1062   }
1063
1064#-------------------------------------------------------------------------------
1065# ACTIVATION section
1066#-------------------------------------------------------------------------------
1067
1068#-------------------------------------------------------------------------------
1069#Nom: disable_pc
1070#Description: désactive une machine (du DHCP ou en IP statique, et du DNS) (champs enabled=non)
1071
1072sub disable_pc {
1073   my ($hostname, $domainset, $ip) = @_;
1074
1075   my $computer_db = ipamdb_load($COMPUTER_YAML);
1076
1077   if ($ip ne '') { # disable by IP
1078      control_syntax_ip($ip);
1079      if ( control_exist_ip($computer_db, $ip) == 1 ) {
1080         die "Error: Unkown IP address: $ip [FAILED]\n";
1081         }
1082
1083      for my $domainset_current (keys %{$computer_db}) {
1084         next if $domainset_current eq 'dset';
1085         next if $domainset_current eq 'pool';
1086         next if $domainset_current eq 'pxe';
1087         next if $domainset_current eq 'tag';
1088         next if $domainset_current eq 'version';
1089
1090         my @domainsetdb = @{$computer_db->{$domainset_current}};
1091         LOOP_ON_COMPUTER:
1092         for my $computer (@domainsetdb) {
1093            my ($mac_address, $attribute) = %{$computer};
1094
1095            next LOOP_ON_COMPUTER if $attribute->{'ip'} ne $ip;
1096
1097            if ($attribute->{'enabled'} eq 'no') {
1098               print "Info: IP $ip from domain set $domainset_current is already disable [OK]" .
1099                  " ... Status: $attribute->{'enabled'}\n";
1100               exit;
1101               }
1102
1103            my $timestamp = time;
1104            $attribute->{'modify_time'} = $timestamp;
1105            $attribute->{'enabled'}     = 'no';
1106            ipamdb_save("$COMPUTER_YAML", $computer_db);
1107            print "Info: Disabling IP $ip from domain set $domainset_current [OK]" .
1108               " ... Status: $attribute->{'enabled'}\n";
1109            exit;
1110            }
1111         }
1112      }
1113   else { # disable by Hostname
1114      control_exist_domainset($computer_db, $domainset);
1115      if ( control_exist_hostname($computer_db, $domainset, $hostname) == 1 ) {
1116         die "Error: Unkown host: $hostname, in domain set: $domainset [FAILED]\n";
1117         }
1118
1119      LOOP_ON_COMPUTER:
1120      for my  $computer (@{$computer_db->{$domainset}}) {
1121         my ($mac_address, $attribute) = %{$computer};
1122
1123         next LOOP_ON_COMPUTER if $attribute->{'hostname'} ne $hostname;
1124
1125         if ($attribute->{'address_type'} eq 'pool-dhcp') {
1126            die "Error: Host $hostname from domain set $domainset belongs to a a pool [FAILED]" .
1127               " ... use 'disable-float' command instead";
1128            }
1129
1130         if ($attribute->{'enabled'} eq 'no') {
1131            print "Info: Host $hostname from domain set $domainset is already disable [OK]" .
1132               " ... Status: $attribute->{'enabled'}\n";
1133            exit;
1134            }
1135
1136         my $timestamp = time;
1137         $attribute->{'modify_time'} = $timestamp;
1138         $attribute->{'enabled'}     = 'no';
1139         ipamdb_save("$COMPUTER_YAML", $computer_db);
1140         print "Info: Disabling host $hostname from domain set $domainset [OK]" .
1141            " ... Status: $attribute->{'enabled'}\n";
1142         exit;
1143         }
1144      }
1145   }
1146
1147#-------------------------------------------------------------------------------
1148
1149sub disable_float {
1150   my ($pool, $mac) = @_;
1151
1152   my $computer_db = ipamdb_load($COMPUTER_YAML);
1153
1154   my $computer_index;
1155   if ( control_exist_mac($computer_db, $mac) == 1 ) {
1156      die "Error: Unkown physical MAC address: $mac [FAILED]\n";
1157      }
1158
1159   for my $domainset_current (keys %{$computer_db}) {
1160      next if $domainset_current eq 'dset';
1161      next if $domainset_current eq 'pool';
1162      next if $domainset_current eq 'pxe';
1163      next if $domainset_current eq 'tag';
1164      next if $domainset_current eq 'version';
1165
1166      my @domainsetdb = @{$computer_db->{$domainset_current}};
1167
1168      LOOP_ON_COMPUTER:
1169      for my $computer (@domainsetdb) {
1170         my ($mac_address, $attribute) = %{$computer};
1171         next LOOP_ON_COMPUTER if $mac_address ne $mac;
1172
1173         if ($attribute->{'ip'} eq $pool) {
1174            if ($attribute->{'enabled'} eq 'no') {
1175               print "Info: Host $mac from pool $pool is already disable [OK]" .
1176                  " ... Status: $attribute->{'enabled'}\n";
1177               exit;
1178               }
1179            my $timestamp = time;
1180            $attribute->{'modify_time'} = $timestamp;
1181            $attribute->{'enabled'}     = 'no';
1182            ipamdb_save("$COMPUTER_YAML", $computer_db);
1183            print "Info: Disabling host $mac from pool $pool [OK]" .
1184               " ... Status: $attribute->{'enabled'}\n";
1185            exit;
1186            }
1187         else {
1188            die "Error: Host disable $mac [FAILED]" .
1189               " ... The host $mac does not belong to the $pool pool.\n";
1190            }
1191         }
1192      }
1193   }
1194
1195#-------------------------------------------------------------------------------
1196#Nom: enable_pc
1197#Description: active une machine désactivée(du DHCP ou en IP statique, et du DNS) (champs enabled=non)
1198
1199sub enable_pc {
1200   my ($hostname, $domainset, $ip) = @_;
1201
1202   my $computer_db = ipamdb_load($COMPUTER_YAML);
1203
1204   control_exist_domainset($computer_db, $domainset) or exit;
1205
1206   if ($ip ne '') { # enable by IP
1207      control_syntax_ip($ip);
1208      if ( control_exist_ip($computer_db, $ip) == 1 ) {
1209         print "Error: Unkown IP address: $ip\n";
1210         exit;
1211         }
1212
1213      for my $domainset_current (keys %{$computer_db}) {
1214         next if $domainset_current eq 'dset';
1215         next if $domainset_current eq 'pool';
1216         next if $domainset_current eq 'pxe';
1217         next if $domainset_current eq 'tag';
1218         next if $domainset_current eq 'version';
1219
1220         my @domainsetdb = @{$computer_db->{$domainset_current}};
1221
1222         LOOP_ON_COMPUTER:
1223         for my $computer (@domainsetdb) {
1224            my ($mac_address, $attribute) = %{$computer};
1225            if ($attribute->{'ip'} eq $ip) {
1226
1227               if ($attribute->{'enabled'} eq 'yes') {
1228                  print "Info: IP $ip belongs to domain set $domainset is already enable [OK]" .
1229                     " ... Status: $attribute->{'enabled'}\n";
1230                  exit;
1231                  }
1232
1233               my $timestamp = time;
1234               $attribute->{'modify_time'} = $timestamp;
1235               $attribute->{'enabled'}     = 'yes';
1236               ipamdb_save("$COMPUTER_YAML", $computer_db);
1237               print "Info: IP $ip is now enable [OK]" .
1238                  " ... Status: $attribute->{'enabled'}\n";
1239               exit;
1240               }
1241            }
1242         }
1243      }
1244   else { # enable by Hostname
1245      if ( control_exist_hostname($computer_db, $domainset, $hostname) == 1 ) {
1246         die "Error: Unkown host: $hostname, in domain set: $domainset\n";
1247         }
1248
1249      LOOP_ON_COMPUTER:
1250      for my $computer (@{$computer_db->{$domainset}}) {
1251         my ($mac_address, $attribute) = %{$computer};
1252         next LOOP_ON_COMPUTER if $attribute->{'hostname'} ne $hostname;
1253
1254         if ($attribute->{'address_type'} eq 'pool-dhcp') {
1255            die "Error: Host $hostname from domain set $domainset belongs to a a pool [FAILED]" .
1256               " ... use 'enable-float' command instead";
1257            }
1258
1259         if ($attribute->{'enabled'} eq 'yes') {
1260            print "Info: Host $hostname belongs to domain set $domainset is already enable [OK]" .
1261               " ... Status: $attribute->{'enabled'}\n";
1262            exit;
1263            }
1264
1265         my $timestamp = time;
1266         $attribute->{'modify_time'} = $timestamp;
1267         $attribute->{'enabled'}     = 'yes';
1268         ipamdb_save("$COMPUTER_YAML", $computer_db);
1269         print "Info: Host $hostname is now enable [OK]" .
1270            " ... Status: $attribute->{'enabled'}\n";
1271         exit;
1272         }
1273      }
1274   }
1275
1276#-------------------------------------------------------------------------------
1277
1278sub enable_float {
1279   my ($pool, $mac) = @_;
1280
1281   my $computer_db = ipamdb_load($COMPUTER_YAML);
1282
1283   if ( control_exist_mac($computer_db, $mac) == 1 ) {
1284      die "Error: Unkown physical MAC address: $mac [FAILED]\n";
1285      }
1286
1287   for my $domainset_current (keys %{$computer_db}) {
1288      next if $domainset_current eq 'dset';
1289      next if $domainset_current eq 'pool';
1290      next if $domainset_current eq 'pxe';
1291      next if $domainset_current eq 'tag';
1292      next if $domainset_current eq 'version';
1293
1294      my @domainsetdb = @{$computer_db->{$domainset_current}};
1295
1296      LOOP_ON_COMPUTER:
1297      for my $computer (@domainsetdb) {
1298         my ($mac_address, $attribute) = %{$computer};
1299         next LOOP_ON_COMPUTER if $mac_address ne $mac;
1300
1301         if ($attribute->{'ip'} ne $pool) {
1302            die "Error: Host enable $mac [FAILED]" .
1303               " ... The host $mac does not belong to the $pool pool.\n";
1304            }
1305
1306         if ($attribute->{'enabled'} eq 'yes') {
1307            print "Info: Host $mac from pool $pool is already enable [OK]" .
1308               " ... Status: $attribute->{'enabled'}\n";
1309            exit;
1310            }
1311
1312         my $timestamp = time;
1313         $attribute->{'modify_time'} = $timestamp;
1314         $attribute->{'enabled'}     = 'yes';
1315         ipamdb_save("$COMPUTER_YAML", $computer_db);
1316         print "Info: Enabling host $mac from pool $pool [OK]" .
1317            " ... Status: $attribute->{'enabled'}\n";
1318         exit;
1319         }
1320      }
1321   }
1322
1323#-------------------------------------------------------------------------------
1324
1325sub cmd_enable_pc {
1326   local @ARGV = @_;
1327
1328   my $help = get_cmd_name();
1329   my ($hostname, $domainset, $ip);
1330
1331   GetOptions(
1332      'hostname|h=s'    => \$hostname,
1333      'domainset|d=s'   => \$domainset,
1334      'ip|i=s'          => \$ip,
1335      );
1336
1337   ($hostname, $domainset) = split /\./, $hostname, 2 if $hostname =~ m/\./;
1338   exit_on_error_option($help)
1339      if $domainset  eq '';
1340   exit_on_error_option($help)
1341      if $hostname   eq ''
1342      and $ip        eq '';
1343   exit_on_error_option($help)
1344      if $hostname   ne ''
1345      and $ip        ne '';
1346
1347   enable_pc($hostname, $domainset, $ip);
1348   }
1349
1350#-------------------------------------------------------------------------------
1351
1352sub cmd_disable_pc {
1353   local @ARGV = @_;
1354
1355   my $help = get_cmd_name();
1356   my ($hostname, $domainset, $ip);
1357
1358   GetOptions(
1359      'hostname|h=s'    => \$hostname,
1360      'domainset|d=s'   => \$domainset,
1361      'ip|i=s'          => \$ip,
1362      );
1363
1364   ($hostname, $domainset) = split /\./, $hostname, 2 if $hostname =~ m/\./;
1365   exit_on_error_option($help)
1366      if $domainset  eq '';
1367   exit_on_error_option($help)
1368      if $hostname   eq ''
1369      and $ip        eq '';
1370   exit_on_error_option($help)
1371      if $hostname   ne ''
1372      and $ip        ne '';
1373
1374   disable_pc($hostname, $domainset, $ip);
1375   }
1376
1377#-------------------------------------------------------------------------------
1378
1379sub cmd_disable_float {
1380   local @ARGV = @_;
1381
1382   my $help = get_cmd_name();
1383   my ($pool, $mac);
1384
1385   GetOptions(
1386      'pool|p=s'  => \$pool,
1387      'mac|m=s'   => \$mac,
1388      );
1389
1390   ($pool) = split /\./, $pool, 2 if $pool =~ m/\./;
1391   exit_on_error_option($help)
1392      if $pool eq ''
1393      or $mac  eq '';
1394
1395   disable_float($pool, $mac);
1396   }
1397
1398#-------------------------------------------------------------------------------
1399
1400sub cmd_enable_float {
1401   local @ARGV = @_;
1402
1403   my $help = get_cmd_name();
1404   my ($pool, $mac);
1405
1406   GetOptions(
1407      'pool|p=s'  => \$pool,
1408      'mac|m=s'   => \$mac,
1409      );
1410
1411   ($pool) = split /\./, $pool, 2 if $pool =~ m/\./;
1412   exit_on_error_option($help)
1413      if $pool eq ''
1414      or $mac  eq '';
1415
1416   enable_float($pool, $mac);
1417   }
1418
1419#-------------------------------------------------------------------------------
1420# DELETE section
1421#-------------------------------------------------------------------------------
1422
1423#-------------------------------------------------------------------------------
1424#Nom: del_pc
1425#Description: supprime une machine en DHCP ou en IP statique.
1426
1427sub del_pc {
1428   my ($hostname, $domainset, $ip) = @_;
1429
1430   my $computer_db = ipamdb_load($COMPUTER_YAML);
1431
1432   control_exist_domainset($computer_db, $domainset) or exit;
1433   if ($ip ne '') { # delete by IP
1434      if ( control_exist_ip($computer_db, $ip) == 1 ) {
1435         die "Error: Unkown IP address: $ip\n";
1436         }
1437
1438      my $computer_index = 0;
1439
1440      LOOP_ON_COMPUTER:
1441      for my $computer (@{$computer_db->{$domainset}}) {
1442         my ($mac_address, $attribute) = %{$computer};
1443
1444         $computer_index++, next LOOP_ON_COMPUTER if $attribute->{'ip'} ne $ip;
1445         
1446         splice(@{$computer_db->{$domainset}}, $computer_index => 1);
1447         ipamdb_save("$COMPUTER_YAML", $computer_db);
1448         print "Info: Host $ip has been removed from the domain set $domainset [OK]\n";
1449         exit;
1450         }
1451      }
1452   else {
1453      if ( control_exist_hostname($computer_db, $domainset, $hostname) == 1 ) {
1454         die "Error: Unkown host: $hostname, in domain set: $domainset\n";
1455         }
1456
1457      my $computer_index = 0;
1458
1459      LOOP_ON_COMPUTER:
1460      for my $computer (@{$computer_db->{$domainset}}) {
1461         my ($mac_address, $attribute) = %{$computer};
1462
1463         $computer_index++, next LOOP_ON_COMPUTER if $attribute->{'hostname'} ne $hostname;
1464
1465         if ($attribute->{'address_type'} eq 'pool-dhcp') {
1466            die "Error: Host remove $hostname from the domain set $domainset [FAILED]" .
1467               " ... The host $hostname belongs to a DHCP pool.\n";
1468            }
1469
1470         splice(@{$computer_db->{$domainset}}, $computer_index => 1);
1471         ipamdb_save("$COMPUTER_YAML", $computer_db);
1472         print "Info: Host $hostname has been removed from the domain set $domainset [OK]\n";
1473         exit;
1474         }
1475      }
1476   }
1477
1478#-------------------------------------------------------------------------------
1479#Nom: del_float
1480#Description: supprime une machine d'un pool DHCP
1481
1482sub del_float {
1483   my ($pool, $mac) = @_;
1484
1485   my $computer_db = ipamdb_load($COMPUTER_YAML);
1486
1487   if ( control_exist_mac($computer_db, $mac) == 1 ) {
1488      print "Adresse MAC $mac non trouvée.\n";
1489      exit;
1490      }
1491
1492   for my $domainset_current (keys %{$computer_db}) {
1493      next if $domainset_current eq 'dset';
1494      next if $domainset_current eq 'pool';
1495      next if $domainset_current eq 'pxe';
1496      next if $domainset_current eq 'tag';
1497      next if $domainset_current eq 'version';
1498
1499      my @domainsetdb = @{$computer_db->{$domainset_current}};
1500
1501      my $computer_index = 0;
1502
1503      LOOP_ON_COMPUTER:
1504      for my $computer (@domainsetdb) {
1505         my ($mac_address, $attribute) = %{$computer};
1506
1507         $computer_index++, next LOOP_ON_COMPUTER if $mac_address ne $mac;
1508
1509         if ($attribute->{'ip'} ne $pool) {
1510            die "Error: Host remove $mac [FAILED]" .
1511               " ... The host $mac does not belong to the $pool pool.\n";
1512            }
1513
1514         splice(@{$computer_db->{$domainset_current}}, $computer_index => 1);
1515         ipamdb_save("$COMPUTER_YAML", $computer_db);
1516         print "Info: remove host $mac from the pool $pool [OK]\n";
1517         exit;
1518         }
1519      }
1520   }
1521
1522#-------------------------------------------------------------------------------
1523
1524sub cmd_del_pc {
1525   local @ARGV = @_;
1526
1527   my $help = get_cmd_name();
1528   my ($hostname, $domainset, $ip);
1529
1530   GetOptions(
1531      'hostname|h=s'    => \$hostname,
1532      'domainset|d=s'   => \$domainset,
1533      'ip|i=s'          => \$ip,
1534      );
1535
1536   ($hostname, $domainset) = split /\./, $hostname, 2 if $hostname =~ m/\./;
1537   exit_on_error_option($help)
1538      if $domainset  eq '';
1539   exit_on_error_option($help)
1540      if $hostname   eq ''
1541      and $ip        eq '';
1542   exit_on_error_option($help)
1543      if $hostname   ne ''
1544      and $ip        ne '';
1545
1546   del_pc($hostname, $domainset, $ip);
1547   }
1548
1549#-------------------------------------------------------------------------------
1550
1551sub cmd_del_float {
1552   local @ARGV = @_;
1553
1554   my $help = get_cmd_name();
1555   my ($pool, $mac);
1556
1557   GetOptions(
1558      'pool|p=s'        => \$pool,
1559      'mac|m=s'         => \$mac,
1560      );
1561
1562   ($pool) = split /\./, $pool, 2 if $pool =~ m/\./;
1563   exit_on_error_option($help)
1564      if $pool eq ''
1565      or $mac  eq '';
1566
1567   del_float($pool, $mac);
1568   }
1569
1570#-------------------------------------------------------------------------------
1571# DOMAIN SET section
1572#-------------------------------------------------------------------------------
1573
1574sub cmd_create_domainset {
1575   local @ARGV = @_;
1576
1577   my $help = get_cmd_name();
1578   my ($domainset, $dns_extension, $comment);
1579
1580   GetOptions(
1581      'domainset|d=s'      => \$domainset,
1582      'dns-extension|e=s'  => \$dns_extension,
1583      'comment|c=s'        => \$comment,
1584      );
1585
1586   exit_on_error_option($help)
1587      if $domainset     eq ''
1588      or $dns_extension eq ''
1589      or $comment       eq '';
1590
1591   $comment = normalize_comment($comment);
1592
1593   my $computer_db = ipamdb_load($COMPUTER_YAML);
1594
1595   $computer_db->{'dset'} ||= {};
1596   die "Error: Domain Set already exists: $domainset\n" if exists $computer_db->{'dset'}{$domainset};
1597
1598   control_syntax_comment($comment)    or exit;
1599
1600   my $timestamp = time;
1601   $computer_db->{'dset'}{$domainset} = {
1602      'dns_extension'   => $dns_extension,
1603      'comment'         => $comment,
1604      'create_time'     => $timestamp,
1605      'modify_time'     => $timestamp,
1606      };
1607   $computer_db->{$domainset} ||= []; # Create empty Domain Set computer list by default
1608   ipamdb_save("$COMPUTER_YAML", $computer_db);
1609   }
1610
1611#-------------------------------------------------------------------------------
1612# POOL section
1613#-------------------------------------------------------------------------------
1614
1615#-------------------------------------------------------------------------------
1616#Nom: create_pool
1617#Description: crée un pool dans le fichier de données YAML et dans le DHCP.
1618#
1619#Commentaires: il y a un petit bug si jamais on rentre que des adresses ip qui existent déjà.
1620#              Le pool est créé mais sans adresses ip.
1621
1622sub cmd_create_pool {
1623   local @ARGV = @_;
1624
1625   my $help = get_cmd_name();
1626   my ($pool, $domainset, $file_pool, $ipaddress_pool);
1627
1628   GetOptions(
1629      'pool|p=s'           => \$pool,
1630      'domainset|d=s'      => \$domainset,
1631      'file-pool|f=s'      => \$file_pool,
1632      'ipaddress-pool|i=s' => \$ipaddress_pool,
1633      );
1634
1635   exit_on_error_option($help)
1636      if $pool             eq ''
1637      or $domainset        eq ''
1638      or $file_pool        eq ''
1639      or $ipaddress_pool   eq '';
1640
1641   my $computer_db = ipamdb_load($COMPUTER_YAML);
1642
1643   if ($computer_db->{'pool'}) {
1644      die "Error: Pool already exists: $pool\n" if exists $computer_db->{'pool'}{$pool};
1645      }
1646
1647   #--- control if the domain's pool exist ---#
1648   control_exist_domainset($computer_db, $domainset) or exit;
1649
1650   my @ip_list = ();
1651   #---control if address exist ---#
1652   if ($ipaddress_pool =~ /,/) {
1653      for my $ip (split /,/, $ipaddress_pool) {
1654         if ($ip =~ /-/) {
1655            my ($ip1, $ip2, $ip3, $range) = split /\./, $ip;
1656            my ($first, $last) = split /-/, $range;
1657            for (my $cpt = $first; $cpt <= $last; $cpt++) {
1658               my $ip_loc = "$ip1.$ip2.$ip3.$cpt";
1659               control_syntax_ip($ip_loc) or die "Error: Bad IP syntax: $ip_loc\n";
1660               control_exist_ip($computer_db, $ip_loc) or die "Error: IP address already exists: $ip_loc\n";
1661               push @ip_list, $ip_loc;
1662               }
1663            }
1664         else {
1665            control_syntax_ip($ip) or next;
1666            if ( control_exist_ip($computer_db, $ip) == 0 ) {
1667               print "L'adresse IP $ip existe déjà\n";
1668               next;
1669               }
1670            push @ip_list, $ip;
1671            }
1672         }
1673      }
1674
1675   my $timestamp = time;
1676   $computer_db->{'pool'}{$pool} = {
1677      'ip'          => [@ip_list],
1678      'enabled'     => 'yes',
1679      'create_time' => $timestamp,
1680      'modify_time' => $timestamp,
1681      'file'        => $file_pool,
1682      'domain'      => $domainset,
1683      };
1684   ipamdb_save("$COMPUTER_YAML", $computer_db);
1685   }
1686
1687#-------------------------------------------------------------------------------
1688
1689sub cmd_show_pool {
1690   local @ARGV = @_;
1691
1692   my ($no_header);
1693
1694   GetOptions(
1695      'no-header|H' => \$no_header,
1696      );
1697
1698   my $computer_db = ipamdb_load($COMPUTER_YAML);
1699
1700   printf "%-17s %-17s %s\n", 'Pool', 'File', 'DNS-Domain' if not $no_header;
1701   LOOP_ON_PXE:
1702   for my $pool ( keys %{$computer_db->{'pool'}} ) {
1703
1704      printf "%-17s %-17s %s\n",
1705         $pool,
1706         $computer_db->{'pool'}{$pool}{'file'},
1707         $computer_db->{'pool'}{$pool}{'domain'},
1708      }
1709   }
1710
1711#-------------------------------------------------------------------------------
1712# PXE section
1713#-------------------------------------------------------------------------------
1714
1715sub cmd_create_pxe {
1716   local @ARGV = @_;
1717
1718   my $help = get_cmd_name();
1719   my ($pxe_config, $ip_next_server, $filename, $comment);
1720
1721   GetOptions(
1722      'bootp|b=s'       => \$pxe_config,
1723      'next-server|n=s' => \$ip_next_server,
1724      'filename|f=s'    => \$filename,
1725      'comment|c=s'     => \$comment,
1726      );
1727
1728   exit_on_error_option($help)
1729      if $pxe_config       eq ''
1730      or $ip_next_server   eq ''
1731      or $filename         eq ''
1732      or $comment          eq '';
1733
1734   my $computer_db = ipamdb_load($COMPUTER_YAML);
1735
1736   $comment = normalize_comment($comment);
1737
1738   $computer_db->{'pxe'} ||= {};
1739   die "Error: PXE config already exists: $pxe_config\n" if exists $computer_db->{'pxe'}{$pxe_config};
1740
1741   control_syntax_ip($ip_next_server)  or die "Error: Bad IP syntax: $ip_next_server\n";
1742   control_syntax_comment($comment)    or exit;
1743
1744   my $timestamp = time;
1745   $computer_db->{'pxe'}{$pxe_config} = {
1746      'ip_next_server'  => $ip_next_server,
1747      'filename'        => $filename,
1748      'comment'         => $comment,
1749      'create_time'     => $timestamp,
1750      'modify_time'     => $timestamp,
1751      };
1752   ipamdb_save("$COMPUTER_YAML", $computer_db);
1753   }
1754
1755#-------------------------------------------------------------------------------
1756
1757sub cmd_remove_pxe {
1758   local @ARGV = @_;
1759
1760   my $help = get_cmd_name();
1761   my ($pxe_config);
1762
1763   GetOptions(
1764      'bootp|b=s' => \$pxe_config,
1765      );
1766
1767   exit_on_error_option($help)
1768      if $pxe_config eq '';
1769
1770   my $computer_db = ipamdb_load($COMPUTER_YAML);
1771
1772   $computer_db->{'pxe'} ||= {};
1773   die "Error: PXE config does not exist: $pxe_config\n" if not exists $computer_db->{'pxe'}{$pxe_config};
1774
1775   # Test if some computer use this config
1776   LOOP_ON_DOMAIN:
1777   for my $domainset_current (keys %{$computer_db}) {
1778      next if $domainset_current eq 'dset';
1779      next if $domainset_current eq 'pool';
1780      next if $domainset_current eq 'pxe';
1781      next if $domainset_current eq 'tag';
1782      next if $domainset_current eq 'version';
1783
1784      LOOP_ON_COMPUTER:
1785      for my $computer (@{$computer_db->{$domainset_current}}) {
1786         my ($mac_address, $attribute) = %{$computer};
1787
1788         if (exists $attribute->{'pxe_config'}) {
1789            my $hostname = $attribute->{'hostname'};
1790            die "Error: computer still use this PXE config: $hostname.$domainset_current $mac_address\n" if $pxe_config eq $attribute->{'pxe_config'};
1791            }
1792         }
1793      }
1794
1795   delete $computer_db->{'pxe'}{$pxe_config};
1796   ipamdb_save("$COMPUTER_YAML", $computer_db);
1797   }
1798
1799#--------------------------------------------------------------------------------
1800
1801sub cmd_show_pxe {
1802   local @ARGV = @_;
1803
1804   my ($no_header);
1805
1806   GetOptions(
1807      'no-header|H' => \$no_header,
1808      );
1809
1810   my $computer_db = ipamdb_load($COMPUTER_YAML);
1811
1812   printf "%-12s %-13s %-30s %s\n", 'PXE-Config', 'Next-Server', 'Filename', 'Comment' if not $no_header;
1813   LOOP_ON_PXE:
1814   for my $pxe_config ( keys %{$computer_db->{'pxe'}} ) {
1815      my $ip_next_server = $computer_db->{'pxe'}{$pxe_config}{'ip_next_server'};
1816      my $filename       = $computer_db->{'pxe'}{$pxe_config}{'filename'};
1817      my $comment        = $computer_db->{'pxe'}{$pxe_config}{'comment'};
1818
1819      printf "%-12s %-13s %-30s %s\n", $pxe_config, $ip_next_server, $filename, $comment;
1820      }
1821   }
1822
1823#-------------------------------------------------------------------------------
1824
1825sub cmd_enable_pxe {
1826   local @ARGV = @_;
1827
1828   my $help = get_cmd_name();
1829   my ($hostname, $domainset, $ip, $pxe_config);
1830
1831   GetOptions(
1832      'hostname|h=s'    => \$hostname,
1833      'domainset|d=s'   => \$domainset,
1834      'ip|i=s'          => \$ip,
1835      'bootp|b=s'       => \$pxe_config,
1836      );
1837
1838   ($hostname, $domainset) = split /\./, $hostname, 2 if $hostname =~ m/\./;
1839   exit_on_error_option($help)
1840      if $domainset  eq ''
1841      or $pxe_config eq '';
1842   exit_on_error_option($help)
1843      if $hostname   eq ''
1844      and $ip        eq '';
1845   exit_on_error_option($help)
1846      if $hostname   ne ''
1847      and $ip        ne '';
1848
1849   my $computer_db = ipamdb_load($COMPUTER_YAML);
1850
1851   die "Error: PXE config not exists: $pxe_config\n" if not exists $computer_db->{'pxe'}{$pxe_config};
1852
1853   control_exist_domainset($computer_db, $domainset) or exit;
1854   if ($ip ne '') {
1855      control_syntax_ip($ip);
1856      if ( control_exist_ip($computer_db, $ip) == 1 ) {
1857         die "Error: Unkown IP address: $ip\n";
1858         }
1859
1860      for my $domainset_current (keys %{$computer_db}) {
1861         next if $domainset_current eq 'dset';
1862         next if $domainset_current eq 'pool';
1863         next if $domainset_current eq 'pxe';
1864         next if $domainset_current eq 'tag';
1865         next if $domainset_current eq 'version';
1866
1867         my $computer_index = 0;
1868         for my $computer (@{$computer_db->{$domainset_current}}) {
1869            for my $id (keys %{$computer}) {
1870               if ($computer->{$id}->{'ip'} eq $ip) {
1871                  my $timestamp = time;
1872                  $computer_db->{$domainset_current}[$computer_index]->{$id}->{'modify_time'} = $timestamp;
1873                  $computer_db->{$domainset_current}[$computer_index]->{$id}->{'pxe_config'}  = $pxe_config;
1874                  print "IP Address: $ip, PXE enabled in config: $pxe_config\n";
1875                  ipamdb_save("$COMPUTER_YAML", $computer_db);
1876                  exit;
1877                  }
1878               $computer_index++;
1879               }
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), PXE enabled in config: $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_DOMAIN:
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_DOMAIN:
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     );
2163
2164   LOOP_ON_DOMAIN:
2165   for my $domainset_current (keys %{$computer_db}) {
2166      next if $domainset_current eq 'dset';
2167      next if $domainset_current eq 'pool';
2168      next if $domainset_current eq 'pxe';
2169      next if $domainset_current eq 'tag';
2170      next if $domainset_current eq 'version';
2171
2172      $tb_computer->add($domainset_current) and next LOOP_ON_DOMAIN if not exists $computer_db->{'dset'}{$domainset_current};
2173
2174      my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime $computer_db->{'dset'}{$domainset_current}{'modify_time'};
2175      $year += 1900;
2176      $mon++;
2177      my $date = sprintf '%04i-%02i-%02i', $year, $mon, $mday;
2178
2179      my $comment = $computer_db->{'dset'}{$domainset_current}{'comment'};
2180      $comment =~ s/^\d\d\d\d-\d\d-\d\d\s//;
2181         
2182      $tb_computer->add($domainset_current,
2183         $computer_db->{'dset'}{$domainset_current}{'dns_extension'},
2184         $date,
2185         $comment,
2186         );
2187      }
2188
2189   print $tb_computer->title(),
2190         $tb_computer->rule('-') if not $no_header;
2191   print $tb_computer->body();
2192   }
2193
2194#--------------------------------------------------------------------------------
2195
2196sub cmd_search_mac {
2197   local @ARGV = @_;
2198
2199   my $help = get_cmd_name();
2200   my ($mac);
2201
2202   GetOptions(
2203      'mac|m=s' => \$mac,
2204      );
2205
2206   exit_on_error_option($help)
2207      if $mac eq '';
2208
2209   $mac = normalize_mac_address($mac);
2210
2211   my $computer_db = ipamdb_load($COMPUTER_YAML);
2212
2213   control_syntax_mac_address($mac) or exit;
2214
2215   LOOP_ON_DOMAIN:
2216   for my $domainset_current (keys %{$computer_db}) {
2217      next if $domainset_current eq 'dset';
2218      next if $domainset_current eq 'pool';
2219      next if $domainset_current eq 'pxe';
2220      next if $domainset_current eq 'tag';
2221      next if $domainset_current eq 'version';
2222
2223      my @domainsetdb = @{$computer_db->{$domainset_current}};
2224
2225      LOOP_ON_COMPUTER:
2226      for my $computer (@domainsetdb) {
2227         my ($mac_address, $attribute) = %{$computer};
2228
2229         next LOOP_ON_COMPUTER if $mac_address ne $mac;
2230
2231         my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime $attribute->{'modify_time'};
2232         $year += 1900;
2233         $mon++;
2234         my $date = sprintf '%04i-%02i-%02i', $year, $mon, $mday;
2235
2236         my $comment = $attribute->{'comment'};
2237         $comment =~ s/^\d\d\d\d-\d\d-\d\d\s//;
2238
2239         my $enable = $attribute->{'enabled'};
2240         if (exists $attribute->{'pxe_config'}) {
2241            $enable .= '/' . $attribute->{'pxe_config'};
2242            }
2243         if (exists $attribute->{'tag'}) {
2244            $enable .= ':' . $attribute->{'tag'};
2245            }
2246
2247         printf "%-30s  %-20s %17s %9s %3s %10s %s\n",
2248            $attribute->{'hostname'} . '.' . $domainset_current,
2249            $attribute->{'ip'},
2250            $mac_address,
2251            $attribute->{'address_type'},
2252            $enable,
2253            $date,
2254            $comment;
2255         }
2256      }
2257   }
2258
2259#--------------------------------------------------------------------------------
2260#Nom: show
2261#Description: liste les machines à partir du fichier YAML par nom de domaine.
2262
2263sub cmd_show_host {
2264   my %ipdb = ();
2265
2266   my $computer_db = ipamdb_load($COMPUTER_YAML);
2267
2268   my $tb_computer = Text::Table->new(
2269     {align  => 'left',   align_title => 'left',   title => 'Hostname.DomainSet'},
2270     {is_sep => 1,        body        => '  '},
2271     {align  => 'left',   align_title => 'left',   title => 'IPv4-Address'},
2272     {is_sep => 1,        body        => '  '},
2273     {align  => 'center', align_title => 'center', title => 'MAC-Address'},
2274     {is_sep => 1,        body        => '  '},
2275     {align  => 'right',  align_title => 'right',  title => 'Type'},
2276     {align  => 'right',  align_title => 'right',  title => 'Status'},
2277     {is_sep => 1,        body        => '  '},
2278     {align  => 'left',   align_title => 'left',   title => 'Date'},
2279     {align  => 'left',   align_title => 'left',   title => 'Comment'},
2280     );
2281
2282  LOOP_ON_DOMAIN:
2283   for my $domainset_current (sort keys %{$computer_db}) {
2284      next if $domainset_current eq 'dset';
2285      next if $domainset_current eq 'pool';
2286      next if $domainset_current eq 'pxe';
2287      next if $domainset_current eq 'tag';
2288      next if $domainset_current eq 'version';
2289
2290      my @domainsetdb = @{$computer_db->{$domainset_current}};
2291
2292      LOOP_ON_COMPUTER:
2293      for my $computer (@domainsetdb) {
2294         my ($mac_address, $attribute) = %{$computer};
2295         my $ip = $attribute->{'ip'};
2296
2297         if ($ip =~ m/$DDT::RE::IPv4_ADDRESS/xms) {
2298            if ( not exists $ipdb{$ip} ) {
2299               $ipdb{$ip} = {
2300                  'mac_address'  => $mac_address,
2301                  %{$attribute},
2302                  'domainset'    => $domainset_current,
2303                  };
2304               }
2305            else {
2306               print {*STDERR} "# Warning: $ip already exists in the database with MAC $mac_address!\n";
2307               }
2308            next LOOP_ON_COMPUTER;
2309            }
2310
2311         my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime $attribute->{'modify_time'};
2312         $year += 1900;
2313         $mon++;
2314         my $date = sprintf '%04i-%02i-%02i', $year, $mon, $mday;
2315
2316         my $comment = normalize_comment($attribute->{'comment'});
2317         $comment =~ s/^\d\d\d\d-\d\d-\d\d\s//;
2318
2319         my $enable = $attribute->{'enabled'};
2320         if (exists $attribute->{'pxe_config'}) {
2321            $enable .= '/' . $attribute->{'pxe_config'};
2322            }
2323         if (exists $attribute->{'tag'}) {
2324            $enable .= ':' . $attribute->{'tag'};
2325            }
2326
2327         #printf "%-30s  %-20s %17s %9s %3s %10s %s\n",
2328         $tb_computer->add(
2329            $attribute->{'hostname'} . '.' . $domainset_current,
2330            $ip,
2331            $mac_address,
2332            $attribute->{'address_type'},
2333            $enable,
2334            $date,
2335            $comment,
2336            );
2337         }
2338      #print "\n# *** List of pool computers in the domain set: $domainset_current ***\n";
2339      }
2340
2341   #print "\n# *** List of computers ordered by IP and domain set ***\n";
2342   LOOP_ON_IP_ADDRESS:
2343   foreach my $ip (Net::Netmask::sort_by_ip_address(keys %ipdb)) {
2344      my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime $ipdb{$ip}->{'modify_time'};
2345      $year += 1900;
2346      $mon++;
2347      my $date = sprintf '%04i-%02i-%02i', $year, $mon, $mday;
2348
2349      my $comment =$ipdb{$ip}->{'comment'};
2350      $comment =~ s/^\d\d\d\d-\d\d-\d\d\s//;
2351
2352      my $enable = $ipdb{$ip}->{'enabled'};
2353      if (exists $ipdb{$ip}->{'pxe_config'}) {
2354         $enable .= '/' . $ipdb{$ip}->{'pxe_config'};
2355         }
2356      if (exists $ipdb{$ip}->{'tag'}) {
2357         $enable .= ':' . $ipdb{$ip}->{'tag'};
2358         }
2359
2360      #printf "%-30s %-20s %17s %9s %3s %10s %s\n",
2361      $tb_computer->add(
2362         $ipdb{$ip}->{'hostname'} . '.' . $ipdb{$ip}->{'domainset'},
2363         $ip,
2364         normalize_mac_address($ipdb{$ip}->{'mac_address'}),
2365         $ipdb{$ip}->{'address_type'},
2366         $enable,
2367         $date,
2368         $comment
2369         );
2370      }
2371
2372   print $tb_computer->title();
2373   print $tb_computer->rule('-');
2374   print $tb_computer->body();
2375   }
2376
2377#-------------------------------------------------------------------------------
2378#Nom: cmd_generate_dhcp_file
2379#Description: génère les fichiers de configuration des machines et des pools du dhcp
2380
2381sub cmd_generate_dhcp_file {
2382   backup_database();
2383
2384   my $computer_db = ipamdb_load($COMPUTER_YAML);
2385
2386   my %file_pool;
2387
2388   for my $domainset_current (keys %{$computer_db}) {
2389      next if $domainset_current eq 'dset';
2390      next if $domainset_current eq 'pool';
2391      next if $domainset_current eq 'pxe';
2392      next if $domainset_current eq 'tag';
2393      next if $domainset_current eq 'version';
2394
2395      open FILE_VLAN, '>', "$FOLDER_GEN_DHCP/$domainset_current";
2396      my @domainsetdb = @{$computer_db->{$domainset_current}};
2397      for my $value (@domainsetdb) {
2398         ALL_MAC_ADDRESS:
2399         for my $mac_addres (keys %{$value}) {
2400            #host pcdavoust {  deny-unknown-clients;
2401            #hardware ethernet 0:6:5b:b8:13:d1;
2402            #fixed-address 194.254.66.72;
2403            #}
2404
2405            my $hostname     = $value->{$mac_addres}{'hostname'};
2406            my $ip           = $value->{$mac_addres}{'ip'};
2407            my $comment      = $value->{$mac_addres}{'comment'};
2408            my $address_type = $value->{$mac_addres}{'address_type'};
2409            my $enabled      = $value->{$mac_addres}{'enabled'};
2410            my $tags         = $value->{$mac_addres}{'tag'} || 'universal';
2411
2412            my $buffer;
2413            if ($address_type eq 'dhcp') {
2414               if ($enabled eq 'yes') {
2415                  $buffer  = "host $hostname {\n"; # deny-unknown-clients;
2416                  $buffer .= "   hardware ethernet $mac_addres;\n";
2417                  $buffer .= "   fixed-address $ip;\n";
2418
2419                  if (exists $value->{$mac_addres}{'pxe_config'}) {
2420                     my $pxe_config     = $value->{$mac_addres}{'pxe_config'};
2421                     my $ip_next_server = $computer_db->{'pxe'}{$pxe_config}{'ip_next_server'};
2422                     my $filename       = $computer_db->{'pxe'}{$pxe_config}{'filename'};
2423                     $buffer .= "   next-server $ip_next_server;\n";
2424                     $buffer .= "   filename \"$filename\";\n";
2425                     }
2426                  $buffer .= "   #comment: $comment\n";
2427                  $buffer .= "   }\n";
2428                  $buffer .= "\n";
2429
2430                  for my $tag (split/,/, $tags) {
2431                     $file_pool{"tag-$tag"} ||= [];
2432                     push @{$file_pool{"tag-$tag"}}, "subclass \"tag-$tag\" 1:$mac_addres; # $comment\n";
2433                     }
2434                  }
2435               else {
2436                  $buffer  = "#host $hostname {\n"; # deny-unknown-clients;
2437                  $buffer .= "#   hardware ethernet $mac_addres;\n";
2438                  $buffer .= "#   fixed-address $ip;\n";
2439                  $buffer .= "#   comment: $comment \n";
2440                  $buffer .= "#   }\n";
2441                  $buffer .= "\n";
2442                  }
2443               print FILE_VLAN $buffer;
2444               }
2445            elsif ($address_type eq 'pool-dhcp') {
2446               #--- Génère les fichiers pool dhcp ---#
2447               for my $current_pool (keys %{$computer_db->{'pool'}}) {
2448                  next if $current_pool ne $ip;
2449
2450                  if ($enabled eq 'yes') {
2451                     $buffer = "subclass \"$current_pool\" 1:$mac_addres; # $comment\n";
2452
2453                     for my $tag (split/,/, $tags) {
2454                        $file_pool{"tag-$tag"} ||= [];
2455                        push @{$file_pool{"tag-$tag"}}, "subclass \"tag-$tag\" 1:$mac_addres; # $comment\n";
2456                        }
2457                     }
2458                  else {
2459                     $buffer = "#subclass \"$current_pool\" 1:$mac_addres; # $comment\n";
2460                     }
2461
2462                  my $current_pool_file_name = $computer_db->{'pool'}{$current_pool}{'file'};
2463
2464                  $file_pool{$current_pool_file_name} ||= [];
2465                  push @{$file_pool{$current_pool_file_name}}, $buffer;
2466                  }
2467               }
2468            }
2469         }
2470
2471      close FILE_VLAN;
2472
2473      for my $file_name (keys %file_pool) {
2474         open FILE_POOL, '>', "$FOLDER_GEN_DHCP/$file_name";
2475         print FILE_POOL @{$file_pool{$file_name}};
2476         close FILE_POOL;
2477         }
2478      }
2479      print "Copy DHCP files from $FOLDER_GEN_DHCP to /etc/dhcp/include/\n";
2480      exec $SCRIPT_UPDATE;
2481   }
2482
2483#-------------------------------------------------------------------------------
2484#Nom: cmd_generate_dns_file
2485#Description: génère les fichiers d'enregistrements DNS
2486
2487sub cmd_generate_dns_file {
2488   my $buffer_fwd;
2489   my $buffer_rev;
2490   my $pool_domain;
2491
2492   my $computer_db = ipamdb_load($COMPUTER_YAML);
2493
2494   for my $domainset_current (keys %{$computer_db}) {
2495      next if $domainset_current eq 'dset';
2496      next if $domainset_current eq 'pool';
2497      next if $domainset_current eq 'pxe';
2498      next if $domainset_current eq 'tag';
2499      next if $domainset_current eq 'version';
2500
2501      if ($domainset_current eq 'pool') {
2502         LOOP_ON_COMPUTER:
2503         for my $computer (@{$computer_db->{$domainset_current}}) {
2504            for my $pool_name (keys %{$computer}) {
2505               $pool_domain = $computer->{$pool_name}->{'domain'}."\n";
2506               #print $computer->{$pool_name}->{'file'};
2507               chomp $pool_domain;
2508               open FILE_FORWARD_DNS, '>>', "$FOLDER_GEN_DNS/db.$pool_domain.fwd";
2509               open FILE_REVERSE_DNS, '>>', "$FOLDER_GEN_DNS/db.$pool_domain.rev";
2510               my @T_pool_ip = @{$computer->{$pool_name}->{'ip'}};
2511               for my $pool_ip (@T_pool_ip) {
2512                  my @T_split = split(/\./ , $pool_ip);
2513                  $buffer_fwd = sprintf "%-24s IN  A  %-15s ;\n", "$pool_name$T_split[3]", $pool_ip;
2514                  $buffer_rev = "$T_split[3]   IN PTR   $pool_name$T_split[3].$pool_domain.\n";
2515                  print FILE_FORWARD_DNS $buffer_fwd;
2516                  print FILE_REVERSE_DNS $buffer_rev;
2517                  }
2518               close FILE_FORWARD_DNS;
2519               close FILE_REVERSE_DNS;
2520               }
2521            }
2522         }
2523
2524      else {
2525         #--- Création du fichier non-reverse ---#
2526         open FILE_FORWARD_DNS, ">> $FOLDER_GEN_DNS/db.$domainset_current.fwd";
2527         open FILE_REVERSE_DNS, ">> $FOLDER_GEN_DNS/db.$domainset_current.rev";
2528
2529         my @domainsetdb = @{$computer_db->{$domainset_current}};
2530
2531         LOOP_ON_COMPUTER:
2532         for my $computer (@domainsetdb) {
2533            my ($mac_address, $attribute) = %{$computer};
2534
2535            #host pcdavoust {  deny-unknown-clients;
2536            #hardware ethernet 0:6:5b:b8:13:d1;
2537            #fixed-address 194.254.66.72;
2538            #}
2539
2540            my $hostname     = $attribute->{'hostname'};
2541            my $ip           = $attribute->{'ip'};
2542            my $comment      = $attribute->{'comment'};
2543            my $address_type = $attribute->{'address_type'};
2544            my $enabled      = $attribute->{'enabled'};
2545
2546            next LOOP_ON_COMPUTER if not (($address_type eq 'dhcp') or ($address_type eq 'static'));
2547
2548            my $dns_domain = $domainset_current;
2549            if (exists $computer_db->{'dset'}{$domainset_current}) {
2550               $dns_domain = $computer_db->{'dset'}{$domainset_current}{'dns_extension'};
2551               }
2552
2553            my @ip_split = split /\./, $ip;
2554            if ($enabled eq 'yes') {
2555               if (exists $attribute->{'dns_extension'}
2556                     and "$attribute->{'dns_extension'}" != "$dns_domain") {
2557                  print "A FAIRE\n";
2558                  }
2559               $buffer_fwd = sprintf "%-24s  IN A   %-15s ; %s\n", $hostname, $ip, $comment;
2560               $buffer_rev = sprintf "%3i    IN PTR %-15s\n", $ip_split[3], "$hostname.$dns_domain.";
2561               }
2562
2563            else {
2564               $buffer_fwd = sprintf ";%-24s IN A   %-15s ; %s\n", $hostname, $ip, $comment;
2565               $buffer_rev = sprintf ";%3i   IN PTR %-15s\n", $ip_split[3], "$hostname.$dns_domain.";
2566               }
2567            print FILE_REVERSE_DNS $buffer_rev;
2568            print FILE_FORWARD_DNS $buffer_fwd;
2569            }
2570         print "- DNS: db.$domainset_current.fwd db.$domainset_current.rev [CREATE].\n";
2571         print "Ex : sort -k 4n -t . /usr/local/dhcp-dns-tools/dns/dns.hmg.priv\n";
2572         close FILE_REVERSE_DNS;
2573         close FILE_FORWARD_DNS;
2574         }
2575      }
2576   }
2577
2578#--------------------------------------------------------------------------------
2579
2580sub shell_command {
2581   my $cmd = shift;
2582
2583   require FileHandle;
2584   my $fh     = new FileHandle;
2585   my @result = ();
2586   open $fh, q{-|}, "LANG=C $cmd" or die "Can't exec $cmd\n";
2587   @result = <$fh>;
2588   close $fh;
2589   chomp @result;
2590   return @result;
2591   }
2592
2593sub cmd_check_dns {
2594   my $computer_db = ipamdb_load($COMPUTER_YAML);
2595
2596   LOOP_ON_DOMAIN:
2597   for my $domainset_current (keys %{$computer_db}) {
2598      next if $domainset_current eq 'dset';
2599      next if $domainset_current eq 'pool';
2600      next if $domainset_current eq 'pxe';
2601      next if $domainset_current eq 'tag';
2602      next if $domainset_current eq 'version';
2603
2604      my @domainsetdb = @{$computer_db->{$domainset_current}};
2605
2606      LOOP_ON_COMPUTER:
2607      for my $computer (@domainsetdb) {
2608         my ($mac_address, $attribute) = %{$computer};
2609         #my $new_mac = normalize_mac_address($mac_address);
2610         my $ip = $attribute->{'ip'};
2611         next LOOP_ON_COMPUTER if not $ip =~ m/$DDT::RE::IPv4_ADDRESS/xms;
2612         next LOOP_ON_COMPUTER if $attribute->{'enabled'} eq 'no';
2613
2614         my $dns_hostname_fq = scalar gethostbyaddr(inet_aton($ip), AF_INET);
2615         my ($dns_hostname) = split /\./, $dns_hostname_fq;
2616
2617         if ($attribute->{'hostname'} ne $dns_hostname) {
2618            print "$mac_address ($domainset_current) $ip - $dns_hostname / $attribute->{'hostname'} # $attribute->{'comment'}\n";
2619            next LOOP_ON_COMPUTER;
2620            }
2621
2622         my $packed_ip = scalar gethostbyname($dns_hostname_fq);
2623         if (defined $packed_ip) {
2624            my $ip_address = inet_ntoa($packed_ip);
2625            if ($ip ne $ip_address) {
2626               print "reverse DNS error for $dns_hostname_fq / $ip\n";
2627               next LOOP_ON_COMPUTER;
2628               }
2629            }
2630         }
2631      }
2632
2633   LOOP_ON_DNS:
2634   for my $dns ('legi.grenoble-inp.fr', 'hmg.priv') {
2635      LOOP_ON_IP:
2636      for (shell_command("host -t A -l $dns")) {
2637         # smtp2.legi.grenoble-inp.fr has address 194.254.67.37
2638         next if not m/has address/;
2639         next if not m/^(\w[\w-_\.]+\w)\s+has\saddress\s+(\d[\d\.]+\d)$/;
2640         my ($hostname_fq, $ip) = ($1, $2);
2641         control_syntax_ip($ip) or next LOOP_ON_IP;
2642         if (control_exist_ip($computer_db, $ip) == 1) {
2643            printf "Unkown IP: %015s / %s\n", $ip, $hostname_fq;
2644            next LOOP_ON_IP;
2645            }
2646         }
2647      }
2648   }
2649
2650#-------------------------------------------------------------------------------
2651#Nom: load_data_dhcp
2652#Description: permet de charger le fichier de données YAML via les fichiers de configuration
2653#             machines.
2654#            ATTENTION: LES COMMENTAIRES DU FICHIER DISPARAITRONT.
2655
2656sub load_data_dhcp {
2657   my ($domainset, $input_file) = @_;
2658
2659   my $computer_db = ipamdb_load($COMPUTER_YAML);
2660
2661   my @T_mac;
2662   my @T_host;
2663   my @T_ip;
2664   my $cpt;
2665   open (FILE, "<$input_file");
2666   my @buffer = <FILE>;
2667   close(FILE);
2668
2669   for my $ligne (@buffer) {
2670      #--
2671      $ligne =~ s/#.*$//;
2672      $ligne =~ s/\s+/ /;
2673      $ligne =~ s/^\s+//;
2674      next if $ligne eq '';
2675
2676      if ($ligne =~ /^host /) {
2677         $cpt=0;
2678         my @T_split = split(/host\s+/, $ligne);
2679         @T_host = split(/ /, $T_split[1]);
2680         chomp($T_host[0]);
2681
2682         $cpt++;
2683         }
2684
2685      if ($ligne =~ /^*ethernet /) {
2686         $ligne =~ s/;//g;
2687         @T_mac = split(/ethernet\s+/, $ligne);
2688         chomp($T_mac[1]);
2689         $cpt++;
2690         }
2691
2692      if ($ligne =~ /^*address /) {
2693         $ligne =~ s/;//g;
2694         @T_ip = split(/address\s+/, $ligne);
2695         chomp($T_ip[1]);
2696
2697         $cpt++;
2698         }
2699
2700      if ($cpt == 3) {
2701         #   print "MAC $T_mac[1] HOST $T_host[0] IP $T_ip[1].\n";
2702         my $mac = $T_mac[1];
2703         my $hostname = $T_host[0];
2704         my $ip = $T_ip[1];
2705         $cpt = 0;
2706
2707         if ( control_exist_hostname($computer_db, $domainset, $hostname) == 0 ) {
2708            print "Error: Hostname already exist in domain set attachement $domainset: $hostname\n";
2709            next;
2710            }
2711         control_syntax_mac_address($mac) or next;
2712         if ( control_exist_mac($computer_db, $mac) == 0) {
2713            print "Error: Physical MAC address already exists: $mac\n";
2714            next;
2715            }
2716
2717         control_syntax_ip($ip) or next;
2718         if ( control_exist_ip($computer_db, $ip) == 0 ) {
2719            print "Error: IP address already exists: $ip\n";
2720            next;
2721            }
2722         my $timestamp = time;
2723         push @{$computer_db->{$domainset}}, { $mac => {
2724            'hostname'     => $hostname,
2725            'ip'           => $ip,
2726            'address_type' => 'dhcp',
2727            'enabled'      => 'yes',
2728            'create_time'  => $timestamp,
2729            'modify_time'  => $timestamp,
2730            'alias'        =>  '',
2731            }};
2732         }
2733      }
2734   }
2735
2736#-------------------------------------------------------------------------------
2737#Nom: load_data_pool
2738#Description: permet de charger le fichier YAML via les fichiers de conf 'pool' du dhcp.
2739
2740sub load_data_pool {
2741   my ($domainset, $input_file) = @_;
2742
2743   my @T_mac;
2744
2745   open (FILE, "<$input_file");
2746   my @buffer = <FILE>;
2747   close(FILE);
2748
2749   my $computer_db = ipamdb_load($COMPUTER_YAML);
2750
2751   for my $ligne (@buffer) {
2752      #--
2753      $ligne =~ s/#.*$//;
2754      $ligne =~ s/\s+/ /;
2755      $ligne =~ s/^\s+//;
2756      $ligne =~ s/;//g;
2757      $ligne =~ s/"//g;
2758      next if $ligne eq '';
2759
2760      if (($ligne =~ /^subclass/)) {
2761         my @T_split = split(/ / ,$ligne);
2762         my $pool = $T_split[1];
2763
2764         @T_mac = split(/:/ , $T_split[2]);
2765         my $mac = $T_mac[1].":".$T_mac[2].":".$T_mac[3].":".$T_mac[4].":".$T_mac[5].":".$T_mac[6];
2766         control_syntax_mac_address($mac) or next;
2767         if (control_exist_mac($computer_db, $mac) == 0) {
2768            print "Error: Physical MAC address already exists: $mac\n";
2769            next;
2770            }
2771
2772         #--- cette partie teste si le pool existe.
2773         if (not exists $computer_db->{'pool'}{$pool}) {
2774            print "Error: Create pool with create_pool command before load database: $pool\n";
2775            exit;
2776            }
2777
2778         if ($computer_db->{'pool'}{'domain'} eq $domainset) {
2779            my $timestamp = time;
2780            push @{$computer_db->{$domainset}}, { $mac => {
2781               'hostname'     => $pool,
2782               'ip'           => $pool,
2783               'address_type' => 'pool-dhcp',
2784               'enabled'      => 'yes',
2785               'create_time'  => $timestamp,
2786               'modify_time'  => $timestamp,
2787               }};
2788            }
2789         else {
2790            print "Ajout de la machine $mac [FAILED]\n";
2791            print "Error: The pool doesn't exists: $pool, for the domain: $domainset\n";
2792            }
2793         }
2794      }
2795   }
2796
2797#-------------------------------------------------------------------------------
2798
2799sub load_data_file {
2800   my ($domainset, $input_file, $type_file) = @_;
2801
2802   my $computer_db = ipamdb_load($COMPUTER_YAML);
2803
2804   #$computer_db
2805   if ($type_file eq 'dhcp') {
2806      load_data_dhcp($domainset, $input_file);
2807      }
2808
2809   elsif ($type_file eq 'pool-dhcp') {
2810      load_data_pool($domainset, $input_file);
2811      }
2812
2813   ipamdb_save("$COMPUTER_YAML", $computer_db);
2814   }
2815
2816#-------------------------------------------------------------------------------
2817
2818sub cmd_load_database {
2819   local @ARGV = @_;
2820
2821   my $help = get_cmd_name();
2822   my ($domainset, $input_file, $type_file);
2823
2824   GetOptions(
2825      'domainset|d=s'   => \$domainset,
2826      'filename|f=s'    => \$input_file,
2827      'kind|k=s'        => \$type_file,
2828      );
2829
2830   exit_on_error_option($help)
2831      if $domainset  eq ''
2832      or $input_file eq ''
2833      or $type_file  eq '';
2834
2835   load_data_file($domainset, $input_file, $type_file);
2836   }
2837
2838#-------------------------------------------------------------------------------
2839#Nom: backup_database
2840#Description: sauvegarde et réinitialise les fichiers d'enregistrements DHCP.
2841
2842sub backup_database {
2843   my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime time;
2844   $year += 1900;
2845   $mon++;
2846   my $date = sprintf '%04i-%02i-%02i-%02i-%02i-%02i', $year, $mon, $mday, $hour, $min, $sec;
2847
2848   copy($COMPUTER_YAML, "$FOLDER_BACKUP/$COMPUTER_BASENAME-$date.conf") or die "Error: Database copy backup failed: $!\n";
2849   }
2850
2851#-------------------------------------------------------------------------------
2852# HELP section
2853#-------------------------------------------------------------------------------
2854
2855#-------------------------------------------------------------------------------
2856#Nom: exit_on_error_option
2857#Description: messages d'aide des options pour les différentes commandes
2858
2859sub exit_on_error_option {
2860  my ($command) = @_;
2861
2862   if ($command eq 'add-dhcp') {
2863      print "List of options for command: $command\n";
2864      print " -d : domain set attachment (mandatory). Example: -d legi-sector03\n";
2865      print " -h : computer hostname (mandatory if option -i != 'pool'). Example: -h info8pc154\n";
2866      print " -m : physical MAC address (mandatory). Example: -m 0F:58:AB:2A\n";
2867      print " -i : internet IP address (mandatory). Possible value: classical IP address or the keyword 'pool'\n";
2868      print " -p : name of the DHCP pool to which the machine belongs (mandatory if option -i == 'pool')\n";
2869      print " -c : comment (mandatory). Example: 2014-04-07 DELL Laptop 6400 - Olivier Toto (INFO)\n";
2870      print "Example:\n";
2871      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";
2872      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";
2873      }
2874
2875   elsif ($command eq 'add-float') {
2876      print "List of options for command: $command\n";
2877      print " -d : domain set attachment (mandatory)\n";
2878      print " -p : name of the DHCP pool to which the machine belongs (mandatory)\n";
2879      print " -m : physical MAC address (mandatory)\n";
2880      print " -c : comment (mandatory). Example: 2014-04-07 DELL Laptop 6400 - Olivier Toto (INFO)\n";
2881      print "Example:\n";
2882      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";
2883      }
2884
2885   elsif ($command eq 'add-static') {
2886      print "List of options for command: $command\n";
2887      print " -d : domain set attachment (mandatory)\n";
2888      print " -i : internet IP address (mandatory)\n";
2889      print " -h : computer hostname (mandatory)\n";
2890      print " -m : physical MAC address (mandatory)\n";
2891      print " -c : comment (mandatory). Example: 2014-04-07 DELL Laptop 6400 - Olivier Toto (INFO)\n";
2892      print "Example:\n";
2893      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";
2894      }
2895
2896   elsif ($command eq 'add-virtual') {
2897      print "List of options for command: $command\n";
2898      print " -d : domain set attachment (mandatory)\n";
2899      print " -i : internet IP address (mandatory)\n";
2900      print " -h : computer hostname (mandatory)\n";
2901      print " -c : comment (mandatory). Example: 2014-04-07 DELL Laptop 6400 - Olivier Toto (INFO)\n";
2902      print "Example:\n";
2903      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";
2904      }
2905
2906   elsif ($command eq 'add-alias') {
2907      print "List of options for command: $command\n";
2908      print " -d : domain set attachment (mandatory)\n";
2909      print " -h : computer hostname (mandatory)\n";
2910      print " -a : computer alias name (mandatory)\n";
2911      }
2912
2913   elsif ($command eq 'create-domainset') {
2914      print "List of options for command: $command\n";
2915      print " -d : new domain set (mandatory)\n";
2916      print " -e : DNS domain name extension( mandatory). Example legi.grenoble-inp.fr\n";
2917      print " -c : comment (mandatory). Example: 2016-08-22 VLAN legi-261 (INFO)\n";
2918      print "Examples:\n";
2919      print " ddt create_domainset -d legi-264 -e legi.grenoble-inp.fr -c '2016-08-22 VLAN legi-261 (INFO)'\n";
2920      }
2921
2922   elsif ($command eq 'create-pool') {
2923      print "List of options for command: $command\n";
2924      print " -p : name of the DHCP pool. Example: pool-legi-priv\n";
2925      print " -d : domain set attachment for the pool. (domain set attachment must exist in file $COMPUTER_BASENAME.conf). Example: legi.grenoble-inp.fr\n";
2926      print " -f : configuration filename on the DHCP server for the pool\n";
2927      print " -i : adresse(s) IP ou plage d'IP. Séparateur d'adresses IP: ','. Séparateur de plage '-'\n";
2928      print "Examples:\n";
2929      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";
2930      print " ddt -p turbocavit -d legi-sector03 -f pool-legi-public -i 192.168.10.1-192.168.10.4\n";
2931      }
2932
2933   elsif ($command eq 'create-pxe') {
2934      print "List of options for command: $command\n";
2935      print " -b : name of the PXE/BOOTP configuration. Example: most\n";
2936      print " -n : internet IP address for the DHCP next-server.\n";
2937      print " -f : filename on TFTP server to load at boot\n";
2938      print " -c : comment (mandatory). Example: 2014-04-07 PXE Boot for CentOS (MOST)\n";
2939      }
2940
2941   elsif ($command eq 'remove-pxe') {
2942      print "List of options for command: $command\n";
2943      print " -b : name of the PXE/BOOTP configuration. Example: most\n";
2944      }
2945
2946   elsif ($command eq 'enable-pxe') {
2947      print "List of options for command: $command\n";
2948      print " -h : computer hostname (mandatory unless option -i)\n";
2949      print " -i : internet IP address (mandatory unless option -h)\n";
2950      print " -d : domain set attachment (mandatory if option -h)\n";
2951      print " -b : name of the PXE/BOOTP configuration. Example: most\n";
2952      }
2953
2954   elsif ($command eq 'disable-pxe') {
2955      print "List of options for command: $command\n";
2956      print " -h : computer hostname (mandatory unless option -i)\n";
2957      print " -i : internet IP address (mandatory unless option -h)\n";
2958      print " -d : domain set attachment (mandatory if option -h)\n";
2959      }
2960
2961   elsif ($command eq 'create-tag') {
2962      print "List of options for command: $command\n";
2963      print " -t : name of the TAG (mandatory). Example: restricted\n";
2964      print " -c : comment (mandatory). Example: 2014-04-07 tag restricted (INFO)\n";
2965      print "tag 'universal' is intrinsic\n";
2966      }
2967
2968   elsif ($command eq 'remove-tag') {
2969      print "List of options for command: $command\n";
2970      print " -b : name of the TAG. Example: restricted\n";
2971      }
2972
2973   elsif ($command eq 'change-mac') {
2974      print "List of options for command: $command\n";
2975      print " -d : domain set attachment (mandatory). Example: -d legi-sector03\n";
2976      print " -h : computer hostname (mandatory unless option -i)\n";
2977      print " -i : internet IP address (mandatory unless option -h). Possible value: classical IP address or the keyword 'pool'\n";
2978      print " -m : physical MAC address (mandatory). Example: -m 0F:58:AB:2A:22:11\n";
2979      }
2980
2981   elsif ($command eq 'change-ip') {
2982      print "List of options for command: $command\n";
2983      print " -d : domain set attachment (mandatory). Example: -d legi-sector03\n";
2984      print " -h : computer hostname (mandatory)\n";
2985      print " -i : new internet IP address (mandatory). Possible value: classical IP address\n";
2986      }
2987
2988   elsif ($command eq 'change-host') {
2989      print "List of options for command: $command\n";
2990      print " -d : domain set attachment (mandatory). Example: -d legi-sector03\n";
2991      print " -i : internet IP address (mandatory). Possible value: classical IP address\n";
2992      print " -h : new computer hostname (mandatory)\n";
2993      print "It's not possible to change hostname for computer that belongs to a pool\n";
2994      }
2995
2996   elsif ($command eq 'change-comment') {
2997      print "List of options for command: $command\n";
2998      print " -d : domain set attachment (mandatory). Example: -d legi-sector03\n";
2999      print " -m : physical MAC address (mandatory). Example: -m 0F:58:AB:2A:22:11\n";
3000      print " -c : new comment (mandatory)\n";
3001      }
3002
3003   elsif ($command eq 'change-domainset') {
3004      print "List of options for command: $command\n";
3005      print " -d : new domain set attachment (mandatory). Example: -d legi-661\n";
3006      print " -m : physical MAC address (mandatory). Example: -m 0F:58:AB:2A:22:11\n";
3007      print " -i : internet IP address (mandatory)\n";
3008      }
3009
3010   elsif ($command eq 'change-tag') {
3011      print "List of options for command: $command\n";
3012      print " -h : computer hostname (mandatory unless option -i or -m)\n";
3013      print " -d : domain set attachment (mandatory). Example: -d legi-sector03\n";
3014      print " -i : internet IP address (mandatory unless option -h or -m)\n";
3015      print " -m : physical MAC address (mandatory unless option -h or -i, priority). Example: -m 0F:58:AB:2A:22:11\n";
3016      print " -t : list of tags separated by comma (mandatory). Example: -t internal,windows\n";
3017      }
3018
3019   elsif ($command eq 'load-database') {
3020      print "List of options for command: $command\n";
3021      print " -d : domain set attachment\n";
3022      print " -f : input file in DHCP format\n";
3023      print " -k : possible cases (kind): dhcp, pool-dhcp, fix-address\n";
3024      }
3025
3026   elsif ($command eq 'enable-pc') {
3027      print "List of options for command: $command\n";
3028      print " -h : computer hostname (mandatory unless option -i)\n";
3029      print " -i : internet IP address (mandatory unless option -h)\n";
3030      print " -d : domain set attachment (mandatory if option -h)\n";
3031      print "Examples:\n";
3032      print " ddt enable_pc -i 192.168.10.1\n";
3033      print " ddt enable_pc -d hmg.priv -h kevinpc\n";
3034      }
3035
3036   elsif ($command eq 'enable-float') {
3037      print "List of options for command: $command\n";
3038      print " -m : physical MAC address (mandatory)\n";
3039      print " -p : name of the DHCP pool (mandatory)\n";
3040      }
3041
3042   elsif ($command eq 'disable-float') {
3043      print "List of options for command: $command\n";
3044      print " -m : physical MAC address (mandatory)\n";
3045      print " -p : name of the DHCP pool (mandatory)\n";
3046      }
3047
3048   elsif ($command eq 'disable-pc') {
3049      print "List of options for command: $command\n";
3050      print " -h : computer hostname (mandatory unless option -i)\n";
3051      print " -i : internet IP address (mandatory unless option -h)\n";
3052      print " -d : domain set attachment (mandatory if option -h)\n";
3053      print "Examples:\n";
3054      print " ddt disable_pc -i 192.168.10.1\n";
3055      print " ddt disable_pc -d hmg.priv -h kevinpc\n";
3056      }
3057
3058   elsif ($command eq 'del-pc') {
3059      print "List of options for command: $command\n";
3060      print " -d : domain set attachment (mandatory)\n";
3061      print " -h : computer hostname (mandatory unless option -i)\n";
3062      print " -i : internet IP address (mandatory unless option -h)\n";
3063      }
3064
3065   elsif ($command eq 'del-float') {
3066      print "List of options for command: $command\n";
3067      print " -m : physical MAC address (mandatory)l\n";
3068      print " -p : name of the DHCP pool\n";
3069      }
3070
3071   elsif ($command eq 'search-mac') {
3072      print "List of options for command: $command\n";
3073      print " -m : physical MAC address (mandatory). Example: -m 0F:58:AB:2A:22:11\n";
3074      }
3075
3076   else {
3077      print "No help for command: $command\n";
3078      }
3079   exit;
3080   }
3081
3082#-------------------------------------------------------------------------------
3083
3084sub cmd_version {
3085
3086   print <<'END';
3087ddt - management of computer names and IP addresses
3088Copyright (C) 2006-2018, LEGI UMR 5519 / CNRS UGA G-INP, Grenoble, France
3089Main author Gabriel Moreau <Gabriel.Moreau(A)univ-grenoble-alpes.fr>
3090License GNU GPL version 2 or later and Perl equivalent
3091END
3092
3093   print "Database Version 1\n";
3094   print "Version $VERSION\n\n";
3095   print ' $Id: ddt 329 2018-08-27 11:30:00Z g7moreau $'."\n";
3096   return;
3097   }
3098
3099#-------------------------------------------------------------------------------
3100#Nom: usage
3101#Description: message d'aide sur les commandes du script
3102
3103sub cmd_help {
3104   print <<END;
3105ddt - management of computer names and IP addresses
3106
3107 ddt add-alias [--hostname|-h hostname] [--domainset|-d domainset] [--alias|-a alias]
3108 ddt add-dhcp [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip] [--mac|-m mac] [--comment|-c comment]
3109 ddt add-float [--pool|-p pool] [--domainset|-d domainset] [--mac|-m mac] [--comment|-c comment]
3110 ddt add-static [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip] [--mac|-m mac] [--comment|-c comment]
3111 ddt add-virtual [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip] [--comment|-c comment]
3112 ddt change-comment [--domainset|-d domainset] [--mac|-m mac] [--comment|-c comment]
3113 ddt change-domainset [--domainset|-d domainset] [--ip|-i ip] [--mac|-m mac]
3114 ddt change-host [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip]
3115 ddt change-ip [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip]
3116 ddt change-mac [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip] [--mac|-m mac]
3117 ddt change-tag [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip] [--mac|-m mac] [--tag|-t tag]
3118 ddt check-dns
3119 ddt create-domainset [--domainset|-d domainset] [--dns-extension|-e dns_extension] [--comment|-c comment]
3120 ddt create-pool [--pool|-p pool] [--domainset|-d domainset] [--file-pool|-f file_pool] [--ipaddress-pool|-i ipaddress_pool]
3121 ddt create-pxe [--bootp|-b pxe_config] [--next-server|-n next_server] [--filename|-f filename] [--comment|-c comment]
3122 ddt create-tag [--tag|-t tag] [--comment|-c comment]
3123 ddt del-float [--pool|-p pool] [--mac|-m mac]
3124 ddt del-pc [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip]
3125 ddt disable-pc [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip]
3126 ddt disable-float [--pool|-p pool] [--mac|-m mac]
3127 ddt disable-pxe [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip]
3128 ddt enable-float [--pool|-p pool] [--mac|-m mac]
3129 ddt enable-pc [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip]
3130 ddt enable-pxe [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip] [--bootp|-b pxe_config]
3131 ddt gen-dhcp-file
3132 ddt gen-dns-file
3133 ddt help
3134 ddt load-database [--domainset|-d domainset] [--filename|-f filename] [--kind|-k kind]
3135 ddt remove-pxe [--bootp|-b pxe_config]
3136 ddt remove-tag [--tag|-t tag]
3137 ddt search-mac [--mac|-m mac]
3138 ddt show-domainset [--no-header|-H]
3139 ddt show
3140 ddt show-pool [--no-header|-H]
3141 ddt show-pxe [--no-header|-H]
3142 ddt show-tag [--no-header|-H]
3143 ddt version
3144
3145COMMANDS
3146
3147 * add-alias        : add an alias for a computer (like CNAME for the DNS)
3148 * add-dhcp         : add a computer with a fix DHCP IP or in a DHCP pool
3149 * add-float        : add a computer with an IP in a DHCP pool
3150 * add-static       : add a computer with a static IP
3151 * add-virtual      : add a virtual computer with a static IP but a virtual MAC (useful to declare float computer in DNS)
3152 * change-comment   : change the computer comment
3153 * change-domainset : change the domain set attachment for a computer
3154 * change-host      : change the computer hostname
3155 * change-ip        : change the computer IP address
3156 * change-mac       : change the computer physical MAC address
3157 * change-tag       : change the list of TAGs associated to a computer
3158 * check-dns        : check the DNS table for base IPs
3159 * create-domainset : create a new domain set
3160 * create-pool      : create a new pool for DHCP records
3161 * create-pxe       : create a new PXE/BOOTP configuration
3162 * create-tag       : create a new TAG
3163 * del-float        : remove a computer from a DHCP pool
3164 * del-pc           : remove a computer (DHCP or static IP) from the YAML database
3165 * disable-pc       : disable a computer (DHCP and/or DNS) (but keep it in the database)
3166 * disable-float    : disable a computer from a DHCP pool (but keep it in the database)
3167 * disable-pxe      : remove PXE/BOOTP configuration on a computer
3168 * enable-float     : enable a previous disable computer (DHCP and/or DNS)
3169 * enable-pc        : enable a previous disable computer (DHCP and/or DNS)
3170 * enable-pxe       : enable PXE/BOOTP configuration on a computer
3171 * gen-dhcp-file    : generate DHCP files for the isc DHCP server
3172 * gen-dns-file     : generate DNS files for the bind domain server
3173 * help             : this help
3174 * load-database    : load the YAML database (be careful)
3175 * remove-pxe       : remove a PXE/BOOTP configuration
3176 * remove-tag       : remove a TAG
3177 * search-mac       : search physical MAC address computer
3178 * show-domainset   : list all domain set group of computer
3179 * show             : list all computers
3180 * show-pool        : list all pool
3181 * show-pxe         : list PXE/BOOTP configuration
3182 * show-tag         : list all TAGs
3183 * version          : return program version
3184END
3185   return;
3186   }
3187
3188################################################################
3189# documentation
3190################################################################
3191
3192__END__
3193
3194=head1 NAME
3195
3196ddt - management of computer names and IP addresses
3197
3198
3199=head1 USAGE
3200
3201 ddt add-alias [--hostname|-h hostname] [--domainset|-d domainset] [--alias|-a alias]
3202 ddt add-dhcp [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip] [--mac|-m mac] [--comment|-c comment]
3203 ddt add-float [--pool|-p pool] [--domainset|-d domainset] [--mac|-m mac] [--comment|-c comment]
3204 ddt add-static [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip] [--mac|-m mac] [--comment|-c comment]
3205 ddt add-virtual [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip] [--comment|-c comment]
3206 ddt change-comment [--domainset|-d domainset] [--mac|-m mac] [--comment|-c comment]
3207 ddt change-domainset [--domainset|-d domainset] [--ip|-i ip] [--mac|-m mac]
3208 ddt change-host [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip]
3209 ddt change-ip [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip]
3210 ddt change-mac [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip] [--mac|-m mac]
3211 ddt change-tag [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip] [--mac|-m mac] [--tag|-t tag]
3212 ddt check-dns
3213 ddt create-domainset [--domainset|-d domainset] [--dns-extension|-e dns_extension] [--comment|-c comment]
3214 ddt create-pool [--pool|-p pool] [--domainset|-d domainset] [--file-pool|-f file_pool] [--ipaddress-pool|-i ipaddress_pool]
3215 ddt create-pxe [--bootp|-b pxe_config] [--next-server|-n next_server] [--filename|-f filename] [--comment|-c comment]
3216 ddt create-tag [--tag|-t tag] [--comment|-c comment]
3217 ddt del-float [--pool|-p pool] [--mac|-m mac]
3218 ddt del-pc [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip]
3219 ddt disable-pc [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip]
3220 ddt disable-float [--pool|-p pool] [--mac|-m mac]
3221 ddt disable-pxe [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip]
3222 ddt enable-float [--pool|-p pool] [--mac|-m mac]
3223 ddt enable-pc [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip]
3224 ddt enable-pxe [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip] [--bootp|-b pxe_config]
3225 ddt gen-dhcp-file
3226 ddt gen-dns-file
3227 ddt help
3228 ddt load-database [--domainset|-d domainset] [--filename|-f filename] [--kind|-k kind]
3229 ddt remove-pxe [--bootp|-b pxe_config]
3230 ddt remove-tag [--tag|-t tag]
3231 ddt search-mac [--mac|-m mac]
3232 ddt show-domainset [--no-header|-H]
3233 ddt show
3234 ddt show-pool [--no-header|-H]
3235 ddt show-pxe [--no-header|-H]
3236 ddt show-tag [--no-header|-H]
3237 ddt version
3238
3239
3240=head1 DESCRIPTION
3241
3242DDT is an acronym for DHCP-DNS-Tools.
3243The previous command name was not C<ddt> but just C<dhcp-dns-tools>...
3244In practise, DDT is an IP Address Management (IPAM) service.
3245It has been used in the LEGI laboratory for over 10 years.
3246
3247The tool is quite effective and tries to keep things simple
3248but easily configurable for your site like a swiss army knife.
3249Everything is saved in a YAML database
3250and entries could be added, deleted, or modified by the command line.
3251
3252
3253=head1 COMMANDS
3254
3255=head2 add-alias
3256
3257 ddt add-alias [--hostname|-h hostname] [--domainset|-d domainset] [--alias|-a alias]
3258
3259=head2 add-dhcp
3260
3261 ddt add-dhcp [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip] [--mac|-m mac] [--comment|-c comment]
3262
3263=head2 add-float
3264
3265 ddt add-float [--pool|-p pool] [--domainset|-d domainset] [--mac|-m mac] [--comment|-c comment]
3266
3267=head2 add-static
3268
3269 ddt add-static [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip] [--mac|-m mac] [--comment|-c comment]
3270
3271=head2 add-virtual
3272
3273 ddt add-virtual [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip] [--comment|-c comment]
3274
3275=head2 change-comment
3276
3277 ddt change-comment [--domainset|-d domainset] [--mac|-m mac] [--comment|-c comment]
3278
3279=head2 change-domainset
3280
3281 ddt change-domainset [--domainset|-d domainset] [--ip|-i ip] [--mac|-m mac]
3282
3283=head2 change-host
3284
3285 ddt change-host [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip]
3286
3287=head2 change-ip
3288
3289 ddt change-ip [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip]
3290
3291=head2 change-mac
3292
3293 ddt change-mac [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip] [--mac|-m mac]
3294
3295=head2 change-tag
3296
3297 ddt change-tag [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip] [--mac|-m mac] [--tag|-t tag]
3298
3299=head2 check-dns
3300
3301 ddt check-dns
3302
3303=head2 create-domainset
3304
3305 ddt create-domainset [--domainset|-d domainset] [--dns-extension|-e dns_extension] [--comment|-c comment]
3306
3307=head2 create-pool
3308
3309 ddt create-pool [--pool|-p pool] [--domainset|-d domainset] [--file-pool|-f file_pool] [--ipaddress-pool|-i ipaddress_pool]
3310
3311=head2 create-pxe
3312
3313 ddt create-pxe [--bootp|-b pxe_config] [--next-server|-n next_server] [--filename|-f filename] [--comment|-c comment]
3314
3315=head2 create-tag
3316
3317 ddt create-tag [--tag|-t tag] [--comment|-c comment]
3318
3319=head2 del-float
3320
3321 ddt del-float [--pool|-p pool] [--mac|-m mac]
3322
3323=head2 del-pc
3324
3325 ddt del-pc [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip]
3326
3327=head2 disable-pc
3328
3329 ddt disable-pc [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip]
3330
3331=head2 disable-float
3332
3333 ddt disable-float [--pool|-p pool] [--mac|-m mac]
3334
3335=head2 disable-pxe
3336
3337 ddt disable-pxe [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip]
3338
3339=head2 enable-float
3340
3341 ddt enable-float [--pool|-p pool] [--mac|-m mac]
3342
3343=head2 enable-pc
3344
3345 ddt enable-pc [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip]
3346
3347=head2 enable-pxe
3348
3349 ddt enable-pxe [--hostname|-h hostname] [--domainset|-d domainset] [--ip|-i ip] [--bootp|-b pxe_config]
3350
3351=head2 gen-dhcp-file
3352
3353 ddt gen-dhcp-file
3354
3355=head2 gen-dns-file
3356
3357 ddt gen-dns-file
3358
3359=head2 help
3360
3361 ddt help
3362
3363=head2 load-database
3364
3365 ddt load-database [--domainset|-d domainset] [--filename|-f filename] [--kind|-k kind]
3366
3367=head2 remove-pxe
3368
3369 ddt remove-pxe [--bootp|-b pxe_config]
3370
3371=head2 remove-tag
3372
3373 ddt remove-tag [--tag|-t tag]
3374
3375=head2 search-mac
3376
3377 ddt search-mac [--mac|-m mac]
3378
3379=head2 show-domainset
3380
3381 ddt show-domainset [--no-header|-H]
3382
3383=head2 show
3384
3385 ddt show
3386
3387=head2 show-pool
3388
3389 ddt show-pool [--no-header|-H]
3390
3391=head2 show-pxe
3392
3393 ddt show-pxe [--no-header|-H]
3394
3395=head2 show-tag
3396
3397 ddt show-tag [--no-header|-H]
3398
3399=head2 version
3400
3401 ddt version
3402
3403
3404=head1 AUTHORS
3405
3406Written by Gabriel Moreau <Gabriel.Moreau(A)univ-grenoble-alpes.fr>, Kevin Reverchon, Olivier De-Marchi - Grenoble - France
3407
3408
3409=head1 LICENSE AND COPYRIGHT
3410
3411License GNU GPL version 2 or later and Perl equivalent
3412
3413Copyright (C) 2006-2018, LEGI UMR 5519 / CNRS UGA G-INP, Grenoble, France
Note: See TracBrowser for help on using the repository browser.