Guide

netlab

netlab builds a lab from a YAML topology and starts each node under containerlab. Ze runs as one of those nodes. netlab calls this the daemon tier: one YAML file and one directory of Jinja2 templates, with no Ansible task lists and no Vagrant box.

The ze side of that integration lives in contrib/netlab/. contrib/netlab/README.md is the source of truth for the artifacts. This page explains how to run them.

What you need

Component Why
netlab 26.08 Renders the topology and calls containerlab
containerlab and docker Start the nodes
netlab/ze:latest The lab image, built by make ze-docker-lab-build

The lab image is not the deployment image. See Docker for the two images and what separates them.

Step 1: build the image

make ze-docker-lab-build

contrib/netlab/ze.yml sets clab.build: False and image: netlab/ze:latest, so netlab starts this image and builds nothing. ZE_LAB_IMAGE and ZE_LAB_TAG change the name. Change them and change image: in ze.yml to match.

Step 2: give netlab the daemon definition

There are two routes, and contrib/netlab/README.md gives both. Copy the daemon definition and the templates into the netlab package:

cp contrib/netlab/ze.yml  <netlab>/netsim/daemons/ze.yml
cp -R contrib/netlab/ze   <netlab>/netsim/daemons/ze

Or leave the netlab install alone and let a topology carry them, which is what make ze-netlab-render-check does. netlab reads a topology-defaults.yml beside the topology and a templates/ze/ directory beside it.

Step 3: run the reference topology

netlab up -t contrib/netlab/topology.yml

contrib/netlab/topology.yml has three nodes:

r1 ---- internal ---- r2      AS 65001, iBGP + OSPF + IS-IS + BFD
 \
  ---- external ---- r3       AS 65002, eBGP only

netlab runs an IGP on internal links only, so the eBGP peer sits on its own link. r1 also carries two static routes. The topology declares every module ze.yml declares: bgp, ospf, isis, bfd, and routing.

How netlab configures a node

netlab renders contrib/netlab/ze/ze.j2 into one file, /etc/ze/ze.conf, and containerlab bind-mounts it into the node. Ze has no include directive, so one file holds the whole running configuration. Each other module key points at an ignore file that nothing reads.

The node starts with ze start /etc/ze/ze.conf. netlab assigns the interface addresses with ip inside the container, so the rendered configuration carries no interface block.

Ze re-reads its configuration on SIGHUP only. handleSIGHUPReload stages the file as a candidate and reloads it. netlab sends no SIGHUP, and ze.yml says so with features.initial.reload: false. A configuration change in a running lab therefore needs kill -HUP on the ze process inside the node, or a node restart.

netlab validate reads the daemon through the CLI. ze.yml declares the show command as ze cli -c "show $@ | json compact", and netlab runs it with docker exec. An explicit format pipe beats the --format flag, so that command emits JSON.

The lab login

The rendered configuration declares one user, netlab, with the password netlab. ze.yml puts the same pair in the container environment, so the CLI inside the node has a credential. This is a well-known password in a throwaway container. Nothing in ze defaults to it and no image carries it.

The template writes the password as plaintext-password. Ze hashes that leaf when it loads the file, and it warns that the file still holds the secret. See Authentication.

What is proven, and what is not

The lab has never been started on the machine that wrote this integration. That machine has no containerlab, so netlab up and netlab validate were not run. The declared bgp, ospf, isis, bfd, and routing features are rendered and parsed. They are not validated against netlab's own integration tests.

Statement Evidence
netlab accepts the daemon definition and finds a template for each module netlab create exits 0 on the reference topology, in make ze-netlab-render-check
The render is valid ze configuration ze config validate exits 0 on each file under. contrib/netlab/golden/
A daemon runs one of those renders and answers the show command with JSON test/plugin/netlab-lab-profile.ci
Routes reach the FIB of a running lab, and a ping validation passes Not run
Each declared feature passes netlab's integration test for it Not run

Ze also sends and receives no LLDP frame, so a netlab validation that reads LLDP data cannot pass. containerlab does not need LLDP, because the topology names the veth links.

Keeping the templates from drifting

make ze-netlab-render-check

It renders the templates with a real netlab, compares the result against contrib/netlab/golden/, and runs ze config validate on each golden file. A missing netlab is an error exit, never a skip. ARGS=--update rewrites the golden files. test/plugin/netlab-lab-profile.ci is the other half and needs no netlab: it starts a daemon from a golden file and parses the show command output.