source: trunk/ddt/ddt @ 305

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