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 _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_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, True)) return commands
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
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
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 = 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 _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. 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
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
def set_commands(self, want, have): cmds = [] obj_in_have = search_obj_in_list(want['name'], have, 'name') if not obj_in_have: cmds = self.add_commands(want, obj_in_have) else: diff = self.diff_of_dicts(want, obj_in_have) cmds = self.add_commands(diff, obj_in_have) return cmds
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) 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 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
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
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_commands(h)) for w in want: commands.extend(self.set_commands(w, have)) 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['vrf'], have, 'vrf') if obj_in_have: commands.extend(self.del_commands([obj_in_have])) else: if have: commands = self.del_commands(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, 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 _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_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
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 del_delta_attribs(self, w, have): commands = [] obj_in_have = search_obj_in_list(w['name'], have, 'name') if obj_in_have: lst_to_del = [] ipv4_intersect = self.intersect_list_of_dicts( w.get('ipv4'), obj_in_have.get('ipv4')) ipv6_intersect = self.intersect_list_of_dicts( w.get('ipv6'), obj_in_have.get('ipv6')) if ipv4_intersect: lst_to_del.append({'ipv4': ipv4_intersect}) if ipv6_intersect: lst_to_del.append({'ipv6': ipv6_intersect}) if lst_to_del: for item in lst_to_del: commands.extend(self.generate_delete_commands(item)) else: commands.extend(self.generate_delete_commands(obj_in_have)) if commands: commands.insert(0, 'interface ' + obj_in_have['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
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, want, have): commands = [] have_afi = search_obj_in_list(want['afi'], have, 'afi') ip = '' if 'v6' in want['afi']: ip = 'ipv6 ' else: ip = 'ip ' if have_afi: if want.get('acls'): for w_acl in want['acls']: have_acl = search_obj_in_list(w_acl['name'], have_afi['acls'], 'name') name = w_acl['name'] flag = 0 ace_commands = [] if have_acl != w_acl: if have_acl: ace_list = [] if w_acl.get('aces') and have_acl.get('aces'): # case 1 --> sequence number not given in want --> new ace # case 2 --> new sequence number in want --> new ace # case 3 --> existing sequence number given --> update rule (only for merged state. # For replaced and overridden, rule is deleted in the state's config) ace_list = [ item for item in w_acl['aces'] if 'sequence' not in item.keys() ] # case 1 want_seq = [ item['sequence'] for item in w_acl['aces'] if 'sequence' in item.keys() ] have_seq = [ item['sequence'] for item in have_acl['aces'] ] new_seq = list(set(want_seq) - set(have_seq)) common_seq = list( set(want_seq).intersection(set(have_seq))) temp_list = [ item for item in w_acl['aces'] if 'sequence' in item.keys() and item['sequence'] in new_seq ] # case 2 ace_list.extend(temp_list) for w in w_acl['aces']: self.argument_spec = AclsArgs.argument_spec params = utils.validate_config( self.argument_spec, { 'config': [{ 'afi': want['afi'], 'acls': [{ 'name': name, 'aces': ace_list }] }] }) if 'sequence' in w.keys( ) and w['sequence'] in common_seq: temp_obj = search_obj_in_list( w['sequence'], have_acl['aces'], 'sequence') # case 3 if temp_obj != w: for key, val in w.items(): temp_obj[key] = val ace_list.append(temp_obj) if self._module.params[ 'state'] == 'merged': ace_commands.append( 'no ' + str(w['sequence'])) # remove existing rule to update it elif w_acl.get('aces'): # 'have' has ACL defined without any ACE ace_list = [item for item in w_acl['aces']] for w_ace in ace_list: ace_commands.append( self.process_ace(w_ace).strip()) flag = 1 if flag: ace_commands.insert(0, ip + 'access-list ' + name) else: commands.append(ip + 'access-list ' + name) if 'aces' in w_acl.keys(): for w_ace in w_acl['aces']: commands.append( self.process_ace(w_ace).strip()) commands.extend(ace_commands) else: if want.get('acls'): for w_acl in want['acls']: name = w_acl['name'] commands.append(ip + 'access-list ' + name) if 'aces' in w_acl.keys(): for w_ace in w_acl['aces']: commands.append(self.process_ace(w_ace).strip()) 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 = [] delete_commands = [] merged_commands = [] q(have) obj_in_have = search_obj_in_list(want['vrf'], have, 'vrf') q(obj_in_have) if obj_in_have and obj_in_have != {'vrf': '__global__'}: afi_list = [w['afi'] for w in want['address_families']] q(afi_list) for h in obj_in_have['address_families']: if h['afi'] in afi_list: q(h['afi'], want) want_afi = search_obj_in_list(h['afi'], want['address_families'], 'afi') q(want_afi) want_dest_list = [w['dest'] for w in want_afi['routes']] for ro in h['routes']: if ro['dest'] in want_dest_list: q(ro) want_dest = search_obj_in_list( ro['dest'], want_afi['routes'], 'dest') want_next_hops = [ nh for nh in want_dest['next_hops'] ] q(want_next_hops) for next_hop in ro['next_hops']: if next_hop in want_next_hops: {} else: q(next_hop) if obj_in_have['vrf'] is '__global__': obj_in_have['vrf'] = 'default' if h['afi'] == 'ipv4': com = 'no ip route ' + \ ro['dest'] + ' ' + \ self.add_commands(next_hop) q(com) else: com = 'no ipv6 route ' + \ ro['dest'] + ' ' + \ self.add_commands(next_hop) delete_commands.append(com.strip()) # string = 'vrf context ' + \ # str(obj_in_have['vrf']) # if string not in delete_commands: # delete_commands.insert(0, string) # delete next_hop else: delete_dict = { 'vrf': obj_in_have['vrf'], 'address_families': [{ 'afi': h['afi'], 'routes': [ro] }] } q(delete_dict) delete_commands.extend( self.del_commands([delete_dict])) # delete ro['dest'] else: q(h) delete_commands.extend( self.del_commands([{ 'address_families': [h], 'vrf': obj_in_have['vrf'] }])) # delete h['afi'] q(delete_commands) final_delete_commands = [] for d in delete_commands: if d not in final_delete_commands: final_delete_commands.append(d) # if there are two afis, 'vrf context..' is added twice fom del_commands. set() gets unique commands merged_commands = (self.set_commands(want, have)) q(merged_commands) if merged_commands: cmds = set(final_delete_commands).intersection( set(merged_commands)) for cmd in cmds: merged_commands.remove(cmd) q(merged_commands) commands.extend(final_delete_commands) commands.extend(merged_commands) q(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: # and have != want: for w in want: ip = 'ipv6' if w['afi'] == 'ipv6' else 'ip' acl_names = [] have_afi = search_obj_in_list(w['afi'], have, 'afi') # if want['afi] not in have, ignore if have_afi: if w.get('acls'): for acl in w['acls']: if 'aces' in acl.keys(): have_name = search_obj_in_list( acl['name'], have_afi['acls'], 'name') if have_name: ace_commands = [] flag = 0 for ace in acl['aces']: if list(ace.keys()) == ['sequence']: # only sequence number is specified to be deleted if 'aces' in have_name.keys(): for h_ace in have_name['aces']: if h_ace[ 'sequence'] == ace[ 'sequence']: ace_commands.append( 'no ' + str(ace['sequence'] )) flag = 1 else: if 'aces' in have_name.keys(): for h_ace in have_name['aces']: # when want['ace'] does not have seq number if 'sequence' not in ace.keys( ): del h_ace['sequence'] if ace == h_ace: ace_commands.append( 'no ' + self.process_ace( ace)) flag = 1 if flag: ace_commands.insert( 0, ip + ' access-list ' + acl['name']) commands.extend(ace_commands) else: # only name given for h in have_afi['acls']: if h['name'] == acl['name']: acl_names.append(acl['name']) for name in acl_names: commands.append('no ' + ip + ' access-list ' + name) else: # 'only afi is given' if have_afi.get('acls'): for h in have_afi['acls']: acl_names.append(h['name']) for name in acl_names: commands.append('no ' + ip + ' access-list ' + name) else: v6 = [] v4 = [] v6_local = v4_local = None for h in have: if h['afi'] == 'ipv6': v6 = (acl['name'] for acl in h['acls']) if 'match_local_traffic' in h.keys(): v6_local = True else: v4 = (acl['name'] for acl in h['acls']) if 'match_local_traffic' in h.keys(): v4_local = True self.no_commands(v4, commands, v4_local, 'ip') self.no_commands(v6, commands, v6_local, 'ipv6') for name in v6: commands.append('no ipv6 access-list ' + name) if v4_local: commands.append('no ipv6 access-list match-local-traffic') 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 = [] have_afi = search_obj_in_list(want['afi'], have, 'afi') del_dict = {'acls': []} want_names = [] if have_afi != want: if have_afi: del_dict.update({'afi': have_afi['afi'], 'acls': []}) if want.get('acls'): want_names = [w['name'] for w in want['acls']] have_names = [h['name'] for h in have_afi['acls']] want_acls = want.get('acls') for w in want_acls: acl_commands = [] if w['name'] not in have_names: # creates new ACL in replaced state merge_dict = {'afi': want['afi'], 'acls': [w]} commands.extend( self._state_merged(merge_dict, have)) else: # acl in want exists in have have_name = search_obj_in_list( w['name'], have_afi['acls'], 'name') have_aces = have_name.get('aces') if have_name.get( 'aces') else [] merge_aces = [] del_aces = [] w_aces = w.get('aces') if w.get('aces') else [] for ace in have_aces: if ace not in w_aces: del_aces.append(ace) for ace in w_aces: if ace not in have_aces: merge_aces.append(ace) merge_dict = { 'afi': want['afi'], 'acls': [{ 'name': w['name'], 'aces': merge_aces }] } del_dict = { 'afi': want['afi'], 'acls': [{ 'name': w['name'], 'aces': del_aces }] } if del_dict['acls']: acl_commands.extend( self._state_deleted([del_dict], have)) acl_commands.extend( self._state_merged(merge_dict, have)) for i in range(1, len(acl_commands)): if acl_commands[i] == acl_commands[0]: acl_commands[i] = '' commands.extend(acl_commands) else: acls = [] # no acls given in want, so delete all have acls for acl in have_afi['acls']: acls.append({'name': acl['name']}) del_dict['acls'] = acls if del_dict['acls']: commands.extend(self._state_deleted([del_dict], have)) else: # want_afi is not present in have commands.extend(self._state_merged(want, have)) commands = list(filter(None, commands)) return commands