class CLI: def __init__(self, path: str): self._serial = Serial(path) self._pexpect = SerialSpawn(self._serial) def close(self): self._pexpect.close() self._serial.close() def tx(self, cmd: str) -> str: self._pexpect.send('\r') self._pexpect.expect('cli>') self._pexpect.send(cmd.strip() + '\r') self._pexpect.expect(cmd.strip()) self._pexpect.expect('cli>') return self._pexpect.before.decode('utf-8').strip().replace( '\r\n', '\n')
def main(): with serial.Serial('/dev/ttyAMA0', 115200, timeout=0) as ser: ss = SerialSpawn(ser) # DEBUG ss.logfile = sys.stderr.buffer total_cnt = 0 success_cnt = 0 fail_cnt = 0 logfile = time.strftime("UBOOT-LOG-%Y-%m-%d.txt", time.localtime()) f = open(logfile, 'a') power_cycle() start_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) while True: # try: # a = ss.expect('SCHNEIDER2 login:'******'root') # b = ss.expect('root@SCHNEIDER2:') # ss.sendline('poweroff') # power_cycle() # except TIMEOUT: # a = ss.expect('SCHNEIDER2 login:'******'root') # b = ss.expect('root@SCHNEIDER2:') # ss.sendline('poweroff') # power_cycle() # ser_bytes = ser.readline() # print(ser_bytes) time.sleep(0.1) ss.sendline() index_login = ss.expect( pattern=['CPU : AM335X-GP rev 2.1', pexpect.TIMEOUT], timeout=TIMEOUT_LOGIN) if index_login == 1: # device get stuck print("Device get stuck in index_login.") f.write("Device get stuck in index_login.\r\n") power_cycle() continue # ser_bytes = ser.readline() # print(ser_bytes) for i in range(6): ss.send('\x03') time.sleep(0.3) ss.sendline() index_shell = ss.expect(pattern=['=>', pexpect.TIMEOUT], timeout=TIMEOUT_SHELL) if index_shell == 0: # normal ss.sendline('poweroff') elif index_shell == 1: # device get stuck print("Device get stuck in index_shell.") f.write("Device get stuck in index_shell.\r\n") power_cycle() continue '''record log''' # ret = chardet.detect(data) # print(ret) # s = str(data, encoding = "ascii") # print(type(data)) # print(type(s)) # f.write(s) total_cnt = total_cnt + 1 is_repower = False end_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) time.sleep(1) index_btldr = ss.expect(pattern=['U-Boot ', pexpect.TIMEOUT], timeout=TIMEOUT_PWROFF) if index_btldr == 0: fail_cnt = fail_cnt + 1 print('____________________________________') print('****** \033[5;31;43m POWER OFF FAILED \033[0m') print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') f.write("POWEROFF FAILED!\r\n") elif index_btldr == 1: # time out = success success_cnt = success_cnt + 1 is_repower = True print('____________________________________') print('###### \033[1;42m POWER OFF OK! \033[0m') print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') f.write("POWEROFF OK!\r\n") # print(ss.before) print("total_cnt :", total_cnt) print("success_cnt :", success_cnt) print("fail_cnt :", fail_cnt) print("start time :", start_time) print("end time :", end_time) print("------------------------------------------------------\n") f.write("total_cnt :" + str(total_cnt) + "\r\n") f.write("success_cnt :" + str(success_cnt) + "\r\n") f.write("fail_cnt :" + str(fail_cnt) + "\r\n") f.write("start time :" + start_time + "\r\n") f.write("end time :" + end_time + "\r\n") f.write( "------------------------------------------------------\r\n\r\n" ) f.flush() if is_repower: power_cycle() start_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
class UI(): """Class Name: UI Purpose Provides DUT command line user interface and terminal output/logging features. """ log_stream = sys.stdout log_terminal_output = True end_msg = True last_ui = '' test_result = 'CHECK' def __init__(self, credentials, platform): self.__platform = platform self.__dut = None self.__prompt = '' self.__type = credentials[0].lower() self.__last_buff = '' self.__out_even = True if not settings.glb.show_login: UI.log_terminal_output = False if self.__type == 'host': if platform == 'windows': self.__EOF = pexpect_for_winpexpect.EOF self.__TIMEOUT = pexpect_for_winpexpect.TIMEOUT else: self.__EOF = pexpect.EOF self.__TIMEOUT = pexpect.TIMEOUT return elif self.__type == 'snmp': self.__dut_ip = credentials[1] self.__snmp_ver = credentials[2] return elif self.__type == 'console': self.__EOF = pexpect.EOF self.__TIMEOUT = pexpect.TIMEOUT login_status = self.__initserial__(*credentials[1:]) elif 'telnet' in self.__type or 'ssh' in self.__type: if settings.host_os == 'windows': self.__EOF = pexpect_for_winpexpect.EOF self.__TIMEOUT = pexpect_for_winpexpect.TIMEOUT else: self.__EOF = pexpect.EOF self.__TIMEOUT = pexpect.TIMEOUT if 'telnet' in self.__type: login_status = self.__inittelnet__(*credentials[1:]) elif 'ssh' in self.__type: login_status = self.__initssh__(*credentials[1:]) if login_status == 'PASS': if self.__platform == 'simba': self.send('terminal length 0\r') self.expect(self.__prompt) self.send('terminal width ' + str(settings.glb.log_width) + '\r') self.expect(self.__prompt) self.__last_buff = self.getBuff() UI.log_terminal_output = True self.__init = True return self.__dut elif login_status == 'FAIL': self.__init = False self.__dut = None self.__prompt = '' self.__type = '' return self.__dut def __setas__(self, other): self.__type = other.__type self.__dut = other.__dut self.__prompt = other.__prompt self.__last_buff = other.__last_buff self.__EOF = other.__EOF self.__TIMEOUT = other.__TIMEOUT self.__init = other.__init def __initserial__(self, com_port, speed, user, pwd, prompt): m = re.match('COM([0-9]+)', com_port) if m and settings.host_os == 'linux': com_num = m.group(1) com_port = '/dev/ttyS' + com_num self.__ui_str = 'console ' + com_port + ' baud rate ' + str(speed) UI.log('ACTION', 'Initializing ' + self.__ui_str) try: ser = serial.Serial(com_port, speed, timeout=0.1) self.__dut = SerialSpawn(ser, timeout=10, encoding='utf-8') except Exception as e: if not settings.glb.print_to_stdout: sys.stdout.write( 'CRITICAL ALERT: Serial spawn session failed to initialize' ) sys.stdout.write( 'Please check console login credentials, and verify the COM port is available.' ) sys.stdout.write(e) UI.log( 'CRITICAL ALERT', 'Serial spawn session failed to initialize', 'Please check console login credentials, and verify the COM port is available.', str(e)) return 'FAIL' self.__prompt = prompt return self.__login__(user, pwd) def __inittelnet__(self, ip, port, user, pwd, prompt): if port != '': self.__ui_str = 'Telnet ' + ip + ' on port ' + port else: self.__ui_str = 'Telnet ' + ip UI.log('ACTION', 'Initializing ' + self.__ui_str) try: if settings.host_os == 'windows': if port != '': spw = winspawn('bin_win32/plink -telnet ' + ip + ' -P ' + port) else: spw = winspawn('bin_win32/plink -telnet ' + ip) #spw = winspawn('bin_win32/telnet_win.exe '+ip) else: spw = pexpect.spawn('telnet ' + ip + ' ' + port, encoding='utf-8') except Exception as e: if not settings.glb.print_to_stdout: sys.stdout.write( 'CRITICAL ALERT: Telnet spawn session failed to initialize' ) sys.stdout.write( 'Please check Telnet login credentials, and verify the IP address is configured ' + 'properly.') sys.stdout.write(e) UI.log( 'CRITICAL ALERT', 'Telnet spawn session failed to initialize', 'Please check Telnet login credentials, and verify the IP address is configured properly.', str(e)) return 'FAIL' self.__dut = spw self.__prompt = prompt return self.__login__(user, pwd) def __initssh__(self, ip, port, user, pwd, prompt): if port != '': self.__ui_str = 'SSH ' + user + '@' + ip + ' on port ' + port else: self.__ui_str = 'SSH ' + user + '@' + ip UI.log('ACTION', 'Initializing ' + self.__ui_str) try: if settings.host_os == 'windows': if port != '': spw = winspawn('bin_win32/plink -ssh ' + user + '@' + ip + ' -P ' + port) else: spw = winspawn('bin_win32/plink -ssh ' + user + '@' + ip) else: spw = pexpect.spawn( 'ssh ' + user + '@' + ip + ' -p ' + port + ' -o StrictHostKeyChecking=no -o ServerAliveInterval=60', encoding='utf-8') except Exception as e: if not settings.glb.print_to_stdout: sys.stdout.write( 'CRITICAL ALERT: SSH spawn session failed to initialize') sys.stdout.write( 'Please check SSH login credentials, and verify the IP address is configured ' + 'properly.') sys.stdout.write(e) UI.log( 'CRITICAL ALERT', 'SSH spawn session failed to initialize', 'Please check SSH login credentials, and verify the IP address is configured properly.', str(e)) return 'FAIL' self.__dut = spw self.__prompt = prompt return self.__login__(user, pwd) def __login__(self, user, pwd): if 'ssh' in self.__type and settings.host_os == 'windows': return_char = '\n' else: return_char = '\r' if not settings.glb.show_login and user != '' and pwd != '': UI.log('Logging in with username/password: '******'/' + pwd) login_count = 0 status = '' try: # if 'telnet' in self.__type: # self.send('') # else: # self.send('\r') self.send('\r') while True: i = self.expect([ '(Username|Login|sonic login|bmc-oob. login: ).*', '(?i)password.*', '(?i)note:', self.__prompt, '(?i)permission denied', 'y/n' ], timeout=10) if i == 3: status = 'PASS' break elif i == 0: self.send(user + return_char) elif i == 1: self.send(pwd + return_char) login_count += 1 elif i == 2: if self.__type == 'console': self.send('\r') elif i == 5: self.send('y' + return_char) if login_count > 2: if not settings.glb.print_to_stdout: sys.stdout.write( 'CRITICAL ALERT: %s Login failed. Permission denied for username/password: %s/%s' % (self.__type.capitalize(), user, pwd)) UI.log( 'CRITICAL ALERT', '%s Login failed. Permission denied for username/password: %s/%s' % (self.__type.capitalize(), user, pwd)) status = 'FAIL' break if not settings.glb.show_login: UI.log('LOGIN SUCCESS', str(self) + ' is initialized.') if status == 'FAIL': self.__dut.close() return status except self.__EOF: UI.log_stream.write(self.getBuff()) if not settings.glb.print_to_stdout: sys.stdout.write( 'CRITICAL ALERT: %s login failed; please check login credentials.' % self.__type.capitalize()) UI.log( 'CRITICAL ALERT', '%s login failed; please check login credentials.' % self.__type.capitalize()) except self.__TIMEOUT: UI.log_stream.write(self.getBuff()) if not settings.glb.print_to_stdout: sys.stdout.write( 'CRITICAL ALERT: %s login timed out; please check login credentials.' % self.__type.capitalize()) UI.log( 'CRITICAL ALERT', '%s login timed out; please check login credentials.' % self.__type.capitalize()) def getOutEven(self): return self.__out_even def init(self): return self.__init def getPrompt(self): return self.__prompt def getEOF(self): return self.__EOF def getTIMEOUT(self): return self.__TIMEOUT def close(self, close_cmd='exit'): if self.__dut is None: return if not settings.glb.show_login: UI.log('LOGGING OUT', 'Closed ' + self.__ui_str) UI.log_terminal_output = False try: self.send(settings.glb.ctrl_c) self.expect(self.__prompt, writting=None) self.send(close_cmd + '\r') while True: i = self.expect([ self.__EOF, '(?i)(note:|login|exit session).*', self.__prompt ], writting=None) if i == 0 or i == 1: break elif i == 2: self.send(close_cmd + '\r') except: if self.__dut.isalive(): self.__dut.terminate() if self.__dut != None: self.__dut.close() if UI.log_terminal_output: UI.log('Closed ' + self.__ui_str) self.__dut = None self.__type = None self.__init = False UI.log_terminal_output = True return None def spawn(self, *cmd): try: if settings.host_os == 'windows': self.__ui_str = 'Windows host CMD' self.__dut = winspawn(*cmd) elif settings.host_os == 'linux': self.__ui_str = 'Linux host Bash shell' self.__dut = pexpect.spawn(*cmd, encoding='utf-8') cmd = ''.join(*cmd) UI.log('ACTION', 'Executing command on ' + self.__ui_str, 'Command: ' + cmd) UI.logTitle('TERMINAL OUTPUT from ' + self.__ui_str) UI.last_ui = str(self) last_line = self.__last_buff.split('\n')[-1] UI.log_stream.write(last_line) if settings.glb.print_to_stdout: sys.stdout.write(last_line) UI.end_msg = False except Exception as e: if not settings.glb.print_to_stdout: sys.stdout.write( 'CRITICAL ALERT: Host spawn session failed to initialize') sys.stdout.write(str(e)) UI.log('CRITICAL ALERT', 'Host spawn session failed to initialize', str(e)) self.__dut = None def send(self, *args): if self.__dut == None: return if (UI.end_msg or UI.last_ui != str(self)) and UI.log_terminal_output: UI.log_stream.write(settings.glb.change_line) UI.logTitle('TERMINAL OUTPUT from ' + self.__ui_str) UI.last_ui = str(self) last_line = self.__last_buff.split('\n')[-1] UI.log_stream.write(last_line) if settings.glb.print_to_stdout: sys.stdout.write(last_line) UI.end_msg = False return self.__dut.send(*args) def sendWithoutOutput(self, *args): if self.__dut == None: return else: return self.__dut.send(*args) def expect(self, *args, timeout=10, writting=True, before=True, after=True): self.__out_even = False expectError = False if self.__dut == None: return try: ret = self.__dut.expect(*args, timeout=timeout) except: expectError = True ret = 1 pass if writting: buff = self.getBuff(before=before, after=after) if UI.log_terminal_output: UI.log_stream.write(buff) if settings.glb.print_to_stdout: sys.stdout.write(buff) else: UI.end_msg = True if args[0][ret] == self.__EOF: UI.last_ui = '' self.__dut = None self.__last_buff = '' else: self.__last_buff = buff self.__out_even = True if expectError: return 100 else: return ret def getBuff(self, before=True, after=True): if self.__dut == None: return '' ret_str = '' if 'str' in str(type(self.__dut.before)) and before: ret_str = self.__dut.before if 'str' in str(type(self.__dut.after)) and after: ret_str += self.__dut.after return ret_str def getLastBuff(self): return self.__last_buff def getBeforeBuff(self): if 'str' in str(type(self.__dut.before)): return self.__dut.before else: return "NULL" def getAfterBuff(self): if 'str' in str(type(self.__dut.after)): return self.__dut.after else: return "NULL" def sendCmd(self, cmd, prompt="", writting=True, timeout=10): if prompt == "": prompt = self.__prompt self.send(cmd + '\r') ret = self.expect(prompt, writting=writting, timeout=timeout) if ret == 0: return self.getOutputFromLastBuff(cmd, prompt=prompt) else: return "" def getOutputFromLastBuff(self, cmd, prompt=""): if prompt == "": prompt = self.__prompt relist = self.getBuff().splitlines() retstr = "" for line in relist: if not re.search('^\x1b]0;root.*', line): if cmd != line: retstr += line + '\n' return retstr def snmpGet(self, oids, credentials='', port=161, engine=hlapi.SnmpEngine(), context=hlapi.ContextData()): target = self.__dut_ip if self.__snmp_ver.lower() == '2c': credentials = hlapi.CommunityData('public') handler = hlapi.getCmd(engine, credentials, hlapi.UdpTransportTarget((target, port)), context, *construct_object_types(oids)) ret = fetch(handler, 1)[0] ret_list = [] for key, value in ret.items(): temp = key + ': ' + value ret_list.append(temp) UI.log('SNMP-GET', 'Remote IP: ' + self.__dut_ip, *ret_list) return ret def snmpSet(self, value_pairs, credentials='', port=161, engine=hlapi.SnmpEngine(), context=hlapi.ContextData()): target = self.__dut_ip if self.__snmp_ver.lower() == '2c': credentials = hlapi.CommunityData('private') handler = hlapi.setCmd(engine, credentials, hlapi.UdpTransportTarget((target, port)), context, *construct_value_pairs(value_pairs)) ret = fetch(handler, 1)[0] ret_list = [] for key, value in ret.items(): temp = key + ': ' + value ret_list.append(temp) UI.log('SNMP-SET', 'Remote IP: ' + self.__dut_ip, *ret_list) return ret @classmethod def openLog(class_object, filename): UI.log_stream = open(filename, 'a') @classmethod def logTitle(class_object, title): if not UI.end_msg: UI.log_stream.write(settings.glb.change_line) if settings.glb.print_to_stdout: sys.stdout.write('\n') centered_title = '{:=^{w}}'.format(' ' + title + ' ', w=settings.glb.log_width) UI.log_stream.write(centered_title) if settings.glb.print_to_stdout: sys.stdout.write(centered_title) UI.log_stream.write(settings.glb.change_line) UI.end_msg = True if settings.glb.print_to_stdout: sys.stdout.write('\n\n') if title == 'PASS' and UI.test_result == 'CHECK': UI.test_result = 'PASS' elif title == 'FAIL': UI.test_result = 'FAIL' @classmethod def log(class_object, *msg): if not UI.end_msg: UI.log_stream.write(settings.glb.change_line) if settings.glb.print_to_stdout: sys.stdout.write('\n') if msg[0].isupper(): title = msg[0] msg = msg[1:] UI.logTitle(title) else: divider = '=' * settings.glb.log_width UI.log_stream.write(divider) UI.log_stream.write(settings.glb.change_line) if settings.glb.print_to_stdout: sys.stdout.write(divider) sys.stdout.write('\n\n') first_word = msg[0].split(' ')[0] if re.match('(\.|:)', first_word[-1]): indent = ' ' * (len(first_word) + 1) else: indent = '' for m in msg: # Perform word wrap for each line of message. m.strip('\n') lines = '' word_list = str(m).split(' ') for w in word_list: last_line = (lines + w).split('\n')[-1] if len(last_line) > settings.glb.log_width: lines += '\n' + indent + w + ' ' else: lines += w + ' ' UI.log_stream.write(lines + '\n') if settings.glb.print_to_stdout: sys.stdout.write(lines + '\n') if settings.glb.print_to_stdout: sys.stdout.write('\n') UI.end_msg = True @classmethod def closeLog(class_object): UI.log_stream.write('\n\n') UI.log_stream.close() f = open(UI.log_stream.name, 'r') l_list = f.readlines() f.close() new_f = open(UI.log_stream.name, 'w') empty_line_count = 0 for l in l_list: l = l.replace(']0;root@minipack:~', '') if re.search('^[\r\n]+$', l, re.M) or len(l) == 1: empty_line_count += 1 else: if empty_line_count > 2: new_f.write('\n') new_f.write(l) empty_line_count = 0 new_f.close
def main(): with serial.Serial('/dev/ttyAMA0', 115200, timeout=0) as ser: ss = SerialSpawn(ser) # DEBUG ss.logfile = sys.stderr.buffer total_cnt = 0 success_cnt = 0 fail_cnt = 0 first = True log_first = "" logfile = time.strftime("UBOOT-LOG-%Y-%m-%d-%H.txt", time.localtime()) f = open(logfile, 'a') f.write("DC_OFF_SECS = {}\n".format(DC_OFF_SECS)) f.write("TIMEOUT_LOGIN = {}\n".format(TIMEOUT_LOGIN)) f.write("TIMEOUT_SHELL = {}\n".format(TIMEOUT_SHELL)) f.write("TIMEOUT_PWROFF = {}\n".format(TIMEOUT_PWROFF)) power_cycle() tm_start = time.localtime() while True: # try: # a = ss.expect('SCHNEIDER2 login:'******'root') # b = ss.expect('root@SCHNEIDER2:') # ss.sendline('poweroff') # power_cycle() # except TIMEOUT: # pass # power_cycle() # ser_bytes = ser.readline() # print(ser_bytes) time.sleep(0.1) if first: log_first += decode_all(ss) ss.sendline() index_login = ss.expect( pattern=['CPU : AM335X-GP rev 2.1', pexpect.TIMEOUT], timeout=TIMEOUT_LOGIN) if index_login == 1: # device get stuck print("Wait login TIMEOUT!!!") f.write("Wait login TIMEOUT!!!\n") power_cycle() log_first += decode_all(ss) f.write("### BOOT LOG ###\n" + log_first) f.write("\n\n\n\n\n") continue # ser_bytes = ser.readline() # print(ser_bytes) for i in range(6): ss.send('\x03') time.sleep(0.3) ss.sendline() if first: log_first += decode_all(ss) index_shell = ss.expect(pattern=['=>', pexpect.TIMEOUT], timeout=TIMEOUT_SHELL) if index_shell == 0: # normal pass elif index_shell == 1: # device get stuck print("Wait shell TIMEOUT!!!") f.write("Wait shell TIMEOUT!!!\n") power_cycle() continue ss.sendline('setenv ipaddr 192.168.4.58') time.sleep(0.2) ss.sendline('ping 192.168.4.2') time.sleep(2.0) ss.sendline('poweroff') total_cnt = total_cnt + 1 is_repower = False time.sleep(1) tm_pwrdn = time.localtime() if first: log_first += decode_all(ss) index_btldr = ss.expect(pattern=['U-Boot ', pexpect.TIMEOUT], timeout=TIMEOUT_PWROFF) if first: log_first += decode_all(ss) if index_btldr == 0: fail_cnt = fail_cnt + 1 print('____________________________________') print('****** \033[5;31;43m POWER OFF FAILED \033[0m') print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') f.write("POWEROFF FAILED!\n") elif index_btldr == 1: # time out = success success_cnt = success_cnt + 1 is_repower = True print('____________________________________') print('###### \033[1;42m POWER OFF OK! \033[0m') print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') f.write("POWEROFF OK!\n") fa = "FAIL : {}\n".format(fail_cnt) ot = "OK/TOTAL : {} / {}\n".format(success_cnt, total_cnt) tm_start_str = time.strftime("%Y-%m-%d %H:%M:%S", tm_start) st = "START : {}\n".format(tm_start_str) ps = time.mktime(tm_pwrdn) - time.mktime(tm_start) cy = "USED : {} Secs\n".format(ps) print(fa + ot + st + cy, end='') print("------------------------------------------------------\n") if first: log_first += decode_all(ss) f.write("### BOOT LOG ###\n" + log_first) f.write("\n\n\n\n\n") f.write(fa + ot + st + cy) f.write( "------------------------------------------------------\n\n") f.flush() if is_repower: power_cycle() tm_start = time.localtime() first = False
def main(): global logfile AP_ESCAPE = "Escape character is '^]'." AP_USERNAME = "******" AP_PASSWORD = "******" AP_EN = "en" AP_MORE = "--More--" AP_EXIT = "exit" LF_PROMPT = "$" CR = "\r\n" parser = argparse.ArgumentParser(description="Cisco AP Control Script") parser.add_argument("-a", "--prompt", type=str, help="ap prompt") parser.add_argument("-d", "--dest", type=str, help="address of the AP 172.19.27.55") parser.add_argument("-o", "--port", type=int, help="control port on the AP, 2008") parser.add_argument("-u", "--user", type=str, help="credential login/username, admin") parser.add_argument("-p", "--passwd", type=str, help="credential password Wnbulab@123") parser.add_argument("-s", "--scheme", type=str, choices=["serial", "ssh", "telnet"], help="Connect via serial, ssh or telnet") parser.add_argument("-t", "--tty", type=str, help="tty serial device for connecting to AP") parser.add_argument("-l", "--log", type=str, help="logfile for messages, stdout means output to console",default="stdout") parser.add_argument("-z", "--action", type=str, help="action, current action is powercfg") parser.add_argument("-b", "--baud", type=str, help="action, baud rate lanforge: 115200 cisco: 9600") args = None try: args = parser.parse_args() host = args.dest scheme = args.scheme port = (default_ports[scheme], args.port)[args.port != None] user = args.user if (args.log != None): logfile = args.log except Exception as e: logging.exception(e) usage() exit(2) console_handler = logging.StreamHandler() formatter = logging.Formatter(FORMAT) logg = logging.getLogger(__name__) logg.setLevel(logging.DEBUG) file_handler = None if (logfile is not None): if (logfile != "stdout"): file_handler = logging.FileHandler(logfile, "w") file_handler.setLevel(logging.DEBUG) file_handler.setFormatter(formatter) logg.addHandler(file_handler) logging.basicConfig(format=FORMAT, handlers=[file_handler]) else: # stdout logging logging.basicConfig(format=FORMAT, handlers=[console_handler]) egg = None # think "eggpect" ser = None try: if (scheme == "serial"): #eggspect = pexpect.fdpexpect.fdspan(telcon, logfile=sys.stdout.buffer) ser = serial.Serial(args.tty, int(args.baud), timeout=5) print("Created serial connection on %s, open: %s"%(args.tty, ser.is_open)) egg = SerialSpawn(ser) egg.logfile = FileAdapter(logg) time.sleep(1) egg.sendline(CR) time.sleep(1) elif (scheme == "ssh"): if (port is None): port = 22 cmd = "ssh -p%d %s@%s"%(port, user, host) logg.info("Spawn: "+cmd+NL) egg = pexpect.spawn(cmd) #egg.logfile_read = sys.stdout.buffer egg.logfile = FileAdapter(logg) elif (scheme == "telnet"): if (port is None): port = 23 cmd = "telnet {} {}".format(host, port) logg.info("Spawn: "+cmd+NL) egg = pexpect.spawn(cmd) egg.logfile = FileAdapter(logg) # Will login below as needed. else: usage() exit(1) except Exception as e: logging.exception(e) AP_PROMPT = "{}>".format(args.prompt) AP_HASH = "{}#".format(args.prompt) time.sleep(0.1) logged_in = False loop_count = 0 while (loop_count <= 8 and logged_in == False): loop_count += 1 i = egg.expect_exact([AP_ESCAPE,AP_PROMPT,AP_HASH,AP_USERNAME,AP_PASSWORD,AP_MORE,LF_PROMPT,pexpect.TIMEOUT],timeout=5) if i == 0: logg.info("Expect: {} i: {} before: {} after: {}".format(AP_ESCAPE,i,egg.before,egg.after)) egg.sendline(CR) # Needed after Escape or should just do timeout and then a CR? sleep(1) if i == 1: logg.info("Expect: {} i: {} before: {} after: {}".format(AP_PROMPT,i,egg.before,egg.after)) egg.sendline(AP_EN) sleep(1) j = egg.expect_exact([AP_PASSWORD,pexpect.TIMEOUT],timeout=5) if j == 0: logg.info("Expect: {} i: {} j: {} before: {} after: {}".format(AP_PASSWORD,i,j,egg.before,egg.after)) egg.sendline(args.passwd) sleep(1) k = egg.expect_exact([AP_HASH,pexpect.TIMEOUT],timeout=5) if k == 0: logg.info("Expect: {} i: {} j: {} k: {} before: {} after: {}".format(AP_PASSWORD,i,j,k,egg.before,egg.after)) logged_in = True if k == 1: logg.info("Expect: {} i: {} j: {} k: {} before: {} after: {}".format("Timeout",i,j,k,egg.before,egg.after)) if j == 1: logg.info("Expect: {} i: {} j: {} before: {} after: {}".format("Timeout",i,j,egg.before,egg.after)) if i == 2: logg.info("Expect: {} i: {} before: {} after: {}".format(AP_HASH,i,egg.before,egg.after)) logged_in = True sleep(1) if i == 3: logg.info("Expect: {} i: {} before: {} after: {}".format(AP_USERNAME,i,egg.before,egg.after)) egg.sendline(args.user) sleep(1) if i == 4: logg.info("Expect: {} i: {} before: {} after: {}".format(AP_PASSWORD,i,egg.before,egg.after)) egg.sendline(args.passwd) sleep(1) if i == 5: logg.info("Expect: {} i: {} before: {} after: {}".format(AP_MORE,i,egg.before,egg.after)) if (scheme == "serial"): egg.sendline("r") else: egg.sendcontrol('c') sleep(1) # for Testing serial connection using Lanforge if i == 6: logg.info("Expect: {} i: {} before: {} after: {}".format(LF_PROMPT,i,egg.before.decode('utf-8', 'ignore'),egg.after.decode('utf-8', 'ignore'))) if (loop_count < 3): egg.send("ls -lrt") sleep(1) if (loop_count > 4): logged_in = True # basically a test mode using lanforge serial if i == 7: logg.info("Expect: {} i: {} before: {} after: {}".format("Timeout",i,egg.before,egg.after)) egg.sendline(CR) sleep(1) if (args.action == "powercfg"): logg.info("execute: show controllers dot11Radio 1 powercfg | g T1") egg.sendline('show controllers dot11Radio 1 powercfg | g T1') egg.expect([pexpect.TIMEOUT], timeout=3) # do not delete this for it allows for subprocess to see output print(egg.before.decode('utf-8', 'ignore')) # do not delete this for it allows for subprocess to see output i = egg.expect_exact([AP_MORE,pexpect.TIMEOUT],timeout=5) if i == 0: egg.sendcontrol('c') if i == 1: logg.info("send cntl c anyway") egg.sendcontrol('c') elif (args.action == "clear_log"): logg.info("execute: clear log") egg.sendline('clear log') sleep(0.4) egg.sendline('show log') egg.expect([pexpect.TIMEOUT], timeout=2) # do not delete this for it allows for subprocess to see output print(egg.before.decode('utf-8', 'ignore')) # do not delete this for it allows for subprocess to see output # allow for normal logout below elif (args.action == "show_log"): logg.info("execute: show log") egg.sendline('show log') sleep(0.4) egg.expect([pexpect.TIMEOUT], timeout=2) # do not delete this for it allows for subprocess to see output print(egg.before.decode('utf-8', 'ignore')) # do not delete this for it allows for subprocess to see output i = egg.expect_exact([AP_MORE,pexpect.TIMEOUT],timeout=4) if i == 0: egg.sendline('r') egg.expect([pexpect.TIMEOUT], timeout=4) # do not delete this for it allows for subprocess to see output print(egg.before.decode('utf-8', 'ignore')) # do not delete this for it allows for subprocess to see output if i == 1: print(egg.before.decode('utf-8', 'ignore')) # do not delete this for it allows for subprocess to see output # allow for normal logout below # show log | g DOT11_DRV # CAC_EXPIRY_EVT: CAC finished on DFS channel 52 elif (args.action == "cac_expiry_evt"): logg.info("execute: show log | g CAC_EXPIRY_EVT") egg.sendline('show log | g CAC_EXPIRY_EVT') sleep(0.4) egg.expect([pexpect.TIMEOUT], timeout=2) # do not delete this for it allows for subprocess to see output print(egg.before.decode('utf-8', 'ignore')) # do not delete this for it allows for subprocess to see output i = egg.expect_exact([AP_MORE,pexpect.TIMEOUT],timeout=4) if i == 0: egg.sendline('r') egg.expect([pexpect.TIMEOUT], timeout=4) # do not delete this for it allows for subprocess to see output print(egg.before.decode('utf-8', 'ignore')) # do not delete this for it allows for subprocess to see output if i == 1: print(egg.before.decode('utf-8', 'ignore')) # do not delete this for it allows for subprocess to see output elif (args.action == "ds_data_5ghz"): logg.info("execute: wl -i wl1 bs_data") egg.sendline('wl -i wl1 bs_data') egg.expect([pexpect.TIMEOUT], timeout=4) # do not detete this for it allow for subprocess to read print(egg.before.decode('utf-8','ignore')) # do not delete this for it allows for subprocess to see output elif (args.action == "ds_data_24ghz"): logg.info("execute: wl -i wl0 bs_data") egg.sendline('wl -i wl1 bs_data') egg.expect([pexpect.TIMEOUT], timeout=4) # do not detete this for it allow for subprocess to read print(egg.before.decode('utf-8','ignore')) # do not delete this for it allows for subprocess to see output else: # no other command at this time so send the same power command #logg.info("no action so execute: show controllers dot11Radio 1 powercfg | g T1") logg.info("no action") i = egg.expect_exact([AP_PROMPT,AP_HASH,pexpect.TIMEOUT],timeout=1) if i == 0: logg.info("received {} we are done send exit".format(AP_PROMPT)) egg.sendline(AP_EXIT) if i == 1: logg.info("received {} send exit".format(AP_HASH)) egg.sendline(AP_EXIT) if i == 2: logg.info("timed out waiting for {} or {}".format(AP_PROMPT,AP_HASH))
import sys # pip3 install pyserial # sudo apt-get install python3-serial import serial # pip3 install pexpect-serial from pexpect_serial import SerialSpawn # If pexpect-serial is not available, use pexpect + picocom. with serial.Serial('/dev/ttyACM0', baudrate = 115200, bytesize = 8, \ parity = 'N', stopbits = 1) as ser: p = SerialSpawn(ser) p.logfile_read = sys.stdout.buffer p.expect('U-Boot ') p.expect('Hit any key to stop autoboot: ') p.send("s") p.expect('> ') p.logfile_read = None p.interact() # press CTRL-] to contine python execution # python3 -c " # import pexpect, sys # c = pexpect.spawn('$VPN_CMD') # c.logfile_read = sys.stdout.buffer # c.expect('Password:'******'$VPN_PASSWORD') # c.interact() # "
def main(): global prompt parser = argparse.ArgumentParser(description="OpenWrt AP Control Script") parser.add_argument("-d", "--dest", type=str, help="address of the cisco controller") parser.add_argument("-o", "--port", type=int, help="control port on the controller") parser.add_argument("-u", "--user", type=str, help="credential login/username") parser.add_argument("-p", "--passwd", type=str, help="credential password") parser.add_argument("-P", "--prompt", type=str, help="Prompt to look for") parser.add_argument("-s", "--scheme", type=str, choices=["serial", "ssh", "telnet"], help="Connect via serial, ssh or telnet") parser.add_argument("-t", "--tty", type=str, help="tty serial device") parser.add_argument( "-l", "--log", type=str, help="logfile for messages, stdout means output to console") parser.add_argument("--action", type=str, help="perform action", choices=[ "logread", "journalctl", "lurk", "sysupgrade", "download", "upload", "reboot", "cmd" ]) parser.add_argument("--value", type=str, help="set value") parser.add_argument("--value2", type=str, help="set value2") tty = None args = None try: args = parser.parse_args() host = args.dest scheme = args.scheme port = args.port #port = (default_ports[scheme], args.port)[args.port != None] user = args.user passwd = args.passwd logfile = args.log tty = args.tty if (args.prompt != None): prompt = args.prompt filehandler = None except Exception as e: logging.exception(e) usage() exit(2) console_handler = logging.StreamHandler() formatter = logging.Formatter(FORMAT) logg = logging.getLogger(__name__) logg.setLevel(logging.DEBUG) file_handler = None if (logfile is not None): if (logfile != "stdout"): file_handler = logging.FileHandler(logfile, "w") file_handler.setLevel(logging.DEBUG) file_handler.setFormatter(formatter) logg.addHandler(file_handler) logging.basicConfig(format=FORMAT, handlers=[file_handler]) else: # stdout logging logging.basicConfig(format=FORMAT, handlers=[console_handler]) CCPROMPT = prompt ser = None egg = None # think "eggpect" try: if (scheme == "serial"): #eggspect = pexpect.fdpexpect.fdspan(telcon, logfile=sys.stdout.buffer) import serial from pexpect_serial import SerialSpawn ser = serial.Serial(tty, 115200, timeout=5) egg = SerialSpawn(ser) egg.logfile = FileAdapter(logg) egg.sendline(NL) try: i = egg.expect( [prompt, "Please press Enter to activate", "login:"******"Password:"******"ssh"): # Not implemented/tested currently. --Ben if (port is None): port = 22 cmd = "ssh -p%d %s@%s" % (port, user, host) logg.info("Spawn: " + cmd + NL) egg = pexpect.spawn(cmd) #egg.logfile_read = sys.stdout.buffer egg.logfile = FileAdapter(logg) i = egg.expect(["password:"******"continue connecting (yes/no)?"], timeout=3) time.sleep(0.1) if i == 1: egg.sendline('yes') egg.expect('password:'******' ') egg.expect('User\:') egg.sendline(user) egg.expect('Password\:') egg.sendline(passwd) egg.sendline('config paging disable') else: usage() exit(1) except Exception as e: logging.exception(e) command = None CLOSEDBYREMOTE = "closed by remote host." CLOSEDCX = "Connection to .* closed." try: egg.expect(CCPROMPT) except Exception as e: egg.sendline(NL) TO = 10 wait_forever = False # Clean pending output egg.sendline("echo __hello__") egg.expect("__hello__") egg.expect(CCPROMPT) logg.info("Action[%s] Value[%s] Value2[%s]" % (args.action, args.value, args.value2)) if (args.action == "reboot"): command = "reboot" TO = 60 if (args.action == "cmd"): if (args.value is None): raise Exception("cmd requires value to be set.") command = "%s" % (args.value) if (args.action == "logread"): command = "logread -f" TO = 1 wait_forever = True if (args.action == "journalctl"): command = "journalctl -f" TO = 1 wait_forever = True if (args.action == "lurk"): command = "date" TO = 1 wait_forever = True if (args.action == "sysupgrade"): command = "scp %s /tmp/new_img.bin" % (args.value) logg.info("Command[%s]" % command) egg.sendline(command) i = egg.expect(["password:"******"Do you want to continue connecting"], timeout=5) if i == 1: egg.sendline("y") egg.expect("password:"******"lanforge") egg.expect(CCPROMPT, timeout=20) egg.sendline("sysupgrade /tmp/new_img.bin") egg.expect("link becomes ready", timeout=100) return if (args.action == "download"): command = "scp %s /tmp/%s" % (args.value, args.value2) logg.info("Command[%s]" % command) egg.sendline(command) i = egg.expect([ "password:"******"Do you want to continue connecting", "Network unreachable" ], timeout=5) if i == 2: print("Network unreachable, wait 15 seconds and try again.") time.sleep(15) command = "scp %s /tmp/%s" % (args.value, args.value2) logg.info("Command[%s]" % command) egg.sendline(command) i = egg.expect([ "password:"******"Do you want to continue connecting", "Network unreachable" ], timeout=5) if i == 2: print("ERROR: Could not connect to LANforge to get download file") exit(2) if i == 1: egg.sendline("y") egg.expect("password:"******"lanforge") egg.expect(CCPROMPT, timeout=20) return if (args.action == "upload"): command = "scp %s %s" % (args.value, args.value2) logg.info("Command[%s]" % command) egg.sendline(command) i = egg.expect([ "password:"******"Do you want to continue connecting", "Network unreachable" ], timeout=5) if i == 2: print("Network unreachable, wait 15 seconds and try again.") time.sleep(15) command = "scp /tmp/%s %s" % (args.value, args.value2) logg.info("Command[%s]" % command) egg.sendline(command) i = egg.expect([ "password:"******"Do you want to continue connecting", "Network unreachable" ], timeout=5) if i == 2: print("ERROR: Could not connect to LANforge to put upload file") exit(2) if i == 1: egg.sendline("y") egg.expect("password:"******"lanforge") egg.expect(CCPROMPT, timeout=20) return if (command is None): logg.info("No command specified, going to log out.") else: logg.info("Command[%s]" % command) egg.sendline(command) while True: try: i = egg.expect( [CCPROMPT, "kmodloader: done loading kernel", "\n"], timeout=TO) print(egg.before.decode('utf-8', 'ignore')) if i == 1: egg.sendline(' ') egg.expect(CCPROMPT, timeout=20) print(egg.before.decode('utf-8', 'ignore')) if i == 2: # new line of text, just print and continue continue if not wait_forever: break except Exception as e: # Some commands take a long time (logread -f) if not wait_forever: logging.exception(e) break
class PipeSerial: """The PipeSerial class.""" __version__ = __version__ def __init__( self, serialport: str, baudrate: int = 115200, bytesize: int = 8, parity: str = "N", stopbits: float = 1, rtscts: bool = False, xonxoff: bool = False, rts: typing.Optional[int] = None, dtr: typing.Optional[int] = None, ) -> None: """Initialise pyserial object and configure the serial port. Args: serialport: The serial port device to use, like "/dev/cuaU0" baudrate: The serial port speed, default: 115200 bytesize: Serial port bytesize, one of {5 6 7 8}, default: 8 parity: Serial port parity, one of {N E O S M}, default: N stopbits: Serial port stopbits, one of {1 1.5 2}, default: 1 rtscts: Enable serial port RTS/CTS hardware flow control, default: False xonxoff: Enable serial port software flow control, default: False rts: Set initial RTS line state, one of {0, 1}, default: None dtr: Set initial DTR line state, one of {0, 1}, default: None Returns: Nothing """ logger.debug(f"Configuring serial port {serialport} ...") self.ser = serial.serial_for_url(serialport, do_not_open=True) self.ser.baudrate = baudrate self.ser.bytesize = bytesize self.ser.parity = parity self.ser.stopbits = stopbits self.ser.rtscts = rtscts self.ser.xonxoff = xonxoff if rts is not None: self.ser.rts = rts if dtr is not None: self.ser.dtr = dtr def open(self) -> bool: """Open the serial port and initialise the pexpect_serial object. Args: None Returns: None """ # open serial port try: logger.debug("Opening serial port...") self.ser.open() except serial.SerialException: logger.exception(f"Could not open serial port {self.ser.name}") return False # and init pexpect_serial object self.ss = SerialSpawn(self.ser) logger.debug("Serial port opened OK!") return True def run( self, payload: str, expect: typing.List[str], delay: float = 0.9, expectcount: int = 1, timeout: int = 30, ) -> typing.List[str]: """Send the payload to serial device. Args: payload: The payload to send to the serial device. expect: A list of regex to expect as the end of output. Returns: The output from the serial device as list of string, one for each line. """ # send the input to serial, line by line, with \r\n newlines for line in payload.split("\n"): if not line: # skip empty lines continue logger.debug(f"Sending payload line: {line}") self.ss.send(line.strip() + "\r\n") time.sleep(delay) # Wait for some matching output output = b"" logger.debug( f"Collecting output, looking for one of these regular expressions: {expect}" ) logger.debug(f"Will stop collecting after {expectcount} matches") for i in range(1, expectcount + 1): match = self.ss.expect(expect, timeout=timeout) logger.debug( f"Found match: '{expect[match].strip()}' (match number {i} of {expectcount})" ) # we want all the output, before and including the expected string output += self.ss.before + self.ss.after # decode, strip and return the lines of output logger.debug( f"Done! Returning {len(output)} bytes of output from serial device" ) return [line.strip() for line in output.decode("LATIN1").split("\n")] def close(self) -> None: """Close the serial port.""" logger.debug("Closing serial port...") self.ss.ser.close() logger.debug("Serial port closed")