File: 1.09.0a/server/base/freenats.inc.php (View as Code)

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