|
|
@ -30,18 +30,24 @@ import itertools
|
|
|
|
|
|
|
|
|
|
|
|
from ansible.module_utils.basic import AnsibleModule
|
|
|
|
from ansible.module_utils.basic import AnsibleModule
|
|
|
|
from ansible.module_utils.basic import env_fallback, get_exception
|
|
|
|
from ansible.module_utils.basic import env_fallback, get_exception
|
|
|
|
|
|
|
|
from ansible.module_utils.netcmd import Cli, Command
|
|
|
|
|
|
|
|
from ansible.module_utils.netcfg import Config
|
|
|
|
from ansible.module_utils.shell import Shell, ShellError, HAS_PARAMIKO
|
|
|
|
from ansible.module_utils.shell import Shell, ShellError, HAS_PARAMIKO
|
|
|
|
|
|
|
|
|
|
|
|
NET_TRANSPORT_ARGS = dict(
|
|
|
|
NET_TRANSPORT_ARGS = dict(
|
|
|
|
host=dict(required=True),
|
|
|
|
host=dict(required=True),
|
|
|
|
port=dict(type='int'),
|
|
|
|
port=dict(type='int'),
|
|
|
|
|
|
|
|
|
|
|
|
username=dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])),
|
|
|
|
username=dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])),
|
|
|
|
password=dict(no_log=True, fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD'])),
|
|
|
|
password=dict(no_log=True, fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD'])),
|
|
|
|
ssh_keyfile=dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']), type='path'),
|
|
|
|
ssh_keyfile=dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']), type='path'),
|
|
|
|
|
|
|
|
|
|
|
|
authorize=dict(default=False, fallback=(env_fallback, ['ANSIBLE_NET_AUTHORIZE']), type='bool'),
|
|
|
|
authorize=dict(default=False, fallback=(env_fallback, ['ANSIBLE_NET_AUTHORIZE']), type='bool'),
|
|
|
|
auth_pass=dict(no_log=True, fallback=(env_fallback, ['ANSIBLE_NET_AUTH_PASS'])),
|
|
|
|
auth_pass=dict(no_log=True, fallback=(env_fallback, ['ANSIBLE_NET_AUTH_PASS'])),
|
|
|
|
|
|
|
|
|
|
|
|
provider=dict(type='dict'),
|
|
|
|
provider=dict(type='dict'),
|
|
|
|
transport=dict(choices=list()),
|
|
|
|
transport=dict(choices=list()),
|
|
|
|
|
|
|
|
|
|
|
|
timeout=dict(default=10, type='int')
|
|
|
|
timeout=dict(default=10, type='int')
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
@ -66,86 +72,6 @@ class ModuleStub(object):
|
|
|
|
self.params[key] = value.get('default')
|
|
|
|
self.params[key] = value.get('default')
|
|
|
|
self.fail_json = fail_json
|
|
|
|
self.fail_json = fail_json
|
|
|
|
|
|
|
|
|
|
|
|
class Command(object):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, command, output=None, prompt=None, response=None,
|
|
|
|
|
|
|
|
is_reboot=False, delay=0):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.command = command
|
|
|
|
|
|
|
|
self.output = output
|
|
|
|
|
|
|
|
self.prompt = prompt
|
|
|
|
|
|
|
|
self.response = response
|
|
|
|
|
|
|
|
self.is_reboot = is_reboot
|
|
|
|
|
|
|
|
self.delay = delay
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
|
|
|
|
return self.command
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Cli(object):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, connection):
|
|
|
|
|
|
|
|
self.connection = connection
|
|
|
|
|
|
|
|
self.default_output = connection.default_output or 'text'
|
|
|
|
|
|
|
|
self.commands = list()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __call__(self, commands, output=None):
|
|
|
|
|
|
|
|
commands = self.to_command(commands, output)
|
|
|
|
|
|
|
|
return self.connection.run_commands(commands)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def to_command(self, commands, output=None):
|
|
|
|
|
|
|
|
output = output or self.default_output
|
|
|
|
|
|
|
|
objects = list()
|
|
|
|
|
|
|
|
for cmd in to_list(commands):
|
|
|
|
|
|
|
|
if not isinstance(cmd, Command):
|
|
|
|
|
|
|
|
cmd = Command(cmd, output)
|
|
|
|
|
|
|
|
objects.append(cmd)
|
|
|
|
|
|
|
|
return objects
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def add_commands(self, commands, output=None):
|
|
|
|
|
|
|
|
commands = self.to_command(commands, output)
|
|
|
|
|
|
|
|
self.commands.extend(commands)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def run_commands(self):
|
|
|
|
|
|
|
|
responses = self.connection.run_commands(self.commands)
|
|
|
|
|
|
|
|
for resp, cmd in itertools.izip(responses, self.commands):
|
|
|
|
|
|
|
|
cmd.response = resp
|
|
|
|
|
|
|
|
return responses
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Config(object):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, connection):
|
|
|
|
|
|
|
|
self.connection = connection
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def invoke(self, method, *args, **kwargs):
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
return method(*args, **kwargs)
|
|
|
|
|
|
|
|
except AttributeError:
|
|
|
|
|
|
|
|
exc = get_exception()
|
|
|
|
|
|
|
|
raise NetworkError('undefined method "%s"' % method.__name__, exc=str(exc))
|
|
|
|
|
|
|
|
except NotImplementedError:
|
|
|
|
|
|
|
|
raise NetworkError('method not supported "%s"' % method.__name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __call__(self, commands):
|
|
|
|
|
|
|
|
lines = to_list(commands)
|
|
|
|
|
|
|
|
return self.invoke(self.connection.configure, commands)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def load_config(self, commands, **kwargs):
|
|
|
|
|
|
|
|
commands = to_list(commands)
|
|
|
|
|
|
|
|
return self.invoke(self.connection.load_config, commands, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_config(self, **kwargs):
|
|
|
|
|
|
|
|
return self.invoke(self.connection.get_config, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def commit_config(self, **kwargs):
|
|
|
|
|
|
|
|
return self.invoke(self.connection.commit_config, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def abort_config(self, **kwargs):
|
|
|
|
|
|
|
|
return self.invoke(self.connection.abort_config, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def save_config(self):
|
|
|
|
|
|
|
|
return self.invoke(self.connection.save_config)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NetworkError(Exception):
|
|
|
|
class NetworkError(Exception):
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, msg, **kwargs):
|
|
|
|
def __init__(self, msg, **kwargs):
|
|
|
@ -234,7 +160,6 @@ class NetworkModule(AnsibleModule):
|
|
|
|
exc = get_exception()
|
|
|
|
exc = get_exception()
|
|
|
|
self.fail_json(msg=exc.message)
|
|
|
|
self.fail_json(msg=exc.message)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NetCli(object):
|
|
|
|
class NetCli(object):
|
|
|
|
"""Basic paramiko-based ssh transport any NetworkModule can use."""
|
|
|
|
"""Basic paramiko-based ssh transport any NetworkModule can use."""
|
|
|
|
|
|
|
|
|
|
|
@ -274,9 +199,11 @@ class NetCli(object):
|
|
|
|
msg='failed to connect to %s:%s' % (host, port), exc=str(exc)
|
|
|
|
msg='failed to connect to %s:%s' % (host, port), exc=str(exc)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self._connected = True
|
|
|
|
|
|
|
|
|
|
|
|
def disconnect(self, **kwargs):
|
|
|
|
def disconnect(self, **kwargs):
|
|
|
|
self._connected = False
|
|
|
|
|
|
|
|
self.shell.close()
|
|
|
|
self.shell.close()
|
|
|
|
|
|
|
|
self._connected = False
|
|
|
|
|
|
|
|
|
|
|
|
def authorize(self, params, **kwargs):
|
|
|
|
def authorize(self, params, **kwargs):
|
|
|
|
passwd = params['auth_pass']
|
|
|
|
passwd = params['auth_pass']
|
|
|
|