Convert Cisco CML and VIRL lab topologies into GNS3 projects or deploy them directly to a GNS3 server
Project description
cml2gns
Network lab topology translation and GNS3 deployment.
cml2gns converts Cisco Modeling Labs (CML) and VIRL topologies into GNS3 project files, deploys them against templates installed on a GNS3 server, and provides supporting tools for validation, comparison, visualization, reverse conversion, and containerlab export.
The package name stays focused on its primary workflow—CML to GNS3—while the project now presents itself honestly as a broader topology toolkit. Renaming the Python package would break existing commands and imports without improving interoperability.
What works
- CML YAML in list-based and dictionary-based layouts
- VIRL XML parsed with
defusedxml - GNS3 2.x project generation using the official
node_typeproject field - Server-backed deployment using real, installed GNS3 template IDs
- Link, node-position, annotation, and sidecar startup-config preservation
- GNS3-to-CML best-effort reverse conversion
- containerlab import and export
- Topology validation, diffing, batch conversion, and ASCII visualization
- GNS3 portable archives with the
.gns3projectextension
The test suite covers Python 3.9 through 3.14 in GitHub Actions.
Installation
Install the latest release from PyPI:
python -m pip install cml2gns
To install from source instead:
git clone https://github.com/daniissac/cml2gns.git
cd cml2gns
python -m pip install .
For development:
python -m pip install -e ".[dev]"
python -m pytest -q
Choose a conversion mode
Create an offline GNS3 project
cml2gns convert \
--input branch-lab.yaml \
--output build/branch-lab \
--portable
This writes a schema-valid .gns3 file and, when requested, a .gns3project archive. CML startup configurations are written unchanged into the output's configs/ directory.
Offline conversion cannot discover proprietary images or machine-specific GNS3 template settings. QEMU, IOU, and Docker nodes still need compatible images and properties on the system that opens the project.
Deploy through a running GNS3 server
cml2gns deploy \
--input branch-lab.yaml \
--host localhost \
--port 3080
Deployment resolves only the templates needed by the topology, creates nodes from their real server-side templates, connects their interfaces, and rolls back the new project if a later step fails. Template names come from the built-in mappings or a custom mapping file.
For token authentication, set GNS3_API_TOKEN. For basic authentication, pass --user and set GNS3_PASSWORD.
Startup configs are not injected during server deployment because the destination filename and mechanism depend on the emulator and appliance. Use offline conversion to preserve them as sidecars, then apply them through the appropriate GNS3/device workflow.
Common commands
# Validate without writing files
cml2gns validate --input branch-lab.yaml
# Preview an offline conversion
cml2gns convert -i branch-lab.yaml -o build/branch-lab --dry-run
# Fail instead of creating generic fallback nodes
cml2gns convert -i branch-lab.yaml -o build/branch-lab --strict
# Check installed templates on a GNS3 server
cml2gns server-check --host localhost --port 3080
# Convert a GNS3 project back to CML YAML (best effort)
cml2gns reverse -i project.gns3 -o recovered.yaml
# Export any supported topology to containerlab
cml2gns export-clab -i branch-lab.yaml -o branch-lab.clab.yml
# Compare or visualize topologies
cml2gns diff -a before.yaml -b after.yaml
cml2gns show -i branch-lab.yaml
# Inspect built-in node mappings
cml2gns list-mappings
Run cml2gns --help or cml2gns COMMAND --help for every option.
Custom node mappings
Custom mappings override built-in mappings by CML node_definition:
{
"iosv": {
"gns3_template": "My IOSv Template",
"console_type": "telnet",
"compute_type": "qemu",
"symbol": ":/symbols/classic/router.svg",
"properties": {
"ram": 768,
"adapters": 4,
"adapter_type": "e1000"
}
}
}
Use it with --mapping mappings.json. For server deployment, gns3_template must match an installed template name. A real template_id may also be supplied; the server verifies that it exists.
Conversion boundaries
Topology formats do not share a perfect one-to-one model. Keep these boundaries in mind:
- Device images are never bundled. Cisco and other vendor images must be supplied under their own licenses.
- GNS3-to-CML node definitions are inferred from GNS3 emulator types when the original CML metadata is unavailable.
- Interface labels are matched first; adapter/port numbers are used as a fallback.
- The optional
--normalize-configtransform only removes quotes around a quoted hostname. Secrets and other configuration lines are preserved. - Portable archives contain the generated project and sidecar files, not missing appliance images.
Contributing
See CONTRIBUTING.md. Please include a regression test for parser, generator, or API behavior changes.
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cml2gns-0.2.1.tar.gz.
File metadata
- Download URL: cml2gns-0.2.1.tar.gz
- Upload date:
- Size: 50.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cc547a71c57b9733a0b7b81e33f8e1b6d5edbb817496ab91ad27e80218794f51
|
|
| MD5 |
5668340d29005d1026b818c465c818da
|
|
| BLAKE2b-256 |
7cdf34a2a9f06834d41701e1749fac9f725ee547bab3dbf689191cee7a12ca08
|
Provenance
The following attestation bundles were made for cml2gns-0.2.1.tar.gz:
Publisher:
publish.yml on daniissac/cml2gns
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cml2gns-0.2.1.tar.gz -
Subject digest:
cc547a71c57b9733a0b7b81e33f8e1b6d5edbb817496ab91ad27e80218794f51 - Sigstore transparency entry: 2172984987
- Sigstore integration time:
-
Permalink:
daniissac/cml2gns@1bba84d3657f8abc26bcc055c9f1f1d5f2f49060 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/daniissac
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1bba84d3657f8abc26bcc055c9f1f1d5f2f49060 -
Trigger Event:
release
-
Statement type:
File details
Details for the file cml2gns-0.2.1-py3-none-any.whl.
File metadata
- Download URL: cml2gns-0.2.1-py3-none-any.whl
- Upload date:
- Size: 44.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f87b710be93f9d879311f8a68352ffe6ffb5d940b0bd37b0f566865eb1b1c5fa
|
|
| MD5 |
481667d46f7948002fe6e3a86367f834
|
|
| BLAKE2b-256 |
f3ddd10ee541bf3f53f745e102233c07e704868a3f140d69865b0a2f6df836cd
|
Provenance
The following attestation bundles were made for cml2gns-0.2.1-py3-none-any.whl:
Publisher:
publish.yml on daniissac/cml2gns
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cml2gns-0.2.1-py3-none-any.whl -
Subject digest:
f87b710be93f9d879311f8a68352ffe6ffb5d940b0bd37b0f566865eb1b1c5fa - Sigstore transparency entry: 2172985000
- Sigstore integration time:
-
Permalink:
daniissac/cml2gns@1bba84d3657f8abc26bcc055c9f1f1d5f2f49060 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/daniissac
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1bba84d3657f8abc26bcc055c9f1f1d5f2f49060 -
Trigger Event:
release
-
Statement type: