source: trunk/ddt/ddt @ 332

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