Exemple #1
0
def connectApp(ns, name):
    """
    Connects to a remote application.

    :param Pyro4.naming.Nameserver ns: Instance of a nameServer
    :param str name: Name of the application to be connected to
    :return: Application
    :rtype: Instance of an application
    :raises Exception: When cannot find registered server or Cannot connect to application
    """
    try:
        uri = ns.lookup(name)
        log.debug("Found URI %s from a nameServer %s" % (uri, ns) )
        app2 = Pyro4.Proxy(uri)
    except Exception as e:
        log.error("Cannot find registered server %s on %s" % (name, ns) )
        raise

    try:
        sig = app2.getApplicationSignature()
        log.debug("Connected to " + sig + " with the name " + name)
    except Exception as e:
        log.exception("Cannot connect to application " + name + ". Is the server running?")
        raise

    return app2
Exemple #2
0
def connectNameServer(nshost, nsport, hkey, timeOut=3.0):
    """
    Connects to a NameServer.

    :param str nshost: IP address of nameServer
    :param int nsport: Nameserver port.
    :param str hkey: A password string
    :param float timeOut: Waiting time for response in seconds
    :return: NameServer
    :rtype: Pyro4.naming.Nameserver
    :raises Exception: When can not connect to a LISTENING port of nameserver
    """
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.settimeout(timeOut)
        s.connect((nshost, nsport))
        s.close()
        log.debug("Can connect to a LISTENING port of nameserver on " + nshost + ":" + str(nsport))
    except Exception:
        msg = "Can not connect to a LISTENING port of nameserver on " + nshost + ":" + str(nsport) + ". Does a firewall block INPUT or OUTPUT on the port? Exiting."
        log.exception(msg)
        raise

    #locate nameserver
    try:
        ns = Pyro4.locateNS(host=nshost, port=nsport,hmac_key=hkey)
        msg = "Connected to NameServer on %s:%s. Pyro4 version on your localhost is %s" %(nshost, nsport, Pyro4.constants.VERSION)
        log.debug(msg)
    except Exception:
        msg = "Can not connect to NameServer on %s:%s. Is the NameServer running? Runs the NameServer on the same Pyro version as this version %s? Do you have the correct hmac_key (password is now %s)? Exiting." %(nshost, nsport, Pyro4.constants.VERSION, hkey)
        log.exception(msg)
        raise

    return ns
Exemple #3
0
def runDaemon(host, port, nathost, natport):
    """
    Runs a daemon without geristering to a name server
    :param str(int) host: Host name where daemon runs. This is typically a localhost
    :param int port: Port number where daemon will listen (internal port number)
    :param str(int) nathost: Hostname of the server as reported by nameserver, for secure ssh tunnel it should be set to 'localhost' (external host name)
    :param int natport: Server NAT port, optional (external port)

    :return Instance of the running daemon, None if a problem
    :rtype Pyro4.Daemon
    """
    try:
        daemon = Pyro4.Daemon(host=host, port=port, nathost=nathost, natport=natport)
        log.info('Pyro4 daemon runs on %s:%d using nathost %s:%d' % (host, port, nathost, natport))
    except socket.error as e:
        log.debug('Socket port %s:%d seems to be already in use' % (host,port))
        daemon = None
        raise e

    except Exception:
        log.exception('Can not run Pyro4 daemon on %s:%d using nathost %s:%d' % (host, port, nathost, natport))
        daemon = None
        raise

    return daemon
Exemple #4
0
def allocateApplicationWithJobManager (ns, jobManRec, natPort, sshClient='ssh', options='', sshHost=''):
    """
    Connect to jobManager described by given jobManRec

    :param Pyro4.naming.Nameserver ns: running name server
    :param tuple jobManRec: tuple containing (jobManPort, jobManNatport, jobManHostname, jobManUserName, jobManDNSName), see clientConfig.py
    :param int natPort: nat port in local computer for ssh tunnel for the application
    :param str sshClient: client for ssh tunnel, see :func:`sshTunnel`, default 'ssh'
    :param str options: parameters for ssh tunnel, see :func:`sshTunnel`, default ''
    :param str sshHost: parameters for ssh tunnel, see :func:`sshTunnel`, default ''

    :return: RemoteAppRecord containing application, tunnel to application, tunnel to jobman, jobid
    :rtype: RemoteAppRecord
    :raises Exception: if allocation of job fails
    """
    (jobManPort, jobManNatport, jobManHostname, jobManUserName, jobManName) = jobManRec
    log.debug('Trying to connect to JobManager')
    (jobMan, tunnelJobMan) = connectJobManager (ns, jobManRec, sshClient, options, sshHost)

    if jobMan is None:
       e = OSError("Can not connect to JobManager")
       log.exception(e)
       raise e
    else:
       log.debug('Connected to JobManager %s using tunnel %s' % (jobMan, tunnelJobMan))

    if tunnelJobMan is None:
       e = OSError("Can not create a ssh tunnel to JobManager")
       log.exception(e)
       raise

    try:
        retRec = jobMan.allocateJob(getUserInfo(), natPort=natPort)
        log.info('Allocated job, returned record from jobMan:' +  str(retRec))
    except Exception:
        log.exception("JobManager allocateJob() failed")
        raise

    #create tunnel to application's daemon running on (remote) server
    try:
        tunnelApp = sshTunnel(remoteHost=jobManHostname, userName=jobManUserName, localPort=natPort, remotePort=retRec[2], sshClient=sshClient, options=options, sshHost=sshHost)
    except Exception:
        log.exception("Creating ssh tunnel for application's daemon failed")
        raise
    else:
        log.info("Scenario: Connecting to " + retRec[1] + " " + str(retRec[2]))

    #time.sleep(1)
    # connect to (remote) application, requests remote proxy
    app = connectApp(ns, retRec[1])
    if app==None:
        tunnelApp.terminate()
    return RemoteAppRecord.RemoteAppRecord(app, tunnelApp, jobMan, tunnelJobMan, retRec[1])
Exemple #5
0
def runAppServer(server, port, nathost, natport, nshost, nsport, nsname, hkey, app, daemon=None):
    """
    Runs a simple application server

    :param str server: Host name of the server (internal host name)
    :param int port: Port number on the server where daemon will listen (internal port number)
    :param str nathost: Hostname of the server as reported by nameserver, for secure ssh tunnel it should be set to 'localhost' (external host name)
    :param int natport: Server NAT port as reported by nameserver (external port)
    :param str nshost: Hostname of the computer running nameserver
    :param int nsport: Nameserver port
    :param str nsname: Name of registered application
    :param str hkey: A password string
    :param instance app: Application instance
    :param daemon: Reference to already running daemon, if available. Optional parameter.

    :raises Exception: if can not run Pyro4 daemon
    """
    externalDaemon = False
    if not daemon:
        try:
            daemon = Pyro4.Daemon(host=server, port=port, nathost=nathost, natport=natport)
            log.info('Pyro4 daemon runs on %s:%d using nathost %s:%d and hkey %s' % (server, port, nathost, natport, hkey))
        except Exception:
            log.exception('Can not run Pyro4 daemon on %s:%d using nathost %s:%d  and hmac %s' % (server, port, nathost, natport, hkey))
            raise
            exit(1)
    else:
        externalDaemon = True

    ns = connectNameServer(nshost, nsport, hkey)
    #register agent
    uri = daemon.register(app)
    ns.register(nsname, uri)
    app.registerPyro(daemon, ns, uri, externalDaemon=externalDaemon)

    log.debug('NameServer %s has registered uri %s' % (nsname, uri) )
    log.debug('Running runAppServer: server:%s, port:%d, nathost:%s, natport:%d, nameServer:%s, nameServerPort:%d, applicationName:%s, daemon URI %s' % (server, port, nathost, natport, nshost, nsport, nsname, uri) )
    daemon.requestLoop()
Exemple #6
0
def sshTunnel(remoteHost, userName, localPort, remotePort, sshClient='ssh', options='', sshHost='', Reverse=False):
    """
    Automatic creation of ssh tunnel, using putty.exe for Windows and ssh for Linux

    :param str remoteHost: IP of remote host
    :param str userName: User name, if empty, current user name is used
    :param int localPort: Local port
    :param int remotePort: Remote port
    :param str sshClient: Path to executable ssh client (on Windows use double backslashes 'C:\\Program Files\\Putty\putty.exe')
    :param str options: Arguments to ssh clinent, e.g. the location of private ssh keys
    :param str sshHost: Computer used for tunelling, optional. If empty, equals to remoteHost
    :param bool Reverse: True if reverse tunnel to be created (default is False)

    :return: Instance of subprocess.Popen running the tunneling command
    :rtype: subprocess.Popen
    :raises Exception: if creation of a tunnel failed
    """

    if sshHost =='':
        sshHost = remoteHost
    if userName =='':
        userName = os.getenv('USER')

    direction = 'L'
    if Reverse == True:
        direction = 'R'

    #use direct system command. Paramiko or sshtunnel do not work.
    #put ssh public key on a server - interaction with a keyboard for password will not work here (password goes through TTY, not stdin)
    if sshClient=='ssh':
        cmd = 'ssh -%s %d:%s:%d %s@%s -N %s' % (direction, localPort, remoteHost, remotePort, userName, sshHost, options)
        log.debug("Creating ssh tunnel via command: " + cmd)
    elif sshClient=='autossh':
        cmd = 'autossh -%s %d:%s:%d %s@%s -N %s' % (direction, localPort, remoteHost, remotePort, userName, sshHost, options)
        log.debug("Creating autossh tunnel via command: " + cmd)
    elif 'putty' in sshClient.lower():
        #need to create a public key *.ppk using puttygen. It can be created by importing Linux private key. The path to that key is given as -i option
        cmd = '%s -%s %d:%s:%d %s@%s -N %s' % (sshClient, direction, localPort, remoteHost, remotePort, userName, sshHost, options)
        log.debug("Creating ssh tunnel via command: " + cmd)
    elif sshClient=='manual':
        #You need ssh server running, e.g. UNIX-sshd or WIN-freesshd
        cmd1 = 'ssh -%s %d:%s:%d %s@%s -N %s' % (direction, localPort, remoteHost, remotePort, userName, sshHost, options)
        cmd2 = 'putty.exe -%s %d:%s:%d %s@%s -N %s' % (direction, localPort, remoteHost, remotePort, userName, sshHost, options)
        log.info("If ssh tunnel does not exist, do it manually using a command e.g. " + cmd1 + " , or " + cmd2)
        return 'manual'
    else:
        log.error("Unknown ssh client, exiting")
        exit(0)
    try:
        tunnel = subprocess.Popen(cmd.split())
    except Exception:
        log.exception("Creation of a tunnel failed. Can not execute the command: %s " % cmd)
        raise

    time.sleep(1.0)

    return tunnel