├── Module 2 Python Files ├── Hello World.py ├── inventory.txt ├── Loops.py ├── Files.py └── Conditionals.py ├── Module 5 Python Files ├── get_interfaces.xml ├── telnetRouter.py ├── sshNetmiko.py ├── sshParamiko.py ├── switchQos.py ├── get_capabilities.py ├── get_interfaces_config.py └── get_hostname.py ├── README.md ├── Module 3 Python Files ├── Service Ticket.py ├── User.py └── Host.py ├── Module 4 Python File └── DEMO-TENANT.py └── Module 1 Python File └── Hello World.py /Module 2 Python Files/Hello World.py: -------------------------------------------------------------------------------- 1 | print("Hello World") 2 | 3 | -------------------------------------------------------------------------------- /Module 2 Python Files/inventory.txt: -------------------------------------------------------------------------------- 1 | Cisco 3750 Catalyst Switch 2 | Cisco 2960 Catalyst Switch 3 | Cisco 2911 Router 4 | Cisco 7965G IP Phone -------------------------------------------------------------------------------- /Module 2 Python Files/Loops.py: -------------------------------------------------------------------------------- 1 | x=input("Enter the number to which you wish to count: ") 2 | x=int(x) 3 | y=1 4 | while True: 5 | print(y) 6 | y=y+1 7 | if y>x: 8 | break 9 | -------------------------------------------------------------------------------- /Module 5 Python Files/get_interfaces.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Module 2 Python Files/Files.py: -------------------------------------------------------------------------------- 1 | file=open("inventory.txt", "a") 2 | while True: 3 | newitem=input("Enter new inventory item: ") 4 | if newitem == "exit": 5 | print("All done!") 6 | break 7 | file.write(newitem + "\n") 8 | file.close 9 | -------------------------------------------------------------------------------- /Module 2 Python Files/Conditionals.py: -------------------------------------------------------------------------------- 1 | dscp=input("Enter the DSCP value: ") 2 | if dscp=="46": 3 | print("This is a voice media packet.") 4 | elif dscp=="24": 5 | print("This is a voice signaling packet.") 6 | else: 7 | print("This is not a voice packet.") 8 | 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Fundamentals of Network Programmablity Course Files 2 | 3 | The creation of the files in this repository was shown in Kevin Wallace's "Fundamentals of Network Programmability" course. 4 | 5 | The files are provided here as a resource for learners in that course. 6 | 7 | The files are organized into folders corresponding to the course modules in which they were created. 8 | -------------------------------------------------------------------------------- /Module 5 Python Files/telnetRouter.py: -------------------------------------------------------------------------------- 1 | import getpass 2 | import telnetlib 3 | 4 | HOST = "192.168.1.77" 5 | user = input("Enter your username: ") 6 | password = getpass.getpass() 7 | 8 | tn = telnetlib.Telnet(HOST) 9 | 10 | tn.read_until(b"Username: ") 11 | tn.write(user.encode('ascii') + b"\n") 12 | if password: 13 | tn.read_until(b"Password: ") 14 | tn.write(password.encode('ascii') + b"\n") 15 | 16 | tn.write(b"enable\n") 17 | tn.write(b"cisco\n") 18 | tn.write(b"conf t\n") 19 | tn.write(b"host HQ-ROUTER\n") 20 | tn.write(b"end\n") 21 | tn.write(b"copy run star\n") 22 | tn.write(b"\n") 23 | tn.write(b"exit\n") 24 | 25 | print(tn.read_all().decode('ascii')) -------------------------------------------------------------------------------- /Module 3 Python Files/Service Ticket.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | requests.packages.urllib3.disable_warnings() 4 | 5 | 6 | CONTROLLER_IP="devnetapi.cisco.com/sandbox/apic_em" 7 | 8 | payload={"username":"devnetuser","password":"Cisco123!"} 9 | url="https://"+CONTROLLER_IP+"/api/v1/ticket" 10 | header={"content-type":"application/json"} 11 | 12 | 13 | response=requests.post(url,data=json.dumps(payload),headers=header,verify=False) 14 | 15 | if(not response): 16 | print("No data returned!") 17 | else: 18 | r_json=response.json() 19 | print(r_json) 20 | ticket=r_json["response"]["serviceTicket"] 21 | print("Ticket: "+ticket) 22 | 23 | -------------------------------------------------------------------------------- /Module 5 Python Files/sshNetmiko.py: -------------------------------------------------------------------------------- 1 | from netmiko import ConnectHandler 2 | 3 | cat2960 = { 4 | "device_type": "cisco_ios", 5 | "ip": "192.168.1.202", 6 | "username": "cisco", 7 | "password": "cisco", 8 | "secret": "cisco", 9 | } 10 | 11 | net_connect = ConnectHandler(**cat2960) 12 | 13 | net_connect.enable() 14 | 15 | output = net_connect.send_command("show vlan brief") 16 | print (output) 17 | 18 | for vlan in range (10,51,10): 19 | config_commands = ["vlan " + str(vlan), "name Netmiko_VLAN_" + str(vlan)] 20 | output = net_connect.send_config_set(config_commands) 21 | print (output) 22 | 23 | output = net_connect.send_command("show vlan brief") 24 | print (output) 25 | -------------------------------------------------------------------------------- /Module 5 Python Files/sshParamiko.py: -------------------------------------------------------------------------------- 1 | import paramiko 2 | import time 3 | 4 | HOST = "192.168.1.202" 5 | USER = "cisco" 6 | PASS = "cisco" 7 | 8 | ssh_client = paramiko.SSHClient() 9 | ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 10 | ssh_client.connect(hostname=HOST,username=USER,password=PASS) 11 | 12 | ssh_connection = ssh_client.invoke_shell() 13 | 14 | ssh_connection.send("enable\n") 15 | ssh_connection.send("cisco\n") 16 | ssh_connection.send("conf t\n") 17 | 18 | for vlan in range (10,51,10): 19 | ssh_connection.send("vlan " + str(vlan) + "\n") 20 | ssh_connection.send("name Paramiko_VLAN_" + str(vlan) + "\n") 21 | ssh_connection.send("end\n") 22 | 23 | time.sleep(1) 24 | 25 | output = ssh_connection.recv(11111).decode(encoding="utf-8") 26 | 27 | print(output) 28 | 29 | ssh_client.close 30 | -------------------------------------------------------------------------------- /Module 5 Python Files/switchQos.py: -------------------------------------------------------------------------------- 1 | import getpass 2 | import telnetlib 3 | 4 | file=open("switches.txt","r") 5 | 6 | for switchIp in file: 7 | switchIp=switchIp.strip() 8 | print("Current switch: "+switchIp) 9 | user = input("Enter your username: ") 10 | password = getpass.getpass() 11 | 12 | tn = telnetlib.Telnet(switchIp) 13 | 14 | tn.read_until(b"Username: ") 15 | tn.write(user.encode('ascii') + b"\n") 16 | if password: 17 | tn.read_until(b"Password: ") 18 | tn.write(password.encode('ascii') + b"\n") 19 | 20 | tn.write(b"enable\n") 21 | tn.write(b"cisco\n") 22 | tn.write(b"conf t\n") 23 | tn.write(b"int range fa 0/1-10\n") 24 | tn.write(b"auto qos voip cisco-phone\n") 25 | tn.write(b"end\n") 26 | tn.write(b"copy run star\n") 27 | tn.write(b"\n") 28 | tn.write(b"exit\n") 29 | 30 | print(tn.read_all().decode('ascii')) 31 | 32 | file.close() -------------------------------------------------------------------------------- /Module 5 Python Files/get_capabilities.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from ncclient import manager 4 | import sys 5 | 6 | 7 | # the variables below assume the user is leveraging the 8 | # network programmability lab and accessing csr1000v 9 | # use the IP address or hostname of your CSR1000V device 10 | HOST = 'ios-xe-mgmt.cisco.com' 11 | # use the NETCONF port for your IOS-XE device 12 | PORT = 10000 13 | # use the user credentials for your IOS-XE device 14 | USER = 'root' 15 | PASS = 'D_Vay!_10&' 16 | 17 | 18 | # create a main() method 19 | def main(): 20 | """ 21 | Main method that prints netconf capabilities of remote device. 22 | """ 23 | with manager.connect(host=HOST, port=PORT, username=USER, 24 | password=PASS, hostkey_verify=False, 25 | device_params={'name': 'default'}, 26 | look_for_keys=False, allow_agent=False) as m: 27 | 28 | # print all NETCONF capabilities 29 | print('***Here are the Remote Devices Capabilities***') 30 | for capability in m.server_capabilities: 31 | print(capability.split('?')[0]) 32 | 33 | if __name__ == '__main__': 34 | sys.exit(main()) 35 | -------------------------------------------------------------------------------- /Module 5 Python Files/get_interfaces_config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Get configured interfaces using Netconf 4 | # 5 | # darien@sdnessentials.com 6 | # 7 | 8 | from ncclient import manager 9 | import sys 10 | import xml.dom.minidom 11 | 12 | 13 | # the variables below assume the user is leveraging the 14 | # network programmability lab and accessing csr1000v 15 | # use the IP address or hostname of your CSR1000V device 16 | HOST = 'ios-xe-mgmt.cisco.com' 17 | # use the NETCONF port for your IOS-XE device 18 | PORT = 10000 19 | # use the user credentials for your IOS-XE device 20 | USER = 'root' 21 | PASS = 'D_Vay!_10&' 22 | # XML file to open 23 | FILE = 'get_interfaces.xml' 24 | 25 | 26 | # create a main() method 27 | def get_configured_interfaces(xml_filter): 28 | """ 29 | Main method that retrieves the interfaces from config via NETCONF. 30 | """ 31 | with manager.connect(host=HOST, port=PORT, username=USER, 32 | password=PASS, hostkey_verify=False, 33 | device_params={'name': 'default'}, 34 | allow_agent=False, look_for_keys=False) as m: 35 | with open(xml_filter) as f: 36 | return(m.get_config('running', f.read())) 37 | 38 | 39 | def main(): 40 | """ 41 | Simple main method calling our function. 42 | """ 43 | interfaces = get_configured_interfaces(FILE) 44 | print(xml.dom.minidom.parseString(interfaces.xml).toprettyxml()) 45 | 46 | if __name__ == '__main__': 47 | sys.exit(main()) 48 | -------------------------------------------------------------------------------- /Module 3 Python Files/User.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | requests.packages.urllib3.disable_warnings() 4 | 5 | 6 | CONTROLLER_IP="devnetapi.cisco.com/sandbox/apic_em" 7 | GET="get" 8 | POST="post" 9 | 10 | def getServiceTicket(): 11 | payload={"username":"devnetuser","password":"Cisco123!"} 12 | url="https://"+CONTROLLER_IP+"/api/v1/ticket" 13 | header={"content-type":"application/json"} 14 | 15 | response=requests.post(url,data=json.dumps(payload),headers=header,verify=False) 16 | 17 | if(not response): 18 | print("No data returned!") 19 | else: 20 | r_json=response.json() 21 | print(r_json) 22 | ticket=r_json["response"]["serviceTicket"] 23 | print("Ticket: "+ticket) 24 | return ticket 25 | 26 | def doRestCall(aTicket,command,url,aData=None): 27 | response_json=None 28 | payload=None 29 | if(aData!=None): 30 | payload=json.dumps(aData) 31 | header={"X-Auth-Token":aTicket,"content-type":"application/json"} 32 | if(command==GET): 33 | r=requests.get(url,data=payload,headers=header,verify=False) 34 | elif(command==POST): 35 | r=requests.post(url,data=payload,headers=header,verify=False) 36 | else: 37 | print("Unknown command!") 38 | return 39 | if(not r): 40 | print("No data returned!") 41 | else: 42 | response_json=r.json() 43 | print(response_json) 44 | 45 | def main(): 46 | ticket=getServiceTicket() 47 | if(ticket): 48 | doRestCall(ticket,GET,"https://"+CONTROLLER_IP+"/api/v1/user") 49 | else: 50 | print("no service ticket was received. Ending program!") 51 | 52 | main() 53 | 54 | -------------------------------------------------------------------------------- /Module 3 Python Files/Host.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | requests.packages.urllib3.disable_warnings() 4 | 5 | 6 | CONTROLLER_IP="devnetapi.cisco.com/sandbox/apic_em" 7 | GET="get" 8 | POST="post" 9 | 10 | def getServiceTicket(): 11 | payload={"username":"devnetuser","password":"Cisco123!"} 12 | url="https://"+CONTROLLER_IP+"/api/v1/ticket" 13 | header={"content-type":"application/json"} 14 | 15 | response=requests.post(url,data=json.dumps(payload),headers=header,verify=False) 16 | 17 | if(not response): 18 | print("No data returned!") 19 | else: 20 | r_json=response.json() 21 | ticket=r_json["response"]["serviceTicket"] 22 | return ticket 23 | 24 | def doRestCall(aTicket,command,url,aData=None): 25 | response_json=None 26 | payload=None 27 | if(aData!=None): 28 | payload=json.dumps(aData) 29 | header={"X-Auth-Token":aTicket,"content-type":"application/json"} 30 | if(command==GET): 31 | r=requests.get(url,data=payload,headers=header,verify=False) 32 | elif(command==POST): 33 | r=requests.post(url,data=payload,headers=header,verify=False) 34 | else: 35 | print("Unknown command!") 36 | return 37 | if(not r): 38 | print("No data returned!") 39 | else: 40 | response_json=r.json() 41 | r1=(response_json["response"]) 42 | r2=(r1[0]) 43 | print("Host IP = "+r2["hostIp"]) 44 | 45 | def main(): 46 | ticket=getServiceTicket() 47 | if(ticket): 48 | doRestCall(ticket,GET,"https://"+CONTROLLER_IP+"/api/v1/host") 49 | else: 50 | print("no service ticket was received. Ending program!") 51 | 52 | main() 53 | 54 | -------------------------------------------------------------------------------- /Module 4 Python File/DEMO-TENANT.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | ''' 3 | Autogenerated code using arya.py 4 | Original Object Document Input: 5 | { 6 | "imdata": [ 7 | { 8 | "fvTenant": { 9 | "attributes": { 10 | "descr": "", 11 | "dn": "uni/tn-DEMO", 12 | "name": "DEMO", 13 | "nameAlias": "", 14 | "ownerKey": "", 15 | "ownerTag": "" 16 | }, 17 | "children": [ 18 | { 19 | "vnsSvcCont": { 20 | "attributes": {} 21 | } 22 | }, 23 | { 24 | "fvRsTenantMonPol": { 25 | "attributes": { 26 | "tnMonEPGPolName": "" 27 | } 28 | } 29 | } 30 | ] 31 | } 32 | } 33 | ], 34 | "totalCount": "1" 35 | } 36 | 37 | ''' 38 | 39 | # list of packages that should be imported for this code to work 40 | import cobra.mit.access 41 | import cobra.mit.request 42 | import cobra.mit.session 43 | import cobra.model.fv 44 | import cobra.model.pol 45 | import cobra.model.vns 46 | from cobra.internal.codec.xmlcodec import toXMLStr 47 | 48 | # log into an APIC and create a directory object 49 | ls = cobra.mit.session.LoginSession('https://10.10.20.70', 'admin', 'ciscopsdt') 50 | md = cobra.mit.access.MoDirectory(ls) 51 | md.login() 52 | 53 | # the top level object on which operations will be made 54 | polUni = cobra.model.pol.Uni('') 55 | 56 | # build the request using cobra syntax 57 | fvTenant = cobra.model.fv.Tenant(polUni, ownerKey=u'', name=u'DEMO', descr=u'', nameAlias=u'', ownerTag=u'') 58 | vnsSvcCont = cobra.model.vns.SvcCont(fvTenant) 59 | fvRsTenantMonPol = cobra.model.fv.RsTenantMonPol(fvTenant, tnMonEPGPolName=u'') 60 | 61 | 62 | # commit the generated code to APIC 63 | print toXMLStr(polUni) 64 | c = cobra.mit.request.ConfigRequest() 65 | c.addMo(fvTenant) 66 | md.commit(c) 67 | 68 | -------------------------------------------------------------------------------- /Module 5 Python Files/get_hostname.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # import the ncclient library 4 | from ncclient import manager 5 | import sys 6 | import xml.dom.minidom 7 | 8 | 9 | # the variables below assume the user is leveraging the 10 | # DEVNET Sandbox CSR1000v Lab 11 | # 12 | # use the IP address or hostname of your CSR1000V device 13 | HOST = 'ios-xe-mgmt.cisco.com' 14 | # use the NETCONF port for your IOS-XE device 15 | PORT = 10000 16 | # use the user credentials for your IOS-XE device 17 | USER = 'root' 18 | PASS = 'D_Vay!_10&' 19 | 20 | 21 | # create a main() method 22 | def main(): 23 | """ 24 | Main method that retrieves the hostname from config via NETCONF. 25 | """ 26 | with manager.connect(host=HOST, port=PORT, username=USER, 27 | password=PASS, hostkey_verify=False, 28 | device_params={'name': 'default'}, 29 | allow_agent=False, look_for_keys=False) as m: 30 | 31 | # XML filter to issue with the get operation 32 | # IOS-XE pre-16.2 YANG model called urn:ios 33 | # IOS-XE 16.2 - 16.4 YANG model called http://cisco.com/ns/yang/ned/ios 34 | # IOS-XE 16.5+ YANG model called http://cisco.com/ns/yang/Cisco-IOS-XE-native 35 | hostname_filter = ''' 36 | 37 | 38 | 39 | 40 | 41 | ''' 42 | result = m.get_config('running', hostname_filter) 43 | xml_doc = xml.dom.minidom.parseString(result.xml) 44 | hostname = xml_doc.getElementsByTagName("hostname") 45 | print(hostname[0].firstChild.nodeValue) 46 | 47 | 48 | if __name__ == '__main__': 49 | sys.exit(main()) 50 | -------------------------------------------------------------------------------- /Module 1 Python File/Hello World.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | requests.packages.urllib3.disable_warnings() # Disable warnings 4 | 5 | 6 | CONTROLLER_IP="devnetapi.cisco.com/sandbox/apic_em" 7 | GET="get" 8 | POST="post" 9 | 10 | 11 | def getServiceTicket(): 12 | ticket=None 13 | #specify the username and password which will be included in the data. Replace ‘xxxx’ with 14 | #your username and password 15 | payload = {"username":"devnetuser","password":"Cisco123!"} 16 | 17 | #This is the URL to get the service ticket. 18 | #The base IP call is https://[Controller IP]/api/v1 19 | #The REST function is ‘ticket’ 20 | url = "https://" + CONTROLLER_IP + "/api/v1/ticket" 21 | 22 | #Content type must be included in the header 23 | header = {"content-type": "application/json"} 24 | 25 | #Format the payload to JSON and add to the data. Include the header in the call. 26 | #SSL certification is turned off, but should be active in production environments 27 | response= requests.post(url,data=json.dumps(payload), headers=header, verify=False) 28 | 29 | #Check if a response was received. If not, print an error message. 30 | if(not response): 31 | print ("No data returned!") 32 | else: 33 | #Data received. Get the ticket and print to screen. 34 | r_json=response.json() 35 | ticket = r_json["response"]["serviceTicket"] 36 | print ("ticket: ", ticket) 37 | return ticket 38 | 39 | #Make the REST call using the service ticket, command, http url, data for the body (if any) 40 | def doRestCall(aTicket,command,url,aData=None): 41 | response_json=None 42 | payload=None 43 | try: 44 | 45 | #if data for the body is passed in put into JSON format for the payload 46 | if(aData != None): 47 | payload=json.dumps(aData) 48 | 49 | #add the service ticket and content type to the header 50 | header = {"X-Auth-Token": aTicket, "content-type" : "application/json"} 51 | if(command==GET): 52 | r = requests.get(url, data=payload, headers=header, verify=False) 53 | elif(command==POST): 54 | r = requests.post(url, data=payload, headers=header, verify=False) 55 | else: 56 | #if the command is not GET or POST we don’t handle it. 57 | print ("Unknown command!") 58 | return 59 | 60 | #if no data is returned print a message; otherwise print data to the screen 61 | if(not r): 62 | print("No data returned!") 63 | else: 64 | print ("Returned status code: %d" % r.status_code) 65 | 66 | #put into dictionary format 67 | response_json = r.json() 68 | print(response_json) 69 | except: 70 | err = sys.exc_info()[0] 71 | msg_det = sys.exc_info()[1] 72 | print( "Error: %s Details: %s StackTrace: %s" % 73 | (err,msg_det,traceback.format_exc())) 74 | 75 | 76 | 77 | #the main function 78 | def main(): 79 | #Call the function to get the service ticket 80 | ticket=getServiceTicket() 81 | 82 | #If ticket received get the users 83 | if(ticket): 84 | #Get user types in the system 85 | doRestCall(ticket,GET, "https://" + CONTROLLER_IP + "/api/v1/user") 86 | 87 | #Create a new application 88 | doRestCall(ticket, POST, "https://" + CONTROLLER_IP + "/api/v1/topology/application",[{"id":"1","description":"cool app","name":"appABC"}]) 89 | else: 90 | print("No service ticket was received. Ending program!") 91 | 92 | #Calls the main function to start the application 93 | main() 94 | --------------------------------------------------------------------------------