1#!/usr/bin/perl -w 2 3####################################################################### 4# Processus d'interrogation de l'ensemble des equipements Osiris 5# - Interrogation SNMP + generation de graphes rrdtools 6# - Mise a jour de la base d'association Postgres pour les AP WiFi 7# - Mise a jour des fichiers d'etat du spanning tree pour l'ensemble 8# des commutateurs du parc Osiris 9# 10# Ce processus travaille avec des sondes qui interrogent les 11# equipements. 12# 13# parametres : 14# option : indique si le processus travaille sur l'ensemble des sondes, sur 15# une liste de type de sonde executer ou a ignorer 16# 17# Les 2 parametres suivants determinent la maniere dont les processus 18# vont se partager l'execution des sondes 19# num_process : donne le numero du process 20# nb_process : donne le nombre total de processus 21 22use strict; 23use warnings; 24use Sys::Syslog; # Misses setlogsock. 25use Sys::Syslog qw(:DEFAULT setlogsock); # Also gets setlogsock 26use Net::SNMP; 27use SNMP_util; 28use Socket; 29use RRDs; 30use DBI; 31use POSIX; 32 33our $group = $ARGV[0]; 34our $num_process = $ARGV[1]; 35our $nb_process = $ARGV[2]; 36 37require "%NMLIBDIR%/libmetro.pl"; 38 39# lecture du fichier de configuration general 40our $conf_file = "%CONFFILE%"; 41our %global_conf = read_global_conf_file($conf_file); 42 43# check parameters, if one of them emty, set it to default value 44check_params(); 45 46our %config = (); 47 48$config{dir_lock} = $global_conf{metrodatadir} . "/lock" ; 49$config{defaultdomain} = $global_conf{defaultdomain}; 50$config{syslog_facility} = $global_conf{"pollerlogfacility"}; 51$config{path_probes} = "%NMLIBDIR%/probes"; 52$config{path_poll} = $global_conf{metrodatadir} . "/poller"; 53$config{path_rrd_db} = $global_conf{metrodatadir} . "/db"; 54$config{path_cache_probes} = $global_conf{metrodatadir} . "/cache"; 55$config{dir_plugins} = "%NMLIBDIR%/plugins"; 56$config{dir_report} = $global_conf{metrodatadir} . "/report"; 57# recuperation du groupe de pollers 58$config{options} = $global_conf{"gpopt_$group"}; 59# arguments de connexion a la base PSQL 60$config{PGHOST} = $global_conf{macdbhost}; 61$config{PGDATABASE} = $global_conf{macdbname}; 62$config{PGUSER} = $global_conf{macdbuser}; 63$config{PGPASSWORD} = $global_conf{macdbpassword}; 64$config{fichier_etat} = $global_conf{metrodatadir} . "/wifi/ap_state.txt"; 65 66# timeout snmp 67$config{snmp_timeout} = $global_conf{snmptimeout}; 68 69# liste des sondes 70our %function_probes = ( 71 'ifNom-ap' => \&ifNom_ap, 72 'ifNom-snmp64' => \&ifNom_counter64, 73 'ifNom-broadcast64' => \&ifNom_broadcast64, 74 'broadcast' => \&ifNom_broadcast64, 75 'ifNom-multicast64' => \&ifNom_multicast64, 76 'multicast' => \&ifNom_multicast64, 77 'ifNom_error' => \&ifNom_error, 78 'ifNom-snmp32' => \&ifNom_counter32, 79 'ifIP-snmp' => \&get_if_by_ip, 80 'get_value_generic' => \&get_generic, 81 'plugin' => \&get_plugins, 82 'ipmac' => \&get_arp_table, 83 'portmac.cisco' => \&get_portmac_cisco, 84 'portmac.hp' => \&get_portmac_hp, 85 'portmac.juniper' => \&get_portmac_juniper 86); 87 88# load all probes 89require $config{path_probes} . "/sensor-if-snmp-ap.pl"; 90require $config{path_probes} . "/sensor-if-snmp64.pl"; 91require $config{path_probes} . "/sensor-if-snmp32.pl"; 92require $config{path_probes} . "/sensor-if-by-ip.pl"; 93require $config{path_probes} . "/sensor-generic-gauge.pl"; 94require $config{path_probes} . "/sensor-plugins.pl"; 95require $config{path_probes} . "/sensor-if-broadcast.pl"; 96require $config{path_probes} . "/sensor-if-multicast.pl"; 97require $config{path_probes} . "/sensor-if-error.pl"; 98require $config{path_probes} . "/sensor-arp-table.pl"; 99require $config{path_probes} . "/sensor-portmac.pl"; 100 101our $lock_cache_file = 0; 102our $maj_cache_file = 0; 103 104our %collsess; 105our %liste_ap; 106our %liste_ap_state; 107our %ApSnmpHashref = (); 108our %APSupSSID = (); 109our @total_activesess = (); 110our @total_authsess = (); 111our %mac_auth; 112 113our %ok_sondes = (); 114our %nok_sondes = (); 115 116init_test_sondes(); 117 118# recuperation de la date et heure de lancement du script 119our %time = get_time("NOW"); 120 121# lectures des options passees en parametres 122$ok_sondes{'all'} = 1; 123 124my @liste_options = split(/,/,$config{'options'}); 125foreach my $elem (@liste_options) 126{ 127 if($elem=~m/^!(.*)/) 128 { 129 $nok_sondes{$1} = 1; 130 } 131 else 132 { 133 $ok_sondes{$elem} = 1; 134 $ok_sondes{'all'} = 0; 135 } 136} 137 138# multiprocessus calcul du resultat du modulo pour matcher une sonde 139our $modulo_match = $num_process % $nb_process; 140 141# Creation d'une socket syslog unix 142setlogsock("unix"); 143 144# Message des logs demarrage du d�mon #################### 145writelog("poller_$group$num_process",$config{'syslog_facility'},"info", 146 "\t -> START. Demarrage du polling ########"); 147 148 149################################################################## 150# gestion specifique pour les AP WiFi 151# recuperation de la liste des authentifies sur le WiFi 152if($ok_sondes{'assoc_ap'} == 1 && check_periodicity("*/5 * * * *")) 153{ 154 writelog("poller_$group$num_process",$config{'syslog_facility'},"info", 155 "\t -> INFO : Recuperation des authentifies du reseau sans fil ..."); 156 157 get_authaccess(); 158} 159 160################################################################# 161# Traitement des sondes 162# 163opendir(MAJDIR, $config{'path_poll'}); 164our @FICHIERS=grep(/(\.sensor|\.plugin)$/, readdir MAJDIR); 165closedir(MAJDIR); 166 167# lecture des fichiers en cache 168our %idxcache; 169 170if(open(CACHE,"$config{path_cache_probes}/idx.cache")) 171{ 172 while(my $l=<CACHE>) 173 { 174 chomp $l; 175 if($l =~ /(.+);(.+);(.+)/) 176 { 177 $idxcache{$1}{$2} = $3; 178 } 179 } 180 close(CACHE); 181} 182else 183{ 184 writelog("poller_$group$num_process",$config{'syslog_facility'},"info", 185 "\t -> ERROR : fichier de cache : $!"); 186} 187 188read_tab_asso(%idxcache); 189 190 191my $elem; 192my $compteur = 0; 193foreach $elem (@FICHIERS) 194{ 195 $compteur += ouvre_fichier_conf($elem); 196} 197 198writelog("poller_$group$num_process",$config{'syslog_facility'},"info", 199 "\t -> $compteur sondes"); 200 201Net::SNMP->snmp_dispatcher(); 202 203# ecriture des fichiers qui stockent les index snmp des interfaces 204maj_if_files(); 205 206######## 207 208################################################################## 209# gestion specifique pour les AP WiFi 210if($ok_sondes{'assoc_ap'} == 1 && check_periodicity("*/5 * * * *")) 211{ 212 ################################### 213 # cr�ation du tableau d'�tat des AP 214 writelog("poller_$group$num_process",$config{'syslog_facility'},"info", 215 "\t -> Ecriture du fichier de supervision des AP"); 216 217 maj_liste_ap_state(); 218 219 ################################################################ 220 ## mise � jour de la base des associations WiFi 221 writelog("poller_$group$num_process",$config{'syslog_facility'},"info", 222 "\t -> MAJ de la base des associations WIFI"); 223 224 set_assoc_ap_base(); 225} 226######## 227 228 229writelog("poller_$group$num_process",$config{'syslog_facility'},"info", 230 "\t -> STOP. Fin du polling ###############"); 231######## 232 233 234 235################################################################## 236# FONCTIONS 237################################################################## 238 239################################################################## 240# mise � jour des fichiers contenant les index SNMP des interfaces 241# des �quipements connus 242sub maj_if_files 243{ 244 my $i; 245 my @fichier; 246 247 if($maj_cache_file == 1) 248 { 249 if(check_lock_file($config{'dir_lock'},"metropollercache.lock","metropoller") == 0) 250 { 251 # on locke tant que l'appli tourne 252 create_lock_file($config{'dir_lock'},"metropollercache.lock","metropoller"); 253 254 writelog("poller_$group$num_process",$config{'syslog_facility'},"info", 255 "\t -> INFO : Mise a jour du fichier de cache"); 256 257 open(BD,">$config{path_cache_probes}/idx.cache"); 258 259 foreach my $key (keys %idxcache) 260 { 261 foreach my $kkey (keys %{$idxcache{$key}}) 262 { 263 my $string = "$key;$kkey;$idxcache{$key}{$kkey}"; 264 if($string =~ /(.+);(.+);(.+)/) 265 { 266 print BD "$string\n"; 267 } 268 } 269 } 270 271 close(BD); 272 273 # suppression du verrou 274 delete_lock_file("$config{'dir_lock'}/metropollercache.lock"); 275 } 276 else 277 { 278 writelog("poller_$group$num_process",$config{'syslog_facility'},"info", 279 "\t WARNING fichier de cache locke"); 280 } 281 } 282} 283 284 285############################################################### 286# lecture des fichiers contenant les ordres de polling 287sub ouvre_fichier_conf 288{ 289 my ($file) = @_; 290 my ($sonde,$base,$host,$community,$l_param,$periodicity); 291 my $ok = 0; 292 my $num_ligne = 0; 293 294 open(FILE, "$config{'path_poll'}/$file"); 295 296 #print LOG "fichier : $config{'path_poll'}/$file\n"; 297 298 while(<FILE>) 299 { 300 if(! /^#/ && ! /^\s+/) 301 { 302 chomp; 303 # detection d'un parametre de periodicite facon cron pour savoir si la sonde doit etre executee 304 if(/(.*);(.*)/) 305 { 306 $periodicity = $1; 307 ($sonde,$base,$host,$community,$l_param) = (split(/\s+/,$2))[0,1,2,3,4]; 308 } 309 # aucun parametre de periodicite, la sonde est execute par defaut 310 else 311 { 312 $periodicity = "*/5 * * * *"; 313 ($sonde,$base,$host,$community,$l_param) = (split(/\s+/,$_))[0,1,2,3,4]; 314 } 315 316 $num_ligne ++; 317 318 #print LOG "ligne : $periodicity;$sonde,$base,$host,$community,$l_param\n"; 319 320 # multiprocessus : ce processus doit-il traiter cette ligne? 321 my $test_modulo = $num_ligne % $nb_process; 322 323 if($test_modulo == $modulo_match) 324 { 325 if(check_periodicity($periodicity)) 326 { 327 $ok ++; 328 # nettoyage du nom de la sonde 329 $sonde = clean_probe($sonde); 330 331 # parametres a appliquer dans l'appel de chaque fonction 332 # $base,$host,$community,$l_param,$sonde 333 if(defined($function_probes{$sonde})) 334 { 335 if(($ok_sondes{'all'} == 1 || $ok_sondes{$sonde} == 1) && $nok_sondes{$sonde} != 1) 336 { 337 $function_probes{$sonde}->($base,$host,$community,$l_param,$sonde,$periodicity); 338 } 339 else 340 { 341 $ok --; 342 } 343 } 344 else 345 { 346 if(($ok_sondes{'all'} == 1 || $ok_sondes{$sonde} == 1) && $nok_sondes{$sonde} != 1) 347 { 348 writelog("poller_$group$num_process",$config{'syslog_facility'},"info", 349 "\t -> WARNING: Sonde $sonde inexistante"); 350 # aucune sonde trouvee, n'a rien fait 351 $ok --; 352 } 353 } 354 } 355 } 356 } 357 } 358 close(FILE); 359 360 return $ok; 361} 362 363 364###################################### 365# Nettoie le nom des sondes dans update_rrd qui disposent encore 366# du chemin /local/obj999 .... 367sub clean_probe 368{ 369 my ($sonde) = @_; 370 371 my @decomp_rep = split(/\//,$sonde); 372 my $t_decomp_rep = @decomp_rep; 373 ($sonde) = (split(/\.pl/,$decomp_rep[$t_decomp_rep - 1]))[0]; 374 375 return $sonde; 376} 377 378 379########################################################## 380# fonction de mise � jour du fichier de supervision des AP 381sub maj_liste_ap_state 382{ 383 my $key; 384 385 open(STATE,">$config{'fichier_etat'}"); 386 foreach $key (keys %liste_ap_state) 387 { 388 print STATE "$key=$liste_ap_state{$key}\n"; 389 } 390 close(STATE); 391} 392 393 394############################################################ 395# initialisation des booleens qui indiquent au programme 396# les types de sondes a executer 397sub init_test_sondes 398{ 399 foreach my $key (keys %function_probes) 400 { 401 $ok_sondes{$key} = 0; 402 $nok_sondes{$key} = 0; 403 } 404} 405 406############################################################ 407# cree un tableau nominatif avec les index sql des tous les 408# ssid du reseau wifi 409sub init_list_ssid 410{ 411 my ($l) = @_; 412 413 my %l_ssid; 414 415 chomp $l; 416 my @ll = split(/,/,$l); 417 418 foreach my $s (@ll) 419 { 420 $l_ssid{$s} = read_conf_file("$conf_file","ID_SQL_$s"); 421 } 422 423 return %l_ssid; 424} 425 426############################################################ 427# controle le parametre de periodicite du lancement d'une sonde 428# exemple : 429# */5 * * * * : toutes les 5 minutes 430# * */1 * * * : toute les heures 431# sinon renseigner a la maniere de cron : 432# minute hour mday month wday (1 = lundi) 433# exemple : * * * * 1 : tous les lundi 434# 435# renvoie 1 si la sonde doit etre lancee 436sub check_periodicity 437{ 438 my($periodicity) = @_; 439 440 my($mwday,$mmonth,$mmday); 441 #print LOG "$periodicity, time = $time{WDAY}, $time{MON}, $time{MDAY}, $time{HOUR}:$time{MIN}\n"; 442 443 my($min,$hour,$mday,$month,$wday) = (split(/\s+/,$periodicity))[0,1,2,3,4]; 444 445 if($wday eq "*" || $wday !~/[1-7]/) 446 { 447 $mwday = $wday; 448 $wday = "0,1,2,3,4,5,6"; 449 } 450 if($month eq "*" || $month !~/[1-12]/) 451 { 452 $mmonth = $month; 453 $month = "1,2,3,4,5,6,7,8,9,10,11,12"; 454 } 455 if($mday eq "*" || $mday !~/[1-31]/) 456 { 457 $mmday = $mday; 458 $mday = "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31"; 459 } 460 if($min eq "*") 461 { 462 if($mwday =~/[0-6]/ || $mmonth =~/[1-12]/ || $mmday =~/[1-31]/) 463 { 464 $min = 0; 465 } 466 else 467 { 468 $min = "0-59"; 469 } 470 } 471 elsif($min =~/\*\/([0-9]+)/) 472 { 473 my $temp_min =""; 474 475 for(my $i=0;$i<60;$i++) 476 { 477 my $modulo = $i % $1; 478 if($modulo == 0) 479 { 480 $temp_min = "$temp_min" . "$i,"; 481 } 482 } 483 $min = $temp_min; 484 } 485 if($hour eq "*") 486 { 487 if($mwday =~/[0-6]/ || $mmonth =~/[1-12]/ || $mmday =~/[1-31]/) 488 { 489 $hour = 0; 490 } 491 else 492 { 493 $hour = "0-23"; 494 } 495 } 496 elsif($hour =~/\*\/([0-9]+)/) 497 { 498 my $temp = ""; 499 500 for(my $i=0;$i<23;$i++) 501 { 502 my $modulo = $i % $1; 503 if($modulo == 0) 504 { 505 $temp = "$temp" . "$i,"; 506 } 507 } 508 $hour = $temp; 509 } 510 511 512 my $etap_check = 0; 513 514 my @l_wday = split(/,/,$wday); 515 for (my $i=0;$i<@l_wday;$i++) 516 { 517 # print LOG "WDAY : $l_wday[$i] == $time{WDAY}"; 518 519 if($l_wday[$i] == $time{WDAY}) 520 { 521 # on est dans le bon jour de la semaine pour executer la sonde 522 $i = @l_wday; 523 $etap_check =1; 524 } 525 } 526 if($etap_check == 1) 527 { 528 #print LOG "=> OK\n"; 529 530 my @l_month = split(/,/,$month); 531 for (my $i=0;$i<@l_month;$i++) 532 { 533 # print LOG "MON : $l_month[$i] == $time{MON}"; 534 535 if($l_month[$i] == $time{MON}) 536 { 537 # on est dans le bon mois pour executer la sonde 538 $i = @l_month; 539 $etap_check =2; 540 } 541 } 542 } 543 if($etap_check == 2) 544 { 545 #print LOG "=> OK\n"; 546 547 my @l_mday = split(/,/,$mday); 548 for (my $i=0;$i<@l_mday;$i++) 549 { 550 #print LOG "MDAY : $l_mday[$i] == $time{MDAY}"; 551 552 if($l_mday[$i] == $time{MDAY}) 553 { 554 # on est dans le bon mois pour executer la sonde 555 $i = @l_mday; 556 $etap_check =3; 557 } 558 } 559 } 560 if($etap_check == 3) 561 { 562 #print LOG "=> OK\n"; 563 564 if($hour eq "0-23") 565 { 566 $etap_check =4; 567 568 #print LOG "HOUR : $hour == $time{HOUR}"; 569 } 570 else 571 { 572 my @l_hour = split(/,/,$hour); 573 for (my $i=0;$i<@l_hour;$i++) 574 { 575 # print LOG "HOUR : $l_hour[$i] == $time{HOUR}"; 576 577 if($l_hour[$i] == $time{HOUR}) 578 { 579 # on est dans le bon mois pour executer la sonde 580 $i = @l_hour; 581 $etap_check =4; 582 } 583 } 584 } 585 } 586 if($etap_check == 4) 587 { 588 if($min eq "0-59") 589 { 590 return 1; 591 592 #print LOG "=> OK\n"; 593 } 594 else 595 { 596 my @l_min= split(/,/,$min); 597 for (my $i=0;$i<@l_min;$i++) 598 { 599 if($l_min[$i] == $time{MIN}) 600 { 601 # on est dans le bon mois pour executer la sonde 602 $i = @l_min; 603 return 1; 604 605 #print LOG "=> OK\n"; 606 } 607 } 608 } 609 } 610 return 0; 611} 612 613 614# check parameters 615sub check_params 616{ 617 if(not defined $group) 618 { 619 $group = "default"; 620 print "WARNING : process group not defined, set to default\n"; 621 } 622 if(defined $num_process and defined $nb_process and $num_process > $nb_process) 623 { 624 print "ERROR : $num_process > $nb_process. Exit.\n"; 625 usage(); 626 exit(); 627 } 628 if(not defined $num_process) 629 { 630 print "WARNING : process number not defined, set to 1, set number of processes to 1\n"; 631 usage(); 632 $num_process = 1; 633 $nb_process = 1; 634 } 635 if(not defined $nb_process) 636 { 637 print "WARNING : number of processes not defined, set to 1, set process number to 1\n"; 638 usage(); 639 $num_process = 1; 640 $nb_process = 1; 641 } 642} 643 644# print usage 645sub usage 646{ 647 print "Metropoller 648 ### 649 ./metropoller <group> <process number> <total number of processes> 650 651 - group : group of sensors. Default value 'default', 652 - process number : process number between 1 and <total number of processes>, 653 - total number of processes : total number of processes. 654 \n"; 655} 656