username, password, ssl_verify=False) client.is_system_ready() except: print( f"\nUnable to contact CML2.x server, please check server connectivity." ) # get list of labs all_labs = client.all_labs() # check if programmatic_network_build exists if 'programmatic_network_build' in [lab.title for lab in all_labs]: print(f"\nprogrammatic_network_build exists, deleting lab..") lab = client.find_labs_by_title(title='programmatic_network_build')[0] try: lab.stop() lab.wipe() lab.remove() except Exception as e: print(f"Unable to stop programmatic_network_build lab, error: {e}") print(f"\nprogrammatic_network_build has been successfully deleted..") print(f"\nprogrammatic_network_build doesn't exist, creating lab..") # create new programmatic_network_build lab try: lab = client.create_lab(title='programmatic_network_build') # create nodes
from virl2_client import ClientLibrary VIRL_CONTROLLER = "virl2-controller" VIRL_USERNAME = input("username: "******"password: "******"enter lab name: ") client = ClientLibrary(VIRL_CONTROLLER, VIRL_USERNAME, VIRL_PASSWORD, ssl_verify=False) # Find the lab by title and join it as long as it's the only # lab with that title. 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)) exit(1) lobj = client.join_existing_lab(labs[0].id) if not lobj: print("ERROR: Failed to join lab {}".format(LAB_NAME)) exit(1) # Print all links in the lab and ask which link to condition. i = 1 liobjs = [] for link in lobj.links():
def parse(self, inventory, loader, path, cache=True): # call base method to ensure properties are available for use with other helper methods super(InventoryModule, self).parse(inventory, loader, path, cache) # this method will parse 'common format' inventory sources and # update any options declared in DOCUMENTATION as needed # config = self._read_config_data(self, path) self._read_config_data(path) # if NOT using _read_config_data you should call set_options directly, # to process any defined configuration for this plugin, # if you dont define any options you can skip # self.set_options() if 'VIRL_HOST' in os.environ and len(os.environ['VIRL_HOST']): self.host = os.environ['VIRL_HOST'] else: self.host = self.get_option('host') self.display.vvv("virl2.py - VIRL_HOST: {0}".format(self.host)) if 'VIRL_USERNAME' in os.environ and len(os.environ['VIRL_USERNAME']): self.username = os.environ['VIRL_USERNAME'] else: self.username = self.get_option('username') self.display.vvv("virl2.py - VIRL_USERNAME: {0}".format(self.username)) if 'VIRL_PASSWORD' in os.environ and len(os.environ['VIRL_PASSWORD']): self.password = os.environ['VIRL_PASSWORD'] else: self.password = self.get_option('password') if 'VIRL_LAB' in os.environ and len(os.environ['VIRL_LAB']): self.lab = os.environ['VIRL_LAB'] else: self.lab = self.get_option('lab') self.display.vvv("virl2.py - VIRL_LAB: {0}".format(self.lab)) if not self.lab: self.display.vvv("No lab defined. Nothing to do.") return self.group = self.get_option('group') if self.group is None: self.group = 'virl_hosts' self.display.vvv("virl2.py - Group: {0}".format(self.group)) self.inventory.set_variable('all', 'virl_host', self.host) self.inventory.set_variable('all', 'virl_username', self.username) self.inventory.set_variable('all', 'virl_password', self.password) self.inventory.set_variable('all', 'virl_lab', self.lab) url = 'https://{0}'.format(self.host) try: client = ClientLibrary(url, username=self.username, password=self.password, ssl_verify=False) except: raise AnsibleParserError('Unable to log into {0}'.format(url)) labs = (client.find_labs_by_title(self.lab)) if not labs: return try: group = self.inventory.add_group(self.group) except AnsibleError as e: raise AnsibleParserError("Unable to add group %s: %s" % (group, to_text(e))) group_dict = {} lab = labs[0] lab.sync() for node in lab.nodes(): self.inventory.add_host(node.label, group=self.group) virl = { 'state': node.state, 'image_definition': node.image_definition, 'node_definition': node.node_definition, 'cpus': node.cpus, 'ram': node.ram, 'config': node.config, 'data_volume': node.data_volume, } interface_list = [] ansible_host = None for interface in node.interfaces(): if interface.discovered_ipv4 and not ansible_host: ansible_host = interface.discovered_ipv4[0] interface_dict = { 'name': interface.label, 'state': interface.state, 'ipv4_addresses': interface.discovered_ipv4, 'ipv6_addresses': interface.discovered_ipv6, 'mac_address': interface.discovered_mac_address } interface_list.append(interface_dict) virl.update({'interfaces': interface_list}) if ansible_host: self.inventory.set_variable(node.label, 'ansible_host', ansible_host) self.inventory.set_variable(node.label, 'virl_facts', virl) self.display.vvv("Adding {0}({1}) to group {2}, state: {3}, ansible_host: {4}".format( node.label, node.node_definition, self.group, node.state, ansible_host)) # Group by node_definition if node.node_definition not in group_dict: try: group_dict[node.node_definition] = self.inventory.add_group(node.node_definition) except AnsibleError as e: raise AnsibleParserError("Unable to add group %s: %s" % (group, to_text(e))) self.inventory.add_host(node.label, group=node.node_definition)
data=payload, files=files) response.raise_for_status() if __name__ == "__main__": urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) client = ClientLibrary(cml_server_url, cml_username, cml_password, ssl_verify=False, raise_for_auth_failure=True, allow_http=True) #get lab lab = client.find_labs_by_title("Jupyter Lab")[0] #get lab testbed pyats_testbed = lab.get_pyats_testbed() #add credentials to testbed add_cml_credentials(pyats_testbed, "lab_testbed.yaml", cml_username, cml_password) #create directories if doesn't exist if not os.path.exists("./learn_results"): os.makedirs("./learn_results") if not os.path.exists("./diff_results"): os.makedirs("./diff_results") #load testbed
class DSTTopology(object): __client = None __lab = None __started = False __wiped = True __base_config_dir = None __nodes = { "Internet Router": { "type": "iosv", "node": None, "config": "internet_router.txt" }, "HQ Firewall": { "type": "asav", "node": None, "config": "hq_firewall.txt" }, "HQ Switch": { "type": "unmanaged_switch", "node": None }, "HQ Server": { "type": "ubuntu", "node": None, "config": "hq_server.txt" }, "Internet": { "type": "external_connector", "node": None }, "OOB Management": { "type": "external_connector", "node": None, "config": "oob_management.txt" }, } def __init__(self, cml_controller, base_config_dir): self.__base_config_dir = base_config_dir ssl_cert = False if "CA_BUNDLE" in os.environ: ssl_cert = os.environ["CA_BUNDLE"] # Create a client and use the environment to provide the username, password, and CA bundle self.__client = ClientLibrary(cml_controller, ssl_verify=ssl_cert) @staticmethod def __get_lab_suffix(): return "".join( random.choice(string.ascii_lowercase + string.digits) for i in range(8)) def __create_lab(self): # Wait for the low-level drive to connect self.__client.wait_for_lld_connected() lab_prefix = "Dynamic Split Tunnel Test-" lab_suffix = DSTTopology.__get_lab_suffix() # Find a unique name for this lab while True: labs = self.__client.find_labs_by_title(lab_prefix + lab_suffix) if labs is not None and len(labs) > 0: lab_suffix = DSTTopology.__get_lab_suffix() else: break self.__lab = self.__client.create_lab(title=lab_prefix + lab_suffix) self.__lab.description = "This lab is for testing a Dynamic Split Tunnel config change (created at: {ctime})".format( ctime=time.ctime()) self.__lab.wait_for_convergence = False def __add_nodes(self): # Create each node for node in list(self.__nodes.keys()): self.__nodes[node]["node"] = self.__lab.create_node( node, self.__nodes[node]["type"], populate_interfaces=True) def __connect_nodes(self): """ Connect all nodes in the test topology is a known, static way. """ # First connect Gi0/0 of the Internet Router to the Internet igi0 = self.__nodes["Internet Router"]["node"].get_interface_by_label( "GigabitEthernet0/0") iport = self.__nodes["Internet"]["node"].get_interface_by_label("port") self.__lab.create_link(igi0, iport) # Next connect Gi0/1 of the Internet Router to Gi0/0 of the HQ Firewall igi1 = self.__nodes["Internet Router"]["node"].get_interface_by_label( "GigabitEthernet0/1") fgi0 = self.__nodes["HQ Firewall"]["node"].get_interface_by_label( "GigabitEthernet0/0") self.__lab.create_link(igi1, fgi0) # Next connect Gi0/1 of the HQ Firewall to port0 of the HQ Switch # ...But before we can do that, we need to add a new interface. self.__nodes["HQ Firewall"]["node"].create_interface() fgi1 = self.__nodes["HQ Firewall"]["node"].get_interface_by_label( "GigabitEthernet0/1") sport0 = self.__nodes["HQ Switch"]["node"].get_interface_by_label( "port0") self.__lab.create_link(fgi1, sport0) # Next connect Management0/0 of HQ Firewall to the OOB Management network fm0 = self.__nodes["HQ Firewall"]["node"].get_interface_by_label( "Management0/0") oport = self.__nodes["OOB Management"]["node"].get_interface_by_label( "port") self.__lab.create_link(fm0, oport) # Next connect port1 of HQ Switch to port enp0s2 of the HQ Server sport1 = self.__nodes["HQ Switch"]["node"].get_interface_by_label( "port1") seth = self.__nodes["HQ Server"]["node"].get_interface_by_label( "enp0s2") self.__lab.create_link(sport1, seth) def __configure_nodes(self): for node, properties in list(self.__nodes.items()): if "config" in properties: config = self.__base_config_dir + "/" + properties["config"] if not os.path.exists(config): raise FileNotFoundError(config) with open(config, "r") as fd: conf_contents = fd.read() properties["node"].config = conf_contents def create_topology(self): """ Create a DST test topology and configure it. """ self.__create_lab() self.__add_nodes() self.__connect_nodes() self.__configure_nodes() def start(self): """ Start the DST test lab. """ if self.__started: return self.__lab.start() self.__started = True self.__wiped = False def stop(self): """ Stop the DST test lab. """ if not self.__started: return self.__lab.stop(wait=True) self.__started = False def is_ready(self): """ Check if the overall lab is ready. Returns: Boolean: True if all nodes have converged, False otherwise. """ if not self.__started: raise Exception("Lab has not been started yet.") ready = True for node, properties in list(self.__nodes.items()): if not properties["node"].has_converged( ) or properties["node"].has_converged( ) == 0 or not properties["node"].is_booted(): ready = False break return ready def get_fw_ip(self, wait=False): """ Return the IP address of the OOB Management interface on the firewall node. Parameters: wait (Boolean): Whether or not to wait for the firewall node to converge (default: False) Returns: string: The first IP address on Management0/0 if found, else None """ if not self.__started: raise Exception("Lab has not been started yet.") if not wait and not self.__nodes["HQ Firewall"]["node"].has_converged( ): raise Exception("Firewall node has not yet converged.") elif not self.__nodes["HQ Firewall"]["node"].has_converged(): while not self.__nodes["HQ Firewall"]["node"].has_converged(): time.sleep(1) fm0 = self.__nodes["HQ Firewall"]["node"].get_interface_by_label( "Management0/0") ip4_addr = fm0.discovered_ipv4 if len(ip4_addr) > 0: return ip4_addr[0] return None def wipe(self): """ Wipe the DST test lab """ if self.__started: raise Exception("Lab must be stopped first.") self.__lab.wipe(wait=True) self.__wiped = True def remove(self): """ Remove the lab from the CML controller. """ if not self.__wiped: raise Exception("Lab must be wiped before it can be removed.") self.__lab.remove()
def test_group_api_permissions(controller_url, client_library_session: ClientLibrary): cl_admin = client_library_session # create non-admin user username = "******" satoshi_pwd = "super-secret-pwd" satoshi = cl_admin.user_management.create_user(username=username, pwd=satoshi_pwd) halfinn = cl_admin.user_management.create_user(username="******", pwd=satoshi_pwd) satoshi_uid = satoshi["id"] cml2_uid = client_library_session.user_management.user_id(username="******") halfinn_uid = client_library_session.user_management.user_id( username="******") # assert there is no lab assert cl_admin.all_labs(show_all=True) == [] # create lab lab0 = cl_admin.create_lab(title="lab0") lab1 = cl_admin.create_lab(title="lab1") # create students group lab0_ro = [{"id": lab0.id, "permission": "read_only"}] lab0_1_rw = [ { "id": lab0.id, "permission": "read_write" }, { "id": lab1.id, "permission": "read_write" }, ] students_group = cl_admin.group_management.create_group( name="students", description="students group", members=[satoshi_uid], labs=lab0_ro, ) teachers_group = cl_admin.group_management.create_group( name="teachers", description="teachers group", members=[], labs=lab0_1_rw) all_groups = cl_admin.group_management.groups() assert len(all_groups) == 2 all_groups_names = [group["id"] for group in all_groups] assert students_group["id"] in all_groups_names assert teachers_group["id"] in all_groups_names # log in as non-admin satoshi user cl_satoshi = ClientLibrary( controller_url, username=username, password=satoshi_pwd, ssl_verify=False, allow_http=True, ) # satoshi must only see groups that he is part of satoshi_groups = cl_satoshi.group_management.groups() assert len(satoshi_groups) == 1 assert satoshi_groups[0]["name"] == "students" assert cl_satoshi.user_management.user_groups(user_id=satoshi_uid) == [ students_group["id"] ] # cannot check other user info with pytest.raises(requests.exceptions.HTTPError) as err: cl_satoshi.user_management.user_groups(user_id=cml2_uid) assert err.value.response.status_code == 403 assert "User does not have required access" in err.value.response.text # user cannot see groups he is not part of with pytest.raises(requests.exceptions.HTTPError) as err: cl_satoshi.group_management.get_group(group_id=teachers_group["id"]) assert err.value.response.status_code == 403 assert "User does not have required access" in err.value.response.text # can see those where he is member students_group = cl_satoshi.group_management.get_group( group_id=students_group["id"]) assert students_group["members"] == [satoshi_uid] # only admin can create, delete and modify group # create with pytest.raises(requests.exceptions.HTTPError) as err: cl_satoshi.group_management.create_group(name="xxx") assert err.value.response.status_code == 403 assert "User does not have required access" in err.value.response.text # update with pytest.raises(requests.exceptions.HTTPError) as err: cl_satoshi.group_management.update_group(group_id=teachers_group["id"], description="new") assert err.value.response.status_code == 403 assert "User does not have required access" in err.value.response.text # delete with pytest.raises(requests.exceptions.HTTPError) as err: cl_satoshi.group_management.delete_group(group_id=teachers_group["id"]) assert err.value.response.status_code == 403 assert "User does not have required access" in err.value.response.text # user cannot see members of group that he is not part of with pytest.raises(requests.exceptions.HTTPError) as err: cl_satoshi.group_management.group_members( group_id=teachers_group["id"]) assert err.value.response.status_code == 403 assert "User does not have required access" in err.value.response.text # can see those where he is member students_group_members = cl_satoshi.group_management.group_members( group_id=students_group["id"]) assert students_group_members == [satoshi_uid] # user cannot see labs of group that he is not part of with pytest.raises(requests.exceptions.HTTPError) as err: cl_satoshi.group_management.group_labs(group_id=teachers_group["id"]) assert err.value.response.status_code == 403 assert "User does not have required access" in err.value.response.text # can see those where he is member students_group_labs = cl_satoshi.group_management.group_labs( group_id=students_group["id"]) assert students_group_labs == [lab0.id] # we need to get lab objects again so that they are bound to satoshi user lab0 = cl_satoshi.find_labs_by_title(title="lab0")[0] # satishi can only see groups where he is a member - in this case students assert lab0.groups == [ { "id": students_group["id"], "permission": "read_only" }, ] # we cannot modify groups associations as satoshi is not owner or admin with pytest.raises(requests.exceptions.HTTPError) as err: lab0.update_lab_groups(group_list=[]) assert err.value.response.status_code == 403 assert "User does not have required access" in err.value.response.text # we cannot modify notes with pytest.raises(requests.exceptions.HTTPError) as err: lab0.notes = "new note" assert err.value.response.status_code == 403 assert "User does not have write permission to lab" in err.value.response.text # we cannot modify description with pytest.raises(requests.exceptions.HTTPError) as err: lab0.description = "new description" assert err.value.response.status_code == 403 assert "User does not have write permission to lab" in err.value.response.text # change students association to lab0 to read_write assert cl_admin.group_management.update_group( group_id=students_group["id"], labs=[{ "id": lab0.id, "permission": "read_write" }], ) # now user can perform writes to associated lab lab0.notes = "new note" assert lab0.notes == "new note" lab0.description = "new description" assert lab0.description == "new description" # get students groups association to lab0 back to read only # satoshi cannot - he is not admin or owner with pytest.raises(requests.exceptions.HTTPError) as err: lab0.update_lab_groups(group_list=[ { "id": students_group["id"], "permission": "read_only" }, ]) assert err.value.response.status_code == 403 assert "User does not have required access" in err.value.response.text # admin can lab0 = cl_admin.find_labs_by_title(title="lab0")[0] lab0.update_lab_groups(group_list=[ { "id": students_group["id"], "permission": "read_only" }, ]) lab0 = cl_satoshi.find_labs_by_title(title="lab0")[0] assert lab0.groups == [ { "id": students_group["id"], "permission": "read_only" }, ] # add teachers group rw association to lab0 (admin action) teachers_group = cl_admin.group_management.update_group( group_id=teachers_group["id"], labs=lab0_1_rw) # we cannot modify groups associations as satoshi is not admin or owner with pytest.raises(requests.exceptions.HTTPError) as err: lab0.update_lab_groups(group_list=[]) assert err.value.response.status_code == 403 assert "User does not have required access" in err.value.response.text # we cannot modify notes with pytest.raises(requests.exceptions.HTTPError) as err: lab0.notes = "new note" assert err.value.response.status_code == 403 assert "User does not have write permission to lab" in err.value.response.text # we cannot modify description with pytest.raises(requests.exceptions.HTTPError) as err: lab0.description = "new description" assert err.value.response.status_code == 403 assert "User does not have write permission to lab" in err.value.response.text # as satoshi has no access to lab1 - below list is empty assert cl_satoshi.find_labs_by_title(title="lab1") == [] # add satoshi to teachers group - by doing this now he gains read write # access to both ;ab0 and lab1 cl_admin.group_management.update_group(group_id=teachers_group["id"], members=[satoshi_uid]) # now we can access teachers group and related data assert cl_satoshi.group_management.get_group(group_id=teachers_group["id"]) assert cl_satoshi.group_management.group_members( group_id=teachers_group["id"]) == [satoshi_uid] assert (len( cl_satoshi.group_management.group_labs( group_id=teachers_group["id"])) == 2) user_groups = cl_satoshi.user_management.user_groups(user_id=satoshi_uid) assert students_group["id"] in user_groups and teachers_group[ "id"] in user_groups associated_groups_names = [ group["name"] for group in cl_satoshi.group_management.groups() ] assert ("students" in associated_groups_names and "teachers" in associated_groups_names) # test adjusting lab groups (only owner and admin can change lab group associations) # admin must see all associations # owner and non-admin users can only see those associations where they are members of group # log in as non-admin satoshi user cl_halfinn = ClientLibrary( controller_url, username="******", password=satoshi_pwd, ssl_verify=False, allow_http=True, ) # create lab owned by halfin lab2 = cl_halfinn.create_lab(title="lab2") # only satoshi in students group + add lab2 association cl_admin.group_management.update_group( group_id=students_group["id"], members=[satoshi_uid], labs=[{ "id": lab2.id, "permission": "read_only" }], ) # only halfinney in teachers group + add lab2 association cl_admin.group_management.update_group( group_id=teachers_group["id"], members=[halfinn_uid], labs=[{ "id": lab2.id, "permission": "read_only" }], ) halfinn_lab2 = cl_halfinn.find_labs_by_title(title="lab2")[0] # get lab owned by halfinney with satoshi (who is not owner) satoshi_lab2 = cl_satoshi.find_labs_by_title(title="lab2")[0] # get lab owned by halfinney with admin admin_lab2 = cl_admin.find_labs_by_title(title="lab2")[0] # admin must see both groups associated with lab2 assert admin_lab2.groups == [ { "id": students_group["id"], "permission": "read_only" }, { "id": teachers_group["id"], "permission": "read_only" }, ] # halfinney only sees group that he is member of (teachers) assert halfinn_lab2.groups == [ { "id": teachers_group["id"], "permission": "read_only" }, ] # satoshi only sees group that he is member of (students) assert satoshi_lab2.groups == [ { "id": students_group["id"], "permission": "read_only" }, ] # satoshi cannot update lab groups associations for lab2 -> 403 (not owner or admin) with pytest.raises(requests.exceptions.HTTPError) as err: satoshi_lab2.update_lab_groups(group_list=[]) assert err.value.response.status_code == 403 assert "User does not have required access" in err.value.response.text # associations mus still be present after above failure assert admin_lab2.groups == [ { "id": students_group["id"], "permission": "read_only" }, { "id": teachers_group["id"], "permission": "read_only" }, ] # halfinney cannot add/remove students association to lab2 as he is not member of students halfinn_lab2.update_lab_groups(group_list=[]) # above only removed the group teachers as halfinn is owner and also member of teachers assert halfinn_lab2.groups == [] # sees nothing assert satoshi_lab2.groups == [ { "id": students_group["id"], "permission": "read_only" }, ] # sees students assert admin_lab2.groups == [ { "id": students_group["id"], "permission": "read_only" }, ] # admin too sees only students as that is now only associtation # halfinney cannot add students group as he is not member with pytest.raises(requests.exceptions.HTTPError) as err: halfinn_lab2.update_lab_groups(group_list=[{ "id": students_group["id"], "permission": "read_only" }]) assert err.value.response.status_code == 403 assert "User does not have required access" in err.value.response.text # halfinney can add teachers as he is a member halfinn_lab2.update_lab_groups(group_list=[{ "id": teachers_group["id"], "permission": "read_only" }]) # halfinney only sees group that he is member of (teachers) assert halfinn_lab2.groups == [ { "id": teachers_group["id"], "permission": "read_only" }, ] # add halfinney to students group cl_admin.group_management.update_group( group_id=students_group["id"], members=[satoshi_uid, halfinn_uid], ) # halfinney now sees both students and teachers # associations mus still be present after above failure assert halfinn_lab2.groups == [ { "id": students_group["id"], "permission": "read_only" }, { "id": teachers_group["id"], "permission": "read_only" }, ] # he can now also remove both associations halfinn_lab2.update_lab_groups(group_list=[]) assert admin_lab2.groups == [] assert halfinn_lab2.groups == [] # satoshi lost access --> 404 with pytest.raises(requests.exceptions.HTTPError) as err: assert satoshi_lab2.groups == [] assert err.value.response.status_code == 404 assert "Lab not found" in err.value.response.text # add also possible halfinn_lab2.update_lab_groups(group_list=[ { "id": students_group["id"], "permission": "read_only" }, { "id": teachers_group["id"], "permission": "read_only" }, ]) assert halfinn_lab2.groups == [ { "id": students_group["id"], "permission": "read_only" }, { "id": teachers_group["id"], "permission": "read_only" }, ] assert satoshi_lab2.groups == [ { "id": students_group["id"], "permission": "read_only" }, ] # sees students as he is only part of students not teachers assert admin_lab2.groups == [ { "id": students_group["id"], "permission": "read_only" }, { "id": teachers_group["id"], "permission": "read_only" }, ] # admin can do whatever he pleases admin_lab2.update_lab_groups(group_list=[]) assert admin_lab2.groups == [] assert halfinn_lab2.groups == [] # satoshi lost access --> 404 with pytest.raises(requests.exceptions.HTTPError) as err: assert satoshi_lab2.groups == [] assert err.value.response.status_code == 404 assert "Lab not found" in err.value.response.text # CLEAN UP # again need to get lab0 from admin account lab0 = cl_admin.find_labs_by_title(title="lab0")[0] lab0.remove() lab1.remove() lab2.remove() cl_admin.user_management.delete_user(user_id=satoshi_uid) cl_admin.user_management.delete_user(user_id=halfinn_uid) assert cl_admin.group_management.delete_group( group_id=students_group["id"]) is None assert cl_admin.group_management.delete_group( group_id=teachers_group["id"]) is None assert cl_admin.group_management.groups() == [] assert cl_admin.all_labs(show_all=True) == []
def config_worker(param): netmiko_delay = 0.1 client = ClientLibrary( param["virl_controller"], param["virl_username"], param["virl_password"], ssl_verify=False, ) client.wait_for_lld_connected() with print_lock: print(f"{param['hostname']}: Connected to VIRL") our_lab = client.find_labs_by_title(param["lab_id"])[0] our_node = our_lab.get_node_by_label(param["hostname"]) with print_lock: print( f"{param['hostname']}: Identified lab and device: /{our_lab.id}/{our_node.id}/0" ) c = netmiko.ConnectHandler( device_type="terminal_server", host=param["virl_controller"], username=param["virl_username"], password=param["virl_password"], ) with print_lock: print(f"{param['hostname']}: Connected to terminal server") c.write_channel("\r\n") time.sleep(1) c.write_channel("\r\n") time.sleep(1) c.write_channel(f"open /{our_lab.id}/{our_node.id}/0\r") c.write_channel("\r\n") time.sleep(1) c.write_channel("\r\n") time.sleep(1) c.write_channel("\r\n") time.sleep(1) c.write_channel("\r\n") with print_lock: print(f"{param['hostname']} : Switching to IOS interpreter") try: netmiko.redispatch(c, device_type="cisco_ios") except Exception as e: with print_lock: print( f"{param['hostname']} : Failed to switch to IOS interpreter. {e}" ) c.find_prompt() # c.enable() with print_lock: print(f"{param['hostname']} : Preparing config") try: with open("swtemplate.j2", "r") as f: template = jinja2.Template(f.read()) config_to_send = template.render(device=param).split("\n") except: with print_lock: print(f"{param['hostname']} : Failed to prepare config") with print_lock: print(f"{param['hostname']} : Sending config") try: # I have found that console messages can upset netmiko, # so turn them off with a timed command c.send_command_timing("enable", netmiko_delay) c.send_command_timing("conf t", netmiko_delay) c.send_command_timing("no logging console", netmiko_delay) c.send_command_timing("end", netmiko_delay) time.sleep(1) c.write_channel("\r\n") c.find_prompt() c.send_config_set(config_to_send) with print_lock: print(f"{param['hostname']} : Config sent") except Exception as e: with print_lock: print(f"{param['hostname']} : Error, send config failed. {e}")
log = logging.getLogger(__name__) #Script for gathering testbed from CML #Environment variables cml_server_url = env.config['CML_SERVER_URL'] cml_username = env.config['CML_USERNAME'] cml_password = env.config['CML_PASSWORD'] #connect urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) client = ClientLibrary(cml_server_url, cml_username, cml_password, ssl_verify=False, raise_for_auth_failure=True, allow_http=True) #setup config files config_files = os.listdir(path='./config') config_files = [file for file in config_files if ".txt" in file] #get lab lab = client.find_labs_by_title("BRAIN 16.2")[0] print(lab) #get lab testbed pyats_testbed = lab.get_pyats_testbed() # Write the YAML testbed out to a file with open("lab_testbed.yaml", "w") as f: f.write(pyats_testbed)
LAB_USERNAME = '******' LAB_PASSWORD = '******' VIRL_CONTROLLER = 'virl.twpsyn.com' VIRL_USERNAME = input('username: '******'password: '******'s exactly one lab with this title our_lab = client.find_labs_by_title('Lab1')[0] xr_node = our_lab.get_node_by_label('S4') logging.info("Identified lab and device") # open the Netmiko connection via the terminal server # (SSH to the controller connects to the terminal server) c = netmiko.ConnectHandler(device_type='terminal_server', host=VIRL_CONTROLLER, username=VIRL_USERNAME, password=VIRL_PASSWORD) logging.info("Netmiko connection created") # send CR, get a prompt on terminal server c.write_channel('\r\n') sleep(1)