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