def log_error(): req = request.values page = int(req.get("p", 1)) date_from = req.get("date_from", DateHelper.getCurrentTime(fmt="%Y-%m-%d")) date_to = req.get("date_to", DateHelper.getCurrentTime(fmt="%Y-%m-%d")) query = AppErrLog.query.filter( AppErrLog.created_time.between(date_from, date_to + " 23:59:59")) page_params = { "total": query.count(), "page_size": CommonConstant.PAGE_SIZE, "page": page, "display": CommonConstant.PAGE_DISPLAY, } pages = UtilHelper.iPagination(page_params) offset = (page - 1) * CommonConstant.PAGE_SIZE limit = CommonConstant.PAGE_SIZE * page list = query.order_by(AppErrLog.id.desc())[offset:limit] sc = {'date_from': date_from, 'date_to': date_to} return UtilHelper.renderView("home/log/error.html", { "list": list, "pages": pages, "sc": sc })
def home_news(): query = UserNews.query.filter_by( uid=CurrentUserService.getUid(), status=CommonConstant.default_status_false) total = query.count() list = query.order_by(UserNews.id.desc()).all() data = [] if list: for item in list: tmp_content = "<h5 class='text-danger'>标题:%s</h5><br/>%s<br/>时间:%s" % ( item.title, item.content, item.created_time) tmp_data = { "id": item.id, "title": item.title, "content": tmp_content, "created_time": DateHelper.getFormatDate(DateHelper.str2Date( item.created_time), format="%m-%d %H:%M"), } data.append(tmp_data) content = UtilHelper.renderView("home/index/news.html", { "list": data, "total": total }) return UtilHelper.renderSucJSON({"total": total, "content": content})
def job_info(): req = request.values id = int(req['id']) if ('id' in req and req['id']) else 0 info = JobList.query.filter_by(id=id).first() if not info: return redirect(GlobalUrlService.buildHomeUrl("/job/index/index")) info = ModelHelper.model2Dict(info) server_info = JobServer.query.filter_by(id=info['server_id']).first() cate_info = JobCategory.query.filter_by(id=info['cate_id']).first() server_env_map = CommonConstant.server_env_map run_status_map = CommonConstant.run_status_map info['next_run_time'] = DateHelper.getDateOnTimestamps( info['next_run_time'], '%Y-%m-%d %H:%M') info['env_name'] = server_env_map.get(info['env_id']) info['run_status_desc'] = run_status_map.get(info['run_status']) info['job_status_desc'] = job_status_map.get(info['status']) info['server_name'] = server_info.name info['cate_name'] = cate_info.name if cate_info else '' info['run_interval_desc'] = DateHelper.formatBeautyTime( info['run_interval'] * 60) user_map = ModelHelper.getDictFilterField( User, select_field=User.id, id_list=[info['owner_uid'], info['relate_uid']]) ##获取最近5天运行记录 log_list = JobRunLog.query.filter_by(job_id=id).order_by( JobRunLog.id.desc())[0:5] log_data = [] if log_list: for item in log_list: tmp_data = ModelHelper.model2Dict(item) tmp_data['status_desc'] = CommonConstant.job_log_status_map[ tmp_data['status']] tmp_data['duration'] = "" if DateHelper.getCurrentTime(date=tmp_data['end_time'] ) == CommonConstant.DEFAULT_DATETIME: tmp_data['end_time'] = "未知" tmp_data['duration'] = time.time() - time.mktime( tmp_data['start_time'].timetuple()) else: tmp_data['duration'] = tmp_data['end_time'].timestamp( ) - tmp_data['start_time'].timestamp() tmp_data['duration'] = DateHelper.formatBeautyTime( tmp_data['duration']) log_data.append(tmp_data) return UtilHelper.renderView( "home/job/index/info.html", { "info": info, "log_list": log_data, "user_map": user_map, "job_level_map": CommonConstant.job_level_map, })
def tools_alert(): req = request.values page = int(req.get("p", 1)) date_from = req.get("date_from", DateHelper.getCurrentTime(fmt="%Y-%m-%d")) date_to = req.get("date_to", DateHelper.getCurrentTime(fmt="%Y-%m-%d")) status = int(req.get("status", CommonConstant.default_status_neg_99)) query = JobAlertList.query.filter( JobAlertList.created_time.between(date_from, date_to + " 23:59:59")) if status > CommonConstant.default_status_neg_99: query = query.filter_by(status=status) page_params = { "total": query.count(), "page_size": CommonConstant.PAGE_SIZE, "page": page, "display": CommonConstant.PAGE_DISPLAY, } pages = UtilHelper.iPagination(page_params) offset = (page - 1) * CommonConstant.PAGE_SIZE limit = CommonConstant.PAGE_SIZE * page list = query.order_by(JobAlertList.id.desc())[offset:limit] data = [] if list: job_ids = ModelHelper.getFieldList(list, "job_id") job_map = ModelHelper.getDictFilterField(JobList, select_field=JobList.id, id_list=job_ids.sort()) for item in list: tmp_data = ModelHelper.model2Dict(item) tmp_job_info = ModelHelper.model2Dict( job_map.get(tmp_data['job_id'])) tmp_data['status_desc'] = CommonConstant.common_status_map4[ tmp_data['status']] tmp_data['job_name'] = tmp_job_info['name'] data.append(tmp_data) sc = {'date_from': date_from, 'date_to': date_to, 'status': status} return UtilHelper.renderView( "home/job/tools/alert.html", { "list": data, "pages": pages, "sc": sc, "status_map": CommonConstant.common_status_map4, "current": "alert" })
def home_index(): date = DateHelper.getCurrentTime(fmt="%Y-%m-%d") job_count = JobList.query.filter_by(is_del=CommonConstant.default_status_false).count() server_count = JobServer.query.filter_by(status=CommonConstant.default_status_true).count() alert_count = JobAlertList.query.filter(JobAlertList.created_time.between(date, date + " 23:59:59")).count() cate_map = ModelHelper.getDictFilterField( JobCategory ) cat_job_map = {} cat_job_list = JobList.query.with_entities(JobList.cate_id ,func.count( JobList.id) )\ .filter_by(is_del=CommonConstant.default_status_false)\ .group_by(JobList.cate_id).all() if cat_job_list: for _item in cat_job_list: cat_job_map[ _item[0] ] = _item[1] type_job_map = {} job_type_map = CommonConstant.job_type_map type_job_list = JobList.query.with_entities(JobList.job_type, func.count(JobList.id)) \ .filter_by(is_del=CommonConstant.default_status_false) \ .group_by(JobList.job_type).all() if type_job_list: for _item in type_job_list: type_job_map[ _item[0] ] = _item[1] return UtilHelper.renderView("home/index/index.html", { "job_count": job_count, "server_count": server_count, "alert_count": alert_count, 'cate_map' : cate_map, 'cat_job_map' : cat_job_map, 'job_type_map' : job_type_map, 'type_job_map' : type_job_map, })
def getReleaseVersion(): ver = "%s" % (DateHelper.getCurrentTime("%Y%m%d%H%M%S%f")) release_path = app.config.get('RELEASE_PATH') if release_path and os.path.exists(release_path): with open(release_path, 'r') as f: ver = f.readline() return ver
def updateRunLog(log_id=0, max_mem=0, status=0): params = { "end_time": DateHelper.getCurrentTime(), "max_mem": max_mem, "status": status } JobRunLog.query.filter_by(id=log_id).update(dict(params)) db.session.commit() return True
def alertRunTimeJudge(self, job_info, job_run_start_time): #常驻Job不用判断时间 if job_info.job_type == CommonConstant.default_status_pos_2: return True job_run_total_time = int( time.time() - job_run_start_time) job_id = job_info.id alert_temp = "[运行时间异常]您的job(job_{0} {1})在{2}开始运行,预计时长{3} - {4}分钟,但是运行了{5}分钟" alert_content = "" if job_run_total_time < (job_info.threshold_down * 60 - 10 * 60): # 运行时长低于下限值,报警(阀值后面-10分钟) alert_content = alert_temp.format(job_id, job_info.name, DateHelper.getDateOnTimestamps(job_info.next_run_time,format="%Y-%m-%d %H:%M"), job_info.threshold_down, job_info.threshold_up,DateHelper.formatBeautyTime( job_run_total_time ) ) elif job_run_total_time > ( job_info.threshold_up * 60 + 15 * 60 ): alert_content = alert_temp.format(job_id, job_info.name, DateHelper.getDateOnTimestamps(job_info.next_run_time,format="%Y-%m-%d %H:%M"), job_info.threshold_down, job_info.threshold_up,DateHelper.formatBeautyTime( job_run_total_time ) ) if alert_content: JobService.saveAlertLog( job_id , alert_content) return True
def index(): return "APP_NAME:{0} VERSION:{1} APP:API {2}"\ .format( app.config.get("APP_NAME"),app.config.get("APP_VERSION"), DateHelper.getCurrentTime() )
def handleItem(self, item, host): pid_file = self.getPidPath('job_%s.pid' % item['id']) pid = 0 if self.checkPidExist(pid_file): # 文件存储的是python的进程id,找真真运行的需要使用关键词查找 pid = self.findPidByKw(item['id']) app.logger.info("%s : %s" % (pid_file, pid)) # 判断进程本身是否存在,但是由于删除pid在进程结束之后 会有延迟,所以需要临时增加删除功能 run_flag = os.path.exists('/proc/%s' % pid) if pid > 0 else False ''' 1=>该结束未结束 2=>该运行未运行 3=>执行命令异常 4=>Job平台标识正在运行,但是在机器上没有发现job进程 5=>Job平台标识没有运行,但是在机器上发现了job进程 6=>运行时间过短 ''' alert_content = '' if item['run_status'] == CommonConstant.default_status_true and run_flag: # 数据库中标记没有运行,但是在机器上发现了进程 alert_content = "您的job(job_{0} {1})运行状态异常,可能原因:{2}"\ .format(item['id'], item['name'], "Job平台标识没有运行,但是在机器%s上发现了job进程" % host ) os.system('ls -al /proc/%s' % pid) os.system('ps -ef |grep tmp_job_%s' % item['id']) elif item[ 'run_status'] == CommonConstant.default_status_pos_2 and not run_flag: # 重新检查job的状态,避免运行时间较短的job误报警 time.sleep(2) job_info = JobList.query.filter_by(id=item['id']).first() if job_info.run_status == CommonConstant.default_status_pos_2: alert_content = "您的job(job_{0} {1})运行状态异常[Job平台会自动修复],可能原因:{2}" \ .format(item['id'], item['name'], "Job平台标识正在运行,但是在机器%s上没有发现job进程" % host ) elif item['run_status'] == CommonConstant.default_status_true and item[ 'next_run_time'] < self.current_time: # 该运行未运行 alert_content = "您的JOB(job_{0} {1})应该在{2}运行,但是现在还没有运行" \ .format(item['id'], item['name'], DateHelper.getDateOnTimestamps(item['next_run_time'], '%Y-%m-%d %H:%M')) elif item['run_status'] == CommonConstant.default_status_pos_2 and item[ 'job_type'] != CommonConstant.default_status_pos_2: # 常驻Job不判断时间 # 对于固定运行时长,如果运行时间大于原计划时间的120%就报警;动态运行时长,超出上限就报警 run_duration_time = int(time.time() - item['next_run_time']) # 使用动态预估运行时间确定是否报警,加了15分钟的缓冲时间 if run_duration_time > (item['threshold_up'] + 15) * 60: # 运行时长高于上限值,报警 run_duration_min = round(run_duration_time / 60, 1) alert_content = "[运行超时]您的job(job_{0} {1})在{2}开始运行,预计时长{3}-{4}分钟,但是目前仍然在运行(运行了{5}分钟)"\ .format(item['id'], item['name'], DateHelper.getDateOnTimestamps(item['next_run_time'], '%Y-%m-%d %H:%M'), item['threshold_down'], item['threshold_up'],run_duration_min ) # 自动修复 if 'Job平台标识正在运行' in alert_content and 'Job平台会自动修复' in alert_content: try: ##下一分钟 # next_date = datetime.datetime.now() + datetime.timedelta(minutes=1) # next_date = next_date.replace(second=0) # next_run_time = int(time.mktime(next_date.timetuple())) # params = { # "next_run_time": next_run_time, # "run_status": CommonConstant.default_status_true, # "status": CommonConstant.default_status_true # } # JobList.query.filter_by(id=item['id']).update(dict(params)) # db.session.commit() app.logger.info("您的job(job_{0} {1}) 自动修复成功~~".format( item['id'], item['name'])) except: app.logger.info("您的job(job_{0} {1}) 自动修复失败,错误原因:{2}~~".format( item['id'], item['name'], self.getErrMsg())) ##存储到报警日志表 if alert_content: app.logger.info(alert_content) JobService.saveAlertLog(item['id'], alert_content) return True
def tools_log(): status_map = CommonConstant.job_log_status_map req = request.values page = int(req.get("p", 1)) date_from = req.get("date_from", DateHelper.getCurrentTime(fmt="%Y-%m-%d")) date_to = req.get("date_to", DateHelper.getCurrentTime(fmt="%Y-%m-%d")) status = int(req.get("status", CommonConstant.default_status_neg_99)) job_id = int(req.get("job_id", CommonConstant.default_status_false)) query = JobRunLog.query.filter( JobRunLog.created_time.between(date_from, date_to + " 23:59:59")) if job_id: query = query.filter_by(job_id=job_id) if status > CommonConstant.default_status_neg_99: query = query.filter_by(status=status) page_params = { "total": query.count(), "page_size": CommonConstant.PAGE_SIZE, "page": page, "display": CommonConstant.PAGE_DISPLAY, } pages = UtilHelper.iPagination(page_params) offset = (page - 1) * CommonConstant.PAGE_SIZE limit = CommonConstant.PAGE_SIZE * page list = query.order_by(JobRunLog.id.desc())[offset:limit] data = [] if list: job_ids = ModelHelper.getFieldList(list, "job_id") job_map = ModelHelper.getDictFilterField(JobList, select_field=JobList.id, id_list=job_ids.sort()) for item in list: tmp_data = ModelHelper.model2Dict(item) tmp_job_info = ModelHelper.model2Dict( job_map.get(tmp_data['job_id'])) tmp_data['status_desc'] = status_map[tmp_data['status']] tmp_data['job_name'] = tmp_job_info['name'] tmp_data['duration'] = "" if DateHelper.getCurrentTime(date=tmp_data['end_time'] ) == CommonConstant.DEFAULT_DATETIME: tmp_data['end_time'] = "未知" tmp_data['duration'] = time.time() - time.mktime( tmp_data['start_time'].timetuple()) else: tmp_data['duration'] = (tmp_data['end_time'].timestamp() - tmp_data['start_time'].timestamp()) tmp_data['duration'] = DateHelper.formatBeautyTime( tmp_data['duration']) data.append(tmp_data) sc = { 'date_from': date_from, 'date_to': date_to, 'status': status, 'job_id': job_id } return UtilHelper.renderView( "home/job/tools/log.html", { "list": data, "pages": pages, "sc": sc, "status_map": status_map, "current": "log" })
def run(self, params): pid_path = self.getPidPath('dispatch.pid') if self.checkPidExist(pid_path): app.logger.info("[core] dispatch is running") return False pid = str(os.getpid()) if not self.setPidFile(pid_path, pid): err_msg = self.getErrMsg() app.logger.info("Cann't get a lock file,err msg : " + err_msg) return False params = self.getEnvFile() server_id = params['id'] host = params['name'] list = JobList.query.filter_by( server_id = server_id,status = CommonConstant.default_status_true, run_status = CommonConstant.default_status_true,is_del = CommonConstant.default_status_false ).all() if not list: app.logger.info("没有数据需要调度~~") return True for t in list: ##调度时间是否到了,应该加入到SQL查询中查询 if t.next_run_time >= time.time(): app.logger.info( "job_id:%s,运行时间未到"%( t.id ) ) continue # 启子进程中运行 app.logger.info( "get a task: job_id:%s,运行时间:%s" % (t.id,DateHelper.getCurrentTime()) ) ''' 子进程复制一份父进程内存给自己,两个进程之间的执行是相互独立的,其执行顺序可以是不确定的、随机的、不可预测的 多进程(os.fork())下,子进程会继承父进程的连接,所以会有问题.先销毁已有的engine,确保父进程没有数据库连接 相关错误:Mysql server has gone away ''' self.closePoolDB() pid = os.fork() if pid == 0: #子进程,这里是一个独立进程(在复制出来的那一刻 所有变量都会共享到子进程),所以写代码 就要感觉在一个独立方法中 self.closePoolDB() job_id = t.id job_pid_file = self.getPidPath( 'job_%s.pid' % job_id ) if self.checkPidExist(job_pid_file): app.logger.info("job_id:%s is running on %s" % (job_id, host)) return 0 ## 建立具体job的pid 文件,防止重复运行,这个进程id其实记录的是不对的,应该使用下面的 tmp_pid = str(os.getpid()) if not self.setPidFile(job_pid_file, tmp_pid): app.logger.info("job_id:%s 不能建立pid,path:%s,msg:%s" % (job_id, job_pid_file, self.getErrMsg())) return True app.logger.info("job_id:%s 建立pid,子进程pid:%s" % (job_id, tmp_pid)) ## 更新job为运行中 try: tmp_affect_rows = JobList.query.filter_by( id = job_id,run_status = CommonConstant.default_status_true )\ .update( dict( run_status = CommonConstant.default_status_pos_2 ) ) db.session.commit() if tmp_affect_rows < 1: app.logger.info("job_id:%s不能得到lock,任务已经运行中" % job_id) return False except: app.logger.info( "job_id:%s不能得到锁状态,err:%s" % (job_id,str( sys.exc_info() ) ) ) ##写入一条调度日志 tmp_log_id = 0 try: tmp_log_params = { "job_id":job_id, "server_id":server_id, "server_name":host, "status": CommonConstant.default_status_neg_1, "start_time":DateHelper.getCurrentTime() } tmp_log_id = JobService.addRunLog( tmp_log_params ) except : pass self.closePoolDB() tmp_job_run_start_time = time.time() # job开始运行的时间 # t.command无法获取job内部输出的内容,我们需要按行读取或者按buffer读取的 # status = os.system(t.command)>>8#status, output = commands.getstatusoutput(t.command) # 可以加 bufsize = -1 表示使用系统默认缓存 # 命令前面加一下前缀,方便搜索关键词查找 # 创建子进程后子进程不结束 https://bbs.csdn.net/topics/390596479?_=1515055076 tmp_command = t.command tmp_command = "tmp_job_%s='%s' && %s"%( job_id,DateHelper.getCurrentTime(),tmp_command) #如果想要达到2>&1 可以设置为stdout=subprocess.PIPE,stderr=subprocess.STDOUT sp = subprocess.Popen(tmp_command, bufsize = -1, shell = True, close_fds=True, stdout=subprocess.PIPE,stderr=subprocess.STDOUT) tmp_run_job_pid = sp.pid #上面存的关于job的进程id 是不对的,这里在覆盖一次 self.coverPidFile(job_pid_file,tmp_run_job_pid) ''' 如果是包裹了一层runshell的需要找到进程的子进程pid,然后在查看内存 tmp_pid 是目前子进程的进程号 tmp_run_job_pid 是目前 subprocess启动的进程好 真真运行的进程号,需要通过关键词查询,所以在命令前面加了特别东西 ''' app.logger.info( "job_id:%s 启动Job脚本,pid:%s" % (job_id, tmp_run_job_pid)) ##统计内存占用量 tmp_max_job_used_mem = tmp_job_used_mem = UtilHelper.getUsedMemory( tmp_run_job_pid ) app.logger.info("job_id:%s 日志start-------" %job_id ) ''' sp.poll() 返回值 0 正常结束 1 sleep 2 子进程不存在 -15 kill None 在运行 判断进程状态 ''' while sp.poll() is None: ##统计内存占用量 tmp_job_used_mem = UtilHelper.getUsedMemory( tmp_run_job_pid ) if tmp_job_used_mem > tmp_max_job_used_mem: tmp_max_job_used_mem = tmp_job_used_mem tmp_line_output = sp.stdout.readline() tmp_line_output = tmp_line_output.strip() #返回的是bytes tmp_line_output = str(tmp_line_output, encoding="utf8") tmp_lines = tmp_line_output.split("\n") for tmp_line in tmp_lines: app.logger.info("job_id:%s %s" % (job_id, tmp_line) ) app.logger.info("job_id:%s 日志end-------" % job_id) ##统计内存占用量 tmp_job_used_mem = UtilHelper.getUsedMemory( tmp_run_job_pid ) if tmp_job_used_mem > tmp_max_job_used_mem: tmp_max_job_used_mem = tmp_job_used_mem app.logger.info("job_id:%s PID:%s, 使用内存(end) %s" % (job_id, tmp_run_job_pid, tmp_job_used_mem)) app.logger.info("job_id:%s PID:%s, 最大使用内存 %s" % (job_id, tmp_run_job_pid, tmp_max_job_used_mem)) app.logger.info("job_id:%s 更新消耗内存完毕" % (job_id)) # 将标准输出关闭了 sp.stdout.close() tmp_status = sp.wait() app.logger.info("job_id:%s status_code:%s,%s" % (t.id, str(tmp_status),tmp_command )) #和下面分开就是怕报警影响正常处理 try: #杀死常驻job也会发生 MySQL server has gone away,只要运行的时间太长就会出问题了 self.closePoolDB() #相关报警判断 self.alertStatusJudge(t, tmp_status) self.alertRunTimeJudge(t, tmp_job_run_start_time) except: app.logger.info( self.getErrMsg() ) # 更新状态和下一次运行时间 try: self.closePoolDB() ##提前将文件释放下,因为当服务器状态非常繁忙的时候,进程比较缓慢,会导致状态已经更新但是pid文件没有删除 self.atexit_removepid(job_pid_file) if int( t.job_type ) == CommonConstant.default_status_pos_3 :#一次性job JobList.query.filter_by(id=job_id).update( dict( run_status = CommonConstant.default_status_false,status = CommonConstant.default_status_false) ) db.session.commit() else: if int( t.job_type ) == CommonConstant.default_status_pos_2: # 常驻Job,他停止之后下一分钟直接运行 tmp_next_time = datetime.datetime.now() + datetime.timedelta(minutes=1) tmp_next_time = tmp_next_time.replace(second=0) tmp_next_time = int( time.mktime(tmp_next_time.timetuple() ) ) else: tmp_next_time = t.next_run_time + int( math.ceil((time.time() - t.next_run_time) / (t.run_interval * 60)) * t.run_interval * 60) JobList.query.filter_by(id=job_id).update( dict( run_status = CommonConstant.default_status_true ,next_run_time = tmp_next_time ) ) db.session.commit() ##更新对应日志的log,担心出错影响其他 JobService.updateRunLog(tmp_log_id, tmp_max_job_used_mem, (tmp_status == 0)) except: app.logger.info( self.getErrMsg() ) # 完成 self.closePoolDB() app.logger.info('job_id:%s 运行完成时间为:%s,子进程结束~~' % (job_id, DateHelper.getCurrentTime() )) return 0 elif pid > 0: # 父进程 ''' status是一个传出参数。 waitpid的pid参数选择: < -1 回收指定进程组内的任意子进程 = -1 回收任意子进程,等待所有的子进程终止 = 0 回收和当前调用waitpid一个组的所有子进程 > 0 回收指定ID的子进程 ''' app.logger.info("父进程 job_id:%s pid:%s" % (t.id, pid)) #os.waitpid( pid , os.WNOHANG) os.waitpid(-1, os.WNOHANG) app.logger.info("job_id:%s 父进程结束~~" % t.id) else: app.logger.info("job_id:%s,不能建立调度器" % (t.id)) app.logger.info("it's over~~") return True
def job_index(): req = request.values cate_id = int(req.get("cate_id", CommonConstant.default_status_false)) owner_uid = int(req.get("owner_uid", CurrentUserService.getUid())) env_id = int(req.get("env_id", CommonConstant.default_status_false)) server_id = int(req.get("server_id", CommonConstant.default_status_false)) status = int(req.get("status", CommonConstant.default_status_neg_99)) display_status = int( req.get("display_status", CommonConstant.default_status_neg_99)) job_type = int(req.get("job_type", CommonConstant.default_status_neg_99)) job_level = int(req.get("job_level", CommonConstant.default_status_neg_99)) kw = req.get("kw", "").strip() page = int(req.get("p", 1)) query = JobList.query if RBACService.checkDataPrivilege("all"): pass else: query = query.filter_by(owner_uid=CurrentUserService.getUid()) if cate_id: query = query.filter_by(cate_id=cate_id) if env_id: query = query.filter_by(env_id=env_id) if owner_uid: query = query.filter_by(owner_uid=owner_uid) if server_id: query = query.filter_by(server_id=server_id) if status > CommonConstant.default_status_neg_99: query = query.filter_by(status=status) if display_status > CommonConstant.default_status_neg_99: query = query.filter_by(is_del=display_status) if job_type > CommonConstant.default_status_neg_99: query = query.filter_by(job_type=job_type) if job_level > CommonConstant.default_status_neg_99: query = query.filter_by(job_level=job_level) if kw: if kw.isdigit(): query = query.filter_by(id=int(kw)) else: query = query.filter( or_(JobList.name.ilike('%{}%'.format(kw)), JobList.command.ilike('%{}%'.format(kw)))) page_params = { "total": query.count(), "page_size": CommonConstant.PAGE_SIZE, "page": page, "display": CommonConstant.PAGE_DISPLAY } pages = UtilHelper.iPagination(page_params) offset = (page - 1) * CommonConstant.PAGE_SIZE limit = CommonConstant.PAGE_SIZE * page list = query.order_by(JobList.id.desc())[offset:limit] data = [] server_map = ModelHelper.getDictFilterField(JobServer) cate_map = ModelHelper.getDictFilterField(JobCategory) staff_map = ModelHelper.getDictFilterField(User) server_env_map = CommonConstant.server_env_map run_status_map = CommonConstant.run_status_map job_type_map = CommonConstant.job_type_map job_level_map = CommonConstant.job_level_map if list: for item in list: tmp_data = ModelHelper.model2Dict(item) tmp_server_info = ModelHelper.model2Dict( server_map.get(tmp_data['server_id'])) tmp_cate_info = ModelHelper.model2Dict( cate_map.get(tmp_data['cate_id'])) tmp_owner_staff_info = ModelHelper.model2Dict( staff_map.get(tmp_data['owner_uid'])) tmp_relate_staff_info = ModelHelper.model2Dict( staff_map.get(tmp_data['relate_uid'])) tmp_data['next_run_time'] = DateHelper.getDateOnTimestamps( tmp_data['next_run_time'], '%Y-%m-%d %H:%M') tmp_data['env_name'] = server_env_map.get(tmp_data['env_id']) tmp_data['run_status_desc'] = run_status_map.get( tmp_data['run_status']) tmp_data['job_status_desc'] = job_status_map.get( tmp_data['status']) tmp_data['server_name'] = tmp_server_info.get("name") tmp_data['cate_name'] = tmp_cate_info.get("name", '') tmp_data['owner_name'] = tmp_owner_staff_info.get("name", '') tmp_data['relate_name'] = tmp_relate_staff_info.get("name", '') tmp_data['run_interval_desc'] = DateHelper.formatBeautyTime( tmp_data['run_interval'] * 60) data.append(tmp_data) sc = { 'kw': kw, 'cate_id': cate_id, 'owner_uid': owner_uid, 'env_id': env_id, 'server_id': server_id, 'status': status, 'display_status': display_status, 'job_type': job_type, 'job_level': job_level, } set_flag = RBACService.checkPageRelatePrivilege("set") ops_flag = RBACService.checkPageRelatePrivilege("ops") return UtilHelper.renderView( "home/job/index/index.html", { "list": data, "pages": pages, "job_status_map": job_status_map, "server_env_map": server_env_map, "server_map": server_map, "staff_map": staff_map, "cate_map": cate_map, "display_status_map": display_status_map, "job_type_map": job_type_map, "job_level_map": job_level_map, "sc": sc, "set_flag": set_flag, "ops_flag": ops_flag, })
def job_set(): if UtilHelper.isGet(): req = request.values id = int(req['id']) if ('id' in req and req['id']) else 0 act = req.get("act", "").strip() info = {'owner_uid': CurrentUserService.getUid()} if id > 0: info = JobList.query.filter_by(id=id).first() info = ModelHelper.model2Dict(info) info['next_run_time'] = DateHelper.getDateOnTimestamps( info['next_run_time'], '%Y-%m-%d %H:%M') if act == "copy": info['id'] = 0 info['status'] = 0 info['name'] = "【复制】" + info['name'] server_list = JobServer.query.order_by(JobServer.id.desc()).all() user_list = User.query.order_by(User.id.desc()).all() cate_list = JobCategory.query.order_by(JobCategory.id.desc()).all() return UtilHelper.renderView( "home/job/index/set.html", { "info": info, "server_list": server_list, "user_list": user_list, "cate_list": cate_list, "server_env_map": CommonConstant.server_env_map, "job_type_map": CommonConstant.job_type_map, "job_status_map": job_status_map, "job_level_map": CommonConstant.job_level_map, }) req = request.values id = int(req['id']) if ('id' in req and req['id']) else 0 cate_id = int(req.get("cate_id", "0").strip()) name = req.get("name", "").strip() env_id = int(req.get("env_id", "0").strip()) server_id = int(req.get("server_id", "0").strip()) owner_uid = int(req.get("owner_uid", "0").strip()) relate_uid = int(req.get("relate_uid", "0").strip()) command = req.get("command", "").strip() command_kill = req.get("command_kill", "").strip() job_type = int(req.get("job_type", "0").strip()) job_level = int(req.get("job_level", "1").strip()) status = int(req.get("status", "0").strip()) next_run_time = req.get("next_run_time", "").strip() run_interval = int(req.get("run_interval", "0").strip()) threshold_down = int(req.get("threshold_down", "0").strip()) threshold_up = int(req.get("threshold_up", "0").strip()) note = req.get("note", "").strip() if cate_id < 1: return UtilHelper.renderErrJSON("请选择所属分类~~") if not ValidateHelper.validLength(name, 1, 15): return UtilHelper.renderErrJSON("请输入符合规范的名称~~") if env_id < 1: return UtilHelper.renderErrJSON("请选择运行环境~~") if server_id < 1: return UtilHelper.renderErrJSON("请选择运行服务器~~") if owner_uid < 1: return UtilHelper.renderErrJSON("请选择Job负责人~~") if relate_uid < 1: return UtilHelper.renderErrJSON("请选择Job相关人~~") if not ValidateHelper.validLength(command, 5): return UtilHelper.renderErrJSON("请输入Job命令~~") if job_type < 1: return UtilHelper.renderErrJSON("请选择Job类型~~") if not ValidateHelper.validDate(next_run_time, r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$'): return UtilHelper.renderErrJSON("请选择调度时间~~") if job_type != CommonConstant.default_status_pos_2: if run_interval < 1: return UtilHelper.renderErrJSON("请输入运行间隔~~") if threshold_down < 0: return UtilHelper.renderErrJSON("请输入预估最短运行时长~~") if threshold_up < 1: return UtilHelper.renderErrJSON("请输入预估最长运行时长~~") else: run_interval = threshold_down = threshold_up = 0 info = JobList.query.filter_by(id=id).first() if info: model_job = info ##正在运行的Job不能编辑运行时间 if info.run_status == CommonConstant.default_status_pos_2: if info.command != command: return UtilHelper.renderErrJSON("正在运行的Job不能修改运行命令~~") if info.job_type != job_type: return UtilHelper.renderErrJSON("正在运行的Job不能修改类型~~") if info.status != status: return UtilHelper.renderErrJSON("正在运行的Job不能修改调度状态~~") if info.next_run_time != DateHelper.getTimestamps(next_run_time + ":00"): return UtilHelper.renderErrJSON("正在运行的Job不能修改调度时间~~") else: model_job = JobList() ##只有需要调度的才需要判断时间 if model_job.run_status != CommonConstant.default_status_pos_2 and status \ and DateHelper.getTimestamps(next_run_time + ":00") < time.time(): return UtilHelper.renderErrJSON("调度时间不能小于当前时间~~") model_job.name = name model_job.env_id = env_id model_job.server_id = server_id model_job.owner_uid = owner_uid model_job.relate_uid = relate_uid model_job.job_type = job_type model_job.job_level = job_level model_job.cate_id = cate_id model_job.command = command model_job.command_kill = command_kill model_job.next_run_time = DateHelper.getTimestamps(next_run_time + ":00") model_job.run_interval = run_interval model_job.threshold_up = threshold_up model_job.threshold_down = threshold_down model_job.note = note model_job.status = status if status and (not info or not info.run_status): model_job.run_status = CommonConstant.default_status_true db.session.add(model_job) db.session.commit() return UtilHelper.renderSucJSON({"id": model_job.id})