summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--etc/plugins.ini3
-rw-r--r--etc/quantum.conf3
-rw-r--r--etc/quantum/plugins/ryu/ryu.ini10
-rw-r--r--quantum/api/__init__.py12
-rw-r--r--quantum/api/v2/base.py2
-rw-r--r--quantum/api/v2/router.py14
-rw-r--r--quantum/common/config.py317
-rw-r--r--quantum/common/utils.py57
-rw-r--r--quantum/extensions/extensions.py15
-rw-r--r--quantum/manager.py30
-rw-r--r--quantum/openstack/common/cfg.py319
-rw-r--r--quantum/plugins/cisco/common/cisco_credentials.py4
-rw-r--r--quantum/plugins/cisco/l2network_plugin_configuration.py8
-rw-r--r--quantum/plugins/cisco/nexus/cisco_nexus_configuration.py4
-rw-r--r--quantum/plugins/cisco/tests/unit/test_cisco_extension.py6
-rw-r--r--quantum/plugins/cisco/ucs/cisco_ucs_configuration.py6
-rw-r--r--quantum/plugins/cisco/ucs/cisco_ucs_inventory_configuration.py4
-rw-r--r--quantum/plugins/linuxbridge/common/config.py4
-rw-r--r--quantum/plugins/linuxbridge/db/l2network_db.py4
-rw-r--r--quantum/plugins/openvswitch/common/config.py4
-rw-r--r--quantum/plugins/openvswitch/ovs_quantum_plugin.py4
-rwxr-xr-xquantum/plugins/ryu/agent/ryu_quantum_agent.py18
-rw-r--r--quantum/plugins/ryu/common/__init__.py15
-rw-r--r--quantum/plugins/ryu/common/config.py43
-rw-r--r--quantum/plugins/ryu/ovs_quantum_plugin_base.py22
-rw-r--r--quantum/plugins/ryu/ryu_quantum_plugin.py12
-rw-r--r--quantum/plugins/ryu/tests/unit/fake_plugin.py4
-rw-r--r--quantum/plugins/ryu/tests/unit/test_ryu_driver.py9
-rw-r--r--quantum/policy.py4
-rwxr-xr-xquantum/server/__init__.py25
-rw-r--r--quantum/service.py45
-rw-r--r--quantum/tests/etc/quantum.conf.test (renamed from etc/quantum.conf.test)0
-rw-r--r--quantum/tests/unit/_test_api.py21
-rw-r--r--quantum/tests/unit/test_api_v2.py19
-rw-r--r--quantum/tests/unit/test_db_plugin.py18
-rw-r--r--quantum/tests/unit/test_extensions.py25
-rw-r--r--setup.py2
37 files changed, 554 insertions, 558 deletions
diff --git a/etc/plugins.ini b/etc/plugins.ini
deleted file mode 100644
index 49c660249d..0000000000
--- a/etc/plugins.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[PLUGIN]
-# Quantum plugin provider module
-provider = quantum.plugins.sample.SamplePlugin.FakePlugin
diff --git a/etc/quantum.conf b/etc/quantum.conf
index b19442865f..b96d0ef721 100644
--- a/etc/quantum.conf
+++ b/etc/quantum.conf
@@ -18,6 +18,9 @@ bind_port = 9696
# extensions are in there you don't need to specify them here
api_extensions_path =
+# Quantum plugin provider module
+core_plugin = quantum.plugins.sample.SamplePlugin.FakePlugin
+
[composite:quantum]
use = egg:Paste#urlmap
/: quantumversions
diff --git a/etc/quantum/plugins/ryu/ryu.ini b/etc/quantum/plugins/ryu/ryu.ini
index 2d5a2c5d7c..a90e8466b9 100644
--- a/etc/quantum/plugins/ryu/ryu.ini
+++ b/etc/quantum/plugins/ryu/ryu.ini
@@ -5,12 +5,12 @@
sql_connection = sqlite://
[OVS]
-integration-bridge = br-int
+integration_bridge = br-int
-# openflow-controller = <host IP address of ofp controller>:<port: 6633>
-# openflow-rest-api = <host IP address of ofp rest api service>:<port: 8080>
-openflow-controller = 127.0.0.1:6633
-openflow-rest-api = 127.0.0.1:8080
+# openflow_controller = <host IP address of ofp controller>:<port: 6633>
+# openflow_rest_api = <host IP address of ofp rest api service>:<port: 8080>
+openflow_controller = 127.0.0.1:6633
+openflow_rest_api = 127.0.0.1:8080
[AGENT]
# Change to "sudo quantum-rootwrap" to limit commands that can be run
diff --git a/quantum/api/__init__.py b/quantum/api/__init__.py
index aa5a8791b1..813ff40ec4 100644
--- a/quantum/api/__init__.py
+++ b/quantum/api/__init__.py
@@ -42,23 +42,23 @@ class APIRouter(wsgi.Router):
"""
_version = None
- def __init__(self, options=None):
+ def __init__(self):
mapper = self._mapper()
- self._setup_routes(mapper, options)
+ self._setup_routes(mapper)
super(APIRouter, self).__init__(mapper)
def _mapper(self):
return routes.Mapper()
- def _setup_routes(self, mapper, options):
- self._setup_base_routes(mapper, options, self._version)
+ def _setup_routes(self, mapper):
+ self._setup_base_routes(mapper, self._version)
- def _setup_base_routes(self, mapper, options, version):
+ def _setup_base_routes(self, mapper, version):
"""Routes common to all versions."""
# Loads the quantum plugin
# Note(salvatore-orlando): Should the plugin be versioned
# I don't think so
- plugin = manager.QuantumManager.get_plugin(options)
+ plugin = manager.QuantumManager.get_plugin()
uri_prefix = '/tenants/{tenant_id}/'
attachment_path = (
diff --git a/quantum/api/v2/base.py b/quantum/api/v2/base.py
index fbd92468c1..08148087b7 100644
--- a/quantum/api/v2/base.py
+++ b/quantum/api/v2/base.py
@@ -293,7 +293,7 @@ class Controller(object):
return body
-def create_resource(collection, resource, plugin, conf, params):
+def create_resource(collection, resource, plugin, params):
controller = Controller(plugin, collection, resource, params)
# NOTE(jkoelker) To anyone wishing to add "proper" xml support
diff --git a/quantum/api/v2/router.py b/quantum/api/v2/router.py
index 04b2ff7f60..0b2d7a6f8c 100644
--- a/quantum/api/v2/router.py
+++ b/quantum/api/v2/router.py
@@ -24,6 +24,7 @@ import webob.exc
from quantum import manager
from quantum import wsgi
from quantum.api.v2 import base
+from quantum.openstack.common import cfg
LOG = logging.getLogger(__name__)
@@ -118,16 +119,14 @@ class APIRouter(wsgi.Router):
@classmethod
def factory(cls, global_config, **local_config):
- return cls(global_config, **local_config)
+ return cls(**local_config)
- def __init__(self, conf, **local_config):
+ def __init__(self, **local_config):
mapper = routes_mapper.Mapper()
- plugin_provider = manager.get_plugin_provider(conf)
+ plugin_provider = cfg.CONF.core_plugin
+ LOG.debug("Plugin location:%s", plugin_provider)
plugin = manager.get_plugin(plugin_provider)
- # NOTE(jkoelker) Merge local_conf into conf after the plugin
- # is discovered
- conf.update(local_config)
col_kwargs = dict(collection_actions=COLLECTION_ACTIONS,
member_actions=MEMBER_ACTIONS)
@@ -137,8 +136,7 @@ class APIRouter(wsgi.Router):
def _map_resource(collection, resource, params):
controller = base.create_resource(collection, resource,
- plugin, conf,
- params)
+ plugin, params)
mapper_kwargs = dict(controller=controller,
requirements=REQUIREMENTS,
**col_kwargs)
diff --git a/quantum/common/config.py b/quantum/common/config.py
index f426b4594a..1e608c013e 100644
--- a/quantum/common/config.py
+++ b/quantum/common/config.py
@@ -20,325 +20,100 @@ Routines for configuring Quantum
"""
import logging
-import logging.config
import logging.handlers
-import optparse
import os
-import socket
import sys
from paste import deploy
-from quantum.common import flags
+from quantum.openstack.common import cfg
+from quantum.version import version_string
LOG = logging.getLogger(__name__)
-DEFAULT_LOG_FORMAT = "%(asctime)s %(levelname)8s [%(name)s] %(message)s"
-DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
-FLAGS = flags.FLAGS
+bind_opts = [
+ cfg.StrOpt('bind_host', default='0.0.0.0'),
+ cfg.IntOpt('bind_port', default=9696),
+ cfg.StrOpt('api_extensions_path', default=""),
+ cfg.StrOpt('core_plugin',
+ default='quantum.plugins.sample.SamplePlugin.FakePlugin'),
+]
+# Register the configuration options
+cfg.CONF.register_opts(bind_opts)
-def parse_options(parser, cli_args=None):
- """
- Returns the parsed CLI options, command to run and its arguments, merged
- with any same-named options found in a configuration file.
-
- The function returns a tuple of (options, args), where options is a
- mapping of option key/str(value) pairs, and args is the set of arguments
- (not options) supplied on the command-line.
-
- The reason that the option values are returned as strings only is that
- ConfigParser and paste.deploy only accept string values...
-
- :param parser: The option parser
- :param cli_args: (Optional) Set of arguments to process. If not present,
- sys.argv[1:] is used.
- :retval tuple of (options, args)
- """
-
- (options, args) = parser.parse_args(cli_args)
-
- return (vars(options), args)
-
-
-def add_common_options(parser):
- """
- Given a supplied optparse.OptionParser, adds an OptionGroup that
- represents all common configuration options.
-
- :param parser: optparse.OptionParser
- """
- help_text = "The following configuration options are common to "\
- "all quantum programs."
- group = optparse.OptionGroup(parser, "Common Options", help_text)
- group.add_option('-v', '--verbose', default=False, dest="verbose",
- action="store_true",
- help="Print more verbose output")
- group.add_option('-d', '--debug', default=False, dest="debug",
- action="store_true",
- help="Print debugging output")
- group.add_option('--config-file', default=None, metavar="PATH",
- help="Path to the config file to use. When not specified "
- "(the default), we generally look at the first "
- "argument specified to be a config file, and if "
- "that is also missing, we search standard "
- "directories for a config file.")
- parser.add_option_group(group)
+def parse(args):
+ cfg.CONF(args=args, project='quantum',
+ version='%%prog %s' % version_string())
-def add_log_options(parser):
- """
- Given a supplied optparse.OptionParser, adds an OptionGroup that
- represents all the configuration options around logging.
-
- :param parser: optparse.OptionParser
- """
- help_text = "The following configuration options are specific to logging "\
- "functionality for this program."
-
- group = optparse.OptionGroup(parser, "Logging Options", help_text)
- group.add_option('--log-config', default=None, metavar="PATH",
- help="If this option is specified, the logging "
- "configuration file specified is used and overrides "
- "any other logging options specified. Please see "
- "the Python logging module documentation for "
- "details on logging configuration files.")
- group.add_option('--log-date-format', metavar="FORMAT",
- default=DEFAULT_LOG_DATE_FORMAT,
- help="Format string for %(asctime)s in log records. "
- "Default: %default")
- group.add_option('--use-syslog', default=False,
- action="store_true",
- help="Output logs to syslog.")
- group.add_option('--log-file', default=None, metavar="PATH",
- help="(Optional) Name of log file to output to. "
- "If not set, logging will go to stdout.")
- group.add_option("--log-dir", default=None,
- help="(Optional) The directory to keep log files in "
- "(will be prepended to --logfile)")
- parser.add_option_group(group)
-
-
-def setup_logging(options, conf):
+def setup_logging(conf):
"""
Sets up the logging options for a log with supplied name
- :param options: Mapping of typed option key/values
- :param conf: Mapping of untyped key/values from config file
+ :param conf: a cfg.ConfOpts object
"""
- if options.get('log_config', None):
+ if conf.log_config:
# Use a logging configuration file for all settings...
- if os.path.exists(options['log_config']):
- logging.config.fileConfig(options['log_config'])
+ if os.path.exists(conf.log_config):
+ logging.config.fileConfig(conf.log_config)
return
else:
raise RuntimeError("Unable to locate specified logging "
- "config file: %s" % options['log_config'])
+ "config file: %s" % conf.log_config)
- # If either the CLI option or the conf value
- # is True, we set to True
- debug = (options.get('debug') or
- get_option(conf, 'debug', type='bool', default=False))
- verbose = (options.get('verbose') or
- get_option(conf, 'verbose', type='bool', default=False))
root_logger = logging.root
- if debug:
+ if conf.debug:
root_logger.setLevel(logging.DEBUG)
- elif verbose:
+ elif conf.verbose:
root_logger.setLevel(logging.INFO)
else:
root_logger.setLevel(logging.WARNING)
- # Set log configuration from options...
- # Note that we use a hard-coded log format in the options
- # because of Paste.Deploy bug #379
- # http://trac.pythonpaste.org/pythonpaste/ticket/379
- log_format = options.get('log_format', DEFAULT_LOG_FORMAT)
- log_date_format = options.get('log_date_format', DEFAULT_LOG_DATE_FORMAT)
- formatter = logging.Formatter(log_format, log_date_format)
+ formatter = logging.Formatter(conf.log_format, conf.log_date_format)
- syslog = options.get('use_syslog')
- if not syslog:
- syslog = conf.get('use_syslog')
-
- if syslog:
- SysLogHandler = logging.handlers.SysLogHandler
+ if conf.use_syslog:
try:
- handler = SysLogHandler(address='/dev/log',
- facility=SysLogHandler.LOG_SYSLOG)
- except socket.error:
- handler = SysLogHandler(address='/var/run/syslog',
- facility=SysLogHandler.LOG_SYSLOG)
- handler.setFormatter(formatter)
- root_logger.addHandler(handler)
-
- logfile = options.get('log_file')
- if not logfile:
- logfile = conf.get('log_file')
-
- if logfile:
- logdir = options.get('log_dir')
- if not logdir:
- logdir = conf.get('log_dir')
- if logdir:
- logfile = os.path.join(logdir, logfile)
- logfile = logging.FileHandler(logfile)
- logfile.setFormatter(formatter)
- logfile.setFormatter(formatter)
- root_logger.addHandler(logfile)
+ facility = getattr(logging.handlers.SysLogHandler,
+ conf.syslog_log_facility)
+ except AttributeError:
+ raise ValueError(_("Invalid syslog facility"))
+
+ handler = logging.handlers.SysLogHandler(address='/dev/log',
+ facility=facility)
+ elif conf.log_file:
+ logfile = conf.log_file
+ if conf.log_dir:
+ logfile = os.path.join(conf.log_dir, logfile)
+ handler = logging.handlers.WatchedFileHandler(logfile)
else:
handler = logging.StreamHandler(sys.stdout)
- handler.setFormatter(formatter)
- root_logger.addHandler(handler)
-
-
-def find_config_file(options, args, config_file='quantum.conf'):
- """
- Return the first config file found.
-
- We search for the paste config file in the following order:
- * If --config-file option is used, use that
- * If args[0] is a file, use that
- * Search for the configuration file in standard directories:
- * .
- * ~.quantum/
- * ~
- * $FLAGS.state_path/etc/quantum
- * $FLAGS.state_path/etc
-
- :retval Full path to config file, or None if no config file found
- """
-
- fix_path = lambda p: os.path.abspath(os.path.expanduser(p))
- if options.get('config_file'):
- if os.path.exists(options['config_file']):
- return fix_path(options['config_file'])
- elif args:
- if os.path.exists(args[0]):
- return fix_path(args[0])
-
- dir_to_common = os.path.dirname(os.path.abspath(__file__))
- root = os.path.join(dir_to_common, '..', '..', '..', '..')
- # Handle standard directory search for the config file
- config_file_dirs = [fix_path(os.path.join(os.getcwd(), 'etc')),
- fix_path(os.path.join('~', '.quantum-venv', 'etc',
- 'quantum')),
- fix_path('~'),
- os.path.join(FLAGS.state_path, 'etc'),
- os.path.join(FLAGS.state_path, 'etc', 'quantum'),
- fix_path(os.path.join('~', '.local',
- 'etc', 'quantum')),
- '/usr/etc/quantum',
- '/usr/local/etc/quantum',
- '/etc/quantum/',
- '/etc']
-
- if 'plugin' in options:
- config_file_dirs = [os.path.join(x, 'quantum',
- 'plugins', options['plugin'])
- for x in config_file_dirs]
-
- if os.path.exists(os.path.join(root, 'plugins')):
- plugins = [fix_path(os.path.join(root, 'plugins', p, 'etc'))
- for p in os.listdir(os.path.join(root, 'plugins'))]
- plugins = [p for p in plugins if os.path.isdir(p)]
- config_file_dirs.extend(plugins)
-
- for cfg_dir in config_file_dirs:
- cfg_file = os.path.join(cfg_dir, config_file)
- if os.path.exists(cfg_file):
- return cfg_file
-
-
-def load_paste_config(app_name, options, args):
- """
- Looks for a config file to use for an app and returns the
- config file path and a configuration mapping from a paste config file.
- We search for the paste config file in the following order:
- * If --config-file option is used, use that
- * If args[0] is a file, use that
- * Search for quantum.conf in standard directories:
- * .
- * ~.quantum/
- * ~
- * /etc/quantum
- * /etc
+ handler.setFormatter(formatter)
+ root_logger.addHandler(handler)
- :param app_name: Name of the application to load config for, or None.
- None signifies to only load the [DEFAULT] section of
- the config file.
- :param options: Set of typed options returned from parse_options()
- :param args: Command line arguments from argv[1:]
- :retval Tuple of (conf_file, conf)
- :raises RuntimeError when config file cannot be located or there was a
- problem loading the configuration file.
- """
- conf_file = find_config_file(options, args)
- if not conf_file:
- raise RuntimeError("Unable to locate any configuration file. "
- "Cannot load application %s" % app_name)
- try:
- conf = deploy.appconfig("config:%s" % conf_file, name=app_name)
- return conf_file, conf
- except Exception, e:
- raise RuntimeError("Error trying to load config %s: %s"
- % (conf_file, e))
-
-
-def load_paste_app(app_name, options, args):
+def load_paste_app(app_name, config_file):
"""
Builds and returns a WSGI app from a paste config file.
- We search for the paste config file in the following order:
- * If --config-file option is used, use that
- * If args[0] is a file, use that
- * Search for quantum.conf in standard directories:
- * .
- * ~.quantum/
- * ~
- * /etc/quantum
- * /etc
-
:param app_name: Name of the application to load
- :param options: Set of typed options returned from parse_options()
- :param args: Command line arguments from argv[1:]
-
+ :param config_file: name of the configuration file
:raises RuntimeError when config file cannot be located or application
cannot be loaded from config file
"""
- conf_file, conf = load_paste_config(app_name, options, args)
+
+ config_path = os.path.abspath(cfg.CONF.find_file(config_file))
+ LOG.info("Config paste file: %s", config_path)
try:
- app = deploy.loadapp("config:%s" % conf_file, name=app_name)
+ app = deploy.loadapp("config:%s" % config_path, name=app_name)
except (LookupError, ImportError):
msg = ("Unable to load %(app_name)s from "
- "configuration file %(conf_file)s.") % locals()
+ "configuration file %(config_path)s.") % locals()
LOG.exception(msg)
raise RuntimeError(msg)
- return conf, app
-
-
-def get_option(options, option, **kwargs):
- if option in options:
- value = options[option]
- type_ = kwargs.get('type', 'str')
- if type_ == 'bool':
- if hasattr(value, 'lower'):
- return value.lower() == 'true'
- else:
- return value
- elif type_ == 'int':
- return int(value)
- elif type_ == 'float':
- return float(value)
- else:
- return value
- elif 'default' in kwargs:
- return kwargs['default']
- else:
- raise KeyError("option '%s' not found" % option)
+ return app
diff --git a/quantum/common/utils.py b/quantum/common/utils.py
index 4a355bdf92..4ac2c328be 100644
--- a/quantum/common/utils.py
+++ b/quantum/common/utils.py
@@ -21,7 +21,8 @@
"""Utilities and helper functions."""
-import ConfigParser
+import datetime
+import inspect
import logging
import os
import subprocess
@@ -75,12 +76,6 @@ def execute(cmd, process_input=None, addl_env=None, check_exit_code=True):
return result
-def get_plugin_from_config(file="config.ini"):
- Config = ConfigParser.ConfigParser()
- Config.read(file)
- return Config.get("PLUGIN", "provider")
-
-
class LazyPluggable(object):
"""A pluggable backend loaded lazily based on some value."""
@@ -110,3 +105,51 @@ class LazyPluggable(object):
def __getattr__(self, key):
backend = self.__get_backend()
return getattr(backend, key)
+
+
+def find_config_file(options, config_file):
+ """
+ Return the first config file found.
+
+ We search for the paste config file in the following order:
+ * If --config-file option is used, use that
+ * Search for the configuration files via common cfg directories
+ :retval Full path to config file, or None if no config file found
+ """
+ fix_path = lambda p: os.path.abspath(os.path.expanduser(p))
+ if options.get('config_file'):
+ if os.path.exists(options['config_file']):
+ return fix_path(options['config_file'])
+
+ dir_to_common = os.path.dirname(os.path.abspath(__file__))
+ root = os.path.join(dir_to_common, '..', '..', '..', '..')
+ # Handle standard directory search for the config file
+ config_file_dirs = [fix_path(os.path.join(os.getcwd(), 'etc')),
+ fix_path(os.path.join('~', '.quantum-venv', 'etc',
+ 'quantum')),
+ fix_path('~'),
+ os.path.join(FLAGS.state_path, 'etc'),
+ os.path.join(FLAGS.state_path, 'etc', 'quantum'),
+ fix_path(os.path.join('~', '.local',
+ 'etc', 'quantum')),
+ '/usr/etc/quantum',
+ '/usr/local/etc/quantum',
+ '/etc/quantum/',
+ '/etc']
+
+ if 'plugin' in options:
+ config_file_dirs = [
+ os.path.join(x, 'quantum', 'plugins', options['plugin'])
+ for x in config_file_dirs
+ ]
+
+ if os.path.exists(os.path.join(root, 'plugins')):
+ plugins = [fix_path(os.path.join(root, 'plugins', p, 'etc'))
+ for p in os.listdir(os.path.join(root, 'plugins'))]
+ plugins = [p for p in plugins if os.path.isdir(p)]
+ config_file_dirs.extend(plugins)
+
+ for cfg_dir in config_file_dirs:
+ cfg_file = os.path.join(cfg_dir, config_file)
+ if os.path.exists(cfg_file):
+ return cfg_file
diff --git a/quantum/extensions/extensions.py b/quantum/extensions/extensions.py
index 26aebc246e..1f5dc5d4ca 100644
--- a/quantum/extensions/extensions.py
+++ b/quantum/extensions/extensions.py
@@ -29,6 +29,7 @@ import webob.exc
from quantum.common import exceptions
import quantum.extensions
from quantum.manager import QuantumManager
+from quantum.openstack.common import cfg
from quantum import wsgi
@@ -217,12 +218,12 @@ class ExtensionController(wsgi.Controller):
class ExtensionMiddleware(wsgi.Middleware):
"""Extensions middleware for WSGI."""
- def __init__(self, application, config_params,
+ def __init__(self, application,
ext_mgr=None):
self.ext_mgr = (ext_mgr
or ExtensionManager(
- get_extensions_path(config_params)))
+ get_extensions_path()))
mapper = routes.Mapper()
# extended resources
@@ -339,10 +340,10 @@ class ExtensionMiddleware(wsgi.Middleware):
def plugin_aware_extension_middleware_factory(global_config, **local_config):
"""Paste factory."""
def _factory(app):
- extensions_path = get_extensions_path(global_config)
+ extensions_path = get_extensions_path()
ext_mgr = PluginAwareExtensionManager(extensions_path,
QuantumManager.get_plugin())
- return ExtensionMiddleware(app, global_config, ext_mgr=ext_mgr)
+ return ExtensionMiddleware(app, ext_mgr=ext_mgr)
return _factory
@@ -539,9 +540,9 @@ class ResourceExtension(object):
# Returns the extention paths from a config entry and the __path__
# of quantum.extensions
-def get_extensions_path(config=None):
+def get_extensions_path():
paths = ':'.join(quantum.extensions.__path__)
- if config:
- paths = ':'.join([config.get('api_extensions_path', ''), paths])
+ if cfg.CONF.api_extensions_path:
+ paths = ':'.join([cfg.CONF.api_extensions_path, paths])
return paths
diff --git a/quantum/manager.py b/quantum/manager.py
index 1f5f4f8f87..2d833c30e1 100644
--- a/quantum/manager.py
+++ b/quantum/manager.py
@@ -24,27 +24,15 @@ The caller should make sure that QuantumManager is a singleton.
"""
import logging
-import os
-from quantum.common import utils
-from quantum.common.config import find_config_file
from quantum.common.exceptions import ClassNotFound
+from quantum.openstack.common import cfg
from quantum.openstack.common import importutils
LOG = logging.getLogger(__name__)
-CONFIG_FILE = "plugins.ini"
-
-
-def find_config(basepath):
- for root, dirs, files in os.walk(basepath):
- if CONFIG_FILE in files:
- return os.path.join(root, CONFIG_FILE)
- return None
-
-
def get_plugin(plugin_provider):
# If the plugin can't be found let them know gracefully
try:
@@ -58,16 +46,6 @@ def get_plugin(plugin_provider):
return plugin_klass()
-def get_plugin_provider(options, config_file=None):
- if config_file:
- config_file = [config_file]
-
- if not 'plugin_provider' in options:
- cf = find_config_file(options, config_file, CONFIG_FILE)
- options['plugin_provider'] = utils.get_plugin_from_config(cf)
- return options['plugin_provider']
-
-
class QuantumManager(object):
_instance = None
@@ -81,12 +59,12 @@ class QuantumManager(object):
# breaks tach monitoring. It has been removed
# intentianally to allow v2 plugins to be monitored
# for performance metrics.
- plugin_provider = get_plugin_provider(options, config_file)
+ plugin_provider = cfg.CONF.core_plugin
LOG.debug("Plugin location:%s", plugin_provider)
self.plugin = get_plugin(plugin_provider)
@classmethod
- def get_plugin(cls, options=None, config_file=None):
+ def get_plugin(cls):
if cls._instance is None:
- cls._instance = cls(options, config_file)
+ cls._instance = cls()
return cls._instance.plugin
diff --git a/quantum/openstack/common/cfg.py b/quantum/openstack/common/cfg.py
index 80345a6d2a..b1493a31c0 100644
--- a/quantum/openstack/common/cfg.py
+++ b/quantum/openstack/common/cfg.py
@@ -95,7 +95,7 @@ and --config-dir::
class ConfigOpts(object):
- def __init__(self, ...):
+ def __call__(self, ...):
opts = [
MultiStrOpt('config-file',
@@ -233,6 +233,22 @@ log files:
...
]
+This module also contains a global instance of the CommonConfigOpts class
+in order to support a common usage pattern in OpenStack:
+
+ from openstack.common import cfg
+
+ opts = [
+ cfg.StrOpt('bind_host' default='0.0.0.0'),
+ cfg.IntOpt('bind_port', default=9292),
+ ]
+
+ CONF = cfg.CONF
+ CONF.register_opts(opts)
+
+ def start(server, app):
+ server.start(app, CONF.bind_port, CONF.bind_host)
+
"""
import collections
@@ -478,7 +494,8 @@ class Opt(object):
multi = False
def __init__(self, name, dest=None, short=None, default=None,
- metavar=None, help=None, secret=False, required=False):
+ metavar=None, help=None, secret=False, required=False,
+ deprecated_name=None):
"""Construct an Opt object.
The only required parameter is the option's name. However, it is
@@ -492,6 +509,7 @@ class Opt(object):
:param help: an explanation of how the option is used
:param secret: true iff the value should be obfuscated in log output
:param required: true iff a value must be supplied for this option
+ :param deprecated_name: deprecated name option. Acts like an alias
"""
self.name = name
if dest is None:
@@ -504,6 +522,10 @@ class Opt(object):
self.help = help
self.secret = secret
self.required = required
+ if deprecated_name is not None:
+ self.deprecated_name = deprecated_name.replace('-', '_')
+ else:
+ self.deprecated_name = None
def _get_from_config_parser(self, cparser, section):
"""Retrieves the option value from a MultiConfigParser object.
@@ -515,7 +537,13 @@ class Opt(object):
:param cparser: a ConfigParser object
:param section: a section name
"""
- return cparser.get(section, self.dest)
+ return self._cparser_get_with_deprecated(cparser, section)
+
+ def _cparser_get_with_deprecated(self, cparser, section):
+ """If cannot find option as dest try deprecated_name alias."""
+ if self.deprecated_name is not None:
+ return cparser.get(section, [self.dest, self.deprecated_name])
+ return cparser.get(section, [self.dest])
def _add_to_cli(self, parser, group=None):
"""Makes the option available in the command line interface.
@@ -530,9 +558,11 @@ class Opt(object):
container = self._get_optparse_container(parser, group)
kwargs = self._get_optparse_kwargs(group)
prefix = self._get_optparse_prefix('', group)
- self._add_to_optparse(container, self.name, self.short, kwargs, prefix)
+ self._add_to_optparse(container, self.name, self.short, kwargs, prefix,
+ self.deprecated_name)
- def _add_to_optparse(self, container, name, short, kwargs, prefix=''):
+ def _add_to_optparse(self, container, name, short, kwargs, prefix='',
+ deprecated_name=None):
"""Add an option to an optparse parser or group.
:param container: an optparse.OptionContainer object
@@ -545,6 +575,8 @@ class Opt(object):
args = ['--' + prefix + name]
if short:
args += ['-' + short]
+ if deprecated_name:
+ args += ['--' + prefix + deprecated_name]
for a in args:
if container.has_option(a):
raise DuplicateOptError(a)
@@ -577,7 +609,7 @@ class Opt(object):
dest = group.name + '_' + dest
kwargs.update({'dest': dest,
'metavar': self.metavar,
- 'help': self.help})
+ 'help': self.help, })
return kwargs
def _get_optparse_prefix(self, prefix, group):
@@ -627,7 +659,8 @@ class BoolOpt(Opt):
return value
- return [convert_bool(v) for v in cparser.get(section, self.dest)]
+ return [convert_bool(v) for v in
+ self._cparser_get_with_deprecated(cparser, section)]
def _add_to_cli(self, parser, group=None):
"""Extends the base class method to add the --nooptname option."""
@@ -640,7 +673,8 @@ class BoolOpt(Opt):
kwargs = self._get_optparse_kwargs(group, action='store_false')
prefix = self._get_optparse_prefix('no', group)
kwargs["help"] = "The inverse of --" + self.name
- self._add_to_optparse(container, self.name, None, kwargs, prefix)
+ self._add_to_optparse(container, self.name, None, kwargs, prefix,
+ self.deprecated_name)
def _get_optparse_kwargs(self, group, action='store_true', **kwargs):
"""Extends the base optparse keyword dict for boolean options."""
@@ -654,7 +688,8 @@ class IntOpt(Opt):
def _get_from_config_parser(self, cparser, section):
"""Retrieve the opt value as a integer from ConfigParser."""
- return [int(v) for v in cparser.get(section, self.dest)]
+ return [int(v) for v in self._cparser_get_with_deprecated(cparser,
+ section)]
def _get_optparse_kwargs(self, group, **kwargs):
"""Extends the base optparse keyword dict for integer options."""
@@ -668,7 +703,8 @@ class FloatOpt(Opt):
def _get_from_config_parser(self, cparser, section):
"""Retrieve the opt value as a float from ConfigParser."""
- return [float(v) for v in cparser.get(section, self.dest)]
+ return [float(v) for v in
+ self._cparser_get_with_deprecated(cparser, section)]
def _get_optparse_kwargs(self, group, **kwargs):
"""Extends the base optparse keyword dict for float options."""
@@ -685,7 +721,8 @@ class ListOpt(Opt):
def _get_from_config_parser(self, cparser, section):
"""Retrieve the opt value as a list from ConfigParser."""
- return [v.split(',') for v in cparser.get(section, self.dest)]
+ return [v.split(',') for v in
+ self._cparser_get_with_deprecated(cparser, section)]
def _get_optparse_kwargs(self, group, **kwargs):
"""Extends the base optparse keyword dict for list options."""
@@ -714,6 +751,13 @@ class MultiStrOpt(Opt):
return super(MultiStrOpt,
self)._get_optparse_kwargs(group, action='append')
+ def _cparser_get_with_deprecated(self, cparser, section):
+ """If cannot find option as dest try deprecated_name alias."""
+ if self.deprecated_name is not None:
+ return cparser.get(section, [self.dest, self.deprecated_name],
+ multi=True)
+ return cparser.get(section, [self.dest], multi=True)
+
class OptGroup(object):
@@ -766,6 +810,14 @@ class OptGroup(object):
return True
+ def _unregister_opt(self, opt):
+ """Remove an opt from this group.
+
+ :param opt: an Opt object
+ """
+ if opt.dest in self._opts:
+ del self._opts[opt.dest]
+
def _get_optparse_group(self, parser):
"""Build an optparse.OptionGroup for this group."""
if self._optparse_group is None:
@@ -773,6 +825,10 @@ class OptGroup(object):
self.help)
return self._optparse_group
+ def _clear(self):
+ """Clear this group's option parsing state."""
+ self._optparse_group = None
+
class ParseError(iniparser.ParseError):
def __init__(self, msg, lineno, line, filename):
@@ -816,25 +872,38 @@ class ConfigParser(iniparser.BaseParser):
class MultiConfigParser(object):
def __init__(self):
- self.sections = {}
+ self.parsed = []
def read(self, config_files):
read_ok = []
for filename in config_files:
- parser = ConfigParser(filename, self.sections)
+ sections = {}
+ parser = ConfigParser(filename, sections)
try:
parser.parse()
except IOError:
continue
-
+ self.parsed.insert(0, sections)
read_ok.append(filename)
return read_ok
- def get(self, section, name):
- return self.sections[section][name]
+ def get(self, section, names, multi=False):
+ rvalue = []
+ for sections in self.parsed:
+ if section not in sections:
+ continue
+ for name in names:
+ if name in sections[section]:
+ if multi:
+ rvalue = sections[section][name] + rvalue
+ else:
+ return sections[section][name]
+ if multi and rvalue != []:
+ return rvalue
+ raise KeyError
class ConfigOpts(collections.Mapping):
@@ -847,57 +916,41 @@ class ConfigOpts(collections.Mapping):
the values of options.
"""
- def __init__(self,
- project=None,
- prog=None,
- version=None,
- usage=None,
- default_config_files=None):
- """Construct a ConfigOpts object.
+ def __init__(self):
+ """Construct a ConfigOpts object."""
+ self._opts = {} # dict of dicts of (opt:, override:, default:)
+ self._groups = {}
- Automatically registers the --config-file option with either a supplied
- list of default config files, or a list from find_config_files().
+ self._args = None
+ self._oparser = None
+ self._cparser = None
+ self._cli_values = {}
+ self.__cache = {}
+ self._config_opts = []
+ self._disable_interspersed_args = False
- :param project: the toplevel project name, used to locate config files
- :param prog: the name of the program (defaults to sys.argv[0] basename)
- :param version: the program version (for --version)
- :param usage: a usage string (%prog will be expanded)
- :param default_config_files: config files to use by default
- """
+ def _setup(self, project, prog, version, usage, default_config_files):
+ """Initialize a ConfigOpts object for option parsing."""
if prog is None:
prog = os.path.basename(sys.argv[0])
if default_config_files is None:
default_config_files = find_config_files(project, prog)
- self.project = project
- self.prog = prog
- self.version = version
- self.usage = usage
- self.default_config_files = default_config_files
-
- self._opts = {} # dict of dicts of (opt:, override:, default:)
- self._groups = {}
-
- self._args = None
- self._cli_values = {}
-
- self._oparser = optparse.OptionParser(prog=self.prog,
- version=self.version,
- usage=self.usage)
- self._cparser = None
+ self._oparser = optparse.OptionParser(prog=prog,
+ version=version,
+ usage=usage)
+ if self._disable_interspersed_args:
+ self._oparser.disable_interspersed_args()
- self.__cache = {}
-
- opts = [
+ self._config_opts = [
MultiStrOpt('config-file',
- default=self.default_config_files,
+ default=default_config_files,
metavar='PATH',
help='Path to a config file to use. Multiple config '
'files can be specified, with values in later '
'files taking precedence. The default files '
- ' used are: %s' %
- (self.default_config_files)),
+ ' used are: %s' % (default_config_files, )),
StrOpt('config-dir',
metavar='DIR',
help='Path to a config directory to pull *.conf '
@@ -908,7 +961,13 @@ class ConfigOpts(collections.Mapping):
'hence over-ridden options in the directory take '
'precedence.'),
]
- self.register_cli_opts(opts)
+ self.register_cli_opts(self._config_opts)
+
+ self.project = project
+ self.prog = prog
+ self.version = version
+ self.usage = usage
+ self.default_config_files = default_config_files
def __clear_cache(f):
@functools.wraps(f)
@@ -919,7 +978,13 @@ class ConfigOpts(collections.Mapping):
return __inner
- def __call__(self, args=None):
+ def __call__(self,
+ args=None,
+ project=None,
+ prog=None,
+ version=None,
+ usage=None,
+ default_config_files=None):
"""Parse command line arguments and config files.
Calling a ConfigOpts object causes the supplied command line arguments
@@ -929,35 +994,34 @@ class ConfigOpts(collections.Mapping):
The object may be called multiple times, each time causing the previous
set of values to be overwritten.
+ Automatically registers the --config-file option with either a supplied
+ list of default config files, or a list from find_config_files().
+
If the --config-dir option is set, any *.conf files from this
directory are pulled in, after all the file(s) specified by the
--config-file option.
- :params args: command line arguments (defaults to sys.argv[1:])
+ :param args: command line arguments (defaults to sys.argv[1:])
+ :param project: the toplevel project name, used to locate config files
+ :param prog: the name of the program (defaults to sys.argv[0] basename)
+ :param version: the program version (for --version)
+ :param usage: a usage string (%prog will be expanded)
+ :param default_config_files: config files to use by default
:returns: the list of arguments left over after parsing options
:raises: SystemExit, ConfigFilesNotFoundError, ConfigFileParseError,
- RequiredOptError
+ RequiredOptError, DuplicateOptError
"""
self.clear()
- self._args = args
-
- (values, args) = self._oparser.parse_args(self._args)
-
- self._cli_values = vars(values)
-
- def _list_config_dir():
- return sorted(glob.glob(os.path.join(self.config_dir, '*.conf')))
-
- from_file = list(self.config_file)
+ self._setup(project, prog, version, usage, default_config_files)
- from_dir = _list_config_dir() if self.config_dir else []
+ self._cli_values, leftovers = self._parse_cli_opts(args)
- self._parse_config_files(from_file + from_dir)
+ self._parse_config_files()
self._check_required_opts()
- return args
+ return leftovers
def __getattr__(self, name):
"""Look up an option value and perform string substitution.
@@ -994,8 +1058,12 @@ class ConfigOpts(collections.Mapping):
def clear(self):
"""Clear the state of the object to before it was called."""
self._args = None
- self._cli_values = {}
+ self._cli_values.clear()
+ self._oparser = None
self._cparser = None
+ self.unregister_opts(self._config_opts)
+ for group in self._groups.values():
+ group._clear()
@__clear_cache
def register_opt(self, opt, group=None):
@@ -1042,15 +1110,7 @@ class ConfigOpts(collections.Mapping):
if self._args is not None:
raise ArgsAlreadyParsedError("cannot register CLI option")
- if not self.register_opt(opt, group, clear_cache=False):
- return False
-
- if group is not None:
- group = self._get_group(group, autocreate=True)
-
- opt._add_to_cli(self._oparser, group)
-
- return True
+ return self.register_opt(opt, group, clear_cache=False)
@__clear_cache
def register_cli_opts(self, opts, group=None):
@@ -1072,6 +1132,28 @@ class ConfigOpts(collections.Mapping):
self._groups[group.name] = copy.copy(group)
@__clear_cache
+ def unregister_opt(self, opt, group=None):
+ """Unregister an option.
+
+ :param opt: an Opt object
+ :param group: an optional OptGroup object or group name
+ :raises: ArgsAlreadyParsedError, NoSuchGroupError
+ """
+ if self._args is not None:
+ raise ArgsAlreadyParsedError("reset before unregistering options")
+
+ if group is not None:
+ self._get_group(group)._unregister_opt(opt)
+ elif opt.dest in self._opts:
+ del self._opts[opt.dest]
+
+ @__clear_cache
+ def unregister_opts(self, opts, group=None):
+ """Unregister multiple CLI option schemas at once."""
+ for opt in opts:
+ self.unregister_opt(opt, group, clear_cache=False)
+
+ @__clear_cache
def set_override(self, name, override, group=None):
"""Override an opt value.
@@ -1101,16 +1183,24 @@ class ConfigOpts(collections.Mapping):
opt_info = self._get_opt_info(name, group)
opt_info['default'] = default
+ def _all_opt_infos(self):
+ """A generator function for iteration opt infos."""
+ for info in self._opts.values():
+ yield info, None
+ for group in self._groups.values():
+ for info in group._opts.values():
+ yield info, group
+
+ def _all_opts(self):
+ """A generator function for iteration opts."""
+ for info, group in self._all_opt_infos():
+ yield info['opt'], group
+
def _unset_defaults_and_overrides(self):
"""Unset any default or override on all options."""
- def unset(opts):
- for info in opts.values():
- info['default'] = None
- info['override'] = None
-
- unset(self._opts)
- for group in self._groups.values():
- unset(group._opts)
+ for info, group in self._all_opt_infos():
+ info['default'] = None
+ info['override'] = None
def disable_interspersed_args(self):
"""Set parsing to stop on the first non-option.
@@ -1129,13 +1219,13 @@ class ConfigOpts(collections.Mapping):
i.e. argument parsing is stopped at the first non-option argument.
"""
- self._oparser.disable_interspersed_args()
+ self._disable_interspersed_args = True
def enable_interspersed_args(self):
"""Set parsing to not stop on the first non-option.
This it the default behaviour."""
- self._oparser.enable_interspersed_args()
+ self._disable_interspersed_args = False
def find_file(self, name):
"""Locate a file located alongside the config files.
@@ -1272,7 +1362,7 @@ class ConfigOpts(collections.Mapping):
def _substitute(self, value):
"""Perform string template substitution.
- Substititue any template variables (e.g. $foo, ${bar}) in the supplied
+ Substitute any template variables (e.g. $foo, ${bar}) in the supplied
string value(s) with opt values.
:param value: the string value, or list of string values
@@ -1329,11 +1419,17 @@ class ConfigOpts(collections.Mapping):
return opts[opt_name]
- def _parse_config_files(self, config_files):
- """Parse the supplied configuration files.
+ def _parse_config_files(self):
+ """Parse the config files from --config-file and --config-dir.
:raises: ConfigFilesNotFoundError, ConfigFileParseError
"""
+ config_files = list(self.config_file)
+
+ if self.config_dir:
+ config_dir_glob = os.path.join(self.config_dir, '*.conf')
+ config_files += sorted(glob.glob(config_dir_glob))
+
self._cparser = MultiConfigParser()
try:
@@ -1345,8 +1441,12 @@ class ConfigOpts(collections.Mapping):
not_read_ok = filter(lambda f: f not in read_ok, config_files)
raise ConfigFilesNotFoundError(not_read_ok)
- def _do_check_required_opts(self, opts, group=None):
- for info in opts.values():
+ def _check_required_opts(self):
+ """Check that all opts marked as required have values specified.
+
+ :raises: RequiredOptError
+ """
+ for info, group in self._all_opt_infos():
default, opt, override = [info[k] for k in sorted(info.keys())]
if opt.required:
@@ -1356,15 +1456,25 @@ class ConfigOpts(collections.Mapping):
if self._get(opt.name, group) is None:
raise RequiredOptError(opt.name, group)
- def _check_required_opts(self):
- """Check that all opts marked as required have values specified.
+ def _parse_cli_opts(self, args):
+ """Parse command line options.
+
+ Initializes the command line option parser and parses the supplied
+ command line arguments.
+
+ :param args: the command line arguments
+ :returns: a dict of parsed option values
+ :raises: SystemExit, DuplicateOptError
- :raises: RequiredOptError
"""
- self._do_check_required_opts(self._opts)
+ self._args = args
- for group in self._groups.values():
- self._do_check_required_opts(group._opts, group)
+ for opt, group in self._all_opts():
+ opt._add_to_cli(self._oparser, group)
+
+ values, leftovers = self._oparser.parse_args(args)
+
+ return vars(values), leftovers
class GroupAttr(collections.Mapping):
@@ -1480,7 +1590,10 @@ class CommonConfigOpts(ConfigOpts):
help='syslog facility to receive log lines')
]
- def __init__(self, **kwargs):
- super(CommonConfigOpts, self).__init__(**kwargs)
+ def __init__(self):
+ super(CommonConfigOpts, self).__init__()
self.register_cli_opts(self.common_cli_opts)
self.register_cli_opts(self.logging_cli_opts)
+
+
+CONF = CommonConfigOpts()
diff --git a/quantum/plugins/cisco/common/cisco_credentials.py b/quantum/plugins/cisco/common/cisco_credentials.py
index 7c6302ae62..0e5eb0d3db 100644
--- a/quantum/plugins/cisco/common/cisco_credentials.py
+++ b/quantum/plugins/cisco/common/cisco_credentials.py
@@ -18,7 +18,7 @@
import logging as LOG
-from quantum.common.config import find_config_file
+from quantum.common.utils import find_config_file
from quantum.plugins.cisco.common import cisco_configparser as confp
from quantum.plugins.cisco.common import cisco_constants as const
from quantum.plugins.cisco.common import cisco_exceptions as cexc
@@ -28,7 +28,7 @@ from quantum.plugins.cisco.db import l2network_db as cdb
LOG.basicConfig(level=LOG.WARN)
LOG.getLogger(const.LOGGER_COMPONENT_NAME)
-CREDENTIALS_FILE = find_config_file({'plugin': 'cisco'}, None,
+CREDENTIALS_FILE = find_config_file({'plugin': 'cisco'},
"credentials.ini")
TENANT = const.NETWORK_ADMIN
diff --git a/quantum/plugins/cisco/l2network_plugin_configuration.py b/quantum/plugins/cisco/l2network_plugin_configuration.py
index 59196156c1..fdd4191bc5 100644
--- a/quantum/plugins/cisco/l2network_plugin_configuration.py
+++ b/quantum/plugins/cisco/l2network_plugin_configuration.py
@@ -17,11 +17,11 @@
# @author: Sumit Naiksatam, Cisco Systems, Inc.
# @author: Rohit Agarwalla, Cisco Systems, Inc.
-from quantum.common.config import find_config_file
+from quantum.common.utils import find_config_file
from quantum.plugins.cisco.common import cisco_configparser as confp
-CONF_FILE = find_config_file({'plugin': 'cisco'}, None, "l2network_plugin.ini")
+CONF_FILE = find_config_file({'plugin': 'cisco'}, "l2network_plugin.ini")
CONF_PARSER_OBJ = confp.CiscoConfigParser(CONF_FILE)
@@ -43,7 +43,7 @@ MAX_NETWORKS = SECTION_CONF['max_networks']
SECTION_CONF = CONF_PARSER_OBJ['MODEL']
MODEL_CLASS = SECTION_CONF['model_class']
-CONF_FILE = find_config_file({'plugin': 'cisco'}, None, "cisco_plugins.ini")
+CONF_FILE = find_config_file({'plugin': 'cisco'}, "cisco_plugins.ini")
SECTION_CONF = CONF_PARSER_OBJ['SEGMENTATION']
MANAGER_CLASS = SECTION_CONF['manager_class']
@@ -55,7 +55,7 @@ CONF_PARSER_OBJ = confp.CiscoConfigParser(CONF_FILE)
# Read the config for the device plugins
PLUGINS = CONF_PARSER_OBJ.walk(CONF_PARSER_OBJ.dummy)
-CONF_FILE = find_config_file({'plugin': 'cisco'}, None, "db_conn.ini")
+CONF_FILE = find_config_file({'plugin': 'cisco'}, "db_conn.ini")
CONF_PARSER_OBJ = confp.CiscoConfigParser(CONF_FILE)
diff --git a/quantum/plugins/cisco/nexus/cisco_nexus_configuration.py b/quantum/plugins/cisco/nexus/cisco_nexus_configuration.py
index 449924ed2f..790a351ab0 100644
--- a/quantum/plugins/cisco/nexus/cisco_nexus_configuration.py
+++ b/quantum/plugins/cisco/nexus/cisco_nexus_configuration.py
@@ -23,11 +23,11 @@ This module will export the configuration parameters
from the nexus.ini file
"""
-from quantum.common.config import find_config_file
+from quantum.common.utils import find_config_file
from quantum.plugins.cisco.common import cisco_configparser as confp
-CP = confp.CiscoConfigParser(find_config_file({'plugin': 'cisco'}, None,
+CP = confp.CiscoConfigParser(find_config_file({'plugin': 'cisco'},
"nexus.ini"))
SECTION = CP['SWITCH']
diff --git a/quantum/plugins/cisco/tests/unit/test_cisco_extension.py b/quantum/plugins/cisco/tests/unit/test_cisco_extension.py
index f0d92496f7..94c2c7788a 100644
--- a/quantum/plugins/cisco/tests/unit/test_cisco_extension.py
+++ b/quantum/plugins/cisco/tests/unit/test_cisco_extension.py
@@ -52,7 +52,7 @@ from quantum import wsgi
LOG = logging.getLogger('quantum.plugins.cisco.tests.test_cisco_extensions')
-TEST_CONF_FILE = config.find_config_file({'plugin': 'cisco'}, None,
+TEST_CONF_FILE = config.find_config_file({'plugin': 'cisco'},
'quantum.conf.ciscoext')
EXTENSIONS_PATH = os.path.join(os.path.dirname(__file__), os.pardir, os.pardir,
os.pardir, os.pardir, "extensions")
@@ -1256,8 +1256,8 @@ def setup_extensions_middleware(extension_manager=None):
PluginAwareExtensionManager(EXTENSIONS_PATH,
L2Network()))
options = {'config_file': TEST_CONF_FILE}
- conf, app = config.load_paste_app('extensions_test_app', options, None)
- return ExtensionMiddleware(app, conf, ext_mgr=extension_manager)
+ app = config.load_paste_app('extensions_test_app', options, None)
+ return ExtensionMiddleware(app, ext_mgr=extension_manager)
def setup_extensions_test_app(extension_manager=None):
diff --git a/quantum/plugins/cisco/ucs/cisco_ucs_configuration.py b/quantum/plugins/cisco/ucs/cisco_ucs_configuration.py
index b065ddfc2a..ff512c7741 100644
--- a/quantum/plugins/cisco/ucs/cisco_ucs_configuration.py
+++ b/quantum/plugins/cisco/ucs/cisco_ucs_configuration.py
@@ -17,11 +17,11 @@
# @author: Sumit Naiksatam, Cisco Systems, Inc.
#
-from quantum.common.config import find_config_file
+from quantum.common.utils import find_config_file
from quantum.plugins.cisco.common import cisco_configparser as confp
-CP = confp.CiscoConfigParser(find_config_file({'plugin': 'cisco'}, [],
+CP = confp.CiscoConfigParser(find_config_file({'plugin': 'cisco'},
'ucs.ini'))
SECTION = CP['UCSM']
@@ -34,7 +34,7 @@ PROFILE_NAME_PREFIX = SECTION['profile_name_prefix']
SECTION = CP['DRIVER']
UCSM_DRIVER = SECTION['name']
-CP = confp.CiscoConfigParser(find_config_file({'plugin': 'cisco'}, [],
+CP = confp.CiscoConfigParser(find_config_file({'plugin': 'cisco'},
'ucs_inventory.ini'))
INVENTORY = CP.walk(CP.dummy)
diff --git a/quantum/plugins/cisco/ucs/cisco_ucs_inventory_configuration.py b/quantum/plugins/cisco/ucs/cisco_ucs_inventory_configuration.py
index e8474f6728..8166233521 100644
--- a/quantum/plugins/cisco/ucs/cisco_ucs_inventory_configuration.py
+++ b/quantum/plugins/cisco/ucs/cisco_ucs_inventory_configuration.py
@@ -17,11 +17,11 @@
# @author: Sumit Naiksatam, Cisco Systems, Inc.
#
-from quantum.common.config import find_config_file
+from quantum.common.utils import find_config_file
from quantum.plugins.cisco.common import cisco_configparser as confp
-CONF_FILE = find_config_file({'plugin': 'cisco'}, None, "ucs_inventory.ini")
+CONF_FILE = find_config_file({'plugin': 'cisco'}, "ucs_inventory.ini")
CP = confp.CiscoConfigParser(CONF_FILE)
INVENTORY = CP.walk(CP.dummy)
diff --git a/quantum/plugins/linuxbridge/common/config.py b/quantum/plugins/linuxbridge/common/config.py
index c4f51f7bc0..85cc907bc1 100644
--- a/quantum/plugins/linuxbridge/common/config.py
+++ b/quantum/plugins/linuxbridge/common/config.py
@@ -41,8 +41,8 @@ agent_opts = [
def parse(config_file):
- conf = cfg.ConfigOpts(default_config_files=[config_file])
- conf(args=[])
+ conf = cfg.ConfigOpts()
+ conf(args=[], default_config_files=[config_file])
conf.register_opts(vlan_opts, "VLANS")
conf.register_opts(database_opts, "DATABASE")
conf.register_opts(bridge_opts, "LINUX_BRIDGE")
diff --git a/quantum/plugins/linuxbridge/db/l2network_db.py b/quantum/plugins/linuxbridge/db/l2network_db.py
index effb268feb..8160142a73 100644
--- a/quantum/plugins/linuxbridge/db/l2network_db.py
+++ b/quantum/plugins/linuxbridge/db/l2network_db.py
@@ -21,14 +21,14 @@ from sqlalchemy import func
from sqlalchemy.orm import exc
from quantum.common import exceptions as q_exc
-from quantum.common.config import find_config_file
+from quantum.common.utils import find_config_file
import quantum.db.api as db
from quantum.plugins.linuxbridge.common import exceptions as c_exc
from quantum.plugins.linuxbridge.db import l2network_models
from quantum.plugins.linuxbridge.common import config
LOG = logging.getLogger(__name__)
-CONF_FILE = find_config_file({'plugin': 'linuxbridge'}, None,
+CONF_FILE = find_config_file({'plugin': 'linuxbridge'},
"linuxbridge_conf.ini")
CONF = config.parse(CONF_FILE)
diff --git a/quantum/plugins/openvswitch/common/config.py b/quantum/plugins/openvswitch/common/config.py
index 16ff7d9cf6..c0f7680f63 100644
--- a/quantum/plugins/openvswitch/common/config.py
+++ b/quantum/plugins/openvswitch/common/config.py
@@ -38,8 +38,8 @@ agent_opts = [
def parse(config_file):
- conf = cfg.ConfigOpts(default_config_files=[config_file])
- conf(args=[])
+ conf = cfg.ConfigOpts()
+ conf(args=[], default_config_files=[config_file])
conf.register_opts(database_opts, "DATABASE")
conf.register_opts(ovs_opts, "OVS")
conf.register_opts(agent_opts, "AGENT")
diff --git a/quantum/plugins/openvswitch/ovs_quantum_plugin.py b/quantum/plugins/openvswitch/ovs_quantum_plugin.py
index 059451af4e..572a0c8fcd 100644
--- a/quantum/plugins/openvswitch/ovs_quantum_plugin.py
+++ b/quantum/plugins/openvswitch/ovs_quantum_plugin.py
@@ -23,7 +23,7 @@ import os
from quantum.api.api_common import OperationalStatus
from quantum.common import exceptions as q_exc
-from quantum.common.config import find_config_file
+from quantum.common.utils import find_config_file
import quantum.db.api as db
from quantum.plugins.openvswitch import ovs_db
from quantum.plugins.openvswitch.common import config
@@ -33,7 +33,7 @@ LOG = logging.getLogger("ovs_quantum_plugin")
CONF_FILE = find_config_file({"plugin": "openvswitch"},
- None, "ovs_quantum_plugin.ini")
+ "ovs_quantum_plugin.ini")
# Exception thrown if no more VLANs are available
diff --git a/quantum/plugins/ryu/agent/ryu_quantum_agent.py b/quantum/plugins/ryu/agent/ryu_quantum_agent.py
index 3fa8b507c7..74513e1894 100755
--- a/quantum/plugins/ryu/agent/ryu_quantum_agent.py
+++ b/quantum/plugins/ryu/agent/ryu_quantum_agent.py
@@ -20,7 +20,6 @@
# under the License.
# @author: Isaku Yamahata
-import ConfigParser
import logging as LOG
from optparse import OptionParser
import shlex
@@ -34,6 +33,7 @@ from ryu.app.client import OFPClient
from sqlalchemy.ext.sqlsoup import SqlSoup
from quantum.agent.linux import utils
+from quantum.plugins.ryu.common import config
OP_STATUS_UP = "UP"
OP_STATUS_DOWN = "DOWN"
@@ -286,18 +286,10 @@ def main():
sys.exit(1)
config_file = args[0]
- config = ConfigParser.ConfigParser()
- try:
- config.read(config_file)
- except Exception, e:
- LOG.error("Unable to parse config file \"%s\": %s",
- config_file, str(e))
-
- integ_br = config.get("OVS", "integration-bridge")
-
- root_helper = config.get("AGENT", "root_helper")
-
- options = {"sql_connection": config.get("DATABASE", "sql_connection")}
+ conf = config.parse(config_file)
+ integ_br = conf.OVS.integration_bridge
+ root_helper = conf.AGENT.root_helper
+ options = {"sql_connection": conf.DATABASE.sql_connection}
db = SqlSoup(options["sql_connection"])
LOG.info("Connecting to database \"%s\" on %s",
diff --git a/quantum/plugins/ryu/common/__init__.py b/quantum/plugins/ryu/common/__init__.py
new file mode 100644
index 0000000000..e5f41adfee
--- /dev/null
+++ b/quantum/plugins/ryu/common/__init__.py
@@ -0,0 +1,15 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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.
diff --git a/quantum/plugins/ryu/common/config.py b/quantum/plugins/ryu/common/config.py
new file mode 100644
index 0000000000..871ef54e37
--- /dev/null
+++ b/quantum/plugins/ryu/common/config.py
@@ -0,0 +1,43 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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 quantum.openstack.common import cfg
+
+
+database_opts = [
+ cfg.StrOpt('sql_connection', default='sqlite://'),
+ cfg.IntOpt('reconnect_interval', default=2),
+]
+
+ovs_opts = [
+ cfg.StrOpt('integration_bridge', default='br-int'),
+ cfg.StrOpt('openflow_controller', default='127.0.0.1:6633'),
+ cfg.StrOpt('openflow_rest_api', default='127.0.0.1:8080'),
+]
+
+agent_opts = [
+ cfg.IntOpt('polling_interval', default=2),
+ cfg.StrOpt('root_helper', default='sudo'),
+]
+
+
+def parse(config_file):
+ conf = cfg.ConfigOpts()
+ conf(args=[], default_config_files=[config_file])
+ conf.register_opts(database_opts, "DATABASE")
+ conf.register_opts(ovs_opts, "OVS")
+ conf.register_opts(agent_opts, "AGENT")
+ return conf
diff --git a/quantum/plugins/ryu/ovs_quantum_plugin_base.py b/quantum/plugins/ryu/ovs_quantum_plugin_base.py
index 91841928fa..fd9a5dfde0 100644
--- a/quantum/plugins/ryu/ovs_quantum_plugin_base.py
+++ b/quantum/plugins/ryu/ovs_quantum_plugin_base.py
@@ -16,15 +16,14 @@
# under the License.
# @author: Isaku Yamahata
-import ConfigParser
from abc import ABCMeta, abstractmethod
import logging as LOG
import os
from quantum.api.api_common import OperationalStatus
from quantum.common import exceptions as q_exc
+from quantum.plugins.ryu.common import config
import quantum.db.api as db
-from quantum.manager import find_config
from quantum.quantum_plugin_base import QuantumPluginBase
@@ -55,24 +54,23 @@ class OVSQuantumPluginBase(QuantumPluginBase):
"""
def __init__(self, conf_file, mod_file, configfile=None):
super(OVSQuantumPluginBase, self).__init__()
- config = ConfigParser.ConfigParser()
if configfile is None:
- if conf_file and os.path.exists(conf_file):
+ if os.path.exists(conf_file):
configfile = conf_file
else:
- configfile = (
- find_config(os.path.abspath(os.path.dirname(mod_file))))
+ configfile = find_config(os.path.abspath(
+ os.path.dirname(__file__)))
if configfile is None:
raise Exception("Configuration file \"%s\" doesn't exist" %
(configfile))
- LOG.debug("Using configuration file: %s", configfile)
- config.read(configfile)
- LOG.debug("Config: %s", config)
-
- options = {"sql_connection": config.get("DATABASE", "sql_connection")}
+ LOG.debug("Using configuration file: %s" % configfile)
+ conf = config.parse(configfile)
+ options = {"sql_connection": conf.DATABASE.sql_connection}
+ reconnect_interval = conf.DATABASE.reconnect_interval
+ options.update({"reconnect_interval": reconnect_interval})
db.configure_db(options)
- self.config = config
+ self.conf = conf
# Subclass must set self.driver to its own OVSQuantumPluginDriverBase
self.driver = None
diff --git a/quantum/plugins/ryu/ryu_quantum_plugin.py b/quantum/plugins/ryu/ryu_quantum_plugin.py
index a08fb591ee..c6af60f3b4 100644
--- a/quantum/plugins/ryu/ryu_quantum_plugin.py
+++ b/quantum/plugins/ryu/ryu_quantum_plugin.py
@@ -19,7 +19,7 @@
from ryu.app import client
from ryu.app import rest_nw_id
-from quantum.common.config import find_config_file
+from quantum.common.utils import find_config_file
from quantum.common import exceptions as q_exc
import quantum.db.api as db
from quantum.plugins.ryu import ofp_service_type
@@ -27,14 +27,14 @@ from quantum.plugins.ryu import ovs_quantum_plugin_base
from quantum.plugins.ryu.db import api as db_api
-CONF_FILE = find_config_file({"plugin": "ryu"}, None, "ryu.ini")
+CONF_FILE = find_config_file({"plugin": "ryu"}, "ryu.ini")
class OFPRyuDriver(ovs_quantum_plugin_base.OVSQuantumPluginDriverBase):
- def __init__(self, config):
+ def __init__(self, conf):
super(OFPRyuDriver, self).__init__()
- ofp_con_host = config.get("OVS", "openflow-controller")
- ofp_api_host = config.get("OVS", "openflow-rest-api")
+ ofp_con_host = conf.OVS.openflow_controller
+ ofp_api_host = conf.OVS.openflow_rest_api
if ofp_con_host is None or ofp_api_host is None:
raise q_exc.Invalid("invalid configuration. check ryu.ini")
@@ -64,4 +64,4 @@ class OFPRyuDriver(ovs_quantum_plugin_base.OVSQuantumPluginDriverBase):
class RyuQuantumPlugin(ovs_quantum_plugin_base.OVSQuantumPluginBase):
def __init__(self, configfile=None):
super(RyuQuantumPlugin, self).__init__(CONF_FILE, __file__, configfile)
- self.driver = OFPRyuDriver(self.config)
+ self.driver = OFPRyuDriver(self.conf)
diff --git a/quantum/plugins/ryu/tests/unit/fake_plugin.py b/quantum/plugins/ryu/tests/unit/fake_plugin.py
index 55c4853ed2..3d521b4f77 100644
--- a/quantum/plugins/ryu/tests/unit/fake_plugin.py
+++ b/quantum/plugins/ryu/tests/unit/fake_plugin.py
@@ -21,6 +21,8 @@ from quantum.plugins.ryu import ovs_quantum_plugin_base
class FakePluginDriver(ovs_quantum_plugin_base.OVSQuantumPluginDriverBase):
def __init__(self, config):
super(FakePluginDriver, self).__init__()
+ conf = config.parse(config)
+ self.conf = conf
def create_network(self, net):
pass
@@ -32,4 +34,4 @@ class FakePluginDriver(ovs_quantum_plugin_base.OVSQuantumPluginDriverBase):
class FakePlugin(ovs_quantum_plugin_base.OVSQuantumPluginBase):
def __init__(self, configfile=None):
super(FakePlugin, self).__init__(None, __file__, configfile)
- self.driver = FakePluginDriver(self.config)
+ self.driver = FakePluginDriver(self.conf)
diff --git a/quantum/plugins/ryu/tests/unit/test_ryu_driver.py b/quantum/plugins/ryu/tests/unit/test_ryu_driver.py
index ad113e74be..c3a10a308c 100644
--- a/quantum/plugins/ryu/tests/unit/test_ryu_driver.py
+++ b/quantum/plugins/ryu/tests/unit/test_ryu_driver.py
@@ -18,16 +18,21 @@
import uuid
import quantum.db.api as db
+from quantum.common.utils import find_config_file
+from quantum.plugins.ryu.common import config
from quantum.plugins.ryu.tests.unit.basetest import BaseRyuTest
from quantum.plugins.ryu.tests.unit import utils
from quantum.plugins.ryu.tests.unit.utils import patch_fake_ryu_client
+CONF_FILE = find_config_file({"plugin": "ryu"}, "ryu.ini")
+
+
class RyuDriverTest(BaseRyuTest):
"""Class conisting of OFPRyuDriver unit tests"""
def setUp(self):
super(RyuDriverTest, self).setUp()
-
+ self.conf = config.parse(CONF_FILE)
# fake up ryu.app.client and ryu.app.rest_nw_id
# With those, plugin can be tested without ryu installed
self.module_patcher = patch_fake_ryu_client()
@@ -65,7 +70,7 @@ class RyuDriverTest(BaseRyuTest):
db.network_create('test', uuid0)
from quantum.plugins.ryu import ryu_quantum_plugin
- ryu_driver = ryu_quantum_plugin.OFPRyuDriver(self.config)
+ ryu_driver = ryu_quantum_plugin.OFPRyuDriver(self.conf)
ryu_driver.create_network(net1)
ryu_driver.delete_network(net1)
self.mox.VerifyAll()
diff --git a/quantum/policy.py b/quantum/policy.py
index cc656456f0..702d1cc512 100644
--- a/quantum/policy.py
+++ b/quantum/policy.py
@@ -21,7 +21,7 @@ Policy engine for quantum. Largely copied from nova.
import os.path
-from quantum.common import config
+from quantum.common.utils import find_config_file
from quantum.common import exceptions
from quantum.openstack.common import policy
@@ -38,7 +38,7 @@ def reset():
def init():
global _POLICY_PATH
if not _POLICY_PATH:
- _POLICY_PATH = config.find_config_file({}, [], 'policy.json')
+ _POLICY_PATH = find_config_file({}, 'policy.json')
if not _POLICY_PATH:
raise exceptions.PolicyNotFound(path=FLAGS.policy_file)
with open(_POLICY_PATH) as f:
diff --git a/quantum/server/__init__.py b/quantum/server/__init__.py
index c8820c1a99..2388944e39 100755
--- a/quantum/server/__init__.py
+++ b/quantum/server/__init__.py
@@ -25,28 +25,19 @@ import sys
from quantum import service
from quantum.common import config
+from quantum.openstack.common import cfg
from quantum.version import version_string
-def create_options(parser):
- """
- Sets up the CLI and config-file options that may be
- parsed and program commands.
- :param parser: The option parser
- """
- config.add_common_options(parser)
- config.add_log_options(parser)
-
-
def main():
- oparser = optparse.OptionParser(version='%prog ' + version_string())
- create_options(oparser)
- (options, args) = config.parse_options(oparser)
-
+ # the configuration will be read into the cfg.CONF global data structure
+ config.parse(sys.argv)
+ if not cfg.CONF.config_file:
+ sys.exit("ERROR: Unable to find configuration file via the default"
+ " search paths (~/.quantum/, ~/, /etc/quantum/, /etc/) and"
+ " the '--config-file' option!")
try:
- quantum_service = service.serve_wsgi(service.QuantumApiService,
- options=options,
- args=args)
+ quantum_service = service.serve_wsgi(service.QuantumApiService)
quantum_service.wait()
except RuntimeError, e:
sys.exit("ERROR: %s" % e)
diff --git a/quantum/service.py b/quantum/service.py
index ea2855c6c7..d6432ac15f 100644
--- a/quantum/service.py
+++ b/quantum/service.py
@@ -18,7 +18,7 @@
import logging
from quantum.common import config
-from quantum.common import exceptions as exception
+from quantum.openstack.common import cfg
from quantum import wsgi
@@ -34,14 +34,12 @@ class WsgiService(object):
"""
- def __init__(self, app_name, conf_file, conf):
+ def __init__(self, app_name):
self.app_name = app_name
- self.conf_file = conf_file
- self.conf = conf
self.wsgi_app = None
def start(self):
- self.wsgi_app = _run_wsgi(self.app_name, self.conf, self.conf_file)
+ self.wsgi_app = _run_wsgi(self.app_name)
def wait(self):
self.wsgi_app.wait()
@@ -51,13 +49,8 @@ class QuantumApiService(WsgiService):
"""Class for quantum-api service."""
@classmethod
- def create(cls, conf=None, options=None, args=None):
+ def create(cls):
app_name = "quantum"
- if not conf:
- conf_file, conf = config.load_paste_config(app_name, options, args)
- if not conf:
- message = (_('No paste configuration found for: %s'), app_name)
- raise exception.Error(message)
# Setup logging early, supplying both the CLI options and the
# configuration mapping from the config file
@@ -65,32 +58,24 @@ class QuantumApiService(WsgiService):
# flags. Everything else must be set up in the conf file...
# Log the options used when starting if we're in debug mode...
- config.setup_logging(options, conf)
- debug = (options.get('debug') or
- config.get_option(conf, 'debug', type='bool', default=False))
- verbose = (options.get('verbose') or
- config.get_option(conf, 'verbose', type='bool',
- default=False))
- conf['debug'] = debug
- conf['verbose'] = verbose
+ config.setup_logging(cfg.CONF)
LOG.debug("*" * 80)
LOG.debug("Configuration options gathered from config file:")
- LOG.debug(conf_file)
LOG.debug("================================================")
- items = dict([(k, v) for k, v in conf.items()
+ items = dict([(k, v) for k, v in cfg.CONF.items()
if k not in ('__file__', 'here')])
for key, value in sorted(items.items()):
LOG.debug("%(key)-30s %(value)s" % {'key': key,
'value': value,
})
LOG.debug("*" * 80)
- service = cls(app_name, conf_file, conf)
+ service = cls(app_name)
return service
-def serve_wsgi(cls, conf=None, options=None, args=None):
+def serve_wsgi(cls):
try:
- service = cls.create(conf, options, args)
+ service = cls.create()
except Exception:
logging.exception('in WsgiService.create()')
raise
@@ -100,15 +85,11 @@ def serve_wsgi(cls, conf=None, options=None, args=None):
return service
-def _run_wsgi(app_name, paste_conf, paste_config_file):
- LOG.info(_('Using paste.deploy config at: %s'), paste_config_file)
- conf, app = config.load_paste_app(app_name,
- {'config_file': paste_config_file},
- None)
+def _run_wsgi(app_name):
+ app = config.load_paste_app(app_name, "quantum.conf")
if not app:
- LOG.error(_('No known API applications configured in %s.'),
- paste_config_file)
+ LOG.error(_('No known API applications configured.'))
return
server = wsgi.Server("Quantum")
- server.start(app, int(paste_conf['bind_port']), paste_conf['bind_host'])
+ server.start(app, cfg.CONF.bind_port, cfg.CONF.bind_host)
return server
diff --git a/etc/quantum.conf.test b/quantum/tests/etc/quantum.conf.test
index 6157d5b028..6157d5b028 100644
--- a/etc/quantum.conf.test
+++ b/quantum/tests/etc/quantum.conf.test
diff --git a/quantum/tests/unit/_test_api.py b/quantum/tests/unit/_test_api.py
index 46f77f2437..08b0ca2f10 100644
--- a/quantum/tests/unit/_test_api.py
+++ b/quantum/tests/unit/_test_api.py
@@ -21,19 +21,30 @@ import logging
import unittest2 as unittest
import mock
+import os
from quantum.api.api_common import APIFaultWrapper
from quantum.api.networks import Controller
from quantum.common.test_lib import test_config
+from quantum.common import config
from quantum.db import api as db
from quantum.openstack.common import importutils
import quantum.tests.unit.testlib_api as testlib
+from quantum.openstack.common import cfg
from quantum.wsgi import XMLDeserializer, JSONDeserializer
LOG = logging.getLogger('quantum.tests.test_api')
+ROOTDIR = os.path.dirname(os.path.dirname(__file__))
+ETCDIR = os.path.join(ROOTDIR, 'etc')
+
+
+def etcdir(*p):
+ return os.path.join(ETCDIR, *p)
+
+
NETS = "networks"
PORTS = "ports"
ATTS = "attachments"
@@ -105,10 +116,13 @@ class AbstractAPITest(unittest.TestCase):
self.assertEqual(put_attachment_res.status_int, expected_res_status)
def setUp(self, api_router_klass, xml_metadata_dict):
- options = {}
- options['plugin_provider'] = test_config['plugin_name']
+ # Create the default configurations
+ args = ['--config-file', etcdir('quantum.conf.test')]
+ config.parse(args=args)
+ # Update the plugin
+ cfg.CONF.set_override('core_plugin', test_config['plugin_name'])
api_router_cls = importutils.import_class(api_router_klass)
- self.api = api_router_cls(options)
+ self.api = api_router_cls()
self.tenant_id = "test_tenant"
self.network_name = "test_network"
@@ -136,6 +150,7 @@ class AbstractAPITest(unittest.TestCase):
"""Clear the test environment"""
# Remove database contents
db.clear_db()
+ cfg.CONF.reset()
class BaseAPIOperationsTest(AbstractAPITest):
diff --git a/quantum/tests/unit/test_api_v2.py b/quantum/tests/unit/test_api_v2.py
index 06e8c4148f..90f1082f6e 100644
--- a/quantum/tests/unit/test_api_v2.py
+++ b/quantum/tests/unit/test_api_v2.py
@@ -12,6 +12,7 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the spec
+import os
import logging
import unittest
import uuid
@@ -26,6 +27,8 @@ from quantum.common import exceptions as q_exc
from quantum.api.v2 import resource as wsgi_resource
from quantum.api.v2 import router
from quantum.api.v2 import views
+from quantum.common import config
+from quantum.openstack.common import cfg
LOG = logging.getLogger(__name__)
@@ -34,6 +37,13 @@ LOG = logging.getLogger(__name__)
def _uuid():
return str(uuid.uuid4())
+ROOTDIR = os.path.dirname(os.path.dirname(__file__))
+ETCDIR = os.path.join(ROOTDIR, 'etc')
+
+
+def etcdir(*p):
+ return os.path.join(ETCDIR, *p)
+
def _get_path(resource, id=None, fmt=None):
path = '/%s' % resource
@@ -123,16 +133,23 @@ class APIv2TestCase(unittest.TestCase):
# will get around this.
def setUp(self):
plugin = 'quantum.quantum_plugin_base_v2.QuantumPluginBaseV2'
+ # Create the default configurations
+ args = ['--config-file', etcdir('quantum.conf.test')]
+ config.parse(args=args)
+ # Update the plugin
+ cfg.CONF.set_override('core_plugin', plugin)
+
self._plugin_patcher = mock.patch(plugin, autospec=True)
self.plugin = self._plugin_patcher.start()
- api = router.APIRouter({'plugin_provider': plugin})
+ api = router.APIRouter()
self.api = webtest.TestApp(api)
def tearDown(self):
self._plugin_patcher.stop()
self.api = None
self.plugin = None
+ cfg.CONF.reset()
def test_verbose_attr(self):
instance = self.plugin.return_value
diff --git a/quantum/tests/unit/test_db_plugin.py b/quantum/tests/unit/test_db_plugin.py
index 46a22f9530..d3e89d1d71 100644
--- a/quantum/tests/unit/test_db_plugin.py
+++ b/quantum/tests/unit/test_db_plugin.py
@@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import os
import logging
import unittest
import contextlib
@@ -22,12 +23,21 @@ import quantum
from quantum.api.v2.router import APIRouter
from quantum.common import exceptions as q_exc
from quantum.db import api as db
+from quantum.common import config
+from quantum.openstack.common import cfg
from quantum.tests.unit.testlib_api import create_request
from quantum.wsgi import Serializer, JSONDeserializer
LOG = logging.getLogger(__name__)
+ROOTDIR = os.path.dirname(os.path.dirname(__file__))
+ETCDIR = os.path.join(ROOTDIR, 'etc')
+
+
+def etcdir(*p):
+ return os.path.join(ETCDIR, *p)
+
class QuantumDbPluginV2TestCase(unittest.TestCase):
def setUp(self):
@@ -46,7 +56,12 @@ class QuantumDbPluginV2TestCase(unittest.TestCase):
}
plugin = 'quantum.db.db_base_plugin_v2.QuantumDbPluginV2'
- self.api = APIRouter({'plugin_provider': plugin})
+ # Create the default configurations
+ args = ['--config-file', etcdir('quantum.conf.test')]
+ config.parse(args=args)
+ # Update the plugin
+ cfg.CONF.set_override('core_plugin', plugin)
+ self.api = APIRouter()
def tearDown(self):
super(QuantumDbPluginV2TestCase, self).tearDown()
@@ -54,6 +69,7 @@ class QuantumDbPluginV2TestCase(unittest.TestCase):
# doesn't like when the plugin changes ;)
db._ENGINE = None
db._MAKER = None
+ cfg.CONF.reset()
def _req(self, method, resource, data=None, fmt='json', id=None):
if id:
diff --git a/quantum/tests/unit/test_extensions.py b/quantum/tests/unit/test_extensions.py
index ecda049ea2..9c64d36cd7 100644
--- a/quantum/tests/unit/test_extensions.py
+++ b/quantum/tests/unit/test_extensions.py
@@ -14,6 +14,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import logging
+import os
import unittest
import routes
@@ -41,8 +43,15 @@ from quantum.tests.unit.extension_stubs import (
import quantum.tests.unit.extensions
from quantum import wsgi
+LOG = logging.getLogger('quantum.tests.test_extensions')
+
+ROOTDIR = os.path.dirname(os.path.dirname(__file__))
+ETCDIR = os.path.join(ROOTDIR, 'etc')
+
+
+def etcdir(*p):
+ return os.path.join(ETCDIR, *p)
-test_conf_file = config.find_config_file({}, None, "quantum.conf.test")
extensions_path = ':'.join(quantum.tests.unit.extensions.__path__)
@@ -455,8 +464,10 @@ def app_factory(global_conf, **local_conf):
def setup_base_app():
- options = {'config_file': test_conf_file}
- conf, app = config.load_paste_app('extensions_test_app', options, None)
+ config_file = 'quantum.conf.test'
+ args = ['--config-file', etcdir(config_file)]
+ config.parse(args=args)
+ app = config.load_paste_app('extensions_test_app', config_file)
return app
@@ -464,9 +475,11 @@ def setup_extensions_middleware(extension_manager=None):
extension_manager = (extension_manager or
PluginAwareExtensionManager(extensions_path,
QuantumEchoPlugin()))
- options = {'config_file': test_conf_file}
- conf, app = config.load_paste_app('extensions_test_app', options, None)
- return ExtensionMiddleware(app, conf, ext_mgr=extension_manager)
+ config_file = 'quantum.conf.test'
+ args = ['--config-file', etcdir(config_file)]
+ config.parse(args=args)
+ app = config.load_paste_app('extensions_test_app', config_file)
+ return ExtensionMiddleware(app, ext_mgr=extension_manager)
def setup_extensions_test_app(extension_manager=None):
diff --git a/setup.py b/setup.py
index fe4f5fafdf..4d28542794 100644
--- a/setup.py
+++ b/setup.py
@@ -51,7 +51,7 @@ ryu_plugin_config_path = 'etc/quantum/plugins/ryu'
DataFiles = [
(config_path,
- ['etc/quantum.conf', 'etc/quantum.conf.test', 'etc/plugins.ini']),
+ ['etc/quantum.conf']),
(init_path, ['etc/init.d/quantum-server']),
(ovs_plugin_config_path,
['etc/quantum/plugins/openvswitch/ovs_quantum_plugin.ini']),