add initial files for topology api
Implements: blueprint get-topology-api Change-Id: I3fa8a811edb04decf52dba875f5d8073b69b91a6
This commit is contained in:
parent
87ce06e8ea
commit
7ba498cf58
@ -6,3 +6,8 @@ pbr>=1.6
|
||||
Babel>=1.3
|
||||
|
||||
oslo.log>=1.12.0 # Apache-2.0
|
||||
pecan>=0.8.0
|
||||
PasteDeploy>=1.5.0
|
||||
Werkzeug>=0.7
|
||||
oslo.policy>=0.3.0
|
||||
keystonemiddleware>=2.3.0
|
||||
|
10
setup.cfg
10
setup.cfg
@ -17,6 +17,16 @@ classifier =
|
||||
Programming Language :: Python :: 2.7
|
||||
Topic :: System :: Monitoring
|
||||
|
||||
[global]
|
||||
setup-hooks =
|
||||
pbr.hooks.setup_hook
|
||||
|
||||
console_scripts =
|
||||
vitrage-api = vitrage.cmd.api:main
|
||||
|
||||
oslo.config.opts =
|
||||
vitrage = vitrage.opts:list_opts
|
||||
|
||||
[files]
|
||||
packages =
|
||||
vitrage
|
||||
|
101
vitrage/api/app.py
Normal file
101
vitrage/api/app.py
Normal file
@ -0,0 +1,101 @@
|
||||
# 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 logging
|
||||
import os
|
||||
import pecan
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log
|
||||
from paste import deploy
|
||||
from vitrage.api import hooks
|
||||
from vitrage.i18n import _
|
||||
from vitrage.i18n import _LW
|
||||
from vitrage import service
|
||||
from werkzeug import serving
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
PECAN_CONFIG = {
|
||||
'app': {
|
||||
'root': 'vitrage.api.controllers.root.RootController',
|
||||
'modules': ['vitrage.api'],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def setup_app(pecan_config=PECAN_CONFIG, conf=None):
|
||||
if conf is None:
|
||||
raise RuntimeError("Config is actually mandatory")
|
||||
app_hooks = [hooks.ConfigHook(conf),
|
||||
hooks.TranslationHook()]
|
||||
|
||||
pecan.configuration.set_config(dict(pecan_config), overwrite=True)
|
||||
pecan_debug = conf.api.pecan_debug
|
||||
if conf.api.workers != 1 and pecan_debug:
|
||||
pecan_debug = False
|
||||
LOG.warning(_LW('pecan_debug cannot be enabled, if workers is > 1, '
|
||||
'the value is overridden with False'))
|
||||
|
||||
app = pecan.make_app(
|
||||
pecan_config['app']['root'],
|
||||
debug=pecan_debug,
|
||||
hooks=app_hooks,
|
||||
guess_content_type_from_ext=False
|
||||
)
|
||||
|
||||
return app
|
||||
|
||||
|
||||
def load_app(conf):
|
||||
# Build the WSGI app
|
||||
cfg_file = None
|
||||
cfg_path = conf.api.paste_config
|
||||
if not os.path.isabs(cfg_path):
|
||||
cfg_file = conf.find_file(cfg_path)
|
||||
elif os.path.exists(cfg_path):
|
||||
cfg_file = cfg_path
|
||||
|
||||
if not cfg_file:
|
||||
raise cfg.ConfigFilesNotFoundError([conf.api.paste_config])
|
||||
LOG.info("Full WSGI config used: %s" % cfg_file)
|
||||
return deploy.loadapp("config:" + cfg_file)
|
||||
|
||||
|
||||
def build_server(conf):
|
||||
app = load_app(conf)
|
||||
# Create the WSGI server and start it
|
||||
host, port = conf.api.host, conf.api.port
|
||||
|
||||
LOG.info(_('Starting server in PID %s') % os.getpid())
|
||||
LOG.info(_("Configuration:"))
|
||||
conf.log_opt_values(LOG, logging.INFO)
|
||||
|
||||
if host == '0.0.0.0':
|
||||
LOG.info(_(
|
||||
'serving on 0.0.0.0:%(sport)s, view at http://127.0.0.1:%(vport)s')
|
||||
% ({'sport': port, 'vport': port}))
|
||||
else:
|
||||
LOG.info(_("serving on http://%(host)s:%(port)s") % (
|
||||
{'host': host, 'port': port}))
|
||||
|
||||
serving.run_simple(host, port,
|
||||
app, processes=conf.api.workers)
|
||||
|
||||
|
||||
def _app():
|
||||
conf = service.prepare_service()
|
||||
return setup_app(conf=conf)
|
||||
|
||||
|
||||
def app_factory(global_config, **local_conf):
|
||||
return _app()
|
23
vitrage/api/app.wsgi
Normal file
23
vitrage/api/app.wsgi
Normal file
@ -0,0 +1,23 @@
|
||||
# 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.
|
||||
|
||||
"""Use this file for deploying the API under mod_wsgi.
|
||||
See http://pecan.readthedocs.org/en/latest/deployment.html for details.
|
||||
"""
|
||||
from oslo_config import cfg
|
||||
|
||||
from vitrage.api import app
|
||||
from vitrage import service
|
||||
|
||||
# Initialize the oslo configuration library and logging
|
||||
conf = service.prepare_service()
|
||||
application = app.load_app(conf)
|
0
vitrage/api/controllers/__init__.py
Normal file
0
vitrage/api/controllers/__init__.py
Normal file
37
vitrage/api/controllers/root.py
Normal file
37
vitrage/api/controllers/root.py
Normal file
@ -0,0 +1,37 @@
|
||||
# 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 pecan as pecan
|
||||
from vitrage.api.controllers.v1 import root as v1
|
||||
|
||||
|
||||
class RootController(object):
|
||||
v1 = v1.V1Controller()
|
||||
|
||||
@staticmethod
|
||||
@pecan.expose('json')
|
||||
def index():
|
||||
return {
|
||||
"versions": [
|
||||
{
|
||||
"status": "CURRENT",
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"href": pecan.request.application_url + "/v1/"
|
||||
}
|
||||
],
|
||||
"id": "v1.0",
|
||||
"updated": "2015-11-29"
|
||||
}
|
||||
]
|
||||
}
|
0
vitrage/api/controllers/v1/__init__.py
Normal file
0
vitrage/api/controllers/v1/__init__.py
Normal file
@ -1,5 +1,3 @@
|
||||
# Copyright 2015 - Alcatel-Lucent
|
||||
#
|
||||
# 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
|
||||
@ -12,4 +10,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
__author__ = 'stack'
|
||||
from vitrage.api.controllers.v1 import topology
|
||||
|
||||
|
||||
class V1Controller(object):
|
||||
topology = topology.TopologyController()
|
19
vitrage/api/controllers/v1/topology.py
Normal file
19
vitrage/api/controllers/v1/topology.py
Normal file
@ -0,0 +1,19 @@
|
||||
# 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.
|
||||
|
||||
from pecan import rest
|
||||
|
||||
|
||||
class TopologyController(rest.RestController):
|
||||
"""Manages operations on the topology."""
|
||||
|
||||
pass
|
38
vitrage/api/hooks.py
Normal file
38
vitrage/api/hooks.py
Normal file
@ -0,0 +1,38 @@
|
||||
# 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.
|
||||
|
||||
from oslo_policy import policy
|
||||
from pecan import hooks
|
||||
|
||||
|
||||
class ConfigHook(hooks.PecanHook):
|
||||
"""Attach the configuration and policy enforcer object to the request. """
|
||||
|
||||
def __init__(self, conf):
|
||||
self.conf = conf
|
||||
self.enforcer = policy.Enforcer(conf)
|
||||
|
||||
def before(self, state):
|
||||
state.request.cfg = self.conf
|
||||
state.request.enforcer = self.enforcer
|
||||
|
||||
|
||||
class TranslationHook(hooks.PecanHook):
|
||||
|
||||
def after(self, state):
|
||||
# After a request has been done, we need to see if
|
||||
# ClientSideError has added an error onto the response.
|
||||
# If it has we need to get it info the thread-safe WSGI
|
||||
# environ to be used by the ParsableErrorMiddleware.
|
||||
if hasattr(state.response, 'translatable_error'):
|
||||
state.request.environ['translatable_error'] = (
|
||||
state.response.translatable_error)
|
19
vitrage/cmd/api.py
Normal file
19
vitrage/cmd/api.py
Normal file
@ -0,0 +1,19 @@
|
||||
# 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.
|
||||
|
||||
from vitrage.api import app
|
||||
from vitrage import service
|
||||
|
||||
|
||||
def main():
|
||||
conf = service.prepare_service()
|
||||
app.build_server(conf)
|
42
vitrage/i18n.py
Normal file
42
vitrage/i18n.py
Normal file
@ -0,0 +1,42 @@
|
||||
# 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.
|
||||
|
||||
"""oslo.i18n integration module.
|
||||
See http://docs.openstack.org/developer/oslo.i18n/usage.html
|
||||
"""
|
||||
|
||||
import oslo_i18n
|
||||
|
||||
DOMAIN = 'vitrage'
|
||||
|
||||
_translators = oslo_i18n.TranslatorFactory(domain=DOMAIN)
|
||||
|
||||
# The primary translation function using the well-known name "_"
|
||||
_ = _translators.primary
|
||||
|
||||
# Translators for log levels.
|
||||
#
|
||||
# The abbreviated names are meant to reflect the usual use of a short
|
||||
# name like '_'. The "L" is for "log" and the other letter comes from
|
||||
# the level.
|
||||
_LI = _translators.log_info
|
||||
_LW = _translators.log_warning
|
||||
_LE = _translators.log_error
|
||||
_LC = _translators.log_critical
|
||||
|
||||
|
||||
def translate(value, user_locale):
|
||||
return oslo_i18n.translate(value, user_locale)
|
||||
|
||||
|
||||
def get_available_languages():
|
||||
return oslo_i18n.get_available_languages(DOMAIN)
|
24
vitrage/opts.py
Normal file
24
vitrage/opts.py
Normal file
@ -0,0 +1,24 @@
|
||||
# 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.
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
|
||||
def list_opts():
|
||||
return [("api", (
|
||||
cfg.IntOpt('workers', default=1,
|
||||
min=1,
|
||||
help='Number of workers for vitrage API server.'),
|
||||
|
||||
cfg.BoolOpt('pecan_debug', default=False,
|
||||
help='Toggle Pecan Debug Middleware.')
|
||||
))]
|
56
vitrage/service.py
Normal file
56
vitrage/service.py
Normal file
@ -0,0 +1,56 @@
|
||||
# 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 keystoneclient.auth
|
||||
import logging
|
||||
|
||||
|
||||
from keystonemiddleware import opts as ks_opts
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log
|
||||
from oslo_policy import opts as policy_opts
|
||||
|
||||
from vitrage import opts
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
def prepare_service(args=None, default_opts=None, conf=None):
|
||||
if conf is None:
|
||||
conf = cfg.ConfigOpts()
|
||||
log.register_options(conf)
|
||||
for group, options in ks_opts.list_auth_token_opts():
|
||||
conf.register_opts(list(options), group=group)
|
||||
policy_opts.set_defaults(conf)
|
||||
|
||||
for group, options in opts.list_opts():
|
||||
conf.register_opts(list(options),
|
||||
group=None if group == "DEFAULT" else group)
|
||||
|
||||
for opt, value, group in default_opts or []:
|
||||
conf.set_default(opt, value, group)
|
||||
|
||||
conf(args, project='vitrage', validate_default_values=True)
|
||||
log.setup(conf, 'vitrage')
|
||||
conf.log_opt_values(LOG, logging.DEBUG)
|
||||
|
||||
# NOTE(sileht): keystonemiddleware assume we use the global CONF object
|
||||
# (LP#1428317). In gnocchi, this is not the case, so we have to register
|
||||
# some keystoneclient options ourself. Missing options are hidden into
|
||||
# private area of keystonemiddleware and keystoneclient, so we
|
||||
# create a keystoneclient AuthPlugin object, that will register the options
|
||||
# into our configuration object. This have to be done after the
|
||||
# configuration files have been loaded because the authplugin options
|
||||
# depends of the authplugin present in the configuration file.
|
||||
keystoneclient.auth.register_conf_options(conf, 'keystone_authtoken')
|
||||
keystoneclient.auth.load_from_conf_options(conf, 'keystone_authtoken')
|
||||
return conf
|
Loading…
x
Reference in New Issue
Block a user