File: 1.09.3a/node/posix/freenats-node.php (View as HTML)

  1: <?php // freenats-node.php
  2: // FreeNATS Push/Pull XML Node for Posix Environments
  3: /* -------------------------------------------------------------
  4: This file is part of FreeNATS
  5: 
  6: FreeNATS is (C) Copyright 2008 PurplePixie Systems
  7: 
  8: FreeNATS is free software: you can redistribute it and/or modify
  9: it under the terms of the GNU General Public License as published by
 10: the Free Software Foundation, either version 3 of the License, or
 11: (at your option) any later version.
 12: 
 13: FreeNATS is distributed in the hope that it will be useful,
 14: but WITHOUT ANY WARRANTY; without even the implied warranty of
 15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16: GNU General Public License for more details.
 17: 
 18: You should have received a copy of the GNU General Public License
 19: along with FreeNATS.  If not, see www.gnu.org/licenses
 20: 
 21: For more information see www.purplepixie.org/freenats
 22: -------------------------------------------------------------- */
 23: 
 24: // Configuration Section
 25: 
 26: $nodeCfg=array();
 27: 
 28: $nodeCfg['allowpull']=true;
 29: $nodeCfg['allowpush']=true;
 30: $nodeCfg['nodekey']="";
 31: $nodeCfg['nodeid']="";
 32: $nodeCfg['restrict_pull_ip']="";
 33: $nodeCfg['push_target']="";
 34: $nodeCfg['tmp_dir']="/tmp/";
 35: 
 36: $nodeCfg['phpscan']=false;
 37: $nodeCfg['phpscandir']="site/";
 38: 
 39: $nodeCfg['xmlscan']=false;
 40: $nodeCfg['xmlscandir']="xml/";
 41: 
 42: $nodeCfg['version']="0.05";
 43: 
 44: $nodeCfg['uptime']	=	true;
 45: $nodeCfg['disk']	=	true;
 46: $nodeCfg['memory']	=	true;
 47: $nodeCfg['net']		=	true;
 48: $nodeCfg['systime']	=	true;
 49: $nodeCfg['process']	=	true;
 50: 
 51: // End of Configuration Section
 52: 
 53: $configFile="config.inc.php";
 54: $fileUpdate=true;
 55: 
 56: // XML Format
 57: /*
 58: Format:
 59: <freenats-data>
 60:  <header>
 61:   <whatever>something</whatever>
 62:  </header>
 63:  <test name=testname>
 64:   <name>testname</name>
 65:   <desc>Test Description</desc>
 66:   <value>return value</value>
 67:   <alertlevel>suggested alert level</alertlevel>
 68:  </test>
 69: </freenats-data>
 70: */
 71: 
 72: class FreeNATS_XML_Node
 73: {
 74: var $xml="";
 75: var $Config;
 76: 
 77: function AddLine($line)
 78: {
 79: $this->xml.=$line."\n";
 80: }
 81: 
 82: function AddTest($name,$desc,$val,$lvl=-1)
 83: {
 84: $this->AddLine("");
 85: $this->AddLine(" <test NAME=\"".$name."\">");
 86: $this->AddLine("  <name>".$name."</name>");
 87: $this->AddLine("  <desc>".$desc."</desc>");
 88: $this->AddLine("  <value>".$val."</value>");
 89: $this->AddLine("  <alertlevel>".$lvl."</alertlevel>");
 90: $this->AddLine(" </test>");
 91: $this->AddLine("");
 92: }
 93: 
 94: function FreeNATS_XML_Node()
 95: {
 96: global $nodeCfg;
 97: $this->AddLine("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
 98: $this->Config=&$nodeCfg;
 99: }
100: 
101: function Start()
102: {
103: $this->AddLine("<freenats-data>");
104: }
105: 
106: function Stop()
107: {
108: $this->AddLine("</freenats-data>");
109: }
110: 
111: function DataHeader($is_header=true)
112: {
113: if ($is_header) $this->AddLine(" <header>");
114: else $this->AddLine(" </header>");
115: }
116: 
117: function HeaderItem($name,$value)
118: {
119: $this->AddLine("  <".$name.">".$value."</".$name.">");
120: }
121: 
122: function ScreenOutput()
123: {
124: header("Content-type: text/xml");
125: echo $this->xml;
126: exit();
127: }
128: 
129: }
130: 
131: $Node=new FreeNATS_XML_Node();
132: $Node->Start();
133: 
134: 
135: // How Were We Called
136: $pull=false;
137: 
138: if (isset($_SERVER['REMOTE_ADDR'])) // called via HTTP
139: 	{
140: 	$pull=true;
141: 	if ($nodeCfg['restrict_pull_ip']!="") // check IP
142: 		{
143: 		if ($_SERVER['REMOTE_ADDR']!=$nodeCfg['restrict_pull_ip'])
144: 			{
145: 			echo "Authorisation Failure: IP Address Denied";
146: 			exit();
147: 			}
148: 		}
149: 	if ($nodeCfg['nodekey']!="") // check authorisation
150: 		{
151: 		if ( !(isset($_REQUEST['nodekey'])) || ($_REQUEST['nodekey']!=$nodeCfg['nodekey']) )
152: 			{
153: 			echo "Authorisation Failure: Incorrect NODEKEY Configured";
154: 			exit();
155: 			}
156: 		}
157: 	if (isset($_REQUEST['noupdate']) && ($_REQUEST['noupdate']==1)) $fileUpdate=false;
158: 	}	
159: else // called via CLI
160: 	{
161: 	$a=1;
162: 	for ($a=1; $a<$argc; $a++)
163: 		{
164: 		switch($argv[$a])
165: 			{
166: 			case "-c": case "--c": case "-config": case "--config":
167: 			 $configFile=$argv[++$a];
168: 			 break;
169: 			case "-d": case "--d": case "-debug": case "--debug":
170: 			 $pull=true; // output to the console
171: 			 break;
172: 			case "--noupdate": case "-noupdate":
173: 			 $fileUpdate=false;
174: 			 break;
175: 		 	}
176: 	 	}
177:  	}
178:  	
179: if ($configFile!="") require($configFile);
180: 
181: 
182: $Node->DataHeader();
183: $Node->HeaderItem("name","FreeNATS Posix Node XML");
184: $Node->HeaderItem("version",$nodeCfg['version']);
185: if (!$pull) // we are pushing instead
186: 	$Node->HeaderItem("nodekey",$nodeCfg['nodekey']);
187: $Node->DataHeader(false);
188: 
189: // Node Type and Version Pseudo-Tests
190: $Node->AddTest("fnn.version","FreeNATS Node Version",$nodeCfg['version'],0);
191: $Node->AddTest("fnn.name","FreeNATS Node Type","Posix XML",0);
192: 
193: //$Node->AddTest("bob.one","Bob One",10,0);
194: //$Node->AddTest("bob.two","Bob Two",11,0);
195: 
196: 
197: // Data from Uptime
198: if ($nodeCfg['uptime'])
199: {
200: $uptime=exec("/usr/bin/uptime");
201: 
202: $ut=preg_split("/\s+/",$uptime);
203: //var_dump($ut);
204: 
205: 
206: 
207: $Node->AddTest("uptime.1m","One Minute Load Average",substr($ut[count($ut)-3],0,strlen($ut[count($ut)-3])-1),0);
208: $Node->AddTest("uptime.5m","Five Minute Load Average",substr($ut[count($ut)-2],0,strlen($ut[count($ut)-2])-1),0);
209: $Node->AddTest("uptime.15m","Fifteen Minute Load Average",$ut[count($ut)-1],0);
210: $Node->AddTest("uptime.users","Logged in Users",$ut[count($ut)-7],0);
211: }
212: 
213: // Data from Time
214: if ($nodeCfg['systime'])
215: {
216: $nowx=time();
217: $utf=date("Y-m-d H:i:s",$nowx);
218: $dts=date("H:i:s d/m/Y",$nowx);
219: $pasthour= (date("i",$nowx)*60)+date("s",$nowx);
220: 
221: $Node->AddTest("systime.x","Node Time (Seconds Since Epoch)",$nowx,0);
222: $Node->AddTest("systime.utf","Node Time (UTF)",$utf,0);
223: $Node->AddTest("systime.dts","Note Time",$dts,0);
224: $Node->AddTest("systime.sph","Seconds Past Hour",$pasthour,0);
225: }
226: 
227: // ------------------ DISK SPACE
228: 
229: // Data from DF
230: if ($nodeCfg['disk'])
231: {
232:  $result=array();
233:   exec("/bin/df -P",$result);
234:  
235:   // filesystem blocks used available use% mount
236:   for ($a=1; $a<count($result); $a++)
237:    {
238:    $parts=preg_split("/\s+/",$result[$a]);
239:    if (count($parts)>4) // not a duff line
240:    		{
241: 		$filesystem=$parts[0];
242: 		$size=$parts[1]/1024;
243: 		$used=$parts[2]/1024;
244: 		$free=$parts[3]/1024;
245: 	   	$perc=substr($parts[4],0,(strlen($parts[4])-1));
246: 		$percfree=100-$perc;
247: 	   	$mount=$parts[5];
248: 		
249: 		if ($perc >= 90) $alertlevel=2; // failed
250: 		else if ($perc >= 80) $alertlevel=1; // warning
251: 		else $alertlevel=0; // passed
252: 	  
253: 	   //$nicefs=str_replace("/","_",$filesystem);
254: 	   $name=$filesystem.".size";
255: 	   $desc="Total Size of ".$filesystem." (".$mount.") (Mb)";
256: 	   $Node->AddTest($name,$desc,round($size,2),$alertlevel);
257: 	   
258: 	   $name=$filesystem.".used";
259: 	   $desc="Space Used on ".$filesystem." (".$mount.") (Mb)";
260: 	   $Node->AddTest($name,$desc,round($used,2),$alertlevel);
261: 	   
262: 	   $name=$filesystem.".free";
263: 	   $desc="Space Free on ".$filesystem." (".$mount.") (Mb)";
264: 	   $Node->AddTest($name,$desc,round($free,2),$alertlevel);
265: 	   
266: 	   $name=$filesystem.".perc";
267: 	   $desc="Percentage Used on ".$filesystem." (".$mount.")";
268: 	   $Node->AddTest($name,$desc,$perc,$alertlevel);
269: 	
270: 	   $name=$filesystem.".percfree";
271: 	   $desc="Percentage Free on ".$filesystem." (".$mount.")";
272: 	   $Node->AddTest($name,$desc,$percfree,$alertlevel);
273: 		}
274:    }
275: }
276: 	
277: 
278: 
279: // ------------------ RAM
280: // Data from FREE
281: if ($nodeCfg['memory'])
282: {
283: 
284:  
285:   $free=array();
286:   exec("/usr/bin/free",$free);
287:   
288:   //unset($this->mm_elements);
289: 
290:   for ($fc=1; $fc< count($free); $fc++)
291:    {
292:    // Mem: Swap:   -- total, used, free -- kb
293:    $parts=preg_split("/\s+/",$free[$fc]);
294:    $proc=false;
295:    if ($parts[0]=="Mem:") { $proc=true; $type="System Memory"; $prefix="mem"; }
296:    else if ($parts[0]=="Swap:") { $proc=true; $type="System Swap File"; $prefix="swap"; }
297:    /*
298:    else 
299:    	{
300: 	   echo $free[$fc]."\n";
301: 	   exit();
302:   }*/
303:    
304:    if ($proc)
305:     {
306: 	$total=round($parts[1]/1024,3);
307: 	$usedmb=round($parts[2]/1024,3);
308: 	$freemb=round($parts[3]/1024,3);
309: 	$used_perc=0;
310: 	$free_perc=0;
311: 	if ($total>0)
312: 		{
313: 		if ($used>0) $used_perc=round (($usedmb/$total)*100,2);
314: 		if ($free>0) $free_perc=round (($freemb/$total)*100,2);
315: 		}
316: 	$name=$prefix.".total";
317: 	$Node->AddTest($name,$type." Total (Mb)",$total,0);
318: 
319: 		
320: 	$name=$prefix.".used"; // parts[2] used kb
321: 	$Node->AddTest($name,$type." Used (Mb)",$usedmb,0);
322: 		
323: 	$name=$prefix.".free"; // parts[3] free kb
324: 	$Node->AddTest($name,$type." Free (Mb)",$freemb,0);
325: 	
326: 	$name=$prefix.".free.perc";
327: 	$Node->AddTest($name,$type." Free (%)",$free_perc,0);
328: 	
329: 	$name=$prefix.".used.perc";
330: 	$Node->AddTest($name,$type." Used (%)",$used_perc,0);
331:     } // end of if $proc
332:     
333:    } // end of for
334:  
335: }
336: 
337: 
338: 
339: // ------------------ NETWORK USAGE
340: // Data from /proc/net/dev
341: if ($nodeCfg['net'])
342: {
343: $netarr=@file("/proc/net/dev");
344: for($a=2; $a<count($netarr); $a++)
345: 	{
346: 	$line=explode(":",$netarr[$a]);
347: 	$dev=trim($line[0]);
348: 	$data=trim($line[1]);
349: 	$darr=preg_split("/[\s]+/",$data);
350: 	//print_r($darr);
351: 	//exit();
352: 	$rx=trim($darr[0]);
353: 	$tx=trim($darr[8]);
354: 	if ($rx=="") $rx=0; // bodge
355: 	if ($tx=="") $tx=0;
356: 	$tt=$tx+$rx;
357: 	
358: 	$Node->AddTest("net.".$dev.".rxt","Total Received on Interface ".$dev." (bytes)",$rx,0);
359: 	$Node->AddTest("net.".$dev.".txt","Total Sent on Interface ".$dev." (bytes)",$tx,0);
360: 	$Node->AddTest("net.".$dev.".trt","Total Passed on Interface ".$dev." (bytes)",$tt,0);
361: 	
362: 	$trrx=0;
363: 	$trtx=0;
364: 	$trtt=0;
365: 	$trlvl=0;
366: 	
367: 	$nowx=time();
368: 	// does the file exist
369: 	$fp=fopen($nodeCfg['tmp_dir']."fnnode.net.".$dev,"r");
370: 	if ($fp>0) // yes
371: 		{
372: 		$lastx=trim(fgets($fp,128));
373: 		$lrx=trim(fgets($fp,128));
374: 		$ltx=trim(fgets($fp,128));
375: 		$ltt=$lrx+$ltx;
376: 		// wrap checking and the like...
377: 		if ( ($lrx>$rx) ) //|| ($ltx>$tx) || ($ltt>$tt) )
378: 			{
379: 			$trlvl=-1; // untested
380: 			$diffx=0;
381: 			//echo "untested ".trim($lrx)."-$rx";
382: 			}
383: 		else // test it
384: 			{
385: 			$diffx=$nowx-$lastx;
386: 			if ($diffx>0)
387: 				{
388: 				$trrx=(($rx-$lrx)/$diffx)/1024;
389: 				$trtx=(($tx-$ltx)/$diffx)/1024;
390: 				$trtt=(($tt-$ltt)/$diffx)/1024;
391: 				}
392: 			if($trrx=="") $trrx=0;
393: 			if($trtx=="") $trtx=0;
394: 			if($trtt=="") $trtt=0;
395: 			}
396: 		}
397: 	else $trlvl=-1;
398: 	@fclose($fp);
399: 	
400: 	// write my file
401: 	if ($fileUpdate)
402: 		{
403: 		//echo "Writing Files!\n";
404: 		$fp=fopen($nodeCfg['tmp_dir']."fnnode.net.".$dev,"w");
405: 		fputs($fp,$nowx."\n");
406: 		fputs($fp,$rx."\n");
407: 		fputs($fp,$tx."\n");
408: 		fclose($fp);
409: 		}
410: 		
411: 	$Node->AddTest("net.".$dev.".rx","Receive Speed on ".$dev." (kbyte/s)",$trrx,$trlvl);
412: 	$Node->AddTest("net.".$dev.".tx","Transmit Speed on ".$dev." (kbyte/s)",$trtx,$trlvl);
413: 	$Node->AddTest("net.".$dev,"Combined Speed on ".$dev." (kbyte/s)",$trtt,$trlvl);
414: 	$Node->AddTest("net.".$dev.".elapsed","Speed Sample Time on ".$dev." (secs)",$diffx,$trlvl);
415: 	}
416: }
417: 	
418: // ------------------ PROCESS INFORMATION
419: if ($nodeCfg['process'])
420: 	{
421: 	$ps=array();
422: 	exec("/bin/ps -e -w",$ps);
423: 	
424: 	$pdata=array();
425: 	//foreach($ps as $psl)
426: 	for ($z=1; $z<count($ps); $z++)
427: 		{
428: 		$psl=$ps[$z];
429: 		$lineparts=preg_split("/\s+/",$psl);
430: 		$parts=array();
431: 		for ($a=0; $a<count($lineparts); $a++)
432: 			{
433: 			if ($lineparts[$a]!="") $parts[]=$lineparts[$a];
434: 			}
435: 		//echo $psl."\n";
436: 		// pid pts time name
437: 		//echo "[".$parts[0]."] ";
438: 		//echo "[".$parts[1]."] ";
439: 		//echo "[".$parts[2]."] ";
440: 		//echo "[".$parts[3]."]\n";
441: 		
442: 		$pname=$parts[3];
443: 		if (isset($pdata[$pname])) $pdata[$pname]++;
444: 		else $pdata[$pname]=1;
445: 		}
446: 	
447: 	foreach($pdata as $key=>$val)
448: 		{
449: 		$Node->AddTest("ps.".$key,"Number of ".$key." Processes",$val,0);
450: 		}
451: 	}
452: 	
453: 
454: // ------------------ END OF TEST DATA
455: 
456: 
457: // End FreeNATS Data
458: $Node->Stop();
459: 
460: if ($pull)
461: 	{
462: 	// Output Data to Screen
463: 	$Node->ScreenOutput();
464: 	}
465: else // push
466: 	{
467: 	// PHP 5 Required
468: 	$data=array( "nodeid" => $nodeCfg['nodeid'],
469: 		"nodekey" => $nodeCfg['nodekey'],
470: 		"xml" => $Node->xml );
471: 	$data=http_build_query($data);
472: 	
473: 	$request=array( "http" => array( "method" => "POST",
474: 		"header" => "Content-type: application/x-www-form-urlencoded", "content" => $data ) );
475: 	$context=stream_context_create($request);
476: 	$fp=fopen($nodeCfg['push_target'],'rb',false,$context);
477: 	if ($fp<=0)
478: 		{
479: 		echo "Push Failed to open URL\n";
480: 		exit();
481: 		}
482: 	$serverdata=@stream_get_contents($fp);
483: 	
484: 	if ($serverdata===false)
485: 		{
486: 		echo "Push Data is FALSE\n";
487: 		exit();
488: 		}
489: 		
490: 	if ($serverdata!="1")
491: 		{
492: 		echo "Server Returned Error: ".$serverdata."\n";
493: 		exit();
494: 		}
495: 		
496: 	echo "Push Succeeded\n";
497: 	}
498: 		
499: ?>
500: