├── .gitattributes ├── README.md ├── callback_plugins ├── installer_checkpoint.py └── installer_checkpoint.pyc ├── files ├── tcpClient.py ├── tcpServer.py ├── udpClient.py └── udpServer.py ├── inventory ├── lookup_plugins ├── ip.py └── ip.pyc ├── main.yaml ├── port_definition.yaml └── tasks ├── init_phases.yaml ├── loop_phase_from_clients.yaml ├── loop_phase_to_server.yaml ├── register_test_result.yaml ├── server_check.yaml ├── start_port_check.yaml ├── start_to_servers.yaml ├── tcp_from_clients.yaml ├── tcp_to_server.yaml ├── udp_from_clients.yaml └── udp_to_server.yaml /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ansible Playbook for network port checking from host level - OpenShift as example 2 | 3 | It has been a long time that we always having issues when deploying an application and firewalls are not ready yet.  4 | 5 | There is plenty of ways of testing network connectivities, such as using telnet or nc. 6 | 7 | However all these has its own problem 8 | 9 | * Telnet requires installing packages which may not be by default installed 10 | * Telnet requires the target service to be up and running 11 | * nc requires installation of netcat package which may consider as not secure 12 | * nc works well for tcp, but for udp, it will fail if the firewall rule is drop packet instead of reject 13 | 14 | There are several other approaches, and most of the approaches are either requires installation of additional packages nor needs the service to be already installed. 15 | 16 | Checking network connectivity before actually spend effort to install large applications such as EAP, Openshift, Openstack or other applications that require large number of ports for communication becomes a difficult task in real world. 17 | 18 | 19 | ## Design principles 20 | 21 | * Minimum requirements for managing node and managed node 22 | * Test of TCP and UDP 23 | * Allow checking from groups of client to groups of servers 24 | * Target services does not have to start 25 | 26 | ## Requirements 27 | 28 | * Python in both managing node and managed node 29 | * The testing port is not binding (that is the actual service is not up and running yet) 30 | 31 | 32 | ## How it works 33 | 34 | This playbook will basically starts the server application which is a simple python scripts at server side and then starts the python clients trying to send a simple message to server. The client will ensure that a reply is received. 35 | 36 | 37 | After all clients has sent it message, we will check the server and see how many clients have connected to it since it starts. 38 | 39 | 40 | By this way we can make the connectivity green. And all the others not being able to connect will be marked as fail – red. 41 | 42 | ## Play book structure 43 | 44 | ``` 45 | |- callback_plugins 46 | | | - installer_checkpoint.py 47 | | | - installer_checkpoint.pyc 48 | | - files 49 | | | - tcpClient.py 50 | | | - tcpServer.py 51 | | | - udpClient.py 52 | | | - udpServer.py 53 | | - inventory 54 | | - lookup_plugins 55 | | | - ip.py 56 | | | - ip.pyc 57 | | - main.yaml 58 | | - port_definition.yaml 59 | | - tasks 60 | | - init_phases.yaml 61 | | - loop_phase_from_clients.yaml 62 | | - loop_phase_to_server.yaml 63 | | - register_test_result.yaml 64 | | - server_check.yaml 65 | | - start_port_check.yaml 66 | | - start_to_servers.yaml 67 | | - tcp_from_clients.yaml 68 | | - tcp_to_server.yaml 69 | | - udp_from_clients.yaml 70 | | - udp_to_server.yaml 71 | 72 | ``` 73 | 74 | ## How to use: 75 | 1. Fill in the inventory as usual, grouping the nodes by zone or by nature. For example, Openshift groups the hosts into masters, nodes 76 | 2. Fill in the port_definition.yaml for the ports to be scanned 77 | 3. Run the playbook as usual 78 | 79 | 80 | 81 | ## Example port_definition.yaml 82 | 83 | ```yaml 84 | port_definitions: 85 | - from_group: nodes 86 | to_group: nodes 87 | type: udp 88 | port: 4789 89 | - from_group: nodes 90 | to_group: masters 91 | type: udp 92 | port: 8053 93 | - from_group: nodes 94 | to_group: masters 95 | type: tcp 96 | port: 8053 97 | - from_group: nodes 98 | to_group: masters 99 | type: tcp 100 | port: 8443 101 | - from_group: masters 102 | to_group: nodes 103 | type: tcp 104 | port: 10250 105 | - from_group: masters 106 | to_group: nodes 107 | type: tcp 108 | port: 10010 109 | - from_group: masters 110 | to_group: masters 111 | type: udp 112 | port: 8053 113 | 114 | # Optional for NFS 115 | - from_group: masters 116 | to_group: masters 117 | type: udp 118 | port: 2049 119 | 120 | 121 | - from_group: masters 122 | to_group: masters 123 | type: tcp 124 | port: 2379 125 | - from_group: masters 126 | to_group: masters 127 | type: tcp 128 | port: 2380 129 | 130 | ################ addition for 3.11 prometheus monitoring 131 | - from_group: nodes 132 | to_group: nodes 133 | type: tcp 134 | port: 9100 135 | 136 | - from_group: nodes 137 | to_group: nodes 138 | type: tcp 139 | port: 10250 140 | 141 | - from_group: nodes 142 | to_group: nodes 143 | type: udp 144 | port: 8444 145 | 146 | ``` 147 | 148 | ## Technical skill worth note taking 149 | 150 | ### Customizing ansible set_stats callback 151 | In order to generate a report for all the ports we scanned, we will use the 152 | set_stats callback and allow ansible to print out a report after the playbook runs 153 | 154 | ### Customizing ansible loopup module 155 | 156 | To check the ip of the hostname maps to, we used customized loop up plugin instead of using ansible gathered fact for the reason that we only need to know which ip is the host actually mapped to when there is multiple network devices 157 | 158 | ## To be improved 159 | 160 | ### Performance 161 | 162 | In current design, the whole process is flat looping all the node recursively, so the performance order is n to the power 3. Which is not a perfect way. Will think for more ways to improve the performance 163 | 164 | ### Check multi-cast 165 | 166 | Multi-cast testing is needed for some of the clustering application but they are not being tested in the playbook. I believe multi-cast ports to be used are not as many as tcp and udp one. But will still consider to improve this by adding this function 167 | 168 | 169 | ## Feedback 170 | 171 | https://github.com/apoletics/ansible-network-check 172 | -------------------------------------------------------------------------------- /callback_plugins/installer_checkpoint.py: -------------------------------------------------------------------------------- 1 | """Ansible callback plugin to print a summary completion status of installation 2 | phases. 3 | """ 4 | from datetime import datetime 5 | from ansible.plugins.callback import CallbackBase 6 | from ansible import constants as C 7 | 8 | 9 | class CallbackModule(CallbackBase): 10 | """This callback summarizes installation phase status.""" 11 | 12 | CALLBACK_VERSION = 2.0 13 | CALLBACK_TYPE = 'aggregate' 14 | CALLBACK_NAME = 'installer_checkpoint' 15 | CALLBACK_NEEDS_WHITELIST = False 16 | 17 | def __init__(self): 18 | super(CallbackModule, self).__init__() 19 | 20 | def v2_playbook_on_stats(self, stats): 21 | 22 | # Return if there are no custom stats to process 23 | if stats.custom == {}: 24 | return 25 | 26 | phases = stats.custom['_run'] 27 | 28 | ordered_phases = sorted(phases, key=lambda x: (phases[x].get('from', ''),phases[x].get('to', ''),phases[x].get('protocol', ''), phases[x].get('port', ''), phases[x].get('result', '') )) 29 | 30 | self._display.banner('NETWORK CHECK REPORT') 31 | # Display status information for each phase 32 | for phase in ordered_phases: 33 | phase_protocol = str(phases[phase].get('protocol', '')).upper() 34 | phase_from = phases[phase].get('from', '') 35 | phase_to = phases[phase].get('to', '') 36 | phase_port = phases[phase].get('port', '') 37 | phase_result = phases[phase].get('result', '') 38 | if phase_protocol: 39 | self._display.display( 40 | 'FROM:{}, TO:{}, PROT:{}, PORT:{}, RESULT:{} '.format(phase_from, phase_to,phase_protocol, phase_port, phase_result),color=self.phase_color(phase_result)) 41 | 42 | def phase_color(self, status): 43 | """ Return color code for installer phase""" 44 | valid_status = [ 45 | 'FAILED', 46 | 'OK', 47 | ] 48 | 49 | if status not in valid_status: 50 | self._display.warning('Invalid phase status defined: {}'.format(status)) 51 | 52 | if status == 'OK': 53 | phase_color = C.COLOR_OK 54 | elif status == 'FAILED': 55 | phase_color = C.COLOR_ERROR 56 | else: 57 | phase_color = C.COLOR_WARN 58 | 59 | return phase_color 60 | -------------------------------------------------------------------------------- /callback_plugins/installer_checkpoint.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apoletics/ansible-network-check/0de988a62ccdcadf2d82c0a2902fe8a63020dfbf/callback_plugins/installer_checkpoint.pyc -------------------------------------------------------------------------------- /files/tcpClient.py: -------------------------------------------------------------------------------- 1 | import socket, sys 2 | 3 | TCP_IP = sys.argv[1] 4 | TCP_PORT = sys.argv[2] 5 | MESSAGE = sys.argv[3] 6 | 7 | print MESSAGE 8 | client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 9 | 10 | client.connect((TCP_IP, int(TCP_PORT) )) 11 | 12 | client.send(MESSAGE) 13 | 14 | response = client.recv(4096) 15 | 16 | print response 17 | -------------------------------------------------------------------------------- /files/tcpServer.py: -------------------------------------------------------------------------------- 1 | import socket, sys, threading 2 | 3 | TCP_IP = sys.argv[1] 4 | TCP_PORT = sys.argv[2] 5 | FILE = sys.argv[3] 6 | 7 | 8 | server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 9 | 10 | server.bind((TCP_IP, int(TCP_PORT))) 11 | 12 | server.listen(5) 13 | 14 | #f = open(FILE, "a") 15 | #f.write("STARTED") 16 | #f.close() 17 | 18 | 19 | def handle_client(client_socket): 20 | 21 | request = client_socket.recv(1024) 22 | f = open(FILE, "a") 23 | f.write(request+"\r\n") 24 | f.close() 25 | 26 | client_socket.send(request) 27 | client_socket.close() 28 | 29 | while True: 30 | client, addr = server.accept() 31 | client_handler = threading.Thread(target=handle_client, args=(client,)) 32 | client_handler.start() 33 | -------------------------------------------------------------------------------- /files/udpClient.py: -------------------------------------------------------------------------------- 1 | import socket, sys 2 | 3 | UDP_IP = sys.argv[1] 4 | UDP_PORT = sys.argv[2] 5 | 6 | MESSAGE = sys.argv[3] 7 | 8 | sock = socket.socket(socket.AF_INET, # Internet 9 | socket.SOCK_DGRAM) # UDP 10 | sock.sendto(MESSAGE, (UDP_IP, int(UDP_PORT))) 11 | 12 | -------------------------------------------------------------------------------- /files/udpServer.py: -------------------------------------------------------------------------------- 1 | import socket, sys 2 | 3 | UDP_IP = sys.argv[1] 4 | UDP_PORT = sys.argv[2] 5 | FILE = sys.argv[3] 6 | 7 | sock = socket.socket(socket.AF_INET, # Internet 8 | socket.SOCK_DGRAM) # UDP 9 | sock.bind((UDP_IP, int(UDP_PORT))) 10 | 11 | while True: 12 | data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes 13 | f = open(FILE, "a") 14 | f.write(data+"\r\n") 15 | f.close() 16 | -------------------------------------------------------------------------------- /inventory: -------------------------------------------------------------------------------- 1 | [ansible_network_health_check_from] 2 | 192.168.122.45.nip.io openshift_hostname=192.168.122.45.nip.io openshift_public_hostname=192.168.122.45.nip.io ansible_hostname=192.168.122.45.nip.io 3 | 4 | [ansible_network_health_check_to] 5 | 192.168.122.45.nip.io openshift_hostname=192.168.122.45.nip.io openshift_public_hostname=192.168.122.45.nip.io ansible_hostname=192.168.122.45.nip.io 6 | -------------------------------------------------------------------------------- /lookup_plugins/ip.py: -------------------------------------------------------------------------------- 1 | import socket 2 | from ansible.errors import AnsibleError, AnsibleParserError 3 | from ansible.plugins.lookup import LookupBase 4 | 5 | try: 6 | from __main__ import display 7 | except ImportError: 8 | from ansible.utils.display import Display 9 | display = Display() 10 | 11 | 12 | class LookupModule(LookupBase): 13 | 14 | def run(self, terms, variables=None, **kwargs): 15 | 16 | 17 | # lookups in general are expected to both take a list as input and output a list 18 | # this is done so they work with the looping construct `with_`. 19 | ret = [] 20 | for term in terms: 21 | display.debug("File lookup term: %s" % term) 22 | 23 | # Find the file in the expected search path, using a class method 24 | # that implements the 'expected' search path for Ansible plugins. 25 | lookupip = socket.gethostbyname(term) 26 | 27 | # Don't use print or your own logging, the display class 28 | # takes care of it in a unified way. 29 | display.vvvv(u"File lookup using %s as file" % lookupip) 30 | try: 31 | if lookupip: 32 | ret.append(lookupip.rstrip()) 33 | else: 34 | # Always use ansible error classes to throw 'final' exceptions, 35 | # so the Ansible engine will know how to deal with them. 36 | # The Parser error indicates invalid options passed 37 | raise AnsibleParserError() 38 | except AnsibleParserError: 39 | raise AnsibleError("could not locate file in lookup: %s" % term) 40 | 41 | return ret 42 | 43 | -------------------------------------------------------------------------------- /lookup_plugins/ip.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apoletics/ansible-network-check/0de988a62ccdcadf2d82c0a2902fe8a63020dfbf/lookup_plugins/ip.pyc -------------------------------------------------------------------------------- /main.yaml: -------------------------------------------------------------------------------- 1 | - name: Ansible Network Acceessibility Check 2 | hosts: localhost 3 | ignore_errors: true 4 | vars_files: 5 | - port_definition.yaml 6 | tasks: 7 | - name: print var 8 | debug: 9 | var: port_definitions 10 | 11 | - name: Defining fact initialization 12 | include: "tasks/init_phases.yaml" 13 | vars: 14 | port_definition: "{{item_port}}" 15 | with_items: "{{ port_definitions }}" 16 | loop_control: 17 | loop_var: item_port 18 | run_once: true 19 | 20 | 21 | - name: Testing Ports 22 | include: "tasks/start_port_check.yaml" 23 | vars: 24 | port_definition: "{{item_port}}" 25 | with_items: "{{port_definitions}}" 26 | loop_control: 27 | loop_var: item_port 28 | run_once: true 29 | 30 | 31 | # - name: Ensure no existing process running 32 | # shell: | 33 | # for PIDFILE in $(ls /tmp/ansible_network_health_check*/*PID); do 34 | # kill -9 $(cat $PIDFILE) 35 | # done 36 | # exit 0 37 | 38 | # - name: ensure tmp folder doesnot exist for clean start 39 | # shell: | 40 | # rm -rf /tmp/ansible_network_health_check* 41 | -------------------------------------------------------------------------------- /port_definition.yaml: -------------------------------------------------------------------------------- 1 | port_definitions: 2 | - from_group: nodes 3 | to_group: nodes 4 | type: udp 5 | port: 4789 6 | - from_group: nodes 7 | to_group: masters 8 | type: udp 9 | port: 8053 10 | - from_group: nodes 11 | to_group: masters 12 | type: tcp 13 | port: 8053 14 | - from_group: nodes 15 | to_group: masters 16 | type: tcp 17 | port: 8443 18 | - from_group: masters 19 | to_group: nodes 20 | type: tcp 21 | port: 10250 22 | - from_group: masters 23 | to_group: nodes 24 | type: tcp 25 | port: 10010 26 | - from_group: masters 27 | to_group: masters 28 | type: udp 29 | port: 8053 30 | 31 | # Optional for NFS 32 | - from_group: masters 33 | to_group: masters 34 | type: udp 35 | port: 2049 36 | 37 | 38 | - from_group: masters 39 | to_group: masters 40 | type: tcp 41 | port: 2379 42 | - from_group: masters 43 | to_group: masters 44 | type: tcp 45 | port: 2380 46 | 47 | ################ addition for 3.11 prometheus monitoring 48 | - from_group: nodes 49 | to_group: nodes 50 | type: tcp 51 | port: 9100 52 | 53 | - from_group: nodes 54 | to_group: nodes 55 | type: tcp 56 | port: 10250 57 | 58 | - from_group: nodes 59 | to_group: nodes 60 | type: udp 61 | port: 8444 62 | -------------------------------------------------------------------------------- /tasks/init_phases.yaml: -------------------------------------------------------------------------------- 1 | - name: debug only 2 | debug: 3 | var: port_definition 4 | 5 | - name: looping to servers 6 | include: "loop_phase_to_server.yaml" 7 | vars: 8 | check_to_host: "{{item_to_host}}" 9 | with_items: "{{groups[port_definition['to_group']]}}" 10 | loop_control: 11 | loop_var: item_to_host 12 | -------------------------------------------------------------------------------- /tasks/loop_phase_from_clients.yaml: -------------------------------------------------------------------------------- 1 | 2 | - name: debug check to host only 3 | debug: 4 | var: check_from_host 5 | 6 | - name: set variables 7 | set_fact: 8 | # current_from_ip: "{{hostvars[check_from_host]['ansible_default_ipv4']['address']}}" 9 | current_from_ip: "{{lookup('ip', check_from_host )}}" 10 | 11 | - name: debug state title 12 | debug: 13 | msg: "TITLE is: {{current_protocol}}_{{current_from_ip |regex_replace('\\W','_') }}_{{current_to_ip |regex_replace('\\W','_')}}_{{current_port}}" 14 | 15 | - name: init stat 16 | run_once: true 17 | set_stats: 18 | data: 19 | "{{current_protocol}}_{{current_from_ip |regex_replace('\\W','_') }}_{{current_to_ip |regex_replace('\\W','_')}}_{{current_port}}" : 20 | # testing_data: 21 | protocol: "{{current_protocol}}" 22 | from: "{{current_from_ip}}" 23 | to: "{{current_to_ip}}" 24 | port: "{{current_port}}" 25 | result: 'FAILED' 26 | 27 | -------------------------------------------------------------------------------- /tasks/loop_phase_to_server.yaml: -------------------------------------------------------------------------------- 1 | 2 | - name: debug check to host only 3 | debug: 4 | var: check_to_host 5 | 6 | - name: set variables 7 | set_fact: 8 | current_to_ip: "{{lookup('ip', check_to_host ) }}" 9 | # current_to_ip: "{{hostvars[check_to_host]['ansible_default_ipv4']['address']}}" 10 | current_protocol: "{{port_definition['type']|lower}}" 11 | current_port: "{{port_definition['port']}}" 12 | 13 | 14 | - name: loop from clients 15 | include: tasks/loop_phase_from_clients.yaml 16 | vars: 17 | check_from_host: "{{item_from_host}}" 18 | with_items: "{{groups[port_definition['from_group']]}}" 19 | loop_control: 20 | loop_var: item_from_host 21 | -------------------------------------------------------------------------------- /tasks/register_test_result.yaml: -------------------------------------------------------------------------------- 1 | - name: setup stat result 2 | set_fact: 3 | current_protocol: "{{test_result_string.split(' ')[0]}}" 4 | current_to_ip: "{{test_result_string.split(' ')[4]}}" 5 | current_from_ip: "{{test_result_string.split(' ')[2]}}" 6 | current_port: "{{test_result_string.split(' ')[6]}}" 7 | 8 | - name: debug state title - result 9 | debug: 10 | msg: "TITLE ix: {{current_protocol}}_{{current_from_ip |regex_replace('\\W','_') }}_{{current_to_ip |regex_replace('\\W','_')}}_{{current_port}}" 11 | 12 | 13 | - name: setup stat result 14 | run_once: true 15 | set_stats: 16 | data: 17 | "{{current_protocol|lower}}_{{current_from_ip |regex_replace('\\W','_') }}_{{current_to_ip |regex_replace('\\W','_')}}_{{current_port}}" : 18 | # testing_data: 19 | protocol: "{{current_protocol}}" 20 | from: "{{current_from_ip}}" 21 | to: "{{current_to_ip}}" 22 | port: "{{current_port}}" 23 | result: 'OK' 24 | -------------------------------------------------------------------------------- /tasks/server_check.yaml: -------------------------------------------------------------------------------- 1 | #- name: Server Check up 2 | # hosts: ansible_network_health_check_to 3 | # gather_facts: yes 4 | # tasks: 5 | - name: Register result of tests 6 | # when: check_to_host == inventory_hostname 7 | delegate_to: "{{check_to_host}}" 8 | shell: "cat /tmp/ansible_network_health_check_to/{{test_protocol}}_{{test_to_ip}}_{{test_port}}_OUTPUT" 9 | register: test_reuslts 10 | 11 | - name: Register result of tests 12 | debug: 13 | var: test_reuslts 14 | 15 | - name: Check server status 16 | # when: check_to_host == inventory_hostname 17 | include: tasks/register_test_result.yaml 18 | vars: 19 | test_result_string: "{{item}}" 20 | with_items: "{{test_reuslts.stdout_lines}}" 21 | 22 | - name: Ensure no existing process running 23 | delegate_to: "{{check_to_host}}" 24 | # when: check_to_host == inventory_hostname 25 | shell: | 26 | for PIDFILE in $(ls /tmp/ansible_network_health_check_to/*PID); do 27 | kill -9 $(cat $PIDFILE) 28 | done 29 | exit 0 30 | 31 | - name: ensure tmp folder doesnot exist for clean start 32 | delegate_to: "{{check_to_host}}" 33 | # when: check_to_host == inventory_hostname 34 | file: 35 | path: /tmp/ansible_network_health_check_to/ 36 | state: absent 37 | -------------------------------------------------------------------------------- /tasks/start_port_check.yaml: -------------------------------------------------------------------------------- 1 | - name: debug only 2 | debug: 3 | var: port_definition 4 | 5 | - name: start to as server 6 | include: "start_to_servers.yaml" 7 | vars: 8 | check_to_host: "{{item_to_host}}" 9 | with_items: "{{groups[port_definition['to_group']]}}" 10 | loop_control: 11 | loop_var: item_to_host 12 | -------------------------------------------------------------------------------- /tasks/start_to_servers.yaml: -------------------------------------------------------------------------------- 1 | - name: set variables 2 | set_fact: 3 | test_to_ip: "{{lookup('ip', check_to_host) }}" 4 | test_protocol: "{{port_definition['type']|lower}}" 5 | test_port: "{{port_definition['port']}}" 6 | 7 | - name: debug check to host only 8 | debug: 9 | var: check_to_host 10 | 11 | - name: start tcp server 12 | include: tcp_to_server.yaml 13 | when: port_definition['type']|lower == 'tcp' 14 | 15 | - name: start udp server 16 | include: udp_to_server.yaml 17 | when: port_definition['type']|lower == 'udp' 18 | 19 | - name: start from as client - TCP 20 | when: port_definition['type']|lower == 'tcp' 21 | include: tasks/tcp_from_clients.yaml 22 | vars: 23 | check_from_host: "{{item_from_host}}" 24 | ansible_network_health_check_port: "{{test_port}}" 25 | ansible_network_health_check_server_ip: "{{test_to_ip}}" 26 | with_items: "{{groups[port_definition['from_group']]}}" 27 | loop_control: 28 | loop_var: item_from_host 29 | 30 | - name: start from as client - UDP 31 | when: port_definition['type']|lower == 'udp' 32 | include: tasks/udp_from_clients.yaml 33 | vars: 34 | check_from_host: "{{item_from_host}}" 35 | ansible_network_health_check_port: "{{test_port}}" 36 | ansible_network_health_check_server_ip: "{{test_to_ip}}" 37 | with_items: "{{groups[port_definition['from_group']]}}" 38 | loop_control: 39 | loop_var: item_from_host 40 | 41 | - name: check server result - tcp 42 | include: tasks/server_check.yaml 43 | -------------------------------------------------------------------------------- /tasks/tcp_from_clients.yaml: -------------------------------------------------------------------------------- 1 | #- name: Start Testing server 2 | # hosts: ansible_network_health_check_from 3 | # gather_facts: yes 4 | # tasks: 5 | 6 | # - name: Set etcd install 'In Progress' 7 | # run_once: true 8 | # set_stats: 9 | # data: 10 | # installer_phase_etcd: 11 | # title: "etcd Install" 12 | # status: "In Progress" 13 | # start: "{{ lookup('pipe', 'date +%Y%m%d%H%M%SZ') }}" 14 | 15 | - name: debug check_from_host 16 | debug: 17 | var: check_from_host 18 | 19 | - name: set variables 20 | set_fact: 21 | # test_from_ip: "{{hostvars[check_from_host]['ansible_default_ipv4']['address']}}" 22 | test_from_ip: "{{lookup('ip',check_from_host ) }}" 23 | 24 | - name: debug ansible_network_health_check_port 25 | debug: 26 | var: ansible_network_health_check_port 27 | 28 | - name: ensure tmp folder doesnot exist for clean start 29 | delegate_to: "{{check_from_host}}" 30 | # when: check_from_host == inventory_hostname 31 | file: 32 | path: /tmp/ansible_network_health_check_from/ 33 | state: absent 34 | 35 | - name: ensure folder exist 36 | # when: check_from_host == inventory_hostname 37 | delegate_to: "{{check_from_host}}" 38 | file: 39 | path: /tmp/ansible_network_health_check_from/ 40 | state: directory 41 | 42 | - name: Copy Python to destination 43 | # when: check_from_host == inventory_hostname 44 | delegate_to: "{{check_from_host}}" 45 | copy: 46 | src: files/tcpClient.py 47 | dest: /tmp/ansible_network_health_check_from/tcpClient.py 48 | 49 | - name: Run the echo ping 50 | delegate_to: "{{check_from_host}}" 51 | # when: check_from_host == inventory_hostname 52 | shell: | 53 | cd /tmp/ansible_network_health_check_from/ 54 | python /tmp/ansible_network_health_check_from/tcpClient.py {{test_to_ip}} {{test_port}} "{{test_protocol|upper}} FROM {{test_from_ip}} TO {{test_to_ip}} PORT {{test_port}} OK" 55 | 56 | 57 | - name: ensure tmp folder doesnot exist for clean start 58 | delegate_to: "{{check_from_host}}" 59 | # when: check_from_host == inventory_hostname 60 | file: 61 | path: /tmp/ansible_network_health_check_from/ 62 | state: absent 63 | -------------------------------------------------------------------------------- /tasks/tcp_to_server.yaml: -------------------------------------------------------------------------------- 1 | - name: Ensure no existing process running 2 | # when: check_to_host == inventory_hostname 3 | delegate_to: "{{check_to_host}}" 4 | shell: | 5 | kill -9 $(cat /tmp/ansible_network_health_check_to/{{test_protocol}}_{{test_to_ip}}_{{test_port}}_PID) 6 | exit 0 7 | 8 | - name: ensure tmp folder doesnot exist for clean start 9 | # when: check_to_host == inventory_hostname 10 | delegate_to: "{{check_to_host}}" 11 | file: 12 | path: /tmp/ansible_network_health_check_to/ 13 | state: absent 14 | 15 | - name: ensure folder exist 16 | # when: check_to_host == inventory_hostname 17 | file: 18 | path: /tmp/ansible_network_health_check_to/ 19 | state: directory 20 | delegate_to: "{{check_to_host}}" 21 | 22 | - name: Copy Python to destination 23 | # when: check_to_host == inventory_hostname 24 | copy: 25 | src: files/tcpServer.py 26 | dest: /tmp/ansible_network_health_check_to/tcpServer.py 27 | delegate_to: "{{check_to_host}}" 28 | 29 | 30 | - name: debug start server 31 | delegate_to: "{{check_to_host}}" 32 | debug: 33 | msg: | 34 | python /tmp/ansible_network_health_check_to/tcpServer.py {{test_to_ip}} {{test_port}} /tmp/ansible_network_health_check_to/{{test_protocol}}_{{test_to_ip}}_{{test_port}}_OUTPUT & 35 | 36 | - name: Start Server 37 | delegate_to: "{{check_to_host}}" 38 | # when: check_to_host == inventory_hostname 39 | shell: | 40 | cd /tmp/ansible_network_health_check_to/ 41 | python /tmp/ansible_network_health_check_to/tcpServer.py {{test_to_ip}} {{test_port}} /tmp/ansible_network_health_check_to/{{test_protocol}}_{{test_to_ip}}_{{test_port}}_OUTPUT & 42 | PID=$! 43 | echo $PID > /tmp/ansible_network_health_check_to/{{test_protocol}}_{{test_to_ip}}_{{test_port}}_PID 44 | sleep 10 45 | if [ -f /proc/$PID/status ] 46 | then 47 | exit 0 48 | else 49 | exit -1 50 | fi 51 | async: 45 52 | poll: 0 53 | 54 | - name: register PID of tcpServer.py 55 | delegate_to: "{{check_to_host}}" 56 | shell: "cat /tmp/ansible_network_health_check_to/{{test_protocol}}_{{test_to_ip}}_{{test_port}}_PID" 57 | register: PID_tcpServer 58 | 59 | - name: debug only 60 | debug: 61 | var: PID_tcpServer 62 | 63 | - name: make sure file Exist 64 | delegate_to: "{{check_to_host}}" 65 | # when: check_to_host == inventory_hostname 66 | stat: 67 | path: "/proc/{{PID_tcpServer.stdout}}/status" 68 | register: stat_result 69 | failed_when: not stat_result.stat.exists 70 | -------------------------------------------------------------------------------- /tasks/udp_from_clients.yaml: -------------------------------------------------------------------------------- 1 | 2 | - name: debug check_from_host 3 | debug: 4 | var: check_from_host 5 | 6 | - name: set variables 7 | set_fact: 8 | test_from_ip: "{{lookup('ip',check_from_host ) }}" 9 | 10 | - name: debug ansible_network_health_check_port 11 | debug: 12 | var: ansible_network_health_check_port 13 | 14 | - name: ensure tmp folder doesnot exist for clean start 15 | delegate_to: "{{check_from_host}}" 16 | # when: check_from_host == inventory_hostname 17 | file: 18 | path: /tmp/ansible_network_health_check_from/ 19 | state: absent 20 | 21 | - name: ensure folder exist 22 | delegate_to: "{{check_from_host}}" 23 | # when: check_from_host == inventory_hostname 24 | file: 25 | path: /tmp/ansible_network_health_check_from/ 26 | state: directory 27 | 28 | - name: Copy Python to destination 29 | delegate_to: "{{check_from_host}}" 30 | # when: check_from_host == inventory_hostname 31 | copy: 32 | src: files/udpClient.py 33 | dest: /tmp/ansible_network_health_check_from/udpClient.py 34 | 35 | - name: Run the echo ping 36 | delegate_to: "{{check_from_host}}" 37 | # when: check_from_host == inventory_hostname 38 | shell: | 39 | cd /tmp/ansible_network_health_check_from/ 40 | python /tmp/ansible_network_health_check_from/udpClient.py {{test_to_ip}} {{test_port}} "{{test_protocol|upper}} FROM {{test_from_ip}} TO {{test_to_ip}} PORT {{test_port}} OK" 41 | 42 | - name: ensure tmp folder doesnot exist for clean start 43 | delegate_to: "{{check_from_host}}" 44 | # when: check_from_host == inventory_hostname 45 | file: 46 | path: /tmp/ansible_network_health_check_from/ 47 | state: absent 48 | -------------------------------------------------------------------------------- /tasks/udp_to_server.yaml: -------------------------------------------------------------------------------- 1 | 2 | - name: Ensure no existing process running 3 | delegate_to: "{{check_to_host}}" 4 | # when: check_to_host == inventory_hostname 5 | shell: | 6 | kill -9 $(cat /tmp/ansible_network_health_check_to/{{test_protocol}}_{{test_to_ip}}_{{test_port}}_PID) 7 | exit 0 8 | 9 | 10 | - name: ensure tmp folder doesnot exist for clean start 11 | delegate_to: "{{check_to_host}}" 12 | # when: check_to_host == inventory_hostname 13 | file: 14 | path: /tmp/ansible_network_health_check_to/ 15 | state: absent 16 | 17 | - name: ensure folder exist 18 | delegate_to: "{{check_to_host}}" 19 | # when: check_to_host == inventory_hostname 20 | file: 21 | path: /tmp/ansible_network_health_check_to/ 22 | state: directory 23 | 24 | - name: Copy Python to destination 25 | delegate_to: "{{check_to_host}}" 26 | # when: check_to_host == inventory_hostname 27 | copy: 28 | src: files/udpServer.py 29 | dest: /tmp/ansible_network_health_check_to/udpServer.py 30 | 31 | - name: Start Server 32 | delegate_to: "{{check_to_host}}" 33 | # when: check_to_host == inventory_hostname 34 | shell: | 35 | cd /tmp/ansible_network_health_check_to/ 36 | python /tmp/ansible_network_health_check_to/udpServer.py {{test_to_ip}} {{test_port}} /tmp/ansible_network_health_check_to/{{test_protocol}}_{{test_to_ip}}_{{test_port}}_OUTPUT & 37 | PID=$! 38 | echo $PID > /tmp/ansible_network_health_check_to/{{test_protocol}}_{{test_to_ip}}_{{test_port}}_PID 39 | sleep 10 40 | if [ -f /proc/$PID/status ] 41 | then 42 | exit 0 43 | else 44 | exit -1 45 | fi 46 | async: 45 47 | poll: 0 48 | 49 | - name: register PID of udpServer.py 50 | delegate_to: "{{check_to_host}}" 51 | shell: "cat /tmp/ansible_network_health_check_to/{{test_protocol}}_{{test_to_ip}}_{{test_port}}_PID" 52 | register: PID_udpServer 53 | 54 | - name: debug only 55 | debug: 56 | var: PID_udpServer 57 | 58 | - name: make sure file Exist 59 | delegate_to: "{{check_to_host}}" 60 | # when: check_to_host == inventory_hostname 61 | stat: 62 | path: "/proc/{{PID_udpServer.stdout}}/status" 63 | register: stat_result 64 | failed_when: not stat_result.stat.exists 65 | --------------------------------------------------------------------------------