[API] Migrate to oslo.config
Major configuration change. See examples in etc/ directory. Change-Id: I8090e365f7c1d48ffeede55651ee54801f9d3b90
This commit is contained in:
72
etc/api.cfg
Normal file
72
etc/api.cfg
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
########################################################################
|
||||||
|
# A sample configuration file read by the Libra pool manager utility.
|
||||||
|
########################################################################
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# The [DEFAULT] section contains options common to the various Libra
|
||||||
|
# utilities (worker, mgm, etc).
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
[DEFAULT]
|
||||||
|
# Options to enable more verbose output
|
||||||
|
#verbose = false
|
||||||
|
#debug = false
|
||||||
|
|
||||||
|
# Daemon process options
|
||||||
|
#daemon = true
|
||||||
|
#user = libra
|
||||||
|
#group = libra
|
||||||
|
|
||||||
|
# Other logging options
|
||||||
|
#syslog = false
|
||||||
|
#syslog_socket = /dev/log
|
||||||
|
#syslog_faciltiy = local7
|
||||||
|
#logstash = HOST:PORT
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Options for utilities that are Gearman workers or clients.
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
[gearman]
|
||||||
|
#servers = localhost:4730, HOST:PORT
|
||||||
|
#keepalive = false
|
||||||
|
#keepcnt = COUNT
|
||||||
|
#keepidle = SECONDS
|
||||||
|
#keepintvl = SECONDS
|
||||||
|
#poll = 1
|
||||||
|
#reconnect_sleep = 60
|
||||||
|
#ssl_ca = /path/to/ssl_ca
|
||||||
|
#ssl_cert = /path/to/ssl_cert
|
||||||
|
#ssl_key = /path/to/ssl_key
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# The [api] section is specific to the libra_api utility.
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
[api]
|
||||||
|
|
||||||
|
# Options with defaults
|
||||||
|
#disable_keystone=False
|
||||||
|
#host=0.0.0.0
|
||||||
|
#port=443
|
||||||
|
#keystone_module=keystoneclient.middleware.auth_token:AuthProtocol
|
||||||
|
#logfile=/var/log/libra/libra_api.log
|
||||||
|
#pid=/var/run/libra/libra_api.pid
|
||||||
|
|
||||||
|
# Required options
|
||||||
|
db_sections=mysql1
|
||||||
|
swift_basepath=lbaaslogs
|
||||||
|
swift_endpoint=https://host.com:443/v1/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ssl_certfile=certfile.crt
|
||||||
|
ssl_keyfile=keyfile.key
|
||||||
|
ip_filters=192.168.0.0/24
|
||||||
|
|
||||||
|
[mysql1]
|
||||||
|
username=root
|
||||||
|
password=
|
||||||
|
schema=lbaas
|
||||||
|
host=localhost
|
||||||
|
|
||||||
|
# Keystone options go here
|
||||||
|
[keystone]
|
||||||
@@ -292,7 +292,8 @@ def main():
|
|||||||
MaintThreads(logger, args, drivers)
|
MaintThreads(logger, args, drivers)
|
||||||
sys.stderr = LogStdout(logger)
|
sys.stderr = LogStdout(logger)
|
||||||
|
|
||||||
sock = server.make_socket(args)
|
sock = server.make_socket(args.host, args.port,
|
||||||
|
args.ssl_keyfile, args.ssl_certfile)
|
||||||
wsgi.server(sock, api, keepalive=False)
|
wsgi.server(sock, api, keepalive=False)
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -11,3 +11,52 @@
|
|||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from oslo.config import cfg
|
||||||
|
|
||||||
|
|
||||||
|
api_group = cfg.OptGroup('api', 'Libra API options')
|
||||||
|
|
||||||
|
cfg.CONF.register_group(api_group)
|
||||||
|
|
||||||
|
cfg.CONF.register_opts(
|
||||||
|
[
|
||||||
|
cfg.ListOpt('db_sections',
|
||||||
|
required=True,
|
||||||
|
help='MySQL config sections in the config file'),
|
||||||
|
cfg.BoolOpt('disable_keystone',
|
||||||
|
default=False,
|
||||||
|
help='Unauthenticated server, for testing only'),
|
||||||
|
cfg.StrOpt('host',
|
||||||
|
default='0.0.0.0',
|
||||||
|
help='IP address to bind to, 0.0.0.0 for all IPs'),
|
||||||
|
cfg.ListOpt('ip_filters',
|
||||||
|
help='IP filters for backend nodes in the form '
|
||||||
|
'xxx.xxx.xxx.xxx/yy'),
|
||||||
|
cfg.StrOpt('keystone_module',
|
||||||
|
default='keystoneclient.middleware.auth_token:AuthProtocol',
|
||||||
|
help='A colon separated module and class for keystone '
|
||||||
|
' middleware'),
|
||||||
|
cfg.StrOpt('logfile',
|
||||||
|
default='/var/log/libra/libra_api.log',
|
||||||
|
help='Log file'),
|
||||||
|
cfg.StrOpt('pid',
|
||||||
|
default='/var/run/libra/libra_api.pid',
|
||||||
|
help='PID file'),
|
||||||
|
cfg.IntOpt('port',
|
||||||
|
default=443,
|
||||||
|
help='Port number for API server'),
|
||||||
|
cfg.StrOpt('ssl_certfile',
|
||||||
|
help='Path to an SSL certificate file'),
|
||||||
|
cfg.StrOpt('ssl_keyfile',
|
||||||
|
help='Path to an SSL key file'),
|
||||||
|
cfg.StrOpt('swift_basepath',
|
||||||
|
required=True,
|
||||||
|
help='Default Swift container to place log files'),
|
||||||
|
cfg.StrOpt('swift_endpoint',
|
||||||
|
required=True,
|
||||||
|
help='Default endpoint URL (tenant ID will be appended'
|
||||||
|
' to this)'),
|
||||||
|
],
|
||||||
|
group=api_group
|
||||||
|
)
|
||||||
|
|||||||
@@ -12,10 +12,12 @@
|
|||||||
# 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 ConfigParser
|
|
||||||
import importlib
|
import importlib
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from oslo.config import cfg
|
||||||
from pecan import request
|
from pecan import request
|
||||||
|
|
||||||
from libra.api.library.exp import NotAuthorized
|
from libra.api.library.exp import NotAuthorized
|
||||||
|
|
||||||
|
|
||||||
@@ -43,10 +45,9 @@ class AuthDirector(object):
|
|||||||
will direct intentionally unauthenticated requests to the relevant
|
will direct intentionally unauthenticated requests to the relevant
|
||||||
controllers. """
|
controllers. """
|
||||||
|
|
||||||
def __init__(self, app, args):
|
def __init__(self, app):
|
||||||
self.args = args
|
|
||||||
self.unauthed_app = app
|
self.unauthed_app = app
|
||||||
if not args.disable_keystone:
|
if not cfg.CONF['api']['disable_keystone']:
|
||||||
self.app = self._install()
|
self.app = self._install()
|
||||||
else:
|
else:
|
||||||
self.app = app
|
self.app = app
|
||||||
@@ -60,9 +61,7 @@ class AuthDirector(object):
|
|||||||
|
|
||||||
def _install(self):
|
def _install(self):
|
||||||
"""Install ACL check on application."""
|
"""Install ACL check on application."""
|
||||||
config = ConfigParser.SafeConfigParser()
|
module_details = cfg.CONF['api']['keystone_module'].split(':')
|
||||||
config.read([self.args.config])
|
|
||||||
module_details = self.args.keystone_module.split(':')
|
|
||||||
keystone = importlib.import_module(module_details[0])
|
keystone = importlib.import_module(module_details[0])
|
||||||
auth_class = getattr(keystone, module_details[1])
|
auth_class = getattr(keystone, module_details[1])
|
||||||
return auth_class(self.unauthed_app, config._sections['keystone'])
|
return auth_class(self.unauthed_app, cfg.CONF['keystone'])
|
||||||
|
|||||||
181
libra/api/app.py
181
libra/api/app.py
@@ -13,6 +13,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
import eventlet
|
import eventlet
|
||||||
eventlet.monkey_patch()
|
eventlet.monkey_patch()
|
||||||
|
|
||||||
import daemon
|
import daemon
|
||||||
import daemon.pidfile
|
import daemon.pidfile
|
||||||
import daemon.runner
|
import daemon.runner
|
||||||
@@ -20,14 +21,16 @@ import grp
|
|||||||
import pwd
|
import pwd
|
||||||
import pecan
|
import pecan
|
||||||
import sys
|
import sys
|
||||||
import os
|
|
||||||
import wsme_overrides
|
import wsme_overrides
|
||||||
|
|
||||||
|
from eventlet import wsgi
|
||||||
|
|
||||||
|
from libra import __version__
|
||||||
from libra.api import config as api_config
|
from libra.api import config as api_config
|
||||||
from libra.api import model
|
from libra.api import model
|
||||||
from libra.api import acl
|
from libra.api import acl
|
||||||
from libra.common.api import server
|
from libra.common.api import server
|
||||||
from libra.common.options import Options, setup_logging
|
from libra.common.options import add_common_opts, libra_logging, CONF
|
||||||
from eventlet import wsgi
|
|
||||||
|
|
||||||
|
|
||||||
# Gets rid of pep8 error
|
# Gets rid of pep8 error
|
||||||
@@ -40,31 +43,32 @@ def get_pecan_config():
|
|||||||
return pecan.configuration.conf_from_file(filename)
|
return pecan.configuration.conf_from_file(filename)
|
||||||
|
|
||||||
|
|
||||||
def setup_app(pecan_config, args):
|
def setup_app(pecan_config):
|
||||||
|
|
||||||
model.init_model()
|
model.init_model()
|
||||||
|
|
||||||
if not pecan_config:
|
if not pecan_config:
|
||||||
pecan_config = get_pecan_config()
|
pecan_config = get_pecan_config()
|
||||||
config = dict(pecan_config)
|
config = dict(pecan_config)
|
||||||
config['database'] = args.db_sections
|
config['database'] = CONF['api']['db_sections']
|
||||||
config['conffile'] = args.config
|
# NOTE: We support only 1 config file
|
||||||
|
config['conffile'] = CONF['config-file'][0]
|
||||||
config['swift'] = {
|
config['swift'] = {
|
||||||
'swift_basepath': args.swift_basepath,
|
'swift_basepath': CONF['api']['swift_basepath'],
|
||||||
'swift_endpoint': args.swift_endpoint
|
'swift_endpoint': CONF['api']['swift_endpoint']
|
||||||
}
|
}
|
||||||
config['gearman'] = {
|
config['gearman'] = {
|
||||||
'server': args.gearman,
|
'server': CONF['gearman']['servers'],
|
||||||
'ssl_key': args.gearman_ssl_key,
|
'ssl_key': CONF['gearman']['ssl_key'],
|
||||||
'ssl_cert': args.gearman_ssl_cert,
|
'ssl_cert': CONF['gearman']['ssl_cert'],
|
||||||
'ssl_ca': args.gearman_ssl_ca,
|
'ssl_ca': CONF['gearman']['ssl_ca'],
|
||||||
'keepalive': args.gearman_keepalive,
|
'keepalive': CONF['gearman']['keepalive'],
|
||||||
'keepcnt': args.gearman_keepcnt,
|
'keepcnt': CONF['gearman']['keepcnt'],
|
||||||
'keepidle': args.gearman_keepidle,
|
'keepidle': CONF['gearman']['keepidle'],
|
||||||
'keepintvl': args.gearman_keepintvl
|
'keepintvl': CONF['gearman']['keepintvl']
|
||||||
}
|
}
|
||||||
config['ip_filters'] = args.ip_filters
|
config['ip_filters'] = CONF['api']['ip_filters']
|
||||||
if args.debug:
|
if CONF['debug']:
|
||||||
config['wsme'] = {'debug': True}
|
config['wsme'] = {'debug': True}
|
||||||
config['app']['debug'] = True
|
config['app']['debug'] = True
|
||||||
|
|
||||||
@@ -82,7 +86,7 @@ def setup_app(pecan_config, args):
|
|||||||
True)
|
True)
|
||||||
)
|
)
|
||||||
|
|
||||||
final_app = acl.AuthDirector(app, args)
|
final_app = acl.AuthDirector(app)
|
||||||
return final_app
|
return final_app
|
||||||
|
|
||||||
|
|
||||||
@@ -100,125 +104,20 @@ class LogStdout(object):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
options = Options('api', 'API Server')
|
add_common_opts()
|
||||||
options.parser.add_argument(
|
CONF(project='libra', version=__version__)
|
||||||
'--host', help='IP address to bind to, 0.0.0.0 for all IPs',
|
|
||||||
default='0.0.0.0'
|
|
||||||
)
|
|
||||||
options.parser.add_argument(
|
|
||||||
'--port', help='Port number for API server', type=int, default=443
|
|
||||||
)
|
|
||||||
options.parser.add_argument(
|
|
||||||
'--disable_keystone', help='Unauthenticated server, for testing only',
|
|
||||||
action='store_true'
|
|
||||||
)
|
|
||||||
options.parser.add_argument(
|
|
||||||
'--db_sections', action='append', default=[],
|
|
||||||
help='MySQL config sections in the config file'
|
|
||||||
)
|
|
||||||
options.parser.add_argument(
|
|
||||||
'--gearman', action='append', metavar='HOST:PORT', default=[],
|
|
||||||
help='Gearman job servers'
|
|
||||||
)
|
|
||||||
options.parser.add_argument(
|
|
||||||
'--gearman_keepalive', action="store_true",
|
|
||||||
help='use KEEPALIVE to Gearman server'
|
|
||||||
)
|
|
||||||
options.parser.add_argument(
|
|
||||||
'--gearman_keepcnt', type=int, metavar='COUNT',
|
|
||||||
help='max keepalive probes to send before killing connection'
|
|
||||||
)
|
|
||||||
options.parser.add_argument(
|
|
||||||
'--gearman_keepidle', type=int, metavar='SECONDS',
|
|
||||||
help='seconds of idle time before sending keepalive probes'
|
|
||||||
)
|
|
||||||
options.parser.add_argument(
|
|
||||||
'--gearman_keepintvl', type=int, metavar='SECONDS',
|
|
||||||
help='seconds between TCP keepalive probes'
|
|
||||||
)
|
|
||||||
options.parser.add_argument(
|
|
||||||
'--gearman_ssl_ca', metavar='FILE',
|
|
||||||
help='Gearman SSL certificate authority'
|
|
||||||
)
|
|
||||||
options.parser.add_argument(
|
|
||||||
'--gearman_ssl_cert', metavar='FILE',
|
|
||||||
help='Gearman SSL certificate'
|
|
||||||
)
|
|
||||||
options.parser.add_argument(
|
|
||||||
'--gearman_ssl_key', metavar='FILE',
|
|
||||||
help='Gearman SSL key'
|
|
||||||
)
|
|
||||||
options.parser.add_argument(
|
|
||||||
'--keystone_module',
|
|
||||||
default='keystoneclient.middleware.auth_token:AuthProtocol',
|
|
||||||
help='A colon separated module and class for keystone middleware'
|
|
||||||
)
|
|
||||||
options.parser.add_argument(
|
|
||||||
'--swift_basepath',
|
|
||||||
help='Default swift container to use for pushing log files to'
|
|
||||||
)
|
|
||||||
options.parser.add_argument(
|
|
||||||
'--swift_endpoint',
|
|
||||||
help='Default endpoint URL (tenant ID will be appended to this)'
|
|
||||||
)
|
|
||||||
options.parser.add_argument(
|
|
||||||
'--ssl_certfile',
|
|
||||||
help='Path to an SSL certificate file'
|
|
||||||
)
|
|
||||||
options.parser.add_argument(
|
|
||||||
'--ssl_keyfile',
|
|
||||||
help='Path to an SSL key file'
|
|
||||||
)
|
|
||||||
options.parser.add_argument(
|
|
||||||
'--ip_filters', action='append', default=[],
|
|
||||||
help='IP filters for backend nodes in the form xxx.xxx.xxx.xxx/yy'
|
|
||||||
)
|
|
||||||
|
|
||||||
args = options.run()
|
|
||||||
|
|
||||||
required_args = [
|
|
||||||
'db_sections', 'swift_basepath',
|
|
||||||
'swift_endpoint'
|
|
||||||
]
|
|
||||||
|
|
||||||
missing_args = 0
|
|
||||||
for req in required_args:
|
|
||||||
test_var = getattr(args, req)
|
|
||||||
if test_var is None:
|
|
||||||
missing_args += 1
|
|
||||||
sys.stderr.write(
|
|
||||||
'{app}: error: argument --{test_var} is required\n'
|
|
||||||
.format(app=os.path.basename(sys.argv[0]), test_var=req))
|
|
||||||
if missing_args:
|
|
||||||
return 2
|
|
||||||
|
|
||||||
if not args.gearman:
|
|
||||||
# NOTE(shrews): Can't set a default in argparse method because the
|
|
||||||
# value is appended to the specified default.
|
|
||||||
args.gearman.append('localhost:4730')
|
|
||||||
elif not isinstance(args.gearman, list):
|
|
||||||
# NOTE(shrews): The Options object cannot intelligently handle
|
|
||||||
# creating a list from an option that may have multiple values.
|
|
||||||
# We convert it to the expected type here.
|
|
||||||
svr_list = args.gearman.split()
|
|
||||||
args.gearman = svr_list
|
|
||||||
|
|
||||||
if not isinstance(args.db_sections, list):
|
|
||||||
db_list = args.db_sections.split()
|
|
||||||
args.db_sections = db_list
|
|
||||||
|
|
||||||
if not isinstance(args.ip_filters, list):
|
|
||||||
ip_list = args.ip_filters.split()
|
|
||||||
args.ip_filters = ip_list
|
|
||||||
|
|
||||||
pc = get_pecan_config()
|
pc = get_pecan_config()
|
||||||
|
|
||||||
# NOTE: Let's not force anyone to actually have to use SSL, it shouldn't be
|
# NOTE: Let's not force anyone to actually have to use SSL, it shouldn't be
|
||||||
# up to us to decide.
|
# up to us to decide.
|
||||||
sock = server.make_socket(args)
|
sock = server.make_socket(CONF['api']['host'],
|
||||||
|
CONF['api']['port'],
|
||||||
|
CONF['api']['ssl_keyfile'],
|
||||||
|
CONF['api']['ssl_certfile'])
|
||||||
|
|
||||||
if not args.nodaemon:
|
if CONF['api']['daemon']:
|
||||||
pidfile = daemon.pidfile.TimeoutPIDLockFile(args.pid, 10)
|
pidfile = daemon.pidfile.TimeoutPIDLockFile(CONF['api']['pid'], 10)
|
||||||
if daemon.runner.is_pidfile_stale(pidfile):
|
if daemon.runner.is_pidfile_stale(pidfile):
|
||||||
pidfile.break_lock()
|
pidfile.break_lock()
|
||||||
context = daemon.DaemonContext(
|
context = daemon.DaemonContext(
|
||||||
@@ -227,17 +126,19 @@ def main():
|
|||||||
pidfile=pidfile,
|
pidfile=pidfile,
|
||||||
files_preserve=[sock.fileno()]
|
files_preserve=[sock.fileno()]
|
||||||
)
|
)
|
||||||
if args.user:
|
if CONF['user']:
|
||||||
context.uid = pwd.getpwnam(args.user).pw_uid
|
context.uid = pwd.getpwnam(CONF['user']).pw_uid
|
||||||
if args.group:
|
if CONF['group']:
|
||||||
context.gid = grp.getgrnam(args.group).gr_gid
|
context.gid = grp.getgrnam(CONF['group']).gr_gid
|
||||||
context.open()
|
context.open()
|
||||||
|
|
||||||
# Use the root logger due to lots of services using logger
|
# Use the root logger due to lots of services using logger
|
||||||
logger = setup_logging('', args)
|
logger = libra_logging('', 'api')
|
||||||
logger.info('Starting on {0}:{1}'.format(args.host, args.port))
|
logger.info('Starting on {0}:{1}'.format(CONF['api']['host'],
|
||||||
api = setup_app(pc, args)
|
CONF['api']['port']))
|
||||||
|
api = setup_app(pc)
|
||||||
sys.stderr = LogStdout(logger)
|
sys.stderr = LogStdout(logger)
|
||||||
|
|
||||||
wsgi.server(sock, api, keepalive=False, debug=args.debug)
|
wsgi.server(sock, api, keepalive=False, debug=CONF['debug'])
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -14,11 +14,11 @@
|
|||||||
import eventlet
|
import eventlet
|
||||||
|
|
||||||
|
|
||||||
def make_socket(args):
|
def make_socket(host, port, ssl_keyfile=None, ssl_certfile=None):
|
||||||
sock = eventlet.listen((args.host, args.port))
|
sock = eventlet.listen((host, port))
|
||||||
# TODO: set ca_certs and cert_reqs=CERT_REQUIRED
|
# TODO: set ca_certs and cert_reqs=CERT_REQUIRED
|
||||||
if args.ssl_keyfile and args.ssl_certfile:
|
if ssl_keyfile and ssl_certfile:
|
||||||
sock = eventlet.wrap_ssl(sock, certfile=args.ssl_certfile,
|
sock = eventlet.wrap_ssl(sock, certfile=ssl_certfile,
|
||||||
keyfile=args.ssl_keyfile,
|
keyfile=ssl_keyfile,
|
||||||
server_side=True)
|
server_side=True)
|
||||||
return sock
|
return sock
|
||||||
|
|||||||
Reference in New Issue
Block a user