f38cb5f6b66c68b211643cd34c5b84675d805636
[freeside.git] / FS / FS / Cron / check.pm
1 package FS::Cron::check;
2
3 use strict;
4 use vars qw( @ISA @EXPORT_OK $DEBUG $FS_RUN $error_msg
5              $SELFSERVICE_USER $SELFSERVICE_MACHINES @SELFSERVICE_MACHINES
6            );
7 use Exporter;
8 use LWP::UserAgent;
9 use Email::Send;
10 use FS::Conf;
11 use FS::Record qw(qsearch);
12 use FS::cust_pay_pending;
13
14 @ISA = qw( Exporter );
15 @EXPORT_OK = qw(
16   check_queued check_selfservice check_apache check_bop_failures
17   check_sg check_sgng
18   alert error_msg
19 );
20
21 $DEBUG = 0;
22
23 $FS_RUN = '/var/run';
24
25 sub check_queued {
26   _check_fsproc('queued');
27 }
28
29 $SELFSERVICE_USER = '%%%SELFSERVICE_USER%%%';
30
31 $SELFSERVICE_MACHINES = '%%%SELFSERVICE_MACHINES%%%'; #substituted by Makefile
32 $SELFSERVICE_MACHINES =~ s/^\s+//;
33 $SELFSERVICE_MACHINES =~ s/\s+$//;
34 @SELFSERVICE_MACHINES = split(/\s+/, $SELFSERVICE_MACHINES);
35 @SELFSERVICE_MACHINES = ()
36   if scalar(@SELFSERVICE_MACHINES) == 1
37   && $SELFSERVICE_MACHINES[0] eq '%%%'.'SELFSERVICE_MACHINES'.'%%%';
38
39 sub check_selfservice {
40   foreach my $machine ( @SELFSERVICE_MACHINES ) {
41     unless ( _check_fsproc("selfservice-server.$SELFSERVICE_USER.$machine") ) {
42       $error_msg = "Self-service daemon not running for $machine";
43       return 0;
44     }
45   }
46   return 1;
47 }
48
49 sub check_sg {
50   my $conf = new FS::Conf;
51   #different trigger if they ever stop using multicustomer_hack ?
52   return 1 unless $conf->exists('sg-multicustomer_hack');
53
54   my $ua = new LWP::UserAgent;
55   $ua->agent("FreesideCronCheck/0.1 " . $ua->agent);
56
57   my $USER = $conf->config('sg-ping_username');
58   my $PASS = $conf->config('sg-ping_password');
59   my $req = new HTTP::Request GET=>"https://$USER:$PASS\@localhost/sg/ping.cgi";
60   my $res = $ua->request($req);
61
62   return 1 if $res->is_success
63            && $res->content =~ /OK/
64            && $res->content !~ /error/i; #doh, the error message includes "OK"
65
66   $error_msg = $res->is_success ? $res->content : $res->status_line;
67   return 0;
68
69 }
70
71 sub check_sgng {
72   my $conf = new FS::Conf;
73   #different trigger if they ever stop using multicustomer_hack ?
74   return 1 unless $conf->exists('sg-multicustomer_hack');
75
76   eval 'use RPC::XML; use RPC::XML::Client;';
77   if ($@) { $error_msg = $@; return 0; };
78
79   my $cli = RPC::XML::Client->new('https://localhost/selfservice/xmlrpc.cgi');
80   my $resp = $cli->send_request('FS.SelfService.XMLRPC.ping');
81
82   return 1 if ref($resp)
83            && ! $resp->is_fault
84            && ref($resp->value)
85            && $resp->value->{'pong'} == 1;
86
87   #hua
88   $error_msg = ref($resp)
89                  ? ( $resp->is_fault
90                        ? $resp->string
91                        : ( ref($resp->value) ? $resp->value->{'error'}
92                                              : $resp->value
93                          )
94                  )
95                  : $resp;
96   return 0;
97 }
98
99 sub _check_fsproc {
100   my $arg = shift;
101   _check_pidfile( "freeside-$arg.pid" );
102 }
103
104 sub _check_pidfile {
105   my $pidfile = shift;
106   open(PID, "$FS_RUN/$pidfile") or return 0;
107   chomp( my $pid = scalar(<PID>) );
108   close PID; # or return 0;
109
110   $pid && kill 0, $pid;
111 }
112
113 sub check_apache {
114   my $ua = new LWP::UserAgent;
115   $ua->agent("FreesideCronCheck/0.1 " . $ua->agent);
116
117   my $req = new HTTP::Request GET => 'https://localhost/';
118   my $res = $ua->request($req);
119
120   return 1 if $res->is_success || $res->status_line =~ /^403/;
121   $error_msg = $res->status_line;
122   return 0;
123
124 }
125
126 #and now for something entirely different...
127 my $num_consecutive_bop_failures = 50;
128 sub check_bop_failures {
129
130   return 1 if grep { $_->statustext eq 'captured' }
131                    qsearch({
132                      'table'    => 'cust_pay_pending',
133                      'hashref'  => { 'status' => 'done' },
134                      'order_by' => 'ORDER BY paypendingnum DESC'.
135                                    " LIMIT $num_consecutive_bop_failures",
136                    });
137   $error_msg = "Last $num_consecutive_bop_failures real-time payments failed";
138   return 0;
139 }
140
141 #
142
143 sub error_msg {
144   $error_msg;
145 }
146
147 sub alert {
148   my( $alert, @emails ) = @_;
149
150   my $conf = new FS::Conf;
151   my $smtpmachine = $conf->config('smtpmachine');
152   my $company_name = $conf->config('company_name');
153
154   foreach my $email (@emails) {
155     warn "warning $email about $alert\n" if $DEBUG;
156
157     my $message = <<"__MESSAGE__";
158 From: support\@freeside.biz
159 To: $email
160 Subject: FREESIDE ALERT for $company_name
161
162 FREESIDE ALERT: $alert
163
164 __MESSAGE__
165
166     my $sender = Email::Send->new({ mailer => 'SMTP' });
167     $sender->mailer_args([ Host => $smtpmachine ]);
168     $sender->send($message);
169
170   }
171
172 }
173
174 1;
175