fed6898244cc141464b4daf54bacb9dedc3607f1
[pxelator] / lib / PXElator / syslogd.pm
1 package syslogd;
2
3 use warnings;
4 use strict;
5
6 use IO::Socket;
7 use Data::Dump qw/dump/;
8 use CouchDB;
9 use File::Slurp;
10
11 use server;
12
13 our $port = 514;
14 our $MAXLEN = 1524;
15
16 sub message {
17         my $sock = shift;
18
19         my $buf;
20         $sock->recv($buf, $MAXLEN);
21
22         next unless $buf;
23
24         my ($port, $ipaddr) = sockaddr_in($sock->peername);
25         my $log = {
26                 ip => join('.', unpack('C4',$ipaddr)),
27                 buf => $buf,
28         };
29
30         if ( $buf =~ s/<(\d+)>// ) {
31                 $log->{pri}    = $1 % 8;
32                 $log->{facility} = ( $1 - $log->{pri} ) / 8;
33         
34                 $log->{timestamp} = $1 if $buf =~ s/^(\w\w\w\s+\d+\s+\d\d:\d\d:\d\d)\s*//;      # strip timestamp which some syslog servers insert here
35
36                 if ( $buf =~ s/^([^:]+)\s*:\s*// ) {
37                         my $tag = $1;
38                         if ( $tag =~ m{^(\S+)\s(\S+)} ) {
39                                 $log->{tag} = $2;
40                                 $log->{hostname} = $1;
41                         } else {
42                                 $log->{tag} = $tag;
43                         }
44
45                         if ( $log->{tag} =~ s/\[(\d+)\]$// ) {
46                                 $log->{pid} = $1;
47                         } elsif ( $buf =~ s/^(\d+):\s*// ) {
48                                 $log->{pid} = $1;
49                         }
50                 }
51
52                 $log->{tag} =~ s{^/.+/([^/]+)$}{$1};
53
54                 if ( $log->{tag} =~ m{CRON}i && $buf =~ m{^\((\w+)\) (.+) \((.+)\)$} ) {
55                         $log->{cron} = {
56                                 user => $1,
57                                 command => $2,
58                                 argument => $3,
59                         };
60                 }
61
62                 if ( $buf =~ m{(init|error|mount|smart|usb|fs)}i ) {
63                         $log->{category} = $1;
64                 }
65
66                 $log->{message} = $buf;
67         }
68
69         warn "log ",dump( $log );
70         CouchDB::audit( $log->{tag}, $log );
71 }
72
73 sub start {
74
75         my $sock = IO::Socket::INET->new(
76                 LocalPort => $port,
77                 Proto => 'udp',
78                 ReuseAddr => 1,
79         ) || die "can't listen to $port: $!";
80
81         CouchDB::audit('start', { port => $port });
82
83         while(1) {
84                 message($sock);
85                 server->refresh;
86         }
87 }
88
89 sub install_local {
90         warn "# redirect local syslog to pxelator";
91         my $rsyslog = '/etc/rsyslog.d/pxelator.conf';
92         write_file $rsyslog, "*.*\t\@$server::ip\n";
93         system "( /etc/init.d/rsyslog stop ; sleep 2 ; /etc/init.d/rsyslog start ; rm $rsyslog ) &";
94 }
95
96 1;