예제 #1
0
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
    })
예제 #2
0
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})
예제 #3
0
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,
        })
예제 #4
0
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"
        })
예제 #5
0
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,
    })
예제 #6
0
    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
예제 #7
0
 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
예제 #8
0
    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
예제 #9
0
def index():
    return "APP_NAME:{0} VERSION:{1} APP:API {2}"\
        .format( app.config.get("APP_NAME"),app.config.get("APP_VERSION"), DateHelper.getCurrentTime() )
예제 #10
0
    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
예제 #11
0
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"
        })
예제 #12
0
    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
예제 #13
0
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,
        })
예제 #14
0
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})