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

Source Code for Module Products.ZenStatus.ZenTcpClient

  1  ############################################################################## 
  2  #  
  3  # Copyright (C) Zenoss, Inc. 2007, 2009, 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__ = """ZenTcpClient 
 12  Connect to the remote service and (optionally) test the output from 
 13  the service against what we expect. 
 14   
 15  Error types: 
 16   
 17      1. timeout (no connection) 
 18      2. connection refused - port not available on remote end 
 19      3. bad value - value returned did not match expectRegex 
 20   
 21  """ 
 22  import re 
 23  import logging 
 24  log = logging.getLogger("zen.ZenTcpClient") 
 25  from socket import getfqdn 
 26  hostname = getfqdn() 
 27   
 28  from twisted.internet import reactor, protocol, defer 
 29  from Products.ZenEvents.ZenEventClasses import Status_IpService 
 30  from Products.ZenUtils.Utils import unused 
 31   
32 -class ZenTcpTest(protocol.Protocol):
33 """ 34 Twisted class to make a TCP/IP connection to a remote IP service 35 and report back the result. 36 """ 37 defer = None 38 data = "" 39
40 - def connectionMade(self):
41 """ 42 Connected successfully to the remote device, now test against any 43 regex that we might have and record the result. 44 """ 45 log.debug("Connected to %s" % self.transport.getPeer().host) 46 self.factory.msg = "pass" 47 self.cfg = self.factory.cfg 48 49 if self.cfg.sendString: 50 sendString = self.cfg.sendString.decode("string_escape") 51 log.debug("Sending: %s", sendString) 52 self.transport.write(sendString) 53 54 if self.cfg.expectRegex: 55 log.debug("Waiting for results to check against regex '%s'", 56 self.cfg.expectRegex) 57 self.defer = reactor.callLater(self.cfg.timeout, self.expectTimeout) 58 else: 59 self.loseConnection()
60
61 - def dataReceived(self, data):
62 """ 63 Compare the data from the remote device to what we expect in the 64 regex. 65 66 @parameter data: output from remote service 67 @type data: string 68 """ 69 log.debug("%s %s received data: %s", self.cfg.device, 70 self.cfg.component, data) 71 self.data += data 72 if self.cfg.expectRegex: 73 if re.search(self.cfg.expectRegex, data): 74 log.debug("Found %s in '%s' -- closing connection", 75 self.cfg.expectRegex, data) 76 self.loseConnection() 77 else: 78 log.debug("No match for %s in '%s' -- looking for more data", 79 self.cfg.expectRegex, data)
80
81 - def expectTimeout(self):
82 """ 83 Called if we timeout waiting for the service to connect or for 84 receiving a response from the service that matches our regex. 85 """ 86 msg = "IP Service %s TIMEOUT waiting for '%s'" % ( 87 self.cfg.component, self.cfg.expectRegex) 88 log.debug("%s %s", self.cfg.ip, msg) 89 self.factory.msg = msg 90 self.loseConnection()
91
92 - def loseConnection(self):
93 """ 94 Shut down the connection and cleanup. 95 """ 96 ip, port = self.transport.addr 97 log.debug("Closed connection to %s on port %s for %s", 98 ip, port, self.cfg.component) 99 self.data = "" 100 try: 101 self.defer.cancel() 102 except: 103 self.defer = None 104 self.transport.loseConnection()
105 106
107 -class ZenTcpClient(protocol.ClientFactory):
108 """ 109 Client class to run TCP tests. 110 """ 111 protocol = ZenTcpTest 112 msg = "pass" 113 deferred = None 114
115 - def __init__(self, svc, status):
116 self.cfg = svc 117 self.status = status
118
119 - def clientConnectionLost(self, connector, reason):
120 """ 121 Record why the connection to the remote device was dropped. 122 123 @parameter connector: Twisted protocol object 124 @type connector: Twisted protocol object 125 @parameter reason: explanation for the connection loss 126 @type reason: Twisted error object 127 """ 128 unused(connector) 129 errorMsg = reason.getErrorMessage() 130 if errorMsg != 'Connection was closed cleanly.': 131 log.debug("Lost connection to %s (%s) port %s: %s", 132 self.cfg.device, self.cfg.ip, self.cfg.port, 133 reason.getErrorMessage() ) 134 if self.deferred: 135 self.deferred.callback(self) 136 self.deferred = None
137
138 - def clientConnectionFailed(self, connector, reason):
139 """ 140 Record why the connection to the remote device failed. 141 142 @parameter connector: Twisted protocol object 143 @type connector: Twisted protocol object 144 @parameter reason: explanation for the connection loss 145 @type reason: Twisted error object 146 """ 147 log.debug("Connection to %s (%s) port %s failed: %s", 148 self.cfg.device, connector.host, self.cfg.port, 149 reason.getErrorMessage() ) 150 self.msg = "IP Service %s is down" % self.cfg.component 151 if self.deferred: 152 self.deferred.callback(self) 153 self.deferred = None
154
155 - def getEvent(self):
156 """ 157 Called by zenstatus to report status information about a service. 158 159 @return: event of what happened to our service test 160 @rtype: dictionary 161 """ 162 if self.msg == "pass" and self.status > 0: 163 self.status = sev = 0 164 self.msg = "IP Service %s back up" % self.cfg.component 165 166 elif self.msg != "pass": 167 self.status += 1 168 sev = self.cfg.failSeverity 169 170 else: 171 # Send an event even though there's no problem and 172 # nothing to clear __internally__ to zenstatus. 173 # The event console might have an event that will 174 # otherwise never be cleared. 175 # Code higher up discards duplicate clears. 176 self.status = sev = 0 177 self.msg = "IP Service %s back up" % self.cfg.component 178 179 return dict(device=self.cfg.device, 180 component=self.cfg.component, 181 ipAddress=self.cfg.ip, 182 summary=self.msg, 183 severity=sev, 184 eventClass=Status_IpService, 185 eventGroup="TCPTest", 186 agent="ZenStatus", 187 manager=hostname)
188
189 - def start(self, ip_address):
190 """ 191 Called by zenstatus to make a connection attempt to the service. 192 193 @return: Twisted deferred 194 @rtype: Twisted deferred 195 """ 196 d = self.deferred = defer.Deferred() 197 reactor.connectTCP(ip_address, self.cfg.port, self, self.cfg.timeout) 198 return d
199