diff --git a/neutron_tempest_plugin/common/ip.py b/neutron_tempest_plugin/common/ip.py index 1702bd31..265adf72 100644 --- a/neutron_tempest_plugin/common/ip.py +++ b/neutron_tempest_plugin/common/ip.py @@ -15,6 +15,7 @@ # under the License. import collections +import re import subprocess import netaddr @@ -299,6 +300,23 @@ def _get_ip_address_prefix_len_pairs(port, subnets): netaddr.IPNetwork(subnet['cidr']).prefixlen) +def arp_table(): + # 192.168.0.16 0x1 0x2 dc:a6:32:06:56:51 * enp0s31f6 + regex_str = (r"([^ ]+)\s+(0x\d+)\s+(0x\d+)\s+(\w{2}\:\w{2}\:\w{2}\:\w{2}\:" + r"\w{2}\:\w{2})\s+([\w+\*]+)\s+([\-\w]+)") + regex = re.compile(regex_str) + arp_table = [] + with open('/proc/net/arp', 'r') as proc_file: + for line in proc_file.readlines(): + m = regex.match(line) + if m: + arp_table.append(ARPregister( + ip_address=m.group(1), hw_type=m.group(2), + flags=m.group(3), mac_address=m.group(4), + mask=m.group(5), device=m.group(6))) + return arp_table + + class Route(HasProperties, collections.namedtuple('Route', ['dest', 'properties'])): @@ -314,3 +332,19 @@ class Route(HasProperties, @property def src_ip(self): return netaddr.IPAddress(self.src) + + def __str__(self): + properties_str = ' '.join('%s %s' % (k, v) + for k, v in self.properties.items()) + return '%(dest)s %(properties)s' % {'dest': self.dest, + 'properties': properties_str} + + +class ARPregister(collections.namedtuple( + 'ARPregister', + ['ip_address', 'hw_type', 'flags', 'mac_address', 'mask', 'device'])): + + def __str__(self): + return '%s %s %s %s %s %s' % (self.ip_address, self.hw_type, + self.flags, self.mac_address, self.mask, + self.device) diff --git a/neutron_tempest_plugin/scenario/base.py b/neutron_tempest_plugin/scenario/base.py index 5a29aa1e..7204a0b4 100644 --- a/neutron_tempest_plugin/scenario/base.py +++ b/neutron_tempest_plugin/scenario/base.py @@ -26,6 +26,7 @@ from tempest.lib.common.utils import test_utils from tempest.lib import exceptions as lib_exc from neutron_tempest_plugin.api import base as base_api +from neutron_tempest_plugin.common import ip as ip_utils from neutron_tempest_plugin.common import shell from neutron_tempest_plugin.common import ssh from neutron_tempest_plugin import config @@ -219,6 +220,7 @@ class BaseTempestTestCase(base_api.BaseNetworkTest): except lib_exc.SSHTimeout as ssh_e: LOG.debug(ssh_e) self._log_console_output(servers) + self._log_local_network_status() raise def _log_console_output(self, servers=None): @@ -239,6 +241,12 @@ class BaseTempestTestCase(base_api.BaseNetworkTest): LOG.debug("Server %s disappeared(deleted) while looking " "for the console log", server['id']) + def _log_local_network_status(self): + local_routes = ip_utils.IPCommand().list_routes() + LOG.debug('Local routes:\n%s', '\n'.join(str(r) for r in local_routes)) + arp_table = ip_utils.arp_table() + LOG.debug('Local ARP table:\n%s', '\n'.join(str(r) for r in arp_table)) + def _check_remote_connectivity(self, source, dest, count, should_succeed=True, nic=None, mtu=None, fragmentation=True,