Provide plugins an oslo_config group for their setup
The plugin implementations need to be isolated from the entity that is using os-vif. Plugins should be allowed to define their own custom config parameters, without needing the user of os-vif to pass further options into the os_vif.initialize() method. This change introduces a CONFIG_OPTS attribute on the Plugin class. This provides a list of oslo_config options that are to be used by the plugin. os_vif will register these options into a group 'os_vif_$PLUGIN' eg 'os_vif_linux_bridge'. This gives the plugin impls the ability to have config options in the main project conf (ie /etc/nova/nova.conf) without exposing them directly to all of nova's own config options. Change-Id: I9634b474cd0d3fda09aef5800020c9415c28e3d8
This commit is contained in:
parent
1ff6526c3d
commit
72d5dfbf48
13
README.rst
13
README.rst
@ -14,19 +14,12 @@ Usage
|
|||||||
-----
|
-----
|
||||||
|
|
||||||
The interface to the `os_vif` library is very simple. To begin using the
|
The interface to the `os_vif` library is very simple. To begin using the
|
||||||
library, first call the `os_vif.initialize()` function, supplying a set of
|
library, first call the `os_vif.initialize()` function. This will load
|
||||||
keyword arguments for configuration options::
|
all installed plugins and register the object model::
|
||||||
|
|
||||||
import os_vif
|
import os_vif
|
||||||
|
|
||||||
os_vif.initialize(libvirt_virt_type='kvm',
|
os_vif.initialize()
|
||||||
network_device_mtu=1500,
|
|
||||||
vlan_interface='eth1',
|
|
||||||
use_ipv6=False,
|
|
||||||
iptables_top_regex='',
|
|
||||||
iptables_bottom_regex='',
|
|
||||||
iptables_drop_action='DROP',
|
|
||||||
forward_bridge_interface=['all'])
|
|
||||||
|
|
||||||
Once the `os_vif` library is initialized, there are only two other library
|
Once the `os_vif` library is initialized, there are only two other library
|
||||||
functions: `os_vif.plug()` and `os_vif.unplug()`. Both methods accept a single
|
functions: `os_vif.plug()` and `os_vif.unplug()`. Both methods accept a single
|
||||||
|
@ -24,7 +24,7 @@ _EXT_MANAGER = None
|
|||||||
LOG = logging.getLogger('os_vif')
|
LOG = logging.getLogger('os_vif')
|
||||||
|
|
||||||
|
|
||||||
def initialize(reset=False, **config):
|
def initialize(reset=False):
|
||||||
"""
|
"""
|
||||||
Loads all os_vif plugins and initializes them with a dictionary of
|
Loads all os_vif plugins and initializes them with a dictionary of
|
||||||
configuration options. These configuration options are passed as-is
|
configuration options. These configuration options are passed as-is
|
||||||
@ -32,38 +32,16 @@ def initialize(reset=False, **config):
|
|||||||
|
|
||||||
:param reset: Recreate and load the VIF plugin extensions.
|
:param reset: Recreate and load the VIF plugin extensions.
|
||||||
|
|
||||||
The following configuration options are currently known to be
|
|
||||||
used by the VIF plugins, however this list may change and you
|
|
||||||
should check the documentation of individual plugins for a complete
|
|
||||||
list of configuration options that the plugin understands or uses.
|
|
||||||
|
|
||||||
:param **config: Configuration option dictionary.
|
|
||||||
|
|
||||||
`use_ipv6`: Default: False. For plugins that configure IPv6 iptables
|
|
||||||
rules or functionality, set this option to True if you want
|
|
||||||
to support IPv6.
|
|
||||||
`disable_rootwrap`: Default: False. Set to True to force plugins to use
|
|
||||||
sudoers files instead of any `oslo.rootwrap` functionality.
|
|
||||||
`use_rootwrap_daemon`: Default: False. Set to True to use the optional
|
|
||||||
`oslo.rootwrap` daemon for better performance of root-run
|
|
||||||
commands.
|
|
||||||
`rootwrap_config`: Default: /etc/nova/rootwrap.conf. Path to the
|
|
||||||
rootwrap configuration file.
|
|
||||||
`iptables_top_regex`: Default: ''. Override top filters in iptables
|
|
||||||
rules construction.
|
|
||||||
`iptables_bottom_regex`: Default: ''. Override bottom filters in
|
|
||||||
iptables rules construction.
|
|
||||||
`iptables_drop_action`: Default: DROP. Override the name of the drop
|
|
||||||
action in iptables rules.
|
|
||||||
`forward_bridge_interface`: Default: ['all'].
|
|
||||||
`network_device_mtu`: Default: 1500. Override the MTU of network
|
|
||||||
devices created by a VIF plugin.
|
|
||||||
"""
|
"""
|
||||||
global _EXT_MANAGER
|
global _EXT_MANAGER
|
||||||
if reset or (_EXT_MANAGER is None):
|
if reset or (_EXT_MANAGER is None):
|
||||||
_EXT_MANAGER = extension.ExtensionManager(namespace='os_vif',
|
_EXT_MANAGER = extension.ExtensionManager(namespace='os_vif',
|
||||||
invoke_on_load=True,
|
invoke_on_load=False)
|
||||||
invoke_args=config)
|
for plugin_name in _EXT_MANAGER.keys():
|
||||||
|
cls = _EXT_MANAGER[plugin_name].plugin
|
||||||
|
obj = cls.load(plugin_name)
|
||||||
|
_EXT_MANAGER[plugin_name].obj = obj
|
||||||
|
|
||||||
os_vif.objects.register_all()
|
os_vif.objects.register_all()
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,10 +11,13 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import abc
|
import abc
|
||||||
|
from oslo_config import cfg
|
||||||
import six
|
import six
|
||||||
|
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
class PluginVIFInfo(object):
|
class PluginVIFInfo(object):
|
||||||
"""
|
"""
|
||||||
Class describing the plugin and the versions of VIF object it understands.
|
Class describing the plugin and the versions of VIF object it understands.
|
||||||
@ -54,10 +57,15 @@ class PluginInfo(object):
|
|||||||
class PluginBase(object):
|
class PluginBase(object):
|
||||||
"""Base class for all VIF plugins."""
|
"""Base class for all VIF plugins."""
|
||||||
|
|
||||||
def __init__(self, **config):
|
# Override to provide a tuple of oslo_config.Opt instances for
|
||||||
|
# the plugin config parameters
|
||||||
|
CONFIG_OPTS = ()
|
||||||
|
|
||||||
|
def __init__(self, config):
|
||||||
"""
|
"""
|
||||||
Sets up the plugin using supplied kwargs representing configuration
|
Initialize the plugin object with the provided config
|
||||||
options.
|
|
||||||
|
:param config: `oslo_config.ConfigOpts.GroupAttr` instance:
|
||||||
"""
|
"""
|
||||||
self.config = config
|
self.config = config
|
||||||
|
|
||||||
@ -93,3 +101,24 @@ class PluginBase(object):
|
|||||||
this method should let `processutils.ProcessExecutionError`
|
this method should let `processutils.ProcessExecutionError`
|
||||||
bubble up.
|
bubble up.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def load(cls, plugin_name):
|
||||||
|
"""
|
||||||
|
Load a plugin, registering its configuration options
|
||||||
|
|
||||||
|
:param plugin_name: the name of the plugin extension
|
||||||
|
|
||||||
|
:returns: an initialized instance of the class
|
||||||
|
"""
|
||||||
|
cfg_group_name = "os_vif_" + plugin_name
|
||||||
|
cfg_opts = getattr(cls, "CONFIG_OPTS")
|
||||||
|
cfg_vals = None
|
||||||
|
if cfg_opts and len(cfg_opts) > 0:
|
||||||
|
cfg_group = cfg.OptGroup(
|
||||||
|
cfg_group_name,
|
||||||
|
"os-vif plugin %s options" % plugin_name)
|
||||||
|
CONF.register_opts(cfg_opts, group=cfg_group)
|
||||||
|
|
||||||
|
cfg_vals = getattr(CONF, cfg_group_name)
|
||||||
|
return cls(cfg_vals)
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
from oslo_config import cfg
|
||||||
from stevedore import extension
|
from stevedore import extension
|
||||||
|
|
||||||
import os_vif
|
import os_vif
|
||||||
@ -22,13 +23,34 @@ from os_vif.tests import base
|
|||||||
|
|
||||||
class DemoPlugin(plugin.PluginBase):
|
class DemoPlugin(plugin.PluginBase):
|
||||||
|
|
||||||
|
CONFIG_OPTS = (
|
||||||
|
cfg.BoolOpt("make_it_work",
|
||||||
|
default=False,
|
||||||
|
help="Make everything work correctly by setting this"),
|
||||||
|
cfg.IntOpt("sleep_time",
|
||||||
|
default=0,
|
||||||
|
help="How long to artifically sleep")
|
||||||
|
)
|
||||||
|
|
||||||
def describe(self):
|
def describe(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def plug(self, vif, instance_info):
|
def plug(self, vif, instance_info, config):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def unplug(self, vif, instance_info):
|
def unplug(self, vif, instance_info, config):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class DemoPluginNoConfig(plugin.PluginBase):
|
||||||
|
|
||||||
|
def describe(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def plug(self, vif, instance_info, config):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def unplug(self, vif, instance_info, config):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@ -46,9 +68,25 @@ class TestOSVIF(base.TestCase):
|
|||||||
os_vif.initialize()
|
os_vif.initialize()
|
||||||
os_vif.initialize()
|
os_vif.initialize()
|
||||||
mock_EM.assert_called_once_with(
|
mock_EM.assert_called_once_with(
|
||||||
invoke_args={}, invoke_on_load=True, namespace='os_vif')
|
invoke_on_load=False, namespace='os_vif')
|
||||||
self.assertIsNotNone(os_vif._EXT_MANAGER)
|
self.assertIsNotNone(os_vif._EXT_MANAGER)
|
||||||
|
|
||||||
|
def test_load_plugin(self):
|
||||||
|
obj = DemoPlugin.load("demo")
|
||||||
|
self.assertTrue(hasattr(cfg.CONF, "os_vif_demo"))
|
||||||
|
self.assertTrue(hasattr(cfg.CONF.os_vif_demo, "make_it_work"))
|
||||||
|
self.assertTrue(hasattr(cfg.CONF.os_vif_demo, "sleep_time"))
|
||||||
|
self.assertEqual(cfg.CONF.os_vif_demo.make_it_work, False)
|
||||||
|
self.assertEqual(cfg.CONF.os_vif_demo.sleep_time, 0)
|
||||||
|
|
||||||
|
self.assertEqual(obj.config, cfg.CONF.os_vif_demo)
|
||||||
|
|
||||||
|
def test_load_plugin_no_config(self):
|
||||||
|
obj = DemoPluginNoConfig.load("demonocfg")
|
||||||
|
self.assertFalse(hasattr(cfg.CONF, "os_vif_demonocfg"))
|
||||||
|
|
||||||
|
self.assertIsNone(obj.config)
|
||||||
|
|
||||||
def test_plug_not_initialized(self):
|
def test_plug_not_initialized(self):
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.LibraryNotInitialized,
|
exception.LibraryNotInitialized,
|
||||||
@ -63,8 +101,8 @@ class TestOSVIF(base.TestCase):
|
|||||||
def test_plug(self, mock_plug):
|
def test_plug(self, mock_plug):
|
||||||
plg = extension.Extension(name="demo",
|
plg = extension.Extension(name="demo",
|
||||||
entry_point="os-vif",
|
entry_point="os-vif",
|
||||||
plugin="DemoPlugin",
|
plugin=DemoPlugin,
|
||||||
obj=DemoPlugin())
|
obj=None)
|
||||||
with mock.patch('stevedore.extension.ExtensionManager',
|
with mock.patch('stevedore.extension.ExtensionManager',
|
||||||
return_value={'foobar': plg}):
|
return_value={'foobar': plg}):
|
||||||
os_vif.initialize()
|
os_vif.initialize()
|
||||||
@ -78,8 +116,8 @@ class TestOSVIF(base.TestCase):
|
|||||||
def test_unplug(self, mock_unplug):
|
def test_unplug(self, mock_unplug):
|
||||||
plg = extension.Extension(name="demo",
|
plg = extension.Extension(name="demo",
|
||||||
entry_point="os-vif",
|
entry_point="os-vif",
|
||||||
plugin="DemoPlugin",
|
plugin=DemoPlugin,
|
||||||
obj=DemoPlugin())
|
obj=None)
|
||||||
with mock.patch('stevedore.extension.ExtensionManager',
|
with mock.patch('stevedore.extension.ExtensionManager',
|
||||||
return_value={'foobar': plg}):
|
return_value={'foobar': plg}):
|
||||||
os_vif.initialize()
|
os_vif.initialize()
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
pbr>=1.6
|
pbr>=1.6
|
||||||
netaddr>=0.7.12,!=0.7.16
|
netaddr>=0.7.12,!=0.7.16
|
||||||
|
oslo.config>=3.4.0 # Apache-2.0
|
||||||
oslo.log>=1.14.0 # Apache-2.0
|
oslo.log>=1.14.0 # Apache-2.0
|
||||||
oslo.i18n>=1.5.0 # Apache-2.0
|
oslo.i18n>=1.5.0 # Apache-2.0
|
||||||
oslo.versionedobjects>=0.13.0
|
oslo.versionedobjects>=0.13.0
|
||||||
|
Loading…
Reference in New Issue
Block a user