Package diffpy :: Package pdfgui :: Package control :: Module serverhost
[hide private]
[frames] | no frames]

Source Code for Module diffpy.pdfgui.control.serverhost

  1  #!/usr/bin/env python 
  2  ############################################################################## 
  3  # 
  4  # PDFgui            by DANSE Diffraction group 
  5  #                   Simon J. L. Billinge 
  6  #                   (c) 2006 trustees of the Michigan State University. 
  7  #                   All rights reserved. 
  8  # 
  9  # File coded by:    Jiwu Liu 
 10  # 
 11  # See AUTHORS.txt for a list of people who contributed. 
 12  # See LICENSE.txt for license information. 
 13  # 
 14  ############################################################################## 
 15   
 16  from diffpy.pdfgui.control.controlerrors import * 
 17  from diffpy.pdfgui.control.pdfcomponent import PDFComponent 
 18   
19 -class ServerHost(PDFComponent):
20 """ServerHost holds the information about a remote machine where the 21 pdfserver process is running. It can host multiple remote pdfserver. 22 23 Data members: 24 25 servers: a list of local representatives of remote pdfserver instances 26 config: configuration dictionary of remote host 27 connection: a ssh2 connection to remote host 28 """
29 - class Server(object):
30 """Server is the local represetative of a remote pdfserver 31 32 pdfserver: a xmlrpclib.ServerProxy to pdfserver 33 address: a host:port string 34 busy: True if it is in use, otherwise False 35 running: True if it is running 36 connection: a ssh2 connection to remote host 37 port: remote port where pdfserver is servicing 38 """
39 - def __init__(self, connection):
40 """Initialize the remote server 41 42 connection -- a ssh2 connection to remote host 43 """ 44 self.connection = connection 45 self.pdfserver = None 46 self.port = -1 47 self.address = '' 48 49 # One server can only service one fitting request at a time 50 # by default, create and use 51 self.busy = True 52 self.running = False 53 54 self.__start()
55
56 - def __start(self):
57 """Start remote pdfserver. pdfserver.py must be in the user's PATH. 58 It chooses the remote port on which it is running. 59 """ 60 command = "pdffit2server" 61 output = self.connection.execute(command) 62 try: 63 self.port = int(output.splitlines()[0]) 64 except (IndexError,ValueError): 65 raise ControlRuntimeError, \ 66 "Unrecognized output from remote host %s: "%self.connection.host + output 67 return
68
69 - def connect(self):
70 """Set up XMLRPC ServerProxy and test connection. 71 """ 72 from xmlrpclib import ServerProxy 73 self.address = "http://%s:%i"%(self.connection.host, self.port) 74 transport = self.connection.getXMLRPCTransport() 75 self.pdfserver = ServerProxy(self.address,transport) 76 77 import time 78 79 # now keep polling if the server is up ( test for 15 seconds) 80 counter = 5 81 while counter > 0 and not self.running: 82 if self.connection.owner.quit: 83 return 84 try: 85 # server started slowly, allow 3 seconds in the beginning 86 time.sleep(3) 87 self.running = self.pdfserver.isRunning() 88 counter = -1 89 except ControlConnectError: 90 counter -= 1 91 92 93 if counter == 0: 94 raise ControlRuntimeError, \ 95 "Can not connect to pdferver@'%s'"%self.connection.host
96
97 - def close(self):
98 """Kill the server""" 99 if self.running: 100 self.pdfserver.kill_server() 101 return
102 # End of class Server 103
104 - def __init__(self, name, config):
105 """initialize 106 107 name -- component name 108 config -- configuration for this proxy 109 """ 110 if name is None: 111 name = 'ServerHost' 112 113 PDFComponent.__init__(self, name) 114 self.config = config 115 116 import threading 117 self.lock = threading.RLock() 118 self.servers = [] 119 120 from diffpy.pdfgui.control.connection import Connection 121 self.connection = Connection(self) 122 123 self.quit = False 124 return
125
126 - def getServer(self, bWait=False):
127 """Get a pdfserver proxy 128 129 bWait -- wait for server or not (default False) 130 return: a pdfserver proxy 131 """ 132 try: 133 self.lock.acquire() 134 for server in self.servers: 135 if not server.busy and server.running: 136 server.busy = True 137 return server.pdfserver 138 else: 139 # if self.servers is not empty and we'd like to wait 140 if bWait and self.servers: 141 #FIXME: a semaphore should be created so that we can wait here 142 pass 143 else: 144 # i need a new one 145 server = ServerHost.Server(self.getConnection()) 146 server.connect() # connect to pdfserver 147 self.servers.append(server) 148 return server.pdfserver 149 finally: 150 self.lock.release() 151 152 return None
153
154 - def releaseServer(self, pdfserver):
155 """Release a pdfserver proxy 156 157 pdfserver -- a pdfserver proxy 158 """ 159 try: 160 self.lock.acquire() 161 for server in self.servers: 162 if server.pdfserver is pdfserver: 163 server.busy = False 164 break 165 finally: 166 self.lock.release() 167 return
168
169 - def close(self, force = False):
170 """shut down connection to remote host 171 172 force -- if shut down forcefully 173 """ 174 self.quit = True 175 try: 176 self.lock.acquire() 177 #make a copy to traverse 178 for server in self.servers[:]: 179 if server.busy and not force: 180 # we can not close it because some fittings are still use its tunnel 181 raise ControlStatusError, "ServerHost: %s is busy"%self.name 182 else: 183 server.close() 184 self.servers.remove(server) 185 finally: 186 self.lock.release() 187 188 self.connection.close() 189 return
190
191 - def onError(self, address):
192 """handle the error from connection 193 194 address -- remote pdfserver address 195 """ 196 try: 197 self.lock.acquire() 198 for server in self.servers: 199 if server.address == address: 200 server.running = False 201 finally: 202 self.lock.release()
203
204 - def getConnection(self):
205 """Get a verified and connected ssh transport. 206 207 This tries to establish an ssh connection using the ssh2 protocol with a 208 preconfigured host. This uses paramiko's Agent class, which may work 209 differently on Windows. 210 211 return value: connection 212 """ 213 if self.connection.isConnected(): 214 return self.connection 215 216 # otherwise, reconnect to remote host 217 import os 218 from diffpy.pdfgui.control.connection import Connection 219 try: 220 # extract info from configuration 221 host = self.config['host'] 222 user = self.config['username'] 223 auth = self.config['authentication'] 224 if self.config['use_default_port']: 225 port = Connection.DefaultPort 226 else: 227 port = int(self.config['port']) 228 229 if auth == Connection.PSWDAUTH: 230 passwd = self.config['password'] 231 self.connection.connect(host,user,port,auth,passwd=passwd) 232 else: # RSA or DSA 233 if self.config['use_default_path']: 234 keyFile = os.environ['HOME'] + '/.ssh/id_rsa' 235 else: 236 keyFile = self.config['path'] 237 passphrase = self.config.get('passphrase', None) 238 self.connection.connect(host,user,port,auth,keyFile=keyFile, 239 passphrase = passphrase) 240 except KeyError, error: 241 raise ControlConfigError,\ 242 "ServerHost: '%s' doesn't have key '%s'"%(self.name, str(error)) 243 244 return self.connection
245 246 247 if __name__ == '__main__': 248 import sys 249 import getopt 250 import getpass 251 from diffpy.pdfgui.control.connection import Connection
252 - def _usage():
253 print "Usage: %s [-u user@host] [-p(passwd)|-r(rsa)|-d(dsa)]"%sys.argv[0]
254 255 # parse arguments 256 try: 257 optlist, args = getopt.getopt(sys.argv[1:], "u:prd" ) 258 except getopt.GetOptError: 259 usage() 260 sys.exit(1) 261 262 user = getpass.getuser() 263 host = 'localhost' 264 auth = Connection.RSAAUTH 265 for o,a in optlist: 266 if o == '-u': 267 user,host = a.split('@') 268 elif o == '-p': 269 auth = Connection.PSWDAUTH 270 elif o == '-r': 271 auth = Connection.RSAAUTH 272 elif o == '-d': 273 auth = Connection.DSAAUTH 274 275 config = { 276 'use_default_port' : True, 277 'use_default_path' : True, 278 'host' : host, 279 'authentication' : auth, 280 'username' : user, 281 } 282 if auth == Connection.PSWDAUTH: 283 config ['password'] = getpass.getpass("Password: ") 284 285 proxy = ServerHost(host,config) 286 pdfserver = proxy.getServer() 287 #print "pdfserver.isRunning():", pdfserver.isRunning() 288 print "pdfserver.reset():", pdfserver.reset() 289 proxy.close(True) 290 print 'Session closed.' 291 292 # version 293 __id__ = "$Id: serverhost.py 2980 2009-04-02 00:14:33Z juhas $" 294 295 # End of file 296