Dump basic network info in the test_network_basic_ops
Add minimal debug debug capability for basic network informations,
These information, especially the nat rules in the router namespaces
usually very helpful.
Change-Id: I8840cb5e388fc8b674b66f8de4e25754ccbe0863
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 8d96858..e8f898d 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -409,3 +409,7 @@
log_check_interval = 60
# The default number of threads created while stress test
default_thread_number_per_action=4
+
+[debug]
+# Enable diagnostic commands
+enable = True
diff --git a/tempest/common/commands.py b/tempest/common/commands.py
new file mode 100644
index 0000000..4fc85b6
--- /dev/null
+++ b/tempest/common/commands.py
@@ -0,0 +1,76 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import shlex
+import subprocess
+
+from tempest.openstack.common import log as logging
+
+LOG = logging.getLogger(__name__)
+
+# NOTE(afazekas):
+# These commands assumes the tempest node is the same as
+# the only one service node. all-in-one installation.
+
+
+def sudo_cmd_call(cmd):
+ args = shlex.split(cmd)
+ subprocess_args = {'stdout': subprocess.PIPE,
+ 'stderr': subprocess.STDOUT}
+ try:
+ proc = subprocess.Popen(['/usr/bin/sudo'] + args, **subprocess_args)
+ return proc.communicate()[0]
+ if proc.returncode != 0:
+ LOG.error(cmd + "returned with: " +
+ proc.returncode + "exit status")
+ except subprocess.CalledProcessError as e:
+ LOG.error("command output:\n%s" % e.output)
+
+
+def ip_addr_raw():
+ return sudo_cmd_call("ip a")
+
+
+def ip_route_raw():
+ return sudo_cmd_call("ip r")
+
+
+def ip_ns_raw():
+ return sudo_cmd_call("ip netns list")
+
+
+def iptables_raw(table):
+ return sudo_cmd_call("iptables -v -S -t " + table)
+
+
+def ip_ns_list():
+ return ip_ns_raw().split()
+
+
+def ip_ns_exec(ns, cmd):
+ return sudo_cmd_call(" ".join(("ip netns exec", ns, cmd)))
+
+
+def ip_ns_addr(ns):
+ return ip_ns_exec(ns, "ip a")
+
+
+def ip_ns_route(ns):
+ return ip_ns_exec(ns, "ip r")
+
+
+def iptables_ns(ns, table):
+ return ip_ns_exec(ns, "iptables -v -S -t " + table)
diff --git a/tempest/common/debug.py b/tempest/common/debug.py
new file mode 100644
index 0000000..69c933c
--- /dev/null
+++ b/tempest/common/debug.py
@@ -0,0 +1,41 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.common import commands
+from tempest import config
+
+from tempest.openstack.common import log as logging
+
+LOG = logging.getLogger(__name__)
+
+tables = ['filter', 'nat', 'mangle']
+
+
+def log_ip_ns():
+ if not config.TempestConfig().debug.enable:
+ return
+ LOG.info("Host Addr:\n" + commands.ip_addr_raw())
+ LOG.info("Host Route:\n" + commands.ip_route_raw())
+ for table in ['filter', 'nat', 'mangle']:
+ LOG.info('Host %s table:\n%s', table, commands.iptables_raw(table))
+ ns_list = commands.ip_ns_list()
+ LOG.info("Host ns list" + str(ns_list))
+ for ns in ns_list:
+ LOG.info("ns(%s) Addr:\n%s", ns, commands.ip_ns_addr(ns))
+ LOG.info("ns(%s) Route:\n%s", ns, commands.ip_ns_route(ns))
+ for table in ['filter', 'nat', 'mangle']:
+ LOG.info('ns(%s) table(%s):\n%s', ns, table,
+ commands.iptables_ns(ns, table))
diff --git a/tempest/config.py b/tempest/config.py
index 7245b10..ce87bc6 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -609,6 +609,21 @@
for opt in ServiceAvailableGroup:
conf.register_opt(opt, group='service_available')
+debug_group = cfg.OptGroup(name="debug",
+ title="Debug System")
+
+DebugGroup = [
+ cfg.BoolOpt('enable',
+ default=True,
+ help="Enable diagnostic commands"),
+]
+
+
+def register_debug_opts(conf):
+ conf.register_group(debug_group)
+ for opt in DebugGroup:
+ conf.register_opt(opt, group='debug')
+
@singleton
class TempestConfig:
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 930ffae..7ea0353 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -17,6 +17,7 @@
# under the License.
from tempest.api.network import common as net_common
+from tempest.common import debug
from tempest.common.utils.data_utils import rand_name
from tempest import config
from tempest.openstack.common import log as logging
@@ -245,10 +246,17 @@
# key-based authentication by cloud-init.
ssh_login = self.config.compute.image_ssh_user
private_key = self.keypairs[self.tenant_id].private_key
- for server, floating_ips in self.floating_ips.iteritems():
- for floating_ip in floating_ips:
- ip_address = floating_ip.floating_ip_address
- self._check_vm_connectivity(ip_address, ssh_login, private_key)
+ try:
+ for server, floating_ips in self.floating_ips.iteritems():
+ for floating_ip in floating_ips:
+ ip_address = floating_ip.floating_ip_address
+ self._check_vm_connectivity(ip_address,
+ ssh_login,
+ private_key)
+ except Exception as exc:
+ LOG.exception(exc)
+ debug.log_ip_ns()
+ raise exc
@attr(type='smoke')
def test_network_basic_ops(self):