diff --git a/lib/ansible/modules/network/vyos/vyos_ping.py b/lib/ansible/modules/network/vyos/vyos_ping.py new file mode 100644 index 00000000000..7afdff6691b --- /dev/null +++ b/lib/ansible/modules/network/vyos/vyos_ping.py @@ -0,0 +1,246 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# (c) 2017, Ansible by Red Hat, inc +# +# This file is part of Ansible by Red Hat +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see . +# + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + +DOCUMENTATION = """ +--- +module: vyos_ping +short_description: Tests reachability using ping from VyOS network devices +description: + - Tests reachability using ping from a VyOS device to a remote destination. + - Tested against VyOS 1.1.8 (helium) + - For a general purpose network module, see the M(net_ping) module. + - For Windows targets, use the M(win_ping) module instead. + - For targets running Python, use the M(ping) module instead. +author: + - Nilashish Chakraborty (@nilashishc) +version_added: '2.8' +options: + dest: + description: + - The IP Address or hostname (resolvable by the device) of the remote node. + required: true + count: + description: + - Number of packets to send to check reachability. + type: int + default: 5 + source: + description: + - The source interface or IP Address to use while sending the ping packet(s). + ttl: + description: + - The time-to-live value for the ICMP packet(s). + type: int + size: + description: + - Determines the size (in bytes) of the ping packet(s). + type: int + interval: + description: + - Determines the interval (in seconds) between consecutive pings. + type: int + state: + description: + - Determines if the expected result is success or fail. + choices: [ absent, present ] + default: present +notes: + - For a general purpose network module, see the M(net_ping) module. + - For Windows targets, use the M(win_ping) module instead. + - For targets running Python, use the M(ping) module instead. +extends_documentation_fragment: vyos +""" + +EXAMPLES = """ +- name: Test reachability to 10.10.10.10 + vyos_ping: + dest: 10.10.10.10 + +- name: Test reachability to 10.20.20.20 using source and ttl set + vyos_ping: + dest: 10.20.20.20 + source: eth0 + ttl: 128 + +- name: Test unreachability to 10.30.30.30 using interval + vyos_ping: + dest: 10.30.30.30 + interval: 3 + state: absent + +- name: Test reachability to 10.40.40.40 setting count and source + vyos_ping: + dest: 10.40.40.40 + source: eth1 + count: 20 + size: 512 +""" + +RETURN = """ +commands: + description: List of commands sent. + returned: always + type: list + sample: ["ping 10.8.38.44 count 10 interface eth0 ttl 128"] +packet_loss: + description: Percentage of packets lost. + returned: always + type: str + sample: "0%" +packets_rx: + description: Packets successfully received. + returned: always + type: int + sample: 20 +packets_tx: + description: Packets successfully transmitted. + returned: always + type: int + sample: 20 +rtt: + description: The round trip time (RTT) stats. + returned: when ping succeeds + type: dict + sample: {"avg": 2, "max": 8, "min": 1, "mdev": 24} +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.network.vyos.vyos import run_commands +from ansible.module_utils.network.vyos.vyos import vyos_argument_spec +import re + + +def main(): + """ main entry point for module execution + """ + argument_spec = dict( + count=dict(type="int", default=5), + dest=dict(type="str", required=True), + source=dict(type="str"), + ttl=dict(type='int'), + size=dict(type='int'), + interval=dict(type='int'), + state=dict(type="str", choices=["absent", "present"], default="present"), + ) + + argument_spec.update(vyos_argument_spec) + + module = AnsibleModule(argument_spec=argument_spec) + + count = module.params["count"] + dest = module.params["dest"] + source = module.params["source"] + size = module.params["size"] + ttl = module.params["ttl"] + interval = module.params["interval"] + + warnings = list() + + results = {} + if warnings: + results["warnings"] = warnings + + results["commands"] = [build_ping(dest, count, size, interval, source, ttl)] + + ping_results = run_commands(module, commands=results["commands"]) + ping_results_list = ping_results[0].split("\n") + + rtt_info, rate_info = None, None + for line in ping_results_list: + if line.startswith('rtt'): + rtt_info = line + if line.startswith('%s packets transmitted' % count): + rate_info = line + + if rtt_info: + rtt = parse_rtt(rtt_info) + for k, v in rtt.items(): + if rtt[k] is not None: + rtt[k] = int(v) + results["rtt"] = rtt + + pkt_loss, rx, tx = parse_rate(rate_info) + results["packet_loss"] = str(pkt_loss) + "%" + results["packets_rx"] = int(rx) + results["packets_tx"] = int(tx) + + validate_results(module, pkt_loss, results) + + module.exit_json(**results) + + +def build_ping(dest, count, size=None, interval=None, source=None, ttl=None): + cmd = "ping {0} count {1}".format(dest, str(count)) + + if source: + cmd += " interface {0}".format(source) + + if ttl: + cmd += " ttl {0}".format(str(ttl)) + + if size: + cmd += " size {0}".format(str(size)) + + if interval: + cmd += " interval {0}".format(str(interval)) + + return cmd + + +def parse_rate(rate_info): + rate_re = re.compile( + r"(?P\d+) (?:\w+) (?:\w+), (?P\d+) (?:\w+), (?P\d+)% (?:\w+) (?:\w+), (?:\w+) (?P