Repository: ansible/ansible

Issue:
[Regression] network_cli: indefinite hang if sshkey isn't in known_hosts
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
network_cli

##### ANSIBLE VERSION
```
ansible 2.5.0 (devel 43f89004a0) last updated 2017/11/15 11:25:45 (GMT +100)

```

##### SUMMARY
If the fingerprint isn't in `known_hosts` then ansible-playbook will hang

This is a regression as in `stable-2.4` after a timeout we would get `unable to open shell`.

So there seem to be two issues here: 
1) Timeout isn't triggered
2) No message displayed (possibly caused by #1)

##### STEPS TO REPRODUCE
Move known_hosts or use `ssh-keygen -f "/home/johnb/.ssh/known_hosts" -R ios02.example.net`

```
[ios]
ios02.example.net ansible_connection=local ansible_user=ansible ansible_ssh_pass=ansible
```

```yaml
- name: "Download switch configuration"
  hosts: switches
  gather_facts: no

  tasks:
   ###
   # Collect data
    - name: Gather facts (ios)
      ios_facts:
      register: result_ios
      when: "'ios' in group_names"

```


If I use  `connection: network_cli` the same issue

##### EXPECTED RESULTS

Something along the lines of:

```
fatal: [ios02.example.net]: FAILED! => {"msg": "host key not known ios02.example.net"}
```

##### ACTUAL RESULTS

```
TASK [Gather facts (ios)] ************************************************************************************************************************************************************************************************************************
task path: /home/johnb/git/ansible-inc/gundalows-test-cases/net-usecase-1-facts-v4/net-usecase-1-facts.yml:8
skipping: [eos01.example.net] => {
    "changed": false, 
    "skip_reason": "Conditional result was False"
}
skipping: [vyos01.example.net] => {
    "changed": false, 
    "skip_reason": "Conditional result was False"
}
<ios02.example.net> attempting to start connection
<ios02.example.net> using connection plugin network_cli
```
Hangs for minutes


Discussion:
cc @Qalthos @ganeshrn @kedarX @privateip @rcarrillocruz @trishnaguha
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/lib/ansible/plugins/connection/network_cli.py b/lib/ansible/plugins/connection/network_cli.py
--- a/lib/ansible/plugins/connection/network_cli.py
+++ b/lib/ansible/plugins/connection/network_cli.py
@@ -78,7 +78,6 @@ class Connection(ConnectionBase):
     def __init__(self, play_context, new_stdin, *args, **kwargs):
         super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
 
-        self.ssh = None
         self._ssh_shell = None
 
         self._matched_prompt = None
@@ -164,12 +163,12 @@ def _connect(self):
 
         p = connection_loader.get('paramiko', self._play_context, '/dev/null')
         p.set_options(direct={'look_for_keys': bool(self._play_context.password and not self._play_context.private_key_file)})
+        p.force_persistence = self.force_persistence
         ssh = p._connect()
-        self.ssh = ssh.ssh
 
         display.vvvv('ssh connection done, setting terminal', host=self._play_context.remote_addr)
 
-        self._ssh_shell = self.ssh.invoke_shell()
+        self._ssh_shell = ssh.ssh.invoke_shell()
         self._ssh_shell.settimeout(self._play_context.timeout)
 
         network_os = self._play_context.network_os
diff --git a/lib/ansible/plugins/connection/paramiko_ssh.py b/lib/ansible/plugins/connection/paramiko_ssh.py
--- a/lib/ansible/plugins/connection/paramiko_ssh.py
+++ b/lib/ansible/plugins/connection/paramiko_ssh.py
@@ -188,7 +188,7 @@ def missing_host_key(self, client, hostname, key):
             fingerprint = hexlify(key.get_fingerprint())
             ktype = key.get_name()
 
-            if C.USE_PERSISTENT_CONNECTIONS:
+            if C.USE_PERSISTENT_CONNECTIONS or self.connection.force_persistence:
                 # don't print the prompt string since the user cannot respond
                 # to the question anyway
                 raise AnsibleError(AUTHENTICITY_MSG[1:92] % (hostname, ktype, fingerprint))


Test patch: