b02035f429
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
105 lines
3.6 KiB
Python
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()
|