cisco.ios icon indicating copy to clipboard operation
cisco.ios copied to clipboard

add vrf support to L3 interfaces

Open bentole opened this issue 2 years ago • 6 comments

SUMMARY

Adds VRF support to L3 interfaces

  • Include VRF info in Facts. Fixes #653
  • VRF Interface assignment
  • Optional restoration of removed commands
  • Legacy support
ISSUE TYPE
  • Feature Pull Request
COMPONENT NAME

ios.ios_l3_interfaces ios.ios_vrf

ADDITIONAL INFORMATION

Background

Ok, trying to be brief. I was recently tasked by a customer of mine to automate changing vrfs on interfaces on hundres of routers. The interfaces were to keep same addressing and configuration as before the vrf change.

I find there's a lot regarding VRFS that I feel is missing so I updated ios.l3_interfaces in my fork with features necessary to complete the task. I'm now putting this up here for review and debate in case there's any interest of having some isotope of it merged

The features I've added or modified are:

FACTS

As far as I can see, neither ios_vrf or l3_interfaces provides VRF facts. This is kind of surprising since a large number of routers today, if not most of them, use vrfs. ios.l3_interfaces provides ip adressing information, but not vrf information. Addng vrfs to the l3_interfaces facts will make the module much more attractive and useable.

VRF INTERFACE CONFIGURATION

My original plan was to be a slacker and not do anything beyond the facts since ios.ios_vrf already has the option to assign vrfs to interfaces. But after some pondering I concluded that it doesn't sit right that interface assignment is handled by ios.ios_vrf. My humble opinion is that ios.ios_vrf should handle vrf definitions and ios.l3_interfaces should handle assignments. This would more correctly reflect how vrfs are configured on routers as well.

Example:

# Not like this. Not to critize though, its very convenient :)
- name: assign interface to vrf
  cisco.ios.ios_vrf:
    name: test_vrf
    interfaces:
      - GigabitEthernet5

# Proper way. IMHO
- name: vrf definition
  cisco.ios.ios_vrf:
    name: test_vrf

- name: apply to interface
  ios_l3_interfaces:
    config:
      - name: GigabitEthernet5
      	vrf: test_vrf
    state: merged

RESTORATION

Changing vrfs on interfaces removes the assigned ip address and ip addresses used for FHRP (HSRP,GLBP), multicast/igmp-joins etc. I noticed that ios.ios_vrf automatically reapplies/restores the ip/ipv6 address(es) when assigning vrfs to interfaces, BUT this automacy contradicts Ciscos behavior of removing the configuration in the first place. Not removing this configuration could in fact be quite dangerous. At least in theory.

It's very convenient that addresses are restored, but it should be a choice made by the user, due to the potential risk involved. In addition, ios.ios_vrf restores the ip/ipv6 address command, but it does not restore other removed commands like the HSRP address. After some back and forth I ended up implementing a code that follows the following principles for restoration

  • Automatically restore configuration that is part of the play/intent. Makes sense!
  • Do not restore commands negated by the play. Well, Duh...
  • Restore commands only if the restore_commands option is set, which defaults to false to "comply" with Cisco behavior. Ha!

This is probably better explained by example:

# Before state

interface GigabitEthernet5
 ip address 192.168.0.2 255.255.255.0
 ip address 169.254.1.2 255.255.255.0 secondary
 ipv6 address 2001:db8::1/64
 standby 1 ip 192.168.0.1

# Play

- name: apply to interface
  ios_l3_interfaces:
    restore_commands: false
    config:
      - name: GigabitEthernet5
      	vrf: test_vrf
      	ipv4:
      	  - address: 192.168.0.2/24
      	ipv6:
      	  - address: 2001:db8::1/64
    state: merged

# After state

interface GigabitEthernet5
 vrf forwarding test_vrf
 ip address 192.168.0.2 255.255.255.0
 ipv6 address 2001:db8::1/64

The remote_command option is set to false (default), but the primary ip/ipv6 addresses are still restored since they are part of the play. The secondary & hsrp addresses are not restored. Running the same play with restore_commands set to true would restore all commands.

LEGACY SUPPORT

There are two ways to configure vrfs. vrf definition vs ip vrf. The latter, is considered legacy, and does not support ipv6, but there might be alot of peeps out there who still use the legacy way for various reasons. To complicate things further, the legacy way has the possibility of running ipv4 in a vrf and ipv6 globally. Finally, I can't find any documentation at cisco where they mention they plan to deprecate the legacy way so decided to add support for this as well.

Legacy way breaks the symbiosis with ios.ios_vrf since that module uses vrf definition. A vrf created using vrf definition, MUST use vrf forwarding when applied to an interface. A vrf created using ip vrf, MUST use ip vrf forwarding. IOS returns an error if the oposite is attempted.

I guess legacy way could be used for migrating to the new syntax, but Cisco already has a command for this called vrf upgrace-cli. This command does not merge ipv6 into the vrf though.

Hmm, I just realised that I might have just argued myself away from implementing this, but it's already done so here's an example using legacy way

# Before state

interface GigabitEthernet5
 ip address 192.168.0.2 255.255.255.0
 ipv6 address 2001:db8::1/64
 standby 1 ip 192.168.0.1

# Play

- name: apply to interface
  ios_l3_interfaces:
    restore_commands: false
    config:
      - name: GigabitEthernet5
      	ipv4:
      	  - vrf test_vrf
      	  - address: 192.168.0.2/24
    state: merged

# After state

interface GigabitEthernet5
 ip vrf forwarding test_vrf
 ip address 192.168.0.2 255.255.255.0
 ipv6 address 2001:db8::1/64

Pay attention to the ipv6 address. It was not part of the play and restore_commands is set to false, yet it's still present! Since ip vrf forwarding does not support ipv6, the ipv6 address is not removed when the vrf is applied. This interface now operates ipv4 in the test_vrf routing table and ipv6 in global routing table.

bentole avatar Jan 13 '23 08:01 bentole

Build failed.

:heavy_check_mark: ansible-galaxy-importer SUCCESS in 4m 03s :heavy_check_mark: build-ansible-collection SUCCESS in 4m 13s :x: ansible-ee-integration-ios-latest FAILURE in 16m 55s (non-voting) :x: ansible-ee-integration-ios-stable-2.9 NODE_FAILURE in 0s (non-voting) :x: ansible-ee-integration-ios-stable-2.11 FAILURE in 17m 28s (non-voting) :x: ansible-ee-integration-ios-stable-2.12 NODE_FAILURE in 0s (non-voting) :x: ansible-ee-integration-ios-libssh-latest FAILURE in 44m 56s (non-voting) :x: ansible-ee-integration-ios-libssh-stable-2.9 NODE_FAILURE in 0s (non-voting) :x: ansible-ee-integration-ios-libssh-stable-2.11 NODE_FAILURE in 0s (non-voting) :x: ansible-ee-integration-ios-libssh-stable-2.12 FAILURE in 43m 14s (non-voting) :x: ansible-tox-linters FAILURE in 5m 07s

Build succeeded.

:heavy_check_mark: ansible-galaxy-importer SUCCESS in 4m 51s :heavy_check_mark: build-ansible-collection SUCCESS in 4m 33s :x: ansible-ee-integration-ios-latest NODE_FAILURE in 0s (non-voting) :x: ansible-ee-integration-ios-stable-2.9 NODE_FAILURE in 0s (non-voting) :x: ansible-ee-integration-ios-stable-2.11 NODE_FAILURE in 0s (non-voting) :x: ansible-ee-integration-ios-stable-2.12 NODE_FAILURE in 0s (non-voting) :x: ansible-ee-integration-ios-libssh-latest NODE_FAILURE in 0s (non-voting) :x: ansible-ee-integration-ios-libssh-stable-2.9 FAILURE in 45m 53s (non-voting) :x: ansible-ee-integration-ios-libssh-stable-2.11 FAILURE in 50m 13s (non-voting) :x: ansible-ee-integration-ios-libssh-stable-2.12 NODE_FAILURE in 0s (non-voting) :heavy_check_mark: ansible-tox-linters SUCCESS in 5m 34s

Build succeeded.

:heavy_check_mark: ansible-galaxy-importer SUCCESS in 4m 38s :heavy_check_mark: build-ansible-collection SUCCESS in 4m 02s :x: ansible-ee-integration-ios-latest FAILURE in 14m 24s (non-voting) :x: ansible-ee-integration-ios-stable-2.9 FAILURE in 14m 53s (non-voting) :x: ansible-ee-integration-ios-stable-2.11 NODE_FAILURE in 0s (non-voting) :x: ansible-ee-integration-ios-stable-2.12 FAILURE in 14m 23s (non-voting) :x: ansible-ee-integration-ios-libssh-latest FAILURE in 43m 20s (non-voting) :x: ansible-ee-integration-ios-libssh-stable-2.9 NODE_FAILURE in 0s (non-voting) :x: ansible-ee-integration-ios-libssh-stable-2.11 NODE_FAILURE in 0s (non-voting) :x: ansible-ee-integration-ios-libssh-stable-2.12 NODE_FAILURE in 0s (non-voting) :heavy_check_mark: ansible-tox-linters SUCCESS in 4m 58s

Codecov Report

Merging #723 (25ad75c) into main (9e2218f) will decrease coverage by 0.37%. The diff coverage is n/a.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #723      +/-   ##
==========================================
- Coverage   85.84%   85.47%   -0.37%     
==========================================
  Files         184      184              
  Lines       11879    11949      +70     
==========================================
+ Hits        10198    10214      +16     
- Misses       1681     1735      +54     

see 2 files with indirect coverage changes

codecov[bot] avatar Aug 30 '23 08:08 codecov[bot]

Build succeeded. https://ansible.softwarefactory-project.io/zuul/buildset/6118a87e37c44d0f8c1c7e3104b4c6e7

:heavy_check_mark: ansible-galaxy-importer SUCCESS in 4m 54s :heavy_check_mark: build-ansible-collection SUCCESS in 8m 40s :x: ansible-ee-integration-ios-latest FAILURE in 13m 37s (non-voting) :x: ansible-ee-integration-ios-stable-2.9 FAILURE in 13m 45s (non-voting) :x: ansible-ee-integration-ios-stable-2.11 FAILURE in 13m 24s (non-voting) :x: ansible-ee-integration-ios-stable-2.12 FAILURE in 13m 46s (non-voting) :x: ansible-ee-integration-ios-libssh-latest FAILURE in 13m 35s (non-voting) :x: ansible-ee-integration-ios-libssh-stable-2.9 FAILURE in 14m 01s (non-voting) :x: ansible-ee-integration-ios-libssh-stable-2.11 FAILURE in 14m 34s (non-voting) :x: ansible-ee-integration-ios-libssh-stable-2.12 FAILURE in 14m 43s (non-voting) :heavy_check_mark: ansible-tox-linters SUCCESS in 10m 09s

Build succeeded. https://ansible.softwarefactory-project.io/zuul/buildset/32baf35993964b199f105e9e5c27d00d

:heavy_check_mark: ansible-galaxy-importer SUCCESS in 4m 48s :heavy_check_mark: build-ansible-collection SUCCESS in 8m 36s :x: ansible-ee-integration-ios-latest FAILURE in 14m 29s (non-voting) :x: ansible-ee-integration-ios-stable-2.9 FAILURE in 17m 40s (non-voting) :x: ansible-ee-integration-ios-stable-2.11 FAILURE in 13m 16s (non-voting) :x: ansible-ee-integration-ios-stable-2.12 FAILURE in 12m 47s (non-voting) :x: ansible-ee-integration-ios-libssh-latest FAILURE in 13m 15s (non-voting) :x: ansible-ee-integration-ios-libssh-stable-2.9 FAILURE in 15m 29s (non-voting) :x: ansible-ee-integration-ios-libssh-stable-2.11 FAILURE in 14m 55s (non-voting) :x: ansible-ee-integration-ios-libssh-stable-2.12 FAILURE in 14m 59s (non-voting) :heavy_check_mark: ansible-tox-linters SUCCESS in 10m 12s

Closing this PR as per the conversation above.

NilashishC avatar Mar 20 '24 10:03 NilashishC