summaryrefslogtreecommitdiffstats
path: root/Monitoring/src/main/python/Driver/SshExec.py
diff options
context:
space:
mode:
Diffstat (limited to 'Monitoring/src/main/python/Driver/SshExec.py')
-rw-r--r--Monitoring/src/main/python/Driver/SshExec.py187
1 files changed, 187 insertions, 0 deletions
diff --git a/Monitoring/src/main/python/Driver/SshExec.py b/Monitoring/src/main/python/Driver/SshExec.py
new file mode 100644
index 0000000..5de7051
--- /dev/null
+++ b/Monitoring/src/main/python/Driver/SshExec.py
@@ -0,0 +1,187 @@
+from __future__ import with_statement
+'''
+Created on Feb 29, 2012
+
+@summary: A Jython compatible ssh driver
+@author: Sandor Laki
+@organization: ELTE
+@contact: lakis@inf.elte.hu
+'''
+
+
+from java.io import BufferedReader
+from java.io import IOException
+from java.io import InputStream
+from java.io import InputStreamReader
+from java.io import File
+from jarray import zeros
+from java.lang import String
+from com.jcraft.jsch import JSch
+from StringIO import StringIO
+#import libssh2
+#import socket
+from tempfile import mkstemp
+from os import close, write, unlink, path, access, R_OK
+#from SshKeygen import SshKeygen
+from threading import Lock
+from Credential.credentialtypes import Credential, UsernameRSAKey,\
+ UsernamePassword
+from Driver import Driver
+import org.python.core.util.FileUtil as FileUtil
+import java.lang.Exception
+#from org.slf4j import Logger
+#from org.slf4j import LoggerFactory
+#import org.python.core.PyFile as PyFile
+#driverlock = Lock()
+
+class SshExec(Driver):
+ '''
+ @summary: this class handles control of a monitoring tool over an ssh channel
+ @author: steger, jozsef
+ @todo: get rid of global lock if possible
+ @note: if no global lock is there, a lot os segmentation faults occur in a concurrent session opening and program execution
+ '''
+ #lock = Lock() #driverlock
+# log = LoggerFactory.getLogger("eu.novi.monitoring.Driver.SshExec")
+
+ def __init__(self, host, credential, port = 22, command = "echo helloworld @ `hostname`", known_host = None):
+ '''
+ @summary: initiates a class to execute a single remote command via ssh protocol, tekes care of opening ssh session
+ @param host: name of the hos machine
+ @type host: string
+ @param credential: authentication details
+ @type credential: Credential
+ @param port: port of the ssh service
+ @type port: integer
+ @param command: the remote command to execute later
+ @type command: string
+ @raise Exception: wrong authentication type
+
+ @note: only a single command can be run by the class
+
+
+ @todo: check what happens with commands run in the background
+ '''
+ self.lock = Lock()
+ self.session = None
+ self.channel = None
+ if host is None: return
+
+ if not isinstance(credential, Credential):
+ raise Exception("wrong type of credential")
+ with self.lock:
+ self._result = ""
+# self.session = libssh2.Session()
+# self.session.set_banner()
+ self.command = command
+ self.fn_pub = None
+# self.pemfile = None
+
+ try:
+ self.jsch = JSch()
+# self.log.info("Host:%s Username:%s Port:%s Command:%s" % (host, credential.username, port, self.command))
+ print "h:%s un:%s p:%s" % (host, credential.username, port)
+ self.session = self.jsch.getSession(credential.username, host, port)
+ #self.jsch.setKnownHosts("/home/maven/.ssh/known_hosts")
+
+ if isinstance(credential, UsernameRSAKey):
+ privatekey = credential.rsakey
+# self.log.info("Credential: %s" % privatekey)
+ self.jsch.addIdentity(privatekey)
+ self.session.setConfig("StrictHostKeyChecking", "no")
+ self.session.setTimeout(5000);
+ print "identity file %s\n" % privatekey
+ PATH=privatekey
+ if path.exists(PATH) and path.isfile(PATH) and access(PATH, R_OK):
+ print "File exists and is readable"
+# self.log.info("Privatekey exists and is readable")
+ else:
+# self.log.info("RSA key is missing: %s" % PATH)
+ raise Exception("RSA key file is missing or not readable: %s" % PATH)
+
+# publickey_srt = SshKeygen.convert_key_from_file(privatekey)
+# fd, publickey = mkstemp(suffix = ".pub", prefix = "rsa", text = True)
+# write(fd, "ssh-rsa %s" % publickey_srt)
+# close(fd)
+# self.fn_pub = publickey
+# self.session._session.userauth_publickey_fromfile(credential.username, publickey, privatekey, credential.password)
+ elif isinstance(credential, UsernamePassword):
+ self.session.setPassword( credential.password )
+ else:
+ raise Exception("wrong type of credential")
+
+ self.session.connect()
+ except java.lang.Exception, e:
+# self.log.info("Connection error")
+ print "Connection Error"
+ print "Exc:%s" % e
+ self.session = None
+ self.channel = None
+ #raise e
+
+# self.channel = self.session.open_session()
+
+ def execute(self):
+ '''
+ @summary: invokes the remote command to run. The standard output of the command is stored in the result variable.
+ '''
+ with self.lock:
+# self.log.info("Execute:%s" % self.command)
+ if self.session is None: return StringIO("")
+ self.channel = self.session.openChannel("exec")
+ self.channel.setCommand(self.command)
+ self.channel.setInputStream(None)
+
+ stdo = self.channel.getInputStream()
+# br = BufferedReader( InputStreamReader( stdo ) )
+ self.channel.connect()
+
+ return FileUtil.wrap( stdo )
+
+# buffer = 4096
+# buf = zeros(1024,'b')
+# while True:
+# while stdo.available()>0:
+# i=stdo.read(buf,0,1024)
+# if i<0: break
+# self._result += str(String(buf,0,i))
+# if channel.isClosed(): break
+# channel.disconnect()
+# return StringIO(self._result)
+
+# def _get_result(self):
+# '''
+# @summary: the copy of the standard output of the remote command
+# @return: the standard output of the remote command
+# @rtype: string
+# '''
+# return str(self._result)
+
+ def close(self):
+ '''
+ @summary: the destructor takes care of closing the session and removing the public key file stored temporary
+ '''
+ with self.lock:
+ if self.channel is not None:
+ self.channel.disconnect()
+ self.channel = None
+ if self.session is not None:
+ self.session.disconnect()
+# if self.fn_pub is not None:
+# unlink(self.fn_pub)
+
+# result = property(_get_result,None,None)
+
+ def __del__(self):
+ self.close()
+
+ def _isConnected(self):
+ try:
+ if self.channel is not None: return True
+ else: return False
+ except:
+ return False
+
+ isConnected = property(_isConnected,None, None)
+
+