8 Commits

Author SHA1 Message Date
Alexander Stevenson
3de5c21134 Add a new CML Free hybrid topology 2025-09-25 13:04:53 -04:00
CML-TAC
85382ce2fc Added note in vJUNOS nodes to enabled performance counters in CML ESXI deployments. (#68)
* Update README.MD

Added note about enabled performance counters in ESXI deployments

* Update README.MD

Fixed formatting

* Update README.MD

Added note about enabling performance counters in ESXI.
2025-09-03 18:53:43 -04:00
Joe Clarke
4cae91833b Fix an indentation bug. 2025-09-03 17:10:26 -04:00
Joe Clarke
e75cf3389d Add a README to catalog external topologies. 2025-09-03 17:03:22 -04:00
Joe Clarke
b96eac424c Remove this orphaned stub module. 2025-09-03 17:01:03 -04:00
Hank Preston
a232fbb6f4 Initial Code Server Custom Commit (#67) 2025-08-01 13:48:25 -04:00
Hank Preston
675e7d491c Merge pull request #65 from jcpmunizie/fix-missing-libnsl-dev
Add libnsl-dev to the aaa-tacacs-exploration lab topologies
2025-07-21 08:54:38 -04:00
Joao Muniz
e0045ff571 Add libnsl-dev as it's a required dependency to compile tac_plus package used in aaa-tacacs-exploration lab topology 2025-07-07 02:01:26 +01:00
16 changed files with 1445 additions and 6 deletions

20
lab-topologies/README.md Normal file
View File

@@ -0,0 +1,20 @@
# Cisco Modeling Labs (CML) Use Cases
This directory contains sample topologies that can be loaded within CML.
## Topologies in This Repository
- Explore the subdirectories for available sample topologies hosted here.
## External Use Cases
The following sample topologies are not hosted in this repository but may be useful:
- [ciscolive-brkcrt-2059](https://github.com/CiscoLearning/ciscolive-brkcrt-2059) - Lab Up For Success With Cisco Modeling Labs.
## Contributing
If you wish to submit a sample topologies, you can either create a pull request to host it here in this repository, or you can submit a pull request
for this `README.md` alone that points to your CML use cases hosted elsewhere.
Feel free to contribute new topologies or suggest additional resources!

View File

@@ -223,6 +223,7 @@ nodes:
- flex
- bison
- libwrap0-dev
- libnsl-dev
write_files:
# Create the tac_plus configuration file

View File

@@ -499,6 +499,7 @@ nodes:
- bison
- libwrap0-dev
- python3.10-venv
- libnsl-dev
write_files:
# Create the tac_plus configuration file

View File

@@ -270,11 +270,11 @@ nodes:
tags: []
x: 280
y: -160
interfaces:
- id: i0
label: eth0
slot: 0
type: physical
interfaces:
- id: i0
label: eth0
slot: 0
type: physical
- boot_disk_size: null
configuration:
- name: ios_config.txt

Submodule lab-topologies/ciscolive-brkcrt-2059 deleted from d13fd45574

View File

@@ -0,0 +1,22 @@
**Hybrid Networking Topology**
Cisco Modeling Labs - Free allows up to five nodes to run concurrently.
The **External Connector** (`ext-conn-0`) and the **Unmanaged Switch** (`unmanaged-switch-0`) do not count against the device node limit of five. Besides these two nodes, for your Cisco Modeling Labs network, you have the following five nodes running:
1. `router-1`: an IOL router running Cisco IOS-XE version 17.15.1
2. `switch-1`: an IOL-L2 switch running Cisco IOS-XE version 17.15.1
3. `ubuntu-te`: Ubuntu Linux version 24.04.1 LTS (Noble Numbat)
4. `client-1`: Alpine Linux version 3.20.3
5. `server-1`: TinyCore Linux version 15.0
![topology](hybrid-networking.png)
> **Note:** The provided Cisco Modeling Labs template ([hybrid-network-cml-topology.yaml](hybrid-networking-cml-topology.yaml)) for this tutorial is designed to minimize your setup time. The lab is preconfigured for connectivity between the nodes and the router, which will obtain an IP address via DHCP from your network and serve as the lab's default gateway. Everywhere in the Cisco Modeling Labs network topology where a password is required, the default of "cisco/cisco" has been used.
> **Note:** `server-1` is running TinyCore Linux, where Python 3 can be installed using the `tce-load` command.
```bash
tce-load -wi python3.9
```

View File

@@ -0,0 +1,730 @@
annotations:
- border_color: "#00000000"
border_style: ""
color: "#808080FF"
rotation: 0
text_bold: false
text_content: |-
Inside interface:
192.168.100.1
text_font: monospace
text_italic: false
text_size: 12
text_unit: pt
thickness: 1
type: text
x1: -280.0
y1: 80.0
z_index: 1
- border_color: "#00000000"
border_style: ""
color: "#808080FF"
rotation: 0
text_bold: false
text_content: |-
VLAN 1:
192.168.100.100
text_font: monospace
text_italic: false
text_size: 12
text_unit: pt
thickness: 1
type: text
x1: -80.0
y1: 80.0
z_index: 3
- border_color: "#00000000"
border_style: ""
color: "#808080FF"
rotation: 0
text_bold: false
text_content: 192.168.100.102
text_font: monospace
text_italic: false
text_size: 12
text_unit: pt
thickness: 1
type: text
x1: 240.0
y1: -40.0
z_index: 5
- border_color: "#00000000"
border_style: ""
color: "#808080FF"
rotation: 0
text_bold: false
text_content: 192.168.100.103
text_font: monospace
text_italic: false
text_size: 12
text_unit: pt
thickness: 1
type: text
x1: 240.0
y1: 280.0
z_index: 6
- border_color: "#00000000"
border_style: ""
color: "#808080FF"
rotation: 0
text_bold: false
text_content: 192.168.100.101
text_font: monospace
text_italic: false
text_size: 12
text_unit: pt
thickness: 1
type: text
x1: 240.0
y1: -240.0
z_index: 7
smart_annotations: []
nodes:
- boot_disk_size: null
configuration:
- name: default
content: System Bridge
cpu_limit: null
cpus: null
data_volume: null
hide_links: false
id: n0
image_definition: null
label: ext-conn-0
node_definition: external_connector
parameters: {}
ram: null
tags: []
x: -600
y: 0
interfaces:
- id: i0
label: port
mac_address: null
slot: 0
type: physical
- boot_disk_size: null
configuration: []
cpu_limit: null
cpus: null
data_volume: null
hide_links: false
id: n1
image_definition: null
label: unmanaged-switch-0
node_definition: unmanaged_switch
parameters: {}
ram: null
tags: []
x: -440
y: 0
interfaces:
- id: i0
label: port0
mac_address: null
slot: 0
type: physical
- id: i1
label: port1
mac_address: null
slot: 1
type: physical
- id: i2
label: port2
mac_address: null
slot: 2
type: physical
- id: i3
label: port3
mac_address: null
slot: 3
type: physical
- id: i4
label: port4
mac_address: null
slot: 4
type: physical
- id: i5
label: port5
mac_address: null
slot: 5
type: physical
- id: i6
label: port6
mac_address: null
slot: 6
type: physical
- id: i7
label: port7
mac_address: null
slot: 7
type: physical
- boot_disk_size: null
configuration:
- name: ios_config.txt
content: |-
Building configuration...
Current configuration : 1084 bytes
!
! Last configuration change at 13:47:40 UTC Fri Jun 27 2025
!
version 17.15
service timestamps debug datetime msec
service timestamps log datetime msec
!
hostname router-1
!
boot-start-marker
boot-end-marker
!
!
no logging console
no aaa new-model
!
!
!
!
!
!
!
!
!
!
!
!
!
ip domain name cml.local
ip cef
login on-success log
no ipv6 cef
!
!
!
!
!
!
!
!
!
!
!
!
!
memory free low-watermark processor 80093
!
!
spanning-tree mode rapid-pvst
!
!
username cisco privilege 15 password 0 cisco
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
interface Ethernet0/0
ip address dhcp
!
interface Ethernet0/1
ip address 192.168.100.1 255.255.255.0
!
interface Ethernet0/2
no ip address
shutdown
!
interface Ethernet0/3
no ip address
shutdown
!
ip forward-protocol nd
!
!
ip http server
ip http secure-server
ip ssh bulk-mode 131072
no logging btrace
!
!
!
control-plane
!
!
!
line con 0
exec-timeout 0 0
logging synchronous
line aux 0
line vty 0 4
session-timeout 10
exec-timeout 0 0
login local
transport input ssh
!
!
!
!
interface Ethernet0/0
ip nat outside
!
interface Ethernet0/1
ip nat inside
!
access-list 1 permit 192.168.100.0 0.0.0.255
!
ip nat inside source list 1 interface Ethernet0/0 overload
!
end
cpu_limit: 60
cpus: null
data_volume: null
hide_links: false
id: n2
image_definition: iol-xe-17-15-01
label: router-1
node_definition: iol-xe
parameters: {}
ram: null
tags: []
x: -240
y: 0
interfaces:
- id: i0
label: Loopback0
mac_address: null
type: loopback
- id: i1
label: Ethernet0/0
mac_address: null
slot: 0
type: physical
- id: i2
label: Ethernet0/1
mac_address: null
slot: 1
type: physical
- id: i3
label: Ethernet0/2
mac_address: null
slot: 2
type: physical
- id: i4
label: Ethernet0/3
mac_address: null
slot: 3
type: physical
- boot_disk_size: null
configuration:
- name: ios_config.txt
content: |-
Building configuration...
Current configuration : 1083 bytes
!
! Last configuration change at 13:51:18 UTC Fri Jun 27 2025
!
version 17.15
service timestamps debug datetime msec
service timestamps log datetime msec
!
hostname switch-1
!
boot-start-marker
boot-end-marker
!
!
no logging console
no aaa new-model
!
!
!
!
!
!
!
!
!
!
!
!
!
ip audit notify log
ip audit po max-events 100
ip cef
login on-success log
no ipv6 cef
!
!
!
!
!
!
!
!
!
!
!
memory free low-watermark processor 79593
!
!
spanning-tree mode rapid-pvst
spanning-tree extend system-id
!
!
vlan internal allocation policy ascending
!
vlan 1
name default
!
!
!
!
interface Ethernet0/0
switchport mode access
!
interface Ethernet0/1
switchport mode access
!
interface Ethernet0/2
switchport mode access
!
interface Ethernet0/3
switchport mode access
!
interface Vlan1
ip address 192.168.100.100 255.255.255.0
no shutdown
!
ip forward-protocol nd
!
!
ip http server
ip http secure-server
ip ssh bulk-mode 131072
!
no logging btrace
!
!
!
control-plane
!
!
!
line con 0
exec-timeout 0 0
logging synchronous
line aux 0
line vty 0 4
exec-timeout 0 0
login
transport input ssh
!
!
end
cpu_limit: 75
cpus: null
data_volume: null
hide_links: false
id: n3
image_definition: ioll2-xe-17-15-01
label: switch-1
node_definition: ioll2-xe
parameters: {}
ram: null
tags: []
x: -40
y: 0
interfaces:
- id: i0
label: Loopback0
mac_address: null
type: loopback
- id: i1
label: Ethernet0/0
mac_address: null
slot: 0
type: physical
- id: i2
label: Ethernet0/1
mac_address: null
slot: 1
type: physical
- id: i3
label: Ethernet0/2
mac_address: null
slot: 2
type: physical
- id: i4
label: Ethernet0/3
mac_address: null
slot: 3
type: physical
- boot_disk_size: 8
configuration:
- name: iosxe_config.txt
content: |-
# this is a shell script which will be sourced at boot
hostname server-1
# configurable user account
USERNAME=cisco
PASSWORD=cisco
# no password for tc user by default
TC_PASSWORD=cisco
# Apply network configuration directly since /opt is read-only during boot
# Configure eth0 with static IP
ifconfig eth0 192.168.100.101 netmask 255.255.255.0 up
# Add default route
route add default gw 192.168.100.1
# Set up DNS
echo "nameserver 1.1.1.1" > /etc/resolv.conf
echo "nameserver 8.8.8.8" >> /etc/resolv.conf
cpu_limit: 74
cpus: null
data_volume: 8
hide_links: false
id: n4
image_definition: server-tcl-15-0
label: server-1
node_definition: server
parameters: {}
ram: 1024
tags: []
x: 320
y: -200
interfaces:
- id: i0
label: eth0
mac_address: null
slot: 0
type: physical
- boot_disk_size: 4
configuration:
- name: node.cfg
content: |-
# This is a shell script which will be sourced at boot
hostname client-1
# Configure /etc/network/interfaces for static IP
cat << EOF > /etc/network/interfaces
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
address 192.168.100.102
netmask 255.255.255.0
gateway 192.168.100.1
EOF
# Configure /etc/resolv.conf for nameservers
echo "nameserver 1.1.1.1" > /etc/resolv.conf
echo "nameserver 8.8.8.8" >> /etc/resolv.conf
# Commit changes for persistence across reboots (Alpine specific)
lbu commit -d "Initial network configuration"
# Restart networking service to apply changes
rc-service networking restart
cpu_limit: 50
cpus: 1
data_volume: 2
hide_links: false
id: n5
image_definition: alpine-desktop-3-20-3
label: client-1
node_definition: desktop
parameters: {}
ram: null
tags: []
x: 320
y: 0
interfaces:
- id: i0
label: eth0
mac_address: null
slot: 0
type: physical
- boot_disk_size: 4
configuration:
- name: user-data
content: |-
#cloud-config
hostname: ubuntu-te
manage_etc_hosts: True
system_info:
default_user:
name: cisco
password: cisco
chpasswd: { expire: False }
ssh_pwauth: True
ssh_authorized_keys:
- your-ssh-pubkey-line-goes-here
packages:
- python3
- python3-pip
runcmd:
- [ sh, -c, 'if [ ! -d /data ]; then mkdir -p /data; fi' ]
- [ sh, -c, 'if ! blkid /dev/vdb | grep -q TYPE; then mkfs.ext4 -F /dev/vdb; fi' ]
- [ sh, -c, 'if ! grep -q "/dev/vdb" /etc/fstab; then echo "/dev/vdb /data ext4 defaults 0 2" >> /etc/fstab; fi' ]
- [ mount, -a ]
- [ chown, 'cisco:cisco', '/data' ]
- [ chmod, '755', '/data' ]
- [ apt-get, update ]
- [ apt-get, install, -y, 'ca-certificates', 'curl', 'gnupg', 'lsb-release' ]
- [ sh, -c, 'curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg' ]
- [ sh, -c, 'echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null' ]
- [ apt-get, update ]
- [ apt-get, install, -y, 'docker-ce', 'docker-ce-cli', 'containerd.io', 'docker-buildx-plugin', 'docker-compose-plugin' ]
- [ mkdir, -p, '/data/docker' ]
- [ sh, -c, 'echo "{\"data-root\": \"/data/docker\"}" > /etc/docker/daemon.json' ]
- [ systemctl, enable, docker ]
- [ systemctl, restart, docker ]
- [ usermod, -aG, docker, cisco ]
- [ su, -c, 'newgrp docker', cisco ]
# Optional: Create a welcome message for students
write_files:
- path: /data/README.txt
content: |
Welcome to your CML Ubuntu Lab Node!
This system has two storage areas:
- Root filesystem (/): 4GB for OS and system files
- Data volume (/data): 6GB for your projects, files, and Docker containers
Docker is pre-installed and configured to use /data for container storage.
You can store your lab work in /data to avoid filling up the root filesystem.
Useful commands:
- df -h # Show disk usage
- du -sh /data/* # Show space used in data directory
- docker system df # Show Docker disk usage
- docker system prune # Clean up unused Docker resources
Docker usage:
- All Docker images and containers are stored in /data/docker
- The 'cisco' user can run Docker commands without sudo
- Log out and back in after first boot to use Docker
Happy learning!
owner: cisco:cisco
permissions: '0644'
- name: network-config
content: |-
network:
version: 2
ethernets:
ens2:
dhcp4: false
addresses:
- 192.168.100.103/24
gateway4: 192.168.100.1
nameservers:
addresses:
- 1.1.1.1
- 8.8.8.8
cpu_limit: 90
cpus: null
data_volume: 6
hide_links: false
id: n6
image_definition: null
label: ubuntu-te
node_definition: ubuntu
parameters: {}
ram: null
tags: []
x: 320
y: 200
interfaces:
- id: i0
label: ens2
mac_address: null
slot: 0
type: physical
- id: i1
label: ens3
mac_address: null
slot: 1
type: physical
- id: i2
label: ens4
mac_address: null
slot: 2
type: physical
- id: i3
label: ens5
mac_address: null
slot: 3
type: physical
- id: i4
label: ens6
mac_address: null
slot: 4
type: physical
links:
- id: l0
n1: n0
n2: n1
i1: i0
i2: i0
conditioning: {}
label: ext-conn-0-port<->unmanaged-switch-0-port0
- id: l1
n1: n2
n2: n1
i1: i1
i2: i1
conditioning: {}
label: router-1-Ethernet0/0<->unmanaged-switch-0-port1
- id: l2
n1: n3
n2: n2
i1: i1
i2: i2
conditioning: {}
label: switch-1-Ethernet0/0<->router-1-Ethernet0/1
- id: l3
n1: n4
n2: n3
i1: i0
i2: i2
conditioning: {}
label: server-1-eth0<->switch-1-Ethernet0/1
- id: l4
n1: n5
n2: n3
i1: i0
i2: i3
conditioning: {}
label: client-1-eth0<->switch-1-Ethernet0/2
- id: l5
n1: n6
n2: n3
i1: i0
i2: i4
conditioning: {}
label: ubuntu-te-ens2<->switch-1-Ethernet0/3
lab:
description: ""
notes: ""
title: ThousandEyes_Splunk
version: 0.3.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View File

@@ -9,3 +9,5 @@ Image can be downloaded from https://support.juniper.net/support/downloads/?p=vj
Minimum CML version 2.8.0
Tested with vJUNOS ROUTER image version 23.2
For CML deployed in ESXI, `Performance Counters` should be enabled in CPU section of CML VM Edit settings. Without it the vJUNOS may not boot.

View File

@@ -9,3 +9,5 @@ Image can be downloaded from https://support.juniper.net/support/downloads/?p=vj
Minimum CML version 2.8.
Tested with vJUNOS SWITCH image version 23.2
For CML deployed in ESXI, `Performance Counters` should be enabled in CPU section of CML VM Edit settings. Without it the vJUNOS may not boot.

View File

@@ -0,0 +1,429 @@
annotations:
- border_color: '#00000000'
border_style: ''
color: '#050505'
rotation: 0
text_bold: false
text_content: |-
Code Server Addresses:
- From Chrome Node: http://10.0.0.11:8443
- PATty Configured: http://{CML IP}:7001
(requires PATty enabled on CML server)
text_font: monospace
text_italic: false
text_size: 10
text_unit: pt
thickness: 1
type: text
x1: 40.0
y1: -280.0
z_index: 0
- border_color: '#00000000'
border_style: ''
color: '#050505'
rotation: 0
text_bold: false
text_content: |-
Code Server Addresses:
- From Chrome Node: http://10.0.0.11:8443
- PATty Configured: http://{CML IP}:7001
(requires PATty enabled on CML server)
text_font: monospace
text_italic: false
text_size: 10
text_unit: pt
thickness: 1
type: text
x1: -240.0
y1: 0.0
z_index: 0
- border_color: '#00000000'
border_style: ''
color: '#050505'
rotation: 0
text_bold: false
text_content: |-
Code Server Addresses:
- From Chrome Node: http://10.0.0.11:8443
- PATty Configured: http://{CML IP}:7001
(requires PATty enabled on CML server)
text_font: monospace
text_italic: false
text_size: 10
text_unit: pt
thickness: 1
type: text
x1: -240.0
y1: 0.0
z_index: 0
- border_color: '#00000000'
border_style: ''
color: '#050505'
rotation: 0
text_bold: false
text_content: 'ip: 10.0.0.1'
text_font: monospace
text_italic: false
text_size: 10
text_unit: pt
thickness: 1
type: text
x1: -120.0
y1: -320.0
z_index: 0
- border_color: '#00000000'
border_style: ''
color: '#000000'
rotation: 0
text_bold: true
text_content: 'Example: Using Code Server For Network Automation Testing'
text_font: monospace
text_italic: false
text_size: 12
text_unit: pt
thickness: 1
type: text
x1: -280.0
y1: -400.0
z_index: 1
smart_annotations:
- tag: pat:tcp:7001:8443
is_on: true
padding: 35
label: pat:tcp:7001:8443
tag_offset_x: 0
tag_offset_y: 0
tag_size: 14
group_distance: 400
thickness: 1
border_style: ''
fill_color: '#005C9980'
border_color: '#00000080'
z_index: 1
nodes:
- boot_disk_size: null
configuration: []
cpu_limit: null
cpus: null
data_volume: null
hide_links: false
id: n0
image_definition: null
label: internet
node_definition: external_connector
parameters: {}
ram: null
tags: []
x: -240
y: -280
interfaces:
- id: i0
label: port
mac_address: null
type: physical
slot: 0
- boot_disk_size: null
configuration:
- name: boot.sh
content: |-
# The following commands will run at boot.
# Note: Suggested that eth0 be connected to ext-conn for
# internet access to reach locations such as GitHub
# and PyPi. Leave eth0 gaining IP from DHCP. Add
# second interface (eth1) for reachability to
# "lab networks"
# Examples :
# - Static IP address, routes, and DNS server
ip address add dev eth1 10.0.0.11/24
ip route add 10.0.0.0/16 via 10.0.0.1
ip link set dev eth1 up
# echo "nameserver 192.168.10.11" >> /etc/resolv.conf
# - Clone something from Source Control
# If the container is getting its IP via DHCP, uncomment
# this sleep to ensure the DHCP process completes before
# attempting to clone the repo
sleep 10
# Recommend placing code in the /app/code directory for default workspace
cd /app/code
# Do the clone as the user "abc", which is the code-server user
sudo -u abc git clone https://github.com/hpreston/net-hello-world.git
# Install Python requirements file into the container virtual environment
sudo -u abc /app/code/.venv/bin/python -m pip install -r net-hello-world/requirements.txt
# End the script cleanly
exit 0
cpu_limit: null
cpus: null
data_volume: null
hide_links: false
id: n1
image_definition: null
label: codeserver-0
node_definition: code-server-custom-4.102
parameters: {}
ram: null
tags:
- pat:tcp:7001:8443
x: -240
y: -120
interfaces:
- id: i0
label: eth0
mac_address: null
type: physical
slot: 0
- id: i1
label: eth1
mac_address: null
type: physical
slot: 1
- boot_disk_size: null
configuration:
- name: ios_config.txt
content: |-
hostname router01
ip domain name net.internal
ip domain list net.internal
!
! EEM Applet to add SSH Key Automatically
event manager applet do-ssh authorization bypass
event timer cron cron-entry "@reboot" maxrun 130
action 01 wait 10
action 02 cli command "enable"
action 11 cli command "crypto key generate rsa modulus 2048"
action 20 cli command "config t"
action 21 cli command "no event manager applet do-ssh"
action 22 cli command "end"
action 23 cli command "write mem"
!
enable secret cisco
username cisco privilege 15 secret cisco
!
line vty 0 4
transport input ssh
login local
exit
!
!
! In order to avoid entering a configuration dialog on boot, please
! ensure that all interfaces have some IP configuration present here
! such as the example below:
!
interface range Ethernet0/0-3
no ip address
shutdown
!
interface Serial1/0
no ip address
shutdown
!
interface Serial1/1
no ip address
shutdown
!
interface Serial1/2
no ip address
shutdown
!
interface Serial1/3
no ip address
shutdown
!
interface Ethernet0/0
no shut
ip address 10.0.0.1 255.255.255.0
!
end
cpu_limit: null
cpus: null
data_volume: null
hide_links: false
id: n2
image_definition: null
label: router01
node_definition: iol-xe-serial-4eth
parameters: {}
ram: null
tags: []
x: -80
y: -280
interfaces:
- id: i0
label: Loopback0
mac_address: null
type: loopback
- id: i1
label: Ethernet0/0
mac_address: null
type: physical
slot: 0
- id: i2
label: Ethernet0/1
mac_address: null
type: physical
slot: 1
- id: i3
label: Ethernet0/2
mac_address: null
type: physical
slot: 2
- id: i4
label: Ethernet0/3
mac_address: null
type: physical
slot: 3
- id: i5
label: Serial1/0
mac_address: null
type: physical
slot: 4
- id: i6
label: Serial1/1
mac_address: null
type: physical
slot: 5
- id: i7
label: Serial1/2
mac_address: null
type: physical
slot: 6
- id: i8
label: Serial1/3
mac_address: null
type: physical
slot: 7
- boot_disk_size: null
configuration:
- name: boot.sh
content: |-
# insert commands here, e.g. a static IP address
ip address add dev eth0 10.0.0.12/24
ip link set dev eth0 up
exit 0
- name: environment
content: |-
# NOTE 2025-08-01:
# The current (CML 2.9.0) Chrome and Firefox containers
# do NOT support setting the HOME_URL for code-server due
# to code-server returning a 405 error to HEAD requests
# A future CML node update will enable more flexible checks
# to enable using HOME_URL for code-server
# -- These are understood by the start script
# -- Homepage to open at start (needs network!)
# HOME_URL=https://www.cisco.com/go/cml
# -- Wait additional time for network before starting Chrome
# WAIT=2
cpu_limit: null
cpus: null
data_volume: null
hide_links: false
id: n3
image_definition: null
label: chrome-0
node_definition: chrome
parameters: {}
ram: null
tags: []
x: 80
y: -120
interfaces:
- id: i0
label: eth0
mac_address: null
type: physical
slot: 0
- boot_disk_size: null
configuration: []
cpu_limit: null
cpus: null
data_volume: null
hide_links: false
id: n4
image_definition: null
label: switch
node_definition: unmanaged_switch
parameters: {}
ram: null
tags: []
x: -80
y: -120
interfaces:
- id: i0
label: port0
mac_address: null
type: physical
slot: 0
- id: i1
label: port1
mac_address: null
type: physical
slot: 1
- id: i2
label: port2
mac_address: null
type: physical
slot: 2
- id: i3
label: port3
mac_address: null
type: physical
slot: 3
- id: i4
label: port4
mac_address: null
type: physical
slot: 4
- id: i5
label: port5
mac_address: null
type: physical
slot: 5
- id: i6
label: port6
mac_address: null
type: physical
slot: 6
- id: i7
label: port7
mac_address: null
type: physical
slot: 7
links:
- id: l0
n1: n1
n2: n0
i1: i0
i2: i0
conditioning: {}
label: codeserver-0-eth0<->internet-port
- id: l1
n1: n1
n2: n4
i1: i1
i2: i0
conditioning: {}
label: codeserver-0-eth1<->unmanaged-switch-0-port0
- id: l2
n1: n4
n2: n2
i1: i1
i2: i1
conditioning: {}
label: unmanaged-switch-0-port1<->router01-Ethernet0/0
- id: l3
n1: n3
n2: n4
i1: i0
i2: i2
conditioning: {}
label: chrome-0-eth0<->unmanaged-switch-0-port2
lab:
description: 'This is an example topology that shows how the Code Server Custom
Node can be used in a topology to provide a developer experience for Network Automation
use cases. '
notes: ''
title: Example - Code Server Custom
version: 0.3.0

View File

@@ -0,0 +1,77 @@
# Code Server Custom
Looking to easily add a network automation workspace to your CML topologies? Well this node definition is for you.
![](cml-code-server-01.png)
Built from the [Linux Servers Container Image for "Code Server"](https://hub.docker.com/r/linuxserver/code-server), this node provides a web based VS Code interface that can be added into your CML topologies like any other node.
You can then use a Chrome/Firefox container within the topology to begin your automation work. Or setup a PATty connection, and directly access the Code Server from your local workstation.
## Node Details
* Requires CML version 2.9+
* Code Server Version 4.102.2 used
* Automation Tools Included:
* Python 3.12.3
* Terraform v1.12.2
* Default Workspace Configured:
* Path: `/app/code`
* Python VENV: `/app/code/.venv` (No Packages Installed)
* Requires matching image definition and container image
* Image Definition File: [`code-server.custom.01.4.102.yaml`](../../../virl-base-images/opensource/code-server.custom.01.4.102/code-server.custom.01.4.102.yaml).
* Container Image: [`code-server-custom.01.4.102.tar`](https://cml-images.nerdops.io/code-server-custom.01.4.102.tar.gz)
> Note: CML container node definition, image definition, and container image file are tightly coupled. The image "name" (ex: `code-server-custom:01_04.102.2`), and the SHA Hash (ex: `6525a3a31...`) must match exactly. Changing to a different container image with your own customizations, will require updating the node and image definitions.
* Container SHA value: `6525a3a31b1b18cf01f64425e96b080aeac86f87c0f02fc041792358bc599dd1` (Required for Image Definition Creation)
## Adding the node to your CML instance
> Container support was added in CML 2.9.0.
> Adding a container image to CML is slightly different than adding a typical VM based node. As with many things in the world, there are multiple ways to accomplish the same task. These instructions present one method, but feel free to adjust for your own environment and preferences as you see fit.
1. Import the node definition file to CML from the CML GUI.
2. Download the container image file to your local workstation.
```
# Example:
wget https://cml-images.nerdops.io/code-server-custom.01.4.102.tar.gz
Saving to: code-server-custom.01.4.102.tar.gz
code-server-custom.01.4.102.tar.gz 100%[=======>] 666.61M 47.1MB/s in 14s
2025-08-01 16:17:27 (47.9 MB/s) - code-server-custom.01.4.102.tar.gz saved [698992808/698992808]
```
1. Upload the container image to the CML server. Here I use SCP to do the upload.
```
scp code-server-custom.01.4.102.tar.gz admin@{CML_SERVER_ADDRESS}:
code-server-custom.01.4.102.tar.gz 100% 667MB 315.1MB/s 00:02
```
1. If the container image is compressed into a `.tar.gz` file like this example, you'll need to uncompress it into just a `.tar` file to continue. You can do this before you upload it to CML, but you can also do it on the CML server after the upload as the `sysadmin` account.
```
sudo -u virl2 gunzip /var/local/virl2/dropfolder/code-server-custom.01.4.102.tar.gz
```
* Access the `sysadmin` terminal through the Cockpit interface, or by SSHing to the CML server (if enabled) on port 1122
* Use `sudo -u virl2` to run the unzip as the CML service account
1. Create the Image Definition using the CML GUI. Be sure to select the correct Node and Disk Image. You'll need to provide ID, Label, Description, and Disk Hash (SHA value).
> There isn't an "Import" ability for Image Definitions, but you can use the details from the [image definition file here](../../../virl-base-images/opensource/code-server.custom.01.4.102/code-server.custom.01.4.102.yaml) in the CML Community to fill in the blanks.
## Testing the Node Definition
If you'd like to test the new node definition, a simple CML topology file is included in this repo: [Example - Code Server Custom](Example_-_Code_Server_Custom.yaml)
![](example-cml-topology-01.png)
This example includes the Code Server node with a configuraiton that automatically will clone down [https://github.com/hpreston/net-hello-world](https://github.com/hpreston/net-hello-world#) and install the Python requirements from the project automatically. There is also an IOL router, that the [`hello_world.py`](https://github.com/hpreston/net-hello-world/blob/main/hello_world.py) will use pyATS to query and print the device version.
You can access the Code-Server using the Chrome node in the topology by navigating to the code-server address of `http://10.0.0.11:8443`. If your CML server is configured for PATty, you can also access the code-server at `http://{CML_IP}:7001`.

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

View File

@@ -0,0 +1,125 @@
id: code-server-custom-4.102
boot:
timeout: 30
completed:
- READY
uses_regex: false
sim:
linux_native:
libvirt_domain_driver: docker
driver: ubuntu
ram: 4096
cpus: 1
cpu_limit: 100
video:
memory: 1
general:
nature: host
description: Code-Server Customized 4.102.2 (Docker)
read_only: false
configuration:
generator:
driver: null
provisioning:
files:
- editable: false
name: config.json
content: |-
{
"docker": {
"image": "code-server-custom:01_04.102.2",
"mounts": [
"type=bind,source=cfg/boot.sh,target=/boot.sh"
],
"misc_args": [
"--security-opt","seccomp=unconfined"
],
"env": [
"DOCKER_MODS=code-server-python3|linuxserver/mods:code-server-terraform",
"TZ=Etc/UTC",
"DEFAULT_WORKSPACE=/app/code/code.code-workspace"
]
},
"shell": "/bin/sh",
"day0cmd": [ "/bin/sh", "/boot.sh" ],
"busybox": true
}
- editable: true
name: boot.sh
content: |-
# The following commands will run at boot.
# Note: Suggested that eth0 be connected to ext-conn for
# internet access to reach locations such as GitHub
# and PyPi. Leave eth0 gaining IP from DHCP. Add
# second interface (eth1) for reachability to
# "lab networks"
# Examples :
# - Static IP address, routes, and DNS server
# ip address add dev eth1 192.168.10.11/24
# ip route add 192.168.11.0/24 via 192.168.10.1
# ip link set dev eth1 up
# echo "nameserver 192.168.10.11" >> /etc/resolv.conf
# - Clone something from Source Control
# If the container is getting its IP via DHCP, uncomment
# this sleep to ensure the DHCP process completes before
# attempting to clone the repo
# sleep 10
# Recommend placing code in the /app/code directory for default workspace
# cd /app/code
# Do the clone as the user "abc", which is the code-server user
# sudo -u abc git clone {REPO_ADDRESS}
# Install Python requirements file into the container virtual environment
# Note: Depending on internet speed and number of requirements, the
# installation can take significant time to complete.
# sudo -u abc /app/code/.venv/bin/python -m pip install -r {PROJECT_FOLDER}/requirements.txt
# End the script cleanly
exit 0
- editable: true
name: environment
content: |-
# Create any additional Environment Variables for the Server
# Example:
# ROUTER_ADDRESS=10.0.0.1
media_type: raw
volume_name: cfg
device:
interfaces:
serial_ports: 2
physical:
- eth0
- eth1
- eth2
- eth3
has_loopback_zero: false
default_count: 1
ui:
label_prefix: codeserver-
icon: host
label: Code-Server (Python/Terraform)
visible: true
group: Others
description: |-
Code Server 4.102.2 (Docker) Based on linuxserver/code-server
* Python and Terraform Installed
* Code workspace created at `/app/code`
* Workspace Python venv: `/app/code/.venv`
* Access Code Server at: http://{CONTAINER_IP}:8443
* PATty support: `pat:tcp:{PATty Port}:8443`
inherited:
image:
ram: true
cpus: false
data_volume: false
boot_disk_size: false
cpu_limit: false
node:
ram: true
cpus: false
data_volume: false
boot_disk_size: false
cpu_limit: false
schema_version: 0.0.1

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View File

@@ -0,0 +1,31 @@
id: code-server.custom.01.4.102
node_definition_id: code-server-custom-4.102
description: |-
Code Server (4.102) from https://hub.docker.com/r/linuxserver/code-server
Reachable at: http://{IP_ADDRESS}:8443
Customizations:
* DOCKER_MODS=linuxserver/mods:code-server-python3|linuxserver/mods:code-server-terraform"
* VS Code Extensions
```
code-server --install-extension dotjoshjohnson.xml
code-server --install-extension ms-python.black-formatter
code-server --install-extension ms-python.debugpy
code-server --install-extension ms-python.flake8
code-server --install-extension ms-python.python
code-server --install-extension redhat.ansible
code-server --install-extension redhat.vscode-yaml
code-server --install-extension samuelcolvin.jinjahtml
code-server --install-extension hashicorp.terraform
code-server --install-extension ms-toolsai.jupyter
```
* Workspace for /app/code created
label: Code Server Custom
disk_image: code-server-custom.01.4.102.tar
read_only: false
schema_version: 0.0.1
sha256: 6525a3a31b1b18cf01f64425e96b080aeac86f87c0f02fc041792358bc599dd1