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