From 5a6ee054c0c103a91c1cf535254495a51e1339d7 Mon Sep 17 00:00:00 2001 From: paulquack Date: Tue, 17 Oct 2017 23:54:32 +1100 Subject: [PATCH] Network command module for Brocade IronWare routers (#31429) --- .github/BOTMETA.yml | 13 + lib/ansible/config/base.yml | 2 +- lib/ansible/module_utils/ironware.py | 120 +++++ .../modules/network/ironware/__init__.py | 0 .../network/ironware/ironware_command.py | 192 ++++++++ lib/ansible/plugins/action/ironware.py | 89 ++++ lib/ansible/plugins/cliconf/ironware.py | 81 ++++ lib/ansible/plugins/terminal/ironware.py | 78 +++ .../utils/module_docs_fragments/ironware.py | 91 ++++ .../modules/network/ironware/__init__.py | 0 .../network/ironware/fixtures/show_version | 450 ++++++++++++++++++ .../network/ironware/ironware_module.py | 114 +++++ .../network/ironware/test_ironware_command.py | 99 ++++ 13 files changed, 1328 insertions(+), 1 deletion(-) create mode 100644 lib/ansible/module_utils/ironware.py create mode 100644 lib/ansible/modules/network/ironware/__init__.py create mode 100644 lib/ansible/modules/network/ironware/ironware_command.py create mode 100644 lib/ansible/plugins/action/ironware.py create mode 100644 lib/ansible/plugins/cliconf/ironware.py create mode 100644 lib/ansible/plugins/terminal/ironware.py create mode 100644 lib/ansible/utils/module_docs_fragments/ironware.py create mode 100644 test/units/modules/network/ironware/__init__.py create mode 100644 test/units/modules/network/ironware/fixtures/show_version create mode 100644 test/units/modules/network/ironware/ironware_module.py create mode 100644 test/units/modules/network/ironware/test_ironware_command.py diff --git a/.github/BOTMETA.yml b/.github/BOTMETA.yml index d43e8f4864..6eb7055b24 100644 --- a/.github/BOTMETA.yml +++ b/.github/BOTMETA.yml @@ -466,6 +466,7 @@ files: $modules/network/interface/: $team_networking $modules/network/ios/: privateip rcarrillocruz kedarX $modules/network/iosxr/: privateip rcarrillocruz kedarX + $modules/network/ironware/: paulquack $modules/network/junos/: Qalthos ganeshrn $modules/network/layer2/: $team_networking $modules/network/layer3/: $team_networking @@ -963,6 +964,9 @@ files: $module_utils/iosxr.py: maintainers: $team_networking labels: networking + $module_utils/ironware.py: + maintainers: paulquack + labels: networking $module_utils/junos.py: maintainers: $team_networking labels: networking @@ -1046,6 +1050,9 @@ files: lib/ansible/plugins/action/ios: maintainers: $team_networking labels: networking + lib/ansible/plugins/action/ironware: + maintainers: paulquack + labels: networking lib/ansible/plugins/action/junos: maintainers: $team_networking labels: networking @@ -1064,6 +1071,9 @@ files: lib/ansible/plugins/cliconf/: maintainers: $team_networking labels: networking + lib/ansible/plugins/cliconf/ironware.py: + maintainers: paulquack + labels: networking lib/ansible/plugins/connection/netconf.py: maintainers: $team_networking labels: networking @@ -1111,6 +1121,9 @@ files: lib/ansible/plugins/terminal/iosxr.py: maintainers: $team_networking labels: networking + lib/ansible/plugins/terminal/ironware.py: + maintainers: paulquack + labels: networking lib/ansible/plugins/terminal/junos.py: maintainers: $team_networking labels: networking diff --git a/lib/ansible/config/base.yml b/lib/ansible/config/base.yml index 0ace566641..c6f8ba9715 100644 --- a/lib/ansible/config/base.yml +++ b/lib/ansible/config/base.yml @@ -1293,7 +1293,7 @@ MERGE_MULTIPLE_CLI_TAGS: version_added: "2.3" NETWORK_GROUP_MODULES: name: Network module families - default: [eos, nxos, ios, iosxr, junos, enos, ce, vyos, sros, dellos9, dellos10, dellos6, asa, aruba, aireos, bigip] + default: [eos, nxos, ios, iosxr, junos, enos, ce, vyos, sros, dellos9, dellos10, dellos6, asa, aruba, aireos, bigip, ironware] description: 'TODO: write it' env: [{name: NETWORK_GROUP_MODULES}] ini: diff --git a/lib/ansible/module_utils/ironware.py b/lib/ansible/module_utils/ironware.py new file mode 100644 index 0000000000..d59973f3d9 --- /dev/null +++ b/lib/ansible/module_utils/ironware.py @@ -0,0 +1,120 @@ +# This code is part of Ansible, but is an independent component. +# This particular file snippet, and this file snippet only, is BSD licensed. +# Modules you write using this snippet, which is embedded dynamically by Ansible +# still belong to the author of the module, and may assign their own license +# to the complete work. +# +# (c) 2016 Red Hat Inc. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +from ansible.module_utils._text import to_text +from ansible.module_utils.basic import env_fallback, return_values +from ansible.module_utils.network_common import to_list, EntityCollection +from ansible.module_utils.connection import Connection, exec_command + +_DEVICE_CONFIG = None +_CONNECTION = None + +ironware_provider_spec = { + 'host': dict(), + 'port': dict(type='int'), + 'username': dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])), + 'password': dict(fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD']), no_log=True), + 'ssh_keyfile': dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']), type='path'), + 'authorize': dict(fallback=(env_fallback, ['ANSIBLE_NET_AUTHORIZE']), type='bool'), + 'auth_pass': dict(fallback=(env_fallback, ['ANSIBLE_NET_AUTH_PASS']), no_log=True), + 'timeout': dict(type='int'), +} + +ironware_argument_spec = { + 'provider': dict(type='dict', options=ironware_provider_spec) +} + +command_spec = { + 'command': dict(key=True), + 'prompt': dict(), + 'answer': dict() +} + + +def get_provider_argspec(): + return ironware_provider_spec + + +def check_args(module): + pass + + +def get_connection(module): + global _CONNECTION + if _CONNECTION: + return _CONNECTION + _CONNECTION = Connection(module) + + return _CONNECTION + + +def to_commands(module, commands): + assert isinstance(commands, list), 'argument must be of type ' + + transform = EntityCollection(module, command_spec) + commands = transform(commands) + + for index, item in enumerate(commands): + if module.check_mode and not item['command'].startswith('show'): + module.warn('only show commands are supported when using check ' + 'mode, not executing `%s`' % item['command']) + + return commands + + +def run_commands(module, commands, check_rc=True): + connection = get_connection(module) + + commands = to_commands(module, to_list(commands)) + + responses = list() + + for cmd in commands: + out = connection.get(**cmd) + responses.append(to_text(out, errors='surrogate_then_replace')) + + return responses + + +def get_config(module, source='running', flags=None): + if source is 'running' and flags is None and _DEVICE_CONFIG is not None: + return _DEVICE_CONFIG + else: + conn = get_connection(module) + out = conn.get_config(source=source, flags=flags) + cfg = to_text(out, errors='surrogate_then_replace').strip() + if source is 'running' and flags is None: + _DEVICE_CONFIG = cfg + return cfg + + +def load_config(module, config): + conn = get_connection(module) + conn.edit_config(config) diff --git a/lib/ansible/modules/network/ironware/__init__.py b/lib/ansible/modules/network/ironware/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/ansible/modules/network/ironware/ironware_command.py b/lib/ansible/modules/network/ironware/ironware_command.py new file mode 100644 index 0000000000..52e8e663b4 --- /dev/null +++ b/lib/ansible/modules/network/ironware/ironware_command.py @@ -0,0 +1,192 @@ +#!/usr/bin/python +# +# Copyright: Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + + +DOCUMENTATION = """ +--- +module: ironware_command +version_added: "2.5" +author: "Paul Baker (@paulquack)" +short_description: Run arbitrary commands on Brocade IronWare devices +description: + - Sends arbitrary commands to a Brocade Ironware node and returns the + results read from the device. This module includes a I(wait_for) + argument that will cause the module to wait for a specific condition + before returning or timing out if the condition is not met. +extends_documentation_fragment: ironware +options: + commands: + description: + - List of commands to send to the remote device over the + configured provider. The resulting output from the command + is returned. If the I(wait_for) argument is provided, the + module is not returned until the condition is satisfied or + the number of retires as expired. + required: true + wait_for: + description: + - List of conditions to evaluate against the output of the + command. The task will wait for each condition to be true + before moving forward. If the conditional is not true + within the configured number of retries, the task fails. + See examples. + required: false + default: null + match: + description: + - The I(match) argument is used in conjunction with the + I(wait_for) argument to specify the match policy. If the value + is set to C(all) then all conditionals in the I(wait_for) must be + satisfied. If the value is set to C(any) then only one of the + values must be satisfied. + required: false + default: all + choices: ['any', 'all'] + retries: + description: + - Specifies the number of retries a command should by tried + before it is considered failed. The command is run on the + target device every retry and evaluated against the + I(wait_for) conditions. + required: false + default: 10 + interval: + description: + - Configures the interval in seconds to wait between retries + of the command. If the command does not pass the specified + conditions, the interval indicates how long to wait before + trying the command again. + required: false + default: 1 +""" + +EXAMPLES = """ +# Note: examples below use the following provider dict to handle +# transport and authentication to the node. +--- +vars: + cli: + host: "{{ inventory_hostname }}" + username: username + password: secret + authorize: yes + auth_pass: supersecret + transport: cli + +--- +- ironware_command: + commands: + - show version + provider: "{{ cli }}" + +- ironware_command: + commands: + - show interfaces brief wide + - show mpls vll + provider: "{{ cli }}" +""" + +RETURN = """ +stdout: + description: the set of responses from the commands + returned: always + type: list + sample: ['...', '...'] + +stdout_lines: + description: The value of stdout split into a list + returned: always + type: list + sample: [['...', '...'], ['...'], ['...']] + +failed_conditions: + description: the conditionals that failed + returned: failed + type: list + sample: ['...', '...'] +""" +import time + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.ironware import ironware_argument_spec, check_args +from ansible.module_utils.ironware import run_commands +from ansible.module_utils.netcli import Conditional +from ansible.module_utils.six import string_types + + +def to_lines(stdout): + for item in stdout: + if isinstance(item, string_types): + item = str(item).split('\n') + yield item + + +def main(): + spec = dict( + # { command: , prompt: , response: } + commands=dict(type='list', required=True), + + wait_for=dict(type='list'), + match=dict(default='all', choices=['all', 'any']), + + retries=dict(default=10, type='int'), + interval=dict(default=1, type='int') + ) + + spec.update(ironware_argument_spec) + + module = AnsibleModule(argument_spec=spec, supports_check_mode=True) + check_args(module) + + result = {'changed': False} + + wait_for = module.params['wait_for'] or list() + conditionals = [Conditional(c) for c in wait_for] + + commands = module.params['commands'] + retries = module.params['retries'] + interval = module.params['interval'] + match = module.params['match'] + + while retries > 0: + responses = run_commands(module, commands) + + for item in list(conditionals): + if item(responses): + if match == 'any': + conditionals = list() + break + conditionals.remove(item) + + if not conditionals: + break + + time.sleep(interval) + retries -= 1 + + if conditionals: + failed_conditions = [item.raw for item in conditionals] + msg = 'One or more conditional statements have not be satisfied' + module.fail_json(msg=msg, failed_conditions=failed_conditions) + + result.update({ + 'changed': False, + 'stdout': responses, + 'stdout_lines': list(to_lines(responses)) + }) + + module.exit_json(**result) + + +if __name__ == '__main__': + main() diff --git a/lib/ansible/plugins/action/ironware.py b/lib/ansible/plugins/action/ironware.py new file mode 100644 index 0000000000..91662e04e0 --- /dev/null +++ b/lib/ansible/plugins/action/ironware.py @@ -0,0 +1,89 @@ +# +# (c) 2016 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . +# +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import sys +import copy +import json + +from ansible import constants as C +from ansible.plugins.action.normal import ActionModule as _ActionModule +from ansible.module_utils.network_common import load_provider +from ansible.module_utils.ironware import ironware_provider_spec + +try: + from __main__ import display +except ImportError: + from ansible.utils.display import Display + display = Display() + + +class ActionModule(_ActionModule): + + def run(self, tmp=None, task_vars=None): + + if self._play_context.connection != 'local': + return dict( + failed=True, + msg='invalid connection specified, expected connection=local, ' + 'got %s' % self._play_context.connection + ) + + 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.timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT) + pc.become = provider['authorize'] or False + pc.become_pass = provider['auth_pass'] + + display.vvv('using connection plugin %s' % pc.connection, pc.remote_addr) + connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin) + + 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'} + + # make sure we are in the right cli context which should be + # enable mode and not config module + rc, out, err = connection.exec_command('prompt()') + if str(out).strip().endswith(')#'): + display.vvvv('wrong context, sending exit to device', self._play_context.remote_addr) + connection.exec_command('exit') + + task_vars['ansible_socket'] = socket_path + + if self._play_context.become_method == 'enable': + self._play_context.become = False + self._play_context.become_method = None + + result = super(ActionModule, self).run(tmp, task_vars) + + return result diff --git a/lib/ansible/plugins/cliconf/ironware.py b/lib/ansible/plugins/cliconf/ironware.py new file mode 100644 index 0000000000..2b80aa2667 --- /dev/null +++ b/lib/ansible/plugins/cliconf/ironware.py @@ -0,0 +1,81 @@ +# +# (c) 2017 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . +# +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import re +import json + +from itertools import chain + +from ansible.module_utils._text import to_bytes, to_text +from ansible.module_utils.network_common import to_list +from ansible.plugins.cliconf import CliconfBase, enable_mode + + +class Cliconf(CliconfBase): + + def get_device_info(self): + device_info = {} + + device_info['network_os'] = 'ironware' + reply = self.send_command(b'show version') + data = to_text(reply, errors='surrogate_or_strict').strip() + + match = re.search(r'IronWare : Version (\S+),', data) + if match: + device_info['network_os_version'] = match.group(1) + + match = re.search(r'^(?:System Mode\:|System\:) (CES|CER|MLX|XMR)', data, re.M) + if match: + device_info['network_os_model'] = match.group(1) + + return device_info + + @enable_mode + def get_config(self, source='running', flags=None): + if source not in ('running', 'startup'): + return self.invalid_params("fetching configuration from %s is not supported" % source) + + if source == 'running': + cmd = b'show running-config' + if flags is not None: + cmd += ' ' + ' '.join(flags) + + else: + cmd = b'show configuration' + if flags is not None: + return self.invalid_params("flags are only supported with running-config") + + return self.send_command(cmd) + + @enable_mode + def edit_config(self, command): + for cmd in chain([b'configure terminal'], to_list(command), [b'end']): + self.send_command(cmd) + + def get(self, *args, **kwargs): + return self.send_command(*args, **kwargs) + + def get_capabilities(self): + result = {} + result['rpc'] = self.get_base_rpc() + result['network_api'] = 'cliconf' + result['device_info'] = self.get_device_info() + return json.dumps(result) diff --git a/lib/ansible/plugins/terminal/ironware.py b/lib/ansible/plugins/terminal/ironware.py new file mode 100644 index 0000000000..d55eb55c1d --- /dev/null +++ b/lib/ansible/plugins/terminal/ironware.py @@ -0,0 +1,78 @@ +# +# (c) 2016 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . +# +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import re +import json + +from ansible.errors import AnsibleConnectionFailure +from ansible.module_utils._text import to_text, to_bytes +from ansible.plugins.terminal import TerminalBase + + +class TerminalModule(TerminalBase): + + terminal_stdout_re = [ + re.compile(r"[\r\n]?(?:\w+@)?[\w+\-\.:\/\[\]]+(?:\([^\)]+\)){,3}(?:>|#) ?$") + ] + + terminal_stderr_re = [ + re.compile(r"[\r\n]Error - "), + re.compile(r"[\r\n](?:incomplete|ambiguous|unrecognised|invalid) (?:command|input)", re.I) + ] + + def on_open_shell(self): + self.disable_pager() + + def disable_pager(self): + cmd = {u'command': u'terminal length 0'} + try: + self._exec_cli_command(u'terminal length 0') + except AnsibleConnectionFailure: + raise AnsibleConnectionFailure('unable to disable terminal pager') + + def on_authorize(self, passwd=None): + if self._get_prompt().strip().endswith(b'#'): + return + + cmd = {u'command': u'enable'} + if passwd: + # Note: python-3.5 cannot combine u"" and r"" together. Thus make + # an r string and use to_text to ensure it's text on both py2 and py3. + cmd[u'prompt'] = to_text(r"[\r\n]?password: ?$", errors='surrogate_or_strict') + cmd[u'answer'] = passwd + + try: + self._exec_cli_command(to_bytes(json.dumps(cmd), errors='surrogate_or_strict')) + except AnsibleConnectionFailure: + raise AnsibleConnectionFailure('unable to elevate privilege to enable mode') + + def on_deauthorize(self): + prompt = self._get_prompt() + if prompt is None: + # if prompt is None most likely the terminal is hung up at a prompt + return + + if b'(config' in prompt: + self._exec_cli_command(b'end') + self._exec_cli_command(b'exit') + + elif prompt.endswith(b'#'): + self._exec_cli_command(b'exit') diff --git a/lib/ansible/utils/module_docs_fragments/ironware.py b/lib/ansible/utils/module_docs_fragments/ironware.py new file mode 100644 index 0000000000..54a11b6485 --- /dev/null +++ b/lib/ansible/utils/module_docs_fragments/ironware.py @@ -0,0 +1,91 @@ +# +# (c) 2017, Paul Baker <@paulquack> +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + + +class ModuleDocFragment(object): + + # Standard files documentation fragment + DOCUMENTATION = """ +options: + authorize: + description: + - 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 + is not specified in the task, the value of environment variable + C(ANSIBLE_NET_AUTHORIZE) will be used instead. + default: no + choices: ['yes', 'no'] + provider: + description: + - A dict object containing connection details. + default: null + suboptions: + host: + description: + - Specifies the DNS host name or address for connecting to the remote + device over the specified transport. The value of host is used as + the destination address for the transport. + port: + description: + - Specifies the port to use when building the connection to the remote + device. + default: 22 + username: + description: + - Configures the username to use to authenticate the connection to + the remote device. This value is used to authenticate + the SSH session. If the value is not specified in the task, the + value of environment variable C(ANSIBLE_NET_USERNAME) will be used instead. + password: + description: + - Specifies the password to use to authenticate the connection to + the remote device. This value is used to authenticate + the SSH session. If the value is not specified in the task, the + value of environment variable C(ANSIBLE_NET_PASSWORD) will be used instead. + default: null + ssh_keyfile: + description: + - Specifies the SSH key to use to authenticate the connection to + the remote device. This value is the path to the + key used to authenticate the SSH session. If the value is not specified + in the task, the value of environment variable C(ANSIBLE_NET_SSH_KEYFILE) + will be used instead. + authorize: + description: + - 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 + is not specified in the task, the value of environment variable + C(ANSIBLE_NET_AUTHORIZE) will be used instead. + default: no + choices: ['yes', 'no'] + auth_pass: + description: + - Specifies the password to use if required to enter privileged mode + on the remote device. If I(authorize) is false, then this argument + does nothing. If the value is not specified in the task, the value of + environment variable C(ANSIBLE_NET_AUTH_PASS) will be used instead. + default: none + timeout: + description: + - Specifies idle timeout in seconds for the connection, in seconds. Useful + if the console freezes before continuing. For example when saving + configurations. + default: 10 +""" diff --git a/test/units/modules/network/ironware/__init__.py b/test/units/modules/network/ironware/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/units/modules/network/ironware/fixtures/show_version b/test/units/modules/network/ironware/fixtures/show_version new file mode 100644 index 0000000000..18c8732676 --- /dev/null +++ b/test/units/modules/network/ironware/fixtures/show_version @@ -0,0 +1,450 @@ +System Mode: MLX +Chassis: NetIron 16-slot (Serial #: H70529F00X, Part #: 35568-001) +NI-X-HSF Switch Fabric Module 1 (Serial #: BEU3243L04H, Part #: 60-1003266-01) +FE 1: Type fe600, Version 1 +FE 2: Type fe600, Version 1 +FE 3: Type fe600, Version 1 +Switch Fabric Module 1 Up Time is 154 days 15 hours 27 minutes 52 seconds +NI-X-HSF Switch Fabric Module 2 (Serial #: BEU3243L03N, Part #: 60-1003266-01) +FE 1: Type fe600, Version 1 +FE 2: Type fe600, Version 1 +FE 3: Type fe600, Version 1 +Switch Fabric Module 2 Up Time is 154 days 15 hours 27 minutes 52 seconds +NI-X-HSF Switch Fabric Module 3 (Serial #: BEU3243L03X, Part #: 60-1003266-01) +FE 1: Type fe600, Version 1 +FE 2: Type fe600, Version 1 +FE 3: Type fe600, Version 1 +Switch Fabric Module 3 Up Time is 154 days 15 hours 27 minutes 52 seconds +NI-X-HSF Switch Fabric Module 4 (Serial #: BEU3243L041, Part #: 60-1003266-01) +FE 1: Type fe600, Version 1 +FE 2: Type fe600, Version 1 +FE 3: Type fe600, Version 1 +Switch Fabric Module 4 Up Time is 154 days 15 hours 27 minutes 52 seconds +========================================================================== +SL M1: BR-MLX-MR2-M Management Module Active (Serial #: BVP3248L00T, Part #: 60-1003268-01): +Boot : Version 5.8.0T165 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:10 labeled as xmprm05800 + (521590 bytes) from boot flash +Monitor : Version 5.8.0T165 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:01:40 labeled as xmb05800 + (539721 bytes) from code flash +IronWare : Version 5.8.0fT163 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on Feb 24 2017 at 02:54:38 labeled as xmr05800fb + (9983317 bytes) from Primary +Board ID : 00 MBRIDGE Revision : 37 +1666 MHz Power PC processor 7448 (version 8004/0202) 166 MHz bus +512 KB Boot Flash (MX29LV040C), 128 MB Code Flash (MT28F256J3) +4096 MB DRAM INSTALLED +4096 MB DRAM ADDRESSABLE +Active Management uptime is 154 days 15 hours 27 minutes 52 seconds +========================================================================== +SL M2: BR-MLX-MR2-M Management Module Standby (Serial #: BVP3248L00N, Part #: 60-1003268-01): +Boot : Version 5.8.0T165 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:10 labeled as xmprm05800 + (521590 bytes) from boot flash +Monitor : Version 5.8.0T165 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:01:40 labeled as xmb05800 + (539721 bytes) from code flash +IronWare : Version 5.8.0fT163 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on Feb 24 2017 at 02:54:38 labeled as xmr05800fb + (9983317 bytes) from Primary +Board ID : 00 MBRIDGE Revision : 37 +1666 MHz Power PC processor 7448 (version 8004/0202) 166 MHz bus +512 KB Boot Flash (MX29LV040C), 128 MB Code Flash (MT28F256J3) +4096 MB DRAM INSTALLED +4096 MB DRAM ADDRESSABLE +Standby Management uptime is 154 days 15 hours 26 minutes 13 seconds +========================================================================== +SL 1: BR-MLX-1GFx24-X 24-port 1GbE SFP Module (Serial #: BND0401H034, Part #: 60-1001892-10) +License: (LID: dpfFJFGjFIJ) +Boot : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:24 labeled as xmlprm05800 + (449481 bytes) from boot flash +Monitor : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:40 labeled as xmlb05800 + (568745 bytes) from code flash +IronWare : Version 5.8.0fT177 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on Feb 24 2017 at 03:02:10 labeled as xmlp05800fb + (9304807 bytes) from Primary +FPGA versions: +Valid PBIF Version = 4.04, Build Time = 11/10/2014 22:10:00 + +Valid XPP Version = 1.03, Build Time = 6/30/2016 10:37:00 + +Valid STATS Version = 0.09, Build Time = 11/21/2010 14:52:00 + +BCM56512GMAC 0 +BCM56512GMAC 1 +666 MHz MPC MPC8541E (version 8020/0020) 333 MHz bus +512 KB Boot Flash (MX29LV040C), 16 MB Code Flash (MT28F128J3) +1024 MB DRAM, 8 KB SRAM +LP Slot 1 uptime is 154 days 15 hours 26 minutes 17 seconds +========================================================================== +SL 2: BR-MLX-1GFx24-X 24-port 1GbE SFP Module (Serial #: BND0401H030, Part #: 60-1001892-10) +License: (LID: dpfFJFGjFIF) +Boot : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:24 labeled as xmlprm05800 + (449481 bytes) from boot flash +Monitor : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:40 labeled as xmlb05800 + (568745 bytes) from code flash +IronWare : Version 5.8.0fT177 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on Feb 24 2017 at 03:02:10 labeled as xmlp05800fb + (9304807 bytes) from Primary +FPGA versions: +Valid PBIF Version = 4.04, Build Time = 11/10/2014 22:10:00 + +Valid XPP Version = 1.03, Build Time = 6/30/2016 10:37:00 + +Valid STATS Version = 0.09, Build Time = 11/21/2010 14:52:00 + +BCM56512GMAC 0 +BCM56512GMAC 1 +666 MHz MPC MPC8541E (version 8020/0020) 333 MHz bus +512 KB Boot Flash (MX29LV040C), 16 MB Code Flash (MT28F128J3) +1024 MB DRAM, 8 KB SRAM +LP Slot 2 uptime is 154 days 15 hours 26 minutes 17 seconds +========================================================================== +SL 3: BR-MLX-1GFx24-X 24-port 1GbE SFP Module (Serial #: BND0415H00E, Part #: 60-1001892-11) +License: (LID: dpfFJGKjFFg) +Boot : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:24 labeled as xmlprm05800 + (449481 bytes) from boot flash +Monitor : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:40 labeled as xmlb05800 + (568745 bytes) from code flash +IronWare : Version 5.8.0fT177 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on Feb 24 2017 at 03:02:10 labeled as xmlp05800fb + (9304807 bytes) from Primary +FPGA versions: +Valid PBIF Version = 4.04, Build Time = 11/10/2014 22:10:00 + +Valid XPP Version = 1.03, Build Time = 6/30/2016 10:37:00 + +Valid STATS Version = 0.09, Build Time = 11/21/2010 14:52:00 + +BCM56512GMAC 0 +BCM56512GMAC 1 +666 MHz MPC MPC8541E (version 8020/0020) 333 MHz bus +512 KB Boot Flash (MX29LV040C), 16 MB Code Flash (MT28F128J3) +1024 MB DRAM, 8 KB SRAM +LP Slot 3 uptime is 154 days 15 hours 26 minutes 17 seconds +========================================================================== +SL 4: BR-MLX-1GFx24-X 24-port 1GbE SFP Module (Serial #: BND0415H02C, Part #: 60-1001892-11) +License: (LID: dpfFJGKjFHe) +Boot : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:24 labeled as xmlprm05800 + (449481 bytes) from boot flash +Monitor : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:40 labeled as xmlb05800 + (568745 bytes) from code flash +IronWare : Version 5.8.0fT177 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on Feb 24 2017 at 03:02:10 labeled as xmlp05800fb + (9304807 bytes) from Primary +FPGA versions: +Valid PBIF Version = 4.04, Build Time = 11/10/2014 22:10:00 + +Valid XPP Version = 1.03, Build Time = 6/30/2016 10:37:00 + +Valid STATS Version = 0.09, Build Time = 11/21/2010 14:52:00 + +BCM56512GMAC 0 +BCM56512GMAC 1 +666 MHz MPC MPC8541E (version 8020/0020) 333 MHz bus +512 KB Boot Flash (MX29LV040C), 16 MB Code Flash (MT28F128J3) +1024 MB DRAM, 8 KB SRAM +LP Slot 4 uptime is 154 days 15 hours 26 minutes 17 seconds +========================================================================== +SL 5: BR-MLX-1GFx24-X 24-port 1GbE SFP Module (Serial #: BND0422H01T, Part #: 60-1001892-11) +License: (LID: dpfFJHHjFGv) +Boot : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:24 labeled as xmlprm05800 + (449481 bytes) from boot flash +Monitor : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:40 labeled as xmlb05800 + (568745 bytes) from code flash +IronWare : Version 5.8.0fT177 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on Feb 24 2017 at 03:02:10 labeled as xmlp05800fb + (9304807 bytes) from Primary +FPGA versions: +Valid PBIF Version = 4.04, Build Time = 11/10/2014 22:10:00 + +Valid XPP Version = 1.03, Build Time = 6/30/2016 10:37:00 + +Valid STATS Version = 0.09, Build Time = 11/21/2010 14:52:00 + +BCM56512GMAC 0 +BCM56512GMAC 1 +666 MHz MPC MPC8541E (version 8020/0020) 333 MHz bus +512 KB Boot Flash (MX29LV040C), 16 MB Code Flash (MT28F128J3) +1024 MB DRAM, 8 KB SRAM +LP Slot 5 uptime is 154 days 15 hours 26 minutes 17 seconds +========================================================================== +SL 6: BR-MLX-1GFx24-X 24-port 1GbE SFP Module (Serial #: BND0430H01S, Part #: 60-1001892-11) +License: (LID: dpfFJIFjFGu) +Boot : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:24 labeled as xmlprm05800 + (449481 bytes) from boot flash +Monitor : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:40 labeled as xmlb05800 + (568745 bytes) from code flash +IronWare : Version 5.8.0fT177 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on Feb 24 2017 at 03:02:10 labeled as xmlp05800fb + (9304807 bytes) from Primary +FPGA versions: +Valid PBIF Version = 4.04, Build Time = 11/10/2014 22:10:00 + +Valid XPP Version = 1.03, Build Time = 6/30/2016 10:37:00 + +Valid STATS Version = 0.09, Build Time = 11/21/2010 14:52:00 + +BCM56512GMAC 0 +BCM56512GMAC 1 +666 MHz MPC MPC8541E (version 8020/0020) 333 MHz bus +512 KB Boot Flash (MX29LV040C), 16 MB Code Flash (MT28F128J3) +1024 MB DRAM, 8 KB SRAM +LP Slot 6 uptime is 154 days 15 hours 26 minutes 17 seconds +========================================================================== +SL 7: BR-MLX-1GFx24-X 24-port 1GbE SFP Module (Serial #: BND0428H024, Part #: 60-1001892-11) +License: MLX-1Gx24-X-Upgrade (LID: dpfFJHNjFHJ) +Boot : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:24 labeled as xmlprm05800 + (449481 bytes) from boot flash +Monitor : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:40 labeled as xmlb05800 + (568745 bytes) from code flash +IronWare : Version 5.8.0fT177 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on Feb 24 2017 at 03:02:10 labeled as xmlp05800fb + (9304807 bytes) from Primary +FPGA versions: +Valid PBIF Version = 4.04, Build Time = 11/10/2014 22:10:00 + +Valid XPP Version = 1.03, Build Time = 6/30/2016 10:37:00 + +Valid STATS Version = 0.09, Build Time = 11/21/2010 14:52:00 + +BCM56512GMAC 0 +BCM56512GMAC 1 +666 MHz MPC MPC8541E (version 8020/0020) 333 MHz bus +512 KB Boot Flash (MX29LV040C), 16 MB Code Flash (MT28F128J3) +1024 MB DRAM, 8 KB SRAM +LP Slot 7 uptime is 154 days 15 hours 26 minutes 17 seconds +========================================================================== +SL 8: BR-MLX-1GFx24-X 24-port 1GbE SFP Module (Serial #: BND0427H00A, Part #: 60-1001892-11) +License: MLX-1Gx24-X-Upgrade (LID: dpfFJHMjFFc) +Boot : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:24 labeled as xmlprm05800 + (449481 bytes) from boot flash +Monitor : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:40 labeled as xmlb05800 + (568745 bytes) from code flash +IronWare : Version 5.8.0fT177 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on Feb 24 2017 at 03:02:10 labeled as xmlp05800fb + (9304807 bytes) from Primary +FPGA versions: +Valid PBIF Version = 4.04, Build Time = 11/10/2014 22:10:00 + +Valid XPP Version = 1.03, Build Time = 6/30/2016 10:37:00 + +Valid STATS Version = 0.09, Build Time = 11/21/2010 14:52:00 + +BCM56512GMAC 0 +BCM56512GMAC 1 +666 MHz MPC MPC8541E (version 8020/0020) 333 MHz bus +512 KB Boot Flash (MX29LV040C), 16 MB Code Flash (MT28F128J3) +1024 MB DRAM, 8 KB SRAM +LP Slot 8 uptime is 154 days 15 hours 26 minutes 17 seconds +========================================================================== +SL 9: BR-MLX-1GFx24-X 24-port 1GbE SFP Module (Serial #: BND0428J029, Part #: 60-1001892-12) +License: MLX-1Gx24-X-Upgrade (LID: dpfFJHNlFHO) +Boot : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:24 labeled as xmlprm05800 + (449481 bytes) from boot flash +Monitor : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:40 labeled as xmlb05800 + (568745 bytes) from code flash +IronWare : Version 5.8.0fT177 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on Feb 24 2017 at 03:02:10 labeled as xmlp05800fb + (9304807 bytes) from Primary +FPGA versions: +Valid PBIF Version = 4.04, Build Time = 11/10/2014 22:10:00 + +Valid XPP Version = 1.03, Build Time = 6/30/2016 10:37:00 + +Valid STATS Version = 0.09, Build Time = 11/21/2010 14:52:00 + +BCM56512GMAC 0 +BCM56512GMAC 1 +666 MHz MPC MPC8541E (version 8020/0020) 333 MHz bus +512 KB Boot Flash (MX29LV040C), 16 MB Code Flash (MT28F128J3) +1024 MB DRAM, 8 KB SRAM +LP Slot 9 uptime is 154 days 15 hours 26 minutes 17 seconds +========================================================================== +SL 10: BR-MLX-1GFx24-X 24-port 1GbE SFP Module (Serial #: BND0418J00E, Part #: 60-1001892-12) +License: (LID: dpfFJGNlFFg) +Boot : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:24 labeled as xmlprm05800 + (449481 bytes) from boot flash +Monitor : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:40 labeled as xmlb05800 + (568745 bytes) from code flash +IronWare : Version 5.8.0fT177 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on Feb 24 2017 at 03:02:10 labeled as xmlp05800fb + (9304807 bytes) from Primary +FPGA versions: +Valid PBIF Version = 4.04, Build Time = 11/10/2014 22:10:00 + +Valid XPP Version = 1.03, Build Time = 6/30/2016 10:37:00 + +Valid STATS Version = 0.09, Build Time = 11/21/2010 14:52:00 + +BCM56512GMAC 0 +BCM56512GMAC 1 +666 MHz MPC MPC8541E (version 8020/0020) 333 MHz bus +512 KB Boot Flash (MX29LV040C), 16 MB Code Flash (MT28F128J3) +1024 MB DRAM, 8 KB SRAM +LP Slot 10 uptime is 154 days 15 hours 26 minutes 17 seconds +========================================================================== +SL 11: BR-MLX-1GFx24-X 24-port 1GbE SFP Module (Serial #: BND0437J012, Part #: 60-1001892-12) +License: MLX-1Gx24-X-Upgrade (LID: dpfFJIMlFGH) +Boot : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:24 labeled as xmlprm05800 + (449481 bytes) from boot flash +Monitor : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:40 labeled as xmlb05800 + (568745 bytes) from code flash +IronWare : Version 5.8.0fT177 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on Feb 24 2017 at 03:02:10 labeled as xmlp05800fb + (9304807 bytes) from Primary +FPGA versions: +Valid PBIF Version = 4.04, Build Time = 11/10/2014 22:10:00 + +Valid XPP Version = 1.03, Build Time = 6/30/2016 10:37:00 + +Valid STATS Version = 0.09, Build Time = 11/21/2010 14:52:00 + +BCM56512GMAC 0 +BCM56512GMAC 1 +666 MHz MPC MPC8541E (version 8020/0020) 333 MHz bus +512 KB Boot Flash (MX29LV040C), 16 MB Code Flash (MT28F128J3) +1024 MB DRAM, 8 KB SRAM +LP Slot 11 uptime is 154 days 15 hours 26 minutes 17 seconds +========================================================================== +SL 12: BR-MLX-1GFx24-X 24-port 1GbE SFP Module (Serial #: BND0401H05A, Part #: 60-1001892-10) +License: (LID: dpfFJFGjFKc) +Boot : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:24 labeled as xmlprm05800 + (449481 bytes) from boot flash +Monitor : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:40 labeled as xmlb05800 + (568745 bytes) from code flash +IronWare : Version 5.8.0fT177 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on Feb 24 2017 at 03:02:10 labeled as xmlp05800fb + (9304807 bytes) from Primary +FPGA versions: +Valid PBIF Version = 4.04, Build Time = 11/10/2014 22:10:00 + +Valid XPP Version = 1.03, Build Time = 6/30/2016 10:37:00 + +Valid STATS Version = 0.09, Build Time = 11/21/2010 14:52:00 + +BCM56512GMAC 0 +BCM56512GMAC 1 +666 MHz MPC MPC8541E (version 8020/0020) 333 MHz bus +512 KB Boot Flash (MX29LV040C), 16 MB Code Flash (MT28F128J3) +1024 MB DRAM, 8 KB SRAM +LP Slot 12 uptime is 154 days 15 hours 26 minutes 17 seconds +========================================================================== +SL 13: NI-MLX-10Gx8-M 8-port 10GbE (M) Module (Serial #: BEQ3219M01V, Part #: 60-1003263-01) +(LID: dgsIHGOoFGx) +Boot : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:24 labeled as xmlprm05800 + (449481 bytes) from boot flash +Monitor : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:40 labeled as xmlb05800 + (568745 bytes) from code flash +IronWare : Version 5.8.0fT177 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on Feb 24 2017 at 03:02:10 labeled as xmlp05800fb + (9304807 bytes) from Primary +FPGA versions: +Valid PBIF Version = 2.24, Build Time = 4/7/2016 14:16:00 + +Valid XPP Version = 0.08, Build Time = 6/27/2016 10:36:00 + +MACXPP40G 0 +MACXPP40G 1 +1333 MHz MPC MPC8548 (version 8021/0022) 533 MHz bus +512 KB Boot Flash (MX29LV040C), 64 MB Code Flash (MT28F256J3) +1024 MB DRAM, 8 KB SRAM +LP Slot 13 uptime is 154 days 15 hours 26 minutes 20 seconds +========================================================================== +SL 14: NI-MLX-10Gx8-M 8-port 10GbE (M) Module (Serial #: BEQ3219M01Z, Part #: 60-1003263-01) +(LID: dgsIHGOoFGb) +Boot : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:24 labeled as xmlprm05800 + (449481 bytes) from boot flash +Monitor : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:40 labeled as xmlb05800 + (568745 bytes) from code flash +IronWare : Version 5.8.0fT177 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on Feb 24 2017 at 03:02:10 labeled as xmlp05800fb + (9304807 bytes) from Primary +FPGA versions: +Valid PBIF Version = 2.24, Build Time = 4/7/2016 14:16:00 + +Valid XPP Version = 0.08, Build Time = 6/27/2016 10:36:00 + +MACXPP40G 0 +MACXPP40G 1 +1333 MHz MPC MPC8548 (version 8021/0022) 533 MHz bus +512 KB Boot Flash (MX29LV040C), 64 MB Code Flash (MT28F256J3) +1024 MB DRAM, 8 KB SRAM +LP Slot 14 uptime is 154 days 15 hours 26 minutes 21 seconds +========================================================================== +SL 15: NI-MLX-10Gx8-M 8-port 10GbE (M) Module (Serial #: BEQ0428J001, Part #: 60-1001587-16) +(LID: dgsFJHNlFFG) +Boot : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:24 labeled as xmlprm05800 + (449481 bytes) from boot flash +Monitor : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:40 labeled as xmlb05800 + (568745 bytes) from code flash +IronWare : Version 5.8.0fT177 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on Feb 24 2017 at 03:02:10 labeled as xmlp05800fb + (9304807 bytes) from Primary +FPGA versions: +Valid PBIF Version = 2.24, Build Time = 4/7/2016 14:16:00 + +Valid XPP Version = 0.08, Build Time = 6/27/2016 10:36:00 + +MACXPP40G 0 +MACXPP40G 1 +1333 MHz MPC MPC8548 (version 8021/0022) 533 MHz bus +512 KB Boot Flash (MX29LV040C), 64 MB Code Flash (MT28F256J3) +1024 MB DRAM, 8 KB SRAM +LP Slot 15 uptime is 154 days 15 hours 26 minutes 21 seconds +========================================================================== +SL 16: NI-MLX-10Gx8-M 8-port 10GbE (M) Module (Serial #: BEQ0443G098, Part #: 60-1001587-14) +(LID: dgsFJJIiFON) +Boot : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:24 labeled as xmlprm05800 + (449481 bytes) from boot flash +Monitor : Version 5.8.0T175 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on May 18 2015 at 13:02:40 labeled as xmlb05800 + (568745 bytes) from code flash +IronWare : Version 5.8.0fT177 Copyright (c) 1996-2014 Brocade Communications Systems, Inc. +Compiled on Feb 24 2017 at 03:02:10 labeled as xmlp05800fb + (9304807 bytes) from Primary +FPGA versions: +Valid PBIF Version = 2.24, Build Time = 4/7/2016 14:16:00 + +Valid XPP Version = 0.08, Build Time = 6/27/2016 10:36:00 + +MACXPP40G 0 +MACXPP40G 1 +1333 MHz MPC MPC8548 (version 8021/0022) 533 MHz bus +512 KB Boot Flash (MX29LV040C), 64 MB Code Flash (MT28F256J3) +1024 MB DRAM, 8 KB SRAM +LP Slot 16 uptime is 154 days 15 hours 26 minutes 20 seconds +========================================================================== +All show version done diff --git a/test/units/modules/network/ironware/ironware_module.py b/test/units/modules/network/ironware/ironware_module.py new file mode 100644 index 0000000000..4a68cbbc54 --- /dev/null +++ b/test/units/modules/network/ironware/ironware_module.py @@ -0,0 +1,114 @@ +# (c) 2016 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import os +import json + +from ansible.compat.tests import unittest +from ansible.compat.tests.mock import patch +from ansible.module_utils import basic +from ansible.module_utils._text import to_bytes + + +def set_module_args(args): + args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) + basic._ANSIBLE_ARGS = to_bytes(args) + +fixture_path = os.path.join(os.path.dirname(__file__), 'fixtures') +fixture_data = {} + + +def load_fixture(name): + path = os.path.join(fixture_path, name) + + if path in fixture_data: + return fixture_data[path] + + with open(path) as f: + data = f.read() + + try: + data = json.loads(data) + except: + pass + + fixture_data[path] = data + return data + + +class AnsibleExitJson(Exception): + pass + + +class AnsibleFailJson(Exception): + pass + + +class TestIronwareModule(unittest.TestCase): + + def execute_module(self, failed=False, changed=False, commands=None, sort=True, defaults=False): + + self.load_fixtures(commands) + + if failed: + result = self.failed() + self.assertTrue(result['failed'], result) + else: + result = self.changed(changed) + self.assertEqual(result['changed'], changed, result) + + if commands is not None: + if sort: + self.assertEqual(sorted(commands), sorted(result['commands']), result['commands']) + else: + self.assertEqual(commands, result['commands'], result['commands']) + + return result + + def failed(self): + def fail_json(*args, **kwargs): + kwargs['failed'] = True + raise AnsibleFailJson(kwargs) + + with patch.object(basic.AnsibleModule, 'fail_json', fail_json): + with self.assertRaises(AnsibleFailJson) as exc: + self.module.main() + + result = exc.exception.args[0] + self.assertTrue(result['failed'], result) + return result + + def changed(self, changed=False): + def exit_json(*args, **kwargs): + if 'changed' not in kwargs: + kwargs['changed'] = False + raise AnsibleExitJson(kwargs) + + with patch.object(basic.AnsibleModule, 'exit_json', exit_json): + with self.assertRaises(AnsibleExitJson) as exc: + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], changed, result) + return result + + def load_fixtures(self, commands=None): + pass diff --git a/test/units/modules/network/ironware/test_ironware_command.py b/test/units/modules/network/ironware/test_ironware_command.py new file mode 100644 index 0000000000..9cb4c22acd --- /dev/null +++ b/test/units/modules/network/ironware/test_ironware_command.py @@ -0,0 +1,99 @@ +# (c) 2016 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import json + +from ansible.compat.tests.mock import patch +from ansible.modules.network.ironware import ironware_command +from .ironware_module import TestIronwareModule, load_fixture, set_module_args + + +class TestIronwareCommandModule(TestIronwareModule): + + module = ironware_command + + def setUp(self): + self.mock_run_commands = patch('ansible.modules.network.ironware.ironware_command.run_commands') + self.run_commands = self.mock_run_commands.start() + + def tearDown(self): + self.mock_run_commands.stop() + + def load_fixtures(self, commands=None): + + def load_from_file(*args, **kwargs): + module, commands = args + output = list() + + for command in commands: + filename = str(command).replace(' ', '_') + output.append(load_fixture(filename)) + return output + + self.run_commands.side_effect = load_from_file + + def test_ironware_command_simple(self): + set_module_args(dict(commands=['show version'])) + result = self.execute_module() + self.assertEqual(len(result['stdout']), 1) + self.assertTrue(result['stdout'][0].startswith('System Mode: MLX')) + + def test_ironware_command_multiple(self): + set_module_args(dict(commands=['show version', 'show version'])) + result = self.execute_module() + self.assertEqual(len(result['stdout']), 2) + self.assertTrue(result['stdout'][0].startswith('System Mode: MLX')) + + def test_ironware_command_wait_for(self): + wait_for = 'result[0] contains "IronWare"' + set_module_args(dict(commands=['show version'], wait_for=wait_for)) + self.execute_module() + + def test_ironware_command_wait_for_fails(self): + wait_for = 'result[0] contains "test string"' + set_module_args(dict(commands=['show version'], wait_for=wait_for)) + self.execute_module(failed=True) + self.assertEqual(self.run_commands.call_count, 10) + + def test_ironware_command_retries(self): + wait_for = 'result[0] contains "test string"' + set_module_args(dict(commands=['show version'], wait_for=wait_for, retries=2)) + self.execute_module(failed=True) + self.assertEqual(self.run_commands.call_count, 2) + + def test_ironware_command_match_any(self): + wait_for = ['result[0] contains "IronWare"', + 'result[0] contains "test string"'] + set_module_args(dict(commands=['show version'], wait_for=wait_for, match='any')) + self.execute_module() + + def test_ironware_command_match_all(self): + wait_for = ['result[0] contains "IronWare"', + 'result[0] contains "uptime is"'] + set_module_args(dict(commands=['show version'], wait_for=wait_for, match='all')) + self.execute_module() + + def test_ironware_command_match_all_failure(self): + wait_for = ['result[0] contains "IronWare"', + 'result[0] contains "test string"'] + commands = ['show version', 'show version'] + set_module_args(dict(commands=commands, wait_for=wait_for, match='all')) + self.execute_module(failed=True)