diff --git a/README.rst b/README.rst index 6f8ee04c..f016ec74 100644 --- a/README.rst +++ b/README.rst @@ -14,19 +14,12 @@ Usage ----- 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 -keyword arguments for configuration options:: +library, first call the `os_vif.initialize()` function. This will load +all installed plugins and register the object model:: import os_vif - os_vif.initialize(libvirt_virt_type='kvm', - network_device_mtu=1500, - vlan_interface='eth1', - use_ipv6=False, - iptables_top_regex='', - iptables_bottom_regex='', - iptables_drop_action='DROP', - forward_bridge_interface=['all']) + os_vif.initialize() 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 diff --git a/os_vif/__init__.py b/os_vif/__init__.py index 5d0d6208..968cfcc8 100644 --- a/os_vif/__init__.py +++ b/os_vif/__init__.py @@ -24,7 +24,7 @@ _EXT_MANAGER = None 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 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. - 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 if reset or (_EXT_MANAGER is None): _EXT_MANAGER = extension.ExtensionManager(namespace='os_vif', - invoke_on_load=True, - invoke_args=config) + invoke_on_load=False) + 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() diff --git a/os_vif/plugin.py b/os_vif/plugin.py index 8687b346..b4346301 100644 --- a/os_vif/plugin.py +++ b/os_vif/plugin.py @@ -11,10 +11,13 @@ # under the License. import abc - +from oslo_config import cfg import six +CONF = cfg.CONF + + class PluginVIFInfo(object): """ Class describing the plugin and the versions of VIF object it understands. @@ -54,10 +57,15 @@ class PluginInfo(object): class PluginBase(object): """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 - options. + Initialize the plugin object with the provided config + + :param config: `oslo_config.ConfigOpts.GroupAttr` instance: """ self.config = config @@ -93,3 +101,24 @@ class PluginBase(object): this method should let `processutils.ProcessExecutionError` 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) diff --git a/os_vif/tests/test_os_vif.py b/os_vif/tests/test_os_vif.py index 51674a1b..ce0f3e2b 100644 --- a/os_vif/tests/test_os_vif.py +++ b/os_vif/tests/test_os_vif.py @@ -11,6 +11,7 @@ # under the License. import mock +from oslo_config import cfg from stevedore import extension import os_vif @@ -22,13 +23,34 @@ from os_vif.tests import base 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): pass - def plug(self, vif, instance_info): + def plug(self, vif, instance_info, config): 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 @@ -46,9 +68,25 @@ class TestOSVIF(base.TestCase): os_vif.initialize() os_vif.initialize() 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) + 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): self.assertRaises( exception.LibraryNotInitialized, @@ -63,8 +101,8 @@ class TestOSVIF(base.TestCase): def test_plug(self, mock_plug): plg = extension.Extension(name="demo", entry_point="os-vif", - plugin="DemoPlugin", - obj=DemoPlugin()) + plugin=DemoPlugin, + obj=None) with mock.patch('stevedore.extension.ExtensionManager', return_value={'foobar': plg}): os_vif.initialize() @@ -78,8 +116,8 @@ class TestOSVIF(base.TestCase): def test_unplug(self, mock_unplug): plg = extension.Extension(name="demo", entry_point="os-vif", - plugin="DemoPlugin", - obj=DemoPlugin()) + plugin=DemoPlugin, + obj=None) with mock.patch('stevedore.extension.ExtensionManager', return_value={'foobar': plg}): os_vif.initialize() diff --git a/requirements.txt b/requirements.txt index 770a6a03..b6f499a0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,6 +4,7 @@ pbr>=1.6 netaddr>=0.7.12,!=0.7.16 +oslo.config>=3.4.0 # Apache-2.0 oslo.log>=1.14.0 # Apache-2.0 oslo.i18n>=1.5.0 # Apache-2.0 oslo.versionedobjects>=0.13.0