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

Source Code for Module flumotion.manager.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 Fluendo, S.L. (www.fluendo.com). 
  6  # All rights reserved. 
  7   
  8  # This file may be distributed and/or modified under the terms of 
  9  # the GNU General Public License version 2 as published by 
 10  # the Free Software Foundation. 
 11  # This file is distributed without any warranty; without even the implied 
 12  # warranty of merchantability or fitness for a particular purpose. 
 13  # See "LICENSE.GPL" in the source distribution for more information. 
 14   
 15  # Licensees having purchased or holding a valid Flumotion Advanced 
 16  # Streaming Server license may use this file in accordance with the 
 17  # Flumotion Advanced Streaming Server Commercial License Agreement. 
 18  # See "LICENSE.Flumotion" in the source distribution for more information. 
 19   
 20  # Headers in this file shall remain intact. 
 21   
 22  """ 
 23  manager main function 
 24  """ 
 25   
 26  import os 
 27  import sys 
 28   
 29  from twisted.internet import reactor, error 
 30   
 31  from flumotion.manager import manager, config 
 32  from flumotion.common import log, errors, setup 
 33  from flumotion.common import server 
 34  from flumotion.common.options import OptionGroup, OptionParser 
 35  from flumotion.common.process import startup 
 36  from flumotion.configure import configure 
 37   
 38  __version__ = "$Rev: 6988 $" 
 39  defaultSSLPort = configure.defaultSSLManagerPort 
 40  defaultTCPPort = configure.defaultTCPManagerPort 
 41   
42 -def _createParser():
43 usagemessage = "usage: %prog [options] manager.xml flow1.xml [...]" 44 desc = "The manager is the core component of the Flumotion streaming\ 45 server. It takes its configuration from one or more planet configuration\ 46 files. The first file is mandatory, and contains base configuration \ 47 information for the manager. Zero or more additional configuration files\ 48 can be provided, these are used to configure flows that the manager should run\ 49 on available workers." 50 51 parser = OptionParser(usage=usagemessage, description=desc, 52 domain="flumotion-manager") 53 54 group = OptionGroup(parser, "manager options") 55 group.add_option('-H', '--hostname', 56 action="store", type="string", dest="host", 57 help="hostname to listen as") 58 group.add_option('-P', '--port', 59 action="store", type="int", dest="port", 60 default=None, 61 help="port to listen on [default %d (ssl) or %d (tcp)]" % (defaultSSLPort, defaultTCPPort)) 62 group.add_option('-T', '--transport', 63 action="store", type="string", dest="transport", 64 help="transport protocol to use (tcp/ssl) [default ssl]") 65 group.add_option('-C', '--certificate', 66 action="store", type="string", dest="certificate", 67 default=None, 68 help="PEM certificate file (for SSL) " 69 "[default default.pem]") 70 group.add_option('-n', '--name', 71 action="store", type="string", dest="name", 72 help="manager name") 73 group.add_option('-s', '--service-name', 74 action="store", type="string", dest="serviceName", 75 help="name to use for log and pid files " 76 "when run as a daemon") 77 group.add_option('-D', '--daemonize', 78 action="store_true", dest="daemonize", 79 default=False, 80 help="run in background as a daemon") 81 group.add_option('', '--daemonize-to', 82 action="store", dest="daemonizeTo", 83 help="what directory to run from when daemonizing") 84 85 parser.add_option('-L', '--logdir', 86 action="store", dest="logdir", 87 help="flumotion log directory (default: %s)" % 88 configure.logdir) 89 parser.add_option('-R', '--rundir', 90 action="store", dest="rundir", 91 help="flumotion run directory (default: %s)" % 92 configure.rundir) 93 94 parser.add_option_group(group) 95 96 return parser
97
98 -def _initialLoadConfig(vishnu, paths):
99 # this is used with a callLater for the initial config loading 100 # since this is run after daemonizing, it should show errors, but not stop 101 for path in paths: 102 log.debug('manager', 'Loading configuration file from (%s)' % path) 103 vishnu.loadComponentConfigurationXML(path, manager.LOCAL_IDENTITY)
104
105 -def main(args):
106 parser = _createParser() 107 108 log.debug('manager', 'Parsing arguments (%r)' % ', '.join(args)) 109 options, args = parser.parse_args(args) 110 111 # Force options down configure's throat 112 for d in ['logdir', 'rundir']: 113 o = getattr(options, d, None) 114 if o: 115 log.debug('manager', 'Setting configure.%s to %s' % (d, o)) 116 setattr(configure, d, o) 117 118 # parse planet config file 119 if len(args) <= 1: 120 log.warning('manager', 'Please specify a planet configuration file') 121 sys.stderr.write("Please specify a planet configuration file.\n") 122 return 1 123 124 planetFile = args[1] 125 try: 126 cfg = config.ManagerConfigParser(planetFile) 127 except IOError, e: 128 sys.stderr.write("ERROR: Could not read configuration from '%s':\n" % 129 planetFile) 130 sys.stderr.write("ERROR: %s\n" % e.strerror) 131 return 1 132 except errors.ConfigError, e: 133 sys.stderr.write("ERROR: Could not read configuration from '%s':\n" % 134 planetFile) 135 sys.stderr.write("ERROR: %s\n" % e.args[0]) 136 return 1 137 138 managerConfigDir = os.path.abspath(os.path.dirname(planetFile)) 139 140 # now copy over stuff from config that is not set yet 141 if cfg.manager: 142 if not options.host and cfg.manager.host: 143 options.host = cfg.manager.host 144 log.debug('manager', 'Setting manager host to %s' % options.host) 145 if not options.port and cfg.manager.port: 146 options.port = cfg.manager.port 147 log.debug('manager', 'Setting manager port to %s' % options.port) 148 if not options.transport and cfg.manager.transport: 149 options.transport = cfg.manager.transport 150 log.debug('manager', 'Setting manager transport to %s' % 151 options.transport) 152 if not options.certificate and cfg.manager.certificate: 153 options.certificate = cfg.manager.certificate 154 log.debug('manager', 'Using certificate %s' % 155 options.certificate) 156 if not options.name and cfg.manager.name: 157 options.name = cfg.manager.name 158 log.debug('manager', 'Setting manager name to %s' % options.name) 159 # environment debug > command-line debug > config file debug 160 if not options.debug and cfg.manager.fludebug \ 161 and not os.environ.has_key('FLU_DEBUG'): 162 options.debug = cfg.manager.fludebug 163 log.debug('manager', 'Setting debug level to config file value %s' % 164 options.debug) 165 166 # set debug level as soon as we can after deciding 167 if options.debug: 168 log.setFluDebug(options.debug) 169 170 # set default values for all unset options 171 if not options.host: 172 options.host = "" # needed for bind to work 173 if not options.transport: 174 options.transport = 'ssl' 175 if not options.port: 176 if options.transport == "tcp": 177 options.port = defaultTCPPort 178 elif options.transport == "ssl": 179 options.port = defaultSSLPort 180 if not options.certificate and options.transport == 'ssl': 181 options.certificate = 'default.pem' 182 if not options.name: 183 # if the file is in a directory under a 'managers' directory, 184 # use the parent directory name 185 head, filename = os.path.split(os.path.abspath(planetFile)) 186 head, name = os.path.split(head) 187 head, managers = os.path.split(head) 188 if managers != 'managers': 189 options.name = 'unnamed' 190 log.debug('manager', 'Setting name to unnamed') 191 else: 192 options.name = name 193 log.debug('manager', 'Setting name to %s based on path' % name) 194 195 # check for wrong options/arguments 196 if not options.transport in ['ssl', 'tcp']: 197 sys.stderr.write('ERROR: wrong transport %s, must be ssl or tcp\n' % 198 options.transport) 199 return 1 200 201 # register package path 202 setup.setupPackagePath() 203 204 # log our standardized starting marker 205 log.info('manager', "Starting manager '%s'" % options.name) 206 207 log.debug('manager', 'Running Flumotion version %s' % 208 configure.version) 209 import twisted.copyright 210 log.debug('manager', 'Running against Twisted version %s' % 211 twisted.copyright.version) 212 from flumotion.project import project 213 for p in project.list(): 214 log.debug('manager', 'Registered project %s version %s' % ( 215 p, project.get(p, 'version'))) 216 217 vishnu = manager.Vishnu(options.name, configDir=managerConfigDir) 218 for managerConfigFile in args[1:]: 219 vishnu.loadManagerConfigurationXML(managerConfigFile) 220 221 paths = [os.path.abspath(filename) for filename in args[1:]] 222 reactor.callLater(0, _initialLoadConfig, vishnu, paths) 223 reactor.callLater(0, vishnu.startManagerPlugs) 224 225 # set up server based on transport 226 myServer = server.Server(vishnu) 227 try: 228 if options.transport == "ssl": 229 myServer.startSSL(options.host, options.port, options.certificate, 230 configure.configdir) 231 elif options.transport == "tcp": 232 myServer.startTCP(options.host, options.port) 233 except error.CannotListenError, e: 234 # e is a socket.error() 235 message = "Could not listen on port %d: %s" % ( 236 e.port, e.socketError.args[1]) 237 raise errors.FatalError, message 238 239 if options.daemonizeTo and not options.daemonize: 240 sys.stderr.write( 241 'ERROR: --daemonize-to can only be used with -D/--daemonize.\n') 242 return 1 243 244 if options.serviceName and not options.daemonize: 245 sys.stderr.write( 246 'ERROR: --service-name can only be used with -D/--daemonize.\n') 247 return 1 248 249 name = options.name 250 251 if options.daemonize: 252 if options.serviceName: 253 name = options.serviceName 254 if not options.daemonizeTo: 255 options.daemonizeTo = "/" 256 257 startup("manager", name, options.daemonize, options.daemonizeTo) 258 259 reactor.run() 260 261 return 0
262