Fix netconf guess_network_os to use ssh_config if supplied. (#55199)

* feature: use network_os=auto to trigger network os guessing

* doc: add debug messages

* fix linting

* fix test_netconf_init default network_os is auto

* add documentation

* fix rst errors

* use init lexer

* Update docs/docsite/rst/network/user_guide/platform_netconf_enabled.rst

Co-Authored-By: Sandra McCann <samccann@redhat.com>

* Update docs/docsite/rst/network/user_guide/platform_netconf_enabled.rst

Co-Authored-By: Sandra McCann <samccann@redhat.com>

* Update docs/docsite/rst/network/user_guide/platform_netconf_enabled.rst

Co-Authored-By: Sandra McCann <samccann@redhat.com>

* Update docs/docsite/rst/network/user_guide/platform_netconf_enabled.rst

Co-Authored-By: Sandra McCann <samccann@redhat.com>

* Update docs/docsite/rst/network/user_guide/platform_netconf_enabled.rst

Co-Authored-By: Sandra McCann <samccann@redhat.com>

* Update docs/docsite/rst/network/user_guide/platform_netconf_enabled.rst

Co-Authored-By: Sandra McCann <samccann@redhat.com>

* Update docs/docsite/rst/network/user_guide/platform_netconf_enabled.rst

Co-Authored-By: Sandra McCann <samccann@redhat.com>

* Update lib/ansible/plugins/connection/netconf.py

Co-Authored-By: Sandra McCann <samccann@redhat.com>

* Update lib/ansible/plugins/connection/netconf.py

Co-Authored-By: Sandra McCann <samccann@redhat.com>

* Update lib/ansible/plugins/connection/netconf.py

Co-Authored-By: Sandra McCann <samccann@redhat.com>

* Update docs/docsite/rst/network/user_guide/platform_netconf_enabled.rst

Co-Authored-By: Sandra McCann <samccann@redhat.com>

* Update docs/docsite/rst/network/user_guide/platform_netconf_enabled.rst

Co-Authored-By: Sandra McCann <samccann@redhat.com>

* Update docs/docsite/rst/network/user_guide/platform_netconf_enabled.rst

Co-Authored-By: Sandra McCann <samccann@redhat.com>
This commit is contained in:
markafarrell 2019-06-21 13:34:13 +10:00 committed by Ganesh Nalawade
parent f864f621d8
commit 43872d6b88
7 changed files with 78 additions and 19 deletions

View file

@ -84,6 +84,39 @@ Example NETCONF Task with configurable variables
vars:
ansible_private_key_file: /home/admin/.ssh/newprivatekeyfile
Note: For nectonf connection plugin configurable variables .. _Refer: https://docs.ansible.com/ansible/latest/plugins/connection/netconf.html
Note: For netconf connection plugin configurable variables see :ref:`netconf <netconf_connection>`.
Bastion/Jumphost Configuration
------------------------------
To use a jump host to connect to a NETCONF enabled device you must set the ``ANSIBLE_NETCONF_SSH_CONFIG`` environment variable.
``ANSIBLE_NETCONF_SSH_CONFIG`` can be set to either:
- 1 or TRUE (to trigger the use of the default SSH config file ~/.ssh/config)
- The absolute path to a custom SSH config file.
The SSH config file should look something like:
.. code-block:: ini
Host *
proxycommand ssh -o StrictHostKeyChecking=no -W %h:%p jumphost-username@jumphost.fqdn.com
StrictHostKeyChecking no
Authentication for the jump host must use key based authentication.
You can either specify the private key used in the SSH config file:
.. code-block:: ini
IdentityFile "/absolute/path/to/private-key.pem"
Or you can use an ssh-agent.
ansible_network_os auto-detection
---------------------------------
If ``ansible_network_os`` is not specified for a host, then Ansible will attempt to automatically detect what ``network_os`` plugin to use.
``ansible_network_os`` auto-detection can also be triggered by using ``auto`` as the ``ansible_network_os``. (Note: Previously ``default`` was used instead of ``auto``).
.. include:: shared_snippets/SSH_warning.txt

View file

@ -44,7 +44,9 @@ options:
description:
- Configures the device platform network operating system. This value is
used to load a device specific netconf plugin. If this option is not
configured, then the default netconf plugin will be used.
configured (or set to C(auto)), then Ansible will attempt to guess the
correct network_os to use.
If it can not guess a network_os correctly it will use C(default).
vars:
- name: ansible_network_os
remote_user:
@ -219,7 +221,9 @@ class Connection(NetworkConnectionBase):
def __init__(self, play_context, new_stdin, *args, **kwargs):
super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
self._network_os = self._network_os or 'default'
# If network_os is not specified then set the network os to auto
# This will be used to trigger the the use of guess_network_os when connecting.
self._network_os = self._network_os or 'auto'
netconf = netconf_loader.get(self._network_os, self)
if netconf:
@ -233,6 +237,7 @@ class Connection(NetworkConnectionBase):
self._manager = None
self.key_filename = None
self._ssh_config = None
def exec_command(self, cmd, in_data=None, sudoable=True):
"""Sends the request to the node and returns the reply
@ -275,25 +280,34 @@ class Connection(NetworkConnectionBase):
if self.key_filename:
self.key_filename = str(os.path.expanduser(self.key_filename))
if self._network_os == 'default':
self._ssh_config = self.get_option('netconf_ssh_config')
if self._ssh_config in BOOLEANS_TRUE:
self._ssh_config = True
elif self._ssh_config in BOOLEANS_FALSE:
self._ssh_config = None
# Try to guess the network_os if the network_os is set to auto
if self._network_os == 'auto':
for cls in netconf_loader.all(class_only=True):
network_os = cls.guess_network_os(self)
if network_os:
self.queue_message('log', 'discovered network_os %s' % network_os)
self.queue_message('vvv', 'discovered network_os %s' % network_os)
self._network_os = network_os
# If we have tried to detect the network_os but were unable to i.e. network_os is still 'auto'
# then use default as the network_os
if self._network_os == 'auto':
# Network os not discovered. Set it to default
self.queue_message('vvv', 'Unable to discover network_os. Falling back to default.')
self._network_os = 'default'
device_params = {'name': NETWORK_OS_DEVICE_PARAM_MAP.get(self._network_os) or self._network_os}
ssh_config = self.get_option('netconf_ssh_config')
if ssh_config in BOOLEANS_TRUE:
ssh_config = True
elif ssh_config in BOOLEANS_FALSE:
ssh_config = None
try:
port = self._play_context.port or 830
self.queue_message('vvv', "ESTABLISH NETCONF SSH CONNECTION FOR USER: %s on PORT %s TO %s" %
(self._play_context.remote_user, port, self._play_context.remote_addr))
self.queue_message('vvv', "ESTABLISH NETCONF SSH CONNECTION FOR USER: %s on PORT %s TO %s WITH SSH_CONFIG = %s" %
(self._play_context.remote_user, port, self._play_context.remote_addr, self._ssh_config))
self._manager = manager.connect(
host=self._play_context.remote_addr,
port=port,
@ -305,7 +319,7 @@ class Connection(NetworkConnectionBase):
device_params=device_params,
allow_agent=self._play_context.allow_agent,
timeout=self.get_option('persistent_connect_timeout'),
ssh_config=ssh_config
ssh_config=self._ssh_config
)
except SSHUnknownHostError as exc:
raise AnsibleConnectionFailure(to_native(exc))

View file

@ -110,7 +110,10 @@ class Netconf(NetconfBase):
hostkey_verify=obj.get_option('host_key_checking'),
look_for_keys=obj.get_option('look_for_keys'),
allow_agent=obj._play_context.allow_agent,
timeout=obj.get_option('persistent_connect_timeout')
timeout=obj.get_option('persistent_connect_timeout'),
# We need to pass in the path to the ssh_config file when guessing
# the network_os so that a jumphost is correctly used if defined
ssh_config=obj._ssh_config
)
except SSHUnknownHostError as exc:
raise AnsibleConnectionFailure(to_native(exc))

View file

@ -104,7 +104,10 @@ class Netconf(NetconfBase):
hostkey_verify=obj.get_option('host_key_checking'),
look_for_keys=obj.get_option('look_for_keys'),
allow_agent=obj._play_context.allow_agent,
timeout=obj.get_option('persistent_connect_timeout')
timeout=obj.get_option('persistent_connect_timeout'),
# We need to pass in the path to the ssh_config file when guessing
# the network_os so that a jumphost is correctly used if defined
ssh_config=obj._ssh_config
)
except SSHUnknownHostError as exc:
raise AnsibleConnectionFailure(to_native(exc))

View file

@ -119,7 +119,10 @@ class Netconf(NetconfBase):
hostkey_verify=obj.get_option('host_key_checking'),
look_for_keys=obj.get_option('look_for_keys'),
allow_agent=obj._play_context.allow_agent,
timeout=obj.get_option('persistent_connect_timeout')
timeout=obj.get_option('persistent_connect_timeout'),
# We need to pass in the path to the ssh_config file when guessing
# the network_os so that a jumphost is correctly used if defined
ssh_config=obj._ssh_config
)
except SSHUnknownHostError as exc:
raise AnsibleConnectionFailure(to_native(exc))

View file

@ -82,7 +82,10 @@ class Netconf(NetconfBase):
hostkey_verify=obj.get_option('host_key_checking'),
look_for_keys=obj.get_option('look_for_keys'),
allow_agent=obj._play_context.allow_agent,
timeout=obj.get_option('persistent_connect_timeout')
timeout=obj.get_option('persistent_connect_timeout'),
# We need to pass in the path to the ssh_config file when guessing
# the network_os so that a jumphost is correctly used if defined
ssh_config=obj._ssh_config
)
except SSHUnknownHostError as exc:
raise AnsibleConnectionFailure(to_native(exc))

View file

@ -63,7 +63,7 @@ class TestNetconfConnectionClass(unittest.TestCase):
pc = PlayContext()
conn = connection_loader.get('netconf', pc, '/dev/null')
self.assertEqual('default', conn._network_os)
self.assertEqual('auto', conn._network_os)
self.assertIsNone(conn._manager)
self.assertFalse(conn._connected)