def press_bar_handle(key): if key == 'TB_EXPAND': tree_inst.expand_trees() elif key in ['TB_ABOUT', "MENU_ABOUT"]: TopAbout() elif key in ['TB_SCREEN', 'MENU_SCREEN']: ScreenShot() elif key in ['TB_HELP', 'MENU_HELP']: pdf = 'SystemController.pdf' if not Common.is_file(pdf): WidgetTip.error('{}不存在,请确认!'.format(pdf)) return Common.create_thread(lambda: Common.system_open(pdf)) elif key in ['MENU_SET', 'TB_SET']: GuiSettings.pack() elif key == 'MENU_EXIT': app_gate.close() elif key == 'TB_LAST': tree_inst.last() elif key == 'TB_NEXT': tree_inst.next() elif key in ["MENU_WHITE", "MENU_BLACK"]: WidgetTip.info("敬请期待 !") else: # 根据界面 image 值即可进入对应界面 # tree_inst.selection(key)
def get_widget_input(): if widget == 'Combobox': # 默认选择了第一个 #[shell_params[ip].append(str(instance.current())) for ip in ips] [shell_params[ip].append(instance.get()) for ip in ips] elif widget == 'MultiCombobox': # 默认选择第一个,但可能是”“ for ip, inst in instance: if ip not in ips: continue _v = inst.get() if not _v and not can_be_null: return False shell_params[ip].append(_v) elif widget == 'Checkbox': # 默认无勾选 choose = [str(_v.get()) for _v in instance] # 未选择任意一项 if not can_be_null and len( set(choose)) == 1 and choose[0] == '0': return False [shell_params[ip].append('@'.join(choose)) for ip in ips] elif widget == 'Entry': # 默认为空 for ip in ips: _v = instance.get() if not _v and not can_be_null: return False shell_params[ip].append(_v) elif widget == 'Text': _v = instance.get('1.0', 'end').strip() if not _v and not can_be_null: return False f = '{0}\\__{1}_{2}__.txt'.format(pid_dir, widget, index) Common.write_to_file(f, _v) [shell_params[ip].append(f) for ip in ips] return True
def _execute_now(): for ip in ips: Common.create_thread(func=self.exec_start_impl, args=(ip, uploads[ip], params[ip])) logger.info( "execute_start {} for {}, params:{}, uploads:{}".format( self.task, ip, params[ip], uploads[ip]))
def upload_file(self, ssh, ip, uploads, offset): # 不直接在上传的callback中调用更新状态的Caller,因为会影响上传的速度, # callback中只更新内存,状态更新在一个线程中定时去调用 def upload_back(current, total): size[0] = current size[1] = total def get_progress(): return int(size[0] / size[1] * offset) def update_thread(): while not is_done: self.return_exec_start_result(ip, get_progress(), '', True) Common.sleep(0.2) size, is_done = [0, 1], False server_upload = Global.G_SERVER_UPLOAD % model_gate.settings_data.server_dir for local in uploads: remote = "{0}/{1}".format(server_upload, Common.basename(local)) Common.create_thread(func=update_thread, args=()) self.insert_text_info(ip, get_progress(), 'Uploading {}'.format(local)) ret, err = SSHUtil.upload_file(ssh, local, remote, upload_back) is_done = True if not ret: self.insert_text_info( ip, get_progress(), 'Upload {} failed: {}'.format(local, err), 'ERROR') self.return_exec_start_result(ip, get_progress(), '', False) return False self.return_exec_start_result(ip, get_progress(), '', True) return True
def set_data(self, data, asynccall=False): def func(args=None): self._instance.data = data if asynccall: Common.create_thread(func=func) else: func()
def click_login(): def async_login(args=None): self.login_handle() try: login_btn.disable(False) except: pass login_btn.disable(True) Common.create_thread(func=async_login)
def for_delay_loop(): if delay and not self._mutex('DELAY'): model_gate.exception_data.set_data("已经存在延迟任务\n如需重置,请先点击'停止'") return if loop and not self._mutex('LOOP'): model_gate.exception_data.set_data("已经存在循环任务\n如需重置,请先点击'停止'") return if delay: start_time = Common.time() while True: if self.is_break: return Common.sleep(1) left_sec = delay * 60 - int(Common.time() - start_time) left_sec = 0 if left_sec < 0 else left_sec model_gate.delay_loop_timer_data.set_data( [left_sec, left_sec]) if left_sec == 0: self._mutex('DELAY', False) break _execute_now() if loop: start_time = Common.time() while True: if self.is_break: return Common.sleep(1) left_sec = loop * 60 - int(Common.time() - start_time) left_sec = 0 if left_sec < 0 else left_sec model_gate.delay_loop_timer_data.set_data([0, left_sec]) if left_sec == 0: _execute_now() start_time = Common.time()
def download_file(self, ssh, ip, file): if file in ["", "NULL"]: self.insert_text_info(ip, 100, 'Success') return True download_dir = "{0}\\{1}".format(Global.G_DOWNLOAD_DIR, ip) filename = "{0}\\{1}".format(download_dir, Common.basename(file)) Common.mkdir(download_dir) self.insert_text_info(ip, 100, 'Downloading to {}'.format(filename)) if not SSHUtil.download_file(ssh, remote=file, local=filename): return False self.insert_text_info(ip, 100, "Download success") return True
def onLeftButtonUp(event): self.sel = False deleteLastDraw() Common.sleep(0.1) # 考虑鼠标左键从右下方按下而从左上方抬起的截图 left, right = sorted([self.X.get(), event.x]) top, bottom = sorted([self.Y.get(), event.y]) pic = ImageGrab.grab((left+1, top+1, right, bottom)) save_name = "ScreenShot-{0}.png".format(Common.get_time(format=False)) pic.save(save_name) self.top.destroy() Common.remove(self.temp_png) WidgetTip.info("截图成功: {0}\n截图保存在工具家目录下".format(save_name))
def _mutex(self, ip, lock=True): """ 防重入 """ _lock_file = '{0}\\{1}-{2}.lock'.format(Global.G_PID_DIR, self.task, ip) # 释放锁 if not lock: try: Common.remove(_lock_file) except: pass return True # 尝试加锁 if Common.is_file(_lock_file): return False Common.write_to_file(_lock_file, 'lock') return True
def pack_sub_foot_fm(): def update_info(): while True: time.sleep(60) sec = time.time() - app_gate.start_time run_time = '软件运行时长 {} 小时 {} 分钟'.format( int(sec / 3600), int((sec % 3600) / 60)) text = "{} {}".format(use_time, run_time) label['text'] = text use_time = '软件启动耗时 %.3f 秒' % app_gate.use_time run_time = '软件运行时长 0 小时 0 分钟' Common.create_thread(update_info) label = tk.Label(foot_fm, text="{} {}".format(use_time, run_time)) label.pack()
def auto(cls, plot_param, detail=False): cls.plot_param = plot_param only_image = "TkAgg" if detail else "Agg" plt.close('all') matplotlib.use(only_image) plt.rcParams['font.sans-serif'] = [u'SimHei'] plt.rcParams['axes.unicode_minus'] = False instance, file_name, plot_size = plot_param width, height = (plot_size[0] - 120) / 100, plot_size[1] / 100 - 0.5 download_dir = view_gate.query_env_define_data('G_DOWNLOAD_DIR') pid_dir = view_gate.query_env_define_data('G_PID_DIR') for ip, inst in instance.items(): file = "{}\\{}\\__FILE_DATA__\\{}".format(download_dir, ip, file_name) if not Common.is_file(file): raise Exception("{} 不存在\n请稍候重试".format(file)) png = "{}\\{}_{}.png".format(pid_dir, ip, file_name.split('.')[0]) data = pd.read_csv(file, parse_dates=True, index_col=0) data.plot(title="{}: {}".format(ip, file_name), grid=True, figsize=(width, height)) if not detail: plt.savefig(png, dpi=100) view_gate.add_image_data.set_data( ['AUTOPLOT_{}'.format(ip), png]) inst.image_create('0.0', image=view_gate.query_photo_image_data( 'AUTOPLOT_{}'.format(ip))) else: plt.show()
def execute_start(self, data): def _execute_now(): for ip in ips: Common.create_thread(func=self.exec_start_impl, args=(ip, uploads[ip], params[ip])) logger.info( "execute_start {} for {}, params:{}, uploads:{}".format( self.task, ip, params[ip], uploads[ip])) def for_delay_loop(): if delay and not self._mutex('DELAY'): model_gate.exception_data.set_data("已经存在延迟任务\n如需重置,请先点击'停止'") return if loop and not self._mutex('LOOP'): model_gate.exception_data.set_data("已经存在循环任务\n如需重置,请先点击'停止'") return if delay: start_time = Common.time() while True: if self.is_break: return Common.sleep(1) left_sec = delay * 60 - int(Common.time() - start_time) left_sec = 0 if left_sec < 0 else left_sec model_gate.delay_loop_timer_data.set_data( [left_sec, left_sec]) if left_sec == 0: self._mutex('DELAY', False) break _execute_now() if loop: start_time = Common.time() while True: if self.is_break: return Common.sleep(1) left_sec = loop * 60 - int(Common.time() - start_time) left_sec = 0 if left_sec < 0 else left_sec model_gate.delay_loop_timer_data.set_data([0, left_sec]) if left_sec == 0: _execute_now() start_time = Common.time() ips, script, root, delay, loop, params, uploads = data self.init(script, root, True) Common.create_thread(for_delay_loop)
def try_login(self, ip_data_list): zip_file = "{0}\\{1}".format(Global.G_PID_DIR, Global.G_PACK_ZIP) Common.zip_dir(Global.G_SCRIPTS_DIR, zip_file) model_gate.login_state_data.set_data({}) # 初始化登录状态数据 for ip_data in ip_data_list: index = ip_data_list.index(ip_data) model_gate.login_return_data.set_data( [index, 'LOGGING', '{} 登录中...'.format(ip_data[0])]) ret, err = self.login_server(ip_data, zip_file) if ret: model_gate.login_return_data.set_data([index, 'SUCCESS', None]) else: model_gate.login_return_data.set_data([index, 'FAILED', None]) break # 有失败则停止并返回 if ret: settings_handler.update_prefer_ips() TimerHandler() # 开启定时器任务 # model_gate.login_return_data.set_data( ['ALL', ret, '登录成功' if ret else err])
def parser_widget_actions(): for act in actions: if act == 'UploadFile': for ip in ips: # 本地的文件路径传给上传列表,同时修改脚本参数为文件名 _local_f = shell_params[ip][-1] prev_uploads[ip].append(_local_f) shell_params[ip][-1] = Common.basename(_local_f) else: WidgetTip.error("Not support WidgetAction: {}".format(act)) continue
def check_result(self, ssh, ip, offset): progress_cmd = "{0} get_task_progress {1}".format( self.inner_caller, self.task) print_cmd = "{0} get_task_stdout {1}".format(self.inner_caller, self.task) progress, last, retry, result = 0, 0, 1, "" timeout, consume, period = 10, 0, 0.5 while True: Common.sleep(period) try: result = self.execute_out(ssh, progress_cmd) if not result: if consume > timeout: raise Exception("Timeout for result") consume += period continue progress, status, info = result.split('|') progress = int(int(progress) * (1 - offset / 100) + offset) result = self.execute_out(ssh, print_cmd) if status == 'FAILED': raise Exception(info) self.return_exec_start_result(ip, progress, result, True) if last == progress: continue last = progress self.insert_text_info(ip, progress, info) if progress == 100: if not self.download_file(ssh, ip, info): raise Exception("Download {} failed !".format(info)) break except Exception as e: retry += 1 if retry < model_gate.settings_data.retry_times: continue if not isinstance(progress, int): progress = 2 self.return_exec_start_result(ip, progress, result, False) self.insert_text_info(ip, progress, "{}, retry:{}".format(str(e), retry), 'ERROR') break
def check_input(): if not all(input_list): WidgetTip.error('输入不可为空') return False ip, user, upwd, rpwd = input_list if not Common.is_ip(ip): WidgetTip.error('请输入正确的IP地址') return False if ip in ip_exist_list: WidgetTip.error('{} 输入重复'.format(ip)) return False ip_exist_list.append(ip) return True
def check_file(self): Global.G_PID_DIR = "{}\\{}".format(Global.G_RUN_DIR, Common.get_pid()) Common.mkdir(Global.G_RUN_DIR) Common.mkdir(Global.G_DOWNLOAD_DIR) Common.mkdir(Global.G_PID_DIR) logger.info(Global.G_TEXT_LOGO) for path in [ Global.G_RESOURCE_DIR, Global.G_DEPENDENCE_FILE, Global.G_SETTINGS_FILE, Global.G_SCRIPTS_DIR ]: if not Common.is_exists(path): model_gate.exception_data.set_data( "{} is not exist".format(path)) logger.error("{} is not exist".format(path)) return False return True
def manual(cls, params): try: matplotlib.use('TkAgg') plt.ion() # 开启interactive mode plt.close('all') ''' l = len(params) if l == 1: axes = plt.subplots(figsize=(12, 6), nrows=1, ncols=1, sharey=True, sharex=True)[1] ax_list = [axes] elif 1 < l <= 2: axes = plt.subplots(figsize=(12, 6), nrows=2, ncols=1, sharey=True, sharex=True)[1] ax_list = [axes[1], axes[0]] else: axes = plt.subplots(figsize=(12, 6), nrows=2, ncols=2, sharey=True, sharex=True)[1] ax_list = [axes[1, 0], axes[0, 0], axes[1, 1], axes[0, 1]] ''' download_dir = view_gate.query_env_define_data('G_DOWNLOAD_DIR') index = 0 for ip, res_list in params.items(): # proc, res, period = res_list proc, res = res_list file = "{}\\{}\\__FILE_DATA__\\{}.csv".format( download_dir, ip, proc) if not Common.is_file(file): raise Exception("{} 不存在\n如果是首次登录,请等待30秒再进此界面".format(file)) data = pd.read_csv(file, usecols=['Date', res], parse_dates=True, index_col=0) axes = plt.subplots(figsize=(12, 6), nrows=1, ncols=1, sharey=True, sharex=True)[1] data.plot(ax=axes, title="{}: {}".format(ip, proc), grid=True) #data.plot(ax=ax_list[index], title="{}: {}".format(ip, proc), grid=True) index += 1 plt.rcParams['font.sans-serif'] = [u'SimHei'] plt.rcParams['axes.unicode_minus'] = False plt.subplots_adjust(wspace=0.02, hspace=0.2) # 调整子图间距 # plt.savefig('aa.png', dpi=200) plt.show() except Exception as e: WidgetTip.error(str(e))
def refresh_file_data(self, args=None): logger.debug('[timer] refresh file data start...') server_dir = model_gate.settings_data.server_dir scripts = model_gate.settings_data.refresh_file['scripts'] server_download = Global.G_SERVER_DOWNLOAD % server_dir try: for ip, data in model_gate.login_state_data.get_data().items(): ssh = data['SSH'] local_download = "{}\\{}".format(Global.G_DOWNLOAD_DIR, ip) data_dir = "{}\\__FILE_DATA__".format(local_download) Common.mkdir(local_download) Common.mkdir(data_dir) # 初始运行时先把之前已经运行的进程杀死,每次都用最新代码跑 if ip not in self.is_first_run: [ SSHUtil.exec_ret(ssh, "killall {}".format(script), True) for script in scripts ] self.is_first_run[ip] = True cmd = '' for script in scripts: cmd = "{0}\n{1}/{2}".format(cmd, server_dir, script) SSHUtil.exec_ret(ssh, cmd, True) # 再压缩DOWNLOAD目录 cmd = 'cd {0} && zip refresh_file.zip *;chmod 777 *.zip'.format( server_download) SSHUtil.exec_ret(ssh, cmd, True) # 然后下载文件 SSHUtil.download_file( ssh, "{}/refresh_file.zip".format(server_download), '{}\\refresh_file.zip'.format(local_download)) # 最后解压 Common.unzip_file( '{}\\refresh_file.zip'.format(local_download), data_dir) except Exception as e: logger.error("RefreshTimer refresh_file_impl {}".format(str(e))) logger.debug('[timer] refresh file data end')
def images(self, image_data): for key, path in image_data.items(): path = "{}\\{}".format(Global.G_RESOURCE_DIR, path) if not Common.is_file(path): raise Exception("%s is not exist !" % path) self.append_photo_image((key, path))
def query_running_task_data(self, args=None): return Common.exist_suffix_file(Global.G_PID_DIR, '.lock')[1]
def close(self, data=None): Common.rm_dir(Global.G_PID_DIR)
def truncate(self, data=None): self.info('Bye...') Common.remove('{}.1'.format(self.log_path)) Common.rename(self.log_path, '{}.1'.format(self.log_path))
def insert_text_info(self, data): info, level = data color = Global.G_INFOWIN_LEVEL_COLOR[level.upper()] info = "[{0}] {1}: {2}".format(level.upper(), Common.get_time(), info) self.info_inst.insert_text(info, color)
def execute_enter(self, data): ips, script = data self.init(script, True, False) for ip in ips: Common.create_thread(func=self.exec_enter_impl, args=(ip, )) logger.info("execute_enter {} for {}".format(self.task, ip))
def update_thread(): while not is_done: self.return_exec_start_result(ip, get_progress(), '', True) Common.sleep(0.2)