Package ClusterShell :: Package Worker :: Module Popen
[hide private]
[frames] | no frames]

Source Code for Module ClusterShell.Worker.Popen

  1  # 
  2  # Copyright (C) 2008-2015 CEA/DAM 
  3  # Copyright (C) 2015 Stephane Thiell <sthiell@stanford.edu> 
  4  # 
  5  # This file is part of ClusterShell. 
  6  # 
  7  # ClusterShell is free software; you can redistribute it and/or 
  8  # modify it under the terms of the GNU Lesser General Public 
  9  # License as published by the Free Software Foundation; either 
 10  # version 2.1 of the License, or (at your option) any later version. 
 11  # 
 12  # ClusterShell is distributed in the hope that it will be useful, 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
 15  # Lesser General Public License for more details. 
 16  # 
 17  # You should have received a copy of the GNU Lesser General Public 
 18  # License along with ClusterShell; if not, write to the Free Software 
 19  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 
 20   
 21  """ 
 22  WorkerPopen 
 23   
 24  ClusterShell worker for executing local commands. 
 25   
 26  Usage example: 
 27     >>> worker = WorkerPopen("/bin/uname", key="mykernel") 
 28     >>> task.schedule(worker)    # schedule worker 
 29     >>> task.resume()            # run task 
 30     >>> worker.retcode()         # get return code 
 31     0 
 32     >>> worker.read()            # read command output 
 33     'Linux' 
 34   
 35  """ 
 36   
 37  from ClusterShell.Worker.Worker import WorkerSimple, StreamClient 
 38   
 39   
40 -class PopenClient(StreamClient):
41
42 - def __init__(self, worker, key, stderr, timeout, autoclose):
43 StreamClient.__init__(self, worker, key, stderr, timeout, autoclose) 44 self.popen = None 45 self.rc = None 46 # Declare writer stream to allow early buffering 47 self.streams.set_writer(worker.SNAME_STDIN, None, retain=False)
48
49 - def _start(self):
50 """Worker is starting.""" 51 assert not self.worker.started 52 assert self.popen is None 53 54 self.popen = self._exec_nonblock(self.worker.command, shell=True) 55 56 task = self.worker.task 57 if task.info("debug", False): 58 task.info("print_debug")(task, "POPEN: %s" % self.worker.command) 59 60 self.worker._on_start(self.key) 61 return self
62
63 - def _close(self, abort, timeout):
64 """ 65 Close client. See EngineClient._close(). 66 """ 67 if abort: 68 # it's safer to call poll() first for long time completed processes 69 prc = self.popen.poll() 70 # if prc is None, process is still running 71 if prc is None: 72 try: # try to kill it 73 self.popen.kill() 74 except OSError: 75 pass 76 prc = self.popen.wait() 77 78 self.streams.clear() 79 80 if prc >= 0: # filter valid rc 81 self.rc = prc 82 self.worker._on_rc(self.key, prc) 83 elif timeout: 84 assert abort, "abort flag not set on timeout" 85 self.worker._on_timeout(self.key) 86 elif not abort: 87 # if process was signaled, return 128 + signum (bash-like) 88 self.rc = 128 + -prc 89 self.worker._on_rc(self.key, self.rc) 90 91 if self.worker.eh: 92 self.worker.eh.ev_close(self.worker)
93 94
95 -class WorkerPopen(WorkerSimple):
96 """ 97 Implements the Popen Worker. 98 """
99 - def __init__(self, command, key=None, handler=None, 100 stderr=False, timeout=-1, autoclose=False):
101 """Initialize Popen worker.""" 102 WorkerSimple.__init__(self, None, None, None, key, handler, stderr, 103 timeout, autoclose, client_class=PopenClient) 104 self.command = command 105 if not self.command: 106 raise ValueError("missing command parameter in WorkerPopen " 107 "constructor")
108
109 - def retcode(self):
110 """Return return code or None if command is still in progress.""" 111 return self.clients[0].rc
112 113 WORKER_CLASS = WorkerPopen 114