Use iptables zone to separate different ip_conntrack

ip_conntrack causes security group rule failures when packets share
the same 5-tuple. Use iptables zone option to separate different
conntrack zone. Currently this patch only works for OVS agent.

Co-authored-by: shihanzhang <shihanzhang@huawei.com>

Change-Id: I90b4d2485e3e491f496dfb7bdee03d57f393be35
Partial-Bug: #1359523
This commit is contained in:
yangxurong 2014-08-26 15:15:40 +08:00 committed by shihanzhang
parent 8978516e49
commit bd5373b670
9 changed files with 459 additions and 196 deletions

View File

@ -193,9 +193,17 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
self.iptables.ipv6['filter'].add_rule('sg-fallback', '-j DROP',
comment=ic.UNMATCH_DROP)
def _add_raw_chain(self, chain_name):
self.iptables.ipv4['raw'].add_chain(chain_name)
self.iptables.ipv6['raw'].add_chain(chain_name)
def _add_chain_by_name_v4v6(self, chain_name):
self.iptables.ipv6['filter'].add_chain(chain_name)
self.iptables.ipv4['filter'].add_chain(chain_name)
self.iptables.ipv6['filter'].add_chain(chain_name)
def _remove_raw_chain(self, chain_name):
self.iptables.ipv4['raw'].remove_chain(chain_name)
self.iptables.ipv6['raw'].remove_chain(chain_name)
def _remove_chain_by_name_v4v6(self, chain_name):
self.iptables.ipv4['filter'].remove_chain(chain_name)
@ -676,3 +684,39 @@ class OVSHybridIptablesFirewallDriver(IptablesFirewallDriver):
def _get_device_name(self, port):
return (self.OVS_HYBRID_TAP_PREFIX + port['device'])[:LINUX_DEV_LEN]
def _get_br_device_name(self, port):
return ('qvb' + port['device'])[:LINUX_DEV_LEN]
def _get_jump_rule(self, port, direction):
if direction == INGRESS_DIRECTION:
device = self._get_br_device_name(port)
else:
device = self._get_device_name(port)
jump_rule = '-m physdev --physdev-in %s -j CT --zone %s' % (
device, port['zone_id'])
return jump_rule
def _add_raw_chain_rules(self, port, direction):
if port['zone_id']:
jump_rule = self._get_jump_rule(port, direction)
self.iptables.ipv4['raw'].add_rule('PREROUTING', jump_rule)
self.iptables.ipv6['raw'].add_rule('PREROUTING', jump_rule)
def _remove_raw_chain_rules(self, port, direction):
if port['zone_id']:
jump_rule = self._get_jump_rule(port, direction)
self.iptables.ipv4['raw'].remove_rule('PREROUTING', jump_rule)
self.iptables.ipv6['raw'].remove_rule('PREROUTING', jump_rule)
def _add_chain(self, port, direction):
super(OVSHybridIptablesFirewallDriver, self)._add_chain(port,
direction)
if direction in [INGRESS_DIRECTION, EGRESS_DIRECTION]:
self._add_raw_chain_rules(port, direction)
def _remove_chain(self, port, direction):
super(OVSHybridIptablesFirewallDriver, self)._remove_chain(port,
direction)
if direction in [INGRESS_DIRECTION, EGRESS_DIRECTION]:
self._remove_raw_chain_rules(port, direction)

View File

@ -326,10 +326,11 @@ class IptablesManager(object):
{'nat': IptablesTable(binary_name=self.wrap_name)})
builtin_chains[4].update({'nat': ['PREROUTING',
'OUTPUT', 'POSTROUTING']})
self.ipv4.update(
{'raw': IptablesTable(binary_name=self.wrap_name)})
builtin_chains[4].update({'raw': ['PREROUTING',
'OUTPUT']})
self.ipv4.update({'raw': IptablesTable(binary_name=self.wrap_name)})
builtin_chains[4].update({'raw': ['PREROUTING', 'OUTPUT']})
self.ipv6.update({'raw': IptablesTable(binary_name=self.wrap_name)})
builtin_chains[6].update({'raw': ['PREROUTING', 'OUTPUT']})
for ip_version in builtin_chains:
if ip_version == 4:

View File

@ -84,10 +84,12 @@ def disable_security_group_extension_by_config(aliases):
class SecurityGroupAgentRpc(object):
"""Enables SecurityGroup agent support in agent implementations."""
def __init__(self, context, plugin_rpc, defer_refresh_firewall=False):
def __init__(self, context, plugin_rpc, local_vlan_map=None,
defer_refresh_firewall=False,):
self.context = context
self.plugin_rpc = plugin_rpc
self.init_firewall(defer_refresh_firewall)
self.local_vlan_map = local_vlan_map
def init_firewall(self, defer_refresh_firewall=False):
firewall_driver = cfg.CONF.SECURITYGROUP.firewall_driver
@ -108,6 +110,23 @@ class SecurityGroupAgentRpc(object):
self.global_refresh_firewall = False
self._use_enhanced_rpc = None
def set_local_zone(self, device):
"""Set local zone id for device
In order to separate conntrack in different networks, a local zone
id is needed to generate related iptables rules. This routine sets
zone id to device according to the network it belongs to. For OVS
agent, vlan id of each network can be used as zone id.
:param device: dictionary of device information, get network id by
device['network_id'], and set zone id by device['zone_id']
"""
net_id = device['network_id']
zone_id = None
if self.local_vlan_map and net_id in self.local_vlan_map:
zone_id = self.local_vlan_map[net_id].vlan
device['zone_id'] = zone_id
@property
def use_enhanced_rpc(self):
if self._use_enhanced_rpc is None:
@ -157,6 +176,7 @@ class SecurityGroupAgentRpc(object):
with self.firewall.defer_apply():
for device in devices.values():
self.set_local_zone(device)
self.firewall.prepare_port_filter(device)
if self.use_enhanced_rpc:
LOG.debug("Update security group information for ports %s",
@ -244,6 +264,7 @@ class SecurityGroupAgentRpc(object):
with self.firewall.defer_apply():
for device in devices.values():
LOG.debug("Update port filter for %s", device['device'])
self.set_local_zone(device)
self.firewall.update_port_filter(device)
if self.use_enhanced_rpc:
LOG.debug("Update security group information for ports %s",

View File

@ -254,9 +254,14 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
# Collect additional bridges to monitor
self.ancillary_brs = self.setup_ancillary_bridges(integ_br, tun_br)
# In order to keep existed device's local vlan unchanged,
# restore local vlan mapping at start
self._restore_local_vlan_map()
# Security group agent support
self.sg_agent = sg_rpc.SecurityGroupAgentRpc(self.context,
self.sg_plugin_rpc, defer_refresh_firewall=True)
self.sg_plugin_rpc, self.local_vlan_map,
defer_refresh_firewall=True)
# Initialize iteration counter
self.iter_num = 0
@ -283,6 +288,21 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
except Exception:
LOG.exception(_LE("Failed reporting state!"))
def _restore_local_vlan_map(self):
cur_ports = self.int_br.get_vif_ports()
for port in cur_ports:
local_vlan_map = self.int_br.db_get_val("Port", port.port_name,
"other_config")
local_vlan = self.int_br.db_get_val("Port", port.port_name, "tag")
net_uuid = local_vlan_map.get('net_uuid')
if (net_uuid and net_uuid not in self.local_vlan_map
and local_vlan != DEAD_VLAN_TAG):
self.provision_local_vlan(local_vlan_map['net_uuid'],
local_vlan_map['network_type'],
local_vlan_map['physical_network'],
local_vlan_map['segmentation_id'],
local_vlan)
def setup_rpc(self):
self.agent_id = 'ovs-agent-%s' % cfg.CONF.host
self.topic = topics.AGENT
@ -496,7 +516,7 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
LOG.warning(_LW('Action %s not supported'), action)
def provision_local_vlan(self, net_uuid, network_type, physical_network,
segmentation_id):
segmentation_id, local_vlan=None):
'''Provisions a local VLAN.
:param net_uuid: the uuid of the network associated with this vlan.
@ -513,11 +533,15 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
if lvm:
lvid = lvm.vlan
else:
if not self.available_local_vlans:
LOG.error(_LE("No local VLAN available for net-id=%s"),
net_uuid)
return
lvid = self.available_local_vlans.pop()
if local_vlan in self.available_local_vlans:
lvid = local_vlan
self.available_local_vlans.remove(local_vlan)
else:
if not self.available_local_vlans:
LOG.error(_LE("No local VLAN available for net-id=%s"),
net_uuid)
return
lvid = self.available_local_vlans.pop()
self.local_vlan_map[net_uuid] = LocalVLANMapping(lvid,
network_type,
physical_network,
@ -697,14 +721,43 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
self.dvr_agent.bind_port_to_dvr(port, lvm,
fixed_ips,
device_owner)
port_other_config = self.int_br.db_get_val("Port", port.port_name,
"other_config")
vlan_mapping = {'net_uuid': net_uuid,
'network_type': network_type,
'physical_network': physical_network,
'segmentation_id': segmentation_id}
port_other_config.update(vlan_mapping)
self.int_br.set_db_attribute("Port", port.port_name, "other_config",
port_other_config)
# Do not bind a port if it's already bound
cur_tag = self.int_br.db_get_val("Port", port.port_name, "tag")
if cur_tag != lvm.vlan:
self.int_br.set_db_attribute("Port", port.port_name, "tag",
lvm.vlan)
if port.ofport != -1:
self.int_br.delete_flows(in_port=port.ofport)
def _bind_devices(self, need_binding_ports):
for port_detail in need_binding_ports:
lvm = self.local_vlan_map[port_detail['network_id']]
port = port_detail['vif_port']
device = port_detail['device']
# Do not bind a port if it's already bound
cur_tag = self.int_br.db_get_val("Port", port.port_name, "tag")
if cur_tag != lvm.vlan:
self.int_br.set_db_attribute(
"Port", port.port_name, "tag", lvm.vlan)
if port.ofport != -1:
self.int_br.delete_flows(in_port=port.ofport)
# update plugin about port status
# FIXME(salv-orlando): Failures while updating device status
# must be handled appropriately. Otherwise this might prevent
# neutron server from sending network-vif-* events to the nova
# API server, thus possibly preventing instance spawn.
if port_detail.get('admin_state_up'):
LOG.debug("Setting status for %s to UP", device)
self.plugin_rpc.update_device_up(
self.context, device, self.agent_id, cfg.CONF.host)
else:
LOG.debug("Setting status for %s to DOWN", device)
self.plugin_rpc.update_device_down(
self.context, device, self.agent_id, cfg.CONF.host)
LOG.info(_LI("Configuration for device %s completed."), device)
@staticmethod
def setup_arp_spoofing_protection(bridge, vif, port_details):
@ -1150,6 +1203,7 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
# an OVS ofport configured, as only these ports were considered
# for being treated. If that does not happen, it is a potential
# error condition of which operators should be aware
port_needs_binding = True
if not vif_port.ofport:
LOG.warn(_LW("VIF port: %s has no ofport configured, "
"and might not be able to transmit"), vif_port.vif_id)
@ -1160,8 +1214,10 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
fixed_ips, device_owner, ovs_restarted)
else:
self.port_dead(vif_port)
port_needs_binding = False
else:
LOG.debug("No VIF port for port %s defined on agent.", port_id)
return port_needs_binding
def _setup_tunnel_port(self, br, port_name, remote_ip, tunnel_type):
ofport = br.add_tunnel_port(port_name,
@ -1222,6 +1278,7 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
def treat_devices_added_or_updated(self, devices, ovs_restarted):
skipped_devices = []
need_binding_devices = []
try:
devices_details_list = self.plugin_rpc.get_devices_details_list(
self.context,
@ -1244,37 +1301,26 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
if 'port_id' in details:
LOG.info(_LI("Port %(device)s updated. Details: %(details)s"),
{'device': device, 'details': details})
self.treat_vif_port(port, details['port_id'],
details['network_id'],
details['network_type'],
details['physical_network'],
details['segmentation_id'],
details['admin_state_up'],
details['fixed_ips'],
details['device_owner'],
ovs_restarted)
need_binding = self.treat_vif_port(port, details['port_id'],
details['network_id'],
details['network_type'],
details['physical_network'],
details['segmentation_id'],
details['admin_state_up'],
details['fixed_ips'],
details['device_owner'],
ovs_restarted)
if self.prevent_arp_spoofing:
self.setup_arp_spoofing_protection(self.int_br,
port, details)
# update plugin about port status
# FIXME(salv-orlando): Failures while updating device status
# must be handled appropriately. Otherwise this might prevent
# neutron server from sending network-vif-* events to the nova
# API server, thus possibly preventing instance spawn.
if details.get('admin_state_up'):
LOG.debug("Setting status for %s to UP", device)
self.plugin_rpc.update_device_up(
self.context, device, self.agent_id, cfg.CONF.host)
else:
LOG.debug("Setting status for %s to DOWN", device)
self.plugin_rpc.update_device_down(
self.context, device, self.agent_id, cfg.CONF.host)
LOG.info(_LI("Configuration for device %s completed."), device)
if need_binding:
details['vif_port'] = port
need_binding_devices.append(details)
else:
LOG.warn(_LW("Device %s not defined on plugin"), device)
if (port and port.ofport != -1):
self.port_dead(port)
return skipped_devices
return skipped_devices, need_binding_devices
def treat_ancillary_devices_added(self, devices):
try:
@ -1344,10 +1390,6 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
# sources: the neutron server, and the ovs db monitor process
# If there is an exception while processing security groups ports
# will not be wired anyway, and a resync will be triggered
# TODO(salv-orlando): Optimize avoiding applying filters unnecessarily
# (eg: when there are no IP address changes)
self.sg_agent.setup_port_filters(port_info.get('added', set()),
port_info.get('updated', set()))
# VIF wiring needs to be performed always for 'new' devices.
# For updated ports, re-wiring is not needed in most cases, but needs
# to be performed anyway when the admin state of a device is changed.
@ -1358,8 +1400,9 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
if devices_added_updated:
start = time.time()
try:
skipped_devices = self.treat_devices_added_or_updated(
devices_added_updated, ovs_restarted)
skipped_devices, need_binding_devices = (
self.treat_devices_added_or_updated(
devices_added_updated, ovs_restarted))
LOG.debug("process_network_ports - iteration:%(iter_num)d - "
"treat_devices_added_or_updated completed. "
"Skipped %(num_skipped)d devices of "
@ -1369,6 +1412,12 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
'num_skipped': len(skipped_devices),
'num_current': len(port_info['current']),
'elapsed': time.time() - start})
# TODO(salv-orlando): Optimize avoiding applying filters
# unnecessarily, (eg: when there are no IP address changes)
self.sg_agent.setup_port_filters(
port_info.get('added', set()),
port_info.get('updated', set()))
self._bind_devices(need_binding_devices)
# Update the list of current ports storing only those which
# have been actually processed.
port_info['current'] = (port_info['current'] -

View File

@ -56,8 +56,12 @@ class BaseIptablesFirewallTestCase(base.BaseTestCase):
self.iptables_inst = mock.Mock()
self.v4filter_inst = mock.Mock()
self.v6filter_inst = mock.Mock()
self.iptables_inst.ipv4 = {'filter': self.v4filter_inst}
self.iptables_inst.ipv6 = {'filter': self.v6filter_inst}
self.iptables_inst.ipv4 = {'filter': self.v4filter_inst,
'raw': self.v4filter_inst
}
self.iptables_inst.ipv6 = {'filter': self.v6filter_inst,
'raw': self.v6filter_inst
}
iptables_cls.return_value = self.iptables_inst
self.firewall = iptables_firewall.IptablesFirewallDriver()
@ -69,6 +73,7 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase):
def _fake_port(self):
return {'device': 'tapfake_dev',
'mac_address': 'ff:ff:ff:ff:ff:ff',
'network_id': 'fake_net',
'fixed_ips': [FAKE_IP['IPv4'],
FAKE_IP['IPv6']]}
@ -921,7 +926,7 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase):
'-m physdev --physdev-out tapfake_dev '
'--physdev-is-bridged '
'-j $ifake_dev',
comment=ic.SG_TO_VM_SG),
comment=ic.SG_TO_VM_SG)
]
if ethertype == 'IPv6':
for icmp6_type in constants.ICMPV6_ALLOWED_TYPES:
@ -1247,8 +1252,8 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase):
def test_defer_chain_apply_coalesce_multiple_ports(self):
chain_applies = self._mock_chain_applies()
port1 = {'device': 'd1', 'mac_address': 'mac1'}
port2 = {'device': 'd2', 'mac_address': 'mac2'}
port1 = {'device': 'd1', 'mac_address': 'mac1', 'network_id': 'net1'}
port2 = {'device': 'd2', 'mac_address': 'mac2', 'network_id': 'net1'}
device2port = {'d1': port1, 'd2': port2}
with self.firewall.defer_apply():
self.firewall.prepare_port_filter(port1)
@ -1259,6 +1264,7 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase):
def test_ip_spoofing_filter_with_multiple_ips(self):
port = {'device': 'tapfake_dev',
'mac_address': 'ff:ff:ff:ff:ff:ff',
'network_id': 'fake_net',
'fixed_ips': ['10.0.0.1', 'fe80::1', '10.0.0.2']}
self.firewall.prepare_port_filter(port)
calls = [mock.call.add_chain('sg-fallback'),
@ -1338,6 +1344,7 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase):
def test_ip_spoofing_no_fixed_ips(self):
port = {'device': 'tapfake_dev',
'mac_address': 'ff:ff:ff:ff:ff:ff',
'network_id': 'fake_net',
'fixed_ips': []}
self.firewall.prepare_port_filter(port)
calls = [mock.call.add_chain('sg-fallback'),
@ -1421,6 +1428,7 @@ class IptablesFirewallEnhancedIpsetTestCase(BaseIptablesFirewallTestCase):
def _fake_port(self, sg_id=FAKE_SGID):
return {'device': 'tapfake_dev',
'mac_address': 'ff:ff:ff:ff:ff:ff',
'network_id': 'fake_net',
'fixed_ips': [FAKE_IP['IPv4'],
FAKE_IP['IPv6']],
'security_groups': [sg_id],

View File

@ -314,7 +314,7 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
]
if use_ipv6:
self._extend_with_ip6tables_filter(expected_calls_and_values,
filter_dump_ipv6)
raw_dump + filter_dump_ipv6)
tools.setup_mock_calls(self.execute, expected_calls_and_values)
@ -374,7 +374,7 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
]
if use_ipv6:
self._extend_with_ip6tables_filter(expected_calls_and_values,
filter_dump)
raw_dump + filter_dump)
tools.setup_mock_calls(self.execute, expected_calls_and_values)
@ -421,7 +421,7 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
]
if use_ipv6:
self._extend_with_ip6tables_filter(expected_calls_and_values,
FILTER_DUMP)
RAW_DUMP + FILTER_DUMP)
tools.setup_mock_calls(self.execute, expected_calls_and_values)
@ -452,6 +452,8 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
iptables_args['filter_rules'] = filter_rules
filter_dump_mod = FILTER_WITH_RULES_TEMPLATE % iptables_args
raw_dump = RAW_DUMP % IPTABLES_ARG
expected_calls_and_values = [
(mock.call(['iptables-save', '-c'],
run_as_root=True),
@ -473,7 +475,7 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
]
if use_ipv6:
self._extend_with_ip6tables_filter(expected_calls_and_values,
FILTER_DUMP)
raw_dump + FILTER_DUMP)
tools.setup_mock_calls(self.execute, expected_calls_and_values)
@ -533,6 +535,8 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
'# Completed by iptables_manager\n'
% iptables_args)
raw_dump = RAW_DUMP % IPTABLES_ARG
expected_calls_and_values = [
(mock.call(['iptables-save', '-c'],
run_as_root=True),
@ -553,7 +557,7 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
]
if use_ipv6:
self._extend_with_ip6tables_filter(expected_calls_and_values,
FILTER_DUMP)
raw_dump + FILTER_DUMP)
tools.setup_mock_calls(self.execute, expected_calls_and_values)
@ -624,7 +628,7 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
]
if use_ipv6:
self._extend_with_ip6tables_filter(expected_calls_and_values,
FILTER_DUMP)
RAW_DUMP + FILTER_DUMP)
tools.setup_mock_calls(self.execute, expected_calls_and_values)
@ -680,6 +684,8 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
'# Completed by iptables_manager\n'
% IPTABLES_ARG)
raw_dump = RAW_DUMP % IPTABLES_ARG
expected_calls_and_values = [
(mock.call(['iptables-save', '-c'],
run_as_root=True),
@ -700,7 +706,7 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
]
if use_ipv6:
self._extend_with_ip6tables_filter(expected_calls_and_values,
FILTER_DUMP)
raw_dump + FILTER_DUMP)
tools.setup_mock_calls(self.execute, expected_calls_and_values)
@ -769,7 +775,7 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
]
if use_ipv6:
self._extend_with_ip6tables_filter(expected_calls_and_values,
FILTER_DUMP)
RAW_DUMP + FILTER_DUMP)
tools.setup_mock_calls(self.execute, expected_calls_and_values)
@ -911,6 +917,10 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
''),
]
if use_ipv6:
expected_calls_and_values.append(
(mock.call(['ip6tables', '-t', 'raw', '-L', 'OUTPUT',
'-n', '-v', '-x'], run_as_root=True),
''))
expected_calls_and_values.append(
(mock.call(['ip6tables', '-t', 'filter', '-L', 'OUTPUT',
'-n', '-v', '-x'],
@ -960,6 +970,10 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
'')
]
if use_ipv6:
expected_calls_and_values.append(
(mock.call(['ip6tables', '-t', 'raw', '-L', 'OUTPUT',
'-n', '-v', '-x', '-Z'], run_as_root=True),
''))
expected_calls_and_values.append(
(mock.call(['ip6tables', '-t', 'filter', '-L', 'OUTPUT',
'-n', '-v', '-x', '-Z'],

View File

@ -13,9 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
import collections
import contextlib
import collections
import mock
from oslo_config import cfg
import oslo_messaging
@ -34,6 +34,7 @@ from neutron.db import securitygroups_rpc_base as sg_db_rpc
from neutron.extensions import allowedaddresspairs as addr_pair
from neutron.extensions import securitygroup as ext_sg
from neutron import manager
from neutron.plugins.openvswitch.agent import ovs_neutron_agent
from neutron.tests import base
from neutron.tests.unit.extensions import test_securitygroup as test_sg
@ -1107,6 +1108,7 @@ class BaseSecurityGroupAgentRpcTestCase(base.BaseTestCase):
self.firewall.defer_apply.side_effect = firewall_object.defer_apply
self.agent.firewall = self.firewall
self.fake_device = {'device': 'fake_device',
'network_id': 'fake_net',
'security_groups': ['fake_sgid1', 'fake_sgid2'],
'security_group_source_groups': ['fake_sgid2'],
'security_group_rules': [{'security_group_id':
@ -1667,6 +1669,42 @@ IPTABLES_ARG['ip1'] = IPS.values()[0]
IPTABLES_ARG['ip2'] = IPS.values()[1]
IPTABLES_ARG['chains'] = CHAINS_NAT
IPTABLES_RAW_DEFAULT = """# Generated by iptables_manager
*raw
:%(bn)s-OUTPUT - [0:0]
:%(bn)s-PREROUTING - [0:0]
[0:0] -A PREROUTING -j %(bn)s-PREROUTING
[0:0] -A OUTPUT -j %(bn)s-OUTPUT
COMMIT
# Completed by iptables_manager
""" % IPTABLES_ARG
IPTABLES_RAW_DEVICE_1 = """# Generated by iptables_manager
*raw
:%(bn)s-OUTPUT - [0:0]
:%(bn)s-PREROUTING - [0:0]
[0:0] -A PREROUTING -j %(bn)s-PREROUTING
[0:0] -A OUTPUT -j %(bn)s-OUTPUT
[0:0] -A %(bn)s-PREROUTING -m physdev --physdev-in qvbtap_port1 -j CT --zone 1
[0:0] -A %(bn)s-PREROUTING -m physdev --physdev-in tap_port1 -j CT --zone 1
COMMIT
# Completed by iptables_manager
""" % IPTABLES_ARG
IPTABLES_RAW_DEVICE_2 = """# Generated by iptables_manager
*raw
:%(bn)s-OUTPUT - [0:0]
:%(bn)s-PREROUTING - [0:0]
[0:0] -A PREROUTING -j %(bn)s-PREROUTING
[0:0] -A OUTPUT -j %(bn)s-OUTPUT
[0:0] -A %(bn)s-PREROUTING -m physdev --physdev-in qvbtap_port1 -j CT --zone 1
[0:0] -A %(bn)s-PREROUTING -m physdev --physdev-in tap_port1 -j CT --zone 1
[0:0] -A %(bn)s-PREROUTING -m physdev --physdev-in qvbtap_port2 -j CT --zone 1
[0:0] -A %(bn)s-PREROUTING -m physdev --physdev-in tap_port2 -j CT --zone 1
COMMIT
# Completed by iptables_manager
""" % IPTABLES_ARG
IPTABLES_NAT = """# Generated by iptables_manager
*nat
:neutron-postrouting-bottom - [0:0]
@ -2469,9 +2507,7 @@ class TestSecurityGroupAgentWithIptables(base.BaseTestCase):
cfg.CONF.set_override('comment_iptables_rules', False, group='AGENT')
self.rpc = mock.Mock()
self.agent = sg_rpc.SecurityGroupAgentRpc(
context=None, plugin_rpc=self.rpc,
defer_refresh_firewall=defer_refresh_firewall)
self._init_agent(defer_refresh_firewall)
if test_rpc_v1_1:
self.rpc.security_group_info_for_devices.side_effect = (
@ -2542,8 +2578,14 @@ class TestSecurityGroupAgentWithIptables(base.BaseTestCase):
'12:34:56:78:9a:bd',
rule5)}
def _init_agent(self, defer_refresh_firewall):
self.agent = sg_rpc.SecurityGroupAgentRpc(
context=None, plugin_rpc=self.rpc,
defer_refresh_firewall=defer_refresh_firewall)
def _device(self, device, ip, mac_address, rule):
return {'device': device,
'network_id': 'fakenet',
'fixed_ips': [ip],
'mac_address': mac_address,
'security_groups': ['security_group1'],
@ -2588,14 +2630,14 @@ class TestSecurityGroupAgentWithIptables(base.BaseTestCase):
self.assertThat(kwargs['process_input'],
matchers.MatchesRegex(expected_regex))
def _replay_iptables(self, v4_filter, v6_filter):
def _replay_iptables(self, v4_filter, v6_filter, raw):
self._register_mock_call(
['iptables-save', '-c'],
run_as_root=True,
return_value='')
self._register_mock_call(
['iptables-restore', '-c'],
process_input=self._regex(IPTABLES_RAW + IPTABLES_NAT +
process_input=self._regex(raw + IPTABLES_NAT +
IPTABLES_MANGLE + v4_filter),
run_as_root=True,
return_value='')
@ -2605,14 +2647,16 @@ class TestSecurityGroupAgentWithIptables(base.BaseTestCase):
return_value='')
self._register_mock_call(
['ip6tables-restore', '-c'],
process_input=self._regex(v6_filter),
process_input=self._regex(raw + v6_filter),
run_as_root=True,
return_value='')
def test_prepare_remove_port(self):
self.rpc.security_group_rules_for_devices.return_value = self.devices1
self._replay_iptables(IPTABLES_FILTER_1, IPTABLES_FILTER_V6_1)
self._replay_iptables(IPTABLES_FILTER_EMPTY, IPTABLES_FILTER_V6_EMPTY)
self._replay_iptables(IPTABLES_FILTER_1, IPTABLES_FILTER_V6_1,
IPTABLES_RAW_DEFAULT)
self._replay_iptables(IPTABLES_FILTER_EMPTY, IPTABLES_FILTER_V6_EMPTY,
IPTABLES_RAW_DEFAULT)
self.agent.prepare_devices_filter(['tap_port1'])
self.agent.remove_devices_filter(['tap_port1'])
@ -2621,12 +2665,18 @@ class TestSecurityGroupAgentWithIptables(base.BaseTestCase):
def test_security_group_member_updated(self):
self.rpc.security_group_rules_for_devices.return_value = self.devices1
self._replay_iptables(IPTABLES_FILTER_1, IPTABLES_FILTER_V6_1)
self._replay_iptables(IPTABLES_FILTER_1_2, IPTABLES_FILTER_V6_1)
self._replay_iptables(IPTABLES_FILTER_2, IPTABLES_FILTER_V6_2)
self._replay_iptables(IPTABLES_FILTER_2_2, IPTABLES_FILTER_V6_2)
self._replay_iptables(IPTABLES_FILTER_1, IPTABLES_FILTER_V6_1)
self._replay_iptables(IPTABLES_FILTER_EMPTY, IPTABLES_FILTER_V6_EMPTY)
self._replay_iptables(IPTABLES_FILTER_1, IPTABLES_FILTER_V6_1,
IPTABLES_RAW_DEFAULT)
self._replay_iptables(IPTABLES_FILTER_1_2, IPTABLES_FILTER_V6_1,
IPTABLES_RAW_DEFAULT)
self._replay_iptables(IPTABLES_FILTER_2, IPTABLES_FILTER_V6_2,
IPTABLES_RAW_DEFAULT)
self._replay_iptables(IPTABLES_FILTER_2_2, IPTABLES_FILTER_V6_2,
IPTABLES_RAW_DEFAULT)
self._replay_iptables(IPTABLES_FILTER_1, IPTABLES_FILTER_V6_1,
IPTABLES_RAW_DEFAULT)
self._replay_iptables(IPTABLES_FILTER_EMPTY, IPTABLES_FILTER_V6_EMPTY,
IPTABLES_RAW_DEFAULT)
self.agent.prepare_devices_filter(['tap_port1'])
self.rpc.security_group_rules_for_devices.return_value = self.devices2
@ -2641,8 +2691,10 @@ class TestSecurityGroupAgentWithIptables(base.BaseTestCase):
def test_security_group_rule_updated(self):
self.rpc.security_group_rules_for_devices.return_value = self.devices2
self._replay_iptables(IPTABLES_FILTER_2, IPTABLES_FILTER_V6_2)
self._replay_iptables(IPTABLES_FILTER_2_3, IPTABLES_FILTER_V6_2)
self._replay_iptables(IPTABLES_FILTER_2, IPTABLES_FILTER_V6_2,
IPTABLES_RAW_DEFAULT)
self._replay_iptables(IPTABLES_FILTER_2_3, IPTABLES_FILTER_V6_2,
IPTABLES_RAW_DEFAULT)
self.agent.prepare_devices_filter(['tap_port1', 'tap_port3'])
self.rpc.security_group_rules_for_devices.return_value = self.devices3
@ -2713,8 +2765,10 @@ class TestSecurityGroupAgentEnhancedRpcWithIptables(
def test_prepare_remove_port(self):
self.sg_info.return_value = self.devices_info1
self._replay_iptables(IPTABLES_FILTER_1, IPTABLES_FILTER_V6_1)
self._replay_iptables(IPTABLES_FILTER_EMPTY, IPTABLES_FILTER_V6_EMPTY)
self._replay_iptables(IPTABLES_FILTER_1, IPTABLES_FILTER_V6_1,
IPTABLES_RAW_DEFAULT)
self._replay_iptables(IPTABLES_FILTER_EMPTY, IPTABLES_FILTER_V6_EMPTY,
IPTABLES_RAW_DEFAULT)
self.agent.prepare_devices_filter(['tap_port1'])
self.agent.remove_devices_filter(['tap_port1'])
@ -2723,12 +2777,18 @@ class TestSecurityGroupAgentEnhancedRpcWithIptables(
def test_security_group_member_updated(self):
self.sg_info.return_value = self.devices_info1
self._replay_iptables(IPTABLES_FILTER_1, IPTABLES_FILTER_V6_1)
self._replay_iptables(IPTABLES_FILTER_1_2, IPTABLES_FILTER_V6_1)
self._replay_iptables(IPTABLES_FILTER_2, IPTABLES_FILTER_V6_2)
self._replay_iptables(IPTABLES_FILTER_2_2, IPTABLES_FILTER_V6_2)
self._replay_iptables(IPTABLES_FILTER_1, IPTABLES_FILTER_V6_1)
self._replay_iptables(IPTABLES_FILTER_EMPTY, IPTABLES_FILTER_V6_EMPTY)
self._replay_iptables(IPTABLES_FILTER_1, IPTABLES_FILTER_V6_1,
IPTABLES_RAW_DEFAULT)
self._replay_iptables(IPTABLES_FILTER_1_2, IPTABLES_FILTER_V6_1,
IPTABLES_RAW_DEFAULT)
self._replay_iptables(IPTABLES_FILTER_2, IPTABLES_FILTER_V6_2,
IPTABLES_RAW_DEFAULT)
self._replay_iptables(IPTABLES_FILTER_2_2, IPTABLES_FILTER_V6_2,
IPTABLES_RAW_DEFAULT)
self._replay_iptables(IPTABLES_FILTER_1, IPTABLES_FILTER_V6_1,
IPTABLES_RAW_DEFAULT)
self._replay_iptables(IPTABLES_FILTER_EMPTY, IPTABLES_FILTER_V6_EMPTY,
IPTABLES_RAW_DEFAULT)
self.agent.prepare_devices_filter(['tap_port1'])
self.sg_info.return_value = self.devices_info2
@ -2743,8 +2803,10 @@ class TestSecurityGroupAgentEnhancedRpcWithIptables(
def test_security_group_rule_updated(self):
self.sg_info.return_value = self.devices_info2
self._replay_iptables(IPTABLES_FILTER_2, IPTABLES_FILTER_V6_2)
self._replay_iptables(IPTABLES_FILTER_2_3, IPTABLES_FILTER_V6_2)
self._replay_iptables(IPTABLES_FILTER_2, IPTABLES_FILTER_V6_2,
IPTABLES_RAW_DEFAULT)
self._replay_iptables(IPTABLES_FILTER_2_3, IPTABLES_FILTER_V6_2,
IPTABLES_RAW_DEFAULT)
self.agent.prepare_devices_filter(['tap_port1', 'tap_port3'])
self.sg_info.return_value = self.devices_info3
@ -2765,8 +2827,10 @@ class TestSecurityGroupAgentEnhancedIpsetWithIptables(
def test_prepare_remove_port(self):
self.sg_info.return_value = self.devices_info1
self._replay_iptables(IPSET_FILTER_1, IPTABLES_FILTER_V6_1)
self._replay_iptables(IPTABLES_FILTER_EMPTY, IPTABLES_FILTER_V6_EMPTY)
self._replay_iptables(IPSET_FILTER_1, IPTABLES_FILTER_V6_1,
IPTABLES_RAW_DEFAULT)
self._replay_iptables(IPTABLES_FILTER_EMPTY, IPTABLES_FILTER_V6_EMPTY,
IPTABLES_RAW_DEFAULT)
self.agent.prepare_devices_filter(['tap_port1'])
self.agent.remove_devices_filter(['tap_port1'])
@ -2775,12 +2839,18 @@ class TestSecurityGroupAgentEnhancedIpsetWithIptables(
def test_security_group_member_updated(self):
self.sg_info.return_value = self.devices_info1
self._replay_iptables(IPSET_FILTER_1, IPTABLES_FILTER_V6_1)
self._replay_iptables(IPSET_FILTER_1, IPTABLES_FILTER_V6_1)
self._replay_iptables(IPSET_FILTER_2, IPTABLES_FILTER_V6_2)
self._replay_iptables(IPSET_FILTER_2, IPTABLES_FILTER_V6_2)
self._replay_iptables(IPSET_FILTER_1, IPTABLES_FILTER_V6_1)
self._replay_iptables(IPTABLES_FILTER_EMPTY, IPTABLES_FILTER_V6_EMPTY)
self._replay_iptables(IPSET_FILTER_1, IPTABLES_FILTER_V6_1,
IPTABLES_RAW_DEFAULT)
self._replay_iptables(IPSET_FILTER_1, IPTABLES_FILTER_V6_1,
IPTABLES_RAW_DEFAULT)
self._replay_iptables(IPSET_FILTER_2, IPTABLES_FILTER_V6_2,
IPTABLES_RAW_DEFAULT)
self._replay_iptables(IPSET_FILTER_2, IPTABLES_FILTER_V6_2,
IPTABLES_RAW_DEFAULT)
self._replay_iptables(IPSET_FILTER_1, IPTABLES_FILTER_V6_1,
IPTABLES_RAW_DEFAULT)
self._replay_iptables(IPTABLES_FILTER_EMPTY, IPTABLES_FILTER_V6_EMPTY,
IPTABLES_RAW_DEFAULT)
self.agent.prepare_devices_filter(['tap_port1'])
self.sg_info.return_value = self.devices_info2
@ -2795,8 +2865,10 @@ class TestSecurityGroupAgentEnhancedIpsetWithIptables(
def test_security_group_rule_updated(self):
self.sg_info.return_value = self.devices_info2
self._replay_iptables(IPSET_FILTER_2, IPTABLES_FILTER_V6_2)
self._replay_iptables(IPSET_FILTER_2_3, IPTABLES_FILTER_V6_2)
self._replay_iptables(IPSET_FILTER_2, IPTABLES_FILTER_V6_2,
IPTABLES_RAW_DEFAULT)
self._replay_iptables(IPSET_FILTER_2_3, IPTABLES_FILTER_V6_2,
IPTABLES_RAW_DEFAULT)
self.agent.prepare_devices_filter(['tap_port1', 'tap_port3'])
self.sg_info.return_value = self.devices_info3
@ -2858,11 +2930,77 @@ class TestSecurityGroupAgentWithOVSIptables(
FIREWALL_DRIVER = FIREWALL_HYBRID_DRIVER
def setUp(self, defer_refresh_firewall=False, test_rpc_v1_1=True):
super(TestSecurityGroupAgentWithOVSIptables, self).setUp(
defer_refresh_firewall,
test_rpc_v1_1)
def _init_agent(self, defer_refresh_firewall):
fake_map = ovs_neutron_agent.LocalVLANMapping(1, 'network_type',
'physical_network', 1)
local_vlan_map = {'fakenet': fake_map}
self.agent = sg_rpc.SecurityGroupAgentRpc(
context=None, plugin_rpc=self.rpc,
local_vlan_map=local_vlan_map,
defer_refresh_firewall=defer_refresh_firewall)
def test_prepare_remove_port(self):
self.rpc.security_group_rules_for_devices.return_value = self.devices1
self._replay_iptables(IPTABLES_FILTER_1, IPTABLES_FILTER_V6_1,
IPTABLES_RAW_DEVICE_1)
self._replay_iptables(IPTABLES_FILTER_EMPTY, IPTABLES_FILTER_V6_EMPTY,
IPTABLES_RAW_DEFAULT)
self.agent.prepare_devices_filter(['tap_port1'])
self.agent.remove_devices_filter(['tap_port1'])
self._verify_mock_calls()
def test_security_group_member_updated(self):
self.rpc.security_group_rules_for_devices.return_value = self.devices1
self._replay_iptables(IPTABLES_FILTER_1, IPTABLES_FILTER_V6_1,
IPTABLES_RAW_DEVICE_1)
self._replay_iptables(IPTABLES_FILTER_1_2, IPTABLES_FILTER_V6_1,
IPTABLES_RAW_DEVICE_1)
self._replay_iptables(IPTABLES_FILTER_2, IPTABLES_FILTER_V6_2,
IPTABLES_RAW_DEVICE_2)
self._replay_iptables(IPTABLES_FILTER_2_2, IPTABLES_FILTER_V6_2,
IPTABLES_RAW_DEVICE_2)
self._replay_iptables(IPTABLES_FILTER_1, IPTABLES_FILTER_V6_1,
IPTABLES_RAW_DEVICE_1)
self._replay_iptables(IPTABLES_FILTER_EMPTY, IPTABLES_FILTER_V6_EMPTY,
IPTABLES_RAW_DEFAULT)
self.agent.prepare_devices_filter(['tap_port1'])
self.rpc.security_group_rules_for_devices.return_value = self.devices2
self.agent.security_groups_member_updated(['security_group1'])
self.agent.prepare_devices_filter(['tap_port2'])
self.rpc.security_group_rules_for_devices.return_value = self.devices1
self.agent.security_groups_member_updated(['security_group1'])
self.agent.remove_devices_filter(['tap_port2'])
self.agent.remove_devices_filter(['tap_port1'])
self._verify_mock_calls()
def test_security_group_rule_updated(self):
self.rpc.security_group_rules_for_devices.return_value = self.devices2
self._replay_iptables(IPTABLES_FILTER_2, IPTABLES_FILTER_V6_2,
IPTABLES_RAW_DEVICE_2)
self._replay_iptables(IPTABLES_FILTER_2_3, IPTABLES_FILTER_V6_2,
IPTABLES_RAW_DEVICE_2)
self.agent.prepare_devices_filter(['tap_port1', 'tap_port3'])
self.rpc.security_group_rules_for_devices.return_value = self.devices3
self.agent.security_groups_rule_updated(['security_group1'])
self._verify_mock_calls()
def _regex(self, value):
#Note(nati): tap is prefixed on the device
# in the OVSHybridIptablesFirewallDriver
value = value.replace('tap_port', 'taptap_port')
value = value.replace('qvbtaptap_port', 'qvbtap_port')
value = value.replace('o_port', 'otap_port')
value = value.replace('i_port', 'itap_port')
value = value.replace('s_port', 'stap_port')

View File

@ -134,7 +134,9 @@ class TestOvsNeutronAgent(base.BaseTestCase):
mock.patch('neutron.agent.common.ovs_lib.BaseOVS.get_bridges'),
mock.patch('neutron.openstack.common.loopingcall.'
'FixedIntervalLoopingCall',
new=MockFixedIntervalLoopingCall)):
new=MockFixedIntervalLoopingCall),
mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
'get_vif_ports', return_value=[])):
self.agent = ovs_neutron_agent.OVSNeutronAgent(**kwargs)
# set back to true because initial report state will succeed due
# to mocked out RPC calls
@ -157,22 +159,17 @@ class TestOvsNeutronAgent(base.BaseTestCase):
mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
'set_db_attribute', return_value=True),
mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
'db_get_val', return_value=old_local_vlan),
'db_get_val', return_value={}),
mock.patch.object(self.agent.int_br, 'delete_flows')
) as (set_ovs_db_func, get_ovs_db_func, delete_flows_func):
self.agent.port_bound(port, net_uuid, 'local', None, None,
fixed_ips, "compute:None", False)
get_ovs_db_func.assert_called_once_with("Port", mock.ANY, "tag")
if new_local_vlan != old_local_vlan:
set_ovs_db_func.assert_called_once_with(
"Port", mock.ANY, "tag", new_local_vlan)
if ofport != -1:
delete_flows_func.assert_called_once_with(in_port=port.ofport)
else:
self.assertFalse(delete_flows_func.called)
else:
self.assertFalse(set_ovs_db_func.called)
self.assertFalse(delete_flows_func.called)
vlan_mapping = {'net_uuid': net_uuid,
'network_type': 'local',
'physical_network': None,
'segmentation_id': None}
set_ovs_db_func.assert_called_once_with(
"Port", mock.ANY, "other_config", vlan_mapping)
def test_check_agent_configurations_for_dvr_raises(self):
self.agent.enable_distributed_routing = True
@ -339,7 +336,8 @@ class TestOvsNeutronAgent(base.BaseTestCase):
mock.patch.object(self.agent.plugin_rpc, 'update_device_down'),
mock.patch.object(self.agent, func_name)
) as (get_dev_fn, get_vif_func, upd_dev_up, upd_dev_down, func):
skip_devs = self.agent.treat_devices_added_or_updated([{}], False)
skip_devs, need_bound_devices = (
self.agent.treat_devices_added_or_updated([{}], False))
# The function should not raise
self.assertFalse(skip_devs)
return func.called
@ -379,18 +377,13 @@ class TestOvsNeutronAgent(base.BaseTestCase):
return_value=[dev_mock]),
mock.patch.object(self.agent.int_br, 'get_vif_port_by_id',
return_value=None),
mock.patch.object(self.agent.plugin_rpc, 'update_device_up'),
mock.patch.object(self.agent.plugin_rpc, 'update_device_down'),
mock.patch.object(self.agent, 'treat_vif_port')
) as (get_dev_fn, get_vif_func, upd_dev_up,
upd_dev_down, treat_vif_port):
) as (get_dev_fn, get_vif_func, treat_vif_port):
skip_devs = self.agent.treat_devices_added_or_updated([{}], False)
# The function should return False for resync and no device
# processed
self.assertEqual(['the_skipped_one'], skip_devs)
self.assertEqual((['the_skipped_one'], []), skip_devs)
self.assertFalse(treat_vif_port.called)
self.assertFalse(upd_dev_down.called)
self.assertFalse(upd_dev_up.called)
def test_treat_devices_added_updated_put_port_down(self):
fake_details_dict = {'admin_state_up': False,
@ -411,16 +404,13 @@ class TestOvsNeutronAgent(base.BaseTestCase):
return_value=[fake_details_dict]),
mock.patch.object(self.agent.int_br, 'get_vif_port_by_id',
return_value=mock.MagicMock()),
mock.patch.object(self.agent.plugin_rpc, 'update_device_up'),
mock.patch.object(self.agent.plugin_rpc, 'update_device_down'),
mock.patch.object(self.agent, 'treat_vif_port')
) as (get_dev_fn, get_vif_func, upd_dev_up,
upd_dev_down, treat_vif_port):
skip_devs = self.agent.treat_devices_added_or_updated([{}], False)
) as (get_dev_fn, get_vif_func, treat_vif_port):
skip_devs, need_bound_devices = (
self.agent.treat_devices_added_or_updated([{}], False))
# The function should return False for resync
self.assertFalse(skip_devs)
self.assertTrue(treat_vif_port.called)
self.assertTrue(upd_dev_down.called)
def test_treat_devices_removed_returns_true_for_missing_device(self):
with mock.patch.object(self.agent.plugin_rpc, 'update_device_down',
@ -445,7 +435,7 @@ class TestOvsNeutronAgent(base.BaseTestCase):
with contextlib.nested(
mock.patch.object(self.agent.sg_agent, "setup_port_filters"),
mock.patch.object(self.agent, "treat_devices_added_or_updated",
return_value=[]),
return_value=([], [])),
mock.patch.object(self.agent, "treat_devices_removed",
return_value=False)
) as (setup_port_filters, device_added_updated, device_removed):
@ -1267,7 +1257,9 @@ class AncillaryBridgesTest(base.BaseTestCase):
return_value=bridges),
mock.patch('neutron.agent.common.ovs_lib.BaseOVS.'
'get_bridge_external_bridge_id',
side_effect=pullup_side_effect)):
side_effect=pullup_side_effect),
mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
'get_vif_ports', return_value=[])):
self.agent = ovs_neutron_agent.OVSNeutronAgent(**self.kwargs)
self.assertEqual(len(ancillary), len(self.agent.ancillary_brs))
if ancillary:
@ -1326,7 +1318,9 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
mock.patch('neutron.agent.common.ovs_lib.BaseOVS.get_bridges'),
mock.patch('neutron.openstack.common.loopingcall.'
'FixedIntervalLoopingCall',
new=MockFixedIntervalLoopingCall)):
new=MockFixedIntervalLoopingCall),
mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
'get_vif_ports', return_value=[])):
self.agent = ovs_neutron_agent.OVSNeutronAgent(**kwargs)
# set back to true because initial report state will succeed due
# to mocked out RPC calls
@ -1383,13 +1377,14 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
physical_network = self._physical_network
segmentation_id = self._segmentation_id
network_type = p_const.TYPE_VLAN
with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
with contextlib.nested(
mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
'set_db_attribute',
return_value=True):
with contextlib.nested(
return_value=True),
mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
'db_get_val',
return_value=self._old_local_vlan),
return_value={})):
with contextlib.nested(
mock.patch.object(self.agent.dvr_agent.plugin_rpc,
'get_subnet_for_dvr',
return_value={
@ -1398,13 +1393,12 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
'ip_version': ip_version,
'gateway_mac': gateway_mac}),
mock.patch.object(self.agent.dvr_agent.plugin_rpc,
'get_ports_on_host_by_subnet',
return_value=[]),
'get_ports_on_host_by_subnet',
return_value=[]),
mock.patch.object(self.agent.dvr_agent.int_br,
'get_vif_port_by_id',
return_value=self._port),
mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'),
mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'),
mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'),
mock.patch.object(self.agent.dvr_agent.tun_br, 'delete_flows'),
mock.patch.object(
@ -1413,8 +1407,8 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
mock.patch.object(
self.agent.dvr_agent.phys_brs[physical_network],
'delete_flows')
) as (get_ovs_db_func, get_subnet_fn, get_cphost_fn,
get_vif_fn, add_flow_int_fn, delete_flows_int_fn,
) as (get_subnet_fn, get_cphost_fn,
get_vif_fn, add_flow_int_fn,
add_flow_tun_fn, delete_flows_tun_fn, add_flow_phys_fn,
delete_flows_phys_fn):
self.agent.port_bound(
@ -1479,12 +1473,6 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
]
self.assertEqual(expected_on_int_br,
add_flow_int_fn.call_args_list)
expected_on_int_br = [
mock.call(in_port=self._port.ofport),
mock.call(in_port=self._compute_port.ofport)
]
self.assertEqual(expected_on_int_br,
delete_flows_int_fn.call_args_list)
self.assertFalse(add_flow_tun_fn.called)
self.assertFalse(delete_flows_tun_fn.called)
self.assertFalse(delete_flows_phys_fn.called)
@ -1503,13 +1491,14 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
self._compute_port.vif_mac = '77:88:99:00:11:22'
physical_network = self._physical_network
segmentation_id = self._segmentation_id
with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
with contextlib.nested(
mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
'set_db_attribute',
return_value=True):
with contextlib.nested(
return_value=True),
mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
'db_get_val',
return_value=self._old_local_vlan),
return_value={})):
with contextlib.nested(
mock.patch.object(self.agent.dvr_agent.plugin_rpc,
'get_subnet_for_dvr',
return_value={
@ -1524,7 +1513,6 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
'get_vif_port_by_id',
return_value=self._port),
mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'),
mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'),
mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'),
mock.patch.object(self.agent.dvr_agent.tun_br, 'delete_flows'),
mock.patch.object(
@ -1533,8 +1521,8 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
mock.patch.object(
self.agent.dvr_agent.phys_brs[physical_network],
'delete_flows')
) as (get_ovs_db_func, get_subnet_fn, get_cphost_fn,
get_vif_fn, add_flow_int_fn, delete_flows_int_fn,
) as (get_subnet_fn, get_cphost_fn,
get_vif_fn, add_flow_int_fn,
add_flow_tun_fn, delete_flows_tun_fn,
add_flow_phys_fn, delete_flows_phys_fn):
self.agent.port_bound(
@ -1593,12 +1581,6 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
self.assertEqual(expected_on_int_br,
add_flow_int_fn.call_args_list)
self.assertFalse(add_flow_phys_fn.called)
expected_on_int_br = [
mock.call(in_port=self._port.ofport),
mock.call(in_port=self._compute_port.ofport)
]
self.assertEqual(expected_on_int_br,
delete_flows_int_fn.call_args_list)
self.assertFalse(add_flow_phys_fn.called)
self.assertFalse(delete_flows_tun_fn.called)
self.assertFalse(delete_flows_phys_fn.called)
@ -1635,13 +1617,14 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
def test_port_bound_for_dvr_with_csnat_ports(self, ofport=10):
self._setup_for_dvr_test()
with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
with contextlib.nested(
mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
'set_db_attribute',
return_value=True):
with contextlib.nested(
return_value=True),
mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
'db_get_val',
return_value=self._old_local_vlan),
return_value={})):
with contextlib.nested(
mock.patch.object(
self.agent.dvr_agent.plugin_rpc, 'get_subnet_for_dvr',
return_value={'gateway_ip': '1.1.1.1',
@ -1655,11 +1638,10 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
'get_vif_port_by_id',
return_value=self._port),
mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'),
mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'),
mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'),
mock.patch.object(self.agent.dvr_agent.tun_br, 'delete_flows')
) as (get_ovs_db_func, get_subnet_fn, get_cphost_fn,
get_vif_fn, add_flow_int_fn, delete_flows_int_fn,
) as (get_subnet_fn, get_cphost_fn,
get_vif_fn, add_flow_int_fn,
add_flow_tun_fn, delete_flows_tun_fn):
self.agent.port_bound(
self._port, self._net_uuid, 'vxlan',
@ -1667,7 +1649,6 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
n_const.DEVICE_OWNER_ROUTER_SNAT,
False)
self.assertTrue(add_flow_int_fn.called)
self.assertTrue(delete_flows_int_fn.called)
def test_treat_devices_removed_for_dvr_interface(self, ofport=10):
self._test_treat_devices_removed_for_dvr_interface(ofport)
@ -1683,13 +1664,14 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
else:
gateway_ip = '2001:100::1'
cidr = '2001:100::0/64'
with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
with contextlib.nested(
mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
'set_db_attribute',
return_value=True):
with contextlib.nested(
return_value=True),
mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
'db_get_val',
return_value=self._old_local_vlan),
return_value={})):
with contextlib.nested(
mock.patch.object(
self.agent.dvr_agent.plugin_rpc, 'get_subnet_for_dvr',
return_value={'gateway_ip': gateway_ip,
@ -1703,11 +1685,10 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
'get_vif_port_by_id',
return_value=self._port),
mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'),
mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'),
mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'),
mock.patch.object(self.agent.dvr_agent.tun_br, 'delete_flows')
) as (get_ovs_db_func, get_subnet_fn, get_cphost_fn,
get_vif_fn, add_flow_int_fn, delete_flows_int_fn,
) as (get_subnet_fn, get_cphost_fn,
get_vif_fn, add_flow_int_fn,
add_flow_tun_fn, delete_flows_tun_fn):
self.agent.port_bound(
self._port, self._net_uuid, 'vxlan',
@ -1715,7 +1696,6 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
n_const.DEVICE_OWNER_DVR_INTERFACE,
False)
self.assertTrue(add_flow_tun_fn.called)
self.assertTrue(delete_flows_int_fn.called)
with contextlib.nested(
mock.patch.object(self.agent, 'reclaim_local_vlan'),
@ -1764,13 +1744,14 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
else:
gateway_ip = '2001:100::1'
cidr = '2001:100::0/64'
with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
with contextlib.nested(
mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
'set_db_attribute',
return_value=True):
with contextlib.nested(
return_value=True),
mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
'db_get_val',
return_value=self._old_local_vlan),
return_value={})):
with contextlib.nested(
mock.patch.object(
self.agent.dvr_agent.plugin_rpc, 'get_subnet_for_dvr',
return_value={'gateway_ip': gateway_ip,
@ -1784,11 +1765,10 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
'get_vif_port_by_id',
return_value=self._port),
mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'),
mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'),
mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'),
mock.patch.object(self.agent.dvr_agent.tun_br, 'delete_flows')
) as (get_ovs_db_func, get_subnet_fn, get_cphost_fn,
get_vif_fn, add_flow_int_fn, delete_flows_int_fn,
) as (get_subnet_fn, get_cphost_fn,
get_vif_fn, add_flow_int_fn,
add_flow_tun_fn, delete_flows_tun_fn):
self.agent.port_bound(
self._port, self._net_uuid, 'vxlan',
@ -1802,7 +1782,6 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
device_owner, False)
self.assertTrue(add_flow_tun_fn.called)
self.assertTrue(add_flow_int_fn.called)
self.assertTrue(delete_flows_int_fn.called)
with contextlib.nested(
mock.patch.object(self.agent, 'reclaim_local_vlan'),
@ -1841,13 +1820,14 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
def test_treat_devices_removed_for_dvr_csnat_port(self, ofport=10):
self._setup_for_dvr_test()
with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
with contextlib.nested(
mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
'set_db_attribute',
return_value=True):
with contextlib.nested(
return_value=True),
mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
'db_get_val',
return_value=self._old_local_vlan),
return_value={})):
with contextlib.nested(
mock.patch.object(
self.agent.dvr_agent.plugin_rpc, 'get_subnet_for_dvr',
return_value={'gateway_ip': '1.1.1.1',
@ -1861,11 +1841,10 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
'get_vif_port_by_id',
return_value=self._port),
mock.patch.object(self.agent.dvr_agent.int_br, 'add_flow'),
mock.patch.object(self.agent.dvr_agent.int_br, 'delete_flows'),
mock.patch.object(self.agent.dvr_agent.tun_br, 'add_flow'),
mock.patch.object(self.agent.dvr_agent.tun_br, 'delete_flows')
) as (get_ovs_db_func, get_subnet_fn, get_cphost_fn,
get_vif_fn, add_flow_int_fn, delete_flows_int_fn,
) as (get_subnet_fn, get_cphost_fn,
get_vif_fn, add_flow_int_fn,
add_flow_tun_fn, delete_flows_tun_fn):
self.agent.port_bound(
self._port, self._net_uuid, 'vxlan',
@ -1873,7 +1852,6 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
n_const.DEVICE_OWNER_ROUTER_SNAT,
False)
self.assertTrue(add_flow_int_fn.called)
self.assertTrue(delete_flows_int_fn.called)
with contextlib.nested(
mock.patch.object(self.agent, 'reclaim_local_vlan'),

View File

@ -106,6 +106,8 @@ class TunnelTest(base.BaseTestCase):
self.mock_int_bridge.add_port.return_value = self.MAP_TUN_INT_OFPORT
self.mock_int_bridge.add_patch_port.side_effect = (
lambda tap, peer: self.ovs_int_ofports[tap])
self.mock_int_bridge.get_vif_ports.return_value = []
self.mock_int_bridge.db_get_val.return_value = {}
self.mock_map_tun_bridge = self.ovs_bridges[self.MAP_TUN_BRIDGE]
self.mock_map_tun_bridge.br_name = self.MAP_TUN_BRIDGE
@ -190,7 +192,10 @@ class TunnelTest(base.BaseTestCase):
mock.call.add_patch_port('patch-int', 'patch-tun'),
]
self.mock_int_bridge_expected += [
mock.call.add_patch_port('patch-tun', 'patch-int')
mock.call.add_patch_port('patch-tun', 'patch-int'),
]
self.mock_int_bridge_expected += [
mock.call.get_vif_ports(),
]
self.mock_tun_bridge_expected += [
@ -437,12 +442,15 @@ class TunnelTest(base.BaseTestCase):
self._verify_mock_calls()
def test_port_bound(self):
vlan_mapping = {'segmentation_id': LS_ID,
'physical_network': None,
'net_uuid': NET_UUID,
'network_type': 'gre'}
self.mock_int_bridge_expected += [
mock.call.db_get_val('Port', VIF_PORT.port_name, 'tag'),
mock.call.db_get_val('Port', 'port', 'other_config'),
mock.call.set_db_attribute('Port', VIF_PORT.port_name,
'tag', LVM.vlan),
mock.call.delete_flows(in_port=VIF_PORT.ofport)
]
'other_config',
vlan_mapping)]
a = self._build_agent()
a.local_vlan_map[NET_UUID] = LVM
@ -610,7 +618,9 @@ class TunnelTestUseVethInterco(TunnelTest):
self.mock_int_bridge_expected += [
mock.call.add_patch_port('patch-tun', 'patch-int')
]
self.mock_int_bridge_expected += [
mock.call.get_vif_ports(),
]
self.mock_tun_bridge_expected += [
mock.call.remove_all_flows(),
mock.call.add_flow(priority=1,