diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c7e310392..72988cf28a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -75,6 +75,8 @@ Ansible Changes By Release * exo_dns_record - dnos6 * dnos6_command +- dnos9 + * dnos9_command - f5: * bigip_device_dns * bigip_device_ntp diff --git a/lib/ansible/module_utils/dnos9.py b/lib/ansible/module_utils/dnos9.py new file mode 100755 index 0000000000..71a290e440 --- /dev/null +++ b/lib/ansible/module_utils/dnos9.py @@ -0,0 +1,115 @@ +# This code is part of Ansible, but is an independent component. +# This particular file snippet, and this file snippet only, is BSD licensed. +# Modules you write using this snippet, which is embedded dynamically by Ansible +# still belong to the author of the module, and may assign their own license +# to the complete work. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# 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. +# + +import re + +from ansible.module_utils.shell import CliBase +from ansible.module_utils.network import register_transport, to_list, Command +from ansible.module_utils.netcfg import NetworkConfig, ConfigLine + + +def get_config(module): + contents = module.params['config'] + + if not contents: + contents = module.config.get_config() + module.params['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"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') + + + def authorize(self, params, **kwargs): + passwd = params['auth_pass'] + self.run_commands( + Command('enable', prompt=self.NET_PASSWD_RE, response=passwd) + ) + + + def configure(self, commands, **kwargs): + cmds = ['configure terminal'] + cmds.extend(to_list(commands)) + cmds.append('end') + + responses = self.execute(cmds) + responses.pop(0) + return responses + + + def get_config(self, **kwargs): + return self.execute(['show running-config']) + + + def load_config(self, commands, **kwargs): + return self.configure(commands) + + + def save_config(self): + self.execute(['copy running-config startup-config']) + + +Cli = register_transport('cli', default=True)(Cli) diff --git a/lib/ansible/utils/module_docs_fragments/dnos9.py b/lib/ansible/utils/module_docs_fragments/dnos9.py new file mode 100755 index 0000000000..ea3a0bf4fd --- /dev/null +++ b/lib/ansible/utils/module_docs_fragments/dnos9.py @@ -0,0 +1,86 @@ +# 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 building the connection to the remote + device. + required: false + default: 22 + username: + description: + - This value I(username) is used to authenticate the SSH session to the + remote device. 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: + - This value I(password) is used to authenticate the SSH session to + the remote device. 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: + - This value I(ssh_keyfile) is the path to the key used to authenticate + the SSH session to the remote device. If the value is not specified + in the task, the value of environment variable ANSIBLE_NET_SSH_KEYFILE + will be used instead. + required: false + authorize: + description: + - Instructs the module to enter priviledged mode on the remote device + before sending any commands. If not specified, the device will + attempt to excecute all commands in non-priviledged mode. If the value + is not specified in the task, the value of environment variable + ANSIBLE_NET_AUTHORIZE will be used instead. + required: false + default: no + choices: ['yes', 'no'] + auth_pass: + description: + - Specifies the password to use if required to enter privileged mode + on the remote device. If I(authorize) is false, then this argument + does nothing. If the value is not specified in the task, the value of + environment variable ANSIBLE_NET_AUTH_PASS will be used instead. + required: false + default: none + timeout: + description: + - Specifies idle timeout (in seconds) for the connection. Useful if the + console freezes before continuing. For example when saving + configurations. + required: false + default: 10 + provider: + description: + - Convenience method that allows all M(dnos9) 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 +"""