source: trunk/ddt/ddt @ 236

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