Esempio n. 1
0
def execute(command, host=None, bg=True, **kwds):
  '''execute a command (possibly) on a remote host

Execute a process, and return the launcher. Use 'response' to retrieve the
response from the executed command. Use 'kill' to kill the launcher, and 'pid'
to get the process id for the launcher.

Inputs:
    command -- command string to be executed
    host    -- hostname of execution target  [default = None (i.e. run locally)]
    bg      -- run as background process?  [default = True]
  '''
  #XXX: options, background, stdin can be set w/ kwds (also name, launcher)
  bg = bool(bg) # overrides 'background'
  if host in [None, '']:
    from pathos.connection import Pipe
    launcher = Pipe(**kwds)
    launcher(command=command, background=bg)
  else:
    from pathos.secure import Pipe
    opt = kwds.pop('options', '-q')
    launcher = Pipe(**kwds)
    launcher(options=opt, command=command, host=host, background=bg)
  pathos.logger().info('executing {%s}', launcher.message)
  launcher.launch()
 #response = launcher.response()
 #launcher.kill()
 #return response
  return launcher
Esempio n. 2
0
def copy(source, destination=None, **kwds):
  '''copy source to (possibly) remote destination

Execute a copy, and return the copier. Use 'kill' to kill the copier, and 
'pid' to get the process id for the copier.

Inputs:
    source      -- path string of source 'file'
    destination -- path string for destination target
  '''
  #XXX: options, background, stdin can be set w/ kwds (also name, launcher)
  if destination is None: destination = os.getcwd()
  from pathos.secure import Copier
  opt = kwds.pop('options', None)
  kwds['background'] = kwds.pop('bg', False) # ignores 'background'
  copier = Copier(**kwds)
  if ':' in source or ':' in destination:
    if opt is None: opt = '-q -r'
    copier(options=opt, source=source, destination=destination)
  else:
    if opt is None: opt = '-r'
    copier(launcher='cp', options=opt, source=source, destination=destination)
  pathos.logger().info('executing {%s}', copier.message)
  copier.launch()
  copier.kill()
  return copier
Esempio n. 3
0
def serve(server, host=None, port=None, profile='.bash_profile'):
  '''begin serving RPC requests

Inputs:
    server  -- name of RPC server  (i.e. 'ppserver')
    host    -- hostname on which a server should be launched
    port    -- port number (on host) that server will accept request at
    profile -- file on remote host that instantiates the user's environment
        [default = '.bash_profile']
  '''
  if host is None: #XXX: and...?
    profile = ''
  else:
    profile = 'source %s; ' % profile
  file = '~/bin/%s.py' % server  #XXX: _should_ be on the $PATH
  if port is None: port = randomport(host)
  command = "%s -p %s" % (file,port)
  rserver = execute(command, host, bg=True)
  response = rserver.response()
  pathos.logger().info('response = %r', response)
  if response in ['', None]: #XXX: other responses allowed (?)
    pass
  else: #XXX: not really error checking...
    pathos.logger().error('invalid response = %r', response)
  from time import sleep
  delay = 2.0
  sleep(delay)
  return rserver
Esempio n. 4
0
def execute(command, host=None, bg=True, **kwds):
  '''execute a command (possibly) on a remote host

Execute a process, and return the launcher. Use 'response' to retrieve the
response from the executed command. Use 'kill' to kill the launcher, and 'pid'
to get the process id for the launcher.

Inputs:
    command -- command string to be executed
    host    -- hostname of execution target  [default = None (i.e. run locally)]
    bg      -- run as background process?  [default = True]
  '''
  #XXX: options, background, stdin can be set w/ kwds (also name, launcher)
  bg = bool(bg) # overrides 'background'
  if host in [None, '']:
    from pathos.connection import Pipe
    launcher = Pipe(**kwds)
    launcher(command=command, background=bg)
  else:
    from pathos.secure import Pipe
    opt = kwds.pop('options', '-q')
    launcher = Pipe(**kwds)
    launcher(options=opt, command=command, host=host, background=bg)
  pathos.logger().info('executing {%s}', launcher.message)
  launcher.launch()
 #response = launcher.response()
 #launcher.kill()
 #return response
  return launcher
Esempio n. 5
0
def serve(server, host=None, port=None, profile='.bash_profile'):
  '''begin serving RPC requests

Inputs:
    server  -- name of RPC server  (i.e. 'ppserver')
    host    -- hostname on which a server should be launched
    port    -- port number (on host) that server will accept request at
    profile -- file on remote host that instantiates the user's environment
        [default = '.bash_profile']
  '''
  if host is None: #XXX: and...?
    profile = ''
  else:
    profile = 'source %s; ' % profile
  file = '~/bin/%s.py' % server  #XXX: _should_ be on the $PATH
  if port is None: port = randomport(host)
  command = "%s -p %s" % (file,port)
  rserver = execute(command, host, bg=True)
  response = rserver.response()
  pathos.logger().info('response = %r', response)
  if response in ['', None]: #XXX: other responses allowed (?)
    pass
  else: #XXX: not really error checking...
    pathos.logger().error('invalid response = %r', response)
  from time import sleep
  delay = 2.0
  sleep(delay)
  return rserver
Esempio n. 6
0
def copy(source, destination=None, **kwds):
  '''copy source to (possibly) remote destination

Execute a copy, and return the copier. Use 'kill' to kill the copier, and 
'pid' to get the process id for the copier.

Inputs:
    source      -- path string of source 'file'
    destination -- path string for destination target
  '''
  #XXX: options, background, stdin can be set w/ kwds (also name, launcher)
  if destination is None: destination = os.getcwd()
  from pathos.secure import Copier
  opt = kwds.pop('options', None)
  kwds['background'] = kwds.pop('bg', False) # ignores 'background'
  copier = Copier(**kwds)
  if ':' in source or ':' in destination:
    if opt is None: opt = '-q -r'
    copier(options=opt, source=source, destination=destination)
  else:
    if opt is None: opt = '-r'
    copier(launcher='cp', options=opt, source=source, destination=destination)
  pathos.logger().info('executing {%s}', copier.message)
  copier.launch()
  copier.kill()
  return copier
Esempio n. 7
0
 def onChild(pid, fromparent, toparent):
     try:
         response = self._server._marshaled_dispatch(data)
         self._sendResponse(response)
         line = fromparent.readline()
         toparent.write("done\n")
         toparent.flush()
     except:
         logger(name="pathos.xmlrpc", level=30).error(print_exc_info())
     os._exit(0)
Esempio n. 8
0
 def onChild(pid, fromparent, toparent):
     try:
         response = self._server._marshaled_dispatch(data)
         self._sendResponse(response)
         line = _str(fromparent.readline())
         toparent.write(_b('done\n'))
         toparent.flush()
     except:
         logger(name='pathos.xmlrpc', level=30).error(print_exc_info())
     os._exit(0)
Esempio n. 9
0
    def run_home(self):
        """
        Intended for parallelization in parent class (e.g. aggregator); runs a
        single MPCCalc home.
        :return: None
        """
        fh = logging.FileHandler(os.path.join("home_logs", f"{self.name}.log"))
        fh.setLevel(logging.WARN)

        self.log = pathos.logger(level=logging.INFO,
                                 handler=fh,
                                 name=self.name)

        self.redis_client = RedisClient()
        self.redis_get_initial_values()
        self.cast_redis_timestep()

        if self.timestep > 0:
            self.redis_get_prev_optimal_vals()

        self.get_initial_conditions()
        self.solve_type_problem()
        self.cleanup_and_finish()
        self.redis_write_optimal_vals()

        self.log.removeHandler(fh)
Esempio n. 10
0
def randomport(host=None):
  '''select a open port on a (possibly) remote host

Inputs:
    host -- hostname on which to select a open port
  '''
  from pathos.portpicker import randomport
  if not host:
    return randomport()
  from pathos.secure import Pipe
  from pathos.portpicker import __file__ as src
  # make sure src is a .py file, not .pyc or .pyo
  src = src.rstrip('co')
  launcher = Pipe() #XXX: use pox.which / which_python?
  launcher(command='python', host=host, background=False, stdin=open(src))
  pathos.logger().info('executing {python <%s} on %s', src, host)
  launcher.launch()
  try:
    rport = int(launcher.response())
  except:
    from pathos.secure import TunnelException
    raise TunnelException("failure to pick remote port")
  # return remote port number
  return rport
Esempio n. 11
0
def randomport(host=None):
  '''select a open port on a (possibly) remote host

Inputs:
    host -- hostname on which to select a open port
  '''
  from pathos.portpicker import randomport
  if not host:
    return randomport()
  from pathos.secure import Pipe
  from pathos.portpicker import __file__ as src
  # make sure src is a .py file, not .pyc or .pyo
  src = src.rstrip('co')
  launcher = Pipe() #XXX: use pox.which / which_python?
  launcher(command='python', host=host, background=False, stdin=open(src))
  pathos.logger().info('executing {python <%s} on %s', src, host)
  launcher.launch()
  try:
    rport = int(launcher.response())
  except:
    from pathos.secure import TunnelException
    raise TunnelException("failure to pick remote port")
  # return remote port number
  return rport
Esempio n. 12
0
                    handlers[fd].remove(handler)
            if not handlers[fd]:
                del handlers[fd]

        return

    def _cleanup(self):
        self._debug.info("cleaning up")
        for fd in self._input:
            fd.close()
        for fd in self._output:
            fd.close()
        for fd in self._exception:
            fd.close()

        for handler in self._interrupt:
            handler(self)

        return

    # static members
    from pathos import logger
    _debug = logger(name="pathos.selector", level=30)  # logging.WARN
    del logger

    # constants
    _TIMEOUT = .5


#  End of file
Esempio n. 13
0
class XMLRPCRequestHandler(BaseHTTPRequestHandler):
    ''' create a XML-RPC request handler '''

    _debug = logger(name="pathos.xmlrpc", level=30)  # logging.WARN

    def do_POST(self):
        """ Access point from HTTP handler """
        def onParent(pid, fromchild, tochild):
            self._server._registerChild(pid, fromchild)
            tochild.write(_b('done\n'))
            tochild.flush()

        def onChild(pid, fromparent, toparent):
            try:
                response = self._server._marshaled_dispatch(data)
                self._sendResponse(response)
                line = _str(fromparent.readline())
                toparent.write(_b('done\n'))
                toparent.flush()
            except:
                logger(name='pathos.xmlrpc', level=30).error(print_exc_info())
            os._exit(0)

        try:
            data = self.rfile.read(int(self.headers['content-length']))
            params, method = client.loads(data)
            if method == 'run':  #XXX: _str?
                return spawn2(onParent, onChild)
            else:
                response = self._server._marshaled_dispatch(data)
                self._sendResponse(response)
                return
        except:
            self._debug.error(print_exc_info())
            self.send_response(500)
            self.end_headers()
            return

    def log_message(self, format, *args):
        """ Overriding BaseHTTPRequestHandler.log_message() """

        self._debug.info(
            "%s - - [%s] %s\n" % (self.address_string(),
                                  self.log_date_time_string(), format % args))

    def _sendResponse(self, response):
        """ Write the XML-RPC response """

        response = _b(response)
        self.send_response(200)
        self.send_header("Content-type", "text/xml")
        self.send_header("Content-length", str(len(response)))
        self.end_headers()
        self.wfile.write(response)
        self.wfile.flush()
        self.connection.shutdown(1)

    def __init__(self, server, socket):
        """
Override BaseHTTPRequestHandler.__init__(): we need to be able
to have (potentially) multiple handler objects at a given time.

Inputs:
    server  -- server object to handle requests for 
    socket  -- socket connection 
        """

        ## Settings required by BaseHTTPRequestHandler
        self.rfile = socket.makefile('rb', -1)
        self.wfile = socket.makefile('wb', 0)
        self.connection = socket
        self.client_address = (server.host, server.port)

        self._server = server
Esempio n. 14
0
class Pipe(object):
    """a popen-based pipe for parallel and distributed computing"""
    verbose = True
    from pathos import logger
    _debug = logger(level=30) # logging.WARN
    del logger

    def __init__(self, name=None, **kwds):
        """create a popen-pipe

Inputs:
    name: a unique identifier (string) for the pipe
    command: a command to send  [default = 'echo <name>']
    background: run in background  [default = False]
    decode: ensure response is 'ascii'  [default = True]
    stdin: file-like object to serve as standard input for the remote process
        """
        xyz = string.ascii_letters
        self.name = ''.join(random.choice(xyz) for i in range(16)) \
               if name is None else name

        self.background = kwds.pop('background', False)
        self.stdin = kwds.pop('stdin', sys.stdin)
        self.codec = kwds.pop('decode', 'ascii')
        self.message = kwds.pop('command', 'echo %s' % self.name) #' '?
        self._response = None
        self._pid = 0
        self.config(**kwds)
        return

    def __repr__(self):
        return "Pipe('%s')" % self.message

    def config(self, **kwds):
        '''configure the pipe using given keywords

(Re)configure the pipe for the following inputs:
    command: a command to send  [default = 'echo <name>']
    background: run in background  [default = False]
    decode: ensure response is 'ascii'  [default = True]
    stdin: file-like object to serve as standard input for the remote process
        '''
        if self.message is None:
            self.message = 'echo %s' % self.name  #' '?
        if self.stdin is None:
            self.stdin = sys.stdin
        if self.codec is None:
            self.codec = 'ascii'
        for key, value in kwds.items():
            if key == 'command':
                self.message = value
            elif key == 'background':
                self.background = value
            elif key == 'decode':
                self.codec = value
            elif key == 'stdin':
                self.stdin = value

        self._stdout = None
        names=['message','background','stdin','codec']
        return dict((i,getattr(self, i)) for i in names)

    def launch(self):
        '''launch a configured command'''
        self._response = None
        self._execute()  # preempt with pox.which(message.split()[0]) ?
        return

    def _execute(self):
       #'''execute by piping the command, & saving the file object'''
        from subprocess import Popen, PIPE, STDOUT
        #XXX: what if saved list/dict of _stdout instead of just the one?
        #     could associated name/_pid and _stdout
        if self.background: #Spawn a background process 
            try:
                p = Popen(self.message, shell=True,
                          stdin=self.stdin, stdout=PIPE,
                          stderr=STDOUT, close_fds=True)
            except:
                raise PipeException('failure to pipe: %s' % self.message)
            self._pid = p.pid #get fileobject pid
            self._stdout = p.stdout #save fileobject
        else:
            try:
                p = Popen(self.message, shell=True,
                          stdin=self.stdin, stdout=PIPE)
            except:
                raise PipeException('failure to pipe: %s' % self.message)
            self._stdout = p.stdout
            self._pid = 0 #XXX: MMM --> or -1 ?
        return

    def response(self):
        '''Return the response from the launched process.
        Return None if no response was received yet from a background process.
        ''' #XXX: if PY3, return bytes, decode to ascii, take encoding, or ??? 

        if self._stdout is None:
            raise PipeException("'launch' is required after any reconfiguration")
        if self.codec is True: codec = 'ascii'
        elif self.codec is False: codec = False
        elif self.codec is None: codec = False
        else: codec = self.codec
        if self._response is not None: return _str(self._response, codec)

        # when running in foreground _pid is 0 (may change to -1)
        if self._pid <= 0:
            self._response = self._stdout.read()
            return _str(self._response, codec)
        
        # handle response from a background process
        def onData(selector, fobj):
            if self.verbose: print("handling pipe response")
            self._debug.info('on_remote')
            self._response = fobj.read()
            selector.state = False
            return

        def onTimeout(selector):
            selector.state = False
        
        sel = Selector()
        #sel._info.activate()
        sel.notifyOnReadReady(self._stdout, onData)
        sel.notifyWhenIdle(onTimeout)
        sel.watch(2.0)
        # reset _response to None to allow capture of a next response
        # from a background process
        return _str(self._response, codec)

    def pid(self):
        '''get pipe pid'''
        return self._pid

    def kill(self):
        '''terminate the pipe'''
        if self._pid > 0:
            if self.verbose: print('Kill pid=%d' % self._pid)
            os.kill(self._pid, signal.SIGTERM)
            os.waitpid(self._pid, 0)
            self._pid = 0
        return

    # interface
    __call__ = config
    pass
Esempio n. 15
0
        return


    def _cleanup(self):
        self._debug.info("cleaning up")
        for fd in self._input:
            fd.close()
        for fd in self._output:
            fd.close()
        for fd in self._exception:
            fd.close()

        for handler in self._interrupt:
            handler(self)

        return


    # static members
    from pathos import logger
    _debug = logger(name="pathos.selector", level=30) # logging.WARN
    del logger


    # constants
    _TIMEOUT = .5


#  End of file 
Esempio n. 16
0
class Selector(object):
    """
Selector object for watching and event notification.
    """
    def watch(self, timeout=None):
        """dispatch events to the registered hanlders"""

        if timeout:
            self._timeout = timeout

        self._watch()
        return

        # FIXME:
        # leave like this until I understand better the set of exceptions I
        # would like to handle. It really is bad to catch all exceptions,
        # especially since it hides errors during development
        try:
            self._watch()

        except:
            # catch all exceptions
            self._cleanup()

            # get exception information
            import sys
            type, value = sys.exc_info()[:2]

            # rethrow the exception so the clients can handle it
            raise type(value)

        return

    def notifyOnReadReady(self, fd, handler):
        """add <handler> to the list of routines to call when <fd> is read ready"""
        self._input.setdefault(fd, []).append(handler)
        return

    def notifyOnWriteReady(self, fd, handler):
        """add <handler> to the list of routines to call when <fd> is write ready"""
        self._output.setdefault(fd, []).append(handler)
        return

    def notifyOnException(self, fd, handler):
        """add <handler> to the list of routines to call when <fd> raises an exception"""
        self._exception.setdefault(fd, []).append(handler)
        return

    def notifyOnInterrupt(self, handler):
        """add <handler> to the list of routines to call when a signal arrives"""
        self._interrupt.append(handler)
        return

    def notifyWhenIdle(self, handler):
        """add <handler> to the list of routines to call when a timeout occurs"""
        self._idle.append(handler)
        return

    def __init__(self):
        """
Takes no initial input.
        """
        self.state = True
        self._timeout = self._TIMEOUT

        # the fd activity clients
        self._input = {}
        self._output = {}
        self._exception = {}

        # clients to notify when there is nothing else to do
        self._idle = []
        self._interrupt = []

        return

    def _watch(self):
        import select

        while self.state:

            self._debug.debug("constructing list of watchers")
            iwtd = list(self._input.keys())
            owtd = list(self._output.keys())
            ewtd = list(self._exception.keys())

            self._debug.debug("input: %s" % iwtd)
            self._debug.debug("output: %s" % owtd)
            self._debug.debug("exception: %s" % ewtd)

            self._debug.debug("checking for indefinite block")
            if not iwtd and not owtd and not ewtd and not self._idle:
                self._debug.info("no registered handlers left; exiting")
                return

            self._debug.debug("calling select")
            try:
                reads, writes, excepts = select.select(iwtd, owtd, ewtd,
                                                       self._timeout)
            except select.error as error:  # breaks 2.5 compatibility
                # GUESS:
                # when a signal is delivered to a signal handler registered
                # by the application, the select call is interrupted and
                # raises a select.error
                errno, msg = error.args
                self._debug.info("signal received: %d: %s" % (errno, msg))
                continue

            self._debug.debug("returned from select")

            # dispatch to the idle handlers if this was a timeout
            if not reads and not writes and not excepts:
                self._debug.info("no activity; dispatching to idle handlers")
                for handler in self._idle:
                    if not handler(self):
                        self._idle.remove(handler)
            else:
                # dispatch to the registered handlers
                self._debug.info("dispatching to exception handlers")
                self._dispatch(self._exception, excepts)
                self._debug.info("dispatching to output handlers")
                self._dispatch(self._output, writes)
                self._debug.info("dispatching to input handlers")
                self._dispatch(self._input, reads)

        return

    def _dispatch(self, handlers, entities):

        for fd in entities:
            for handler in handlers[fd]:
                if not handler(self, fd):
                    handlers[fd].remove(handler)
            if not handlers[fd]:
                del handlers[fd]

        return

    def _cleanup(self):
        self._debug.info("cleaning up")
        for fd in self._input:
            fd.close()
        for fd in self._output:
            fd.close()
        for fd in self._exception:
            fd.close()

        for handler in self._interrupt:
            handler(self)

        return

    # static members
    from pathos import logger
    _debug = logger(name="pathos.selector", level=30)  # logging.WARN
    del logger

    # constants
    _TIMEOUT = .5
Esempio n. 17
0
#!/usr/bin/env python
#
# Author: Mike McKerns (mmckerns @caltech and @uqfoundation)
# Copyright (c) 1997-2015 California Institute of Technology.
# License: 3-clause BSD.  The full license text is available at:
#  - http://trac.mystic.cacr.caltech.edu/project/pathos/browser/pathos/LICENSE
"""
example of building a simple xmlrpc server and proxy,
and then demonstrate the handling of a few basic requests

To run: python xmlrpc_server.py
"""

from pathos.xmlrpc import XMLRPCServer
from pathos import logger
logger(level=20, name='pathos.xmlrpc')   # logging.INFO
logger(level=20, name='pathos.selector') # logging.INFO

if __name__ == '__main__':
    
    import os, time, xmlrpclib

    s = XMLRPCServer('', 0)
    print 'port=%d' % s.port
    port = s.port

    pid = os.fork()
    if pid > 0: #parent
        def add(x, y): return x + y
        s.register_function(add)
        s.activate()
Esempio n. 18
0
# Author: Mike McKerns (mmckerns @caltech and @uqfoundation)
# Copyright (c) 1997-2016 California Institute of Technology.
# Copyright (c) 2016-2017 The Uncertainty Quantification Foundation.
# License: 3-clause BSD.  The full license text is available at:
#  - http://trac.mystic.cacr.caltech.edu/project/pathos/browser/pathos/LICENSE
"""
example of building a simple xmlrpc server and proxy,
and then demonstrate the handling of a few basic requests

To run: python xmlrpc_server.py
To stop: < Ctrl+C >
"""

from pathos.xmlrpc import XMLRPCServer
from pathos import logger
logger(level=20, name='pathos.xmlrpc')   # logging.INFO
logger(level=20, name='pathos.selector') # logging.INFO

if __name__ == '__main__':
    
    import os, time
    try:
        import xmlrpc.client as client
    except ImportError:
        import xmlrpclib as client

    s = XMLRPCServer('', 0)
    print('port=%d' % s.port)
    port = s.port

    pid = os.fork()