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 
 32  from flumotion.common import log, config, common, errors, setup 
 33  from flumotion.configure import configure 
 34  from flumotion.common import server 
 35  from flumotion.common.options import OptionGroup, OptionParser 
 36   
 37  defaultSSLPort = configure.defaultSSLManagerPort 
 38  defaultTCPPort = configure.defaultTCPManagerPort 
 39   
40 -def _createParser():
41 usagemessage = "usage: %prog [options] manager.xml flow1.xml [...]" 42 desc = "The manager is the core component of the Flumotion streaming\ 43 server. It takes its configuration from one or more planet configuration\ 44 files. The first file is mandatory, and contains base configuration \ 45 information for the manager. Zero or more additional configuration files\ 46 can be provided, these are used to configure flows that the manager should run\ 47 on available workers." 48 49 parser = OptionParser(usage=usagemessage, description=desc, 50 domain="flumotion-manager") 51 52 group = OptionGroup(parser, "manager options") 53 group.add_option('-H', '--hostname', 54 action="store", type="string", dest="host", 55 help="hostname to listen as") 56 group.add_option('-P', '--port', 57 action="store", type="int", dest="port", 58 default=None, 59 help="port to listen on [default %d (ssl) or %d (tcp)]" % (defaultSSLPort, defaultTCPPort)) 60 group.add_option('-T', '--transport', 61 action="store", type="string", dest="transport", 62 help="transport protocol to use (tcp/ssl) [default ssl]") 63 group.add_option('-C', '--certificate', 64 action="store", type="string", dest="certificate", 65 default=None, 66 help="PEM certificate file (for SSL) " 67 "[default default.pem]") 68 group.add_option('-n', '--name', 69 action="store", type="string", dest="name", 70 help="manager name") 71 group.add_option('-s', '--service-name', 72 action="store", type="string", dest="serviceName", 73 help="name to use for log and pid files " 74 "when run as a daemon") 75 group.add_option('-D', '--daemonize', 76 action="store_true", dest="daemonize", 77 default=False, 78 help="run in background as a daemon") 79 group.add_option('', '--daemonize-to', 80 action="store", dest="daemonizeTo", 81 help="what directory to run from when daemonizing") 82 83 parser.add_option('-L', '--logdir', 84 action="store", dest="logdir", 85 help="flumotion log directory (default: %s)" % 86 configure.logdir) 87 parser.add_option('-R', '--rundir', 88 action="store", dest="rundir", 89 help="flumotion run directory (default: %s)" % 90 configure.rundir) 91 92 parser.add_option_group(group) 93 94 return parser
95
96 -def _initialLoadConfig(vishnu, paths):
97 # this is used with a callLater for the initial config loading 98 # since this is run after daemonizing, it should show errors, but not stop 99 for path in paths: 100 log.debug('manager', 'Loading configuration file from (%s)' % path) 101 vishnu.loadComponentConfigurationXML(path, manager.LOCAL_IDENTITY)
102
103 -def main(args):
104 parser = _createParser() 105 106 log.debug('manager', 'Parsing arguments (%r)' % ', '.join(args)) 107 options, args = parser.parse_args(args) 108 109 # Force options down configure's throat 110 for d in ['logdir', 'rundir']: 111 o = getattr(options, d, None) 112 if o: 113 log.debug('manager', 'Setting configure.%s to %s' % (d, o)) 114 setattr(configure, d, o) 115 116 # parse planet config file 117 if len(args) <= 1: 118 log.warning('manager', 'Please specify a planet configuration file') 119 sys.stderr.write("Please specify a planet configuration file.\n") 120 return 1 121 122 planetFile = args[1] 123 try: 124 cfg = config.ManagerConfigParser(planetFile) 125 except IOError, e: 126 sys.stderr.write("ERROR: Could not read configuration from '%s':\n" % 127 planetFile) 128 sys.stderr.write("ERROR: %s\n" % e.strerror) 129 return 1 130 except errors.ConfigError, e: 131 sys.stderr.write("ERROR: Could not read configuration from '%s':\n" % 132 planetFile) 133 sys.stderr.write("ERROR: %s\n" % e.args[0]) 134 return 1 135 136 configDir = os.path.abspath(os.path.dirname(planetFile)) 137 138 # now copy over stuff from config that is not set yet 139 if cfg.manager: 140 if not options.host and cfg.manager.host: 141 options.host = cfg.manager.host 142 log.debug('manager', 'Setting manager host to %s' % options.host) 143 if not options.port and cfg.manager.port: 144 options.port = cfg.manager.port 145 log.debug('manager', 'Setting manager port to %s' % options.port) 146 if not options.transport and cfg.manager.transport: 147 options.transport = cfg.manager.transport 148 log.debug('manager', 'Setting manager transport to %s' % 149 options.transport) 150 if not options.certificate and cfg.manager.certificate: 151 options.certificate = cfg.manager.certificate 152 log.debug('manager', 'Using certificate %s' % 153 options.certificate) 154 if not options.name and cfg.manager.name: 155 options.name = cfg.manager.name 156 log.debug('manager', 'Setting manager name to %s' % options.name) 157 # environment debug > command-line debug > config file debug 158 if not options.debug and cfg.manager.fludebug \ 159 and not os.environ.has_key('FLU_DEBUG'): 160 options.debug = cfg.manager.fludebug 161 log.debug('manager', 'Setting debug level to config file value %s' % 162 options.debug) 163 164 # set debug level as soon as we can after deciding 165 if options.debug: 166 log.setFluDebug(options.debug) 167 168 # set default values for all unset options 169 if not options.host: 170 options.host = "" # needed for bind to work 171 if not options.transport: 172 options.transport = 'ssl' 173 if not options.port: 174 if options.transport == "tcp": 175 options.port = defaultTCPPort 176 elif options.transport == "ssl": 177 options.port = defaultSSLPort 178 if not options.certificate and options.transport == 'ssl': 179 options.certificate = 'default.pem' 180 if not options.name: 181 try: 182 # if the file is in a directory under a 'managers' directory, 183 # use the parent directory name 184 head, filename = os.path.split(os.path.abspath(planetFile)) 185 head, name = os.path.split(head) 186 head, managers = os.path.split(head) 187 if managers != 'managers': 188 raise 189 options.name = name 190 log.debug('manager', 'Setting name to %s based on path' % name) 191 except: 192 options.name = 'unnamed' 193 log.debug('manager', 'Setting name to unnamed') 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=configDir) 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.SystemError, 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 common.startup("manager", name, options.daemonize, 258 options.daemonizeTo) 259 260 reactor.run() 261 262 return 0
263