Package DataCollector :: Module SshSession
[hide private]
[frames] | no frames]

Source Code for Module DataCollector.SshSession

  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  from twisted.conch.ssh import transport, userauth, connection, common, keys, channel 
 15  from twisted.internet import defer, protocol, reactor 
 16  from twisted.python import log 
 17  import struct, sys, getpass, os 
 18   
 19  import logging 
 20   
 21  # BROKEN: these were unknown globals! 
 22  #  - keeps pyflakes quiet 
 23  USER, HOST = None, None 
 24   
 25  from Exceptions import NoValidConnection, LoginFailed, CommandTimeout, CommandNotFound 
 26   
27 -class SshSession:
28
29 - def __init__(self, searchPath=[], existenceCheck='test -f %s', 30 options=None, context=None, log=None):
31 32 self.searchPath = searchPath 33 self.existenceCheck = existenceCheck 34 35 if log: 36 self.log = log 37 else: 38 logging.basicConfig() 39 self.log = logging.getLogger(self.__class__.__name__) 40 if options: self.log.setLevel(options.logseverity)
41 42
43 - def check(self, hostname, timeout=1):
44 "check to see if a device supports ssh" 45 from telnetlib import Telnet 46 import socket 47 try: 48 tn = Telnet(hostname, 22) 49 index, match, data = tn.expect(['SSH',], timeout) 50 tn.close() 51 if index == 0: return 1 52 except socket.error: 53 return 0
54
55 - def connect(self, hostname, username=None, password=None):
56 "login to a machine using ssh" 57 pass
58 59
60 - def execute(self, command, timeout=None):
61 """run a command that will be found by our path if it has been passed 62 and return its output""" 63 fullcommand = self.findFullCommand(command) 64 if fullcommand: 65 return self._execute(fullcommand, timeout) 66 else: 67 raise CommandNotFound, "unable to find command '%s'" % command
68 69
70 - def _execute(self, command, timeout=None):
71 "run a command using the shell path and return its output" 72 pass
73 74
75 - def disconnect(self):
76 "close the telnet session" 77 pass
78 79
80 - def findFullCommand(self, command):
81 "look through the path list to find the full path to this command" 82 if not self.searchPath: return command 83 if type(self.searchPath) == type(''): 84 self.searchPath = self.searchPath.split(":") 85 basecmd = command.split()[0] #remove args 86 for path in self.searchPath: 87 fullcmd = os.path.join(path, basecmd) 88 self._execute(self.existenceCheck % fullcmd) 89 if int(self._execute("echo $?")) == 0: 90 return os.path.join(path, command) 91 self.log.warn('unable to find command %s in search path %s' % 92 (self.searchPath, command))
93 94 95 96 97
98 -class SimpleTransport(transport.SSHClientTransport):
99 - def verifyHostKey(self, hostKey, fingerprint):
100 print 'host key fingerprint: %s' % fingerprint 101 return defer.succeed(1)
102
103 - def connectionSecure(self):
104 # where is USER defined? 105 self.requestService(SimpleUserAuth(USER,SimpleConnection()))
106 107 108
109 -class SimpleUserAuth(userauth.SSHUserAuthClient):
110 - def getPassword(self):
111 # where is HOST defined? 112 return defer.succeed( 113 getpass.getpass("%s@%s's password: " % (USER, HOST)))
114
115 - def getPublicKey(self):
116 log.debug('Getting Public Key from %s' % self.factory.keyPath) 117 path = os.path.expanduser(self.factory.keyPath) 118 # this works with rsa too 119 # just change the name here and in getPrivateKey 120 if not os.path.exists(path) or hasattr(self, 'lastPublicKey'): 121 # the file doesn't exist, or we've tried a public key 122 return 123 return keys.getPublicKeyString(path+'.pub')
124
125 - def getPrivateKey(self):
126 log.debug('Getting Private Key from %s' % self.factory.keyPath) 127 path = os.path.expanduser(self.factory.keyPath) 128 return defer.succeed(keys.getPrivateKeyObject(path))
129 130
131 -class SimpleConnection(connection.SSHConnection):
132 - def serviceStarted(self):
133 for cmd in self.commands: 134 ch = CommandChannel(2**16, 2**15, self) 135 ch.command = cmd 136 self.openChannel(ch)
137 138
139 -class FindCmdChannel(channel.SSHChannel):
140
141 - def openFailed(self, reason):
142 print 'find command %s in path %s failed: %s' % (self.command, self.path, reason)
143
144 - def channelOpen(self, ignoredData):
145 self.conn.sendRequest(self, 'exec', common.NS(''))
146
147 - def request_exit_status(self, data):
148 status = struct.unpack('>L', data)[0] 149 if not status: 150 fpcommand = 0 151 self.loseConnection()
152 153 154 155
156 -class CommandChannel(channel.SSHChannel):
157 name = 'session' 158
159 - def openFailed(self, reason):
160 self.log.warn('open of %s failed: %s' % (self.command, reason))
161
162 - def channelOpen(self, ignoredData):
163 #self.command = '/bin/netstat -an' 164 self.data = '' 165 d = self.conn.sendRequest(self, 'exec', 166 common.NS(self.command), wantReply = 1)
167 # d.addCallback(self._cbRequest) 168 169 #def _cbRequest(self, ignored): 170 # self.conn.sendEOF(self) 171
172 - def dataReceived(self, data):
173 self.data += data
174
175 - def closed(self):
176 #print 'command %s data: %s' % (self.command, repr(self.data)) 177 self.loseConnection() 178 self.results.append(self.data) 179 if len(self.results) == len(self.commands): 180 reactor.stop()
181 182 183 #import pprint 184 #for HOST in hosts: 185 # protocol.ClientCreator(reactor, SimpleTransport).connectTCP(HOST, 22) 186 # reactor.run() 187 # print HOST 188 # pprint.pprint(results) 189 # results = [] 190