- Timestamp:
- 02/29/08 20:15:18 (4 years ago)
- Files:
-
- people/jo/multilevel-groups-3/server/Munin.pm.in (modified) (23 diffs)
- people/jo/multilevel-groups-3/server/munin-domainview.tmpl.in (modified) (5 diffs)
- people/jo/multilevel-groups-3/server/munin-graph.in (modified) (14 diffs)
- people/jo/multilevel-groups-3/server/munin-html.in (modified) (4 diffs)
- people/jo/multilevel-groups-3/server/munin-limits.in (modified) (5 diffs)
- people/jo/multilevel-groups-3/server/munin-nodeview.tmpl.in (modified) (4 diffs)
- people/jo/multilevel-groups-3/server/munin-overview.tmpl.in (modified) (1 diff)
- people/jo/multilevel-groups-3/server/munin-serviceview.tmpl.in (modified) (3 diffs)
- people/jo/multilevel-groups-3/server/munin-update.in (modified) (17 diffs)
- people/jo/multilevel-groups-3/server/style.css (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
people/jo/multilevel-groups-3/server/Munin.pm.in
r1440 r1502 1 1 package Munin; # -*- perl -*- 2 2 # 3 # Copyright (C) 2003-200 4Jimmy Olsen, Audun Ytterdal3 # Copyright (C) 2003-2007 Jimmy Olsen, Audun Ytterdal 4 4 # 5 5 # This program is free software; you can redistribute it and/or … … 23 23 24 24 use Exporter; 25 25 26 @ISA = ('Exporter'); 26 27 @EXPORT = ('munin_trend', … … 45 46 'munin_category_status', 46 47 'munin_get_picture_filename', 48 'munin_get_html_filename', 47 49 'munin_get_filename', 48 50 'munin_graph_column_headers', 49 51 'munin_get_max_label_length', 50 52 'munin_get_field_order', 51 'munin_get_rrd_filename' 53 'munin_get_rrd_filename', 54 'munin_get_node_name', 55 'munin_get_parent_name', 56 'munin_get_node_loc', 57 'munin_get_node', 58 'munin_set_var_loc', 59 'munin_set_var', 60 'munin_copy_node_toloc', 61 'munin_get_separated_node', 62 'munin_mkdir_p', 63 'munin_find_field', 64 'munin_get_parent', 65 'munin_get_children', 66 'munin_get_node_partialpath' 52 67 ); 53 68 … … 84 99 "tls_verify_certificate", "tls_verify_depth", "tls_ca_certificate", 85 100 "graph_data_size", "colour", "graph_printf", "ok", "unknown", 86 "palette" 101 "palette", "realservname", "cdef_name", "graphable", "process", 102 "realname" 87 103 ); 88 104 … … 90 106 91 107 # Fields to copy when "aliasing" a field 92 my @ copy_fields = ("label", "draw", "type", "rrdfile", "fieldname", "info");108 my @COPY_FIELDS = ("label", "draw", "type", "rrdfile", "fieldname", "info"); 93 109 94 110 sub munin_trend { … … 110 126 } 111 127 128 # munin_draw_field: Check whether a field will be visible in the graph or not 129 # Parameters: 130 # - $hash: A ref to the hash node for the field 131 # Returns: 132 # - Success: Boolean; true if field will be graphed, false if not 133 # - Failure: undef 112 134 sub munin_draw_field { 113 my $node = shift; 114 my $service = shift; 115 my $field = shift; 116 117 $field =~ s/=.*//; 118 119 print "DEBUG: munin_draw_field: Checking $service -> $field: " . &munin_get_bool_val ($node->{client}->{$service}->{$field.".graph"}, 1) . ".\n" if $DEBUG;; 120 return 0 if (exists $node->{client}->{$service}->{$field.".skipdraw"}); 121 return (&munin_get_bool_val ($node->{client}->{$service}->{$field.".graph"}, 1)); 135 my $hash = shift; 136 137 return 0 if munin_get_bool ($hash, "skipdraw", 0); 138 return 0 if !munin_get_bool ($hash, "graph", 1); 139 return defined $hash->{"label"}; 122 140 } 123 141 … … 218 236 my ($configfile,$overwrite) = @_; 219 237 for my $key (keys %$overwrite) { 238 next if $key =~ /^#%#/; 220 239 if (ref $overwrite->{$key}) { 221 240 &munin_overwrite($overwrite->{$key},$configfile->{$key}); … … 233 252 $conf ||= $configfile; 234 253 if (! -r $conf and ! $missingok) { 235 ::logger ("munin_readconfig: cannot open '$conf'");236 return undef;254 ::logger ("munin_readconfig: cannot open '$conf'"); 255 return undef; 237 256 } 238 257 if (open (CFG, $conf)) … … 250 269 $config->{'tmpldir'}||= "@@CONFDIR@@/templates/"; 251 270 $config->{'htmldir'}||= "@@HTMLDIR@@/"; 271 $config->{'#%#parent'}= undef; 272 $config->{'#%#name'}= "root"; 252 273 return ($config); 253 274 } … … 256 277 { 257 278 my $lines = shift; 258 my $hash = undef;279 my $hash = {}; 259 280 my $prefix = ""; 260 281 my $prevline = ""; … … 263 284 { 264 285 chomp $line; 265 #$line =~ s/(^|[^\\])#.*/$1/g if $line =~ /#/; # Skip comments...266 286 if ($line =~ /#/) { 267 287 next if ($line =~ /^#/); … … 367 387 } 368 388 369 sub munin_set_var_path 389 390 # munin_find_field: Search a hash to find nodes with $field defined 391 # Parameters: 392 # - $hash: A hash ref to search 393 # - $field: The name of the field to search for, or a regex 394 # - $avoid: [optional] Stop traversing further down if this field is found 395 # Returns: 396 # - Success: A ref to an array of the hash nodes containing $field. 397 # - Failure: undef 398 sub munin_find_field { 399 my $hash = shift; 400 my $field = shift; 401 my $avoid = shift; 402 my $res = []; 403 404 if (ref ($field) ne "Regexp") { 405 if ($field =~ /^\^/) { 406 $field = qr/^$field$/; 407 } else { 408 $field = qr/$field/; 409 } 410 } 411 412 if (ref ($hash) eq "HASH") { 413 foreach my $key (keys %{$hash}) { 414 next if $key =~ /^#%#/; 415 last if defined $avoid and $key eq $avoid; 416 if ($key =~ $field) { 417 push @$res, $hash; 418 } elsif (ref ($hash->{$key}) eq "HASH") { 419 push @$res, @{munin_find_field ($hash->{$key}, $field, $avoid)}; 420 } 421 } 422 } 423 424 return $res; 425 } 426 427 # munin_get_children: Get all child hash nodes 428 # Parameters: 429 # - $hash: A hash ref to the parent node 430 # Returns: 431 # - Success: A ref to an array of the child nodes 432 # - Failure: undef 433 sub munin_get_children { 434 my $hash = shift; 435 my $res = []; 436 437 return undef if (ref ($hash) ne "HASH"); 438 439 foreach my $key (keys %{$hash}) { 440 next if $key =~ /^#%#/; 441 if (defined $hash->{$key} and ref ($hash->{$key}) eq "HASH") { 442 push @$res, $hash->{$key}; 443 } 444 } 445 446 return $res; 447 } 448 449 # munin_get_separated_node: Copy a node to a separate node without "specials" 450 # Parameters: 451 # - $hash: The node to copy 452 # Returns: 453 # - Success: A ref to a new node without "#%#"-fields 454 # - Failure: undef 455 sub munin_get_separated_node 456 { 457 my $hash = shift; 458 my $ret = {}; 459 460 if (ref ($hash) eq "HASH") { 461 foreach my $key (keys %$hash) { 462 next if $key =~ /^#%#/; 463 if (ref ($hash->{$key}) eq "HASH") { 464 $ret->{$key} = munin_get_separated_node ($hash->{$key}); 465 } else { 466 $ret->{$key} = $hash->{$key}; 467 } 468 } 469 } else { 470 return undef; 471 } 472 473 return $ret; 474 } 475 476 # munin_get_parent_name: Return the name of the parent of the hash node supplied 477 # Parameters: 478 # - $hash: A ref to the hash node 479 # Returns: 480 # - Success: The name of the parent node 481 # - Failure: If no parent node exists, "none" is returned. 482 sub munin_get_parent_name 483 { 484 my $hash = shift; 485 486 if (ref ($hash) eq "HASH" and defined $hash->{'#%#parent'}) { 487 return munin_get_node_name ($hash->{'#%#parent'}); 488 } else { 489 return "none"; 490 } 491 } 492 493 # munin_get_node_name: Return the name of the hash node supplied 494 # Parameters: 495 # - $hash: A ref to the hash node 496 # Returns: 497 # - Success: The name of the node 498 sub munin_get_node_name 499 { 500 my $hash = shift; 501 502 if (ref ($hash) eq "HASH" and defined $hash->{'#%#name'}) { 503 return $hash->{'#%#name'}; 504 } else { 505 return undef; 506 } 507 } 508 509 510 # munin_get_node_loc: Get location array for hash node 511 # Parameters: 512 # - $hash: A ref to the node 513 # Returns: 514 # - Success: Ref to an array with the full path of the variable 515 # - Failure: undef 516 sub munin_get_node_loc { 517 my $hash = shift; 518 my $res = []; 519 520 if (ref ($hash) ne "HASH") { # Not a has node 521 return undef; 522 } 523 if (defined $hash->{'#%#parent'}) { 524 $res = munin_get_node_loc ($hash->{'#%#parent'}); 525 push @$res, munin_get_node_name ($hash) if defined $res; 526 } 527 return $res; 528 } 529 530 # munin_get_parent: Get parent node of a hash 531 # Parameters: 532 # - $hash: A ref to the node 533 # Returns: 534 # - Success: Ref to an parent 535 # - Failure: undef 536 sub munin_get_parent { 537 my $hash = shift; 538 539 if (ref ($hash) ne "HASH") { # Not a has node 540 return undef; 541 } 542 if (defined $hash->{'#%#parent'}) { 543 return $hash->{'#%#parent'}; 544 } else { 545 return undef; 546 } 547 } 548 549 # munin_get_node: Gets a node by loc 550 # Parameters: 551 # - $hash: A ref to the hash to set the variable in 552 # - $loc: A ref to an array with the full path of the node 553 # Returns: 554 # - Success: The node ref found by $loc 555 # - Failure: undef 556 sub munin_get_node 557 { 558 my $hash = shift; 559 my $loc = shift; 560 561 foreach my $tmpvar (@$loc) { 562 if ($tmpvar !~ /\S/) { 563 ::logger ("Error: munin_get_node: Cannot work on hash node \"$tmpvar\""); 564 return undef; 565 } 566 return undef if !exists $hash->{$tmpvar}; 567 $hash = $hash->{$tmpvar}; 568 } 569 return $hash; 570 } 571 572 # munin_set_var: sets a variable in a hash 573 # Parameters: 574 # - $hash: A ref to the hash to set the variable in 575 # - $var: The name of the variable 576 # - $val: The value to set the variable to 577 # Returns: 578 # - Success: The $hash we were handed 579 # - Failure: undef 580 sub munin_set_var 370 581 { 371 582 my $hash = shift; … … 373 584 my $val = shift; 374 585 375 print "DEBUG: Setting var \"$var\" = \"$val\"\n" if $DEBUG; 376 if ($var =~ /^\s*([^;:]+);([^:]+):(\S+)\s*$/) 377 { 378 my ($dom, $host, $rest) = ($1, $2, $3); 379 my @sp = split (/\./, $rest); 380 381 if (@sp == 3) 382 { 383 ::logger ("Warning: Unknown option \"$sp[2]\" in \"$dom;$host:$sp[0].$sp[1].$sp[2]\".") 384 unless defined $legal_expanded{$sp[2]}; 385 $hash->{domain}->{$dom}->{node}->{$host}->{client}->{$sp[0]}->{"$sp[1].$sp[2]"} = $val; 386 } 387 elsif (@sp == 2) 388 { 389 ::logger ("Warning: Unknown option \"$sp[1]\" in \"$dom;$host:$sp[0].$sp[1]\".") 390 unless defined $legal_expanded{$sp[1]}; 391 $hash->{domain}->{$dom}->{node}->{$host}->{client}->{$sp[0]}->{$sp[1]} = $val; 392 } 393 elsif (@sp == 1) 394 { 395 ::logger ("Warning: Unknown option \"$sp[0]\" in \"$dom;$host:$sp[0]\".") 396 unless defined $legal_expanded{$sp[0]}; 397 $hash->{domain}->{$dom}->{node}->{$host}->{$sp[0]} = $val; 398 } 399 else 400 { 401 warn "munin_set_var: Malformatted variable path \"$var\"."; 402 } 403 } 404 elsif ($var =~ /^\s*([^;:]+);([^;:]+)\s*$/) 405 { 406 my ($dom, $rest) = ($1, $2); 407 my @sp = split (/\./, $rest); 408 409 if (@sp == 1) 410 { 411 ::logger ("Warning: Unknown option \"$sp[0]\" in \"$dom;$sp[0]\".") 412 unless defined $legal_expanded{$sp[0]}; 413 $hash->{domain}->{$dom}->{$sp[0]} = $val; 414 } 415 else 416 { 417 warn "munin_set_var: Malformatted variable path \"$var\"."; 418 } 419 } 420 elsif ($var =~ /^\s*([^;:\.]+)\s*$/) 421 { 422 ::logger ("Warning: Unknown option \"$1\" in \"$1\".") 423 unless defined $legal_expanded{$1}; 424 $hash->{$1} = $val; 425 } 426 elsif ($var =~ /^\s*([^\.]+)\.([^\.]+)\.([^\.]+)$/) 427 { 428 ::logger ("Warning: Unknown option \"$1\" in \"$var\".") 429 unless defined $legal_expanded{$1}; 430 ::logger ("Warning: Unknown option \"$3\" in \"$var\".") 431 unless defined $legal_expanded{$3}; 432 $hash->{$1}->{$2}->{$3} = $val; 433 } 434 else 435 { 436 warn "munin_set_var: Malformatted variable path \"$var\"."; 586 return munin_set_var_loc ($hash, [$var], $val); 587 } 588 589 # munin_set_var_loc: sets a variable in a hash 590 # Parameters: 591 # - $hash: A ref to the hash to set the variable in 592 # - $loc: A ref to an array with the full path of the variable 593 # - $val: The value to set the variable to 594 # Returns: 595 # - Success: The $hash we were handed 596 # - Failure: undef 597 sub munin_set_var_loc 598 { 599 my $hash = shift; 600 my $loc = shift; 601 my $val = shift; 602 my @aloc = @$loc; 603 604 my $tmpvar = shift @aloc; 605 $tmpvar = shift @aloc while (defined $tmpvar and $tmpvar =~ /^#%#/); 606 if ($tmpvar !~ /\S/) { 607 ::logger ("Error: munin_set_var_loc: Cannot work on hash node \"$tmpvar\""); 608 return undef; 609 } 610 if (@aloc > 0) { 611 if (!defined $hash->{$tmpvar}) { # Init the new node 612 $hash->{$tmpvar}->{"#%#parent"} = $hash; 613 $hash->{$tmpvar}->{"#%#name"} = $tmpvar; 614 } 615 return munin_set_var_loc ($hash->{$tmpvar}, \@aloc, $val); 616 } else { 617 ::logger ("Warning: munin_set_var_loc: Setting unknown option \"$tmpvar\".") 618 unless defined $legal_expanded{$tmpvar}; 619 $hash->{$tmpvar} = $val; 620 return $hash; 621 } 622 } 623 624 # munin_get_node_partialpath: gets a node froma partial path 625 # Parameters: 626 # - $hash: A ref to the "current" location in the hash tree 627 # - $var: A path string with relative location (from the $hash). 628 # Returns: 629 # - Success: The node 630 # - Failure: undef 631 sub munin_get_node_partialpath 632 { 633 my $hash = shift; 634 my $var = shift; 635 my $ret = undef; 636 637 return undef if !defined $hash or ref ($hash) ne "HASH"; 638 639 my $root = munin_get_root_node ($hash); 640 my $hashloc = munin_get_node_loc ($hash); 641 my $varloc = undef; 642 643 if ($var =~ /^\s*([^:]+):(\S+)\s*$/) { 644 my ($leftstring, $rightstring) = ($1, $2); 645 646 my @leftarr = split (/;/, $leftstring); 647 my @rightarr = split (/\./, $rightstring); 648 push @$varloc, @leftarr, @rightarr 649 } elsif ($var =~ /^\s*([^;:\.]+)\s*$/) { 650 push @$varloc, $var; 651 } elsif ($var =~ /^\s*(.+)\.([^\.:;]+)$/) { 652 my ($leftstring, $rightstring) = ($1, $2); 653 654 my @leftarr = split (/;/, $leftstring); 655 my @rightarr = split (/\./, $rightstring); 656 push @$varloc, @leftarr, @rightarr; 657 } elsif ($var =~ /^\s*(\S+)\s*$/) { 658 my @leftarr = split (/;/, $1); 659 push @$varloc, @leftarr; 660 } else { 661 ::logger ("Error: munin_get_node_partialpath: Malformatted variable path \"$var\"."); 662 } 663 664 # We've got both parts of the loc (varloc and hashloc) -- let's figure out 665 # where they meet up. 666 do { 667 $ret = munin_get_node ($root, [@$hashloc, @$varloc]); 668 } while (!defined $ret and pop @$hashloc); 669 670 return $ret; 671 } 672 673 # munin_set_var_path: sets a variable in a hash 674 # Parameters: 675 # - $hash: A ref to the hash to set the variable in 676 # - $var: A string with the full path of the variable 677 # - $val: The value to set the variable to 678 # Returns: 679 # - Success: The $hash we were handed 680 # - Failure: The $hash we were handed 681 sub munin_set_var_path 682 { 683 my $hash = shift; 684 my $var = shift; 685 my $val = shift; 686 687 my $result = undef; 688 689 ::logger ("Debug: munin_set_var_path: Setting var \"$var\" = \"$val\"") if $DEBUG; 690 if ($var =~ /^\s*([^:]+):(\S+)\s*$/) { 691 my ($leftstring, $rightstring) = ($1, $2); 692 693 my @leftarr = split (/;/, $leftstring); 694 my @rightarr = split (/\./, $rightstring); 695 $result = munin_set_var_loc ($hash, [@leftarr, @rightarr], $val); 696 } elsif ($var =~ /^\s*([^;:\.]+)\s*$/) { 697 $result = munin_set_var_loc ($hash, [$1], $val); 698 } elsif ($var =~ /^\s*([^:;]+)$/) { 699 my @leftarr = split (/\./, $1); 700 $result = munin_set_var_loc ($hash, [@leftarr], $val); 701 } elsif ($var =~ /^\s*(.+)\.([^\.:;]+)$/) { 702 my ($leftstring, $rightstring) = ($1, $2); 703 704 my @leftarr = split (/;/, $leftstring); 705 my @rightarr = split (/\./, $rightstring); 706 $result = munin_set_var_loc ($hash, [@leftarr, @rightarr], $val); 707 } elsif ($var =~ /^\s*(\S+)\s*$/) { 708 my @leftarr = split (/;/, $1); 709 $result = munin_set_var_loc ($hash, [@leftarr], $val); 710 } else { 711 ::logger ("Error: munin_set_var_path: Malformatted variable path \"$var\"."); 712 } 713 714 if (!defined $result) { 715 ::logger ("Error: munin_set_var_path: Failed setting \"$var\" = \"$val\"."); 437 716 } 438 717 … … 440 719 } 441 720 442 sub munin_writeconfig_loop { 443 my ($data,$fh,$pre) = @_; 444 $pre |= ""; 445 446 # Write datafile 447 foreach my $a (keys %{$data}) 448 { 449 if (ref ($data->{$a}) eq "HASH") 450 { 451 if ($a eq "domain" or $a eq "node" or $a eq "client") 452 { 453 &munin_writeconfig_loop ($data->{$a}, $fh, "$pre"); 454 } 455 elsif ($a eq "contact" and $pre eq "") 456 { 457 &munin_writeconfig_loop ($data->{$a}, $fh, "contact."); 458 } 459 else 460 { 461 my $lpre = $pre; 462 if ($lpre eq "") 463 { 464 $lpre = $a.";"; 465 } 466 elsif ($lpre =~ /;$/) 467 { 468 $lpre .= $a.":"; 469 } 470 else 471 { 472 $lpre .= $a."."; 473 } 474 &munin_writeconfig_loop ($data->{$a}, $fh, "$lpre"); 475 } 476 } 477 elsif (defined $data->{$a} and length $data->{$a}) 478 { 479 next if "$pre$a" eq "version"; # Handled separately 480 (my $outstring = $data->{$a}) =~ s/([^\\])#/$1\\#/g; 481 print "Writing: $pre$a $outstring\n" if $DEBUG; 721 # munin_get_root_node: Get the root node of the hash tree 722 # Parameters: 723 # - $hash: A hash node to traverse up from 724 # Returns: 725 # - Success: A ref to the root hash node 726 # - Failure: undef 727 sub munin_get_root_node 728 { 729 my $hash = shift; 730 731 return undef if ref ($hash) ne "HASH"; 732 733 while (defined $hash->{'#%#parent'}) { 734 $hash = $hash->{'#%#parent'}; 735 } 736 737 return $hash; 738 } 739 740 sub munin_writeconfig_loop 741 { 742 my ($hash,$fh,$pre) = @_; 743 744 foreach my $key (keys %$hash) { 745 next if $key =~ /#%#/; 746 my $path = (defined $pre ? join(';', ($pre, $key)) : $key); 747 if (ref ($hash->{$key}) eq "HASH") { 748 munin_writeconfig_loop ($hash->{$key}, $fh, $path); 749 } else { 750 next if !defined $pre and $key eq "version"; # Handled separately 751 next if !defined $hash->{$key} or !length $hash->{$key}; 752 (my $outstring = $hash->{$key}) =~ s/([^\\])#/$1\\#/g; 753 print "Writing: $path $outstring\n" if $DEBUG; 482 754 if ($outstring =~ /\\$/) 483 755 { # Backslash as last char has special meaning. Avoid it. 484 print $fh "$p re$a$outstring\\\n";756 print $fh "$path $outstring\\\n"; 485 757 } else { 486 print $fh "$p re$a$outstring\n";758 print $fh "$path $outstring\n"; 487 759 } 488 760 } 489 761 } 490 762 } 763 491 764 sub munin_writeconfig { 492 765 my ($datafilename,$data,$fh) = @_; 493 # my $datafile = new Config::General();494 # $datafile->save_file($datafilename,$data);495 766 496 767 if (!defined $fh) … … 506 777 print $fh "version $VERSION\n"; 507 778 # Write datafile 508 &munin_writeconfig_loop ($data, $fh , "");779 &munin_writeconfig_loop ($data, $fh); 509 780 510 781 if (defined $fh) … … 527 798 } 528 799 800 # munin_get_html_filename: Get the full path-name of an html file 801 # Parameters: 802 # - $hash: A ref to the service hash node 803 # Returns: 804 # - Success: The file name with full path 805 # - Failure: undef 806 sub munin_get_html_filename { 807 my $hash = shift; 808 my $loc = munin_get_node_loc ($hash); 809 my $ret = munin_get ($hash, 'htmldir'); 810 my $plugin = "index"; 811 812 # Sanitise 813 $ret =~ s/[^\w_\/"'\[\]\(\)+=-]\./_/g; 814 $hash =~ s/[^\w_\/"'\[\]\(\)+=-]/_/g; 815 @$loc = map { s/\//_/g; $_ } @$loc; 816 @$loc = map { s/^\./_/g; $_ } @$loc; 817 818 if (defined $hash->{'graph_title'}) { 819 $plugin = pop @$loc or return undef; 820 } 821 822 if (@$loc) { # The rest is used as directory names... 823 $ret .= "/" . join ('/', @$loc); 824 } 825 826 return "$ret/$plugin.html"; 827 } 828 829 # munin_get_picture_filename: Get the full path+name of a picture file 830 # Parameters: 831 # - $hash: A ref to the service hash node 832 # - $scale: The scale (day, week, year, month) 833 # - $sum: [optional] Boolean value, whether it's a sum graph or not. 834 # Returns: 835 # - Success: The file name with full path 836 # - Failure: undef 529 837 sub munin_get_picture_filename { 530 my $config = shift; 531 my $domain = shift; 532 my $name = shift; 533 my $service = shift; 838 my $hash = shift; 534 839 my $scale = shift; 535 840 my $sum = shift; 536 my $dir = $config->{'htmldir'}; 841 my $loc = munin_get_node_loc ($hash); 842 my $ret = munin_get ($hash, 'htmldir'); 537 843 538 844 # Sanitise 539 $dir =~ s/[^\w_\/"'\[\]\(\)+=-]\./_/g; 540 $domain =~ s/[^\w_\/"'\[\]\(\)+=\.-]/_/g; 541 $name =~ s/[^\w_\/"'\[\]\(\)+=\.-]/_/g; 542 $service =~ s/[^\w_\/"'\[\]\(\)+=-]/_/g; 845 $ret =~ s/[^\w_\/"'\[\]\(\)+=-]\./_/g; 846 $hash =~ s/[^\w_\/"'\[\]\(\)+=-]/_/g; 543 847 $scale =~ s/[^\w_\/"'\[\]\(\)+=-]/_/g; 544 545 if (defined $sum and $sum) 546 { 547 return "$dir/$domain/$name-$service-$scale-sum.png"; 548 } 549 else 550 { 551 return "$dir/$domain/$name-$service-$scale.png"; 552 } 553 } 554 848 @$loc = map { s/\//_/g; $_ } @$loc; 849 @$loc = map { s/^\./_/g; $_ } @$loc; 850 851 my $plugin = pop @$loc or return undef; 852 my $node = pop @$loc or return undef; 853 854 if (@$loc) { # The rest is used as directory names... 855 $ret .= "/" . join ('/', @$loc); 856 } 857 858 if (defined $sum and $sum) { 859 return "$ret/$node/$plugin-$scale-sum.png"; 860 } else { 861 return "$ret/$node/$plugin-$scale.png"; 862 } 863 } 864 865 # munin_path_to_loc: Returns a loc array from a path string 866 # Parameters: 867 # - $path: A path string 868 # Returns: 869 # - Success: A ref to an array with the loc 870 # - Failure: undef 871 sub munin_path_to_loc 872 { 873 my $path = shift; 874 875 my $result = undef; 876 877 if ($path =~ /^\s*([^:]+):(\S+)\s*$/) { 878 my ($leftstring, $rightstring) = ($1, $2); 879 880 my @leftarr = split (/;/, $leftstring); 881 my @rightarr = split (/\./, $rightstring); 882 $result = [@leftarr, @rightarr]; 883 } elsif ($path =~ /^\s*([^;:\.]+)\s*$/) { 884 $result = [$1]; 885 } elsif ($path =~ /^\s*(.+)\.([^\.:;]+)$/) { 886 my ($leftstring, $rightstring) = ($1, $2); 887 888 my @leftarr = split (/;/, $leftstring); 889 my @rightarr = split (/\./, $rightstring); 890 $result = [@leftarr, @rightarr]; 891 } elsif ($path =~ /^\s*(\S+)\s*$/) { 892 my @leftarr = split (/;/, $1); 893 $result = [@leftarr]; 894 } else { 895 ::logger ("Error: munin_path_to_loc: Malformatted variable path \"$path\"."); 896 } 897 898 if (!defined $result) { 899 ::logger ("Error: munin_path_to_loc: Failed converting \"$path\"."); 900 } 901 902 return $result; 903 } 904 905 906 # munin_get_filename: Get rrd filename for a field, without any 907 # bells or whistles. Used by munin-update to 908 # figure out which file to update. 909 # Parameters: 910 # - $hash: Ref to hash field 911 # Returns: 912 # - Success: Full path to rrd file 913 # - Failure: undef 555 914 sub munin_get_filename { 556 my ($config,$domain,$node,$service,$field) = @_; 557 558 return ($config->{'dbdir'} . "/$domain/$node-$service-$field-" . lc substr (($config->{domain}->{$domain}->{node}->{$node}->{client}->{$service}->{$field.".type"}||"GAUGE"), 0,1). ".rrd"); 559 560 } 561 915 my $hash = shift; 916 my $loc = munin_get_node_loc ($hash); 917 my $ret = munin_get ($hash, "dbdir"); 918 919 if (!defined $loc or !defined $ret) { 920 return undef; 921 } 922 923 # Not really a danger (we're not doing this stuff via the shell), so more to avoid 924 # confusion with silly filenames 925 @$loc = map { s/\//_/g; $_ } @$loc; 926 @$loc = map { s/^\./_/g; $_ } @$loc; 927 928 my $field = pop @$loc or return undef; 929 my $plugin = pop @$loc or return undef; 930 my $node = pop @$loc or return undef; 931 932 if (@$loc) { # The rest is used as directory names... 933 $ret .= "/" . join ('/', @$loc); 934 } 935 936 return ($ret . "/$node-$plugin-$field-" . lc substr (munin_get($hash, "type", "GAUGE"), 0,1). ".rrd"); 937 938 } 939 940 # munin_get_bool: Get boolean variable 941 # Parameters: 942 # - $hash: Ref to hash node 943 # - $field: Name of field to get 944 # - $default: [optional] Value to return if $field isn't set 945 # Returns: 946 # - Success: 1 or 0 (true or false) 947 # - Failure: $default if defined, else undef 562 948 sub munin_get_bool 563 949 { 564 my $conf = shift; 565 my $field = shift; 566 my $default = shift; 567 my $domain = shift; 568 my $node = shift; 569 my $service = shift; 570 my $plot = shift; 571 572 return undef unless defined $field; 573 574 my $ans = &munin_get ($conf, $field, $default, $domain, $node, $service, $plot); 950 my $hash = shift; 951 my $field = shift; 952 my $default = shift; 953 954 my $ans = &munin_get ($hash, $field, $default); 575 955 return undef if not defined $ans; 576 956 … … 580 960 $ans =~ /^enable$/i or 581 961 $ans =~ /^enabled$/i 582 ) 583 { 584 return 1; 585 } 586 elsif ($ans =~ /^no$/i or 962 ) { 963 return 1; 964 } elsif ($ans =~ /^no$/i or 587 965 $ans =~ /^false$/i or 588 966 $ans =~ /^off$/i or 589 967 $ans =~ /^disable$/i or 590 968 $ans =~ /^disabled$/i 591 ) 592 { 593 return 0; 594 } 595 elsif ($ans !~ /\D/) 596 { 597 return $ans; 598 } 599 else 600 { 601 return undef; 969 ) { 970 return 0; 971 } elsif ($ans !~ /\D/) { 972 return $ans; 973 } else { 974 return $default; 602 975 } 603 976 } … … 648 1021 } 649 1022 1023 # munin_get: Get variable 1024 # Parameters: 1025 # - $hash: Ref to hash node 1026 # - $field: Name of field to get 1027 # - $default: [optional] Value to return if $field isn't set 1028 # Returns: 1029 # - Success: field contents 1030 # - Failure: $default if defined, else undef 650 1031 sub munin_get 651 1032 { 652 my $conf = shift; 653 my $field = shift; 654 my $default = shift; 655 my $domain = shift; 656 my $node = shift; 657 my $service = shift; 658 my $plot = shift; 659 660 if (defined $field) 661 { 662 return $conf->{domain}->{$domain}->{node}->{$node}->{client}->{$service}->{"$plot.$field"} 663 if (defined $domain and defined $node and defined $service and defined $plot and 664 defined $conf->{domain}->{$domain}->{node}->{$node}->{client}->{$service}->{"$plot.$field"}); 665 666 667 668 return $conf->{domain}->{$domain}->{node}->{$node}->{client}->{$service}->{$field} 669 if (defined $domain and defined $node and defined $service and 670 defined $conf->{domain}->{$domain}->{node}->{$node}->{client}->{$service}->{$field}); 671 return $conf->{domain}->{$domain}->{node}->{$node}->{$field} 672 if (defined $domain and defined $node and 673 defined $conf->{domain}->{$domain}->{node}->{$node}->{$field}); 674 return $conf->{domain}->{$domain}->{$field} 675 if (defined $domain and defined $conf->{domain}->{$domain}->{$field}); 676 return $conf->{$field} 677 if (defined $conf->{$field}); 678 return $default; 679 } 680 else 681 { 682 return $conf->{domain}->{$domain}->{node}->{$node}->{client}->{$service} 683 if (defined $domain and defined $node and defined $service and 684 defined $conf->{domain}->{$domain}->{node}->{$node}->{client}->{$service}); 685 return $conf->{domain}->{$domain}->{node}->{$node} 686 if (defined $domain and defined $node and 687 defined $conf->{domain}->{$domain}->{node}->{$node}); 688 return $conf->{domain}->{$domain} 689 if (defined $domain and defined $conf->{domain}->{$domain}); 690 return $conf 691 if (defined $conf); 692 return $default; 693 } 1033 my $hash = shift; 1034 my $field = shift; 1035 my $default = shift; 1036 1037 return $default if (ref ($hash) ne "HASH"); 1038 return $hash->{$field} if defined $hash->{$field} and ref($hash->{$field}) ne "HASH"; 1039 return $default if not defined $hash->{'#%#parent'}; 1040 return munin_get ($hash->{'#%#parent'}, $field, $default); 1041 } 1042 1043 # munin_copy_node_toloc: Copy hash node at 1044 # - $from: Hash node to copy 1045 # - $to: Where to copy it to 1046 # - $loc: Path to node under $to 1047 # Returns: 1048 # - Success: $to 1049 # - Failure: undef 1050 sub munin_copy_node_toloc 1051 { 1052 my $from = shift; 1053 my $to = shift; 1054 my $loc = shift; 1055 1056 return undef unless defined $from and defined $to and defined $loc; 1057 1058 if (ref ($from) eq "HASH") { 1059 foreach my $key (keys %$from) { 1060 next if $key =~ /^#%#/; 1061 if (ref ($from->{$key}) eq "HASH") { 1062 munin_copy_node_toloc ($from->{$key}, $to, [@$loc, $key]); 1063 } else { 1064 munin_set_var_loc ($to, [@$loc, $key], $from->{$key}); 1065 } 1066 } 1067 } else { 1068 $to = $from; 1069 } 1070 return $to; 1071 } 1072 1073 # munin_copy_node: Copy hash node 1074 # - $from: Hash node to copy 1075 # - $to: Where to copy it to 1076 # Returns: 1077 # - Success: $to 1078 # - Failure: undef 1079 sub munin_copy_node 1080 { 1081 my $from = shift; 1082 my $to = shift; 1083 1084 if (ref ($from) eq "HASH") { 1085 foreach my $key (keys %$from) { 1086 if (ref ($from->{$key}) eq "HASH") { 1087 # Easier to do with the other copy function 1088 munin_copy_node_toloc ($from->{$key}, $to, [$key]); 1089 } else { 1090 munin_set_var_loc ($to, [$key], $from->{$key}); 1091 } 1092 } 1093 } else { 1094 $to = $from; 1095 } 1096 return $to; 694 1097 } 695 1098 … … 722 1125 } 723 1126 724 sub munin_category_status 725 { 726 my ($config, $limits, $domain, $node, $category, $check_draw) = @_; 727 my $state = "ok"; 728 729 return undef unless defined $config->{domain}->{$domain}->{node}->{$node}; 730 my $snode = $config->{domain}->{$domain}->{node}->{$node}; 731 732 foreach my $service (keys %{$snode->{client}}) 733 { 734 next if ((not defined $snode->{client}->{$service}->{graph_category}) and 735 $category ne 'other'); 736 next if ((defined $snode->{client}->{$service}->{graph_category}) and 737 ($snode->{client}->{$service}->{graph_category} ne $category)); 738 739 my $fres = &munin_service_status ($config, $limits, $domain, $node, $service, $check_draw); 740 if (defined $fres) 741 { 742 if ($fres eq "critical") 743 { 1127 # munin_category_status: Gets current status of a category 1128 # Parameters: 1129 # - $hash: A ref to the hash node whose children to check 1130 # - $limits: A ref to the root node of the limits tree 1131 # - $category: The category to review 1132 # - $check_draw: [optional] Ignore undrawn fields 1133 # Returns: 1134 # - Success: The status of the field 1135 # - Failure: undef 1136 sub munin_category_status { 1137 my $hash = shift || return undef; 1138 my $limits = shift || return undef; 1139 my $category = shift || return undef; 1140 my $check_draw = 0; 1141 my $state = "ok"; 1142 1143 return undef unless (defined $hash and ref ($hash) eq "HASH"); 1144 1145 foreach my $service (@{munin_get_children ($hash)}) { 1146 next if (!defined $service or ref ($service) ne "HASH"); 1147 next if (!defined $service->{'graph_title'}); 1148 next if ($category ne munin_get ($service, "graph_category", "other")); 1149 next if ($check_draw and not munin_get_bool ($service, "graph", 1)); 1150 1151 my $fres = munin_service_status ($service, $limits, $check_draw); 1152 if (defined $fres) { 1153 if ($fres eq "critical") { 744 1154 $state = $fres; 745 1155 last; 746 } 747 elsif ($fres eq "warning")748 {1156 } elsif ($fres eq "warning") { 1157 $state = $fres; 1158 } elsif ($fres eq "unknown" and $state eq "ok") { 749 1159 $state = $fres; 750 1160 } … … 755 1165 } 756 1166 757 sub munin_service_status 758 { 759 my ($config, $limits, $domain, $node, $service, $check_draw) = @_; 1167 # munin_field_status: Gets current status of a field 1168 # Parameters: 1169 # - $hash: A ref to the field hash node 1170 # - $limits: A ref to the root node of the limits tree 1171 # - $check_draw: [optional] Ignore undrawn fields 1172 # Returns: 1173 # - Success: The status of the field 1174 # - Failure: undef 1175 sub munin_service_status { 1176 my ($config, $limits, $check_draw) = @_; 760 1177 my $state = "ok"; 761 1178 762 return undef unless defined $config->{domain}->{$domain}->{node}->{$node}->{client}->{$service}; 763 foreach my $key (keys %{$config->{domain}->{$domain}->{node}->{$node}->{client}->{$service}}) 764 { 765 next unless $key =~ /^([^\.]+)\.label$/; 766 my $field = $1; 767 my $fres = &munin_field_status ($config, $limits, $domain, $node, $service, $field, $check_draw); 768 if (defined $fres) 769 { 770 if ($fres eq "critical") 771 { 1179 return undef unless defined $config; 1180 for my $fieldnode (@{munin_find_field ($config, "label")}) { 1181 my $field = munin_get_node_name ($fieldnode); 1182 my $fres = munin_field_status ($fieldnode, $limits, $check_draw); 1183 if (defined $fres) { 1184 if ($fres eq "critical") { 772 1185 $state = $fres; 773 1186 last; 774 } 775 elsif ($fres eq "warning") 776 { 1187 } elsif ($fres eq "warning") { 777 1188 $state = $fres; 778 1189 } … … 783 1194 } 784 1195 785 sub munin_field_status 786 { 787 my ($config, $limits, $domain, $node, $service, $field, $check_draw) = @_; 1196 # munin_field_status: Gets current status of a field 1197 # Parameters: 1198 # - $hash: A ref to the field hash node 1199 # - $limits: A ref to the root node of the limits tree 1200 # - $check_draw: [optional] Ignore undrawn fields 1201 # Returns: 1202 # - Success: The status of the field 1203 # - Failure: undef 1204 sub munin_field_status { 1205 my ($hash, $limits, $check_draw) = @_; 788 1206 my $state = undef; 789 1207 790 1208 # Return undef if nagios is turned off, or the field doesn't have any limits 791 unless ((defined $config->{domain}->{$domain}->{node}->{$node}->{client}->{$service}->{"$field.warning"}) or 792 (defined $config->{domain}->{$domain}->{node}->{$node}->{client}->{$service}->{"$field.critical"})) 793 { 1209 if ((!defined munin_get ($hash, "warning", undef)) and (!defined munin_get ($hash, "critical"))) { 794 1210 return undef; 795 1211 } 796 1212 797 if (defined $limits->{domain}->{$domain}->{node}->{$node}->{client}->{$service}->{"$field.critical"} and (!defined $check_draw or !$check_draw or 798 &munin_draw_field ($config->{domain}->{$domain}->{node}->{$node}, $service, $field))) 799 { 800 return "critical"; 801 } 802 elsif (defined $limits->{domain}->{$domain}->{node}->{$node}->{client}->{$service}->{"$field.warning"} and (!defined $check_draw or !$check_draw or 803 &munin_draw_field ($config->{domain}->{$domain}->{node}->{$node}, $service, $field))) 804 { 805 return "warning"; 806 } 807 else 808 { 809 return "ok"; 1213 if (!defined $check_draw or !$check_draw or munin_draw_field ($hash)) { 1214 my $loc = munin_get_node_loc ($hash); 1215 my $node = munin_get_node ($limits, $loc); 1216 return $node->{"state"} || "ok"; 810 1217 } 811 1218 } … … 834 1241 } 835 1242 1243 # munin_get_max_label_length: Get the length of the longest labe in a graph 1244 # Parameters: 1245 # - $hash: the graph in question 1246 # - $order: A ref to an array of fields (graph_order) 1247 # Returns: 1248 # - Success: The length of the longest label in the graph 1249 # - Failure: undef 836 1250 sub munin_get_max_label_length 837 1251 { 838 my $node = shift;839 my $config = shift;840 my $domain = shift;841 my $host = shift;842 1252 my $service = shift; 843 1253 my $order = shift; 844 1254 my $result = 0; 1255 my $tot = munin_get ($service, "graph_total"); 845 1256 846 1257 for my $field (@$order) { 847 1258 my $path = undef; 848 1259 (my $f = $field) =~ s/=.+//; 849 next if (exists $node->{client}->{$service}->{$f.".process"} and 850 $node->{client}->{$service}->{$f.".process"} ne "yes"); 851 next if (exists $node->{client}->{$service}->{$f.".skipdraw"}); 852 next unless (!exists $node->{client}->{$service}->{$f.".graph"} or 853 $node->{client}->{$service}->{$f.".graph"} eq "yes"); 854 if ($result < length ($node->{client}->{$service}->{$f.".label"} || $f)) { 855 $result = length ($node->{client}->{$service}->{$f.".label"} || $f); 856 } 857 if (exists $node->{client}->{$service}->{graph_total} and 858 length $node->{client}->{$service}->{graph_total} > $result) 859 { 860 $result = length $node->{client}->{$service}->{graph_total}; 861 } 1260 next if (!munin_get_bool ($service->{$f}, "process", 1)); 1261 next if (munin_get_bool ($service->{$f}, "skipdraw", 0)); 1262 next if (!munin_get_bool ($service->{$f}, "graph", 1)); 1263 1264 my $len = length (munin_get ($service->{$f}, "label") || $f); 1265 1266 if ($result < $len) { 1267 $result = $len; 1268 } 1269 } 1270 if (defined $tot and length $tot > $result) { 1271 $result = length $tot; 862 1272 } 863 1273 return $result; 864 1274 } 865 1275 1276 # munin_get_field_order: Get the field order in a graph 1277 # Parameters: 1278 # - $hash: A hash ref to the service 1279 # Returns: 1280 # - Success: A ref to an array of the field names 1281 # - Failure: undef 866 1282 sub munin_get_field_order 867 1283 { 868 my $node = shift; 869 my $config = shift; 870 my $domain = shift; 871 my $host = shift; 872 my $service = shift; 1284 my $hash = shift; 873 1285 my $result = []; 874 1286 875 if ($node->{client}->{$service}->{graph_sources}) 876 { 877 foreach my $gs (split /\s+/, $node->{client}->{$service}->{'graph_sources'}) 878 { 1287 return undef if !defined $hash or ref($hash) ne "HASH"; 1288 1289 my $order = munin_get ($hash, "graph_order"); 1290 1291 if (defined $hash->{graph_sources}) { 1292 foreach my $gs (split /\s+/, $hash->{'graph_sources'}) { 879 1293 push (@$result, "-".$gs); 880 1294 } 881 1295 } 882 if ($node->{client}->{$service}->{graph_order}) 883 { 884 push (@$result, split /\s+/, $node->{client}->{$service}->{'graph_order'}); 1296 if (defined $order) { 1297 push (@$result, split /\s+/, $order); 885 1298 } 886 1299 887 for my $key (keys %{$node->{client}->{$service}}) 888 { 889 my ($client,$type)=""; 890 ($client,$type) = split /\./,$key; 891 if (defined $type and $type eq "label") 892 { 893 push @$result,$client if !grep /^\Q$client\E(?:=|$)/, @$result;; 894 } 1300 for my $fieldnode (@{munin_find_field ($hash, "label")}) { 1301 my $fieldname = munin_get_node_name ($fieldnode); 1302 push @$result,$fieldname if !grep /^\Q$fieldname\E(?:=|$)/, @$result;; 895 1303 } 896 1304 … … 898 1306 } 899 1307 1308 # munin_get_rrd_filename: Get the name of the rrd file corresponding to a 1309 # field. Checks for lots of bells and whistles. 1310 # This function is the correct one to use when 1311 # figuring out where to fetch data from. 1312 # Parameters: 1313 # - $field: The hash object of the field 1314 # - $path: [optional] The path to the field (as given in graph_order/sum/stack/et al) 1315 # Returns: 1316 # - Success: A string with the filename of the rrd file 1317 # - Failure: undef 900 1318 sub munin_get_rrd_filename { 901 my $node = shift;902 my $config = shift;903 my $domain = shift;904 my $name = shift;905 my $service = shift;906 1319 my $field = shift; 907 1320 my $path = shift; 908 my $result = "unknown"; 909 910 if ($node->{client}->{$service}->{$field.".filename"}) 911 { 912 $result = $node->{client}->{$service}->{$field.".filename"}; 913 } 914 elsif ($path) 915 { 916 if (!defined ($node->{client}->{$service}->{$field.".label"})) 917 { 918 print "DEBUG: Setting label: $field\n" if $DEBUG; 919 $node->{client}->{$service}->{$field.".label"} = $field; 920 } 921 922 if ($path =~ /^\s*([^:;]+)[:;]([^:]+):([^:\.]+)[:\.]([^:\.]+)\s*$/) 923 { 924 $result = munin_get_filename ($config, $1, $2, $3, $4); 925 print "\nDEBUG1: Expanding $path...\n" if $DEBUG; 926 if (! defined $node->{client}->{$service}->{$field."label"}) 927 { 928 for my $f (@copy_fields) 929 { 930 if (not exists $node->{client}->{$service}->{"$field.$f"} and 931 exists $config->{'domain'}->{$1}->{'node'}->{$2}->{'client'}->{$3}->{"$4.$f"}) 932 { 933 $node->{client}->{$service}->{"$field.$f"} = $config->{'domain'}->{$1}->{'node'}->{$2}->{'client'}->{$3}->{"$4.$f"}; 934 } 935 } 1321 my $result = undef; 1322 my $name = munin_get_node_name ($field); 1323 1324 # Bail out on bad input data 1325 return undef if !defined $field or ref ($field) ne "HASH"; 1326 1327 # If the field has a .filename setting, use it 1328 return $result if $result = munin_get ($field, "filename"); 1329 1330 # Handle custom paths (used in .sum, .stack, graph_order, et al) 1331 if (defined $path and length $path) { 1332 1333 my $sourcenode = munin_get_node_partialpath ($field, $path); 1334 $result = munin_get_filename ($sourcenode); 1335 1336 for my $f (@COPY_FIELDS) { 1337 if (not exists $field->{$f} and exists $sourcenode->{$f}) { 1338 print "DEBUG: Copying $f...\n" if $DEBUG; 1339 munin_set_var_loc ($field, [$f], $sourcenode->{$f}); 936 1340 } 937 1341 } 938 elsif ($path =~ /^\s*([^:]+):([^:\.]+)[:\.]([^:\.]+)\s*$/) 939 { 940 print "\nDEBUG2: Expanding $path...\n" if $DEBUG; 941 $result = munin_get_filename ($config, $domain, $1, $2, $3); 942 for my $f (@copy_fields) 943 { 944 if (not exists $node->{client}->{$service}->{"$field.$f"} and 945 exists $config->{'domain'}->{$domain}->{'node'}->{$1}->{'client'}->{$2}->{"$3.$f"}) 946 { 947 print "DEBUG: Copying $f...\n" if $DEBUG; 948 $node->{client}->{$service}->{"$field.$f"} = $config->{'domain'}->{$domain}->{'node'}->{$1}->{'client'}->{$2}->{"$3.$f"}; 949 } 950 } 951 } 952 elsif ($path =~ /^\s*([^:\.]+)[:\.]([^:\.]+)\s*$/) 953 { 954 print "\nDEBUG3: Expanding $path...\n" if $DEBUG; 955 $result = munin_get_filename ($config, $domain, $name, $1, $2); 956 for my $f (@copy_fields) 957 { 958 if (not exists $node->{client}->{$service}->{"$field.$f"} and 959 exists $node->{client}->{$1}->{"$2.$f"}) 960 { 961 $node->{client}->{$service}->{"$field.$f"} = $node->{client}->{$1}->{"$2.$f"}; 962 } 963 } 964 } 965 elsif ($path =~ /^\s*([^:\.]+)\s*$/) 966 { 967 print "\nDEBUG4: Expanding $path...\n" if $DEBUG; 968 $result = munin_get_filename ($config, $domain, $name, $service, $1); 969 for my $f (@copy_fields) 970 { 971 if (not exists $node->{client}->{$service}->{"$field.$f"} and 972 exists $node->{client}->{$service}->{"$1.$f"}) 973 { 974 $node->{client}->{$service}->{"$field.$f"} = $node->{client}->{$service}->{"$1.$f"}; 975 } 976 } 977 } 978 } 979 else 980 { 981 print "\nDEBUG5: Doing path...\n" if $DEBUG; 982 $result = munin_get_filename($config, $domain,$name,$service,$field); 1342 } else { 1343 $result = munin_get_filename ($field); 983 1344 } 984 1345 return $result; 985 1346 } 986 1347 1348 # munin_mkdir_p: Make directory (and path to it) 1349 # Parameters: 1350 # - $dirname: Directory to create 1351 # - $umask: Umask (in addition to the user umask) 1352 # Returns: 1353 # - Success: $dirname 1354 # - Failure: undef 1355 sub munin_mkdir_p 1356 { 1357 my $dirname = shift; 1358 my $umask = shift; 1359 1360 return $dirname if (-e $dirname); 1361 1362 1363 ::logger ("Notice: Created directory \"$dirname\"."); 1364 (my $prev = $dirname) =~ s/\/[^\/]+\/?$//; 1365 if (munin_mkdir_p ($prev, $umask)) { 1366 if (mkdir ($dirname, $umask)) { 1367 return $dirname; 1368 } else { 1369 return undef; 1370 } 1371 } else { 1372 return undef; 1373 } 1374 } 1375 987 1376 988 1377 1; people/jo/multilevel-groups-3/server/munin-domainview.tmpl.in
r860 r1502 4 4 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> 5 5 <head> 6 <link rel="stylesheet" href=" ../style.css" type="text/css" />6 <link rel="stylesheet" href="<TMPL_VAR NAME="CSSPATH">" type="text/css" /> 7 7 <meta http-equiv="refresh" content="300" /> 8 <title>Munin :: <TMPL_VAR NAME="DOMAIN"></title>8 <title>Munin <TMPL_LOOP NAME="PATH">:: <TMPL_VAR ESCAPE="HTML" NAME="NAME"></TMPL_LOOP></title> 9 9 <meta http-equiv="content-type" content="application/xhtml+xml; charset=iso-8859-1" /> 10 10 <meta name="author" content="Auto-generated by Munin" /> … … 15 15 <td rowspan="2"><div class="logo"> </div></td> 16 16 <td valign="top"> 17 <h2><a href="../index.html">Overview</a> :: <TMPL_VAR ESCAPE="HTML" NAME="DOMAIN"></h2>17 <h2><TMPL_LOOP NAME="PATH"><TMPL_IF NAME="PATH"><a href="<TMPL_VAR NAME="PATH">"></TMPL_IF><TMPL_VAR NAME="NAME"><TMPL_IF NAME="PATH"></a> :: </TMPL_IF></TMPL_LOOP></title> 18 18 </td> 19 19 </tr> … … 21 21 <tr> 22 22 <td valign="top"> 23 <h2><TMPL_VAR ESCAPE="HTML" NAME=" DOMAIN"> :: [ <a href="comparison-day.html">day</a> <a href="comparison-week.html">week</a> <a href="comparison-month.html">month</a> <a href="comparison-year.html">year</a> ]</h2>23 <h2><TMPL_VAR ESCAPE="HTML" NAME="NAME"> :: [ <a href="comparison-day.html">day</a> <a href="comparison-week.html">week</a> <a href="comparison-month.html">month</a> <a href="comparison-year.html">year</a> ]</h2> 24 24 </td> 25 25 </tr></TMPL_IF> … … 30 30 <td class="linkbox"> 31 31 <ul> 32 <TMPL_LOOP NAME=" NODES">33 <li><span class="domain"><a href="<TMPL_VAR NAME="NODE">.html"><TMPL_VAR ESCAPE="HTML" NAME="NODE"></a></span>32 <TMPL_LOOP NAME="GROUPS"> 33 <li><span class="domain"><a href="<TMPL_VAR NAME="URLX">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a></span> 34 34 <ul> 35 <TMPL_LOOP NAME="CATEGORIES"> 36 <li><span class="domain"><a href="<TMPL_VAR NAME="NODE">.html#<TMPL_VAR NAME="NAME">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a></span> 35 <TMPL_IF NAME="NCATEGORIES"><TMPL_LOOP NAME="CATEGORIES"> 36 <li><span class="host"><a href="<TMPL_VAR NAME="URLX">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a></span> 37 <ul> 38 <TMPL_LOOP NAME="SERVICES"> 39 <li><span class="service"><a <TMPL_IF NAME="STATE_WARNING">class="warn"</TMPL_IF> <TMPL_IF NAME="STATE_CRITICAL">class="crit"</TMPL_IF> href="<TMPL_VAR NAME="URLX">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a></span></li> 40 </TMPL_LOOP> 41 </ul> 42 </li> 43 </TMPL_LOOP></TMPL_IF> 44 <TMPL_IF NAME="NGROUPS"> 45 <TMPL_LOOP NAME="GROUPS"> 46 <li><span class="domain"><a href="<TMPL_VAR NAME="URLX">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a></span> 37 47 <ul> 38 <TMPL_LOOP NAME="SERVICES"> 39 <li><span class="host"><a <TMPL_IF NAME="STATE_WARNING">class="warn"</TMPL_IF> <TMPL_IF NAME="STATE_CRITICAL">class="crit"</TMPL_IF> href="<TMPL_VAR NAME="NODE">-<TMPL_VAR NAME="SERVICE">.html"><TMPL_VAR ESCAPE="HTML" NAME="LABEL"></a></span></li> 40 </TMPL_LOOP> 48 <TMPL_IF NAME="NCATEGORIES"><TMPL_LOOP NAME="CATEGORIES"> 49 <li><span class="host"><a href="<TMPL_VAR NAME="URLX">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a></span> 50 <ul> 51 <TMPL_LOOP NAME="SERVICES"> 52 <li><span class="service"><a <TMPL_IF NAME="STATE_WARNING">class="warn"</TMPL_IF> <TMPL_IF NAME="STATE_CRITICAL">class="crit"</TMPL_IF> href="<TMPL_VAR NAME="URLX">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a></span></li> 53 </TMPL_LOOP> 54 </ul> 55 </li> 56 </TMPL_LOOP></TMPL_IF> 57 <TMPL_IF NAME="NGROUPS"> 58 <TMPL_LOOP NAME="GROUPS"> 59 <li><span class="domain"><a href="<TMPL_VAR NAME="URLX">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a></span> 60 <ul> 61 <TMPL_IF NAME="NCATEGORIES"><TMPL_LOOP NAME="CATEGORIES"> 62 <li><span class="host"><a href="<TMPL_VAR NAME="URLX">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a></span> 63 <ul> 64 <TMPL_LOOP NAME="SERVICES"> 65 <li><span class="service"><a <TMPL_IF NAME="STATE_WARNING">class="warn"</TMPL_IF> <TMPL_IF NAME="STATE_CRITICAL">class="crit"</TMPL_IF> href="<TMPL_VAR NAME="URLX">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a></span></li> 66 </TMPL_LOOP> 67 </ul> 68 </li> 69 </TMPL_LOOP></TMPL_IF> 70 <TMPL_IF NAME="NGROUPS"> 71 </TMPL_IF> 41 72 </ul> 42 </li> 43 </TMPL_LOOP> 73 </li> 74 </TMPL_LOOP> 75 </TMPL_IF> 44 76 </ul> 45 </li> 46 </TMPL_LOOP> 77 </li> 78 </TMPL_LOOP> 79 </TMPL_IF> 80 </ul> 81 </li> 82 </TMPL_LOOP> 47 83 </ul> 48 84 </td></tr> … … 50 86 <tr> 51 87 <td class="linkbox"> 52 <TMPL_LOOP NAME="DOMAINS"> 53 <a href="../<TMPL_VAR NAME="DOMAIN">/index.html"><TMPL_VAR NAME="DOMAIN"></a> : 54 </TMPL_LOOP> 88 <TMPL_VAR NAME="PARENT"> :<TMPL_LOOP NAME="PEERS">: <TMPL_IF NAME="LINK"><a href="<TMPL_VAR NAME="LINK">"></TMPL_IF><TMPL_VAR NAME="NAME"><TMPL_IF NAME="LINK"></a></TMPL_IF></a> </TMPL_LOOP> 55 89 </td> 56 90 </tr> people/jo/multilevel-groups-3/server/munin-graph.in
r1442 r1502 214 214 my $watermark = "Munin $VERSION"; 215 215 216 for my $key ( keys %{$config->{domain}}) { 217 my $domain_time= Time::HiRes::time; 218 mkdir "$config->{htmldir}/$key",0777; 219 logger("Processing domain: $key"); 220 &process_domain($key); 221 $domain_time = sprintf ("%.2f",(Time::HiRes::time - $domain_time)); 222 logger("Processed domain: $key ($domain_time sec)"); 223 print STATS "GD|$key|$domain_time\n" unless $skip_stats; 224 } 225 216 # Make array of what is probably needed to graph 217 my $work_array = []; 218 if (@limit_hosts) { # Limit what to update if needed 219 foreach my $nodename (@limit_hosts) { 220 push @$work_array, map { @{munin_find_field ($_->{$nodename}, "graph_title")} } @{munin_find_field($config, $nodename)}; 221 } 222 } else { # ...else just search for all adresses to update 223 push @$work_array, @{munin_find_field($config, "graph_title")}; 224 } 225 226 227 for my $service (@$work_array) { 228 process_service ($service); 229 } 226 230 227 231 $graph_time = sprintf ("%.2f",(Time::HiRes::time - $graph_time)); … … 236 240 # ### The End 237 241 238 sub process_domain {239 my ($domain) = @_;240 for my $key ( keys %{$config->{domain}->{$domain}->{node}}) {241 my $node_time= Time::HiRes::time;242 243 process_node($domain,$key ,$config->{domain}->{$domain}->{node}->{$key} );244 $node_time = sprintf ("%.2f",(Time::HiRes::time - $node_time));245 logger ("Processed node: $key ($node_time sec)");246 print STATS "GN|$domain|$key|$node_time\n" unless $skip_stats;247 }248 }249 250 242 sub get_title { 251 my $node = shift;252 243 my $service = shift; 253 244 my $scale = shift; 254 245 255 return ($node->{client}->{$service}->{'graph_title'}? 256 $node->{client}->{$service}->{'graph_title'}:$service) . 257 " - by $scale"; 246 return (munin_get ($service, "graph_title", $service) . " - by $scale"); 258 247 } 259 248 260 249 sub get_custom_graph_args 261 250 { 262 my $node = shift;263 251 my $service = shift; 264 252 my $result = []; 265 253 266 if ($node->{client}->{$service}->{graph_args}) { 267 push @$result, split /\s/,$node->{client}->{$service}->{graph_args}; 254 my $args = munin_get ($service, "graph_args"); 255 if (defined $args) { 256 push @$result, split /\s/,$args; 268 257 return $result; 269 } 270 else 271 { 258 } else { 272 259 return undef; 273 260 } … … 276 263 sub get_vlabel 277 264 { 278 my $node = shift;279 265 my $service = shift; 280 my $scale = shift; 281 282 if ($node->{client}->{$service}->{graph_vlabel}) { 283 (my $res = $node->{client}->{$service}->{graph_vlabel}) =~ s/\$\{graph_period\}/$scale/g; 284 return $res; 285 } 286 elsif ($node->{client}->{$service}->{graph_vtitle}) 287 { 288 return $node->{client}->{$service}->{graph_vtitle}; 289 } 290 return undef; 266 my $scale = munin_get ($service, "graph_period", "second"); 267 my $res = munin_get ($service, "graph_vlabel", munin_get ($service, "graph_vtitle")); 268 269 if (defined $res) { 270 $res =~ s/\$\{graph_period\}/$scale/g; 271 } 272 return $res; 291 273 } 292 274 293 275 sub should_scale 294 276 { 295 my $node = shift;296 277 my $service = shift; 297 298 if (defined $node->{client}->{$service}->{graph_scale}) 299 { 300 return &munin_get_bool_val ($node->{client}->{$service}->{graph_scale}, 1); 301 } 302 elsif (defined $node->{client}->{$service}->{graph_noscale}) 303 { 304 return ! &munin_get_bool_val ($node->{client}->{$service}->{graph_noscale}, 0); 305 } 306 307 return 1; 278 my $ret; 279 280 if (!defined ($ret = munin_get_bool ($service, "graph_scale"))) { 281 $ret = !munin_get_bool ($service, "graph_noscale", 0); 282 } 283 284 return $ret; 308 285 } 309 286 310 287 sub get_header { 311 my $node = shift;312 my $config = shift;313 my $domain = shift;314 my $host = shift;315 288 my $service = shift; 316 289 my $scale = shift; … … 320 293 321 294 # Picture filename 322 push @$result, &munin_get_picture_filename ($config, $domain, $host,$service, $scale, $sum||undef);295 push @$result, munin_get_picture_filename ($service, $scale, $sum||undef); 323 296 324 297 # Title 325 push @$result, ("--title", &get_title ($node,$service, $scale));298 push @$result, ("--title", get_title ($service, $scale)); 326 299 327 300 # When to start the graph … … 329 302 330 303 # Custom graph args, vlabel and graph title 331 if (defined ($tmp_field = &get_custom_graph_args ($node,$service))) {304 if (defined ($tmp_field = get_custom_graph_args ($service))) { 332 305 push (@$result, @{$tmp_field}); 333 306 } 334 if (defined ($tmp_field = &get_vlabel ($node, $service, munin_get ($config, "graph_period", "second", $domain, $host, $service)))) {307 if (defined ($tmp_field = get_vlabel ($service))) { 335 308 push @$result, ("--vertical-label", $tmp_field); 336 309 } 337 310 338 push @$result,"--height", &munin_get ($config, "graph_height", "175", $domain, $host, $service);339 push @$result,"--width", &munin_get ($config, "graph_width", "400", $domain, $host, $service);311 push @$result,"--height", munin_get ($service, "graph_height", "175"); 312 push @$result,"--width", munin_get ($service, "graph_width", "400"); 340 313 push @$result,"--imgformat", "PNG"; 341 314 push @$result,"--lazy" if ($force_lazy); 342 315 343 push (@$result, "--units-exponent", "0") 344 if (! &should_scale ($node, $service)); 316 push (@$result, "--units-exponent", "0") if (! should_scale ($service)); 345 317 346 318 return $result; … … 349 321 sub get_sum_command 350 322 { 351 my $node = shift;352 my $service = shift;353 323 my $field = shift; 354 324 355 if (defined $node->{client}->{$service}->{$field.".special_sum"}) 356 { 357 return $node->{client}->{$service}->{$field.".special_sum"}; 358 } 359 elsif (defined $node->{client}->{$service}->{$field.".sum"}) 360 { 361 return $node->{client}->{$service}->{$field.".sum"}; 362 } 363 364 return undef; 325 if (defined $field->{"special_sum"}) { # Deprecated 326 return $field->{"special_sum"}; 327 } 328 329 return munin_get ($field, "sum"); 365 330 } 366 331 367 332 sub get_stack_command 368 333 { 369 my $node = shift;370 my $service = shift;371 334 my $field = shift; 372 335 373 if (defined $node->{client}->{$service}->{$field.".special_stack"}) 374 { 375 return $node->{client}->{$service}->{$field.".special_stack"}; 376 } 377 elsif (defined $node->{client}->{$service}->{$field.".stack"}) 378 { 379 return $node->{client}->{$service}->{$field.".stack"}; 380 } 381 382 return undef; 336 if (defined $field->{"special_stack"}) { # Deprecated 337 return $field->{"special_stack"}; 338 } 339 340 return munin_get ($field, "stack"); 383 341 } 384 342 385 343 sub expand_specials 386 344 { 387 my $node = shift;388 my $config = shift;389 my $domain = shift;390 my $host = shift;391 345 my $service = shift; 392 346 my $preproc = shift; … … 397 351 my $fieldnum = 0; 398 352 for my $field (@$order) { # Search for 'specials'... 399 400 if ($field =~ /^-(.+)$/) 401 {353 my $tmp_field; 354 355 if ($field =~ /^-(.+)$/) { # Invisible field 402 356 $field = $1; 403 unless (defined $node->{client}->{$service}->{$field.".graph"} or 404 defined $node->{client}->{$service}->{$field.".skipdraw"}) 405 { 406 $node->{client}->{$service}->{$field.".graph"} = "no"; 407 } 357 munin_set_var_loc ($service, [$field, "graph"], "no"); 408 358 } 409 359 410 360 $fieldnum++; 411 my $tmp_field; 412 if (defined ($tmp_field = &get_stack_command ($node, $service, $field))) 413 { 414 print "DEBUG: Doing special_stack...\n" if $DEBUG; 361 if ($field =~ /^([^=]+)=(.+)$/) { # Aliased in graph_order 362 my $fname = $1; 363 my $spath = $2; 364 my $src = munin_get_node_partialpath ($service, $spath); 365 my $sname = munin_get_node_name ($src); 366 367 next unless defined $src; 368 logger ("Debug: Copying settings from $sname to $fname.") if $DEBUG; 369 370 foreach my $foption ("draw", "type", "rrdfile", "fieldname", "info") { 371 if (!defined $service->{$fname}->{$foption}) { 372 if (defined $src->{$foption}) { 373 munin_set_var_loc ($service, [$fname, $foption], $src->{$foption}); 374 } 375 } 376 } 377 378 # cdef is special... 379 if (!defined $service->{$fname}->{"cdef"}) { 380 if (defined $src->{"cdef"}) { 381 (my $tmpcdef = $src->{"cdef"}) =~ s/([,=])$sname([,=]|$)/$1$fname$2/g; 382 munin_set_var_loc ($service, [$fname, "cdef"], $tmpcdef); 383 } 384 } 385 386 munin_set_var_loc ($service, [$fname, "label"], $fname); 387 munin_set_var_loc ($service, [$fname, "filename"], munin_get_rrd_filename ($src)); 388 389 } elsif (defined ($tmp_field = get_stack_command ($service->{$field}))) { 390 logger ("DEBUG: expand_specials ($tmp_field): Doing stack...") if $DEBUG; 415 391 my @spc_stack = (); 416 foreach my $pre (split (/\s+/, $tmp_field)) 417 { 392 foreach my $pre (split (/\s+/, $tmp_field)) { 418 393 (my $name = $pre) =~ s/=.+//; 419 if (!@spc_stack) 420 { 421 $node->{client}->{$service}->{$name.".draw"} = $node->{client}->{$service}->{$field.".draw"}; 422 $node->{client}->{$service}->{$field.".process"} = "no"; 423 } 424 else 425 { 426 $node->{client}->{$service}->{$name.".draw"} = "STACK"; 394 if (!@spc_stack) { 395 munin_set_var_loc ($service, [$name, "draw"], munin_get ($service->{$field}, "draw", "LINE2")); 396 munin_set_var_loc ($service, [$field, "process"], "no"); 397 } else { 398 munin_set_var_loc ($service, [$name, "draw"], "STACK"); 427 399 } 428 400 push (@spc_stack, $name); … … 432 404 push @$result, "$name.cdef"; 433 405 434 $node->{client}->{$service}->{$name.".label"} = $name; 435 $node->{client}->{$service}->{$name.".cdef"} = "$name,UN,0,$name,IF"; 436 if (exists $node->{client}->{$service}->{$field.".cdef"} and !exists $node->{client}->{$service}->{$name.".onlynullcdef"}) 437 { 438 print "NotOnlynullcdef ($field)...\n" if $DEBUG; 439 $node->{client}->{$service}->{$name.".cdef"} .= "," . 440 $node->{client}->{$service}->{$field.".cdef"}; 441 $node->{client}->{$service}->{$name.".cdef"} =~ s/\b$field\b/$name/g; 442 } 443 else 444 { 445 print "Onlynullcdef ($field)...\n" if $DEBUG; 446 $node->{client}->{$service}->{$name.".onlynullcdef"} = 1; 406 munin_set_var_loc ($service, [$name, "label"], $name); 407 munin_set_var_loc ($service, [$name, "cdef"], "$name,UN,0,$name,IF"); 408 if (munin_get ($service->{$field}, "cdef") and !munin_get_bool ($service->{$name}, "onlynullcdef", 0)) { 409 logger ("NotOnlynullcdef ($field)...") if $DEBUG; 410 $service->{$name}->{"cdef"} .= "," . $service->{$field}->{"cdef"}; 411 $service->{$name}->{"cdef"} =~ s/\b$field\b/$name/g; 412 } else { 413 logger ("Onlynullcdef ($field)...") if $DEBUG; 414 munin_set_var_loc ($service, [$name, "onlynullcdef"], 1); 447 415 push @$result, "$name.onlynullcdef"; 448 416 } 449 417 } 450 } 451 elsif (defined ($tmp_field = &get_sum_command ($node, $service, $field))) 452 { 418 } elsif (defined ($tmp_field = get_sum_command ($service->{$field}))) { 453 419 my @spc_stack = (); 454 420 my $last_name = ""; 455 print "DEBUG: Doing special_sum...\n" if $DEBUG; 456 457 if (@$order == 1 or 458 @$order == 2 && $node->{client}->{$service}->{$field.".negative"}) 459 { 460 $single = 1; 461 } 421 logger ("DEBUG: expand_specials ($tmp_field): Doing sum...") if $DEBUG; 422 423 if (@$order == 1 or (@$order == 2 and munin_get {$field, "negative", 0})) { 424 $single = 1; 425 } 462 426 463 foreach my $pre (split (/\s+/, $tmp_field)) 464 { 427 foreach my $pre (split (/\s+/, $tmp_field)) { 465 428 (my $path = $pre) =~ s/.+=//; 466 429 my $name = "z".$fieldnum."_".scalar (@spc_stack); 467 430 $last_name = $name; 468 431 469 $node->{client}->{$service}->{$name.".cdef"} = "$name,UN,0,$name,IF";470 $node->{client}->{$service}->{$name.".graph"} = "no";471 $node->{client}->{$service}->{$name.".label"} = $name;432 munin_set_var_loc ($service, [$name, "cdef"], "$name,UN,0,$name,IF"); 433 munin_set_var_loc ($service, [$name, "graph"], "no"); 434 munin_set_var_loc ($service, [$name, "label"], $name); 472 435 push @$result, "$name.cdef"; 473 436 push @$result, "$name.graph"; … … 477 440 push (@$preproc, "$name=$pre"); 478 441 } 479 $node->{client}->{$service}->{$last_name.".cdef"} .= 480 "," . join (',+,', @spc_stack[0 .. @spc_stack-2]) . ',+'; 481 if (exists $node->{client}->{$service}->{$field.".cdef"} and 482 length $node->{client}->{$service}->{$field.".cdef"}) 483 { # Oh bugger... 484 my $tc = $node->{client}->{$service}->{$field.".cdef"}; 442 $service->{$last_name}->{"cdef"} .= "," . join (',+,', @spc_stack[0 .. @spc_stack-2]) . ',+'; 443 444 if (my $tc = munin_get ($service->{$field}, "cdef", 0)) { # Oh bugger... 485 445 print "Oh bugger...($field)...\n" if $DEBUG; 486 $tc =~ s/\b$field\b/$node->{client}->{$service}->{$last_name.".cdef"}/; 487 $node->{client}->{$service}->{$last_name.".cdef"} = $tc; 488 } 489 $node->{client}->{$service}->{$field.".process"} = "no"; 490 $node->{client}->{$service}->{$last_name.".draw"} = $node->{client}->{$service}->{$field.".draw"}; 491 $node->{client}->{$service}->{$last_name.".label"} = $node->{client}->{$service}->{$field.".label"}; 492 if (defined $node->{client}->{$service}->{$field.".graph"}) 493 { 494 $node->{client}->{$service}->{$last_name.".graph"} = $node->{client}->{$service}->{$field.".graph"}; 495 } 496 else 497 { 498 $node->{client}->{$service}->{$last_name.".graph"} = "yes"; 499 } 500 if (defined $node->{client}->{$service}->{$field.".negative"}) 501 { 502 $node->{client}->{$service}->{$last_name.".negative"} = $node->{client}->{$service}->{$field.".negative"};; 503 } 504 $node->{client}->{$service}->{$field.".realname"} = $last_name; 505 print "Setting node->{client}->{$service}->{$field} -> realname = $last_name...\n" if $DEBUG; 506 } 507 elsif (defined $node->{client}->{$service}->{$field.".negative"}) 508 { 509 my $nf = $node->{client}->{$service}->{$field.".negative"}; 510 unless (defined $node->{client}->{$service}->{$nf.".graph"} or 511 defined $node->{client}->{$service}->{$nf.".skipdraw"}) 512 { 513 $node->{client}->{$service}->{$nf.".graph"} = "no"; 446 $tc =~ s/\b$field\b/$service->{$last_name}->{"cdef"}/; 447 $service->{$last_name}->{"cdef"} = $tc; 448 } 449 munin_set_var_loc ($service, [$field, "process"], "no"); 450 munin_set_var_loc ($service, [$last_name, "draw"], munin_get ($service->{$field}, "draw")); 451 munin_set_var_loc ($service, [$last_name, "label"], munin_get ($service->{$field}, "label")); 452 munin_set_var_loc ($service, [$last_name, "graph"], munin_get ($service->{$field}, "graph", "yes")); 453 454 if (my $tmp = munin_get($service->{$field}, "negative")) { 455 munin_set_var_loc ($service, [$last_name, "negative"], $tmp); 456 } 457 458 munin_set_var_loc ($service, [$field, "realname"], $last_name); 459 460 } elsif (my $nf = munin_get ($service->{$field}, "negative", 0)) { 461 if (!munin_get_bool ($service->{$nf}, "graph", 1) or munin_get_bool ($service->{$nf}, "skipdraw", 0)) { 462 munin_set_var_loc ($service, [$nf, "graph"], "no"); 514 463 } 515 464 } … … 520 469 sub single_value 521 470 { 522 my $node = shift;523 my $config = shift;524 my $domain = shift;525 my $host = shift;526 471 my $service = shift; 527 my $field = shift; 528 my $order = shift; 529 530 return 1 if @$order == 1; 531 return 1 if (@$order == 2 and $node->{client}->{$service}->{$field.".negative"}); 532 533 my $graphable = 0; 534 if (!defined $node->{client}->{$service}->{"graphable"}) 535 { 536 # foreach my $field (keys %{$node->{client}->{$service}}) 537 foreach my $field (&munin_get_field_order ($node, $config, $domain, $host, $service)) 538 { 539 print "DEBUG: single_value: Checking field \"$field\".\n" if $DEBUG; 540 if ($field =~ /^([^\.]+)\.label/ or $field =~ /=/) 541 { 542 $graphable++ if &munin_draw_field ($node, $service, $1); 543 } 544 } 545 $node->{client}->{$service}->{"graphable"} = $graphable; 546 } 547 return 1 if ($node->{client}->{$service}->{"graphable"} == 1); 548 549 return 0; 472 473 my $graphable = munin_get ($service, "graphable", 0);; 474 if (!$graphable) { 475 foreach my $field (@{munin_get_field_order ($service)}) { 476 logger ("DEBUG: single_value: Checking field \"$field\"."); 477 $graphable++ if munin_draw_field ($service->{$field}); 478 } 479 munin_set_var_loc ($service, ["graphable"], $graphable); 480 } 481 logger ("Debug: service ". join (' :: ', @{munin_get_node_loc ($service)}) ." has $graphable elements."); 482 return ($graphable == 1); 550 483 } 551 484 … … 561 494 562 495 sub process_field { 563 my $node = shift;564 my $service = shift;565 496 my $field = shift; 566 return (&munin_get_bool_val ($node->{client}->{$service}->{$field.".process"}, 1)); 567 } 568 569 sub process_node { 570 my ($domain,$name,$node) = @_; 571 572 # See if we should skip it because of command-line arguments 573 return if (@limit_hosts and not grep (/^$name$/, @limit_hosts)); 497 return munin_get_bool ($field, "process", 1); 498 } 499 500 sub process_service { 501 my ($service) = @_; 574 502 575 503 # Make my graphs 576 logger ("Processing $name") if $DEBUG; 577 for my $service (keys %{$node->{client}}) { 578 my $service_time= Time::HiRes::time; 579 my $lastupdate = 0; 580 my $now = time; 581 my $fnum = 0; 582 my @rrd; 583 my @added = (); 584 585 # See if we should skip the service 586 next if (&skip_service ($node, $service)); 587 588 my $field_count = 0; 589 my $max_field_len = 0; 590 my @field_order = (); 591 my $rrdname; 592 my $force_single_value; 593 594 # munin_set_context($node,$config,$domain,$name,$service); 595 596 @field_order = 597 @{&munin_get_field_order($node, $config, $domain, $name, 598 $service, \$force_single_value)}; 599 600 # Array to keep 'preprocess'ed fields. 601 my @rrd_preprocess = (); 602 print "DEBUG: Expanding specials \"", 603 join("\",\"", @field_order), "\".\n" 604 if $DEBUG; 605 606 @added = 607 @{&expand_specials ($node, $config, $domain, $name, 608 $service, \@rrd_preprocess, \@field_order)}; 609 610 @field_order = (@rrd_preprocess, @field_order); 611 print "DEBUG: Checking field lengths \"", 612 join("\",\"", @rrd_preprocess), "\".\n" 613 if $DEBUG; 614 615 # Get max label length 616 $max_field_len = 617 &munin_get_max_label_length ($node, $config, $domain, $name, 618 $service, \@field_order); 619 # my $global_headers = ($max_field_len >= 16); 620 # Global headers makes the value tables easier to read no matter how 621 # wide the labels are. 622 my $global_headers = 1; 623 624 # Default format for printing under graph. 625 my $avgformat; 626 my $rrdformat=$avgformat="%6.2lf"; 627 628 if (exists $node->{client}->{$service}->{graph_args} and 629 $node->{client}->{$service}->{graph_args} =~ /--base\s+1024/) { 630 # If the base unit is 1024 then 1012.56 is a valid 631 # number to show. That's 7 positions, not 6. 632 $rrdformat=$avgformat="%7.2lf"; 633 } 634 635 if (exists $node->{client}->{$service}->{graph_printf} ) { 636 # Plugin specified complete printf format 637 $rrdformat=$node->{client}->{$service}->{graph_printf}; 638 } 639 640 my $rrdscale = ''; 641 $rrdscale = '%s' 642 if munin_get_bool_val ($node->{client}->{$service}->{graph_scale},1); 643 644 # Array to keep negative data until we're finished with positive. 645 my @rrd_negatives = (); 646 my $filename = "unknown"; 647 my %total_pos; 648 my %total_neg; 649 my $autostacking=0; 650 print "DEBUG: Treating fields \"", join "\",\"", @field_order, "\".\n" if $DEBUG; 651 for my $field (@field_order) { 652 my $path = undef; 653 if ($field =~ s/=(.+)//) { 654 $path = $1; 655 } 656 657 next unless &process_field ($node, $service, $field); 658 print "DEBUG: Processing field \"$field\".\n" if $DEBUG; 659 660 my $fielddraw = munin_get ($config, "draw", "LINE2", $domain, 661 $name, $service, $field); 662 663 if ($field_count == 0 and $fielddraw eq 'STACK') { 664 # Illegal -- first field is a STACK 665 logger ("ERROR: First field (\"$field\") of graph \"$domain\"". 666 ":: \"$name\" :: \"$service\" is STACK. STACK can ". 667 "only be drawn after a LINEx or AREA."); 668 $fielddraw = "LINE2"; 669 } 670 671 if ($fielddraw eq 'AREASTACK') { 672 if ($autostacking==0) { 673 $fielddraw='AREA'; 674 $autostacking=1; 675 } else { 676 $fielddraw='STACK'; 677 } 678 } 679 680 if ($fielddraw =~ /LINESTACK(\d+(?:.\d+)?)/ ) { 681 if ($autostacking==0) { 682 $fielddraw="LINE$1"; 683 $autostacking=1; 684 } else { 685 $fielddraw='STACK'; 686 } 687 } 688 689 # Getting name of rrd file 690 $filename = &munin_get_rrd_filename ($node, $config, $domain, 691 $name, $service, $field, 692 $path); 693 694 my $update = RRDs::last ($filename); 695 $update = 0 if ! defined $update; 696 if ($update > $lastupdate) { 697 $lastupdate = $update; 698 } 699 700 # It does not look like $fieldname.rrdfield is possible to set 701 my $rrdfield = ($node->{client}->{$service}->{$field.".rrdfield"} 702 || "42"); 703 704 my $single_value = $force_single_value || 705 &single_value ($node, $config, $domain, $name, 706 $service, $field, \@field_order); 707 708 my $has_negative = 709 exists $node->{client}->{$service}->{$field.".negative"}; 710 711 # Trim the fieldname to make room for other field names. 712 $rrdname = &get_field_name ($field); 713 if ($rrdname ne $field) { 714 # A change was made 715 set_cdef_name ($node->{client}->{$service}, $field, $rrdname); 716 } 717 718 push (@rrd, "DEF:g$rrdname=" . 719 $filename . ":" . $rrdfield . ":AVERAGE"); 720 push (@rrd, "DEF:i$rrdname=" . 721 $filename . ":" . $rrdfield . ":MIN"); 722 push (@rrd, "DEF:a$rrdname=" . 723 $filename . ":" . $rrdfield . ":MAX"); 724 725 if (exists $node->{client}->{$service}->{$field.".onlynullcdef"} 726 and 727 $node->{client}->{$service}->{$field.".onlynullcdef"}) { 728 push (@rrd, "CDEF:c$rrdname=g$rrdname" . 729 (($now-$update)>900 ? ",POP,UNKN" : "")); 730 } 731 732 if (($node->{client}->{$service}->{$field.".type"}||"GAUGE") 733 ne "GAUGE" 734 and graph_by_minute ($config, $domain, $name, $service)) { 735 push (@rrd, &expand_cdef($node->{client}->{$service}, 736 \$rrdname, "$field,60,*")); 737 } 738 739 if ($node->{client}->{$service}->{$field.".cdef"}) { 740 push (@rrd,&expand_cdef($node->{client}->{$service}, 741 \$rrdname, 742 $node->{client}->{$service}->{$field.".cdef"})); 743 push (@rrd, "CDEF:c$rrdname=g$rrdname"); 744 print "DEBUG: Field name after cdef set to $rrdname\n" if $DEBUG; 745 } elsif (!(exists $node->{client}->{$service}->{$field.".onlynullcdef"} 746 and $node->{client}->{$service}->{$field.".onlynullcdef"})) { 747 push (@rrd, "CDEF:c$rrdname=g$rrdname" . (($now-$update)>900 ? ",POP,UNKN" : "")); 748 } 749 750 next unless &munin_draw_field ($node, $service, $field); 751 print "DEBUG: Drawing field \"$field\".\n" if $DEBUG; 504 my $sname = munin_get_node_name ($service); 505 my $service_time= Time::HiRes::time; 506 my $lastupdate = 0; 507 my $now = time; 508 my $fnum = 0; 509 my @rrd; 510 my @added = (); 511 512 # See if we should skip the service 513 return if (skip_service ($service)); 514 515 my $field_count = 0; 516 my $max_field_len = 0; 517 my @field_order = (); 518 my $rrdname; 519 my $force_single_value; 520 521 @field_order = @{munin_get_field_order($service)}; 522 523 # Array to keep 'preprocess'ed fields. 524 my @rrd_preprocess = (); 525 logger ("Debug: Expanding specials for $sname: \"" . join("\",\"", @field_order) . "\".") if $DEBUG; 526 527 @added = @{&expand_specials ($service, \@rrd_preprocess, \@field_order, \$force_single_value)}; 528 529 @field_order = (@rrd_preprocess, @field_order); 530 logger ("DEBUG: Checking field lengths for $sname: \"" . join("\",\"", @rrd_preprocess) . "\".") if $DEBUG; 531 532 # Get max label length 533 $max_field_len = munin_get_max_label_length ($service, \@field_order); 534 535 # Global headers makes the value tables easier to read no matter how 536 # wide the labels are. 537 my $global_headers = 1; 538 539 # Default format for printing under graph. 540 my $avgformat; 541 my $rrdformat=$avgformat="%6.2lf"; 542 543 if (munin_get ($service, "graph_args", "") =~ /--base\s+1024/) { 544 # If the base unit is 1024 then 1012.56 is a valid 545 # number to show. That's 7 positions, not 6. 546 $rrdformat=$avgformat="%7.2lf"; 547 } 548 549 # Plugin specified complete printf format 550 $rrdformat = munin_get ($service, "graph_printf", $rrdformat); 551 552 my $rrdscale = ''; 553 if (munin_get_bool ($service, "graph_scale", 1)) { 554 $rrdscale = '%s'; 555 } 556 557 # Array to keep negative data until we're finished with positive. 558 my @rrd_negatives = (); 559 560 my $filename = "unknown"; 561 my %total_pos; 562 my %total_neg; 563 my $autostacking=0; 564 565 logger ("DEBUG: Treating fields \"" . join ("\",\"", @field_order) . "\".") if $DEBUG; 566 for my $fname (@field_order) { 567 my $path = undef; 568 my $field = undef; 569 570 if ($fname =~ s/=(.+)//) { 571 $path = $1; 572 } 573 $field = munin_get_node ($service, [$fname]); 574 575 next if (!defined $field or !$field or !process_field ($field)); 576 logger ("DEBUG: Processing field \"$fname\" [".munin_get_node_name($field)."].") if $DEBUG; 577 578 my $fielddraw = munin_get ($field, "draw", "LINE2"); 579 580 if ($field_count == 0 and $fielddraw eq 'STACK') { 581 # Illegal -- first field is a STACK 582 logger ("ERROR: First field (\"$fname\") of graph " . join (' :: ', munin_get_node_loc ($service)) . 583 " is STACK. STACK can only be drawn after a LINEx or AREA."); 584 $fielddraw = "LINE2"; 585 } 586 587 if ($fielddraw eq 'AREASTACK') { 588 if ($autostacking==0) { 589 $fielddraw='AREA'; 590 $autostacking=1; 591 } else { 592 $fielddraw='STACK'; 593 } 594 } 595 596 if ($fielddraw =~ /LINESTACK(\d+(?:.\d+)?)/ ) { 597 if ($autostacking==0) { 598 $fielddraw="LINE$1"; 599 $autostacking=1; 600 } else { 601 $fielddraw='STACK'; 602 } 603 } 604 605 # Getting name of rrd file 606 $filename = munin_get_rrd_filename ($field, $path); 607 608 my $update = RRDs::last ($filename); 609 $update = 0 if ! defined $update; 610 if ($update > $lastupdate) { 611 $lastupdate = $update; 612 } 613 614 # It does not look like $fieldname.rrdfield is possible to set 615 my $rrdfield = munin_get ($field, "rrdfield", "42"); 616 617 my $single_value = $force_single_value || single_value ($service); 618 619 my $has_negative = munin_get ($field, "negative"); 620 621 # Trim the fieldname to make room for other field names. 622 $rrdname = &get_field_name ($fname); 623 if ($rrdname ne $fname) { 624 # A change was made 625 munin_set_var ($field, "cdef_name", $rrdname); 626 } 627 628 push (@rrd, "DEF:g$rrdname=" . 629 $filename . ":" . $rrdfield . ":AVERAGE"); 630 push (@rrd, "DEF:i$rrdname=" . 631 $filename . ":" . $rrdfield . ":MIN"); 632 push (@rrd, "DEF:a$rrdname=" . 633 $filename . ":" . $rrdfield . ":MAX"); 634 635 if (munin_get_bool ($field, "onlynullcdef", 0)) { 636 push (@rrd, "CDEF:c$rrdname=g$rrdname" . (($now-$update)>900 ? ",POP,UNKN" : "")); 637 } 638 639 if (munin_get ($field, "type", "GAUGE") ne "GAUGE" and graph_by_minute ($service)) { 640 push (@rrd, expand_cdef($service, \$rrdname, "$fname,60,*")); 641 } 642 643 if (my $tmpcdef = munin_get ($field, "cdef")) { 644 push (@rrd,expand_cdef($service, \$rrdname, $tmpcdef)); 645 push (@rrd, "CDEF:c$rrdname=g$rrdname"); 646 logger ("DEBUG: Field name after cdef set to $rrdname") if $DEBUG; 647 } elsif (!munin_get_bool ($field, "onlynullcdef", 0)) { 648 push (@rrd, "CDEF:c$rrdname=g$rrdname" . (($now-$update)>900 ? ",POP,UNKN" : "")); 649 } 650 651 next if !munin_draw_field ($field); 652 logger ("DEBUG: Drawing field \"$fname\".") if $DEBUG; 653 654 if ($single_value) { 655 # Only one field. Do min/max range. 656 push (@rrd, "CDEF:min_max_diff=a$rrdname,i$rrdname,-"); 657 push (@rrd, "CDEF:re_zero=min_max_diff,min_max_diff,-") if !munin_get ($field, "negative"); 658 push (@rrd, "AREA:i$rrdname#ffffff"); 659 push (@rrd, "STACK:min_max_diff$range_colour"); 660 push (@rrd, "LINE2:re_zero#000000") if !munin_get ($field, "negative"); 661 } 662 663 if ($has_negative and !@rrd_negatives) { # Push "global" headers... 664 push (@rrd, "COMMENT:" . (" " x $max_field_len)); 665 push (@rrd, "COMMENT:Cur (-/+)"); 666 push (@rrd, "COMMENT:Min (-/+)"); 667 push (@rrd, "COMMENT:Avg (-/+)"); 668 push (@rrd, "COMMENT:Max (-/+) \\j"); 669 } elsif ($global_headers == 1) { 670 push (@rrd, "COMMENT:" . (" " x $max_field_len)); 671 push (@rrd, "COMMENT: Cur$RRDkludge:"); 672 push (@rrd, "COMMENT:Min$RRDkludge:"); 673 push (@rrd, "COMMENT:Avg$RRDkludge:"); 674 push (@rrd, "COMMENT:Max$RRDkludge: \\j"); 675 $global_headers++; 676 } 677 678 my $colour; 679 680 if (my $tmpcol = munin_get ($field, "colour")) { 681 $colour = "#" . $tmpcol; 682 } elsif ($single_value) { 683 $colour = $single_colour; 684 } else { 685 $colour = $COLOUR[$field_count%@COLOUR]; 686 } 687 688 $field_count++; 689 690 my $tmplabel = munin_get ($field, "label", $fname); 691 692 push (@rrd, $fielddraw . ":g$rrdname" . $colour . ":" . 693 escape ($tmplabel) . (" " x ($max_field_len + 1 - length $tmplabel))); 694 695 # Check for negative fields (typically network (or disk) traffic) 696 if ($has_negative) { 697 my $negfieldname = orig_to_cdef ($service, munin_get ($field, "negative")); 698 my $negfield = $service->{$negfieldname}; 699 if (my $tmpneg = munin_get ($negfield, "realname")) { 700 $negfieldname = $tmpneg; 701 $negfield = $service->{$negfieldname}; 702 } 703 704 if (!@rrd_negatives) { 705 # zero-line, to redraw zero afterwards. 706 push (@rrd_negatives, "CDEF:re_zero=g$negfieldname,UN,0,0,IF"); 707 } 708 709 push (@rrd_negatives, "CDEF:ng$negfieldname=g$negfieldname,-1,*"); 752 710 753 711 if ($single_value) { 754 712 # Only one field. Do min/max range. 755 push (@rrd, "CDEF:min_max_diff=a$rrdname,i$rrdname,-"); 756 push (@rrd, "CDEF:re_zero=min_max_diff,min_max_diff,-") 757 unless ($node->{client}->{$service}->{$field.".negative"}); 758 push (@rrd, "AREA:i$rrdname#ffffff"); 759 push (@rrd, "STACK:min_max_diff$range_colour"); 760 push (@rrd, "LINE2:re_zero#000000") 761 unless ($node->{client}->{$service}->{$field.".negative"}); 762 } 763 764 if ($has_negative and !@rrd_negatives) { # Push "global" headers... 765 push (@rrd, "COMMENT:" . (" " x $max_field_len)); 766 push (@rrd, "COMMENT:Cur (-/+)"); 767 push (@rrd, "COMMENT:Min (-/+)"); 768 push (@rrd, "COMMENT:Avg (-/+)"); 769 push (@rrd, "COMMENT:Max (-/+) \\j"); 770 } elsif ($global_headers == 1) { 771 push (@rrd, "COMMENT:" . (" " x $max_field_len)); 772 push (@rrd, "COMMENT: Cur$RRDkludge:"); 773 push (@rrd, "COMMENT:Min$RRDkludge:"); 774 push (@rrd, "COMMENT:Avg$RRDkludge:"); 775 push (@rrd, "COMMENT:Max$RRDkludge: \\j"); 776 $global_headers++; 777 } 778 779 my $colour; 780 781 if (exists $node->{client}->{$service}->{$field.".colour"}) { 782 $colour = "#". 783 $node->{client}->{$service}->{$field.".colour"}; 784 } elsif ($single_value) { 785 $colour = $single_colour; 786 } else { 787 $colour = $COLOUR[$field_count%@COLOUR]; 788 } 789 790 $field_count++; 791 792 push (@rrd, $fielddraw . ":g$rrdname" . $colour . ":" . 793 (escape ($node->{client}->{$service}->{"$field.label"}) || escape ($field)) 794 . (" " x ($max_field_len + 1 - 795 length ($node->{client}->{$service}->{"$field.label"} || $field)))); 796 797 # Check for negative fields (typically network (or disk) traffic) 798 if ($has_negative) { 799 my $negfield = &orig_to_cdef ($node->{client}->{$service}, $node->{client}->{$service}->{$field.".negative"}); 800 print "DEBUG: negfield = $negfield\n" if $DEBUG; 801 if (exists $node->{client}->{$service}->{$negfield.".realname"}) { 802 $negfield = $node->{client}->{$service}->{$negfield.".realname"}; 803 } 804 805 if (!@rrd_negatives) { 806 # zero-line, to redraw zero afterwards. 807 push (@rrd_negatives, "CDEF:re_zero=g$negfield,UN,0,0,IF"); 808 } 809 810 push (@rrd_negatives, "CDEF:ng$negfield=g$negfield,-1,*"); 811 812 if ($single_value) { 813 # Only one field. Do min/max range. 814 push (@rrd, "CDEF:neg_min_max_diff=i$negfield,a$negfield,-"); 815 push (@rrd, "CDEF:ni$negfield=i$negfield,-1,*"); 816 push (@rrd, "AREA:ni$negfield#ffffff"); 817 push (@rrd, "STACK:neg_min_max_diff$range_colour"); 818 } 819 820 push (@rrd_negatives, $fielddraw . ":ng$negfield" . $colour ); 821 822 # Draw HRULEs 823 my $linedef = munin_get ($config, "line", undef, $domain, $name, $service, $node->{client}->{$service}->{$field.".negative"}); 824 if ($linedef) { 825 my ($number, $ldcolour, $label) = split (/:/, $linedef, 3); 826 push (@rrd_negatives, "HRULE:".$number. 827 ($ldcolour ? "#$ldcolour" : $colour)); 828 829 } elsif ($node->{client}->{$service}->{"$negfield.warn"}) { 830 push (@rrd_negatives, "HRULE:".$node->{client}->{$service}->{$node->{client}->{$service}->{$field.".negative"}.".warn"}. 831 (defined $single_value and $single_value) ? "#ff0000" : $colour); 832 } 833 834 push (@rrd, "GPRINT:c$negfield:LAST:$rrdformat" . $rrdscale . "/\\g"); 835 push (@rrd, "GPRINT:c$rrdname:LAST:$rrdformat" . $rrdscale . ""); 836 push (@rrd, "GPRINT:i$negfield:MIN:$rrdformat" . $rrdscale . "/\\g"); 837 push (@rrd, "GPRINT:i$rrdname:MIN:$rrdformat" . $rrdscale . ""); 838 push (@rrd, "GPRINT:g$negfield:AVERAGE:$avgformat" . $rrdscale . "/\\g"); 839 push (@rrd, "GPRINT:g$rrdname:AVERAGE:$avgformat" . $rrdscale . ""); 840 push (@rrd, "GPRINT:a$negfield:MAX:$rrdformat" . $rrdscale . "/\\g"); 841 push (@rrd, "GPRINT:a$rrdname:MAX:$rrdformat" . $rrdscale . "\\j"); 842 push (@{$total_pos{'min'}}, "i$rrdname"); 843 push (@{$total_pos{'avg'}}, "g$rrdname"); 844 push (@{$total_pos{'max'}}, "a$rrdname"); 845 push (@{$total_neg{'min'}}, "i$negfield"); 846 push (@{$total_neg{'avg'}}, "g$negfield"); 847 push (@{$total_neg{'max'}}, "a$negfield"); 848 } else { 849 push (@rrd, "COMMENT: Cur$RRDkludge:") unless $global_headers; 850 push (@rrd, "GPRINT:c$rrdname:LAST:$rrdformat" . $rrdscale . ""); 851 push (@rrd, "COMMENT: Min$RRDkludge:") unless $global_headers; 852 push (@rrd, "GPRINT:i$rrdname:MIN:$rrdformat" . $rrdscale . ""); 853 push (@rrd, "COMMENT: Avg$RRDkludge:") unless $global_headers; 854 push (@rrd, "GPRINT:g$rrdname:AVERAGE:$avgformat" . $rrdscale . ""); 855 push (@rrd, "COMMENT: Max$RRDkludge:") unless $global_headers; 856 push (@rrd, "GPRINT:a$rrdname:MAX:$rrdformat" . $rrdscale . "\\j"); 857 push (@{$total_pos{'min'}}, "i$rrdname"); 858 push (@{$total_pos{'avg'}}, "g$rrdname"); 859 push (@{$total_pos{'max'}}, "a$rrdname"); 860 } 713 push (@rrd, "CDEF:neg_min_max_diff=i$negfieldname,a$negfieldname,-"); 714 push (@rrd, "CDEF:ni$negfieldname=i$negfieldname,-1,*"); 715 push (@rrd, "AREA:ni$negfieldname#ffffff"); 716 push (@rrd, "STACK:neg_min_max_diff$range_colour"); 717 } 718 719 push (@rrd_negatives, $fielddraw . ":ng$negfieldname" . $colour ); 861 720 862 721 # Draw HRULEs 863 my $linedef = munin_get ($ config, "line", undef, $domain, $name, $service, $field);722 my $linedef = munin_get ($negfield, "line"); 864 723 if ($linedef) { 865 724 my ($number, $ldcolour, $label) = split (/:/, $linedef, 3); 866 $label =~ s/:/\\:/g if defined $label; 867 push (@rrd, "HRULE:".$number. 868 ($ldcolour ? "#$ldcolour" : 869 ((defined $single_value and $single_value) ? 870 "#ff0000" : $colour)). 871 ((defined $label and length ($label)) ? ":$label" : ""), 872 "COMMENT: \\j" 873 ); 874 } elsif ($node->{client}->{$service}->{"$field.warn"}) { 875 push (@rrd,"HRULE:". 876 $node->{client}->{$service}->{"$field.warn"}. 877 ($single_value ? "#ff0000" : $colour)); 878 } 879 } 880 881 if (@rrd_negatives) { 882 push (@rrd, @rrd_negatives); 883 push (@rrd, "LINE2:re_zero#000000"); # Redraw zero. 884 if (exists $node->{client}->{$service}->{graph_total} and 885 exists $total_pos{'min'} and exists $total_neg{'min'} and 886 @{$total_pos{'min'}} and @{$total_neg{'min'}}) { 887 888 push (@rrd, "CDEF:ipostotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_pos{'min'}}).(",+" x (@{$total_pos{'min'}}-1))); 889 push (@rrd, "CDEF:gpostotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_pos{'avg'}}).(",+" x (@{$total_pos{'avg'}}-1))); 890 push (@rrd, "CDEF:apostotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_pos{'max'}}).(",+" x (@{$total_pos{'max'}}-1))); 891 push (@rrd, "CDEF:inegtotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_neg{'min'}}).(",+" x (@{$total_neg{'min'}}-1))); 892 push (@rrd, "CDEF:gnegtotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_neg{'avg'}}).(",+" x (@{$total_neg{'avg'}}-1))); 893 push (@rrd, "CDEF:anegtotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_neg{'max'}}).(",+" x (@{$total_neg{'max'}}-1))); 894 push (@rrd, "CDEF:dpostotal=ipostotal,UN,ipostotal,UNKN,IF"); 895 push (@rrd, "LINE1:dpostotal#000000:" . $node->{client}->{$service}->{graph_total} . (" " x ($max_field_len - length ($node->{client}->{$service}->{graph_total}) + 1))); 896 push (@rrd, "GPRINT:gnegtotal:LAST:$rrdformat" . $rrdscale . "/\\g"); 897 push (@rrd, "GPRINT:gpostotal:LAST:$rrdformat" . $rrdscale . ""); 898 push (@rrd, "GPRINT:inegtotal:MIN:$rrdformat" . $rrdscale . "/\\g"); 899 push (@rrd, "GPRINT:ipostotal:MIN:$rrdformat" . $rrdscale . ""); 900 push (@rrd, "GPRINT:gnegtotal:AVERAGE:$avgformat" . $rrdscale . "/\\g"); 901 push (@rrd, "GPRINT:gpostotal:AVERAGE:$avgformat" . $rrdscale . ""); 902 push (@rrd, "GPRINT:anegtotal:MAX:$rrdformat" . $rrdscale . "/\\g"); 903 push (@rrd, "GPRINT:apostotal:MAX:$rrdformat" . $rrdscale . "\\j"); 904 } 905 } 906 elsif (exists $node->{client}->{$service}->{graph_total} and exists $total_pos{'min'} and @{$total_pos{'min'}}) { 725 push (@rrd_negatives, "HRULE:".$number. 726 ($ldcolour ? "#$ldcolour" : $colour)); 727 728 } elsif (my $tmpwarn = munin_get ($negfield, "warn")) { 729 push (@rrd_negatives, "HRULE:".$negfieldname. 730 (defined $single_value and $single_value) ? "#ff0000" : $colour); 731 } 732 733 push (@rrd, "GPRINT:c$negfieldname:LAST:$rrdformat" . $rrdscale . "/\\g"); 734 push (@rrd, "GPRINT:c$rrdname:LAST:$rrdformat" . $rrdscale . ""); 735 push (@rrd, "GPRINT:i$negfieldname:MIN:$rrdformat" . $rrdscale . "/\\g"); 736 push (@rrd, "GPRINT:i$rrdname:MIN:$rrdformat" . $rrdscale . ""); 737 push (@rrd, "GPRINT:g$negfieldname:AVERAGE:$avgformat" . $rrdscale . "/\\g"); 738 push (@rrd, "GPRINT:g$rrdname:AVERAGE:$avgformat" . $rrdscale . ""); 739 push (@rrd, "GPRINT:a$negfieldname:MAX:$rrdformat" . $rrdscale . "/\\g"); 740 push (@rrd, "GPRINT:a$rrdname:MAX:$rrdformat" . $rrdscale . "\\j"); 741 push (@{$total_pos{'min'}}, "i$rrdname"); 742 push (@{$total_pos{'avg'}}, "g$rrdname"); 743 push (@{$total_pos{'max'}}, "a$rrdname"); 744 push (@{$total_neg{'min'}}, "i$negfieldname"); 745 push (@{$total_neg{'avg'}}, "g$negfieldname"); 746 push (@{$total_neg{'max'}}, "a$negfieldname"); 747 } else { 748 push (@rrd, "COMMENT: Cur$RRDkludge:") unless $global_headers; 749 push (@rrd, "GPRINT:c$rrdname:LAST:$rrdformat" . $rrdscale . ""); 750 push (@rrd, "COMMENT: Min$RRDkludge:") unless $global_headers; 751 push (@rrd, "GPRINT:i$rrdname:MIN:$rrdformat" . $rrdscale . ""); 752 push (@rrd, "COMMENT: Avg$RRDkludge:") unless $global_headers; 753 push (@rrd, "GPRINT:g$rrdname:AVERAGE:$avgformat" . $rrdscale . ""); 754 push (@rrd, "COMMENT: Max$RRDkludge:") unless $global_headers; 755 push (@rrd, "GPRINT:a$rrdname:MAX:$rrdformat" . $rrdscale . "\\j"); 756 push (@{$total_pos{'min'}}, "i$rrdname"); 757 push (@{$total_pos{'avg'}}, "g$rrdname"); 758 push (@{$total_pos{'max'}}, "a$rrdname"); 759 } 760 761 # Draw HRULEs 762 my $linedef = munin_get ($field, "line"); 763 if ($linedef) { 764 my ($number, $ldcolour, $label) = split (/:/, $linedef, 3); 765 $label =~ s/:/\\:/g if defined $label; 766 push (@rrd, "HRULE:".$number. 767 ($ldcolour ? "#$ldcolour" : 768 ((defined $single_value and $single_value) ? 769 "#ff0000" : $colour)). 770 ((defined $label and length ($label)) ? ":$label" : ""), 771 "COMMENT: \\j" 772 ); 773 } elsif (my $tmpwarn = munin_get ($field, "warn")) { 774 push (@rrd,"HRULE:".$tmpwarn.($single_value ? "#ff0000" : $colour)); 775 } 776 } 777 778 my $graphtotal = munin_get ($service, "graph_total"); 779 if (@rrd_negatives) { 780 push (@rrd, @rrd_negatives); 781 push (@rrd, "LINE2:re_zero#000000"); # Redraw zero. 782 if (defined $graphtotal and exists $total_pos{'min'} and 783 exists $total_neg{'min'} and 784 @{$total_pos{'min'}} and @{$total_neg{'min'}}) { 785 907 786 push (@rrd, "CDEF:ipostotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_pos{'min'}}).(",+" x (@{$total_pos{'min'}}-1))); 908 787 push (@rrd, "CDEF:gpostotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_pos{'avg'}}).(",+" x (@{$total_pos{'avg'}}-1))); 909 788 push (@rrd, "CDEF:apostotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_pos{'max'}}).(",+" x (@{$total_pos{'max'}}-1))); 910 789 push (@rrd, "CDEF:inegtotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_neg{'min'}}).(",+" x (@{$total_neg{'min'}}-1))); 790 push (@rrd, "CDEF:gnegtotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_neg{'avg'}}).(",+" x (@{$total_neg{'avg'}}-1))); 791 push (@rrd, "CDEF:anegtotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_neg{'max'}}).(",+" x (@{$total_neg{'max'}}-1))); 911 792 push (@rrd, "CDEF:dpostotal=ipostotal,UN,ipostotal,UNKN,IF"); 912 push (@rrd, "LINE1:dpostotal#000000: " . $node->{client}->{$service}->{graph_total} . (" " x ($max_field_len - length ($node->{client}->{$service}->{graph_total}) + 1)));913 push (@rrd, " COMMENT: Cur$RRDkludge:") unless $global_headers;793 push (@rrd, "LINE1:dpostotal#000000:$graphtotal" . (" " x ($max_field_len - length ($graphtotal) + 1))); 794 push (@rrd, "GPRINT:gnegtotal:LAST:$rrdformat" . $rrdscale . "/\\g"); 914 795 push (@rrd, "GPRINT:gpostotal:LAST:$rrdformat" . $rrdscale . ""); 915 push (@rrd, " COMMENT: Min$RRDkludge:") unless $global_headers;796 push (@rrd, "GPRINT:inegtotal:MIN:$rrdformat" . $rrdscale . "/\\g"); 916 797 push (@rrd, "GPRINT:ipostotal:MIN:$rrdformat" . $rrdscale . ""); 917 push (@rrd, " COMMENT: Avg$RRDkludge:") unless $global_headers;918 push (@rrd, "GPRINT:gpostotal:AVERAGE:$avgformat" . $rrdscale . "");919 push (@rrd, " COMMENT: Max$RRDkludge:") unless $global_headers;798 push (@rrd, "GPRINT:gnegtotal:AVERAGE:$avgformat" . $rrdscale . "/\\g"); 799 push (@rrd, "GPRINT:gpostotal:AVERAGE:$avgformat" . $rrdscale . ""); 800 push (@rrd, "GPRINT:anegtotal:MAX:$rrdformat" . $rrdscale . "/\\g"); 920 801 push (@rrd, "GPRINT:apostotal:MAX:$rrdformat" . $rrdscale . "\\j"); 921 802 } 922 923 for my $time (keys %times) { 924 next unless ($draw{$time}); 925 my @complete = (); 926 if ($RRDkludge) { 927 push (@complete, 928 '--font' ,'LEGEND:7:@@LIBDIR@@/VeraMono.ttf', 929 '--font' ,'UNIT:7:@@LIBDIR@@/VeraMono.ttf', 930 '--font' ,'AXIS:7:@@LIBDIR@@/VeraMono.ttf'); 931 } 803 } elsif (defined $graphtotal and exists $total_pos{'min'} and @{$total_pos{'min'}}) { 804 push (@rrd, "CDEF:ipostotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_pos{'min'}}).(",+" x (@{$total_pos{'min'}}-1))); 805 push (@rrd, "CDEF:gpostotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_pos{'avg'}}).(",+" x (@{$total_pos{'avg'}}-1))); 806 push (@rrd, "CDEF:apostotal=".join (",", map { "$_,UN,0,$_,IF" } @{$total_pos{'max'}}).(",+" x (@{$total_pos{'max'}}-1))); 807 808 push (@rrd, "CDEF:dpostotal=ipostotal,UN,ipostotal,UNKN,IF"); 809 push (@rrd, "LINE1:dpostotal#000000:$graphtotal" . (" " x ($max_field_len - length ($graphtotal) + 1))); 810 push (@rrd, "COMMENT: Cur$RRDkludge:") unless $global_headers; 811 push (@rrd, "GPRINT:gpostotal:LAST:$rrdformat" . $rrdscale . ""); 812 push (@rrd, "COMMENT: Min$RRDkludge:") unless $global_headers; 813 push (@rrd, "GPRINT:ipostotal:MIN:$rrdformat" . $rrdscale . ""); 814 push (@rrd, "COMMENT: Avg$RRDkludge:") unless $global_headers; 815 push (@rrd, "GPRINT:gpostotal:AVERAGE:$avgformat" . $rrdscale .""); 816 push (@rrd, "COMMENT: Max$RRDkludge:") unless $global_headers; 817 push (@rrd, "GPRINT:apostotal:MAX:$rrdformat" . $rrdscale . "\\j"); 818 } 932 819 push(@complete,'-W', $watermark) if $RRDs::VERSION >= 1.2; 933 820 934 logger ("Processing $name -> $time") if $DEBUG; 935 936 # Do the header (title, vtitle, size, etc...) 937 push @complete, @{&get_header ($node, $config, $domain, $name, $service, $time)}; 938 if ($LINEkluge) { 939 @rrd = map { s/LINE3:/LINE2.2:/; $_; } @rrd; 940 @rrd = map { s/LINE2:/LINE1.6:/; $_; } @rrd; 941 # LINE1 is thin enough. 942 } 943 push @complete, @rrd; 944 945 push (@complete, "COMMENT:Last update$RRDkludge: " . 946 RRDescape(scalar localtime($lastupdate)) . "\\r"); 821 for my $time (keys %times) { 822 next unless ($draw{$time}); 823 my $picfilename = munin_get_picture_filename ($service, $time); 824 (my $picdirname = $picfilename) =~ s/\/[^\/]+$//; 825 826 my @complete = (); 827 if ($RRDkludge) { 828 push (@complete, 829 '--font' ,'LEGEND:7:@@LIBDIR@@/VeraMono.ttf', 830 '--font' ,'UNIT:7:@@LIBDIR@@/VeraMono.ttf', 831 '--font' ,'AXIS:7:@@LIBDIR@@/VeraMono.ttf'); 832 } 833 834 # Do the header (title, vtitle, size, etc...) 835 push @complete, @{get_header ($service, $time)}; 836 if ($LINEkluge) { 837 @rrd = map { s/LINE3:/LINE2.2:/; $_; } @rrd; 838 @rrd = map { s/LINE2:/LINE1.6:/; $_; } @rrd; 839 # LINE1 is thin enough. 840 } 841 push @complete, @rrd; 842 843 push (@complete, "COMMENT:Last update$RRDkludge: " . 844 RRDescape(scalar localtime($lastupdate)) . "\\r"); 845 846 if (time - 300 < $lastupdate) { 847 push @complete, "--end", 848 (int($lastupdate/$resolutions{$time}))*$resolutions{$time}; 849 } 850 print "\n\nrrdtool \"graph\" \"", 851 join ("\"\n\t\"",@complete), "\"\n" if $DEBUG; 852 853 # Make sure directory exists 854 munin_mkdir_p ($picdirname, 0777); 855 856 RRDs::graph (@complete); 857 if (my $ERROR = RRDs::error) { 858 logger ("Unable to graph ". munin_get_picture_filename ($service, $time) . ": $ERROR"); 859 } elsif ($list_images) { 860 # Command-line option to list images created 861 print munin_get_picture_filename ($service, $time),"\n"; 862 } 863 } 864 865 if (munin_get_bool ($service, "graph_sums", 0)) { 866 foreach my $time (keys %sumtimes) { 867 my $picfilename = munin_get_picture_filename ($service, $time, 1); 868 (my $picdirname = $picfilename) =~ s/\/[^\/]+$//; 869 next unless ($draw{"sum".$time}); 870 my @rrd_sum; 871 push @rrd_sum, @{get_header ($service, $time, 1)}; 947 872 948 873 if (time - 300 < $lastupdate) { 949 push @complete, "--end", 950 (int($lastupdate/$resolutions{$time}))*$resolutions{$time}; 951 } 952 print "\n\nrrdtool \"graph\" \"", 953 join ("\"\n\t\"",@complete), "\"\n" if $DEBUG; 954 RRDs::graph (@complete); 874 push @rrd_sum, "--end",(int($lastupdate/$resolutions{$time}))*$resolutions{$time}; 875 } 876 push @rrd_sum, @rrd; 877 push (@rrd_sum, "COMMENT:Last update$RRDkludge: " . RRDescape(scalar localtime($lastupdate)) . "\\r"); 878 879 my $labelled = 0; 880 my @defined = (); 881 for (my $index = 0; $index <= $#rrd_sum; $index++) { 882 if ($rrd_sum[$index] =~ /^(--vertical-label|-v)$/) { 883 (my $label = munin_get ($service, "graph_vlabel")) =~ s/\$\{graph_period\}/$sumtimes{$time}[0]/g; 884 splice (@rrd_sum, $index, 2, ("--vertical-label", $label)); 885 $index++; 886 $labelled++; 887 } elsif ($rrd_sum[$index] =~ /^(LINE[123]|STACK|AREA|GPRINT):([^#:]+)([#:].+)$/) { 888 my ($pre, $fname, $post) = ($1, $2, $3); 889 next if $fname eq "re_zero"; 890 if ($post =~ /^:AVERAGE/) { 891 splice (@rrd_sum, $index, 1, $pre . ":x$fname" . $post); 892 $index++; 893 next; 894 } 895 next if grep /^x$fname$/, @defined; 896 push @defined, "x$fname"; 897 my @replace; 898 899 if (munin_get ($service->{$fname}, "type", "GAUGE") ne "GAUGE") { 900 if ($time eq "week") { 901 # Every plot is half an hour. Add two plots and multiply, to get per hour 902 if (graph_by_minute ($service)) { 903 # Already multiplied by 60 904 push @replace, "CDEF:x$fname=PREV($fname),UN,0,PREV($fname),IF,$fname,+,5,*,6,*"; 905 } else { 906 push @replace, "CDEF:x$fname=PREV($fname),UN,0,PREV($fname),IF,$fname,+,300,*,6,*"; 907 } 908 } else { 909 # Every plot is one day exactly. Just multiply. 910 if (graph_by_minute ($service)) { 911 # Already multiplied by 60 912 push @replace, "CDEF:x$fname=$fname,5,*,288,*"; 913 } else { 914 push @replace, "CDEF:x$fname=$fname,300,*,288,*"; 915 } 916 } 917 } 918 push @replace, $pre . ":x$fname" . $post; 919 splice (@rrd_sum, $index, 1, @replace); 920 $index++; 921 } elsif ($rrd_sum[$index] =~ /^(--lower-limit|--upper-limit|-l|-u)$/) { 922 $index++; 923 $rrd_sum[$index] = $rrd_sum[$index] * 300 * $sumtimes{$time}->[1]; 924 } 925 } 926 927 unless ($labelled) { 928 my $label = munin_get ($service, "graph_vlabel_sum_$time", $sumtimes{$time}->[0]); 929 unshift @rrd_sum, "--vertical-label", $label; 930 } 931 932 print "\n\nrrdtool \"graph\" \"", join ("\"\n\t\"",@rrd_sum), "\"\n" if $DEBUG; 933 934 # Make sure directory exists 935 munin_mkdir_p ($picdirname, 0777); 936 937 RRDs::graph (@rrd_sum); 938 955 939 if (my $ERROR = RRDs::error) { 956 logger ("Unable to graph $filename: $ERROR");940 logger ("Unable to graph ". munin_get_picture_filename ($service, $time) . ": $ERROR"); 957 941 } elsif ($list_images) { 958 942 # Command-line option to list images created 959 print &munin_get_picture_filename ($config, $domain, $name, 960 $service, $time),"\n"; 961 } 962 } 963 964 if (&munin_get_bool_val ($node->{client}->{$service}->{"graph_sums"}, 0)) { 965 foreach my $time (keys %sumtimes) { 966 next unless ($draw{"sum".$time}); 967 my @rrd_sum; 968 push @rrd_sum, @{&get_header ($node, $config, $domain, $name, $service, $time, 1)}; 969 970 if (time - 300 < $lastupdate) { 971 push @rrd_sum, "--end",(int($lastupdate/$resolutions{$time}))*$resolutions{$time}; 972 } 973 push @rrd_sum, @rrd; 974 push (@rrd_sum, "COMMENT:Last update$RRDkludge: " . RRDescape(scalar localtime($lastupdate)) . "\\r"); 975 976 my $labelled = 0; 977 my @defined = (); 978 for (my $index = 0; $index <= $#rrd_sum; $index++) { 979 if ($rrd_sum[$index] =~ /^(--vertical-label|-v)$/) { 980 (my $label = $node->{client}->{$service}->{graph_vlabel}) =~ s/\$\{graph_period\}/$sumtimes{$time}[0]/g; 981 splice (@rrd_sum, $index, 2, ("--vertical-label", $label)); 982 $index++; 983 $labelled++; 984 } elsif ($rrd_sum[$index] =~ /^(LINE[123]|STACK|AREA|GPRINT):([^#:]+)([#:].+)$/) { 985 my ($pre, $fname, $post) = ($1, $2, $3); 986 next if $fname eq "re_zero"; 987 if ($post =~ /^:AVERAGE/) { 988 splice (@rrd_sum, $index, 1, $pre . ":x$fname" . $post); 989 $index++; 990 next; 991 } 992 next if grep /^x$fname$/, @defined; 993 push @defined, "x$fname"; 994 my @replace; 995 996 if (!defined ($node->{client}->{$service}->{$fname.".type"}) or 997 $node->{client}->{$service}->{$fname.".type"} ne "GAUGE") { 998 if ($time eq "week") { 999 # Every plot is half an hour. Add two plots and multiply, to get per hour 1000 if (graph_by_minute ($config, $domain, $name, $service)) { 1001 # Already multiplied by 60 1002 push @replace, "CDEF:x$fname=PREV($fname),UN,0,PREV($fname),IF,$fname,+,5,*,6,*"; 1003 } else { 1004 push @replace, "CDEF:x$fname=PREV($fname),UN,0,PREV($fname),IF,$fname,+,300,*,6,*"; 1005 } 1006 } else { 1007 # Every plot is one day exactly. Just multiply. 1008 if (graph_by_minute ($config, $domain, $name, $service)) { 1009 # Already multiplied by 60 1010 push @replace, "CDEF:x$fname=$fname,5,*,288,*"; 1011 } else { 1012 push @replace, "CDEF:x$fname=$fname,300,*,288,*"; 1013 } 1014 } 1015 } 1016 push @replace, $pre . ":x$fname" . $post; 1017 splice (@rrd_sum, $index, 1, @replace); 1018 $index++; 1019 } elsif ($rrd_sum[$index] =~ /^(--lower-limit|--upper-limit|-l|-u)$/) { 1020 $index++; 1021 $rrd_sum[$index] = $rrd_sum[$index] * 300 * $sumtimes{$time}->[1]; 1022 } 1023 } 1024 1025 unless ($labelled) { 1026 my $label = $node->{client}->{$service}->{"graph_vlabel_sum_$time"} || $sumtimes{$time}->[0]; 1027 unshift @rrd_sum, "--vertical-label", $label; 1028 } 1029 1030 print "\n\nrrdtool \"graph\" \"", join ("\"\n\t\"",@rrd_sum), "\"\n" if $DEBUG; 1031 RRDs::graph (@rrd_sum); 1032 1033 if (my $ERROR = RRDs::error) { 1034 logger ("Unable to graph $filename: $ERROR"); 1035 } elsif ($list_images) { 1036 # Command-line option to list images created 1037 print &munin_get_picture_filename ($config, $domain, $name, $service, $time, 1), "\n"; 1038 } 1039 } 1040 } 1041 1042 $service_time = sprintf ("%.2f",(Time::HiRes::time - $service_time)); 1043 logger ("Graphed service : $service ($service_time sec * 4)"); 1044 print STATS "GS|$domain|$name|$service|$service_time\n" unless $skip_stats; 1045 1046 foreach (@added) { 1047 delete $node->{client}->{$service}->{$_} 1048 if exists $node->{client}->{$service}->{$_}; 1049 } 1050 @added = (); 1051 } 943 print munin_get_picture_filename ($service, $time, 1),"\n"; 944 } 945 } 946 } 947 948 $service_time = sprintf ("%.2f",(Time::HiRes::time - $service_time)); 949 logger ("Graphed service : $sname ($service_time sec * 4)"); 950 print STATS "GS|$service_time\n" unless $skip_stats; 951 952 foreach (@added) { 953 delete $service->{$_} if exists $service->{$_}; 954 } 955 @added = (); 1052 956 } 1053 957 1054 958 sub graph_by_minute { 1055 my $config = shift;1056 my $domain = shift;1057 my $name = shift;1058 959 my $service = shift; 1059 960 1060 return (munin_get ($ config, "graph_period", "second", $domain, $name, $service) eq "minute");961 return (munin_get ($service, "graph_period", "second") eq "minute"); 1061 962 } 1062 963 1063 964 sub orig_to_cdef { 965 my $service = shift; 966 my $fieldname = shift; 967 968 return undef unless ref ($service) eq "HASH"; 969 970 if (defined $service->{$fieldname}->{"cdef_name"}) { 971 return orig_to_cdef ($service, $service->{$fieldname}->{"cdef_name"}); 972 } 973 return $fieldname; 974 } 975 976 sub skip_service { 1064 977 my $service = shift; 1065 my $field = shift; 1066 1067 if (defined $service->{$field.".cdef_name"}) 1068 { 1069 return &orig_to_cdef ($service, $service->{$field.".cdef_name"}); 1070 } 1071 return $field; 1072 } 1073 1074 sub set_cdef_name { 1075 my $service = shift; 1076 my $field = shift; 1077 my $new = shift; 1078 1079 $service->{$field.".cdef_name"} = $new; 1080 print "DEBUG: set_cdef_name from $field to $new.\n" if $DEBUG; 1081 } 1082 1083 sub skip_service { 1084 my $node = shift; 1085 my $service = shift; 1086 1087 # Check to make sure that service exists 1088 return 1 unless (ref $node->{client}->{$service}); 978 my $sname = munin_get_node_name ($service); 979 980 # Skip if we've limited services with cli options 981 return 1 if (@limit_services and !grep /^$sname$/, @limit_services); 982 983 # Always graph if --force is present 984 return 0 if $force_graphing; 1089 985 1090 986 # See if we should skip it because of conf-options 1091 return 1 if ($node->{client}->{$service}->{'graph'} and 1092 ($node->{client}->{$service}->{'graph'} eq "no" || 1093 ($node->{client}->{$service}->{'graph'} eq "on-demand") && !$force_graphing)); 1094 1095 # See if we should skip it because of command-line arguments 1096 return 1 if (@limit_services and not grep (/^$service$/, @limit_services)); 987 return 1 if (munin_get ($service, "graph", "yes") eq "on-demand" or 988 !munin_get_bool ($service, "graph", 1)); 1097 989 1098 990 # Don't skip … … 1109 1001 my ($max, $min, $avg) = ("CDEF:a$new_field=$cdef", "CDEF:i$new_field=$cdef", "CDEF:g$new_field=$cdef"); 1110 1002 1111 foreach my $field (keys %$service) 1112 { 1113 next unless ($field =~ /^(.+)\.label$/); 1114 my $fieldname = $1; 1003 foreach my $field (@{munin_find_field ($service, "label")}) { 1004 my $fieldname = munin_get_node_name ($field); 1115 1005 my $rrdname = &orig_to_cdef ($service, $fieldname); 1116 if ($cdef =~ /\b$fieldname\b/) 1117 { 1006 if ($cdef =~ /\b$fieldname\b/) { 1118 1007 $max =~ s/([,=])$fieldname([,=]|$)/$1a$rrdname$2/g; 1119 1008 $min =~ s/([,=])$fieldname([,=]|$)/$1i$rrdname$2/g; … … 1122 1011 } 1123 1012 1124 &set_cdef_name ($service, $$cfield_ref, $new_field);1013 munin_set_var_loc ($service, [$$cfield_ref, "cdef_name"], $new_field); 1125 1014 $$cfield_ref = $new_field; 1126 1015 … … 1131 1020 my $dirname = shift; 1132 1021 1133 if (!$log->opened) 1134 { 1135 unless (open ($log, ">>$dirname/munin-graph.log")) 1136 { 1137 print STDERR "Warning: Could not open log file \"$dirname/munin-graph.log\" for writing: $!"; 1138 } 1022 if (!$log->opened) { 1023 unless (open ($log, ">>$dirname/munin-graph.log")) { 1024 print STDERR "Warning: Could not open log file \"$dirname/munin-graph.log\" for writing: $!"; 1025 } 1026 } else { 1027 close (STDERR); 1028 *STDERR = \$log; 1139 1029 } 1140 1030 } 1141 1031 1142 1032 sub logger { 1143 my ($comment) = @_; 1144 my $now = strftime "%b %d %H:%M:%S", localtime; 1145 1146 print "$now - $comment\n" if $stdout; 1147 if ($log->opened) 1148 { 1149 print $log "$now - $comment\n"; 1150 } 1151 else 1152 { 1153 if (defined $config->{logdir}) 1154 { 1155 if (open ($log, ">>$config->{logdir}/munin-graph.log")) 1156 { 1157 print $log "$now - $comment\n"; 1158 $log->flush; 1159 close (STDERR); 1160 open (STDERR, ">&", $log); 1161 } 1162 else 1163 { 1164 print STDERR "Warning: Could not open log file \"$config->{logdir}/munin-graph.log\" for writing: $!"; 1165 print STDERR "$now - $comment\n"; 1166 } 1167 } 1168 else 1169 { 1170 print STDERR "$now - $comment\n"; 1171 } 1033 my ($comment) = @_; 1034 my $now = strftime "%b %d %H:%M:%S", localtime; 1035 1036 print "$now - $comment\n" if $stdout; 1037 if ($log->opened) { 1038 print $log "$now - $comment\n"; 1039 } else { 1040 if (defined $config->{logdir}) { 1041 if (open ($log, ">>$config->{logdir}/munin-graph.log")) { 1042 print $log "$now - $comment\n"; 1043 $log->flush; 1044 close (STDERR); 1045 open (STDERR, ">&", $log); 1046 } else { 1047 print STDERR "Warning: Could not open log file \"$config->{logdir}/munin-graph.log\" for writing: $!"; 1048 print STDERR "$now - $comment\n"; 1049 } 1050 } else { 1051 print STDERR "$now - $comment\n"; 1052 } 1172 1053 } 1173 1054 } people/jo/multilevel-groups-3/server/munin-html.in
r1442 r1502 32 32 my @times = ( "day", "week", "month", "year" ); 33 33 34 my @limit_hosts; 34 35 my $DEBUG=0; 35 my $VERSION ="@@VERSION@@";36 my $VERSION = "@@VERSION@@"; 36 37 my $conffile = "@@CONFDIR@@/munin.conf"; 37 38 my $force_root = 0; … … 144 145 if ($config->{domain_order}) { 145 146 @domainorder = split /\s+/, $config->{domain_order}; 146 }147 foreach my $d (sort (keys %{$config->{domain}})) {148 unless (grep (/^$d$/, @domainorder)) {149 push @domainorder, $d;150 }151 147 } 152 148 … … 165 161 } 166 162 167 #make domain list 168 my @domainlist = map { { DOMAIN => $_ } } @domainorder; 163 # For timestamping graphs 169 164 my $timestamp = strftime("%Y-%m-%d T %T", localtime); 170 for my $domain (@domainorder) { 171 logger("processing domain: $domain"); 172 my %domain; 173 $domain{domain}=$domain; 174 my @nodes; 175 my %comparisons; 176 my @nodeorder = (); 177 if ($config->{domain}->{$domain}->{node_order}) { 178 @nodeorder = split /\s+/, $config->{domain}->{$domain}->{node_order}; 179 } 180 foreach my $n (sort (keys %{$config->{domain}->{$domain}->{node}})) { 181 unless (grep (/^$n$/, @nodeorder)) { 182 push @nodeorder, $n; 183 } 184 } 185 for my $node (@nodeorder) { 186 logger("processing node: $node"); 187 my %node; 188 $node{node}=$node; 189 $node{url}="$domain/$node.html"; 190 my @services; 191 my @categories; 192 my %categories; 193 my %tmp_cats; 194 my @serviceorder; 195 if ($config->{domain}->{$domain}->{node}->{$node}->{service_order}) { 196 @serviceorder = split /\s+/, 197 $config->{domain}->{$domain}->{node}->{$node}->{service_order}; 198 } else { 199 @serviceorder = sort 200 keys %{$config->{domain}->{$domain}->{node}->{$node}->{client}}; 201 } 202 203 for my $service (@serviceorder) { 204 logger("processing service: $service"); 205 next unless 206 defined($config->{domain}->{$domain}->{node}->{$node}->{client}->{$service} ) 207 && $config->{domain}->{$domain}->{node}->{$node}->{client}->{$service} ne ""; 208 209 next unless 210 munin_get_bool ($config, "graph", 1, $domain, $node, $service); 211 212 my @service; 213 my %service; 214 my $fieldnum = 0; 215 my @graph_info; 216 my @field_info; 217 $service{service}=$service; 218 $service{label}= 219 $config->{domain}->{$domain}->{node}->{$node}->{client}-> 220 {$service}->{graph_title}; 221 222 my $method = &munin_get ($config, "graph_strategy", "cron"); 223 if ($method eq "cgi") { 224 $service{imgday}=$config->{'cgiurl_graph'}. 225 "/$domain/$node/$service-day.png"; 226 $service{imgweek}=$config->{'cgiurl_graph'}. 227 "/$domain/$node/$service-week.png"; 228 $service{imgmonth}=$config->{'cgiurl_graph'}. 229 "/$domain/$node/$service-month.png"; 230 $service{imgyear}=$config->{'cgiurl_graph'}. 231 "/$domain/$node/$service-year.png"; 232 233 if (&munin_get_bool_val($config->{domain}->{$domain}-> 234 {node}->{$node}-> 235 {client}->{$service}->{"graph_sums"}, 0)) { 236 $service{imgweeksum} = 237 $config->{'cgiurl_graph'}."/$domain/$node/$service-week-sum.png"; 238 $service{imgyearsum} = 239 $config->{'cgiurl_graph'}."/$domain/$node/$service-year-sum.png"; 240 } 241 242 # There is a disturbance in the force here, the sizes are off. 243 # if (my ($w, $h) = 244 # &calculate_png_size ($config, $domain, $node, $service)) { 245 # for my $scale (@times) { 246 # $service{"img".$scale."width"} = $w; 247 # $service{"img".$scale."height"} = $h; 248 # } 249 # if (&munin_get_bool_val($config->{domain}->{$domain}-> 250 # {node}->{$node}-> 251 # {client}->{$service}->{"graph_sums"}, 0)) { 252 # for my $scale (["week", "year"]) { 253 # $service{"img".$scale."sumwidth"} = $w; 254 # $service{"img".$scale."sumheight"} = $h; 255 # } 256 # } 257 # } 258 } else { 259 # graph strategy cron 260 $service{imgday}="$node-$service-day.png"; 261 $service{imgweek}="$node-$service-week.png"; 262 $service{imgmonth}="$node-$service-month.png"; 263 $service{imgyear}="$node-$service-year.png"; 264 265 for my $scale (@times) { 266 if (my ($w, $h) = 267 &get_png_size(&munin_get_picture_filename($config, $domain, 268 $node, $service, 269 $scale))) { 270 $service{"img".$scale."width"} = $w; 271 $service{"img".$scale."height"} = $h; 272 } 273 } 274 275 if (&munin_get_bool_val ($config->{domain}->{$domain}-> 276 {node}->{$node}->{client}-> 277 {$service}->{"graph_sums"}, 0)) { 278 $service{imgweeksum} = "$node-$service-week-sum.png"; 279 $service{imgyearsum} = "$node-$service-year-sum.png"; 280 for my $scale (["week", "year"]) { 281 if (my ($w, $h) = 282 &get_png_size (&munin_get_picture_filename($config,$domain, 283 $node, $service, 284 $scale, 1))) { 285 $service{"img".$scale."sumwidth"} = $w; 286 $service{"img".$scale."sumheight"} = $h; 287 } 288 } 289 } 290 } 291 $service{url}="$node-$service.html"; 292 $service{domain}="$domain"; 293 $service{node}=$node; 294 $service{category}= lc( $config->{domain}->{$domain}-> 295 {node}->{$node}->{client}-> 296 {$service}->{graph_category} || "other" ); 297 298 # Do "help" section 299 if (defined($config->{domain}->{$domain}-> 300 {node}->{$node}-> 301 {client}->{$service}->{graph_info})) { 302 my %graph_info; 303 304 $graph_info{info} = $config->{domain}->{$domain}-> 305 {node}->{$node}->{client}->{$service}->{graph_info}; 306 307 push @{$service{graphinfo}}, \%graph_info; 308 } 309 310 $service{fieldlist} .= "<tr><th align='left' valign='top'>Field</th><th align='left' valign='top'>Type</th><th align='left' valign='top'>Warn</th><th align='left' valign='top'>Crit</th><th></tr>"; 311 # foreach my $field (keys %{$config->{domain}->{$domain}->{node}->{$node}->{client}->{$service}}) 312 foreach my $f (@{&munin_get_field_order ($config->{domain}->{$domain}->{node}->{$node}, $config, $domain, $node, $service)}) { 313 $f =~ s/=(.*)$//; 314 my $path = $1; 315 next unless &munin_draw_field ($config->{domain}->{$domain}-> 316 {node}->{$node}, $service, $f); 317 318 print "DEBUG: single_value: Checking field \"$f\" ($path).\n" 319 if $DEBUG; 320 321 if (defined $path) { 322 # HUH? Get the filename and then forget? Some side effect here? 323 munin_get_rrd_filename ($config->{domain}->{$domain}-> 324 {node}->{$node}, $config, $domain, 325 $node, $service, $f, $path); 326 } 327 328 my %field_info; 329 $fieldnum++; 330 331 $field_info{'hr'} = 1 unless ($fieldnum % 3); 332 $field_info{'field'} = $f; 333 $field_info{'label'} = $config->{domain}->{$domain}-> 334 {node}->{$node}->{client}->{$service}->{$f.".label"} || $f; 335 336 $field_info{'type'} = lc( $config->{domain}->{$domain}-> 337 {node}->{$node}->{client}->{$service}-> 338 {$f.".type"} || "GAUGE" ); 339 340 $field_info{'warn'} = $config->{domain}->{$domain}-> 341 {node}->{$node}->{client}->{$service}->{$f.".warning"} || "None"; 342 $field_info{'crit'} = $config->{domain}->{$domain}-> 343 {node}->{$node}->{client}->{$service}->{$f.".critical"} || "None"; 344 $field_info{'info'} = $config->{domain}->{$domain}-> 345 {node}->{$node}->{client}->{$service}->{$f.".info"} || ""; 346 347 my $state = &munin_field_status ($config, $limits, $domain, 348 $node, $service, $f, 1); 349 350 if (defined $state) { 351 $field_info{'state_warning'} = 1 if $state eq "warning"; 352 $field_info{'state_critical'} = 1 if $state eq "critical"; 353 $field_info{'state_unknown'} = 1 if $state eq "unknown"; 354 } 355 push @{$service{fieldinfo}}, \%field_info; 356 } 357 358 { 359 my $state = &munin_service_status ($config, $limits, $domain, 360 $node, $service, 1); 361 if (defined $state) { 362 $service{'state_warning'} = 1 if $state eq "warning"; 363 $service{'state_critical'} = 1 if $state eq "critical"; 364 $service{'state_unknown'} = 1 if $state eq "unknown"; 365 } 366 } 367 368 push @services, \%service; 369 push @service, \%service; 370 push @{$tmp_cats{$service{'category'}}}, \%service; 371 $servicetemplate->param(SERVICES => \@service, 372 SERVICE => $service, 373 NODE => $node, 374 DOMAIN => $domain, 375 DOMAINS => \@domainlist, 376 TIMESTAMP => $timestamp); 377 open (FILE, ">$config->{htmldir}/$domain/$node-$service.html") or 378 die "Cannot open $config->{htmldir}/$domain/$node-$service.html: $!"; 379 print FILE $servicetemplate->output; 380 close FILE; 381 } 382 foreach my $key (keys %tmp_cats) { 383 next if $key eq "other"; 384 my %tmp; 385 my $state = &munin_category_status ($config, $limits, $domain, 386 $node, $key, 1); 387 print "DEBUG: Pushing category \"$node\" -> \"$key\"...\n" if $DEBUG; 388 if (defined $state) { 389 $tmp{'state_warning'} = 1 if $state eq "warning"; 390 $tmp{'state_critical'} = 1 if $state eq "critical"; 391 $tmp{'state_unknown'} = 1 if $state eq "unknown"; 392 } 393 $tmp{name} = ucfirst $key; 394 $tmp{services} = \@{$tmp_cats{$key}}; 395 $tmp{node} = $node; 396 $tmp{domain} = $domain; 397 $categories{ucfirst $key} = \%tmp; 398 $comparisons{$key}{$node} = \%tmp; 399 } 400 if (defined $tmp_cats{'other'}) { 401 my $key = 'other'; 402 my %tmp; 403 my $state = &munin_category_status ($config, $limits, $domain, 404 $node, $key, 1); 405 print "DEBUG: Pushing category \"$node\" -> \"$key\"...\n" if $DEBUG; 406 if (defined $state) { 407 $tmp{'state_warning'} = 1 if $state eq "warning"; 408 $tmp{'state_critical'} = 1 if $state eq "critical"; 409 $tmp{'state_unknown'} = 1 if $state eq "unknown"; 410 } 411 $tmp{name} = ucfirst $key; 412 $tmp{services} = \@{$tmp_cats{$key}}; 413 $tmp{node} = $node; 414 $tmp{domain} = $domain; 415 $categories{ucfirst $key} = \%tmp; 416 $comparisons{'other'}{$node} = \%tmp; 417 } 418 # Handle category_order 419 @categories = (); 420 if ($config->{domain}->{$domain}->{node}->{$node}->{category_order}) { 421 foreach my $cat (split /\s+/, 422 $config->{domain}->{$domain}-> 423 {node}->{$node}->{category_order}) { 424 push @categories, $categories{ucfirst $cat}; 425 } 426 foreach my $cat (sort keys %categories) { 427 push @categories, $categories{$cat} 428 unless (grep { $_->{name} eq $cat } @categories); 429 } 430 } else { 431 @categories = map { $categories{$_} } sort keys %categories; 432 } 433 $nodetemplate->param(SERVICES => \@services, 434 NODE => $node, 435 DOMAIN => $domain, 436 DOMAINS => \@domainlist, 437 TIMESTAMP => $timestamp, 438 CATEGORIES => \@categories); 439 open (FILE, ">$config->{htmldir}/$domain/$node.html") or 440 die "Cannot open $config->{htmldir}/$domain/$node.html: $!"; 441 print FILE $nodetemplate->output; 442 close FILE; 443 $node{services} = \@services; 444 $node{categories} = \@categories; 445 $node{domain} = $domain; 446 push @nodes,\%node; 447 448 } 449 $domaintemplate->param(NODES => \@nodes, 450 DOMAIN => $domain, 451 DOMAINS => \@domainlist, 452 COMPARE => (&munin_get_bool ($config, "compare", 1, 453 $domain) 454 and @nodeorder > 1), 455 TIMESTAMP => $timestamp); 456 open (FILE, ">$config->{htmldir}/$domain/index.html") or 457 die "Cannot open $config->{htmldir}/$domain/index.html: $!"; 458 print FILE $domaintemplate->output; 459 close FILE; 460 461 $domain{nodes} = \@nodes; 462 $domain{domain} = $domain; 463 $domain{compare} = (&munin_get_bool ($config, "compare", 1, $domain) 464 and @nodeorder > 1); 465 466 my @cats = (); 467 foreach my $key (sort keys %comparisons) { 468 my %cat; 469 my %servlist; 470 my $nodewidth = 0; 471 472 foreach my $node (sort keys %{$comparisons{$key}}) { 473 foreach my $serv (@{$comparisons{$key}{$node}->{services}}) { 474 $servlist{$serv->{service}}{$node} = $serv; 475 $nodewidth = $serv->{imgdaywidth} 476 if (defined $serv->{imgdaywidth} 477 and $serv->{imgdaywidth} > $nodewidth); 478 } 479 } 480 foreach my $sname (sort keys %servlist) { 481 my %s; 482 foreach my $node (@nodeorder) { 483 if (defined $servlist{$sname}{$node}) { 484 $servlist{$sname}{$node}->{width} = $nodewidth; 485 push (@{$s{nodes}}, $servlist{$sname}{$node}); 486 } else { 487 my %ts; 488 $ts{label} = "Not present"; 489 $ts{service} = "$sname"; 490 $ts{title} = "Not present"; 491 $ts{node} = $node; 492 $ts{width} = $nodewidth; 493 push (@{$s{nodes}}, \%ts); 494 } 495 } 496 push @{$cat{services}}, \%s; 497 } 498 $cat{name} = ucfirst $key; 499 $cat{numnodes} = @nodeorder; 500 $cat{numnodes} = @nodeorder; 501 push @cats, \%cat; 502 } 503 504 if (&munin_get_bool ($config, "compare", 1, $domain) and @nodeorder > 1) { 505 foreach my $t (@times) { 506 $comparisontemplates{$t}->param(DOMAIN => $domain, 507 DOMAINS => \@domainlist, 508 TIMESTAMP => $timestamp, 509 CATEGORIES => \@cats); 510 open (FILE, ">$config->{htmldir}/$domain/comparison-$t.html") or 511 die "Cannot open $config->{htmldir}/$domain/comparison-$t.html: $!"; 512 print FILE $comparisontemplates{$t}->output; 513 close FILE; 514 } 515 } 516 push @domains,\%domain; 517 } 518 519 $template->param(DOMAINS => \@domains, 520 TIMESTAMP => $timestamp); 521 open (FILE, ">$config->{htmldir}/index.html") or die "Cannot open $config->{htmldir}/index.html: $!"; 165 166 # Preparing the group tree... 167 my $groups = get_group_tree ($config); 168 if (defined $groups->{"name"} and $groups->{"name"} eq "root") { 169 $groups = $groups->{"groups"}; # root->groups 170 } 171 172 # Draw main index 173 $template->param(GROUPS => $groups, 174 TIMESTAMP => $timestamp); 175 my $filename = munin_get_html_filename ($config); 176 open (FILE, ">$filename") or 177 die "Cannot open $filename for writing: $!"; 522 178 print FILE $template->output; 523 179 close FILE; 180 181 generate_group_templates ($groups); 524 182 525 183 munin_removelock("$config->{rundir}/munin-html.lock"); … … 640 298 } 641 299 300 sub get_peer_nodes { 301 my $hash = shift || return undef; 302 my $category = shift; 303 my $ret = []; 304 my $link = "index.html"; 305 my $parent = munin_get_parent ($hash) || return undef; 306 my $me = munin_get_node_name ($hash); 307 my $pchildren = munin_get_children ($parent); 308 309 foreach my $peer (sort {munin_get_node_name($a) <=> munin_get_node_name($b)} @$pchildren) { 310 next unless defined $peer and ref ($peer) eq "HASH"; 311 next if defined $category and lc (munin_get ($peer, "graph_category", "other")) ne $category; 312 logger ("FNORD! ". munin_get_node_name ($peer)." -- ".munin_get_node_name ($parent)); 313 my $peername = munin_get_node_name ($peer); 314 next if $peername eq "contact" and munin_get_node_name ($parent) eq "root"; 315 if ($peername eq $me) { 316 unshift @$ret, { "name" => $peername, "link" => undef }; 317 } else { 318 if (defined $peer->{'graph_title'}) { 319 unshift @$ret, { "name" => $peername, "link" => "$peername.html" }; 320 } else { 321 unshift @$ret, { "name" => $peername, "link" => "../$peername/index.html" }; 322 } 323 } 324 } 325 return $ret; 326 } 327 328 sub get_group_tree { 329 my $hash = shift; 330 my $base = shift || ""; 331 my $graphs = []; 332 my $groups = []; 333 my $cattrav = {}; 334 my $cats = []; 335 my $path = []; 336 my $rpath = undef; 337 my $ret = {}; 338 my $csspath; 339 340 foreach my $child (@{munin_get_children ($hash)}) { 341 next unless defined $child and ref ($child) eq "HASH" and keys %$child; 342 next if munin_get_node_name ($child) eq "contact"; 343 if (defined $child->{"graph_title"}) { 344 my $childname = munin_get_node_name ($child); 345 my $childnode = generate_service_templates ($child); 346 push @$graphs, { "name" => $childname }; 347 $childnode->{'name'} = $child->{"graph_title"}; 348 $childnode->{'url'} = $base . $childname.".html"; 349 for (my $shrinkpath = $childnode->{'url'}, my $counter = 0; $shrinkpath; $shrinkpath =~ s/^[^\/]+\/?//, $counter++) { 350 $childnode->{'url'.$counter} = $shrinkpath; 351 } 352 push @{$cattrav->{ lc munin_get ($child, "graph_category", "other") }}, $childnode; 353 } elsif (ref ($child) eq "HASH") { 354 push @$groups, get_group_tree ($child, $base . munin_get_node_name ($child) . "/"); 355 } 356 } 357 358 # We need the categories in another format. 359 foreach my $cat (sort keys %$cattrav) { 360 my $obj = {}; 361 $obj->{'name'} = $cat; 362 $obj->{'url'} = $base."index.html#".$cat; 363 $obj->{'services'} = $cattrav->{$cat}; 364 $obj->{'state_'.lc munin_category_status ($hash, $limits, $cat, 1)} = 1; 365 for (my $shrinkpath = $obj->{'url'}, my $counter = 0; $shrinkpath =~ /\//; $shrinkpath =~ s/^[^\/]+\/*//, $counter++) { 366 $obj->{'url'.$counter} = $shrinkpath; 367 } 368 push @$cats, $obj; 369 } 370 371 # ...and we need a couple of paths available. 372 @$path = reverse map { { "name" => $_, "path" => (defined $rpath?($rpath.="../")."index.html":($rpath="")) } } reverse ( "Overview", split ('\/', $base) ); 373 ($csspath = $path->[0]->{'path'}) =~ s/index.html$/style.css/; 374 375 $ret = { 376 "name" => munin_get_node_name ($hash), 377 "url" => $base . "index.html", 378 "path" => $path, 379 "depth" => scalar(split("/",$base."index.html"))-1, 380 "filename" => munin_get_html_filename ($hash), 381 "csspath" => $csspath, 382 "groups" => $groups, 383 "graphs" => $graphs, 384 "categories" => $cats, 385 "ngroups" => scalar (@$groups), 386 "ngraphs" => scalar (@$graphs), 387 "ncategories" => scalar (@$cats), 388 "peers" => get_peer_nodes ($hash), 389 }; 390 if ($ret->{'url'} ne "/index.html") { 391 for (my $shrinkpath = $ret->{'url'}, my $counter = 0; $shrinkpath =~ /\//; $shrinkpath =~ s/^[^\/]+\/*//, $counter++) { 392 $ret->{'url'.$counter} = $shrinkpath; 393 } 394 } 395 396 return $ret; 397 } 398 399 sub generate_group_templates { 400 my $arr = shift || return undef; 401 return undef unless ref ($arr) eq "ARRAY"; 402 403 foreach my $key (@$arr) { 404 if (defined $key and ref ($key) eq "HASH") { 405 if (defined $key->{'ngroups'} and $key->{'ngroups'}) { 406 generate_group_templates ($key->{'groups'}); 407 408 my $grouptemplate = HTML::Template->new( 409 filename => munin_get ($config, "tmpldir", "")."/munin-domainview.tmpl", 410 die_on_bad_params => 0, 411 loop_context_vars => 1, 412 filter => sub { my $ref=shift; $$ref =~ s/URLX/URL$key->{'depth'}/g; } 413 ); 414 415 $grouptemplate->param ( 416 GROUPS => $key->{'groups'}, 417 PATH => $key->{'path'}, 418 CSSPATH => $key->{'csspath'}, 419 PEERS => $key->{'peers'}, 420 PARENT => $key->{'path'}->[-2]->{'name'} 421 ); 422 my $filename = $key->{'filename'}; 423 open (FILE, ">$filename") or 424 die "Cannot open $filename for writing: $!"; 425 print FILE $grouptemplate->output; 426 close FILE; 427 } 428 429 if (defined $key->{'ngraphs'} and $key->{'ngraphs'}) { 430 my $graphtemplate = HTML::Template->new( 431 filename => munin_get ($config, "tmpldir", "")."/munin-nodeview.tmpl", 432 die_on_bad_params => 0, 433 loop_context_vars => 1, 434 filter => sub { my $ref=shift; $$ref =~ s/URLX/URL$key->{'depth'}/g; } 435 ); 436 437 $graphtemplate->param ( 438 GROUPS => $key->{'groups'}, 439 PATH => $key->{'path'}, 440 CSSPATH => $key->{'csspath'}, 441 PEERS => $key->{'peers'}, 442 PARENT => $key->{'path'}->[-2]->{'name'}, 443 NAME => $key->{'name'}, 444 CATEGORIES => $key->{'categories'}, 445 NCATEGORIES => $key->{'ncategories'}, 446 ); 447 my $filename = $key->{'filename'}; 448 open (FILE, ">$filename") or 449 die "Cannot open $filename for writing: $!"; 450 print FILE $graphtemplate->output; 451 close FILE; 452 } 453 } 454 } 455 } 456 457 sub generate_service_templates { 458 459 my $service = shift || return undef; 460 return undef unless munin_get_bool ($service, "graph", 1); 461 462 my %srv; 463 my $fieldnum = 0; 464 my @graph_info; 465 my @field_info; 466 my @loc = munin_get_node_loc ($service); 467 my $pathnodes = get_path_nodes ($service); 468 my $peers = get_peer_nodes ($service, lc munin_get ($service, "graph_category", "other")); 469 (my $csspath = $pathnodes->[0]->{'link'}) =~ s/index.html$/style.css/; 470 471 $srv{'node'} = munin_get_node_name ($service); 472 logger("processing service: $srv{node}"); 473 $srv{'service'} = $service; 474 $srv{'label'} = munin_get ($service, "graph_title"); 475 $srv{'category'} = lc( munin_get ($service, "graph_category", "other") ); 476 477 my $method = munin_get ($service, "graph_strategy", "cron"); 478 479 $srv{'url'} = "$srv{node}.html"; 480 481 my $path = join ('/', @loc); 482 483 if ($method eq "cgi") { 484 $srv{'imgday'} =$config->{'cgiurl_graph'}."/$path-day.png"; 485 $srv{'imgweek'} =$config->{'cgiurl_graph'}."/$path-week.png"; 486 $srv{'imgmonth'}=$config->{'cgiurl_graph'}."/$path-month.png"; 487 $srv{'imgyear'} =$config->{'cgiurl_graph'}."/$path-year.png"; 488 489 if (munin_get_bool ($service, "graph_sums", 0)) { 490 $srv{'imgweeksum'} = $config->{'cgiurl_graph'}."/$path-week-sum.png"; 491 $srv{'imgyearsum'} = $config->{'cgiurl_graph'}."/$path-year-sum.png"; 492 } 493 } else { 494 # graph strategy cron 495 496 $srv{'imgday'} ="$srv{node}-day.png"; 497 $srv{'imgweek'} ="$srv{node}-week.png"; 498 $srv{'imgmonth'}="$srv{node}-month.png"; 499 $srv{'imgyear'} ="$srv{node}-year.png"; 500 501 for my $scale (@times) { 502 if (my ($w, $h) = get_png_size(munin_get_picture_filename($service, $scale))) { 503 $srv{"img".$scale."width"} = $w; 504 $srv{"img".$scale."height"} = $h; 505 } 506 } 507 508 if (munin_get_bool ($service, "graph_sums", 0)) { 509 $srv{imgweeksum} = "$srv{node}-week-sum.png"; 510 $srv{imgyearsum} = "$srv{node}-year-sum.png"; 511 for my $scale (["week", "year"]) { 512 if (my ($w, $h) = get_png_size (munin_get_picture_filename($service, $scale, 1))) { 513 $srv{"img".$scale."sumwidth"} = $w; 514 $srv{"img".$scale."sumheight"} = $h; 515 } 516 } 517 } 518 } 519 520 # Do "help" section 521 if (my $info = munin_get ($service, "graph_info")) { 522 my %graph_info; 523 $graph_info{info} = $info; 524 push @{$srv{graphinfo}}, \%graph_info; 525 } 526 527 $srv{fieldlist} .= "<tr><th align='left' valign='top'>Field</th><th align='left' valign='top'>Type</th><th align='left' valign='top'>Warn</th><th align='left' valign='top'>Crit</th><th></tr>"; 528 foreach my $f (@{munin_get_field_order ($service)}) { 529 $f =~ s/=(.*)$//; 530 my $path = $1; 531 next if (!defined $service->{$f}); 532 my $fieldobj = $service->{$f}; 533 next if (ref ($fieldobj) != "HASH" or !defined $fieldobj->{'label'}); 534 next if (!munin_draw_field ($fieldobj)); 535 536 logger ("DEBUG: single_value: Checking field \"$f\" ($path).") 537 if $DEBUG; 538 539 if (defined $path) { 540 # This call is to make sure field settings are copied 541 # for aliases, .stack, et al. Todo: put that part of 542 # munin_get_rrd_filename into its own functino. 543 munin_get_rrd_filename ($f, $path); 544 } 545 546 my %field_info; 547 $fieldnum++; 548 549 $field_info{'hr'} = 1 unless ($fieldnum % 3); 550 $field_info{'field'} = $f; 551 $field_info{'label'} = munin_get ($fieldobj, "label", $f); 552 $field_info{'type'} = lc( munin_get ($fieldobj, "type", "GAUGE") ); 553 $field_info{'warn'} = munin_get ($fieldobj, "warning"); 554 $field_info{'crit'} = munin_get ($fieldobj, "critical"); 555 $field_info{'info'} = munin_get ($fieldobj, "info"); 556 557 my $state = munin_field_status ($fieldobj, $limits, 1); 558 logger ("state of ".join('::',@{munin_get_node_loc ($fieldobj)}).": $state"); 559 560 if (defined $state) { 561 $field_info{'state_warning'} = 1 if $state eq "warning"; 562 $field_info{'state_critical'} = 1 if $state eq "critical"; 563 $field_info{'state_unknown'} = 1 if $state eq "unknown"; 564 } 565 push @{$srv{'fieldinfo'}}, \%field_info; 566 } 567 568 my $state = munin_service_status ($service, $limits, 1); 569 if (defined $state) { 570 $srv{'state_warning'} = 1 if $state eq "warning"; 571 $srv{'state_critical'} = 1 if $state eq "critical"; 572 $srv{'state_unknown'} = 1 if $state eq "unknown"; 573 } 574 575 $servicetemplate->param(SERVICES => [\%srv], 576 PATH => $pathnodes, 577 PEERS => $peers, 578 CSS => $csspath, 579 CATEGORY => ucfirst $srv{'category'}, 580 TIMESTAMP => $timestamp); 581 my $filename = munin_get_html_filename ($service); 582 open (FILE, ">$filename") or 583 die "Cannot open $filename for writing: $!"; 584 print FILE $servicetemplate->output; 585 close FILE; 586 587 return \%srv; 588 } 589 590 sub get_path_nodes { 591 my $hash = shift || return undef; 592 my $ret = []; 593 my $link = "index.html"; 594 595 unshift @$ret, { "name" => munin_get_node_name ($hash), "link" => undef }; 596 while ($hash = munin_get_parent ($hash)) { 597 unshift @$ret, { "name" => munin_get_node_name ($hash), "link" => $link }; 598 $link = "../" . $link; 599 } 600 $ret->[0]->{'name'} = undef; 601 return $ret; 602 } 603 642 604 $update_time = sprintf("%.2f",(Time::HiRes::time - $update_time)); 643 605 people/jo/multilevel-groups-3/server/munin-limits.in
r1442 r1502 100 100 101 101 if (!defined $config->{'contact'}->{'nagios'}->{'command'} and 102 defined $config->{'nsca'}) 103 { 102 defined $config->{'nsca'}) { 104 103 $config->{'contact'}->{'old-nagios'}->{'command'} = "$config->{nsca} $config->{nsca_server} -c $config->{nsca_config} -to 60"; 105 104 $config->{'contact'}->{'old-nagios'}->{'always_send'} = "critical warning"; 106 105 } 107 if (!defined $config->{'contact'}->{'nagios'}->{'always_send'}) 108 { 106 if (!defined $config->{'contact'}->{'nagios'}->{'always_send'}) { 109 107 $config->{'contact'}->{'nagios'}->{'always_send'} = "critical warning"; 110 108 } 111 109 112 for my $domain ( keys %{$config->{domain}}) { 113 logger ("processing domain: $domain"); 114 process_domain($domain); 115 } 110 my $defaultcontacts = munin_get ($config, "contacts", ""); 111 if (!length $defaultcontacts) { 112 my @tmpcontacts = (); 113 foreach my $cont (@{munin_get_children ($config->{"contact"})}) { 114 if (munin_get ($cont, "command")) { 115 push @tmpcontacts, munin_get_node_name ($cont); 116 } 117 } 118 $defaultcontacts = join (' ', @tmpcontacts); 119 } 120 munin_set_var_loc ($config, ["contacts"], $defaultcontacts); 121 logger ("Debug: Set default \"contacts\" to \"$defaultcontacts\"") if $DEBUG; 122 123 # Make array of what needs to be checked 124 my %work_hash_tmp; 125 my $work_array = []; 126 foreach my $workfield (@{munin_find_field ($config, qr/^(critical|warning|crit|warn)/)}) { 127 my $parent = munin_get_parent ($workfield); 128 if (!defined $work_hash_tmp{$parent}) { 129 $work_hash_tmp{$parent} = 1; 130 push @$work_array, $parent; 131 } 132 } 133 134 # Process array containing services we need to check 135 foreach my $workservice (@$work_array) { 136 process_service ($workservice); 137 } 138 116 139 &munin_writeconfig ("$config->{dbdir}/limits", \%notes); 117 140 … … 122 145 logger("munin-limits finished ($update_time sec)"); 123 146 124 sub process_domain { 125 my ($domain) = @_; 126 for my $node ( keys %{$config->{domain}->{$domain}->{node}}) { 127 if (@limit_hosts and !grep (/^$node$/, @limit_hosts)) 128 { 129 logger ("skipping node: $node"); 130 next; 131 } 132 logger ("processing node: $node"); 133 process_node($domain,$node ,$config->{domain}->{$domain}->{node}->{$node} ); 134 } 135 } 136 137 sub process_node { 138 my ($domain,$name,$node) = @_; 139 for my $client (keys %{$node->{client}}) { 140 logger ("processing service: $client") if $DEBUG; 141 process_service($domain,$name,$client,$node->{client}->{$client}); 142 } 143 } 147 exit 0; 144 148 145 149 sub process_service { 146 my $critical= undef; 147 my ($domain, $name,$clientname,$client) = @_; 148 return unless $client; 149 for my $service (keys %$client) { 150 if ($service =~ /(^.*)\.label/) { 151 my $key = $1; 152 next unless ((exists $client->{"$key.warning"}) || ($client->{"$key.critical"})); 153 logger ("processing field: $key") if $DEBUG; 154 if (@limit_services and !grep (/^$service$/, @limit_services)) 155 { 156 next; 150 my $hash = shift || return undef; 151 my $parentobj = munin_get_parent ($hash); 152 my $gparentobj = munin_get_parent (munin_get_parent ($hash)); 153 my $service = munin_get_node_name ($hash); 154 my $parent = munin_get_node_name ($parentobj); 155 my $gparent = munin_get_node_name ($gparentobj); 156 my $children = munin_get_children ($hash); 157 158 # Some fields that are nice to have in the plugin output 159 $hash->{'fields'} = join (' ', map { munin_get_node_name ($_) } @$children); 160 $hash->{'plugin'} = $service; 161 $hash->{'graph_title'} = $hash->{'notify_alias'} if defined $hash->{'notify_alias'}; 162 $hash->{'host'} = munin_get ($parentobj, "notify_alias", $parent); 163 $hash->{'group'} = munin_get ($gparentobj, "notify_alias", $gparent); 164 $hash->{'worst'} = "ok"; 165 $hash->{'worstid'} = 0 unless defined $hash->{'worstid'}; 166 167 foreach my $field (@$children) { 168 next if (!defined $field or ref ($field) ne "HASH"); 169 my $fname = munin_get_node_name ($field); 170 my $warn = munin_get ($field, "warning", undef); 171 my $crit = munin_get ($field, "critical", undef); 172 my $fpath = munin_get_node_loc ($field); 173 my $onfield = munin_get_node ($oldnotes, $fpath); 174 175 # Skip fields without warning/critical definitions 176 next if (!defined $warn and !defined $crit); 177 178 logger ("processing field: ".join ('::', @$fpath)) if $DEBUG; 179 next if (@limit_services and !grep (/^$service$/, @limit_services)); 180 181 ($warn, $crit) = get_limits ($field); 182 183 my $filename = munin_get_rrd_filename ($field); 184 my $value = munin_fetch("$filename"); 185 # De-taint. 186 if (!defined $value) { 187 $value = "unknown"; 188 } else { 189 $value = sprintf "%.2f",$value; 190 } 191 192 # Some fields that are nice to have in the plugin output 193 $field->{'value'} = $value; 194 $field->{'crange'} = (defined $crit->[0]?$crit->[0]:"").":".(defined $crit->[1]?$crit->[1]:""); 195 $field->{'wrange'} = (defined $warn->[0]?$warn->[0]:"").":".(defined $warn->[1]?$warn->[1]:""); 196 197 logger ("value: ". join ('::', @{munin_get_node_loc ($hash)}) .": $value (crit: $crit->[0]:$crit->[1]) (warn: $warn->[0]:$warn->[1])") if $DEBUG; 198 if ($value eq "unknown") { 199 $crit->[0] ||= ""; 200 $crit->[1] ||= ""; 201 $hash->{'worst'} = "UNKNOWN" if $hash->{"worst"} eq "OK"; 202 $hash->{'worstid'} = 3 if $hash->{"worstid"} == 0; 203 munin_set_var_loc (\%notes, [@$fpath, "state"], "unknown"); 204 munin_set_var_loc (\%notes, [@$fpath, "unknown"], (defined $field->{"extinfo"} ? "unknown: " . $field->{"extinfo"} : "Value is unknown.")); 205 206 if (!defined $onfield or !defined $onfield->{"state"} or $onfield->{"state"} ne "unknown") { 207 $hash->{'state_changed'} = 1; 157 208 } 158 my $critical; 159 my $warning; 160 ($warning, $critical) = get_limits ($client, $domain, $name, $clientname, $key); 161 162 my $filename = "$config->{dbdir}/$domain/$name-$clientname-$key-". 163 lc substr (($client->{"$key.type"}||"GAUGE"),0,1) . ".rrd"; 164 my $value = &munin_fetch("$filename"); 165 # De-taint. 166 if (!defined $value) { 167 $value = "unknown"; 168 } else { 169 $value = sprintf "%.2f",$value; 209 } elsif ((defined ($crit->[0]) and $value < $crit->[0]) or 210 (defined ($crit->[1]) and $value > $crit->[1])) { 211 $crit->[0] ||= ""; 212 $crit->[1] ||= ""; 213 $hash->{'worst'} = "CRITICAL"; 214 $hash->{'worstid'} = 2; 215 munin_set_var_loc (\%notes, [@$fpath, "state"], "critical"); 216 munin_set_var_loc (\%notes, [@$fpath, "critical"], 217 (defined $field->{"extinfo"}? 218 "$value (not in $crit->[0]:$crit->[1]): ". 219 $field->{"extinfo"}: 220 "Value is $value. Critical range ($crit->[0]:$crit->[1]) exceeded")); 221 222 if (!defined $onfield or !defined $onfield->{"state"} or $onfield->{"state"} ne "critical") { 223 $hash->{'state_changed'} = 1; 170 224 } 171 172 # Some fields that are nice to have in the plugin output 173 $client->{$key.".value"} = $value; 174 $client->{'fields'} = join (' ', map { $_ =~ s/\.label$//; $_} grep (/\.label/, keys %$client)); 175 $client->{'plugin'} = $clientname; 176 $client->{'graph_title'} = $client->{'notify_alias'} if defined $client->{'notify_alias'}; 177 $client->{'host'} = $config->{'domain'}->{$domain}->{'node'}->{$name}->{'notify_alias'} || $name; 178 $client->{'group'} = $config->{'domain'}->{$domain}->{'notify_alias'} || $domain; 179 $client->{'worst'} = "OK"; 180 $client->{'worstid'} = 0 unless defined $client->{'worstid'}; 181 $client->{$key.".crange"} = (defined $critical->[0]?$critical->[0]:"").":".(defined $critical->[1]?$critical->[1]:""); 182 $client->{$key.".wrange"} = (defined $warning->[0]?$warning->[0]:"").":".(defined $warning->[1]?$warning->[1]:""); 183 184 logger ("value: $domain -> $name -> $clientname -> $key : $value") if $DEBUG; 185 if ($value eq "unknown") { 186 $critical->[0] ||= ""; 187 $critical->[1] ||= ""; 188 $client->{'worst'} = "UNKNOWN" if $client->{"worst"} eq "OK"; 189 $client->{'worstid'} = 3 if $client->{"worstid"} == 0; 190 $notes{$domain}{$name}{$clientname}{"$key.state"} = "unknown"; 191 $notes{$domain}{$name}{$clientname}{"$key.unknown"} = 192 (defined $client->{"$key.extinfo"} ? "unknown: " . $client->{"$key.extinfo"} : "Value is unknown."); 193 if (!defined ($oldnotes->{'domain'}->{$domain}->{'node'}->{$name}->{'client'}->{$clientname}->{"$key.state"}) or 194 $oldnotes->{'domain'}->{$domain}->{'node'}->{$name}->{'client'}->{$clientname}->{"$key.state"} ne "unknown") 195 { 196 $client->{'state_changed'} = 1; 197 } 225 } elsif ((defined ($warn->[0]) and $value < $warn->[0]) or 226 (defined ($warn->[1]) and $value > $warn->[1])) { 227 $warn->[0] ||= ""; 228 $warn->[1] ||= ""; 229 $hash->{'worst'} = "WARNING" if $hash->{"worst"} ne "CRITICAL"; 230 $hash->{'worstid'} = 1 if $hash->{"worstid"} != 2; 231 munin_set_var_loc (\%notes, [@$fpath, "state"], "warning"); 232 munin_set_var_loc (\%notes, [@$fpath, "warning"], 233 (defined $field->{"extinfo"}? 234 "$value (not in $warn->[0]:$warn->[1]): ". 235 $field->{"extinfo"}: 236 "Value is $value. Warning range ($warn->[0]:$warn->[1]) exceeded")); 237 238 if (!defined $onfield or !defined $onfield->{"state"} or $onfield->{"state"} ne "warning") { 239 $hash->{'state_changed'} = 1; 198 240 } 199 elsif ((defined ($critical->[0]) and $value < $critical->[0]) or 200 (defined ($critical->[1]) and $value > $critical->[1])) { 201 $critical->[0] ||= ""; 202 $critical->[1] ||= ""; 203 $client->{'worst'} = "CRITICAL"; 204 $client->{'worstid'} = 2; 205 $notes{$domain}{$name}{$clientname}{"$key.state"} = "critical"; 206 $notes{$domain}{$name}{$clientname}{"$key.critical"} = 207 (defined $client->{"$key.extinfo"}? 208 "$value (not in $critical->[0]:$critical->[1]): ". 209 $client->{"$key.extinfo"}: 210 "Value is $value. Critical range ($critical->[0]:$critical->[1]) exceeded"); 211 if (!defined ($oldnotes->{'domain'}->{$domain}->{'node'}->{$name}->{'client'}->{$clientname}->{"$key.state"}) or 212 $oldnotes->{'domain'}->{$domain}->{'node'}->{$name}->{'client'}->{$clientname}->{"$key.state"} ne "critical") 213 { 214 $client->{'state_changed'} = 1; 215 } 216 } 217 elsif ((defined ($warning->[0]) and $value < $warning->[0]) or 218 (defined ($warning->[1]) and $value > $warning->[1])) 219 { 220 $warning->[0] ||= ""; 221 $warning->[1] ||= ""; 222 $client->{'worst'} = "WARNING" if $client->{"worst"} ne "CRITICAL"; 223 $client->{'worstid'} = 1 if $client->{"worstid"} != 2; 224 $notes{$domain}{$name}{$clientname}{"$key.state"} = "warning"; 225 $notes{$domain}{$name}{$clientname}{"$key.warning"} = 226 (defined $client->{"$key.extinfo"}? 227 "$value (not in $warning->[0]:$warning->[1]): ". 228 $client->{"$key.extinfo"}: 229 "Value is $value. Warning range ($warning->[0]:$warning->[1]) exceeded"); 230 if (!defined ($oldnotes->{'domain'}->{$domain}->{'node'}->{$name}->{'client'}->{$clientname}->{"$key.state"}) or 231 $oldnotes->{'domain'}->{$domain}->{'node'}->{$name}->{'client'}->{$clientname}->{"$key.state"} ne "warning") 232 { 233 $client->{'state_changed'} = 1; 234 } 235 } 236 elsif (defined ($oldnotes->{'domain'}->{$domain}->{'node'}->{$name}->{'client'}->{$clientname}->{"$key.state"}) or 237 $force) 238 { 239 $notes{$domain}{$name}{$clientname}{"$key.ok"} = "OK"; 240 $client->{'state_changed'} = 1; 241 } 242 } 243 } 244 generate_service_message ($domain, $name, $clientname, $client); 245 } 246 247 sub get_limits 248 { 249 my $client = shift; 250 my $domain = shift; 251 my $name = shift; 252 my $clientname = shift; 253 my $key = shift; 241 } elsif (defined $onfield and defined $onfield->{"state"} or $force) { 242 munin_set_var_loc (\%notes, [@$fpath, "state"], "ok"); 243 munin_set_var_loc (\%notes, [@$fpath, "ok"], "OK"); 244 $hash->{'state_changed'} = 1; 245 } 246 } 247 generate_service_message ($hash); 248 } 249 250 sub get_limits { 251 my $hash = shift || return undef; 254 252 my @critical = (undef, undef); 255 253 my @warning = (undef, undef); 256 if (defined $client->{"$key.critical"} and 257 $client->{"$key.critical"} =~ /^\s*([-+\d.]*):([-+\d.]*)\s*$/) 258 { 254 my $crit = munin_get ($hash, "critical", undef); 255 my $warn = munin_get ($hash, "warning", undef); 256 my $name = munin_get_node_name ($hash); 257 258 if (defined $crit and $crit =~ /^\s*([-+\d.]*):([-+\d.]*)\s*$/) { 259 259 $critical[0] = $1 if length $1; 260 260 $critical[1] = $2 if length $2; 261 logger ("processing critical: $domain -> $name -> $clientname -> $key -> $critical[0] : $critical[1]") if $DEBUG; 262 } 263 elsif (defined $client->{"$key.critical"} and 264 $client->{"$key.critical"} =~ /^\s*([-+\d.]+)\s*$/) 265 { 261 logger ("processing critical: $name -> $critical[0] : $critical[1]") if $DEBUG; 262 } elsif (defined $crit and $crit =~ /^\s*([-+\d.]+)\s*$/) { 266 263 $critical[1] = $1 if defined $1; 267 logger ("processing critical: $domain -> $name -> $clientname -> $key -> $critical[0] : $critical[1]") if $DEBUG; 268 } 269 elsif (defined $client->{"$key.critical"}) 270 { 264 logger ("processing critical: $name -> $critical[0] : $critical[1]") if $DEBUG; 265 } elsif (defined $crit) { 271 266 @critical = (0, 0); 272 logger ("processing critical: $domain -> $name -> $clientname -> $key -> $critical[0] : $critical[1]") if $DEBUG; 273 } 274 if (defined $client->{"$key.warning"} and 275 $client->{"$key.warning"} =~ /^\s*([-+\d.]*):([-+\d.]*)\s*$/) 276 { 267 logger ("processing critical: $name -> $critical[0] : $critical[1]") if $DEBUG; 268 } 269 270 if (defined $warn and $warn =~ /^\s*([-+\d.]*):([-+\d.]*)\s*$/) { 277 271 $warning[0] = $1 if length $1; 278 272 $warning[1] = $2 if length $2; 279 logger ("processing warning: $domain -> $name -> $clientname -> $key -> $warning[0] : $warning[1]") if $DEBUG; 280 } 281 elsif (defined $client->{"$key.warning"} and 282 $client->{"$key.warning"} =~ /^\s*([-+\d.]+)\s*$/) 283 { 273 logger ("processing warning: $name -> $warning[0] : $warning[1]") if $DEBUG; 274 } elsif (defined $warn and $warn =~ /^\s*([-+\d.]+)\s*$/) { 284 275 $warning[1] = $1 if defined $1; 285 logger ("processing warning: $domain -> $name -> $clientname -> $key -> $warning[0] : $warning[1]") if $DEBUG; 286 } 287 elsif (defined $client->{"$key.warning"}) 288 { 276 logger ("processing warning: $name -> $warning[0] : $warning[1]") if $DEBUG; 277 } elsif (defined $warn) { 289 278 @warning = (0, 0); 290 logger ("processing warning: $ domain -> $name -> $clientname -> $key-> $warning[0] : $warning[1]") if $DEBUG;279 logger ("processing warning: $name -> $warning[0] : $warning[1]") if $DEBUG; 291 280 } 292 281 return (\@warning, \@critical); … … 294 283 295 284 sub generate_service_message { 296 my $critical= undef; 297 my ($domain, $name,$clientname,$client) = @_; 298 return unless $client; 299 my $worst = ""; 300 my %stats = ('critical' => [], 'warning' => [], 'unknown' => [], 'foks' => [], 'ok' => []); 301 302 logger ("generating service message: $domain -> $name -> $clientname") if $DEBUG; 303 foreach my $key (keys %{$notes{$domain}{$name}{$clientname}}) 304 { 305 if ($key =~ /^([^\.]+)\.critical$/) 306 { 307 $worst = "critical"; 308 push @{$stats{'critical'}}, $1; 309 } 310 elsif ($key =~ /^([^\.]+)\.warning$/) 311 { 312 $worst = "warning" if $worst ne "critical"; 313 push @{$stats{'warning'}}, $1; 314 } 315 elsif ($key =~ /^([^\.]+)\.unknown$/) 316 { 317 $worst = "unknown" if (!$worst or $worst eq "ok"); 318 push @{$stats{'unknown'}}, $1; 319 } 320 elsif ($key =~ /^([^\.]+)\.ok$/) 321 { 322 $worst = "ok" unless $worst; 323 push @{$stats{'ok'}}, $1; 324 push @{$stats{'foks'}}, $1; 325 } 326 else 327 { 328 push @{$stats{'ok'}}, $1; 329 } 330 } 331 $client->{'cfields'} = join " ", @{$stats{'critical'}}; 332 $client->{'wfields'} = join " ", @{$stats{'warning'}}; 333 $client->{'ufields'} = join " ", @{$stats{'unknown'}}; 334 $client->{'fofields'} = join " ", @{$stats{'foks'}}; 335 $client->{'ofields'} = join " ", @{$stats{'ok'}}; 336 $client->{'numcfields'} = scalar @{$stats{'critical'}}; 337 $client->{'numwfields'} = scalar @{$stats{'warning'}}; 338 $client->{'numufields'} = scalar @{$stats{'unknown'}}; 339 $client->{'numfofields'} = scalar @{$stats{'foks'}}; 340 $client->{'numofields'} = scalar @{$stats{'ok'}}; 341 342 if ($worst) 343 { 344 foreach my $c (split (/\s+/, munin_get ($config, "contacts", join (' ', keys %{$config->{'contact'}}), $domain, $name, $clientname))) 345 { 346 next if $c eq "none"; 347 next unless defined $config->{'contact'}->{$c}->{'command'}; 348 if (@limit_contacts and !grep (/^$c$/, @limit_contacts)) 349 { 350 next; 285 my $hash = shift || return undef; 286 my $critical = undef; 287 my $worst = $hash->{"worst"}; 288 my %stats = ('critical' => [], 'warning' => [], 'unknown' => [], 'foks' => [], 'ok' => []); 289 my $contacts = munin_get_children (munin_get_node ($config, ["contact"])); 290 291 logger ("generating service message: ". join ('::', @{munin_get_node_loc ($hash)})) if $DEBUG; 292 foreach my $field (@{munin_get_children ($hash)}) { 293 if (defined $field->{"state"}) { 294 push @{$stats{$field->{"state"}}}, munin_get_node_name ($field); 295 if ($field->{"state"} eq "ok") { 296 push @{$stats{"foks"}}, munin_get_node_name ($field); 351 297 } 352 my $obsess = 0; 353 if (defined ($config->{'contact'}->{$c}->{'always_send'})) 354 { 355 $obsess = grep {scalar(@{$stats{$_}})} (split (/\s+/, lc $config->{'contact'}->{$c}->{'always_send'})); 298 } 299 } 300 $hash->{'cfields'} = join " ", @{$stats{'critical'}}; 301 $hash->{'wfields'} = join " ", @{$stats{'warning'}}; 302 $hash->{'ufields'} = join " ", @{$stats{'unknown'}}; 303 $hash->{'fofields'} = join " ", @{$stats{'foks'}}; 304 $hash->{'ofields'} = join " ", @{$stats{'ok'}}; 305 $hash->{'numcfields'} = scalar @{$stats{'critical'}}; 306 $hash->{'numwfields'} = scalar @{$stats{'warning'}}; 307 $hash->{'numufields'} = scalar @{$stats{'unknown'}}; 308 $hash->{'numfofields'} = scalar @{$stats{'foks'}}; 309 $hash->{'numofields'} = scalar @{$stats{'ok'}}; 310 311 my $contactlist = munin_get ($hash, "contacts", ""); 312 logger ("Contact list for ". join ('::', @{munin_get_node_loc ($hash)}) . ": $contactlist"); 313 foreach my $c (split (/\s+/, $contactlist)) { 314 next if $c eq "none"; 315 my $contactobj = munin_get_node ($config, ["contact", $c]); 316 next unless defined $contactobj; 317 next unless defined munin_get ($contactobj, "command", undef); 318 if (@limit_contacts and !grep (/^$c$/, @limit_contacts)) { 319 next; 320 } 321 my $obsess = 0; 322 my $cas = munin_get ($contactobj, "always_send"); 323 if (defined $cas) { 324 $obsess = grep {scalar(@{$stats{$_}})} (split (/\s+/, lc $cas)); 325 } 326 logger ("checking if state has changed $c"); 327 if (!$hash->{'state_changed'} and !$obsess) { 328 next; # No need to send notification 329 } 330 logger ("state has changed, notifying $c"); 331 my $precmd = munin_get ($contactobj, "command"); 332 my $pretxt = munin_get ($contactobj, "text", munin_get (munin_get_node ($config, ["contact", "default"]), "text", $default_text{$c} || $default_text{"default"})); 333 my $txt = message_expand ($hash, $pretxt, ""); 334 my $cmd = message_expand ($hash, $precmd, ""); 335 $txt =~ s/\\n/\n/g; 336 $txt =~ s/\\t/\t/g; 337 338 # In some cases we want to reopen the command 339 my $maxmess = munin_get ($contactobj, "max_messages", 0); 340 my $curmess = munin_get ($contactobj, "num_messages", 0); 341 my $curcmd = munin_get ($contactobj, "pipe_command", undef); 342 my $pipe = munin_get ($contactobj, "pipe", undef); 343 if ($maxmess and $curmess >= $maxmess ) { 344 close ($pipe); 345 $pipe = undef; 346 munin_set_var_loc ($contactobj, ["pipe"], undef); 347 logger ("Debug: Closing \"$c\" -> command (max number of messages reached).") if $DEBUG; 348 } elsif ($curcmd and $curcmd ne $cmd) { 349 close ($pipe); 350 $pipe = undef; 351 munin_set_var_loc ($contactobj, ["pipe"], undef); 352 logger ("Debug: Closing \"$c\" -> command (command has changed).") if $DEBUG; 353 } 354 355 if (!defined $pipe) { 356 my @cmd = extract_multiple ( 357 message_expand ($hash, $cmd), 358 [ sub { extract_delimited ($_[0], q{"'})}, 359 qr/\S+/ 360 ], 361 undef, 1); 362 @cmd = map { s/['"]$//; s/^['"]//; $_ } @cmd; 363 $contactobj->{"num_messages"} = 0; 364 if ($cmd[0] eq "|") { 365 $cmd[0] = "|-"; 366 } elsif ($cmd[0] !~ /^[|>]/) { 367 unshift (@cmd, "|-"); 356 368 } 357 if (!$client->{'state_changed'} and !$obsess) 358 { 359 next; 360 } 361 my $precmd = $config->{'contact'}->{$c}->{'command'}; 362 my $pretxt = ($config->{'contact'}->{$c}->{'text'} || $config->{'contact'}->{'default'}->{'text'} || $default_text{$c} || $default_text{'default'}); 363 my $txt = message_expand ($pretxt, $client, ""); 364 my $cmd = message_expand ($precmd, $client, ""); 365 $txt =~ s/\\n/\n/g; 366 $txt =~ s/\\t/\t/g; 367 368 # In some cases we want to reopen the command 369 if ($config->{'contact'}->{$c}->{'max_messages'} and defined ($config->{'contact'}->{$c}->{'num_messages'}) and 370 $config->{'contact'}->{$c}->{'num_messages'} >= $config->{'contact'}->{$c}->{'max_messages'}) 371 { 372 close ($config->{'contact'}->{$c}->{'pipe'}); 373 $config->{'contact'}->{$c}->{'pipe'} = undef; 374 } 375 elsif (defined ($config->{'contact'}->{$c}->{'pipe_command'}) and 376 $config->{'contact'}->{$c}->{'pipe_command'} ne $cmd) 377 { 378 close ($config->{'contact'}->{$c}->{'pipe'}); 379 $config->{'contact'}->{$c}->{'pipe'} = undef; 380 } 381 382 my $pipe; 383 if (!defined $config->{'contact'}->{$c}->{'pipe'}) 384 { 385 my @cmd = extract_multiple ( 386 message_expand ($cmd), 387 [ sub { extract_delimited ($_[0], q{"'})}, 388 qr/\S+/ 389 ], 390 undef, 1); 391 @cmd = map { s/['"]$//; s/^['"]//; $_ } @cmd; 392 $config->{'contact'}->{$c}->{'num_messages'} = 0; 393 if ($cmd[0] eq "|") 394 { 395 $cmd[0] = "|-"; 396 } 397 elsif ($cmd[0] !~ /^[|>]/) 398 { 399 unshift (@cmd, "|-"); 369 logger ("Debug: opening \"$c\" for writing: \"" . join('" "',@cmd) . "\".") if $DEBUG; 370 if ($cmd[0] eq ">") { 371 if (! open ($pipe, join (' ', @cmd))) { 372 logger ("Fatal: Could not open " . join (' ', @cmd[1 .. $#cmd]) . " for writing: $!"); 373 exit 3; 400 374 } 401 logger ("Debug: opening for writing: \"" . join('" "',@cmd) . "\".") if $DEBUG; 402 if ($cmd[0] eq ">") 403 { 404 if (! open ($pipe, join (' ', @cmd))) 405 { 406 logger ("Fatal: Could not open " . join (' ', @cmd[1 .. $#cmd]) . " for writing: $!"); 375 } else { 376 my $pid = open ($pipe, "|-"); 377 if (!defined $pid) { 378 logger ("Fatal: Unable to fork: $!"); 379 exit 3; 380 } if (!$pid) { # Child 381 # Fork of stdout-to-log filter 382 my $logstdout; 383 my $logstderr; 384 my $logpid = open ($logstdout, "|-"); 385 if (!defined $logpid) { 386 logger ("Fatal: Unable to fork: $!"); 407 387 exit 3; 388 } 389 if (!$logpid) { # Child 390 while (<STDIN>) { 391 chomp; 392 logger ("Command \"$c\" stdout: $_"); 393 } 394 exit 0; 408 395 } 409 } 410 else 411 { 412 my $pid = open ($pipe, "|-"); 413 if (!defined $pid) 414 { 396 close (STDOUT); 397 *STDOUT = \$logstdout; 398 $logpid = open ($logstderr, "|-"); 399 if (!defined $logpid) { 415 400 logger ("Fatal: Unable to fork: $!"); 416 401 exit 3; 417 402 } 418 if (!$pid) # Child 419 { 420 # Fork of stdout-to-log filter 421 my $logstdout; 422 my $logstderr; 423 my $logpid = open ($logstdout, "|-"); 424 if (!defined $logpid) 425 { 426 logger ("Fatal: Unable to fork: $!"); 427 exit 3; 403 if (!$logpid) { # Child 404 while (<STDIN>) { 405 chomp; 406 logger ("Command \"$c\" stderr: $_"); 428 407 } 429 if (!$logpid) # Child 430 { 431 while (<STDIN>) 432 { 433 chomp; 434 logger ("Command \"$c\" stdout: $_"); 435 } 436 exit 0; 437 } 438 my $logpid = open ($logstderr, "|-"); 439 if (!defined $logpid) 440 { 441 logger ("Fatal: Unable to fork: $!"); 442 exit 3; 443 } 444 if (!$logpid) # Child 445 { 446 while (<STDIN>) 447 { 448 chomp; 449 logger ("Command \"$c\" stderr: $_"); 450 } 451 exit 0; 452 } 453 open (STDOUT, ">&", $logstdout); 454 open (STDERR, ">&", $logstderr); 455 456 exec (@cmd[1 .. $#cmd]) or logger ("Warning: Could not run command \"" . join(' ',@cmd[1 .. $#cmd]) . "\": $!"); 457 exit 5; 458 # NOTREACHED 408 exit 0; 459 409 } 460 } 461 $config->{'contact'}->{$c}->{'pipe_command'} = $cmd; 462 $config->{'contact'}->{$c}->{'pipe'} = $pipe; 463 } 464 $pipe = $config->{'contact'}->{$c}->{'pipe'}; 465 logger ("sending message: \"$txt\"") if ($DEBUG); 466 print $pipe $txt, "\n" if (defined $pipe); 467 $config->{'contact'}->{$c}->{'num_messages'}++; 468 } 410 open (STDOUT, ">&", $logstdout); 411 open (STDERR, ">&", $logstderr); 412 413 exec (@cmd[1 .. $#cmd]) or logger ("Warning: Could not run command \"" . join(' ',@cmd[1 .. $#cmd]) . "\": $!"); 414 exit 5; 415 # NOTREACHED 416 } 417 } 418 logger ("baz?"); 419 munin_set_var_loc ($contactobj, ["pipe_command"], $cmd); 420 munin_set_var_loc ($contactobj, ["pipe"], $pipe); 421 } 422 logger ("sending message: \"$txt\"") if ($DEBUG); 423 logger ("bar?"); 424 print $pipe $txt, "\n" if (defined $pipe); 425 $contactobj->{"num_messages"} = 1 + munin_get ($contactobj, "num_messages", 0); # $num_messages++ 469 426 } 470 427 } … … 472 429 473 430 sub message_expand { 431 my $hash = shift; 474 432 my $text = shift; 475 my $client = shift;476 my $prefix = shift || "";477 433 my @res = (); 478 434 479 435 480 while (length ($text)) 481 { 482 if ($text =~ /^([^\$]+|)(?:\$(\{.*)|)$/) 483 { 436 while (length ($text)) { 437 if ($text =~ /^([^\$]+|)(?:\$(\{.*)|)$/) { 484 438 push @res, $1; 485 439 $text = $2; 486 440 } 487 441 my @a = extract_bracketed ($text, '{}'); 488 if ($a[0] =~ /^\{var:(\S+)\}$/) 489 { 490 $a[0] = (defined $client->{$prefix.$1} ? $client->{$prefix.$1} : ""); 491 } 492 elsif ($a[0] =~ /^\{loop<([^>]+)>:\s*(\S+)\s(.+)\}$/) 493 { 442 if ($a[0] =~ /^\{var:(\S+)\}$/) { 443 $a[0] = munin_get ($hash, $1, ""); 444 } elsif ($a[0] =~ /^\{loop<([^>]+)>:\s*(\S+)\s(.+)\}$/) { 494 445 my $d = $1; 495 446 my $f = $2; 496 447 my $t = $3; 448 my $fields = munin_get ($hash, $f, ""); 497 449 my @res = (); 498 if ( defined $client->{$f})499 {500 foreach my $sub (split /\s+/, $client->{$f})501 {502 push @res, message_expand ($t, $client, $sub.".");450 if ($fields) { 451 foreach my $sub (split /\s+/, $fields) { 452 if (defined $hash->{$sub}) { 453 push @res, message_expand ($hash->{$sub}, $t); 454 } 503 455 } 504 456 } 505 457 $a[0] = join ($d, @res); 506 } 507 elsif ($a[0] =~ /^\{loop:\s*(\S+)\s(.+)\}$/) 508 { 458 } elsif ($a[0] =~ /^\{loop:\s*(\S+)\s(.+)\}$/) { 509 459 my $f = $1; 510 460 my $t = $2; 461 my $fields = munin_get ($hash, $f, ""); 511 462 my $res = ""; 512 if ( defined $client->{$f})513 {514 foreach my $sub (split /\s+/, $client->{$f})515 {516 $res .= message_expand ($t, $client, $sub.".");463 if ($fields) { 464 foreach my $sub (split /\s+/, $fields) { 465 if (defined $hash->{$sub}) { 466 push @res, message_expand ($hash->{$sub}, $t); 467 } 517 468 } 518 469 } 519 470 $a[0] = $res; 520 } 521 elsif ($a[0] =~ /^\{strtrunc:\s*(\S+)\s(.+)\}$/) 522 { 471 } elsif ($a[0] =~ /^\{strtrunc:\s*(\S+)\s(.+)\}$/) { 523 472 my $f = "%.".$1."s"; 524 473 my $t = $2; 525 $a[0] = sprintf ($f, message_expand ($t, $client, $prefix)); 526 } 527 elsif ($a[0] =~ /^\{if:\s*(\!)?(\S+)\s(.+)\}$/) 528 { 474 $a[0] = sprintf ($f, message_expand ($hash, $t)); 475 } elsif ($a[0] =~ /^\{if:\s*(\!)?(\S+)\s(.+)\}$/) { 529 476 my $n = $1; 530 477 my $f = $2; 531 478 my $t = $3; 532 479 my $res = ""; 533 my $check = (defined $client->{$prefix.$f} and length($client->{$prefix.$f}) and $client->{$prefix.$f} ne "0"); 534 535 $check = (!defined $client->{$prefix.$f} or !length($client->{$prefix.$f}) or $client->{$prefix.$f} eq "0") 536 if $n; 537 538 if ($check) 539 { 540 $res .= message_expand ($t, $client, $prefix); 480 my $field = munin_get ($hash, $f, 0); 481 my $check = ($field ne "0" and length ($field)); 482 $check = (!length ($field) or $field eq "0") if $n; 483 484 if ($check) { 485 $res .= message_expand ($hash, $t); 541 486 } 542 487 $a[0] = $res; … … 552 497 # Called from the Munin module when we call munin_config 553 498 my $dirname = shift; 554 555 499 556 500 if (!$log->opened) { people/jo/multilevel-groups-3/server/munin-nodeview.tmpl.in
r860 r1502 4 4 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> 5 5 <head> 6 <link rel="stylesheet" href=" ../style.css" type="text/css" />6 <link rel="stylesheet" href="<TMPL_VAR NAME="CSSPATH">" type="text/css" /> 7 7 <meta http-equiv="refresh" content="300" /> 8 <title>Munin :: <TMPL_VAR ESCAPE="HTML" NAME="DOMAIN"> :: <TMPL_VAR ESCAPE="HTML" NAME="NODE"></title>8 <title>Munin <TMPL_LOOP NAME="PATH">:: <TMPL_VAR ESCAPE="HTML" NAME="NAME"></TMPL_LOOP></title> 9 9 <meta http-equiv="content-type" content="application/xhtml+xml; charset=iso-8859-1" /> 10 10 <meta name="author" content="Auto-generated by Munin" /> … … 15 15 <td rowspan="2"><div class="logo"> </div></td> 16 16 <td valign="top"> 17 <h2><a href="../index.html">Overview</a> :: <a href="index.html"> 18 <TMPL_VAR ESCAPE="HTML" NAME="DOMAIN"></a> :: <TMPL_VAR ESCAPE="HTML" NAME="NODE"></h2> 17 <h2><TMPL_LOOP NAME="PATH"><TMPL_IF NAME="PATH"><a href="<TMPL_VAR NAME="PATH">"></TMPL_IF><TMPL_VAR NAME="NAME"><TMPL_IF NAME="PATH"></a> :: </TMPL_IF></TMPL_LOOP></title> 19 18 </td> 20 19 </tr> 21 20 <tr> 22 21 <td valign="top"> 23 <h2><TMPL_VAR NAME="N ODE"> :: [ <TMPL_LOOP NAME="CATEGORIES"><a <TMPL_IF NAME="STATE_WARNING">class="warn"</TMPL_IF> <TMPL_IF NAME="STATE_CRITICAL">class="crit"</TMPL_IF> href="#<TMPL_VAR ESCAPE="HTML" NAME="NAME">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a> </TMPL_LOOP>]</h2>22 <h2><TMPL_VAR NAME="NAME"><TMPL_IF NAME="NCATEGORIES"> :: [ <TMPL_LOOP NAME="CATEGORIES"><a <TMPL_IF NAME="STATE_WARNING">class="warn"</TMPL_IF> <TMPL_IF NAME="STATE_CRITICAL">class="crit"</TMPL_IF> href="#<TMPL_VAR ESCAPE="HTML" NAME="NAME">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a> </TMPL_LOOP>]</TMPL_IF></h2> 24 23 </td> 25 24 </tr> … … 39 38 <TMPL_LOOP NAME="SERVICES"> 40 39 <tr><td></td></tr> 41 <tr><td><div class="lighttext">:: <a <TMPL_IF NAME="STATE_WARNING">class="warn"</TMPL_IF> <TMPL_IF NAME="STATE_CRITICAL">class="crit"</TMPL_IF> href="<TMPL_VAR NAME="URL ">"><TMPL_VAR ESCAPE="HTML" NAME="LABEL"></a></div></td></tr>40 <tr><td><div class="lighttext">:: <a <TMPL_IF NAME="STATE_WARNING">class="warn"</TMPL_IF> <TMPL_IF NAME="STATE_CRITICAL">class="crit"</TMPL_IF> href="<TMPL_VAR NAME="URLX">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a></div></td></tr> 42 41 <tr> 43 <td><a href="<TMPL_VAR NAME="URL ">"><img src="<TMPL_VAR NAME="IMGDAY">" alt="<TMPL_VAR ESCAPE="HTML" NAME="LABEL">" <TMPL_IF NAME="IMGDAYWIDTH">width="<TMPL_VAR NAME="IMGDAYWIDTH">" </TMPL_IF> <TMPL_IF NAME="IMGDAYHEIGHT">height="<TMPL_VAR NAME="IMGDAYHEIGHT">"</TMPL_IF>/></a></td>44 <td><a href="<TMPL_VAR NAME="URL ">"><img src="<TMPL_VAR NAME="IMGWEEK">" alt="<TMPL_VAR ESCAPE="HTML" NAME="LABEL">" <TMPL_IF NAME="IMGWEEKWIDTH">width="<TMPL_VAR NAME="IMGWEEKWIDTH">" </TMPL_IF> <TMPL_IF NAME="IMGWEEKHEIGHT">height="<TMPL_VAR NAME="IMGWEEKHEIGHT">"</TMPL_IF>/></a></td>42 <td><a href="<TMPL_VAR NAME="URLX">"><img src="<TMPL_VAR NAME="IMGDAY">" alt="<TMPL_VAR ESCAPE="HTML" NAME="NAME">" <TMPL_IF NAME="IMGDAYWIDTH">width="<TMPL_VAR NAME="IMGDAYWIDTH">" </TMPL_IF> <TMPL_IF NAME="IMGDAYHEIGHT">height="<TMPL_VAR NAME="IMGDAYHEIGHT">"</TMPL_IF>/></a></td> 43 <td><a href="<TMPL_VAR NAME="URLX">"><img src="<TMPL_VAR NAME="IMGWEEK">" alt="<TMPL_VAR ESCAPE="HTML" NAME="NAME">" <TMPL_IF NAME="IMGWEEKWIDTH">width="<TMPL_VAR NAME="IMGWEEKWIDTH">" </TMPL_IF> <TMPL_IF NAME="IMGWEEKHEIGHT">height="<TMPL_VAR NAME="IMGWEEKHEIGHT">"</TMPL_IF>/></a></td> 45 44 </tr> 46 45 </TMPL_LOOP> … … 52 51 </TMPL_LOOP> 53 52 <tr><td class="linkbox"> 54 <TMPL_LOOP NAME="DOMAINS"> 55 <a href="../<TMPL_VAR NAME="DOMAIN">/index.html"><TMPL_VAR ESCAPE="HTML" NAME="DOMAIN"></a> : 56 </TMPL_LOOP> 53 <TMPL_VAR NAME="PARENT"> :<TMPL_LOOP NAME="PEERS">: <TMPL_IF NAME="LINK"><a href="<TMPL_VAR NAME="LINK">"></TMPL_IF><TMPL_VAR NAME="NAME"><TMPL_IF NAME="LINK"></a></TMPL_IF></a> </TMPL_LOOP> 57 54 </td></tr> 58 55 </table> people/jo/multilevel-groups-3/server/munin-overview.tmpl.in
r860 r1502 18 18 </table> 19 19 <div class="box"> 20 <TMPL_LOOP NAME=" DOMAINS">20 <TMPL_LOOP NAME="GROUPS"> 21 21 <ul> 22 <li><span class="domain"><a href="<TMPL_VAR NAME="DOMAIN">/index.html"><TMPL_VAR ESCAPE="HTML" NAME="DOMAIN"></a></span><TMPL_IF NAME="COMPARE"> :: [ <a href="<TMPL_VAR NAME="DOMAIN">/comparison-day.html">day</a> <a href="<TMPL_VAR NAME="DOMAIN">/comparison-week.html">week</a> <a href="<TMPL_VAR NAME="DOMAIN">/comparison-month.html">month</a> <a href="<TMPL_VAR NAME="DOMAIN">/comparison-year.html">year</a> ]</TMPL_IF> 23 <ul> 24 <TMPL_LOOP NAME="NODES"> 25 <li><span class="host"><a href="<TMPL_VAR NAME="DOMAIN">/<TMPL_VAR NAME="NODE">.html"><TMPL_VAR ESCAPE="HTML" NAME="NODE"></a></span> :: 26 [ <TMPL_LOOP NAME="CATEGORIES"><a <TMPL_IF NAME="STATE_WARNING">class="warn"</TMPL_IF> <TMPL_IF NAME="STATE_CRITICAL">class="crit"</TMPL_IF> href="<TMPL_VAR NAME="DOMAIN">/<TMPL_VAR NAME="NODE">.html#<TMPL_VAR NAME="NAME">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a> </TMPL_LOOP>]</li> 27 </TMPL_LOOP> 28 </ul> 22 <li><TMPL_IF NAME="NCATEGORIES"><span class="host"><TMPL_ELSE><span class="domain"></TMPL_IF><a href="<TMPL_VAR NAME="URL">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a></span><TMPL_IF NAME="COMPARE"> :: [ <a href="<TMPL_VAR NAME="NAME">/comparison-day.html">day</a> <a href="<TMPL_VAR NAME="NAME">/comparison-week.html">week</a> <a href="<TMPL_VAR NAME="NAME">/comparison-month.html">month</a> <a href="<TMPL_VAR NAME="NAME">/comparison-year.html">year</a> ]</TMPL_IF> <TMPL_IF NAME="NCATEGORIES">[ <TMPL_LOOP NAME="CATEGORIES"><a <TMPL_IF NAME="STATE_WARNING">class="warn"</TMPL_IF> <TMPL_IF NAME="STATE_CRITICAL">class="crit"</TMPL_IF> href="<TMPL_VAR NAME="URL">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a> </TMPL_LOOP>]</TMPL_IF> 23 <TMLP_IF NAME="NGROUPS"> 24 <TMPL_LOOP NAME="GROUPS"> 25 <ul> 26 <li><TMPL_IF NAME="NCATEGORIES"><span class="host"><TMPL_ELSE><span class="domain"></TMPL_IF><a href="<TMPL_VAR NAME="URL">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a></span><TMPL_IF NAME="COMPARE"> :: [ <a href="<TMPL_VAR NAME="NAME">/comparison-day.html">day</a> <a href="<TMPL_VAR NAME="NAME">/comparison-week.html">week</a> <a href="<TMPL_VAR NAME="NAME">/comparison-month.html">month</a> <a href="<TMPL_VAR NAME="NAME">/comparison-year.html">year</a> ]</TMPL_IF> <TMPL_IF NAME="NCATEGORIES">[ <TMPL_LOOP NAME="CATEGORIES"><a <TMPL_IF NAME="STATE_WARNING">class="warn"</TMPL_IF> <TMPL_IF NAME="STATE_CRITICAL">class="crit"</TMPL_IF> href="<TMPL_VAR NAME="URL">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a> </TMPL_LOOP>]</TMPL_IF> 27 <TMLP_IF NAME="NGROUPS"> 28 <TMPL_LOOP NAME="GROUPS"> 29 <ul> 30 <li><TMPL_IF NAME="NCATEGORIES"><span class="host"><TMPL_ELSE><span class="domain"></TMPL_IF><a href="<TMPL_VAR NAME="URL">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a></span><TMPL_IF NAME="COMPARE"> :: [ <a href="<TMPL_VAR NAME="NAME">/comparison-day.html">day</a> <a href="<TMPL_VAR NAME="NAME">/comparison-week.html">week</a> <a href="<TMPL_VAR NAME="NAME">/comparison-month.html">month</a> <a href="<TMPL_VAR NAME="NAME">/comparison-year.html">year</a> ]</TMPL_IF> <TMPL_IF NAME="NCATEGORIES">[ <TMPL_LOOP NAME="CATEGORIES"><a <TMPL_IF NAME="STATE_WARNING">class="warn"</TMPL_IF> <TMPL_IF NAME="STATE_CRITICAL">class="crit"</TMPL_IF> href="<TMPL_VAR NAME="URL">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a> </TMPL_LOOP>]</TMPL_IF> 31 <TMLP_IF NAME="NGROUPS"> 32 <TMPL_LOOP NAME="GROUPS"> 33 <ul> 34 <li><TMPL_IF NAME="NCATEGORIES"><span class="host"><TMPL_ELSE><span class="domain"></TMPL_IF><a href="<TMPL_VAR NAME="URL">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a></span><TMPL_IF NAME="COMPARE"> :: [ <a href="<TMPL_VAR NAME="NAME">/comparison-day.html">day</a> <a href="<TMPL_VAR NAME="NAME">/comparison-week.html">week</a> <a href="<TMPL_VAR NAME="NAME">/comparison-month.html">month</a> <a href="<TMPL_VAR NAME="NAME">/comparison-year.html">year</a> ]</TMPL_IF> <TMPL_IF NAME="NCATEGORIES">[ <TMPL_LOOP NAME="CATEGORIES"><a <TMPL_IF NAME="STATE_WARNING">class="warn"</TMPL_IF> <TMPL_IF NAME="STATE_CRITICAL">class="crit"</TMPL_IF> href="<TMPL_VAR NAME="URL">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a> </TMPL_LOOP>]</TMPL_IF> 35 <TMLP_IF NAME="NGROUPS"> 36 <TMPL_LOOP NAME="GROUPS"> 37 <ul> 38 <li><TMPL_IF NAME="NCATEGORIES"><span class="host"><TMPL_ELSE><span class="domain"></TMPL_IF><a href="<TMPL_VAR NAME="URL">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a></span><TMPL_IF NAME="COMPARE"> :: [ <a href="<TMPL_VAR NAME="NAME">/comparison-day.html">day</a> <a href="<TMPL_VAR NAME="NAME">/comparison-week.html">week</a> <a href="<TMPL_VAR NAME="NAME">/comparison-month.html">month</a> <a href="<TMPL_VAR NAME="NAME">/comparison-year.html">year</a> ]</TMPL_IF> <TMPL_IF NAME="NCATEGORIES">[ <TMPL_LOOP NAME="CATEGORIES"><a <TMPL_IF NAME="STATE_WARNING">class="warn"</TMPL_IF> <TMPL_IF NAME="STATE_CRITICAL">class="crit"</TMPL_IF> href="<TMPL_VAR NAME="URL">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a> </TMPL_LOOP>]</TMPL_IF> 39 <TMLP_IF NAME="NGROUPS"> 40 <TMPL_LOOP NAME="GROUPS"> 41 <ul> 42 <li><TMPL_IF NAME="NCATEGORIES"><span class="host"><TMPL_ELSE><span class="domain"></TMPL_IF><a href="<TMPL_VAR NAME="URL">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a></span><TMPL_IF NAME="COMPARE"> :: [ <a href="<TMPL_VAR NAME="NAME">/comparison-day.html">day</a> <a href="<TMPL_VAR NAME="NAME">/comparison-week.html">week</a> <a href="<TMPL_VAR NAME="NAME">/comparison-month.html">month</a> <a href="<TMPL_VAR NAME="NAME">/comparison-year.html">year</a> ]</TMPL_IF> <TMPL_IF NAME="NCATEGORIES">[ <TMPL_LOOP NAME="CATEGORIES"><a <TMPL_IF NAME="STATE_WARNING">class="warn"</TMPL_IF> <TMPL_IF NAME="STATE_CRITICAL">class="crit"</TMPL_IF> href="<TMPL_VAR NAME="URL">"><TMPL_VAR ESCAPE="HTML" NAME="NAME"></a> </TMPL_LOOP>]</TMPL_IF> 43 </li> 44 </ul> 45 </TMPL_LOOP> 46 </TMLP_IF> 47 </li> 48 </ul> 49 </TMPL_LOOP> 50 </TMLP_IF> 51 </li> 52 </ul> 53 </TMPL_LOOP> 54 </TMLP_IF> 55 </li> 56 </ul> 57 </TMPL_LOOP> 58 </TMLP_IF> 59 </li> 60 </ul> 61 </TMPL_LOOP> 62 </TMLP_IF> 29 63 </li> 30 64 </ul> people/jo/multilevel-groups-3/server/munin-serviceview.tmpl.in
r860 r1502 4 4 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> 5 5 <head> 6 <link rel="stylesheet" href=" ../style.css" type="text/css" />6 <link rel="stylesheet" href="<TMPL_VAR NAME="CSS">" type="text/css" /> 7 7 <meta http-equiv="refresh" content="300" /> 8 <title> Munin :: <TMPL_VAR NAME="DOMAIN"> :: <TMPL_VAR NAME="NODE"> :: <TMPL_VAR ESCAPE="HTML" NAME="SERVICE"></title>8 <title><TMPL_LOOP NAME="PATH"><TMPL_IF NAME="name"> :: <TMPL_VAR ESCAPE="HTML" NAME="name"></a><TMPL_ELSE>Munin</TMPL_IF></TMPL_LOOP></title> 9 9 <meta http-equiv="content-type" content="application/xhtml+xml; charset=iso-8859-1" /> 10 10 <meta name="author" content="Auto-generated by Munin" /> … … 15 15 <td><div class="logo"> </div></td> 16 16 <td valign="top"> 17 <h2><a href="../index.html">Overview</a> :: <a href="index.html"> 18 <TMPL_VAR NAME="DOMAIN"></a> :: 19 <a href="<TMPL_VAR NAME="NODE">.html"><TMPL_VAR NAME="NODE"></a> :: <TMPL_VAR ESCAPE="HTML" NAME="SERVICE"></h2> 17 <h2> 18 <TMPL_LOOP NAME="PATH"> 19 <TMPL_IF NAME="name"> :: 20 <TMPL_IF NAME="link"><A HREF="<TMPL_VAR NAME="link">"></TMPL_IF> 21 <TMPL_VAR NAME="name"> 22 <TMPL_IF NAME="link"></A></TMPL_IF> 23 <TMPL_ELSE> 24 <TMPL_IF NAME="link"><A HREF="<TMPL_VAR NAME="link">"></TMPL_IF> 25 Overview 26 <TMPL_IF NAME="link"></A></TMPL_IF> 27 </TMPL_IF> 28 </TMPL_LOOP></h2> 20 29 </td> 21 30 </tr> … … 82 91 <tr> 83 92 <td colspan="2" class="linkbox"> 84 <TMPL_LOOP NAME="DOMAINS"> 85 <a href="../<TMPL_VAR NAME="DOMAIN">/index.html"><TMPL_VAR NAME="DOMAIN"></a> : 86 </TMPL_LOOP> 93 <TMPL_VAR NAME="CATEGORY"> :<TMPL_LOOP NAME="PEERS">: <TMPL_IF NAME="LINK"><a href="<TMPL_VAR NAME="LINK">"></TMPL_IF><TMPL_VAR NAME="NAME"><TMPL_IF NAME="LINK"></a></TMPL_IF> </TMPL_LOOP> 87 94 </td> 88 95 </tr> people/jo/multilevel-groups-3/server/munin-update.in
r1453 r1502 159 159 my $bad_procs = 0; 160 160 my $uaddr; 161 if ($do_fork) 162 {161 162 if ($do_fork) { 163 163 # Set up socket 164 164 $uaddr = sockaddr_un("$config->{rundir}/$serversocket"); … … 172 172 logger("Starting munin-update"); 173 173 174 for my $key (keys %{$config->{domain}}) { 175 my $domain_time = Time::HiRes::time; 176 logger ("Processing domain: $key"); 177 process_domain($key); 178 $domain_time = sprintf ("%.2f",(Time::HiRes::time - $domain_time)); 179 print STATS "UD|$key|$domain_time\n"; 180 logger ("Processed domain: $key ($domain_time sec)"); 181 } 182 183 #sub REAPER { 184 # my $child; 185 # my $waitedpid; 186 # while (($waitedpid = waitpid(-1,WNOHANG)) > 0) { 187 # logger ("reaped $waitedpid" . ($? ? " with exit $?" : '')); 188 # } 189 # $SIG{CHLD} = \&REAPER; # loathe sysV 190 #} 191 # 192 #$SIG{CHLD} = \&REAPER; 193 194 if ($do_fork) 195 { 196 my $timeout_start = time(); 197 $SIG{ALRM} = sub { die "Timed out waiting for children. $!\n"}; 198 alarm ($TIMEOUT); 199 200 for (;(scalar (keys %children) - $bad_procs > 0);) 201 { 202 eval { 203 $SIG{ALRM} = sub { 204 foreach my $key (keys %children) 205 { 206 if (waitpid ($key, WNOHANG) != 0) 207 { 208 my $domain = $children{$key}->[0]; 209 my $name = $children{$key}->[1]; 210 my $oldnode = $children{$key}->[3]; 211 212 logger ("Reaping child: $domain -> $name."); 213 delete $children{$key}; 214 use_old_config ($domain, $name, $oldnode); 215 } 216 } 217 die; 218 }; 219 220 alarm (10); 221 accept (Client, Server); 222 }; 223 alarm ($TIMEOUT - time() + $timeout_start); 224 if ($@) 225 { 226 if (@queue and defined $config->{max_processes} and 227 $config->{max_processes}) 228 { 229 while (keys %children < ($config->{max_processes}-1-$bad_procs)) 230 { 231 my $args = pop @queue; 232 logger ("de-queueing new connection: $args->[1]"); 233 do_node($args->[0], $args->[1], $args->[2], $args->[3]); 174 # Make array of what is probably needed to update 175 my $work_array = []; 176 if (@limit_hosts) { # Limit what to update if needed 177 foreach my $nodename (@limit_hosts) { 178 push @$work_array, map { @{munin_find_field ($_->{$nodename}, "address")} } @{munin_find_field($config, $nodename)}; 179 } 180 } else { # ...else just search for all adresses to update 181 push @$work_array, @{munin_find_field($config, "address")}; 182 } 183 184 # Go through scheduled work to weed out a few bits, and prepare some info 185 for my $hashnode (@$work_array) { 186 my $loc = munin_get_node_loc($hashnode); 187 my $name = munin_get_node_name ($hashnode); 188 189 # Skip anything that has been disabled with the "update" setting 190 if (!munin_get_bool ($hashnode, "update", "true")) { 191 logger ("Skipping \"$name\" (update disabled by config)"); 192 next; 193 } 194 195 # We need to connect to this node; queue it 196 logger ("Queuing \"$name\" for update."); 197 push (@queue, [$loc, $hashnode, munin_get_node ($oldconfig, $loc)]); 198 } 199 200 my $timeout_start = time(); 201 $SIG{ALRM} = sub { die "Timed out waiting for children. $!\n"}; 202 alarm ($TIMEOUT); 203 204 if ($do_fork) { 205 # Initially set off a bunch of nodes... 206 if (defined $config->{max_processes}) { 207 while (keys %children < ($config->{max_processes}-1-$bad_procs)) { 208 do_node(@{pop @queue}); 209 } 210 } else { 211 do_node(@{pop @queue}) while @queue; # No limit on number of procs 212 } 213 # Loop as long as there are kids or queue... 214 for (;(scalar (keys %children) - $bad_procs > 0) or @queue;) { 215 logger ("Debug: Doing a pass to check children status.") if $DEBUG; 216 217 eval { # eval to call accept() with a timeout 218 $SIG{ALRM} = sub { # If we timeout we need to use the old config 219 foreach my $key (keys %children) { 220 if (waitpid ($key, WNOHANG) != 0) { 221 my $loc = $children{$key}->[0]; 222 my $newnode = $children{$key}->[1]; 223 my $oldnode = $children{$key}->[2]; 224 my $name = munin_get_node_name ($newnode); 225 226 logger ("Reaping child: $name."); 227 delete $children{$key}; 228 munin_copy_node_toloc ($oldnode, $config, $loc); 234 229 } 235 230 } 236 next; 231 die; 232 }; # end sub 233 234 alarm (10); 235 accept (Client, Server); 236 }; # end eval 237 238 if ($@) { 239 if (@queue and defined $config->{max_processes} and $config->{max_processes}) { 240 logger ("Debug: Checking whether to spawn off more procs from queue."); 241 while (keys %children < ($config->{max_processes}-1-$bad_procs)) { 242 logger ("Debug: Popping queue item and spawning new proc."); 243 do_node(@{pop @queue}); 244 } 237 245 } 238 close STDIN; 239 open (STDIN, "<&Client") || die "can't dup client to stdin"; 240 241 my $pid; 242 my $name; 243 my $domain; 244 my $tmpref; 245 eval { 246 $tmpref = fd_retrieve (\*STDIN); 247 }; 248 if ($@) 249 { 250 $bad_procs++; 251 logger ("[WARNING] Error communicating with process: $@"); 252 } 253 else 254 { 255 ($pid, $domain, $name) = ($tmpref->[0], $tmpref->[1], $tmpref->[2]); 256 logger ("connection from $domain -> $name ($pid)"); 257 258 eval { 259 $config->{domain}->{$domain}->{node}->{$name} = fd_retrieve (\*STDIN); 260 }; 261 if ($@) 262 { 263 logger ("[WARNING] Error during fd_retrieve of config: $@"); 264 265 my $domain = $children{$pid}->[0]; 266 my $name = $children{$pid}->[1]; 267 my $oldnode = $children{$pid}->[3]; 268 269 use_old_config ($domain, $name, $oldnode); 270 } 271 delete $children{$pid}; 272 waitpid ($pid, 0); 273 logger ("connection from $domain -> $name ($pid) closed"); 274 } 275 if (@queue and defined $config->{max_processes} and 276 $config->{max_processes} and 277 scalar (keys %children) < (($config->{max_processes})-1-$bad_procs)) 278 { 279 my $args = pop @queue; 280 logger ("de-queueing new connection: $args->[1]"); 281 do_node($args->[0], $args->[1], $args->[2], $args->[3]); 282 close (Client); 246 next; 247 } 248 249 alarm ($TIMEOUT - time() + $timeout_start); 250 close STDIN; 251 open (STDIN, "<&Client") || die "can't dup client to stdin"; 252 253 my $pid; 254 my $name; 255 my $loc; 256 my $tmpref; 257 eval { 258 $tmpref = fd_retrieve (\*STDIN); 259 }; 260 if ($@) { 261 $bad_procs++; 262 logger ("[WARNING] Error communicating with process: $@"); 263 } else { 264 ($pid, $loc, $name) = ($tmpref->[0], $tmpref->[1], $tmpref->[2]); 265 logger ("connection from $name ($pid)"); 266 267 eval { 268 my $newnode = fd_retrieve (\*STDIN); 269 munin_copy_node_toloc ($newnode, $config, $loc); 270 }; 271 if ($@) { 272 logger ("[WARNING] Error during fd_retrieve of config: $@"); 273 274 my $loc = $children{$pid}->[0]; 275 my $newnode = $children{$pid}->[1]; 276 my $oldnode = $children{$pid}->[2]; 277 278 munin_copy_node_toloc ($oldnode, $config, $loc); 283 279 } 280 delete $children{$pid}; 281 waitpid ($pid, 0); 282 logger ("connection from $name ($pid) closed"); 283 } 284 if (@queue and defined $config->{max_processes} and 285 $config->{max_processes} and 286 scalar (keys %children) < (($config->{max_processes})-1-$bad_procs)) { 287 do_node(@{pop @queue}); 288 close (Client); 289 } 284 290 } 285 291 alarm (0); 286 } 292 } else { # No forking, just poll the nodes sequentially... 293 for (;@queue;) { 294 do_node(@{pop @queue}); 295 } 296 } 297 298 alarm (0); 287 299 288 300 if ($bad_procs) # Use old configuration for killed children … … 290 302 foreach my $key (keys %children) 291 303 { 292 my $ domain= $children{$key}->[0];293 my $n ame= $children{$key}->[1];294 my $ node= $children{$key}->[2];295 my $ oldnode = $children{$key}->[3];296 297 use_old_config ($domain, $name, $oldnode);298 logger ("Attempting to use old configuration for $ domain -> $name.");304 my $loc = $children{$key}->[0]; 305 my $newnode = $children{$key}->[1]; 306 my $oldnode = $children{$key}->[2]; 307 my $name = munin_get_node_name ($newnode); 308 309 munin_copy_node_toloc ($oldnode, $config, $loc); 310 logger ("Attempting to use old configuration for $name."); 299 311 } 300 312 } 301 313 302 314 unlink ("$config->{rundir}/$serversocket"); 315 303 316 304 317 my $overwrite = &munin_readconfig($conffile); 305 318 $config = &munin_overwrite($config,$overwrite); 306 319 307 &compare_configs ($oldconfig, $config);320 compare_configs ($oldconfig, $config); 308 321 309 322 if (&munin_getlock("$config->{rundir}/munin-datafile.lock")) { … … 332 345 my $just_upgraded = 0; 333 346 334 if (!defined $old->{version} or 335 $old->{version} ne $VERSION) 336 { 347 if (!defined $old->{version} or $old->{version} ne $VERSION) { 337 348 $just_upgraded = 1; 338 349 } 339 350 340 foreach my $dom (%{$new->{domain}}) 341 { 342 foreach my $host (%{$new->{domain}->{$dom}->{node}}) 343 { 344 foreach my $serv (%{$new->{domain}->{$dom}->{node}->{$host}->{client}}) 345 { 346 foreach my $field (%{$new->{domain}->{$dom}->{node}->{$host}->{client}->{$serv}}) 347 { 348 next unless $field =~ /\.label$/; 349 $field =~ s/\.label$//; 350 if ($just_upgraded or &is_changed ($old, $new, $dom, $host, $serv, $field, "max")) 351 { 352 &change_max ($config, $dom, $host, $serv, $field, 353 (defined $new->{domain}->{$dom}->{node}->{$host}->{client}->{$serv}->{$field.".max"} ? 354 $new->{domain}->{$dom}->{node}->{$host}->{client}->{$serv}->{$field.".max"} : undef)); 355 } 356 if ($just_upgraded or &is_changed ($old, $new, $dom, $host, $serv, $field, "min")) 357 { 358 &change_min ($config, $dom, $host, $serv, $field, 359 (defined $new->{domain}->{$dom}->{node}->{$host}->{client}->{$serv}->{$field.".min"} ? 360 $new->{domain}->{$dom}->{node}->{$host}->{client}->{$serv}->{$field.".min"} : undef)); 361 } 362 if ($just_upgraded or &is_changed ($old, $new, $dom, $host, $serv, $field, "type")) 363 { 364 &change_type ($oldconfig, $config, $dom, $host, $serv, $field, 365 (defined $new->{domain}->{$dom}->{node}->{$host}->{client}->{$serv}->{$field.".type"} ? 366 $new->{domain}->{$dom}->{node}->{$host}->{client}->{$serv}->{$field.".type"} : undef)); 367 } 368 } 369 } 370 } 371 } 372 373 } 374 375 sub is_changed 376 { 377 my $old = shift; 378 my $new = shift; 379 my $dom = shift; 380 my $host = shift; 381 my $serv = shift; 382 my $field = shift; 383 my $setting = shift; 384 385 if (defined $new->{domain}->{$dom}->{node}->{$host}->{client}->{$serv}->{$field.".".$setting}) 386 { 387 if ((!defined $old->{domain}->{$dom}->{node}->{$host}->{client}->{$serv}->{$field.".".$setting}) or 388 ($old->{domain}->{$dom}->{node}->{$host}->{client}->{$serv}->{$field.".".$setting} ne 389 $new->{domain}->{$dom}->{node}->{$host}->{client}->{$serv}->{$field.".".$setting} 390 )) 391 { 392 return 1; 393 } 394 } 395 396 if (defined $old->{domain}->{$dom}->{node}->{$host}->{client}->{$serv}->{$field.".".$setting}) 397 { 398 if (!defined $new->{domain}->{$dom}->{node}->{$host}->{client}->{$serv}->{$field.".".$setting}) 399 { 400 return 1; 401 } 402 } 403 404 return 0; 351 foreach my $node (@{munin_find_field($new, "label")}) { 352 my $oldnode = munin_get_node ($old, munin_get_node_loc ($node)); 353 my $name = munin_get_node_name ($node); 354 my ($oldval, $newval); 355 356 $oldval = munin_get ($oldnode, "max", ""); 357 $newval = munin_get ($node, "max", ""); 358 if ($just_upgraded or $oldval ne $newval) { 359 logger ("Notice: compare_configs: $name.max changed from ".(length $oldval?$oldval:"undefined")." to $newval."); 360 change_max (munin_get_filename ($node), $newval); 361 } 362 363 $oldval = munin_get ($oldnode, "min", ""); 364 $newval = munin_get ($node, "min", ""); 365 if ($just_upgraded or $oldval ne $newval) { 366 logger ("Notice: compare_configs: $name.min changed from ".(length $oldval?$oldval:"undefined")." to $newval."); 367 change_min (munin_get_filename ($node), $newval); 368 } 369 370 $oldval = munin_get ($oldnode, "type", "GAUGE"); 371 $newval = munin_get ($node, "type", "GAUGE"); 372 if ($just_upgraded or $oldval ne $newval) { 373 logger ("Notice: compare_configs: $name.type changed from ".(length $oldval?$oldval:"undefined")." to $newval."); 374 change_type (munin_get_filename ($oldnode), munin_get_filename ($node), $newval); 375 } 376 } 405 377 } 406 378 407 379 sub change_type 408 380 { 409 my $oconf = shift; 410 my $nconf = shift; 411 my $domain = shift; 412 my $host = shift; 413 my $serv = shift; 414 my $field = shift; 381 my $ofile = shift; 382 my $nfile = shift; 415 383 my $val = shift; 416 my $ofile = &munin_get_filename ($oconf, $domain, $host, $serv, $field); 417 my $nfile = &munin_get_filename ($nconf, $domain, $host, $serv, $field); 418 419 logger ("[WARNING] Changing type of $domain -> $host -> $serv -> $field to " . (defined $val?$val:"GAUGE") . ".\n"); 420 RRDs::tune ($ofile, "-d", "42:".(defined $val?$val:"GAUGE")); 421 unless (rename ($ofile, $nfile)) 422 { 423 logger ("[ERROR] Could not rename file: $!\n"); 424 } 384 385 if (defined $ofile and -f $ofile) { 386 logger ("[WARNING]: Changing name of $ofile to $nfile"); 387 unless (rename ($ofile, $nfile)) { 388 logger ("[ERROR]: Could not rename file: $!\n"); 389 } 390 } 391 392 logger ("INFO: Changing type of $nfile to " . (defined $val?$val:"GAUGE")); 393 RRDs::tune ($nfile, "-d", "42:".(defined $val?$val:"GAUGE")); 425 394 } 426 395 427 396 sub change_max 428 397 { 429 my $config = shift; 430 my $domain = shift; 431 my $host = shift; 432 my $serv = shift; 433 my $field = shift; 434 my $val = shift; 435 my $file = &munin_get_filename ($config, $domain, $host, $serv, $field); 436 437 logger ("[WARNING] Changing max of $domain -> $host -> $serv -> $field to " . (defined $val?$val:"undef") . ".\n"); 398 my $file = shift; 399 my $val = shift; 400 401 logger ("[WARNING]: Changing max of \"$file\" to \"$val\".\n"); 438 402 RRDs::tune ($file, "-a", "42:".(defined $val?$val:"U")); 439 403 } … … 441 405 sub change_min 442 406 { 443 my $config = shift; 444 my $domain = shift; 445 my $host = shift; 446 my $serv = shift; 447 my $field = shift; 448 my $val = shift; 449 my $file = &munin_get_filename ($config, $domain, $host, $serv, $field); 450 451 logger ("[WARNING] Changing min of $domain -> $host -> $serv -> $field to " . (defined $val?$val:"undef") . ".\n"); 407 my $file = shift; 408 my $val = shift; 409 410 logger ("[WARNING]: Changing min of \"$file\" to \"$val\".\n"); 452 411 RRDs::tune ($file, "-i", "42:".(defined $val?$val:"U")); 453 412 } 454 413 455 sub process_domain { 456 my ($domain) = @_; 457 for my $key ( keys %{$config->{domain}->{$domain}->{node}}) { 458 if (@limit_hosts and !grep (/^$key$/, @limit_hosts)) 459 { 460 logger ("Skipping host \"$key\" - not in hostlist\n") if $DEBUG; 461 next; 462 } 463 if (defined $config->{max_processes} and $config->{max_processes} and 464 ($config->{max_processes}-1-$bad_procs) < keys %children) 465 { 466 push (@queue, [$domain, $key, $config->{domain}->{$domain}->{node}->{$key},$oldconfig->{domain}->{$domain}->{node}->{$key}]); 467 } 468 else 469 { 470 do_node($domain,$key ,$config->{domain}->{$domain}->{node}->{$key},$oldconfig->{domain}->{$domain}->{node}->{$key}); 471 } 414 sub do_node { 415 my ($loc, $newconf, $oldconf) = @_; 416 return undef unless munin_get ($newconf, "update", "true"); # Skip unless we're updating it 417 return undef unless munin_get ($newconf, "fetch_data", "true"); # Old name for "update" 418 419 my $name = munin_get ($newconf, "host_name") || munin_get_node_name ($newconf); 420 421 unless ($newconf->{"address"}) { 422 logger("[ERROR] No address defined for node: $name"); 423 return undef; 472 424 } 473 } 474 475 sub do_node { 476 my ($domain, $name, $config, $oldconfig) = @_; 477 my $node_time = Time::HiRes::time; 478 logger("Processing node: $name"); 479 process_node($domain,$name ,$config,$oldconfig); 480 $node_time = sprintf ("%.2f",(Time::HiRes::time - $node_time)); 481 print STATS "UN|$domain|$name|$node_time\n"; 482 logger ("Processed node: $name ($node_time sec)"); 483 } 484 485 sub process_node { 486 my ($domain,$name,$node,$oldnode) = @_; 487 return if (exists ($node->{fetch_data}) and !$node->{fetch_data}); 488 return if (exists ($node->{update}) and $node->{update} ne "yes"); 489 unless ($node->{address}) { 490 logger("[ERROR] No address defined for node: $name"); 491 return; 492 } 425 logger ("Debug: do_node: Starting on \"$name\".") if $DEBUG; 493 426 494 427 # Then we fork... … … 498 431 if (!defined($pid)) 499 432 { # Something went wrong 500 warn "cannot fork: $!";433 logger ("Error: Unable to fork: $!"); 501 434 return; 502 435 } elsif ($pid) 503 436 { # I'm the parent 504 $children{$pid} = [$ domain, $name, $node, $oldnode];437 $children{$pid} = [$loc, $newconf, $oldconf]; 505 438 return; 506 439 } # else I'm the child -- go spawn … … 510 443 511 444 # First we get lock... 512 unless (&munin_getlock("$config->{rundir}/munin-$domain-$name.lock")) 513 { 514 logger ("[ERROR] Could not get lock for $node -> $name. Skipping node."); 515 if ($do_fork) 516 { # Send the old config to the server before we die 445 unless (&munin_getlock(munin_get($newconf, "rundir").$newconf->{"address"}.".lock")) { 446 logger ("[ERROR] Could not get lock for \"$name\". Skipping node."); 447 if ($do_fork) { # Send the old config to the server before we die 517 448 socket (SOCK, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!"; 518 connect (SOCK, sockaddr_un ( "$config->{rundir}/$serversocket")) || die "connect: $!";519 if (ref $oldnode) { 520 $config->{domain}->{$domain}->{node}->{$name} = $oldnode;521 alarm (0); # Don't want to interrupt this.522 my @tmp = ($$, $domain, $name);449 connect (SOCK, sockaddr_un (munin_get($newconf, "rundir")."/$serversocket")) || die "connect: $!"; 450 alarm (0); # Don't want to interrupt this. 451 my @tmp = ($$, munin_get_node_loc($newconf), $name); 452 if (ref $oldconf) { 453 copy_node ($oldconf, $newconf); 523 454 nstore_fd \@tmp, \*SOCK || die "Could not nstore_fd: $!"; 524 nstore_fd \%{ $config->{domain}->{$domain}->{node}->{$name}}, \*SOCK;455 nstore_fd \%{munin_get_separated_node ($newconf)}, \*SOCK; 525 456 close SOCK; 457 } else { # Well, we'll have to give _something_ to the server, or it'll time out. 458 socket (SOCK, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!"; 459 connect (SOCK, sockaddr_un (munin_get($newconf, "rundir")."/$serversocket")) || die "connect: $!"; 460 nstore_fd \@tmp, \*SOCK || die "Could not nstore_fd: $!"; 461 nstore_fd ({}, \*SOCK); 526 462 } 527 463 exit 1; 528 } 529 else 530 { 464 } else { 531 465 return 0; 532 466 } … … 535 469 my $socket; 536 470 537 if ( &munin_get ($config, "local_address", undef, $domain, $node))471 if (munin_get ($newconf, "local_address")) 538 472 { 539 $socket = new IO::Socket::INET ('PeerAddr' => "$node->{address}:". 540 ($node->{port} || $config->{domain}->{$domain}->{port} || 541 $config->{port} || "4949"), 542 'LocalAddr' => &munin_get ($config, "local_address", undef, $domain, $node), 543 'Proto' => "tcp", "Timeout" => $timeout); 473 $socket = new IO::Socket::INET ('PeerAddr' => "$newconf->{address}:". 474 munin_get ($newconf, "port", "4949"), 475 'LocalAddr' => munin_get ($newconf, "local_address", undef), 476 'Proto' => "tcp", "Timeout" => munin_get($newconf, "timeout", 60)); 544 477 } else { 545 $socket = new IO::Socket::INET ('PeerAddr' => "$node->{address}:". 546 ($node->{port} || $config->{domain}->{$domain}->{port} || 547 $config->{port} || "4949"), 548 'Proto' => "tcp", "Timeout" => $timeout); 478 $socket = new IO::Socket::INET ('PeerAddr' => "$newconf->{address}:". 479 munin_get ($newconf, "port", "4949"), 480 'Proto' => "tcp", "Timeout" => munin_get($newconf, "timeout", 60)); 549 481 } 550 482 my $err = ($socket ? "" : $!); … … 554 486 alarm ($timeout); 555 487 556 my @tmp = ($$, $domain, $name);488 my @tmp = ($$, munin_get_node_loc ($newconf), $name); 557 489 558 490 if (!$socket) { 559 logger ("[ERROR] Could not connect to $name($n ode->{address}): $err - Attempting to use old configuration");491 logger ("[ERROR] Could not connect to $name($newconf->{address}): $err - Attempting to use old configuration"); 560 492 # If we can't reach the client. Using old Configuration. 561 if (ref $old node) {562 $config->{domain}->{$domain}->{node}->{$name} = $oldnode;493 if (ref $oldconf) { 494 copy_node ($oldconf, $newconf); 563 495 alarm (0); # Don't want to interrupt this. 564 496 socket (SOCK, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!"; 565 connect (SOCK, sockaddr_un ( "$config->{rundir}/$serversocket")) || die "connect: $!";497 connect (SOCK, sockaddr_un (munin_get($newconf, "rundir")."/$serversocket")) || die "connect: $!"; 566 498 nstore_fd \@tmp, \*SOCK || die "Could not nstore_fd: $!"; 567 nstore_fd \%{$config->{domain}->{$domain}->{node}->{$name}}, \*SOCK; 568 alarm ($timeout); 499 nstore_fd \%{munin_get_separated_node ($newconf)}, \*SOCK; 569 500 close SOCK; 570 } 571 else 572 { # Well, we'll have to give _something_ to the server, or it'll time out. 501 } else { # Well, we'll have to give _something_ to the server, or it'll time out. 573 502 socket (SOCK, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!"; 574 connect (SOCK, sockaddr_un ( "$config->{rundir}/$serversocket")) || die "connect: $!";503 connect (SOCK, sockaddr_un (munin_get($newconf, "rundir")."/$serversocket")) || die "connect: $!"; 575 504 nstore_fd \@tmp, \*SOCK || die "Could not nstore_fd: $!"; 576 505 nstore_fd ({}, \*SOCK); … … 578 507 } else { 579 508 my $ctx; 580 if (!&config_node($domain,$name,$node,$oldnode,$socket)) 581 { 582 $config->{domain}->{$domain}->{node}->{$name} = $oldnode; 509 if (!config_node($newconf,$oldconf,$socket)) { 510 copy_node ($oldconf, $newconf); 583 511 socket (SOCK, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!"; 584 connect (SOCK, sockaddr_un ( "$config->{rundir}/$serversocket")) || die "connect: $!";512 connect (SOCK, sockaddr_un (munin_get($newconf, "rundir")."/$serversocket")) || die "connect: $!"; 585 513 nstore_fd \@tmp, \*SOCK || die "Could not nstore_fd: $!"; 586 nstore_fd \%{ $config->{domain}->{$domain}->{node}->{$name}}, \*SOCK;514 nstore_fd \%{munin_get_separated_node ($newconf)}, \*SOCK; 587 515 close SOCK; 588 516 exit 1; 589 517 } 590 &fetch_node($ domain,$name,$node,$socket);518 &fetch_node($newconf,$oldconf,$socket); 591 519 # Net::SSLeay::free ($tls) if ($tls); # Shut down TLS 592 520 close $socket; 593 521 alarm (0); # Don't want to interrupt this. 594 522 socket (SOCK, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!"; 595 connect (SOCK, sockaddr_un ("$config->{rundir}/$serversocket")) || 596 die "connect: $!"; 523 connect (SOCK, sockaddr_un ("$config->{rundir}/$serversocket")) || die "connect: $!"; 597 524 nstore_fd \@tmp, \*SOCK || die "Could not nstore_fd: $!"; 598 nstore_fd \%{$config->{domain}->{$domain}->{node}->{$name}}, \*SOCK;525 nstore_fd \%{munin_get_separated_node ($newconf)}, \*SOCK; 599 526 alarm ($timeout); 600 527 close SOCK; … … 607 534 { 608 535 if (!$socket) { 609 logger ("[ERROR] Could not connect to $name($n ode->{address}): $err\nAttempting to use old configuration");536 logger ("[ERROR] Could not connect to $name($newconf->{address}): $err\nAttempting to use old configuration"); 610 537 # If we can't reach the client. Using old Configuration. 611 if (ref $old node) {612 $config->{domain}->{$domain}->{node}->{$name} = $oldnode;538 if (ref $oldconf) { 539 copy_node ($oldconf, $newconf); 613 540 } 614 541 } else { 615 next unless ( &config_node($domain,$name,$node,$oldnode,$socket));616 &fetch_node($domain,$name,$node,$socket);542 next unless (config_node($newconf,$oldconf,$socket)); 543 fetch_node($newconf,$oldconf,$socket); 617 544 # Net::SSLeay::free ($tls) if ($tls); # Shut down TLS 618 545 close $socket; … … 950 877 } 951 878 952 sub config_node { 953 my ($domain,$name,$node,$oldnode,$socket) = @_; 954 my $clientdomain = read_socket_single ($socket); 955 my $fetchdomain; 956 chomp($clientdomain) if $clientdomain; 957 if (!$clientdomain) { 958 logger("[WARNING] Got unknown reply from client \"$domain\" -> \"name\" skipping"); 959 return 0; 960 } 961 $clientdomain =~ s/\#.*(?:lrrd|munin) (?:client|node) at //; 962 if (exists $node->{'use_node_name'} and $node->{'use_node_name'} =~ /^\s*y(?:es)\s*$/i) 963 { 964 $fetchdomain = $clientdomain; 965 } 966 elsif (exists $node->{'use_default_name'} and $node->{'use_default_name'} =~ /^\s*y(?:es)\s*$/i) 967 { 968 $fetchdomain = $clientdomain; 969 } 970 else 971 { 972 $fetchdomain = $name; 973 } 974 my $nodeconf_time = Time::HiRes::time; 975 976 # TLS should only be attempted if explicitly enabled. The default value 977 # is therefore "disabled" (and not "auto" as before). 978 my $tls_requirement = &munin_get ($config,"tls","disabled",$domain, $name); 979 logger ("[DEBUG]: TLS set to \"$tls_requirement\".") if $DEBUG; 980 if ($tls_requirement ne "disabled") 981 { 982 my $key; 983 my $cert; 984 my $depth; 985 my $ca_cert; 986 my $tls_verify; 987 $key = $cert = munin_get ($config, "tls_pem", undef, $domain, $name); 988 $key = &munin_get ($config, "tls_private_key", "@@CONFDIR@@/munin.pem", $domain, $name) 989 unless defined $key; 990 $cert = &munin_get ($config, "tls_certificate", "@@CONFDIR@@/munin.pem", $domain, $name) 991 unless defined $cert; 992 $ca_cert = &munin_get ($config, "tls_ca_certificate", "@@CONFDIR@@/cacert.pem", $domain, $name) 993 unless defined $ca_cert; 994 $tls_verify=&munin_get ($config, "tls_verify_certificate", "no", $domain, $name); 995 $depth=&munin_get ($config, "tls_verify_depth", 5, $domain, $name); 996 997 if (!start_tls ($socket, $tls_requirement, $cert, $key, $ca_cert, $tls_verify, $depth)) 998 { 999 if ($tls_requirement eq "paranoid" or $tls_requirement eq "enabled") 1000 { 1001 logger ("[ERROR] Could not establish TLS connection to \"$domain :: $name\". Skipping."); 1002 exit 13; 1003 } 1004 } 1005 } 1006 1007 logger("[DEBUG] Configuring node: $name") if $DEBUG; 1008 my @services; 1009 eval { 1010 local $SIG{ALRM} = sub { die "Could not run list on $name ($fetchdomain): $!\n"}; 1011 alarm 5; # Should be enough to check the list 1012 write_socket_single ($socket, "list $fetchdomain\n"); 1013 my $list = read_socket_single ($socket); 1014 exit 1 unless defined $list; 1015 chomp $list; 1016 @services = split / /,$list; 1017 alarm 0; 1018 }; 1019 if ($@) { 1020 die unless ($@ =~ m/Could not run list/); 1021 logger ("Could not get list from $node->{address}: $!\nAttempting to use old configuration"); 1022 if (ref $oldnode) { 1023 $config->{domain}->{$domain}->{node}->{$name} = $oldnode; 1024 } 1025 @services = []; 1026 } 1027 1028 for my $service (@services) { 1029 my $servname = $service; 1030 my $fields = {}; 1031 $servname =~ s/\W/_/g; 1032 next if (exists ($node->{client}->{$servname}->{fetch_data}) and 1033 $node->{client}->{$servname}->{fetch_data} == 0); 1034 next if (exists ($node->{client}->{$servname}->{update}) and 1035 $node->{client}->{$servname}->{update} ne "yes"); 1036 next if (@limit_services and !grep (/^$servname$/, @limit_services)); 1037 my @graph_order = (exists $node->{client}->{$servname}->{graph_order} ? 1038 split (/\s+/, $node->{client}->{$servname}->{graph_order}) : ()); 1039 my $serviceconf_time = Time::HiRes::time; 1040 if ($servname ne $service) 1041 { 1042 $node->{client}->{$servname}->{realservname} = $service; 1043 } 1044 logger("[DEBUG] Configuring service: $name->$servname") if $DEBUG; 1045 write_socket_single ($socket, "config $service\n"); 1046 my @lines = read_socket($socket); 1047 return unless $socket; 1048 next unless (@lines); 1049 for (@lines) { 1050 if (/\# timeout/) { 1051 logger("Client reported timeout in configuration of $servname"); 1052 if ($oldnode->{client}->{$servname}) { 1053 logger("Attempting to use old configuration"); 1054 $config->{domain}->{$domain}->{node}->{$name}->{client}->{$servname} = $oldnode->{client}->{$servname}; 1055 } else { 1056 logger("Skipping configuration of $servname"); 1057 delete $node->{client}->{$servname}; 1058 } 1059 } 1060 elsif (/^(\w+)\.(\w+)\s+(.+)/) { 1061 my ($client,$type,$value) = ($1,$2,$3); 1062 $client = &sanitise_fieldname ($client, $fields); 1063 if (($type) and ($type eq "label")) { 1064 $value =~ s/\\/_/g; # Sanitise labels 1065 } 1066 $node->{client}->{$servname}->{$client.".".$type} = "$value"; 1067 logger ("[DEBUG] config: $name->$client.$type = $value") if $DEBUG; 1068 if (($type) and ($type eq "label")) { 1069 push (@graph_order,$client) 1070 unless grep (/^$client$/, @graph_order); 1071 } 1072 } elsif (/(^[^\s\#]+)\s+(.+)/) { 1073 my ($keyword) = $1; 1074 my ($value) = $2; 1075 $node->{client}->{$servname}->{$keyword} = $value; 1076 logger ("[DEBUG] Config: $keyword = $value") if $DEBUG; 1077 if ($keyword eq "graph_order") { 1078 @graph_order = split (/\s+/, $node->{client}->{$servname}->{graph_order}); 1079 } 1080 } 1081 } 1082 for my $subservice (keys %{$node->{client}->{$servname}}) { 1083 my ($client,$type) = split /\./,$subservice; 1084 my ($value) = $node->{client}->{$servname}->{$subservice}; 1085 if (($type) and ($type eq "label")) { 1086 my $fname = "$config->{dbdir}/$domain/$name-$servname-$client-" . 1087 lc substr (($node->{client}->{$servname}->{"$client.type"}||"GAUGE"),0,1). 1088 ".rrd"; 1089 if (! -f "$fname") { 1090 logger ("creating rrd-file for $servname->$subservice"); 1091 mkdir "$config->{dbdir}/$domain/",0777; 1092 my @args = ("$fname", 1093 "DS:42:".($node->{client}->{$servname}->{"$client.type"} || "GAUGE").":600:". 1094 (defined $node->{client}->{$servname}->{"$client.min"} ? 1095 $node->{client}->{$servname}->{"$client.min"} : 1096 "U") . ":" . ($node->{client}->{$servname}->{"$client.max"} || "U")); 1097 my $resolution = &munin_get ($config, "graph_data_size", "normal", $domain, $node, $servname); 1098 if ($resolution eq "normal") 1099 { 1100 push (@args, 879 sub config_node 880 { 881 my ($newconf,$oldconf,$socket) = @_; 882 my ($domain,$name,$node,$oldnode,$socket) = @_; 883 my $clientdomain = read_socket_single ($socket); 884 my $fetchdomain; 885 my $name = munin_get_node_name ($newconf); 886 chomp($clientdomain) if $clientdomain; 887 if (!$clientdomain) { 888 logger("[WARNING] Got unknown reply from client \"$name\" skipping"); 889 return 0; 890 } 891 $clientdomain =~ s/\#.*(?:lrrd|munin) (?:client|node) at //; 892 893 # Decide what to ask for 894 if (munin_get ($newconf, "use_node_name")) { 895 $fetchdomain = $clientdomain; 896 } elsif (munin_get ($newconf, "use_default_name")) { 897 $fetchdomain = $clientdomain; 898 } else { 899 $fetchdomain = $name; 900 } 901 902 # TLS should only be attempted if explicitly enabled. The default value 903 # is therefore "disabled" (and not "auto" as before). 904 my $tls_requirement = &munin_get ($config, "tls", "disabled"); 905 logger ("[DEBUG]: TLS set to \"$tls_requirement\".") if $DEBUG; 906 if ($tls_requirement ne "disabled") 907 { 908 my $key; 909 my $cert; 910 my $depth; 911 my $ca_cert; 912 my $tls_verify; 913 $key = $cert = munin_get ($config, "tls_pem"); 914 $key = &munin_get ($config, "tls_private_key", "@@CONFDIR@@/munin.pem") 915 unless defined $key; 916 $cert = &munin_get ($config, "tls_certificate", "@@CONFDIR@@/munin.pem") 917 unless defined $cert; 918 $ca_cert = &munin_get ($config, "tls_ca_certificate", "@@CONFDIR@@/cacert.pem") 919 unless defined $ca_cert; 920 $tls_verify=&munin_get ($config, "tls_verify_certificate", "no"); 921 $depth=&munin_get ($config, "tls_verify_depth", 5); 922 923 if (!start_tls ($socket, $tls_requirement, $cert, $key, $ca_cert, $tls_verify, $depth)) 924 { 925 if ($tls_requirement eq "paranoid" or $tls_requirement eq "enabled") 926 { 927 logger ("[ERROR]: Could not establish TLS connection to \"$name\". Skipping."); 928 exit 13; 929 } 930 } 931 } 932 933 logger("[DEBUG] Configuring node: $name") if $DEBUG; 934 my @services; 935 eval { 936 local $SIG{ALRM} = sub { die "Could not run list on $name ($fetchdomain): $!\n"}; 937 alarm 5; # Should be enough to check the list 938 write_socket_single ($socket, "list $fetchdomain\n"); 939 my $list = read_socket_single ($socket); 940 exit 1 unless defined $list; 941 chomp $list; 942 @services = split / /,$list; 943 alarm 0; 944 }; 945 if ($@) { 946 die unless ($@ =~ m/Could not run list/); 947 logger ("Error: Could not get list from $newconf->{address}: $!\nAttempting to use old configuration"); 948 if (ref $oldconf) { 949 copy_node ($oldconf, $newconf); 950 } 951 @services = []; 952 } 953 954 for my $service (@services) { 955 my $servname = $service; 956 my $fields = {}; 957 $servname =~ s/\W/_/g; 958 munin_set_var_loc ($newconf, [$servname, "realservname"], $service); 959 logger("[DEBUG] Inspecting possible service: $servname") if $DEBUG; 960 next if (!munin_get_bool ($newconf->{$servname}, "update", "true")); 961 next if (!munin_get_bool ($newconf->{$servname}, "fetch_data", "true")); 962 next if (@limit_services and !grep (/^$servname$/, @limit_services)); 963 964 my @graph_order = split (/\s+/, munin_get ($newconf->{$service}, "graph_order", "")); 965 my $serviceconf_time = Time::HiRes::time; 966 logger("[DEBUG] Configuring service: $servname") if $DEBUG; 967 write_socket_single ($socket, "config $service\n"); 968 my @lines = read_socket($socket); 969 return unless $socket; 970 next unless (@lines); 971 for (@lines) { 972 if (/\# timeout/) { 973 logger("Client reported timeout in configuration of $servname"); 974 if ($oldconf->{$servname}) { 975 logger("Attempting to use old configuration"); 976 copy_node ($newconf->{$servname}, $oldconf->{$servname}); 977 } else { 978 logger("Skipping configuration of $servname"); 979 delete $newconf->{$servname}; 980 } 981 } elsif (/^(\w+)\.(\w+)\s+(.+)/) { 982 my ($client,$type,$value) = ($1,$2,$3); 983 $client = &sanitise_fieldname ($client, $fields); 984 if (($type) and ($type eq "label")) { 985 $value =~ s/\\/_/g; # Sanitise labels 986 push (@graph_order,$client) unless grep (/^$client$/, @graph_order); 987 } 988 munin_set_var_loc ($newconf, [$servname, $client, $type], "$value"); 989 logger ("config: $servname->$client.$type = $value") if $DEBUG; 990 } elsif (/(^[^\s\#]+)\s+(.+)/) { 991 my ($keyword) = $1; 992 my ($value) = $2; 993 munin_set_var_loc ($newconf, [$servname, $keyword], "$value"); 994 logger ("Config: $servname->$keyword = $value") if $DEBUG; 995 if ($keyword eq "graph_order") { 996 @graph_order = split (/\s+/, $value); 997 } 998 } 999 } 1000 for my $field (keys %{$newconf->{$servname}}) { 1001 # Skip anything that isn't a field 1002 next if $field =~ /^#%#/; 1003 next unless (ref ($newconf->{$servname}->{$field}) eq "HASH" and 1004 defined ($newconf->{$servname}->{$field}->{"label"})); 1005 1006 my $fhash = $newconf->{$servname}->{$field}; 1007 1008 # Check if file exists 1009 my $fname = munin_get_filename ($fhash); 1010 (my $dirname = $fname) =~ s/\/[^\/]+$//; 1011 1012 if (! -f "$fname") { 1013 logger ("creating rrd-file for $servname->$field: \"$fname\""); 1014 munin_mkdir_p ($dirname, 0777); 1015 my @args = ("$fname", 1016 "DS:42:".munin_get($fhash, "type", "GAUGE").":600:". 1017 munin_get($fhash, "min", "U") . ":" . munin_get($fhash, "max", "U")); 1018 1019 my $resolution = &munin_get ($fhash, "graph_data_size", "normal"); 1020 if ($resolution eq "normal") { 1021 push (@args, 1101 1022 "RRA:AVERAGE:0.5:1:576", # resolution 5 minutes 1102 1023 "RRA:MIN:0.5:1:576", … … 1111 1032 "RRA:MIN:0.5:288:450", 1112 1033 "RRA:MAX:0.5:288:450"); 1113 } 1114 elsif ($resolution eq "huge") 1115 { 1116 push (@args, "RRA:AVERAGE:0.5:1:115200"); # resolution 5 minutes, for 400 days 1117 push (@args, "RRA:MIN:0.5:1:115200"); # Three times? ARGH! 1118 push (@args, "RRA:MAX:0.5:1:115200"); # Three times? ARGH! 1119 } 1120 RRDs::create @args; 1121 if (my $ERROR = RRDs::error) { 1122 logger ("[ERROR] In RRD: unable to create \"$fname\": $ERROR"); 1123 } 1124 } 1125 } 1126 $node->{client}->{$servname}->{graph_order} = join(' ',@graph_order); 1127 } 1128 $serviceconf_time = sprintf ("%.2f",(Time::HiRes::time - $serviceconf_time)); 1129 print STATS "CS|$domain|$name|$servname|$serviceconf_time\n"; 1130 logger ("Configured service: $name -> $servname ($serviceconf_time sec)"); 1131 } 1132 $nodeconf_time = sprintf ("%.2f",(Time::HiRes::time - $nodeconf_time)); 1133 print STATS "CN|$domain|$name|$nodeconf_time\n"; 1034 } elsif ($resolution eq "huge") { 1035 push (@args, "RRA:AVERAGE:0.5:1:115200"); # resolution 5 minutes, for 400 days 1036 push (@args, "RRA:MIN:0.5:1:115200"); # Three times? ARGH! 1037 push (@args, "RRA:MAX:0.5:1:115200"); # Three times? ARGH! 1038 } 1039 RRDs::create @args; 1040 if (my $ERROR = RRDs::error) { 1041 logger ("[ERROR] Unable to create \"$fname\": $ERROR"); 1042 } 1043 } 1044 } 1045 munin_set_var_loc ($newconf, [$servname, "graph_order"], join(' ',@graph_order)); 1046 } 1134 1047 return 0 unless $socket; 1135 logger("Configured node: $name ($nodeconf_time sec)");1136 return 1; 1137 } 1138 1139 sub fetch_node{1140 my ($ domain,$name,$node,$socket) = @_;1141 my $n odefetch_time = Time::HiRes::time;1048 return 1; 1049 } 1050 1051 sub fetch_node 1052 { 1053 my ($newconf,$oldconf,$socket) = @_; 1054 my $name = munin_get_node_name ($newconf); 1142 1055 logger("[DEBUG] Fetching node: $name") if $DEBUG; 1143 for my $service (keys %{$n ode->{client}}) {1144 my $servicefetch_time = Time::HiRes::time;1145 logger("[DEBUG] Fetching service: $name->$service") if $DEBUG;1146 next if (exists ($node->{client}->{$service}->{fetch_data}) and1147 $node->{client}->{$service}->{fetch_data} == 0);1148 next if (exists ($node->{client}->{$service}->{update}) and1149 $node->{client}->{$service}->{update} ne "yes");1056 for my $service (keys %{$newconf}) { 1057 next if ref ($newconf->{$service}) ne "HASH"; 1058 next if $service =~ /^#%#/; 1059 logger("[DEBUG] Fetching service: $service") if $DEBUG; 1060 next unless exists ($newconf->{$service}->{"graph_title"}); 1061 next unless (munin_get_bool ($newconf->{$service}, "update", "true")); 1062 next unless (munin_get_bool ($newconf->{$service}, "fetch_data", "true")); 1150 1063 next if (@limit_services and !grep (/^$service$/, @limit_services)); 1151 my $realservname = ( $node->{client}->{$service}->{realservname} || 1152 $service ); 1153 delete $node->{client}->{$service}->{realservname} 1154 if exists $node->{client}->{$service}->{realservname}; 1064 1065 # Read (and get rid of) realservname 1066 my $realservname = ( $newconf->{$service}->{"realservname"} || $service ); 1067 delete $newconf->{$service}->{"realservname"} 1068 if exists $newconf->{$service}->{"realservname"}; 1069 1155 1070 write_socket_single ($socket, "fetch $realservname\n"); 1156 1071 my @lines = &read_socket($socket); … … 1180 1095 1181 1096 $key = &sanitise_fieldname ($key, $fields); 1182 if (exists $node->{client}->{$service}->{$key.".label"}) { 1183 my $fname = 1184 "$config->{dbdir}/$domain/$name-$service-$key-". 1185 lc 1186 substr(($node->{client}->{$service}->{$key.".type"}|| 1187 "GAUGE"),0,1).".rrd"; 1097 if (exists $newconf->{$service}->{$key}->{"label"}) { 1098 my $fname = munin_get_filename ($newconf->{$service}->{$key}); 1188 1099 1189 1100 logger("[DEBUG] Updating $fname with $value") if $DEBUG; … … 1193 1104 } 1194 1105 } else { 1195 logger ("[ERROR] Unable to update $ domain -> $name -> $service -> $key: No such field (no \"label\" field defined when running plugin with \"config\").");1106 logger ("[ERROR] Unable to update $name -> $service -> $key: No such field (no \"label\" field defined when running plugin with \"config\")."); 1196 1107 } 1197 1108 } elsif (/(\w+)\.extinfo\s+(.+)/) { 1198 $config->{domain}->{$domain}->{node}->{$name}->{client}->{$service}->{$1.".extinfo"} = $2;1109 munin_set_var_loc ($newconf, [$service, $service, $1, "extinfo"], $2); 1199 1110 } 1200 1111 } 1201 $servicefetch_time = sprintf ("%.2f",(Time::HiRes::time - $servicefetch_time)); 1202 logger ("Fetched service: $name -> $service ($servicefetch_time sec)"); 1203 print STATS "FS|$domain|$name|$service|$servicefetch_time\n"; 1204 } 1205 $nodefetch_time = sprintf ("%.2f",(Time::HiRes::time - $nodefetch_time)); 1206 logger ("Fetched node: $name ($nodefetch_time sec)"); 1207 print STATS "FN|$domain|$name|$nodefetch_time\n"; 1208 1112 } 1209 1113 return 1; 1210 }1211 1212 sub use_old_config1213 {1214 my $domain = shift;1215 my $name = shift;1216 my $oldnode = shift;1217 1218 $config->{domain}->{$domain}->{node}->{$name} = $oldnode;1219 logger ("Attempting to use old configuration for $domain -> $name.");1220 1114 } 1221 1115 … … 1283 1177 } 1284 1178 1179 sub copy_node 1180 { 1181 my $from = shift; 1182 my $to = shift; 1183 1184 if (ref ($from) eq "HASH") { 1185 foreach my $key (keys %$from) { 1186 next if $key =~ /^#%#/; 1187 $to->{$key} = $from->{$key}; 1188 } 1189 } else { 1190 $to = $from; 1191 } 1192 return $to; 1193 } 1194 1285 1195 1; 1286 1196 … … 1372 1282 =head1 COPYRIGHT 1373 1283 1374 Copyright (C)2002-2006 Audun Ytterdal, Jimmy Olsen, and Tore Anderson / Linpro AS.1284 Copyright © 2002-2006 Audun Ytterdal, Jimmy Olsen, and Tore Anderson / Linpro AS. 1375 1285 1376 1286 This is free software; see the source for copying conditions. There is people/jo/multilevel-groups-3/server/style.css
r860 r1502 38 38 } 39 39 40 .service { 41 font-size: x-small; 42 font-weight: bold; 43 } 44 40 45 .center { 41 46 text-align: center;
