1
# Copyright (C) 2011 OpenStack LLC.
3
# Licensed under the Apache License, Version 2.0 (the "License");
4
# you may not use this file except in compliance with the License.
5
# You may obtain a copy of the License at
7
# http://www.apache.org/licenses/LICENSE-2.0
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
# See the License for the specific language governing permissions and
13
# limitations under the License.
15
'''Main server module for burrow.'''
27
# This installs the _(...) function as a built-in so all other modules
29
gettext.install('burrowd')
31
# Default configuration values for this module.
32
DEFAULT_BACKEND = 'burrowd.backend.sqlite'
33
DEFAULT_FRONTENDS = 'burrowd.frontend.wsgi'
34
DEFAULT_THREAD_POOL_SIZE = 1000
37
class Burrowd(object):
38
'''Server class for burrow.'''
40
def __init__(self, config_files=[], add_default_log_handler=True):
41
'''Initialize a server using the config files from the given
42
list. This is passed directly to ConfigParser.read(), so
43
files should be in ConfigParser format. This will load all
44
frontend and backend classes from the configuration.'''
45
if len(config_files) > 0:
46
logging.config.fileConfig(config_files)
47
self._config = ConfigParser.ConfigParser()
48
self._config.read(config_files)
49
self.config = burrowd.config.Config(self._config, 'burrowd')
50
self.log = get_logger(self.config)
51
if add_default_log_handler:
52
self._add_default_log_handler()
53
self._import_backend()
54
self._import_frontends()
56
def _add_default_log_handler(self):
57
'''Add a default log handler it one has not been set.'''
58
root_log = logging.getLogger()
59
if len(root_log.handlers) > 0 or len(self.log.handlers) > 0:
61
handler = logging.StreamHandler()
62
handler.setLevel(logging.DEBUG)
63
log_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
64
handler.setFormatter(logging.Formatter(log_format))
65
root_log.addHandler(handler)
67
def _import_backend(self):
68
'''Load backend given in the 'backend' option.'''
69
backend = self.config.get('backend', DEFAULT_BACKEND)
70
config = (self._config, backend)
71
self.backend = import_class(backend, 'Backend')(config)
73
def _import_frontends(self):
74
'''Load frontends given in the 'frontends' option.'''
76
frontends = self.config.get('frontends', DEFAULT_FRONTENDS)
77
for frontend in frontends.split(','):
78
frontend = frontend.split(':')
79
if len(frontend) == 1:
81
config = (self._config, frontend[0], frontend[1])
82
frontend = import_class(frontend[0], 'Frontend')
83
frontend = frontend(config, self.backend)
84
self.frontends.append(frontend)
87
'''Create the thread pool and start the main server loop. Wait
88
for the pool to complete, but possibly run forever if the
89
frontends and backend never remove threads.'''
90
thread_pool_size = self.config.getint('thread_pool_size',
91
DEFAULT_THREAD_POOL_SIZE)
92
thread_pool = eventlet.GreenPool(size=int(thread_pool_size))
93
self.backend.run(thread_pool)
94
for frontend in self.frontends:
95
frontend.run(thread_pool)
96
self.log.info(_('Waiting for all threads to exit'))
99
except KeyboardInterrupt:
103
class Module(object):
104
'''Common module class for burrow.'''
106
def __init__(self, config):
107
self.config = burrowd.config.Config(*config)
108
self.log = get_logger(self.config)
109
self.log.debug(_('Module created'))
112
def get_logger(config):
113
'''Create a logger from the given config.'''
114
log = logging.getLogger(config.section)
115
log_level = config.get('log_level', 'DEBUG')
116
log_level = logging.getLevelName(log_level)
117
if isinstance(log_level, int):
118
log.setLevel(log_level)
122
def import_class(module_name, class_name=None):
123
'''Import a class given a full module.class name.'''
124
if class_name is None:
125
module_name, _separator, class_name = module_name.rpartition('.')
127
__import__(module_name)
128
return getattr(sys.modules[module_name], class_name)
129
except (ImportError, ValueError, AttributeError), exception:
130
raise ImportError(_('Class %s.%s cannot be found (%s)') %
131
(module_name, class_name, exception))