Add higgins-api command

Change-Id: Ic326d7bc06577d65cbf24ac247d1ebbc9ce79ec2
Implements: blueprint higgins-api
This commit is contained in:
OTSUKA, Yuanying 2016-05-18 13:58:57 +09:00
parent 20d1e9d251
commit 53f7ec03f2
10 changed files with 248 additions and 10 deletions

View File

@ -9,17 +9,57 @@
# 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 higgins import model
from pecan import make_app
from oslo_config import cfg
from oslo_log import log
import pecan
from higgins.api import config as api_config
from higgins.common.i18n import _
# Register options for the service
API_SERVICE_OPTS = [
cfg.PortOpt('port',
default=9512,
help='The port for the higgins API server.'),
cfg.IPOpt('host',
default='127.0.0.1',
help='The listen IP for the higgins API server.'),
cfg.BoolOpt('enable_ssl_api',
default=False,
help=_("Enable the integrated stand-alone API to service "
"requests via HTTPS instead of HTTP. If there is a "
"front-end service performing HTTPS offloading from "
"the service, this option should be False; note, you "
"will want to change public API endpoint to represent "
"SSL termination URL with 'public_endpoint' option.")),
]
CONF = cfg.CONF
opt_group = cfg.OptGroup(name='api',
title='Options for the higgins-api service')
CONF.register_group(opt_group)
CONF.register_opts(API_SERVICE_OPTS, opt_group)
LOG = log.getLogger(__name__)
def setup_app(config):
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(config=None):
if not config:
config = get_pecan_config()
model.init_model()
app_conf = dict(config.app)
return make_app(
app = pecan.make_app(
app_conf.pop('root'),
logging=getattr(config, 'logging', {}),
**app_conf
)
return app

View File

@ -16,11 +16,11 @@ from higgins.api import hooks
# Pecan Application Configurations
app = {
'root': 'higgins.controllers.root.RootController',
'root': 'higgins.api.controllers.root.RootController',
'modules': ['higgins'],
'hooks': [
hooks.ContextHook(),
hooks.NoExceptionTracebackHook(),
],
'debug': True,
'debug': False,
}

0
higgins/cmd/__init__.py Normal file
View File

47
higgins/cmd/api.py Normal file
View File

@ -0,0 +1,47 @@
# -*- encoding: utf-8 -*-
#
# Copyright 2013 Hewlett-Packard Development Company, L.P.
# All Rights Reserved.
#
# 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.
"""The Higgins Service API."""
import sys
from oslo_config import cfg
from higgins.common import service as higgins_service
CONF = cfg.CONF
def main():
# Parse config file and command line options, then start logging
higgins_service.prepare_service(sys.argv)
# Enable object backporting via the conductor
# TODO(yuanying): Uncomment after rpc services are implemented
# base.higginsObject.indirection_api = base.higginsObjectIndirectionAPI()
# Build and start the WSGI app
launcher = higgins_service.process_launcher()
server = higgins_service.WSGIService(
'higgins_api',
CONF.api.enable_ssl_api
)
launcher.launch_service(server, workers=server.workers)
launcher.wait()
if __name__ == '__main__':
sys.exit(main())

View File

31
higgins/common/config.py Normal file
View File

@ -0,0 +1,31 @@
# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
# Copyright 2012 Red Hat, 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.
from oslo_config import cfg
# from higgins.common import rpc
from higgins import version
def parse_args(argv, default_config_files=None):
# TODO(yuanying): Uncomment after rpc is implemented
# rpc.set_defaults(control_exchange='higgins')
cfg.CONF(argv[1:],
project='higgins',
version=version.version_info.release_string(),
default_config_files=default_config_files)
# rpc.init(cfg.CONF)

View File

@ -30,9 +30,9 @@ import pecan
import six
import wsme
from higgins.common.i18n import _
from higgins.common.i18n import _LE
from higgins.common import safe_utils
from higgins.i18n import _
from higgins.i18n import _LE
LOG = logging.getLogger(__name__)
@ -327,3 +327,7 @@ class PatchError(Invalid):
class NotAuthorized(HigginsException):
message = _("Not authorized.")
code = 403
class ConfigInvalid(HigginsException):
message = _("Invalid configuration file. %(error_msg)s")

108
higgins/common/service.py Normal file
View File

@ -0,0 +1,108 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2012 eNovance <licensing@enovance.com>
#
# 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 socket
from oslo_concurrency import processutils
from oslo_config import cfg
from oslo_log import log
from oslo_service import service
from oslo_service import wsgi
from higgins.api import app
from higgins.common import config
from higgins.common import exception
from higgins.common.i18n import _
service_opts = [
cfg.StrOpt('host',
default=socket.getfqdn(),
help=_('Name of this node. This can be an opaque identifier. '
'It is not necessarily a hostname, FQDN, or IP address. '
'However, the node name must be valid within '
'an AMQP key, and if using ZeroMQ, a valid '
'hostname, FQDN, or IP address.')),
]
CONF = cfg.CONF
LOG = log.getLogger(__name__)
CONF.register_opts(service_opts)
def prepare_service(argv=[]):
log.register_options(CONF)
config.parse_args(argv)
log.setup(CONF, 'higgins')
# TODO(yuanying): Uncomment after objects are implemented
# objects.register_all()
def process_launcher():
return service.ProcessLauncher(CONF)
class WSGIService(service.ServiceBase):
"""Provides ability to launch Higgins API from wsgi app."""
def __init__(self, name, use_ssl=False):
"""Initialize, but do not start the WSGI server.
:param name: The name of the WSGI server given to the loader.
:param use_ssl: Wraps the socket in an SSL context if True.
:returns: None
"""
self.name = name
self.app = app.setup_app()
self.workers = (processutils.get_worker_count())
if self.workers and self.workers < 1:
raise exception.ConfigInvalid(
_("api_workers value of %d is invalid, "
"must be greater than 0.") % self.workers)
self.server = wsgi.Server(CONF, name, self.app,
host=CONF.api.host,
port=CONF.api.port,
use_ssl=use_ssl)
def start(self):
"""Start serving this service using loaded configuration.
:returns: None
"""
self.server.start()
def stop(self):
"""Stop serving this API.
:returns: None
"""
self.server.stop()
def wait(self):
"""Wait for the service to stop serving this API.
:returns: None
"""
self.server.wait()
def reset(self):
"""Reset server greenpool size to default.
:returns: None
"""
self.server.reset()

View File

@ -4,10 +4,15 @@
PyYAML>=3.1.0 # MIT
eventlet!=0.18.3,>=0.18.2 # MIT
keystonemiddleware!=4.1.0,>=4.0.0 # Apache-2.0
greenlet>=0.3.2 # MIT
pbr>=1.6 # Apache-2.0
pecan>=1.0.0 # BSD
oslo.i18n>=2.1.0 # Apache-2.0
oslo.log>=1.14.0 # Apache-2.0
oslo.concurrency>=3.5.0 # Apache-2.0
oslo.config>=3.9.0 # Apache-2.0
oslo.service>=1.10.0 # Apache-2.0
oslo.versionedobjects!=1.9.0,>=1.5.0 # Apache-2.0
six>=1.9.0 # MIT
WebOb>=1.2.3 # MIT
WSME>=0.8 # MIT

View File

@ -45,5 +45,8 @@ mapping_file = babel.cfg
output_file = higgins/locale/higgins.pot
[entry_points]
console_scripts =
higgins-api = higgins.cmd.api:main
oslo.config.opts =
higgins = higgins.opts:list_opts