Package flumotion :: Package worker :: Module main
[hide private]

Source Code for Module flumotion.worker.main

  1  # -*- Mode: Python -*- 
  2  # vi:si:et:sw=4:sts=4:ts=4 
  3   
  4  # Flumotion - a streaming media server 
  5  # Copyright (C) 2004,2005,2006,2007,2008,2009 Fluendo, S.L. 
  6  # Copyright (C) 2010,2011 Flumotion Services, S.A. 
  7  # All rights reserved. 
  8  # 
  9  # This file may be distributed and/or modified under the terms of 
 10  # the GNU Lesser General Public License version 2.1 as published by 
 11  # the Free Software Foundation. 
 12  # This file is distributed without any warranty; without even the implied 
 13  # warranty of merchantability or fitness for a particular purpose. 
 14  # See "LICENSE.LGPL" in the source distribution for more information. 
 15  # 
 16  # Headers in this file shall remain intact. 
 17   
 18  import os 
 19  import sys 
 20   
 21  from twisted.internet import reactor 
 22   
 23  from flumotion.configure import configure 
 24  from flumotion.common import log, errors 
 25  from flumotion.common import connection 
 26  from flumotion.common.options import OptionGroup, OptionParser 
 27  from flumotion.common.process import startup 
 28  from flumotion.worker import worker, config 
 29  from flumotion.twisted import pb 
 30   
 31  __version__ = "$Rev$" 
 32   
 33   
34 -def _createParser():
35 parser = OptionParser(domain="flumotion-worker") 36 37 group = OptionGroup(parser, "worker options") 38 group.add_option('-H', '--host', 39 action="store", type="string", dest="host", 40 help="manager host to connect to [default localhost]") 41 group.add_option('-P', '--port', 42 action="store", type="int", dest="port", 43 help="manager port to connect to " \ 44 "[default %d (ssl) or %d (tcp)]" % ( 45 configure.defaultSSLManagerPort, 46 configure.defaultTCPManagerPort)) 47 group.add_option('-T', '--transport', 48 action="store", type="string", dest="transport", 49 help="transport protocol to use (tcp/ssl) [default ssl]") 50 group.add_option('-n', '--name', 51 action="store", type="string", dest="name", 52 help="worker name to use in the manager") 53 group.add_option('-s', '--service-name', 54 action="store", type="string", dest="serviceName", 55 help="name to use for log and pid files " 56 "when run as a daemon") 57 group.add_option('-D', '--daemonize', 58 action="store_true", dest="daemonize", 59 help="run in background as a daemon") 60 group.add_option('', '--daemonize-to', 61 action="store", dest="daemonizeTo", 62 help="what directory to run from when daemonizing") 63 64 parser.add_option('-L', '--logdir', 65 action="store", dest="logdir", 66 help="flumotion log directory (default: %s)" % 67 configure.logdir) 68 parser.add_option('-R', '--rundir', 69 action="store", dest="rundir", 70 help="flumotion run directory (default: %s)" % 71 configure.rundir) 72 73 group.add_option('-u', '--username', 74 action="store", type="string", dest="username", 75 default="", 76 help="username to use") 77 group.add_option('-p', '--password', 78 action="store", type="string", dest="password", 79 default="", 80 help="password to use") 81 82 group.add_option('-F', '--feederports', 83 action="store", type="string", dest="feederports", 84 help="range of feeder ports to use") 85 group.add_option('', '--random-feederports', 86 action="store_true", 87 dest="randomFeederports", 88 help="Use randomly available feeder ports") 89 90 parser.add_option_group(group) 91 92 return parser
93 94
95 -def _readConfig(workerFile, options):
96 # modifies options dict in-place 97 log.info('worker', 'Reading configuration from %s' % workerFile) 98 try: 99 cfg = config.WorkerConfigXML(workerFile) 100 except config.ConfigError, value: 101 raise errors.FatalError( 102 "Could not load configuration from %s: %s" % ( 103 workerFile, value)) 104 except IOError, e: 105 raise errors.FatalError( 106 "Could not load configuration from %s: %s" % ( 107 workerFile, e.strerror)) 108 109 # now copy over stuff from config that is not set yet 110 if not options.name and cfg.name: 111 log.debug('worker', 'Setting worker name %s' % cfg.name) 112 options.name = cfg.name 113 114 # manager 115 if not options.host and cfg.manager.host: 116 options.host = cfg.manager.host 117 log.debug('worker', 'Setting manager host to %s' % options.host) 118 if not options.port and cfg.manager.port: 119 options.port = cfg.manager.port 120 log.debug('worker', 'Setting manager port to %s' % options.port) 121 if not options.transport and cfg.manager.transport: 122 options.transport = cfg.manager.transport 123 log.debug('worker', 'Setting manager transport to %s' % 124 options.transport) 125 126 # authentication 127 if not options.username and cfg.authentication.username: 128 options.username = cfg.authentication.username 129 log.debug('worker', 'Setting username %s' % options.username) 130 if not options.password and cfg.authentication.password: 131 options.password = cfg.authentication.password 132 log.debug('worker', 133 'Setting password [%s]' % ("*" * len(options.password))) 134 135 # feederports: list of allowed ports 136 # XML could specify it as empty, meaning "don't use any" 137 if not options.feederports and cfg.feederports is not None: 138 options.feederports = cfg.feederports 139 if options.randomFeederports is None: 140 options.randomFeederports = cfg.randomFeederports 141 if options.randomFeederports: 142 options.feederports = None 143 log.debug('worker', 'Using random feederports') 144 if options.feederports is not None: 145 log.debug('worker', 'Using feederports %r' % options.feederports) 146 147 # general 148 # command-line debug > environment debug > config file debug 149 if not options.debug and cfg.fludebug \ 150 and not 'FLU_DEBUG' in os.environ: 151 options.debug = cfg.fludebug
152 153
154 -def main(args):
155 parser = _createParser() 156 log.debug('worker', 'Parsing arguments (%r)' % ', '.join(args)) 157 options, args = parser.parse_args(args) 158 159 # Force options down configure's throat 160 for d in ['logdir', 'rundir']: 161 o = getattr(options, d, None) 162 if o: 163 log.debug('worker', 'Setting configure.%s to %s' % (d, o)) 164 setattr(configure, d, o) 165 166 # translate feederports string to range 167 if options.feederports: 168 if not '-' in options.feederports: 169 raise errors.OptionError("feederports '%s' does not contain '-'" % 170 options.feederports) 171 (lower, upper) = options.feederports.split('-') 172 options.feederports = range(int(lower), int(upper) + 1) 173 174 # check if a config file was specified; if so, parse config and copy over 175 if len(args) > 1: 176 workerFile = args[1] 177 _readConfig(workerFile, options) 178 179 # set default values for all unset options 180 if not options.host: 181 options.host = 'localhost' 182 if not options.transport: 183 options.transport = 'ssl' 184 if not options.port: 185 if options.transport == "tcp": 186 options.port = configure.defaultTCPManagerPort 187 elif options.transport == "ssl": 188 options.port = configure.defaultSSLManagerPort 189 190 # set a default name if none is given 191 if not options.name: 192 if options.host == 'localhost': 193 options.name = 'localhost' 194 log.debug('worker', 'Setting worker name localhost') 195 else: 196 import socket 197 options.name = socket.gethostname() 198 log.debug('worker', 'Setting worker name %s (from hostname)' % 199 options.name) 200 201 if options.feederports is None and not options.randomFeederports: 202 options.feederports = configure.defaultGstPortRange 203 log.debug('worker', 'Using default feederports %r' % 204 options.feederports) 205 206 # check for wrong options/arguments 207 if not options.transport in ['ssl', 'tcp']: 208 sys.stderr.write('ERROR: wrong transport %s, must be ssl or tcp\n' % 209 options.transport) 210 return 1 211 212 # reset FLU_DEBUG which could be different after parsing XML file 213 if options.debug: 214 log.setFluDebug(options.debug) 215 216 if options.daemonizeTo and not options.daemonize: 217 sys.stderr.write( 218 'ERROR: --daemonize-to can only be used with -D/--daemonize.\n') 219 return 1 220 221 if options.serviceName and not options.daemonize: 222 sys.stderr.write( 223 'ERROR: --service-name can only be used with -D/--daemonize.\n') 224 return 1 225 226 brain = worker.WorkerBrain(options) 227 228 # Now bind and listen to our unix and tcp sockets 229 if not brain.listen(): 230 sys.stderr.write('ERROR: Failed to listen on worker ports.\n') 231 return 1 232 233 name = options.name 234 if options.daemonize: 235 if options.serviceName: 236 name = options.serviceName 237 if not options.daemonizeTo: 238 options.daemonizeTo = "/" 239 240 startup("worker", name, options.daemonize, options.daemonizeTo) 241 242 log.debug('worker', 'Running Flumotion version %s' % 243 configure.version) 244 import twisted.copyright 245 log.debug('worker', 'Running against Twisted version %s' % 246 twisted.copyright.version) 247 248 # register all package paths (FIXME: this should go away when 249 # components come from manager) 250 from flumotion.common import setup 251 setup.setupPackagePath() 252 253 # FIXME: why address='localhost' ? 254 authenticator = pb.Authenticator(username=options.username, 255 password=options.password, 256 address='localhost', 257 avatarId=options.name) 258 info = connection.PBConnectionInfo(options.host, options.port, 259 options.transport == "ssl", 260 authenticator) 261 brain.login(info) 262 263 log.info('worker', 264 'Connecting to manager %s using %s' % (info, 265 options.transport.upper())) 266 267 268 # go into the reactor main loop 269 reactor.run() 270 271 return 0
272