%PDF- %PDF-
Direktori : /proc/self/root/usr/share/perl5/vendor_perl/Munin/Node/ |
Current File : //proc/self/root/usr/share/perl5/vendor_perl/Munin/Node/Config.pm |
package Munin::Node::Config; use base qw(Munin::Common::Config); # $Id$ use strict; use warnings; use English qw(-no_match_vars); use Carp; use Munin::Node::OS; use Munin::Common::Defaults; my %booleans = map {$_ => 1} qw( paranoia tls_verify_certificate ); { my $instance; sub instance { my ($class) = @_; $instance ||= bless { config_file => "$Munin::Common::Defaults::MUNIN_CONFDIR/munin-node.conf", }, $class; return $instance; } } sub reinitialize { my ($self, $attrs) = @_; $attrs ||= {}; my $new_self = bless $attrs, ref $self; %$self = %$new_self; } sub parse_config_from_file { my $self = shift; my ($file) = @_; # Check permissions of configuration unless (Munin::Node::OS->check_perms_if_paranoid($file)) { croak "Fatal error. Bailing out."; } return $self->SUPER::parse_config_from_file(@_); } sub parse_config { my ($self, $IO_HANDLE) = @_; while (my $line = <$IO_HANDLE>) { my @var = $self->_parse_line($line); next unless @var; if ($var[0] eq 'ignore_file') { push @{$self->{ignores}}, $var[1]; } elsif ($var[0] eq 'unhandled') { next if defined $self->{sconf}{$var[1]}; $self->{sconf}{$var[1]} = $var[2]; } else { $self->{$var[0]} = $var[1]; } } } sub _parse_line { my ($self, $line) = @_; $self->_strip_comment($line); $self->_trim($line); return unless length $line; $line =~ m{\A (\w+) \s+ (.+) \z}xms or croak "Line is not well formed ($line)"; my ($var_name, $var_value) = ($1, $2); return if $self->_handled_by_net_server($var_name); my %config_variables = map { $_ => 1 } qw( global_timeout ignore_file paranoia spooldir timeout tls tls_ca_certificate tls_certificate tls_private_key tls_verify_certificate tls_verify_depth tls_match ); if ($config_variables{$var_name}) { return ($var_name => $booleans{$var_name} ? $self->_parse_bool($var_value) : $var_value); } elsif ($var_name eq 'host_name' || $var_name eq 'hostname') { return (fqdn => $var_value); } elsif ($var_name eq 'default_plugin_user' || $var_name eq 'default_client_user') { my $uid = Munin::Node::OS->get_uid($var_value); croak "Default user does not exist ($var_value)" unless defined $uid; return (defuser => $uid); } elsif ($var_name eq 'default_plugin_group' || $var_name eq 'default_client_group') { my $gid = Munin::Node::OS->get_gid($var_value); croak "Default group does not exist ($var_value)" unless defined $gid; return (defgroup => $gid); } else { return (unhandled => ($var_name => $var_value)); } } { my %handled_by_net_server = map { $_ => 1 } qw( allow deny cidr_allow cidr_deny reverse_lookups ); sub _handled_by_net_server { my ($self, $var_name) = @_; return $handled_by_net_server{$var_name}; } } sub process_plugin_configuration_files { my ($self) = @_; opendir my $DIR, $self->{sconfdir} or croak "Could not open plugin configuration directory: $!"; $self->{sconf} ||= {}; my @ignores = $self->{ignores} ? @{$self->{ignores}} : (); push @ignores, '^\.'; # Hidden files FILE: for my $file ( grep { -f "$self->{sconfdir}/$_" } sort( readdir($DIR) ) ) { # Untaint file next if $file !~ m/^([-\w.:]+)$/; # Skip if any weird chars $file = $1; for my $regex (@ignores) { next FILE if $file =~ /$regex/; } $self->parse_plugin_config_file("$self->{sconfdir}/$file"); } closedir $DIR or carp "Failed to close directory '$self->{sconfdir}': $!"; } sub parse_plugin_config_file { # Parse configuration files. Any errors should cause processing # of the current file to abort with error message, but should not # be fatal. my ($self, $file) = @_; # check perms on a file also checks the directory permissions if (!Munin::Node::OS->check_perms_if_paranoid($file)) { print STDERR "Plugin configuration $file has unsafe permissions, skipping\n"; return; } my $CONF; unless (open $CONF, '<', $file) { my $err = $!; carp "Could not open file '$file' for reading ($err), skipping.\n"; return; } print STDERR "# Processing plugin configuration from $file\n" if $self->{DEBUG}; eval { $self->parse_plugin_config($CONF) }; if ($EVAL_ERROR) { carp sprintf( '%s at %s line %d. Skipping the rest of the file', $EVAL_ERROR, $file, $INPUT_LINE_NUMBER, ); } close $CONF or carp "Failed to close '$file': $!"; } sub parse_plugin_config { my ($self, $IO_HANDLE) = @_; my $service; my $sconf = $self->{sconf}; while (my $line = <$IO_HANDLE>) { $self->_strip_comment($line); $self->_trim($line); next unless $line; if ($line =~ m{\A \s* \[ ([^\]]+) \] \s* \z}xms) { $service = $1; } else { croak "Parse error: Clutter before section start." unless $service; my @var = $self->_parse_plugin_line($line); next unless @var; if ($var[0] eq 'env') { my ($key, $value) = %{$var[1]}; $sconf->{$service}{$var[0]}{$key} = $value; } else { $sconf->{$service}{$var[0]} = $var[1]; } } } } sub _parse_plugin_line { my ($self, $line) = @_; $line =~ m{\A \s* env \s+ ([^=\s]+) \s* = \s* (.+) \z}xms and croak "Deprecated format: 'env $1=$2' should be rewritten to 'env.$1 $2'"; $line =~ m{\A \s* ([\w\.]+) \s+ (.+) \z}xms or croak "Line is not well formed ($line)"; my ($var_name, $var_value) = ($1, $2); if ($var_name eq 'user') { # Evaluation of user name is lazy, so that configuration for # plugins that are not used does not cause errors. return (user => $var_value); } elsif ($var_name eq 'group') { # Evaluation of group names is lazy too. return (group => [split /[\s,]+/, $var_value]); } elsif ($var_name eq 'command') { return (command => [split /\s+/, $var_value]); } elsif ($var_name eq 'host_name') { return (host_name => $var_value); } elsif ($var_name eq 'timeout') { return (timeout => $var_value); } elsif ($var_name eq 'update_rate') { return (update_rate => $var_value); } elsif (index($var_name, 'env.') == 0) { return (env => { substr($var_name, length 'env.') => $var_value}); } else { croak "Failed to parse line: $line. " . "Should it have been 'env.$var_name $var_value'?"; } } sub apply_wildcards { my ($self, @services) = @_; my $wildcard_regex; # Need to sort the keys in descending order so that more specific # wildcards take precedence. for my $wildservice (grep { /\*$/ || /^\*/ } reverse sort keys %{$self->{sconf}}) { if ($wildservice =~ /\*$/) { $wildcard_regex = qr{^} . substr($wildservice, 0, -1); } else { $wildcard_regex = substr($wildservice, 1) . qr{$}; } for my $service (@services) { next unless $service =~ /$wildcard_regex/; $self->_apply_wildcard_to_service($self->{sconf}{$wildservice}, $service); } delete $self->{sconf}{$wildservice}; } } sub _apply_wildcard_to_service { my ($self, $wildservice, $service) = @_; my $sconf = $self->{sconf}{$service} || {}; # Environment if (exists $wildservice->{'env'}) { for my $key (keys %{$wildservice->{'env'}}) { next if exists $sconf->{'env'} && exists $sconf->{'env'}{$key}; $sconf->{'env'}{$key} = $wildservice->{'env'}{$key}; } } for my $key (keys %{$wildservice}) { next if $key eq 'env'; # Already handled next if exists $sconf->{$key}; $sconf->{$key} = $wildservice->{$key}; } $self->{sconf}{$service} = $sconf; return; } 1; __END__ =head1 NAME Munin::Node::Config - Singleton node configuration container. Reads configuration files. =head1 SYNOPSIS $config = Munin::Node::Config->instance(); $config->parse_config_from_file('/etc/munin/munin-node.conf'); print $config->{fqdn}, "\n"; =head1 METHODS =over =item B<instance> $config = Munin::Node::Config->instance(); Returns the singleton instance of this class. =item B<reinitialize> $config->reinitialize(); Deletes all configuration variables $config->reinitialize(\%variables); Deletes all configuration variables and reinitializes the object with values from \%variables. =item B<parse_config_from_file> $config->parse_config_from_file($filename); Parses the munin node configuration from a file. Dies if the file fails the paranoia checks. =item B<parse_config> $config->parse_config($io_handle); Parses the munin node configuration from a filehandle. =item B<process_plugin_configuration_files> $config->process_plugin_configuration_files(); Parses all unignored files in the plugin configuration folder. =item B<parse_plugin_config_file> $config->parse_plugin_config_file($file); Parses the plugin configuration in $file. =item B<parse_plugin_config> $config->parse_plugin_config($io_handle); Parses the plugin configuration from an L<IO::Handle>. =item B<apply_wildcards> $config->apply_wildcards(); Applies the contents of any wildcard plugin configuration sections to matching plugins. See L<http://munin-monitoring.org/wiki/Priority_and_inheritance> =back =cut # vim: sw=4 : ts=4 : et