netviz import
netviz import brings something from outside the tree into the inventory.
There are two sources, and they are different jobs:
| Form | Reads | Produces |
|---|---|---|
netviz import captures/*.json |
what live devices printed | a devices/ and cables/ tree, written |
netviz import drawio FILE |
a diagram somebody edited in draw.io | a netviz plan changeset, confirmed |
The first is the original signature and needs no sub-command: anything that is
not the name of one is read as a capture file, so netviz import caps/*.json
means what it always did. It is spelled netviz import captures … when you
want to be explicit.
This page is the reference for both. Importing a live network is the task for the first; draw.io round trips is the task for the second, including the one thing a reader most needs — what a draw.io user may and may not safely change.
Contents
- Synopsis
- What it reads
- Naming the host a capture came from
- Writing, and refusing to
- A worked example
netviz import drawio- Arguments
- Options
- Exit codes
- See also
Synopsis
netviz [GLOBAL OPTIONS] import [OPTIONS] COMMAND [ARGS]...
netviz [GLOBAL OPTIONS] import captures [OPTIONS] [NAME=]INPUT...
netviz [GLOBAL OPTIONS] import drawio [OPTIONS] FILE
What it reads
An input is a file, or - for standard input, and several may be given: they are
merged into one inventory. --from names the dialect, and its default auto
sniffs each input on its own, so one run may mix all three:
--from |
Sniffed as | Produced by |
|---|---|---|
lldp |
a JSON object with an lldp (or interface) key |
lldpctl -f json, lldpcli -f json show neighbors; -f json0 is understood too |
iproute |
a JSON array of link records | ip -j link show, ip -j addr show; pass both for one host and they merge |
csv |
anything that is not JSON | any spreadsheet or script that writes device,port,device,port[,medium[,label]] rows |
Sniffing is what makes netviz import collected/* work on a directory holding
all three. An input that is JSON but no capture netviz knows is refused with
the advice to name the dialect; a malformed one is refused with the parser's own
message. What each dialect reads goes
through the three in detail.
--exclude PATTERN leaves out interfaces whose name matches a glob. It applies
to iproute captures, where veth* and docker* are rarely part of a physical
topology, and it is repeatable.
Naming the host a capture came from
An lldpctl or ip capture describes one host and never says which, so the name
comes from the first of these that applies — most explicit first:
NAME=INPUTon the argument:netviz import sw-core=neighbors.json;--host NAME, which applies to every input of the run, so--host pc1 link.json addr.jsonmeans the obvious thing;- the file name up to its first dot:
sw-core-01.lldp.json→sw-core-01.
A name taken from a file name is recorded as such in the generated document. A
capture with no name from any of the three — piped in as - with no --host —
is refused, and so is a --host that is not a legal
element name. A CSV needs none of this: every row
names both of its devices. See
naming the host.
Writing, and refusing to
-o/--output is the inventory root to write into, the current directory by
default; it is created if it does not exist. Files already in that tree are never
overwritten without --force, and every clash is named at once rather than one
per run, because an import is re-run repeatedly while the capture set grows.
--force replaces those files wholesale, hand edits included, so once you have
started editing prefer a fresh directory and a diff.
--dry-run prints the tree to stdout — the same bytes that would be written —
and writes nothing; the run report and the validation findings go to stderr, so
netviz import --dry-run … > tree.yaml keeps the two apart. --schema (the
default) points each document at schema/netviz.schema.json with a
yaml-language-server modeline and writes that schema when the tree does not
already hold one; --no-schema leaves the modeline off.
Re-running on the same captures produces the same bytes, so the command is safe to put in a script.
A worked example
tests/fixtures/import/ holds the captures netviz's own tests import: two LLDP
neighbour tables, one ip -j addr show and a patch list exported from a
spreadsheet. Reading all four in one run — dialects sniffed, hosts named after the
files — gives seven devices and seven cables:
$ netviz import --dry-run --exclude 'veth*' sw-core-01.lldp.json pc-alice.lldp.json srv-hyper.addr.json patch-panel.csv
# ===== devices/ap-lobby.yaml =====
...
# ===== cables/links.yaml =====
...
4 notes about what was not imported:
...
dry run: 8 files would be written to ., plus schema/netviz.schema.json
imported 7 devices and 7 cables from 4 inputs
warnings (15):
...
15 warnings, 1 info
...
Drop --dry-run and add -o net to write it. Three things in that report are
worth reading rather than skipping: the notes say what was left out and why, the
... in the tree hides comments marking everything netviz concluded, and the
closing paragraph names the findings an imported tree is expected to trip. The
whole of importing a live network is about those three.
netviz import drawio
A diagram that came back from draw.io is reconciled by the identity netviz stamped into each cell when it exported it — never by the label and never by the position. Four gestures carry:
| On the canvas | In the inventory |
|---|---|
| a cell moved | a geometry write, and nothing else |
| a label retyped | rename, with every reference to it rewritten |
| a cell deleted | delete, cascading to what cannot survive it |
| two cells newly joined | connect, on the first free port at each end |
Everything becomes a netviz edit operation and is shown as a
netviz plan changeset before a single file is touched. --dry-run
prints the changeset and the diff and writes nothing; without --auto-approve
you are asked to confirm.
--view is read from the file and is needed only for a diagram netviz did not
export. --geometry/--no-geometry, --renames/--no-renames,
--deletions/--no-deletions and --connections/--no-connections each turn
one of the four gestures off. --name, --namespace and --file say where new
geometry is written; geometry for something an existing layout document already
places goes back into that document. --force writes even if the result would
introduce a new validation error, and --json reports the notes and the session
as JSON.
A cell that is simply missing is a deletion only when the file says it held the
whole view. Export narrowed by --namespace and nothing is ever deleted on the
strength of it: absence proves nothing about a diagram that was filtered before
it was drawn. A file netviz did not export carries no identity at all, so
nothing is reconciled; it is read anyway and reported cell by cell, with the kind
each one looks like, and netviz will not invent hardware from a rectangle.
$ netviz export drawio -o site.drawio # hand this out
$ netviz import drawio site.drawio -n # see what came back
$ netviz import drawio site.drawio # apply it
Arguments
| Argument | Required | Count | Default |
|---|---|---|---|
[NAME=]INPUT... |
no | any number | — |
| Argument | Required | Count | Default |
|---|---|---|---|
FILE |
yes | 1 | — |
Options
netviz import captures
| Flag | Value | Default | Meaning |
|---|---|---|---|
--from |
[auto|lldp|iproute|csv|netplan|networkd|ifupdown|frr|nftables|wireguard|interfaces] |
auto |
Input dialect. 'auto' sniffs each input on its own, so one run may mix all ten: lldp is 'lldpctl -f json', iproute is 'ip -j link show' or 'ip -j addr show', csv is 'device,port,device,port' cabling rows, and netplan, networkd, ifupdown, frr, nftables, wireguard and interfaces are a device's running configuration in the same dialects 'netviz export' writes. |
--host |
NAME |
— | Device every input was captured on. An lldp or iproute capture never names its own host. Without this the name comes from the file name, or from a 'NAME=path' argument. |
-o, --output |
DIRECTORY |
current directory | Inventory root to write the devices/ and cables/ tree into. |
--dry-run |
— | off | Print the tree to stdout and write nothing. |
--force |
— | off | Overwrite files that are already in the output tree. Without it they are refused. |
--schema, --no-schema |
— | --schema |
Point each generated document at schema/netviz.schema.json with a yaml-language-server modeline, writing the schema when the tree does not already hold one. |
--exclude |
PATTERN |
— | Leave out interfaces whose name matches this glob. Applies to 'iproute' captures, where 'veth*' and 'docker*' are rarely part of a physical topology. Repeatable. |
netviz import drawio
| Flag | Value | Default | Meaning |
|---|---|---|---|
--view |
[physical|l1|l2|l3|ipam|overlay|routing|rack|power|identity|netns|security] |
the view the file says it was exported from | Which view the diagram draws. Read from the file for anything netviz exported; needed only for a diagram netviz did not write. |
--geometry, --no-geometry |
— | --geometry |
Carry cells that were dragged back as stored geometry. |
--renames, --no-renames |
— | --renames |
Carry a retyped label back as a rename, rewriting every reference to it. |
--deletions, --no-deletions |
— | --deletions |
Carry a deleted cell back as a deleted element. Never applied to a diagram that was exported from a filtered view, whichever way this is set. |
--connections, --no-connections |
— | --connections |
Carry an edge drawn in draw.io back as a cable on the first free port at each end. |
--name |
NAME |
layout |
metadata.name of the layout document new geometry goes into. Geometry for something an existing layout already places is written back into that one instead. |
--namespace |
PATH |
— | Folder to declare a new layout document in. The inventory root by default. |
--file |
PATH |
— | File to write a new layout document to. Chosen by the layout conventions when absent. |
--auto-approve |
— | off | Do not ask before writing. For automation; a person should read the changeset first. |
-n, --dry-run |
— | off | Write nothing; print the changeset and the unified diff it would produce. |
--force |
— | off | Write even if the result would introduce new validation errors. |
--json |
— | off | Report as JSON. |
Exit codes
| Code | Meaning |
|---|---|
| 0 | The tree was written (or printed) and holds no error-level finding. |
| 1 | The generated tree does not validate, or nothing could be imported from the inputs at all. The files are still written, so you can see what went wrong. |
| 2 | Usage error, or an unusable netviz.toml. |
| 3 | An input was missing, unreadable, not UTF-8, oversized, not the dialect it was given as — or a file in the output tree would have been clobbered without --force. import drawio also uses it for a file that is not a draw.io diagram it can read. |
Warnings and infos do not fail the run: an imported inventory is partial by
construction and
legitimately has findings.
The configuration that decides which of them are reported is the output tree's
netviz.toml, not the working directory's, so importing into a tree that
already ignores a rule does not produce a report contradicting it.
See also
- Importing a live network — what to collect, what is inferred and what to fix afterwards.
netviz init— a first tree for a network that does not exist yet.netviz fmt— put the generated YAML into the canonical form before committing it.netviz validate— the same checkimportruns, on demand.- draw.io round trips — handing a diagram out, and what comes back.
netviz export— the other half of the round trip,export drawio.