File: 1.01.8a/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.8"; 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="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($alerts); // add as first element to new array 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: $cal=0; // the cal (current alert level) goes to zero if it's a new alert so alert_actions fire ok 405: if ($alertlevel>0) // only if an actual alert 406: { 407: $q="INSERT INTO fnalert(nodeid,alertlevel,openedx) VALUES("; 408: $q.="\"".ss($nodeid)."\",".ss($alertlevel).",".time().")"; 409: $this->DB->Query($q); 410: $alertid=$this->DB->Insert_Id(); 411: $eventdata=array("nodeid"=>$nodeid); 412: $this->EventHandler("alert_open",$eventdata); 413: } 414: } 415: // ALERT LOG with $alertid 416: $t=time(); 417: $at=""; 418: if (is_array($alerts)) 419: { 420: foreach($alerts as $alert) 421: { 422: if (isset($alertid)) // misses on manual runs methinx 423: { 424: if ($at!="") $at.=", "; 425: $at.=$alert; 426: //echo $at."\n"; 427: $iq="INSERT INTO fnalertlog(alertid,postedx,logentry) VALUES("; 428: $iq.=$alertid.",".$t.",\"".ss($alert)."\")"; 429: //echo $iq; 430: $this->DB->Query($iq); 431: } 432: } 433: } 434: 435: $this->AlertAction($nodeid,$alertlevel,$alertlevel-$cal,$at); 436: 437: 438: 439: } 440: 441: function NodeAlertLevel($nodeid) 442: { 443: $q="SELECT alertlevel FROM fnnode WHERE nodeid=\"".ss($nodeid)."\""; 444: $r=$this->DB->Query($q); 445: if ($row=$this->DB->Fetch_Array($r)) return $row['alertlevel']; 446: else return -1; 447: } 448: 449: function GroupAlertLevel($groupid) 450: { 451: $lvl=-1; 452: $q="SELECT nodeid FROM fngrouplink WHERE groupid=\"".ss($groupid)."\""; 453: $r=$this->DB->Query($q); 454: while ($row=$this->DB->Fetch_Array($r)) 455: { 456: $nl=$this->NodeAlertLevel($row['nodeid']); 457: if ($nl>$lvl) $lvl=$nl; 458: } 459: $this->DB->Free($r); 460: return $lvl; 461: } 462: 463: function PhoneHome($mode=0,$type="ping") // 0 - php, 1 - html, 2 - data 464: { 465: if ($mode<2) 466: { 467: $qs="?type=".$type."&data=v=".$this->Version; 468: if (isset($_SERVER['REMOTE_ADDR'])) 469: $qs.=",ip=".$_SERVER['REMOTE_ADDR']; 470: $ploc="http://www.purplepixie.org/freenats/report/"; 471: if ($mode==1) $ploc.="ping.html"; 472: else $ploc.="ping.php"; 473: 474: $ploc.=$qs; 475: 476: $lp=@fopen($ploc,"r"); 477: if ($lp>0) @fclose($lp); 478: } 479: else 480: { 481: // data post -- !! 482: } 483: } 484: 485: function GetNode($nodeid) 486: { 487: $return_row=false; 488: $q="SELECT * FROM fnnode WHERE nodeid=\"".ss($nodeid)."\" LIMIT 0,1"; 489: $r=$this->DB->Query($q); 490: if ($row=$this->DB->Fetch_Array($r)) 491: $return_row=true; 492: 493: $this->DB->Free($r); 494: if ($return_row) // found a valid 495: { 496: if ($row['nodename']!="") $row['name']=$row['nodename']; // make a "nice" name for it 497: else $row['name']=$row['nodeid']; 498: 499: $row['alerttext']=oText($row['alertlevel']); // textual alert status 500: 501: $row['lastrundt']=nicedt($row['lastrunx']); // text date-time last run 502: $row['lastrunago']=dtago($row['lastrunx'],false); // last run ago 503: 504: // protection 505: $row['nskey']=""; 506: 507: return $row; 508: } 509: else 510: return false; // or failed 511: } 512: 513: function SetNode($nodeid,$data) 514: { 515: $q="UPDATE fnnode SET "; 516: $first=true; 517: foreach($data as $key => $val) 518: { 519: if ($first) $first=false; 520: else $q.=","; 521: $q.=ss($key)."=\"".ss($val)."\""; 522: } 523: $q.=" WHERE nodeid=\"".ss($nodeid)."\""; 524: $this->DB->Query($q); 525: if ($this->DB->Affected_Rows()>0) return true; 526: 527: if ($this->DB->Error()) // query failed 528: { 529: $errstr1="Query Failed: ".$q; 530: $errstr2="Query Failed: ".$this->DB->Error_String(); 531: $this->Event($errstr1,2,"Node","Set"); 532: $this->Event($errstr1,2,"Node","Set"); 533: return false; 534: } 535: return true; // query succeeded but nothing was updated 536: } 537: 538: function EnableNode($nodeid,$enabled=true) 539: { 540: if ($enabled) $ne=1; 541: else $ne=0; 542: $data=array("nodeenabled"=>$ne); 543: return $this->SetNode($nodeid,$data); 544: } 545: 546: function DisableNode($nodeid) 547: { 548: return $this->EnableNode($nodeid,false); 549: } 550: 551: function SetNodeSchedule($nodeid,$scheduleid) 552: { 553: $data=array("scheduleid"=>$scheduleid); 554: return $this->SetNode($nodeid,$data); 555: } 556: 557: function GetGroup($groupid) 558: { 559: $q="SELECT * FROM fngroup WHERE groupid=".ss($groupid)." LIMIT 0,1"; 560: $r=$this->DB->Query($q); 561: if (!$row=$this->DB->Fetch_Array($r)) return false; 562: 563: $this->DB->Free($r); 564: $row['alertlevel']=$this->GroupAlertLevel($groupid); 565: $row['alerttext']=oText($row['alertlevel']); 566: return $row; 567: } 568: 569: function GetTest($testid,$protect=false) 570: { 571: if ($testid=="") return false; 572: $class=$testid[0]; 573: if (is_numeric($class)) 574: { 575: // test ID will stay the same 576: $class="L"; 577: $anytestid=$testid; 578: } 579: else 580: { 581: //$testid=substr($testid,1); // as it will here also so direct use to graphs can be made 582: $anytestid=substr($testid,1); // the classless version 583: } 584: 585: $q=""; 586: switch($class) 587: { 588: case "L": // local tests 589: $q="SELECT * FROM fnlocaltest WHERE localtestid=".ss($anytestid)." LIMIT 0,1"; 590: break; 591: case "N": // node-side test 592: $q="SELECT * FROM fnnstest WHERE nstestid=".ss($anytestid)." LIMIT 0,1"; 593: break; 594: default: 595: return false; // can't lookup this class 596: } 597: 598: if ($q=="") return false; 599: 600: $r=$this->DB->Query($q); 601: 602: if (!$row=$this->DB->Fetch_Array($r)) return false; 603: 604: $row['class']=$class; 605: $row['testid']=$testid; 606: $row['anytestid']=$anytestid; 607: $row['alerttext']=oText($row['alertlevel']); 608: $row['lastrundt']=nicedt($row['lastrunx']); 609: $row['lastrunago']=dtago($row['lastrunx'],false); 610: 611: if ($row['testname']!="") $row['name']=$row['testname']; 612: else 613: { 614: if ($class=="L") 615: { 616: $row['name']=lText($row['testtype']); // TODO OTHER TESTS 617: if ($row['testparam']!="") $row['name'].=" (".$row['testparam'].")"; 618: } 619: else if ($class=="N") 620: { 621: if ($row['testdesc']!="") $row['name']=$row['testdesc']; 622: else $row['name']=$row['testtype']; 623: } 624: } 625: 626: if ($protect&&($class=="L")) // module test protection 627: { 628: if ($this->Tests->Exists($row['testtype'])) // in the module register 629: { 630: $this->Tests->Tests[$row['testtype']]->Create(); 631: $this->Tests->Tests[$row['testtype']]->instance->ProtectOutput($row); 632: } 633: } 634: 635: $this->DB->Free($r); 636: 637: return $row; 638: } 639: 640: 641: function DeleteTest($testid) 642: { 643: if ($testid=="") return false; 644: $class=$testid[0]; 645: if (is_numeric($class)) 646: { 647: // test ID will stay the same 648: $class="L"; 649: $anytestid=$testid; 650: } 651: else 652: { 653: $anytestid=substr($testid,1); // the classless version 654: } 655: 656: $q=""; 657: switch($class) 658: { 659: case "L": // local tests 660: $q="DELETE FROM fnlocaltest WHERE localtestid=".ss($anytestid); 661: break; 662: case "N": // node-side test 663: $q="DELETE FROM fnnstest WHERE nstestid=".ss($anytestid); 664: break; 665: default: 666: return false; // can't lookup this class 667: } 668: 669: if ($q=="") return false; 670: 671: $this->DB->Query($q); 672: $tests=$this->DB->Affected_Rows(); 673: 674: $rq="DELETE FROM fnrecord WHERE testid=\"".ss($testid)."\""; 675: $this->DB->Query($rq); 676: $records=$this->DB->Affected_Rows(); 677: 678: $eq="DELETE FROM fneval WHERE testid=\"".ss($testid)."\""; 679: $this->DB->Query($eq); 680: $eval=$this->DB->Affected_Rows(); 681: 682: $s="Deleted test ".$testid." (".$tests." tests, ".$records." records, ".$eval." evaluators)"; 683: $this->Event($s,6,"Test","Delete"); 684: } 685: 686: 687: 688: function InvalidateTest($testid,$rightnow=false) 689: { 690: $class=$testid[0]; 691: if (is_numeric($class)) $class="L"; 692: else $testid=substr($testid,1); 693: if ($rightnow) 694: { 695: $nextx=time(); 696: $q="UPDATE "; 697: if ($class=="L") $q.="fnlocaltest"; 698: // other ones here 699: 700: $q.=" SET nextrunx=".$nextx." WHERE "; 701: 702: if ($class=="L") $q.="localtestid=".$testid; 703: // other ones here 704: 705: $this->DB->Query($q); 706: return true; 707: } 708: // otherwise use it's interval 709: $q="SELECT testinterval FROM "; 710: 711: if ($class=="L") $q.="fnlocaltest WHERE localtestid="; 712: // other ones here 713: 714: $q.=$testid; 715: $r=$this->DB->Query($q); 716: if ($row=$this->DB->Fetch_Array($r)) 717: { 718: $this->DB->Free($r); 719: $nextx=next_run_x($row['testinterval']); 720: $q="UPDATE "; 721: if ($class=="L") $q.="fnlocaltest"; 722: // other ones here 723: 724: $q.=" SET nextrunx=".$nextx." WHERE "; 725: 726: if ($class=="L") $q.="localtestid=".$testid; 727: // other ones here 728: 729: $this->DB->Query($q); 730: return true; 731: } 732: return false; 733: } 734: 735: function InvalidateNode($nodeid,$rightnow=false,$testsaswell=false) 736: { 737: if ($rightnow) 738: { 739: $nextx=time(); 740: $q="UPDATE fnnode SET nextrunx=".$nextx." WHERE nodeid=\"".ss($nodeid)."\""; 741: $this->DB->Query($q); 742: if ($testsaswell) 743: { 744: $q="UPDATE fnlocaltest SET nextrunx=".$nextx." WHERE nodeid=\"".ss($nodeid)."\""; 745: $this->DB->Query($q); 746: } 747: return true; 748: } 749: // otherwise set to it's interval 750: $q="SELECT testinterval FROM fnnode WHERE nodeid=\"".ss($nodeid)."\""; 751: $r=$this->DB->Query($q); 752: if ($row=$this->DB->Fetch_Array($r)) 753: { 754: $nextx=next_run_x($row['testinterval']); 755: $uq="UPDATE fnnode SET nextrunx=".$nextx." WHERE nodeid=\"".ss($nodeid)."\""; 756: $this->DB->Query($uq); 757: $this->DB->Free($r); 758: if ($testsaswell) 759: { 760: $uq="UPDATE fnlocaltest SET nextrunx=".$nextx." WHERE nodeid=\"".ss($nodeid)."\""; 761: $this->DB->Query($uq); 762: } 763: return true; 764: } 765: return false; 766: } 767: 768: 769: function NodeSide_Pull($nodeid) 770: { 771: $eventdata=array("nodeid"=>$nodeid,"success"=>false); 772: $q="SELECT nsenabled,nspullenabled,nsurl,nskey,nsinterval FROM fnnode WHERE nodeid=\"".ss($nodeid)."\" LIMIT 0,1"; 773: $r=$this->DB->Query($q); 774: if (!$row=$this->DB->Fetch_Array($r)) return false; 775: 776: $this->DB->Free($r); 777: 778: $url=$row['nsurl']; 779: if ($row['nskey']!="") $url.="?nodekey=".$row['nskey']; 780: //echo $url."\n"; 781: $this->Event("NodeSide_Pull Started for ".$nodeid,10,"Node","Pull"); 782: 783: $xmlobj=new TNodeXML(); 784: 785: $fp=@fopen($url,"r"); 786: if ($fp<=0) 787: { 788: $this->Event("Pull Failed URL ".$url,1,"Node","Pull"); 789: $this->EventHandler("nodeside_pull",$eventdata); 790: return false; 791: } 792: $xml=""; 793: while (!feof($fp)) 794: { 795: $xml.=fgets($fp,4096); 796: } 797: if ($xml=="") 798: { 799: $this->EventHandler("nodeside_pull",$eventdata); 800: return false; 801: } 802: 803: //echo $xml; 804: 805: $result=$xmlobj->Parse($xml); 806: 807: if ($xmlobj->Error()!="") 808: { 809: $this->Event("NodeXML Error: ".$xmlobj->Error(),1,"Node","Pull"); 810: $this->EventHandler("nodeside_pull",$eventdata); 811: return false; 812: } 813: $this->Event("NodeSide_Pull Fetched ".$xmlobj->Tests." tests for ".$nodeid,10,"Node","Pull"); 814: // Now just to actually process it... 815: $eventdata['success']=true; 816: $this->EventHandler("nodeside_pull",$eventdata); 817: $this->NodeSide_Process($nodeid,$xmlobj); 818: return true; 819: } 820: 821: function NodeSide_Process($nodeid,&$xmlobj) 822: { // nodeid + takes a TNodeXML Object 823: $alvl=0; 824: $this->Event("NodeSide_Process for ".$nodeid,10,"Node","Pull"); 825: $q="SELECT * FROM fnnstest WHERE nodeid=\"".ss($nodeid)."\""; 826: $r=$this->DB->Query($q); 827: $tests=array(); 828: while ($row=$this->DB->Fetch_Array($r)) 829: { 830: $tests[$row['testtype']]=$row; 831: if (isset($xmlobj->Catalogue[$row['testtype']])) 832: { // this test is in the DB and catalogue 833: $tests[$row['testtype']]['incat']=true; 834: if ($row['testenabled']==1) // it is enabled - so we test it 835: { 836: if ($row['simpleeval']==1) $level=$xmlobj->Catalogue[$row['testtype']]['ALERTLEVEL']; // use provided level 837: else $level=nats_eval("N".$row['nstestid'],$xmlobj->Catalogue[$row['testtype']]['VALUE']); 838: $dbs="Nodeside ".$row['testtype']." on ".$row['nodeid']." = ".$level; 839: if ($level==0) $debuglev=8; 840: else if ($level>0) $debuglev=5; 841: else $debuglev=2; 842: $this->Event($dbs,$debuglev,"Node","Process"); 843: 844: if ($level>$alvl) $alvl=$level; 845: 846: if ($row['testrecord']==1) // record it 847: { 848: $testvalue=$xmlobj->Catalogue[$row['testtype']]['VALUE']; 849: $testvalue=str_replace(",",".",$testvalue); 850: if (!is_numeric($testvalue)) $testvalue=0; 851: $iq="INSERT INTO fnrecord(testid,alertlevel,recordx,nodeid,testvalue) VALUES("; 852: $iq.="\"N".$row['nstestid']."\",".$level.",".time().",\"".$row['nodeid']."\",".$testvalue.")"; 853: $this->DB->Query($iq); 854: if ($this->DB->Affected_Rows()<=0) 855: $this->Event("Nodeside ".$row['testtype']." Failed to Record",1,"Node","Process"); 856: } 857: 858: // We don't do any alerting here - the tester will do that for us! 859: $uq="UPDATE fnnstest SET lastrunx=".time().",lastvalue=\"".ss($xmlobj->Catalogue[$row['testtype']]['VALUE'])."\",alertlevel=".$level." "; 860: $uq.="WHERE nstestid=".$row['nstestid']; 861: $this->DB->Query($uq); 862: if ($this->DB->Affected_Rows()<=0) 863: $this->Event("Nodeside ".$row['testtype']." Failed to Update or Same Values",5,"Node","Process"); 864: 865: } 866: 867: // check to see if the desc has changed 868: if ($row['testdesc']!=$xmlobj->Catalogue[$row['testtype']]['DESC']) 869: { 870: $duq="UPDATE fnnstest SET testdesc=\"".ss($xmlobj->Catalogue[$row['testtype']]['DESC'])."\" WHERE nstestid=".$row['nstestid']; 871: $this->DB->Query($duq); 872: } 873: 874: } 875: else 876: { 877: // test in the DB but NOT in the catalogue 878: //$xmlobj->Catalogue[$row['testtype']]['incat']=false; 879: if ($row['testenabled']==1) 880: { // enabled so shown in lists etc 881: // Update it to show failed status 882: $this->Event("No nodeside data for test N".$row['nstestid'],3,"Node","Process"); 883: $uq="UPDATE fnnstest SET alertlevel=2,lastvalue=-1 WHERE nstestid=".$row['nstestid']; 884: $this->DB->Query($uq); 885: $alvl=2; 886: if ($row['testrecord']==1) // record it 887: { 888: $testvalue=-1; 889: $iq="INSERT INTO fnrecord(testid,alertlevel,recordx,nodeid,testvalue) VALUES("; 890: $iq.="\"N".$row['nstestid']."\",2,".time().",\"".$row['nodeid']."\",".$testvalue.")"; 891: $this->DB->Query($iq); 892: if ($this->DB->Affected_Rows()<=0) 893: $this->Event("Nodeside ".$row['testtype']." Failed to Record",1,"Node","Process"); 894: } 895: } 896: else // not enabled so simply delete 897: { 898: $this->DeleteTest("N".$row['nstestid']); 899: } 900: } 901: } 902: $this->DB->Free($r); 903: 904: 905: // and finally we look for new tests i.e. in the cat but not in the DB 906: foreach($xmlobj->Catalogue as $val) 907: { 908: $key=$val['NAME']; 909: if (!isset($tests[$key])) // not in the DB 910: { 911: $q="INSERT INTO fnnstest(nodeid,testtype,testdesc,lastvalue,lastrunx,alertlevel) "; 912: $q.="VALUES(\"".ss($nodeid)."\",\"".$key."\",\"".ss($val['DESC'])."\",\"".ss($val['VALUE'])."\",".time().",".ss($val['ALERTLEVEL']).")"; 913: //echo $q."
";
914: $this->DB->Query($q); 915: } 916: } 917: 918: $eventdata=array("nodeid"=>$nodeid,"alertlevel"=>$alvl); 919: $this->EventHandler("nodeside_process",$eventdata); 920: 921: 922: } 923: 924: 925: function AddEventHandler($event,$function) 926: { 927: if (!isset($this->EventHandlers[$event])) $this->EventHandlers[$event]=array(); 928: $this->EventHandlers[$event][]=$function; 929: } 930: 931: function EventHandler($event,$data) 932: { 933: $res=false; 934: if ( isset($data) && is_array($data) ) $data['event']=$event; 935: 936: if (isset($this->EventHandlers[$event])) // handler(s) exist 937: { 938: for($a=0; $aEventHandlers[$event]); $a++) 939: { 940: if (function_exists($this->EventHandlers[$event][$a])) 941: { 942: $this->Event("Event ".$event." -> ".$this->EventHandlers[$event][$a],6,"Event","Handler"); 943: if($this->EventHandlers[$event][$a]($data)) $res=true; // persist true only 944: } 945: else 946: { 947: $t="Illegal Handler ".$this->EventHandlers[$event][$a]." for ".$event; 948: $this->Event($t,2,"Event","Handler"); 949: //return false; 950: } 951: } 952: } 953: else return $res; 954: } 955: 956: } 957: ?>