aristanetworks / avd

Arista Validated Designs
https://avd.arista.com
Apache License 2.0
278 stars 201 forks source link

Switchport configuration not done if member of channel-group #211

Closed jonnic closed 3 years ago

jonnic commented 4 years ago

Issue Type

Summary

If an ethernet interface is configured to be part of a port-channel then the switchport configuration is not run.

Role or Module Name

eos_cli_config_gen/templates/eos/ethernet-interfaces.j2

arista.avd collection and Python libraries version

ansible 2.9.7
  config file = /home/jjn/ansible-cvp/ansible-avd-cloudvision-demo/ansible.cfg
  configured module search path = ['/home/jjn/ansible-cvp/ansible-avd-cloudvision-demo/ansible-avd/library']
  ansible python module location = /home/jjn/ansible-cvp/ansible-avd-cloudvision-demo/venv/lib/python3.6/site-packages/ansible
  executable location = /home/jjn/ansible-cvp/ansible-avd-cloudvision-demo/venv/bin/ansible
  python version = 3.6.9 (default, Jul 17 2020, 12:50:27) [GCC 8.4.0]
ansible==2.9.7
certifi==2020.4.5.1
cffi==1.14.0
chardet==3.0.4
click==7.1.2
cryptography==2.9.2
fontawesome-markdown==0.2.6
future==0.18.2
idna==2.8
Jinja2==2.11.2
joblib==0.14.1
livereload==2.6.1
lunr==0.5.6
Markdown==3.2.1
MarkupSafe==1.1.1
mkdocs==1.1
mkdocs-bootswatch==1.1
mkdocs-material==5.1.1
mkdocs-material-extensions==1.0b2
mkdocs-rtd-dropdown==1.0.2
mkdocs-windmill==1.0.4
netaddr==0.7.19
nltk==3.5
pkg-resources==0.0.0
pycparser==2.20
Pygments==2.6.1
pymdown-extensions==7.1
PyYAML==5.3.1
regex==2020.4.4
requests==2.22.0
six==1.14.0
tornado==6.0.4
tqdm==4.46.0
treelib==1.5.5
urllib3==1.25.9

This is working on the development branch of avd commit 15f74e30371c89cd563a5c6fb533818fa47ded89

YAML input:-


  Ethernet28/2:
    description: node-1-1-6
    speed: 25gfull
    type: switched
    mode: trunk
    channel_group:
      id: 1025
      mode: active

The switchport mode trunk which we'd expect to see in the output is not present.

I believe that the fix is to move the switchport configuration to before the channel group definition in the template:-

diff --git a/ansible_collections/arista/avd/roles/eos_cli_config_gen/templates/eos/ethernet-interfaces.j2 b/ansible_collections/arista/avd/roles/eos_cli_config_gen/templates/eos/ethernet-interfaces.j2
index 98b9106..276b2a0 100644
--- a/ansible_collections/arista/avd/roles/eos_cli_config_gen/templates/eos/ethernet-interfaces.j2
+++ b/ansible_collections/arista/avd/roles/eos_cli_config_gen/templates/eos/ethernet-interfaces.j2
@@ -11,20 +11,7 @@ interface {{ ethernet_interface }}
 {%         if ethernet_interfaces[ethernet_interface].speed is defined and ethernet_interfaces[ethernet_interface].speed is not none %}
    speed forced {{ ethernet_interfaces[ethernet_interface].speed }}
 {%         endif %}
-{%         if ethernet_interfaces[ethernet_interface].channel_group is defined and ethernet_interfaces[ethernet_interface].channel_group is not none %}
-   channel-group {{ ethernet_interfaces[ethernet_interface].channel_group.id }} mode {{ ethernet_interfaces[ethernet_interface].channel_group.mode }}
-{%         else %}
-{%             if ethernet_interfaces[ethernet_interface].mtu is defined and ethernet_interfaces[ethernet_interface].mtu != 1500 %}
-   mtu {{ ethernet_interfaces[ethernet_interface].mtu }}
-{%             endif %}
-{%             if ethernet_interfaces[ethernet_interface].type is defined and ethernet_interfaces[ethernet_interface].type == "routed" %}
-   no switchport
-{%             endif %}
-{%             if ethernet_interfaces[ethernet_interface].flowcontrol is defined and ethernet_interfaces[ethernet_interface].flowcontrol is not none %}
-{%                 if ethernet_interfaces[ethernet_interface].flowcontrol.received is defined and ethernet_interfaces[ethernet_interface].flowcontrol.received is not none %}
-   flowcontrol receive {{ ethernet_interfaces[ethernet_interface].flowcontrol.received }}
-{%                 endif %}
-{%             endif %}
+{%         if ethernet_interfaces[ethernet_interface].type is defined and ethernet_interfaces[ethernet_interface].type == "switched" %}
 {%             if ethernet_interfaces[ethernet_interface].mode is defined and ethernet_interfaces[ethernet_interface].mode == "access" %}
    switchport access vlan {{ ethernet_interfaces[ethernet_interface].vlans }}
 {%             endif %}
@@ -42,6 +29,21 @@ interface {{ ethernet_interface }}
    switchport trunk group {{ trunk_group }}
 {%                 endfor %}
 {%             endif %}
+{%         endif %}
+{%         if ethernet_interfaces[ethernet_interface].channel_group is defined and ethernet_interfaces[ethernet_interface].channel_group is not none %}
+   channel-group {{ ethernet_interfaces[ethernet_interface].channel_group.id }} mode {{ ethernet_interfaces[ethernet_interface].channel_group.mode }}
+{%         else %}
+{%             if ethernet_interfaces[ethernet_interface].mtu is defined and ethernet_interfaces[ethernet_interface].mtu != 1500 %}
+   mtu {{ ethernet_interfaces[ethernet_interface].mtu }}
+{%             endif %}
+{%             if ethernet_interfaces[ethernet_interface].type is defined and ethernet_interfaces[ethernet_interface].type == "routed" %}
+   no switchport
+{%             endif %}
+{%             if ethernet_interfaces[ethernet_interface].flowcontrol is defined and ethernet_interfaces[ethernet_interface].flowcontrol is not none %}
+{%                 if ethernet_interfaces[ethernet_interface].flowcontrol.received is defined and ethernet_interfaces[ethernet_interface].flowcontrol.received is not none %}
+   flowcontrol receive {{ ethernet_interfaces[ethernet_interface].flowcontrol.received }}
+{%                 endif %}
+{%             endif %}
 {%             if ethernet_interfaces[ethernet_interface].qos.trust is defined and ethernet_interfaces[ethernet_interface].qos.trust is not none %}
    qos trust {{ ethernet_interfaces[ethernet_interface].qos.trust }}
 {%             endif %}

This produces the desired results in my testing.

carlbuchmann commented 4 years ago

@jonnic - Thank you for raising this issue, and you interested in ansible-avd!

This is the intended behavior, as in Arista EOS when an interface belongs to a port-channel, the switchport configuration is only required on the parent Port-Channel interface. This is why in the automated document eos_cli_config_gen provides this additional information in the tables.

Example:

interface Port-Channel10
   description HostC_bond0
   switchport access vlan 30
   mlag 10
   spanning-tree portfast
!
interface Port-Channel11
   description HostE_bond0
   switchport access vlan 20
   mlag 11
   spanning-tree portfast
!
interface Ethernet10
   description HostC_eth0
   channel-group 10 mode active
!
interface Ethernet11
   description HostE_eth0
   channel-group 11 mode active

reference:

If you have additional questions, please feel free to reach out to ansible@arista.com

jonnic commented 4 years ago

Thanks for looking at this. There are a couple of scenarios where we require the underlying interface to have a switchport configuration as well as the port-channel.

  1. We've encountered a bug in EOS (BUG412920) that where when committing a configuration from a config session the order in which trunk groups gets applied is "racey" which can result in the wrong trunk group being applied on an interface. The work-around is to configure the underlying ethernet port with the same switchport configuration as the portchannel. This may have been addressed in the latest eos code.

  2. We want to be able to use lacp failback to allow hosts to be provisioned on the interface, in production the interface will be a trunk on a bonded port. However for the initial PXE boot to work LACP failback individual will mean that the configuration from the individual ethernet ports will be used, these will be configured to be on an access port for the provisioning service.

carlbuchmann commented 4 years ago

@jonnic, thanks for this clarification, re-opened issue, and tracking this as an enhancement to support this use case.

  1. EOS BUG412920 is fixed in the following releases: 4.21.9M, 4.22.3M, 4.23.1F
  2. You are correct, support for lacp failback requires the Ethernet interface to be configured accordingly.
github-actions[bot] commented 3 years ago

This issue is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 15 days

carlbuchmann commented 3 years ago

@jonnic lcap failback has been added with PR #852, with recommended approach in eos_designs.