Package qm :: Module host
[hide private]
[frames] | no frames]

Source Code for Module qm.host

  1  ######################################################################## 
  2  # 
  3  # File:   host.py 
  4  # Author: Mark Mitchell 
  5  # Date:   2005-06-03 
  6  # 
  7  # Contents: 
  8  #   Host 
  9  # 
 10  # Copyright (c) 2005 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  ######################################################################## 
 13   
 14  ######################################################################## 
 15  # Imports 
 16  ####################################################################### 
 17   
 18  from   qm.executable import RedirectedExecutable 
 19  from   qm.extension import Extension 
 20  import os.path 
 21   
 22  ######################################################################## 
 23  # Classes 
 24  ####################################################################### 
 25   
26 -class Host(Extension):
27 """A 'Host' is a logical machine. 28 29 Each logical machine has a default directory. When a file is 30 uploaded to or downloaded from the machine, and a relative path 31 is specified, the patch is relative to the default directory. 32 Similarly, when a program is run on the remote machine, its 33 initial working directory is the default directory. 34 35 The interface presented by 'Host' is a lowest common 36 denominator. The objective is not to expose all the functionality 37 of any host; rather it is to provide an interface that can be used 38 on many hosts.""" 39 40 kind = "host" 41
42 - class Executable(RedirectedExecutable):
43 """An 'Executable' is a simple redirected executable. 44 45 The standard error and standard output streams are combined 46 into a single stream. 47 48 The standard input is not closed before 49 invoking the program because SSH hangs if its standard input 50 is closed before it is invoked. For example, running: 51 52 ssh machine echo hi <&- 53 54 will hang with some versions of SSH.""" 55
56 - def _StderrPipe(self):
57 58 return None
59 60
61 - def __init__(self, arguments = None, **args):
62 63 if arguments: args.update(arguments) 64 super(Host, self).__init__(**args)
65 66
67 - def Run(self, path, arguments, environment = None, timeout = -1, 68 relative = False):
69 """Run a program on the remote host. 70 71 'path' -- The name of the program to run, on the remote host. 72 If 'relative' is true, or if 'path' is not an absolute path 73 but does contain at least one directory separator, then 'path' 74 is interpreted relative to the default directory. Otherwise, 75 'path' is used unmodified. 76 77 'arguments' -- The sequence of arguments that should be passed 78 to the program. 79 80 'environment' -- If not 'None', a dictionary of pairs of 81 strings to add to the environment of the running program. 82 83 'timeout' -- The number of seconds the program is permitted 84 to execute. After the 'timeout' expires, the program will be 85 terminated. However, in some cases (such as when using 'rsh') 86 it will be the local side of the connection that is closed. 87 The remote side of the connection may or may not continue to 88 operate, depending on the vagaries of the remote operating 89 system. 90 91 returns -- A pair '(status, output)'. The 'status' is the 92 exit status returned by the program, or 'None' if the exit 93 status is not available. The 'output' is a string giving the 94 combined standard output and standard error output from the 95 program.""" 96 97 # Compute the full environment for the child. 98 if environment is not None: 99 new_environment = os.environ.copy() 100 new_environment.update(environment) 101 environment = new_environment 102 executable = self.Executable(timeout) 103 if relative: 104 path = os.path.join(os.curdir, path) 105 status = executable.Run([path] + arguments, environment) 106 return (status, executable.stdout)
107 108
109 - def UploadFile(self, local_file, remote_file = None):
110 """Copy 'local_file' to 'remote_file'. 111 112 'local_file' -- The name of the file on the local machine. 113 114 'remote_file' -- The name of the file on the remote machine. 115 The 'remote_file' must be a relative path. It is interpreted 116 relative to the default directory. If 'None', the 117 'remote_file' is placed in the default directory using the 118 basename of the 'local_file'. 119 120 If the 'local_file' and 'remote_file' are the same, then this 121 function succeeds, but takes no action.""" 122 123 raise NotImplementedError
124 125
126 - def DownloadFile(self, remote_file, local_file):
127 """Copy 'remote_file' to 'local_file'. 128 129 'remote_file' -- The name of the file on the remote machine. 130 The 'remote_file' must be a relative path. It is interpreted 131 relative to the default directory. 132 133 'local_file' -- The name of the file on the local machine. If 134 'None', the 'local_file' is placed in the current directory 135 using the basename of the 'remote_file'. 136 137 If the 'local_file' and 'remote_file' are the same, then this 138 function succeeds, but takes no action.""" 139 140 raise NotImplementedError
141 142
143 - def UploadAndRun(self, path, arguments, environment = None, 144 timeout = -1):
145 """Run a program on the remote host. 146 147 'path' -- The name of the program to run, as a path on the 148 local machine. 149 150 'arguments' -- As for 'Run'. 151 152 'environment' -- As for 'Run'. 153 154 'timeout' -- As for 'Run'. 155 156 returns -- As for 'Run'. 157 158 The program is uploaded to the default directory on the remote 159 host, run, and then deleted.""" 160 161 self.UploadFile(path) 162 basename = os.path.basename(path) 163 result = self.Run(basename, 164 arguments, 165 environment, 166 timeout, 167 relative = True) 168 self.DeleteFile(basename) 169 return result
170 171
172 - def DeleteFile(self, remote_file):
173 """Delete the 'remote_file'. 174 175 'remote_file' -- A relative path to the file to be deleted.""" 176 177 raise NotImplementedError
178