コード例 #1
0
    def get_bfd_interfaces_facts(self):
        """ Get the 'facts' (the current configuration)

        :returns: A list of interface configs and a platform string
        """
        facts, _warnings = Facts(self._module).get_facts(self.gather_subset, self.gather_network_resources)
        bfd_interfaces_facts = facts['ansible_network_resources'].get('bfd_interfaces', [])
        platform = facts.get('ansible_net_platform', '')
        return bfd_interfaces_facts, platform
コード例 #2
0
    def get_interfaces_facts(self, data=None):
        """ Get the 'facts' (the current configuration)

        :data: Mocked running-config data for state `parsed`
        :rtype: A dictionary
        :returns: The current configuration as a dictionary
        """
        self.facts, _warnings = Facts(self._module).get_facts(
            self.gather_subset, self.gather_network_resources, data=data)
        interfaces_facts = self.facts["ansible_network_resources"].get(
            "interfaces")

        return interfaces_facts
コード例 #3
0
ファイル: nxos_facts.py プロジェクト: cidrblock/cisco.nxos
def main():
    """
    Main entry point for module execution

    :returns: ansible_facts
    """
    argument_spec = FactsArgs.argument_spec
    argument_spec.update(nxos_argument_spec)

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True)

    warnings = []
    if module.params["gather_subset"] == "!config":
        warnings.append(
            "default value for `gather_subset` will be changed to `min` from `!config` v2.11 onwards"
        )

    ansible_facts = {}
    if module.params.get("available_network_resources"):
        ansible_facts["available_network_resources"] = sorted(
            FACT_RESOURCE_SUBSETS.keys())
    result = Facts(module).get_facts()
    additional_facts, additional_warnings = result
    ansible_facts.update(additional_facts)
    warnings.extend(additional_warnings)

    module.exit_json(ansible_facts=ansible_facts, warnings=warnings)
コード例 #4
0
    def get_bfd_interfaces_facts(self, data=None):
        """ Get the 'facts' (the current configuration)

        :returns: A list of interface configs and a platform string
        """
        if self.state not in self.ACTION_STATES:
            self.gather_subset = ["!all", "!min"]
        facts, _warnings = Facts(self._module).get_facts(
            self.gather_subset, self.gather_network_resources, data=data
        )
        bfd_interfaces_facts = facts["ansible_network_resources"].get(
            "bfd_interfaces", []
        )

        platform = facts.get("ansible_net_platform", "")
        return bfd_interfaces_facts, platform
コード例 #5
0
 def __init__(self, module):
     super(Ospfv3, self).__init__(
         empty_fact_val={},
         facts_module=Facts(module),
         module=module,
         resource="ospfv3",
         tmplt=Ospfv3Template(),
     )
     self.parsers = [
         "auto_cost",
         "flush_routes",
         "graceful_restart.set",
         "graceful_restart.helper_disable",
         "graceful_restart.grace_period",
         "graceful_restart.planned_only",
         "isolate",
         "log_adjacency_changes",
         "max_lsa",
         "max_metric",
         "name_lookup",
         "passive_interface.default",
         "router_id",
         "shutdown",
         "timers.lsa_arrival",
         "timers.lsa_group_pacing",
         "timers.throttle.lsa",
     ]
コード例 #6
0
 def __init__(self, module):
     super(Logging_global, self).__init__(
         empty_fact_val={},
         facts_module=Facts(module),
         module=module,
         resource="logging_global",
         tmplt=Logging_globalTemplate(),
     )
     self._sev_map = get_logging_sevmap(invert=True)
     self._state_set = ("replaced", "deleted", "overridden")
     self.parsers = [
         "console",
         "module",
         "monitor",
         "logfile",
         "event.link_status.enable",
         "event.link_status.default",
         "event.trunk_status.enable",
         "event.trunk_status.default",
         "history.severity",
         "history.size",
         "ip.access_list.cache.entries",
         "ip.access_list.cache.interval",
         "ip.access_list.cache.threshold",
         "ip.access_list.detailed",
         "ip.access_list.include.sgt",
         "origin_id.hostname",
         "origin_id.ip",
         "origin_id.string",
         "rate_limit",
         "rfc_strict",
         "source_interface",
         "timestamp",
     ]
コード例 #7
0
    def get_interfaces_facts(self, get_default_interfaces=False):
        """ Get the 'facts' (the current configuration)

        :get_default_interfaces: boolean - when True include a list of existing-but-default interface names in the facts dict.
          - The defaults list is primarily used to detect non-existent virtual interfaces.
        :rtype: A dictionary
        :returns: The current configuration as a dictionary
        """
        facts, _warnings = Facts(self._module).get_facts(self.gather_subset, self.gather_network_resources)
        interfaces_facts = facts['ansible_network_resources'].get('interfaces')
        interfaces_facts = remove_rsvd_interfaces(interfaces_facts)
        if get_default_interfaces:
            default_interfaces = facts['ansible_network_resources'].get('default_interfaces', [])
            interfaces_facts.append(default_interfaces)

        self.intf_defs = facts.get('intf_defs', {})
        return interfaces_facts
コード例 #8
0
    def get_l3_interfaces_facts(self, data=None):
        """ Get the 'facts' (the current configuration)

        :rtype: A dictionary
        :returns: The current configuration as a dictionary
        """
        if self.state not in self.ACTION_STATES:
            self.gather_subset = ["!all", "!min"]

        facts, _warnings = Facts(self._module).get_facts(
            self.gather_subset, self.gather_network_resources, data=data)

        l3_interfaces_facts = facts["ansible_network_resources"].get(
            "l3_interfaces")
        self.platform = facts.get("ansible_net_platform", "")

        return l3_interfaces_facts
コード例 #9
0
 def __init__(self, module):
     super(Bgp_global, self).__init__(
         empty_fact_val={},
         facts_module=Facts(module),
         module=module,
         resource="bgp_global",
         tmplt=Bgp_globalTemplate(),
     )
     # VRF parsers = 29
     self.parsers = [
         "allocate_index",
         "affinity_group.group_id",
         "bestpath.always_compare_med",
         "bestpath.as_path.ignore",
         "bestpath.as_path.multipath_relax",
         "bestpath.compare_neighborid",
         "bestpath.compare_routerid",
         "bestpath.cost_community_ignore",
         "bestpath.igp_metric_ignore",
         "bestpath.med.confed",
         "bestpath.med.missing_as_worst",
         "bestpath.med.non_deterministic",
         "cluster_id",
         "local_as",
         "confederation.identifier",
         "graceful_restart",
         "graceful_restart.restart_time",
         "graceful_restart.stalepath_time",
         "graceful_restart.helper",
         "log_neighbor_changes",
         "maxas_limit",
         "neighbor_down.fib_accelerate",
         "reconnect_interval",
         "router_id",
         "timers.bestpath_limit",
         "timers.bgp",
         "timers.prefix_peer_timeout",
         "timers.prefix_peer_wait",
         # end VRF parsers
         "disable_policy_batching",
         "disable_policy_batching.ipv4.prefix_list",
         "disable_policy_batching.ipv6.prefix_list",
         "disable_policy_batching.nexthop",
         "dynamic_med_interval",
         "enforce_first_as",
         "enhanced_error",
         "fast_external_fallover",
         "flush_routes",
         "graceful_shutdown.activate",
         "graceful_shutdown.aware",
         "isolate",
         "nexthop.suppress_default_resolution",
         "shutdown",
         "suppress_fib_pending",
         "fabric_soo",
         "rd",
     ]
     self._af_data = {}
コード例 #10
0
 def __init__(self, module):
     super(Prefix_lists, self).__init__(
         empty_fact_val=[],
         facts_module=Facts(module),
         module=module,
         resource="prefix_lists",
         tmplt=Prefix_listsTemplate(),
     )
     self.parsers = []
コード例 #11
0
    def get_hsrp_interfaces_facts(self):
        """ Get the 'facts' (the current configuration)

        :rtype: A dictionary
        :returns: The current configuration as a dictionary
        """
        facts, _warnings = Facts(self._module).get_facts(self.gather_subset, self.gather_network_resources)
        hsrp_interfaces_facts = facts['ansible_network_resources'].get('hsrp_interfaces', [])
        return hsrp_interfaces_facts
コード例 #12
0
 def __init__(self, module):
     super(Hostname, self).__init__(
         empty_fact_val={},
         facts_module=Facts(module),
         module=module,
         resource="hostname",
         tmplt=HostnameTemplate(),
     )
     self.parsers = ["hostname"]
コード例 #13
0
 def get_telemetry_facts(self):
     """ Get the 'facts' (the current configuration)
     :rtype: A dictionary
     :returns: The current configuration as a dictionary
     """
     facts, _warnings = Facts(self._module).get_facts(self.gather_subset, self.gather_network_resources)
     telemetry_facts = facts['ansible_network_resources'].get('telemetry')
     if not telemetry_facts:
         return {}
     return telemetry_facts
コード例 #14
0
    def get_lacp_facts(self, data=None):
        """ Get the 'facts' (the current configuration)

        :rtype: A dictionary
        :returns: The current configuration as a dictionary
        """
        facts, _warnings = Facts(self._module).get_facts(
            self.gather_subset, self.gather_network_resources, data=data)
        lacp_facts = facts["ansible_network_resources"].get("lacp", {})

        return lacp_facts
コード例 #15
0
    def get_vlans_facts(self):
        """ Get the 'facts' (the current configuration)

        :rtype: A dictionary
        :returns: The current configuration as a dictionary
        """
        facts, _warnings = Facts(self._module).get_facts(self.gather_subset, self.gather_network_resources)
        vlans_facts = facts['ansible_network_resources'].get('vlans')
        if not vlans_facts:
            return []
        return vlans_facts
コード例 #16
0
ファイル: acls.py プロジェクト: rohitthakur2590/cisco.nxos
    def get_acls_facts(self, data=None):
        """ Get the 'facts' (the current configuration)

        :rtype: A dictionary
        :returns: The current configuration as a dictionary
        """
        facts, _warnings = Facts(self._module).get_facts(
            self.gather_subset, self.gather_network_resources, data=data)
        acls_facts = facts["ansible_network_resources"].get("acls")
        if not acls_facts:
            return []
        return acls_facts
コード例 #17
0
    def get_interfaces_facts(self):
        """ Get the 'facts' (the current configuration)

        :rtype: A dictionary
        :returns: The current configuration as a dictionary
        """
        facts, _warnings = Facts(self._module).get_facts(
            self.gather_subset, self.gather_network_resources)
        interfaces_facts = facts["ansible_network_resources"].get("interfaces")
        if not interfaces_facts:
            return []
        return interfaces_facts
コード例 #18
0
    def get_lldp_global_facts(self):
        """ Get the 'facts' (the current configuration)

        :rtype: A dictionary
        :returns: The current configuration as a dictionary
        """
        facts, _warnings = Facts(self._module).get_facts(
            self.gather_subset, self.gather_network_resources)
        lldp_global_facts = facts["ansible_network_resources"].get(
            "lldp_global")
        if not lldp_global_facts:
            return {}
        return lldp_global_facts
コード例 #19
0
    def get_lldp_interfaces_facts(self, data=None):
        """ Get the 'facts' (the current configuration)

        :rtype: A dictionary
        :returns: The current configuration as a dictionary
        """
        facts, _warnings = Facts(self._module).get_facts(
            self.gather_subset, self.gather_network_resources, data=data)
        lldp_interfaces_facts = facts['ansible_network_resources'].get(
            'lldp_interfaces')
        if not lldp_interfaces_facts:
            return []
        return lldp_interfaces_facts
コード例 #20
0
    def get_l3_interfaces_facts(self):
        """ Get the 'facts' (the current configuration)

        :rtype: A dictionary
        :returns: The current configuration as a dictionary
        """
        facts, _warnings = Facts(self._module).get_facts(
            self.gather_subset, self.gather_network_resources)
        l3_interfaces_facts = facts['ansible_network_resources'].get(
            'l3_interfaces')

        if not l3_interfaces_facts:
            return []
        return remove_rsvd_interfaces(l3_interfaces_facts)
コード例 #21
0
ファイル: vlans.py プロジェクト: coll-test/cisco.nxos
    def get_vlans_facts(self):
        """ Get the 'facts' (the current configuration)

        :rtype: A dictionary
        :returns: The current configuration as a dictionary
        """
        facts, _warnings = Facts(self._module).get_facts(self.gather_subset, self.gather_network_resources)
        vlans_facts = facts['ansible_network_resources'].get('vlans')
        if not vlans_facts:
            return []

        # Remove vlan 1 from facts list
        vlans_facts = [i for i in vlans_facts if (int(i['vlan_id'])) != 1]
        return vlans_facts
コード例 #22
0
ファイル: ntp_global.py プロジェクト: cidrblock/cisco.nxos
 def __init__(self, module):
     super(Ntp_global, self).__init__(
         empty_fact_val={},
         facts_module=Facts(module),
         module=module,
         resource="ntp_global",
         tmplt=Ntp_globalTemplate(),
     )
     self.parsers = [
         "access_group.match_all",
         "allow.control.rate_limit",
         "allow.private",
         "authenticate",
         "logging",
         "master.stratum",
         "passive",
         "source",
         "source_interface",
     ]
コード例 #23
0
def main():
    """ Main entry point for AnsibleModule
    """
    argument_spec = FactsArgs.argument_spec
    argument_spec.update(nxos_argument_spec)

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True)

    warnings = [
        'default value for `gather_subset` '
        'will be changed to `min` from `!config` v2.11 onwards'
    ]

    result = Facts(module).get_facts()

    ansible_facts, additional_warnings = result
    warnings.extend(additional_warnings)

    module.exit_json(ansible_facts=ansible_facts, warnings=warnings)
コード例 #24
0
 def __init__(self, module):
     super(Bgp_neighbor_address_family, self).__init__(
         empty_fact_val={},
         facts_module=Facts(module),
         module=module,
         resource="bgp_neighbor_address_family",
         tmplt=Bgp_neighbor_address_familyTemplate(),
     )
     self.parsers = [
         "advertise_map.exist_map",
         "advertise_map.non_exist_map",
         "advertisement_interval",
         "allowas_in",
         "as_override",
         "capability.additional_paths.receive",
         "capability.additional_paths.send",
         "default_originate",
         "disable_peer_as_check",
         "filter_list.inbound",
         "filter_list.outbound",
         "inherit",
         "maximum_prefix",
         "next_hop_self",
         "next_hop_third_party",
         "prefix_list.inbound",
         "prefix_list.outbound",
         "rewrite_evpn_rt_asn",
         "route_map.inbound",
         "route_map.outbound",
         "route_reflector_client",
         "send_community.extended",
         "send_community.standard",
         "soft_reconfiguration_inbound",
         "soo",
         "suppress_inactive",
         "unsuppress_map",
         "weight",
     ]
コード例 #25
0
 def __init__(self, module):
     super(Ospfv2, self).__init__(
         empty_fact_val={},
         facts_module=Facts(module),
         module=module,
         resource="ospfv2",
         tmplt=Ospfv2Template(),
     )
     self.parsers = [
         "router_id",
         "auto_cost",
         "graceful_restart.set",
         "graceful_restart.helper_disable",
         "graceful_restart.planned_only",
         "isolate",
         "log_adjacency_changes",
         "max_lsa",
         "mpls.traffic_eng.router_id",
         "mpls.traffic_eng.multicast_intact",
         "name_lookup",
         "passive_interface.default",
         "rfc1583compatibility",
         "shutdown",
         "default_information.originate",
         "default_metric",
         "distance",
         "table_map",
         "timers.lsa_arrival",
         "timers.lsa_group_pacing",
         "timers.throttle.lsa",
         "timers.throttle.spf",
         "maximum_paths",
         "max_metric",
         "down_bit_ignore",
         "capability.vrf_lite",
         "bfd",
     ]
コード例 #26
0
 def __init__(self, module):
     super(Bgp_address_family, self).__init__(
         empty_fact_val={},
         facts_module=Facts(module),
         module=module,
         resource="bgp_address_family",
         tmplt=Bgp_address_familyTemplate(),
     )
     self.parsers = [
         "additional_paths.install_backup",
         "additional_paths.receive",
         "additional_paths.selection.route_map",
         "additional_paths.send",
         "advertise_pip",
         "advertise_system_mac",
         "allow_vni_in_ethertag",
         "client_to_client.no_reflection",
         "dampen_igp_metric",
         "dampening",
         "default_information.originate",
         "default_metric",
         "distance",
         "export_gateway_ip",
         "maximum_paths.parallel_paths",
         "maximum_paths.ibgp.parallel_paths",
         "maximum_paths.eibgp.parallel_paths",
         "maximum_paths.local.parallel_paths",
         "maximum_paths.mixed.parallel_paths",
         "nexthop.route_map",
         "nexthop.trigger_delay",
         "retain.route_target.retain_all",
         "retain.route_target.route_map",
         "suppress_inactive",
         "table_map",
         "timers.bestpath_defer",
         "wait_igp_convergence",
     ]
コード例 #27
0
def main():
    """
    Main entry point for module execution

    :returns: ansible_facts
    """
    argument_spec = FactsArgs.argument_spec
    argument_spec.update(nxos_argument_spec)

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True)

    warnings = []

    ansible_facts = {}
    if module.params.get("available_network_resources"):
        ansible_facts["available_network_resources"] = sorted(
            FACT_RESOURCE_SUBSETS.keys())
    result = Facts(module).get_facts()
    additional_facts, additional_warnings = result
    ansible_facts.update(additional_facts)
    warnings.extend(additional_warnings)

    module.exit_json(ansible_facts=ansible_facts, warnings=warnings)
コード例 #28
0
 def __init__(self, module):
     super(Ospf_interfaces, self).__init__(
         empty_fact_val=[],
         facts_module=Facts(module),
         module=module,
         resource="ospf_interfaces",
         tmplt=Ospf_interfacesTemplate(),
     )
     self.parsers = [
         "authentication",
         "authentication_key",
         "message_digest_key",
         "cost",
         "dead_interval",
         "hello_interval",
         "instance",
         "mtu_ignore",
         "network",
         "passive_interface",
         "priority",
         "retransmit_interval",
         "shutdown",
         "transmit_delay",
     ]
コード例 #29
0
def main():
    """
    Main entry point for module execution

    :returns: ansible_facts
    """
    argument_spec = FactsArgs.argument_spec
    argument_spec.update(nxos_argument_spec)

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True)

    warnings = []
    if module.params["gather_subset"] == "!config":
        warnings.append(
            'default value for `gather_subset` will be changed to `min` from `!config` v2.11 onwards'
        )

    result = Facts(module).get_facts()

    ansible_facts, additional_warnings = result
    warnings.extend(additional_warnings)

    module.exit_json(ansible_facts=ansible_facts, warnings=warnings)
コード例 #30
0
class Interfaces(ConfigBase):
    """
    The nxos_interfaces class
    """

    gather_subset = ["min"]

    gather_network_resources = ["interfaces"]

    exclude_params = ["description", "mtu", "speed", "duplex"]

    def __init__(self, module):
        super(Interfaces, self).__init__(module)

    def get_interfaces_facts(self, data=None):
        """Get the 'facts' (the current configuration)

        :data: Mocked running-config data for state `parsed`
        :rtype: A dictionary
        :returns: The current configuration as a dictionary
        """
        self.facts, _warnings = Facts(self._module).get_facts(
            self.gather_subset,
            self.gather_network_resources,
            data=data,
        )
        interfaces_facts = self.facts["ansible_network_resources"].get("interfaces")

        return interfaces_facts

    def get_platform(self):
        """Wrapper method for getting platform info
        This method exists solely to allow the unit test framework to mock calls.
        """
        return self.facts.get("ansible_net_platform", "")

    def get_system_defaults(self):
        """Wrapper method for `_connection.get()`
        This method exists solely to allow the unit test framework to mock device connection calls.
        """
        return self._connection.get("show running-config all | incl 'system default switchport'")

    def edit_config(self, commands):
        """Wrapper method for `_connection.edit_config()`
        This method exists solely to allow the unit test framework to mock device connection calls.
        """
        return self._connection.edit_config(commands)

    def execute_module(self):
        """Execute the module

        :rtype: A dictionary
        :returns: The result from module execution
        """
        result = {"changed": False}
        commands = []
        warnings = []

        if self.state in self.ACTION_STATES:
            existing_interfaces_facts = self.get_interfaces_facts()
        else:
            existing_interfaces_facts = []

        if self.state in self.ACTION_STATES:
            self.intf_defs = self.render_interface_defaults(
                self.get_system_defaults(),
                existing_interfaces_facts,
            )
            commands.extend(self.set_config(existing_interfaces_facts))

        if self.state == "rendered":
            # Hardcode the system defaults for "rendered"
            # This can be made a configurable option in the future
            self.intf_defs = {
                "sysdefs": {
                    "L2_enabled": False,
                    "L3_enabled": False,
                    "mode": "layer3",
                },
            }
            commands.extend(self.set_config(existing_interfaces_facts))

        if commands and self.state in self.ACTION_STATES:
            if not self._module.check_mode:
                self.edit_config(commands)
            result["changed"] = True

        if self.state in self.ACTION_STATES:
            result["commands"] = commands

        if self.state in self.ACTION_STATES or self.state == "gathered":
            changed_interfaces_facts = self.get_interfaces_facts()

        elif self.state == "rendered":
            result["rendered"] = commands

        elif self.state == "parsed":
            running_config = self._module.params["running_config"]
            if not running_config:
                self._module.fail_json(
                    msg="value of running_config parameter must not be empty for state parsed",
                )
            result["parsed"] = self.get_interfaces_facts(data=running_config)

        if self.state in self.ACTION_STATES:
            result["before"] = existing_interfaces_facts
            if result["changed"]:
                result["after"] = changed_interfaces_facts

        elif self.state == "gathered":
            result["gathered"] = changed_interfaces_facts

        result["warnings"] = warnings
        return result

    def set_config(self, existing_interfaces_facts):
        """Collect the configuration from the args passed to the module,
            collect the current configuration (as a dict from facts)

        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        config = self._module.params.get("config")
        want = []
        if config:
            for w in config:
                w.update({"name": normalize_interface(w["name"])})
                want.append(remove_empties(w))
        have = deepcopy(existing_interfaces_facts)
        resp = self.set_state(want, have)
        return to_list(resp)

    def set_state(self, want, have):
        """Select the appropriate function based on the state provided

        :param want: the desired configuration as a dictionary
        :param have: the current configuration as a dictionary
        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        state = self._module.params["state"]
        if state in ("overridden", "merged", "replaced", "rendered") and not want:
            self._module.fail_json(
                msg="value of config parameter must not be empty for state {0}".format(state),
            )

        commands = list()
        if state == "overridden":
            commands.extend(self._state_overridden(want, have))
        elif state == "deleted":
            commands.extend(self._state_deleted(want, have))
        elif state == "purged":
            commands.extend(self._state_purged(want, have))
        else:
            for w in want:
                if state in ["merged", "rendered"]:
                    commands.extend(self._state_merged(w, have))
                elif state == "replaced":
                    commands.extend(self._state_replaced(w, have))
        return commands

    def _state_replaced(self, w, have):
        """The command generator when state is replaced

        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        commands = []
        name = w["name"]
        obj_in_have = search_obj_in_list(name, have, "name")
        if obj_in_have:
            # If 'w' does not specify mode then intf may need to change to its
            # default mode, however default mode may depend on sysdef.
            if not w.get("mode") and re.search("Ethernet|port-channel", name):
                sysdefs = self.intf_defs["sysdefs"]
                sysdef_mode = sysdefs["mode"]
                if obj_in_have.get("mode") != sysdef_mode:
                    w["mode"] = sysdef_mode
            diff = dict_diff(w, obj_in_have)
        else:
            diff = w

        merged_commands = self.set_commands(w, have)
        # merged_commands:
        #   - These commands are changes specified by the playbook.
        #   - merged_commands apply to both existing and new objects
        # replaced_commands:
        #   - These are the unspecified commands, used to reset any params
        #     that are not already set to default states
        #   - replaced_commands should only be used on 'have' objects
        #     (interfaces that already exist)
        if obj_in_have:
            if "name" not in diff:
                diff["name"] = name
            wkeys = w.keys()
            dkeys = diff.keys()
            for k in wkeys:
                if k in self.exclude_params and k in dkeys:
                    del diff[k]
            replaced_commands = self.del_attribs(diff)
            cmds = set(replaced_commands).intersection(set(merged_commands))
            for cmd in cmds:
                merged_commands.remove(cmd)
            commands.extend(replaced_commands)

        commands.extend(merged_commands)
        return commands

    def _state_overridden(self, want, have):
        """The command generator when state is overridden

        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        # overridden is the same as replaced behavior except for the scope.
        cmds = []
        existing_interfaces = []
        for h in have:
            existing_interfaces.append(h["name"])
            obj_in_want = search_obj_in_list(h["name"], want, "name")
            if obj_in_want:
                if h != obj_in_want:
                    replaced_cmds = self._state_replaced(obj_in_want, [h])
                    if replaced_cmds:
                        cmds.extend(replaced_cmds)
            else:
                cmds.extend(self.del_attribs(h))

        for w in want:
            if w["name"] not in existing_interfaces:
                # This is an object that was excluded from the 'have' list
                # because all of its params are currently set to default states
                # -OR- it's a new object that does not exist on the device yet.
                cmds.extend(self.add_commands(w))
        return cmds

    def _state_merged(self, w, have):
        """The command generator when state is merged

        :rtype: A list
        :returns: the commands necessary to merge the provided into
                  the current configuration
        """
        return self.set_commands(w, have)

    def _state_deleted(self, want, have):
        """The command generator when state is deleted

        :rtype: A list
        :returns: the commands necessary to remove the current configuration
                  of the provided objects
        """
        commands = []
        if want:
            for w in want:
                obj_in_have = search_obj_in_list(w["name"], have, "name")
                commands.extend(self.del_attribs(obj_in_have))
        else:
            if not have:
                return commands
            for h in have:
                commands.extend(self.del_attribs(h))
        return commands

    def _state_purged(self, want, have):
        """The command generator when state is purged

        :rtype: A list
        :returns: the commands necessary to purge interfaces from running
                  configuration
        """
        commands = []
        if want:
            for w in want:
                obj_in_have = search_obj_in_list(w["name"], have, "name")
                if obj_in_have:
                    commands.append("no interface {0}".format(w["name"]))
        return commands

    def default_enabled(self, want=None, have=None, action=""):
        # 'enabled' default state depends on the interface type and L2 state.
        # Note that the current default could change when changing L2/L3 modes.
        if self.state == "rendered":
            # For "rendered", we always assume that
            # the default enabled state is False
            return False
        if want is None:
            want = {}
        if have is None:
            have = {}
        name = have.get("name")
        if name is None:
            return None

        sysdefs = self.intf_defs["sysdefs"]
        sysdef_mode = sysdefs["mode"]

        # Get the default enabled state for this interface. This was collected
        # during Facts gathering.
        intf_def_enabled = self.intf_defs.get(name)

        have_mode = have.get("mode", sysdef_mode)
        if action == "delete" and not want:
            want_mode = sysdef_mode
        else:
            want_mode = want.get("mode", have_mode)
        if (
            (want_mode and have_mode) is None
            or (want_mode != have_mode)
            or intf_def_enabled is None
        ):
            # L2-L3 is changing or this is a new virtual intf. Get new default.
            intf_def_enabled = default_intf_enabled(name=name, sysdefs=sysdefs, mode=want_mode)
        return intf_def_enabled

    def del_attribs(self, obj):
        commands = []
        if not obj or len(obj.keys()) == 1:
            return commands
        # mode/switchport changes should occur before other changes
        sysdef_mode = self.intf_defs["sysdefs"]["mode"]
        if "mode" in obj and obj["mode"] != sysdef_mode:
            no_cmd = "no " if sysdef_mode == "layer3" else ""
            commands.append(no_cmd + "switchport")
        if "description" in obj:
            commands.append("no description")
        if "speed" in obj:
            commands.append("no speed")
        if "duplex" in obj:
            commands.append("no duplex")
        if "enabled" in obj:
            sysdef_enabled = self.default_enabled(have=obj, action="delete")
            if obj["enabled"] is False and sysdef_enabled is True:
                commands.append("no shutdown")
            elif obj["enabled"] is True and sysdef_enabled is False:
                commands.append("shutdown")
        if "mtu" in obj:
            commands.append("no mtu")
        if "ip_forward" in obj and obj["ip_forward"] is True:
            commands.append("no ip forward")
        if (
            "fabric_forwarding_anycast_gateway" in obj
            and obj["fabric_forwarding_anycast_gateway"] is True
        ):
            commands.append("no fabric forwarding mode anycast-gateway")
        if commands:
            commands.insert(0, "interface " + obj["name"])

        return commands

    def diff_of_dicts(self, w, obj):
        diff = set(w.items()) - set(obj.items())
        diff = dict(diff)
        if diff and w["name"] == obj["name"]:
            diff.update({"name": w["name"]})
        return diff

    def add_commands(self, d, obj_in_have=None):
        commands = []
        if obj_in_have is None:
            obj_in_have = {}
        # mode/switchport changes should occur before other changes
        if "mode" in d:
            sysdef_mode = self.intf_defs["sysdefs"]["mode"]
            have_mode = obj_in_have.get("mode", sysdef_mode)
            want_mode = d["mode"]
            if have_mode == "layer2":
                if want_mode == "layer3":
                    commands.append("no switchport")
            elif want_mode == "layer2":
                commands.append("switchport")
        if "description" in d:
            commands.append("description " + d["description"])
        if "speed" in d:
            commands.append("speed " + str(d["speed"]))
        if "duplex" in d:
            commands.append("duplex " + d["duplex"])
        if "enabled" in d:
            have_enabled = obj_in_have.get("enabled", self.default_enabled(d, obj_in_have)) or False
            if d["enabled"] is False and have_enabled is True:
                commands.append("shutdown")
            elif d["enabled"] is True and have_enabled is False:
                commands.append("no shutdown")
        if "mtu" in d:
            commands.append("mtu " + str(d["mtu"]))
        if "ip_forward" in d:
            if d["ip_forward"] is True:
                commands.append("ip forward")
            else:
                commands.append("no ip forward")
        if "fabric_forwarding_anycast_gateway" in d:
            if d["fabric_forwarding_anycast_gateway"] is True:
                commands.append("fabric forwarding mode anycast-gateway")
            else:
                commands.append("no fabric forwarding mode anycast-gateway")
        if commands or not obj_in_have:
            commands.insert(0, "interface" + " " + d["name"])
        return commands

    def set_commands(self, w, have):
        commands = []
        obj_in_have = search_obj_in_list(w["name"], have, "name")
        if not obj_in_have:
            commands = self.add_commands(w)
        else:
            diff = self.diff_of_dicts(w, obj_in_have)
            commands = self.add_commands(diff, obj_in_have)
        return commands

    def render_interface_defaults(self, config, intfs):
        """Collect user-defined-default states for 'system default switchport'
        configurations. These configurations determine default L2/L3 modes
        and enabled/shutdown states. The default values for user-defined-default
        configurations may be different for legacy platforms.
        Notes:
        - L3 enabled default state is False on N9K,N7K but True for N3K,N6K
        - Changing L2-L3 modes may change the default enabled value.
        - '(no) system default switchport shutdown' only applies to L2 interfaces.
        Run through the gathered interfaces and tag their default enabled state.
        """
        intf_defs = {}
        L3_enabled = True if re.search("N[356]K", self.get_platform()) else False
        intf_defs = {
            "sysdefs": {
                "mode": None,
                "L2_enabled": None,
                "L3_enabled": L3_enabled,
            },
        }
        pat = "(no )*system default switchport$"
        m = re.search(pat, config, re.MULTILINE)
        if m:
            intf_defs["sysdefs"]["mode"] = "layer3" if "no " in m.groups() else "layer2"

        pat = "(no )*system default switchport shutdown$"
        m = re.search(pat, config, re.MULTILINE)
        if m:
            intf_defs["sysdefs"]["L2_enabled"] = True if "no " in m.groups() else False

        for item in intfs:
            intf_defs[item["name"]] = default_intf_enabled(
                name=item["name"],
                sysdefs=intf_defs["sysdefs"],
                mode=item.get("mode"),
            )

        return intf_defs