[gnuoy, r=jamespage] Add support for neutron-plugin-api-subordinate relation
This commit is contained in:
commit
421056efa5
@ -368,3 +368,9 @@ options:
|
||||
description: |
|
||||
A comma-separated list of nagios servicegroups.
|
||||
If left empty, the nagios_context will be used as the servicegroup
|
||||
manage-neutron-plugin-legacy-mode:
|
||||
type: boolean
|
||||
default: True
|
||||
description: |
|
||||
If True neutron-server will install neutron packages for the plugin
|
||||
configured.
|
||||
|
1
hooks/neutron-plugin-api-subordinate-relation-changed
Symbolic link
1
hooks/neutron-plugin-api-subordinate-relation-changed
Symbolic link
@ -0,0 +1 @@
|
||||
neutron_api_hooks.py
|
1
hooks/neutron-plugin-api-subordinate-relation-departed
Symbolic link
1
hooks/neutron-plugin-api-subordinate-relation-departed
Symbolic link
@ -0,0 +1 @@
|
||||
neutron_api_hooks.py
|
1
hooks/neutron-plugin-api-subordinate-relation-joined
Symbolic link
1
hooks/neutron-plugin-api-subordinate-relation-joined
Symbolic link
@ -0,0 +1 @@
|
||||
neutron_api_hooks.py
|
@ -234,3 +234,63 @@ class HAProxyContext(context.HAProxyContext):
|
||||
# for haproxy.conf
|
||||
ctxt['service_ports'] = port_mapping
|
||||
return ctxt
|
||||
|
||||
|
||||
class NeutronApiSDNContext(context.SubordinateConfigContext):
|
||||
interfaces = 'neutron-plugin-api-subordinate'
|
||||
|
||||
def __init__(self):
|
||||
super(NeutronApiSDNContext, self).__init__(
|
||||
interface='neutron-plugin-api-subordinate',
|
||||
service='neutron-api',
|
||||
config_file='/etc/neutron/neutron.conf')
|
||||
|
||||
def __call__(self):
|
||||
ctxt = super(NeutronApiSDNContext, self).__call__()
|
||||
defaults = {
|
||||
'core-plugin': {
|
||||
'templ_key': 'core_plugin',
|
||||
'value': 'neutron.plugins.ml2.plugin.Ml2Plugin',
|
||||
},
|
||||
'neutron-plugin-config': {
|
||||
'templ_key': 'neutron_plugin_config',
|
||||
'value': '/etc/neutron/plugins/ml2/ml2_conf.ini',
|
||||
},
|
||||
'service-plugins': {
|
||||
'templ_key': 'service_plugins',
|
||||
'value': 'router,firewall,lbaas,vpnaas,metering',
|
||||
},
|
||||
'restart-trigger': {
|
||||
'templ_key': 'restart_trigger',
|
||||
'value': '',
|
||||
},
|
||||
}
|
||||
for rid in relation_ids('neutron-plugin-api-subordinate'):
|
||||
for unit in related_units(rid):
|
||||
rdata = relation_get(rid=rid, unit=unit)
|
||||
plugin = rdata.get('neutron-plugin')
|
||||
if not plugin:
|
||||
continue
|
||||
ctxt['neutron_plugin'] = plugin
|
||||
for key in defaults.keys():
|
||||
remote_value = rdata.get(key)
|
||||
ctxt_key = defaults[key]['templ_key']
|
||||
if remote_value:
|
||||
ctxt[ctxt_key] = remote_value
|
||||
else:
|
||||
ctxt[ctxt_key] = defaults[key]['value']
|
||||
return ctxt
|
||||
return ctxt
|
||||
|
||||
|
||||
class NeutronApiSDNConfigFileContext(context.OSContextGenerator):
|
||||
interfaces = ['neutron-plugin-api-subordinate']
|
||||
|
||||
def __call__(self):
|
||||
for rid in relation_ids('neutron-plugin-api-subordinate'):
|
||||
for unit in related_units(rid):
|
||||
rdata = relation_get(rid=rid, unit=unit)
|
||||
neutron_server_plugin_conf = rdata.get('neutron-plugin-config')
|
||||
if neutron_server_plugin_conf:
|
||||
return {'config': neutron_server_plugin_conf}
|
||||
return {'config': '/etc/neutron/plugins/ml2/ml2_conf.ini'}
|
||||
|
@ -479,7 +479,8 @@ def zeromq_configuration_relation_joined(relid=None):
|
||||
users="neutron")
|
||||
|
||||
|
||||
@hooks.hook('zeromq-configuration-relation-changed')
|
||||
@hooks.hook('zeromq-configuration-relation-changed',
|
||||
'neutron-plugin-api-subordinate-relation-changed')
|
||||
@restart_on_change(restart_map(), stopstart=True)
|
||||
def zeromq_configuration_relation_changed():
|
||||
CONFIGS.write_all()
|
||||
|
@ -160,16 +160,21 @@ def api_port(service):
|
||||
return API_PORTS[service]
|
||||
|
||||
|
||||
def manage_plugin():
|
||||
return config('manage-neutron-plugin-legacy-mode')
|
||||
|
||||
|
||||
def determine_packages(source=None):
|
||||
# currently all packages match service names
|
||||
packages = [] + BASE_PACKAGES
|
||||
|
||||
for v in resource_map().values():
|
||||
packages.extend(v['services'])
|
||||
pkgs = neutron_plugin_attribute(config('neutron-plugin'),
|
||||
'server_packages',
|
||||
'neutron')
|
||||
packages.extend(pkgs)
|
||||
if manage_plugin():
|
||||
pkgs = neutron_plugin_attribute(config('neutron-plugin'),
|
||||
'server_packages',
|
||||
'neutron')
|
||||
packages.extend(pkgs)
|
||||
|
||||
if get_os_codename_install_source(source) >= 'kilo':
|
||||
packages.extend(KILO_PACKAGES)
|
||||
@ -211,24 +216,31 @@ def resource_map():
|
||||
else:
|
||||
resource_map.pop(APACHE_24_CONF)
|
||||
|
||||
# add neutron plugin requirements. nova-c-c only needs the neutron-server
|
||||
# associated with configs, not the plugin agent.
|
||||
plugin = config('neutron-plugin')
|
||||
conf = neutron_plugin_attribute(plugin, 'config', 'neutron')
|
||||
ctxts = (neutron_plugin_attribute(plugin, 'contexts', 'neutron')
|
||||
or [])
|
||||
services = neutron_plugin_attribute(plugin, 'server_services',
|
||||
'neutron')
|
||||
resource_map[conf] = {}
|
||||
resource_map[conf]['services'] = services
|
||||
resource_map[conf]['contexts'] = ctxts
|
||||
resource_map[conf]['contexts'].append(
|
||||
neutron_api_context.NeutronCCContext())
|
||||
if manage_plugin():
|
||||
# add neutron plugin requirements. nova-c-c only needs the
|
||||
# neutron-server associated with configs, not the plugin agent.
|
||||
plugin = config('neutron-plugin')
|
||||
conf = neutron_plugin_attribute(plugin, 'config', 'neutron')
|
||||
ctxts = (neutron_plugin_attribute(plugin, 'contexts', 'neutron')
|
||||
or [])
|
||||
services = neutron_plugin_attribute(plugin, 'server_services',
|
||||
'neutron')
|
||||
resource_map[conf] = {}
|
||||
resource_map[conf]['services'] = services
|
||||
resource_map[conf]['contexts'] = ctxts
|
||||
resource_map[conf]['contexts'].append(
|
||||
neutron_api_context.NeutronCCContext())
|
||||
|
||||
# update for postgres
|
||||
resource_map[conf]['contexts'].append(
|
||||
context.PostgresqlDBContext(database=config('database')))
|
||||
# update for postgres
|
||||
resource_map[conf]['contexts'].append(
|
||||
context.PostgresqlDBContext(database=config('database')))
|
||||
|
||||
else:
|
||||
resource_map[NEUTRON_CONF]['contexts'].append(
|
||||
neutron_api_context.NeutronApiSDNContext()
|
||||
)
|
||||
resource_map[NEUTRON_DEFAULT]['contexts'] = \
|
||||
[neutron_api_context.NeutronApiSDNConfigFileContext()]
|
||||
return resource_map
|
||||
|
||||
|
||||
|
@ -37,6 +37,9 @@ requires:
|
||||
zeromq-configuration:
|
||||
interface: zeromq-configuration
|
||||
scope: container
|
||||
neutron-plugin-api-subordinate:
|
||||
interface: neutron-plugin-api-subordinate
|
||||
scope: container
|
||||
peers:
|
||||
cluster:
|
||||
interface: neutron-api-ha
|
||||
|
@ -27,10 +27,14 @@ bind_port = 9696
|
||||
|
||||
{% if core_plugin -%}
|
||||
core_plugin = {{ core_plugin }}
|
||||
{% if service_plugins -%}
|
||||
service_plugins = {{ service_plugins }}
|
||||
{% else -%}
|
||||
{% if neutron_plugin in ['ovs', 'ml2'] -%}
|
||||
service_plugins = neutron.services.l3_router.l3_router_plugin.L3RouterPlugin,neutron.services.firewall.fwaas_plugin.FirewallPlugin,neutron.services.loadbalancer.plugin.LoadBalancerPlugin,neutron.services.vpn.plugin.VPNDriverPlugin,neutron.services.metering.metering_plugin.MeteringPlugin
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if neutron_security_groups -%}
|
||||
allow_overlapping_ips = True
|
||||
@ -50,6 +54,12 @@ nova_admin_password = {{ admin_password }}
|
||||
nova_admin_auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/v2.0
|
||||
{% endif -%}
|
||||
|
||||
{% if sections and 'DEFAULT' in sections -%}
|
||||
{% for key, value in sections['DEFAULT'] -%}
|
||||
{{ key }} = {{ value }}
|
||||
{% endfor -%}
|
||||
{% endif %}
|
||||
|
||||
[quotas]
|
||||
quota_driver = neutron.db.quota_db.DbQuotaDriver
|
||||
{% if neutron_security_groups -%}
|
||||
|
@ -54,6 +54,12 @@ nova_admin_password = {{ admin_password }}
|
||||
nova_admin_auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/v2.0
|
||||
{% endif -%}
|
||||
|
||||
{% if sections and 'DEFAULT' in sections -%}
|
||||
{% for key, value in sections['DEFAULT'] -%}
|
||||
{{ key }} = {{ value }}
|
||||
{% endfor -%}
|
||||
{% endif %}
|
||||
|
||||
[quotas]
|
||||
quota_driver = neutron.db.quota_db.DbQuotaDriver
|
||||
{% if neutron_security_groups -%}
|
||||
|
@ -31,10 +31,14 @@ bind_port = 9696
|
||||
|
||||
{% if core_plugin -%}
|
||||
core_plugin = {{ core_plugin }}
|
||||
{% if service_plugins -%}
|
||||
service_plugins = {{ service_plugins }}
|
||||
{% else -%}
|
||||
{% if neutron_plugin in ['ovs', 'ml2'] -%}
|
||||
service_plugins = router,firewall,lbaas,vpnaas,metering
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if neutron_security_groups -%}
|
||||
allow_overlapping_ips = True
|
||||
@ -52,6 +56,12 @@ nova_admin_password = {{ admin_password }}
|
||||
nova_admin_auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/v2.0
|
||||
{% endif -%}
|
||||
|
||||
{% if sections and 'DEFAULT' in sections -%}
|
||||
{% for key, value in sections['DEFAULT'] -%}
|
||||
{{ key }} = {{ value }}
|
||||
{% endfor -%}
|
||||
{% endif %}
|
||||
|
||||
{% include "section-zeromq" %}
|
||||
|
||||
[quotas]
|
||||
|
@ -1,3 +1,4 @@
|
||||
import json
|
||||
from test_utils import CharmTestCase
|
||||
from mock import patch
|
||||
import neutron_api_context as context
|
||||
@ -432,3 +433,135 @@ class NeutronCCContextTest(CharmTestCase):
|
||||
}
|
||||
for key in expect.iterkeys():
|
||||
self.assertEquals(napi_ctxt[key], expect[key])
|
||||
|
||||
|
||||
class NeutronApiSDNContextTest(CharmTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(NeutronApiSDNContextTest, self).setUp(context, TO_PATCH)
|
||||
self.relation_get.side_effect = self.test_relation.get
|
||||
|
||||
def tearDown(self):
|
||||
super(NeutronApiSDNContextTest, self).tearDown()
|
||||
|
||||
def test_init(self):
|
||||
napisdn_ctxt = context.NeutronApiSDNContext()
|
||||
self.assertEquals(
|
||||
napisdn_ctxt.interfaces,
|
||||
['neutron-plugin-api-subordinate']
|
||||
)
|
||||
self.assertEquals(napisdn_ctxt.services, ['neutron-api'])
|
||||
self.assertEquals(
|
||||
napisdn_ctxt.config_file,
|
||||
'/etc/neutron/neutron.conf'
|
||||
)
|
||||
|
||||
@patch.object(charmhelpers.contrib.openstack.context, 'log')
|
||||
@patch.object(charmhelpers.contrib.openstack.context, 'relation_get')
|
||||
@patch.object(charmhelpers.contrib.openstack.context, 'related_units')
|
||||
@patch.object(charmhelpers.contrib.openstack.context, 'relation_ids')
|
||||
def ctxt_check(self, rel_settings, expect, _rids, _runits, _rget, _log):
|
||||
self.test_relation.set(rel_settings)
|
||||
_runits.return_value = ['unit1']
|
||||
_rids.return_value = ['rid2']
|
||||
_rget.side_effect = self.test_relation.get
|
||||
self.relation_ids.return_value = ['rid2']
|
||||
self.related_units.return_value = ['unit1']
|
||||
napisdn_ctxt = context.NeutronApiSDNContext()()
|
||||
self.assertEquals(napisdn_ctxt, expect)
|
||||
|
||||
def test_defaults(self):
|
||||
self.ctxt_check(
|
||||
{'neutron-plugin': 'ovs'},
|
||||
{
|
||||
'core_plugin': 'neutron.plugins.ml2.plugin.Ml2Plugin',
|
||||
'neutron_plugin_config': ('/etc/neutron/plugins/ml2/'
|
||||
'ml2_conf.ini'),
|
||||
'service_plugins': 'router,firewall,lbaas,vpnaas,metering',
|
||||
'restart_trigger': '',
|
||||
'neutron_plugin': 'ovs',
|
||||
'sections': {},
|
||||
}
|
||||
)
|
||||
|
||||
def test_overrides(self):
|
||||
self.ctxt_check(
|
||||
{
|
||||
'neutron-plugin': 'ovs',
|
||||
'core-plugin': 'neutron.plugins.ml2.plugin.MidoPlumODL',
|
||||
'neutron-plugin-config': '/etc/neutron/plugins/fl/flump.ini',
|
||||
'service-plugins': 'router,unicorn,rainbows',
|
||||
'restart-trigger': 'restartnow',
|
||||
},
|
||||
{
|
||||
'core_plugin': 'neutron.plugins.ml2.plugin.MidoPlumODL',
|
||||
'neutron_plugin_config': '/etc/neutron/plugins/fl/flump.ini',
|
||||
'service_plugins': 'router,unicorn,rainbows',
|
||||
'restart_trigger': 'restartnow',
|
||||
'neutron_plugin': 'ovs',
|
||||
'sections': {},
|
||||
}
|
||||
)
|
||||
|
||||
def test_subordinateconfig(self):
|
||||
principle_config = {
|
||||
"neutron-api": {
|
||||
"/etc/neutron/neutron.conf": {
|
||||
"sections": {
|
||||
'DEFAULT': [
|
||||
('neutronboost', True)
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.ctxt_check(
|
||||
{
|
||||
'neutron-plugin': 'ovs',
|
||||
'subordinate_configuration': json.dumps(principle_config),
|
||||
},
|
||||
{
|
||||
'core_plugin': 'neutron.plugins.ml2.plugin.Ml2Plugin',
|
||||
'neutron_plugin_config': ('/etc/neutron/plugins/ml2/'
|
||||
'ml2_conf.ini'),
|
||||
'service_plugins': 'router,firewall,lbaas,vpnaas,metering',
|
||||
'restart_trigger': '',
|
||||
'neutron_plugin': 'ovs',
|
||||
'sections': {u'DEFAULT': [[u'neutronboost', True]]},
|
||||
}
|
||||
)
|
||||
|
||||
def test_empty(self):
|
||||
self.ctxt_check(
|
||||
{},
|
||||
{'sections': {}},
|
||||
)
|
||||
|
||||
|
||||
class NeutronApiSDNConfigFileContextTest(CharmTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(NeutronApiSDNConfigFileContextTest, self).setUp(
|
||||
context, TO_PATCH)
|
||||
self.relation_get.side_effect = self.test_relation.get
|
||||
|
||||
def tearDown(self):
|
||||
super(NeutronApiSDNConfigFileContextTest, self).tearDown()
|
||||
|
||||
def test_configset(self):
|
||||
self.test_relation.set({
|
||||
'neutron-plugin-config': '/etc/neutron/superplugin.ini'
|
||||
})
|
||||
self.relation_ids.return_value = ['rid2']
|
||||
self.related_units.return_value = ['unit1']
|
||||
napisdn_ctxt = context.NeutronApiSDNConfigFileContext()()
|
||||
self.assertEquals(napisdn_ctxt, {
|
||||
'config': '/etc/neutron/superplugin.ini'
|
||||
})
|
||||
|
||||
def test_default(self):
|
||||
self.relation_ids.return_value = []
|
||||
napisdn_ctxt = context.NeutronApiSDNConfigFileContext()()
|
||||
self.assertEquals(napisdn_ctxt, {
|
||||
'config': '/etc/neutron/plugins/ml2/ml2_conf.ini'
|
||||
})
|
||||
|
@ -104,28 +104,57 @@ class TestNeutronAPIUtils(CharmTestCase):
|
||||
expect.extend(nutils.KILO_PACKAGES)
|
||||
self.assertItemsEqual(pkg_list, expect)
|
||||
|
||||
@patch.object(nutils, 'git_install_requested')
|
||||
def test_determine_packages_noplugin(self, git_requested):
|
||||
git_requested.return_value = False
|
||||
self.test_config.set('manage-neutron-plugin-legacy-mode', False)
|
||||
pkg_list = nutils.determine_packages()
|
||||
expect = deepcopy(nutils.BASE_PACKAGES)
|
||||
expect.extend(['neutron-server'])
|
||||
self.assertItemsEqual(pkg_list, expect)
|
||||
|
||||
def test_determine_ports(self):
|
||||
port_list = nutils.determine_ports()
|
||||
self.assertItemsEqual(port_list, [9696])
|
||||
|
||||
@patch.object(nutils, 'manage_plugin')
|
||||
@patch('os.path.exists')
|
||||
def test_resource_map(self, _path_exists):
|
||||
def test_resource_map(self, _path_exists, _manage_plugin):
|
||||
_path_exists.return_value = False
|
||||
_manage_plugin.return_value = True
|
||||
_map = nutils.resource_map()
|
||||
confs = [nutils.NEUTRON_CONF, nutils.NEUTRON_DEFAULT,
|
||||
nutils.APACHE_CONF]
|
||||
[self.assertIn(q_conf, _map.keys()) for q_conf in confs]
|
||||
self.assertTrue(nutils.APACHE_24_CONF not in _map.keys())
|
||||
|
||||
@patch.object(nutils, 'manage_plugin')
|
||||
@patch('os.path.exists')
|
||||
def test_resource_map_apache24(self, _path_exists):
|
||||
def test_resource_map_apache24(self, _path_exists, _manage_plugin):
|
||||
_path_exists.return_value = True
|
||||
_manage_plugin.return_value = True
|
||||
_map = nutils.resource_map()
|
||||
confs = [nutils.NEUTRON_CONF, nutils.NEUTRON_DEFAULT,
|
||||
nutils.APACHE_24_CONF]
|
||||
[self.assertIn(q_conf, _map.keys()) for q_conf in confs]
|
||||
self.assertTrue(nutils.APACHE_CONF not in _map.keys())
|
||||
|
||||
@patch.object(nutils, 'manage_plugin')
|
||||
@patch('os.path.exists')
|
||||
def test_resource_map_noplugin(self, _path_exists, _manage_plugin):
|
||||
_path_exists.return_value = True
|
||||
_manage_plugin.return_value = False
|
||||
_map = nutils.resource_map()
|
||||
found_sdn_ctxt = False
|
||||
found_sdnconfig_ctxt = False
|
||||
for ctxt in _map[nutils.NEUTRON_CONF]['contexts']:
|
||||
if isinstance(ctxt, ncontext.NeutronApiSDNContext):
|
||||
found_sdn_ctxt = True
|
||||
for ctxt in _map[nutils.NEUTRON_DEFAULT]['contexts']:
|
||||
if isinstance(ctxt, ncontext.NeutronApiSDNConfigFileContext):
|
||||
found_sdnconfig_ctxt = True
|
||||
self.assertTrue(found_sdn_ctxt and found_sdnconfig_ctxt)
|
||||
|
||||
@patch('os.path.exists')
|
||||
def test_restart_map(self, mock_path_exists):
|
||||
mock_path_exists.return_value = False
|
||||
@ -520,3 +549,13 @@ class TestNeutronAPIUtils(CharmTestCase):
|
||||
'upgrade',
|
||||
'head']
|
||||
self.subprocess.check_output.assert_called_with(cmd)
|
||||
|
||||
def test_manage_plugin_true(self):
|
||||
self.test_config.set('manage-neutron-plugin-legacy-mode', True)
|
||||
manage = nutils.manage_plugin()
|
||||
self.assertTrue(manage)
|
||||
|
||||
def test_manage_plugin_false(self):
|
||||
self.test_config.set('manage-neutron-plugin-legacy-mode', False)
|
||||
manage = nutils.manage_plugin()
|
||||
self.assertFalse(manage)
|
||||
|
Loading…
Reference in New Issue
Block a user