From f6aa730c3cb2aa2d1a0d5586dc3e01b572db27ed Mon Sep 17 00:00:00 2001 From: Senthil Kumar Ganesan Date: Mon, 29 Aug 2016 21:29:26 -0700 Subject: [PATCH] Utilities to support DELL Networking OS10 command and config modules --- CHANGELOG.md | 3 + lib/ansible/module_utils/dnos10.py | 122 ++++++++++++++++++ lib/ansible/plugins/action/dnos10_config.py | 26 ++++ .../utils/module_docs_fragments/dnos10.py | 71 ++++++++++ 4 files changed, 222 insertions(+) create mode 100644 lib/ansible/module_utils/dnos10.py create mode 100644 lib/ansible/plugins/action/dnos10_config.py create mode 100644 lib/ansible/utils/module_docs_fragments/dnos10.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ad5f632283..9e03fa6d379 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,6 +73,9 @@ Ansible Changes By Release * vmware_local_user_manager * vmware_vmotion - wakeonlan +- Dell Networking + * dnos10_command + * dnos10_config ###Minor Changes: * now -vvv shows exact path from which 'currently executing module' was picked up from. diff --git a/lib/ansible/module_utils/dnos10.py b/lib/ansible/module_utils/dnos10.py new file mode 100644 index 00000000000..c36cc0a1ceb --- /dev/null +++ b/lib/ansible/module_utils/dnos10.py @@ -0,0 +1,122 @@ +# 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 . +# + +import re + +from ansible.module_utils.network import NetworkModule, NetworkError, ModuleStub +from ansible.module_utils.network import add_argument, register_transport, to_list +from ansible.module_utils.shell import CliBase +from ansible.module_utils.netcli import Command +from ansible.module_utils.netcfg import NetworkConfig, ConfigLine + +add_argument('use_ssl', dict(default=True, type='bool')) +add_argument('validate_certs', dict(default=True, type='bool')) + +def argument_spec(): + return dict( + running_config=dict(aliases=['config']), + save_config=dict(default=False, aliases=['save']), + force=dict(type='bool', default=False) + ) +dnos10_argument_spec = argument_spec() + +def get_config(module, include_defaults=False): + contents = module.params['running_config'] + if not contents: + contents = module.config.get_config() + module.params['running_config'] = contents + + return NetworkConfig(indent=1, contents=contents[0]) + +def get_sublevel_config(running_config, module): + contents = list() + current_config_contents = list() + obj = running_config.get_object(module.params['parents']) + if obj: + contents = obj.children + contents[:0] = module.params['parents'] + + for c in contents: + if isinstance(c, str): + current_config_contents.append(c) + if isinstance(c, ConfigLine): + current_config_contents.append(c.raw) + sublevel_config = '\n'.join(current_config_contents) + + return sublevel_config + + +class Cli(CliBase): + + NET_PASSWD_RE = re.compile(r"[\r\n]?password:\s?$", re.I) + + CLI_PROMPTS_RE = [ + re.compile(r"[\r\n]?[\w+\-\.:\/\[\]]+(?:\([^\)]+\)){,3}(?:>|#) ?$"), + re.compile(r"\[\w+\@[\w\-\.]+(?: [^\]])\] ?[>#\$] ?$") + ] + + CLI_ERRORS_RE = [ + re.compile(r"% ?Error"), + re.compile(r"% ?Bad secret"), + re.compile(r"Syntax error:"), + re.compile(r"invalid input", re.I), + re.compile(r"(?:incomplete|ambiguous) command", re.I), + re.compile(r"connection timed out", re.I), + re.compile(r"[^\r\n]+ not found", re.I), + re.compile(r"'[^']' +returned error code: ?\d+"), + ] + + def connect(self, params, **kwargs): + super(Cli, self).connect(params, kickstart=False, **kwargs) + self.shell.send('terminal length 0') + self._connected = True + + def disconnect(self): + self._connected = False + + def run_commands(self, commands, **kwargs): + commands = to_list(commands) + return self.execute([c for c in commands]) + + def configure(self, commands, **kwargs): + cmds = ['configure terminal'] + cmds.extend(to_list(commands)) + cmds.append('end') + cmds.append('commit') + + responses = self.execute(cmds) + responses.pop(0) + return responses + + def get_config(self, include_defaults=False, **kwargs): + return self.execute(['show running-configuration']) + + def load_config(self, commands, **kwargs): + return self.configure(commands) + + def replace_config(self, commands, **kwargs): + raise NotImplementedError + + def commit_config(self, **kwargs): + self.execute(['commit']) + + def abort_config(self, **kwargs): + self.execute(['discard']) + + def save_config(self): + self.execute(['copy running-config startup-config']) + +Cli = register_transport('cli', default=True)(Cli) diff --git a/lib/ansible/plugins/action/dnos10_config.py b/lib/ansible/plugins/action/dnos10_config.py new file mode 100644 index 00000000000..13bcd553451 --- /dev/null +++ b/lib/ansible/plugins/action/dnos10_config.py @@ -0,0 +1,26 @@ +# +# 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 + +from ansible.plugins.action import ActionBase +from ansible.plugins.action.net_config import ActionModule as NetActionModule + +class ActionModule(NetActionModule, ActionBase): + pass + + diff --git a/lib/ansible/utils/module_docs_fragments/dnos10.py b/lib/ansible/utils/module_docs_fragments/dnos10.py new file mode 100644 index 00000000000..3ddffa17c51 --- /dev/null +++ b/lib/ansible/utils/module_docs_fragments/dnos10.py @@ -0,0 +1,71 @@ +# 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: + 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. + required: true + port: + description: + - Specifies the port to use when buiding the connection to the remote + device. The port value will default to the well known SSH port + of 22 + required: false + default: 22 + username: + description: + - Configures the usename to use to authenticate the connection to + the remote device. The value of I(username) is used to authenticate + the SSH session. If the value is not specified in the task, the + value of environment variable ANSIBLE_NET_USERNAME will be used instead. + required: false + password: + description: + - Specifies the password to use to authenticate the connection to + the remote device. The value of I(password) is used to authenticate + the SSH session. If the value is not specified in the task, the + value of environment variable ANSIBLE_NET_PASSWORD will be used instead. + required: false + default: null + ssh_keyfile: + description: + - Specifies the SSH key to use to authenticate the connection to + the remote device. The value of I(ssh_keyfile) 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 ANSIBLE_NET_SSH_KEYFILE + will be used instead. + required: false + timeout: + description: + - Specifies idle timeout for the connection. Useful if the console + freezes before continuing. For example when saving configurations. + required: false + default: 10 + provider: + description: + - Convience method that allows all M(dnos10) arguments to be passed as + a dict object. All constraints (required, choices, etc) must be + met either by individual arguments or values in this dict. + required: false + default: null +"""