ciscodevnet / virl2-client Goto Github PK
View Code? Open in Web Editor NEWClient library for the Cisco VIRL 2 Network Simulation Platform
License: Apache License 2.0
Client library for the Cisco VIRL 2 Network Simulation Platform
License: Apache License 2.0
I have installed CML and can get everything to work except for the images included with the environment. I have tried re-download the refplat and attaching the new one in case something got corrupted along the way, but that didn't work. I am at a loss currently, this is the first time I have worked with CML but I am a networking professional in a cisco environment. Any help would be awesome, the screen shot below depicts the issue. Cheers!
Issue when using cml client to access an sd-wan device via pyats. The initial commands fail as they are not allowed on sd-wan device. The testbed is generated on the fly so I can't see a way to set init_exec_commands=[], init_config_commands=[] on the connect line in virl2_client/models/cl_pyats.py run_command.
If you call node.stop() or node.wipe() with the wait=True flag, they still return immediately. I think this is because both methods use the same has_converged()
code that node.start() uses. This might be fine, but my guess is the /check_if_converged
API endpoint is not doing the right thing for the stop and wipe operations.
For wipe, this may not be a big deal. For stop, my code assumes that when stop(wait=True) completes, the node is down and can be wiped. This is not deterministically true, and therefore I had to add:
node.stop(wait=True)
while node.is_active():
time.sleep(1)
I'd like the wait=True to be honored.
cml generate pyats still generates "series;" instead of "platform:"
This may be a CML2.2 issue but could maybe be fixed in client
virl2-client requires requests_toolbelt, but it is not listed in the poetry.lock or in the wheel/dist on PyPi.
The workaround is to manually install requests_toolbelt.
I've got a bunch of nodes up and I have a set of configs I want to write to each. How I use the API to write the start up configs to each node? The Node.config var seems to be read only.
Hi,
It looks like disabling SSL verification in the library does not work. Here's my setup:
❯ python --version
Python 3.10.8
poetry show virl2_client
name : virl2-client
version : 2.4.1
description : VIRL2 Client Library
dependencies
from pathlib import Path
from virl2_client import ClientLibrary
client = ClientLibrary("https://x.x.x.x", "user", "password", ssl_verify=False)
# this lab name exists on CML system
lab = client.find_labs_by_title("My lab")[0]
I get the following output when I run the above script:
❯ python src/main.py
SSL Verification disabled
Traceback (most recent call last):
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/urllib3/connectionpool.py", line 703, in urlopen
httplib_response = self._make_request(
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/urllib3/connectionpool.py", line 386, in _make_request
self._validate_conn(conn)
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/urllib3/connectionpool.py", line 1042, in _validate_conn
conn.connect()
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/urllib3/connection.py", line 414, in connect
self.sock = ssl_wrap_socket(
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/urllib3/util/ssl_.py", line 453, in ssl_wrap_socket
ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls)
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/urllib3/util/ssl_.py", line 495, in _ssl_wrap_socket_impl
return ssl_context.wrap_socket(sock)
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/ssl.py", line 513, in wrap_socket
return self.sslsocket_class._create(
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/ssl.py", line 1071, in _create
self.do_handshake()
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/ssl.py", line 1342, in do_handshake
self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:997)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/requests/adapters.py", line 489, in send
resp = conn.urlopen(
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/urllib3/connectionpool.py", line 787, in urlopen
retries = retries.increment(
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/urllib3/util/retry.py", line 592, in increment
raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='x.x.x.x', port=443): Max retries exceeded with url: /api/v0/system_information (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:997)')))
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/gethdav/git/naas/virt-lab-man/src/main.py", line 9, in <module>
client = ClientLibrary("https://x.x.x.x", "user", "password", ssl_verify=False)
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/virl2_client/virl2_client.py", line 254, in __init__
self.check_controller_version()
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/virl2_client/virl2_client.py", line 427, in check_controller_version
controller_version or self.system_info().get("version", "").split("-")[0]
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/virl2_client/virl2_client.py", line 411, in system_info
response = self.session.get(urljoin(self._base_url, "system_information"))
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/requests/sessions.py", line 600, in get
return self.request("GET", url, **kwargs)
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/requests/sessions.py", line 587, in request
resp = self.send(prep, **send_kwargs)
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/requests/sessions.py", line 701, in send
r = adapter.send(request, **kwargs)
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/requests/adapters.py", line 563, in send
raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='x.x.x.x', port=443): Max retries exceeded with url: /api/v0/system_information (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:997)')))
I had a look through the source code. I think the problem is that while the ssl_verify
argument is "set" on the session object it is not actually used by the session. For example:
>>> import requests
>>> s = requests.Session()
>>> s.verify = False
>>> s.get("https://x.x.x.x")Traceback (most recent call last):
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/urllib3/connectionpool.py", line 703, in urlopen
httplib_response = self._make_request(
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/urllib3/connectionpool.py", line 386, in _make_request
self._validate_conn(conn)
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/urllib3/connectionpool.py", line 1042, in _validate_conn
conn.connect()
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/urllib3/connection.py", line 414, in connect
self.sock = ssl_wrap_socket(
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/urllib3/util/ssl_.py", line 453, in ssl_wrap_socket
ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls)
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/urllib3/util/ssl_.py", line 495, in _ssl_wrap_socket_impl
return ssl_context.wrap_socket(sock)
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/ssl.py", line 513, in wrap_socket
return self.sslsocket_class._create(
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/ssl.py", line 1071, in _create
self.do_handshake()
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/ssl.py", line 1342, in do_handshake
self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:997)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/requests/adapters.py", line 489, in send
resp = conn.urlopen(
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/urllib3/connectionpool.py", line 787, in urlopen
retries = retries.increment(
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/urllib3/util/retry.py", line 592, in increment
raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='x.x.x.x', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:997)')))
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/requests/sessions.py", line 600, in get
return self.request("GET", url, **kwargs)
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/requests/sessions.py", line 587, in request
resp = self.send(prep, **send_kwargs)
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/requests/sessions.py", line 701, in send
r = adapter.send(request, **kwargs)
File "/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/requests/adapters.py", line 563, in send
raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='x.x.x.x', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:997)')))
But if I pass the verify
option to the get()
call, it works:
>>> s.get("https://x.x.x.x", verify=False)
/Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/urllib3/connectionpool.py:1045: InsecureRequestWarning: Unverified HTTPS request is being made to host 'x.x.x.x'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/1.26.x/advanced-usage.html#ssl-warnings
warnings.warn(
<Response [200]>
The URL referenced in the comments above where ssl_verify is saved (http://docs.python-requests.org/en/master/user/advanced/#ssl-cert-verification) is misleading. Looking at the requests.Session.get() the verify
property does not appear to be used. Running the example I provided through the debugger appears to confirm this:
❯ python -m pdb src/main.py
> /Users/gethdav/git/naas/virt-lab-man/src/main.py(1)<module>()
-> import os
(Pdb) b /Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/requests/sessions.py:599
Breakpoint 1 at /Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/requests/sessions.py:599
(Pdb) c
SSL Verification disabled
> /Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/requests/sessions.py(599)get()
-> kwargs.setdefault("allow_redirects", True)
(Pdb) kwargs
{}
(Pdb) n
> /Users/gethdav/dbConda-2022_05-py39/envs/virt-lab-man/lib/python3.10/site-packages/requests/sessions.py(600)get()
-> return self.request("GET", url, **kwargs)
(Pdb) kwargs
{'allow_redirects': True}
(Pdb) self.request("GET", url, **kwargs)
*** requests.exceptions.SSLError: HTTPSConnectionPool(host='x.x.x.x', port=443): Max retries exceeded with url: /api/v0/system_information (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:997)')))
I am receiving "Please ensure the client version is compatible with the server version. client 2.1.0, server 2.1.1" when trying to run on the new CML 2.1.1. Is there any plan to update this to 2.1.1 soon?
There seems to be a bug with the way CA_BUNDLE
and CML_VERIFY_CERT
are handled, the docstring says:
virl2-client/virl2_client/virl2_client.py
Lines 218 to 220 in 5bf320f
For example, with the following .virlrc
:
VIRL_HOST=cml-04
VIRL_USERNAME=user
VIRL_PASSWORD=password
CML_VERIFY_CERT=True
CA_BUNDLE=False
I get the following exception:
from virl2_client import ClientLibrary
client = ClientLibrary()
<snip>
OSError: Could not find a suitable TLS CA certificate bundle, invalid path: False
It appears that we get the strings "False"
or "True"
and they should be converted to a bool
, ideally case insensitive.
138 if ssl_verify is True:
139 breakpoint()
--> 140 ssl_verify = _get_prop("CA_BUNDLE") or _get_prop("CML_VERIFY_CERT")
141
142 return host, username, password, ssl_verify
ipdb> interact
*interactive*
In [1]: _get_prop("CA_BUNDLE") or _get_prop("CML_VERIFY_CERT")
Out[1]: 'False'
In [2]: _get_prop("CA_BUNDLE")
Out[2]: 'False'
In [3]: _get_prop("CML_VERIFY_CERT")
Out[3]: 'True'
In [4]: _get_prop("CA_BUNDLE") or _get_prop("CML_VERIFY_CERT")
Out[4]: 'False'
Do we need two options for setting ssl_verify
? I initially thought it was for backward compatibility, but it seems this is a relatively new addition (#40).
My concern is that this could lead to unexpected behavior in certain cases. For example, if a path is set with CA_BUNDLE
and CML_VERIFY_CERT
is set to False
, one might expect ssl_verify
will be set to False
but CA_BUNDLE
takes precedence.
In [6]: _get_prop("CA_BUNDLE") or False
Out[6]: '/tmp/blah'
Note the use of a bool
here and not a str
CA_BUNDLE
set to True
and CML_VERIFY_CERT
to a path could also lead to unexpected behavior:
In [7]: True or "/tmp/path"
Out[7]: True
Could we reconsider the need for both options to avoid potential confusion and ensure consistent/simpler behavior?
I understand it might be too late for this, in this case we should probably clarify in the doc.
Maybe not too late for #104 ?
When using node.py add_tag() because it is reading and subsequently appending the new tag to self._tags and then pushing the list to the API it results in multiple entries of the same tag being pushed to CML.
My test code is:
# Apply Tags to Nodes
if len(node_tags) > 0:
print(f'Tag Count for node {node_label} is {len(node_tags)}')
print(f'Node Tags for node {node_label} are {new_node.tags()}')
for tag in node_tags:
print(f'Adding tag {tag} to node {node_label}...')
print(f'Node Tags for node {node_label} are {new_node.tags()}')
new_node.add_tag(tag)
sleep(2)
print(f'Node Tags for node {node_label} are {new_node.tags()}')
The output from a test where I'm attempting to add 3 tags (oob, routers, test) to the device shows as follows:
Tag Count for node dc_router01 is 3
Node Tags for node dc_router01 are []
Adding tag oob to node dc_router01...
Node Tags for node dc_router01 are []
Node Tags for node dc_router01 are ['oob']
Adding tag routers to node dc_router01...
Node Tags for node dc_router01 are ['oob']
Node Tags for node dc_router01 are ['oob', 'oob', 'routers']
Adding tag test to node dc_router01...
Node Tags for node dc_router01 are ['oob', 'oob', 'routers']
Node Tags for node dc_router01 are ['oob', 'oob', 'routers', 'oob', 'oob', 'routers', 'test']
I've fixed this with a modification to node.py to only push the single tag to the API endpoint as follows:
def add_tag(self, tag):
current = self._tags
if tag not in current:
current.append(tag)
# Push single tag to API
self._set_node_property("tags", [tag])
And the output after the change:
Tag Count for node dc_router01 is 3
Node Tags for node dc_router01 are []
Adding tag oob to node dc_router01...
Node Tags for node dc_router01 are []
Node Tags for node dc_router01 are ['oob']
Adding tag routers to node dc_router01...
Node Tags for node dc_router01 are ['oob']
Node Tags for node dc_router01 are ['oob', 'routers']
Adding tag test to node dc_router01...
Node Tags for node dc_router01 are ['oob', 'routers']
Node Tags for node dc_router01 are ['oob', 'routers', 'test']
Hi,
I want to shut down an abandoned lab at a certain period of time. The startup time of the lab can be obtained in the lab's BOOTED. However, virl2_client does not allow me to get this value.
I hope that virl2_client will be extended to be able to get the BOOTED of the lab.
When using the method connect_two_nodes
for two ios nodes
https://github.com/CiscoDevNet/virl2-client/blob/master/virl2_client/models/lab.py#L581
I get an Exception raised.
This occur when the next_available_interface
is Loopback0 - I think the JSON payload returned here https://github.com/CiscoDevNet/virl2-client/blob/master/virl2_client/models/lab.py#L571 does not contain the key id
most certainly because it makes no sense to create a link betwween Loopback0 and something else so probably it should be caught here.
Debugging logs below:
15:20:35,760 INFO: *** Adding link between Node: ios-1 and Node: ios-2
15:20:35,760 WARNING: Interface: Loopback0 <<<<<<<<<<< this is the output of node1.next_available_interface() or node1.create_interface()
15:20:35,806 WARNING: Interface: GigabitEthernet0/0
15:20:35,847 ERROR: API Error: {
"description": "The API at /api/v0/labs/fd2fab/links encountered an unexpected error. Please report this problem to support.",
"code": 500
}
Traceback (most recent call last):
File "virl2.py", line 125, in <module>
add_n_devices(lab, "ios-", "iosv", n)
File "virl2.py", line 111, in add_n_devices
create_link(lab, previous_device, device)
File "virl2.py", line 68, in create_link
lab.connect_two_nodes(d1, d2)
File "/Users/gmuloche/.pyenv/versions/3.7.7/lib/python3.7/site-packages/virl2_client/models/lab.py", line 594, in connect_two_nodes
return self.create_link(iface1, iface2)
File "/Users/gmuloche/.pyenv/versions/3.7.7/lib/python3.7/site-packages/virl2_client/models/lab.py", line 573, in create_link
link_id = result["id"]
KeyError: 'id'
The create_image_definition defines url as:
url = self._base_url + "image_definitions/" + image_id
This results in HTTP 405 error. The correct url should be:
url = self._base_url + "image_definitions/"
Tried to create a testbed, but controller version 2.2.3+build63 is incompatible with virl2_client:
% python3 create_testbed_from_cml.py
SSL Verification disabled
Traceback (most recent call last):
File "/Users/danielkuhl/Coding/nauto-lab-connectivity/create_testbed_from_cml.py", line 10, in
client = ClientLibrary(url, user, password, ssl_verify=False)
File "/Users/danielkuhl/Coding/nauto-lab-connectivity/venv/lib/python3.9/site-packages/virl2_client/virl2_client.py", line 281, in init
self.check_controller_version()
File "/Users/danielkuhl/Coding/nauto-lab-connectivity/venv/lib/python3.9/site-packages/virl2_client/virl2_client.py", line 429, in check_controller_version
raise InitializationError(
virl2_client.virl2_client.InitializationError: Controller version 2.2.3+build63 is marked incompatible! List of versions marked explicitly as incompatible: [2.0.0, 2.0.1, 2.1.0, 2.1.1, 2.1.2, 2.2.1, 2.2.2, 2.2.3].
Tested with the following code:
from virl2_client import ClientLibrary
import os
# Set variables
url = os.environ.get("CML_URL")
user = os.environ.get("CML_USER")
password = os.environ.get("CML_PASS")
# Create a client object for interacting with CML
client = ClientLibrary(url, user, password, ssl_verify=False)
# Find your lab. Method returns a list, this assumes the first lab returned is what you want
lab = client.find_labs_by_title("Test-Lab")[0]
# Retrieve the testbed for the lab
pyats_testbed = lab.get_pyats_testbed()
# Write the YAML testbed out to a file
with open("testbed.yaml", "w") as f:
f.write(pyats_testbed)
Tested with Python 3.9.13 in a virtual environment and the following packages installed:
Package Version
---------------------------- -----------
aiofiles 0.8.0
aiohttp 3.8.1
aiohttp-swagger 1.0.16
aiosignal 1.2.0
async-lru 1.0.3
async-timeout 4.0.2
attrs 21.4.0
bcrypt 3.2.2
certifi 2022.5.18.1
cffi 1.15.0
chardet 4.0.0
charset-normalizer 2.0.12
cisco-gnmi 1.0.15
click 8.1.3
cryptography 36.0.2
dill 0.3.5.1
distro 1.7.0
docopt 0.6.2
Flask 2.1.2
frozenlist 1.3.0
genie 22.4
genie.libs.clean 22.4.1
genie.libs.conf 22.4
genie.libs.filetransferutils 22.4
genie.libs.health 22.4
genie.libs.ops 22.4
genie.libs.parser 22.4
genie.libs.sdk 22.4
gitdb 4.0.9
GitPython 3.1.18
grpcio 1.46.1
gunicorn 20.1.0
idna 3.3
importlib-metadata 4.12.0
itsdangerous 2.1.2
Jinja2 3.1.2
jsonpickle 2.2.0
junit-xml 1.9
lxml 4.8.0
MarkupSafe 2.1.1
multidict 6.0.2
ncclient 0.6.9
netaddr 0.8.0
packaging 21.3
paramiko 2.11.0
pathspec 0.9.0
pip 22.1.2
prettytable 3.3.0
protobuf 3.20.1
psutil 5.9.0
pyats 22.4
pyats.aereport 22.4
pyats.aetest 22.4
pyats.async 22.4
pyats.connections 22.4
pyats.datastructures 22.4
pyats.easypy 22.4
pyats.kleenex 22.4
pyats.log 22.4
pyats.reporter 22.4
pyats.results 22.4
pyats.tcl 22.4
pyats.topology 22.4
pyats.utils 22.4
pycparser 2.21
pyftpdlib 1.5.6
PyNaCl 1.5.0
pyparsing 3.0.9
python-dateutil 2.8.2
python-engineio 3.14.2
python-socketio 4.6.1
PyYAML 6.0
requests 2.27.1
requests-toolbelt 0.9.1
ruamel.yaml 0.17.21
ruamel.yaml.clib 0.2.6
setuptools 62.3.2
six 1.16.0
smmap 5.0.0
tabulate 0.8.10
tftpy 0.8.0
tqdm 4.64.0
unicon 22.4
unicon.plugins 22.4
urllib3 1.26.9
virl2-client 2.4.0
virlutils 1.3.8
wcwidth 0.2.5
Werkzeug 2.1.2
wheel 0.37.1
xmltodict 0.13.0
yamllint 1.26.3
yang.connector 22.4
yarl 1.7.2
zipp 3.8.0
Current NodeImageDefinitions.upload_image_file shows progress like below while uploading image.
$ cml definitions images import image-file -f image.qcow2
Uploading image.qcow2
Progress: 8192 of 19202219 bytes (0%)
But the progress is updated every 10% of the uploaded size. It won't be helpful if the size of the image is big. And I don't think all of us always have stable and high speed uplink to CML.
So I propose more detailed progress report like below. This will be updated every time monitor is called and new byte is processed.
$ cml definitions images import image-file -f ~/Downloads/image.qcow2
Uploading image.qcow2
|###-----------------------------------------------| 1032192/19202219 5.4% [00:00:06]
|##################################################| 19202219/19202219 100.0% [00:02:07]
Upload completed
Hello, I am trying to run a command 'Show run' on a node, here's the sample code.
Code is very basic using the virl2_client module:
client = ClientLibary(server, username, password, ssl_verify=False)
client.wait_for_lld_connected()
lab = client.create_lab(‘testlab’)
r1 = lab.create_node(‘r1’, ‘iosv’, 50, 100)
r1.config = ‘hostname testing’
lab.start()
lab.wait_until_lab_converged()
cmd = r1.run_pyats_command(‘show run’)
then I get an AttributeError: ‘NoneType’ object has no attribute ‘devices’ on the cmd line above
I'm a new virlutils user. New cmlutils installation form pip. Trying to use with Cisco Modeling Labs (CML) v2.2.2 Sandbox on devnet. Getting error message:
virl2_client.exceptions.InitializationError: Controller version 2.2.2+build52 is marked incompatible! List of versions marked explicitly as incompatible: [2.0.0, 2.0.1, 2.1.0, 2.1.1, 2.1.2, 2.2.1, 2.2.2, 2.2.3].
What am I doing wrong?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.