Package Products :: Package ZenStatus :: Package nmap :: Module PingResult
[hide private]
[frames] | no frames]

Source Code for Module Products.ZenStatus.nmap.PingResult

  1  ############################################################################## 
  2  #  
  3  # Copyright (C) Zenoss, Inc. 2011, all rights reserved. 
  4  #  
  5  # This content is made available according to terms specified in 
  6  # License.zenoss under the directory where your Zenoss product is installed. 
  7  #  
  8  ############################################################################## 
  9   
 10   
 11  __doc__ = """PingResult 
 12   
 13  Utilities to parse nmap output and represent results. 
 14  """ 
 15   
 16  import collections 
 17  import math 
 18  from lxml import etree 
 19   
 20  import Globals 
 21  from zope import interface 
 22  from Products.ZenStatus import interfaces, TraceHop 
 23   
 24  import logging 
 25  from traceback import format_exc 
 26  log = logging.getLogger("zen.nmap") 
 27   
 28  _STATE_TO_STRING_MAP = { True: 'up', False: 'down'} 
 29  _NAN = float('nan') 
 30  _NO_TRACE = tuple() 
31 32 -def parseNmapXml(input):
33 """ 34 Parse the XML output of nmap and return a list PingResults. 35 """ 36 results = [] 37 parseTree = etree.parse(input) 38 for hostTree in parseTree.xpath('/nmaprun/host'): 39 result = PingResult.createNmapResult(hostTree) 40 results.append(result) 41 return (results)
42
43 -def parseNmapXmlToDict(input):
44 """ 45 Parse the XML output of nmap and return a dict of PingResults indexed by IP. 46 """ 47 rdict = {} 48 for result in parseNmapXml(input): 49 rdict[result.address] = result 50 return rdict
51
52 53 -class PingResult(object):
54 """ 55 Model of an nmap ping/traceroute result. 56 """ 57 interface.implements(interfaces.IPingResult) 58 59 @staticmethod
60 - def createNmapResult(hostTree):
61 """ 62 Contruct an PingResult from an XML parse tree for a host entry. 63 """ 64 if getattr(hostTree, 'xpath', None) is None: 65 raise ValueError("hostTree must be of lxml.etree.Element type") 66 pr = PingResult("unknown") 67 pr._address = pr._parseAddress(hostTree) 68 pr._timestamp = pr._parseTimestamp(hostTree) 69 pr._isUp, reason = pr._parseState(hostTree) 70 if reason == 'localhost-response': 71 pr._rtt, pr._rttVariace = (0, 0) 72 else: 73 try: 74 pr._rtt, pr._rttVariance = pr._parseTimes(hostTree) 75 except Exception as ex: 76 traceback = format_exc() 77 log.debug("Error parsing times %s %s " % (ex, traceback)) 78 pr._rtt, pr._rttVariace = (_NAN, _NAN) 79 try: 80 pr._trace = pr._parseTraceroute(hostTree) 81 except Exception as ex: 82 traceback = format_exc() 83 log.debug("Error parsing trace routes %s %s " % (ex, traceback)) 84 pr._trace = _NO_TRACE 85 return pr
86
87 - def __init__(self, address, timestamp=None, isUp=False, 88 rtt=_NAN, stddev=_NAN, trace=_NO_TRACE):
89 self._address = address 90 self._timestamp = timestamp 91 self._isUp = isUp 92 self._rtt = rtt 93 self._rttVariance = stddev * stddev 94 self._trace = trace
95
96 - def _parseTimestamp(self, hostTree):
97 """ 98 Extract timestamp if it exists. 99 """ 100 try: 101 timestamp = None 102 starttime = hostTree.attrib.get('starttime', None) 103 if starttime is not None: 104 timestamp = int(starttime) 105 except KeyError: 106 return None 107 except Exception as ex: 108 traceback = format_exc() 109 log.debug("Error parsing timestamp %s %s " % (ex, traceback)) 110 return timestamp
111
112 - def _parseTimes(self, hostTree):
113 """ 114 Extract round trip time from the hostTree. 115 """ 116 times = hostTree.xpath('times') 117 if len(times) != 1: 118 raise ValueError("no times found for hostTree") 119 timesNode = times[0] 120 rtt = timesNode.attrib['srtt'] 121 rtt = float(rtt) / 1000.0 # given in milli sec, convert to secs 122 rttVariance = timesNode.attrib['rttvar'] 123 rttVariance = float(rttVariance) / 1000.0 124 return (rtt, rttVariance)
125
126 - def _parseAddress(self, hostTree):
127 """ 128 Extract the address (ip) from the hostTree. 129 """ 130 131 addressNodes = hostTree.xpath("address[@addrtype='ipv4']") 132 if len(addressNodes) != 1: 133 addressNodes = hostTree.xpath("address[@addrtype='ipv6']") 134 if len(addressNodes) != 1: 135 raise ValueError("hostTree does not have address node") 136 addressNode = addressNodes[0] 137 address = addressNode.attrib['addr'] 138 return address
139
140 - def _parseState(self, hostTree):
141 """ 142 Extract the host status from hostTree: return True if up, False if down. 143 """ 144 statusNodes = hostTree.xpath('status') 145 if len(statusNodes) != 1: 146 raise ValueError("hostTree does not have status node") 147 statusNode = statusNodes[0] 148 state = statusNode.attrib['state'] 149 isUp = state.lower() == 'up' 150 reason = statusNode.attrib.get('reason', 'unknown') 151 return (isUp, reason)
152
153 - def _parseTraceroute(self, hostTree):
154 """ 155 Extract the traceroute hops from hostTree in to a list that 156 preserves the hop order and saves the hop rtt. 157 """ 158 hops = [] 159 traceNodes = hostTree.xpath('trace') 160 if len(traceNodes) != 1: 161 return tuple() # no traceroute info in output file 162 traceNode = traceNodes[0] 163 hopNodes = traceNode.xpath('hop') 164 if len(hopNodes) < 1: 165 raise ValueError("hostTree does not have a trace/hop nodes") 166 for hopNode in hopNodes: 167 ipaddr = hopNode.attrib['ipaddr'] 168 rtt = float(hopNode.attrib['rtt']) 169 hops.append(TraceHop(ip=ipaddr, rtt=rtt)) 170 return hops
171 172 @property
173 - def timestamp(self):
174 """Timestamp of when ping was returned (seconds since epoch).""" 175 return self._timestamp
176 177 @property
178 - def address(self):
179 """Address of the host""" 180 return self._address
181 182 @property
183 - def trace(self):
184 """traceroute of the host""" 185 return tuple(self._trace)
186
187 - def getStatusString(self):
188 """status string: up or down""" 189 return _STATE_TO_STRING_MAP[self._isUp]
190
191 - def __repr__(self):
192 return "PingResult [%s, %s]" % (self._address, self.getStatusString())
193 194 @property
195 - def isUp(self):
196 """true if host is up, false if host is down""" 197 return self._isUp
198 199 @property
200 - def rtt(self):
201 """round trip time aka ping time aka rtt; nan if host was down""" 202 return self._rtt
203 204 @property
205 - def variance(self):
206 """variance of the rtt; nan if host was down""" 207 return self._rttVariance
208 209 @property
210 - def stddev(self):
211 """standard deviation of the rtt; nan if host was down""" 212 math.sqrt(self._rttVariance)
213 214 if __name__ == '__main__': 215 216 import os.path 217 nmap_testfile = os.path.dirname( 218 os.path.realpath(__file__)) + '/../tests/nmap_ping.xml' 219 results = parseNmapXml(nmap_testfile) 220 for result in results: 221 print result 222 for hop in result.trace: 223 print " ->", hop 224