File:
1.01.5b/server/base/freenats.inc.php (
View as Code)
1: 2: /* -------------------------------------------------------------
3: This file is part of FreeNATS
4:
5: FreeNATS is (C) Copyright 2008 PurplePixie Systems
6:
7: FreeNATS is free software: you can redistribute it and/or modify
8: it under the terms of the GNU General Public License as published by
9: the Free Software Foundation, either version 3 of the License, or
10: (at your option) any later version.
11:
12: FreeNATS is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU General Public License for more details.
16:
17: You should have received a copy of the GNU General Public License
18: along with FreeNATS. If not, see www.gnu.org/licenses
19:
20: For more information see www.purplepixie.org/freenats
21: -------------------------------------------------------------- */
22:
23: class TFreeNATS
24: {
25: var $init=false;
26: var $DB;
27: var $Cfg;
28: var $Tests;
29: var $Version="1.01.5";
30: var $Release="b";
31: var $EventHandlers=array();
32:
33: function TFreeNATS()
34: {
35: $this->Tests=new TNATS_Tests(); // need this available during the include phase pre-start
36: }
37:
38: function Start()
39: {
40: global $BaseDir,$fnSkipSiteIncludes;
41: if ( (!isset($BaseDir)) || ($BaseDir=="") ) $BaseDir="./";
42: $this->DB=new TNATS_DB();
43: $this->Cfg=new TNATS_Cfg();
44: $this->DB->Connect();
45: $this->Cfg->Load($this->DB);
46: // Site Includes
47: // Tests
48: if ( (!isset($fnSkipSiteIncludes)) || ($fnSkipSiteIncludes !== false) )
49: {
50:
51: if ($this->Cfg->Get("site.include.tests",0)==1)
52: {
53: foreach(glob($BaseDir."site/tests/*.php") as $phpfile)
54: {
55: $this->Event("Including ".$phpfile,10,"NATS","Start");
56: include_once($phpfile);
57: }
58: }
59: // Events
60: if ($this->Cfg->Get("site.include.events",0)==1)
61: {
62: foreach(glob($BaseDir."site/events/*.php") as $phpfile)
63: {
64: $this->Event("Including ".$phpfile,10,"NATS","Start");
65: include_once($phpfile);
66: }
67: }
68: }
69:
70: $this->init=true;
71: }
72:
73: function Stop()
74: {
75: $t=$this->Cfg->Get("freenats.tracker","");
76: if ( ($t>0) && ($t!="") )
77: {
78: $day=date("Ymd");
79: if ($this->Cfg->Get("freenats.tracker.last","")!=$day)
80: {
81: $this->Cfg->Set("freenats.tracker.last",$day);
82: $this->PhoneHome();
83: }
84: }
85:
86: $this->DB->Disconnect();
87: $this->init=false;
88: }
89:
90: function Event($logevent,$loglevel=1,$modid="NONE",$catid="NONE")
91: {
92: global $NATS_Session;
93: if ((isset($NATS_Session))&&($NATS_Session->auth)) $username=$NATS_Session->username;
94: else $username="";
95: $l=$this->Cfg->Get("log.level");
96: //echo "** $l **\n";
97: if ( $l=="" ) $l=10; // debug logging if no variable
98: if ( $l < $loglevel ) return false;
99: if (strlen($logevent)>249) $logevent=substr($logevent,0,245)."...";
100: $q="INSERT INTO fnlog(postedx,modid,catid,loglevel,logevent,username) VALUES(".time().",";
101: $q.="\"".ss($modid)."\",\"".ss($catid)."\",".ss($loglevel).",\"".ss($logevent)."\",\"".ss($username)."\")";
102: //echo $q;
103: $this->DB->Query($q,false);
104: }
105:
106: function AlertAction($nodeid,$alertlevel,$change,$alerttext)
107: {
108: //echo "Called for node: ".$nodeid."\n";
109: if ($change==0) return false; // no change
110: if (trim($alerttext)=="") return false; // no text so a bogus event i.e. -1 to 0
111: //echo $nodeid.":".$alertlevel.":".$change.":".$alerttext."\n";
112: // get all the alertactions for this node id
113: $q="SELECT aaid FROM fnnalink WHERE nodeid=\"".ss($nodeid)."\"";
114: $r=$this->DB->Query($q);
115: while ($arow=$this->DB->Fetch_Array($r))
116: {
117: // get details for this alert action
118: $aq="SELECT * FROM fnalertaction WHERE aaid=".$arow['aaid']." LIMIT 0,1";
119:
120: $ar=$this->DB->Query($aq);
121: $aa=$this->DB->Fetch_Array($ar);
122: $this->DB->Free($ar);
123:
124: // UGGGGGGGG continue!!
125: // if the type is blank or disabled skip
126: if ( ($aa['atype']=="") || ($aa['atype']=="Disabled") ) continue;
127: // if warnings aren't set and it is a warning skip
128: if ( ($aa['awarnings']==0) && ($alertlevel==1) ) continue;
129: // if decreases aren't set and it is a decrease skip
130: if ( ($aa['adecrease']==0) && ($change<1) ) continue;
131: // if has a schedule and it dictates not to run now then skip
132: if (($aa['scheduleid']!=0)&&(!run_x_in_schedule(time(),$aa['scheduleid']))) continue;
133:
134: // made it this far
135: if ($aa['mdata']!="") $ndata=$aa['mdata']."\n".$nodeid.": ".$alerttext;
136: else $ndata=$nodeid.": ".$alerttext;
137: $uq="UPDATE fnalertaction SET mdata=\"".ss($ndata)."\" WHERE aaid=".$arow['aaid'];
138: //echo $uq."\n";
139: $this->DB->Query($uq);
140: }
141: }
142:
143: function ActionFlush()
144: {
145: global $allowed,$BaseDir; // allowed chars from screen in YA BODGE
146: $q="SELECT * FROM fnalertaction WHERE mdata!=\"\"";
147: $r=$this->DB->Query($q);
148: while ($row=$this->DB->Fetch_Array($r))
149: {
150:
151: $doalert=true;
152:
153: // clear mdata right at the start to get around duplicate emails whilst processing
154: $q="UPDATE fnalertaction SET mdata=\"\" WHERE aaid=".$row['aaid'];
155: $this->DB->Query($q);
156:
157: if ($this->DB->Affected_Rows()<=0) // already flushed or failed to flush
158: {
159: $doalert=false;
160: $this->Event("Alert Action Already Flushed - Skipping",8,"Flush","Action");
161: }
162:
163: // alert counter
164: $td=date("Ymd");
165: if ($td!=$row['ctrdate']) // new day or no flush record
166: {
167: $q="UPDATE fnalertaction SET ctrdate=\"".$td."\",ctrtoday=1 WHERE aaid=".$row['aaid'];
168: $this->DB->Query($q);
169: }
170: else
171: {
172:
173: if ( ($row['ctrlimit']==0) || ($row['ctrlimit']>$row['ctrtoday']) ) // no limit or below
174: {
175: $q="UPDATE fnalertaction SET ctrtoday=ctrtoday+1 WHERE aaid=".$row['aaid'];
176: $this->DB->Query($q);
177: }
178: else // at or over limit
179: {
180: $this->Event("Alert Action Limit Reached - Skipping",2,"Flush","Action");
181: $doalert=false;
182: }
183:
184: }
185:
186:
187: if ($row['atype']=="email")
188: {
189: if ($row['esubject']==0) $sub="";
190: else if ($row['esubject']==1) $sub="FreeNATS Alert";
191: else $sub="** FreeNATS Alert **";
192: $body="";
193: if ($row['etype']==0) $body=$row['mdata'];
194: else $body="FreeNATS Alert,\r\n".$row['mdata']."\r\n--FreeNATS @ ".nicedt(time());
195: //$tolist=preg_split("[\n\r]",$row['etolist']);
196: $tolist=array();
197: $f=0;
198: $tolist[0]="";
199: for ($a=0; $a200: {
201: $chr=$row['etolist'][$a];
202: //echo $chr;
203: if (strpos($allowed,$chr)===false) // special char
204: {
205: $f++;
206: $tolist[$f]="";
207: }
208: else
209: {
210: $tolist[$f].=$chr;
211: }
212: }
213:
214: foreach($tolist as $toaddr)
215: {
216: $toaddr=nices($toaddr);
217: if ($toaddr!="")
218: {
219: $smtpserver=$this->Cfg->Get("mail.smtpserver","");
220: if ($smtpserver=="")
221: {
222: // mail() method - local delivery
223: $header="From: ".$row['efrom']."\r\n";
224: if ($doalert)
225: {
226: mail($toaddr,$sub,$body,$header);
227: $this->Event("Sent alert email to ".$toaddr,4,"Flush","Email");
228: }
229: }
230: else // use phpmailer direct SMTP delivery
231: {
232: include_once($BaseDir."phpmailer/class.phpmailer.php");
233: $fromname=$this->Cfg->Get("mail.fromname","");
234: if ($fromname=="") $fromname="FreeNATS";
235: $smtpusername=$this->Cfg->Get("mail.smtp.username","");
236: if ($smtpusername!="") $smtpauth=true;
237: else $smtpauth=false;
238: $smtppassword=$this->Cfg->Get("mail.smtp.password","");
239: $smtphostname=$this->Cfg->Get("mail.smtp.hostname","");
240: $mail=new PHPMailer();
241: $mail->IsSMTP();
242: $mail->Host=$smtpserver;
243: $mail->From=$row['efrom'];
244: $mail->FromName=$fromname;
245: $mail->AddAddress($toaddr);
246: $mail->Subject=$sub;
247: $mail->Body=$body;
248: $mail->WordWrap=50;
249: if ($smtphostname!="") $mail->Hostname=$smtphostname;
250: if ($smtpauth)
251: {
252: $mail->SMTPAuth=true;
253: $mail->Username=$smtpusername;
254: $mail->Password=$smtppassword;
255: }
256: if (!$mail->Send())
257: { // failed
258: $this->Event("phpMailer to ".$toaddr." failed",1,"Flush","Email");
259: $this->Event("phpMailer Error: ".$mail->ErrorInfo,1,"Flush","Email");
260: }
261: else
262: {
263: $this->Event("phpMailer Sent Email To ".$toaddr,4,"Flush","Email");
264: }
265: }
266:
267: }
268: }
269:
270:
271:
272: }
273: else if ($row['atype']=="url")
274: {
275: // url send
276: if ($row['etype']==0) $body=$row['mdata'];
277: else $body="FreeNATS Alert,\r\n".$row['mdata']."\r\n--FreeNATS @ ".nicedt(time());
278:
279: $body=urlencode($body);
280: $tolist=array();
281: $f=0;
282: $tolist[0]="";
283: for ($a=0; $a284: {
285: $chr=$row['etolist'][$a];
286: //echo $chr;
287: if (strpos($allowed,$chr)===false) // special char
288: {
289: $f++;
290: $tolist[$f]="";
291: }
292: else
293: {
294: $tolist[$f].=$chr;
295: }
296: }
297:
298: foreach($tolist as $tourl)
299: {
300: if ($doalert)
301: {
302: $url=$tourl.$body;
303: $fp=@fopen($url,"r");
304: if ($fp>0) fclose($fp);
305: else $this->Event("URL Alert Failed ".$url,1,"Flush","URL");
306: $this->Event("URL Alert ".$url,4,"Flush","URL");
307: }
308: }
309:
310:
311: }
312: else if ($row['atype']=="mqueue")
313: {
314: // message queue
315: $eventdata=array("aaid"=>$row['aaid'],"name"=>$row['aname'],"data"=>$row['mdata']);
316: $result=$this->EventHandler("alert_action",$eventdata);
317: if ($result===false) // put the data back into the queue
318: {
319: $q="UPDATE fnalertaction SET mdata=\"".$row['mdata']."\"+mdata WHERE aaid=".$row['aaid'];
320: $this->DB->Query($q);
321: if ($this->DB->Affected_Rows()<=0)
322: $this->Event("Persist MDATA Failed for AAID ".$row['aaid'],2,"Flush","MQueue");
323: }
324: else $this->Event("Queue Cleared for AAID ".$row['aaid']." by Handler",4,"Flush","MQueue");
325: }
326:
327: }
328: }
329:
330: function GetAlerts()
331: {
332: $q="SELECT nodeid,alertlevel FROM fnalert WHERE closedx=0";
333: $r=$this->DB->Query($q);
334: $c=0;
335: $al=array();
336: while ($row=$this->DB->Fetch_Array($r))
337: {
338: $al[$c]['nodeid']=$row['nodeid'];
339: $al[$c]['alertlevel']=$row['alertlevel'];
340: $c++;
341: }
342: if ($c>0) return $al;
343: else return false;
344: }
345:
346: function SetAlerts($nodeid,$alertlevel,$alerts="")
347: {
348: if ($alerts=="") $alerts=array();
349: // get current alert level
350: $q="SELECT alertlevel,nodealert FROM fnnode WHERE nodeid=\"".ss($nodeid)."\"";
351: $r=$this->DB->Query($q);
352: $row=$this->DB->Fetch_Array($r);
353: $this->DB->Free($r);
354: $cal=$row['alertlevel'];
355:
356: $eventdata=array("nodeid"=>$nodeid,"alertlevel"=>$alertlevel,
357: "oldalertlevel"=>$cal);
358: $this->EventHandler("set_alerts",$eventdata);
359:
360: if ($alertlevel!=$cal)
361: {
362: // update table
363: $q="UPDATE fnnode SET alertlevel=".ss($alertlevel)." WHERE nodeid=\"".ss($nodeid)."\"";
364: $this->DB->Query($q);
365: }
366:
367: // do not continue if node alert isn't set
368: if ($row['nodealert']!=1) return 0;
369: // or if untested
370: if ($alertlevel<0) return 0;
371:
372: // ALERTS
373: // is there an existing alert for this node
374: $q="SELECT alertid,alertlevel FROM fnalert WHERE nodeid=\"".ss($nodeid)."\" AND closedx=0";
375: $r=$this->DB->Query($q);
376: if ($row=$this->DB->Fetch_Array($r))
377: { // yes there is
378: // if new alert level is 0 let's close it
379: if ($alertlevel==0)
380: {
381: $alertid=$row['alertid'];
382: $q="UPDATE fnalert SET closedx=".time()." WHERE alertid=".$row['alertid'];
383: $this->DB->Query($q);
384: $closetext=$this->Cfg->Get("site.text.closed","Alert Closed");
385: if (is_array($alerts)) $alerts[]=$closetext;
386: else
387: {
388: //$alerts=array(); // WTF?!?
389: $alerts[]=$closetext;
390: }
391: $eventdata=array("nodeid"=>$nodeid);
392: $this->EventHandler("alert_close",$eventdata);
393: }
394: else
395: {
396: $alertid=$row['alertid'];
397: // otherwise update the alert to the new value (was: regardless, now just if not a 0)
398: $q="UPDATE fnalert SET alertlevel=".ss($alertlevel)." WHERE alertid=".$alertid;
399: $this->DB->Query($q);
400: }
401: }
402: else
403: { // no there's not
404: if ($alertlevel>0) // only if an actual alert
405: {
406: $q="INSERT INTO fnalert(nodeid,alertlevel,openedx) VALUES(";
407: $q.="\"".ss($nodeid)."\",".ss($alertlevel).",".time().")";
408: $this->DB->Query($q);
409: $alertid=$this->DB->Insert_Id();
410: $eventdata=array("nodeid"=>$nodeid);
411: $this->EventHandler("alert_open",$eventdata);
412: }
413: }
414: // ALERT LOG with $alertid
415: $t=time();
416: $at="";
417: if (is_array($alerts))
418: {
419: foreach($alerts as $alert)
420: {
421: if (isset($alertid)) // misses on manual runs methinx
422: {
423: if ($at!="") $at.=", ";
424: $at.=$alert;
425: //echo $at."\n";
426: $iq="INSERT INTO fnalertlog(alertid,postedx,logentry) VALUES(";
427: $iq.=$alertid.",".$t.",\"".ss($alert)."\")";
428: //echo $iq;
429: $this->DB->Query($iq);
430: }
431: }
432: }
433:
434: $this->AlertAction($nodeid,$alertlevel,$alertlevel-$cal,$at);
435:
436:
437:
438: }
439:
440: function NodeAlertLevel($nodeid)
441: {
442: $q="SELECT alertlevel FROM fnnode WHERE nodeid=\"".ss($nodeid)."\"";
443: $r=$this->DB->Query($q);
444: if ($row=$this->DB->Fetch_Array($r)) return $row['alertlevel'];
445: else return -1;
446: }
447:
448: function GroupAlertLevel($groupid)
449: {
450: $lvl=-1;
451: $q="SELECT nodeid FROM fngrouplink WHERE groupid=\"".ss($groupid)."\"";
452: $r=$this->DB->Query($q);
453: while ($row=$this->DB->Fetch_Array($r))
454: {
455: $nl=$this->NodeAlertLevel($row['nodeid']);
456: if ($nl>$lvl) $lvl=$nl;
457: }
458: $this->DB->Free($r);
459: return $lvl;
460: }
461:
462: function PhoneHome($mode=0,$type="ping") // 0 - php, 1 - html, 2 - data
463: {
464: if ($mode<2)
465: {
466: $qs="?type=".$type."&data=v=".$this->Version;
467: if (isset($_SERVER['REMOTE_ADDR']))
468: $qs.=",ip=".$_SERVER['REMOTE_ADDR'];
469: $ploc="http://www.purplepixie.org/freenats/report/";
470: if ($mode==1) $ploc.="ping.html";
471: else $ploc.="ping.php";
472:
473: $ploc.=$qs;
474:
475: $lp=@fopen($ploc,"r");
476: if ($lp>0) @fclose($lp);
477: }
478: else
479: {
480: // data post -- !!
481: }
482: }
483:
484: function GetNode($nodeid)
485: {
486: $return_row=false;
487: $q="SELECT * FROM fnnode WHERE nodeid=\"".ss($nodeid)."\" LIMIT 0,1";
488: $r=$this->DB->Query($q);
489: if ($row=$this->DB->Fetch_Array($r))
490: $return_row=true;
491:
492: $this->DB->Free($r);
493: if ($return_row) // found a valid
494: {
495: if ($row['nodename']!="") $row['name']=$row['nodename']; // make a "nice" name for it
496: else $row['name']=$row['nodeid'];
497:
498: $row['alerttext']=oText($row['alertlevel']); // textual alert status
499:
500: $row['lastrundt']=nicedt($row['lastrunx']); // text date-time last run
501: $row['lastrunago']=dtago($row['lastrunx'],false); // last run ago
502:
503: // protection
504: $row['nskey']="";
505:
506: return $row;
507: }
508: else
509: return false; // or failed
510: }
511:
512: function SetNode($nodeid,$data)
513: {
514: $q="UPDATE fnnode SET ";
515: $first=true;
516: foreach($data as $key => $val)
517: {
518: if ($first) $first=false;
519: else $q.=",";
520: $q.=ss($key)."=\"".ss($val)."\"";
521: }
522: $q.=" WHERE nodeid=\"".ss($nodeid)."\"";
523: $this->DB->Query($q);
524: if ($this->DB->Affected_Rows()>0) return true;
525:
526: if ($this->DB->Error()) // query failed
527: {
528: $errstr1="Query Failed: ".$q;
529: $errstr2="Query Failed: ".$this->DB->Error_String();
530: $this->Event($errstr1,2,"Node","Set");
531: $this->Event($errstr1,2,"Node","Set");
532: return false;
533: }
534: return true; // query succeeded but nothing was updated
535: }
536:
537: function EnableNode($nodeid,$enabled=true)
538: {
539: if ($enabled) $ne=1;
540: else $ne=0;
541: $data=array("nodeenabled"=>$ne);
542: return $this->SetNode($nodeid,$data);
543: }
544:
545: function DisableNode($nodeid)
546: {
547: return $this->EnableNode($nodeid,false);
548: }
549:
550: function SetNodeSchedule($nodeid,$scheduleid)
551: {
552: $data=array("scheduleid"=>$scheduleid);
553: return $this->SetNode($nodeid,$data);
554: }
555:
556: function GetGroup($groupid)
557: {
558: $q="SELECT * FROM fngroup WHERE groupid=".ss($groupid)." LIMIT 0,1";
559: $r=$this->DB->Query($q);
560: if (!$row=$this->DB->Fetch_Array($r)) return false;
561:
562: $this->DB->Free($r);
563: $row['alertlevel']=$this->GroupAlertLevel($groupid);
564: $row['alerttext']=oText($row['alertlevel']);
565: return $row;
566: }
567:
568: function GetTest($testid,$protect=false)
569: {
570: if ($testid=="") return false;
571: $class=$testid[0];
572: if (is_numeric($class))
573: {
574: // test ID will stay the same
575: $class="L";
576: $anytestid=$testid;
577: }
578: else
579: {
580: //$testid=substr($testid,1); // as it will here also so direct use to graphs can be made
581: $anytestid=substr($testid,1); // the classless version
582: }
583:
584: $q="";
585: switch($class)
586: {
587: case "L": // local tests
588: $q="SELECT * FROM fnlocaltest WHERE localtestid=".ss($anytestid)." LIMIT 0,1";
589: break;
590: case "N": // node-side test
591: $q="SELECT * FROM fnnstest WHERE nstestid=".ss($anytestid)." LIMIT 0,1";
592: break;
593: default:
594: return false; // can't lookup this class
595: }
596:
597: if ($q=="") return false;
598:
599: $r=$this->DB->Query($q);
600:
601: if (!$row=$this->DB->Fetch_Array($r)) return false;
602:
603: $row['class']=$class;
604: $row['testid']=$testid;
605: $row['anytestid']=$anytestid;
606: $row['alerttext']=oText($row['alertlevel']);
607: $row['lastrundt']=nicedt($row['lastrunx']);
608: $row['lastrunago']=dtago($row['lastrunx'],false);
609:
610: if ($row['testname']!="") $row['name']=$row['testname'];
611: else
612: {
613: if ($class=="L")
614: {
615: $row['name']=lText($row['testtype']); // TODO OTHER TESTS
616: if ($row['testparam']!="") $row['name'].=" (".$row['testparam'].")";
617: }
618: else if ($class=="N")
619: {
620: if ($row['testdesc']!="") $row['name']=$row['testdesc'];
621: else $row['name']=$row['testtype'];
622: }
623: }
624:
625: if ($protect&&($class=="L")) // module test protection
626: {
627: if ($this->Tests->Exists($row['testtype'])) // in the module register
628: {
629: $this->Tests->Tests[$row['testtype']]->Create();
630: $this->Tests->Tests[$row['testtype']]->instance->ProtectOutput($row);
631: }
632: }
633:
634: $this->DB->Free($r);
635:
636: return $row;
637: }
638:
639:
640: function DeleteTest($testid)
641: {
642: if ($testid=="") return false;
643: $class=$testid[0];
644: if (is_numeric($class))
645: {
646: // test ID will stay the same
647: $class="L";
648: $anytestid=$testid;
649: }
650: else
651: {
652: $anytestid=substr($testid,1); // the classless version
653: }
654:
655: $q="";
656: switch($class)
657: {
658: case "L": // local tests
659: $q="DELETE FROM fnlocaltest WHERE localtestid=".ss($anytestid);
660: break;
661: case "N": // node-side test
662: $q="DELETE FROM fnnstest WHERE nstestid=".ss($anytestid);
663: break;
664: default:
665: return false; // can't lookup this class
666: }
667:
668: if ($q=="") return false;
669:
670: $this->DB->Query($q);
671: $tests=$this->DB->Affected_Rows();
672:
673: $rq="DELETE FROM fnrecord WHERE testid=\"".ss($testid)."\"";
674: $this->DB->Query($rq);
675: $records=$this->DB->Affected_Rows();
676:
677: $eq="DELETE FROM fneval WHERE testid=\"".ss($testid)."\"";
678: $this->DB->Query($eq);
679: $eval=$this->DB->Affected_Rows();
680:
681: $s="Deleted test ".$testid." (".$tests." tests, ".$records." records, ".$eval." evaluators)";
682: $this->Event($s,6,"Test","Delete");
683: }
684:
685:
686:
687: function InvalidateTest($testid,$rightnow=false)
688: {
689: $class=$testid[0];
690: if (is_numeric($class)) $class="L";
691: else $testid=substr($testid,1);
692: if ($rightnow)
693: {
694: $nextx=time();
695: $q="UPDATE ";
696: if ($class=="L") $q.="fnlocaltest";
697: // other ones here
698:
699: $q.=" SET nextrunx=".$nextx." WHERE ";
700:
701: if ($class=="L") $q.="localtestid=".$testid;
702: // other ones here
703:
704: $this->DB->Query($q);
705: return true;
706: }
707: // otherwise use it's interval
708: $q="SELECT testinterval FROM ";
709:
710: if ($class=="L") $q.="fnlocaltest WHERE localtestid=";
711: // other ones here
712:
713: $q.=$testid;
714: $r=$this->DB->Query($q);
715: if ($row=$this->DB->Fetch_Array($r))
716: {
717: $this->DB->Free($r);
718: $nextx=next_run_x($row['testinterval']);
719: $q="UPDATE ";
720: if ($class=="L") $q.="fnlocaltest";
721: // other ones here
722:
723: $q.=" SET nextrunx=".$nextx." WHERE ";
724:
725: if ($class=="L") $q.="localtestid=".$testid;
726: // other ones here
727:
728: $this->DB->Query($q);
729: return true;
730: }
731: return false;
732: }
733:
734: function InvalidateNode($nodeid,$rightnow=false,$testsaswell=false)
735: {
736: if ($rightnow)
737: {
738: $nextx=time();
739: $q="UPDATE fnnode SET nextrunx=".$nextx." WHERE nodeid=\"".ss($nodeid)."\"";
740: $this->DB->Query($q);
741: if ($testsaswell)
742: {
743: $q="UPDATE fnlocaltest SET nextrunx=".$nextx." WHERE nodeid=\"".ss($nodeid)."\"";
744: $this->DB->Query($q);
745: }
746: return true;
747: }
748: // otherwise set to it's interval
749: $q="SELECT testinterval FROM fnnode WHERE nodeid=\"".ss($nodeid)."\"";
750: $r=$this->DB->Query($q);
751: if ($row=$this->DB->Fetch_Array($r))
752: {
753: $nextx=next_run_x($row['testinterval']);
754: $uq="UPDATE fnnode SET nextrunx=".$nextx." WHERE nodeid=\"".ss($nodeid)."\"";
755: $this->DB->Query($uq);
756: $this->DB->Free($r);
757: if ($testsaswell)
758: {
759: $uq="UPDATE fnlocaltest SET nextrunx=".$nextx." WHERE nodeid=\"".ss($nodeid)."\"";
760: $this->DB->Query($uq);
761: }
762: return true;
763: }
764: return false;
765: }
766:
767:
768: function NodeSide_Pull($nodeid)
769: {
770: $eventdata=array("nodeid"=>$nodeid,"success"=>false);
771: $q="SELECT nsenabled,nspullenabled,nsurl,nskey,nsinterval FROM fnnode WHERE nodeid=\"".ss($nodeid)."\" LIMIT 0,1";
772: $r=$this->DB->Query($q);
773: if (!$row=$this->DB->Fetch_Array($r)) return false;
774:
775: $this->DB->Free($r);
776:
777: $url=$row['nsurl'];
778: if ($row['nskey']!="") $url.="?nodekey=".$row['nskey'];
779: //echo $url."\n";
780: $this->Event("NodeSide_Pull Started for ".$nodeid,10,"Node","Pull");
781:
782: $xmlobj=new TNodeXML();
783:
784: $fp=@fopen($url,"r");
785: if ($fp<=0)
786: {
787: $this->Event("Pull Failed URL ".$url,1,"Node","Pull");
788: $this->EventHandler("nodeside_pull",$eventdata);
789: return false;
790: }
791: $xml="";
792: while (!feof($fp))
793: {
794: $xml.=fgets($fp,4096);
795: }
796: if ($xml=="")
797: {
798: $this->EventHandler("nodeside_pull",$eventdata);
799: return false;
800: }
801:
802: //echo $xml;
803:
804: $result=$xmlobj->Parse($xml);
805:
806: if ($xmlobj->Error()!="")
807: {
808: $this->Event("NodeXML Error: ".$xmlobj->Error(),1,"Node","Pull");
809: $this->EventHandler("nodeside_pull",$eventdata);
810: return false;
811: }
812: $this->Event("NodeSide_Pull Fetched ".$xmlobj->Tests." tests for ".$nodeid,10,"Node","Pull");
813: // Now just to actually process it...
814: $eventdata['success']=true;
815: $this->EventHandler("nodeside_pull",$eventdata);
816: $this->NodeSide_Process($nodeid,$xmlobj);
817: return true;
818: }
819:
820: function NodeSide_Process($nodeid,&$xmlobj)
821: { // nodeid + takes a TNodeXML Object
822: $alvl=0;
823: $this->Event("NodeSide_Process for ".$nodeid,10,"Node","Pull");
824: $q="SELECT * FROM fnnstest WHERE nodeid=\"".ss($nodeid)."\"";
825: $r=$this->DB->Query($q);
826: $tests=array();
827: while ($row=$this->DB->Fetch_Array($r))
828: {
829: $tests[$row['testtype']]=$row;
830: if (isset($xmlobj->Catalogue[$row['testtype']]))
831: { // this test is in the DB and catalogue
832: $tests[$row['testtype']]['incat']=true;
833: if ($row['testenabled']==1) // it is enabled - so we test it
834: {
835: if ($row['simpleeval']==1) $level=$xmlobj->Catalogue[$row['testtype']]['ALERTLEVEL']; // use provided level
836: else $level=nats_eval("N".$row['nstestid'],$xmlobj->Catalogue[$row['testtype']]['VALUE']);
837: $dbs="Nodeside ".$row['testtype']." on ".$row['nodeid']." = ".$level;
838: if ($level==0) $debuglev=8;
839: else if ($level>0) $debuglev=5;
840: else $debuglev=2;
841: $this->Event($dbs,$debuglev,"Node","Process");
842:
843: if ($level>$alvl) $alvl=$level;
844:
845: if ($row['testrecord']==1) // record it
846: {
847: $testvalue=$xmlobj->Catalogue[$row['testtype']]['VALUE'];
848: $testvalue=str_replace(",",".",$testvalue);
849: if (!is_numeric($testvalue)) $testvalue=0;
850: $iq="INSERT INTO fnrecord(testid,alertlevel,recordx,nodeid,testvalue) VALUES(";
851: $iq.="\"N".$row['nstestid']."\",".$level.",".time().",\"".$row['nodeid']."\",".$testvalue.")";
852: $this->DB->Query($iq);
853: if ($this->DB->Affected_Rows()<=0)
854: $this->Event("Nodeside ".$row['testtype']." Failed to Record",1,"Node","Process");
855: }
856:
857: // We don't do any alerting here - the tester will do that for us!
858: $uq="UPDATE fnnstest SET lastrunx=".time().",lastvalue=\"".ss($xmlobj->Catalogue[$row['testtype']]['VALUE'])."\",alertlevel=".$level." ";
859: $uq.="WHERE nstestid=".$row['nstestid'];
860: $this->DB->Query($uq);
861: if ($this->DB->Affected_Rows()<=0)
862: $this->Event("Nodeside ".$row['testtype']." Failed to Update or Same Values",5,"Node","Process");
863:
864: }
865:
866: // check to see if the desc has changed
867: if ($row['testdesc']!=$xmlobj->Catalogue[$row['testtype']]['DESC'])
868: {
869: $duq="UPDATE fnnstest SET testdesc=\"".ss($xmlobj->Catalogue[$row['testtype']]['DESC'])."\" WHERE nstestid=".$row['nstestid'];
870: $this->DB->Query($duq);
871: }
872:
873: }
874: else
875: {
876: // test in the DB but NOT in the catalogue
877: //$xmlobj->Catalogue[$row['testtype']]['incat']=false;
878: if ($row['testenabled']==1)
879: { // enabled so shown in lists etc
880: // Update it to show failed status
881: $this->Event("No nodeside data for test N".$row['nstestid'],3,"Node","Process");
882: $uq="UPDATE fnnstest SET alertlevel=2,lastvalue=-1 WHERE nstestid=".$row['nstestid'];
883: $this->DB->Query($uq);
884: $alvl=2;
885: if ($row['testrecord']==1) // record it
886: {
887: $testvalue=-1;
888: $iq="INSERT INTO fnrecord(testid,alertlevel,recordx,nodeid,testvalue) VALUES(";
889: $iq.="\"N".$row['nstestid']."\",2,".time().",\"".$row['nodeid']."\",".$testvalue.")";
890: $this->DB->Query($iq);
891: if ($this->DB->Affected_Rows()<=0)
892: $this->Event("Nodeside ".$row['testtype']." Failed to Record",1,"Node","Process");
893: }
894: }
895: else // not enabled so simply delete
896: {
897: $this->DeleteTest("N".$row['nstestid']);
898: }
899: }
900: }
901: $this->DB->Free($r);
902:
903:
904: // and finally we look for new tests i.e. in the cat but not in the DB
905: foreach($xmlobj->Catalogue as $val)
906: {
907: $key=$val['NAME'];
908: if (!isset($tests[$key])) // not in the DB
909: {
910: $q="INSERT INTO fnnstest(nodeid,testtype,testdesc,lastvalue,lastrunx,alertlevel) ";
911: $q.="VALUES(\"".ss($nodeid)."\",\"".$key."\",\"".ss($val['DESC'])."\",\"".ss($val['VALUE'])."\",".time().",".ss($val['ALERTLEVEL']).")";
912: //echo $q."
";
913: $this->DB->Query($q);
914: }
915: }
916:
917: $eventdata=array("nodeid"=>$nodeid,"alertlevel"=>$alvl);
918: $this->EventHandler("nodeside_process",$eventdata);
919:
920:
921: }
922:
923:
924: function AddEventHandler($event,$function)
925: {
926: if (!isset($this->EventHandlers[$event])) $this->EventHandlers[$event]=array();
927: $this->EventHandlers[$event][]=$function;
928: }
929:
930: function EventHandler($event,$data)
931: {
932: $res=false;
933: if ( isset($data) && is_array($data) ) $data['event']=$event;
934:
935: if (isset($this->EventHandlers[$event])) // handler(s) exist
936: {
937: for($a=0; $aEventHandlers[$event]); $a++)
938: {
939: if (function_exists($this->EventHandlers[$event][$a]))
940: {
941: $this->Event("Event ".$event." -> ".$this->EventHandlers[$event][$a],6,"Event","Handler");
942: if($this->EventHandlers[$event][$a]($data)) $res=true; // persist true only
943: }
944: else
945: {
946: $t="Illegal Handler ".$this->EventHandlers[$event][$a]." for ".$event;
947: $this->Event($t,2,"Event","Handler");
948: //return false;
949: }
950: }
951: }
952: else return $res;
953: }
954:
955: }
956: ?>