diff --git a/docs/docsite/rst/network/user_guide/platform_index.rst b/docs/docsite/rst/network/user_guide/platform_index.rst index 83b45101402..c43abeb53e4 100644 --- a/docs/docsite/rst/network/user_guide/platform_index.rst +++ b/docs/docsite/rst/network/user_guide/platform_index.rst @@ -12,6 +12,7 @@ Some Ansible Network platforms support multiple connection types, privilege esca platform_eos platform_ios + platform_ironware platform_junos platform_nxos @@ -20,30 +21,32 @@ Some Ansible Network platforms support multiple connection types, privilege esca Settings by Platform ================================ -+----------------+-------------------------+----------------------+----------------------+------------------+------------------+ -|.. | | ``ansible_connection:`` settings available | -+----------------+-------------------------+----------------------+----------------------+------------------+------------------+ -| Network OS | ``ansible_network_os:`` | network_cli | netconf | httpapi | local | -+================+=========================+======================+======================+==================+==================+ -| Arista EOS* | ``eos`` | in v. >=2.5 | N/A | in v. >=2.6 | in v. >=2.4 | -+----------------+-------------------------+----------------------+----------------------+------------------+------------------+ -| Cisco ASA | ``asa`` | in v. >=2.5 | N/A | N/A | in v. >=2.4 | -+----------------+-------------------------+----------------------+----------------------+------------------+------------------+ -| Cisco IOS* | ``ios`` | in v. >=2.5 | N/A | N/A | in v. >=2.4 | -+----------------+-------------------------+----------------------+----------------------+------------------+------------------+ -| Cisco IOS XR* | ``iosxr`` | in v. >=2.5 | N/A | N/A | in v. >=2.4 | -+----------------+-------------------------+----------------------+----------------------+------------------+------------------+ -| Cisco NX-OS* | ``nxos`` | in v. >=2.5 | N/A | in v. >=2.6 | in v. >=2.4 | -+----------------+-------------------------+----------------------+----------------------+------------------+------------------+ -| F5 BIG-IP | N/A | N/A | N/A | N/A | in v. >=2.0 | -+----------------+-------------------------+----------------------+----------------------+------------------+------------------+ -| F5 BIG-IQ | N/A | N/A | N/A | N/A | in v. >=2.0 | -+----------------+-------------------------+----------------------+----------------------+------------------+------------------+ -| Junos OS* | ``junos`` | in v. >=2.5 | in v. >=2.5 | N/A | in v. >=2.4 | -+----------------+-------------------------+----------------------+----------------------+------------------+------------------+ -| Nokia SR OS | ``sros`` | in v. >=2.5 | N/A | N/A | in v. >=2.4 | -+----------------+-------------------------+----------------------+----------------------+------------------+------------------+ -| VyOS* | ``vyos`` | in v. >=2.5 | N/A | N/A | in v. >=2.4 | -+----------------+-------------------------+----------------------+----------------------+------------------+------------------+ ++------------------+-------------------------+----------------------+----------------------+------------------+------------------+ +|.. | | ``ansible_connection:`` settings available | ++------------------+-------------------------+----------------------+----------------------+------------------+------------------+ +| Network OS | ``ansible_network_os:`` | network_cli | netconf | httpapi | local | ++==================+=========================+======================+======================+==================+==================+ +| Arista EOS* | ``eos`` | in v. >=2.5 | N/A | in v. >=2.6 | in v. >=2.4 | ++------------------+-------------------------+----------------------+----------------------+------------------+------------------+ +| Cisco ASA | ``asa`` | in v. >=2.5 | N/A | N/A | in v. >=2.4 | ++------------------+-------------------------+----------------------+----------------------+------------------+------------------+ +| Cisco IOS* | ``ios`` | in v. >=2.5 | N/A | N/A | in v. >=2.4 | ++------------------+-------------------------+----------------------+----------------------+------------------+------------------+ +| Cisco IOS XR* | ``iosxr`` | in v. >=2.5 | N/A | N/A | in v. >=2.4 | ++------------------+-------------------------+----------------------+----------------------+------------------+------------------+ +| Cisco NX-OS* | ``nxos`` | in v. >=2.5 | N/A | in v. >=2.6 | in v. >=2.4 | ++------------------+-------------------------+----------------------+----------------------+------------------+------------------+ +| Extreme IronWare | ``ironware`` | in v. >=2.5 | N/A | N/A | in v. >=2.5 | ++------------------+-------------------------+----------------------+----------------------+------------------+------------------+ +| F5 BIG-IP | N/A | N/A | N/A | N/A | in v. >=2.0 | ++------------------+-------------------------+----------------------+----------------------+------------------+------------------+ +| F5 BIG-IQ | N/A | N/A | N/A | N/A | in v. >=2.0 | ++------------------+-------------------------+----------------------+----------------------+------------------+------------------+ +| Junos OS* | ``junos`` | in v. >=2.5 | in v. >=2.5 | N/A | in v. >=2.4 | ++------------------+-------------------------+----------------------+----------------------+------------------+------------------+ +| Nokia SR OS | ``sros`` | in v. >=2.5 | N/A | N/A | in v. >=2.4 | ++------------------+-------------------------+----------------------+----------------------+------------------+------------------+ +| VyOS* | ``vyos`` | in v. >=2.5 | N/A | N/A | in v. >=2.4 | ++------------------+-------------------------+----------------------+----------------------+------------------+------------------+ -`*` Maintained by Ansible Network Team \ No newline at end of file +`*` Maintained by Ansible Network Team diff --git a/docs/docsite/rst/network/user_guide/platform_ironware.rst b/docs/docsite/rst/network/user_guide/platform_ironware.rst new file mode 100644 index 00000000000..e04c6a12d26 --- /dev/null +++ b/docs/docsite/rst/network/user_guide/platform_ironware.rst @@ -0,0 +1,70 @@ +.. _ironware_platform_options: + +*************************************** +IronWare Platform Options +*************************************** + +IronWare supports Enable Mode (Privilege Escalation). This page offers details on how to use Enable Mode on IronWare in Ansible 2.7. + +.. contents:: Topics + +Connections Available +================================================================================ + ++---------------------------+-----------------------------------------------+ +|.. | CLI | ++===========================+===============================================+ +| **Protocol** | SSH | ++---------------------------+-----------------------------------------------+ +| | **Credentials** | | uses SSH keys / SSH-agent if present | +| | | | accepts ``-u myuser -k`` if using password | ++---------------------------+-----------------------------------------------+ +| **Indirect Access** | via a bastion (jump host) | ++---------------------------+-----------------------------------------------+ +| | **Connection Settings** | | ``ansible_connection: network_cli`` | +| | | | | +| | | | | ++---------------------------+-----------------------------------------------+ +| | **Enable Mode** | | supported - use ``ansible_become: yes`` | +| | (Privilege Escalation) | | with ``ansible_become_method: enable`` | +| | | | and ``ansible_become_pass:`` | ++---------------------------+-----------------------------------------------+ +| **Returned Data Format** | ``stdout[0].`` | ++---------------------------+-----------------------------------------------+ + +For legacy playbooks, IronWare still supports ``ansible_connection: local``. We recommend modernizing to use ``ansible_connection: network_cli`` as soon as possible. + +Using CLI in Ansible 2.6 +================================================================================ + +Example CLI ``group_vars/mlx.yml`` +---------------------------------- + +.. code-block:: yaml + + ansible_connection: network_cli + ansible_network_os: ironware + ansible_user: myuser + ansible_ssh_pass: !vault... + ansible_become: yes + ansible_become_method: enable + ansible_become_pass: !vault... + ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q bastion01"' + + +- If you are using SSH keys (including an ssh-agent) you can remove the ``ansible_ssh_pass`` configuration. +- If you are accessing your host directly (not through a bastion/jump host) you can remove the ``ansible_ssh_common_args`` configuration. +- If you are accessing your host through a bastion/jump host, you cannot include your SSH password in the ``ProxyCommand`` directive. To prevent secrets from leaking out (for example in ``ps`` output), SSH does not support providing passwords via environment variables. + +Example CLI Task +---------------- + +.. code-block:: yaml + + - name: Backup current switch config (ironware) + ironware_config: + backup: yes + register: backup_ironware_location + when: ansible_network_os == 'ironware' + +.. include:: shared_snippets/SSH_warning.txt diff --git a/lib/ansible/plugins/action/ironware.py b/lib/ansible/plugins/action/ironware.py index b6c92aca803..b84df72ff6b 100644 --- a/lib/ansible/plugins/action/ironware.py +++ b/lib/ansible/plugins/action/ironware.py @@ -21,11 +21,10 @@ __metaclass__ = type import sys import copy -import json from ansible import constants as C from ansible.module_utils._text import to_text -from ansible.module_utils.connection import Connection +from ansible.module_utils.connection import Connection, ConnectionError from ansible.plugins.action.normal import ActionModule as _ActionModule from ansible.module_utils.network.common.utils import load_provider from ansible.module_utils.network.ironware.ironware import ironware_provider_spec @@ -42,55 +41,59 @@ class ActionModule(_ActionModule): def run(self, tmp=None, task_vars=None): del tmp # tmp no longer has any effect - if self._play_context.connection != 'local': - return dict( - failed=True, - msg='invalid connection specified, expected connection=local, ' - 'got %s' % self._play_context.connection - ) + socket_path = None - provider = load_provider(ironware_provider_spec, self._task.args) + if self._play_context.connection == 'network_cli': + provider = self._task.args.get('provider', {}) + if any(provider.values()): + display.warning('provider is unnecessary when using network_cli and will be ignored') + del self._task.args['provider'] + elif self._play_context.connection == 'local': + provider = load_provider(ironware_provider_spec, self._task.args) + pc = copy.deepcopy(self._play_context) + pc.connection = 'network_cli' + pc.network_os = 'ironware' + pc.remote_addr = provider['host'] or self._play_context.remote_addr + 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.private_key_file = provider['ssh_keyfile'] or self._play_context.private_key_file + pc.become = provider['authorize'] or False + if pc.become: + pc.become_method = 'enable' + pc.become_pass = provider['auth_pass'] - pc = copy.deepcopy(self._play_context) - pc.connection = 'network_cli' - pc.network_os = 'ironware' - pc.remote_addr = provider['host'] or self._play_context.remote_addr - 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.private_key_file = provider['ssh_keyfile'] or self._play_context.private_key_file - command_timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT) - pc.become = provider['authorize'] or False - if pc.become: - pc.become_method = 'enable' - pc.become_pass = provider['auth_pass'] + 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) - 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) - connection.set_options(direct={'persistent_command_timeout': command_timeout}) + command_timeout = int(provider['timeout']) if provider['timeout'] else connection.get_option('persistent_command_timeout') + connection.set_options(direct={'persistent_command_timeout': command_timeout}) - socket_path = connection.run() + socket_path = connection.run() + display.vvvv('socket_path: %s' % socket_path, pc.remote_addr) + if not socket_path: + return {'failed': True, + 'msg': 'unable to open shell. Please see: ' + + 'https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell'} - display.vvvv('socket_path: %s' % socket_path, pc.remote_addr) - if not socket_path: - return {'failed': True, - 'msg': 'unable to open shell. Please see: ' + - 'https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell'} + task_vars['ansible_socket'] = socket_path + else: + return {'failed': True, 'msg': 'Connection type %s is not valid for this module' % self._play_context.connection} # make sure we are in the right cli context which should be # enable mode and not config module + if socket_path is None: + socket_path = self._connection.socket_path + conn = Connection(socket_path) - out = conn.get_prompt() - if to_text(out, errors='surrogate_then_replace').strip().endswith(')#'): - display.vvvv('wrong context, sending end to device', self._play_context.remote_addr) - conn.send_command('end') - - task_vars['ansible_socket'] = socket_path - - if self._play_context.become_method == 'enable': - self._play_context.become = False - self._play_context.become_method = None + try: + out = conn.get_prompt() + while to_text(out, errors='surrogate_then_replace').strip().endswith(')#'): + display.vvvv('wrong context, sending exit to device', self._play_context.remote_addr) + conn.send_command('exit') + out = conn.get_prompt() + except ConnectionError as exc: + return {'failed': True, 'msg': to_text(exc)} result = super(ActionModule, self).run(task_vars=task_vars) - return result diff --git a/lib/ansible/utils/module_docs_fragments/ironware.py b/lib/ansible/utils/module_docs_fragments/ironware.py index 7b65f13f512..7a57478e7df 100644 --- a/lib/ansible/utils/module_docs_fragments/ironware.py +++ b/lib/ansible/utils/module_docs_fragments/ironware.py @@ -24,6 +24,10 @@ class ModuleDocFragment(object): options: authorize: description: + - B(Deprecated) + - "Starting with Ansible 2.7 we recommend using C(connection: network_cli) and C(become: yes)." + - For more information please see the L(IronWare Platform Options guide, ../network/user_guide/platform_ironware.html). + - HORIZONTALLINE - Instructs the module to enter privileged mode on the remote device before sending any commands. If not specified, the device will attempt to execute all commands in non-privileged mode. If the value @@ -33,6 +37,10 @@ options: default: 'no' provider: description: + - B(Deprecated) + - "Starting with Ansible 2.7 we recommend using C(connection: network_cli) and C(become: yes)." + - For more information please see the L(IronWare Platform Options guide, ../network/user_guide/platform_ironware.html). + - HORIZONTALLINE - A dict object containing connection details. suboptions: host: @@ -85,4 +93,6 @@ options: if the console freezes before continuing. For example when saving configurations. default: 10 +notes: + - For more information on using Ansible to manage network devices see the :ref:`Ansible Network Guide ` """