source: trunk/ddt/ddt @ 235

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