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,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  """ 
 19  manager main function 
 20  """ 
 21   
 22  import os 
 23  import sys 
 24   
 25  from twisted.internet import reactor, error 
 26   
 27  from flumotion.manager import manager, config 
 28  from flumotion.common import log, errors, setup 
 29  from flumotion.common import server 
 30  from flumotion.common.options import OptionGroup, OptionParser 
 31  from flumotion.common.process import startup 
 32  from flumotion.configure import configure 
 33   
 34  __version__ = "$Rev$" 
 35  defaultSSLPort = configure.defaultSSLManagerPort 
 36  defaultTCPPort = configure.defaultTCPManagerPort 
 37   
 38   
39 -def _createParser():
40 usagemessage = "usage: %prog [options] manager.xml flow1.xml [...]" 41 desc = "The manager is the core component of the Flumotion streaming\ 42 server. It takes its configuration from one or more planet configuration\ 43 files. The first file is mandatory, and contains base configuration \ 44 information for the manager. Zero or more additional configuration files\ 45 can be provided, these are used to configure flows that the manager should\ 46 run on available workers." 47 48 parser = OptionParser(usage=usagemessage, description=desc, 49 domain="flumotion-manager") 50 51 group = OptionGroup(parser, "manager options") 52 group.add_option('-H', '--hostname', 53 action="store", type="string", dest="host", 54 help="hostname to listen as") 55 group.add_option('-P', '--port', 56 action="store", type="int", dest="port", 57 default=None, 58 help="port to listen on [default %d (ssl) or %d (tcp)]" % 59 (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
97 -def _initialLoadConfig(vishnu, paths):
98 # this is used with a callLater for the initial config loading 99 # since this is run after daemonizing, it should show errors, but not stop 100 for path in paths: 101 log.debug('manager', 'Loading configuration file from (%s)' % path) 102 vishnu.loadComponentConfigurationXML(path, manager.LOCAL_IDENTITY)
103 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 'FLU_DEBUG' in os.environ: 162 options.debug = cfg.manager.fludebug 163 log.debug('manager', 164 'Setting debug level to config file value %s' % 165 options.debug) 166 167 # set debug level as soon as we can after deciding 168 if options.debug: 169 log.setFluDebug(options.debug) 170 171 # set default values for all unset options 172 if not options.host: 173 options.host = "" # needed for bind to work 174 if not options.transport: 175 options.transport = 'ssl' 176 if not options.port: 177 if options.transport == "tcp": 178 options.port = defaultTCPPort 179 elif options.transport == "ssl": 180 options.port = defaultSSLPort 181 if not options.certificate and options.transport == 'ssl': 182 options.certificate = 'default.pem' 183 if not options.name: 184 # if the file is in a directory under a 'managers' directory, 185 # use the parent directory name 186 head, filename = os.path.split(os.path.abspath(planetFile)) 187 head, name = os.path.split(head) 188 head, managers = os.path.split(head) 189 if managers != 'managers': 190 options.name = 'unnamed' 191 log.debug('manager', 'Setting name to unnamed') 192 else: 193 options.name = name 194 log.debug('manager', 'Setting name to %s based on path' % name) 195 196 # check for wrong options/arguments 197 if not options.transport in ['ssl', 'tcp']: 198 sys.stderr.write('ERROR: wrong transport %s, must be ssl or tcp\n' % 199 options.transport) 200 return 1 201 202 # register package path 203 setup.setupPackagePath() 204 205 # log our standardized starting marker 206 log.info('manager', "Starting manager '%s'" % options.name) 207 208 log.debug('manager', 'Running Flumotion version %s' % 209 configure.version) 210 import twisted.copyright 211 log.debug('manager', 'Running against Twisted version %s' % 212 twisted.copyright.version) 213 from flumotion.project import project 214 for p in project.list(): 215 log.debug('manager', 'Registered project %s version %s' % ( 216 p, project.get(p, 'version'))) 217 218 vishnu = manager.Vishnu(options.name, configDir=managerConfigDir) 219 for managerConfigFile in args[1:]: 220 vishnu.loadManagerConfigurationXML(managerConfigFile) 221 222 paths = [os.path.abspath(filename) for filename in args[1:]] 223 reactor.callLater(0, _initialLoadConfig, vishnu, paths) 224 reactor.callLater(0, vishnu.startManagerPlugs) 225 226 # set up server based on transport 227 myServer = server.Server(vishnu) 228 try: 229 if options.transport == "ssl": 230 myServer.startSSL(options.host, options.port, options.certificate, 231 configure.configdir) 232 elif options.transport == "tcp": 233 myServer.startTCP(options.host, options.port) 234 except error.CannotListenError, e: 235 # e is a socket.error() 236 message = "Could not listen on port %d: %s" % ( 237 e.port, e.socketError.args[1]) 238 raise errors.FatalError, message 239 240 if options.daemonizeTo and not options.daemonize: 241 sys.stderr.write( 242 'ERROR: --daemonize-to can only be used with -D/--daemonize.\n') 243 return 1 244 245 if options.serviceName and not options.daemonize: 246 sys.stderr.write( 247 'ERROR: --service-name can only be used with -D/--daemonize.\n') 248 return 1 249 250 name = options.name 251 252 if options.daemonize: 253 if options.serviceName: 254 name = options.serviceName 255 if not options.daemonizeTo: 256 options.daemonizeTo = "/" 257 258 startup("manager", name, options.daemonize, options.daemonizeTo) 259 260 reactor.run() 261 262 return 0
263