Created
April 24, 2019 02:43
-
-
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".
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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