Package ZenStatus :: Module pingjob
[hide private]
[frames] | no frames]

Source Code for Module ZenStatus.pingjob

  1  ########################################################################### 
  2  # 
  3  # This program is part of Zenoss Core, an open source monitoring platform. 
  4  # Copyright (C) 2007, Zenoss Inc. 
  5  # 
  6  # This program is free software; you can redistribute it and/or modify it 
  7  # under the terms of the GNU General Public License version 2 as published by 
  8  # the Free Software Foundation. 
  9  # 
 10  # For complete information please visit: http://www.zenoss.com/oss/ 
 11  # 
 12  ########################################################################### 
 13   
 14  ''' pingmonitor 
 15  creates a queue of hosts to be pinged (jobs), 
 16  and pings them until they respond, or the 
 17  maximum number of pings has been sent. After 
 18  sending out all these pings, we loop in a 
 19  receive function processing everything we get 
 20  back''' 
 21   
 22  import socket 
 23  import ip 
 24  import icmp 
 25  import os 
 26  import pprint 
 27  import time 
 28  import select 
 29  import sys 
 30   
31 -class PingJob:
32 '''Class representing a single 33 target to be pinged''' 34
35 - def __init__(self,host):
36 self._host = host 37 self._rtt = 0 38 self._start = 0 39 self._end = 0 40 self._sent = 0
41
42 - def reset(self):
43 self._rtt = 0 44 self._start = 0 45 self._end = 0 46 self._sent = 0
47
48 - def getOrSet(self, attr, value=None):
49 if value: 50 setattr(self, attr, value) 51 else: 52 return getattr(self, attr)
53
54 - def host(self, value=None):
55 return self.getOrSet('_host', value)
56
57 - def rtt(self, value=None):
58 return self.getOrSet('_rtt', value)
59
60 - def start(self, value=None):
61 return self.getOrSet('_start', value)
62
63 - def end(self, value=None):
64 return self.getOrSet('_end', value)
65
66 - def sent(self, value=None):
67 return self.getOrSet('_sent', value)
68
69 -class PingMonitor:
70 - def __init__(self, timeout=0.25, tries=3, chunk=25):
71 self._jobQueue = {} 72 self._resultQueue = [] 73 self._id = os.getpid() 74 self._timeOut = timeout 75 self._tries = tries 76 self._chunkSize = chunk 77 self._socket = self._createSocket()
78
79 - def _createSocket(self):
80 family = socket.AF_INET 81 type = socket.SOCK_RAW 82 proto = socket.IPPROTO_ICMP 83 sock = socket.socket(family, type, proto) 84 sock.setblocking(1) 85 return sock
86
87 - def _setQueue(self, queueDict):
88 self._jobQueue = queueDict
89
90 - def addTarget(self, target):
91 try: 92 target = socket.gethostbyname(target) 93 except: 94 pass 95 self._jobQueue[target] = PingJob(target)
96
97 - def sendPings(self, queue):
98 for target in self._jobQueue.values(): 99 self.sendPacket(target, queue)
100
101 - def recvPings(self, queue):
102 timeOut = self._timeOut 103 startTime = time.time() 104 while 1: 105 rd = select.select( 106 [self._socket], 107 [], 108 [], 109 self._timeOut) 110 if rd[0]: 111 (icmppkt, ippkt) = self.recvPacket() 112 source = ippkt.src 113 if queue.has_key(source): 114 jobObj = queue[source] 115 jobObj.end(time.time()) 116 jobObj.rtt( 117 jobObj.end() - jobObj.start()) 118 self._resultQueue.append(jobObj) 119 del queue[source] 120 timeOut = (startTime + self._timeOut) - time.time() 121 if (not len(queue.keys()) 122 or timeOut < 0): 123 # loop everything in job queue 124 # move everything whose _sent is greater 125 # than or equal to _tries to result queue 126 # as failure 127 for item in queue.values(): 128 if item.sent() >= self._tries: 129 item.rtt(0.0) 130 self._resultQueue.append(item) 131 del queue[item.host()] 132 break
133
134 - def sendPacket(self, target, queue):
135 pkt = icmp.Packet() 136 pkt.type = icmp.ICMP_ECHO 137 pkt._id = self._id 138 pkt.seq = target.sent() 139 pkt.data = 'Confmon connectivity test' 140 buf = icmp.assemble(pkt) 141 target.start(time.time()) 142 #### sockets with bad addresses fail 143 try: 144 self._socket.sendto(buf, (target.host(), 0)) 145 except: 146 target.rtt(0.0) 147 self._resultQueue.append(target) 148 del queue[target.host()] 149 target.sent(pkt.seq + 1)
150
151 - def recvPacket(self):
152 data = self._socket.recv(4096) 153 if data: 154 ipreply = ip.Packet(data) 155 try: 156 reply = icmp.Packet(ipreply.data) 157 except: 158 return 159 return (reply, ipreply)
160
161 - def display(self):
162 for result in self._resultQueue: 163 if result.rtt() == 0.0: 164 print "Host %s :: Sent %s :: FAILED" % ( 165 result.host(), 166 result.sent()) 167 else: 168 print "Host %s :: Sent %s :: RTT %s" % ( 169 result.host(), 170 result.sent(), 171 result.rtt())
172
173 - def setTargets(self, chunk):
174 '''set jobQueue = chunks 175 remove good pings, 176 leave bad pings until 177 exceed _tries''' 178 for ping in self._jobQueue.values(): 179 if ping.sent() >= self._tries: 180 ping.rtt(0.0) 181 del self._jobQueue[ping.host()] 182 self._resultQueue.append(ping) 183 184 for target in chunk: 185 self._jobQueue[target] = PingJob(target)
186
187 - def _getChunk(self):
188 chunk = {} 189 targets = self._jobQueue.values() 190 print len(targets), "LEN" 191 print len(targets) % self._chunkSize 192 if len(targets) % self._chunkSize: 193 for _ in range(len(targets) % self._chunkSize): 194 t = targets.pop() 195 chunk[t.host()] = t 196 else: 197 while targets: 198 for _ in range(self._chunkSize): 199 t = targets.pop() 200 chunk[t.host()] = t 201 return chunk
202
203 - def run(self, targets):
204 '''put failed targets into result queue 205 loop over chunks and call doChunk 206 for each''' 207 208 self.setTargets(targets) 209 while 1: 210 chunk = self._getChunk() 211 if not chunk: 212 break 213 else: 214 print "HERE" 215 # overwriting with one target... 216 self.sendPings(chunk) 217 self.recvPings(chunk)
218 219 220 if __name__=='__main__': 221 # make sure we have wall time on windows 222 if sys.platform == 'win32': 223 time.time = time.clock 224 225 fp = open(sys.argv[1],'r') 226 startTime = time.time() 227 targets = [] 228 x = PingMonitor(chunk=2) 229 for target in fp.readlines(): 230 targets.append(target[:-1]) 231 x.run(targets) 232 x.display() 233 endTime=time.time() 234 print endTime-startTime 235