Enable to use conntrack driver in fwaas_v2
The conntrack entries management codes were identical in fwaas and fwaas_v2 drivers. However [1] didn't handle the fwaas_v2 driver's part. [1] Id0597f74bef67b85776445e7bc591eb085f55acc Related-Bug: #1664294 Change-Id: I4a444fb313bbef2d3a410703ea06d2a0605df772
This commit is contained in:
parent
f4e3d9cc69
commit
24b25ccfbe
|
@ -17,6 +17,26 @@ import abc
|
|||
|
||||
import six
|
||||
|
||||
from neutron_lib.utils import runtime
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def load_and_init_conntrack_driver(*args, **kwargs):
|
||||
driver = cfg.CONF.fwaas.conntrack_driver
|
||||
try:
|
||||
conntrack_driver_cls = runtime.load_class_by_alias_or_classname(
|
||||
'neutron_fwaas.services.firewall.drivers.linux', driver)
|
||||
except ImportError:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.exception("Driver '%s' not found.", driver)
|
||||
conntrack_driver = conntrack_driver_cls()
|
||||
conntrack_driver.initialize(*args, **kwargs)
|
||||
return conntrack_driver
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class ConntrackDriverBase(object):
|
||||
|
|
|
@ -16,12 +16,10 @@
|
|||
from neutron.agent.linux import iptables_manager
|
||||
from neutron.common import utils
|
||||
from neutron_lib.exceptions import firewall_v1 as f_exc
|
||||
from neutron_lib.utils import runtime
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
|
||||
from neutron_fwaas.common import fwaas_constants as f_const
|
||||
from neutron_fwaas.services.firewall.drivers import conntrack_base
|
||||
from neutron_fwaas.services.firewall.drivers import fwaas_base
|
||||
|
||||
|
||||
|
@ -59,27 +57,7 @@ class IptablesFwaasDriver(fwaas_base.FwaasDriverBase):
|
|||
def __init__(self):
|
||||
LOG.debug("Initializing fwaas iptables driver")
|
||||
self.pre_firewall = None
|
||||
conntrack_cls = self._load_firewall_extension_driver(
|
||||
'neutron_fwaas.services.firewall.drivers.linux',
|
||||
cfg.CONF.fwaas.conntrack_driver)
|
||||
self.conntrack = conntrack_cls()
|
||||
self.conntrack.initialize()
|
||||
|
||||
@staticmethod
|
||||
def _load_firewall_extension_driver(namespace, driver):
|
||||
"""Loads driver using alias or class name
|
||||
:param namespace: namespace where alias is defined
|
||||
:param driver: driver alias or class name
|
||||
:returns driver that is loaded
|
||||
:raises ImportError if fails to load driver
|
||||
"""
|
||||
|
||||
try:
|
||||
return runtime.load_class_by_alias_or_classname(
|
||||
namespace, driver)
|
||||
except ImportError:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error("Driver '%s' not found.", driver)
|
||||
self.conntrack = conntrack_base.load_and_init_conntrack_driver()
|
||||
|
||||
def create_firewall(self, agent_mode, apply_list, firewall):
|
||||
LOG.debug('Creating firewall %(fw_id)s for tenant %(tid)s',
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
# under the License.
|
||||
|
||||
from neutron.agent.linux import iptables_manager
|
||||
from neutron.agent.linux import utils as linux_utils
|
||||
from neutron.common import utils
|
||||
from neutron_lib.exceptions import firewall_v2 as fw_ext
|
||||
from oslo_log import log as logging
|
||||
|
||||
from neutron_fwaas.services.firewall.drivers import conntrack_base
|
||||
from neutron_fwaas.services.firewall.drivers import fwaas_base_v2
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
@ -57,6 +57,7 @@ class IptablesFwaasDriver(fwaas_base_v2.FwaasDriverBase):
|
|||
def __init__(self):
|
||||
LOG.debug("Initializing fwaas iptables driver")
|
||||
self.pre_firewall = None
|
||||
self.conntrack = conntrack_base.load_and_init_conntrack_driver()
|
||||
|
||||
def _get_intf_name(self, if_prefix, port_id):
|
||||
_name = "%s%s" % (if_prefix, port_id)
|
||||
|
@ -275,25 +276,6 @@ class IptablesFwaasDriver(fwaas_base_v2.FwaasDriverBase):
|
|||
def _find_new_rules(self, pre_firewall, firewall):
|
||||
return self._find_removed_rules(firewall, pre_firewall)
|
||||
|
||||
def _get_conntrack_cmd_from_rule(self, ipt_mgr, rule=None):
|
||||
prefixcmd = ['ip', 'netns', 'exec'] + [ipt_mgr.namespace]
|
||||
cmd = ['conntrack', '-D']
|
||||
if rule:
|
||||
conntrack_filter = self._get_conntrack_filter_from_rule(rule)
|
||||
exec_cmd = prefixcmd + cmd + conntrack_filter
|
||||
else:
|
||||
exec_cmd = prefixcmd + cmd
|
||||
return exec_cmd
|
||||
|
||||
def _remove_conntrack_by_cmd(self, cmd):
|
||||
if cmd:
|
||||
try:
|
||||
linux_utils.execute(cmd, run_as_root=True,
|
||||
check_exit_code=True,
|
||||
extra_ok_codes=[1])
|
||||
except RuntimeError:
|
||||
LOG.exception("Failed execute conntrack command %s", str(cmd))
|
||||
|
||||
def _remove_conntrack_new_firewall(self, agent_mode, apply_list, firewall):
|
||||
"""Remove conntrack when create new firewall"""
|
||||
routers_list = list(set([apply_info[0] for apply_info in apply_list]))
|
||||
|
@ -302,8 +284,7 @@ class IptablesFwaasDriver(fwaas_base_v2.FwaasDriverBase):
|
|||
agent_mode, ri)
|
||||
for ipt_if_prefix in ipt_if_prefix_list:
|
||||
ipt_mgr = ipt_if_prefix['ipt']
|
||||
cmd = self._get_conntrack_cmd_from_rule(ipt_mgr)
|
||||
self._remove_conntrack_by_cmd(cmd)
|
||||
self.conntrack.flush_entries(ipt_mgr.namespace)
|
||||
|
||||
def _remove_conntrack_updated_firewall(self, agent_mode,
|
||||
apply_list, pre_firewall, firewall):
|
||||
|
@ -319,27 +300,8 @@ class IptablesFwaasDriver(fwaas_base_v2.FwaasDriverBase):
|
|||
i_rules = self._find_new_rules(pre_firewall, firewall)
|
||||
r_rules = self._find_removed_rules(pre_firewall, firewall)
|
||||
removed_conntrack_rules_list = ch_rules + i_rules + r_rules
|
||||
for rule in removed_conntrack_rules_list:
|
||||
cmd = self._get_conntrack_cmd_from_rule(ipt_mgr, rule)
|
||||
self._remove_conntrack_by_cmd(cmd)
|
||||
|
||||
def _get_conntrack_filter_from_rule(self, rule):
|
||||
"""Get conntrack filter from rule.
|
||||
The key for get conntrack filter is protocol, destination_port
|
||||
and source_port. If we want to take more keys, add to the list.
|
||||
"""
|
||||
conntrack_filter = []
|
||||
keys = [['-p', 'protocol'], ['-f', 'ip_version'],
|
||||
['--dport', 'destination_port'], ['--sport', 'source_port']]
|
||||
for key in keys:
|
||||
if rule.get(key[1]):
|
||||
if key[1] == 'ip_version':
|
||||
conntrack_filter.append(key[0])
|
||||
conntrack_filter.append('ipv' + str(rule.get(key[1])))
|
||||
else:
|
||||
conntrack_filter.append(key[0])
|
||||
conntrack_filter.append(rule.get(key[1]))
|
||||
return conntrack_filter
|
||||
self.conntrack.delete_entries(removed_conntrack_rules_list,
|
||||
ipt_mgr.namespace)
|
||||
|
||||
def _remove_default_chains(self, nsid):
|
||||
"""Remove fwaas default policy chain."""
|
||||
|
|
|
@ -37,13 +37,12 @@ MAX_INTF_NAME_LEN = 14
|
|||
class IptablesFwaasTestCase(base.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(IptablesFwaasTestCase, self).setUp()
|
||||
self.utils_exec_p = mock.patch(
|
||||
'neutron.agent.linux.utils.execute')
|
||||
self.utils_exec = self.utils_exec_p.start()
|
||||
self.iptables_cls_p = mock.patch(
|
||||
'neutron.agent.linux.iptables_manager.IptablesManager')
|
||||
self.iptables_cls_p.start()
|
||||
self.firewall = fwaas.IptablesFwaasDriver()
|
||||
self.firewall.conntrack.delete_entries = mock.Mock()
|
||||
self.firewall.conntrack.flush_entries = mock.Mock()
|
||||
|
||||
def _fake_rules_v4(self, fwid, apply_list):
|
||||
rule_list = []
|
||||
|
@ -304,11 +303,8 @@ class IptablesFwaasTestCase(base.BaseTestCase):
|
|||
self.firewall.create_firewall_group(FW_LEGACY, apply_list, firewall)
|
||||
for router_info_inst, port_ids in apply_list:
|
||||
namespace = router_info_inst.iptables_manager.namespace
|
||||
cmd = ['ip', 'netns', 'exec', namespace, 'conntrack', '-D']
|
||||
calls = [
|
||||
mock.call(cmd, run_as_root=True, check_exit_code=True,
|
||||
extra_ok_codes=[1])]
|
||||
self.utils_exec.assert_has_calls(calls)
|
||||
calls = [mock.call(namespace)]
|
||||
self.firewall.conntrack.flush_entries.assert_has_calls(calls)
|
||||
|
||||
def test_remove_conntrack_inserted_rule(self):
|
||||
apply_list = self._fake_apply_list()
|
||||
|
@ -324,18 +320,35 @@ class IptablesFwaasTestCase(base.BaseTestCase):
|
|||
rule_list.insert(2, insert_rule)
|
||||
firewall = self._fake_firewall(rule_list)
|
||||
self.firewall.update_firewall_group(FW_LEGACY, apply_list, firewall)
|
||||
rules_changed = [
|
||||
{'destination_port': '23',
|
||||
'position': '2',
|
||||
'protocol': 'tcp',
|
||||
'ip_version': 4,
|
||||
'enabled': True,
|
||||
'action': 'reject',
|
||||
'id': 'fake-fw-rule3'},
|
||||
{'destination_port': '23',
|
||||
'position': '3',
|
||||
'protocol': 'tcp',
|
||||
'ip_version': 4,
|
||||
'enabled': True,
|
||||
'action': 'reject',
|
||||
'id': 'fake-fw-rule3'}
|
||||
] * 2 # Egress and ingress rule lists
|
||||
rules_inserted = [
|
||||
{'id': 'fake-fw-rule',
|
||||
'protocol': 'icmp',
|
||||
'ip_version': 4,
|
||||
'enabled': True,
|
||||
'action': 'deny',
|
||||
'position': '2'}
|
||||
] * 2 # Egress and ingress rule lists
|
||||
for router_info_inst, port_ids in apply_list:
|
||||
namespace = router_info_inst.iptables_manager.namespace
|
||||
cmd1 = ['ip', 'netns', 'exec', namespace, 'conntrack',
|
||||
'-D', '-p', 'tcp', '-f', 'ipv4', '--dport', '23']
|
||||
cmd2 = ['ip', 'netns', 'exec', namespace, 'conntrack',
|
||||
'-D', '-p', 'icmp', '-f', 'ipv4']
|
||||
calls = [
|
||||
mock.call(cmd1, run_as_root=True, check_exit_code=True,
|
||||
extra_ok_codes=[1]),
|
||||
mock.call(cmd2, run_as_root=True, check_exit_code=True,
|
||||
extra_ok_codes=[1])]
|
||||
self.utils_exec.assert_has_calls(calls)
|
||||
self.firewall.conntrack.delete_entries.assert_called_once_with(
|
||||
rules_changed + rules_inserted, namespace
|
||||
)
|
||||
|
||||
def test_remove_conntrack_removed_rule(self):
|
||||
apply_list = self._fake_apply_list()
|
||||
|
@ -347,18 +360,36 @@ class IptablesFwaasTestCase(base.BaseTestCase):
|
|||
rule_list.remove(remove_rule)
|
||||
firewall = self._fake_firewall(rule_list)
|
||||
self.firewall.update_firewall_group(FW_LEGACY, apply_list, firewall)
|
||||
rules_changed = [
|
||||
{'destination_port': '23',
|
||||
'position': '2',
|
||||
'protocol': 'tcp',
|
||||
'ip_version': 4,
|
||||
'enabled': True,
|
||||
'action': 'reject',
|
||||
'id': 'fake-fw-rule3'},
|
||||
{'destination_port': '23',
|
||||
'position': '1',
|
||||
'protocol': 'tcp',
|
||||
'ip_version': 4,
|
||||
'enabled': True,
|
||||
'action': 'reject',
|
||||
'id': 'fake-fw-rule3'}
|
||||
] * 2 # Egress and ingress rule lists
|
||||
rules_removed = [
|
||||
{'enabled': True,
|
||||
'position': '1',
|
||||
'protocol': 'tcp',
|
||||
'id': 'fake-fw-rule2',
|
||||
'ip_version': 4,
|
||||
'action': 'deny',
|
||||
'destination_port': '22'}
|
||||
] * 2 # Egress and ingress rule lists
|
||||
for router_info_inst, port_ids in apply_list:
|
||||
namespace = router_info_inst.iptables_manager.namespace
|
||||
cmd1 = ['ip', 'netns', 'exec', namespace, 'conntrack',
|
||||
'-D', '-p', 'tcp', '-f', 'ipv4', '--dport', '23']
|
||||
cmd2 = ['ip', 'netns', 'exec', namespace, 'conntrack',
|
||||
'-D', '-p', 'tcp', '-f', 'ipv4', '--dport', '22']
|
||||
calls = [
|
||||
mock.call(cmd1, run_as_root=True, check_exit_code=True,
|
||||
extra_ok_codes=[1]),
|
||||
mock.call(cmd2, run_as_root=True, check_exit_code=True,
|
||||
extra_ok_codes=[1])]
|
||||
self.utils_exec.assert_has_calls(calls)
|
||||
self.firewall.conntrack.delete_entries.assert_called_once_with(
|
||||
rules_changed + rules_removed, namespace
|
||||
)
|
||||
|
||||
def test_remove_conntrack_changed_rule(self):
|
||||
apply_list = self._fake_apply_list()
|
||||
|
@ -368,20 +399,28 @@ class IptablesFwaasTestCase(base.BaseTestCase):
|
|||
income_rule = {'enabled': True,
|
||||
'action': 'deny',
|
||||
'ip_version': 4,
|
||||
'protocol': 'icmp',
|
||||
'id': 'fake-fw-rule2'}
|
||||
rule_list[1] = income_rule
|
||||
'protocol': 'tcp',
|
||||
'id': 'fake-fw-rule3'}
|
||||
rule_list[2] = income_rule
|
||||
firewall = self._fake_firewall(rule_list)
|
||||
self.firewall.update_firewall_group(FW_LEGACY, apply_list, firewall)
|
||||
rules_changed = [
|
||||
{'id': 'fake-fw-rule3',
|
||||
'enabled': True,
|
||||
'action': 'reject',
|
||||
'position': '2',
|
||||
'destination_port': '23',
|
||||
'ip_version': 4,
|
||||
'protocol': 'tcp'},
|
||||
{'position': '2',
|
||||
'enabled': True,
|
||||
'action': 'deny',
|
||||
'id': 'fake-fw-rule3',
|
||||
'ip_version': 4,
|
||||
'protocol': 'tcp'}
|
||||
] * 2 # Egress and ingress rule lists
|
||||
for router_info_inst, port_ids in apply_list:
|
||||
namespace = router_info_inst.iptables_manager.namespace
|
||||
cmd1 = ['ip', 'netns', 'exec', namespace, 'conntrack', '-D',
|
||||
'-p', 'tcp', '-f', 'ipv4', '--dport', '22']
|
||||
cmd2 = ['ip', 'netns', 'exec', namespace, 'conntrack', '-D',
|
||||
'-p', 'icmp', '-f', 'ipv4']
|
||||
calls = [
|
||||
mock.call(cmd1, run_as_root=True, check_exit_code=True,
|
||||
extra_ok_codes=[1]),
|
||||
mock.call(cmd2, run_as_root=True, check_exit_code=True,
|
||||
extra_ok_codes=[1])]
|
||||
self.utils_exec.assert_has_calls(calls)
|
||||
self.firewall.conntrack.delete_entries.assert_called_once_with(
|
||||
rules_changed, namespace
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue