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 """ commands = [] # Drill each iteration of want n have and then based on dest and afi tyoe comparison take config call for w in want: for addr_want in w.get('address_families'): for route_want in addr_want.get('routes'): check = False for h in have: if h.get('address_families'): for addr_have in h.get('address_families'): for route_have in addr_have.get('routes'): if route_want.get('dest') == route_have.get('dest')\ and addr_want['afi'] == addr_have['afi']: check = True have_set = set() new_hops = [] for each in route_want.get( 'next_hops'): want_set = set() new_dict_to_set( each, [], want_set, 0) new_hops.append(want_set) new_dict_to_set( addr_have, [], have_set, 0) commands.extend( self._set_config( w, h, addr_want, route_want, route_have, new_hops, have_set)) if check: break if check: break if not check: # For configuring any non-existing want config new_hops = [] for each in route_want.get('next_hops'): want_set = set() new_dict_to_set(each, [], want_set, 0) new_hops.append(want_set) commands.extend( self._set_config(w, {}, addr_want, route_want, {}, new_hops, set())) return commands
def _set_config(self, want, have, acl_want, afi): """ Function that sets the acls config based on the want and have config :param want: want config :param have: have config :param acl_want: want acls config :param afi: acls afi type :rtype: A list :returns: the commands generated based on input want/have params """ commands = [] change = False want_set = set() have_set = set() # Convert the want and have dict to its respective set for taking the set diff new_dict_to_set(want, [], want_set) new_dict_to_set(have, [], have_set) diff = want_set - have_set # Populate the config only when there's a diff b/w want and have config if diff: name = acl_want.get('name') if afi == 'ipv4': try: name = int(name) # If name is numbered acls if name <= 99: cmd = 'ip access-list standard {0}'.format(name) elif name >= 100: cmd = 'ip access-list extended {0}'.format(name) except ValueError: # If name is named acls acl_type = acl_want.get('acl_type') if acl_type: cmd = 'ip access-list {0} {1}'.format(acl_type, name) else: self._module.fail_json( msg='ACL type value is required for Named ACL!') elif afi == 'ipv6': cmd = 'ipv6 access-list {0}'.format(name) # Get all of aces option values from diff dict sequence = want.get('sequence') grant = want.get('grant') source = want.get('source') destination = want.get('destination') po = want.get('protocol_options') protocol = want.get('protocol') dscp = want.get('dscp') fragments = want.get('fragments') log = want.get('log') log_input = want.get('log_input') option = want.get('option') precedence = want.get('precedence') time_range = want.get('time_range') tos = want.get('tos') ttl = want.get('ttl') if sequence: if afi == 'ipv6': cmd = cmd + ' sequence {0}'.format(sequence) else: cmd = cmd + ' {0}'.format(sequence) if grant: cmd = cmd + ' {0}'.format(grant) if po and isinstance(po, dict): po_key = list(po)[0] if protocol and protocol != po_key: self._module.fail_json( msg= 'Protocol value cannot be different from Protocol option protocol value!' ) cmd = cmd + ' {0}'.format(po_key) if po.get('icmp'): po_val = po.get('icmp') elif po.get('igmp'): po_val = po.get('igmp') elif po.get('tcp'): po_val = po.get('tcp') elif protocol: cmd = cmd + ' {0}'.format(protocol) if source: cmd = self.source_dest_config(source, cmd, po) if destination: cmd = self.source_dest_config(destination, cmd, po) if po: cmd = cmd + ' {0}'.format(list(po_val)[0]) if dscp: cmd = cmd + ' dscp {0}'.format(dscp) if fragments: cmd = cmd + ' fragments {0}'.format(fragments) if log: cmd = cmd + ' log {0}'.format(log) if log_input: cmd = cmd + ' log-input {0}'.format(log_input) if option: cmd = cmd + ' option {0}'.format(list(option)[0]) if precedence: cmd = cmd + ' precedence {0}'.format(precedence) if time_range: cmd = cmd + ' time-range {0}'.format(time_range) if tos: for k, v in iteritems(tos): if k == 'service_value': cmd = cmd + ' tos {0}'.format(v) else: cmd = cmd + ' tos {0}'.format(v) if ttl: for k, v in iteritems(ttl): if k == 'range' and v: start = v.get('start') end = v.get('start') cmd = cmd + ' ttl {0} {1}'.format(start, end) elif v: cmd = cmd + ' ttl {0} {1}'.format(k, v) commands.append(cmd) if commands: change = True return commands, change
def _clear_config(self, want, have, addr_want, addr_have, route_want, route_have): """ Delete the interface config based on the want and have config :rtype: A list :returns: The commands necessary to configure the static routes """ commands = [] cmd = None vrf_diff = False topology_diff = False want_vrf = want.get("vrf") have_vrf = have.get("vrf") if want_vrf != have_vrf: vrf_diff = True want_topology = want.get("topology") have_topology = have.get("topology") if want_topology != have_topology: topology_diff = True want_set = set() new_dict_to_set(addr_want, [], want_set, 0) have_hops = [] for each in route_have.get("next_hops"): temp_have_set = set() new_dict_to_set(each, [], temp_have_set, 0) have_hops.append(temp_have_set) # configure delete cmd for each hops under the same destination for each in have_hops: diff = each - want_set if vrf_diff: each.add(tuple(iteritems({"vrf": have_vrf}))) if topology_diff: each.add(tuple(iteritems({"topology": want_topology}))) if diff or vrf_diff or topology_diff: if want_vrf and not vrf_diff: each.add(tuple(iteritems({"vrf": want_vrf}))) if want_topology and not vrf_diff: each.add(tuple(iteritems({"topology": want_topology}))) if addr_want: each.add(tuple(iteritems({"afi": addr_want.get("afi")}))) else: each.add(tuple(iteritems({"afi": addr_have.get("afi")}))) if route_want: each.add(tuple(iteritems({"dest": route_want.get("dest")}))) else: each.add(tuple(iteritems({"dest": route_have.get("dest")}))) temp_want = {} for each_want in each: temp_want.update(dict(each_want)) if temp_want.get("afi") == "ipv4": cmd = "no ip route " vrf = temp_want.get("vrf") if vrf: cmd = cmd + "vrf {0} ".format(vrf) cmd = self.prepare_config_commands(temp_want, cmd) elif temp_want.get("afi") == "ipv6": cmd = "no ipv6 route " cmd = self.prepare_config_commands(temp_want, cmd) commands.append(cmd) 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 = [] # Creating a copy of want, so that want dict is intact even after delete operation # performed during override want n have comparison temp_want = copy.deepcopy(want) # Drill each iteration of want n have and then based on dest and afi tyoe comparison take config call for h in have: if h.get("address_families"): for addr_have in h.get("address_families"): for route_have in addr_have.get("routes"): check = False for w in temp_want: for addr_want in w.get("address_families"): count = 0 for route_want in addr_want.get("routes"): if (route_want.get("dest") == route_have.get("dest") and addr_want["afi"] == addr_have["afi"]): check = True have_set = set() new_hops = [] for each in route_want.get( "next_hops"): want_set = set() new_dict_to_set( each, [], want_set, 0) new_hops.append(want_set) new_dict_to_set( addr_have, [], have_set, 0) commands.extend( self._clear_config( w, h, addr_want, addr_have, route_want, route_have, )) commands.extend( self._set_config( w, h, addr_want, route_want, route_have, new_hops, have_set, )) del addr_want.get("routes")[count] count += 1 if check: break if check: break if not check: commands.extend( self._clear_config({}, h, {}, addr_have, {}, route_have)) # For configuring any non-existing want config for w in temp_want: for addr_want in w.get("address_families"): for route_want in addr_want.get("routes"): new_hops = [] for each in route_want.get("next_hops"): want_set = set() new_dict_to_set(each, [], want_set, 0) new_hops.append(want_set) commands.extend( self._set_config(w, {}, addr_want, route_want, {}, new_hops, set())) # Arranging the cmds suct that all delete cmds are fired before all set cmds commands = [each for each in sorted(commands) if "no" in each] + [ each for each in sorted(commands) if "no" not in each ] 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 = [] # Drill each iteration of want n have and then based on dest and afi tyoe comparison take config call for w in want: for addr_want in w.get("address_families"): for route_want in addr_want.get("routes"): check = False for h in have: if h.get("address_families"): for addr_have in h.get("address_families"): for route_have in addr_have.get("routes"): if (route_want.get("dest") == route_have.get("dest") and addr_want["afi"] == addr_have["afi"]): check = True have_set = set() new_hops = [] for each in route_want.get( "next_hops"): want_set = set() new_dict_to_set( each, [], want_set, 0) new_hops.append(want_set) new_dict_to_set( addr_have, [], have_set, 0) # Check if the have dict next_hops value is diff from want dict next_hops have_dict = filter_dict_having_none_value( route_want.get("next_hops")[0], route_have.get("next_hops")[0], ) # update the have_dict with forward_router_address have_dict.update({ "forward_router_address": route_have.get("next_hops")[0].get( "forward_router_address") }) # updating the have_dict with next_hops val that's not None new_have_dict = {} for k, v in have_dict.items(): if v is not None: new_have_dict.update({k: v}) # Set the new config from the user provided want config cmd = self._set_config( w, h, addr_want, route_want, route_have, new_hops, have_set, ) if cmd: # since inplace update isn't allowed for static routes, preconfigured # static routes needs to be deleted before the new want static routes changes # are applied clear_route_have = copy.deepcopy( route_have) # inplace update is allowed in case of ipv6 static routes, so not deleting it # before applying the want changes if ":" not in route_want.get( "dest"): commands.extend( self._clear_config( {}, h, {}, addr_have, {}, clear_route_have, )) commands.extend(cmd) if check: break if check: break if not check: # For configuring any non-existing want config new_hops = [] for each in route_want.get("next_hops"): want_set = set() new_dict_to_set(each, [], want_set, 0) new_hops.append(want_set) commands.extend( self._set_config( w, {}, addr_want, route_want, {}, new_hops, set(), )) commands = [each for each in commands if "no" in each ] + [each for each in commands if "no" not in each] return commands
def _set_config(self, want, have, acl_want, afi): """ Function that sets the acls config based on the want and have config :param want: want config :param have: have config :param acl_want: want acls config :param afi: acls afi type :rtype: A list :returns: the commands generated based on input want/have params """ commands = [] change = False want_set = set() have_set = set() # Convert the want and have dict to its respective set for taking the set diff new_dict_to_set(want, [], want_set) new_dict_to_set(have, [], have_set) diff = want_set - have_set # Check Py Version and if its py35, verify the diff again if diff and sys.version[0:3] == "3.5": if not reverify_diff_py35(want_set, have_set): diff = set() # Populate the config only when there's a diff b/w want and have config if diff: name = acl_want.get("name") if afi == "ipv4": try: name = int(name) # If name is numbered acls if name <= 99: cmd = "ip access-list standard {0}".format(name) elif name >= 100: cmd = "ip access-list extended {0}".format(name) except ValueError: # If name is named acls acl_type = acl_want.get("acl_type") if acl_type: cmd = "ip access-list {0} {1}".format(acl_type, name) else: self._module.fail_json( msg="ACL type value is required for Named ACL!" ) elif afi == "ipv6": cmd = "ipv6 access-list {0}".format(name) # Get all of aces option values from diff dict sequence = want.get("sequence") grant = want.get("grant") source = want.get("source") destination = want.get("destination") po = want.get("protocol_options") protocol = want.get("protocol") dscp = want.get("dscp") fragments = want.get("fragments") log = want.get("log") log_input = want.get("log_input") option = want.get("option") precedence = want.get("precedence") time_range = want.get("time_range") tos = want.get("tos") ttl = want.get("ttl") if sequence: if afi == "ipv6": cmd = cmd + " sequence {0}".format(sequence) else: cmd = cmd + " {0}".format(sequence) if grant: cmd = cmd + " {0}".format(grant) if po and isinstance(po, dict): po_key = list(po)[0] po_val = dict() if protocol and protocol != po_key: self._module.fail_json( msg="Protocol value cannot be different from Protocol option protocol value!" ) cmd = cmd + " {0}".format(po_key) if po.get("icmp"): po_val = po.get("icmp") elif po.get("igmp"): po_val = po.get("igmp") elif po.get("tcp"): po_val = po.get("tcp") elif protocol: cmd = cmd + " {0}".format(protocol) if source: cmd = self.source_dest_config(source, cmd, po) if destination: cmd = self.source_dest_config(destination, cmd, po) if po and po_val: cmd = cmd + " {0}".format(list(po_val)[0]) if dscp: cmd = cmd + " dscp {0}".format(dscp) if fragments: cmd = cmd + " fragments {0}".format(fragments) if log: cmd = cmd + " log {0}".format(log) if log_input: cmd = cmd + " log-input {0}".format(log_input) if option: cmd = cmd + " option {0}".format(list(option)[0]) if precedence: cmd = cmd + " precedence {0}".format(precedence) if time_range: cmd = cmd + " time-range {0}".format(time_range) if tos: for k, v in iteritems(tos): if k == "service_value": cmd = cmd + " tos {0}".format(v) else: cmd = cmd + " tos {0}".format(v) if ttl: for k, v in iteritems(ttl): if k == "range" and v: start = v.get("start") end = v.get("start") cmd = cmd + " ttl {0} {1}".format(start, end) elif v: cmd = cmd + " ttl {0} {1}".format(k, v) commands.append(cmd) if commands: change = True return commands, change