Beispiel #1
0
    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
        """
        self.router_id = None
        self.root = build_root_xml_node("configuration")
        self.protocols = build_child_xml_node(self.root, "protocols")
        self.routing_options = build_child_xml_node(self.root,
                                                    "routing-options")
        state = self._module.params["state"]
        if (state in ("merged", "replaced", "overridden", "rendered")
                and not want):
            self._module.fail_json(
                msg="value of config parameter must not be empty for state {0}"
                .format(state))
        config_xmls = []
        if state == "overridden":
            config_xmls = self._state_overridden(want, have)
        elif state == "deleted":
            config_xmls = self._state_deleted(want, have)
        elif state in ("merged", "rendered"):
            config_xmls = self._state_merged(want, have)
        elif state == "replaced":
            config_xmls = self._state_replaced(want, have)

        for xml in config_xmls:
            self.protocols.append(xml)

        return [tostring(xml) for xml in self.root.getchildren()]
Beispiel #2
0
    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"]
        root = build_root_xml_node("configuration")
        routing_options = build_child_xml_node(root, "routing-options")
        routing_instances = build_child_xml_node(root, "routing-instances")
        if state == "overridden":
            config_xmls = self._state_overridden(want, have)
        elif state == "deleted":
            config_xmls = self._state_deleted(want, have)
        elif state == "merged":
            config_xmls = self._state_merged(want, have)
        elif state == "replaced":
            config_xmls = self._state_replaced(want, have)

        for xml in config_xmls:
            if xml["root_type"] == "routing-options":
                routing_options.append(xml["static_route_xml"])
            elif xml["root_type"] == "routing-instances":
                routing_instances.append(xml["static_route_xml"])

        return [tostring(xml) for xml in root.getchildren()]
Beispiel #3
0
    def _state_deleted(self, want, have):
        """ The command generator when state is deleted

        :rtype: A list
        :returns: the xml necessary to migrate the current configuration
                  to the desired configuration
        """
        ospf_xml = []
        delete = {"delete": "delete"}

        if not want:
            ospf_node = build_child_xml_node(self.protocols, "ospf")
            ospf_node.attrib.update(delete)
            router_id = have[0].get("router_id")
            if router_id:
                build_child_xml_node(
                    self.routing_options,
                    "router-id",
                    self.router_id,
                    attrib=delete,
                )
            return ospf_node

        ospf_xml = self._state_merged(want, have, delete=delete)
        return ospf_xml
    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
        """
        plist_xml = []
        existing_plist = []
        plist_node = None
        delete = {"delete": "delete"}
        if have is not None:
            # get the instances in running config
            # form existing instance list
            for h_rinst in have:
                existing_plist.append(h_rinst["name"])

            # Delete target routing-instance
            if want:
                for entry in want:
                    if entry["name"] not in existing_plist:
                        continue
                    plist_node = build_root_xml_node("prefix-list")
                    build_child_xml_node(plist_node, "name", entry["name"])
                    plist_node.attrib.update(delete)
                    plist_xml.append(plist_node)

            else:
                # Delete all the routing-instance
                plist_node = build_root_xml_node("prefix-list")
                plist_node.attrib.update(delete)
                plist_xml.append(plist_node)

            if plist_node is not None:
                plist_xml.append(plist_node)
        return plist_xml
Beispiel #5
0
    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
        """
        delete = {"delete": "delete"}
        if have is not None:
            build_child_xml_node(self.root, "snmp", None, delete)
    def _state_merged(self, want, have, delete=None):
        """ The command generator when state is merged

        :rtype: A list
        :returns: the xml necessary to migrate the current configuration
                  to the desired configuration
        """

        acl_intf_xml = []

        for config in want:
            root_node, unit_node = self._get_common_xml_node(config["name"])
            build_child_xml_node(unit_node, "name", "0")
            family_node = build_child_xml_node(unit_node, "family")
            for acl_filter in config["access_groups"]:
                inet_family = "inet"
                if acl_filter["afi"] == "ipv6":
                    inet_family = "inet6"
                inet_node = build_child_xml_node(family_node, inet_family)
                if acl_filter.get("acls"):
                    filter_node = build_child_xml_node(inet_node, "filter")
                    for acl in acl_filter["acls"]:
                        acl_node = None
                        if acl["direction"] == "in":
                            acl_node = build_child_xml_node(
                                filter_node, "input-list", acl["name"])
                        else:
                            acl_node = build_child_xml_node(
                                filter_node, "output-list", acl["name"])
                        if delete:
                            acl_node.attrib.update(delete)
                elif delete:
                    build_child_xml_node(inet_node, "filter", None, delete)
            acl_intf_xml.append(root_node)
        return acl_intf_xml
Beispiel #7
0
    def _state_merged(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 list xml configuration necessary to migrate the current configuration
                  to the desired configuration
        """
        family_xml = []

        family_root = build_root_xml_node("family")

        want = remove_empties(want)

        # Generate xml node for autonomous-system
        if want.get("as_number"):
            build_child_xml_node(
                self.routing_options,
                "autonomous-system",
                want.get("as_number"),
            )
        w_af_list = want.get("address_family")
        # render global address family attribute commands
        self.render_af(w_af_list, family_root)

        # render commands for group address family attribute commands
        if "groups" in want.keys():
            groups = want.get("groups")
            for group in groups:
                groups_node = build_root_xml_node("group")
                build_child_xml_node(groups_node, "name", group["name"])
                g_family_root = build_child_xml_node(groups_node, "family")
                w_gaf_list = group.get("address_family")
                self.render_af(w_gaf_list, g_family_root)

                # render neighbor address-family commands
                if "neighbors" in group.keys():
                    neighbors = group.get("neighbors")
                    for neighbor in neighbors:
                        neighbors_node = build_child_xml_node(
                            groups_node, "neighbor"
                        )
                        build_child_xml_node(
                            neighbors_node,
                            "name",
                            neighbor["neighbor_address"],
                        )
                        n_family_root = build_child_xml_node(
                            neighbors_node, "family"
                        )
                        w_naf_list = neighbor.get("address_family")
                        self.render_af(w_naf_list, n_family_root)

            family_xml.append(groups_node)

        family_xml.append(family_root)

        return family_xml
Beispiel #8
0
    def _state_merged(self, want, have):
        """The command generator when state is merged

        :rtype: A list
        :returns: the commands necessary to merge the provided into
                  the current configuration
        """
        want = remove_empties(want)

        # add hostname node
        if "hostname" in want.keys():
            build_child_xml_node(self.root, "host-name", want.get("hostname"))
Beispiel #9
0
    def _state_merged(self, want, have):
        """The command generator when state is merged

        :rtype: A list
        :returns: the xml necessary to merge the provided into
                  the current configuration
        """
        intf_xml = []

        for config in want:
            vlan_name = str(config["name"])
            vlan_id = str(config["vlan_id"])
            vlan_description = config.get("description")
            vlan_root = build_root_xml_node("vlan")
            build_child_xml_node(vlan_root, "name", vlan_name)
            build_child_xml_node(vlan_root, "vlan-id", vlan_id)
            if vlan_description:
                build_child_xml_node(vlan_root, "description",
                                     vlan_description)
            if config.get("l3_interface"):
                build_child_xml_node(vlan_root, "l3-interface",
                                     config.get("l3_interface"))

            intf_xml.append(vlan_root)
        return intf_xml
Beispiel #10
0
    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
        """
        delete = {"delete": "delete"}
        if have is not None:
            if "autonomous_system" in have.keys():
                build_child_xml_node(self.routing_options, "autonomous-system",
                                     None, delete)
            if "router_id" in have.keys():
                build_child_xml_node(self.routing_options, "router-id", None,
                                     delete)
Beispiel #11
0
    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
        """
        self.root = build_root_xml_node("configuration")
        self.snmp = build_child_xml_node(self.root, "snmp")
        cmd_lst = []
        state = self._module.params["state"]
        if (state in ("merged", "replaced", "rendered", "overridden")
                and not want):
            self._module.fail_json(
                msg="value of config parameter must not be empty for state {0}"
                .format(state))
        if state == "deleted":
            self._state_deleted(want, have)
        elif state in ("merged", "rendered"):
            self._state_merged(want, have)
        elif state == "replaced":
            self._state_replaced(want, have)
        elif state == "overridden":
            self._state_replaced(want, have)

        if self.root is not None:
            for xml in self.root.getchildren():
                xml = tostring(xml)
                cmd_lst.append(xml)
        return cmd_lst
Beispiel #12
0
    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
        """
        lacp_xml = []

        lacp_root = build_root_xml_node('lacp')
        build_child_xml_node(lacp_root, 'system-priority', None, {'delete': 'delete'})
        element = build_child_xml_node(lacp_root, 'link-protection', None, {'delete': 'delete'})
        build_child_xml_node(element, 'non-revertive', None, {'delete': 'delete'})

        lacp_xml.append(lacp_root)
        return lacp_xml
Beispiel #13
0
 def _add_node(self, want, h_key, w_key, node, cfg=False):
     """ Append the child node to the root node
     :param want: the desired configuration as a dictionary
     :param h_key: the current configuration key
     :param: node: root node
     """
     if cfg:
         if want.get(w_key):
             build_child_xml_node(node, h_key, want[w_key])
     else:
         if w_key in want.keys():
             b_val = want.get(w_key)
             if b_val is not None:
                 if b_val is True:
                     build_child_xml_node(node, h_key)
     return node
    def _state_merged(self, want, have):
        """ The xml generator when state is merged

        :rtype: A list
        :returns: the xml necessary to merge the provided into
                  the current configuration
        """
        intf_xml = []
        for config in want:
            root_node, unit_node = self._get_common_xml_node(config['name'])
            build_child_xml_node(unit_node, 'name', str(config['unit']))
            if config.get('ipv4'):
                self.build_ipaddr_et(config, unit_node)
            if config.get('ipv6'):
                self.build_ipaddr_et(config, unit_node, protocol='ipv6')
            intf_xml.append(root_node)
        return intf_xml
Beispiel #15
0
    def _state_merged(self, want, have):
        """ The command generator when state is merged
        :rtype: A list
        :returns: the commands necessary to merge the provided into
                  the current configuration
        """
        prefix_list_xml = []
        for instance in want:
            instance = remove_empties(instance)

            # generate node: prefix-list
            prefix_root = build_root_xml_node("prefix-list")

            # generate node: name
            if "name" in instance.keys():
                build_child_xml_node(prefix_root, "name", instance.get("name"))

            # generate node: prefix-list-item
            if "address_prefixes" in instance.keys():
                address_prefixes = instance.get("address_prefixes")

                for entry in address_prefixes:
                    add_prefix_node = build_child_xml_node(
                        prefix_root, "prefix-list-item")
                    # generate name node
                    build_child_xml_node(add_prefix_node, "name", entry)

            # generate node: dynamic_db
            if "dynamic_db" in instance.keys() and instance.get("dynamic_db"):
                build_child_xml_node(prefix_root, "dynamic-db")

            prefix_list_xml.append(prefix_root)

        return prefix_list_xml
Beispiel #16
0
    def _state_merged(self, want, have):
        """The command generator when state is merged

        :rtype: A list
        :returns: the commands necessary to merge the provided into
                  the current configuration
        """
        routing_xml = []
        want = remove_empties(want)

        # add authentication-keys node
        if "autonomous_system" in want.keys():
            as_num = want.get("autonomous_system")
            # Generate xml node for autonomous-system
            if as_num.get("as_number"):
                as_node = build_child_xml_node(
                    self.routing_options,
                    "autonomous-system",
                    as_num.get("as_number"),
                )
                # Add node for loops
                if as_num.get("loops"):
                    build_child_xml_node(as_node, "loops", as_num.get("loops"))
                # Add node for asdot_notation
                if as_num.get("asdot_notation"):
                    if "asdot_notation" in as_num.keys():
                        build_child_xml_node(as_node, "asdot-notation")
        if "router_id" in want.keys():
            build_child_xml_node(self.routing_options, "router-id",
                                 want.get("router_id"))
        return routing_xml
Beispiel #17
0
 def _state_purged(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
     """
     bgp_xml = []
     delete = {"delete": "delete"}
     build_child_xml_node(self.protocols, "bgp", None, delete)
     autonomous_system = have.get("as_number")
     if autonomous_system:
         build_child_xml_node(
             self.routing_options,
             "autonomous-system",
             None,
             {"delete": "delete"},
         )
     return bgp_xml
Beispiel #18
0
    def _state_merged(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 list xml configuration necessary to migrate the current configuration
                  to the desired configuration
        """
        lacp_xml = []

        lacp_root = build_root_xml_node('lacp')
        build_child_xml_node(lacp_root, 'system-priority', want.get('system_priority'))
        if want.get('link_protection') == 'non-revertive':
            build_subtree(lacp_root, 'link-protection/non-revertive')
        elif want.get('link_protection') == 'revertive':
            link_root = build_child_xml_node(lacp_root, 'link-protection')
            build_child_xml_node(link_root, 'non-revertive', None, {'delete': 'delete'})
        lacp_xml.append(lacp_root)
        return lacp_xml
Beispiel #19
0
    def _state_deleted(self, want, have):
        """ The command generator when state is deleted

        :rtype: A list
        :returns: the xml necessary to migrate the current configuration
                  to the desired configuration
        """
        ospf_xml = []
        delete = {"delete": "delete"}
        if have:
            for have_ospf in have:
                have_areas = have_ospf.get("areas") or []
                for area in have_areas:
                    ospf_node = build_child_xml_node(self.protocols, "ospf")
                    area_node = build_child_xml_node(ospf_node, "area",
                                                     area["area_id"])
                    area_node.attrib.update(delete)
                    ospf_xml.append(ospf_node)
        return ospf_xml
Beispiel #20
0
    def _state_replaced(self, want, have):
        """The command generator when state is replaced

        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        self._state_deleted(want, have)
        self.snmp = build_child_xml_node(self.root, "snmp")
        self._state_merged(want, have)
    def _state_deleted(self, want, have):
        """ The command generator when state is deleted

        :rtype: A list
        :returns: the xml necessary to remove the current configuration
                  of the provided objects
        """
        intf_xml = []

        if not want:
            want = have

        for config in want:
            vlan_name = config["name"]
            vlan_root = build_root_xml_node("vlan")
            vlan_root.attrib.update({"delete": "delete"})
            build_child_xml_node(vlan_root, "name", vlan_name)
            intf_xml.append(vlan_root)
        return intf_xml
    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
        """
        lldp_xml = []

        lldp_root = build_root_xml_node("lldp")
        build_child_xml_node(lldp_root, "management-address", None,
                             {"delete": "delete"})
        build_child_xml_node(lldp_root, "advertisement-interval", None,
                             {"delete": "delete"})
        build_child_xml_node(lldp_root, "transmit-delay", None,
                             {"delete": "delete"})
        build_child_xml_node(lldp_root, "hold-multiplier", None,
                             {"delete": "delete"})
        build_child_xml_node(lldp_root, "disable", None, {"delete": "delete"})
        lldp_xml.append(lldp_root)
        return lldp_xml
Beispiel #23
0
    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
        """
        lldp_xml = []

        lldp_root = build_root_xml_node('lldp')
        build_child_xml_node(lldp_root, 'management-address', None,
                             {'delete': 'delete'})
        build_child_xml_node(lldp_root, 'advertisement-interval', None,
                             {'delete': 'delete'})
        build_child_xml_node(lldp_root, 'transmit-delay', None,
                             {'delete': 'delete'})
        build_child_xml_node(lldp_root, 'hold-multiplier', None,
                             {'delete': 'delete'})
        build_child_xml_node(lldp_root, 'disable', None, {'delete': 'delete'})
        lldp_xml.append(lldp_root)
        return lldp_xml
Beispiel #24
0
    def _state_deleted(self, want, have):
        """ The xml configuration generator when state is deleted
        :rtype: A list
        :returns: the xml configuration necessary to remove the current configuration
                  of the provided objects
        """
        lldp_intf_xml = []
        intf_obj = want

        if not intf_obj:
            # delete lldp interfaces attribute from all the existing interface
            intf_obj = have

        for config in intf_obj:
            lldp_intf_root = build_root_xml_node("interface")
            lldp_intf_root.attrib.update({"delete": "delete"})
            build_child_xml_node(lldp_intf_root, "name", config["name"])

            lldp_intf_xml.append(lldp_intf_root)

        return lldp_intf_xml
Beispiel #25
0
 def _state_overridden(self, want, have):
     """The xml configuration generator when state is merged
     :rtype: A list
     :returns: the xml configuration necessary to merge the provided into
               the current configuration
     """
     bgp_xml = []
     family_root = None
     if have is not None and have.get("address_family"):
         h_af = have.get("address_family")
         existing_af = [af["afi"] for af in h_af]
         for af in existing_af:
             if family_root is None:
                 family_root = build_child_xml_node(self.bgp, "family")
             build_child_xml_node(family_root, af, None,
                                  {"delete": "delete"})
         if family_root is not None:
             bgp_xml.append(family_root)
     bgp_xml.extend(self._state_deleted(want, have))
     bgp_xml.extend(self._state_merged(want, have))
     return bgp_xml
Beispiel #26
0
    def _state_merged(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 list xml configuration necessary to migrate the current configuration
                  to the desired configuration
        """
        lacp_xml = []

        lacp_root = build_root_xml_node("lacp")
        build_child_xml_node(lacp_root, "system-priority",
                             want.get("system_priority"))
        if want.get("link_protection") == "non-revertive":
            build_subtree(lacp_root, "link-protection/non-revertive")
        elif want.get("link_protection") == "revertive":
            link_root = build_child_xml_node(lacp_root, "link-protection")
            build_child_xml_node(link_root, "non-revertive", None,
                                 {"delete": "delete"})
        lacp_xml.append(lacp_root)
        return lacp_xml
Beispiel #27
0
 def _state_purged(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
     """
     bgp_xml = []
     delete = {"delete": "delete"}
     bgp_node = build_child_xml_node(self.root, "bgp")
     bgp_node.attrib.update(delete)
     bgp_xml.append(bgp_node)
     return bgp_xml
Beispiel #28
0
    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
        """
        plist_xml = []
        delete = {"delete": "delete"}
        if have is not None:
            have_plist = [entry["name"] for entry in have]
            want_plist = [entry["name"] for entry in want]

            for instance in have_plist:
                if instance not in want_plist:
                    plist_node = build_root_xml_node("prefix-list")
                    build_child_xml_node(plist_node, "name", instance)
                    plist_node.attrib.update(delete)
                    plist_xml.append(plist_node)
        plist_xml.extend(self._state_deleted(want, have))
        plist_xml.extend(self._state_merged(want, have))

        return plist_xml
    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
        """
        rinst_xml = []
        existing_rinsts = []
        rinstance_node = None
        delete = {"delete": "delete"}
        if have is not None:
            # get the instances in running config
            # form existing instance list
            for h_rinst in have:
                existing_rinsts.append(h_rinst["name"])

            # Delete target routing-instance
            if want:
                for instance in want:
                    if instance["name"] not in existing_rinsts:
                        continue
                    rinstance_node = build_root_xml_node("instance")
                    build_child_xml_node(rinstance_node, "name",
                                         instance["name"])
                    rinstance_node.attrib.update(delete)
                    rinst_xml.append(rinstance_node)

            else:
                # Delete all the routing-instance
                rinstance_node = build_root_xml_node("instance")
                rinstance_node.attrib.update(delete)
                rinst_xml.append(rinstance_node)

            if rinstance_node is not None:
                rinst_xml.append(rinstance_node)
        return rinst_xml
Beispiel #30
0
    def _state_deleted(self, want, have):
        """ The command generator when state is deleted

        :rtype: A list
        :returns: the xml necessary to migrate the current configuration
                  to the desired configuration
        """
        acls_xml = []
        family_node = build_root_xml_node("family")
        delete = dict(delete="delete")

        if not want:
            want = have

        for config in want:
            try:
                family = "inet6" if config.get("afi") == "ipv6" else "inet"
            except KeyError:
                family = "inet"
            inet_node = build_child_xml_node(family_node, family)

            # Look deeply into have to match replace correctly
            existing_acls = []
            for conf in have:
                if conf.get("afi") == config.get("afi"):
                    existing_acls.extend(conf["acls"] or [])
            acl_names = [acl["name"] for acl in existing_acls]

            if not config["acls"]:
                inet_node.attrib.update(delete)
                continue

            for acl in config["acls"]:
                if acl["name"] not in acl_names:
                    continue

                filter_node = build_child_xml_node(inet_node, "filter")
                build_child_xml_node(filter_node, "name", acl["name"])
                if not acl.get("aces"):
                    filter_node.attrib.update(delete)
                    continue

                for ace in acl["aces"]:
                    # if ace["name"] not in ace_names:
                    term_node = build_child_xml_node(filter_node, "term")
                    build_child_xml_node(term_node, "name", ace["name"])
                    term_node.attrib.update(delete)

        acls_xml.append(family_node)
        return acls_xml