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