storyboard/storyboard/api/app.py

171 lines
5.3 KiB
Python

# Copyright (c) 2013 Mirantis Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
from oslo_config import cfg
from oslo_log import _options
from oslo_log import log
import pecan
from wsgiref import simple_server
from storyboard._i18n import _LI
from storyboard.api import config as api_config
from storyboard.api.middleware.cors_middleware import CORSMiddleware
from storyboard.api.middleware import session_hook
from storyboard.api.middleware import token_middleware
from storyboard.api.middleware import user_id_hook
from storyboard.api.middleware import validation_hook
from storyboard.api.v1.search import impls as search_engine_impls
from storyboard.api.v1.search import search_engine
from storyboard.api.v1.storage import impls as storage_impls
from storyboard.api.v1.storage import storage
from storyboard.notifications.notification_hook import NotificationHook
from storyboard.plugin.scheduler import initialize_scheduler
from storyboard.plugin.user_preferences import initialize_user_preferences
CONF = cfg.CONF
LOG = log.getLogger(__name__)
try:
log.register_options(CONF)
except cfg.ArgsAlreadyParsedError:
pass
API_OPTS = [
cfg.StrOpt('bind_host',
default='0.0.0.0',
help='API host'),
cfg.IntOpt('bind_port',
default=8080,
help='API port'),
cfg.BoolOpt('enable_notifications',
default=False,
help='Enable Notifications'),
cfg.BoolOpt('enable_editable_comments',
default=False,
help='Enable editing and deletion of comments')
]
CORS_OPTS = [
cfg.ListOpt('allowed_origins',
default=None,
help='List of permitted CORS origins.'),
cfg.IntOpt('max_age',
default=3600,
help='Maximum cache age of CORS preflight requests.')
]
CONF.register_opts(API_OPTS)
CONF.register_opts(CORS_OPTS, 'cors')
def get_pecan_config():
# Set up the pecan configuration
filename = api_config.__file__.replace('.pyc', '.py')
return pecan.configuration.conf_from_file(filename)
def setup_app(pecan_config=None):
if not pecan_config:
pecan_config = get_pecan_config()
# Setup logging
cfg.set_defaults(_options.log_opts,
default_log_levels=[
'storyboard=INFO',
'storyboard.openstack.common.db=WARN',
'sqlalchemy=WARN'
])
log.setup(CONF, 'storyboard')
hooks = [
session_hook.DBSessionHook(),
user_id_hook.UserIdHook(),
validation_hook.ValidationHook()
]
# Setup search engine
search_engine_name = CONF.search_engine
search_engine_cls = search_engine_impls.ENGINE_IMPLS[search_engine_name]
search_engine.set_engine(search_engine_cls())
# Setup storage backend
if CONF.attachments.enable_attachments:
storage_type = CONF.attachments.storage_backend
storage_cls = storage_impls.STORAGE_IMPLS[storage_type]
storage.set_storage_backend(storage_cls())
# Load user preference plugins
initialize_user_preferences()
# Initialize scheduler
initialize_scheduler()
# Setup notifier
if CONF.enable_notifications:
hooks.append(NotificationHook())
app = pecan.make_app(
pecan_config.app.root,
debug=CONF.debug,
hooks=hooks,
force_canonical=getattr(pecan_config.app, 'force_canonical', True),
guess_content_type_from_ext=False
)
app = token_middleware.AuthTokenMiddleware(app)
# Setup CORS
if CONF.cors.allowed_origins:
app = CORSMiddleware(app,
allowed_origins=CONF.cors.allowed_origins,
allowed_methods=['GET', 'POST', 'PUT', 'DELETE',
'OPTIONS'],
allowed_headers=['origin', 'authorization',
'accept', 'x-total', 'x-limit',
'x-marker', 'x-client',
'content-type'],
max_age=CONF.cors.max_age)
return app
def start():
CONF(project='storyboard')
api_root = setup_app()
# Create the WSGI server and start it
host = cfg.CONF.bind_host
port = cfg.CONF.bind_port
srv = simple_server.make_server(host, port, api_root)
LOG.info(_LI('Starting server in PID %s') % os.getpid())
LOG.info(_LI("Configuration:"))
if host == '0.0.0.0':
LOG.info(_LI(
'serving on 0.0.0.0:%(port)s, view at http://127.0.0.1:%(port)s')
% ({'port': port}))
else:
LOG.info(_LI("serving on http://%(host)s:%(port)s") % (
{'host': host, 'port': port}))
srv.serve_forever()
if __name__ == '__main__':
start()