source: trunk/ddt/ddt @ 313

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