source: trunk/ddt/ddt @ 307

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