Package osh :: Package command :: Module remote
[frames] | no frames]

Source Code for Module osh.command.remote

  1  # osh 
  2  # Copyright (C) 2005 Jack Orenstein <jao@geophile.com> 
  3  # 
  4  # This program is free software; you can redistribute it and/or modify 
  5  # it under the terms of the GNU General Public License as published by 
  6  # the Free Software Foundation; either version 2 of the License, or 
  7  # (at your option) any later version. 
  8  # 
  9  # This program is distributed in the hope that it will be useful, 
 10  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 11  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 12  # GNU General Public License for more details. 
 13  # 
 14  # You should have received a copy of the GNU General Public License 
 15  # along with this program; if not, write to the Free Software 
 16  # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 17   
 18  """For API usage only, (for CLI use C{osh @CLUSTER [ ... ]} syntax instead.) 
 19  """ 
 20   
 21  import osh.args 
 22  import osh.core 
 23  import osh.spawn 
 24  import osh.error 
 25   
 26  Spawn = osh.spawn.Spawn 
 27  ObjectInputProvider = osh.spawn.ObjectInputProvider 
 28  ObjectOutputConsumer = osh.spawn.ObjectOutputConsumer 
 29  LineOutputConsumer = osh.spawn.LineOutputConsumer 
 30  Option = osh.args.Option 
 31   
 32  _REMOTE_EXECUTABLE = 'remoteosh' 
 33   
34 -def _dump(stream, object):
35 stream.dump(object)
36
37 -def _consume_remote_stdout(consumer, host, object):
38 if isinstance(object, osh.error.Error): 39 exception = object.recreate_exception() 40 osh.error.exception_handler(exception, object.command_description(), object.input(), host) 41 else: 42 consumer.send((host,) + tuple(object))
43
44 -def _consume_remote_stderr(consumer, host, line):
45 # UGLY HACK: remoteosh can occasionally return "[Errno 9] Bad file descriptor" on stderr. 46 # I think this is because of io to a process stream whose process has completed. 47 # I haven't had luck in tracking this down and fixing the problem for real, so 48 # this is a grotesque workaround. 49 if '[Errno 9] Bad file descriptor' not in line: 50 osh.error.stderr_handler(line, consumer, None, host)
51 52 # CLI
53 -def _remote():
54 return _Remote()
55 56 # API
57 -def remote(cluster, remote_command):
58 """Execute a command on each node of C{cluster}. Output from each node is sent to 59 the output stream, with the node name added as the first element of the output tuple. 60 """ 61 import osh.apiparser 62 op = _Remote() 63 if isinstance(remote_command, osh.core.Op): 64 remote_command = [remote_command] 65 remote_pipeline = osh.apiparser._sequence_op(remote_command) 66 op.set_pipeline(remote_pipeline) 67 return op.process_args(Option('-c', cluster))
68
69 -class _Remote(osh.core.RemoteOp):
70 71 # state 72 73 _pipeline = None 74 75 76 # object interface 77
78 - def __init__(self):
79 osh.core.RemoteOp.__init__(self, 'c:', (0, 0))
80 81 # BaseOp interface 82
83 - def doc(self):
84 return __doc__
85
86 - def setup(self):
87 osh.core.RemoteOp.setup(self)
88 89 90 # generator interface 91
92 - def execute(self):
93 osh.core.RemoteOp.execute(self) 94 self.send_complete()
95 96 97 # RemoteOp interface 98
99 - def action(self, host):
100 process = Spawn( 101 self._remote_command(host.address, self.user(), host.db_profile), 102 ObjectInputProvider(lambda stream, object: _dump(stream, object), 103 [osh.core.verbosity, self._pipeline]), 104 ObjectOutputConsumer(lambda object: _consume_remote_stdout(self, host.name, object)), 105 LineOutputConsumer(lambda line: _consume_remote_stderr(self, host.name, line))) 106 process.run() 107 if process.terminating_exception(): 108 self.set_terminating_exception(process.terminating_exception())
109 110 111 # remote compile-time interface 112
113 - def set_pipeline(self, pipeline):
114 self._pipeline = pipeline 115 return self
116 117 118 # for use by this class 119
120 - def _remote_command(self, host, user, db_profile):
121 if db_profile: 122 remote_command = '"%s %s"' % (_REMOTE_EXECUTABLE, db_profile) 123 else: 124 remote_command = _REMOTE_EXECUTABLE 125 ssh_command = 'ssh %s -l %s %s' % (host, user, remote_command) 126 return ssh_command
127