mirror of
				https://github.com/CiscoDevNet/cml-community.git
				synced 2025-11-03 21:43:16 +00:00 
			
		
		
		
	Breakout tool update add mac support (#25)
* breakout update and MAC OS support Added getAllNodes function to cmlApiCalls.py. Added Mac OS support into main.py Added new logic to get all nodes, find label and node_definition, sort by label and add the SecureCRT ini files. This matched what the breakout tool provided for my machine. * Update main.py * Using Lab_title Changed to use the LabTitle for the Directory/CRT. This makes it more human readable when you have multiple labs.
This commit is contained in:
		@@ -21,6 +21,21 @@ class CML:
 | 
				
			|||||||
        access_token = "Bearer " + json.loads(response.text)
 | 
					        access_token = "Bearer " + json.loads(response.text)
 | 
				
			||||||
        return(access_token)
 | 
					        return(access_token)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def getLabInfo(auth, server, lab):
 | 
				
			||||||
 | 
					        headers = {
 | 
				
			||||||
 | 
					        'accept': 'application/json',
 | 
				
			||||||
 | 
					        'Authorization': auth,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        response = requests.get(f'https://{server}/api/v0/labs/{lab}/?simplified=true', headers=headers, verify=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        lab_info = json.loads(response.text)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if response.status_code == 200:
 | 
				
			||||||
 | 
					            return(lab_info)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return("end of list")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getNodesByID(auth, server, lab, node_id):
 | 
					    def getNodesByID(auth, server, lab, node_id):
 | 
				
			||||||
        headers = {
 | 
					        headers = {
 | 
				
			||||||
        'accept': 'application/json',
 | 
					        'accept': 'application/json',
 | 
				
			||||||
@@ -35,3 +50,17 @@ class CML:
 | 
				
			|||||||
            return(node)
 | 
					            return(node)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            return("end of list")
 | 
					            return("end of list")
 | 
				
			||||||
 | 
					    def getAllNodes(auth, server, lab ):
 | 
				
			||||||
 | 
					        headers = {
 | 
				
			||||||
 | 
					        'accept': 'application/json',
 | 
				
			||||||
 | 
					        'Authorization': auth,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        response = requests.get(f'https://{server}/api/v0/labs/{lab}/nodes/?simplified=true', headers=headers, verify=False)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        nodes = json.loads(response.text)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if response.status_code == 200:
 | 
				
			||||||
 | 
					            return(nodes)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return("end of list")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -62,7 +62,7 @@ D:"Disable Directory Tree Detection"=00000002
 | 
				
			|||||||
D:"Disable MLSX"=00000000
 | 
					D:"Disable MLSX"=00000000
 | 
				
			||||||
D:"Log Mode"=00000000
 | 
					D:"Log Mode"=00000000
 | 
				
			||||||
D:"Disable Pass Through Printing"=00000000
 | 
					D:"Disable Pass Through Printing"=00000000
 | 
				
			||||||
S:"Hostname"=127.0.0.1
 | 
					S:"Hostname"=localhost
 | 
				
			||||||
D:"Server Requires Bare CR"=00000000
 | 
					D:"Server Requires Bare CR"=00000000
 | 
				
			||||||
D:"Disable Resize"=00000002
 | 
					D:"Disable Resize"=00000002
 | 
				
			||||||
D:"Enable 80-132 Column Switching"=00000001
 | 
					D:"Enable 80-132 Column Switching"=00000001
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@ import requests
 | 
				
			|||||||
import json
 | 
					import json
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import yaml
 | 
					import yaml
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
requests.packages.urllib3.disable_warnings()
 | 
					requests.packages.urllib3.disable_warnings()
 | 
				
			||||||
from cmlApiCalls import CML as cml
 | 
					from cmlApiCalls import CML as cml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -23,71 +24,81 @@ auth = cml.auth(server, username, password)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# get all nodes from the cml server (funtion in cmlApiCalls.py)
 | 
					# get all nodes from the cml server (funtion in cmlApiCalls.py)
 | 
				
			||||||
allNodes = cml.getAllNodes(auth, server, lab)
 | 
					allNodes = cml.getAllNodes(auth, server, lab)
 | 
				
			||||||
# print(allNodes) -- for troubleshooting
 | 
					# print(allNodes) # -- for troubleshooting
 | 
				
			||||||
N = True
 | 
					
 | 
				
			||||||
n_id = 0
 | 
					 | 
				
			||||||
port = 9000
 | 
					port = 9000
 | 
				
			||||||
try:
 | 
					
 | 
				
			||||||
    os.mkdir(rf"C:/Users/{user}/AppData/Roaming/VanDyke/Config/Sessions/CML-{lab}")
 | 
					## Changing to use Lab title vs Lab ID.
 | 
				
			||||||
except:
 | 
					labInfo = cml.getLabInfo(auth, server, lab)
 | 
				
			||||||
 | 
					labName = labInfo.get("lab_title")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Adding some code to determine if it is running on Mac OS.
 | 
				
			||||||
 | 
					## Not yet tested on Win OS.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					crtPath = "VanDyke/SecureCRT/Config/Sessions"
 | 
				
			||||||
 | 
					if sys.platform == 'darwin':
 | 
				
			||||||
 | 
					    appPath = "/Users/{}/Library/Application Support/{}/CML-{}".format(user,crtPath,labName)
 | 
				
			||||||
 | 
					    pathMode = 0o777
 | 
				
			||||||
 | 
					else: 
 | 
				
			||||||
 | 
					    appPath = "C:/Users/{}/AppData/Roaming/{}/CML-{}".format(user,crtPath,labName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if os.path.exists(appPath):
 | 
				
			||||||
    print("directory already exists... continue...")
 | 
					    print("directory already exists... continue...")
 | 
				
			||||||
 | 
					else:
 | 
				
			||||||
 | 
					    os.mkdir(appPath,pathMode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Create a Dict consisting of all (label:node_definition) from CML
 | 
				
			||||||
 | 
					nodeDict = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
while n_id < 100:
 | 
					for n_id in allNodes:
 | 
				
			||||||
    node_id = f"n{n_id}"
 | 
					    response = cml.getNodesByID(auth, server, lab, n_id)
 | 
				
			||||||
    response = cml.getNodesByID(auth, server, lab, node_id)
 | 
					    nodeDict.update({response.get("label"): response.get("node_definition")})
 | 
				
			||||||
    # print(response) -- for troubleshooting
 | 
					 | 
				
			||||||
    # if node does not exists, check the next node
 | 
					 | 
				
			||||||
    if response == "end of list":
 | 
					 | 
				
			||||||
        print("Node " + node_id + " does not exist, will check all nodes from n0 to n99.")
 | 
					 | 
				
			||||||
        # increment node number
 | 
					 | 
				
			||||||
        n_id = n_id + 1
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Sort keys to match breakout tool.  Tool assigned ports based on label.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for node in sorted(nodeDict):
 | 
				
			||||||
    # dont count devices that cannot be consoled into    
 | 
					    # dont count devices that cannot be consoled into    
 | 
				
			||||||
    elif (response.get("node_definition") == "external_connector" or
 | 
					    if (nodeDict.get(node) == "external_connector" or
 | 
				
			||||||
            response.get("node_definition") == "unmanaged_switch"):
 | 
					            nodeDict.get(node) == "unmanaged_switch"):
 | 
				
			||||||
        # increment node number
 | 
					        print ("Found {}, skipping".format(nodeDict.get(node)))
 | 
				
			||||||
        n_id = n_id + 1    
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        # get label
 | 
					        # get label
 | 
				
			||||||
        node_label = response.get("label")
 | 
					        node_label = node
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # turn port number into hex
 | 
					        # turn port number into hex
 | 
				
			||||||
        # strip "0x2233" and make it only 4 charators   
 | 
					        # strip "0x2233" and make it only 4 charators   
 | 
				
			||||||
        hexport = hex(port).split('x')[-1]
 | 
					        hexport = hex(port).split('x')[-1]
 | 
				
			||||||
        # node definition is also printed for troubleshooting
 | 
					        # node definition is also printed for troubleshooting
 | 
				
			||||||
        print("creating: " + node_label + " Node Definition: " + response.get("node_definition"))
 | 
					        print("creating: " + node_label + " Node Definition: " + nodeDict.get(node))
 | 
				
			||||||
        # create a secureCRT Session
 | 
					        # create a secureCRT Session
 | 
				
			||||||
        with open("config.ini", "r") as config:
 | 
					        with open("config.ini", "r") as config:
 | 
				
			||||||
            temp = config.read()
 | 
					            temp = config.read()
 | 
				
			||||||
            temp = temp.replace("REPLACE", "0000" + hexport)
 | 
					            temp = temp.replace("REPLACE", "0000" + hexport)
 | 
				
			||||||
            location = rf"C:/Users/{user}/AppData/Roaming/VanDyke/Config/Sessions/CML-{lab}/{port}-{node_label}.ini"
 | 
					            location = rf"{appPath}/{port}-{node_label}.ini"
 | 
				
			||||||
            with open( location, "w") as config2write:
 | 
					            with open( location, "w") as config2write:
 | 
				
			||||||
                config2write.write(temp)
 | 
					                config2write.write(temp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # if any custom nodes are added, and they dont add by 2 ports in the breakout tool
 | 
					        # if any custom nodes are added, and they dont add by 2 ports 
 | 
				
			||||||
        # add the node definition to the if statement below to only add by 1 port. 
 | 
					        # in the breakout tool add the node definition to the if 
 | 
				
			||||||
        if (response.get("node_definition") == "wan_emulator" or 
 | 
					        # statement below to only add by 1 port. 
 | 
				
			||||||
                response.get("node_definition") == "asav" or 
 | 
					        if (nodeDict.get(node) == "wan_emulator" or
 | 
				
			||||||
                response.get("node_definition") == "ftdv" or
 | 
					                nodeDict.get(node) == "asav" or
 | 
				
			||||||
                response.get("node_definition") == "server" or
 | 
					                nodeDict.get(node) == "ftdv" or
 | 
				
			||||||
                response.get("node_definition") == "alpine" or
 | 
					                nodeDict.get(node) == "server" or
 | 
				
			||||||
                response.get("node_definition") == "coreos" or
 | 
					                nodeDict.get(node) == "alpine" or
 | 
				
			||||||
                response.get("node_definition") == "desktop" or
 | 
					                nodeDict.get(node) == "coreos" or
 | 
				
			||||||
                response.get("node_definition") == "trex" or   
 | 
					                nodeDict.get(node) == "desktop" or
 | 
				
			||||||
                response.get("node_definition") == "ubuntu"):
 | 
					                nodeDict.get(node) == "trex" or
 | 
				
			||||||
 | 
					                nodeDict.get(node) == "viptela-bond" or
 | 
				
			||||||
 | 
					                nodeDict.get(node) == "viptela-smart" or
 | 
				
			||||||
 | 
					                nodeDict.get(node) == "viptela-manage" or
 | 
				
			||||||
 | 
					                nodeDict.get(node) == "ubuntu"):
 | 
				
			||||||
            # only add 1 to port number for the next device
 | 
					            # only add 1 to port number for the next device
 | 
				
			||||||
            port = port + 1
 | 
					            port = port + 1
 | 
				
			||||||
        # else add 2 to port number for the next device
 | 
					        # else add 2 to port number for the next device
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            port = port + 2
 | 
					            port = port + 2
 | 
				
			||||||
        # increment node number    
 | 
					
 | 
				
			||||||
        n_id = n_id + 1
 | 
					 | 
				
			||||||
# 
 | 
					 | 
				
			||||||
print("Nodes 0-99 checked. if you need more, increase the number checked in the while loop")
 | 
					 | 
				
			||||||
print("example change to: while n_id < 150:")
 | 
					 | 
				
			||||||
print("exiting...")
 | 
					print("exiting...")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user