From 8137c7207d1af96a8f2c6b07ed6d0b071eb28c01 Mon Sep 17 00:00:00 2001 From: Peter Sprygada Date: Wed, 30 Nov 2016 16:28:47 -0500 Subject: [PATCH] adds feature to try to auto determine network_os (#18674) This updates the network_cli connection plugin to attempt to automatically determine the remote device os. The device network os discovery can be overridden by setting the ansible_network_os value. --- lib/ansible/plugins/connection/network_cli.py | 26 ++++++++++++++----- lib/ansible/plugins/terminal/__init__.py | 3 +++ lib/ansible/plugins/terminal/eos.py | 5 ++++ lib/ansible/plugins/terminal/ios.py | 6 +++++ lib/ansible/plugins/terminal/iosxr.py | 6 +++++ lib/ansible/plugins/terminal/junos.py | 6 +++++ lib/ansible/plugins/terminal/nxos.py | 6 +++++ lib/ansible/plugins/terminal/vyos.py | 5 ++++ 8 files changed, 56 insertions(+), 7 deletions(-) diff --git a/lib/ansible/plugins/connection/network_cli.py b/lib/ansible/plugins/connection/network_cli.py index c7491d352a3..34c50292438 100644 --- a/lib/ansible/plugins/connection/network_cli.py +++ b/lib/ansible/plugins/connection/network_cli.py @@ -39,14 +39,8 @@ class Connection(_Connection): def __init__(self, play_context, new_stdin, *args, **kwargs): super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs) - assert self._play_context.network_os, 'ansible_network_os must be set' - - self._terminal = terminal_loader.get(self._play_context.network_os, self) - if not self._terminal: - raise AnsibleConnectionFailure('network os %s is not supported' % self._play_context.network_os) - + self._terminal = None self._shell = None - self._matched_prompt = None self._matched_pattern = None self._last_response = None @@ -64,6 +58,24 @@ class Connection(_Connection): def _connect(self): super(Connection, self)._connect() + + network_os = self._play_context.network_os + if not network_os: + for cls in terminal_loader.all(class_only=True): + network_os = cls.guess_network_os(self.ssh) + if network_os: + break + + if not network_os: + raise AnsibleConnectionFailure( + 'unable to determine device network os. Please configure ' + 'ansible_network_os value' + ) + + self._terminal = terminal_loader.get(network_os, self) + if not self._terminal: + raise AnsibleConnectionFailure('network os %s is not supported' % network_os) + return (0, 'connected', '') def open_shell(self, timeout=10): diff --git a/lib/ansible/plugins/terminal/__init__.py b/lib/ansible/plugins/terminal/__init__.py index 3242559084c..bdd424cbca7 100644 --- a/lib/ansible/plugins/terminal/__init__.py +++ b/lib/ansible/plugins/terminal/__init__.py @@ -69,3 +69,6 @@ class TerminalBase(with_metaclass(ABCMeta, object)): def on_deauthorize(self): pass + @staticmethod + def guess_network_os(conn): + pass diff --git a/lib/ansible/plugins/terminal/eos.py b/lib/ansible/plugins/terminal/eos.py index d84c6fb1d6e..c6f74247288 100644 --- a/lib/ansible/plugins/terminal/eos.py +++ b/lib/ansible/plugins/terminal/eos.py @@ -79,4 +79,9 @@ class TerminalModule(TerminalBase): elif prompt.endswith('#'): self._exec_cli_command('disable') + @staticmethod + def guess_network_os(conn): + stdin, stdout, stderr = conn.exec_command('show version') + if 'Arista' in stdout.read(): + return 'eos' diff --git a/lib/ansible/plugins/terminal/ios.py b/lib/ansible/plugins/terminal/ios.py index 5a39acf06d6..37d3ff4bc58 100644 --- a/lib/ansible/plugins/terminal/ios.py +++ b/lib/ansible/plugins/terminal/ios.py @@ -80,3 +80,9 @@ class TerminalModule(TerminalBase): self._exec_cli_command('disable') + @staticmethod + def guess_network_os(conn): + stdin, stdout, stderr = conn.exec_command('show version') + if 'Cisco IOS Software' in stdout.read(): + return 'ios' + diff --git a/lib/ansible/plugins/terminal/iosxr.py b/lib/ansible/plugins/terminal/iosxr.py index bcbd73a0d64..71e1bbfd830 100644 --- a/lib/ansible/plugins/terminal/iosxr.py +++ b/lib/ansible/plugins/terminal/iosxr.py @@ -52,4 +52,10 @@ class TerminalModule(TerminalBase): except AnsibleConnectionFailure: raise AnsibleConnectionFailure('unable to set terminal parameters') + @staticmethod + def guess_network_os(conn): + stdin, stdout, stderr = conn.exec_command('show version') + if 'Cisco IOS XR' in stdout.read(): + return 'iosxr' + diff --git a/lib/ansible/plugins/terminal/junos.py b/lib/ansible/plugins/terminal/junos.py index 10d8b41da77..d2e0891656a 100644 --- a/lib/ansible/plugins/terminal/junos.py +++ b/lib/ansible/plugins/terminal/junos.py @@ -45,3 +45,9 @@ class TerminalModule(TerminalBase): except AnsibleConnectionFailure: raise AnsibleConnectionFailure('unable to set terminal parameters') + @staticmethod + def guess_network_os(conn): + stdin, stdout, stderr = conn.exec_command('show version') + if 'Junos' in stdout.read(): + return 'junos' + diff --git a/lib/ansible/plugins/terminal/nxos.py b/lib/ansible/plugins/terminal/nxos.py index 23bd7555904..e23192f0774 100644 --- a/lib/ansible/plugins/terminal/nxos.py +++ b/lib/ansible/plugins/terminal/nxos.py @@ -52,5 +52,11 @@ class TerminalModule(TerminalBase): except AnsibleConnectionFailure: raise AnsibleConnectionFailure('unable to set terminal parameters') + @staticmethod + def guess_network_os(conn): + stdin, stdout, stderr = conn.exec_command('show version') + if 'NX-OS' in stdout.read(): + return 'nxos' + diff --git a/lib/ansible/plugins/terminal/vyos.py b/lib/ansible/plugins/terminal/vyos.py index 664025bb36b..309f06a7ac1 100644 --- a/lib/ansible/plugins/terminal/vyos.py +++ b/lib/ansible/plugins/terminal/vyos.py @@ -44,4 +44,9 @@ class TerminalModule(TerminalBase): except AnsibleConnectionFailure: raise AnsibleConnectionFailure('unable to set terminal parameters') + @staticmethod + def guess_network_os(conn): + stdin, stdout, stderr = conn.exec_command('cat /proc/version') + if 'vyos' in stdout.read(): + return 'vyos'