File Coverage

blib/lib/Munin/Node/Client.pm
Criterion Covered Total %
statement 12 98 12.2
branch 0 28 0.0
condition n/a
subroutine 4 18 22.2
pod 10 14 71.4
total 26 158 16.4


line stmt bran cond sub pod time code
1             package Munin::Node::Client;
2              
3             # Name: HealthMatrix
4             ## Author: Sebastian Stellingwerff
5             ## Copyright: 2008
6             ## See COPYRIGHT section in the manpage for usage and distribution rights.
7             ## perltidy -pt=1 -sbt=1 -bt=1 -ce -vt=2 -vtc=0 -nsak="if while for elsif foreach unless"
8             ## vim: set ts=4 et
9              
10             =head1 NAME
11              
12             Munin::Node::Client - Client module for munin nodes.
13              
14             =head1 SYNOPSIS
15              
16             use Munin::Node::Client;
17              
18             my $node = Munin::Node::Client->connect(Host => '127.0.0.1',
19             Port => '4949');
20              
21             my $version = $node->version;
22             my @hostnames = $node->nodes; # get the hostnames
23             my @items = $node->list(); # or $node->list($hostnames[0]);
24              
25             $node->quit;
26              
27             =head1 DESCRIPTION
28              
29             Munin::Node::Client is a client module for munin nodes. This helps simple scripts to talk to munin nodes.
30              
31             =cut
32              
33 1     1   24802 use 5.8.0;
  1         5  
  1         50  
34 1     1   6 use strict;
  1         1  
  1         37  
35 1     1   5 use warnings;
  1         8  
  1         44  
36 1     1   1256 use IO::Socket::INET;
  1         29026  
  1         8  
37              
38             require Exporter;
39              
40             our @ISA = qw(Exporter);
41              
42             our $VERSION = '0.01';
43              
44             =head1 FUNCTIONS
45              
46             Here all functions are specified, for all functions that return in list context (such as with hashes), the scalar context is undocumented and might get a function in the future.
47              
48             =over
49              
50             =item connect(host => $hostname, port => $port)
51              
52             Connects to a node and returns an Munin::Node::Client object.
53             Currently only support plain connections, ssl and tls are planned.
54             Returns undef if connection fails (and $! probably contains something useful).
55             Returns false if connection is not a munin connection.
56             my $node = Munin::Node::Client->connect(Host => '127.0.0.1:4949');
57             =cut
58             sub connect {
59 0     0 1   my ($class, %settings) = @_;
60 0 0         $settings{port} = 4949 unless($settings{port});
61              
62 0 0         my $sock = IO::Socket::INET->new(PeerAddr => $settings{host},
63             PeerPort => $settings{port},
64             Proto => 'tcp') or return undef;
65              
66 0           my $intro = <$sock>;
67 0           my $hostname;
68 0 0         if($intro =~ /munin node at (.+)$/) {
69 0           $hostname = $1
70             } else {
71             # this is not a munin connection??
72 0           close($sock);
73 0           return 0;
74             }
75              
76 0           my %obj = ( settings => \%settings,
77             sock => $sock,
78             intro => $intro,
79             hostname => $hostname);
80              
81 0           bless \%obj;
82             }
83              
84             =item error();
85              
86             Returns the last error message.
87             print $node->error();
88             =cut
89             sub error {
90 0     0 1   my ($self, $data) = @_;
91 0 0         if(defined($data)) {
92 0           $self->{error} = $data;
93 0           return undef;
94             } else {
95 0           return $self->{error};
96             }
97             }
98              
99             sub print {
100 0     0 0   my ($self, @data) = @_;
101 0           my $sock = $self->{sock};
102 0 0         my $sep = $, ? $, : '';
103 0           my $line = join($sep, @data);
104 0           print $sock "$line\r\n";
105             }
106              
107             sub read {
108 0     0 0   my ($self, @data) = @_;
109 0           my $sock = $self->{sock};
110 0           my $data = <$sock>;
111 0           return $data;
112             }
113              
114             sub read_list {
115 0     0 0   my ($self) = @_;
116 0           my @data;
117 0           my $line = $self->read;
118 0           while($line !~ /^\.$/) {
119 0           chomp $line;
120 0           push(@data, $line);
121 0           $line = $self->read;
122             }
123 0 0         $self->error('read_list: No data') if($#data < 0);
124 0           return @data;
125             }
126              
127             =item version()
128              
129             Returns the node's version
130             my $version = $node->version();
131             =cut
132             sub version {
133 0     0 1   my ($self) = @_;
134 0           $self->print('version');
135 0           my $line = $self->read();
136 0           my ($version) = $line =~ /version: (.+)$/;
137 0           return $version;
138             }
139              
140             =item nodes()
141              
142             Returns the available hostnames on this 'node' in a list.
143             my @hosts = $node->nodes();
144             print "$_\n" for(@plugins);
145             =cut
146             sub nodes {
147 0     0 1   my ($self) = @_;
148 0           $self->print('nodes');
149 0           my @hosts = $self->read_list;
150 0 0         return @hosts if(wantarray);
151             }
152              
153             =item hosts()
154              
155             =cut
156             sub hosts {
157 0     0 1   my ($self) = @_;
158 0           return $self->nodes();
159             }
160              
161             =item list($node)
162              
163             Returns the list of plugins for a host (or default host when left out)
164             my @plugins = $node->list($host);
165             print "$_\n" for(@plugins);
166             =cut
167             sub list {
168 0     0 1   my ($self, $node) = @_;
169 0 0         $node = $node ? $node : $self->{hostname};
170 0           $self->print("list $node");
171 0           my $line = $self->read;
172 0           my @items = split(/\s/, $line);
173 0 0         return @items if(wantarray);
174             }
175              
176             =item config($plugin)
177              
178             Returns the configuration settings of a plugin as a hash with hasrefs
179             my %config = config($plugin);
180             my $globals = $config{globals};
181             my $datasrc = $config{datasource};
182             print $globals{graph_title};
183             print $datasrc{system}->{label};
184             =cut
185             sub config {
186 0     0 1   my ($self, $item) = @_;
187              
188 0           $self->print("config $item");
189 0           my (%global, %datasrc);
190 0           for($self->read_list) {
191 0 0         if($_ =~ /^([A-Za-z0-9_-]+)\s+(.+)$/) {
    0          
192 0           $global{$1} = $2;
193             } elsif($_ =~ /^([A-Za-z0-9_-]+)\.([A-Za-z]+)\s+(.+)$/) {
194 0           $datasrc{$1}->{$2} = $3;
195             }
196             }
197 0 0         if(wantarray) {
198 0           return ( global => \%global, datasource => \%datasrc );
199             } else {
200             # return item object;
201             }
202            
203             }
204              
205             =item fetch($plugin)
206              
207             Returns the values of a plugin as a hash
208             my %value = fetch($plugin);
209             print $value{system};
210             =cut
211             sub fetch {
212 0     0 1   my ($self, $item) = @_;
213            
214 0           $self->print("fetch $item");
215 0           my %values;
216 0           for($self->read_list) {
217 0 0         if($_ =~ /^([A-Za-z0-9_-]+)\.value\s+(.+)$/) {
218 0           $values{$1} = $2;
219             }
220             }
221              
222 0 0         return %values if(wantarray);
223             }
224              
225             sub plugin {
226 0     0 0   my ($self, $plugin) = @_;
227 0           my %config = $self->config($plugin);
228 0           my %value = $self->fetch($plugin);
229 0           my $datasource = $config{datasource};
230 0           my $globals = $config{globals};
231            
232 0           my %item;
233 0           for (keys(%{ $datasource })) {
  0            
234 0           my $cfg = $datasource->{$_};
235 0           $item{$_} = $cfg;
236 0           $item{$_}->{value} = $value{$_};
237             }
238            
239             return ( )
240 0           }
241              
242             =item quit()
243              
244             quits/disconnects the connection to the node.
245             $node->quit();
246             =cut
247             sub quit {
248 0     0 1   my ($self) = @_;
249 0           $self->print('quit');
250 0           my $last = $self->read();
251 0           close($self->{sock});
252 0           return $last
253             }
254              
255             =item disconnect()
256              
257             alias for quit
258             =cut
259             sub disconnect {
260 0     0 1   my ($self) = @_;
261 0           $self->quit();
262             }
263              
264             1;
265             __END__