Bug fixes- Dellos modules (#63272)

This commit is contained in:
Dhivyap 2019-10-22 14:06:34 +05:30 committed by Ganesh Nalawade
parent 4745d45711
commit 2e65c1ebb7
10 changed files with 295 additions and 165 deletions

View file

@ -29,12 +29,12 @@
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # 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. # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# #
import re import json
from ansible.module_utils._text import to_text from ansible.module_utils._text import to_text
from ansible.module_utils.basic import env_fallback from ansible.module_utils.basic import env_fallback
from ansible.module_utils.network.common.utils import to_list, ComplexList from ansible.module_utils.network.common.utils import to_list, ComplexList
from ansible.module_utils.connection import exec_command from ansible.module_utils.connection import Connection, ConnectionError, exec_command
from ansible.module_utils.network.common.config import NetworkConfig, ConfigLine from ansible.module_utils.network.common.config import NetworkConfig, ConfigLine
_DEVICE_CONFIGS = {} _DEVICE_CONFIGS = {}
@ -71,6 +71,35 @@ dellos10_top_spec = {
dellos10_argument_spec.update(dellos10_top_spec) dellos10_argument_spec.update(dellos10_top_spec)
def get_provider_argspec():
return dellos10_provider_spec
def get_connection(module):
if hasattr(module, '_dellos10_connection'):
return module._dellos10_connection
capabilities = get_capabilities(module)
network_api = capabilities.get('network_api')
if network_api == 'cliconf':
module._dellos10_connection = Connection(module._socket_path)
else:
module.fail_json(msg='Invalid connection type %s' % network_api)
return module._dellos10_connection
def get_capabilities(module):
if hasattr(module, '_dellos10_capabilities'):
return module._dellos10_capabilities
try:
capabilities = Connection(module._socket_path).get_capabilities()
except ConnectionError as exc:
module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
module._dellos10_capabilities = json.loads(capabilities)
return module._dellos10_capabilities
def check_args(module, warnings): def check_args(module, warnings):
pass pass
@ -78,7 +107,7 @@ def check_args(module, warnings):
def get_config(module, flags=None): def get_config(module, flags=None):
flags = [] if flags is None else flags flags = [] if flags is None else flags
cmd = 'show running-config ' cmd = 'show running-configuration '
cmd += ' '.join(flags) cmd += ' '.join(flags)
cmd = cmd.strip() cmd = cmd.strip()
@ -93,26 +122,12 @@ def get_config(module, flags=None):
return cfg return cfg
def to_commands(module, commands):
spec = {
'command': dict(key=True),
'prompt': dict(),
'answer': dict()
}
transform = ComplexList(spec, module)
return transform(commands)
def run_commands(module, commands, check_rc=True): def run_commands(module, commands, check_rc=True):
responses = list() connection = get_connection(module)
commands = to_commands(module, to_list(commands)) try:
for cmd in commands: return connection.run_commands(commands=commands, check_rc=check_rc)
cmd = module.jsonify(cmd) except ConnectionError as exc:
rc, out, err = exec_command(module, cmd) module.fail_json(msg=to_text(exc))
if check_rc and rc != 0:
module.fail_json(msg=to_text(err, errors='surrogate_or_strict'), rc=rc)
responses.append(to_text(out, errors='surrogate_or_strict'))
return responses
def load_config(module, commands): def load_config(module, commands):

View file

@ -30,11 +30,12 @@
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# #
import re import re
import json
from ansible.module_utils._text import to_text from ansible.module_utils._text import to_text
from ansible.module_utils.basic import env_fallback from ansible.module_utils.basic import env_fallback
from ansible.module_utils.network.common.utils import to_list, ComplexList from ansible.module_utils.network.common.utils import to_list, ComplexList
from ansible.module_utils.connection import exec_command from ansible.module_utils.connection import Connection, ConnectionError, exec_command
from ansible.module_utils.network.common.config import NetworkConfig, ConfigLine, ignore_line from ansible.module_utils.network.common.config import NetworkConfig, ConfigLine, ignore_line
_DEVICE_CONFIGS = {} _DEVICE_CONFIGS = {}
@ -71,6 +72,35 @@ dellos6_top_spec = {
dellos6_argument_spec.update(dellos6_top_spec) dellos6_argument_spec.update(dellos6_top_spec)
def get_provider_argspec():
return dellos6_provider_spec
def get_connection(module):
if hasattr(module, '_dellos6_connection'):
return module._dellos6_connection
capabilities = get_capabilities(module)
network_api = capabilities.get('network_api')
if network_api == 'cliconf':
module._dellos6_connection = Connection(module._socket_path)
else:
module.fail_json(msg='Invalid connection type %s' % network_api)
return module._dellos6_connection
def get_capabilities(module):
if hasattr(module, '_dellos6_capabilities'):
return module._dellos6_capabilities
try:
capabilities = Connection(module._socket_path).get_capabilities()
except ConnectionError as exc:
module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
module._dellos6_capabilities = json.loads(capabilities)
return module._dellos6_capabilities
def check_args(module, warnings): def check_args(module, warnings):
pass pass
@ -93,26 +123,12 @@ def get_config(module, flags=None):
return cfg return cfg
def to_commands(module, commands):
spec = {
'command': dict(key=True),
'prompt': dict(),
'answer': dict()
}
transform = ComplexList(spec, module)
return transform(commands)
def run_commands(module, commands, check_rc=True): def run_commands(module, commands, check_rc=True):
responses = list() connection = get_connection(module)
commands = to_commands(module, to_list(commands)) try:
for cmd in commands: return connection.run_commands(commands=commands, check_rc=check_rc)
cmd = module.jsonify(cmd) except ConnectionError as exc:
rc, out, err = exec_command(module, cmd) module.fail_json(msg=to_text(exc))
if check_rc and rc != 0:
module.fail_json(msg=to_text(err, errors='surrogate_or_strict'), rc=rc)
responses.append(to_text(out, errors='surrogate_or_strict'))
return responses
def load_config(module, commands): def load_config(module, commands):
@ -152,16 +168,16 @@ def os6_parse(lines, indent=None, comment_tokens=None):
re.compile(r'datacenter-bridging.*$'), re.compile(r'datacenter-bridging.*$'),
re.compile(r'line (console|telnet|ssh).*$'), re.compile(r'line (console|telnet|ssh).*$'),
re.compile(r'ip ssh !(server).*$'), re.compile(r'ip ssh !(server).*$'),
re.compile(r'(ip|mac|management|arp) access-list.*$'),
re.compile(r'ip dhcp pool.*$'), re.compile(r'ip dhcp pool.*$'),
re.compile(r'ip vrf !(forwarding).*$'), re.compile(r'ip vrf !(forwarding).*$'),
re.compile(r'(ip|mac|management|arp) access-list.*$'),
re.compile(r'ipv6 (dhcp pool|router).*$'), re.compile(r'ipv6 (dhcp pool|router).*$'),
re.compile(r'mail-server.*$'), re.compile(r'mail-server.*$'),
re.compile(r'vpc domain.*$'), re.compile(r'vpc domain.*$'),
re.compile(r'router.*$'), re.compile(r'router.*$'),
re.compile(r'route-map.*$'), re.compile(r'route-map.*$'),
re.compile(r'policy-map.*$'), re.compile(r'policy-map.*$'),
re.compile(r'class-map match-all.*$'), re.compile(r'((class-map match-(all|any))|(class\s)).*$'),
re.compile(r'captive-portal.*$'), re.compile(r'captive-portal.*$'),
re.compile(r'admin-profile.*$'), re.compile(r'admin-profile.*$'),
re.compile(r'link-dependency group.*$'), re.compile(r'link-dependency group.*$'),
@ -172,7 +188,9 @@ def os6_parse(lines, indent=None, comment_tokens=None):
re.compile(r'address-family.*$'), re.compile(r'address-family.*$'),
re.compile(r'spanning-tree mst configuration.*$'), re.compile(r'spanning-tree mst configuration.*$'),
re.compile(r'logging (?!.*(cli-command|buffered|console|email|facility|file|monitor|protocol|snmp|source-interface|traps|web-session)).*$'), re.compile(r'logging (?!.*(cli-command|buffered|console|email|facility|file|monitor|protocol|snmp|source-interface|traps|web-session)).*$'),
re.compile(r'(radius-server|tacacs-server) host.*$')] re.compile(r'(radius-server|tacacs-server) host.*$'),
re.compile(r'radius server (auth|acct).*$'),
re.compile(r'aaa server radius dynamic-author.*$')]
childline = re.compile(r'^exit$') childline = re.compile(r'^exit$')
config = list() config = list()
@ -184,8 +202,6 @@ def os6_parse(lines, indent=None, comment_tokens=None):
cfg = ConfigLine(text) cfg = ConfigLine(text)
cfg.raw = line cfg.raw = line
if not text or ignore_line(text, comment_tokens): if not text or ignore_line(text, comment_tokens):
parent = list()
children = []
continue continue
else: else:

View file

@ -29,12 +29,12 @@
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # 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. # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# #
import re import json
from ansible.module_utils._text import to_text from ansible.module_utils._text import to_text
from ansible.module_utils.basic import env_fallback from ansible.module_utils.basic import env_fallback
from ansible.module_utils.network.common.utils import to_list, ComplexList from ansible.module_utils.network.common.utils import to_list, ComplexList
from ansible.module_utils.connection import exec_command from ansible.module_utils.connection import Connection, ConnectionError, exec_command
from ansible.module_utils.network.common.config import NetworkConfig, ConfigLine from ansible.module_utils.network.common.config import NetworkConfig, ConfigLine
_DEVICE_CONFIGS = {} _DEVICE_CONFIGS = {}
@ -71,6 +71,35 @@ dellos9_top_spec = {
dellos9_argument_spec.update(dellos9_top_spec) dellos9_argument_spec.update(dellos9_top_spec)
def get_provider_argspec():
return dellos9_provider_spec
def get_connection(module):
if hasattr(module, '_dellos9_connection'):
return module._dellos9_connection
capabilities = get_capabilities(module)
network_api = capabilities.get('network_api')
if network_api == 'cliconf':
module._dellos9_connection = Connection(module._socket_path)
else:
module.fail_json(msg='Invalid connection type %s' % network_api)
return module._dellos9_connection
def get_capabilities(module):
if hasattr(module, '_dellos9_capabilities'):
return module._dellos9_capabilities
try:
capabilities = Connection(module._socket_path).get_capabilities()
except ConnectionError as exc:
module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
module._dellos9_capabilities = json.loads(capabilities)
return module._dellos9_capabilities
def check_args(module, warnings): def check_args(module, warnings):
pass pass
@ -93,26 +122,12 @@ def get_config(module, flags=None):
return cfg return cfg
def to_commands(module, commands):
spec = {
'command': dict(key=True),
'prompt': dict(),
'answer': dict()
}
transform = ComplexList(spec, module)
return transform(commands)
def run_commands(module, commands, check_rc=True): def run_commands(module, commands, check_rc=True):
responses = list() connection = get_connection(module)
commands = to_commands(module, to_list(commands)) try:
for cmd in commands: return connection.run_commands(commands=commands, check_rc=check_rc)
cmd = module.jsonify(cmd) except ConnectionError as exc:
rc, out, err = exec_command(module, cmd) module.fail_json(msg=to_text(exc))
if check_rc and rc != 0:
module.fail_json(msg=to_text(err, errors='surrogate_or_strict'), rc=rc)
responses.append(to_text(out, errors='surrogate_or_strict'))
return responses
def load_config(module, commands): def load_config(module, commands):

View file

@ -35,7 +35,11 @@ options:
configured provider. The resulting output from the command configured provider. The resulting output from the command
is returned. If the I(wait_for) argument is provided, the is returned. If the I(wait_for) argument is provided, the
module is not returned until the condition is satisfied or module is not returned until the condition is satisfied or
the number of retries has expired. the number of retries has expired. If a command sent to the
device requires answering a prompt, it is possible to pass
a dict containing I(command), I(answer) and I(prompt).
Common answers are 'yes' or "\\r" (carriage return, must be
double quotes). See examples.
type: list type: list
required: true required: true
wait_for: wait_for:
@ -43,7 +47,7 @@ options:
- List of conditions to evaluate against the output of the - List of conditions to evaluate against the output of the
command. The task will wait for each condition to be true command. The task will wait for each condition to be true
before moving forward. If the conditional is not true before moving forward. If the conditional is not true
within the configured number of I(retries), the task fails. within the configured number of retries, the task fails.
See examples. See examples.
type: list type: list
version_added: "2.2" version_added: "2.2"
@ -57,7 +61,7 @@ options:
satisfied. satisfied.
type: str type: str
default: all default: all
choices: [ all, any ] choices: [ 'all', 'any' ]
version_added: "2.5" version_added: "2.5"
retries: retries:
description: description:
@ -102,6 +106,13 @@ tasks:
wait_for: wait_for:
- result[0] contains OS10 - result[0] contains OS10
- result[1] contains Ethernet - result[1] contains Ethernet
- name: run commands that require answering a prompt
dellos10_command:
commands:
- command: 'reload'
prompt: '[confirm yes/no]: ?$'
answer: 'no'
""" """
RETURN = """ RETURN = """
@ -128,39 +139,26 @@ warnings:
""" """
import time import time
from ansible.module_utils._text import to_text
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.common.parsing import Conditional
from ansible.module_utils.network.common.utils import transform_commands, to_lines
from ansible.module_utils.network.dellos10.dellos10 import run_commands from ansible.module_utils.network.dellos10.dellos10 import run_commands
from ansible.module_utils.network.dellos10.dellos10 import dellos10_argument_spec, check_args from ansible.module_utils.network.dellos10.dellos10 import dellos10_argument_spec, check_args
from ansible.module_utils.network.common.utils import ComplexList
from ansible.module_utils.network.common.parsing 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 parse_commands(module, warnings): def parse_commands(module, warnings):
command = ComplexList(dict( commands = transform_commands(module)
command=dict(key=True),
prompt=dict(), if module.check_mode:
answer=dict() for item in list(commands):
), module) if not item['command'].startswith('show'):
commands = command(module.params['commands']) warnings.append(
for index, item in enumerate(commands): 'Only show commands are supported when using check mode, not '
if module.check_mode and not item['command'].startswith('show'): 'executing %s' % item['command']
warnings.append( )
'only show commands are supported when using check mode, not ' commands.remove(item)
'executing `%s`' % item['command']
)
elif item['command'].startswith('conf'):
module.fail_json(
msg='dellos10_command does not support running config mode '
'commands. Please use dellos10_config instead'
)
return commands return commands
@ -191,8 +189,11 @@ def main():
result['warnings'] = warnings result['warnings'] = warnings
wait_for = module.params['wait_for'] or list() wait_for = module.params['wait_for'] or list()
conditionals = [Conditional(c) for c in wait_for]
try:
conditionals = [Conditional(c) for c in wait_for]
except AttributeError as exc:
module.fail_json(msg=to_text(exc))
retries = module.params['retries'] retries = module.params['retries']
interval = module.params['interval'] interval = module.params['interval']
match = module.params['match'] match = module.params['match']
@ -219,7 +220,6 @@ def main():
module.fail_json(msg=msg, failed_conditions=failed_conditions) module.fail_json(msg=msg, failed_conditions=failed_conditions)
result.update({ result.update({
'changed': False,
'stdout': responses, 'stdout': responses,
'stdout_lines': list(to_lines(responses)) 'stdout_lines': list(to_lines(responses))
}) })

View file

@ -34,7 +34,11 @@ options:
configured provider. The resulting output from the command configured provider. The resulting output from the command
is returned. If the I(wait_for) argument is provided, the is returned. If the I(wait_for) argument is provided, the
module is not returned until the condition is satisfied or module is not returned until the condition is satisfied or
the number of retries has expired. the number of retries has expired. If a command sent to the
device requires answering a prompt, it is possible to pass
a dict containing I(command), I(answer) and I(prompt).
Common answers are 'yes' or "\\r" (carriage return, must be
double quotes). See examples.
type: list type: list
required: true required: true
wait_for: wait_for:
@ -42,7 +46,7 @@ options:
- List of conditions to evaluate against the output of the - List of conditions to evaluate against the output of the
command. The task will wait for each condition to be true command. The task will wait for each condition to be true
before moving forward. If the conditional is not true before moving forward. If the conditional is not true
within the configured number of I(retries), the task fails. within the configured number of retries, the task fails.
See examples. See examples.
type: list type: list
version_added: "2.2" version_added: "2.2"
@ -56,7 +60,7 @@ options:
satisfied. satisfied.
type: str type: str
default: all default: all
choices: [ all, any ] choices: [ 'all', 'any' ]
version_added: "2.5" version_added: "2.5"
retries: retries:
description: description:
@ -101,6 +105,13 @@ tasks:
wait_for: wait_for:
- result[0] contains Dell - result[0] contains Dell
- result[1] contains Access - result[1] contains Access
- name: run commands that require answering a prompt
dellos6_command:
commands:
- command: 'copy running-config startup-config'
prompt: '[confirm yes/no]: ?$'
answer: 'yes'
""" """
RETURN = """ RETURN = """
@ -128,39 +139,26 @@ warnings:
import time import time
from ansible.module_utils._text import to_text
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.common.parsing import Conditional
from ansible.module_utils.network.common.utils import transform_commands, to_lines
from ansible.module_utils.network.dellos6.dellos6 import run_commands from ansible.module_utils.network.dellos6.dellos6 import run_commands
from ansible.module_utils.network.dellos6.dellos6 import dellos6_argument_spec, check_args from ansible.module_utils.network.dellos6.dellos6 import dellos6_argument_spec, check_args
from ansible.module_utils.network.common.utils import ComplexList
from ansible.module_utils.network.common.parsing 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 parse_commands(module, warnings): def parse_commands(module, warnings):
command = ComplexList(dict( commands = transform_commands(module)
command=dict(key=True),
prompt=dict(), if module.check_mode:
answer=dict() for item in list(commands):
), module) if not item['command'].startswith('show'):
commands = command(module.params['commands']) warnings.append(
for index, item in enumerate(commands): 'Only show commands are supported when using check mode, not '
if module.check_mode and not item['command'].startswith('show'): 'executing %s' % item['command']
warnings.append( )
'only show commands are supported when using check mode, not ' commands.remove(item)
'executing `%s`' % item['command']
)
elif item['command'].startswith('conf'):
module.fail_json(
msg='dellos6_command does not support running config mode '
'commands. Please use dellos6_config instead'
)
return commands return commands
@ -190,8 +188,11 @@ def main():
result['warnings'] = warnings result['warnings'] = warnings
wait_for = module.params['wait_for'] or list() wait_for = module.params['wait_for'] or list()
conditionals = [Conditional(c) for c in wait_for]
try:
conditionals = [Conditional(c) for c in wait_for]
except AttributeError as exc:
module.fail_json(msg=to_text(exc))
retries = module.params['retries'] retries = module.params['retries']
interval = module.params['interval'] interval = module.params['interval']
match = module.params['match'] match = module.params['match']
@ -218,7 +219,6 @@ def main():
module.fail_json(msg=msg, failed_conditions=failed_conditions) module.fail_json(msg=msg, failed_conditions=failed_conditions)
result.update({ result.update({
'changed': False,
'stdout': responses, 'stdout': responses,
'stdout_lines': list(to_lines(responses)) 'stdout_lines': list(to_lines(responses))
}) })

View file

@ -35,7 +35,11 @@ options:
configured provider. The resulting output from the command configured provider. The resulting output from the command
is returned. If the I(wait_for) argument is provided, the is returned. If the I(wait_for) argument is provided, the
module is not returned until the condition is satisfied or module is not returned until the condition is satisfied or
the number of retries has expired. the number of retries has expired. If a command sent to the
device requires answering a prompt, it is possible to pass
a dict containing I(command), I(answer) and I(prompt).
Common answers are 'yes' or "\\r" (carriage return, must be
double quotes). See examples.
type: list type: list
required: true required: true
wait_for: wait_for:
@ -43,7 +47,7 @@ options:
- List of conditions to evaluate against the output of the - List of conditions to evaluate against the output of the
command. The task will wait for each condition to be true command. The task will wait for each condition to be true
before moving forward. If the conditional is not true before moving forward. If the conditional is not true
within the configured number of I(retries), the task fails. within the configured number of retries, the task fails.
See examples. See examples.
type: list type: list
version_added: "2.2" version_added: "2.2"
@ -57,7 +61,7 @@ options:
satisfied. satisfied.
type: str type: str
default: all default: all
choices: [ all, any ] choices: [ 'all', 'any' ]
version_added: "2.5" version_added: "2.5"
retries: retries:
description: description:
@ -111,6 +115,13 @@ tasks:
wait_for: wait_for:
- result[0] contains OS9 - result[0] contains OS9
- result[1] contains Loopback - result[1] contains Loopback
- name: run commands that require answering a prompt
dellos9_command:
commands:
- command: 'copy running-config startup-config'
prompt: '[confirm yes/no]: ?$'
answer: 'yes'
""" """
RETURN = """ RETURN = """
@ -137,39 +148,26 @@ warnings:
""" """
import time import time
from ansible.module_utils._text import to_text
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.common.parsing import Conditional
from ansible.module_utils.network.common.utils import transform_commands, to_lines
from ansible.module_utils.network.dellos9.dellos9 import run_commands from ansible.module_utils.network.dellos9.dellos9 import run_commands
from ansible.module_utils.network.dellos9.dellos9 import dellos9_argument_spec, check_args from ansible.module_utils.network.dellos9.dellos9 import dellos9_argument_spec, check_args
from ansible.module_utils.network.common.utils import ComplexList
from ansible.module_utils.network.common.parsing 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 parse_commands(module, warnings): def parse_commands(module, warnings):
command = ComplexList(dict( commands = transform_commands(module)
command=dict(key=True),
prompt=dict(), if module.check_mode:
answer=dict() for item in list(commands):
), module) if not item['command'].startswith('show'):
commands = command(module.params['commands']) warnings.append(
for index, item in enumerate(commands): 'Only show commands are supported when using check mode, not '
if module.check_mode and not item['command'].startswith('show'): 'executing %s' % item['command']
warnings.append( )
'only show commands are supported when using check mode, not ' commands.remove(item)
'executing `%s`' % item['command']
)
elif item['command'].startswith('conf'):
module.fail_json(
msg='dellos9_command does not support running config mode '
'commands. Please use dellos9_config instead'
)
return commands return commands
@ -200,8 +198,11 @@ def main():
result['warnings'] = warnings result['warnings'] = warnings
wait_for = module.params['wait_for'] or list() wait_for = module.params['wait_for'] or list()
conditionals = [Conditional(c) for c in wait_for]
try:
conditionals = [Conditional(c) for c in wait_for]
except AttributeError as exc:
module.fail_json(msg=to_text(exc))
retries = module.params['retries'] retries = module.params['retries']
interval = module.params['interval'] interval = module.params['interval']
match = module.params['match'] match = module.params['match']
@ -228,7 +229,6 @@ def main():
module.fail_json(msg=msg, failed_conditions=failed_conditions) module.fail_json(msg=msg, failed_conditions=failed_conditions)
result.update({ result.update({
'changed': False,
'stdout': responses, 'stdout': responses,
'stdout_lines': list(to_lines(responses)) 'stdout_lines': list(to_lines(responses))
}) })

View file

@ -36,7 +36,9 @@ import json
from itertools import chain from itertools import chain
from ansible.errors import AnsibleConnectionFailure
from ansible.module_utils._text import to_bytes, to_text from ansible.module_utils._text import to_bytes, to_text
from ansible.module_utils.common._collections_compat import Mapping
from ansible.module_utils.network.common.utils import to_list from ansible.module_utils.network.common.utils import to_list
from ansible.plugins.cliconf import CliconfBase, enable_mode from ansible.plugins.cliconf import CliconfBase, enable_mode
@ -87,3 +89,27 @@ class Cliconf(CliconfBase):
def get_capabilities(self): def get_capabilities(self):
result = super(Cliconf, self).get_capabilities() result = super(Cliconf, self).get_capabilities()
return json.dumps(result) return json.dumps(result)
def run_commands(self, commands=None, check_rc=True):
if commands is None:
raise ValueError("'commands' value is required")
responses = list()
for cmd in to_list(commands):
if not isinstance(cmd, Mapping):
cmd = {'command': cmd}
output = cmd.pop('output', None)
if output:
raise ValueError("'output' value %s is not supported for run_commands" % output)
try:
out = self.send_command(**cmd)
except AnsibleConnectionFailure as e:
if check_rc:
raise
out = getattr(e, 'err', to_text(e))
responses.append(out)
return responses

View file

@ -36,7 +36,9 @@ import json
from itertools import chain from itertools import chain
from ansible.errors import AnsibleConnectionFailure
from ansible.module_utils._text import to_bytes, to_text from ansible.module_utils._text import to_bytes, to_text
from ansible.module_utils.common._collections_compat import Mapping
from ansible.module_utils.network.common.utils import to_list from ansible.module_utils.network.common.utils import to_list
from ansible.plugins.cliconf import CliconfBase, enable_mode from ansible.plugins.cliconf import CliconfBase, enable_mode
@ -58,7 +60,7 @@ class Cliconf(CliconfBase):
if match: if match:
device_info['network_os_model'] = match.group(1) device_info['network_os_model'] = match.group(1)
reply = self.get('show running-config | grep hostname') reply = self.get('show running-config | include hostname')
data = to_text(reply, errors='surrogate_or_strict').strip() data = to_text(reply, errors='surrogate_or_strict').strip()
match = re.search(r'^hostname (.+)', data, re.M) match = re.search(r'^hostname (.+)', data, re.M)
if match: if match:
@ -87,3 +89,27 @@ class Cliconf(CliconfBase):
def get_capabilities(self): def get_capabilities(self):
result = super(Cliconf, self).get_capabilities() result = super(Cliconf, self).get_capabilities()
return json.dumps(result) return json.dumps(result)
def run_commands(self, commands=None, check_rc=True):
if commands is None:
raise ValueError("'commands' value is required")
responses = list()
for cmd in to_list(commands):
if not isinstance(cmd, Mapping):
cmd = {'command': cmd}
output = cmd.pop('output', None)
if output:
raise ValueError("'output' value %s is not supported for run_commands" % output)
try:
out = self.send_command(**cmd)
except AnsibleConnectionFailure as e:
if check_rc:
raise
out = getattr(e, 'err', to_text(e))
responses.append(out)
return responses

View file

@ -36,7 +36,9 @@ import json
from itertools import chain from itertools import chain
from ansible.errors import AnsibleConnectionFailure
from ansible.module_utils._text import to_bytes, to_text from ansible.module_utils._text import to_bytes, to_text
from ansible.module_utils.common._collections_compat import Mapping
from ansible.module_utils.network.common.utils import to_list from ansible.module_utils.network.common.utils import to_list
from ansible.plugins.cliconf import CliconfBase, enable_mode from ansible.plugins.cliconf import CliconfBase, enable_mode
@ -87,3 +89,27 @@ class Cliconf(CliconfBase):
def get_capabilities(self): def get_capabilities(self):
result = super(Cliconf, self).get_capabilities() result = super(Cliconf, self).get_capabilities()
return json.dumps(result) return json.dumps(result)
def run_commands(self, commands=None, check_rc=True):
if commands is None:
raise ValueError("'commands' value is required")
responses = list()
for cmd in to_list(commands):
if not isinstance(cmd, Mapping):
cmd = {'command': cmd}
output = cmd.pop('output', None)
if output:
raise ValueError("'output' value %s is not supported for run_commands" % output)
try:
out = self.send_command(**cmd)
except AnsibleConnectionFailure as e:
if check_rc:
raise
out = getattr(e, 'err', to_text(e))
responses.append(out)
return responses

View file

@ -55,6 +55,12 @@ class TerminalModule(TerminalBase):
terminal_inital_prompt_newline = False terminal_inital_prompt_newline = False
def on_open_shell(self):
try:
self._exec_cli_command(b'terminal length 0')
except AnsibleConnectionFailure:
raise AnsibleConnectionFailure('unable to set terminal parameters')
def on_become(self, passwd=None): def on_become(self, passwd=None):
if self._get_prompt().endswith(b'#'): if self._get_prompt().endswith(b'#'):
return return