Fix east_west capture for vlan tenant
With vlan tenant we have mac-mapping configured in ovs db for compute nodes. These MAC values should be used when filtering relevant traffic for east_west communication. Also, introduced separate tunnel_interface config parameter to define an appropriate value when capturing traffic on a normal node and on ovs_pod. Change-Id: Ibef4498604bd9fff7ab537ed276ce59e8a052cd6
This commit is contained in:
parent
a022d38865
commit
048c752ca3
@ -15,7 +15,6 @@
|
|||||||
|
|
||||||
GLOBAL_IP = '1.1.1.1'
|
GLOBAL_IP = '1.1.1.1'
|
||||||
METADATA_SERVICE_IP = '169.254.169.254'
|
METADATA_SERVICE_IP = '169.254.169.254'
|
||||||
NODE_TUNNEL_INTERFACE = 'genev_sys_6081'
|
|
||||||
OVN_MAX_GW_PORTS_PER_ROUTER = 5
|
OVN_MAX_GW_PORTS_PER_ROUTER = 5
|
||||||
NEUTRON_CONF = {
|
NEUTRON_CONF = {
|
||||||
'devstack': '/etc/neutron/neutron.conf',
|
'devstack': '/etc/neutron/neutron.conf',
|
||||||
|
@ -128,6 +128,10 @@ WhiteboxNeutronPluginOptions = [
|
|||||||
default='eth1',
|
default='eth1',
|
||||||
help='Physical interface of a node that is connected to the '
|
help='Physical interface of a node that is connected to the '
|
||||||
'external network.'),
|
'external network.'),
|
||||||
|
cfg.StrOpt('ovs_pod_ext_interface',
|
||||||
|
default='datacentre',
|
||||||
|
help='Interface of a ovs pod (on podified openstack) that is '
|
||||||
|
'connected to the external network.'),
|
||||||
cfg.IntOpt('minbw_placement_nic_kbps_egress',
|
cfg.IntOpt('minbw_placement_nic_kbps_egress',
|
||||||
default=None,
|
default=None,
|
||||||
help='BW configured per NIC for the minimum BW placement '
|
help='BW configured per NIC for the minimum BW placement '
|
||||||
@ -150,6 +154,18 @@ WhiteboxNeutronPluginOptions = [
|
|||||||
help='Interface of a node that intended to pass tenant'
|
help='Interface of a node that intended to pass tenant'
|
||||||
'network traffic. Note: currently only environments with '
|
'network traffic. Note: currently only environments with '
|
||||||
'the same name of the tenant interface are supported'),
|
'the same name of the tenant interface are supported'),
|
||||||
|
cfg.StrOpt('node_tunnel_interface',
|
||||||
|
default='genev_sys_6081',
|
||||||
|
help='Interface of a node that intended to pass tunnelled '
|
||||||
|
'traffic. genev_sys_6081 is default for geneve tenant '
|
||||||
|
'networks but for vlan tenant network this value should '
|
||||||
|
'be updated according to the environment.'),
|
||||||
|
cfg.StrOpt('ovs_pod_tunnel_interface',
|
||||||
|
default='genev_sys_6081',
|
||||||
|
help='Interface of a ovs pod that intended to pass tunnelled '
|
||||||
|
'traffic. genev_sys_6081 is default for geneve tenant '
|
||||||
|
'networks but for vlan tenant network this value should '
|
||||||
|
'be updated according to the environment.'),
|
||||||
cfg.IntOpt('capture_timeout',
|
cfg.IntOpt('capture_timeout',
|
||||||
default=120,
|
default=120,
|
||||||
help='Maximal time for running remote capture, in seconds. '
|
help='Maximal time for running remote capture, in seconds. '
|
||||||
|
@ -182,6 +182,11 @@ class BaseTempestWhiteboxTestCase(base.BaseTempestTestCase):
|
|||||||
return host_name
|
return host_name
|
||||||
return hostname
|
return hostname
|
||||||
|
|
||||||
|
def get_network_type(self, network_id):
|
||||||
|
network_details = self.os_admin.network_client.show_network(
|
||||||
|
network_id)
|
||||||
|
return network_details['network']['provider:network_type']
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_local_ip_from_network(network):
|
def _get_local_ip_from_network(network):
|
||||||
host_ip_addresses = [ifaddresses(iface)[AF_INET][0]['addr']
|
host_ip_addresses = [ifaddresses(iface)[AF_INET][0]['addr']
|
||||||
@ -1055,7 +1060,7 @@ class TrafficFlowTest(BaseTempestWhiteboxTestCase):
|
|||||||
if node['name'] == line.split()[0]:
|
if node['name'] == line.split()[0]:
|
||||||
node['ovs_pod'] = line.split()[1]
|
node['ovs_pod'] = line.split()[1]
|
||||||
|
|
||||||
def _start_captures(self, filters, interface=None):
|
def _start_captures(self, filters, scenario='north_south', interface=None):
|
||||||
for node in self.nodes:
|
for node in self.nodes:
|
||||||
if not (node['is_controller'] or
|
if not (node['is_controller'] or
|
||||||
node['is_compute'] or
|
node['is_compute'] or
|
||||||
@ -1067,18 +1072,27 @@ class TrafficFlowTest(BaseTempestWhiteboxTestCase):
|
|||||||
node['is_controller']):
|
node['is_controller']):
|
||||||
capture_client = self.proxy_host_client
|
capture_client = self.proxy_host_client
|
||||||
command_prefix = "{} rsh {} ".format(self.OC, node['ovs_pod'])
|
command_prefix = "{} rsh {} ".format(self.OC, node['ovs_pod'])
|
||||||
capture_interface = interface if interface else 'datacentre'
|
if interface:
|
||||||
|
capture_interface = interface
|
||||||
|
else:
|
||||||
|
if scenario == 'north_south':
|
||||||
|
capture_interface = WB_CONF.ovs_pod_ext_interface
|
||||||
|
else:
|
||||||
|
capture_interface = WB_CONF.ovs_pod_tunnel_interface
|
||||||
else:
|
else:
|
||||||
capture_client = node['client']
|
capture_client = node['client']
|
||||||
command_prefix = ''
|
command_prefix = ''
|
||||||
if interface:
|
if interface:
|
||||||
capture_interface = interface
|
capture_interface = interface
|
||||||
else:
|
else:
|
||||||
|
if scenario == 'north_south':
|
||||||
capture_interface = WB_CONF.node_ext_interface
|
capture_interface = WB_CONF.node_ext_interface
|
||||||
|
else:
|
||||||
|
capture_interface = WB_CONF.node_tunnel_interface
|
||||||
node['capture'] = capture.TcpdumpCapture(
|
node['capture'] = capture.TcpdumpCapture(
|
||||||
capture_client, capture_interface, filters, command_prefix)
|
capture_client, capture_interface, filters, command_prefix)
|
||||||
self.useFixture(node['capture'])
|
self.useFixture(node['capture'])
|
||||||
time.sleep(10)
|
time.sleep(2)
|
||||||
|
|
||||||
def _stop_captures(self):
|
def _stop_captures(self):
|
||||||
for node in self.nodes:
|
for node in self.nodes:
|
||||||
@ -1116,9 +1130,9 @@ class TrafficFlowTest(BaseTempestWhiteboxTestCase):
|
|||||||
else:
|
else:
|
||||||
raise TypeError(expected_macs)
|
raise TypeError(expected_macs)
|
||||||
|
|
||||||
self._start_captures(filters,
|
self._start_captures(filters, scenario='east_west')
|
||||||
interface=local_constants.NODE_TUNNEL_INTERFACE)
|
|
||||||
self.check_remote_connectivity(ssh_client, dst_ip, ping_count=2)
|
self.check_remote_connectivity(ssh_client, dst_ip, ping_count=2)
|
||||||
|
time.sleep(5)
|
||||||
self._stop_captures()
|
self._stop_captures()
|
||||||
LOG.debug('Expected routing nodes: {}'.format(
|
LOG.debug('Expected routing nodes: {}'.format(
|
||||||
','.join(expected_routing_nodes)))
|
','.join(expected_routing_nodes)))
|
||||||
@ -1345,6 +1359,14 @@ class BaseTempestTestCaseOvn(BaseTempestWhiteboxTestCase):
|
|||||||
output = self.run_on_master_controller(cmd)
|
output = self.run_on_master_controller(cmd)
|
||||||
self.assertEqual(output, '')
|
self.assertEqual(output, '')
|
||||||
|
|
||||||
|
def get_mac_mappings(self, client, physical_network):
|
||||||
|
output = client.exec_command(
|
||||||
|
"sudo ovs-vsctl get open . external_ids:ovn-chassis-mac-"
|
||||||
|
"mappings").strip().replace('"', '').split(',')
|
||||||
|
for value in output:
|
||||||
|
if physical_network in value:
|
||||||
|
return value.replace(physical_network + ':', '')
|
||||||
|
|
||||||
|
|
||||||
class BaseDisruptiveTempestTestCase(BaseTempestWhiteboxTestCase):
|
class BaseDisruptiveTempestTestCase(BaseTempestWhiteboxTestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -123,9 +123,7 @@ class OvnDvrBase(base.TrafficFlowTest, base.BaseTempestTestCaseOvn):
|
|||||||
# on environments that schedule ovn routers on compute nodes
|
# on environments that schedule ovn routers on compute nodes
|
||||||
self.exclude_hosts = [self.chassis_name]
|
self.exclude_hosts = [self.chassis_name]
|
||||||
|
|
||||||
network_details = self.os_admin.network_client.show_network(
|
if self.get_network_type(self.network['id']) == 'vlan':
|
||||||
self.network['id'])
|
|
||||||
if network_details['network']['provider:network_type'] == 'vlan':
|
|
||||||
# This helps to avoid false positives with vlan+dvr,see BZ2192633
|
# This helps to avoid false positives with vlan+dvr,see BZ2192633
|
||||||
self.ignore_outbound = True
|
self.ignore_outbound = True
|
||||||
else:
|
else:
|
||||||
@ -534,10 +532,29 @@ class OvnDvrTest(OvnDvrBase):
|
|||||||
device_owner=constants.DEVICE_OWNER_ROUTER_INTF,
|
device_owner=constants.DEVICE_OWNER_ROUTER_INTF,
|
||||||
network_id=networks[i]['id'])['ports'][0]['mac_address'])
|
network_id=networks[i]['id'])['ports'][0]['mac_address'])
|
||||||
|
|
||||||
|
def get_mac_mapping_for_vm(vm):
|
||||||
|
return self.get_mac_mappings(
|
||||||
|
self.find_node_client(
|
||||||
|
self.get_host_for_server(vm['server']['id'])),
|
||||||
|
'datacentre')
|
||||||
|
|
||||||
|
def get_expected_macs_for_vlan_tenant():
|
||||||
|
return [
|
||||||
|
(servers[0]['port']['mac_address'],
|
||||||
|
get_mac_mapping_for_vm(servers[1])),
|
||||||
|
(get_mac_mapping_for_vm(servers[0]),
|
||||||
|
servers[1]['port']['mac_address'])]
|
||||||
|
|
||||||
# verify E/W connection between servers
|
# verify E/W connection between servers
|
||||||
|
if self.get_network_type(networks[0]['id']) == 'vlan' and \
|
||||||
|
self.get_network_type(networks[1]['id']) == 'vlan':
|
||||||
|
ew_expected_macs = get_expected_macs_for_vlan_tenant()
|
||||||
|
else:
|
||||||
ew_expected_macs = [
|
ew_expected_macs = [
|
||||||
(servers[0]['port']['mac_address'], router_port_subnet_macs[0]),
|
(servers[0]['port']['mac_address'],
|
||||||
(router_port_subnet_macs[1], servers[1]['port']['mac_address'])]
|
router_port_subnet_macs[0]),
|
||||||
|
(router_port_subnet_macs[1],
|
||||||
|
servers[1]['port']['mac_address'])]
|
||||||
# remove duplicates
|
# remove duplicates
|
||||||
expected_routing_nodes = list(set([host for host in servers_host]))
|
expected_routing_nodes = list(set([host for host in servers_host]))
|
||||||
if len(expected_routing_nodes) == 1:
|
if len(expected_routing_nodes) == 1:
|
||||||
@ -581,6 +598,13 @@ class OvnDvrTest(OvnDvrBase):
|
|||||||
ssh_client=servers_ssh_client[i])
|
ssh_client=servers_ssh_client[i])
|
||||||
|
|
||||||
# verify E/W connection between servers
|
# verify E/W connection between servers
|
||||||
|
# Since with vlan tenant we have MAC mapping on compute nodes
|
||||||
|
# and VMs migrated, we need to retrieve MAC address combination
|
||||||
|
# for filtering again
|
||||||
|
if self.get_network_type(networks[0]['id']) == 'vlan' and \
|
||||||
|
self.get_network_type(networks[1]['id']) == 'vlan':
|
||||||
|
ew_expected_macs = get_expected_macs_for_vlan_tenant()
|
||||||
|
|
||||||
# remove duplicates
|
# remove duplicates
|
||||||
expected_routing_nodes = list(set([host for host in new_servers_host]))
|
expected_routing_nodes = list(set([host for host in new_servers_host]))
|
||||||
if len(expected_routing_nodes) == 1:
|
if len(expected_routing_nodes) == 1:
|
||||||
|
Loading…
Reference in New Issue
Block a user