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_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 = []
        existing_vlans = []
        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
Пример #3
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
Пример #4
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
    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
    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))
        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 = []
        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)
        if 'name' not in diff:
            diff['name'] = w['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)

        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 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, 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
    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_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
Пример #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
        """
        commands = []
        if want:
            for w in want:
                obj_in_have = search_obj_in_list(w['vlan_id'], have, 'vlan_id')
                if obj_in_have:
                    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
    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
    def set_commands(self, w, have):
        commands = []
        name = w['name']
        obj_in_have = search_obj_in_list(name, have, 'name')
        if not obj_in_have:
            commands = self.add_commands(w, name=name)
        else:
            # lists of dicts must be processed separately from non-list attrs
            v4_cmds = self._v4_cmds(w.pop('ipv4', []),
                                    obj_in_have.pop('ipv4', []),
                                    state='merged')
            v6_cmds = self._v6_cmds(w.pop('ipv6', []),
                                    obj_in_have.pop('ipv6', []),
                                    state='merged')

            # diff remaining attrs
            diff = self.diff_of_dicts(w, obj_in_have)
            commands = self.add_commands(diff, name=name)
            commands.extend(v4_cmds)
            commands.extend(v6_cmds)

        self.cmd_order_fixup(commands, name)
        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
        """
        cmds = []
        for h in have:
            # Check existing states, set to default if not in want or different than want
            h = flatten_dict(h)
            obj_in_want = 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