Repository: ansible/ansible

Issue:
wait_for never resolves due to silent fail if IPv6 is disabled in the OS
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
Utility module: wait_for

##### ANSIBLE VERSION
```
ansible 2.2.2.0
```

##### CONFIGURATION
N/A

##### OS / ENVIRONMENT
Linux without IPv6 enabled so that the path `/proc/net/tcp6` returns `No such file or directory`

##### SUMMARY
When IPv6 is disabled the module never resolves to success no matter which settings are used.

I've found the root cause by looking at the [source code](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/utilities/logic/wait_for.py) for the module:

1. [Line 262](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/utilities/logic/wait_for.py#L262): '/proc/net/tcp6' is defined
2. [Line 293](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/utilities/logic/wait_for.py#L293): Code tries to open the path on the second iteration and an `No such file or directory`-exception is thrown
3. [Line 573](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/utilities/logic/wait_for.py#L573): Exception is ignored and we continue waiting until timeout

I was able to make the module behave as expected by temporarily removing '/proc/net/tcp6'  from the `source_file` array.

##### STEPS TO REPRODUCE
Disable IPv6 so path `/proc/net/tcp6` is undefined, and then run:
<!--- Paste example playbooks or commands between quotes below -->
```
ansible localhost -m wait_for -a "state=drained port=80"
```

##### EXPECTED RESULTS
Ok

##### ACTUAL RESULTS
```
fatal: [hostname]: FAILED! => {"changed": false, "elapsed": 300, "failed": true, "msg": "Timeout when waiting for 127.0.0.1:80 to drain"}

wait_for never resolves due to silent fail if IPv6 is disabled in the OS
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
Utility module: wait_for

##### ANSIBLE VERSION
```
ansible 2.2.2.0
```

##### CONFIGURATION
N/A

##### OS / ENVIRONMENT
Linux without IPv6 enabled so that the path `/proc/net/tcp6` returns `No such file or directory`

##### SUMMARY
When IPv6 is disabled the module never resolves to success no matter which settings are used.

I've found the root cause by looking at the [source code](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/utilities/logic/wait_for.py) for the module:

1. [Line 262](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/utilities/logic/wait_for.py#L262): '/proc/net/tcp6' is defined
2. [Line 293](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/utilities/logic/wait_for.py#L293): Code tries to open the path on the second iteration and an `No such file or directory`-exception is thrown
3. [Line 573](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/utilities/logic/wait_for.py#L573): Exception is ignored and we continue waiting until timeout

I was able to make the module behave as expected by temporarily removing '/proc/net/tcp6'  from the `source_file` array.

##### STEPS TO REPRODUCE
Disable IPv6 so path `/proc/net/tcp6` is undefined, and then run:
<!--- Paste example playbooks or commands between quotes below -->
```
ansible localhost -m wait_for -a "state=drained port=80"
```

##### EXPECTED RESULTS
Ok

##### ACTUAL RESULTS
```
fatal: [hostname]: FAILED! => {"changed": false, "elapsed": 300, "failed": true, "msg": "Timeout when waiting for 127.0.0.1:80 to drain"}



Discussion:
cc @gregswift
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Looks like wait_for.py needs to be changed so the try/except handling for IOError gets handled in get_active_connections_count() so it will try all of the source_file/AF_INET* types before waiting.
cc @AnderEnder @jarv @jhoekx
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
cc @gregswift
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Looks like wait_for.py needs to be changed so the try/except handling for IOError gets handled in get_active_connections_count() so it will try all of the source_file/AF_INET* types before waiting.
cc @AnderEnder @jarv @jhoekx
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/lib/ansible/modules/utilities/logic/wait_for.py b/lib/ansible/modules/utilities/logic/wait_for.py
--- a/lib/ansible/modules/utilities/logic/wait_for.py
+++ b/lib/ansible/modules/utilities/logic/wait_for.py
@@ -316,6 +316,8 @@ def _get_exclude_ips(self):
     def get_active_connections_count(self):
         active_connections = 0
         for family in self.source_file.keys():
+            if not os.path.isfile(self.source_file[family]):
+                continue
             f = open(self.source_file[family])
             for tcp_connection in f.readlines():
                 tcp_connection = tcp_connection.strip().split()


Test patch: