Skip to content

Commit

Permalink
Pull persistent connection parameters via get_option (ansible#39367)
Browse files Browse the repository at this point in the history
* WIP Pull persistent connection parameters via get_option

* Fix pep8

* Add use_persistent_connection setting to paramiko_ssh plugin

* Add vars section to persistent_command_timeout setting and prevail provider values over config manager

* Use persistent_command_timeout on network_cli instead of timeout

* Fix unit tests

If we don't call loader to get network_cli, then _load_name is never
set and we get KeyError.

* Pull persistent_command_timeout via config  manager for ios connection local

* Pull persistent_command_timeout via config manager on connection local
  • Loading branch information
rcarrillocruz authored May 16, 2018
1 parent 865f2c5 commit 62e1c14
Show file tree
Hide file tree
Showing 12 changed files with 64 additions and 22 deletions.
5 changes: 3 additions & 2 deletions bin/ansible-connection
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ class ConnectionProcess(object):
while self.connection.connected:
signal.signal(signal.SIGALRM, self.connect_timeout)
signal.signal(signal.SIGTERM, self.handler)
signal.alarm(C.PERSISTENT_CONNECT_TIMEOUT)
signal.alarm(self.connection.get_option('persistent_connect_timeout'))

self.exception = None
(s, addr) = self.sock.accept()
Expand Down Expand Up @@ -141,7 +141,8 @@ class ConnectionProcess(object):
self.shutdown()

def connect_timeout(self, signum, frame):
display.display('persistent connection idle timeout triggered, timeout value is %s secs' % C.PERSISTENT_CONNECT_TIMEOUT, log_only=True)
display.display('persistent connection idle timeout triggered, timeout value is %s secs'
% self.connection.get_option('persistent_connect_timeout'), log_only=True)
self.shutdown()

def command_timeout(self, signum, frame):
Expand Down
2 changes: 1 addition & 1 deletion lib/ansible/executor/task_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@ def _get_connection(self, variables, templar):
self._play_context.set_options_from_plugin(connection)

if any(((connection.supports_persistence and C.USE_PERSISTENT_CONNECTIONS), connection.force_persistence)):
self._play_context.timeout = C.PERSISTENT_COMMAND_TIMEOUT
self._play_context.timeout = connection.get_option('persistent_command_timeout')
display.vvvv('attempting to start connection', host=self._play_context.remote_addr)
display.vvvv('using connection plugin %s' % connection.transport, host=self._play_context.remote_addr)
socket_path = self._start_connection()
Expand Down
5 changes: 4 additions & 1 deletion lib/ansible/plugins/action/eos.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def run(self, tmp=None, task_vars=None):
pc.remote_user = provider['username'] or self._play_context.connection_user
pc.password = provider['password'] or self._play_context.password
pc.private_key_file = provider['ssh_keyfile'] or self._play_context.private_key_file
pc.timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT)
pc.timeout = int(provider['timeout']) if provider['timeout'] else None
pc.become = provider['authorize'] or False
if pc.become:
pc.become_method = 'enable'
Expand All @@ -75,6 +75,9 @@ def run(self, tmp=None, task_vars=None):
display.vvv('using connection plugin %s (was local)' % pc.connection, pc.remote_addr)
connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin)

if connection._play_context.timeout is None:
connection._play_context.timeout = connection.get_option('persistent_command_timeout')

socket_path = connection.run()
display.vvvv('socket_path: %s' % socket_path, pc.remote_addr)
if not socket_path:
Expand Down
5 changes: 4 additions & 1 deletion lib/ansible/plugins/action/ios.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def run(self, tmp=None, task_vars=None):
pc.remote_user = provider['username'] or self._play_context.connection_user
pc.password = provider['password'] or self._play_context.password
pc.private_key_file = provider['ssh_keyfile'] or self._play_context.private_key_file
pc.timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT)
pc.timeout = int(provider['timeout']) if provider['timeout'] else None
pc.become = provider['authorize'] or False
if pc.become:
pc.become_method = 'enable'
Expand All @@ -67,6 +67,9 @@ def run(self, tmp=None, task_vars=None):
display.vvv('using connection plugin %s (was local)' % pc.connection, pc.remote_addr)
connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin)

if connection._play_context.timeout is None:
connection._play_context.timeout = connection.get_option('persistent_command_timeout')

socket_path = connection.run()
display.vvvv('socket_path: %s' % socket_path, pc.remote_addr)
if not socket_path:
Expand Down
5 changes: 4 additions & 1 deletion lib/ansible/plugins/action/iosxr.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,14 @@ def run(self, tmp=None, task_vars=None):
pc.port = int(provider['port'] or self._play_context.port or 22)
pc.remote_user = provider['username'] or self._play_context.connection_user
pc.password = provider['password'] or self._play_context.password
pc.timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT)
pc.timeout = int(provider['timeout']) if provider['timeout'] else None

display.vvv('using connection plugin %s (was local)' % pc.connection, pc.remote_addr)
connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin)

if connection._play_context.timeout is None:
connection._play_context.timeout = connection.get_option('persistent_command_timeout')

socket_path = connection.run()
display.vvvv('socket_path: %s' % socket_path, pc.remote_addr)
if not socket_path:
Expand Down
5 changes: 4 additions & 1 deletion lib/ansible/plugins/action/junos.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,14 @@ def run(self, tmp=None, task_vars=None):
pc.remote_user = provider['username'] or self._play_context.connection_user
pc.password = provider['password'] or self._play_context.password
pc.private_key_file = provider['ssh_keyfile'] or self._play_context.private_key_file
pc.timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT)
pc.timeout = int(provider['timeout']) if provider['timeout'] else None

display.vvv('using connection plugin %s (was local)' % pc.connection, pc.remote_addr)
connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin)

if connection._play_context.timeout is None:
connection._play_context.timeout = connection.get_option('persistent_command_timeout')

socket_path = connection.run()
display.vvvv('socket_path: %s' % socket_path, pc.remote_addr)
if not socket_path:
Expand Down
5 changes: 4 additions & 1 deletion lib/ansible/plugins/action/nxos.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def run(self, tmp=None, task_vars=None):
pc.remote_user = provider['username'] or self._play_context.connection_user
pc.password = provider['password'] or self._play_context.password
pc.private_key_file = provider['ssh_keyfile'] or self._play_context.private_key_file
pc.timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT)
pc.timeout = int(provider['timeout']) if provider['timeout'] else None
pc.become = provider['authorize'] or False
if pc.become:
pc.become_method = 'enable'
Expand All @@ -78,6 +78,9 @@ def run(self, tmp=None, task_vars=None):
display.vvv('using connection plugin %s (was local)' % pc.connection, pc.remote_addr)
connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin)

if connection._play_context.timeout is None:
connection._play_context.timeout = connection.get_option('persistent_command_timeout')

socket_path = connection.run()
display.vvvv('socket_path: %s' % socket_path, pc.remote_addr)
if not socket_path:
Expand Down
5 changes: 4 additions & 1 deletion lib/ansible/plugins/action/vyos.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,14 @@ def run(self, tmp=None, task_vars=None):
pc.remote_user = provider['username'] or self._play_context.connection_user
pc.password = provider['password'] or self._play_context.password
pc.private_key_file = provider['ssh_keyfile'] or self._play_context.private_key_file
pc.timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT)
pc.timeout = int(provider['timeout']) if provider['timeout'] else None

display.vvv('using connection plugin %s (was local)' % pc.connection, pc.remote_addr)
connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin)

if connection._play_context.timeout is None:
connection._play_context.timeout = connection.get_option('persistent_command_timeout')

socket_path = connection.run()
display.vvvv('socket_path: %s' % socket_path, pc.remote_addr)
if not socket_path:
Expand Down
6 changes: 3 additions & 3 deletions lib/ansible/plugins/connection/network_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@
close
default: 10
ini:
section: persistent_connection
key: persistent_command_timeout
- section: persistent_connection
key: command_timeout
env:
- name: ANSIBLE_PERSISTENT_COMMAND_TIMEOUT
"""
Expand Down Expand Up @@ -298,7 +298,7 @@ def _connect(self):
display.vvvv('ssh connection done, setting terminal', host=self._play_context.remote_addr)

self._ssh_shell = ssh.ssh.invoke_shell()
self._ssh_shell.settimeout(self._play_context.timeout)
self._ssh_shell.settimeout(self.get_option('persistent_command_timeout'))

network_os = self._play_context.network_os
if not network_os:
Expand Down
12 changes: 10 additions & 2 deletions lib/ansible/plugins/connection/paramiko_ssh.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,16 @@
version_added: '2.5'
- name: ansible_paramiko_host_key_checking
version_added: '2.5'
use_persistent_connections:
description: 'Toggles the use of persistence for connections'
type: boolean
default: False
env:
- name: ANSIBLE_USE_PERSISTENT_CONNECTIONS
ini:
- section: defaults
key: use_persistent_connections
# TODO:
#C.USE_PERSISTENT_CONNECTIONS:
#timeout=self._play_context.timeout,
"""

Expand Down Expand Up @@ -188,7 +196,7 @@ def missing_host_key(self, client, hostname, key):
fingerprint = hexlify(key.get_fingerprint())
ktype = key.get_name()

if C.USE_PERSISTENT_CONNECTIONS or self.connection.force_persistence:
if self.connection.get_option('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))
Expand Down
24 changes: 19 additions & 5 deletions lib/ansible/plugins/connection/persistent.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,26 @@
__metaclass__ = type

DOCUMENTATION = """
author: Ansible Core Team
connection: persistent
short_description: Use a persistent unix socket for connection
author: Ansible Core Team
connection: persistent
short_description: Use a persistent unix socket for connection
description:
- This is a helper plugin to allow making other connections persistent.
version_added: "2.3"
options:
persistent_command_timeout:
type: int
description:
- This is a helper plugin to allow making other connections persistent.
version_added: "2.3"
- Configures, in seconds, the amount of time to wait for a command to
return from the remote device. If this timer is exceeded before the
command returns, the connection plugin will raise an exception and
close
default: 10
ini:
- section: persistent_connection
key: command_timeout
env:
- name: ANSIBLE_PERSISTENT_COMMAND_TIMEOUT
"""
import os
import pty
Expand Down
7 changes: 4 additions & 3 deletions test/units/plugins/connection/test_network_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from ansible.errors import AnsibleConnectionFailure
from ansible.playbook.play_context import PlayContext
from ansible.plugins.connection import network_cli
from ansible.plugins.loader import connection_loader


class TestConnectionClass(unittest.TestCase):
Expand All @@ -40,7 +41,7 @@ def test_network_cli__connect_error(self, mocked_super):
pc = PlayContext()
new_stdin = StringIO()

conn = network_cli.Connection(pc, new_stdin)
conn = connection_loader.get('network_cli', pc, '/dev/null')
conn.ssh = MagicMock()
conn.receive = MagicMock()
conn._terminal = MagicMock()
Expand All @@ -52,7 +53,7 @@ def test_network_cli__invalid_os(self, mocked_super):
pc = PlayContext()
new_stdin = StringIO()

conn = network_cli.Connection(pc, new_stdin)
conn = connection_loader.get('network_cli', pc, '/dev/null')
conn.ssh = MagicMock()
conn.receive = MagicMock()
conn._terminal = MagicMock()
Expand All @@ -65,7 +66,7 @@ def test_network_cli__connect(self, mocked_super, mocked_terminal_loader):
pc = PlayContext()
new_stdin = StringIO()

conn = network_cli.Connection(pc, new_stdin)
conn = connection_loader.get('network_cli', pc, '/dev/null')
pc.network_os = 'ios'

conn.ssh = MagicMock()
Expand Down

0 comments on commit 62e1c14

Please sign in to comment.