Skip to content
Snippets Groups Projects
Commit a1f06226 authored by Ubuntu's avatar Ubuntu
Browse files

manual merge

parents e9e14669 2024cbb9
No related branches found
No related tags found
No related merge requests found
from tes import app from tes import app
import logging import logging
#logging.basicConfig(filename="tes.log",format="%(asctime)s %(levelname)s:%(process)s: %(message)s") logging.basicConfig(filename="tes.log",format="%(asctime)s %(levelname)s:%(process)s: %(message)s")
logger=logging.getLogger() logger=logging.getLogger()
logger.setLevel(logging.DEBUG) logger.setLevel(logging.DEBUG)
......
...@@ -84,6 +84,7 @@ class SSHAgent(Resource): ...@@ -84,6 +84,7 @@ class SSHAgent(Resource):
try: try:
sshsess = SSHSession.get_sshsession() sshsess = SSHSession.get_sshsession()
if sshsess.socket == None: if sshsess.socket == None:
logger.debug('trying to get the agent contents, but the agent isn\'t started yet')
return [] # The agent hasn't even been started yet return [] # The agent hasn't even been started yet
return sshsess.get_cert_contents() return sshsess.get_cert_contents()
except Exception as e: except Exception as e:
...@@ -129,11 +130,18 @@ def get_conn_params(): ...@@ -129,11 +130,18 @@ def get_conn_params():
appparams = json.loads(appstr) appparams = json.loads(appstr)
except: except:
appparams = {} appparams = {}
try:
appinstancestr = request.args.get('appinstance')
appinstanceparams = json.loads(appinstancestr)
except:
appinstanceparams = {}
params = {} params = {}
params['identity'] = identityparams params['identity'] = identityparams
params['interface'] = interfaceparams params['interface'] = interfaceparams
params['app'] = appparams params['app'] = appparams
params['appinstance'] = appinstanceparams
params.update(interfaceparams) params.update(interfaceparams)
params['user'] = identityparams['username'] params['user'] = identityparams['username']
...@@ -146,14 +154,6 @@ def get_conn_params(): ...@@ -146,14 +154,6 @@ def get_conn_params():
return params return params
def get_app_params():
"""
Return the parameters for the application retrieved from the Session
"""
keys = ['startscript', 'paramscmd', 'client','localbind']
appstr = request.args.get('app')
returnvalue = json.loads(appstr)
return returnvalue
class TunnelstatEP(Resource): class TunnelstatEP(Resource):
""" """
...@@ -204,6 +204,7 @@ class JobStat(Resource): ...@@ -204,6 +204,7 @@ class JobStat(Resource):
""" """
import logging import logging
logger = logging.getLogger() logger = logging.getLogger()
logger.debug('enteringing JobStat')
try: try:
params = get_conn_params() params = get_conn_params()
except: except:
...@@ -225,7 +226,10 @@ class JobStat(Resource): ...@@ -225,7 +226,10 @@ class JobStat(Resource):
cmd = params['interface']['statcmd'] cmd = params['interface']['statcmd']
except (TypeError, KeyError) as e: except (TypeError, KeyError) as e:
flask_restful.abort(400, message="stat: definition of batch interface incomplete") flask_restful.abort(400, message="stat: definition of batch interface incomplete")
logger.debug('ssh sess socket is {}'.format(sshsess.socket))
try: try:
logger.debug('attempting ssh execute {} {} {}'.format(host,user,cmd))
res = Ssh.execute(sshsess, host=host, user=user, cmd=cmd) res = Ssh.execute(sshsess, host=host, user=user, cmd=cmd)
except SshAgentException as e: except SshAgentException as e:
logger.error(e) logger.error(e)
...@@ -240,6 +244,7 @@ class JobStat(Resource): ...@@ -240,6 +244,7 @@ class JobStat(Resource):
for j in jobs: for j in jobs:
j['identity'] = params['identity'] j['identity'] = params['identity']
logger.debug('leaving jobstat gracefully')
return jobs return jobs
except Exception as e: except Exception as e:
import traceback import traceback
...@@ -247,12 +252,46 @@ class JobStat(Resource): ...@@ -247,12 +252,46 @@ class JobStat(Resource):
logger.error(traceback.format_exc()) logger.error(traceback.format_exc())
flask_resful.abort(400, message=e) flask_resful.abort(400, message=e)
class MkDir(Resource):
def post(self):
import logging
logger = logging.getLogger()
data = request.get_json()
logger.debug('mkdir data')
logger.debug(data)
params = get_conn_params()
sshsess = SSHSession.get_sshsession()
Ssh.sftpmkdir(sshsess, host=params['identity']['site']['host'],
user=params['identity']['username'], path=params['path'],name=data['name'])
return
class DirList(Resource): class DirList(Resource):
def get(self): def get(self):
params = get_conn_params() params = get_conn_params()
sshsess = SSHSession.get_sshsession() sshsess = SSHSession.get_sshsession()
dirls = Ssh.sftpls(sshsess, host=params['identity']['site']['host'], site = params['identity']['site']
user=params['identity']['username'], path=params['path'],changepath=params['cd']) if 'dtnport' in site:
sshport = site['dtnport']
else:
sshport = "22"
path = params['path']
cd = params['cd']
if path == "":
path = "."
if cd == "":
cd = "."
print('sshport is {}'.format(sshport))
if 'lscmd' in site and site['lscmd'] is not None and site['lscmd'] is not "":
res = Ssh.execute(sshsess, host=params['identity']['site']['host'], user=params['identity']['username'],
sshport=sshport,
cmd="{} {} {}".format(site['lscmd'],path,cd))
dirls = json.loads(res['stdout'].decode())
print(dirls)
else:
dirls = Ssh.sftpls(sshsess, host=params['identity']['site']['host'],
user=params['identity']['username'], path=params['path'],changepath=params['cd'], sshport=sshport)
return dirls return dirls
class JobCancel(Resource): class JobCancel(Resource):
...@@ -278,6 +317,7 @@ class JobSubmit(Resource): ...@@ -278,6 +317,7 @@ class JobSubmit(Resource):
""" """
def post(self): def post(self):
"""starting a job is a post, since it changes the state of the backend""" """starting a job is a post, since it changes the state of the backend"""
print("entering jobsubmit")
import logging import logging
logger=logging.getLogger() logger=logging.getLogger()
params = get_conn_params() params = get_conn_params()
...@@ -288,7 +328,7 @@ class JobSubmit(Resource): ...@@ -288,7 +328,7 @@ class JobSubmit(Resource):
try: try:
script = data['app']['startscript'].format(**data) script = data['app']['startscript'].format(**data)
except: except:
flask_restful.abort(400,message='Incomplete job information was passed to the backend.') flask_restful.abort(400, message='Incomplete job information was passed to the backend.')
logger.debug('script formated to {}'.format(script)) logger.debug('script formated to {}'.format(script))
res = Ssh.execute(sshsess, host=params['identity']['site']['host'], user=params['identity']['username'], res = Ssh.execute(sshsess, host=params['identity']['site']['host'], user=params['identity']['username'],
...@@ -311,62 +351,46 @@ def gen_authtok(): ...@@ -311,62 +351,46 @@ def gen_authtok():
return ''.join(random.SystemRandom().choice(string.ascii_uppercase + return ''.join(random.SystemRandom().choice(string.ascii_uppercase +
string.digits) for _ in range(16)) string.digits) for _ in range(16))
class JobConnect(Resource): class AppUrl(Resource):
""" def get(self):
endpoints for connecting to an existing JobCancel
"""
def create_tunnel(self, username, loginhost, appparams, batchhost, firewall, data):
import logging import logging
logger=logging.getLogger() logger = logging.getLogger()
logger.debug('entering JobConnect.create_tunnel {} {}'.format(username,batchhost)) appdef = json.loads(request.args.get('app'))
connectparams = {} logger.debug('appdef {}'.format(appdef))
inst = json.loads(request.args.get('appinst'))
logger.debug('appinst {}'.format(inst))
url = "{}{}".format(app.config['TWSPROXY'],appdef['client']['redir'].format(**inst))
return url
class AppInstance(Resource):
def get(self, username, loginhost, batchhost):
"""Run a command to get things like password and port number
command is passed as a query string"""
sshsess = SSHSession.get_sshsession() sshsess = SSHSession.get_sshsession()
paramscmd = request.args.get('cmd')
import logging
logger = logging.getLogger()
logger.debug('getting appinstance {} {} {}'.format(username,loginhost,batchhost))
logger.debug('ssh sess socket is {}'.format(sshsess.socket))
cmd = 'ssh -o StrictHostKeyChecking=no -o CheckHostIP=no {batchhost} '.format(batchhost=batchhost) + paramscmd
res = Ssh.execute(sshsess, host=loginhost, user=username, cmd=cmd)
try:
data = json.loads(res['stdout'].decode())
except json.decoder.JSONDecodeError as e:
raise AppParamsException(res['stderr']+res['stdout'])
if len(res['stderr']) > 0:
raise AppParamsException(res['stderr'])
if 'error' in data:
raise AppParamsException(data['error'])
if not (res['stderr'] == '' or res['stderr'] is None or res['stderr'] == b''):
flask_restful.abort(400, message=res['stderr'].decode())
return data
if 'paramscmd' in appparams and appparams['paramscmd'] is not None: class CreateTunnel(Resource):
connectparams['batchhost'] = batchhost @staticmethod
paramcmd = 'ssh -o StrictHostKeyChecking=no -o CheckHostIP=no {batchhost} '.format(batchhost=batchhost) + appparams['paramscmd'] def validate_connect_params(port, username, host, batchhost):
logger.debug('JobCreate.create_tunnel: using ssh to extract connection parameters')
res = Ssh.execute(sshsess, host=loginhost, user=username, cmd=paramcmd.format(data))
try:
data = json.loads(res['stdout'])
except json.decoder.JSONDecodeError as e:
raise AppParamsException(res['stderr']+res['stdout'])
if len(res['stderr']) > 0:
raise AppParamsException(res['stderr'])
if 'error' in data:
raise AppParamsException(data['error'])
try:
connectparams.update(json.loads(res['stdout']))
except json.decoder.JSONDecodeError as e:
logger.error(res['stdout'])
logger.error(res['stderr'])
if not (res['stderr'] == '' or res['stderr'] is None or res['stderr'] == b''):
flask_restful.abort(400, message=res['stderr'].decode())
if self.validate_connect_params(connectparams, username, loginhost):
authtok = gen_authtok()
logger.debug('JobCreate.create_tunnel: creating a tunnel for authtok {}'.format(authtok))
tunnelport, pids = Ssh.tunnel(sshsess, port=connectparams['port'],
batchhost=connectparams['batchhost'],
user=username, host=loginhost,
internalfirewall=firewall,
localbind=appparams['localbind'], authtok=authtok)
connectparams['localtunnelport'] = tunnelport
connectparams['authtok'] = authtok
logger.debug('JobCreate.create_tunnel: created a tunnel for authtok {} port {}'.format(authtok,tunnelport))
else:
raise AppParamsException("connection parameters invalid {} {} {}".format(connectparams,username,loginhost))
return connectparams
def validate_connect_params(self, connectparams, username, host):
if not 'port' in connectparams:
return False
if not 'batchhost' in connectparams:
return False
try: try:
intport = int(connectparams['port']) intport = int(port)
except Exception as e: except Exception as e:
return False return False
if ' ' in username or '\n' in username: # This really needs more validation if ' ' in username or '\n' in username: # This really needs more validation
...@@ -375,52 +399,45 @@ class JobConnect(Resource): ...@@ -375,52 +399,45 @@ class JobConnect(Resource):
return False return False
return True return True
def get(self, jobid, batchhost): def post(self,username,loginhost,batchhost):
""" """
Connecting to a job is a get operation (i.e. it does not make modifications) Create a tunnel using established keys
parameters for the tunnel (host username port etc)
will be passed in the body
""" """
import logging import logging
logger=logging.getLogger() logger = logging.getLogger()
logger.debug('entering JobConnect.get for jobid {} {}'.format(jobid,batchhost)) logger.debug("Createing tunnel")
params = get_conn_params() logger.debug("recieved data {}".format(request.data))
appparams = get_app_params()
data = request.get_json() data = request.get_json()
try: try:
connectparams = self.create_tunnel(params['identity']['username'],params['identity']['site']['host'], port = data['port']
appparams, batchhost, params['interface']['internalfirewall'], except KeyError as missingdata:
data) raise AppParamsException("missing value for {}".format(missingdata))
except AppParamsException as e: if not CreateTunnel.validate_connect_params(port, username, loginhost, batchhost):
return make_response(render_template('appparams.html.j2',data = "{}".format(e))) raise AppParamsException("Invalid value: {} {} {} {}".
logger.debug('JobConnect.get tunnels created, moving to redirect'.format(jobid,batchhost)) format(username, loginhost, batchhost, port))
return self.connect(appparams, connectparams) if 'internalfirewall' in data:
firewall = data['internalfirewall']
def connect(self, appparams, connectparams): else:
""" firewall = False
perform the connection either by forking a local client or returning a redirect if 'localbind' in data:
""" localbind = data['localbind']
import subprocess else:
import logging localbind = True
import json sshsess = SSHSession.get_sshsession()
logger=logging.getLogger() authtok = gen_authtok()
if 'cmd' in appparams['client'] and appparams['client']['cmd'] is not None: # logger.debug('JobCreate.create_tunnel: creating a tunnel for authtok {}'.format(authtok))
# We need for fork a local process such as vncviewer or a terminal Ssh.tunnel(sshsess, port=port, batchhost=batchhost,
# We may need a wrapper for local processes to find the correct user=username, host=loginhost,
# process on all OS internalfirewall=firewall,
cmdlist = [] localbind=localbind, authtok=authtok)
for cmdarg in appparams['client']['cmd']: response = make_response("")
cmdlist.append(cmdarg.format(**connectparams)) response.mime_type = 'application/json'
app_process = subprocess.Popen(cmdlist, stdout=subprocess.PIPE, stderr=subprocess.PIPE) response.set_cookie('twsproxyauth', authtok)
elif 'redir' in appparams['client'] and appparams['client']['redir'] is not None: logger.debug('JobConnect.connect: connecting via redirect with cookie authtok set to {}'.format(authtok))
twsproxy = app.config['TWSPROXY'] return response
data = json.dumps({'location': twsproxy+appparams['client']['redir'].
format(**connectparams) })
response = make_response(data)
response.mime_type = 'application/json'
response.set_cookie('twsproxyauth', connectparams['authtok'])
logger.debug('JobConnect.connect: connecting via redirect with cookie authtok set to {}'.format(connectparams['authtok']))
return response
return "Connecting with cmd {}".format(cmdlist)
api.add_resource(TunnelstatEP, '/tunnelstat/<string:authtok>') api.add_resource(TunnelstatEP, '/tunnelstat/<string:authtok>')
...@@ -428,8 +445,9 @@ api.add_resource(GetCert, '/getcert') ...@@ -428,8 +445,9 @@ api.add_resource(GetCert, '/getcert')
api.add_resource(JobStat, '/stat') api.add_resource(JobStat, '/stat')
api.add_resource(JobCancel, '/cancel/<int:jobid>') api.add_resource(JobCancel, '/cancel/<int:jobid>')
api.add_resource(JobSubmit, '/submit') api.add_resource(JobSubmit, '/submit')
api.add_resource(JobConnect, '/connect/<int:jobid>/<string:batchhost>') api.add_resource(CreateTunnel, '/createtunnel/<string:username>/<string:loginhost>/<string:batchhost>')
# api.add_resource(SessionTest,'/sesstest') api.add_resource(AppInstance, '/appinstance/<string:username>/<string:loginhost>/<string:batchhost>')
#api.add_resource(StartAgent,'/startagent') api.add_resource(AppUrl, '/appurl')
api.add_resource(SSHAgent,'/sshagent') api.add_resource(SSHAgent,'/sshagent')
api.add_resource(DirList,'/ls') api.add_resource(DirList,'/ls')
api.add_resource(MkDir,'/mkdir')
...@@ -68,7 +68,7 @@ class Ssh: ...@@ -68,7 +68,7 @@ class Ssh:
pass pass
@staticmethod @staticmethod
def get_ctrl_master_socket(sess, host, user): def get_ctrl_master_socket(sess, host, user, sshport):
""" """
Returns the socket for the control master process Returns the socket for the control master process
Opens it if needed. Opens it if needed.
...@@ -87,16 +87,18 @@ class Ssh: ...@@ -87,16 +87,18 @@ class Ssh:
sshcmd = ["ssh", '-o', 'StrictHostKeyChecking=no', sshcmd = ["ssh", '-o', 'StrictHostKeyChecking=no',
"-S", ctrlsocket, "-S", ctrlsocket,
"-M", '-o', 'ControlPersist=10m', "-M", '-o', 'ControlPersist=10m',
'-N','-l', user, host] '-p', sshport, '-N','-l', user, host]
env = os.environ.copy() env = os.environ.copy()
if sess.socket is None: if sess.socket is None:
raise SshAgentException("No ssh-agent yet") raise SshAgentException("No ssh-agent yet")
env['SSH_AUTH_SOCK'] = sess.socket env['SSH_AUTH_SOCK'] = sess.socket
logger.debug("socket not found, starting new master")
ctrl_p = subprocess.Popen(sshcmd, ctrl_p = subprocess.Popen(sshcmd,
stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=None,
env=env) env=env)
stdout = ctrl_p.communicate() logger.debug("master spawned, attempt communicate")
stdout, stderr = ctrl_p.communicate()
logger.debug('communicate on the control port complete') logger.debug('communicate on the control port complete')
sess.pids.append(ctrl_p.pid) sess.pids.append(ctrl_p.pid)
...@@ -108,6 +110,7 @@ class Ssh: ...@@ -108,6 +110,7 @@ class Ssh:
logger.error(ctrl_p.stderr.read()) logger.error(ctrl_p.stderr.read())
raise SshCtrlException() raise SshCtrlException()
if not stat.S_ISSOCK(mode): if not stat.S_ISSOCK(mode):
logger.error(ctrl_p.stderr.read())
raise SshCtrlException() raise SshCtrlException()
return ctrlsocket return ctrlsocket
...@@ -119,7 +122,7 @@ class Ssh: ...@@ -119,7 +122,7 @@ class Ssh:
pwd = None pwd = None
import dateutil.parser import dateutil.parser
for l in output.splitlines(): for l in output.splitlines():
fields = l.split(None,8) fields = l.split(None,8)
fd = {} fd = {}
if len(fields) == 9: if len(fields) == 9:
...@@ -138,9 +141,51 @@ class Ssh: ...@@ -138,9 +141,51 @@ class Ssh:
pwd = l[len(remotestr):].rstrip() pwd = l[len(remotestr):].rstrip()
return ({'pwd':pwd,'files':rv}) return ({'pwd':pwd,'files':rv})
@staticmethod
def sftpmkdir(sess, host, user, path, name, sshport):
"""
Use sftp to run mkdir.
"""
import os
import logging
logger = logging.getLogger()
env = os.environ.copy()
if path is None:
path = "."
if sess.socket is None:
raise SshAgentException("No ssh-agent yet")
env['SSH_AUTH_SOCK'] = sess.socket
Ssh.validate_username(user)
Ssh.validate_hostname(host)
ctrlsocket = Ssh.get_ctrl_master_socket(sess, host, user, sshport)
exec_p = subprocess.Popen(['sftp', '-b', '-','-o', 'Stricthostkeychecking=no',
'-P', sshport, '-o', 'ControlPath={}'.format(ctrlsocket),
'{}@{}'.format(user, host)],
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=subprocess.PIPE, env=env)
sftpcmd="cd {}\n mkdir \"{}\"\n".format(path,name)
(stdout, stderr) = exec_p.communicate(sftpcmd.encode())
if stderr is not None:
if not (stderr == b''):
logger.error('sftp failure')
logger.error(stdout.decode())
logger.error(stderr.decode())
if ('Couldn\'t create directory: Failure' in stderr.decode()):
return
if ('Couldn\'t canonicalize: No such file or directory' in stderr.decode()):
logger.error('can\'t change to that directory')
return
if ('Permission denied' in stderr.decode()):
logger.error('can\'t change to that directory')
return
raise SshCtrlException()
return
@staticmethod @staticmethod
def sftpls(sess, host, user, path=".",changepath="."): def sftpls(sess, host, user, sshport, path=".",changepath="."):
""" """
Use sftp to run an ls on the given path. Use sftp to run an ls on the given path.
Return the directory listing (as a list) and the cwd Return the directory listing (as a list) and the cwd
...@@ -154,13 +199,13 @@ class Ssh: ...@@ -154,13 +199,13 @@ class Ssh:
env['SSH_AUTH_SOCK'] = sess.socket env['SSH_AUTH_SOCK'] = sess.socket
Ssh.validate_username(user) Ssh.validate_username(user)
Ssh.validate_hostname(host) Ssh.validate_hostname(host)
ctrlsocket = Ssh.get_ctrl_master_socket(sess, host, user) ctrlsocket = Ssh.get_ctrl_master_socket(sess, host, user, sshport)
if (path is None or path == ""): if (path is None or path == ""):
path="." path="."
if (changepath is None or changepath == ""): if (changepath is None or changepath == ""):
changepath="." changepath="."
exec_p = subprocess.Popen(['sftp', '-b', '-','-o', 'Stricthostkeychecking=no', exec_p = subprocess.Popen(['sftp', '-b', '-','-o', 'Stricthostkeychecking=no',
'-o', 'ControlPath={}'.format(ctrlsocket), '-P', sshport, '-o', 'ControlPath={}'.format(ctrlsocket),
'{}@{}'.format(user, host)], '{}@{}'.format(user, host)],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=subprocess.PIPE, env=env) stdin=subprocess.PIPE, env=env)
...@@ -173,10 +218,10 @@ class Ssh: ...@@ -173,10 +218,10 @@ class Ssh:
logger.error('sftp failure') logger.error('sftp failure')
if ('Couldn\'t canonicalize: No such file or directory' in stderr.decode()): if ('Couldn\'t canonicalize: No such file or directory' in stderr.decode()):
logger.error('can\'t change to that directory') logger.error('can\'t change to that directory')
return Ssh.sftpls(sess,host,user,path,changepath='.') return Ssh.sftpls(sess,host,user,sshport, path,changepath='.')
if ('Permission denied' in stderr.decode()): if ('Permission denied' in stderr.decode()):
logger.error('can\'t change to that directory') logger.error('can\'t change to that directory')
return Ssh.sftpls(sess,host,user,path,changepath='.') return Ssh.sftpls(sess,host,user,sshport, path,changepath='.')
logger.error(stderr.decode()) logger.error(stderr.decode())
logger.error(('Permission denied' in stderr.decode())) logger.error(('Permission denied' in stderr.decode()))
...@@ -188,13 +233,15 @@ class Ssh: ...@@ -188,13 +233,15 @@ class Ssh:
@staticmethod @staticmethod
def execute(sess, host, user, cmd, stdin=None): def execute(sess, host, user, cmd, stdin=None, sshport="22"):
""" """
execute the command cmd on the host via ssh execute the command cmd on the host via ssh
# assume the environment is already setup with an # assume the environment is already setup with an
# SSH_AUTH_SOCK that allows login # SSH_AUTH_SOCK that allows login
""" """
import os import os
import logging
logger = logging.getLogger()
if cmd is None and stdin is None: if cmd is None and stdin is None:
return {'stdout': b'', 'stderr': b'No command given to execute'} return {'stdout': b'', 'stderr': b'No command given to execute'}
env = os.environ.copy() env = os.environ.copy()
...@@ -204,10 +251,12 @@ class Ssh: ...@@ -204,10 +251,12 @@ class Ssh:
Ssh.validate_username(user) Ssh.validate_username(user)
Ssh.validate_hostname(host) Ssh.validate_hostname(host)
Ssh.validate_command(cmd) Ssh.validate_command(cmd)
ctrlsocket = Ssh.get_ctrl_master_socket(sess, host, user) logger.debug('getting ctrl_master')
ctrlsocket = Ssh.get_ctrl_master_socket(sess, host, user, sshport)
logger.debug('ssh.execute: got ctrlsocket {}'.format(ctrlsocket))
exec_p = subprocess.Popen(['ssh', '-A', '-o', 'Stricthostkeychecking=no', exec_p = subprocess.Popen(['ssh', '-A', '-o', 'Stricthostkeychecking=no',
'-S', ctrlsocket, '-S', ctrlsocket,
'-l', user, host, cmd], '-p', sshport, '-l', user, host, cmd],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=subprocess.PIPE, env=env) stdin=subprocess.PIPE, env=env)
if stdin is not None: if stdin is not None:
...@@ -217,7 +266,7 @@ class Ssh: ...@@ -217,7 +266,7 @@ class Ssh:
return {'stdout':stdout, 'stderr':stderr} return {'stdout':stdout, 'stderr':stderr}
@staticmethod @staticmethod
def tunnel(sess, port, batchhost, user, host, internalfirewall = True, localbind = True, authtok = None): def tunnel(sess, port, batchhost, user, host, internalfirewall = True, localbind = True, authtok = None, sshport="22"):
""" """
the ProxyCommand is used if the server we run on the batch host is only the ProxyCommand is used if the server we run on the batch host is only
addressable on localhost addressable on localhost
...@@ -237,7 +286,7 @@ class Ssh: ...@@ -237,7 +286,7 @@ class Ssh:
Ssh.validate_hostname(batchhost) Ssh.validate_hostname(batchhost)
Ssh.validate_username(user) Ssh.validate_username(user)
Ssh.validate_hostname(host) Ssh.validate_hostname(host)
ctrlsocket = Ssh.get_ctrl_master_socket(sess, host, user) ctrlsocket = Ssh.get_ctrl_master_socket(sess, host, user, sshport)
logger.debug('Ssh.tunnel, got ctrlsocket') logger.debug('Ssh.tunnel, got ctrlsocket')
localport = Ssh.get_free_port() localport = Ssh.get_free_port()
...@@ -248,7 +297,7 @@ class Ssh: ...@@ -248,7 +297,7 @@ class Ssh:
'-L', '{localport}:{batchhost}:{port}'. '-L', '{localport}:{batchhost}:{port}'.
format(port=port, localport=localport, batchhost=batchhost), format(port=port, localport=localport, batchhost=batchhost),
'-O', 'forward', '-S', ctrlsocket, '-O', 'forward', '-S', ctrlsocket,
'-l', user, host] '-p', sshport, '-l', user, host]
else: else:
# Create an ssh tunnel to the batch node using a proxycommand. # Create an ssh tunnel to the batch node using a proxycommand.
# The proxy command should utilise # The proxy command should utilise
...@@ -261,7 +310,7 @@ class Ssh: ...@@ -261,7 +310,7 @@ class Ssh:
'-L', '{localport}:localhost:{port}'. '-L', '{localport}:localhost:{port}'.
format(port=port, localport=localport), format(port=port, localport=localport),
'-o', "ProxyCommand={}".format(proxycmd), '-o', "ProxyCommand={}".format(proxycmd),
'-l', user, batchhost] '-p', sshport, '-l', user, batchhost]
logger.debug('Ssh.tunnel: attempting command {}'.format(sshcmd)) logger.debug('Ssh.tunnel: attempting command {}'.format(sshcmd))
tunnel_p = subprocess.Popen(sshcmd, env=env) tunnel_p = subprocess.Popen(sshcmd, env=env)
......
...@@ -41,7 +41,9 @@ class SSHSession: ...@@ -41,7 +41,9 @@ class SSHSession:
import logging import logging
logger = logging.getLogger() logger = logging.getLogger()
if self.socket is None: if self.socket is None:
logger.debug('adding a cert, start the agent first')
self.start_agent() self.start_agent()
logger.debug('agent socket is now {}'.format(self.socket))
keyf = tempfile.NamedTemporaryFile(mode='w',delete=False) keyf = tempfile.NamedTemporaryFile(mode='w',delete=False)
keyname = keyf.name keyname = keyf.name
keyf.write(key) keyf.write(key)
...@@ -160,6 +162,7 @@ class SSHSession: ...@@ -160,6 +162,7 @@ class SSHSession:
session['sshsessid'] = sshsessid session['sshsessid'] = sshsessid
if sshsessid not in sshsessions: if sshsessid not in sshsessions:
sshsessions[sshsessid] = SSHSession() sshsessions[sshsessid] = SSHSession()
return sshsessions[sshsessid] return sshsessions[sshsessid]
@staticmethod @staticmethod
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment