Esempio n. 1
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
        """
        commands = []
        want_afi = [w["afi"] for w in want]
        for h in have:
            if h["afi"] in want_afi:
                w = search_obj_in_list(h["afi"], want, "afi")
                for h_acl in h["acls"]:
                    w_acl = search_obj_in_list(h_acl["name"], w["acls"],
                                               "name")
                    if not w_acl:
                        del_dict = {
                            "afi": h["afi"],
                            "acls": [{
                                "name": h_acl["name"]
                            }],
                        }
                        commands.extend(self._state_deleted([del_dict], have))
            else:
                # if afi is not in want
                commands.extend(self._state_deleted([{"afi": h["afi"]}], have))
        for w in want:
            commands.extend(self._state_replaced(w, have))
        return commands
    def set_commands(self, want, have, deleted=False):
        commands = []
        have_name = search_obj_in_list(want["name"], have, "name")
        if have_name and have_name.get("access_groups"):
            if want.get("access_groups"):
                for w_afi in want["access_groups"]:
                    ip = "ipv6"
                    if w_afi["afi"] == "ipv4":
                        ip = "ip"
                    have_afi = search_obj_in_list(
                        w_afi["afi"], have_name["access_groups"], "afi"
                    )
                    if have_afi:
                        new_acls = []
                        if deleted:
                            if w_afi.get("acls") and have_afi.get("acls"):
                                new_acls = [
                                    acl
                                    for acl in w_afi.get("acls")
                                    if acl in have_afi.get("acls")
                                ]
                            elif "acls" not in w_afi.keys():
                                new_acls = have_afi.get("acls")
                        else:
                            if w_afi.get("acls"):
                                new_acls = [
                                    acl
                                    for acl in w_afi["acls"]
                                    if acl not in have_afi["acls"]
                                ]
                        commands.extend(
                            self.process_acl(new_acls, ip, deleted)
                        )
                    else:
                        if not deleted:
                            if w_afi.get("acls"):
                                commands.extend(
                                    self.process_acl(w_afi["acls"], ip)
                                )
            else:
                # only name is given to delete
                if deleted and "access_groups" in have_name.keys():
                    commands.extend(self.process_access_group(have_name, True))
        else:
            if not deleted:  # and 'access_groups' in have_name.keys():
                commands.extend(self.process_access_group(want))

        if len(commands) > 0:
            commands.insert(0, "interface " + want["name"])
        return commands
Esempio n. 3
0
    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 = []
        obj_in_have = flatten_dict(search_obj_in_list(w['name'], have, 'name'))
        if obj_in_have:
            diff = dict_diff(w, obj_in_have)
        else:
            diff = w
        merged_commands = self.set_commands(w, have, True)
        if 'name' not in diff:
            diff['name'] = w['name']

        dkeys = diff.keys()
        for k in w.copy():
            if k in self.exclude_params and k in dkeys:
                del diff[k]
        replaced_commands = self.del_attribs(diff)

        if merged_commands:
            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_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
        """
        commands = []
        del_commands = []
        delete_dict = {}
        obj_in_have = flatten_dict(
            search_obj_in_list(want["name"], have, "name"))
        for k1 in obj_in_have.keys():
            if k1 not in want.keys():
                delete_dict.update({k1: obj_in_have[k1]})

        if delete_dict:
            delete_dict.update({"name": want["name"]})
            del_commands = self.del_commands(delete_dict)
        merged_commands = self.set_commands(want, have)

        if merged_commands:
            cmds = set(del_commands).intersection(set(merged_commands))
            for cmd in cmds:
                merged_commands.remove(cmd)

        commands.extend(del_commands)
        commands.extend(merged_commands)
        return commands
Esempio n. 5
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
        """
        # 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
Esempio n. 6
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
        """
        cmds = []
        obj_in_have = search_obj_in_list(want["name"], have, "name")
        if obj_in_have:
            diff = dict_diff(want, obj_in_have)
        else:
            diff = want
        merged_cmds = self.set_commands(want, have)
        if "name" not in diff:
            diff["name"] = want["name"]

        replaced_cmds = []
        if obj_in_have:
            replaced_cmds = self.del_attribs(diff)
        if replaced_cmds or merged_cmds:
            for cmd in set(replaced_cmds).intersection(set(merged_cmds)):
                merged_cmds.remove(cmd)
            cmds.extend(replaced_cmds)
            cmds.extend(merged_cmds)
        return cmds
Esempio n. 7
0
    def _state_overridden(self, want, have):
        """ The command generator when state is overridden
        Scope includes all interface objects on the device.

        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        # overridden behavior is the same as replaced except for scope.
        cmds = []
        for i in have:
            obj_in_want = search_obj_in_list(i["name"], want, "name")
            if obj_in_want:
                if i != obj_in_want:
                    v4_cmds = self._v4_cmds(
                        obj_in_want.pop("ipv4", []),
                        i.pop("ipv4", []),
                        state="overridden",
                    )
                    replaced_cmds = self._state_replaced(obj_in_want, [i])
                    replaced_cmds.extend(v4_cmds)
                    self.cmd_order_fixup(replaced_cmds, obj_in_want["name"])
                    cmds.extend(replaced_cmds)
            else:
                deleted_cmds = self.generate_delete_commands(i)
                self.cmd_order_fixup(deleted_cmds, i["name"])
                cmds.extend(deleted_cmds)

        for i in want:
            if [item for item in have if i["name"] == item["name"]]:
                continue
            cmds.extend(self.add_commands(i, name=i["name"]))

        return cmds
Esempio n. 8
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
        """
        cmds = []
        for h in have:
            # Clean up bfd attrs for any interfaces not listed in the play
            h = flatten_dict(h)
            obj_in_want = flatten_dict(
                search_obj_in_list(h["name"], want, "name")
            )
            if obj_in_want:
                # Let the 'want' loop handle all vals for this interface
                continue
            cmds.extend(self.del_attribs(h))
        for w in want:
            # Update any want attrs if needed. The overridden state considers
            # the play as the source of truth for the entire device, therefore
            # set any unspecified attrs to their default state.
            w = self.set_none_vals_to_defaults(flatten_dict(w))
            cmds.extend(self.set_commands(w, have))
        return cmds
Esempio n. 9
0
    def _state_replaced(self, want, have):
        """ The command generator when state is replaced.
        Scope is limited to vlan objects defined in the playbook.
        :rtype: A list
        :returns: The minimum command set required to migrate the current
                  configuration to the desired configuration.
        """
        obj_in_have = search_obj_in_list(want['vlan_id'], have, 'vlan_id')
        if obj_in_have:
            # ignore states that are already reset, then diff what's left
            obj_in_have = self.remove_default_states(obj_in_have)
            diff = dict_diff(want, obj_in_have)
            # Remove merge items from diff; what's left will be used to
            # remove states not specified in the playbook
            for k in dict(set(want.items()) - set(obj_in_have.items())).keys():
                diff.pop(k, None)
        else:
            diff = want

        # merged_cmds: 'want' cmds to update 'have' states that don't match
        # replaced_cmds: remaining 'have' cmds that need to be reset to default
        merged_cmds = self.set_commands(want, have)
        replaced_cmds = []
        if obj_in_have:
            # Remaining diff items are used to reset states to default
            replaced_cmds = self.del_attribs(diff)
        cmds = []
        if replaced_cmds or merged_cmds:
            cmds += ['vlan %s' % str(want['vlan_id'])]
            cmds += merged_cmds + replaced_cmds
        return cmds
Esempio n. 10
0
    def _state_overridden(self, want, have):
        """ The command generator when state is overridden.
        Scope includes all vlan objects on the device.
        :rtype: A list
        :returns: the minimum command set required to migrate the current
                  configuration to the desired configuration.
        """
        # overridden behavior is the same as replaced except for scope.
        cmds = []
        existing_vlans = []
        for h in have:
            existing_vlans.append(h['vlan_id'])
            obj_in_want = search_obj_in_list(h['vlan_id'], want, 'vlan_id')
            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.append('no vlan %s' % h['vlan_id'])

        # Add wanted vlans that don't exist on the device yet
        for w in want:
            if w['vlan_id'] not in existing_vlans:
                new_vlan = ['vlan %s' % w['vlan_id']]
                cmds.extend(new_vlan + self.add_commands(w))
        return cmds
Esempio n. 11
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
        """
        commands = []
        for h in have:
            h = flatten_dict(h)
            obj_in_want = flatten_dict(
                search_obj_in_list(h['name'], want, 'name'))
            if h == obj_in_want:
                continue
            for w in want:
                w = flatten_dict(w)
                if h['name'] == w['name']:
                    wkeys = w.keys()
                    hkeys = h.keys()
                    for k in wkeys:
                        if k in self.exclude_params and k in hkeys:
                            del h[k]
            commands.extend(self.del_attribs(h))
        for w in want:
            commands.extend(self.set_commands(flatten_dict(w), have, True))
        return commands
Esempio n. 12
0
    def set_commands(self, w, have, replace=False):
        commands = []

        obj_in_have = flatten_dict(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)
            if diff and not replace:
                if 'mode' in diff.keys() and diff['mode']:
                    commands = self.add_commands(diff)
                if "allowed_vlans" in diff.keys() and diff["allowed_vlans"]:
                    vlan_tobe_added = diff["allowed_vlans"].split(',')
                    vlan_list = vlan_tobe_added[:]
                    if obj_in_have.get("allowed_vlans"):
                        have_vlans = obj_in_have["allowed_vlans"].split(',')
                    else:
                        have_vlans = []
                    for w_vlans in vlan_list:
                        if w_vlans in have_vlans:
                            vlan_tobe_added.pop(vlan_tobe_added.index(w_vlans))
                    if vlan_tobe_added:
                        diff.update(
                            {"allowed_vlans": ','.join(vlan_tobe_added)})
                        if have_vlans:
                            commands = self.add_commands(diff, True)
                        else:
                            commands = self.add_commands(diff)
                    return commands
            commands = self.add_commands(diff)
        return commands
Esempio n. 13
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
        """
        new_commands = []
        del_dict = {"name": want["name"], "access_groups": []}
        obj_in_have = search_obj_in_list(want["name"], have, "name")
        if obj_in_have != want:
            commands = []
            if obj_in_have and "access_groups" in obj_in_have.keys():
                for ag in obj_in_have["access_groups"]:
                    want_afi = []
                    if want.get("access_groups"):
                        want_afi = search_obj_in_list(ag["afi"],
                                                      want["access_groups"],
                                                      "afi")
                    if not want_afi:
                        # whatever in have is not in want
                        del_dict["access_groups"].append(ag)
                    else:
                        del_acl = []
                        for acl in ag["acls"]:
                            if want_afi.get("acls"):
                                if acl not in want_afi["acls"]:
                                    del_acl.append(acl)
                            else:
                                del_acl.append(acl)
                        afi = want_afi["afi"]
                        del_dict["access_groups"].append({
                            "afi": afi,
                            "acls": del_acl
                        })

            commands.extend(self._state_deleted([del_dict], have))
            commands.extend(self._state_merged(want, have))
            new_commands.append(commands[0])
            commands = [
                commands[i] for i in range(1, len(commands))
                if commands[i] != commands[0]
            ]
            new_commands.extend(commands)
        return new_commands
Esempio n. 14
0
 def set_commands(self, want, have):
     cmds = []
     obj_in_have = flatten_dict(search_obj_in_list(want['name'], have, 'name'))
     if not obj_in_have:
         cmds = self.add_commands(want)
     else:
         diff = self.diff_of_dicts(want, obj_in_have)
         cmds = self.add_commands(diff)
     return cmds
Esempio n. 15
0
 def set_commands(self, w, have):
     commands = []
     obj_in_have = search_obj_in_list(w['vlan_id'], have, 'vlan_id')
     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)
     return commands
Esempio n. 16
0
 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 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['members'], w['name'])
     else:
         diff = self.diff_list_of_dicts(w['members'],
                                        obj_in_have['members'])
         commands = self.add_commands(diff, w['name'])
     return commands
 def del_intf_commands(self, w, have):
     commands = []
     obj_in_have = search_obj_in_list(w["name"], have, "name")
     if obj_in_have:
         lst_to_del = self.intersect_list_of_dicts(w["members"],
                                                   obj_in_have["members"])
         if lst_to_del:
             for item in lst_to_del:
                 commands.append("interface" + " " + item["member"])
                 commands.append("no channel-group")
     return commands
 def del_intf_commands(self, w, have):
     commands = []
     obj_in_have = search_obj_in_list(w['name'], have, 'name')
     if obj_in_have:
         lst_to_del = self.intersect_list_of_dicts(w['members'],
                                                   obj_in_have['members'])
         if lst_to_del:
             for item in lst_to_del:
                 commands.append('interface' + ' ' + item['member'])
                 commands.append('no channel-group')
     return commands
Esempio n. 20
0
    def set_commands(self, want, have, deleted=False):
        commands = []
        have_name = search_obj_in_list(want['name'], have, 'name')
        if have_name and have_name.get('access_groups'):
            if want.get('access_groups'):
                for w_afi in want['access_groups']:
                    ip = 'ipv6'
                    if w_afi['afi'] == 'ipv4':
                        ip = 'ip'
                    have_afi = search_obj_in_list(
                        w_afi['afi'], have_name['access_groups'], 'afi')
                    if have_afi:
                        new_acls = []
                        if deleted:
                            if w_afi.get('acls') and have_afi.get('acls'):
                                new_acls = [
                                    acl for acl in w_afi.get('acls') if acl in have_afi.get('acls')]
                            elif 'acls' not in w_afi.keys():
                                new_acls = have_afi.get('acls')
                        else:
                            if w_afi.get('acls'):
                                new_acls = [
                                    acl for acl in w_afi['acls'] if acl not in have_afi['acls']]
                        commands.extend(self.process_acl(
                            new_acls, ip, deleted))
                    else:
                        if not deleted:
                            if w_afi.get('acls'):
                                commands.extend(
                                    self.process_acl(w_afi['acls'], ip))
            else:
                # only name is given to delete
                if deleted and 'access_groups' in have_name.keys():
                    commands.extend(self.process_access_group(have_name, True))
        else:
            if not deleted:  # and 'access_groups' in have_name.keys():
                commands.extend(self.process_access_group(want))

        if len(commands) > 0:
            commands.insert(0, 'interface ' + want['name'])
        return commands
 def set_commands(self, want, have):
     commands = []
     obj_in_have = flatten_dict(
         search_obj_in_list(want["name"], have, "name"))
     if not obj_in_have:
         commands = self.add_commands(flatten_dict(want))
     else:
         diff = dict_diff(obj_in_have, want)
         if diff:
             diff.update({"name": want["name"]})
             commands = self.add_commands(diff)
     return commands
Esempio n. 22
0
    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
Esempio n. 23
0
    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)
        if merged_commands:
            # 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
        """
        commands = []
        for h in have:
            obj_in_want = search_obj_in_list(h['name'], want, 'name')
            if h == obj_in_want:
                continue
            commands.extend(self.del_all_attribs(h))
        for w in want:
            commands.extend(self.set_commands(w, have))
        return commands
Esempio n. 25
0
 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, w["name"])
     else:
         diff = {}
         diff.update({
             "ipv4":
             self.diff_list_of_dicts(w.get("ipv4"), obj_in_have.get("ipv4"))
         })
         diff.update({
             "ipv6":
             self.diff_list_of_dicts(w.get("ipv6"), obj_in_have.get("ipv6"))
         })
         commands = self.add_commands(diff, w["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, w['name'])
     else:
         diff = {}
         diff.update({
             'ipv4':
             self.diff_list_of_dicts(w.get('ipv4'), obj_in_have.get('ipv4'))
         })
         diff.update({
             'ipv6':
             self.diff_list_of_dicts(w.get('ipv6'), obj_in_have.get('ipv6'))
         })
         commands = self.add_commands(diff, w['name'])
     return commands
Esempio n. 27
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
        """
        commands = []
        if want:
            for w in want:
                obj_in_have = search_obj_in_list(w["name"], have, "name")
                commands.extend(self.del_all_attribs(obj_in_have))
        else:
            if not have:
                return commands
            for h in have:
                commands.extend(self.del_all_attribs(h))
        return commands
Esempio n. 28
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
        """
        if not (want or have):
            return []
        cmds = []
        if want:
            for w in want:
                obj_in_have = flatten_dict(search_obj_in_list(w['name'], have, 'name'))
                cmds.extend(self.del_attribs(obj_in_have))
        else:
            for h in have:
                cmds.extend(self.del_attribs(flatten_dict(h)))
        return cmds
Esempio n. 29
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
        """
        commands = []
        if want:
            for w in want:
                obj_in_have = search_obj_in_list(w['vlan_id'], have, 'vlan_id')
                commands.append('no vlan ' + str(obj_in_have['vlan_id']))
        else:
            if not have:
                return commands
            for h in have:
                commands.append('no vlan ' + str(h['vlan_id']))
        return commands
Esempio n. 30
0
    def _state_replaced(self, want, have):
        """ The command generator when state is replaced
        Scope is limited to interface objects defined in the playbook.

        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        cmds = []
        name = want["name"]
        obj_in_have = search_obj_in_list(want["name"], have, "name")

        have_v4 = obj_in_have.pop("ipv4", []) if obj_in_have else []
        have_v6 = obj_in_have.pop("ipv6", []) if obj_in_have else []

        # Process lists of dicts separately
        v4_cmds = self._v4_cmds(
            want.pop("ipv4", []), have_v4, state="replaced"
        )
        v6_cmds = self._v6_cmds(
            want.pop("ipv6", []), have_v6, state="replaced"
        )

        # Process remaining attrs
        if obj_in_have:
            # Find 'want' changes first
            diff = self.diff_of_dicts(want, obj_in_have)
            rmv = {"name": name}
            haves_not_in_want = (
                set(obj_in_have.keys()) - set(want.keys()) - set(diff.keys())
            )
            for i in haves_not_in_want:
                rmv[i] = obj_in_have[i]
            cmds.extend(self.generate_delete_commands(rmv))
        else:
            diff = want

        cmds.extend(self.add_commands(diff, name=name))
        cmds.extend(v4_cmds)
        cmds.extend(v6_cmds)
        self.cmd_order_fixup(cmds, name)
        return cmds