def run(self): try: logic_logger.debug('Thread ' + str(self.threadnum) + ' is started') if self.gui_cmd: self.gui_cmd(active=True) if self.configFile: commandlist = self.service_command.split() commandlist.append(self.configFile) self.service_process = subprocess.Popen( commandlist, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=False, universal_newlines=True) self.service_process.wait() else: if self.tunnelling_method == 'internal': self.execute_service_command_with_internal_ssh_tunnel() elif self.tunnelling_method == 'external': self.execute_service_command_with_external_ssh_tunnel() else: logic_logger.error( str(self.tunnelling_method) + 'is not a valid option!') self.terminate() except Exception as e: self.terminate() logic_logger.error("Error running service command\n-->" + self.service_command + "<--\n Error:" + str(e) + " ---- " + str(traceback.format_exc()))
def run(self): logic_logger.debug('Thread ' + str(self.threadnum) + ' is started') if self.gui_cmd: self.gui_cmd(active=True) if self.configFile: commandlist = self.vnc_command.split() commandlist.append(self.configFile) logic_logger.debug('This is thread ' + str(self.threadnum) + ' CONFIGFILE, executing-->' + ' '.join(commandlist) + "<--") self.vnc_process = subprocess.Popen(commandlist, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=False, universal_newlines=True) self.vnc_process.wait() else: if self.tunnelling_method == 'internal': self.execute_vnc_command_with_internal_ssh_tunnel() elif self.tunnelling_method == 'external' or self.tunnelling_method == 'via': self.execute_vnc_command_with_external_ssh_tunnel() else: logic_logger.error(str(self.tunnelling_method) + 'is not a valid option!') self.vnc_process = None if self.gui_cmd: self.gui_cmd(active=False)
def get_server_command(host, user, passwd=''): """ It call bare ssh server to check if on login node, the user has defined a variable named RCM_SERVER_COMMAND, in tht case the content of that variable overrides the default rcm command string used for the remaining part of the server interaction """ ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) logic_logger.info("getting server command from host " + host + " with user " + user) try: ssh.connect(host, username=user, password=passwd) except Exception as e: logic_logger.error("ERROR {0}: ".format(e) + "in ssh.connect to host " + host) raise e chan = ssh.get_transport().open_session() chan.get_pty() stdin = chan.makefile('wb') stdout = chan.makefile('rb') start_string = '_##start##_' end_string = '_##end##_' evn_variable = '${RCM_SERVER_COMMAND}' get_rcm_server_command = 'echo ' + start_string + evn_variable + end_string + '\n' chan.invoke_shell() chan.sendall(get_rcm_server_command) stdin.flush() chan.settimeout(20) loop = True output = '' rcm_server_command = '' while loop: try: # python3 if sys.version_info >= (3, 0): line = str(stdout.readline(), 'utf-8') # python2 else: line = stdout.readline() logic_logger.debug("parsing output line: ->" + line + "<-") if end_string in line and start_string in line: tmp_command = line.split(end_string)[0].split(start_string)[1] if not evn_variable in tmp_command: rcm_server_command = tmp_command loop = False output += line except socket.timeout: logic_logger.warning( "WARNING TIMEOUT: unable to grab output of -->" + get_rcm_server_command + "< on host:" + host) loop = False return rcm_server_command
def kill_session_thread(self): try: if self.session_threads: for thread in self.session_threads: thread.terminate() self.session_threads = None except Exception: logic_logger.error('Failed to kill a session thread still alive')
def build(self): exe = rcm_utils.which('vncviewer') if not exe: logic_logger.error( "vncviewer not found! Check the PATH environment variable.") return if sys.platform == 'win32': # if the executable path contains spaces, it has to be put inside apexes exe = "\"" + exe + "\"" self.exe = exe logic_logger.debug("vncviewer path: " + self.exe)
def get_threads_exceptions(): go = True exc = None while go: try: exc = threads_exception_queue.get(block=False) except queue.Empty: go = False else: logic_logger.error("one thread raised ->" + exc) if exc: raise Exception("ERROR: " + exc + " in thread")
def prex(self, cmd, commandnode=''): """ This is the function that wrap all the remote comman execution, accept the input command and return the remote server output that comes after the rcm.serverOutputString separation string """ if self.commandnode == '': commandnode = self.proxynode else: commandnode = self.commandnode self.commandnode = '' fullcommand = self.ssh_remote_exec_command + "@" + commandnode + ' ' + cmd ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) logic_logger.debug("on " + commandnode + " run-->" + self.config['remote_rcm_server'] + ' ' + cmd + "<") try: ssh.connect(commandnode, username=self.remoteuser, password=self.passwd, timeout=10) except Exception as e: logic_logger.warning("ERROR {0}: ".format(e) + "in ssh.connect to node->" + commandnode + "< user->" + self.remoteuser + "<") return ('') self.auth_method = ssh.get_transport().auth_handler.auth_method stdin, stdout, stderr = ssh.exec_command( self.config['remote_rcm_server'] + ' ' + cmd) myout = ''.join(stdout) myerr = stderr.readlines() if myerr: logic_logger.error(myerr) raise Exception("Server error: {0}".format(myerr)) # find where the real server output starts index = myout.find(rcm.serverOutputString) if index != -1: index += len(rcm.serverOutputString) myout = myout[index:] return myout
def __init__(self): self.set_env() if sys.platform.startswith('darwin'): exe = "open" else: exe = rcm_utils.which('vncviewer') if not exe: logic_logger.error( "vncviewer not found! Check the PATH environment variable." ) if sys.platform == 'win32': # if the executable path contains spaces, it has to be put inside apexes exe = "\"" + exe + "\"" # self.exe = exe logic_logger.debug("vncviewer path: " + exe) super(TurboVNCExecutable, self).__init__(exe)
def __init__(self): self.set_env() # ssh executable if sys.platform == 'win32': exe = rcm_utils.which('PLINK') else: exe = rcm_utils.which('ssh') if not exe: if sys.platform == 'win32': logic_logger.error( "plink.exe not found! Check the PATH environment variable." ) else: logic_logger.error("ssh not found!") return if sys.platform == 'win32': # if the executable path contains spaces, it has to be put inside apexes exe = "\"" + exe + "\"" super(SSHExecutable, self).__init__(exe)
def __init__(self, pack_info=None): self.proxynode = '' self.remoteuser = '' self.passwd = '' self.auth_method = '' self.session_thread = [] self.commandnode = '' # here we instatiate the remote procedure call stub, it will automatically # have all the methods of rcm_protoclo_server.rcm_protocol class # --- TO BE DONE --- handle automatically output type self.protocol = rcm_protocol_client.get_protocol() def mycall(command): return self.prex(command) self.protocol.mycall = mycall if not pack_info: self.pack_info = rcm_utils.pack_info() else: self.pack_info = pack_info self.config = dict() self.config['ssh'] = dict() self.config['ssh']['win32'] = ("PLINK.EXE", " -ssh", "echo yes | ") self.config['ssh']['linux2'] = ("ssh", "", "") # for python3 self.config['ssh']['linux'] = ("ssh", "", "") self.config['ssh']['darwin'] = ("ssh", "", "") self.config['remote_rcm_server'] = json.loads( parser.get('Settings', 'preload_command', fallback='""') ) + "module load rcm; python $RCM_HOME/bin/server/rcm_new_server.py" self.activeConnectionsList = [] # set the environment if getattr(sys, 'frozen', False): logic_logger.debug("Running in a bundle") # if running in a bundle, we hardcode the path # of the built-in vnc viewer and plink (windows only) os.environ['JAVA_HOME'] = resource_path('turbovnc') os.environ['JDK_HOME'] = os.environ['JAVA_HOME'] os.environ['JRE_HOME'] = os.path.join(os.environ['JAVA_HOME'], 'jre') os.environ['CLASSPATH'] = os.path.join(os.environ['JAVA_HOME'], 'lib') + \ os.pathsep + os.path.join(os.environ['JRE_HOME'], 'lib') os.environ['PATH'] = os.path.join( os.environ['JAVA_HOME'], 'bin') + os.pathsep + os.environ['PATH'] logic_logger.debug("JAVA_HOME: " + str(os.environ['JAVA_HOME'])) logic_logger.debug("JRE_HOME: " + str(os.environ['JRE_HOME'])) logic_logger.debug("JDK_HOME: " + str(os.environ['JDK_HOME'])) logic_logger.debug("CLASSPATH: " + str(os.environ['CLASSPATH'])) logic_logger.debug("PATH: " + str(os.environ['PATH'])) # ssh executable if sys.platform == 'win32': sshexe = rcm_utils.which('PLINK') else: sshexe = rcm_utils.which('ssh') if not sshexe: if sys.platform == 'win32': logic_logger.error( "plink.exe not found! Check the PATH environment variable." ) else: logic_logger.error("ssh not found!") sys.exit() if sys.platform == 'win32': # if the executable path contains spaces, it has to be put inside apexes sshexe = "\"" + sshexe + "\"" self.ssh_command = self.config['ssh'][sys.platform][2] + \ sshexe + \ self.config['ssh'][sys.platform][1] logic_logger.debug("ssh command: " + self.ssh_command) self.vnc_cmdline_builder = vnc_client.VNCClientCommandLineBuilder() self.vnc_cmdline_builder.build()
def vncsession(self, session=None, otp='', gui_cmd=None, configFile=None): tunnel_command = '' vnc_command = '' vncpassword_decrypted = '' try: tunnelling_method = json.loads(parser.get('Settings', 'ssh_client')) except Exception: tunnelling_method = "internal" logic_logger.info("Using " + str(tunnelling_method) + " ssh tunnelling") if session: portnumber = 5900 + int(session.hash['display']) local_portnumber = rcm_utils.get_unused_portnumber() node = session.hash['node'] nodelogin = session.hash['nodelogin'] tunnel = session.hash['tunnel'] vncpassword = session.hash.get('vncpassword', '') # Decrypt password rcm_cipher = cipher.RCMCipher() vncpassword_decrypted = rcm_cipher.decrypt(vncpassword) logic_logger.debug("portnumber --> " + str(portnumber) + " node --> " + str(node) + " nodelogin --> " + str(nodelogin) + " tunnel --> " + str(tunnel)) if sys.platform.startswith('darwin'): vnc_command = self.vnc_cmdline_builder.get_executable_path() + " -quality 80 -subsampling 2X" \ + " -password " + vncpassword_decrypted vnc_command += " -loglevel " + str(rcm_utils.vnc_loglevel) elif sys.platform == 'win32': vnc_command = "echo " + vncpassword_decrypted + " | " + self.vnc_cmdline_builder.get_executable_path() \ + " -autopass -nounixlogin" vnc_command += " -logfile " + os.path.join( rcm_utils.log_folder(), 'vncviewer_' + nodelogin + '_' + session.hash.get('sessionid', '') + '.log') vnc_command += " -loglevel " + str(rcm_utils.vnc_loglevel) else: vnc_command = self.vnc_cmdline_builder.get_executable_path() + " -quality 80 " \ + " -password " + vncpassword_decrypted if sys.platform == 'win32' or sys.platform.startswith('darwin'): if tunnel == 'y': tunnel_command = self.ssh_command + " -L 127.0.0.1:" + str(local_portnumber) + ":" + node + ":" \ + str(portnumber) + " " + self.login_options + "@" + nodelogin if sys.platform.startswith('darwin'): tunnel_command += " echo 'rcm_tunnel'; sleep 20" else: tunnel_command += " echo 'rcm_tunnel'; sleep 10" vnc_command += " 127.0.0.1:" + str(local_portnumber) else: vnc_command += " " + nodelogin + ":" + str(portnumber) else: if tunnel == 'y': if tunnelling_method == 'internal': vnc_command += " 127.0.0.1:" + str(local_portnumber) elif tunnelling_method == 'external': tunnel_command = self.ssh_command + " -L 127.0.0.1:" + str(local_portnumber) + ":" + node + ":" \ + str(portnumber) + " " + self.login_options + "@" + nodelogin elif tunnelling_method == 'via': vnc_command += " -via '" + self.login_options + "@" + nodelogin + "' " \ + node + ":" + str(session.hash['display']) else: logic_logger.error(tunnelling_method + ' is not a valid option') return else: vnc_command += ' ' + nodelogin + ":" + session.hash[ 'display'] else: vnc_command = self.vnc_cmdline_builder.get_executable_path( ) + " -config " logic_logger.debug("tunnel->" + tunnel_command.replace(self.passwd, "****") + "< vnc->" + vnc_command + "< conffile->" + str(configFile) + "<") st = thread.SessionThread(tunnel_command, vnc_command, self.proxynode, self.remoteuser, self.passwd, vncpassword_decrypted, otp, gui_cmd, configFile, self.auth_method, local_portnumber, node, portnumber, tunnelling_method) logic_logger.debug("session thread--->" + str(st) + "<--- num thread:" + str(len(self.session_thread))) self.session_thread.append(st) st.start()
def prex(self, cmd): """ A wrapper around all the remote command execution; accept the input command and return the remote server output that comes after the rcm.serverOutputString separation string """ if self.commandnode == '': host = self.proxynode else: host = self.commandnode self.commandnode = '' # build the full command if self.preload.strip(): fullcommand = self.preload.strip() # if fullcommand ends with ';' add the preset rcm server command, otherwise use it as is if fullcommand[-1] == ';': fullcommand += ' ' + self.rcm_server_command else: fullcommand = self.rcm_server_command fullcommand += ' ' + cmd logic_logger.info( "On " + host + " run: <br><span style=\" font-size:5; font-weight:400; color:#101010;\" >" + fullcommand + "</span>") # ssh full command execution ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: ssh.connect(host, username=self.user, password=self.password, timeout=10) self.auth_method = ssh.get_transport().auth_handler.auth_method stdin, stdout, stderr = ssh.exec_command(fullcommand) out = ''.join(stdout) err = stderr.readlines() except Exception as e: ssh.close() raise RuntimeError(e) finally: ssh.close() if err: logic_logger.warning(err) # find where the real server output starts index = out.find(rcm.serverOutputString) if index != -1: index += len(rcm.serverOutputString) out = out[index:] else: logic_logger.error( "Missing serverOutputString: {0} in server output".format( rcm.serverOutputString)) if err: raise Exception("Server error: {0}".format(err)) return out