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