0

I have a simple program to grab information from switch/router cisco with SSH Connection using Netmiko Library.

The program works well, but the program freeze until the process complete.

my code:

When I press 'generate' button it will call sshConnection function after sshConnection run my Apps suddenly freeze

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from netmiko import ConnectHandler
from paramiko import SSHException
import jtextfsm as textfsm
import ipaddress
import matplotlib.pyplot as plt
import numpy as np
import io
import time

class Stream(QObject):
    newText = pyqtSignal(str)

    def write(self, text):
        self.newText.emit(str(text))

    def flush(self):
        pass

class MyClass(object):
    def __init__(self, device_type=None, ip=None, username=None, password=None, secret=None, command=None):
        self.device_type = device_type
        self.ip = ip
        self.username = username
        self.password = password
        self.secret = secret
        self.command = command

class Widget(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent=parent)
        self.device_list = []  # object array
        self.setWindowTitle("Network Automation")
        self.setFixedSize(350,500)
        ############################# Input IP

        sys.stdout = Stream(newText=self.onUpdateText)

        # Device Type
        lb_device_list = QLabel(self)
        lb_device_list.setText('Device Type')
        self.cb_device_list = QComboBox(self)
        self.cb_device_list.addItem('cisco_ios')
        self.cb_device_list.addItem('cisco_s300')

        # Ip Device
        lb_ip = QLabel(self)
        lb_ip.setText('IP Address')
        self.le_ip = QLineEdit(self)
        self.le_ip.setText('')
        self.le_ip.setPlaceholderText('Input Device IP')
        self.le_ip.setFixedWidth(150)

        # username
        lb_username = QLabel(self)
        self.le_username = QLineEdit(self)
        lb_username.setText('Username')
        self.le_username.setText('')
        self.le_username.setPlaceholderText('Input Username')
        self.le_username.setFixedWidth(150)

        # password
        lb_password = QLabel(self)
        self.le_password = QLineEdit(self)
        lb_password.setText('Password')
        self.le_password.setText('')
        self.le_password.setPlaceholderText('Input Password')
        self.le_password.setFixedWidth(150)

        # Privilage Password
        lb_enable = QLabel(self)
        lb_enable.setText('Privilege Mode Password')
        self.le_enable = QLineEdit(self)
        self.le_enable.setText('')
        self.le_enable.setPlaceholderText('Input Enable Password')
        self.le_enable.setFixedWidth(150)

        # button generate and add
        btgenerate = QPushButton(self)
        btgenerate.setText('Generate')
        btgenerate.setFixedWidth(70)
        btadd = QPushButton(self)
        btadd.setText('Add')

        # button delete
        btdel = QPushButton(self)
        btdel.setFixedWidth(70)
        btdel.setText('Remove')

        # line
        line = QFrame(self)
        line.setFrameShape(QFrame.VLine)
        line.setFrameShadow(QFrame.Sunken)
        line.setLineWidth(3)

        #line 2
        line2 = QFrame(self)
        line2.setFrameShape(QFrame.HLine)
        line2.setFrameShadow(QFrame.Sunken)
        line2.setLineWidth(3)

        ########################### Layout Ip Device List

        lb3 = QLabel(self)
        lb3.setText('IP Device List')
        self.ip_device_list = QListWidget(self)
        self.ip_device_list.setFixedWidth(150)
        # self.combobox_ip_list = QComboBox(self)
        # self.combobox_ip_list.setFixedWidth(170)

        ############################## SubLayout and Layout
        hblayout = QHBoxLayout()
        hblayout.addWidget(btgenerate)
        hblayout.addWidget(btadd)

        ###############################  Processs
        processlabel = QLabel("Process",self)

        self.process = QTextEdit(self)
        self.process.setLineWrapColumnOrWidth(400)
        self.process.setLineWrapMode(QTextEdit.FixedPixelWidth)
        self.process.setReadOnly(True)


        sublayout = QVBoxLayout()
        sublayout.addWidget(lb_device_list)
        sublayout.addWidget(self.cb_device_list)
        sublayout.addWidget(lb_ip)
        sublayout.addWidget(self.le_ip)
        sublayout.addWidget(lb_username)
        sublayout.addWidget(self.le_username)
        sublayout.addWidget(lb_password)
        sublayout.addWidget(self.le_password)
        sublayout.addWidget(lb_enable)
        sublayout.addWidget(self.le_enable)
        sublayout.addLayout(hblayout)

        sublayout2 = QVBoxLayout()
        sublayout2.addWidget(lb3)
        sublayout2.addWidget(self.ip_device_list)
        #sublayout2.addWidget(self.combobox_ip_list)
        sublayout2.addWidget(btdel)
        sublayout2.addStretch(1)

        sublayout3 = QVBoxLayout()
        sublayout3.addWidget(processlabel)
        sublayout3.addWidget(self.process)

        layout = QGridLayout(self)
        layout.addLayout(sublayout, 0, 0)
        layout.addWidget(line, 0, 1)
        layout.addWidget(line2, 1, 0, 1, 3)
        #layout.addWidget(processlabel,2,0)
        layout.addLayout(sublayout3,2,0,2,3)
        layout.addLayout(sublayout2, 0, 2)

        btadd.clicked.connect(self.addDevice)
        btdel.clicked.connect(self.remove)
        btgenerate.clicked.connect(self.sshConection)

    def onUpdateText(self, text):
        cursor = self.process.textCursor()
        cursor.movePosition(QTextCursor.End)
        cursor.insertText(text)
        self.process.setTextCursor(cursor)
        self.process.ensureCursorVisible()

    def __del__(self):
        sys.stdout = sys.__stdout__

    # ----------- AddDevice Process

    def addDevice(self):
        try:
            ip = self.le_ip.text()
            ipaddress.ip_address(ip)
            device_type = str(self.cb_device_list.currentText())
            username = self.le_username.text()
            password = self.le_password.text()
            secret = self.le_enable.text()
            command = 'show tech'
            coomand2 = ''
            self.device_list.append(MyClass(device_type, ip, username, password, secret, command))

            # self.combobox_ip_list.addItem(ip)# Add Ip to ComboBox
            self.ip_device_list.addItem(ip)

            self.le_ip.clear()
            self.le_username.clear()
            self.le_password.clear()
            self.le_enable.clear()
            for list in self.device_list:
                print(list.ip, list.device_type)
        except ValueError:
            print("insert you're ip correctly")
            QMessageBox.question(self, 'Warning', "Insert You're IP Corecctly")

    def remove(self):
        index = self.ip_device_list.currentRow()
        if index != -1:
            self.ip_device_list.takeItem(index)
            del self.device_list[index]

    # ------------- TEXTFSM Process
    def TextFSM(self, nameFile, nameFile2):
        try:
            input_file = open(nameFile + '.txt', encoding='utf-8')  # show version
            raw_text_data = input_file.read()
            input_file.close()

            input_file2 = open(nameFile + '.txt', encoding='utf-8')  # show env
            raw_text_data2 = input_file2.read()
            input_file2.close()

            input_file3 = open(nameFile + '.txt', encoding='utf-8')  # show flash
            raw_text_data3 = input_file3.read()
            input_file3.close()

            input_file4 = open(nameFile + '.txt', encoding='utf-8')  # show memory statistic
            raw_text_data4 = input_file4.read()
            input_file4.close()

            input_file5 = open(nameFile + '.txt', encoding='utf-8')  # show process cpu
            raw_text_data5 = input_file5.read()
            input_file5.close()

            template = open("show-version.textfsm")  # show version
            re_table = textfsm.TextFSM(template)
            fsm_results = re_table.ParseText(raw_text_data)

            template2 = open("show-env.textfsm")  # show env
            re_table2 = textfsm.TextFSM(template2)
            fsm_results2 = re_table2.ParseText(raw_text_data2)

            template3 = open("show-flash.textfsm")  # show flash
            re_table3 = textfsm.TextFSM(template3)
            fsm_results3 = re_table3.ParseText(raw_text_data3)

            template4 = open("show-memory-statistic.textfsm")  # show memory statistic
            re_table4 = textfsm.TextFSM(template4)
            fsm_results4 = re_table4.ParseText(raw_text_data4)

            template5 = open("show-process-cpu.textfsm")  # show process cpu
            re_table5 = textfsm.TextFSM(template5)
            fsm_results5 = re_table5.ParseText(raw_text_data5)

            outfile_name = open(nameFile2 + "-show-version.csv", "w+")  # show version
            outfile = outfile_name

            outfile_name2 = open(nameFile2 + "-show-env.csv", "w+")  # show env
            outfile2 = outfile_name2

            outfile_name3 = open(nameFile2 + "-show-flash.csv", "w+")  # show flash
            outfile3 = outfile_name3

            outfile_name4 = open(nameFile2 + "-show-memory-statistic.csv", "w+")  # show memory statistic
            outfile4 = outfile_name4

            outfile_name5 = open(nameFile2 + "-show-process-cpu.csv", "w+")  # show process cpu
            outfile5 = outfile_name5

            print(re_table.header)  # show version
            for s in re_table.header:
                outfile.write("%s;" % s)
            outfile.write("\n")

            counter = 0
            for row in fsm_results:  # show version
                print(row)
                for s in row:
                    outfile.write("%s;" % s)
                outfile.write("\n")
                counter += 1
            print("Write %d records" % counter)

            print(re_table2.header)  # show env
            for s in re_table2.header:
                outfile2.write("%s;" % s)
            outfile2.write("\n")

            counter = 0
            for row in fsm_results2:  # show env
                print(row)
                for s in row:
                    outfile2.write("%s;" % s)
                outfile2.write("\n")
                counter += 1
            print("Write %d records" % counter)

            print(re_table3.header)  # show flash
            for s in re_table3.header:
                outfile3.write("%s;" % s)
            outfile3.write("\n")

            counter = 0
            for row in fsm_results3:  # show flash
                print(row)
                for s in row:
                    outfile3.write("%s;" % s)
                outfile3.write("\n")
                counter += 1
            print("Write %d records" % counter)

            print(re_table4.header)  # show memory statistics
            for s in re_table4.header:
                outfile4.write("%s;" % s)
            outfile4.write("\n")

            counter = 0
            for row in fsm_results4:  # show memory statistics
                print(row)
                for s in row:
                    outfile4.write("%s;" % s)
                outfile4.write("\n")
                counter += 1
            print("Write %d records" % counter)

            print(re_table5.header)  # show process cpu
            for s in re_table5.header:
                outfile5.write("%s;" % s)
            outfile5.write("\n")

            counter = 0
            for row in fsm_results5:  # show process cpu
                print(row)
                for s in row:
                    outfile5.write("%s;" % s)
                outfile5.write("\n")
                counter += 1
            print("Write %d records" % counter)
        except IOError:
            print("Error: There Have File does not appear to exist.")
            QMessageBox.question(self, 'Warning', "ERROR:Please check you're '.txt' file and TextFSM File.")

    # ------------- Convert Data to Graphic
    def Graph(self, fileName2):
        fig = plt.figure(figsize=(8.8, 5.5), dpi=150)  # ukuran frame gambar (L X P)
        plt.rcParams['text.color'] = 'k'  # warna tulisan
        plt.rcParams.update({'font.size': 6})  # font size
        plt.subplots_adjust(hspace=.4, right=.8, bottom=.2)  # jarak antar gambar (margin)

        # 1 - show flash
        plt.subplot(2, 2, 1)
        try:
            data = np.loadtxt(fileName2 + '-show-flash.csv', dtype=bytes, delimiter=';', usecols=(0, 1))\
                .astype(str, io.StringIO())

            slices = data[1]
            labels = data[0]
            colors = ['lightskyblue', 'lightcoral']
            explode = [0.08, 0.01]
            pie = plt.pie(slices, labels=labels, colors=colors, explode=explode, startangle=90, shadow=True,
                          autopct='%1.1f%%')

            plt.title('Flash Memory\n(Bytes)')
            plt.legend(pie[0], [" ".join(a) for a in zip(labels, slices)], loc='upper right')
            plt.axis('equal')
        except IOError:
            print("Error: There Have File does not appear to exist.")
            QMessageBox.question(self, 'Warning', "Error: There Have File does not appear to exist")

        # 2 - show memory statistic
        plt.subplot(2, 2, 2)
        try:
            data = np.loadtxt(fileName2 + '-show-memory-statistic.csv', dtype=bytes, delimiter=';',
                              usecols=(3, 4)).astype(str, io.StringIO())
            slices = data[1]
            labels = data[0]
            colors = ['lightskyblue', 'lightcoral']
            explode = [0.08, 0.01]
            pie = plt.pie(slices, labels=labels, colors=colors, explode=explode, startangle=90, shadow=True,
                          autopct='%1.1f%%')

            plt.title('Memory Statistic\n(Bytes)')
            plt.legend(pie[0], [" ".join(a) for a in zip(labels, slices)], loc='upper right')
            plt.axis('equal')
        except IOError:
            print("Error: There Have File does not appear to exist.")
            QMessageBox.question(self, 'Warning', "Error: There Have File does not appear to exist")

        # 3 - show cpu utilization

        plt.subplot(2, 2, 3)

        def autolabel(rects):
            for rect in rects:
                height = rect.get_height()
                plt.text(rect.get_x() + rect.get_width() / 2, height - 2, '%1.1f%%' % int(height), ha='center',
                         va='bottom')
        N = 3
        try:
            data = np.loadtxt(fileName2 + '-show-process-cpu.csv', dtype=bytes, delimiter=';',
                              usecols=(0, 1, 2)).astype(str)

            my_xticks = data[0]
            utilization = data[1]
            utilization_int = [int(x) for x in utilization]

            ind = np.arange(N)
            width = 0.5

            rects1 = plt.bar(ind, utilization_int, width, color='lightblue', )

            plt.title("CPU Utilization\n ('%') ")
            plt.xticks(ind, my_xticks)
            plt.xlabel("CPU Utilization")
            plt.ylabel("Percent(%)")

            autolabel(rects1)
        except IOError:
            print("Error: There Have File does not appear to exist.")
            QMessageBox.question(self, 'Warning', "Error: There Have File does not appear to exist")

        # 4 - CPU Environtment
        plt.subplot(2, 2, 4)

        def autolabel(rects):
            for rect in rects:
                height = rect.get_height()
                plt.text(rect.get_x() + rect.get_width() / 2, height - 5, '%d C' % int(height), ha='center',
                         va='bottom')

        N = 3
        try:
            data = np.loadtxt(fileName2 + '-show-env.csv', dtype=bytes, delimiter=';', usecols=2).astype(str)
            value = data[1]
            if value == '':
                try:
                    fan = np.loadtxt(fileName2 + '-show-env.csv', dtype=bytes, delimiter=';', usecols=0).astype(str)
                    system_temp = np.loadtxt(fileName2 + '-show-env.csv', dtype=bytes, delimiter=';', usecols=1).astype(
                        str)
                    power = np.loadtxt(fileName2 + '-show-env.csv', dtype=bytes, delimiter=';', usecols=6).astype(str)
                    rps = np.loadtxt(fileName2 + '-show-env.csv', dtype=bytes, delimiter=';', usecols=7).astype(str)

                    uptime = np.loadtxt(fileName2 + '-show-version.csv', dtype=bytes, delimiter=';', usecols=3).astype(
                        str)
                    pid = np.loadtxt(fileName2 + '-show-version.csv', dtype=bytes, delimiter=';', usecols=5).astype(str)
                    sn = np.loadtxt(fileName2 + '-show-version.csv', dtype=bytes, delimiter=';', usecols=6).astype(str)

                    uptime_title = uptime[0]
                    uptime_value = uptime[1]

                    pid_title = pid[0]
                    pid_value = pid[1]

                    sn_title = sn[0]
                    sn_value = sn[1]

                    fan_title = fan[0]
                    fan_status = fan[1]

                    system_temp_title = system_temp[0]
                    system_temp_value = system_temp[1]

                    power_tile = power[0]
                    power_value = power[1]

                    rps_tile = rps[0]
                    rps_value = rps[1]

                    text = fan_title + ' : ' + fan_status + '\n' + system_temp_title + ' : ' + system_temp_value + '\n' \
                           + power_tile + ' : ' + power_value + '\n' + rps_tile + ' : ' + rps_value + ' PRESENT' + '\n\n' \
                           + uptime_title + ' : ' + uptime_value + '\n' + pid_title + ' : ' + pid_value + '\n' + sn_title\
                           + ' : ' + sn_value

                    plt.title("Cpu Environment\n ('Celcius') ")
                    plt.xlabel('CPU Environment')
                    plt.ylabel('Celcius')

                    plt.text(.15, 1 / 3, text, style='oblique', bbox={'facecolor': 'white', 'alpha': 0.5, 'pad': 5})

                    # plt.show('')
                    plt.savefig(fileName2 + '.png', bbox_inches='tight')
                except (IOError):
                    print("Error: There Have File does not appear to exist.")
                    QMessageBox.question(self, 'Warning', "Error: There Have File does not appear to exist")
                    plt.savefig(fileName2 + '.png', bbox_inches='tight')
            else:

                try:

                    data = np.loadtxt(fileName2 + '-show-env.csv', dtype=bytes, delimiter=';',
                                      usecols=(2, 4, 5)).astype(str)
                    fan = np.loadtxt(fileName2 + '-show-env.csv', dtype=bytes, delimiter=';', usecols=0).astype(str)
                    system_temp = np.loadtxt(fileName2 + '-show-env.csv', dtype=bytes, delimiter=';', usecols=1).astype(
                        str)
                    system_temp_state = np.loadtxt(fileName2 + '-show-env.csv', dtype=bytes, delimiter=';',
                                                   usecols=3).astype(str)

                    uptime = np.loadtxt(fileName2 + '-show-version.csv', dtype=bytes, delimiter=';', usecols=3).astype(
                        str)
                    pid = np.loadtxt(fileName2 + '-show-version.csv', dtype=bytes, delimiter=';', usecols=5).astype(str)
                    sn = np.loadtxt(fileName2 + '-show-version.csv', dtype=bytes, delimiter=';', usecols=6).astype(str)

                    y_height = np.loadtxt(fileName2 + '-show-env.csv', dtype=bytes, skiprows=1, delimiter=';',
                                          usecols=5).astype(int)

                    uptime_title = uptime[0]
                    uptime_value = uptime[1]

                    pid_title = pid[0]
                    pid_value = pid[1]

                    sn_title = sn[0]
                    sn_value = sn[1]

                    fan_title = fan[0]
                    fan_status = fan[1]

                    system_temp_title = system_temp[0]
                    system_temp_value = system_temp[1]

                    system_temp_state_title = system_temp_state[0]
                    system_temp_state_status = system_temp_state[1]

                    my_xticks = data[0]
                    utilization = data[1]
                    utilization_int = [int(x) for x in utilization]

                    ind = np.arange(N)
                    width = 0.5

                    text = fan_title + ': ' + fan_status + '\n' + system_temp_title + ': ' + system_temp_value + \
                           '\n' + system_temp_state_title + ': ' + system_temp_state_status

                    text2 = pid_title + ' : ' + pid_value + '\n' + sn_title + ' : ' + sn_value +\
                            '\n\n' + uptime_title + ' : ' + uptime_value

                    rects1 = plt.bar(ind, utilization_int, width, color='r')

                    plt.title("CPU Environment\n ('Celcius') ")
                    plt.xticks(ind, my_xticks)
                    plt.xlabel('CPU Environment')
                    plt.ylabel('Celcius')
                    plt.text(2.4, y_height / 2, text)
                    plt.text(-1.59, -y_height / 1.77, text2, style='oblique',
                             bbox={'facecolor': 'red', 'alpha': 0.5, 'pad': 5})
                    autolabel(rects1)

                    # plt.show()
                    plt.savefig(fileName2 + '.png', bbox_inches='tight')

                except (IOError, ValueError):
                    print("Error: There Have File does not appear to exist.")
                    QMessageBox.question(self, 'Warning', "Error: There Have File does not appear to exist")
                    plt.savefig(fileName2 + '.png', bbox_inches='tight')

        except (IOError):
            print("Error: There Have File does not appear to exist.")
            QMessageBox.question(self, 'Warning', "Error: There Have File does not appear to exist")
            plt.savefig(fileName2 + '.png', bbox_inches='tight')

    # ------------- SSH Connection
    def sshConection(self):
        for list in self.device_list:
            # time.sleep(0.2)
            # Cisco IOS

            if list.device_type == 'cisco_ios':
                try:
                    print("SSH Connection Establishing---111")
                    net_connect = ConnectHandler(device_type=list.device_type, ip=list.ip, username=list.username,
                                                 password=list.password, secret=list.secret)
                    net_connect.enable()
                    print("SSH Connection Established---222")
                    output = net_connect.find_prompt()
                    hostname = output[:-1]
                    result = net_connect.send_command_expect(list.command, delay_factor=50)
                    try:
                        file = open(hostname + "-" + list.command + ".txt", "w", encoding="utf-8")
                        file.write(result)
                        print("Write File Sucess")
                        nameFile = hostname + "-" + list.command
                        nameFile2 = hostname
                        self.TextFSM(nameFile, nameFile2)
                        self.Graph(nameFile2)
                    except EOFError:
                        print("Faild Write Text File")
                        QMessageBox.question(self, 'Warning', "Faild Write Text File")
                    net_connect.disconnect()

                except (EOFError, SSHException):
                    print("\nError: Connection Faild.")
                    QMessageBox.question(self, 'Warning', "Error: Connection Faild.")

            # CISCO_S300 (SF300)

            elif list.device_type == 'cisco_s300':
                try:
                    net_connect = ConnectHandler(device_type=list.device_type, ip=list.ip, username=list.username,
                                                 password=list.password)
                    output = net_connect.find_prompt()
                    hostname = output[:-1]
                    result = net_connect.send_command(list.command, delay_factor=50)
                    file = open(hostname + "-" + list.command + ".txt", "w", encoding="utf-8")
                    file.write(result)
                    nameFile = hostname + "-" + list.command
                    nameFile2 = hostname
                    self.TextFSM(nameFile, nameFile2)
                    self.Graph(nameFile2)
                    net_connect.disconnect()
                except (EOFError, SSHException):
                    print("\nError: Connection Faild.")

##################################
app = QApplication(sys.argv)
QApplication.processEvents()
app.setStyle('cleanlooks')
window = Widget()
window.show()
sys.exit(app.exec_())
wp78de
  • 18,207
  • 7
  • 43
  • 71
Nedy Suprianto
  • 201
  • 1
  • 6
  • 14
  • You should post the relevant code in the question – Dylan Meeus Jun 09 '17 at 08:57
  • i updated the post, can you see my code again? – Nedy Suprianto Jun 09 '17 at 09:03
  • Put actual code in the post. – codeepic Jun 09 '17 at 09:20
  • i cant post my code, i got this message 'it looks like your post is mostly code; please add some more details'... how can i fix it? – Nedy Suprianto Jun 09 '17 at 09:28
  • when this happens usually is that the thread doing the background working is the same as the one of the GUI and the GUI is blocked. You should try to do a [minimal example](https://stackoverflow.com/help/mcve) so people can figure out easily what is wrong. – api55 Jun 12 '17 at 09:41
  • hhmm.. should i make a new class for run the process function? do you have a idea what should i do to fix this problem ? @api55 – Nedy Suprianto Jun 13 '17 at 03:11
  • I am no expert in pyQt but normally you have to create another thread that does the process in the background and use signals/slots of Qt to get the GUI updated (like a progress bar) or something similar. You may take a look to [this post](https://stackoverflow.com/questions/6783194/background-thread-with-qthread-in-pyqt) and maybe get the idea of how to proceed. – api55 Jun 13 '17 at 09:31
  • yeahh.. i think i should create another thread for the process. Thanks @api55 – Nedy Suprianto Jun 14 '17 at 02:54

0 Answers0