Pluribus Networks network cli terminal and cliconf plugins (#53735)

* Pluribus Networks network cli terminal and cliconf plugins

* Changes in Unit tests and modules according to network_cli connection

* Changes in Unit tests and modules according to network_cli connection
This commit is contained in:
rajaspachipulusu17 2019-03-15 13:51:50 +05:30 committed by Ganesh Nalawade
parent 4594aee25a
commit e2d92e82c4
53 changed files with 345 additions and 155 deletions

View file

@ -0,0 +1,59 @@
# Copyright: (c) 2018, Pluribus Networks
# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
#
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import json
from ansible.module_utils._text import to_text
from ansible.module_utils.network.common.utils import to_list, ComplexList
from ansible.module_utils.connection import Connection, ConnectionError
from ansible.module_utils.connection import exec_command
def get_connection(module):
if hasattr(module, '_nvos_connection'):
return module._nvos_connection
capabilities = get_capabilities(module)
network_api = capabilities.get('network_api')
if network_api == 'cliconf':
module._nvos_connection = Connection(module._socket_path)
else:
module.fail_json(msg='Invalid connection type %s' % network_api)
return module._nvos_connection
def get_capabilities(module):
if hasattr(module, '_nvos_capabilities'):
return module._nvos_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._nvos_capabilities = json.loads(capabilities)
return module._nvos_capabilities
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):
commands = to_commands(module, to_list(commands))
for cmd in commands:
cmd = module.jsonify(cmd)
rc, out, err = exec_command(module, cmd)
if check_rc and rc != 0:
module.fail_json(msg=to_text(err, errors='surrogate_or_strict'), rc=rc)
responses = (to_text(out, errors='surrogate_or_strict'))
return rc, out, err

View file

@ -6,7 +6,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
import shlex
from ansible.module_utils.network.netvisor.netvisor import run_commands
def pn_cli(module, switch=None, username=None, password=None, switch_local=None):
@ -16,7 +16,7 @@ def pn_cli(module, switch=None, username=None, password=None, switch_local=None)
:return: The cli string for further processing.
"""
cli = '/usr/bin/cli --quiet -e --no-login-prompt '
cli = ''
if username and password:
cli += '--user "%s":"%s" ' % (username, password)
@ -48,25 +48,19 @@ def run_cli(module, cli, state_map):
state = module.params['state']
command = state_map[state]
cmd = shlex.split(cli)
result, out, err = module.run_command(cmd)
remove_cmd = '/usr/bin/cli --quiet -e --no-login-prompt'
result, out, err = run_commands(module, cli)
results = dict(
command=' '.join(cmd).replace(remove_cmd, ''),
msg="%s operation completed" % command,
command=cli,
msg="%s operation completed" % cli,
changed=True
)
# Response in JSON format
if result != 0:
module.exit_json(
command=' '.join(cmd).replace(remove_cmd, ''),
stderr=err.strip(),
msg="%s operation failed" % command,
command=cli,
msg="%s operation failed" % cli,
changed=False
)
if out:
results['stdout'] = out.strip()
module.exit_json(**results)

View file

@ -85,38 +85,29 @@ changed:
type: bool
"""
import shlex
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.netvisor.pn_nvos import pn_cli, run_cli
from ansible.module_utils.network.netvisor.netvisor import run_commands
def check_cli(module, cli):
"""
This method checks for idempotency using the access-list-show command.
If a list with given name exists, return ACC_LIST_EXISTS
as True else False.
If a list with given name exists, return True else False.
:param module: The Ansible module to fetch input parameters
:param cli: The CLI string
:return Global Booleans: ACC_LIST_EXISTS
"""
list_name = module.params['pn_name']
show = cli + \
' access-list-show format name no-show-headers'
show = shlex.split(show)
out = module.run_command(show)[1]
cli += ' access-list-show format name no-show-headers'
out = run_commands(module, cli)
out = out.split()
# Global flags
global ACC_LIST_EXISTS
ACC_LIST_EXISTS = True if list_name in out else False
return True if list_name in out else False
def main():
""" This section is for arguments parsing """
global state_map
state_map = dict(
present='access-list-create',
absent='access-list-delete',
@ -148,7 +139,7 @@ def main():
# Building the CLI command string
cli = pn_cli(module, cliswitch)
check_cli(module, cli)
ACC_LIST_EXISTS = check_cli(module, cli)
cli += ' %s name %s ' % (command, list_name)
if command == 'access-list-delete':

View file

@ -81,6 +81,7 @@ changed:
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.netvisor.pn_nvos import pn_cli, run_cli
from ansible.module_utils.network.netvisor.netvisor import run_commands
def check_cli(module, cli):
@ -92,19 +93,28 @@ def check_cli(module, cli):
"""
name = module.params['pn_name']
ip = module.params['pn_ip']
clicopy = cli
cli += ' access-list-show name %s no-show-headers ' % name
out = run_commands(module, cli)[1]
if name not in out:
module.fail_json(
failed=True,
msg='access-list with name %s does not exist' % name
)
cli = clicopy
cli += ' access-list-ip-show name %s format ip no-show-headers' % name
out = module.run_command(cli.split(), use_unsafe_shell=True)[1]
out = run_commands(module, cli)[1]
out = out.split()
return True if ip in out else False
def main():
""" This section is for arguments parsing """
global state_map
state_map = dict(
present='access-list-ip-add',
absent='access-list-ip-remove',

View file

@ -135,7 +135,6 @@ from ansible.module_utils.network.netvisor.pn_nvos import pn_cli, booleanArgs, r
def main():
""" This section is for arguments parsing """
global state_map
state_map = dict(
update='admin-service-modify'
)

View file

@ -73,7 +73,7 @@ options:
EXAMPLES = """
- name: admin-syslog functionality
pn_admin_syslog:
pn_cliswitch: sw01
pn_cliswitch: "sw01"
state: "absent"
pn_name: "foo"
pn_scope: "local"
@ -116,6 +116,7 @@ changed:
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.netvisor.pn_nvos import pn_cli, run_cli
from ansible.module_utils.network.netvisor.netvisor import run_commands
def check_cli(module, cli):
@ -129,7 +130,7 @@ def check_cli(module, cli):
name = module.params['pn_name']
cli += ' admin-syslog-show format name no-show-headers'
out = module.run_command(cli.split(), use_unsafe_shell=True)[1]
out = run_commands(module, cli)[1]
out = out.split()

View file

@ -140,8 +140,7 @@ stdout:
returned: always
type: list
stderr:
description: set of error responses from the connection-stats-settings
command.
description: set of error responses from the connection-stats-settings command.
returned: on error
type: list
changed:

View file

@ -100,6 +100,7 @@ changed:
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.netvisor.pn_nvos import pn_cli, run_cli
from ansible.module_utils.network.netvisor.netvisor import run_commands
def check_cli(module, cli):
@ -110,9 +111,21 @@ def check_cli(module, cli):
:param cli: The CLI string
"""
name = module.params['pn_name']
clicopy = cli
cli += ' cpu-class-show format name no-show-headers'
out = module.run_command(cli.split(), use_unsafe_shell=True)[1]
cli += ' system-settings-show format cpu-class-enable no-show-headers'
out = run_commands(module, cli)[1]
out = out.split()
if 'on' not in out:
module.fail_json(
failed=True,
msg='Enable CPU class before creating or deleting'
)
cli = clicopy
cli += ' cpu-class-show name %s format name no-show-headers' % name
out = run_commands(module, cli)[1]
out = out.split()
return True if name in out else False
@ -121,7 +134,6 @@ def check_cli(module, cli):
def main():
""" This section is for arguments parsing """
global state_map
state_map = dict(
present='cpu-class-create',
absent='cpu-class-delete',

View file

@ -88,6 +88,7 @@ changed:
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.netvisor.pn_nvos import pn_cli, run_cli
from ansible.module_utils.network.netvisor.netvisor import run_commands
def check_cli(module, cli):
@ -100,7 +101,7 @@ def check_cli(module, cli):
user_name = module.params['pn_name']
cli += ' dhcp-filter-show format name no-show-headers'
out = module.run_command(cli.split(), use_unsafe_shell=True)[1]
out = run_commands(module, cli)[1]
out = out.split()

View file

@ -80,6 +80,7 @@ changed:
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.netvisor.pn_nvos import pn_cli, run_cli
from ansible.module_utils.network.netvisor.netvisor import run_commands
def check_cli(module, cli):
@ -92,17 +93,16 @@ def check_cli(module, cli):
name = module.params['pn_name']
cli += ' dscp-map-show name %s format name no-show-headers' % name
out = module.run_command(cli.split(), use_unsafe_shell=True)[1]
out = run_commands(module, cli)[1]
out = out.split()
return True if name in out else False
return True if name in out[-1] else False
def main():
""" This section is for arguments parsing """
global state_map
state_map = dict(
present='dscp-map-create',
absent='dscp-map-delete'

View file

@ -52,7 +52,7 @@ options:
EXAMPLES = """
- name: dscp map pri map modify
pn_dscp_map_pri_map:
pn_cliswitch: "sw01"
pn_cliswitch: 'sw01'
state: 'update'
pn_name: 'foo'
pn_pri: '0'
@ -60,7 +60,7 @@ EXAMPLES = """
- name: dscp map pri map modify
pn_dscp_map_pri_map:
pn_cliswitch: "sw01"
pn_cliswitch: 'sw01'
state: 'update'
pn_name: 'foo'
pn_pri: '1'
@ -88,6 +88,7 @@ changed:
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.netvisor.pn_nvos import pn_cli, run_cli
from ansible.module_utils.network.netvisor.netvisor import run_commands
def check_cli(module, cli):
@ -100,11 +101,11 @@ def check_cli(module, cli):
name = module.params['pn_name']
cli += ' dscp-map-show name %s format name no-show-headers' % name
out = module.run_command(cli.split(), use_unsafe_shell=True)[1]
out = run_commands(module, cli)[1]
out = out.split()
return True if name in out else False
return True if name in out[-1] else False
def main():

View file

@ -208,6 +208,7 @@ changed:
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.netvisor.pn_nvos import pn_cli, run_cli, booleanArgs
from ansible.module_utils.network.netvisor.netvisor import run_commands
def check_cli(module, cli):
@ -220,11 +221,11 @@ def check_cli(module, cli):
name = module.params['pn_dscp_map']
cli += ' dscp-map-show name %s format name no-show-headers' % name
out = module.run_command(cli.split(), use_unsafe_shell=True)[1]
out = run_commands(module, cli)[1]
out = out.split()
return True if name in out else False
return True if name in out[-1] else False
def main():

View file

@ -74,6 +74,7 @@ EXAMPLES = """
state: "update"
pn_port: "all"
pn_cos: "0"
pn_weight: "priority"
"""
RETURN = """

View file

@ -88,6 +88,7 @@ changed:
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.netvisor.pn_nvos import pn_cli, run_cli
from ansible.module_utils.network.netvisor.netvisor import run_commands
def check_cli(module, cli):
@ -101,10 +102,10 @@ def check_cli(module, cli):
network = module.params['pn_network']
show = cli
cli += ' prefix-list-show name %s format name no-show-headers' % name
rc, out, err = module.run_command(cli, use_unsafe_shell=True)
cli += ' prefix-list-show format name no-show-headers'
out = run_commands(module, cli)[1]
if not out:
if name not in out.split()[-1]:
module.fail_json(
failed=True,
msg='Prefix list with name %s does not exists' % name
@ -112,7 +113,7 @@ def check_cli(module, cli):
cli = show
cli += ' prefix-list-network-show name %s format network no-show-headers' % name
out = module.run_command(cli, use_unsafe_shell=True)[1]
rc, out, err = run_commands(module, cli)
if out:
out = out.split()[1]

View file

@ -118,6 +118,7 @@ changed:
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.netvisor.pn_nvos import pn_cli, run_cli, booleanArgs
from ansible.module_utils.network.netvisor.netvisor import run_commands
def check_cli(module, cli):
@ -130,7 +131,7 @@ def check_cli(module, cli):
role_name = module.params['pn_name']
cli += ' role-show format name no-show-headers'
out = module.run_command(cli.split(), use_unsafe_shell=True)[1]
out = run_commands(module, cli)[1]
out = out.split()

View file

@ -87,6 +87,7 @@ changed:
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.netvisor.pn_nvos import pn_cli, run_cli
from ansible.module_utils.network.netvisor.netvisor import run_commands
def check_cli(module, cli):
@ -99,7 +100,7 @@ def check_cli(module, cli):
comm_str = module.params['pn_community_string']
cli += ' snmp-community-show format community-string no-show-headers'
out = module.run_command(cli.split(), use_unsafe_shell=True)[1]
out = run_commands(module, cli)[1]
out = out.split()

View file

@ -93,6 +93,7 @@ changed:
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.netvisor.pn_nvos import pn_cli, run_cli
from ansible.module_utils.network.netvisor.netvisor import run_commands
def check_cli(module, cli):
@ -107,14 +108,14 @@ def check_cli(module, cli):
show = cli
cli += ' snmp-community-show format community-string no-show-headers'
rc, out, err = module.run_command(cli, use_unsafe_shell=True)
rc, out, err = run_commands(module, cli)
out = out.split()
if community in out:
cli = show
cli += ' snmp-trap-sink-show community %s format type,dest-host no-show-headers' % community
rc, out, err = module.run_command(cli, use_unsafe_shell=True)
rc, out, err = run_commands(module, cli)
out = out.split()

View file

@ -57,20 +57,23 @@ options:
"""
EXAMPLES = """
- name: snmp vacm functionality
- name: create snmp vacm
pn_snmp_vacm:
pn_cliswitch: "sw01"
state: "present"
pn_user_name: "foo"
pn_user_type: "rouser"
- name: snmp vacm functionality
- name: update snmp vacm
pn_snmp_vacm:
pn_cliswitch: "sw01"
state: "update"
pn_user_name: "foo"
pn_user_type: "rwuser"
- name: snmp vacm functionality
- name: delete snmp vacm
pn_snmp_vacm:
pn_cliswitch: "sw01"
state: "absent"
pn_user_name: "foo"
"""
@ -97,6 +100,7 @@ changed:
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.netvisor.pn_nvos import pn_cli, run_cli, booleanArgs
from ansible.module_utils.network.netvisor.netvisor import run_commands
def check_cli(module, cli):
@ -110,7 +114,7 @@ def check_cli(module, cli):
show = cli
cli += ' snmp-user-show user-name %s format user-name no-show-headers' % user_name
rc, out, err = module.run_command(cli, use_unsafe_shell=True)
rc, out, err = run_commands(module, cli)
if out:
pass
else:
@ -118,7 +122,7 @@ def check_cli(module, cli):
cli = show
cli += ' snmp-vacm-show format user-name no-show-headers'
out = module.run_command(cli, use_unsafe_shell=True)[1]
out = run_commands(module, cli)[1]
out = out.split()

View file

@ -96,6 +96,7 @@ changed:
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.netvisor.pn_nvos import pn_cli, run_cli
from ansible.module_utils.network.netvisor.netvisor import run_commands
def check_cli(module, cli):
@ -108,7 +109,7 @@ def check_cli(module, cli):
name = module.params['pn_name']
cli += ' user-show format name no-show-headers'
out = module.run_command(cli, use_unsafe_shell=True)[1]
out = run_commands(module, cli)[1]
out = out.split()

View file

@ -53,7 +53,7 @@ options:
EXAMPLES = """
- name: Add network to bgp
pn_vrouter_bgp_network:
pn_cliswitch: "{{ inventory_hostname }}"
pn_cliswitch: "sw01"
state: "present"
pn_vrouter_name: "foo-vrouter"
pn_network: '10.10.10.10'
@ -61,7 +61,7 @@ EXAMPLES = """
- name: Remove network from bgp
pn_vrouter_bgp_network:
pn_cliswitch: "{{ inventory_hostname }}"
pn_cliswitch: "sw01"
state: "absent"
pn_vrouter_name: "foo-vrouter"
pn_network: '10.10.10.10'
@ -89,6 +89,7 @@ changed:
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.netvisor.pn_nvos import pn_cli, run_cli
from ansible.module_utils.network.netvisor.netvisor import run_commands
def check_cli(module, cli):
@ -103,14 +104,14 @@ def check_cli(module, cli):
show = cli
cli += ' vrouter-show name %s format name no-show-headers' % name
rc, out, err = module.run_command(cli, use_unsafe_shell=True)
rc, out, err = run_commands(module, cli)
VROUTER_EXISTS = '' if out else None
cli = show
cli += ' vrouter-bgp-network-show vrouter-name %s network %s format network no-show-headers' % (name, network)
out = module.run_command(cli, use_unsafe_shell=True)[1]
NETWORK_EXISTS = True if network in out else False
out = run_commands(module, cli)[1]
out = out.split()
NETWORK_EXISTS = True if network in out[-1] else False
return NETWORK_EXISTS, VROUTER_EXISTS

View file

@ -105,6 +105,7 @@ changed:
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.netvisor.pn_nvos import pn_cli, run_cli
from ansible.module_utils.network.netvisor.netvisor import run_commands
def check_cli(module, cli):
@ -130,19 +131,19 @@ def check_cli(module, cli):
nic_str = module.params['pn_nic']
# Check for vRouter
check_vrouter = cli + ' vrouter-show format name no-show-headers '
out = module.run_command(check_vrouter, use_unsafe_shell=True)[1]
check_vrouter = cli + ' vrouter-show name %s format name no-show-headers ' % vrouter_name
out = run_commands(module, check_vrouter)[1]
out = out.split()
VROUTER_EXISTS = True if vrouter_name in out else False
VROUTER_EXISTS = True if vrouter_name in out[-1] else False
if interface_ip:
# Check for interface and VRRP and fetch nic for VRRP
show = cli + ' vrouter-interface-show vrouter-name %s ' % vrouter_name
show += 'ip2 %s format ip2,nic no-show-headers' % interface_ip
out = module.run_command(show, use_unsafe_shell=True)[1]
out = run_commands(module, show)[1]
if out and interface_ip in out.split(' ')[1]:
if out and interface_ip in out.split(' ')[-2]:
INTERFACE_EXISTS = True
else:
INTERFACE_EXISTS = False
@ -151,7 +152,8 @@ def check_cli(module, cli):
# Check for nic
show = cli + ' vrouter-interface-show vrouter-name %s ' % vrouter_name
show += ' format nic no-show-headers'
out = module.run_command(show, use_unsafe_shell=True)[1]
out = run_commands(module, show)[1]
out = out.split()
NIC_EXISTS = True if nic_str in out else False

View file

@ -88,6 +88,7 @@ changed:
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.netvisor.pn_nvos import pn_cli, run_cli
from ansible.module_utils.network.netvisor.netvisor import run_commands
def check_cli(module, cli):
@ -109,7 +110,7 @@ def check_cli(module, cli):
# Check for vRouter
check_vrouter = cli + ' vrouter-show format name no-show-headers '
out = module.run_command(check_vrouter, use_unsafe_shell=True)[1]
out = run_commands(module, check_vrouter)[1]
out = out.split()
VROUTER_EXISTS = True if vrouter_name in out else False
@ -117,7 +118,7 @@ def check_cli(module, cli):
if nic_str:
# Check for nic
show = cli + ' vrouter-ospf6-show vrouter-name %s format nic no-show-headers' % vrouter_name
out = module.run_command(show, use_unsafe_shell=True)[1]
out = run_commands(module, show)[1]
NIC_EXISTS = True if nic_str in out else False

View file

@ -84,6 +84,7 @@ changed:
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.netvisor.pn_nvos import pn_cli, run_cli
from ansible.module_utils.network.netvisor.netvisor import run_commands
def check_cli(module, cli):
@ -96,16 +97,18 @@ def check_cli(module, cli):
name = module.params['pn_vrouter_name']
show = cli
cli += 'vrouter-show name %s format name no-show-headers ' % name
out = module.run_command(cli, use_unsafe_shell=True)
if out:
cli += ' vrouter-show name %s format name no-show-headers ' % name
out = run_commands(module, cli)[1]
out = out.split()
if out[-1] == name:
pass
else:
return False
cli = show
cli += ' vrouter-show name %s format proto-multi no-show-headers' % name
out = module.run_command(cli, use_unsafe_shell=True)[1]
out = run_commands(module, cli)[1]
out = out.split()
return True if 'none' not in out else False

View file

@ -0,0 +1,66 @@
#
# (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 <http://www.gnu.org/licenses/>.
#
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = """
---
cliconf: netvisor
short_description: Use netvisor cliconf to run command on Pluribus netvisor platform
description:
- This netvisor plugin provides low level abstraction apis for
sending and receiving CLI commands from Pluribus netvisor devices.
version_added: 2.8
"""
import json
from ansible.plugins.cliconf import CliconfBase
class Cliconf(CliconfBase):
def get(self, command=None, prompt=None, answer=None, sendonly=False, output=None, check_all=False):
if not command:
raise ValueError('must provide value of command to execute')
if output:
raise ValueError("'output' value %s is not supported for get" % output)
return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, check_all=check_all)
def get_option_values(self):
return {
'format': ['text'],
'diff_match': ['line', 'strict', 'exact', 'none'],
'diff_replace': ['line', 'block'],
'output': []
}
def get_capabilities(self):
result = dict()
result['rpc'] = self.get_base_rpc()
result['network_api'] = 'cliconf'
result['device_info'] = self.get_device_info()
result.update(self.get_option_values())
return json.dumps(result)
def get_device_info(self):
device_info = {}
device_info['network_os'] = 'netvisor'
return device_info

View file

@ -0,0 +1,39 @@
#
# (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 <http://www.gnu.org/licenses/>.
#
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import json
import re
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(br">.*[\r\n]?(.*)")
]
terminal_stderr_re = [
re.compile(br"% ?Error: (?!\bdoes not exist\b)(?!\balready exists\b)")
]