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