Server IP : 85.214.239.14 / Your IP : 3.145.191.85 Web Server : Apache/2.4.62 (Debian) System : Linux h2886529.stratoserver.net 4.9.0 #1 SMP Tue Jan 9 19:45:01 MSK 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.18 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, MySQL : OFF | cURL : OFF | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /usr/lib/python3/dist-packages/ansible_collections/cisco/nxos/plugins/modules/ |
Upload File : |
#!/usr/bin/python # -*- coding: utf-8 -*- from __future__ import absolute_import, division, print_function __metaclass__ = type # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) DOCUMENTATION = """ module: nxos_pim_interface extends_documentation_fragment: - cisco.nxos.nxos short_description: Manages PIM interface configuration. description: - Manages PIM interface configuration settings. version_added: 1.0.0 author: - Jason Edelman (@jedelman8) notes: - Tested against NXOSv 7.3.(0)D1(1) on VIRL - Unsupported for Cisco MDS - When C(state=default), supported params will be reset to a default state. These include C(dr_prio), C(hello_auth_key), C(hello_interval), C(jp_policy_out), C(jp_policy_in), C(jp_type_in), C(jp_type_out), C(border), C(neighbor_policy), C(neighbor_type). - The C(hello_auth_key) param is not idempotent. - C(hello_auth_key) only supports clear text passwords. - When C(state=absent), pim interface configuration will be set to defaults and pim-sm will be disabled on the interface. - PIM must be enabled on the device to use this module. - This module is for Layer 3 interfaces. options: interface: description: - Full name of the interface such as Ethernet1/33. type: str required: true sparse: description: - Enable/disable sparse-mode on the interface. type: bool default: false bfd: description: - Enables BFD for PIM at the interface level. This overrides the bfd variable set at the pim global level. - Valid values are 'enable', 'disable' or 'default'. - "Dependency: ''feature bfd''" type: str choices: - enable - disable - default dr_prio: description: - Configures priority for PIM DR election on interface. type: str hello_auth_key: description: - Authentication for hellos on this interface. type: str hello_interval: description: - Hello interval in milliseconds or seconds for this interface. - Use the option I(hello_interval_ms) to specify if the given value is in milliseconds or seconds. The default is seconds. type: int hello_interval_ms: description: - Specifies that the hello_interval is in milliseconds. - When set to True, this indicates that the user is providing the hello_interval in milliseconds and hence, no conversion is required. type: bool version_added: 2.0.0 jp_policy_out: description: - Policy for join-prune messages (outbound). type: str jp_policy_in: description: - Policy for join-prune messages (inbound). type: str jp_type_out: description: - Type of policy mapped to C(jp_policy_out). type: str choices: - prefix - routemap jp_type_in: description: - Type of policy mapped to C(jp_policy_in). type: str choices: - prefix - routemap border: description: - Configures interface to be a boundary of a PIM domain. type: bool default: false neighbor_policy: description: - Configures a neighbor policy for filtering adjacencies. type: str neighbor_type: description: - Type of policy mapped to neighbor_policy. type: str choices: - prefix - routemap state: description: - Manages desired state of the resource. type: str choices: - present - absent - default default: present """ EXAMPLES = """ - name: Ensure PIM is not running on the interface cisco.nxos.nxos_pim_interface: interface: eth1/33 state: absent - name: Ensure the interface has pim-sm enabled with the appropriate priority and hello interval cisco.nxos.nxos_pim_interface: interface: eth1/33 dr_prio: 10 hello_interval: 40 state: present - name: Ensure join-prune policies exist cisco.nxos.nxos_pim_interface: interface: eth1/33 jp_policy_in: JPIN jp_policy_out: JPOUT jp_type_in: routemap jp_type_out: routemap - name: disable bfd on the interface cisco.nxos.nxos_pim_interface: interface: eth1/33 bfd: disable - name: Ensure defaults are in place cisco.nxos.nxos_pim_interface: interface: eth1/33 state: default """ RETURN = r""" commands: description: command sent to the device returned: always type: list sample: ["interface eth1/33", "ip pim neighbor-policy test", "ip pim bfd-instance disable", "ip pim neighbor-policy test" ] """ import re from ansible.module_utils.basic import AnsibleModule from ansible_collections.cisco.nxos.plugins.module_utils.network.nxos.nxos import ( get_config, get_interface_type, load_config, run_commands, ) PARAM_TO_COMMAND_KEYMAP = { "interface": "", "bfd": "ip pim bfd-instance", "sparse": "ip pim sparse-mode", "dr_prio": "ip pim dr-priority {0}", "hello_interval": "ip pim hello-interval {0}", "hello_auth_key": "ip pim hello-authentication ah-md5 {0}", "border": "ip pim border", "jp_policy_out": "ip pim jp-policy prefix-list {0} out", "jp_policy_in": "ip pim jp-policy prefix-list {0} in", "jp_type_in": "", "jp_type_out": "", "neighbor_policy": "ip pim neighbor-policy prefix-list {0}", "neighbor_type": "", } PARAM_TO_DEFAULT_KEYMAP = { "bfd": "default", "dr_prio": "1", "hello_interval": "30000", "sparse": False, "border": False, "hello_auth_key": False, } BFD_KEYMAP = { None: None, "default": "no ip pim bfd-instance", "disable": "ip pim bfd-instance disable", "enable": "ip pim bfd-instance", } def execute_show_command(command, module, text=False): if text: cmds = [{"command": command, "output": "text"}] else: cmds = [{"command": command, "output": "json"}] return run_commands(module, cmds) def flatten_list(command_lists): flat_command_list = [] for command in command_lists: if isinstance(command, list): flat_command_list.extend(command) else: flat_command_list.append(command) return flat_command_list def local_existing(gexisting): jp_bidir = False isauth = False if gexisting: jp_bidir = gexisting.get("jp_bidir") isauth = gexisting.get("isauth") if jp_bidir and isauth: gexisting.pop("jp_bidir") gexisting.pop("isauth") return gexisting, jp_bidir, isauth def get_interface_mode(interface, intf_type, module): mode = "unknown" command = "show interface {0}".format(interface) body = execute_show_command(command, module) try: interface_table = body[0]["TABLE_interface"]["ROW_interface"] except (KeyError, AttributeError, IndexError): return mode if intf_type in ["ethernet", "portchannel"]: mode = str(interface_table.get("eth_mode", "layer3")) if mode in ["access", "trunk"]: mode = "layer2" elif mode == "routed": mode = "layer3" elif intf_type in ["loopback", "svi"]: mode = "layer3" return mode def get_pim_interface(module, interface): pim_interface = {} body = get_config(module, flags=["interface {0}".format(interface)]) pim_interface["bfd"] = "default" pim_interface["neighbor_type"] = None pim_interface["neighbor_policy"] = None pim_interface["jp_policy_in"] = None pim_interface["jp_policy_out"] = None pim_interface["jp_type_in"] = None pim_interface["jp_type_out"] = None pim_interface["jp_bidir"] = False pim_interface["isauth"] = False if body: all_lines = body.splitlines() for each in all_lines: if "jp-policy" in each: policy_name = re.search( r"ip pim jp-policy(?: prefix-list)? (\S+)(?: \S+)?", each, ).group(1) if "prefix-list" in each: ptype = "prefix" else: ptype = "routemap" if "out" in each: pim_interface["jp_policy_out"] = policy_name pim_interface["jp_type_out"] = ptype elif "in" in each: pim_interface["jp_policy_in"] = policy_name pim_interface["jp_type_in"] = ptype else: pim_interface["jp_policy_in"] = policy_name pim_interface["jp_policy_out"] = policy_name pim_interface["jp_bidir"] = True elif "neighbor-policy" in each: pim_interface["neighbor_policy"] = re.search( r"ip pim neighbor-policy(?: prefix-list)? (\S+)", each, ).group(1) if "prefix-list" in each: pim_interface["neighbor_type"] = "prefix" else: pim_interface["neighbor_type"] = "routemap" elif "ah-md5" in each: pim_interface["isauth"] = True elif "sparse-mode" in each: pim_interface["sparse"] = True elif "bfd-instance" in each: m = re.search(r"ip pim bfd-instance(?P<disable> disable)?", each) if m: pim_interface["bfd"] = "disable" if m.group("disable") else "enable" elif "border" in each: pim_interface["border"] = True elif "hello-interval" in each: pim_interface["hello_interval"] = re.search( r"ip pim hello-interval (\d+)", body, ).group(1) elif "dr-priority" in each: pim_interface["dr_prio"] = re.search(r"ip pim dr-priority (\d+)", body).group(1) return pim_interface def fix_delta(delta, existing): for key in list(delta): if key in ["dr_prio", "hello_interval", "sparse", "border"]: if delta.get(key) == PARAM_TO_DEFAULT_KEYMAP.get(key) and existing.get(key) is None: delta.pop(key) return delta def config_pim_interface(delta, existing, jp_bidir, isauth): command = None commands = [] delta = fix_delta(delta, existing) if jp_bidir: if delta.get("jp_policy_in") or delta.get("jp_policy_out"): if existing.get("jp_type_in") == "prefix": command = "no ip pim jp-policy prefix-list {0}".format(existing.get("jp_policy_in")) else: command = "no ip pim jp-policy {0}".format(existing.get("jp_policy_in")) if command: commands.append(command) for k, v in delta.items(): if k in [ "bfd", "dr_prio", "hello_interval", "hello_auth_key", "border", "sparse", ]: if k == "bfd": command = BFD_KEYMAP[v] elif v: command = PARAM_TO_COMMAND_KEYMAP.get(k).format(v) elif k == "hello_auth_key": if isauth: command = "no ip pim hello-authentication ah-md5" else: command = "no " + PARAM_TO_COMMAND_KEYMAP.get(k).format(v) if command: commands.append(command) elif k in [ "neighbor_policy", "jp_policy_in", "jp_policy_out", "neighbor_type", ]: if k in ["neighbor_policy", "neighbor_type"]: temp = delta.get("neighbor_policy") or existing.get("neighbor_policy") if delta.get("neighbor_type") == "prefix": command = PARAM_TO_COMMAND_KEYMAP.get(k).format(temp) elif delta.get("neighbor_type") == "routemap": command = "ip pim neighbor-policy {0}".format(temp) elif existing.get("neighbor_type") == "prefix": command = PARAM_TO_COMMAND_KEYMAP.get(k).format(temp) elif existing.get("neighbor_type") == "routemap": command = "ip pim neighbor-policy {0}".format(temp) elif k in ["jp_policy_in", "jp_type_in"]: temp = delta.get("jp_policy_in") or existing.get("jp_policy_in") if delta.get("jp_type_in") == "prefix": command = PARAM_TO_COMMAND_KEYMAP.get(k).format(temp) elif delta.get("jp_type_in") == "routemap": command = "ip pim jp-policy {0} in".format(temp) elif existing.get("jp_type_in") == "prefix": command = PARAM_TO_COMMAND_KEYMAP.get(k).format(temp) elif existing.get("jp_type_in") == "routemap": command = "ip pim jp-policy {0} in".format(temp) elif k in ["jp_policy_out", "jp_type_out"]: temp = delta.get("jp_policy_out") or existing.get("jp_policy_out") if delta.get("jp_type_out") == "prefix": command = PARAM_TO_COMMAND_KEYMAP.get(k).format(temp) elif delta.get("jp_type_out") == "routemap": command = "ip pim jp-policy {0} out".format(temp) elif existing.get("jp_type_out") == "prefix": command = PARAM_TO_COMMAND_KEYMAP.get(k).format(temp) elif existing.get("jp_type_out") == "routemap": command = "ip pim jp-policy {0} out".format(temp) if command: commands.append(command) command = None if "no ip pim sparse-mode" in commands: # sparse is long-running on some platforms, process it last commands.remove("no ip pim sparse-mode") commands.append("no ip pim sparse-mode") return commands def get_pim_interface_defaults(): args = dict( dr_prio=PARAM_TO_DEFAULT_KEYMAP.get("dr_prio"), bfd=PARAM_TO_DEFAULT_KEYMAP.get("bfd"), border=PARAM_TO_DEFAULT_KEYMAP.get("border"), sparse=PARAM_TO_DEFAULT_KEYMAP.get("sparse"), hello_interval=PARAM_TO_DEFAULT_KEYMAP.get("hello_interval"), hello_auth_key=PARAM_TO_DEFAULT_KEYMAP.get("hello_auth_key"), ) default = dict((param, value) for (param, value) in args.items() if value is not None) return default def default_pim_interface_policies(existing, jp_bidir): commands = [] if jp_bidir: if existing.get("jp_policy_in") or existing.get("jp_policy_out"): if existing.get("jp_type_in") == "prefix": command = "no ip pim jp-policy prefix-list {0}".format(existing.get("jp_policy_in")) if command: commands.append(command) elif not jp_bidir: command = None for k in existing: if k == "jp_policy_in": if existing.get("jp_policy_in"): if existing.get("jp_type_in") == "prefix": command = "no ip pim jp-policy prefix-list {0} in".format( existing.get("jp_policy_in"), ) else: command = "no ip pim jp-policy {0} in".format(existing.get("jp_policy_in")) elif k == "jp_policy_out": if existing.get("jp_policy_out"): if existing.get("jp_type_out") == "prefix": command = "no ip pim jp-policy prefix-list {0} out".format( existing.get("jp_policy_out"), ) else: command = "no ip pim jp-policy {0} out".format( existing.get("jp_policy_out"), ) if command: commands.append(command) command = None if existing.get("neighbor_policy"): command = "no ip pim neighbor-policy" commands.append(command) return commands def config_pim_interface_defaults(existing, jp_bidir, isauth): command = [] # returns a dict defaults = get_pim_interface_defaults() delta = dict(set(defaults.items()).difference(existing.items())) if delta: # returns a list command = config_pim_interface(delta, existing, jp_bidir, isauth) comm = default_pim_interface_policies(existing, jp_bidir) if comm: for each in comm: command.append(each) return command def normalize_proposed_values(proposed, module): keys = proposed.keys() if "bfd" in keys: # bfd is a tri-state string: enable, disable, default proposed["bfd"] = proposed["bfd"].lower() if "hello_interval" in keys: hello_interval = proposed["hello_interval"] if not module.params["hello_interval_ms"]: hello_interval = hello_interval * 1000 proposed["hello_interval"] = str(hello_interval) def main(): argument_spec = dict( interface=dict(type="str", required=True), sparse=dict(type="bool", default=False), dr_prio=dict(type="str"), hello_auth_key=dict(type="str", no_log=True), hello_interval=dict(type="int"), hello_interval_ms=dict(type="bool"), jp_policy_out=dict(type="str"), jp_policy_in=dict(type="str"), jp_type_out=dict(type="str", choices=["prefix", "routemap"]), jp_type_in=dict(type="str", choices=["prefix", "routemap"]), bfd=dict(type="str", choices=["enable", "disable", "default"]), border=dict(type="bool", default=False), neighbor_policy=dict(type="str"), neighbor_type=dict(type="str", choices=["prefix", "routemap"]), state=dict( type="str", default="present", choices=["absent", "default", "present"], ), ) required_by = {"hello_interval_ms": "hello_interval"} module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, required_by=required_by, ) warnings = list() results = {"changed": False, "commands": [], "warnings": warnings} state = module.params["state"] interface = module.params["interface"] jp_type_in = module.params["jp_type_in"] jp_type_out = module.params["jp_type_out"] jp_policy_in = module.params["jp_policy_in"] jp_policy_out = module.params["jp_policy_out"] neighbor_policy = module.params["neighbor_policy"] neighbor_type = module.params["neighbor_type"] intf_type = get_interface_type(interface) if get_interface_mode(interface, intf_type, module) == "layer2": module.fail_json(msg="this module only works on Layer 3 interfaces.") if jp_policy_in: if not jp_type_in: module.fail_json(msg="jp_type_in required when using jp_policy_in.") if jp_policy_out: if not jp_type_out: module.fail_json(msg="jp_type_out required when using jp_policy_out.") if neighbor_policy: if not neighbor_type: module.fail_json(msg="neighbor_type required when using neighbor_policy.") get_existing = get_pim_interface(module, interface) existing, jp_bidir, isauth = local_existing(get_existing) args = PARAM_TO_COMMAND_KEYMAP.keys() proposed = dict((k, v) for k, v in module.params.items() if v is not None and k in args) normalize_proposed_values(proposed, module) delta = dict(set(proposed.items()).difference(existing.items())) commands = [] if state == "present": if delta: command = config_pim_interface(delta, existing, jp_bidir, isauth) if command: commands.append(command) elif state == "default" or state == "absent": defaults = config_pim_interface_defaults(existing, jp_bidir, isauth) if defaults: commands.append(defaults) if commands: commands.insert(0, ["interface {0}".format(interface)]) cmds = flatten_list(commands) if cmds: results["changed"] = True if not module.check_mode: load_config(module, cmds) if "configure" in cmds: cmds.pop(0) results["commands"] = cmds module.exit_json(**results) if __name__ == "__main__": main()