zuul-jobs/roles/validate-host/library/zuul_debug_info.py
Ian Wienand b02035f429 Log output and exception when traceroute fails
These traceroutes currently fail in a very opaque way.  We are
occasionally seeing Fedora nodes fail in here (which is odd, because
obviously networking is up enough for zuul to connect) and don't have
much to go on.

When an exception is caught, add the output, return code and basic
traceback to the return attributes, and include them in the failure
case.

Depends-On: https://review.openstack.org/563702
Change-Id: I047bf2b1daa22a5b6bfc12b3f42b108975097409
2018-06-20 09:44:53 +00:00

105 lines
3.6 KiB
Python

#!/usr/bin/python
# Copyright (c) 2017 Red Hat
#
# This module is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this software. If not, see <http://www.gnu.org/licenses/>.
import os
import shlex
import subprocess
import traceback
command_map = {
'uname': 'uname -a',
'network_interfaces': 'ip address show',
'network_routing_v4': 'ip route show',
'network_routing_v6': 'ip -6 route show',
'network_neighbors': 'ip neighbor show',
}
def run_command(command):
env = os.environ.copy()
env['PATH'] = '{path}:/sbin:/usr/sbin'.format(path=env['PATH'])
return subprocess.check_output(
shlex.split(command),
stderr=subprocess.STDOUT,
env=env)
def main():
module = AnsibleModule(
argument_spec=dict(
image_manifest=dict(required=False, type='str'),
image_manifest_files=dict(required=False, type='list'),
traceroute_host=dict(required=False, type='str'),
)
)
image_manifest = module.params['image_manifest']
traceroute_host = module.params['traceroute_host']
image_manifest_files = module.params['image_manifest_files']
if not image_manifest_files and image_manifest:
image_manifest_files = [image_manifest]
ret = {'image_manifest_files': [], 'traceroute': None}
for image_manifest in image_manifest_files:
if image_manifest and os.path.exists(image_manifest):
ret['image_manifest_files'].append({
'filename': image_manifest,
# Do this in python cause it's easier than in jinja2
'underline': len(image_manifest) * '-',
'content': open(image_manifest, 'r').read(),
})
if traceroute_host:
passed = False
try:
ret['traceroute_v6'] = run_command(
'traceroute6 -n {host}'.format(host=traceroute_host))
passed = True
except (subprocess.CalledProcessError, OSError) as e:
ret['traceroute_v6_exception'] = traceback.format_exc(e)
ret['traceroute_v6_output'] = e.output
ret['traceroute_v6_return'] = e.returncode
pass
try:
ret['traceroute_v4'] = run_command(
'traceroute -n {host}'.format(host=traceroute_host))
passed = True
except (subprocess.CalledProcessError, OSError) as e:
ret['traceroute_v4_exception'] = traceback.format_exc(e)
ret['traceroute_v4_output'] = e.output
ret['traceroute_v4_return'] = e.returncode
pass
if not passed:
module.fail_json(
msg="No viable v4 or v6 route found to {traceroute_host}."
" The build node is assumed to be invalid.".format(
traceroute_host=traceroute_host), **ret)
for key, command in command_map.items():
try:
ret[key] = run_command(command)
except subprocess.CalledProcessError:
pass
module.exit_json(changed=False, _zuul_nolog_return=True, **ret)
from ansible.module_utils.basic import * # noqa
from ansible.module_utils.basic import AnsibleModule
if __name__ == '__main__':
main()