initial commit of vyos shared module with Cli transport
This adds support for the VyOS network operating system using the Cli transport. This module will simplify building VyOS based modules in Ansible
This commit is contained in:
parent
c117b9d79b
commit
77922f82e2
1 changed files with 154 additions and 0 deletions
154
lib/ansible/module_utils/vyos.py
Normal file
154
lib/ansible/module_utils/vyos.py
Normal file
|
@ -0,0 +1,154 @@
|
|||
#
|
||||
# (c) 2015 Peter Sprygada, <psprygada@ansible.com>
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
import re
|
||||
|
||||
from ansible.module_utils.network import NetworkError, get_module, get_exception
|
||||
from ansible.module_utils.network import register_transport, to_list
|
||||
from ansible.module_utils.network import Command, NetCli
|
||||
from ansible.module_utils.shell import Shell, ShellError, HAS_PARAMIKO
|
||||
|
||||
DEFAULT_COMMENT = 'configured by vyos_config'
|
||||
|
||||
def argument_spec():
|
||||
return dict(
|
||||
config=dict(),
|
||||
comment=dict(default=DEFAULT_COMMENT),
|
||||
save=dict(type='bool')
|
||||
)
|
||||
vyos_argument_spec = argument_spec()
|
||||
|
||||
get_config = lambda x: x.params['config'] or x.config.get_config()
|
||||
|
||||
def diff_config(candidate, config):
|
||||
updates = set()
|
||||
config = [str(c).replace("'", '') for c in config]
|
||||
|
||||
for line in candidate:
|
||||
item = str(line).replace("'", '')
|
||||
|
||||
if not item.startswith('set') and not item.startswith('delete'):
|
||||
raise ValueError('line must start with either `set` or `delete`')
|
||||
|
||||
elif item.startswith('set') and item not in config:
|
||||
updates.add(line)
|
||||
|
||||
elif item.startswith('delete'):
|
||||
if not config:
|
||||
updates.add(line)
|
||||
else:
|
||||
item = re.sub(r'delete', 'set', item)
|
||||
for entry in config:
|
||||
if entry.startswith(item):
|
||||
updates.add(line)
|
||||
|
||||
return list(updates)
|
||||
|
||||
def load_config(module, candidate):
|
||||
config = get_config(module).split('\n')
|
||||
updates = diff_config(candidate, config)
|
||||
|
||||
comment = module.params['comment']
|
||||
save = module.params['save']
|
||||
|
||||
result = dict(changed=False)
|
||||
|
||||
if updates:
|
||||
diff = module.config.load_config(updates)
|
||||
if diff:
|
||||
result['diff'] = dict(prepared=diff)
|
||||
|
||||
result['changed'] = True
|
||||
result['updates'] = updates
|
||||
|
||||
if not module.check_mode:
|
||||
module.config.commit_config(comment=comment)
|
||||
if save:
|
||||
module.config.save_config()
|
||||
else:
|
||||
module.config.abort_config()
|
||||
|
||||
# exit from config mode
|
||||
module.cli('exit')
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class Cli(NetCli):
|
||||
|
||||
CLI_PROMPTS_RE = [
|
||||
re.compile(r"[\r\n]?[\w+\-\.:\/\[\]]+(?:\([^\)]+\)){,3}(?:>|#) ?$"),
|
||||
re.compile(r"\@[\w\-\.]+:\S+?[>#\$] ?$")
|
||||
]
|
||||
|
||||
CLI_ERRORS_RE = [
|
||||
re.compile(r"\n\s*Invalid command:"),
|
||||
re.compile(r"\nCommit failed"),
|
||||
re.compile(r"\n\s+Set failed"),
|
||||
]
|
||||
|
||||
def connect(self, params, **kwargs):
|
||||
super(Cli, self).connect(params, kickstart=False, **kwargs)
|
||||
self.shell.send('set terminal length 0')
|
||||
self._connected = True
|
||||
|
||||
### Cli methods ###
|
||||
|
||||
def run_commands(self, commands, **kwargs):
|
||||
commands = to_list(commands)
|
||||
response = self.execute([str(c) for c in commands])
|
||||
return response
|
||||
|
||||
### Config methods ###
|
||||
|
||||
def configure(self, commands, commit=True, **kwargs):
|
||||
"""Called by Config.__call__
|
||||
"""
|
||||
cmds = ['configure']
|
||||
cmds.extend(to_list(commands))
|
||||
response = self.execute(cmds)
|
||||
if commit:
|
||||
self.commit_config()
|
||||
return response
|
||||
|
||||
def load_config(self, commands):
|
||||
self.configure(commands, commit=False)
|
||||
diff = None
|
||||
if not self.execute('compare')[0].startswith('No changes'):
|
||||
diff = self.execute(['show'])[0]
|
||||
return diff
|
||||
|
||||
def get_config(self):
|
||||
return self.execute(['show configuration commands'])[0]
|
||||
|
||||
def commit_config(self, confirm=0, comment=None):
|
||||
if confirm > 0:
|
||||
cmd = 'commit-confirm %s' % confirm
|
||||
else:
|
||||
cmd = 'commit'
|
||||
if comment:
|
||||
cmd += ' comment "%s"' % comment
|
||||
self.execute([cmd])
|
||||
|
||||
def abort_config(self):
|
||||
self.execute(['discard'])
|
||||
|
||||
def save_config(self):
|
||||
self.execute(['save'])
|
||||
Cli = register_transport('cli', default=True)(Cli)
|
Loading…
Reference in a new issue