-
Notifications
You must be signed in to change notification settings - Fork 86
Task (class)
Task
is the main class of ClusterShell commands execution support. It represents the whole application task (if application is single-threaded, see note below). Its interface is the main entry point to submit work to do (launch commands, gather outputs, arm timers, copy files, etc.).
A ClusterShell's Task
is bound to a specific execution thread. The Task
class is a ''per-thread Singleton class''.
For single-threaded applications, a Task
is a simple singleton which instance is available through the task_self()
function. The task_self()
function is available at the module Task
root:
from ClusterShell.Task import task_self
task = task_self()
You can submit a set of commands for local or distant execution (in parallel) with the help of the following methods:
Task.shell(...) # submit local or distant command for execution
Task.copy(...) # copy a file to distant nodes
Task.rcopy(...) # copy distant file or directory to local node
Local usage:
task.shell(command [, key=key] [, handler=handler] [, timeout=secs])
Distant usage:
task.shell(command, nodes=nodeset [, handler=handler] [, timeout=secs])
Once the work submitted through the shell()
, copy()
or rcopy()
methods, start the Task
execution with the following method:
task.resume()
At this time, all previously submitted commands will start in the associated Task
's thread. For a single-threaded application, the current thread will be blocked until the end of the commands execution.
Additionally, the library provides a convenience method Task.run()
to run a command (locally or on a set of nodes):
task.run([command, nodes=nodeset [, handler=handler] [, timeout=secs]])
With arguments, it will schedule a command exactly like a Task.shell()
would have done it and run it.
Two coding/usage models are available with the ClusterShell library, for each Task:
- sequential model: each execution waits for the end of all commands, ie. when
task.resume()
returns, - event-based model: the application derives the EventHandler class to listen for events.
The sequential model is convenient for administration scripts that don't need any interaction during commands execution.
The script access to the standard output (automatic gathering) and to return codes through:
Example of command execution on distant nodes:
from ClusterShell.Task import task_self
task = task_self()
task.run("/bin/uname -r", nodes="green[36-39,133]")
for buf, nodes in task.iter_buffers():
print nodes, buf
Result:
['green37', 'green38', 'green133', 'green36', 'green39'] 2.6.18-164.11.1.el5
Similar example but with multiple commands:
from ClusterShell.Task import task_self
task = task_self()
task.shell("/bin/uname -r", nodes="green[36-39,133]")
task.shell("/bin/uname -p", nodes="green[36-39,133]")
task.resume()
for buf, nodes in task.iter_buffers():
print nodes, buf
Result:
['green37', 'green38', 'green133', 'green36', 'green39'] 2.6.18-164.11.1.el5
['green37', 'green38', 'green133', 'green36', 'green39'] x86_64
The event-based model is required when the application needs to interact with the user during while commands are executing.
To use it, you need to:
- derive the EventHandler class and implement choosen
ev_*
methods (for example:ev_start()
,ev_read()
,ev_close()
...) - instantiate this class and add it as a parameter when calling
Task.shell()
Example of Task.shell()
call:
task.shell(“/bin/uname -r“, nodes=“green[36-39,133]“, handler=MyHandler())
Example of use: filter standard outputs of commands during their execution:
from ClusterShell.Task import task_self
from ClusterShell.Event import EventHandler
class MyHandler(EventHandler):
def ev_read(self, worker):
node, buf = worker.last_read()
if buf.find(".el5") < 0:
print "%s: %s" % (node, buf)
task = task_self()
task.run("/bin/uname -a", nodes="nova[32-159]", handler=MyHandler())
Result:
nova142: Linux nova142 2.6.25.11-cea4 #1 SMP Tue Dec 2 15:47:32 CET 2008 x86_64 x86_64 x86_64 GNU/Linux
...