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