1# 2# (c) 2020 Peter Sprygada, <psprygada@ansible.com> 3# (c) 2020 Red Hat, Inc 4# 5# Copyright (c) 2020 Dell Inc. 6# 7# This code is part of Ansible, but is an independent component. 8# This particular file snippet, and this file snippet only, is BSD licensed. 9# Modules you write using this snippet, which is embedded dynamically by Ansible 10# still belong to the author of the module, and may assign their own license 11# to the complete work. 12# 13# Redistribution and use in source and binary forms, with or without modification, 14# are permitted provided that the following conditions are met: 15# 16# * Redistributions of source code must retain the above copyright 17# notice, this list of conditions and the following disclaimer. 18# * Redistributions in binary form must reproduce the above copyright notice, 19# this list of conditions and the following disclaimer in the documentation 20# and/or other materials provided with the distribution. 21# 22# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 23# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 30# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31# 32 33from __future__ import (absolute_import, division, print_function) 34 35import re 36 37from ansible.module_utils._text import to_text 38from ansible.module_utils.basic import env_fallback 39from ansible.module_utils.connection import exec_command 40from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, ComplexList 41from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig, ConfigLine 42 43__metaclass__ = type 44 45_DEVICE_CONFIGS = {} 46 47WARNING_PROMPTS_RE = [ 48 r"[\r\n]?\[confirm yes/no\]:\s?$", 49 r"[\r\n]?\[y/n\]:\s?$", 50 r"[\r\n]?\[yes/no\]:\s?$" 51] 52 53os10_provider_spec = { 54 'host': dict(), 55 'port': dict(type='int'), 56 'username': dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])), 57 'password': dict(fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD']), no_log=True), 58 'ssh_keyfile': dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']), type='path'), 59 'authorize': dict(fallback=(env_fallback, ['ANSIBLE_NET_AUTHORIZE']), type='bool'), 60 'auth_pass': dict(fallback=(env_fallback, ['ANSIBLE_NET_AUTH_PASS']), no_log=True), 61 'timeout': dict(type='int'), 62} 63os10_argument_spec = { 64 'provider': dict(type='dict', options=os10_provider_spec), 65} 66 67 68def check_args(module, warnings): 69 pass 70 71 72def get_config(module, flags=None): 73 flags = [] if flags is None else flags 74 75 cmd = 'show running-configuration' 76 cmd += ' '.join(flags) 77 cmd = cmd.strip() 78 79 try: 80 return _DEVICE_CONFIGS[cmd] 81 except KeyError: 82 rc, out, err = exec_command(module, cmd) 83 if rc != 0: 84 module.fail_json(msg='unable to retrieve current config', stderr=to_text(err, errors='surrogate_or_strict')) 85 cfg = to_text(out, errors='surrogate_or_strict').strip() 86 _DEVICE_CONFIGS[cmd] = cfg 87 return cfg 88 89 90def to_commands(module, commands): 91 spec = { 92 'command': dict(key=True), 93 'prompt': dict(), 94 'answer': dict() 95 } 96 transform = ComplexList(spec, module) 97 return transform(commands) 98 99 100def run_commands(module, commands, check_rc=True): 101 responses = list() 102 commands = to_commands(module, to_list(commands)) 103 for cmd in commands: 104 cmd = module.jsonify(cmd) 105 rc, out, err = exec_command(module, cmd) 106 if check_rc and rc != 0: 107 module.fail_json(msg=to_text(err, errors='surrogate_or_strict'), rc=rc) 108 responses.append(to_text(out, errors='surrogate_or_strict')) 109 return responses 110 111 112def load_config(module, commands): 113 rc, out, err = exec_command(module, 'configure terminal') 114 if rc != 0: 115 module.fail_json(msg='unable to enter configuration mode', err=to_text(err, errors='surrogate_or_strict')) 116 117 commands.append('commit') 118 for command in to_list(commands): 119 if command == 'end': 120 continue 121 rc, out, err = exec_command(module, command) 122 if rc != 0: 123 module.fail_json(msg=to_text(err, errors='surrogate_or_strict'), command=command, rc=rc) 124 125 exec_command(module, 'end') 126 127 128def get_sublevel_config(running_config, module): 129 contents = list() 130 current_config_contents = list() 131 running_config = NetworkConfig(contents=running_config, indent=1) 132 obj = running_config.get_object(module.params['parents']) 133 if obj: 134 contents = obj.children 135 contents[:0] = module.params['parents'] 136 137 indent = 0 138 for c in contents: 139 if isinstance(c, str): 140 current_config_contents.append(c.rjust(len(c) + indent, ' ')) 141 if isinstance(c, ConfigLine): 142 current_config_contents.append(c.raw) 143 indent = 1 144 sublevel_config = '\n'.join(current_config_contents) 145 146 return sublevel_config 147