srl-labs / containerlab

container-based networking labs
https://containerlab.dev
BSD 3-Clause "New" or "Revised" License
1.48k stars 251 forks source link

Add option to specify the name of the management interface for cEOS #389

Closed teunvink closed 2 years ago

teunvink commented 3 years ago

On physical Arista EOS switches, the default management interface is called 'Management1'. cEOS containers are generated with 'Management0' as the management interface name. I'd like to be able to specify this name (or switch it to Management1 in some other way) so that I can run my ansible playbooks for my physical (production) switches on my test containers in containerlab as well without modifying them.

I assume this would be a feature request, but if there's already a way to do this that I missed I'd be more than happy to hear so.

karimra commented 3 years ago

Hi,

You can edit the default cEOS config template, but it will be overwritten on next upgrade. It should be located under /etc/containerlab/templates/arista/ Change interface Management0 to interface Management1

hostname {{ .ShortName }}
username admin privilege 15 secret admin
!
service routing protocols model multi-agent
!
interface Management0 
{{ if .MgmtIPv4Address }}ip address {{ .MgmtIPv4Address }}/{{.MgmtIPv4PrefixLength}}{{end}}
{{ if .MgmtIPv6Address }}ipv6 address {{ .MgmtIPv6Address }}/{{.MgmtIPv6PrefixLength}}{{end}}
!
management api gnmi
   transport grpc default
!
management api netconf
   transport ssh default
!
management api http-commands
   no shutdown
!
end

Or you could set a custom template ( written in Go Text Template ), per kind or per node, in your lab file:

topology:
  kinds:
    ceos:
      config: /path/to/custom_ceos.cfg ## <- applies to all nodes with kind ceos
  nodes:
    node1:  
      kind: ceos
      config: /path/to/my/template.cfg ## <- overwrites the config under topology.kinds.ceos.config
teunvink commented 3 years ago

Thanks for the quick response! I tried doing that, but unfortunately that doesn't work. I end up with two management interfaces (Management0 and Management1) in the config, but the device only knows Ma0:

leaf-sw1#show run section Management
interface Management0
!
interface Management1
   ip address 172.20.20.5/24
   ipv6 address 2001:172:20:20::5/64

leaf-sw1#show int desc | inc Ma
Ma0                            up             up

leaf-sw1#sh int Ma1
% Interface does not exist

So the Management1 config statements end up in the config, but it does not result into an interface named Management1.

hellt commented 3 years ago

Hi @teunvink I think that is how cEOS is built, it doesn't allow to have Ma1 to act as a management interface. Will arista people to see if there is an env var that can make Ma1 to act as a management interfaces

teunvink commented 3 years ago

@hellt thanks for the quick response. I've contacted our SE at Arista to see if he has some input on this.

jorisc90 commented 3 years ago

Hi @hellt and @teunvink - the env var you would be looking for is MGMT_INTF. The code seems to have changed a bit since I last checked it out, back then the number of the Ma interface was derived from the Ethernet port that was mapped to it (default Et0 --> Ma0). It seems to have changed since, sadly don't have time to check it out on-the-spot just now.

Attached the (ugly) scripted hack that I used to get this to work in an earlier build - as said it seems like there is a nicer fix in place in the current version. ceoslab-4-24-0f.txt

Used start command and env vars we tried with that test:

/sbin/init systemd.setenv=CEOS=1 systemd.setenv=container=docker systemd.setenv=EOS_PLATFORM=ceoslab systemd.setenv=SKIP_ZEROTOUCH_BARRIER_IN_SYSDBINIT=1 systemd.setenv=ETBA=1 systemd.setenv=INTFTYPE=eth systemd.setenv=MGMT_INTF=Ethernet1

Env variables: CEOS=1 container=docker EOS_PLATFORM=ceoslab SKIP_ZEROTOUCH_BARRIER_IN_SYSDBINIT=1 ETBA=1 INTFTYPE=eth MGMT_INTF=Ethernet1

Can follow up later if required.

jorisc90 commented 3 years ago

Just finished testing cEOS-lab 4.26.0F with scripts I found in my lab environment. We are able to change the management interface, but it requires changes when the containers get initialised. I've attached a script which creates two ceos instances, changes the management interface to ma1 and then starts the containers.

create_ceos.txt

The result is this:

localhost#sh ver cEOSLab Hardware version: Serial number: Hardware MAC address: 0ea4.30b0.e51a System MAC address: 0ea4.30b0.e51a

Software image version: 4.26.0F-21792469.4260F (engineering build) Architecture: i686 Internal build version: 4.26.0F-21792469.4260F Internal build ID: c5b41f65-54cd-44b1-b576-b5c48700ee19

cEOS tools version: 1.1 Kernel version: 5.4.17-17652383.AroraKernelnext.fc18.x86_64

Uptime: 0 weeks, 0 days, 0 hours and 6 minutes Total memory: 4037776 kB Free memory: 2669456 kB localhost#sh int stat Port Name Status Vlan Duplex Speed Type Flags Encapsulation Et1 connected 1 full 1G EbraTestPhyPort Et2 connected 1 full 1G EbraTestPhyPort Et3 connected 1 full 1G EbraTestPhyPort Et4 connected 1 full 1G EbraTestPhyPort Et5 connected 1 full 1G EbraTestPhyPort Ma1 connected routed a-full a-1G 10/100/1000

One other small thing I noted - he ETBA variable was changed to 4 in a previous PR. While this is not bad per-se, there is no change in cEOS-lab behaviour done in this change, the key thing is that the var is set :-)

hellt commented 3 years ago

@jorisc90 thanks I will later show an example how this ENV var can be used in containerlab to start cEOS with this one. So no script will be needed

basically, user needs to use ENV vars and CMD for the ceos kind.

I need to test it, but maybe someone will be quicker

jorisc90 commented 3 years ago

Would be great to have this embedded in containerlab. Sadly my Go skills are not to the level that I will be able to help with the implementation itself...

Please do take note that in addition to changing the ENV var there needs to be an interface within the container namespace that corresponds to this variable, so just the variable won't be enough to make this work.

hellt commented 3 years ago

@jorisc90 does it mean that for cEOS to have Ma1 interface it needs to use eth1 interface instead of eth0? Can't Ma1 use eth0?

jorisc90 commented 3 years ago

The logic currently looks for interfaces matching the following syntax:

It will then first try to match the first maX interface and bind it to maX in the container. If there is no maX it will fall back to eth0, which will then be mapped to ma0 respectively. We can override this logic using the MGMT_INTF variable.

Currently there is no support to map the internal number to another number than the interface in the container namespace; hence the renaming in my script. To get ma1 internally in cEOS-lab, we would either need an interface in the container namespace that is called "Ethernet1", "Eth1", "Et1", or "ma1" - nothing that "Eth1" is already mapped to "Et1" within EOS (so effectively we would have to use ether "Ethernet1", "Et1" or "Ma1" as naming within the container namespace).

hellt commented 3 years ago

ah, ok, I see what you attached. Pasting it here

create_ceos() {
   sudo docker create --name=$1 --privileged -e INTFTYPE=eth -e ETBA=1 -e MGMT_INTF=ma1 -e SKIP_ZEROTOUCH_BARRIER_IN_SYSDBINIT=1 -e CEOS=1 -e EOS_PLATFORM=ceoslab -e container=docker -i -t ceosimage:4.26.0F /sbin/init systemd.setenv=INTFTYPE=eth systemd.setenv=ETBA=1 systemd.setenv=MGMT_INTF=ma1 systemd.setenv=SKIP_ZEROTOUCH_BARRIER_IN_SYSDBINIT=1 systemd.setenv=CEOS=1 systemd.setenv=EOS_PLATFORM=ceoslab systemd.setenv=container=docker
   sudo docker start $1
   sudo docker pause $1
}

connect_ceos() {
   echo "Connecting ${1}:${3} to ${2}:${4}"
   sudo mkdir -p /var/run/netns
   pid1="$(sudo docker inspect -f '{{.State.Pid}}' ${1})"
   pid2="$(sudo docker inspect -f '{{.State.Pid}}' ${2})"
   sudo ln -sf /proc/$pid1/ns/net /var/run/netns/$1
   sudo ln -sf /proc/$pid2/ns/net /var/run/netns/$2

   sudo ip link add $1-$3 type veth peer name $2-$4
   sudo ip link set $1-$3 netns $1
   sudo ip link set $2-$4 netns $2
   sudo ip netns exec $1 ip link set $1-$3 name $3
   sudo ip netns exec $2 ip link set $2-$4 name $4
   sudo ip netns exec $1 ip link set $3 up
   sudo ip netns exec $2 ip link set $4 up
}

change_mgmt() {
   echo "Changing interface name from eth0 to ma1 on ${1}"
   sudo mkdir -p /var/run/netns
   pid1="$(sudo docker inspect -f '{{.State.Pid}}' ${1})"
   sudo ln -sf /proc/$pid1/ns/net /var/run/netns/$1

   sudo ip netns exec $1 ip link set eth0 down
   sudo ip netns exec $1 ip link set eth0 name ma1
   sudo ip netns exec $1 ip link set ma1 up
}

sudo docker stop ceos1 ceos2
sudo docker rm ceos1 ceos2

create_ceos ceos1
create_ceos ceos2

change_mgmt ceos1
change_mgmt ceos2

for i in `seq 1 5`;
do
    connect_ceos ceos1 ceos2 eth$i eth$i
done

sudo docker unpause ceos1
sudo docker unpause ceos2

That seems doable.

I wonder if that needs to be a default - using Ma1 as management interface. @burnyd any input on this?

hellt commented 3 years ago

@jorisc90

thanks for your inputs!

hellt commented 2 years ago

Hi @teunvink @jorisc90 this feature has been added in #787 and will be part of the next release