Add support for firewall driver configuration

Neutron has supported use of a native openvswitch firewall driver
for a few releases; OpenStack Mitaka on Ubuntu 16.04 has the
required kernel and openvswitch versions to support this feature.

Add a new firewall-driver configuration option to support use
of the openvswitch native firewall; the default remains as the
iptables_hybrid driver, and users can switch to the openvswitch
driver if they are deployed on Ubuntu Xenial or later.

Change-Id: I4c228c5cbbff7f9673c1028ee4b075edba1fdc13
Closes-Bug: 1681890
This commit is contained in:
James Page 2017-04-27 11:32:02 +01:00
parent dd7332386a
commit f22e6e9d1e
4 changed files with 87 additions and 1 deletions

View File

@ -96,6 +96,13 @@ options:
<physical_network> specifying physical_network names usable for VLAN <physical_network> specifying physical_network names usable for VLAN
provider and tenant networks, as well as ranges of VLAN tags on each provider and tenant networks, as well as ranges of VLAN tags on each
available for allocation to tenant networks. available for allocation to tenant networks.
firewall-driver:
type: string
default:
description: |
Firewall driver to use to support use of security groups with
instances; valid values include iptables_hybrid (default) and
openvswitch (>= Mitaka on Ubuntu 16.04 or later).
# Network configuration options # Network configuration options
# by default all access is over 'private-address' # by default all access is over 'private-address'
os-data-network: os-data-network:

View File

@ -24,6 +24,10 @@ from charmhelpers.core.hookenv import (
unit_get, unit_get,
network_get_primary_address, network_get_primary_address,
) )
from charmhelpers.core.host import (
CompareHostReleases,
lsb_release,
)
from charmhelpers.contrib.openstack import context from charmhelpers.contrib.openstack import context
from charmhelpers.contrib.openstack.utils import get_host_ip from charmhelpers.contrib.openstack.utils import get_host_ip
from charmhelpers.contrib.network.ip import get_address_in_network from charmhelpers.contrib.network.ip import get_address_in_network
@ -34,6 +38,31 @@ from charmhelpers.contrib.openstack.context import (
) )
from charmhelpers.core.unitdata import kv from charmhelpers.core.unitdata import kv
IPTABLES_HYBRID = 'iptables_hybrid'
OPENVSWITCH = 'openvswitch'
VALID_FIREWALL_DRIVERS = (IPTABLES_HYBRID, OPENVSWITCH)
def _get_firewall_driver():
'''
Determine the firewall driver to use based on configuration,
OpenStack and Ubuntu releases.
@returns str: firewall driver to use for OpenvSwitch
'''
driver = config('firewall-driver') or IPTABLES_HYBRID
release = lsb_release()['DISTRIB_CODENAME']
if driver not in VALID_FIREWALL_DRIVERS:
return IPTABLES_HYBRID
if (driver == OPENVSWITCH and
CompareHostReleases(release) < 'xenial'):
# NOTE(jamespage): Switch back to iptables_hybrid for
# Ubuntu releases prior to Xenial due
# to requirements for Linux >= 4.4 and
# Open vSwitch >= 2.5
return IPTABLES_HYBRID
return driver
class OVSPluginContext(context.NeutronContext): class OVSPluginContext(context.NeutronContext):
interfaces = [] interfaces = []
@ -117,6 +146,8 @@ class OVSPluginContext(context.NeutronContext):
if vlan_ranges: if vlan_ranges:
ovs_ctxt['vlan_ranges'] = ','.join(vlan_ranges.split()) ovs_ctxt['vlan_ranges'] = ','.join(vlan_ranges.split())
ovs_ctxt['firewall_driver'] = _get_firewall_driver()
return ovs_ctxt return ovs_ctxt

View File

@ -24,7 +24,7 @@ veth_mtu = {{ veth_mtu }}
[securitygroup] [securitygroup]
{% if neutron_security_groups and not enable_dpdk -%} {% if neutron_security_groups and not enable_dpdk -%}
enable_security_group = True enable_security_group = True
firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver firewall_driver = {{ firewall_driver }}
{% else -%} {% else -%}
enable_security_group = False enable_security_group = False
{% endif -%} {% endif -%}

View File

@ -18,6 +18,14 @@ from mock import patch, Mock
import neutron_ovs_context as context import neutron_ovs_context as context
import charmhelpers import charmhelpers
_LSB_RELEASE_XENIAL = {
'DISTRIB_CODENAME': 'xenial',
}
_LSB_RELEASE_TRUSTY = {
'DISTRIB_CODENAME': 'trusty',
}
TO_PATCH = [ TO_PATCH = [
'config', 'config',
'unit_get', 'unit_get',
@ -28,6 +36,7 @@ TO_PATCH = [
'relation_ids', 'relation_ids',
'relation_get', 'relation_get',
'related_units', 'related_units',
'lsb_release',
] ]
@ -48,6 +57,7 @@ class OVSPluginContextTest(CharmTestCase):
self.test_config.set('verbose', True) self.test_config.set('verbose', True)
self.test_config.set('use-syslog', True) self.test_config.set('use-syslog', True)
self.network_get_primary_address.side_effect = NotImplementedError self.network_get_primary_address.side_effect = NotImplementedError
self.lsb_release.return_value = _LSB_RELEASE_XENIAL
def tearDown(self): def tearDown(self):
super(OVSPluginContextTest, self).tearDown() super(OVSPluginContextTest, self).tearDown()
@ -152,6 +162,7 @@ class OVSPluginContextTest(CharmTestCase):
'config': 'neutron.randomconfig', 'config': 'neutron.randomconfig',
'use_syslog': True, 'use_syslog': True,
'enable_dpdk': False, 'enable_dpdk': False,
'firewall_driver': 'iptables_hybrid',
'network_manager': 'neutron', 'network_manager': 'neutron',
'debug': True, 'debug': True,
'core_plugin': 'neutron.randomdriver', 'core_plugin': 'neutron.randomdriver',
@ -219,6 +230,7 @@ class OVSPluginContextTest(CharmTestCase):
'config': 'neutron.randomconfig', 'config': 'neutron.randomconfig',
'use_syslog': True, 'use_syslog': True,
'enable_dpdk': False, 'enable_dpdk': False,
'firewall_driver': 'iptables_hybrid',
'network_manager': 'neutron', 'network_manager': 'neutron',
'debug': True, 'debug': True,
'core_plugin': 'neutron.randomdriver', 'core_plugin': 'neutron.randomdriver',
@ -580,3 +592,39 @@ class TestRemoteRestartContext(CharmTestCase):
context.RemoteRestartContext()(), context.RemoteRestartContext()(),
{'restart_trigger_neutron': 'neutron-uuid'} {'restart_trigger_neutron': 'neutron-uuid'}
) )
class TestFirewallDriver(CharmTestCase):
TO_PATCH = [
'config',
'lsb_release',
]
def setUp(self):
super(TestFirewallDriver, self).setUp(context,
self.TO_PATCH)
self.config.side_effect = self.test_config.get
def test_get_firewall_driver_xenial_unset(self):
self.lsb_release.return_value = _LSB_RELEASE_XENIAL
self.assertEqual(context._get_firewall_driver(),
context.IPTABLES_HYBRID)
def test_get_firewall_driver_xenial_openvswitch(self):
self.test_config.set('firewall-driver', 'openvswitch')
self.lsb_release.return_value = _LSB_RELEASE_XENIAL
self.assertEqual(context._get_firewall_driver(),
context.OPENVSWITCH)
def test_get_firewall_driver_xenial_invalid(self):
self.test_config.set('firewall-driver', 'foobar')
self.lsb_release.return_value = _LSB_RELEASE_XENIAL
self.assertEqual(context._get_firewall_driver(),
context.IPTABLES_HYBRID)
def test_get_firewall_driver_trusty_openvswitch(self):
self.test_config.set('firewall-driver', 'openvswitch')
self.lsb_release.return_value = _LSB_RELEASE_TRUSTY
self.assertEqual(context._get_firewall_driver(),
context.IPTABLES_HYBRID)