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.
| Component | Why |
|---|---|
| netlab 26.08 | Renders the topology and calls containerlab |
| containerlab and docker | Start the nodes |
netlab/ze:latest |
The lab image, built from docker/Dockerfile.lab |
The lab image is not the deployment image. See Docker for the two images and what separates them.
docker build -t netlab/ze:latest -f docker/Dockerfile.lab .contrib/netlab/ze.yml sets clab.build: False and names
netlab/ze:latest, so netlab starts this image and builds nothing. Change its
image: value when you choose a different Docker tag.
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/zeOr leave the netlab install alone and let a topology carry them, which is what
./le test netlab render-check does. netlab reads a topology-defaults.yml beside the
topology and a templates/ze/ directory beside it.
netlab up -t contrib/netlab/topology.ymlcontrib/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.
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 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.
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 ./le test 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.
./le test netlab render-checkIt renders the templates with a real netlab, compares the result with
contrib/netlab/golden/, and runs ze config validate on each golden file. A
missing netlab is an error exit, never a skip. Use
./le test netlab render-update to rewrite 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.