예제 #1
0
파일: tools.py 프로젝트: tmanfree/DNMT
class Tools:
    def __init__(self, cmdargs, config):
        # initialize values
        self.log_array = []
        self.cmdargs = cmdargs
        self.config = config
        self.subs = SubRoutines(cmdargs, config)
        #self.config.logpath = os.path.join(os.path.expanduser(self.config.logpath), "logs", "UpgradeCheck",
        #                                   datetime.date.today().strftime('%Y%m%d'))

    def TDR_Test(self,net_connect,interface):
        net_connect.enable()
        print("performing diagnostic on {}".format(interface))
        result = net_connect.send_command('test cable-diagno tdr interface {}'.format(interface))
        print("waiting for 15 seconds")
        time.sleep(15)
        test_result = net_connect.send_command('show cable-diagnostics tdr int {}'.format(interface))
        print("Results are:\n{}".format(test_result))
        #net_connect.disable() #incorrect syntax

        return



    def ap_poke(self):
        #cmdargs.interface
        #cmdargs.ipaddr


        #format interface string:
        self.cmdargs.interface = re.sub('[a-zA-Z]', '', self.cmdargs.interface)

        if self.subs.ping_check(self.cmdargs.ipaddr):
            self.subs.verbose_printer(print(
                "{} Reachable, Now performing AP Poke Operation on {}".format(self.cmdargs.ipaddr,
                                                                              self.cmdargs.interface)))
            if self.cmdargs.login:
                self.config.username = input("Input user name to login to switch:")
                self.config.password = getpass.getpass("Input password to login to switch:")
                self.config.enable_pw = getpass.getpass("Input enable password for switch:")

            try:
                net_connect = self.subs.create_connection(self.cmdargs.ipaddr)

                if net_connect:
                    swcheck_dict = {"ip": self.cmdargs.ipaddr, "interface": self.cmdargs.interface}
                    net_connect.send_command('term shell 0')
                    swcheck_dict["sh_int_status"] = net_connect.send_command(
                        'show int status | include {} .'.format(swcheck_dict["interface"]))
                    #create a variable to grab speed (assuming just a number is passed (1/0/11 for example)
                    # if re.search('[a-zA-Z]', self.cmdargs.interface):
                    #     swcheck_dict["local_int"] = self.cmdargs.interface
                    # else:
                    swcheck_dict["local_int"] = self.subs.regex_parser_var0(r'^(\S+)',swcheck_dict["sh_int_status"])

                    swcheck_dict["sh_int"] = net_connect.send_command(
                        'show int {} | include {} .'.format(swcheck_dict["local_int"], swcheck_dict["interface"]))
                    swcheck_dict["sh_mac"] = net_connect.send_command(
                        'show mac address int {}'.format(swcheck_dict["local_int"]))
                    swcheck_dict["mac_stat"] = \
                        re.findall(r'({}+)'.format(swcheck_dict["interface"]), swcheck_dict["sh_mac"], re.MULTILINE)
                    swcheck_dict["sh_cdp"] = net_connect.send_command(
                        'show cdp neigh {}'.format(swcheck_dict["local_int"]))
                    swcheck_dict["cdp_stat"] = \
                        re.findall(r'entries displayed : (\S+)', swcheck_dict["sh_cdp"], re.MULTILINE)
                    swcheck_dict["sh_power"] = net_connect.send_command(
                        'show power inline | include {} .'.format(swcheck_dict["interface"]))
                    swcheck_dict["power_stat"] = self.subs.regex_parser_var0(r'^(?:\S+\s+\S+\s+\S+\s+\S+\s+)(\S+)',
                                                                             swcheck_dict["sh_power"])
                    swcheck_dict["int_stat"] = self.subs.regex_parser_var0(r'(?:line protocol is \S+ \()(\S+)\)',
                                                                           swcheck_dict["sh_int"])
                    swcheck_dict["power_stat"] = self.subs.regex_parser_var0(r'^(?:\S+\s+\S+\s+\S+\s+\S+\s+)(\S+)', swcheck_dict["sh_power"])
                    swcheck_dict["int_stat"] = self.subs.regex_parser_var0(r'(?:line protocol is )(\S+)',swcheck_dict["sh_int"] )


                    self.subs.verbose_printer(
                        "Switch:{}\nInterface:{}\nInt Status:{}\nPower Status:{}\n# of MACs:{}".format(
                            swcheck_dict["ip"], swcheck_dict["local_int"], swcheck_dict["int_stat"],
                            swcheck_dict["power_stat"], len(swcheck_dict["mac_stat"])))

                    # Currently will only work if:
                    # -The port is down (AP may be locked up)
                    # -The port is up with an AP (catches some odd APs behaviour, used on 100M connections)
                    # -The port is up with Ieee and 0 Mac Addresses (AP is locked up)
                    if (swcheck_dict["int_stat"] == "notconnect") or (swcheck_dict["int_stat"] == "connected" and (
                            ("AIR" in swcheck_dict["power_stat"]) or (
                            "Ieee" in swcheck_dict["power_stat"] and len(swcheck_dict["mac_stat"]) == 0))):


                        # #TODO Add some logic to reload APs if not fincioning correctly
                        # if "AIR" in swcheck_dict['sh_cdp']:
                        #     response = input("Port appears to have a live AP, confirm action of toggling port on/off ('yes'):")
                        #     if not response == 'yes':
                        #         self.subs.verbose_printer('Did not proceed with change.')
                        #         sys.exit(1)

                        print("Change appears safe*") # change mac addresses to be 0,
                        if not self.cmdargs.skip:
                            if self.cmdargs.tdr: #Run a TDR test before if flag is set
                                self.TDR_Test(net_connect,swcheck_dict['local_int'])
                            response = input("Confirm action of toggling port on/off ('yes'):")
                            if not response == 'yes':
                                self.subs.verbose_printer('Did not proceed with change.')
                                sys.exit(1)



                        self.subs.snmp_reset_interface(self.cmdargs.ipaddr,
                            self.subs.snmp_get_interface_id(self.cmdargs.ipaddr,
                                                                     swcheck_dict["local_int"]))
                        # net_connect.enable()
                        # config_command = ["interface " + swcheck_dict["local_int"], "shutdown"]
                        # shutdown_output = net_connect.send_config_set(config_command)
                        # self.subs.verbose_printer('Port Shutdown, waiting 5 seconds.')
                        # time.sleep(5)
                        # config_command = ["interface " + swcheck_dict["local_int"], "no shutdown"]
                        # shutdown_output = net_connect.send_config_set(config_command)
                        # self.subs.verbose_printer('Port Enabled.')

                    else:
                        print("Change may be unsafe, exiting.")
                       # net_connect.send_command('int {}'.format(swcheck_dict["local_int"]))
                       # net_connect.send_command('shutdown')
                    net_connect.disconnect()
            # netmiko connection error handling
            except netmiko.ssh_exception.NetMikoAuthenticationException as err:
                self.subs.verbose_printer(err.args[0], "Netmiko Authentication Failure")
                sys.exit(1)
            except netmiko.ssh_exception.NetMikoTimeoutException as err:
                self.subs.verbose_printer(err.args[0], "Netmiko Timeout Failure")
                sys.exit(1)
            except ValueError as err:
                print(err.args[0])
                sys.exit(1)
            except Exception as err:  # currently a catch all to stop linux from having a conniption when reloading
                print("NETMIKO ERROR {}:{}".format(self.cmdargs.ipaddr, err.args[0]))
                sys.exit(1)
#
#

    def change_port_vlan(self):
      #TODO update to have batch file act on csv with format <IP,interface,vlan,desc> desc optional?
      # have csv in format of <KEY=VAL,KEY=VAL,KEY=VAL, need IP,interface as first two EX <A.A.A.A,Gi1/0/1,DESC=blah>
        vendor = self.subs.snmp_get_vendor_string(self.cmdargs.ipaddr)
        vlanList = self.subs.snmp_get_vlan_database(self.cmdargs.ipaddr,vendor)


        for vlan in vlanList:
            print("Vlan ID:{} Vlan Name:{}".format(vlan["ID"],vlan["Name"].decode("utf-8")))



        # Find the ID of the requested interface
        intId = self.subs.snmp_get_interface_id(self.cmdargs.ipaddr, self.cmdargs.interface)

        fullInterface = self.subs.snmp_get_full_interface(self.cmdargs.ipaddr, intId)
        intDescription = self.subs.snmp_get_interface_description(self.cmdargs.ipaddr, intId)
        currentVlan = self.subs.snmp_get_interface_vlan(self.cmdargs.ipaddr, intId,vendor)

        #TEST
        self.subs.snmp_set_interface_vlan(self.cmdargs.ipaddr, intId, 2101,int(currentVlan), vendor)


        #enter vlan id to change to
        bLoop = True  # TODO make this more efficient
        while (bLoop):
            print("Interface {} Description:{}".format(fullInterface,intDescription))
            vlanResponse = input("Current Vlan is {} Enter VLAN ID to change to:".format(currentVlan ))
            if any(d['ID'] == int(vlanResponse) for d in vlanList):
                bLoop = False
            else:
                print("Please enter an existing Vlan ID")


        response = input("Do you want to change vlan on port {} from {} to {}?\n"
                         "enter (yes) to proceed:".format(self.cmdargs.interface,currentVlan,vlanResponse))
        if not response == 'yes':
            self.subs.verbose_printer('Did not proceed with change.')
            sys.exit(1)

        #set new vlan
        self.subs.snmp_set_interface_vlan(self.cmdargs.ipaddr, intId, int(vlanResponse), int(currentVlan), vendor)

        #check what vlan is now
        newVlan = self.subs.snmp_get_interface_vlan(self.cmdargs.ipaddr, intId, vendor)

        if int(newVlan) == int(vlanResponse): #
            print("Vlan updated to Vlan {}".format(newVlan))
        else:
            print("vlan not updated, Vlan is still {}".format(newVlan))

        response = input("Do you want to change description on port {} from {}?\n"
                         "enter (yes) to proceed:".format(self.cmdargs.interface, intDescription))
        if not response == 'yes':
            self.subs.verbose_printer('No new Description.')
            sys.exit(1)
        response = input("Enter new description:")
        self.subs.snmp_set_interface_description(self.cmdargs.ipaddr,intId,response)
        newDescription = self.subs.snmp_get_interface_description(self.cmdargs.ipaddr, intId)

        if newDescription == response: #
            print("Description updated to \"{}\"".format(response))
        else:
            print("Description not updated, still \"{}\"".format(newDescription))


    def diggle(self):
        switchlisting = None
        try:
            # Grab the name server first
            soa_answer = dns.resolver.query(self.cmdargs.domain, 'SOA')
            master_answer = dns.resolver.query(soa_answer[0].mname, 'A')
            # could skip previous 2 lines by presetting Name server address
            z = dns.zone.from_xfr(dns.query.xfr(master_answer[0].address, self.cmdargs.domain))
            names = z.nodes.keys()
            matchcounter = 0

            if 'advanced' in self.cmdargs and self.cmdargs.advanced:
                switchlisting = "Hostname , IP , Vendor\n"
            else:
                switchlisting = "Hostname , IP\n"
            for n in names:
                if re.match(self.cmdargs.hoststring, str(n),flags=re.IGNORECASE): #Case insensitive for simplicity
                    matchcounter += 1
                    FQDN = str(n)+"."+self.cmdargs.domain
                    IP = socket.gethostbyname(FQDN)

                    if 'advanced' in self.cmdargs and self.cmdargs.advanced:
                        vendor = self.subs.snmp_get_vendor_string(IP)
                        switchlisting += "{} , {} , {}\n".format(FQDN, IP, vendor)
                    else:
                        switchlisting += "{} , {}\n".format(FQDN,IP)
        except socket.error as e:
            print('Failed to perform zone transfer:', e)
        except dns.exception.FormError as e:
            print('Failed to perform zone transfer:', e)
        except Exception as err:
            print(err)
        if switchlisting is not None:
            print("{}\n Job complete, {} matches found".format(switchlisting,matchcounter))
        else:
            print(" Job complete, NO matches found")

    def port_label_check(self):
        # self.read_email_from_gmail()
        try:
            #login and grab mail from
            mailconnection = imaplib.IMAP4_SSL('imap.gmail.com')
            mailconnection.login(self.config.port_label_email, self.config.port_label_pw)
            mailconnection.select('PortLabels')

            # result, data = mail.search(None, 'ALL')
            # mailconnection.store(b'1', '-FLAGS', '(\\Seen)')
            # mailconnection.uid('STORE', b'1', '+FLAGS', '\SEEN')
            result, data = mailconnection.search(None, 'UNSEEN')
            mail_ids = data[0]

            id_list = mail_ids.split()
            if len(id_list) > 0:
                for msg_index in id_list:
                    int_msg_index = int(msg_index)    # need str(i)
                    result, data = mailconnection.fetch(str(int_msg_index), '(RFC822)') #sets read
                    mailconnection.store(msg_index, '-FLAGS', '(\\Seen)')

                    for response_part in data:
                        if isinstance(response_part, tuple):
                            # from_bytes, not from_string
                            msg = email.message_from_bytes(response_part[1])
                            email_subject = msg['subject']
                            email_from = msg['from']
                            if (email_subject == '<PORTLABELS> New Port Labels'):
                                self.log_array.append("Email processing beginning\n")
                                email_body = msg.get_payload(decode=True)
                                dict_str = email_body.decode("UTF-8")
                                label_dict = ast.literal_eval(dict_str) #WILL BALK AT MULTI LINK DESCRIPTIONS
                                if (self.Apply_Port_Labels(label_dict)):
                                    self.Print_And_Log("Labels applied correctly, message index:{}".format(str(int_msg_index)))
                                    mailconnection.store(msg_index, '+FLAGS', '(\\Seen)')
                                else:
                                    self.Print_And_Log("ERROR: Labels did not apply correctly, message index:{}".format(
                                        str(int_msg_index)))
                                    mailconnection.store(msg_index, '-FLAGS', '(\\Seen)')

                            else:
                               self.Print_And_Log("ERROR: incorrect message subject, message index:{}, subject:{}".format(
                                    str(int_msg_index),email_subject))
                            if self.cmdargs.notify:
                                self.Email_Now(email_from,email_body)
        except Exception as e:
            print("Email processing failure:{}".format(e))



    def Print_And_Log(self,to_print):
        self.subs.verbose_printer(to_print)
        self.log_array[0] += (to_print + "\n")

    def Apply_Port_Labels(self,full_label_dict,):
        #TODO list previous description and new description, to show the change
        #TODO add processing for Vlans
        #TODO make a list of the ports to change and then change them all at the same time (same command_list)
        #   to send to netmiko to improve processing time, rather than jumping in and out of the config for each one

        bSuccess = True
        for switch_dict in full_label_dict['switches']:
            try:
                net_connect = self.subs.create_connection(switch_dict['IP'])
                if net_connect:
                    net_connect.enable()  # move this out of the if/else statements
                    net_connect.send_command('term shell 0')
                    for label in switch_dict['Labels']:
                        current_config = net_connect.send_command('show run {}'.format(label['port']))
                        current_descr = self.subs.regex_parser_var0("description (.*)",current_config)
                        if re.search('Invalid input detected', current_config) is not None:
                            self.Print_And_Log(
                                "\nERROR grabbing port info of {} on {}, skipping\n".format(label['port'],
                                                                                            switch_dict['IP']))
                            bSuccess = False
                        else:
                            if not self.cmdargs.batch:
                                response = input(
                                    "Current Config of {}:\n{}\n !!!!  Apply new port label of \"{}\"? (type 'yes' to continue'):".format(
                                        label['port'], current_config, label['desc']))
                                if not response == 'yes':
                                    self.Print_And_Log("\nDid not proceed with changing {} on {}, skipping\n".format(label['port'],switch_dict['IP']))
                                    bSuccess = False
                                else:
                                    bSuccess = self.Apply_Description(net_connect,label,switch_dict['IP'],current_descr,bSuccess)
                            else: #if in batch mode
                                bSuccess = self.Apply_Description(net_connect,label,switch_dict['IP'],current_descr,bSuccess)
                    result = net_connect.save_config()
                    if re.search('Invalid input detected', result) is not None:
                        self.Print_And_Log("\nError saving config on {}\n".format(switch_dict['IP']))
                        bSuccess = False
                    else:
                        self.Print_And_Log("\nSuccess saving config on {}\n".format(switch_dict['IP']))
                    net_connect.disconnect()
            except Exception as e:
                self.Print_And_Log("\nConnection/label application failure:{}\n".format(e))
                bSuccess = False
        return bSuccess

    def Apply_Description(self,net_connect,label,ipaddr,current_descr,bSuccess):
        result = net_connect.send_config_set([label['port'], label['desc']])
        if re.search('Invalid input detected', result) is not None:
            self.Print_And_Log("\nERROR updating port info of {} on {}\n".format(label['port'],
                                                                                 ipaddr))
            bSuccess = False
        else:
            self.Print_And_Log(
                "\nSuccessfully updated port info of {} on {}\n Old:{} New:{}\n".format(label['port'],
                                                                                        ipaddr,
                                                                                        current_descr, label['desc']))
        return bSuccess

    def Email_Now(self,to_email,original_text):
        try:
            self.subs.verbose_printer("##### Emailing now #####")

            temp_from = "admin@localhost"

            # Create the message
            themsg = MIMEMultipart()
            themsg["From"] = temp_from
            themsg["Subject"] = "response from Port Labelling - {}".format(datetime.date.today().strftime('%Y-%m-%d'))
            themsg["To"] = to_email



            # themsg.preamble = 'I am not using a MIME-aware mail reader.\n'
            # msg = MIMEBase('application', 'zip')
            # msg.set_payload(zf.read())
            # encoders.encode_base64(msg)
            # msg.add_header('Content-Disposition', 'attachment',
            #                filename=status_filename + '.zip')
            #
            #
            # themsg.attach(msg)

            #create the body of the email
            body = self.log_array[0] + "\n"
            body += "\n ------------------------------------\n ORIGINAL MSG BELOW\n{}".format(original_text)+"\n"


            themsg.attach(MIMEText(body, 'plain'))

            themsg = themsg.as_string()

            # send the message
            smtp = smtplib.SMTP()
            smtp.connect()
            smtp.sendmail(temp_from, to_email, themsg)
            smtp.close()

        except smtplib.SMTPException as err:
            print("Failed to send Email:{}".format(err))
        except Exception as err:
            print(err)

    def standardize_begin(self):
        if 'apply' in self.cmdargs and self.cmdargs.apply:
            print("Beginning Apply Standards Operation")
        else:
            print("Beginning Check Standards Operation")
            # File will have mandatory first row with at least these fields:  ip, type, user, pass, en, port
        file = open(self.cmdargs.ipfile, "r")
        summary_list = []

        if 'manual' in self.cmdargs and self.cmdargs.manual:
            row_titles = next(file).split(',') #grab the first row (the titles) use these to make the standardize switch call dynamic
            row_titles[len(row_titles)-1] = row_titles[len(row_titles)-1].rstrip() #remove the trailing newline

        for ip in file:
            if ('manual' in self.cmdargs and self.cmdargs.manual and len(row_titles) == 6): #{IP][Vendor][UN][PW][EN][PORT.split]
                ip_entry = ip.split(',')
                if (len(ip_entry) == len(row_titles)):
                    ip_entry[len(ip_entry)-1] = ip_entry[len(ip_entry)-1].rstrip()
                    summary_list.append(self.Standardize_Switch(ip_entry[row_titles.index("ip")], ip_entry[row_titles.index("type")],
                                            ip_entry[row_titles.index("user")], ip_entry[row_titles.index("pass")],
                                            ip_entry[row_titles.index("en")], ip_entry[row_titles.index("port")]))
            elif 'manual' in self.cmdargs and not self.cmdargs.manual:
                try:
                    vendor = self.subs.snmp_get_vendor_string(ip.rstrip())
                    if vendor =="Cisco":
                        device_type = "cisco_ios"
                    elif vendor =="HP":
                        device_type="hp_procurve"
                    else:
                        device_type="generic_termserver"
                    summary_list.append(self.Standardize_Switch(ip.rstrip(),device_type,self.config.username, self.config.password,self.config.enable_pw,22))
                except Exception as err:
                    print(err)
        file.close()
        print("\nSUMMARY:")
        for entry in summary_list:
            print(entry)

    def Standardize_Switch(self,ipaddr,vendor,username,password,enable_pw,port):
        print_summary = ""
        if self.subs.ping_check(ipaddr):
            try:
                if "hp_procurve_telnet" in vendor:
                    net_connect = self.subs.create_connection_manual(ipaddr, vendor, username, password, enable_pw,
                                                                     port, "sername", "assword")
                else:
                    net_connect = self.subs.create_connection_custom(ipaddr, vendor, username, password, enable_pw, port)
                if 'manual' in self.cmdargs and self.cmdargs.manual:
                    enable_success =self.subs.vendor_enable_manual(vendor,net_connect,username,password,enable_pw)
                else:
                    enable_success =  self.subs.vendor_enable(vendor,net_connect)
                if enable_success:
                    if "hp_procurve" in vendor: #temporary fix for
                        net_connect.send_command("term length 1000")
                    sh_run = net_connect.send_command("show run") # add a check for hp and term length 0?
                    # print(sh_run)
                    #TODO seperate the commandlist into headings like auth=
                    #   then have seperate check/apply fields for some that can have hashed values

                    # commandlist = self.gather_standard_commands(vendor,"tacacsshow")
                    foundnum,missingnum,appliednum,errornum = self.gather_standard_commands(ipaddr,vendor,sh_run,net_connect)

                    self.subs.verbose_printer("{} - {} CMDs exist {} CMDs missing {} CMDs applied {} CMDs Errors".format(ipaddr,foundnum,missingnum,appliednum,errornum))
                    return "{} - {} CMDs exist {} CMDs missing {} CMDs applied {} CMDs Errors".format(ipaddr,foundnum,missingnum,appliednum,errornum)
                else:
                    self.subs.verbose_printer("###{}### ERROR Unable to enable".format(ipaddr))
                    return "{} - Unable to Enable".format(ipaddr)
                net_connect.disconnect()
            except netmiko.ssh_exception.NetMikoAuthenticationException as err:
                self.subs.verbose_printer(err.args[0], "###{}### ERROR Netmiko Authentication Failure ".format(ipaddr))
                return "{} - {}".format(ipaddr,err.args[0])
            except netmiko.ssh_exception.NetMikoTimeoutException as err:
                self.subs.verbose_printer(err.args[0], "###{}### ERROR Netmiko Timeout Failure".format(ipaddr))
                return "{} - {}".format(ipaddr,err.args[0])
            except netmiko.ssh_exception.SSHException as err:
                if (err.args[0] == "Incompatible version (1.5 instead of 2.0)"):
                    self.subs.verbose_printer(err.args[0], "###{}### ERROR Netmiko incompatible version".format(ipaddr))
                    result2 = self.Standardize_Switch(ipaddr, "{}_telnet".format(vendor), username, password, enable_pw, 23)
                    return "{} - {}\n{}".format(ipaddr, err.args[0], result2)
                else:
                    self.subs.verbose_printer(err.args[0], "###{}### ERROR Netmiko SSH Exception".format(ipaddr))
                    return "{} - {}".format(ipaddr, err.args[0])
            except Exception as err:  # currently a catch all to stop linux from having a conniption when reloading
                self.subs.verbose_printer("###{}### ERROR NETMIKO:{}".format(ipaddr, err.args[0]))
                return "{} - {}".format(ipaddr, err.args[0])

        else:
            self.subs.verbose_printer("####{}### ERROR Unable to ping ".format(ipaddr))
            return "{} - No Ping Response".format(ipaddr)


    def gather_standard_commands(self,ipaddr,vendor,sh_run, net_connect):
        config = configparser.ConfigParser()

        #Check wehere to grab the config for
        if 'cmdfile' in self.cmdargs and self.cmdargs.cmdfile is not None:
            config.read(self.cmdargs.cmdfile)
        else:
            config.read(os.path.abspath(os.path.join(os.sep, 'usr', 'lib', 'capt', 'standard.conf')))

        #set the heading to grab from the custom file
        if vendor in ["Cisco", "cisco_ios", "cisco_ios_telnet"]:
            Vendor_Heading = "CISCO"
        elif vendor in ["HP", "hp_procurve", "hp_procurve_telnet"]:
            Vendor_Heading = "HP"
        else:
            Vendor_Heading = "UNKNOWN"

        foundnum = 0
        missingnum = 0
        appliednum=0
        errornum=0

        for Heading in (MainHeading for MainHeading in config if Vendor_Heading in MainHeading ):
            if "BASE" in Heading or "SHOW" in Heading:
                for Category in config[Heading]:
                    command_list = config[Heading][Category].splitlines()
                    if len(command_list) > 1: #for multiline commands
                        try:
                            for command in command_list:
                                if self.check_config_for_command(command, sh_run):
                                    self.subs.verbose_printer("###{}### FOUND: {} ".format(ipaddr, command))
                                    foundnum += 1
                                else:
                                    print("###{}### MISSING: {} ".format(ipaddr, command))
                                    missingnum += 1
                                    if "apply" in self.cmdargs and self.cmdargs.apply:
                                        if "solo" not in Category:  # exit out and apply all if dependent commands
                                            raise ValueError
                                        result = net_connect.send_config_set(command)
                                        if self.subs.print_config_results(ipaddr,result,command):
                                            appliednum +=1
                                        else:
                                            errornum += 1
                        except ValueError:  # break out of that for loop if one of the commands are missing and you have apply set
                            if "BASE" in Heading:
                                send_command_set = config[Heading][
                                    Category].splitlines()  # if missing any of the values for the entry, apply them all
                            elif "SHOW" in Heading:
                                send_command_set = config["{} APPLY".format(Vendor_Heading)][Category].split(',')
                            result = net_connect.send_config_set(send_command_set)
                            if self.subs.print_config_results(ipaddr, result, send_command_set):
                                appliednum += 1
                            else:
                                errornum += 1

                    elif len(command_list) == 1: # for commands with a single entry
                        if self.check_config_for_command(command_list[0],sh_run):
                            self.subs.verbose_printer("###{}### FOUND: {} ".format(ipaddr, command_list[0]))
                            foundnum += 1
                        else:
                            print("###{}### MISSING: {} ".format(ipaddr, command_list[0]))
                            missingnum += 1
                            if 'apply' in self.cmdargs and self.cmdargs.apply:
                                if "BASE" in Heading:
                                    send_command_set = command_list[0]  # if missing any of the values for the entry, apply them all
                                elif "SHOW" in Heading:
                                    send_command_set =config["{} APPLY".format(Vendor_Heading)][Category].split(',')
                                result = net_connect.send_config_set(send_command_set)
                                if self.subs.print_config_results(ipaddr, result, send_command_set):
                                        appliednum += 1
                                else:
                                    errornum += 1
        if "apply" in self.cmdargs and self.cmdargs.apply:
            result = net_connect.save_config()
            self.subs.verbose_printer("{} - {}".format(ipaddr,result))
        return foundnum,missingnum,appliednum,errornum

    def check_config_for_command(self,command,sh_run):
        escapedcommand = command.translate(str.maketrans({"-": r"\-",
                                                                  "]": r"\]",
                                                                  "\\": r"\\",
                                                                  "^": r"\^",
                                                                  "$": r"\$",
                                                                  "*": r"\*",
                                                                  "+": r"\+",
                                                                  ".": r"\."}))
        if re.search('^\s*{}'.format(escapedcommand), sh_run, flags=re.IGNORECASE | re.MULTILINE):
            return True
        else:
            return False

    def hp_password_change_begin(self):
        if 'apply' in self.cmdargs and self.cmdargs.apply:
            print("Beginning Apply Standards Operation")
        else:
            print("Beginning Check Standards Operation")
            # File will have mandatory first row with at least these fields:  ip, type, user, pass, en, port
        file = open(self.cmdargs.ipfile, "r")
        summary_list = []

        if 'manual' in self.cmdargs and self.cmdargs.manual:
            row_titles = next(file).split(
                ',')  # grab the first row (the titles) use these to make the standardize switch call dynamic
            row_titles[len(row_titles) - 1] = row_titles[len(row_titles) - 1].rstrip()  # remove the trailing newline

        for ip in file:
            if ('manual' in self.cmdargs and self.cmdargs.manual and len(
                    row_titles) == 6):  # {IP][Vendor][UN][PW][EN][PORT.split]
                ip_entry = ip.split(',')
                if (len(ip_entry) == len(row_titles)):
                    ip_entry[len(ip_entry) - 1] = ip_entry[len(ip_entry) - 1].rstrip()
                    summary_list.append(
                        self.HP_Pass_Change(ip_entry[row_titles.index("ip")], ip_entry[row_titles.index("type")],
                                                ip_entry[row_titles.index("user")], ip_entry[row_titles.index("pass")],
                                                ip_entry[row_titles.index("en")], ip_entry[row_titles.index("port")]))
            elif 'manual' in self.cmdargs and not self.cmdargs.manual:
                try:
                    vendor = self.subs.snmp_get_vendor_string(ip.rstrip())
                    if vendor == "Cisco":
                        device_type = "cisco_ios"
                    elif vendor == "HP":
                        device_type = "hp_procurve"
                    else:
                        device_type = "generic_termserver"
                    summary_list.append(
                        self.HP_Pass_Change(ip.rstrip(), device_type, self.config.username, self.config.password,
                                                self.config.enable_pw, 22))
                except Exception as err:
                    print(err)
        file.close()
        print("\nSUMMARY:")
        for entry in summary_list:
            print(entry)

    def HP_Pass_Change(self,ipaddr,vendor,username,password,enable_pw,port):
        print_summary = ""
        if self.subs.ping_check(ipaddr):
            try:
                if "hp_procurve_telnet" in vendor:
                    net_connect = self.subs.create_connection_manual(ipaddr, vendor, username, password, enable_pw, port, "sername","assword")
                else:
                    net_connect = self.subs.create_connection_custom(ipaddr, vendor, username, password, enable_pw,
                                                                     port)
                if 'manual' in self.cmdargs and self.cmdargs.manual:
                    enable_success = self.subs.vendor_enable_manual(vendor, net_connect, username, password, enable_pw)
                else:
                    enable_success = self.subs.vendor_enable(vendor, net_connect)
                if enable_success:
                    if 'apply' in self.cmdargs and self.cmdargs.apply:
                        result = net_connect.send_command("conf t","#")
                        result += net_connect.send_command("pass manager user-name {}".format(self.cmdargs.username), ":")
                        result += net_connect.send_command("{}".format(self.cmdargs.password), ":")
                        result += net_connect.send_command("{}".format(self.cmdargs.password), "#")
                        result += net_connect.save_config()
                        self.subs.verbose_printer("{} - {}".format(ipaddr,result))
                        self.subs.verbose_printer("{} - Updated password".format(ipaddr))
                        return "{} - Updated password".format(ipaddr)
                    else:
                        self.subs.verbose_printer("{} - Logged in successfully, but did not change Password".format(ipaddr))
                        return "{} - Logged in successfully, but did not change Password".format(ipaddr)
                else:
                    self.subs.verbose_printer("###{}### ERROR Unable to enable".format(ipaddr))
                    return "{} - Unable to Enable".format(ipaddr)
                net_connect.disconnect()
            except netmiko.ssh_exception.NetMikoAuthenticationException as err:
                self.subs.verbose_printer(err.args[0], "###{}### ERROR Netmiko Authentication Failure ".format(ipaddr))
                return "{} - {}".format(ipaddr, err.args[0])
            except netmiko.ssh_exception.NetMikoTimeoutException as err:
                self.subs.verbose_printer(err.args[0], "###{}### ERROR Netmiko Timeout Failure".format(ipaddr))
                return "{} - {}".format(ipaddr, err.args[0])
            except netmiko.ssh_exception.SSHException as err:
                if (err.args[0] == "Incompatible version (1.5 instead of 2.0)"):
                    self.subs.verbose_printer(err.args[0], "###{}### ERROR Netmiko incompatible version".format(ipaddr))
                    result2 = self.HP_Pass_Change(ipaddr, "{}_telnet".format(vendor), username, password, enable_pw, 23) # try telnet if v1 only
                    return "{} - {}\n{} - {}".format(ipaddr, err.args[0], ipaddr,result2)
                else:
                    self.subs.verbose_printer(err.args[0], "###{}### ERROR Netmiko SSH Exception".format(ipaddr))
                    return "{} - {}".format(ipaddr, err.args[0])
            except Exception as err:  # currently a catch all to stop linux from having a conniption when reloading
                self.subs.verbose_printer("###{}### ERROR NETMIKO:{}".format(ipaddr, err.args[0]))
                return "{} - {}".format(ipaddr, err.args[0])

        else:
            self.subs.verbose_printer("####{}### ERROR Unable to ping ".format(ipaddr))
            return "{} - No Ping Response".format(ipaddr)

    def arp_table_check(self):
        cmdlist = []

        file = open(os.path.join(self.cmdargs.cmdfile), "r")
        self.subs.verbose_printer("##### file opened:{} #####".format(file))

        for cmd in file:
            cmdlist.append(cmd.rstrip())
        file.close()

        if self.subs.ping_check(self.cmdargs.ipaddr):
            try:
                net_connect = self.subs.create_connection(self.cmdargs.ipaddr) #added this
                if net_connect:
                    output = net_connect.send_command("term length 0")
                    for cmd in cmdlist:

                        # Show Interface Status
                        self.subs.custom_printer("verbose", "show ip arp {}".format(cmd))
                        output = net_connect.send_command("show ip arp {}".format(cmd))
                        # example output: 2044    0000.AAAA.BBBB    DYNAMIC     Po9
                        if 'csv' in self.cmdargs and self.cmdargs.csv:
                            outputlist = output.splitlines()
                            for line in outputlist:
                                if 'filter' in self.cmdargs and self.cmdargs.filter is not None:
                                    filterlist = self.cmdargs.filter.split(',')

                                    if not any([x in line for x in filterlist]):
                                        csv = re.sub("\s+", ",", line)
                                        print("{},{},{}".format(self.cmdargs.ipaddr, cmd, csv))
                                else:
                                    csv = re.sub("\s+", ",", line)
                                    print("{},{},{}".format(self.cmdargs.ipaddr,cmd,csv))
                        else:
                            print(output)
            except netmiko.ssh_exception.NetMikoAuthenticationException as err:
                self.subs.verbose_printer(err.args[0],"Netmiko Authentication Failure")
            except netmiko.ssh_exception.NetMikoTimeoutException as err:
                self.subs.verbose_printer(err.args[0], "Netmiko Timeout Failure")
            except ValueError as err:
                #if 'verbose' in self.cmdargs and self.cmdargs.verbose:
                print(err.args[0])


    def mac_table_check(self):
        iplist = []

        file = open(os.path.join(self.cmdargs.ipfile), "r")
        self.subs.verbose_printer("##### file opened:{} #####".format(file))
        for ip in file:
            iplist.append(ip.rstrip())
        file.close()


        for ip in iplist:
            if self.subs.ping_check(ip):
                try:
                    net_connect = self.subs.create_connection(ip)  # added this
                    if net_connect:
                        output = net_connect.send_command("term length 0")

                        # Show Interface Status
                        self.subs.custom_printer("verbose", "show mac addr")
                        output = net_connect.send_command("show mac addr")
                        if 'csv' in self.cmdargs and self.cmdargs.csv:
                            outputlist = output.splitlines()
                            for line in outputlist:
                                if 'filter' in self.cmdargs and self.cmdargs.filter is not None:
                                    filterlist = self.cmdargs.filter.split(',')

                                    if not any([x in line for x in filterlist]):
                                        csv = re.sub("\s+", ",", line.strip())
                                        print("{},{}".format(ip, csv))
                                else:
                                    csv = re.sub("\s+", ",", line.strip())
                                    print("{},{}".format(ip, csv))


                        else:
                            print(output)
                except netmiko.ssh_exception.NetMikoAuthenticationException as err:
                    self.subs.verbose_printer(err.args[0], "Netmiko Authentication Failure")
                except netmiko.ssh_exception.NetMikoTimeoutException as err:
                    self.subs.verbose_printer(err.args[0], "Netmiko Timeout Failure")
                except ValueError as err:
                    # if 'verbose' in self.cmdargs and self.cmdargs.verbose:
                    print(err.args[0])
예제 #2
0
class Test:
    def __init__(self, cmdargs, config):
        # initialize values
        self.log_array = []
        self.cmdargs = cmdargs
        self.config = config
        self.subs = SubRoutines(cmdargs, config)
        self.log_path = os.path.abspath(
            os.path.join(os.sep, 'var', 'log', 'dnmt'))
        urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning
                                 )  #Supress the ssl unverified notification

    # self.config.logpath = os.path.join(os.path.expanduser(self.config.logpath), "logs", "UpgradeCheck",
    #                                   datetime.date.today().strftime('%Y%m%d'))

    def error_check(self):
        error_dict = {"ip": self.cmdargs.ipaddr}
        intId = self.subs.snmp_get_interface_id(self.cmdargs.ipaddr,
                                                self.cmdargs.interface)
        self.subs.verbose_printer("interface ID:{}".format(intId))
        error_dict["input errors"] = self.subs.snmp_get_input_errors_by_id(
            self.cmdargs.ipaddr, intId)
        error_dict["output errors"] = self.subs.snmp_get_output_errors_by_id(
            self.cmdargs.ipaddr, intId)
        error_dict["crc errors"] = self.subs.snmp_get_crc_errors_by_id(
            self.cmdargs.ipaddr, intId)
        for entry in error_dict:
            print("{}:{}".format(entry, error_dict[entry]))

    def command_blaster_begin(self):

        #Make Command List
        commandlist = []
        file = open(self.cmdargs.commandfile, "r")
        for ip in file:
            commandlist.append(ip.rstrip())
        file.close()

        #Iterate through addresses List
        if 'single' in self.cmdargs and self.cmdargs.single:
            vendor = self.subs.snmp_get_vendor_string(
                self.cmdargs.ipaddrfile.rstrip())
            if vendor == "Cisco":
                device_type = "cisco_ios"
            elif vendor == "HP":
                device_type = "hp_procurve"
            else:
                device_type = "generic_termserver"
            self.Command_Blast(self.cmdargs.ipaddrfile.rstrip(), device_type,
                               self.config.username, self.config.password,
                               self.config.enable_pw, 22, commandlist)
            # self.Command_Blast(self.cmdargs.ipaddrfile, commandlist)
        else:
            file = open(self.cmdargs.ipaddrfile, "r")

            ##########Begin
            # summary_list = []
            if 'manual' in self.cmdargs and self.cmdargs.manual:
                row_titles = next(file).split(
                    ','
                )  # grab the first row (the titles) use these to make the standardize switch call dynamic
                row_titles[len(row_titles) - 1] = row_titles[
                    len(row_titles) -
                    1].rstrip()  # remove the trailing newline
            ############END
            for ip in file:
                #TODO replace the manual flag with a split length check to see if there are multiple fields
                if ('manual' in self.cmdargs and self.cmdargs.manual
                        and len(row_titles)
                        == 6):  # {IP][Vendor][UN][PW][EN][PORT.split]
                    ip_entry = ip.split(',')
                    if (len(ip_entry) == len(row_titles)):
                        ip_entry[len(ip_entry) - 1] = ip_entry[len(ip_entry) -
                                                               1].rstrip()
                        self.Command_Blast(ip_entry[row_titles.index("ip")],
                                           ip_entry[row_titles.index("type")],
                                           ip_entry[row_titles.index("user")],
                                           ip_entry[row_titles.index("pass")],
                                           ip_entry[row_titles.index("en")],
                                           ip_entry[row_titles.index("port")],
                                           commandlist)

                elif 'manual' in self.cmdargs and not self.cmdargs.manual:
                    try:
                        vendor = self.subs.snmp_get_vendor_string(ip.rstrip())
                        if vendor == "Cisco":
                            device_type = "cisco_ios"
                        elif vendor == "HP":
                            device_type = "hp_procurve"
                        else:
                            device_type = "generic_termserver"
                        self.Command_Blast(ip.rstrip(), device_type,
                                           self.config.username,
                                           self.config.password,
                                           self.config.enable_pw, 22,
                                           commandlist)
                    except Exception as err:
                        print(err)

                # #############
                # self.Command_Blast(ip.rstrip(), commandlist)
            file.close()

    def Command_Blast(self, ipaddr, vendor, username, password, enable_pw,
                      port, commandlist):
        # SSH Connection
        try:
            # net_connect = self.subs.create_connection(ipaddr)
            # net_connect = ConnectHandler(**cisco_sw)
            if "hp_procurve_telnet" in vendor:
                net_connect = self.subs.create_connection_manual(
                    ipaddr, vendor, username, password, enable_pw, port,
                    "sername", "assword")
            else:
                net_connect = self.subs.create_connection_custom(
                    ipaddr, vendor, username, password, enable_pw, port)

            if net_connect:
                ### ADD ERROR HANDLING FOR FAILED CONNECTION
                print("-------- CONNECTED TO {} --------".format(ipaddr))

                if 'enable' in self.cmdargs and self.cmdargs.enable:
                    if 'manual' in self.cmdargs and self.cmdargs.manual:
                        enable_success = self.subs.vendor_enable_manual(
                            vendor, net_connect, username, password, enable_pw)
                    else:
                        enable_success = self.subs.vendor_enable(
                            vendor, net_connect)
                # test = net_connect.find_prompt()

                for command in commandlist:
                    if 'timing' in self.cmdargs and self.cmdargs.timing:
                        result = net_connect.send_command_timing(command)
                    else:
                        result = net_connect.send_command(command)
                    print("COMMAND:{}\nRESPONSE:{}".format(command, result))
                if 'write' in self.cmdargs and self.cmdargs.write:
                    net_connect.save_config()
                    self.subs.custom_printer(
                        "debug", "## DBG - {} config saved ##".format(ipaddr))
                net_connect.disconnect()
                self.subs.custom_printer(
                    "debug", "## DBG - {} disconnected ##".format(ipaddr))
                print(
                    "-------- CLOSED CONNECTION TO {} --------".format(ipaddr))
            else:
                print("-------- FAILED TO CONNECTED TO {} --------".format(
                    ipaddr))
        except netmiko.ssh_exception.NetMikoAuthenticationException as err:
            self.subs.verbose_printer(err.args[0],
                                      "Netmiko Authentication Failure")
        except netmiko.ssh_exception.NetMikoTimeoutException as err:
            self.subs.verbose_printer(err.args[0], "Netmiko Timeout Failure")
        except ValueError as err:
            print(err.args[0])
        except Exception as err:  # currently a catch all to stop linux from having a conniption when reloading
            print("NETMIKO ERROR {}:{}".format(ipaddr, err.args[0]))

    def bad_phone_search_begin(self):
        iplist = []
        file = open(self.cmdargs.file, "r")
        for ip in file:
            if len(ip.rstrip()) > 0:
                iplist.append(ip.rstrip())
            else:
                self.subs.custom_printer(
                    "debug",
                    "## DBG - Creating activitycheck/processedfiles directory ##"
                )
        file.close()

        for ip in iplist:
            self.BadPhoneFinder(ip)

    def BadPhoneFinder(self, ipaddr):
        try:
            # test = self.subs.snmp_get_mac_table_bulk(self.cmdargs.ipaddr)
            # test1 = self.subs.snmp_get_switch_data_full(self.cmdargs.ipaddr)
            net_connect = self.subs.create_connection(ipaddr)
            if net_connect:
                sw_dict = {"ip": ipaddr}
                sw_dict["int_return"] = net_connect.send_command(
                    'show power inline | include Ieee')
                sw_dict["int_list"] = re.findall('(?:\s*)(\S+)(?:\s+.*)',
                                                 sw_dict["int_return"],
                                                 re.VERBOSE | re.MULTILINE)
                if len(sw_dict["int_list"]) != 0:
                    print("{} --- {} Ieee interfaces found".format(
                        sw_dict["ip"], len(sw_dict["int_list"])))
                    for interface in sw_dict["int_list"]:
                        int_status = net_connect.send_command(
                            'show int {}'.format(interface)).split("\n")[0]

                        if "notconnect" in int_status:
                            if 'skip' in self.cmdargs and not self.cmdargs.skip:
                                response = input(
                                    "{} --- {} is showing NotConnected, toggle port on/off ('yes'):"
                                    .format(sw_dict["ip"], interface))
                                if not response == 'yes':
                                    self.subs.verbose_printer(
                                        'Did not proceed with change.')
                                    sys.exit(1)
                            self.subs.snmp_reset_interface(
                                ipaddr,
                                self.subs.snmp_get_interface_id(
                                    ipaddr, interface))
                            print("{} --- {} interface restarted".format(
                                sw_dict["ip"], interface))

                        else:
                            print("{} --- {} Port is showing connected".format(
                                sw_dict["ip"], interface))
                else:
                    print("{} --- No Ieee entries found".format(sw_dict["ip"]))

            net_connect.disconnect()
            # netmiko connection error handling
        except netmiko.ssh_exception.NetMikoAuthenticationException as err:
            self.subs.verbose_printer(err.args[0],
                                      "Netmiko Authentication Failure")
        except netmiko.ssh_exception.NetMikoTimeoutException as err:
            self.subs.verbose_printer(err.args[0], "Netmiko Timeout Failure")
        except ValueError as err:
            print(err.args[0])
        except Exception as err:  #currently a catch all to stop linux from having a conniption when reloading
            print("NETMIKO ERROR {}:{}".format(ipaddr, err.args[0]))

    def batch_command_wrapper(self):
        file = open(self.cmdargs.file, "r")
        for command in file:
            self.subs.custom_printer(
                "verbose",
                "### running command:{} ### ".format(command.rstrip()))
            Return_val = subprocess.run(command, shell=True)
            self.subs.custom_printer(
                "verbose",
                "### return :{} ### ".format(command.rstrip(), Return_val))
        file.close()

    def connection_count_begin(self):
        #Iterate through addresses List
        file = open(self.cmdargs.file, "r")
        for ip in file:
            self.connectcount(ip.rstrip())
        file.close()

    def connectcount(self, ipaddr):
        try:
            # test = self.subs.snmp_get_mac_table_bulk(self.cmdargs.ipaddr)
            # test1 = self.subs.snmp_get_switch_data_full(self.cmdargs.ipaddr)
            net_connect = self.subs.create_connection(ipaddr)
            if net_connect:
                # Show Interface Status
                # output = net_connect.send_command('show mac address-table ')
                net_connect.send_command('term shell 0')
                #before_swcheck_dict = {"ip": ipaddr}
                intlist = []
                desclist = []
                vlanlist = []

                tempvar = net_connect.send_command(
                    'show int  | include thernet|Last input')
                lastvar = ""
                for line in tempvar.splitlines():
                    portnum = self.subs.regex_parser_var0(
                        r"Ethernet([0-9]/\d{1,2})", line)
                    if portnum is not None:
                        lastvar = portnum
                    elif lastvar != "":
                        innertemp = self.subs.regex_parser_varx(
                            r"Last input (\S+),\s+output (\S+),", line)
                        if innertemp is not None:
                            pass
                            intlist.append(
                                (lastvar, innertemp[0], innertemp[1]))
                            lastvar = ""
                    # if (len(lastvar) == 2): #verify that return isn't borked, should get 3 length tuple
                    #    before_swcheck_dict[lastvar] = "test"\
                tempvar = net_connect.send_command('show int desc')
                for line in tempvar.splitlines():
                    interface = self.subs.regex_parser_var0(
                        r"^\S+(\d/\d{1,2})", line)
                    if interface is not None:
                        description = self.subs.regex_parser_var0(
                            r"^\S+\d/\d{1,2}\s+(?:up|down)\s+(?:up|down)\s+(.+)",
                            line)
                        desclist.append((interface, description))
                        # if description is not "" and description is not None:
                        #     description = description.rstrip()

                tempvar = net_connect.send_command('show int status')
                for line in tempvar.splitlines():
                    interface = self.subs.regex_parser_var0(
                        r"^\S+(\d/\d{1,2})", line)
                    if interface is not None:
                        # description = self.subs.regex_parser_var0(r"^\S+\d/\d{1,2}\s+(.+)(?:connected|notconnect)", line)
                        # if description is not "" and description is not None:
                        #     description = description.rstrip()

                        vlan = self.subs.regex_parser_var0(
                            r"(?:connected|notconnect)\s+(\S+)\s+", line)
                        vlanlist.append((interface, vlan))

                net_connect.disconnect()
                # print("Interface,Last input,Last output")
                # for line in intlist:
                #     print("{},{},{}".format(line[0],line[1],line[2]))
                # for line in  desclist:
                #     print("{},{},{}".format(line[0], line[1], line[2]))

                print("descint,intint,label,vlan,lastinput,lastoutput")
                for descit, intit, vlanit in zip(desclist, intlist, vlanlist):
                    print("{},{},{},{},{},{},{},{}".format(
                        ipaddr, descit[0], intit[0], vlanit[0], vlanit[1],
                        descit[1], intit[1], intit[2]))
                    if descit[0] != intit[0] or descit[0] != vlanit[0]:
                        print(
                            "^^^^^^^^^^^^^^^^^^^^^^^ERROR MISMATCHED INTS^^^^^^^^^^^^"
                        )
        # netmiko connection error handling
        except netmiko.ssh_exception.NetMikoAuthenticationException as err:
            self.subs.verbose_printer(err.args[0],
                                      "Netmiko Authentication Failure")
        except netmiko.ssh_exception.NetMikoTimeoutException as err:
            self.subs.verbose_printer(err.args[0], "Netmiko Timeout Failure")
        except ValueError as err:
            print(err.args[0])
        except Exception as err:  # currently a catch all to stop linux from having a conniption when reloading
            print("NETMIKO ERROR {}:{}".format(ipaddr, err.args[0]))

    def dell_snmp_Begin(self):
        #Iterate through addresses List
        file = open(self.cmdargs.file, "r")
        for ip in file:
            self.DellSnmpAdd(ip.rstrip())
        file.close()

    def DellSnmpAdd(self, ipaddr):
        try:
            # test = self.subs.snmp_get_mac_table_bulk(self.cmdargs.ipaddr)
            # test1 = self.subs.snmp_get_switch_data_full(self.cmdargs.ipaddr)
            print(self.cmdargs.snmpstring)
            net_connect = self.subs.create_connection_vendor(
                ipaddr, "dell_force10_ssh")
            if net_connect:
                net_connect.enable()
                result = net_connect.send_command('show run | include snmp')
                print("#####{} SNMP before #####\n{}".format(ipaddr, result))
                config_command = ["snmp-server community ncgwWR0C ro"]
                result = net_connect.send_config_set(config_command)
                print("#####{} Progress #####\n{}".format(ipaddr, result))
                result = net_connect.send_command('show run | include snmp')
                print("#####{} SNMP after #####\n{}".format(ipaddr, result))
                output = net_connect.send_command_timing('write')
                if "y/n" in output:
                    output += net_connect.send_command_timing(
                        "y", strip_prompt=False, strip_command=False)
                    print("#####{} Save Progress #####\n{}".format(
                        ipaddr, output))

            net_connect.disconnect()
            # netmiko connection error handling
        except netmiko.ssh_exception.NetMikoAuthenticationException as err:
            self.subs.verbose_printer(err.args[0],
                                      "Netmiko Authentication Failure")
        except netmiko.ssh_exception.NetMikoTimeoutException as err:
            self.subs.verbose_printer(err.args[0], "Netmiko Timeout Failure")
        except ValueError as err:
            print(err.args[0])
        except Exception as err:  #currently a catch all to stop linux from having a conniption when reloading
            print("NETMIKO ERROR {}:{}".format(ipaddr, err.args[0]))

    def vlan_namer_begin(self):
        # Iterate through addresses List
        if 'apply' in self.cmdargs and self.cmdargs.apply:
            print("Beginning Apply Vlan Naming Operation")
        else:
            print("Beginning Check Vlan Naming Operation")
        file = open(self.cmdargs.file, "r")
        for ip in file:
            try:
                if self.subs.ping_check(ip):  #check if reachable first
                    self.Vlan_Namer(ip.rstrip())
                else:
                    print("####{}### ERROR Unable to ping ".format(
                        ip.rstrip()))
            except Exception as err:
                print(err)
        file.close()

    def Vlan_Namer(self, ipaddr):
        vendor = self.subs.snmp_get_vendor_string(ipaddr)
        hostname = self.subs.snmp_get_hostname(ipaddr)
        hostname_split = hostname.split('-')
        if len(hostname_split) > 0:
            building_code = hostname_split[0]
        else:
            raise Exception(
                "##### ERROR - unable to parse building name for {}: #####".
                format(ipaddr))

        current_vlan_list = self.subs.snmp_get_vlan_database(ipaddr, vendor)
        if len(current_vlan_list) > 0:
            try:
                new_vlan_list = self.Ipam_Rest_Get(
                    "DNS_DOMAIN_DUMMY", {
                        "WHERE":
                        "vlmdomain_description like '{}'".format(building_code)
                    })

                if new_vlan_list is None:
                    raise Exception(
                        "###{}#### ERROR No entries found for building code:{}"
                        .format(ipaddr, building_code))

                #grab new vlan name if in IPAM
                for vlanEntry in current_vlan_list:
                    vlanEntry["NewName"] = next(
                        (newvlanEntry['vlmvlan_name']
                         for newvlanEntry in new_vlan_list
                         if newvlanEntry["vlmvlan_vlan_id"] == str(
                             vlanEntry["ID"])), None)

                if 'apply' in self.cmdargs and self.cmdargs.apply:
                    if vendor == "Cisco":
                        net_connect = self.subs.create_connection_vendor(
                            ipaddr, "cisco_ios")
                        result = net_connect.enable()
                    elif vendor == "HP":
                        net_connect = self.subs.create_connection_vendor(
                            ipaddr, "hp_procurve")
                        result = self.subs.hp_connection_enable(
                            net_connect)  #TODO ADD error handling here
                    else:
                        net_connect = self.subs.create_connection(ipaddr)
                        result = net_connect.enable()

                    if net_connect:
                        ### ADD ERROR HANDLING FOR FAILED CONNECTION
                        print(
                            "-------- PROCESSING {}  --------".format(ipaddr))

                        for vlanEntry in current_vlan_list:  #This can miss the case where nvram is not
                            if vlanEntry["NewName"] is not None and vlanEntry[
                                    "NewName"] != "":
                                if (vlanEntry["NewName"] == vlanEntry["Name"]):
                                    self.subs.custom_printer(
                                        "verbose",
                                        "###{}### vlan {} is the SAME: {} ".
                                        format(ipaddr, vlanEntry["ID"],
                                               vlanEntry["Name"]))
                                else:
                                    result = net_connect.send_config_set([
                                        "vlan {}".format(vlanEntry["ID"]),
                                        "name {}".format(vlanEntry["NewName"])
                                    ])
                                    self.subs.custom_printer(
                                        "debug",
                                        "###{}### vlan {} change result:{}".
                                        format(ipaddr, vlanEntry["ID"],
                                               result))
                                    #self.subs.verbose_printer(result)
                                    #If the names are too long they won't apply, HP Procurve in ASH reporting a limit of 12 characters
                                    print(
                                        "###{}### vlan {} changed from {} to {}"
                                        .format(ipaddr, vlanEntry["ID"],
                                                vlanEntry["Name"],
                                                vlanEntry["NewName"]))
                            else:
                                self.subs.custom_printer(
                                    "verbose",
                                    "###{}### vlan {} not found in IPAM. Old Name: {}"
                                    .format(ipaddr, vlanEntry["ID"],
                                            vlanEntry["Name"]))
                        result = net_connect.save_config()
                        # self.subs.verbose_printer("###{}###   {}".format(ipaddr, result))
                        net_connect.disconnect()
                        print("-------- FINISHED PROCESSING {}  --------\n".
                              format(ipaddr))
                    else:
                        print("-------- FAILED TO CONNECTED TO {} --------\n".
                              format(ipaddr))
                else:  #just checking
                    print("-------- CHECKING VLANS ON {}  --------".format(
                        ipaddr))
                    for vlanEntry in current_vlan_list:
                        if vlanEntry["NewName"] is not None and vlanEntry[
                                "NewName"] != "":
                            if (vlanEntry["NewName"] == vlanEntry["Name"]):
                                self.subs.verbose_printer(
                                    "###{}### vlan {} is the SAME: {} ".format(
                                        ipaddr, vlanEntry["ID"],
                                        vlanEntry["Name"]))
                            else:
                                print(
                                    "###{}### vlan {} is DIFFERENT. \nOLD: {} \nNEW: {}"
                                    .format(ipaddr, vlanEntry["ID"],
                                            vlanEntry["Name"],
                                            vlanEntry["NewName"]))
                        else:
                            print(
                                "###{}### vlan {} not found in IPAM. Old Name: {}"
                                .format(ipaddr, vlanEntry["ID"],
                                        vlanEntry["Name"]))
                    print("-------- FINISHED CHECKING {}  --------\n".format(
                        ipaddr))

            except netmiko.ssh_exception.NetMikoAuthenticationException as err:
                self.subs.verbose_printer(err.args[0],
                                          "Netmiko Authentication Failure")
            except netmiko.ssh_exception.NetMikoTimeoutException as err:
                self.subs.verbose_printer(err.args[0],
                                          "Netmiko Timeout Failure")
            except ValueError as err:
                print(err.args[0])
            except Exception as err:  # currently a catch all to stop linux from having a conniption when reloading
                print("NETMIKO ERROR {}:{}".format(ipaddr, err.args[0]))

    def Core_Mapper(self, ipaddr):
        try:
            vendor = self.subs.snmp_get_vendor_string(ipaddr)
            # Get CDP information for ports
            cdp_list = self.subs.snmp_get_neighbour_bulk(ipaddr, vendor)

            connected_uplinks = [
                cdpEntry for cdpEntry, cdpEntry in enumerate(cdp_list)
                if "corenet" in cdpEntry["Value"]
            ]
            if len(connected_uplinks) > 0:
                vlan_list = self.subs.snmp_get_vlan_database(ipaddr, vendor)
                for uplinkEntry in connected_uplinks:
                    uplinkEntry["LocalPort"] = next(
                        (cdpEntry['Value'] for cdpEntry in cdp_list
                         if cdpEntry["Id"] == uplinkEntry['Id']
                         and cdpEntry["Category"] == 7), None)
                    try:
                        net_connect = self.subs.create_connection(
                            uplinkEntry['Value'])
                        if net_connect:
                            ### ADD ERROR HANDLING FOR FAILED CONNECTION
                            print("-------- CONNECTED TO {} for {} --------".
                                  format(uplinkEntry['Value'], ipaddr))
                            for vlanEntry in vlan_list:
                                result = net_connect.send_command(
                                    "show vlan id {} | include active".format(
                                        vlanEntry['ID']))
                                vlanEntry["CoreName"] = self.regex_parser_var0(
                                    r"^\d+\s+(\S+)$", result)
                            print(" ID:{} Current Name:{} Core Name:{}".format(
                                vlanEntry["ID"], vlanEntry["Name"],
                                vlanEntry["CoreName"]))

                            net_connect.disconnect()
                        else:
                            print(
                                "-------- FAILED TO CONNECTED TO {} --------".
                                format(ipaddr))
                    except netmiko.ssh_exception.NetMikoAuthenticationException as err:
                        self.subs.verbose_printer(
                            err.args[0], "Netmiko Authentication Failure")
                    except netmiko.ssh_exception.NetMikoTimeoutException as err:
                        self.subs.verbose_printer(err.args[0],
                                                  "Netmiko Timeout Failure")
                    except ValueError as err:
                        print(err.args[0])
                    except Exception as err:  # currently a catch all to stop linux from having a conniption when reloading
                        print("NETMIKO ERROR {}:{}".format(
                            ipaddr, err.args[0]))

                #login to edge switch to get the remote port of the cdp stuff

                #verify which vlans are actually passed to the edge switch
                #Log onto connected core now to get names of connected vlans

            vlan_list = self.subs.snmp_get_vlan_database(ipaddr, vendor)

        except Exception as err:
            print(err)
        pass

    def Ipam_Rest_Get(self, url, params):

        # url = "IPAM_DUMMY_URL"
        # params = {"WHERE":"vlmdomain_description like 'VPL' and vlmvlan_vlan_id = 4031"}
        # params = {"WHERE": "vlmdomain_description like '{}'".format(buildingcode)}

        try:

            response = requests.get(url,
                                    params,
                                    verify=False,
                                    auth=(self.config.ipam_un,
                                          self.config.ipam_pw))
            #Add error handling
            test = response.json()
            if len(test) > 0:
                return test
                # vlanName = next((vlanEntry['vlmvlan_name'] for vlanEntry in test if vlanEntry["vlmvlan_vlan_id"] == vlanid ), None)
                # print("ID:{} NAME:{}".format(vlanid,vlanName))
            else:
                raise Exception('##### ERROR - no return from IPAM: #####')

        except Exception as err:
            print(err)