source: trunk/ddt/ddt @ 309

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