Boxen
put your network operating systems in a box!
Install / Use
/learn @carlmontanari/BoxenREADME
boxen -- put your network operating systems in a box (or if you speak 🇩🇪, fight them! 🤣)!
boxen is a cli tool written in Go that allows you to package your network operating systems neatly into little... boxes (container images) so they are easily portable, and, most importantly, so you can use them with the wonderful containerlab. boxen also provides some basic functionality for running network operating systems on your local machine (without containers) -- even on Darwin systems (for platforms that work with HVF/HAX or no acceleration).
Please note that this is a work in progress... especially the documentation!
Key Features:
- Easy: It's easy to get going with boxen -- grab your network operating systems qcow2 disk and point boxen to it!
- Native VMs: Containers are cool, but sometimes (especially for Darwin systems) it is nice to launch network operating system VMs without containers/GUIs/etc. -- boxen has you covered!
- Containerlab: Love containerlab? Of course you do! We do too -- boxen was built to be used to package network operating systems up neatly for containerlab to orchestrate, it's a great match!
Supported Platform Types
- Arista
- vEOS (tested with 4.22.1F)
- Cisco
- CSR1000v (tested with 16.12.03)
- N9Kv (tested with 9.2.4)
- XRv9K (tested with 6.5.3)
- Juniper
- vSRX (tested with 17.3R2.10)
- Palo Alto
- PA-VM (tested with 10.0.6)
- Checkpoint
- Cloudguard (tested with R81.10)
Additional platforms can of course be added!
Installation
The simplest way to install boxen is to use the installation script:
# download and install the latest release
bash -c "$(curl -sL https://raw.githubusercontent.com/carlmontanari/boxen/main/get.sh)"
# download a specific version - 0.0.1
bash -c "$(curl -sL https://raw.githubusercontent.com/carlmontanari/boxen/main/get.sh)" -- -v 0.0.1
# with wget
bash -c "$(wget -qO - https://raw.githubusercontent.com/carlmontanari/boxen/main/get.sh)"
Packaging For Containerlab
Packaging images for use with containerlab is easy! Snag the appropriate vmdk/qcow2 for your
platform of choice, and of course boxen. With those two things done, all you need to do is to run
boxen with the package command, and provide a disk to the --disk flag.
$ boxen package --disk ~/disks/nxosv.9.2.4.qcow2
info 1640884754 package requested for disk 'nxosv.9.2.4.qcow2'
debug 1640884754 temporary directory '/tmp/boxen2756986238' created successfully
debug 1640884755 disks allocated for packaging
debug 1640884755 packaging instance created
debug 1640884756 bundling required packaging files complete
debug 1640884756 pre packaging complete, begin docker-ization!
info 1640884756 docker build output available at '/tmp/boxen2756986238/initial_build.log'
debug 1640884995 base image building complete!
debug 1640884995 package install starting
debug 1640884995 begin instance install
info 1640884995 install requested
info 1640884995 qemu instance start requested
debug 1640884995 launching instance with command: [-name cisco_n9kv -uuid 3c7fe9f9-61af-4c37-bf7b-338fd504f8ae -accel kvm -display none -machine pc -m 8192 -cpu max -smp cores=8,threads=1,sockets=1 -monitor tcp:0.0.0.0:4001,server,nowait -serial telnet:0.0.0.0:5001,server,nowait -drive if=none,file=disk.qcow2,format=qcow2,id=drive-sata-disk0 -device ahci,id=ahci0,bus=pci.0 -device ide-hd,drive=drive-sata-disk0,bus=ahci0.0,id=drive-sata-disk0,bootindex=1 -device pci-bridge,chassis_nr=1,id=pci.1 -device e1000,netdev=mgmt -netdev user,id=mgmt,net=10.0.0.0/24,tftp=/tftpboot,hostfwd=tcp::21022-10.0.0.15:22,hostfwd=tcp::21023-10.0.0.15:23,hostfwd=tcp::21443-10.0.0.15:443,hostfwd=tcp::21830-10.0.0.15:830,hostfwd=udp::31161-10.0.0.15:161 -device e1000,netdev=p001,bus=pci.1,addr=0x2,mac=52:54:00:54:6a:01 -netdev socket,id=p001,listen=:10001 -device e1000,netdev=p002,bus=pci.1,addr=0x3,mac=52:54:00:ee:56:02 -netdev socket,id=p002,listen=:10002 -device e1000,netdev=p003,bus=pci.1,addr=0x4,mac=52:54:00:4e:75:03 -netdev socket,id=p003,listen=:10003 -device e1000,netdev=p004,bus=pci.1,addr=0x5,mac=52:54:00:66:83:04 -netdev socket,id=p004,listen=:10004 -device e1000,netdev=p005,bus=pci.1,addr=0x6,mac=52:54:00:76:d0:05 -netdev socket,id=p005,listen=:10005 -device e1000,netdev=p006,bus=pci.1,addr=0x7,mac=52:54:00:66:25:06 -netdev socket,id=p006,listen=:10006 -device e1000,netdev=p007,bus=pci.1,addr=0x8,mac=52:54:00:6d:8b:07 -netdev socket,id=p007,listen=:10007 -device e1000,netdev=p008,bus=pci.1,addr=0x9,mac=52:54:00:34:99:08 -netdev socket,id=p008,listen=:10008 -bios ./OVMF.fd -boot c]
debug 1640884995 stdout logger provided, setting execute argument
debug 1640884995 stderr logger provided, setting execute argument
info 1640885005 qemu instance start complete
debug 1640885005 instance started, waiting for start ready state
info 1640885015 install logs available at '/tmp/boxen2756986238/install_build.log', or by inspect container 'b54b335336c667df60dd04aaaec88b5adf9d455aa46a2f17638239228dbc8d93' logs
debug 1640885199 start ready state acquired, handling initial config dialog
debug 1640885211 initial config dialog addressed, logging in
debug 1640885217 log in complete
debug 1640885217 install config lines provided, executing scrapligo on open
debug 1640885225 initial installation complete
info 1640885225 save config requested
info 1640885230 install complete, stopping instance
info 1640885230 qemu instance stop requested
info 1640885230 qemu instance stop complete
debug 1640885240 instance installation complete!
info 1640885280 final image build logs available at '/tmp/boxen2756986238/final_build.log'
debug 1640885280 packaging complete!
✅ finished successfully in 527 seconds
This "package" command will copy the disk image to a temporary directory and write out a few Dockerfiles that will be used for the packaging process. The first dockerfile is the "build" image; this image gets the disk and any necessary files (OVMF.fd, config.iso, etc.) copied into it. Once the build image is created, a container is spawned from that image -- this "install container" is where the initial device prompts (POAP, ZTP, etc.) is dealt with, and a base configuration is deployed. Once the initial configuration is sorted, the configuration is saved, and the container is stopped.
With the initial "installation" done, the disk image is copied out of the stopped container. Finally, a final slimmer container is built, which includes copying in the freshly installed disk.
At that point, the final image will be tagged "boxen_vendor_platform" with a version of whatever the provided disk version was.
Packaging for local VM Use
The process for setting up local VMs is somewhat similar to the packaging setup. First things first
is that boxen will need a nice little directory to store its config file as well as any source disks
and of course instance disks. The init command initializes this boxen directory, which by default
is ~/boxen, but you can provide whatever path you like to the --directory flag.
With boxen "initialized" you are set to "install" a disk as a local source disk. This is done with
the appropriately named install flag.
boxen install --disk somedisk.qcow2
Note that by default boxen will look for its config file at ~/boxen/boxen.yaml -- if you
initialized boxen with a different path, make sure you pass the config file path with the --config
flag!
Just like the packaging process, boxen will automagically determine the vendor, platform and disk version from the provided image. The "installation" process is pretty similar to the packaging process, just without containers of course. The disk is copied to a temp directory and is launched via qemu. The initial configuration process is sorted out, and the configuration is saved. Once complete, the new "source" disk is copied to the "source" sub-directory in the boxen directory.
At this point the "source" disk is ready, but we have no instances to launch!
The boxen provision command allows for provisioning one or many of the same type of instance. If
you just installed an Arista vEOS source disk you could provision two vEOS instances like:
boxen provision --vendor arista --platform veos --instances eos1,eos2
The "provisioning" process simply installs these instances into the boxen config file and allocates instance IDs, management interface nat ports, and data plane interface listen ports. You can view the config file to see all of these settings.
Once provisioned you can start or stop instances easily:
boxen start instance --instances eos1,eos2
boxen stop instance --instances eos2
Other Info
Sparsify Disks
Some platforms will support disk "sparsification" -- to enable this, run boxen with the
BOXEN_SPARSIFY_DISK env var set to anything > 0.
Dev Mode
During installation/dev/testing and such it is very handy to not delete boxen's temp build
directory, you can enable this behavior by setting the BOXEN_DEV_MODE env var to anything > 0.
Log Level
BOXEN_LOG_LEVEL env var can be set to "info", "debug" or "critical" (default info) to control log
verbosity. Note that this environment variable is copied i
