Load cyborg-api app with paste_deploy

Change-Id: I3976d05f737e09ceb88c40f65b445bad0b096516
Story: 2002121
Task: 19800
This commit is contained in:
wangzh21 2018-05-29 20:46:00 +08:00
parent 07a273e70d
commit cc9da9a944
8 changed files with 66 additions and 29 deletions

View File

@ -13,13 +13,21 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import os
import pecan import pecan
from oslo_config import cfg from oslo_config import cfg
from oslo_log import log
from paste import deploy
from cyborg.api import config from cyborg.api import config
from cyborg.api import hooks from cyborg.api import hooks
from cyborg.api import middleware from cyborg.api import middleware
import cyborg.conf
CONF = cyborg.conf.CONF
LOG = log.getLogger(__name__)
def get_pecan_config(): def get_pecan_config():
@ -29,6 +37,9 @@ def get_pecan_config():
def setup_app(pecan_config=None, extra_hooks=None): def setup_app(pecan_config=None, extra_hooks=None):
if not pecan_config:
pecan_config = get_pecan_config()
app_hooks = [hooks.ConfigHook(), app_hooks = [hooks.ConfigHook(),
hooks.ConductorAPIHook(), hooks.ConductorAPIHook(),
hooks.ContextHook(pecan_config.app.acl_public_routes), hooks.ContextHook(pecan_config.app.acl_public_routes),
@ -36,31 +47,31 @@ def setup_app(pecan_config=None, extra_hooks=None):
if extra_hooks: if extra_hooks:
app_hooks.extend(extra_hooks) app_hooks.extend(extra_hooks)
if not pecan_config: app_conf = dict(pecan_config.app)
pecan_config = get_pecan_config()
pecan.configuration.set_config(dict(pecan_config), overwrite=True)
app = pecan.make_app( app = pecan.make_app(
pecan_config.app.root, app_conf.pop('root'),
static_root=pecan_config.app.static_root,
debug=False,
force_canonical=getattr(pecan_config.app, 'force_canonical', True), force_canonical=getattr(pecan_config.app, 'force_canonical', True),
hooks=app_hooks, hooks=app_hooks,
wrap_app=middleware.ParsableErrorMiddleware wrap_app=middleware.ParsableErrorMiddleware,
**app_conf
) )
app = middleware.AuthTokenMiddleware(
app, dict(cfg.CONF),
public_api_routes=pecan_config.app.acl_public_routes)
return app return app
class VersionSelectorApplication(object): def load_app():
def __init__(self): cfg_file = None
pc = get_pecan_config() cfg_path = CONF.api.api_paste_config
self.v1 = setup_app(pecan_config=pc) if not os.path.isabs(cfg_path):
cfg_file = CONF.find_file(cfg_path)
elif os.path.exists(cfg_path):
cfg_file = cfg_path
def __call__(self, environ, start_response): if not cfg_file:
return self.v1(environ, start_response) raise cfg.ConfigFilesNotFoundError([CONF.api.api_paste_config])
LOG.info("Full WSGI config used: %s", cfg_file)
return deploy.loadapp("config:" + cfg_file)
def app_factory(global_config, **local_conf):
return setup_app()

View File

@ -92,12 +92,3 @@ class ContextHook(hooks.PecanHook):
is_admin = policy.authorize('is_admin', creds, creds) is_admin = policy.authorize('is_admin', creds, creds)
state.request.context = context.RequestContext( state.request.context = context.RequestContext(
is_admin=is_admin, **creds) is_admin=is_admin, **creds)
def after(self, state):
if state.request.context == {}:
# An incorrect url path will not create RequestContext
return
# RequestContext will generate a request_id if no one
# passing outside, so it always contain a request_id.
request_id = state.request.context.request_id
state.response.headers['Openstack-Request-Id'] = request_id

View File

@ -62,3 +62,13 @@ class AuthTokenMiddleware(auth_token.AuthProtocol):
return self.app(env, start_response) return self.app(env, start_response)
return super(AuthTokenMiddleware, self).__call__(env, start_response) return super(AuthTokenMiddleware, self).__call__(env, start_response)
@classmethod
def factory(cls, global_config, **local_conf):
public_routes = local_conf.get('acl_public_routes', '')
public_api_routes = [path.strip() for path in public_routes.split(',')]
def _factory(app):
return cls(app, global_config, public_api_routes=public_api_routes)
return _factory

View File

@ -103,7 +103,7 @@ class WSGIService(service.ServiceBase):
:returns: None :returns: None
""" """
self.name = name self.name = name
self.app = app.VersionSelectorApplication() self.app = app.load_app()
self.workers = (CONF.api.api_workers or self.workers = (CONF.api.api_workers or
processutils.get_worker_count()) processutils.get_worker_count())
if self.workers and self.workers < 1: if self.workers and self.workers < 1:

View File

@ -45,6 +45,9 @@ opts = [
"host URL. If the API is operating behind a proxy, you " "host URL. If the API is operating behind a proxy, you "
"will want to change this to represent the proxy's URL. " "will want to change this to represent the proxy's URL. "
"Defaults to None.")), "Defaults to None.")),
cfg.StrOpt('api_paste_config',
default="api-paste.ini",
help="Configuration file for WSGI definition of API."),
] ]
opt_group = cfg.OptGroup(name='api', opt_group = cfg.OptGroup(name='api',

View File

@ -37,6 +37,7 @@ CYBORG_STATE_PATH=/var/lib/cyborg
CYBORG_AUTH_CACHE_DIR=${CYBORG_AUTH_CACHE_DIR:-/var/cache/cyborg} CYBORG_AUTH_CACHE_DIR=${CYBORG_AUTH_CACHE_DIR:-/var/cache/cyborg}
CYBORG_CONF_DIR=${CYBORG_CONF_DIR:-/etc/cyborg} CYBORG_CONF_DIR=${CYBORG_CONF_DIR:-/etc/cyborg}
CYBORG_CONF_FILE=$CYBORG_CONF_DIR/cyborg.conf CYBORG_CONF_FILE=$CYBORG_CONF_DIR/cyborg.conf
CYBORG_API_PASTE_INI=$CYBORG_CONF_DIR/api-paste.ini
CYBORG_ROOTWRAP_CONF=$CYBORG_CONF_DIR/rootwrap.conf CYBORG_ROOTWRAP_CONF=$CYBORG_CONF_DIR/rootwrap.conf
CYBORG_POLICY_JSON=$CYBORG_CONF_DIR/policy.json CYBORG_POLICY_JSON=$CYBORG_CONF_DIR/policy.json
CYBORG_SERVICE_HOST=${CYBORG_SERVICE_HOST:-$SERVICE_HOST} CYBORG_SERVICE_HOST=${CYBORG_SERVICE_HOST:-$SERVICE_HOST}
@ -173,6 +174,7 @@ function configure_cyborg_conductor {
sudo cp $CYBORG_DIR/etc/cyborg/rootwrap.conf $CYBORG_ROOTWRAP_CONF sudo cp $CYBORG_DIR/etc/cyborg/rootwrap.conf $CYBORG_ROOTWRAP_CONF
sudo cp -r $CYBORG_DIR/etc/cyborg/rootwrap.d $CYBORG_CONF_DIR sudo cp -r $CYBORG_DIR/etc/cyborg/rootwrap.d $CYBORG_CONF_DIR
sudo cp -p $CYBORG_DIR/etc/cyborg/api-paste.ini $CYBORG_API_PASTE_INI
local cyborg_rootwrap local cyborg_rootwrap
cyborg_rootwrap=$(get_rootwrap_location cyborg) cyborg_rootwrap=$(get_rootwrap_location cyborg)
local rootwrap_isudoer_cmd="$cyborg_rootwrap $CYBORG_CONF_DIR/rootwrap.conf *" local rootwrap_isudoer_cmd="$cyborg_rootwrap $CYBORG_CONF_DIR/rootwrap.conf *"

19
etc/cyborg/api-paste.ini Normal file
View File

@ -0,0 +1,19 @@
[pipeline:main]
pipeline = cors request_id authtoken api_v1
[app:api_v1]
paste.app_factory = cyborg.api.app:app_factory
[filter:authtoken]
acl_public_routes = /, /v1
paste.filter_factory = cyborg.api.middleware.auth_token:AuthTokenMiddleware.factory
[filter:osprofiler]
paste.filter_factory = cyborg.common.profiler:WsgiMiddleware.factory
[filter:request_id]
paste.filter_factory = oslo_middleware:RequestId.factory
[filter:cors]
paste.filter_factory = oslo_middleware.cors:filter_factory
oslo_config_project = cyborg

View File

@ -26,6 +26,7 @@ data_files =
etc/cyborg = etc/cyborg =
etc/cyborg/rootwrap.conf etc/cyborg/rootwrap.conf
etc/cyborg/policy.json etc/cyborg/policy.json
etc/cyborg/api-paste.ini
etc/cyborg/rootwrap.d = etc/cyborg/rootwrap.d =
etc/cyborg/rootwrap.d/* etc/cyborg/rootwrap.d/*