File: 1.01.5b/server/base/freenats.inc.php (View as Code)

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