From dc8b3e94ad0c5c2fb04ec63c159df3e4b9dfff43 Mon Sep 17 00:00:00 2001 From: anasbadaha <43231942+anasbadaha@users.noreply.github.com> Date: Thu, 1 Nov 2018 10:55:25 +0200 Subject: [PATCH] Adding IGMP vlan module for onyx switches (#47811) Signed-off-by: Anas Badaha --- .../modules/network/onyx/onyx_igmp_vlan.py | 436 ++++++++++++++++++ .../fixtures/onyx_show_ip_igmp_snooping.cfg | 10 + .../onyx_show_ip_igmp_snooping_groups.cfg | 30 ++ .../onyx_show_ip_igmp_snooping_querier.cfg | 20 + .../network/onyx/test_onyx_igmp_vlan.py | 190 ++++++++ 5 files changed, 686 insertions(+) create mode 100644 lib/ansible/modules/network/onyx/onyx_igmp_vlan.py create mode 100644 test/units/modules/network/onyx/fixtures/onyx_show_ip_igmp_snooping.cfg create mode 100644 test/units/modules/network/onyx/fixtures/onyx_show_ip_igmp_snooping_groups.cfg create mode 100644 test/units/modules/network/onyx/fixtures/onyx_show_ip_igmp_snooping_querier.cfg create mode 100644 test/units/modules/network/onyx/test_onyx_igmp_vlan.py diff --git a/lib/ansible/modules/network/onyx/onyx_igmp_vlan.py b/lib/ansible/modules/network/onyx/onyx_igmp_vlan.py new file mode 100644 index 00000000000..5ab9a166c5c --- /dev/null +++ b/lib/ansible/modules/network/onyx/onyx_igmp_vlan.py @@ -0,0 +1,436 @@ +#!/usr/bin/python +# +# Copyright: Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + +DOCUMENTATION = """ +--- +module: onyx_igmp_vlan +version_added: '2.8' +author: 'Anas Badaha(@anasb)' +short_description: Configures IGMP Vlan parameters +description: + - This module provides declarative management of IGMP vlan configuration on Mellanox ONYX network devices. +notes: + - Tested on ONYX 3.7.0932-01 +options: + vlan_id: + description: + - VLAN ID, vlan should exist. + required: true + state: + description: + - IGMP state. + choices: ['enabled', 'disabled'] + default: enabled + mrouter: + description: + - Configure ip igmp snooping mrouter port on vlan + suboptions: + state: + description: + - Enable IGMP snooping mrouter on vlan interface. + choices: ['enabled', 'disabled'] + default: enabled + name: + description: + - Configure mrouter interface + required: true + querier: + description: + - Configure the IGMP querier parameters + suboptions: + state: + description: + - Enable IGMP snooping querier on vlan in the switch. + choices: ['enabled', 'disabled'] + default: enabled + interval: + description: + - Update time interval between querier queries, range 60-600 + address: + description: + - Update IP address for the querier + static_groups: + description: + - List of IGMP static groups. + suboptions: + multicast_ip_address: + description: + - Configure static IP multicast group, range 224.0.1.0-239.255.255.25. + required: true + name: + description: + - interface name to configure static groups on it. + sources: + description: + - List of IP sources to be configured + version: + description: + - IGMP snooping operation version on this vlan + choices: ['V2','V3'] +""" + +EXAMPLES = """ +- name: configure igmp vlan + onyx_igmp_vlan: + state: enabled + vlan_id: 10 + version: + V2 + querier: + state: enabled + interval: 70 + address: 10.11.121.13 + mrouter: + state: disabled + name: Eth1/2 + static_groups: + - multicast_ip_address: 224.5.5.8 + name: Eth1/1 + sources: + - 1.1.1.1 + - 1.1.1.2 +""" + +RETURN = """ +commands: + description: The list of configuration mode commands to send to the device. + returned: always + type: list + sample: + - vlan 10 ip igmp snooping + - vlan 10 ip igmp snooping static-group 224.5.5.5 interface ethernet 1/1 +""" +import socket +import struct + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.network.onyx.onyx import show_cmd +from ansible.module_utils.network.onyx.onyx import BaseOnyxModule + + +def _ip_to_int(addr): + return struct.unpack("!I", socket.inet_aton(addr))[0] + + +class OnyxIgmpVlanModule(BaseOnyxModule): + MIN_MULTICAST_IP = _ip_to_int("224.0.1.0") + MAX_MULTICAST_IP = _ip_to_int("239.255.255.255") + + def init_module(self): + """ initialize module + """ + mrouter_spec = dict(name=dict(required=True), + state=dict(choices=['enabled', 'disabled'], default='enabled')) + querier_spec = dict(state=dict(choices=['enabled', 'disabled'], default='enabled'), + interval=dict(type='int'), address=dict()) + static_groups_spec = dict(multicast_ip_address=dict(required=True), + name=dict(required=True), sources=dict(type='list')) + element_spec = dict(vlan_id=dict(type='int', required=True), + state=dict(choices=['enabled', 'disabled'], default='enabled'), + querier=dict(type='dict', options=querier_spec), + static_groups=dict(type='list', elements='dict', options=static_groups_spec), + mrouter=dict(type='dict', options=mrouter_spec), + version=dict(choices=['V2', 'V3'])) + argument_spec = dict() + argument_spec.update(element_spec) + self._module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True) + + def get_required_config(self): + module_params = self._module.params + self._required_config = dict(module_params) + self.validate_param_values(self._required_config) + + def _validate_attr_is_not_none(self, attr_name, attr_value): + if attr_name == 'vlan_id' or attr_name == 'state': + pass + elif attr_value is not None: + self._module.fail_json(msg='Can not set %s value on switch while state is disabled' % attr_name) + + def validate_param_values(self, obj, param=None): + if obj['state'] == 'disabled': + for attr_name in obj: + self._validate_attr_is_not_none(attr_name, obj[attr_name]) + super(OnyxIgmpVlanModule, self).validate_param_values(obj, param) + + def validate_querier(self, value): + interval = value.get('interval') + if interval and not 60 <= int(interval) <= 600: + self._module.fail_json(msg='query-interval value must be between 60 and 600') + + def validate_static_groups(self, value): + multicast_ip = value.get('multicast_ip_address') + multicast_ip = _ip_to_int(multicast_ip) + + if multicast_ip < self.MIN_MULTICAST_IP or multicast_ip > self.MAX_MULTICAST_IP: + self._module.fail_json(msg='multicast IP address must be in range 224.0.1.0 - 239.255.255.255') + + @staticmethod + def _get_curr_mrouter_config(mrouter_port): + if mrouter_port == "none": + return {'state': 'disabled'} + else: + return {'state': 'enabled', + 'name': mrouter_port} + + def _get_curr_querier_config(self, querier_config): + if "Non-Querier" in querier_config: + return {'state': 'disabled'} + elif "Querier" in querier_config: + igmp_querier_config = self._show_igmp_querier_config()[0] + snooping_querier_info = igmp_querier_config["Snooping querier information for VLAN %d" % ( + self._required_config['vlan_id'])] + snooping_querier_info = snooping_querier_info[1] + interval = int(snooping_querier_info["Query interval"]) + address = snooping_querier_info["Configured querier IP address"] + return {'state': 'enabled', + 'interval': interval, + 'address': address} + + @staticmethod + def _get_curr_version(version): + if "V3" in version: + return "V3" + elif "V2" in version: + return "V2" + + def _get_curr_static_group_config(self, multicast_ip_address): + sources = None + names = None + igmp_snooping_groups_config = self._show_igmp_snooping_groups_config(multicast_ip_address) + if igmp_snooping_groups_config is not None: + igmp_snooping_groups_config = igmp_snooping_groups_config[0] + snooping_group_information = igmp_snooping_groups_config.get('Snooping group ' + 'information for VLAN %d and group ' + '%s' % (self._required_config['vlan_id'], + multicast_ip_address)) + if snooping_group_information is not None: + if len(snooping_group_information) == 1: + names = snooping_group_information[0].get('V1/V2 Receiver Ports') + elif len(snooping_group_information) == 2: + sources_dict = dict() + v3_receiver_ports = snooping_group_information[1].get('V3 Receiver Ports') + ports_number = v3_receiver_ports[0].get('Port Number') + sources = v3_receiver_ports[0].get('Include sources') + if isinstance(ports_number, list): + i = 0 + for port_number in ports_number: + sources_dict[port_number] = sources[i] + i += 1 + else: + sources_dict[ports_number] = sources + names = snooping_group_information[0].get('V1/V2 Receiver Ports') + sources = sources_dict + + return {'sources': sources, + 'names': names} + else: + return None + else: + return None + + def _set_igmp_config(self, igmp_vlan_config): + igmp_vlan_config = igmp_vlan_config[0] + if not igmp_vlan_config: + return + + self._current_config['state'] = igmp_vlan_config.get('message 1') + if "enabled" in self._current_config['state']: + self._current_config['state'] = "enabled" + elif "disabled" in self._current_config['state']: + self._current_config['state'] = "disabled" + + mrouter_port = igmp_vlan_config.get('mrouter static port list') + self._current_config['mrouter'] = dict(self._get_curr_mrouter_config(mrouter_port)) + + querier_config = igmp_vlan_config.get('message 3') + self._current_config['querier'] = dict(self._get_curr_querier_config(querier_config)) + + version = igmp_vlan_config.get('message 2') + self._current_config['version'] = self._get_curr_version(version) + + req_static_groups = self._required_config.get('static_groups') + if req_static_groups is not None: + static_groups = self._current_config['static_groups'] = dict() + for static_group in req_static_groups: + static_group_config = self._get_curr_static_group_config(static_group['multicast_ip_address']) + static_groups[static_group['multicast_ip_address']] = static_group_config + + def _show_igmp_vlan(self): + cmd = ("show ip igmp snooping vlan %d" % self._required_config['vlan_id']) + return show_cmd(self._module, cmd, json_fmt=True, fail_on_error=False) + + def _show_igmp_querier_config(self): + cmd = ("show ip igmp snooping querier vlan %d " % self._required_config['vlan_id']) + return show_cmd(self._module, cmd, json_fmt=True, fail_on_error=False) + + def _show_igmp_snooping_groups_config(self, multicast_ip_address): + cmd = ("show ip igmp snooping groups vlan %d group %s" % (self._required_config['vlan_id'], + multicast_ip_address)) + return show_cmd(self._module, cmd, json_fmt=True, fail_on_error=False) + + def load_current_config(self): + self._current_config = dict() + igmp_vlan_config = self._show_igmp_vlan() + if igmp_vlan_config: + self._set_igmp_config(igmp_vlan_config) + + def generate_commands(self): + req_state = self._required_config.get('state', 'enabled') + self._generate_igmp_vlan_cmds(req_state) + + _mrouter = self._required_config.get('mrouter') + if _mrouter is not None: + self._generate_igmp_mrouter_cmds(_mrouter) + + _querier = self._required_config.get('querier') + if _querier is not None: + req_querier_state = _querier.get('state', 'enabled') + self._generate_igmp_querier_cmds(req_querier_state) + + req_querier_interval = _querier.get('interval') + if req_querier_interval is not None: + self._gen_querier_attr_commands("interval", req_querier_interval, "query-interval") + + req_querier_address = _querier.get('address') + if req_querier_address is not None: + self._gen_querier_attr_commands("address", req_querier_address, "address") + + _version = self._required_config.get('version') + if _version is not None: + self._generate_igmp_version_cmds(_version) + + _static_groups = self._required_config.get('static_groups') + if _static_groups is not None: + for static_group in _static_groups: + self._generate_igmp_static_groups_cmd(static_group) + + def _add_igmp_vlan_commands(self, req_state): + if req_state == 'enabled': + igmp_vlan_cmd = 'vlan %d ip igmp snooping' % self._required_config['vlan_id'] + else: + igmp_vlan_cmd = 'vlan %d no ip igmp snooping' % self._required_config['vlan_id'] + + self._commands.append(igmp_vlan_cmd) + + def _generate_igmp_vlan_cmds(self, req_state): + curr_state = self._current_config.get('state') + if curr_state != req_state: + self._add_igmp_vlan_commands(req_state) + + def _gen_querier_attr_commands(self, attr_name, req_attr_value, attr_cmd_name): + _curr_querier = self._current_config.get('querier') + curr_querier_val = _curr_querier.get(attr_name) + if req_attr_value != curr_querier_val: + self._commands.append('vlan %d ip igmp snooping querier %s %s' % (self._required_config['vlan_id'], + attr_cmd_name, req_attr_value)) + + def _add_querier_commands(self, req_querier_state): + if req_querier_state == 'enabled': + self._commands.append('vlan %d ip igmp snooping querier' % self._required_config['vlan_id']) + elif req_querier_state == 'disabled': + self._commands.append('vlan %d no ip igmp snooping querier' % ( + self._required_config['vlan_id'])) + + def _generate_igmp_querier_cmds(self, req_querier_state): + _curr_querier = self._current_config.get('querier') + curr_querier_state = _curr_querier.get('state') + if req_querier_state != curr_querier_state: + self._add_querier_commands(req_querier_state) + + def _generate_igmp_version_cmds(self, version): + _curr_version = self._current_config.get('version') + if version != _curr_version: + self._commands.append('vlan %d ip igmp snooping version %s' % ( + self._required_config['vlan_id'], version[1])) + + def _add_mrouter_commands(self, req_mrouter, curr_mrouter): + curr_state = curr_mrouter.get('state') + curr_interface = curr_mrouter.get('name') + req_state = req_mrouter.get('state') + req_interface = req_mrouter.get('name') + mrouter_interface = req_interface.replace("Eth", "ethernet ") + if curr_state == 'enabled' and req_state == 'disabled': + self._commands.append('vlan %d no ip igmp snooping mrouter interface ' + '%s' % (self._required_config['vlan_id'], mrouter_interface)) + elif curr_state == 'disabled' and req_state == 'enabled': + self._commands.append('vlan %d ip igmp snooping mrouter interface ' + '%s' % (self._required_config['vlan_id'], mrouter_interface)) + elif req_state == 'enabled' and curr_state == 'enabled' and req_interface != curr_interface: + self._commands.append('vlan %d ip igmp snooping mrouter interface ' + '%s' % (self._required_config['vlan_id'], mrouter_interface)) + + def _generate_igmp_mrouter_cmds(self, req_mrouter): + curr_mrouter = self._current_config.get('mrouter') + if curr_mrouter != req_mrouter: + self._add_mrouter_commands(req_mrouter, curr_mrouter) + + def _add_igmp_static_groups_cmd(self, req_name, req_multicast_ip_address, curr_names): + if curr_names is None: + self._commands.append('vlan %d ip igmp snooping static-group %s interface %s' % ( + self._required_config['vlan_id'], req_multicast_ip_address, req_name.replace('Eth', 'ethernet '))) + elif req_name.replace('E', 'e') not in curr_names: + self._commands.append('vlan %d ip igmp snooping static-group %s interface %s' % ( + self._required_config['vlan_id'], req_multicast_ip_address, req_name.replace('Eth', 'ethernet '))) + + def _add_igmp_static_groups_sources_cmd(self, req_sources, req_name, req_multicast_ip_address, curr_sources): + if curr_sources is None: + for source in req_sources: + self._commands.append('vlan %d ip igmp snooping static-group %s interface %s source %s' % ( + self._required_config['vlan_id'], req_multicast_ip_address, req_name.replace('Eth', 'ethernet '), + source)) + else: + curr_sources = curr_sources.get(req_name.replace('E', 'e')) + if curr_sources is None: + curr_sources = set([]) + else: + curr_sources = set(x.strip() for x in curr_sources.split(',')) + sources_to_add = set(req_sources) - set(curr_sources) + sources_to_remove = set(curr_sources) - set(req_sources) + if len(sources_to_add) != 0: + for source in sources_to_add: + self._commands.append('vlan %d ip igmp snooping static-group %s interface %s source %s' % ( + self._required_config['vlan_id'], req_multicast_ip_address, + req_name.replace('Eth', 'ethernet '), source)) + if len(sources_to_remove) != 0: + for source in sources_to_remove: + self._commands.append('vlan %d no ip igmp snooping static-group %s interface %s source %s' % ( + self._required_config['vlan_id'], req_multicast_ip_address, + req_name.replace('Eth', 'ethernet '), + source)) + + def _generate_igmp_static_groups_cmd(self, static_group): + req_multicast_ip_address = static_group.get('multicast_ip_address') + req_name = static_group.get('name') + req_sources = static_group.get('sources') + curr_static_groups = self._current_config.get('static_groups') + curr_static_group = curr_static_groups.get(req_multicast_ip_address) + curr_names = None + curr_sources = None + if curr_static_group is not None: + curr_names = curr_static_group.get('names') + curr_sources = curr_static_group.get('sources') + + self._add_igmp_static_groups_cmd(req_name, req_multicast_ip_address, curr_names) + if req_sources is not None: + self._add_igmp_static_groups_sources_cmd(req_sources, req_name, req_multicast_ip_address, curr_sources) + + +def main(): + """ main entry point for module execution + """ + OnyxIgmpVlanModule.main() + + +if __name__ == '__main__': + main() diff --git a/test/units/modules/network/onyx/fixtures/onyx_show_ip_igmp_snooping.cfg b/test/units/modules/network/onyx/fixtures/onyx_show_ip_igmp_snooping.cfg new file mode 100644 index 00000000000..975b6723008 --- /dev/null +++ b/test/units/modules/network/onyx/fixtures/onyx_show_ip_igmp_snooping.cfg @@ -0,0 +1,10 @@ +[ + { + "mrouter static port list": "none", + "mrouter dynamic port list": "none", + "header": "Vlan 10 configuration parameters", + "message 1": "IGMP snooping is disabled", + "message 2": "IGMP version is V3", + "message 3": "Snooping switch is acting as Non-Querier" + } +] diff --git a/test/units/modules/network/onyx/fixtures/onyx_show_ip_igmp_snooping_groups.cfg b/test/units/modules/network/onyx/fixtures/onyx_show_ip_igmp_snooping_groups.cfg new file mode 100644 index 00000000000..3d84667b2e8 --- /dev/null +++ b/test/units/modules/network/onyx/fixtures/onyx_show_ip_igmp_snooping_groups.cfg @@ -0,0 +1,30 @@ +[ + { + "Snooping group information for VLAN 10 and group 224.5.5.1": [ + { + "Group flag": "St", + "Filter Mode": "EXCLUDE", + "V1/V2 Receiver Ports": "eth1/1, eth1/2", + "Exclude sources": "None" + }, + { + "V3 Receiver Ports": [ + { + "Exclude sources": [ + "None", + "None" + ], + "Include sources": [ + "1.1.1.1, 1.1.1.2", + "1.1.1.3" + ], + "Port Number": [ + "eth1/1", + "eth1/2" + ] + } + ] + } + ] + } +] \ No newline at end of file diff --git a/test/units/modules/network/onyx/fixtures/onyx_show_ip_igmp_snooping_querier.cfg b/test/units/modules/network/onyx/fixtures/onyx_show_ip_igmp_snooping_querier.cfg new file mode 100644 index 00000000000..b64c260d3be --- /dev/null +++ b/test/units/modules/network/onyx/fixtures/onyx_show_ip_igmp_snooping_querier.cfg @@ -0,0 +1,20 @@ +[ + { + "Snooping querier information for VLAN 10": [ + { + "Lines": [ + "IGMP Querier Not Present" + ] + }, + { + "Response interval": "100", + "Elected querier IP address": "0.0.0.0", + "Group membership interval": "1", + "Robustness": "2", + "Configured querier IP address": "-", + "Query interval": "125", + "Version": "3" + } + ] + } +] diff --git a/test/units/modules/network/onyx/test_onyx_igmp_vlan.py b/test/units/modules/network/onyx/test_onyx_igmp_vlan.py new file mode 100644 index 00000000000..1943090eaae --- /dev/null +++ b/test/units/modules/network/onyx/test_onyx_igmp_vlan.py @@ -0,0 +1,190 @@ +# +# Copyright: Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +from units.compat.mock import patch +from ansible.modules.network.onyx import onyx_igmp_vlan +from units.modules.utils import set_module_args +from .onyx_module import TestOnyxModule, load_fixture + + +class TestOnyxIgmpVlan(TestOnyxModule): + + module = onyx_igmp_vlan + enabled = False + mrouter_state = False + querier_state = False + static_groups_enabled = False + + def setUp(self): + self.enabled = False + super(TestOnyxIgmpVlan, self).setUp() + self.mock_get_igmp_config = patch.object( + onyx_igmp_vlan.OnyxIgmpVlanModule, "_show_igmp_vlan") + self.get_igmp_config = self.mock_get_igmp_config.start() + + self.mock_load_config = patch( + 'ansible.module_utils.network.onyx.onyx.load_config') + self.load_config = self.mock_load_config.start() + + self.mock_get_igmp_guerier_config = patch.object( + onyx_igmp_vlan.OnyxIgmpVlanModule, "_show_igmp_querier_config") + self.get_igmp_guerier_config = self.mock_get_igmp_guerier_config.start() + + self.mock_get_igmp_static_groups_config = patch.object( + onyx_igmp_vlan.OnyxIgmpVlanModule, "_show_igmp_snooping_groups_config") + self.get_igmp_static_groups_config = self.mock_get_igmp_static_groups_config.start() + + def tearDown(self): + super(TestOnyxIgmpVlan, self).tearDown() + self.mock_get_igmp_config.stop() + self.mock_load_config.stop() + self.mock_get_igmp_guerier_config.stop() + self.mock_get_igmp_static_groups_config.stop() + + def load_fixtures(self, commands=None, transport='cli'): + igmp_vlan_config_file = 'onyx_show_ip_igmp_snooping.cfg' + igmp_querier_config_file = 'onyx_show_ip_igmp_snooping_querier.cfg' + igmp_static_groups_file = 'onyx_show_ip_igmp_snooping_groups.cfg' + igmp_vlan_data = load_fixture(igmp_vlan_config_file) + igmp_querier_data = load_fixture(igmp_querier_config_file) + igmp_static_groups_data = None + if self.enabled: + igmp_vlan_data[0]['message 1'] = 'IGMP snooping is enabled' + + if self.querier_state: + igmp_vlan_data[0]['message 3'] = 'Snooping switch is acting as Querier' + + if self.mrouter_state: + igmp_vlan_data[0]['mrouter static port list'] = 'Eth1/1' + + if self.static_groups_enabled: + igmp_static_groups_data = load_fixture(igmp_static_groups_file) + + self.get_igmp_config.return_value = igmp_vlan_data + self.get_igmp_guerier_config = igmp_querier_data + self.get_igmp_static_groups_config = igmp_static_groups_data + self.load_config.return_value = None + + def test_igmp_disabled_no_change(self): + set_module_args(dict(state='disabled', vlan_id=10)) + self.execute_module(changed=False) + + def test_igmp_disabled_with_change(self): + self.enabled = True + set_module_args(dict(state='disabled', vlan_id=10)) + commands = ['vlan 10 no ip igmp snooping'] + self.execute_module(changed=True, commands=commands) + + def test_igmp_enabled_no_change(self): + self.enabled = True + set_module_args(dict(state='enabled', vlan_id=10)) + self.execute_module(changed=False) + + def test_igmp_enabled_with_change(self): + set_module_args(dict(state='enabled', vlan_id=10)) + commands = ['vlan 10 ip igmp snooping'] + self.execute_module(changed=True, commands=commands) + + def test_igmp_mrouter_disabled_no_change(self): + self.enabled = True + set_module_args(dict(vlan_id=10, mrouter=dict(state='disabled', name='Eth1/1'))) + self.execute_module(changed=False) + + def test_igmp_mrouter_disabled_with_change(self): + self.enabled = True + self.mrouter_state = True + set_module_args(dict(vlan_id=10, mrouter=dict(state='disabled', name='Eth1/1'))) + commands = ['vlan 10 no ip igmp snooping mrouter interface ethernet 1/1'] + self.execute_module(changed=True, commands=commands) + + def test_igmp_mrouter_enabled_no_change(self): + self.enabled = True + self.mrouter_state = True + set_module_args(dict(vlan_id=10, mrouter=dict(state='enabled', name='Eth1/1'))) + self.execute_module(changed=False) + + def test_igmp_mrouter_enabled_with_change(self): + self.enabled = True + set_module_args(dict(vlan_id=10, mrouter=dict(state='enabled', name='Eth1/1'))) + commands = ['vlan 10 ip igmp snooping mrouter interface ethernet 1/1'] + self.execute_module(changed=True, commands=commands) + + def test_igmp_mrouter_enabled_withinterface_change(self): + self.enabled = True + self.mrouter_state = True + set_module_args(dict(vlan_id=10, mrouter=dict(state='enabled', name='Eth1/2'))) + commands = ['vlan 10 ip igmp snooping mrouter interface ethernet 1/2'] + self.execute_module(changed=True, commands=commands) + + def test_igmp_querier_disabled_no_change(self): + self.enabled = True + set_module_args(dict(vlan_id=10, querier=dict(state='disabled'))) + self.execute_module(changed=False) + + def test_igmp_querier_disabled_with_change(self): + self.enabled = True + self.querier_state = True + set_module_args(dict(vlan_id=10, querier=dict(state='disabled'))) + commands = ['vlan 10 no ip igmp snooping querier'] + self.execute_module(changed=True, commands=commands) + + def test_igmp_querier_enabled_no_change(self): + self.enabled = True + self.querier_state = True + set_module_args(dict(vlan_id=10, querier=dict(state='enabled'))) + self.execute_module(changed=False) + + def test_igmp_querier_enabled_with_change(self): + self.enabled = True + set_module_args(dict(vlan_id=10, querier=dict(state='enabled'))) + commands = ['vlan 10 ip igmp snooping querier'] + self.execute_module(changed=True, commands=commands) + + def test_igmp_querier_attr_no_change(self): + self.enabled = True + self.querier_state = True + set_module_args(dict(vlan_id=10, querier=dict(state='enabled', interval=125, address='-'))) + self.execute_module(changed=True) + + def test_igmp_querier_attr_with_change(self): + self.enabled = True + self.querier_state = True + set_module_args(dict(vlan_id=10, querier=dict(state='enabled', interval=127, address='10.10.10.1'))) + commands = ['vlan 10 ip igmp snooping querier query-interval 127', + 'vlan 10 ip igmp snooping querier address 10.10.10.1'] + self.execute_module(changed=True, commands=commands) + + def test_igmp_version_no_change(self): + self.enabled = True + set_module_args(dict(vlan_id=10, version='V3')) + self.execute_module(changed=False) + + def test_igmp_version_with_change(self): + self.enabled = True + set_module_args(dict(vlan_id=10, version='V2')) + commands = ['vlan 10 ip igmp snooping version 2'] + self.execute_module(changed=True, commands=commands) + + def test_igmp_static_groups_multicast_ip_address_not_configured(self): + self.enabled = True + set_module_args(dict(vlan_id=10, static_groups=[dict(multicast_ip_address='224.5.5.2', name='Eth1/1', + sources=["1.1.1.2", "1.1.1.3"])])) + commands = ['vlan 10 ip igmp snooping static-group 224.5.5.2 interface ethernet 1/1', + 'vlan 10 ip igmp snooping static-group 224.5.5.2 interface ethernet 1/1 source 1.1.1.2', + 'vlan 10 ip igmp snooping static-group 224.5.5.2 interface ethernet 1/1 source 1.1.1.3'] + self.execute_module(changed=True, commands=commands) + + def test_igmp_static_groups_multicast_ip_address_configured_with_change(self): + self.enabled = True + self.static_groups_enabled = True + set_module_args(dict(vlan_id=10, static_groups=[dict(multicast_ip_address='224.5.5.1', name='Eth1/3', + sources=["1.1.1.1", "1.1.1.2"])])) + commands = ['vlan 10 ip igmp snooping static-group 224.5.5.1 interface ethernet 1/3', + 'vlan 10 ip igmp snooping static-group 224.5.5.1 interface ethernet 1/3 source 1.1.1.1', + 'vlan 10 ip igmp snooping static-group 224.5.5.1 interface ethernet 1/3 source 1.1.1.2'] + self.execute_module(changed=True, commands=commands)