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:
parent
f864f621d8
commit
43872d6b88
7 changed files with 78 additions and 19 deletions
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in a new issue