ansible/network/cumulus/cl_quagga_protocol.py
2016-01-25 15:59:45 -08:00

212 lines
7.2 KiB
Python
Executable file

#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2016, Cumulus Networks <ce-ceng@cumulusnetworks.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/>.
DOCUMENTATION = '''
---
module: cl_quagga_protocol
version_added: "2.1"
author: "Cumulus Networks (@CumulusNetworks)"
short_description: Enable routing protocol services via Quagga
description:
- Enable Quagga services available on Cumulus Linux. This includes OSPF
v2/v3 and BGP. Quagga services are defined in the /etc/quagga/daemons
file. This module creates a file that will only enable OSPF or BGP routing
protocols, because this is what Cumulus Linux currently supports. Zebra is
automatically enabled when a supported routing protocol is listed. If all
routing protocols are disabled, this module will disable zebra as well.
Using Ansible Templates you can run any supported or unsupported quagga
routing protocol. For more details go to the Quagga Documentation located
at http://docs.cumulusnetworks.com/ and at
http://www.nongnu.org/quagga/docs.html
options:
name:
description:
- name of the protocol to update
choices: ['ospfd', 'ospf6d', 'bgpd']
required: true
state:
description:
- describe whether the protocol should be enabled or disabled
choices: ['present', 'absent']
required: true
activate:
description:
- restart quagga process to activate the change. If the service
is already configured but not activated, setting activate=yes will
not activate the service. This will be fixed in an upcoming
release
choices: ['yes', 'no']
default: ['no']
requirements: ['Quagga version 0.99.23 and higher']
'''
EXAMPLES = '''
Example playbook entries using the cl_quagga module
## Enable OSPFv2. Do not activate the change
cl_quagga_protocol name="ospfd" state=present
## Disable OSPFv2. Do not activate the change
cl_quagga_protocol name="ospf6d" state=absent
## Enable BGPv2. Do not activate the change. Activating the change requires a
## restart of the entire quagga process.
cl_quagga_protocol name="bgpd" state=present
## Enable OSPFv2 and activate the change as this might not start quagga when you
## want it to
cl_quagga_protocol name="ospfd" state=present activate=yes
## To activate a configured service
- name: disable ospfv2 service. Its configured but not enabled
cl_quagga_protocol name=ospfd state=absent
- name: enable ospfv2 service and activate it
cl_quagga_protocol name=ospfd state=present activate=yes
'''
RETURN = '''
changed:
description: whether the interface was changed
returned: changed
type: bool
sample: True
msg:
description: human-readable report of success or failure
returned: always
type: string
sample: "interface bond0 config updated"
'''
def run_cl_cmd(module, cmd, check_rc=True):
try:
(rc, out, err) = module.run_command(cmd, check_rc=check_rc)
except Exception, e:
module.fail_json(msg=e.strerror)
# trim last line as it is always empty
ret = out.splitlines()
return ret
def convert_to_yes_or_no(_state):
if _state == 'present':
_str = 'yes'
else:
_str = 'no'
return _str
def read_daemon_file(module):
f = open(module.quagga_daemon_file)
if f:
return f.readlines()
else:
return []
def setting_is_configured(module):
_protocol = module.params.get('name')
_state = module.params.get('state')
_state = convert_to_yes_or_no(_state)
_daemon_output = read_daemon_file(module)
_str = "(%s)=(%s)" % (_protocol, 'yes|no')
_daemonstr = re.compile("\w+=yes")
_zebrastr = re.compile("zebra=(yes|no)")
_matchstr = re.compile(_str)
daemoncount = 0
module.disable_zebra = False
for _line in _daemon_output:
_match = re.match(_matchstr, _line)
_active_daemon_match = re.match(_daemonstr, _line)
_zebramatch = re.match(_zebrastr, _line)
if _active_daemon_match:
daemoncount += 1
if _zebramatch:
if _zebramatch.group(1) == 'no' and _state == 'yes':
return False
elif _match:
if _state == _match.group(2):
_msg = "%s is configured and is %s" % \
(_protocol, module.params.get('state'))
module.exit_json(msg=_msg, changed=False)
# for nosetests purposes only
if daemoncount < 3 and _state == 'no':
module.disable_zebra = True
return False
def modify_config(module):
_protocol = module.params.get('name')
_state = module.params.get('state')
_state = convert_to_yes_or_no(_state)
_daemon_output = read_daemon_file(module)
_str = "(%s)=(%s)" % (_protocol, 'yes|no')
_zebrastr = re.compile("zebra=(yes|no)")
_matchstr = re.compile(_str)
write_to_file = open(module.quagga_daemon_file, 'w')
for _line in _daemon_output:
_match = re.match(_matchstr, _line)
_zebramatch = re.match(_zebrastr, _line)
if _zebramatch:
if module.disable_zebra is True and _state == 'no':
write_to_file.write('zebra=no\n')
elif _state == 'yes':
write_to_file.write('zebra=yes\n')
else:
write_to_file.write(_line)
elif _match:
if _state != _match.group(2):
_str = "%s=%s\n" % (_protocol, _state)
write_to_file.write(_str)
else:
write_to_file.write(_line)
write_to_file.close()
def main():
module = AnsibleModule(
argument_spec=dict(
name=dict(type='str',
choices=['ospfd', 'ospf6d', 'bgpd'],
required=True),
state=dict(type='str',
choices=['present', 'absent'],
required=True),
activate=dict(type='bool', choices=BOOLEANS, default=False)
))
module.quagga_daemon_file = '/etc/quagga/daemons'
setting_is_configured(module)
modify_config(module)
_protocol = module.params.get('name')
_state = module.params.get('state')
_state = convert_to_yes_or_no(_state)
_msg = "%s protocol setting modified to %s" % \
(_protocol, _state)
if module.params.get('activate') is True:
run_cl_cmd(module, '/usr/sbin/service quagga restart')
_msg += '. Restarted Quagga Service'
module.exit_json(msg=_msg, changed=True)
# import module snippets
from ansible.module_utils.basic import *
# incompatible with ansible 1.4.4 - ubuntu 12.04 version
# from ansible.module_utils.urls import *
import re
if __name__ == '__main__':
main()