예제 #1
0
    def _merge_task_status(self, task: IscoutTask):
        """合并处理子任务状态"""
        try:
            # 当前模块为 任务发送管理器,只负责 等待发送的任务及其状态管理。
            # 合并子任务状态,并将总任务状态从 等待发送更新为正在执行。
            # 只要有一个子任务发送成功,则总任务更新为发送成功
            # 若全部子任务发送失败,整个任务才算发送失败,
            # 貌似这样才能在非实时性的任务状态中没什么错

            ## 先看是否还有尚未发送的子任务,有的话先不要乱动。。
            waitforsendcount: int = self._dbmanager.get_iscoutbtask_count_by_cmdstatus(
                task._platform, task.taskid, ECommandStatus.WaitForSend)
            if waitforsendcount > 0:
                return

            ## 再看有没有发送成功的,有的话直接总任务发送成功,正在执行
            sendsucccount: int = self._dbmanager.get_iscoutbtask_count_by_cmdstatus(
                task._platform, task.taskid, ECommandStatus.Dealing)
            if sendsucccount > 0:
                task.cmdstatus = ECommandStatus.Dealing
                self._logger.info("IScoutTask all sent, taskid={}".format(
                    task.taskid))
                # 只要有一个子任务发送成功,则更新总任务为正在执行(不需要返回回馈数据)
                if not self._dbmanager.update_iscouttask_status(
                        task._platform, task.taskid, ECommandStatus.Dealing):
                    self._logger.error(
                        "Update IScoutTask cmdstatus to {} faled: taskid:{}".
                        format(ECommandStatus.Dealing.name, task.taskid))
            else:
                task.cmdstatus = ECommandStatus.Failed
                self._logger.error(
                    "IScoutTask all sent failed, taskid={} objtype={} obj={}".
                    format(task.taskid, task._objecttype, task._object))
                # 若全部子任务都已发送(不管发成功还是失败),且子任务没有发送成功的,
                # 则更新总任务为失败,并返回回馈数据
                if not self._dbmanager.update_iscouttask_status(
                        task._platform, task.taskid, ECommandStatus.Failed):
                    self._logger.error(
                        "Update IScoutTask cmdstatus to {} faled: taskid:{}".
                        format(ECommandStatus.Failed.name, task.taskid))
                # 失败,返回总任务回馈数据
                tb: IscoutTaskBack = IscoutTaskBack.create_from_task(
                    task, ECommandStatus.Failed, "任务执行失败,发送到采集端失败")
                if not OutputManagement.output(tb):
                    self._logger.error(
                        "Write IscoutTaskBack failed:\ntaskid:{}".format(
                            task.taskid))

        except Exception as ex:
            self._logger.error(
                "Merge IScoutTask status error:\nplatform:{}\ntaskid:{}\nerror:{}"
                .format(task._platform, task.taskid, ex.args))
            self._dbmanager.update_iscouttask_status(task._platform,
                                                     task.taskid,
                                                     ECommandStatus.Failed)
예제 #2
0
    def _generate_task_back_percent(self, task: IscoutTask) -> bool:
        """返回总任务百分比"""
        res: bool = False
        try:
            currpercent = math.floor(task.batchcompletecount /
                                     task.batchtotalcount * 100)

            lastprogress = task.progress * 100

            if task.batchtotalcount > 100:
                # 子任务数大于100个的,每1%返回一次
                if currpercent - lastprogress < 1:
                    res = True
            elif 50 < task.batchtotalcount <= 100:
                # 50<x<=100个子任务的,总共返回25个百分比文件,每%4返回一次
                if currpercent - lastprogress < 4:
                    res = True
            else:
                # 0<x<=50个子任务的,每%10左右返回一次
                if currpercent - lastprogress < 10:
                    res = True
            if res:
                return res

            # 最新总任务Progress更新到数据库并发送回馈数据
            task.progress = currpercent / 100
            task.cmdstatus = ECommandStatus.Progress
            if not self._dbmanager.update_iscout_task2(task):
                self._logger.error(
                    "Update IScoutTask with progress failed: taskid={} objecttype={} progress={}"
                    .format(task.taskid, task._objecttype.name, task.progress))
                return res

            taskback: IscoutTaskBack = IscoutTaskBack.create_from_task(
                task,
                ECommandStatus.Progress,
                recvmsg='{}%'.format(currpercent),
                batchcompletecount=task.batchtotalcount)

            if not OutputManagement.output(taskback):
                res = False
                self._logger.error(
                    "Output IscoutTaskBack progress failed:\ntaskid:{}\ncmdstatus:{}\nprogress:{}"
                    .format(task.taskid, task.cmdstatus.name, currpercent))
                return res

            res = True
            self._logger.info(
                "IscoutTaskBack generated [Progress {}]:\ntaskid={}".format(
                    task.progress, task.taskid))

        except Exception:
            res = False
            self._logger.error(
                "Generate IscoutTaskBack for batch complete percent error:\ntaskid:{}\nerror:{}"
                .format(task.taskid, traceback.format_exc()))
        finally:
            pass

        return res
예제 #3
0
    def _update_to_db(self, task: IscoutTask, targetclient: Client,
                      succ: bool):
        """同步任务下发状态到数据库。这里来的永远是子任务"""
        try:
            task.laststarttime = helper_time.ts_since_1970_tz()
            updatefields: dict = {}
            updatefields["PeriodNum"] = task.periodnum
            if not succ:
                # 失败,返回回馈数据
                task.lastendtime = helper_time.ts_since_1970_tz()
                updatefields["LastEndTime"] = task.lastendtime

                task.cmdstatus = ECommandStatus.Failed
                task.cmdrcvmsg = "发送任务到采集端失败"
                tb: IscoutBtaskBack = IscoutBtaskBack.create_from_task(
                    task, cmdstatus=task.cmdstatus, recvmsg=task.cmdrcvmsg)
                if not OutputManagement.output(tb):
                    self._logger.error(
                        "Write IscoutBtaskBack failed:\ntaskid:{}".format(
                            task.taskid))
                if isinstance(task.cmd, IdownCmd):
                    task.cmd.cmdstatus = ECommandStatus.Failed
                    task.cmd.cmdrcvmsg = task.cmdrcvmsg
                    cmdback: CmdFeedBack = CmdFeedBack.create_from_cmd(
                        task.cmd, task.cmd.cmdstatus, task.cmd.cmdrcvmsg)
                    if not OutputManagement.output(cmdback):
                        self._logger.error(
                            "Write IDownCmdBack failed:\nplatform:{}\ncmdid:{}"
                            .format(task._platform, task.cmd_id))
            else:
                # 成功
                task.cmdstatus = ECommandStatus.Dealing
                if isinstance(task.cmd, IdownCmd):
                    task.cmd.cmdstatus = ECommandStatus.Dealing
                # 返回 子任务开始回馈
                task.cmdstatus = ECommandStatus.Dealing
                task.cmdrcvmsg = "任务开始执行"
                if task.periodnum > 1:
                    task.cmdrcvmsg += ",周期{}".format(task.periodnum)
                tb: IscoutBtaskBack = IscoutBtaskBack.create_from_task(
                    task, cmdstatus=task.cmdstatus, recvmsg=task.cmdrcvmsg)
                if not OutputManagement.output(tb):
                    self._logger.error(
                        "Write IscoutBtaskBack failed:\ntaskid:{}".format(
                            task.taskid))
                self._logger.info(
                    "Send IScoutTask succeed [{}: {}]:\ntaskid:{}\nbatchid:{}\nperiod:{}\nclient:{}\t{}"
                    .format(
                        task._objecttype.name,
                        task._object,
                        task.taskid,
                        task.batchid,
                        task.periodnum,
                        task._clientid,
                        targetclient._statusbasic.ip,
                    ))

            with self._dbmanager.get_automic_locker(
                    EDBAutomic.ReduplicateIScoutTask):
                # 总任务batchcompletecount -1
                # 子任务isbatchcompletecountincreaced 置0
                self._dbmanager.decreace_iscouttask_batch_complete_count(
                    task._platform, task.taskid, task.batchid)
                task.batchcompletecount -= 1
                # 更新数据库当前子任务状态
                updatefields["Status"] = task.cmdstatus.value
                updatefields["LastStartTime"] = task.laststarttime
                if not self._dbmanager.update_iscoutbtask(
                        task._platform, task.taskid, task.batchid,
                        updatefields):
                    # 这里如果更新数据库状态失败了,那发送线程可能会重新发送当前子任务。
                    # 此时需要采集端支持 冥等性(任务去重,保证多次收到同一条任务只会处理一条)
                    self._logger.error(
                        "Update IScoutBatchTask cmdstatus failed:\ntaskid:{}\ncmdstatus:{}"
                        .format(task.taskid, task.cmdstatus.name))
                # 更新总任务开始时间
                if not self._dbmanager.update_iscout_task(
                        task._platform,
                        task.taskid,
                        updatefields={
                            "LastStartTime": helper_time.ts_since_1970_tz(),
                            "PeriodNum": task.periodnum,
                        },
                ):
                    self._logger.error(
                        "Update IScouttask LastStartTime failed:\ntaskid:{}\ncmdstatus:{}"
                        .format(task.taskid, task.cmdstatus.name))
                # 如果带cmd,更新cmd状态
                if isinstance(
                        task.cmd,
                        IdownCmd) and not self._dbmanager.update_cmd_status(
                            task.cmd.platform,
                            task.cmd.cmd_id,
                            targetclient._statusbasic._clientid
                            if not targetclient is None else task._clientid,
                            task.cmd.cmdstatus,
                        ):
                    self._logger.error(
                        "Update cmd cmdstatus failed:\ntaskid:{}\ncmdstatus:{}"
                        .format(task.taskid, task.cmdstatus.name))

                # 返回 总任务开始回馈
                task.cmdstatus = ECommandStatus.Dealing
                task.cmdrcvmsg = "任务开始执行,周期{}".format(task.periodnum)
                tb: IscoutTaskBack = IscoutTaskBack.create_from_task(
                    task,
                    cmdstatus=task.cmdstatus,
                    recvmsg=task.cmdrcvmsg,
                    batchcompletecount=task.batchcompletecount,
                    periodnum=task.periodnum,
                )
                if not OutputManagement.output(tb):
                    self._logger.error(
                        "Write IscoutBtaskBack failed:\ntaskid:{}".format(
                            task.taskid))
        except Exception:
            self._logger.error("Update task cmdstatus to db error: {}".format(
                traceback.format_exc()))
            self._dbmanager.update_iscouttask_status(task._platform,
                                                     task.taskid,
                                                     ECommandStatus.Failed)
            if isinstance(task.cmd, IdownCmd):
                self._dbmanager.update_cmd_status(
                    task._platform,
                    task.cmd_id,
                    task.cmd._clientid,
                    ECommandStatus.Failed,
                )