Package: cmlutils
virlutilsA collection of utilities for interacting withCisco VIRL1.x orCisco Modeling Labs (CML)v2.0+.This document describes the new version of virlutils (aka cmlutils) that works with Cisco Modeling Labs v2.0 and higher.  Documentation for working with VIRL/CML 1.x is availablehere.virl up / cml upvirl(orcml) is a devops style cli which supports the most common VIRL/CML operations.  Adding new ones is easy...Usage:cml[OPTIONS]COMMAND[ARGS]...

Options:--debug/--no-debugPrintanydebuggingoutput.--helpShowthismessageandexit.

Commands:clearclearthecurrentlabIDclusterdisplayandmanageCMLclusterdetailscockpitopenstheCockpitUIcommandsendacommandorconfigtoanode(requirespyATS)consoleconsolefornodedefinitionsmanageimageandnodedefinitionsdownstopalabextractextractconfigurationsfromallnodesinalabgenerategenerateinvfileforvarioustoolsidgetthecurrentlabtitleandIDlicenseworkwithproductlicensinglslistsrunninglabsandoptionallythoseinthecachenodesgetnodelistforthecurrentlabpullpulltopology.yamlfromrepormremovealabsavesavelabtoalocalyamlfilesearchlisttopologiesavailableviagithubsshsshtoanodestartstartanodestopstopanodetelnettelnettoanodeuiopenstheWorkbenchforthecurrentlabupstartalabuseuselablaunchedelsewhereversionversioninformationwipewipealabornodeswithinalabPrerequisitesInstallationConfigurationUsage / WorkflowsDevelopmentPrerequisitesPython 3.8+ (tested with Python 3.8, 3.9, 3.10, 3.11 and 3.12)Installation1.Clone this repogitclonehttps://github.com/CiscoDevNet/virlutilscdvirlutils2.Either (2a) use pip, or (2b) use setup.py2a. Use pippipinstallcmlutilsOrpipinstallvirlutils2b. Use setup.pypython3-mvenvvenvsourcevenv/bin/activate
pythonsetup.pyinstallConfigurationThere really isn't much to configure, just set your CML credentials.  There are a few different ways to accomplish this, pick whichever one works best for you. The options listed below are in thepreferredorder..virlrc in working directoryAdd a .virlrc to the working directory, this will always be checked first and
is useful when you want to override one or more parameters for a particular project
directory.The contents would look something like this.VIRL_HOST=specialvirlserver.foo.comenvironment variablesYou can also add them as environment variables. This is useful if you want to override
the global VIRL settings.exportVIRL_HOST=192.0.2.100exportVIRL_USERNAME=adminexportVIRL_PASSWORD=admin123.virlrc in your home directoryConfigure VIRL credentials globally by putting them in ~/.virlrc the formattingVIRL_USERNAME=netadminsVIRL_PASSWORD=cancodetoo!Other configuration optionsIn addition to basic credentials, the following configuration options are supported
using any of the methods mentioned previouslyVIRL_TELNET_COMMAND- allows the user to customize the telnet command that is called.
This command will be passed the host/ip information from the running simulationExample:exportVIRL_TELNET_COMMAND="mytelnet {host}"VIRL_SSH_COMMAND- allows the user to customize the ssh command that is called.
This command will be passed the host/ip as well as the username from the running simulationExample:exportVIRL_SSH_COMMAND="myssh {username}@{host}"CML_VERIFY_CERT- The path to a PEM-encoded certificate file to use to verify the CML controller VM's SSL certificate.  If you do not wish to verify the certificate, set this to "False"Example:exportCML_VERIFY_CERT=/etc/certs/ca_bundle.pemCML_CONSOLE_COMMAND- allows the user to customize the SSH command that is called.This command will be passed the CML controller VM IP, the console path of the node, and the CML controller username (note:you may have to force a TTY allocation in your SSH command)Example:exportCML_CONSOLE_COMMAND="myssh {user}@{host} {console}"CML2_PLUS- If set in the config or in the environment then virlutils will assume the server is a CML 2+ server and not try and automatically guess its version.  If omitted, then virutils will attempt to automatically determine the CML/VIRL server versionExample:exportCML2_PLUS="yes"CML_PLUGIN_PATH- A delimiter-separated list of directories in which to find cmlutils plugins.  See theplugin documentationfor more details.  By default, thepluginsdirectory in the current.virldirectory will be searched.Example:exportCML_PLUGIN_PATH="~/cmlutils/plugins:/opt/cmlutils/plugins"Why so many choices??!?Understanding the precedence allows you to do some pretty cool things.Assume the following directory structure....
├── dev
│   ├── .virlrc
│   └── topology.yaml
├── prod
│   ├── .virlrc
│   └── topology.yaml
└── test
    ├── .virlrc
    └── topology.yamlThis allows three major benefits.you can easily use different credentials/servers for various environmentsyou can customize your lab .yaml files to include different tags, different node configurations, etc.you have a badass workflow.$cmllsLabsonServer
╒════════╤════════════════════════════════╤═════════════════════════╤═════════════════╤═════════╤═════════╤══════════════╕
│ID│Title│Description│Status│Nodes│Links│Interfaces│
╞════════╪════════════════════════════════╪═════════════════════════╪═════════════════╪═════════╪═════════╪══════════════╡||||||||╘════════╧════════════════════════════════╧═════════════════════════╧═════════════════╧═════════╧═════════╧══════════════╛
$cd../test
$cmlls
LabsonServer
╒════════╤════════════════════════════════╤═════════════════════════╤═════════════════╤═════════╤═════════╤══════════════╕
│ID│Title│Description│Status│Nodes│Links│Interfaces│
╞════════╪════════════════════════════════╪═════════════════════════╪═════════════════╪═════════╪═════════╪══════════════╡
│7c2cf3│SmallBranchTest││STARTED│9│8│23│
╘════════╧════════════════════════════════╧═════════════════════════╧═════════════════╧═════════╧═════════╧══════════════╛
$cd../prod
$cmlls
RunningSimulations
╒════════╤════════════════════════════════╤═════════════════════════╤═════════════════╤═════════╤═════════╤══════════════╕
│ID│Title│Description│Status│Nodes│Links│Interfaces│
╞════════╪════════════════════════════════╪═════════════════════════╪═════════════════╪═════════╪═════════╪══════════════╡
│7c2cf3│SmallBranchProd││STARTED│9│8│23│
╘════════╧════════════════════════════════╧═════════════════════════╧═════════════════╧═════════╧═════════╧══════════════╛Usage / WorkflowsBasic Workflowin the absence of better documentation, here's a sample workflow[venv]jclarke@jamahal:~/src/git/virlutils|cmlutils
⇒cmlls
LabsonServer
╒════════╤════════════════════════════════╤═════════════════════════╤═════════════════╤═════════╤═════════╤══════════════╕
│ID│Title│Description│Status│Nodes│Links│Interfaces│
╞════════╪════════════════════════════════╪═════════════════════════╪═════════════════╪═════════╪═════════╪══════════════╡
│02f6c6│CCIEEnterpriseInfrastructure││DEFINED_ON_CORE│54│67│216│
├────────┼────────────────────────────────┼─────────────────────────┼─────────────────┼─────────┼─────────┼──────────────┤
│332eab│BranchTest││DEFINED_ON_CORE│6│5│15│
├────────┼────────────────────────────────┼─────────────────────────┼─────────────────┼─────────┼─────────┼──────────────┤
│7c2cf3│SmallBranch││STOPPED│9│8│23│
├────────┼────────────────────────────────┼─────────────────────────┼─────────────────┼─────────┼─────────┼──────────────┤
│e5afaf│DynamicSplitTunnel││STOPPED│10│9│36│
├────────┼────────────────────────────────┼─────────────────────────┼─────────────────┼─────────┼─────────┼──────────────┤
│66defd│LabatTue14:45PM││STOPPED│2│1│6│
├────────┼────────────────────────────────┼─────────────────────────┼─────────────────┼─────────┼─────────┼──────────────┤
│bc518e│LabatWed21:39PM││STOPPED│9│1│26│
├────────┼────────────────────────────────┼─────────────────────────┼─────────────────┼─────────┼─────────┼──────────────┤
│0e1bb2│DFN│GermanResearchNetwork│DEFINED_ON_CORE│51│80│211│
╘════════╧════════════════════════════════╧═════════════════════════╧═════════════════╧═════════╧═════════╧══════════════╛[venv]jclarke@jamahal:~/src/git/virlutils|cmlutils
⇒cmlid
SmallBranch(ID:7c2cf3)[venv]jclarke@jamahal:~/src/git/virlutils|cmlutils
⇒cmlup
LabSmallBranch(ID:7c2cf3)isalreadysetasthecurrentlab
StartinglabSmallBranch(ID:7c2cf3)[venv]jclarke@jamahal:~/src/git/virlutils|cmlutils
⇒cmlls
LabsonServer
╒════════╤════════════════════════════════╤═════════════════════════╤═════════════════╤═════════╤═════════╤══════════════╕
│ID│Title│Description│Status│Nodes│Links│Interfaces│
╞════════╪════════════════════════════════╪═════════════════════════╪═════════════════╪═════════╪═════════╪══════════════╡
│02f6c6│CCIEEnterpriseInfrastructure││DEFINED_ON_CORE│54│67│216│
├────────┼────────────────────────────────┼─────────────────────────┼─────────────────┼─────────┼─────────┼──────────────┤
│332eab│BranchTest││DEFINED_ON_CORE│6│5│15│
├────────┼────────────────────────────────┼─────────────────────────┼─────────────────┼─────────┼─────────┼──────────────┤
│7c2cf3│SmallBranch││STARTED│9│8│23│
├────────┼────────────────────────────────┼─────────────────────────┼─────────────────┼─────────┼─────────┼──────────────┤
│e5afaf│DynamicSplitTunnel││STOPPED│10│9│36│
├────────┼────────────────────────────────┼─────────────────────────┼─────────────────┼─────────┼─────────┼──────────────┤
│66defd│LabatTue14:45PM││STOPPED│2│1│6│
├────────┼────────────────────────────────┼─────────────────────────┼─────────────────┼─────────┼─────────┼──────────────┤
│bc518e│LabatWed21:39PM││STOPPED│9│1│26│
├────────┼────────────────────────────────┼─────────────────────────┼─────────────────┼─────────┼─────────┼──────────────┤
│0e1bb2│DFN│GermanResearchNetwork│DEFINED_ON_CORE│51│80│211│
╘════════╧════════════════════════════════╧═════════════════════════╧═════════════════╧═════════╧═════════╧══════════════╛[venv]jclarke@jamahal:~/src/git/virlutils|cmlutils
⇒cmlnodes
Hereisalistofnodesinthislab
╒══════╤════════════════╤════════════════════╤═════════╤══════════╤══════════════════╕
│ID│Label│Type│State│Wiped?│L3Address(es)│
╞══════╪════════════════╪════════════════════╪═════════╪══════════╪══════════════════╡
│n0│branch-rtr│csr1000v│BOOTED│False│192.168.10.219│
├──────┼────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│n1│Internet│external_connector│BOOTED│False││
├──────┼────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│n2│branch-sw│iosvl2│BOOTED│False││
├──────┼────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│n3│client-desktop│desktop│BOOTED│False││
├──────┼────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│n4│WANLink1│wan_emulator│BOOTED│False││
├──────┼────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│n5│rtr-2│iosv│BOOTED│False││
├──────┼────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│n8│ext-conn-1│external_connector│BOOTED│False││
├──────┼────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│n6│trex-0│trex│BOOTED│False││
├──────┼────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│n7│VLAN10│external_connector│BOOTED│False││
╘══════╧════════════════╧════════════════════╧═════════╧══════════╧══════════════════╛[venv]jclarke@jamahal:~/src/git/virlutils|cmlutils
⇒cmlconsolebranch-rtr
admin@192.168.10.214's password:Connecting to console forConnected to terminalserver.Escape character is '^]'.

branch-rtr#
branch-rtr#
branch-rtr#
branch-rtr#[venv]jclarke@jamahal:~/src/git/virlutils|cmlutils
⇒cmldown
ShuttingdownlabSmallBranch(ID:7c2cf3).....
SUCCESS[venv]jclarke@jamahal:~/src/git/virlutils|cmlutils
⇒cmlls
LabsonServer
╒════════╤════════════════════════════════╤═════════════════════════╤═════════════════╤═════════╤═════════╤══════════════╕
│ID│Title│Description│Status│Nodes│Links│Interfaces│
╞════════╪════════════════════════════════╪═════════════════════════╪═════════════════╪═════════╪═════════╪══════════════╡
│02f6c6│CCIEEnterpriseInfrastructure││DEFINED_ON_CORE│54│67│216│
├────────┼────────────────────────────────┼─────────────────────────┼─────────────────┼─────────┼─────────┼──────────────┤
│332eab│BranchTest││DEFINED_ON_CORE│6│5│15│
├────────┼────────────────────────────────┼─────────────────────────┼─────────────────┼─────────┼─────────┼──────────────┤
│7c2cf3│SmallBranch││STOPPED│9│8│23│
├────────┼────────────────────────────────┼─────────────────────────┼─────────────────┼─────────┼─────────┼──────────────┤
│e5afaf│DynamicSplitTunnel││STOPPED│10│9│36│
├────────┼────────────────────────────────┼─────────────────────────┼─────────────────┼─────────┼─────────┼──────────────┤
│66defd│LabatTue14:45PM││STOPPED│2│1│6│
├────────┼────────────────────────────────┼─────────────────────────┼─────────────────┼─────────┼─────────┼──────────────┤
│bc518e│LabatWed21:39PM││STOPPED│9│1│26│
├────────┼────────────────────────────────┼─────────────────────────┼─────────────────┼─────────┼─────────┼──────────────┤
│0e1bb2│DFN│GermanResearchNetwork│DEFINED_ON_CORE│51│80│211│
╘════════╧════════════════════════════════╧═════════════════════════╧═════════════════╧═════════╧═════════╧══════════════╛[venv]jclarke@jamahal:~/src/git/virlutils|cmlutils
⇒cmluse--lab-name"Small Branch"[venv]jclarke@jamahal:~/src/git/virlutils|cmlutils
⇒cmlnodes
Hereisalistofnodesinthislab
╒══════╤════════════════╤════════════════════╤═════════╤══════════╤══════════════════╕
│ID│Label│Type│State│Wiped?│L3Address(es)│
╞══════╪════════════════╪════════════════════╪═════════╪══════════╪══════════════════╡
│n0│branch-rtr│csr1000v│STOPPED│False││
├──────┼────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│n1│Internet│external_connector│STOPPED│False││
├──────┼────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│n2│branch-sw│iosvl2│STOPPED│False││
├──────┼────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│n3│client-desktop│desktop│STOPPED│False││
├──────┼────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│n4│WANLink1│wan_emulator│STOPPED│False││
├──────┼────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│n5│rtr-2│iosv│STOPPED│False││
├──────┼────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│n8│ext-conn-1│external_connector│STOPPED│False││
├──────┼────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│n6│trex-0│trex│STOPPED│False││
├──────┼────────────────┼────────────────────┼─────────┼──────────┼──────────────────┤
│n7│VLAN10│external_connector│STOPPED│False││
╘══════╧════════════════╧════════════════════╧═════════╧══════════╧══════════════════╛Inventory Generationvirlutils will generate inventories for various management systemspyATS Testbed Generationquickly turn your simulations into a testbed file that can be used for pyATS/GeniecmlgeneratepyatsCommand and Config ExecutionUsing the same pyATS framework,virlutilscan execute CLI EXEC-level (e.g., "show") commands as well as configuration commands on nodes within a lab.  These nodes do not have to be externally reachable or have any IP connectivity.  This is a great way to test operational aspects of a completely isolated topology.  Before using thecommandcommand you must install pyATS.  You can install pyATS by runningpip install pyats.[venv]jclarke@jamahal:~/src/git/virlutils|cmlutils
⇒cmlcommand"branch-rtr""show version"CiscoIOSXESoftware,Version16.11.01b
CiscoIOSSoftware[Gibraltar],VirtualXESoftware(X86_64_LINUX_IOSD-UNIVERSALK9-M),Version16.11.1b,RELEASESOFTWARE(fc2)TechnicalSupport:http://www.cisco.com/techsupport
...[venv]jclarke@jamahal:~/src/git/virlutils|cmlutils
⇒cmlcommand--config"branch-rtr""snmp-server community notpublic"Ansible Inventory Generationquickly turn your simulations into an inventory file that can be used to run your playbooks
against.  Both INI and YAML(default) formats are supported by the tool.Usage:cmlgenerateansible[OPTIONS]generateansibleinventory

Options:-o,--outputTEXToutputFilename--style[ini|yaml]outputformat(defaultisyaml)--helpShowthismessageandexit.The ansible group membership can be controlled by adding the "ansible_group" tag to nodes in your CML labs.  Multiple "ansible_group" tags can be assigned to a single node, and that node will be placed into each Ansible inventory group.nodes:-id:n0label:branch-rtrnode_definition:csr1000vtags:-ansible_group=mygroupwould result in the following inventory entryall:children:mygroup:hosts:branch-router:ansible_host:192.0.2.1NOTE:if the ansible_group tag is not specified for a node, that node will not be included during inventory generation.  Additionally, CML needs to know each node's management IP address before it will be placed into the inventory fileCisco Network Services OrchestratorYou can add/update Network Services Orchestrator with your VIRL simulation.UsageUsage:cmlgeneratenso[OPTIONS]generatensoinventory

Options:-o,--outputTEXTjustdumpthepayloadtofilewithoutsending--syncfrom/--no-syncfromPerformsync-fromafterupdatingdevices--helpShowthismessageandexit.outputUpdatingNSO....
EnterNSOIP/Hostname:localhost
EnterNSOusername:admin
EnterNSOpassword:
SuccessfullyaddedCMLdevicestoNSONOTE:  NSO environment is also attempted to be determined using the following environment
variablesNSO_HOSTNSO_USERNAMENSO_PASSWORDNSO Configuration ExampleexportNSO_HOST=localhostexportNSO_USERNAME=adminexportNSO_PASSWORD=adminTab Completions[venv]jclarke@jamahal:~/src/git/virlutils|cmlutils
⇒cmll<tab>
licenselsYou can activate VIRL autocompletions by executing the following commandeval"$(_VIRL_COMPLETE=bash_sourcevirl)"To do the same for thecmlcommand, do the followingeval"$(_CML_COMPLETE=bash_sourcecml)"zsh users may need to run the following priorautoloadbashcompinit
bashcompinitAnd then the following to properly enable completions for zsheval"$(_VIRL_COMPLETE=zsh_sourcevirl)"eval"$(_CML_COMPLETE=zsh_sourcecml)"Local DevelopmentIf you have an idea for a feature you would like to see, we gladly accept pull requests.  To get started developing, simply run the following..gitclonehttps://github.com/CiscoDevNet/virlutilscdvirlutils
pythonsetup.pydevelopLintingWe use flake 8 to lint our code. Please keep the repository clean by running:flake8TestingWe have some testing implemented, but would love to have better coverage. If you
add a feature, or just feel like writing tests please update the appropriate files
in thetestsfolder.To run the tests in thetestsfolder, you can simply runmake testfrom
the project root.