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