Adding files for RM static_routes

pull/65402/head
GomathisevliS 5 years ago
parent 88d8cf8197
commit dafdd92d43

@ -13,6 +13,12 @@ from ansible.module_utils.network.common.network import get_resource_connection
class ConfigBase(object):
""" The base class for all resource modules
"""
ACTION_STATES = ['merged', 'replaced', 'overridden', 'deleted']
def __init__(self, module):
self._module = module
self.state = module.params['state']
self._connection = None
if self.state not in ['rendered', 'parsed']:
self._connection = get_resource_connection(module)

@ -20,8 +20,9 @@ class FactsBase(object):
self._warnings = []
self._gather_subset = module.params.get('gather_subset')
self._gather_network_resources = module.params.get('gather_network_resources')
self._connection = None
if module.params.get('state') not in ['rendered', 'parsed']:
self._connection = get_resource_connection(module)
self.ansible_facts = {'ansible_network_resources': {}}
self.ansible_facts['ansible_net_gather_network_resources'] = list()
self.ansible_facts['ansible_net_gather_subset'] = list()

@ -0,0 +1,109 @@
#
# -*- coding: utf-8 -*-
# Copyright 2019 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#############################################
# WARNING #
#############################################
#
# This file is auto generated by the resource
# module builder playbook.
#
# Do not edit this file manually.
#
# Changes to this file will be over written
# by the resource module builder.
#
# Changes should be made in the model used to
# generate this file or in the resource module
# builder template.
#
#############################################
"""
The arg spec for the eos_static_routes module
"""
class Static_routesArgs(object): # pylint: disable=R0903
"""The arg spec for the eos_static_routes module
"""
def __init__(self, **kwargs):
pass
argument_spec = {
'config': {
'elements': 'dict',
'options': {
'address_families': {
'elements': 'dict',
'options': {
'afi': {
'choices': ['ipv4', 'ipv6'],
'required': True,
'type': 'str'
},
'routes': {
'elements': 'dict',
'options': {
'dest': {
'required': True,
'type': 'str'
},
'next_hops': {
'elements': 'dict',
'options': {
'admin_distance': {
'type': 'int'
},
'description': {
'type': 'str'
},
'forward_router_address': {
'type': 'str'
},
'interface': {
'type': 'str'
},
'mpls_label': {
'type': 'int'
},
'tag': {
'type': 'int'
},
'track': {
'type': 'str'
},
'vrf': {
'type': 'str'
}
},
'type': 'list'
}
},
'type': 'list'
}
},
'type': 'list'
},
'vrf': {
'type': 'str'
}
},
'type': 'list'
},
'running_config': {
'type': 'str'
},
'state': {
'choices': [
'deleted', 'merged', 'overridden', 'replaced', 'gathered',
'rendered', 'parsed'
],
'default':
'merged',
'type':
'str'
}
} # pylint: disable=C0301

@ -0,0 +1,374 @@
#
# -*- coding: utf-8 -*-
# Copyright 2019 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""
The eos_static_routes class
It is in this file where the current configuration (as dict)
is compared to the provided configuration (as dict) and the command set
necessary to bring the current configuration to it's desired end-state is
created
"""
from ansible.module_utils.network.common.cfg.base import ConfigBase
from ansible.module_utils.network.common.utils import to_list, dict_diff, remove_empties
from ansible.module_utils.network.eos.facts.facts import Facts
import re
class Static_routes(ConfigBase):
"""
The eos_static_routes class
"""
gather_subset = [
'!all',
'!min',
]
gather_network_resources = [
'static_routes',
]
def __init__(self, module):
super(Static_routes, self).__init__(module)
def get_static_routes_facts(self, data=None):
""" Get the 'facts' (the current configuration)
:rtype: A dictionary
:returns: The current configuration as a dictionary
"""
facts, _warnings = Facts(self._module).get_facts(self.gather_subset, self.gather_network_resources, data=data)
static_routes_facts = facts['ansible_network_resources'].get('static_routes')
if not static_routes_facts:
return []
return static_routes_facts
def execute_module(self):
""" Execute the module
:rtype: A dictionary
:returns: The result from module execution
"""
result = {'changed': False}
warnings = list()
commands = list()
if self.state in self.ACTION_STATES:
existing_static_routes_facts = self.get_static_routes_facts()
else:
existing_static_routes_facts = []
if self.state in self.ACTION_STATES or self.state == 'rendered':
commands.extend(self.set_config(existing_static_routes_facts))
if commands and self.state in self.ACTION_STATES:
if not self._module.check_mode:
for command in commands:
self._connection.edit_config(command)
result['changed'] = True
if self.state in self.ACTION_STATES:
result['commands'] = commands
if self.state in self.ACTION_STATES or self.state == 'gathered':
changed_static_routes_facts = self.get_static_routes_facts()
elif self.state == 'rendered':
result['rendered'] = commands
elif self.state == 'parsed':
result['parsed'] = self.get_static_routes_facts(data=self._module.params['running_config'])
else:
changed_static_routes_facts = []
if self.state in self.ACTION_STATES:
result['before'] = existing_static_routes_facts
if result['changed']:
result['after'] = changed_static_routes_facts
elif self.state == 'gathered':
result['gathered'] = changed_static_routes_facts
result['warnings'] = warnings
return result
#changed_static_routes_facts = self.get_static_routes_facts()
#result['before'] = existing_static_routes_facts
#if result['changed']:
# result['after'] = changed_static_routes_facts
#result['warnings'] = warnings
#return result
def set_config(self, existing_static_routes_facts):
""" Collect the configuration from the args passed to the module,
collect the current configuration (as a dict from facts)
:rtype: A list
:returns: the commands necessary to migrate the current configuration
to the desired configuration
"""
commands = []
onbox_configs = []
for h in existing_static_routes_facts:
return_command = add_commands(h)
for command in return_command:
onbox_configs.append(command)
config = self._module.params.get('config')
want = []
if config:
for w in config:
want.append(remove_empties(w))
have = existing_static_routes_facts
resp = self.set_state(want, have)
for want_config in resp:
if want_config not in onbox_configs:
commands.append(want_config)
return commands
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
"""
commands = []
state = self._module.params['state']
if state == 'overridden':
commands = self._state_overridden(want, have)
elif state == 'deleted':
commands = self._state_deleted(want,have)
elif state == 'merged' or self.state == 'rendered':
commands = self._state_merged(want,have)
elif state == 'replaced':
commands = self._state_replaced(want, have)
return commands
@staticmethod
def _state_replaced(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 = []
haveconfigs = []
vrf = get_vrf(want)
for h in have:
return_command = add_commands(h)
for command in return_command:
if vrf == "default":
if "vrf" not in command:
haveconfigs.append(command)
else:
if vrf in command:
haveconfigs.append(command)
wantconfigs = set_commands(want, have)
removeconfigs = list(set(haveconfigs) - set(wantconfigs))
for command in removeconfigs:
commands.append("no " + command)
for wantcmd in wantconfigs:
commands.append(wantcmd)
return commands
@staticmethod
def _state_overridden(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 = []
haveconfigs = []
for h in have:
return_command = add_commands(h)
for command in return_command:
haveconfigs.append(command)
wantconfigs = set_commands(want, have)
removeconfigs = list(set(haveconfigs) - set(wantconfigs))
for command in removeconfigs:
commands.append("no " + command)
for wantcmd in wantconfigs:
commands.append(wantcmd)
return commands
@staticmethod
def _state_merged(want, have):
""" The command generator when state is merged
:rtype: A list
:returns: the commands necessary to merge the provided into
the current configuration
"""
return set_commands(want, have)
@staticmethod
def _state_deleted(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 not want:
for h in have:
return_command = add_commands(h)
for command in return_command:
command = "no " + command
commands.append(command)
else :
for w in want:
return_command = del_commands(w,have)
for command in return_command:
commands.append(command)
return commands
def set_commands(want, have):
commands = []
for w in want:
return_command = add_commands(w)
for command in return_command:
commands.append(command)
return commands
# 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 add_commands(want):
commandset = []
if not want:
return commandset
vrf = want["vrf"] if "vrf" in want.keys() and want["vrf"] != "default" else None
for address_family in want["address_families"]:
for route in address_family["routes"]:
for next_hop in route["next_hops"]:
commands = []
if address_family["afi"] == "ipv4":
commands.append('ip route')
else:
commands.append('ipv6 route')
if vrf:
commands.append(' vrf ' + vrf)
if not re.search(r'/', route["dest"]):
mask = route["dest"].split( )[1]
cidr = get_net_size(mask)
commands.append(' ' + route["dest"].split( )[0] + '/' + cidr)
else:
commands.append(' ' + route["dest"])
commands.append(' ' + next_hop["interface"])
if "forward_router_address" in next_hop.keys():
commands.append(' ' + next_hop["forward_router_address"])
if "mpls_label" in next_hop.keys():
commands.append(' label ' + str(next_hop["mpls_label"]))
if "track" in next_hop.keys():
commands.append(' track '+next_hop["track"])
if "admin_distance" in next_hop.keys():
commands.append(' '+str(next_hop["admin_distance"]))
if "description" in next_hop.keys():
commands.append(' name '+str(next_hop["description"]))
if "tag" in next_hop.keys():
commands.append(' tag '+str(next_hop["tag"]))
config_commands = "".join(commands)
commandset.append(config_commands)
return commandset
def del_commands(want,have):
commandset = []
haveconfigs = []
for h in have:
return_command = add_commands(h)
for command in return_command:
command = "no " + command
haveconfigs.append(command)
if want is None or "address_families" not in want.keys():
commandset = haveconfigs
if "address_families" not in want.keys() and "vrf" in want.keys():
commandset = []
for command in haveconfigs:
if want["vrf"] in command:
commandset.append(command)
elif want is not None and "vrf" not in want.keys() and "address_families" not in want.keys():
commandset = []
for command in haveconfigs:
if "vrf" not in command:
commandset.append(command)
elif want["address_families"]:
vrf = want["vrf"] if "vrf" in want.keys() and want["vrf"] else None
for address_family in want["address_families"]:
if "routes" not in address_family.keys():
for command in haveconfigs:
afi = "ip " if address_family["afi"] == "ipv4" else "ipv6"
if afi in command:
if vrf:
if vrf in command:
commandset.append(command)
else:
commandset.append(command)
else:
for route in address_family["routes"]:
if not re.search(r'/', route["dest"]):
mask = route["dest"].split( )[1]
cidr = get_net_size(mask)
destination = route["dest"].split( )[0] + '/' + cidr
else:
destination = route["dest"]
if "next_hops" not in route.keys():
for command in haveconfigs:
if destination in command:
if vrf:
if vrf in command:
commandset.append(command)
else:
commandset.append(command)
else:
for next_hop in route["next_hops"]:
commands = []
if address_family["afi"] == "ipv4":
commands.append('no ip route')
else:
commands.append('no ipv6 route')
if vrf:
commands.append(' vrf ' + vrf)
commands.append(' ' + destination)
commands.append(' ' + next_hop["interface"])
if "forward_router_address" in next_hop.keys():
commands.append(' ' + next_hop["forward_router_address"])
if "mpls_label" in next_hop.keys():
commands.append(' label ' + str(next_hop["mpls_label"]))
if "track" in next_hop.keys():
commands.append(' track '+next_hop["track"])
if "admin_distance" in next_hop.keys():
commands.append(' '+str(next_hop["admin_distance"]))
if "description" in next_hop.keys():
commands.append(' name '+str(next_hop["description"]))
if "tag" in next_hop.keys():
commands.append(' tag '+str(next_hop["tag"]))
config_commands = "".join(commands)
commandset.append(config_commands)
return commandset
def get_net_size(netmask):
binary_str = ''
netmask = netmask.split('.')
for octet in netmask:
binary_str += bin(int(octet))[2:].zfill(8)
return str(len(binary_str.rstrip('0')))
def get_vrf(config):
vrf = ""
for c in config:
vrf = c["vrf"] if "vrf" in c.keys() and c["vrf"] else "default"
return vrf

@ -21,6 +21,8 @@ from ansible.module_utils.network.eos.facts.lldp_global.lldp_global import Lldp_
from ansible.module_utils.network.eos.facts.lldp_interfaces.lldp_interfaces import Lldp_interfacesFacts
from ansible.module_utils.network.eos.facts.vlans.vlans import VlansFacts
from ansible.module_utils.network.eos.facts.legacy.base import Default, Hardware, Config, Interfaces
from ansible.module_utils.network.eos.facts.static_routes.static_routes import Static_routesFacts
FACT_LEGACY_SUBSETS = dict(
@ -39,6 +41,7 @@ FACT_RESOURCE_SUBSETS = dict(
lldp_global=Lldp_globalFacts,
lldp_interfaces=Lldp_interfacesFacts,
vlans=VlansFacts,
static_routes=Static_routesFacts,
)

@ -0,0 +1,202 @@
#
# -*- coding: utf-8 -*-
# Copyright 2019 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""
The eos static_routes fact class
It is in this file the configuration is collected from the device
for a given resource, parsed, and the facts tree is populated
based on the configuration.
"""
import re
from copy import deepcopy
from ansible.module_utils.network.common import utils
from ansible.module_utils.network.eos.argspec.static_routes.static_routes import Static_routesArgs
class Static_routesFacts(object):
""" The eos static_routes fact class
"""
def __init__(self, module, subspec='config', options='options'):
self._module = module
self.argument_spec = Static_routesArgs.argument_spec
spec = deepcopy(self.argument_spec)
import q
if subspec:
if options:
facts_argument_spec = spec[subspec][options]
else:
facts_argument_spec = spec[subspec]
else:
facts_argument_spec = spec
self.generated_spec = utils.generate_dict(facts_argument_spec)
def get_device_data(self, connection):
return connection.get('show running-config | grep route')
def populate_facts(self, connection, ansible_facts, data=None):
""" Populate the facts for static_routes
:param connection: the device connection
:param ansible_facts: Facts dictionary
:param data: previously collected conf
:rtype: dictionary
:returns: facts
"""
if not data:
data = self.get_device_data(connection)
import q
# split the config into instances of the resource
resource_delim = 'ip.* route'
find_pattern = r'(?:^|\n)%s.*?(?=(?:^|\n)%s|$)' % (resource_delim,
resource_delim)
resources = [p.strip() for p in re.findall(find_pattern, data)]
resources_without_vrf = []
resource_vrf = {}
for resource in resources:
if resource and "vrf" not in resource:
resources_without_vrf.append(resource)
else:
vrf = re.search(r'ip(v6)* route vrf (.*?) .*',resource)
if vrf.group(2) in resource_vrf.keys():
vrf_val = resource_vrf[vrf.group(2)]
vrf_val.append(resource)
resource_vrf.update({vrf.group(2): vrf_val})
else :
resource_vrf.update({vrf.group(2): [resource]})
resources_without_vrf = ["\n".join(resources_without_vrf)]
for vrf in resource_vrf.keys():
vrflist = ["\n".join(resource_vrf[vrf])]
resource_vrf.update({vrf: vrflist})
objs = []
for resource in resources_without_vrf:
if resource:
obj = self.render_config(self.generated_spec, resource)
if obj:
objs.append(obj)
for resource in resource_vrf.keys():
if resource:
obj = self.render_config(self.generated_spec, resource_vrf[resource][0])
if obj:
objs.append(obj)
ansible_facts['ansible_network_resources'].pop('static_routes', None)
facts = {}
if objs:
facts['static_routes'] = []
params = utils.validate_config(self.argument_spec, {'config': objs})
for cfg in params['config']:
facts['static_routes'].append(utils.remove_empties(cfg))
ansible_facts['ansible_network_resources'].update(facts)
return ansible_facts
def render_config(self, spec, conf):
"""
Render config as dictionary structure and delete keys
from spec for null values
:param spec: The facts tree, generated from the argspec
:param conf: The configuration
:rtype: dictionary
:returns: The generated config
"""
config = deepcopy(spec)
import q
address_family_dict = {}
route_dict = {}
dest_list = []
afi_list = []
vrf_list = []
routes = []
vrf_config_list = []
config["address_families"] = []
next_hops = {}
interface_list = ["Ethernet", "Loopback", "Management", "Nexthop-Group",
"Port-Channel", "Tunnel", "Vlan", "Vxlan", "vtep"]
conf_list = conf.split('\n')
for conf_elem in conf_list:
matches = re.findall(r'(ip|ipv6) route ([\d\.\/:]+|vrf) (.+)$', conf_elem)
if matches:
remainder = matches[0][2].split()
route_update = False
if matches[0][1] == "vrf":
vrf = remainder.pop(0)
# new vrf
if vrf not in vrf_list and vrf_list:
route_dict.update({"next_hops": next_hops})
routes.append(route_dict)
address_family_dict.update({"routes": routes})
config["address_families"].append(address_family_dict)
route_update = True
config.update({"vrf": vrf})
vrf_list.append(vrf)
dest = remainder.pop(0)
else:
config["vrf"] = "default"
dest = matches[0][1]
afi = "ipv4" if matches[0][0] == "ip" else "ipv6"
if afi not in afi_list:
if afi_list and not route_update:
# new afi and not the first updating all prev configs
route_dict.update({"next_hops": next_hops})
routes.append(route_dict)
address_family_dict.update({"routes": routes})
config["address_families"].append(address_family_dict)
route_update = True
address_family_dict = {}
address_family_dict.update({"afi": afi})
routes = []
afi_list.append(afi)
# To check the format of the dest
prefix = re.search(r'/', dest)
if not prefix:
dest = dest + ' ' + remainder.pop(0)
if dest not in dest_list:
# For new dest and not the first dest
if dest_list and not route_update:
route_dict.update({"next_hops": next_hops})
routes.append(route_dict)
dest_list.append(dest)
next_hops = []
route_dict = {}
route_dict.update({"dest": dest})
nexthops = {}
nxthop_addr = re.search(r'[\.\:]', remainder[0])
if nxthop_addr:
nexthops.update({"interface": remainder.pop(0)})
if remainder and remainder[0] == "label":
nexthops.update({"mpls_label": remainder.pop(1)})
remainder.pop(0)
else:
interface = remainder.pop(0)
if interface in interface_list:
interface = interface +" "+ remainder.pop(0)
nexthops.update({"interface": interface})
for attribute in remainder:
forward_addr = re.search(r'([\dA-Fa-f]+[:\.]+)+[\dA-Fa-f]+', attribute)
if forward_addr:
nexthops.update({"forward_router_address": remainder.pop(remainder.index(attribute))})
for attribute in remainder:
for params in ["tag", "name", "track"]:
if attribute == params:
keyname = params
if attribute == "name":
keyname = "description"
nexthops.update({keyname: remainder.pop(remainder.index(attribute)+1)})
remainder.pop(remainder.index(attribute))
if remainder:
metric = re.search(r'\d+', remainder[0])
if metric:
nexthops.update({"admin_distance": remainder.pop(0)})
next_hops.append(nexthops)
route_dict.update({"next_hops": next_hops})
routes.append(route_dict)
address_family_dict.update({"routes": routes})
config["address_families"].append(address_family_dict)
return utils.remove_empties(config)

@ -0,0 +1,363 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright 2019 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#############################################
# WARNING #
#############################################
#
# This file is auto generated by the resource
# module builder playbook.
#
# Do not edit this file manually.
#
# Changes to this file will be over written
# by the resource module builder.
#
# Changes should be made in the model used to
# generate this file or in the resource module
# builder template.
#
#############################################
"""
The module file for eos_static_routes
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'network'
}
DOCUMENTATION = """
---
module: eos_static_routes
version_added: 2.10
short_description: Configures and manages attributes of static routes on Arista EOS platforms.
description: This module configures and manages the attributes of static routes on Arista EOS platforms.
author: Gomathi Selvi Srinivasan (@GomathiselviS)
notes:
options:
config:
description:
- A list of configurations for static routes.
type: list
elements: dict
suboptions:
vrf:
description:
- The VRF to which the static route(s) belong.
type: str
address_families:
description: A dictionary specifying the address family to which the static route(s) belong.
type: list
elements: dict
suboptions:
afi:
description:
- Specifies the top level address family indicator.
type: str
choices: ['ipv4', 'ipv6']
required: True
routes:
description: A dictionary that specifies the static route configurations.
elements: dict
type: list
suboptions:
dest:
description:
- Destination IPv4 subnet (CIDR or address-mask notation).
- The address format is <v4/v6 address>/<mask> or <v4/v6 address> <mask>.
- The mask is number in range 0-32 for IPv4 and in range 0-128 for IPv6.
type: str
required: True
next_hops:
description:
- Details of route to be taken.
type: list
elements: dict
suboptions:
forward_router_address:
description:
- Forwarding router's address on destination interface.
type: str
interface:
description:
- Outgoing interface to take. For anything except 'null0', then next hop IP address should also be configured.
- IP address of the next hop router or
- null0 Null0 interface or
- ethernet e_num Ethernet interface or
- loopback l_num Loopback interface or
- management m_num Management interface or
- port-channel p_num
- vlan v_num
- vxlan vx_num
- Nexthop-Group Specify nexthop group name
- Tunnel Tunnel interface
- vtep Configure VXLAN Tunnel End Points
type: str
admin_distance:
description:
- Preference or administrative distance of route (range 1-255).
type: int
description:
description:
- Name of the static route.
type: str
tag:
description:
- Route tag value (ranges from 0 to 4294967295).
type: int
track:
description:
- Track value (range 1 - 512). Track must already be configured on the device before adding the route.
type: str
mpls_label:
description:
- MPLS label
type: int
vrf:
description:
- VRF of the destination.
type: str
state:
description:
- The state the configuration should be left in.
type: str
choices:
['deleted', 'merged', 'overridden', 'replaced', 'gathered', 'rendered']
default:
merged
"""
EXAMPLES = """
# Using deleted
Before State
-------------
veos(config)#show running-config | grep "route"
ip route 165.10.1.0/24 Ethernet1 100
ip route 172.17.252.0/24 Nexthop-Group testgroup
ip route vrf testvrf 130.1.122.0/24 Ethernet1 tag 50
ipv6 route 5001::/64 Ethernet1 50
veos(config)#
- name: Delete static route configuration
eos_static_routes:
state: deleted
After State
-----------
veos(config)#show running-config | grep "route"
veos(config)#
# Using merged
Before State
-------------
veos(config)#show running-config | grep "route"
ip route 165.10.1.0/24 Ethernet1 100
ip route 172.17.252.0/24 Nexthop-Group testgroup
ip route vrf testvrf 130.1.122.0/24 Ethernet1 tag 50
ipv6 route 5001::/64 Ethernet1 50
veos(config)#
- name: Merge new static route configuration
eos_static_routes:
config:
- vrf: testvrf
address_families:
- afi: ipv6
routes:
- dest: 2211::0/64
next_hop:
- forward_router_address: 100:1::2
interface: "Ethernet1"
state: merged
After State
-----------
veos(config)#show running-config | grep "route"
ip route 165.10.1.0/24 Ethernet1 100
ip route 172.17.252.0/24 Nexthop-Group testgroup
ip route vrf testvrf 130.1.122.0/24 Ethernet1 tag 50
ipv6 route 2211::/64 Ethernet1 100:1::2
ipv6 route 5001::/64 Ethernet1 50
veos(config)#
# Using overridden
Before State
-------------
veos(config)#show running-config | grep "route"
ip route 165.10.1.0/24 Ethernet1 100
ip route 172.17.252.0/24 Nexthop-Group testgroup
ip route vrf testvrf 130.1.122.0/24 Ethernet1 tag 50
ipv6 route 5001::/64 Ethernet1 50
veos(config)#
- name: Overridden static route configuration
eos_static_routes:
config:
- vrf: testvrf
address_families:
- afi: ipv4
routes:
- dest: 150.10.1.0/24
next_hop:
- forward_router_address: 10.1.1.2
interface: "Ethernet1"
state: replaced
After State
-----------
veos(config)#show running-config | grep "route"
ip route 150.10.1.0/24 Ethernet1 10.1.1.2
veos(config)#
# Using replaced
Before State
-------------
veos(config)#show running-config | grep "route"
ip route 165.10.1.0/24 Ethernet1 100
ip route 172.17.252.0/24 Nexthop-Group testgroup
ip route vrf testvrf 130.1.122.0/24 Ethernet1 tag 50
ipv6 route 5001::/64 Ethernet1 50
veos(config)#
- name: Replace static route configuration
eos_static_routes:
config:
- vrf: testvrf
address_families:
- afi: ipv4
routes:
- dest: 165.10.1.0/24
next_hop:
- forward_router_address: 10.1.1.2
interface: "Ethernet1"
state: replaced
After State
-----------
veos(config)#show running-config | grep "route"
ip route 165.10.1.0/24 Ethernet1 10.1.1.2
ip route 172.17.252.0/24 Nexthop-Group testgroup
ip route vrf testvrf 130.1.122.0/24 Ethernet1 tag 50
ipv6 route 2211::/64 Ethernet1 100:1::2
ipv6 route 5001::/64 Ethernet1 50
veos(config)#
Before State
-------------
veos(config)#show running-config | grep "route"
ip route 165.10.1.0/24 Ethernet1 10.1.1.2 100
ipv6 route 5001::/64 Ethernet1
veos(config)#
- name: Gather the exisitng condiguration
eos_static_routes:
state: gathered
returns :
eos_static_routes:
config:
- address_families:
- afi: ipv4
routes:
- dest: 165.10.1.0/24
next_hop:
- forward_router_address: 10.1.1.2
interface: "Ethernet1"
admin_distance: 100
- afi: ipv6
routes:
- dest: 5001::/64
next_hop:
- interface: "Ethernet1"
# Using rendered
i eos_static_routes:
config:
- address_families:
- afi: ipv4
routes:
- dest: 165.10.1.0/24
next_hop:
- forward_router_address: 10.1.1.2
interface: "Ethernet1"
admin_distance: 100
- afi: ipv6
routes:
- dest: 5001::/64
next_hop:
- interface: "Ethernet1"
returns:
ip route 165.10.1.0/24 Ethernet1 10.1.1.2 100
ipv6 route 5001::/64 Ethernet1
"""
RETURN = """
before:
description: The configuration prior to the model invocation.
returned: always
sample: >
The configuration returned will always be in the same format
of the parameters above.
after:
description: The resulting configuration model invocation.
returned: when changed
sample: >
The configuration returned will always be in the same format
of the parameters above.
commands:
description: The set of commands pushed to the remote device.
returned: always
type: list
sample: ['command 1', 'command 2', 'command 3']
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.eos.argspec.static_routes.static_routes import Static_routesArgs
from ansible.module_utils.network.eos.config.static_routes.static_routes import Static_routes
def main():
"""
Main entry point for module execution
:returns: the result form module invocation
"""
module = AnsibleModule(argument_spec=Static_routesArgs.argument_spec,
supports_check_mode=True)
result = Static_routes(module).execute_module()
module.exit_json(**result)
if __name__ == '__main__':
main()
Loading…
Cancel
Save