source: trunk/ddt/ddt @ 302

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