Skip to content

Commit

Permalink
SIMPLE-5377 PCL general improvements (#59)
Browse files Browse the repository at this point in the history
Co-authored-by: Daniel Valent <dvalent@cisco.com>
  • Loading branch information
tmikuska and daniel-valent committed Oct 10, 2023
1 parent 6d3108e commit aecac89
Show file tree
Hide file tree
Showing 25 changed files with 2,865 additions and 1,554 deletions.
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@
# Bibliographic Dublin Core info.
epub_title = project

# The unique identifier of the text. This can be a ISBN number
# The unique identifier of the text. This can be an ISBN
# or the project homepage.
#
# epub_identifier = ''
Expand Down
2 changes: 0 additions & 2 deletions examples/demo.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@
"metadata": {},
"outputs": [],
"source": [
"import urllib3\n",
"from virl2_client import ClientLibrary\n",
"\n",
"urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)\n",
"client = ClientLibrary(\"https://192.168.1.1\", \"virl2\", \"virl2\", ssl_verify=False)"
]
},
Expand Down
2 changes: 1 addition & 1 deletion examples/licensing.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
result = licensing.register_wait(SL_TOKEN)
if not result:
result = licensing.get_reservation_return_code()
print("ERROR: Failed to register with Smart License server: {}!".format(result))
print(f"ERROR: Failed to register with Smart License server: {result}!")
exit(1)

# Get the current registration status. This returns a JSON blob with license
Expand Down
49 changes: 21 additions & 28 deletions examples/link_conditioning.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@


import getpass
import re

from httpx import HTTPStatusError

Expand All @@ -39,67 +38,61 @@
labs = client.find_labs_by_title(LAB_NAME)

if not labs or len(labs) != 1:
print("ERROR: Unable to find a unique lab named {}".format(LAB_NAME))
print(f"ERROR: Unable to find a unique lab named {LAB_NAME}")
exit(1)

lobj = client.join_existing_lab(labs[0].id)
lab = client.join_existing_lab(labs[0].id)

if not lobj:
print("ERROR: Failed to join lab {}".format(LAB_NAME))
if not lab:
print(f"ERROR: Failed to join lab {LAB_NAME}")
exit(1)

# Print all links in the lab and ask which link to condition.
i = 1
liobjs = []
for link in lobj.links():
links = []
for link in lab.links():
print(
"{}. {}[{}] <-> {}[{}]".format(
i,
link.interface_a.node.label,
link.interface_a.label,
link.interface_b.node.label,
link.interface_b.label,
)
f"{i}. {link.interface_a.node.label}[{link.interface_a.label}] <-> "
f"{link.interface_b.node.label}[{link.interface_b.label}]"
)
liobjs.append(lobj.get_link_by_interfaces(link.interface_a, link.interface_b))
links.append(link.interface_a.get_link_to(link.interface_b))
i += 1

print()
lnum = 0
while lnum < 1 or lnum > i:
lnum = input("Enter link number to condition (1-{}): ".format(i))
link_number = 0
while link_number < 1 or link_number > i:
try:
lnum = int(lnum)
link_number = int(input(f"Enter link number to condition (1-{i}): "))
except ValueError:
lnum = 0
link_number = 0

# Print the selected link's current conditioning (if any).
link = liobjs[lnum - 1]
print("Current condition is {}".format(link.get_condition()))
link = links[link_number - 1]
print(f"Current condition is {link.get_condition()}")
# Request the new conditoning for bandwidth, latency, jitter, and loss.
# Bandwidth is an integer between 0-10000000 kbps
# Bandwidth of 0 is "no bandwidth restriction"
# Latency is an integer between 0-10000 ms
# Jitter is an integer between 0-10000 ms
# Loss is a float between 0-100%
new_cond = input(
new_condition = input(
"enter new condition in format 'BANDWIDTH, "
"LATENCY, JITTER, LOSS' or 'None' to disable: "
)
# If "None" is provided disable any conditioning on the link.
if new_cond.lower() == "none":
if new_condition.lower() == "none":
link.remove_condition()
print("Link conditioning has been disabled.")
else:
try:
# Set the current conditioning based on the provided values.
cond_list = re.split(r"\s*,\s*", new_cond)
bw = int(cond_list[0]) # Bandwidth is an int
cond_list = new_condition.split(",")
bandwidth = int(cond_list[0]) # Bandwidth is an int
latency = int(cond_list[1]) # Latency is an int
jitter = int(cond_list[2]) # Jitter is an int
loss = float(cond_list[3]) # Loss is a float
link.set_condition(bw, latency, jitter, loss)
link.set_condition(bandwidth, latency, jitter, loss)
print("Link conditioning set.")
except HTTPStatusError as exc:
print("ERROR: Failed to set link conditioning: {}", format(exc))
print(f"ERROR: Failed to set link conditioning: {exc}")
exit(1)
118 changes: 72 additions & 46 deletions examples/sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@
# limitations under the License.
#

# This script demonstrates various functionalities of the client library.
# Each example is accompanied by comments explaining its purpose and usage.
import pathlib

from virl2_client import ClientLibrary

# Licensing setup configuration
CERT = """-----BEGIN CERTIFICATE-----
MIIDGzCCAgOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAvMQ4wDAYDVQQKEwVDaXNj
WhcNMzMwNDI0MjE1NTQzWjAvMQ4wDAYDVQQKEwVDaXNjbzEdMBsGA1UEAxMUTGlj
Expand All @@ -45,55 +50,76 @@
)


# setup the connection and clean everything
cl = ClientLibrary("http://localhost:8001", "cml2", "cml2cml2", allow_http=True)
cl.is_system_ready(wait=True)
# Set up the CML 2 connection
server_url = "http://localhost:8001"
username = "cml2" # Default username if not changed in CML instance
password = pathlib.Path("/etc/machine-id").read_text().strip()
# Default password is equal to the contents of the CML instances /etc/machine-id file
# If you are running this script remotely, replace the password above
client_library = ClientLibrary(server_url, username, password, allow_http=True)

# set transport if needed - also proxy can be set if needed
# cl.licensing.licensing.set_transport(
# ssms=ssms, proxy_server="172.16.1.100", proxy_port=8888
# )
cl.licensing.set_transport(ssms=SSMS)
cl.licensing.install_certificate(cert=CERT)
# 'register_wait' method waits max 45s for registration status to become COMPLETED
# and another 45s for authorization status to become IN_COMPLIANCE
cl.licensing.register_wait(token=TOKEN)
# Check if the CML 2 system is ready
client_library.is_system_ready(wait=True)

# Set up licensing configuration
client_library.licensing.set_transport(ssms=SSMS)
client_library.licensing.install_certificate(cert=CERT)
client_library.licensing.register_wait(token=TOKEN)

lab_list = cl.get_lab_list()
# Get a list of existing labs and print their details
lab_list = client_library.get_lab_list()
for lab_id in lab_list:
lab = cl.join_existing_lab(lab_id)
lab.stop()
lab.wipe()
cl.remove_lab(lab_id)

lab = cl.create_lab()
lab = cl.join_existing_lab(lab_id="lab_1")

s1 = lab.create_node("s1", "server", 50, 100)
s2 = lab.create_node("s2", "server", 50, 200)
print(s1, s2)

# create a link between s1 and s2, equivalent to
# s1_i1 = s1.create_interface()
# s2_i1 = s2.create_interface()
# lab.create_link(s1_i1, s2_i1)
lab.connect_two_nodes(s1, s2)

# this must remove the link between s1 and s2
lab.remove_node(s2)

lab = client_library.join_existing_lab(lab_id)
print("Lab ID:", lab.id)
print("Lab Title:", lab.title)
print("Lab Description:", lab.description)
print("Lab State:", lab.state)
print("----")

# A simpler way to join all labs at once
labs = client_library.all_labs()

# Create a lab
lab = client_library.create_lab()

# Create two server nodes
server1 = lab.create_node("server1", "server", 50, 100)
server2 = lab.create_node("server2", "server", 50, 200)
print("Created nodes:", server1, server2)

# Create a link between server1 and server2
link = lab.connect_two_nodes(server1, server2)
print("Created link between server1 and server2")

# Remove the link between server1 and server2
link.remove()
print("Removed link between server1 and server2")

# Manually synchronize lab states - this happens automatically once per second
# by default, but we can skip the wait by calling this method
lab.sync_states()

# Print the state of each node and its interfaces
for node in lab.nodes():
print(node, node.state)
for iface in node.interfaces():
print(iface, iface.state)

assert [link for link in lab.links() if link.state is not None] == []

# in case you's like to deregister after you're done
status = cl.licensing.deregister()
cl.licensing.remove_certificate()
# set licensing back to default transport
# default ssms is "https://smartreceiver.cisco.com/licservice/license"
cl.licensing.set_default_transport()
print(f"Node: {node.label} | State: {node.state}")
for interface in node.interfaces():
print(f" Interface: {interface.label} | State: {interface.state}")

# Export a lab topology to a file
lab_data = lab.download()
with open("demo_lab_export.yaml", "w") as file:
file.write(lab_data)
print("Lab exported successfully.")

# Clean up the lab
lab.stop()
lab.wipe()
lab.remove() # or client_library.remove_lab(lab_id)

# Deregister and remove the certificate (optional)
client_library.licensing.deregister()
client_library.licensing.remove_certificate()

# Set licensing back to the default transport (optional)
# Default SSMS is "https://smartreceiver.cisco.com/licservice/license"
client_library.licensing.set_default_transport()
Loading

0 comments on commit aecac89

Please sign in to comment.