|
1 | 1 | #!/usr/bin/env python3
|
2 | 2 | #
|
3 | 3 | # This file is part of VIRL 2
|
4 |
| -# Copyright (c) 2019-2023, Cisco Systems, Inc. |
| 4 | +# Copyright (c) 2019-2024, Cisco Systems, Inc. |
5 | 5 | # All rights reserved.
|
6 | 6 | #
|
7 | 7 | # Python bindings for the Cisco VIRL 2 Network Simulation Platform
|
|
19 | 19 | # limitations under the License.
|
20 | 20 | #
|
21 | 21 |
|
22 |
| -from virl2_client import ClientLibrary |
| 22 | +# This script demonstrates various functionalities of the client library. |
| 23 | +# Each example is accompanied by comments explaining its purpose and usage. |
| 24 | +import pathlib |
23 | 25 |
|
24 |
| -CERT = """-----BEGIN CERTIFICATE----- |
25 |
| -MIIDGzCCAgOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAvMQ4wDAYDVQQKEwVDaXNj |
26 |
| -WhcNMzMwNDI0MjE1NTQzWjAvMQ4wDAYDVQQKEwVDaXNjbzEdMBsGA1UEAxMUTGlj |
27 |
| -ZW5zaW5nIFJvb3QgLSBERVYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB |
28 |
| -AQCcVnEB1h7fLrzDunrg27JBs7QyipsA64qA0Cqob17xrr/etnvWrX2te0P1gnU7 |
29 |
| -/8wcpaeEGgdpNNOvmQeO9heRlvpPs/LtOULHVr8coKnMmKen+eQ3JNnmHUeJ6eeS |
30 |
| -3Z8ntFF8K97Q61uaeHughdm78APwVjvgpEUMjxJ7VYM+vBOFLZutmGjTrgdcJ5h8 |
31 |
| -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRDIUUhtfshehpNG7cCNuZky+yLZTANBgkq |
32 |
| -hkiG9w0BAQsFAAOCAQEAhfGx8q6ufS+cqwNRwynj8a6YLfEfXjyQ9gCzze1aFJH7 |
33 |
| -3wfgbKoPQyWftMSuIID2dYw7esVOqqA+xbUKL2cK/4ftpkYvz8Q5Z8AkqzLuPM3P |
34 |
| -oEudrhu6u9rI31WHz1HLHABaKC+LUYpajG+bPKq6NEYy7zp1wvRUUHqbz9MMi+VK |
35 |
| -EYct4M8SANDRAY/ZrGhZaBZ+Qhybw5Ttm8hUY4OygUYHsr3t38FgW00WAHtocj4l |
36 |
| -z1LPIlCn0j76n2sH+w9jhp3MO7xlJQaTOM9rpsuO/Q== |
37 |
| ------END CERTIFICATE-----""" |
| 26 | +from virl2_client import ClientLibrary |
38 | 27 |
|
39 | 28 | SSMS = "https://sch-alpha.cisco.com/its/service/oddce/services/DDCEService"
|
40 | 29 |
|
|
45 | 34 | )
|
46 | 35 |
|
47 | 36 |
|
48 |
| -# setup the connection and clean everything |
49 |
| -cl = ClientLibrary("http://localhost:8001", "cml2", "cml2cml2", allow_http=True) |
50 |
| -cl.is_system_ready(wait=True) |
| 37 | +# Set up the CML 2 connection |
| 38 | +server_url = "http://localhost:8001" |
| 39 | +username = "cml2" # Default username if not changed in CML instance |
| 40 | +password = pathlib.Path("/etc/machine-id").read_text().strip() |
| 41 | +# Default password is equal to the contents of the CML instances /etc/machine-id file |
| 42 | +# If you are running this script remotely, replace the password above |
| 43 | +client_library = ClientLibrary(server_url, username, password, allow_http=True) |
51 | 44 |
|
52 |
| -# set transport if needed - also proxy can be set if needed |
53 |
| -# cl.licensing.licensing.set_transport( |
54 |
| -# ssms=ssms, proxy_server="172.16.1.100", proxy_port=8888 |
55 |
| -# ) |
56 |
| -cl.licensing.set_transport(ssms=SSMS) |
57 |
| -cl.licensing.install_certificate(cert=CERT) |
58 |
| -# 'register_wait' method waits max 45s for registration status to become COMPLETED |
59 |
| -# and another 45s for authorization status to become IN_COMPLIANCE |
60 |
| -cl.licensing.register_wait(token=TOKEN) |
| 45 | +# Check if the CML 2 system is ready |
| 46 | +client_library.is_system_ready(wait=True) |
61 | 47 |
|
| 48 | +# Set up licensing configuration |
| 49 | +client_library.licensing.set_transport(ssms=SSMS) |
| 50 | +client_library.licensing.register_wait(token=TOKEN) |
62 | 51 |
|
63 |
| -lab_list = cl.get_lab_list() |
| 52 | +# Get a list of existing labs and print their details |
| 53 | +lab_list = client_library.get_lab_list() |
64 | 54 | for lab_id in lab_list:
|
65 |
| - lab = cl.join_existing_lab(lab_id) |
66 |
| - lab.stop() |
67 |
| - lab.wipe() |
68 |
| - cl.remove_lab(lab_id) |
69 |
| - |
70 |
| -lab = cl.create_lab() |
71 |
| -lab = cl.join_existing_lab(lab_id="lab_1") |
72 |
| - |
73 |
| -s1 = lab.create_node("s1", "server", 50, 100) |
74 |
| -s2 = lab.create_node("s2", "server", 50, 200) |
75 |
| -print(s1, s2) |
76 |
| - |
77 |
| -# create a link between s1 and s2, equivalent to |
78 |
| -# s1_i1 = s1.create_interface() |
79 |
| -# s2_i1 = s2.create_interface() |
80 |
| -# lab.create_link(s1_i1, s2_i1) |
81 |
| -lab.connect_two_nodes(s1, s2) |
82 |
| - |
83 |
| -# this must remove the link between s1 and s2 |
84 |
| -lab.remove_node(s2) |
85 |
| - |
| 55 | + lab = client_library.join_existing_lab(lab_id) |
| 56 | + print("Lab ID:", lab.id) |
| 57 | + print("Lab Title:", lab.title) |
| 58 | + print("Lab Description:", lab.description) |
| 59 | + print("Lab State:", lab.state) |
| 60 | + print("----") |
| 61 | + |
| 62 | +# A simpler way to join all labs at once |
| 63 | +labs = client_library.all_labs() |
| 64 | + |
| 65 | +# Create a lab |
| 66 | +lab = client_library.create_lab() |
| 67 | + |
| 68 | +# Create two server nodes |
| 69 | +server1 = lab.create_node("server1", "server", 50, 100) |
| 70 | +server2 = lab.create_node("server2", "server", 50, 200) |
| 71 | +print("Created nodes:", server1, server2) |
| 72 | + |
| 73 | +# Create a link between server1 and server2 |
| 74 | +link = lab.connect_two_nodes(server1, server2) |
| 75 | +print("Created link between server1 and server2") |
| 76 | + |
| 77 | +# Remove the link between server1 and server2 |
| 78 | +link.remove() |
| 79 | +print("Removed link between server1 and server2") |
| 80 | + |
| 81 | +# Manually synchronize lab states - this happens automatically once per second |
| 82 | +# by default, but we can skip the wait by calling this method |
86 | 83 | lab.sync_states()
|
| 84 | + |
| 85 | +# Print the state of each node and its interfaces |
87 | 86 | for node in lab.nodes():
|
88 |
| - print(node, node.state) |
89 |
| - for iface in node.interfaces(): |
90 |
| - print(iface, iface.state) |
91 |
| - |
92 |
| -assert [link for link in lab.links() if link.state is not None] == [] |
93 |
| - |
94 |
| -# in case you's like to deregister after you're done |
95 |
| -status = cl.licensing.deregister() |
96 |
| -cl.licensing.remove_certificate() |
97 |
| -# set licensing back to default transport |
98 |
| -# default ssms is "https://smartreceiver.cisco.com/licservice/license" |
99 |
| -cl.licensing.set_default_transport() |
| 87 | + print(f"Node: {node.label} | State: {node.state}") |
| 88 | + for interface in node.interfaces(): |
| 89 | + print(f" Interface: {interface.label} | State: {interface.state}") |
| 90 | + |
| 91 | +# Export a lab topology to a file |
| 92 | +lab_data = lab.download() |
| 93 | +with open("demo_lab_export.yaml", "w") as file: |
| 94 | + file.write(lab_data) |
| 95 | +print("Lab exported successfully.") |
| 96 | + |
| 97 | +# Clean up the lab |
| 98 | +lab.stop() |
| 99 | +lab.wipe() |
| 100 | +lab.remove() # or client_library.remove_lab(lab_id) |
| 101 | + |
| 102 | +# Deregister (optional) and set licensing back to the default transport (optional) |
| 103 | +# Default SSMS is "https://smartreceiver.cisco.com/licservice/license" |
| 104 | +client_library.licensing.deregister() |
| 105 | +client_library.licensing.set_default_transport() |
0 commit comments