diff --git a/hooks/neutron_ovs_context.py b/hooks/neutron_ovs_context.py index 5c10ecb0..900bfb67 100644 --- a/hooks/neutron_ovs_context.py +++ b/hooks/neutron_ovs_context.py @@ -15,6 +15,7 @@ import collections import glob import os +import socket import uuid from pci import PCINetDevices from charmhelpers.core.hookenv import ( @@ -35,7 +36,10 @@ from charmhelpers.contrib.openstack.utils import ( config_flags_parser, get_host_ip, ) -from charmhelpers.contrib.network.ip import get_address_in_network +from charmhelpers.contrib.network.ip import ( + get_address_in_network, + get_relation_ip, +) from charmhelpers.contrib.openstack.context import ( OSContextGenerator, NeutronAPIContext, @@ -584,3 +588,28 @@ class APIIdentityServiceContext(context.IdentityServiceContext): if ctxt['region']: return ctxt return ctxt + + +class HostIPContext(context.OSContextGenerator): + def __call__(self): + ctxt = {} + # Use the address used in the neutron-plugin subordinate relation + host_ip = get_relation_ip('neutron-plugin') + + # the contents of the Neutron ``host`` configuration option is + # referenced throughout a OpenStack deployment, an example being + # Neutron port bindings. It's value should not change after a + # individual units initial deployment. + # + # We do want to migrate to using FQDNs so we enable this for new + # installations. + db = kv() + if db.get('install_version', 0) >= 1910 and host_ip: + fqdn = socket.getfqdn(host_ip) + if '.' in fqdn: + # only populate the value if getfqdn() is able to find an + # actual FQDN for this host. If not, we revert back to + # not setting the configuration option and use Neutron's + # default behaviour. + ctxt['host'] = fqdn + return ctxt diff --git a/hooks/neutron_ovs_hooks.py b/hooks/neutron_ovs_hooks.py index e57d32c5..554a535e 100755 --- a/hooks/neutron_ovs_hooks.py +++ b/hooks/neutron_ovs_hooks.py @@ -43,6 +43,8 @@ from charmhelpers.core.host import ( is_container, ) +from charmhelpers.core.unitdata import kv + from neutron_ovs_utils import ( DHCP_PACKAGES, DVR_PACKAGES, @@ -74,10 +76,14 @@ hooks = Hooks() CONFIGS = register_configs() -@hooks.hook() +@hooks.hook('install.real') def install(): install_packages() + db = kv() + db.set('install_version', 1910) + db.flush() + # NOTE(wolsen): Do NOT add restart_on_change decorator without consideration # for the implications of modifications to the /etc/default/openvswitch-switch. diff --git a/hooks/neutron_ovs_utils.py b/hooks/neutron_ovs_utils.py index c101b011..49795be0 100644 --- a/hooks/neutron_ovs_utils.py +++ b/hooks/neutron_ovs_utils.py @@ -162,7 +162,9 @@ BASE_RESOURCE_MAP = OrderedDict([ ['neutron-plugin', 'neutron-control']), context.AMQPContext(ssl_dir=NEUTRON_CONF_DIR), context.ZeroMQContext(), - context.NotificationDriverContext()], + context.NotificationDriverContext(), + neutron_ovs_context.HostIPContext(), + ], }), (ML2_CONF, { 'services': ['neutron-plugin-openvswitch-agent'], diff --git a/templates/stein/neutron.conf b/templates/stein/neutron.conf new file mode 100644 index 00000000..ec9aad2e --- /dev/null +++ b/templates/stein/neutron.conf @@ -0,0 +1,52 @@ +# stein +############################################################################### +# [ WARNING ] +# Configuration file maintained by Juju. Local changes may be overwritten. +# Config managed by neutron-openvswitch charm +# Service restart triggered by remote application: {{ restart_trigger }} +# {{ restart_trigger_neutron }} +############################################################################### +[DEFAULT] +verbose = {{ verbose }} +debug = {{ debug }} +use_syslog = {{ use_syslog }} +state_path = /var/lib/neutron +bind_host = 0.0.0.0 +bind_port = 9696 +{% if network_device_mtu -%} +network_device_mtu = {{ network_device_mtu }} +{% endif -%} +{% if core_plugin -%} +core_plugin = {{ core_plugin }} +{% endif -%} +{% if transport_url %} +transport_url = {{ transport_url }} +{% endif %} + +{% if host -%} +host = {{ host }} +{% endif -%} + +api_paste_config = /etc/neutron/api-paste.ini +auth_strategy = keystone +rpc_response_timeout = {{ rpc_response_timeout }} + +{% include "section-zeromq" %} + +{% include "section-oslo-messaging-rabbit-ocata" %} + +{% include "section-oslo-notifications" %} + +[QUOTAS] + +[DEFAULT_SERVICETYPE] + +[AGENT] +root_helper = sudo neutron-rootwrap /etc/neutron/rootwrap.conf +report_interval = {{ report_interval }} + +[keystone_authtoken] +signing_dir = /var/lib/neutron/keystone-signing + +[oslo_concurrency] +lock_path = $state_path/lock diff --git a/test-requirements.txt b/test-requirements.txt index 627da027..bb2e3a72 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -12,7 +12,7 @@ requests>=2.18.4 amulet>=1.14.3,<2.0;python_version=='2.7' bundletester>=0.6.1,<1.0;python_version=='2.7' python-ceilometerclient>=1.5.0 -python-cinderclient>=1.4.0 +python-cinderclient>=1.4.0,<5.0.0 python-glanceclient>=1.1.0 python-heatclient>=0.8.0 python-keystoneclient>=1.7.1 diff --git a/unit_tests/test_neutron_ovs_context.py b/unit_tests/test_neutron_ovs_context.py index b110a8d0..fdff28b0 100644 --- a/unit_tests/test_neutron_ovs_context.py +++ b/unit_tests/test_neutron_ovs_context.py @@ -941,3 +941,25 @@ class TestFirewallDriver(CharmTestCase): self.lsb_release.return_value = _LSB_RELEASE_XENIAL self.assertEqual(context._get_firewall_driver(ctxt), context.IPTABLES_HYBRID) + + +class TestHostIPContext(CharmTestCase): + + def setUp(self): + super(TestHostIPContext, self).setUp(context, TO_PATCH) + self.config.side_effect = self.test_config.get + + @patch.object(context.socket, 'getfqdn') + @patch.object(context, 'kv') + @patch.object(context, 'get_relation_ip') + def test_host_ip_context(self, _get_relation_ip, _kv, _getfqdn): + _kv.return_value = {'install_version': 0} + _getfqdn.return_value = 'some' + ctxt = context.HostIPContext() + self.assertDictEqual({}, ctxt()) + _getfqdn.return_value = 'some.hostname' + ctxt = context.HostIPContext() + self.assertDictEqual({}, ctxt()) + _kv.return_value = {'install_version': 1910} + ctxt = context.HostIPContext() + self.assertDictEqual({'host': 'some.hostname'}, ctxt()) diff --git a/unit_tests/test_neutron_ovs_hooks.py b/unit_tests/test_neutron_ovs_hooks.py index e36ce934..ea3f0d01 100644 --- a/unit_tests/test_neutron_ovs_hooks.py +++ b/unit_tests/test_neutron_ovs_hooks.py @@ -71,9 +71,14 @@ class NeutronOVSHooksTests(CharmTestCase): hooks.hooks.execute([ 'hooks/{}'.format(hookname)]) - def test_install_hook(self): + @patch.object(hooks, 'kv') + def test_install_hook(self, _kv): + fake_dict = MagicMock() + _kv.return_value = fake_dict self._call_hook('install') self.install_packages.assert_called_with() + _kv.assert_called_once_with() + fake_dict.set.assert_called_once_with('install_version', 1910) @patch('neutron_ovs_hooks.enable_sriov', MagicMock(return_value=False)) @patch.object(hooks, 'restart_map')