{"id":874,"date":"2019-01-21T00:50:10","date_gmt":"2019-01-20T22:50:10","guid":{"rendered":"http:\/\/www.mythryll.com\/?p=874"},"modified":"2019-07-07T19:44:40","modified_gmt":"2019-07-07T17:44:40","slug":"python-script-to-change-inactive-switch-ports-to-a-dummy-vlan","status":"publish","type":"post","link":"https:\/\/www.mythryll.com\/?p=874","title":{"rendered":"Python Script to change inactive cisco switch ports to a dummy vlan"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">I am working on this script for a repetitive task we do at work. We often do a scan for inactive ports in building switches and if they are inactive for a long time, we set them to a dummy vlan that offers no ip connectivity to anyone connecting to it and turning on the snmp traps for that port for changes in up\/down status. Then if a user wants to connect to the network through a new workstation, that would probably get connected to such an &#8220;inactive port&#8221; and we would be called to &#8220;turn on&#8221; that port by switching it back from the dummy vlan to a regular one. In this case we would either run the <a href=\"http:\/\/www.mythryll.com\/?p=861\">script <\/a>(<a href=\"http:\/\/www.mythryll.com\/?p=861\">http:\/\/www.mythryll.com\/?p=861<\/a>) I put up a few days ago to find his mac address or search for traps and logs in the switches and find the port that was connected.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The script reads a file that contains a list of the switches, one switch per line, with the following info: ip address, platform, list of interfaces, all separated by commas (CSV). You have to build that to process those switches.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Regular expressions are used to identify the vlanid and construct the list of interfaces per switch that need to be modified. We also test for the existence of the &#8220;snmp trap link-status command&#8221; (if it&#8217;s not active, the negation of the command is present: &#8220;no snmp trap link-status) and run that as well if necessary.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">There are three lists in the code. Each line is first split into a list as a result of applying .split(&#8216;,&#8217;) to the string. After that there is the interface list (interlist) that is used to store all interfaces to be examined. Then a configlist gets created to store all interfaces that need to be modified. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The commands that check the config mode and print vlanid and other info are for control and can be ommited if you prefer.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I have to admit that the script takes a lot of time. I am guessing it&#8217;s the time needed to run each switch command, either for pattern recognition for the switch prompt or to allow the time to pass if we are sending timed commands with send_command_timing for 2950s.  I guess there must be a more efficient way but I don&#8217;t know what it is yet. I definitely know it would run faster in pearl or tcl (did similar things before with those, see post  <br \/><a href=\"http:\/\/www.mythryll.com\/?p=861\">http:\/\/www.mythryll.com\/?p=861<\/a> .<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So here it is, the dummy vlan id is supposed to be 599 :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from netmiko import ConnectHandler, ssh_exception\nfrom paramiko.ssh_exception import SSHException\nfrom getpass import getpass\nfrom datetime import datetime\nimport os\nimport subprocess\nimport re\nimport sys\n\nuser = input('username:')\npasswd = getpass()#count the time\n\nprint('Starting:', datetime.now().time())\ntotalcounter = 0\n\n#open the switch list file\nwith open(\"switchlist.txt\") as switchfile:\n    #each line represents one switch with ipaddress,platform,int1,int2,int3,.. format\n    for nextline in switchfile:\n        #turn the line into a list for the current switch, split at commas\n        linestring = nextline.strip().split(',')\n        switchlength = len(linestring)\n        #show how many interfaces were entered for the switch to be changed\n\n        interlist = []\n        index = 1\n        #we store first item as switchaddress, second as platform to choose commands, and third and so forth as interfaces\n        for switchitem in linestring:\n            print (switchitem)\n            if index == 1 :\n                switchaddress = switchitem.strip()\n                index +=1\n            elif index == 2:\n                switchplatform = switchitem.strip()\n                index +=1\n                print(switchlength-2)\n            else:\n                switchinterface = switchitem.strip()\n                interlist.append(switchitem)\n\n        #2950s don't support ssh\n        if \"2950\" not in switchplatform:\n            contype = \"cisco_ios_ssh\"\n        else:\n            contype = \"cisco_ios_telnet\"\n\n        #define connection\n        swcon = {\n            'device_type': contype,\n            'ip': switchaddress,\n            'username': user,\n            'password': passwd,\n        }\n\n        #if connections fails we want to exit the script with the correct message\n        try:\n            net_connect = ConnectHandler(**swcon)\n        except SSHException:\n            print (\"can't connect to last device\")\n            sys.exit(1)\n        except ssh_exception.NetMikoTimeoutException:\n            print(\"  SSH Timed out\")\n            sys.exit(1)\n        except ssh_exception.NetMikoAuthenticationException:\n            print(\"Invalid Credentials: \", switchaddress)\n            sys.exit(1)\n        #the configlist will contain only those interfaces that need to change access vlan\n        configlist = []\n        for interface in interlist:\n            #define pattern to look for vlanid\n            vlanpt = re.compile(r\"switchport access vlan\\s+(?P&lt;vlanid>\\d+)\")\n            snmppt = re.compile(r\"no snmp trap link-status\")\n            commandstring = \"show run int \" + interface + \" | in vlan\"\n            commandstring2 = \"show run int \" + interface\n            #check platform to send command\n            if switchplatform == \"2950\":\n                output = net_connect.send_command_timing(commandstring)\n                output2 = net_connect.send_command_timing(commandstring2)\n            else:\n                output = net_connect.send_command(commandstring)\n                output2 = net_connect.send_command(commandstring2)\n            #perform search for vlanid and get back match objects\n            vlansearch = vlanpt.search(output)\n            snmpsearch = snmppt.search(output2)\n            #if there are no matches we have to inform user that vlanid was not captured\n            #that would imply an incorrect filter for the platform or a connection issue\n            #if there are matches we go ahead and append those interfaces to the list\n            if vlansearch != None:\n                vlanid = vlansearch.group('vlanid')\n                if (vlanid != \"599\") or (snmpsearch != None):\n                    configlist.append(interface)\n                    print(vlanid)\n            else:\n                print(\"vlan id not recognized for interface \",interface,\"at\",switchaddress)\n\n        #proceed in config mode only if there are any interfaces to change access vlan\n        if len(configlist) > 0:\n            output = net_connect.config_mode()\n            confcheck = net_connect.check_config_mode()\n            print(\"config mode :\",confcheck)\n\n            for interface in configlist:\n                commandstring = \"interface \" + interface\n                output = net_connect.send_command_timing(commandstring)\n                output = net_connect.send_command_timing(\"switchport access vlan 599\")\n                print(output)\n                output = net_connect.send_command_timing(\"snmp trap link-status\")\n                print(output)\n\n            net_connect.exit_config_mode()\n            confcheck = net_connect.check_config_mode()\n            print(\"config mode :\",confcheck)\n            print(\"no of interfaces changed:\", len(configlist))\n\n            #save configuration\n            output = net_connect.save_config()\n            print(output)\n            totalcounter = totalcounter + int(len(configlist))\n\n        #get out\n        net_connect.disconnect()\n        print(\"done with\", switchaddress)\n\n#show time and number of changes when finished\nprint('Finished:', datetime.now().time())\nprint(\"interfaces changed:\", totalcounter)\nprint(\"\\nEnd\")\n\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Take a look, modify it if you need to and try it out. Always test before deploying.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">JT<br \/><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I am working on this script for a repetitive task we do at work. We often do a scan for inactive ports in building switches and if they are inactive for a long time, we set them to a dummy vlan that offers no ip connectivity to anyone connecting to it and turning on the&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[27,14],"tags":[31,32,28],"class_list":["post-874","post","type-post","status-publish","format-standard","hentry","category-automation","category-it","tag-automation","tag-netmiko","tag-python"],"_links":{"self":[{"href":"https:\/\/www.mythryll.com\/index.php?rest_route=\/wp\/v2\/posts\/874","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mythryll.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mythryll.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mythryll.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mythryll.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=874"}],"version-history":[{"count":4,"href":"https:\/\/www.mythryll.com\/index.php?rest_route=\/wp\/v2\/posts\/874\/revisions"}],"predecessor-version":[{"id":879,"href":"https:\/\/www.mythryll.com\/index.php?rest_route=\/wp\/v2\/posts\/874\/revisions\/879"}],"wp:attachment":[{"href":"https:\/\/www.mythryll.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=874"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mythryll.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=874"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mythryll.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=874"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}