Extend configurable variables and retrieve config data
Gate ``available`` state on remote end signalling availability. Depends-On: I9eb5f8a6039b74288a395a584f844507448cdc23 Change-Id: I44a23549e4830d89ba3182250c40dfe395767fb0
This commit is contained in:
parent
1ab760f201
commit
4f7dba3da8
43
README.md
43
README.md
@ -6,25 +6,46 @@ that charm.
|
|||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
## States
|
## Flags and States
|
||||||
The interface provides the `{relation-name}.connected` and
|
The interface provides the `{relation-name}.connected` and
|
||||||
`{relation_name}.available` states.
|
`{relation_name}.available` flags and states.
|
||||||
|
|
||||||
|
## neutron\_config\_data
|
||||||
|
|
||||||
|
The neutron\_config\_data property allows the charm author to introspect a
|
||||||
|
subset of the principle charm context values prior to applying the context
|
||||||
|
provided by this relation.
|
||||||
|
|
||||||
|
This enables the subordinate charm to make informed decisions about how it
|
||||||
|
should configure Neutron based on how the deployment is configured.
|
||||||
|
|
||||||
|
```python
|
||||||
|
@reactive.when('neutron-plugin-api-subordinate.connected')
|
||||||
|
def configure_principle():
|
||||||
|
api_principle = reactive.endpoint_from_flag(
|
||||||
|
'neutron-plugin-api-subordinate.connected')
|
||||||
|
if 'dns' in api_principle.neutron_config_data['extension_drivers']:
|
||||||
|
...
|
||||||
|
|
||||||
## configure\_plugin
|
## configure\_plugin
|
||||||
|
|
||||||
The configure\_plugin method allows the following to be configured in the
|
The configure\_plugin method allows the following to be configured in the
|
||||||
principle charm:
|
principle charm:
|
||||||
|
|
||||||
* **neutron\_plugin**: Name of the plugin type eg 'ovs', 'odl' etc. This is not
|
* **neutron\_plugin**: Name of the plugin type eg 'ovs', 'ovn' etc. This is not
|
||||||
currently used in the principle but should be set to
|
currently used in the principle but should be set to
|
||||||
something representitve of the plugin type.
|
something representitve of the plugin type.
|
||||||
* **core\_plugin**: Value of core\_plugin to be set in neutron.conf
|
* **core\_plugin**: Value of core\_plugin to be set in neutron.conf
|
||||||
* **neutron\_plugin\_config**: File containing plugin config. This config file is
|
* **neutron\_plugin\_config**: File containing plugin config. This config file
|
||||||
appended to the list of configs the neutron
|
is appended to the list of configs the neutron
|
||||||
services read on startup.
|
services read on startup.
|
||||||
* **service\_plugins**: Value of service\_plugins to be set in neutron.conf
|
* **service\_plugins**: Value of service\_plugins to be set in neutron.conf
|
||||||
* **subordinate\_configuration**: Config to be inserted into a configuration file
|
* **subordinate\_configuration**: Config to be inserted into a configuration
|
||||||
that the principle manages.
|
file that the principle manages.
|
||||||
|
* **extension\_drivers**: Value of extension\_drivers to be set in
|
||||||
|
ml2\_conf.ini
|
||||||
|
* **neutron\_security\_groups**: Toggle whether the Neutron security group
|
||||||
|
feature should be enabled or not.
|
||||||
|
|
||||||
Request `foo = bar` is inserted into the `DEFAULT` section of neutron.conf
|
Request `foo = bar` is inserted into the `DEFAULT` section of neutron.conf
|
||||||
|
|
||||||
@ -43,11 +64,15 @@ def configure_principle(api_principle):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
service_plugins = ','.join((
|
||||||
|
api_principle.neutron_config_data.get('service_plugins', ''),
|
||||||
|
'networking_ovn.l3.l3_ovn.OVNL3RouterPlugin'),
|
||||||
|
)
|
||||||
api_principle.configure_plugin(
|
api_principle.configure_plugin(
|
||||||
neutron_plugin='odl',
|
neutron_plugin='ovn',
|
||||||
core_plugin='neutron.plugins.ml2.plugin.Ml2Plugin',
|
core_plugin='neutron.plugins.ml2.plugin.Ml2Plugin',
|
||||||
neutron_plugin_config='/etc/neutron/plugins/ml2/ml2_conf.ini',
|
neutron_plugin_config='/etc/neutron/plugins/ml2/ml2_conf.ini',
|
||||||
service_plugins='router,firewall,lbaas,vpnaas,metering',
|
service_plugins=service_plugins,
|
||||||
subordinate_configuration=inject_config)
|
subordinate_configuration=inject_config)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
48
provides.py
48
provides.py
@ -14,6 +14,7 @@ class NeutronPluginAPISubordinate(RelationBase):
|
|||||||
def changed(self):
|
def changed(self):
|
||||||
"""Set connected state"""
|
"""Set connected state"""
|
||||||
self.set_state('{relation_name}.connected')
|
self.set_state('{relation_name}.connected')
|
||||||
|
if self.neutron_api_ready():
|
||||||
self.set_state('{relation_name}.available')
|
self.set_state('{relation_name}.available')
|
||||||
|
|
||||||
@hook(
|
@hook(
|
||||||
@ -23,17 +24,33 @@ class NeutronPluginAPISubordinate(RelationBase):
|
|||||||
self.remove_state('{relation_name}.available')
|
self.remove_state('{relation_name}.available')
|
||||||
self.remove_state('{relation_name}.connected')
|
self.remove_state('{relation_name}.connected')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def neutron_config_data(self):
|
||||||
|
return json.loads(self.get_remote('neutron_config_data', "{}"))
|
||||||
|
|
||||||
|
def neutron_api_ready(self):
|
||||||
|
if self.get_remote('neutron-api-ready') == 'yes':
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def configure_plugin(self, neutron_plugin, core_plugin=None,
|
def configure_plugin(self, neutron_plugin, core_plugin=None,
|
||||||
neutron_plugin_config=None, service_plugins=None,
|
neutron_plugin_config=None, service_plugins=None,
|
||||||
subordinate_configuration=None):
|
subordinate_configuration=None,
|
||||||
|
extension_drivers=None, mechanism_drivers=None,
|
||||||
|
tenant_network_types=None,
|
||||||
|
neutron_security_groups=None):
|
||||||
"""Send principle plugin information
|
"""Send principle plugin information
|
||||||
|
|
||||||
:param neutron_plugin: str Neutron plugin name eg odl
|
:param neutron_plugin: Neutron plugin name
|
||||||
:param core_plugin: str eg neutron.plugins.ml2.plugin.Ml2Plugin
|
:type neutron_plugin: str
|
||||||
:param neutron-plugin-config: str /etc/neutron/plugins/ml2/ml2_conf.ini
|
:param core_plugin: Entry point eg neutron.plugins.ml2.plugin.Ml2Plugin
|
||||||
:param service-plugins str: Comma delimited list of service plugins eg
|
:type core_plugin: str
|
||||||
|
:param neutron-plugin-config: /etc/neutron/plugins/ml2/ml2_conf.ini
|
||||||
|
:type neutron-plugin-config: str
|
||||||
|
:param service-plugins: Comma delimited list of service plugins eg
|
||||||
router,firewall,lbaas,vpnaas,metering
|
router,firewall,lbaas,vpnaas,metering
|
||||||
:param subordinate_configuration dict: Configuration for the principle
|
:type service-plugins: str
|
||||||
|
:param subordinate_configuration: Configuration for the principle
|
||||||
to inject into a configuration
|
to inject into a configuration
|
||||||
file it is managing eg:
|
file it is managing eg:
|
||||||
# Add sections and tuples to insert values into neutron-server's
|
# Add sections and tuples to insert values into neutron-server's
|
||||||
@ -53,6 +70,21 @@ class NeutronPluginAPISubordinate(RelationBase):
|
|||||||
# }
|
# }
|
||||||
# }
|
# }
|
||||||
# }
|
# }
|
||||||
|
:type subordinate_configuration:
|
||||||
|
Dict[str, Dict[
|
||||||
|
str Dict[
|
||||||
|
str, List[
|
||||||
|
Union[str, str]]]]]
|
||||||
|
:param extension_drivers: Extension drivers eg dns,port_security
|
||||||
|
:type extension_drivers: str
|
||||||
|
:param mechanism_drivers: Mechanism drivers eg openvswitch,hyperv
|
||||||
|
:type mechanism_drivers: str
|
||||||
|
:param tenant_network_types: Tenant network types eg local,gre
|
||||||
|
Note that this also configures
|
||||||
|
``type_drivers``
|
||||||
|
:type tenant_network_types: str
|
||||||
|
:param neutron_security_groups: 'true' to enable security groups
|
||||||
|
:type neutron_security_groups: str
|
||||||
"""
|
"""
|
||||||
if subordinate_configuration is None:
|
if subordinate_configuration is None:
|
||||||
subordinate_configuration = {}
|
subordinate_configuration = {}
|
||||||
@ -62,6 +94,10 @@ class NeutronPluginAPISubordinate(RelationBase):
|
|||||||
'core-plugin': core_plugin,
|
'core-plugin': core_plugin,
|
||||||
'neutron-plugin-config': neutron_plugin_config,
|
'neutron-plugin-config': neutron_plugin_config,
|
||||||
'service-plugins': service_plugins,
|
'service-plugins': service_plugins,
|
||||||
|
'extension-drivers': extension_drivers,
|
||||||
|
'mechanism-drivers': mechanism_drivers,
|
||||||
|
'tenant-network-types': tenant_network_types,
|
||||||
|
'neutron-security-groups': neutron_security_groups,
|
||||||
'subordinate_configuration': json.dumps(subordinate_configuration),
|
'subordinate_configuration': json.dumps(subordinate_configuration),
|
||||||
}
|
}
|
||||||
conversation.set_remote(**relation_info)
|
conversation.set_remote(**relation_info)
|
||||||
|
@ -109,6 +109,12 @@ class TestNeutronPluginApiSubordinateProvides(test_utils.PatchHelper):
|
|||||||
conversation = mock.MagicMock()
|
conversation = mock.MagicMock()
|
||||||
self.patch_target('conversation', conversation)
|
self.patch_target('conversation', conversation)
|
||||||
self.patch_target('set_state')
|
self.patch_target('set_state')
|
||||||
|
self.patch_target('get_remote')
|
||||||
|
self.get_remote.return_value = None
|
||||||
|
self.target.changed()
|
||||||
|
self.set_state.assert_called_once_with('{relation_name}.connected')
|
||||||
|
self.set_state.reset_mock()
|
||||||
|
self.get_remote.return_value = 'yes'
|
||||||
self.target.changed()
|
self.target.changed()
|
||||||
self.set_state.assert_has_calls([
|
self.set_state.assert_has_calls([
|
||||||
mock.call('{relation_name}.connected'),
|
mock.call('{relation_name}.connected'),
|
||||||
@ -125,6 +131,18 @@ class TestNeutronPluginApiSubordinateProvides(test_utils.PatchHelper):
|
|||||||
mock.call('{relation_name}.connected'),
|
mock.call('{relation_name}.connected'),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def test_neutron_api_ready(self):
|
||||||
|
self.patch_target('get_remote')
|
||||||
|
self.get_remote.return_value = 'yes'
|
||||||
|
self.assertTrue(self.target.neutron_api_ready())
|
||||||
|
self.get_remote.return_value = None
|
||||||
|
self.assertFalse(self.target.neutron_api_ready())
|
||||||
|
|
||||||
|
def teat_neutron_config_data(self):
|
||||||
|
self.patch_target('get_remote')
|
||||||
|
self.get_remote = json.dumps({'k': 'v'})
|
||||||
|
self.assertEquals(self.target.neutron_config_data, {'k': 'v'})
|
||||||
|
|
||||||
def test_configure_plugin(self):
|
def test_configure_plugin(self):
|
||||||
conversation = mock.MagicMock()
|
conversation = mock.MagicMock()
|
||||||
self.patch_target('conversation', conversation)
|
self.patch_target('conversation', conversation)
|
||||||
@ -132,13 +150,22 @@ class TestNeutronPluginApiSubordinateProvides(test_utils.PatchHelper):
|
|||||||
'aCorePlugin',
|
'aCorePlugin',
|
||||||
'aNeutronPluginConfig',
|
'aNeutronPluginConfig',
|
||||||
'servicePlugins1,servicePlugin2',
|
'servicePlugins1,servicePlugin2',
|
||||||
{'aKey': 'aValue'})
|
{'aKey': 'aValue'},
|
||||||
|
'extensionDriver1,extensionDriver2',
|
||||||
|
'mechanismDriver1,mechanismDriver2',
|
||||||
|
'typeDriver1,typeDriver2',
|
||||||
|
'toggleSecurityGroups',
|
||||||
|
)
|
||||||
conversation.set_remote.assert_called_once_with(
|
conversation.set_remote.assert_called_once_with(
|
||||||
**{
|
**{
|
||||||
'core-plugin': 'aCorePlugin',
|
'core-plugin': 'aCorePlugin',
|
||||||
'neutron-plugin': 'aPlugin',
|
'neutron-plugin': 'aPlugin',
|
||||||
'neutron-plugin-config': 'aNeutronPluginConfig',
|
'neutron-plugin-config': 'aNeutronPluginConfig',
|
||||||
'service-plugins': 'servicePlugins1,servicePlugin2',
|
'service-plugins': 'servicePlugins1,servicePlugin2',
|
||||||
|
'extension-drivers': 'extensionDriver1,extensionDriver2',
|
||||||
|
'mechanism-drivers': 'mechanismDriver1,mechanismDriver2',
|
||||||
|
'tenant-network-types': 'typeDriver1,typeDriver2',
|
||||||
|
'neutron-security-groups': 'toggleSecurityGroups',
|
||||||
'subordinate_configuration': json.dumps({'aKey': 'aValue'})},
|
'subordinate_configuration': json.dumps({'aKey': 'aValue'})},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user