From 456b3d2c23e6218c6c3a1b718f940e4830f8e5c9 Mon Sep 17 00:00:00 2001 From: Peter Sprygada Date: Fri, 8 Jan 2016 14:00:23 -0500 Subject: [PATCH] adds new iosxr shared module for developing modules that work with IOS XR devices This commit adds a new shared module for working with Cisco IOS XR devices over CLI (SSH). It also provides a documentation fragement for the commmon arguments provided by the iosxr module. --- lib/ansible/module_utils/iosxr.py | 121 ++++++++++++++++++ .../utils/module_docs_fragments/iosxr.py | 52 ++++++++ 2 files changed, 173 insertions(+) create mode 100644 lib/ansible/module_utils/iosxr.py create mode 100644 lib/ansible/utils/module_docs_fragments/iosxr.py diff --git a/lib/ansible/module_utils/iosxr.py b/lib/ansible/module_utils/iosxr.py new file mode 100644 index 0000000000..9686adc7f5 --- /dev/null +++ b/lib/ansible/module_utils/iosxr.py @@ -0,0 +1,121 @@ +# +# (c) 2015 Peter Sprygada, +# +# 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 . +# + +NET_PASSWD_RE = re.compile(r"[\r\n]?password: $", re.I) + +NET_COMMON_ARGS = dict( + host=dict(required=True), + port=dict(default=22, type='int'), + username=dict(required=True), + password=dict(no_log=True) +) + +def to_list(val): + if isinstance(val, (list, tuple)): + return list(val) + elif val is not None: + return [val] + else: + return list() + +class Cli(object): + + def __init__(self, module): + self.module = module + self.shell = None + + def connect(self, **kwargs): + host = self.module.params['host'] + port = self.module.params['port'] or 22 + + username = self.module.params['username'] + password = self.module.params['password'] + + self.shell = Shell() + self.shell.open(host, port=port, username=username, password=password) + + def send(self, commands): + return self.shell.send(commands) + +class IosxrModule(AnsibleModule): + + def __init__(self, *args, **kwargs): + super(IosxrModule, self).__init__(*args, **kwargs) + self.connection = None + self._config = None + + @property + def config(self): + if not self._config: + self._config = self.get_config() + return self._config + + def connect(self): + try: + self.connection = Cli(self) + self.connection.connect() + self.execute('terminal length 0') + except Exception, exc: + self.fail_json(msg=exc.message) + + def configure(self, commands): + commands = to_list(commands) + commands.insert(0, 'configure terminal') + commands.append('commit') + responses = self.execute(commands) + responses.pop(0) + responses.pop() + return responses + + def execute(self, commands, **kwargs): + return self.connection.send(commands) + + def disconnect(self): + self.connection.close() + + def parse_config(self, cfg): + return parse(cfg, indent=1) + + def get_config(self): + return self.execute('show running-config')[0] + +def get_module(**kwargs): + """Return instance of IosxrModule + """ + + argument_spec = NET_COMMON_ARGS.copy() + if kwargs.get('argument_spec'): + argument_spec.update(kwargs['argument_spec']) + kwargs['argument_spec'] = argument_spec + kwargs['check_invalid_arguments'] = False + + module = IosxrModule(**kwargs) + + if not HAS_PARAMIKO: + module.fail_json(msg='paramiko is required but does not appear to be installed') + + # copy in values from local action. + params = json_dict_unicode_to_bytes(json.loads(MODULE_COMPLEX_ARGS)) + for key, value in params.iteritems(): + module.params[key] = value + + module.connect() + + return module + diff --git a/lib/ansible/utils/module_docs_fragments/iosxr.py b/lib/ansible/utils/module_docs_fragments/iosxr.py new file mode 100644 index 0000000000..cb9ba28fc2 --- /dev/null +++ b/lib/ansible/utils/module_docs_fragments/iosxr.py @@ -0,0 +1,52 @@ +# +# (c) 2015, Peter Sprygada +# +# 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 + required: true + password: + description: + - Specifies the password to use when authentication the connection to + the remote device. The value of I(password) is used to authenticate + the SSH session + required: false + default: null + + """