Skip to content

Instantly share code, notes, and snippets.

@cloudnull
Created April 24, 2019 02:43
Show Gist options
  • Save cloudnull/bd03516e768b5dee47e51d93b53ea7c8 to your computer and use it in GitHub Desktop.
Save cloudnull/bd03516e768b5dee47e51d93b53ea7c8 to your computer and use it in GitHub Desktop.
simple ansible traceraoute callback plugin used to run a traceroute whenever a node is "UNREACHABLE".
from __future__ import absolute_import
__metaclass__ = type
import socket
import time
from traceroute.core import Tracer
from ansible import constants as C
from ansible.plugins.callback import CallbackBase
DOCUMENTATION = '''
callback: 'null'
callback_type: stdout
requirements:
- set as main display callback
short_description: Traceroute to `ansible_host` on failure.
version_added: "2.7"
description:
- This callback plugin will run a traceroute whenever a node becomes "unreachable".
'''
class PyTracer(Tracer):
def run(self):
results = list()
try:
dst_ip = socket.gethostbyname(self.dst)
except socket.error as e:
raise IOError('Unable to resolve {}: {}', self.dst, e)
text = 'traceroute to {} ({}), {} hops max'.format(
self.dst,
dst_ip,
self.hops
)
results.append(text)
while True:
startTimer = time.time()
receiver = self.create_receiver()
sender = self.create_sender()
sender.sendto(b'', (self.dst, self.port))
addr = None
try:
data, addr = receiver.recvfrom(1024)
entTimer = time.time()
except socket.error:
pass
finally:
receiver.close()
sender.close()
if addr:
address = addr[0]
timeCost = round((entTimer - startTimer) * 1000, 2)
results.append('{:<4} {} {} ms'.format(self.ttl, address, timeCost))
if address == dst_ip:
break
else:
print('{:<4} *'.format(self.ttl))
self.ttl += 1
if self.ttl > self.hops:
break
return results
class CallbackModule(CallbackBase):
CALLBACK_VERSION = 2.0
CALLBACK_TYPE = 'notification'
CALLBACK_NAME = 'traceroute'
CALLBACK_NEEDS_WHITELIST = False
def _traceroute(self, host_address, hostname):
tracer = PyTracer(
dst=host_address,
hops=int(8)
)
traced = tracer.run()
self._display.display(
"Traceroute to [{}] => {}".format(
hostname,
'\n'.join(traced)
),
color=C.COLOR_ERROR,
stderr=True
)
def v2_runner_on_unreachable(self, result, **kwargs):
delegated_vars = result._result.get('_ansible_delegated_vars', None)
if delegated_vars:
self._traceroute(
host_address=delegated_vars['ansible_host'],
hostname=result._host.get_name()
)
else:
self._traceroute(
host_address=result._host.vars['ansible_host'],
hostname=result._host.get_name()
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment