Exemple #1
0
def fetch_tpl_list(request):
    """
    查询巡检模板列表
    """
    os_id = request.GET.get('os_id')
    if os_id:
        data = [
            tpl.to_dict() for tpl in Tpl.objects.filter(
                author='system', tpl_os=os_id, is_deleted=0).order_by(
                    "-created_time")
        ]
        data.extend([
            tpl.to_dict()
            for tpl in Tpl.objects.filter(tpl_os=os_id, is_deleted=0).exclude(
                author='system').order_by("-created_time")
        ])
        return Request.succFcun(msg="", data=data)
    else:
        data = [
            tpl.to_dict() for tpl in Tpl.objects.filter(
                author='system', is_deleted=0).order_by("-created_time")
        ]
        data.extend([
            tpl.to_dict() for tpl in Tpl.objects.filter(is_deleted=0).exclude(
                author='system').order_by("-created_time")
        ])
        return Request.succFcun(msg="", data=data)
    def post(self, request):
        req = get_post_params(request)
        os_name = req.get("os_name", "")
        os_id = req.get("os_id", 0)
        is_deleted = int(req.get("is_deleted", 0))

        if not os_name and is_deleted == "":
            return Request.errorFcun("参数异常", data=[])

        data = {"os_name": os_name, "is_deleted": is_deleted}

        # 如果id 存在更新
        if os_id:
            os_obj = CheckSystemOs.objects.get(pk=os_id)
            os_obj.__dict__.update(**data)
            os_obj.save()

            if os_obj and is_deleted == 1:
                result_message = "删除成功"
            else:
                result_message = "修改成功"
        else:
            os_obj, created = CheckSystemOs.objects.get_or_create(
                defaults=data, os_name=os_name)
            if created:
                result_message = "创建成功"
            else:
                result_message = "数据已存在"

        if os_obj:
            return Request.succFcun(result_message, data=os_obj.to_dict())
        else:
            return Request.errorFcun("创建/更新失败", data={})
Exemple #3
0
def operation_log(request):
    current = request.GET.get("current", 1)
    limit = request.GET.get("limit", 10)
    start_time = request.GET.get("start_time", "1970-01-01")
    end_time = request.GET.get("end_time", time.strftime("%Y-%m-%d", time.localtime()))

    usernames = request.GET.get("operator[]", '')

    start_time = start_time + " 00:00:00"
    end_time = end_time + " 23:59:59"
    kwargs = {
        'operation_module': request.GET.get("operation_module", ""),
        'request_method': request.GET.get("request_method", ""),
        'request_time__range': [start_time, end_time]
    }
    if usernames:
        kwargs['username__in'] = usernames.split(",")

    # 删除空值项
    for key_str in list(kwargs.keys()):
        if not kwargs[key_str]:
            kwargs.pop(key_str)

    logs = CheckSystemOperationLog.objects.filter(**kwargs).order_by("-created_time")

    paginator = Paginator(logs, int(limit))
    data = [log.to_dict() for log in paginator.page(int(current))]
    return Request.succFcun('', data={"count": paginator.count, "data": data})
Exemple #4
0
    def post(self, request):
        req = req_body_to_json(request)
        tpl_name = req.get("tpl_name", '')
        tpl_os = req.get("tpl_os", '')
        description = req.get("description", '')
        quotas = req.get("quotas", [])

        if not all([tpl_name, tpl_os, len(quotas)]):
            return Request.errorFcun("参数异常", data=[])

        tpl_obj = Tpl.objects.filter(tpl_name=tpl_name, is_deleted=0).first()
        if tpl_obj:
            return Request.errorFcun(msg="添加失败 名称重复", data=[])

        tpl = Tpl(tpl_name=tpl_name,
                  tpl_os=tpl_os,
                  description=description,
                  author=request.user.username)
        # 批量插入
        if tpl:
            try:
                # 下面的代码在一个事务中执行,一但出现异常,整个with函数内部的数据库操作都会回滚
                with transaction.atomic():
                    tpl.save()

                    # 准备批量插入数据
                    tpl_quota_list_to_insert = list()
                    for quota in quotas:
                        tpl_quota_list_to_insert.append(
                            CheckSystemTplQuta(tpl_id=tpl.id,
                                               quota_id=quota['id'],
                                               quota_threshold=str(
                                                   quota['quota_threshold'])))
                    CheckSystemTplQuta.objects.bulk_create(
                        tpl_quota_list_to_insert)

                    field_names = Log.get_model_field(Tpl)
                    field_names['quotas'] = "巡检指标"
                    req['author'] = request.user.username
                    req['tpl_os'] = CheckSystemOs.objects.get(
                        pk=req['tpl_os']).os_name
                    req['quotas'] = tpl_quotas(quotas)
                    Log.operation_log(request,
                                      table_name=Tpl._meta.verbose_name,
                                      update_fields=req,
                                      operation_module_name="模板管理",
                                      field_names=field_names)

                    data = req_body_to_json(request)
                    data['tpl_id'] = tpl.id
            except:
                logger.error(
                    f"新增模板失败  接口名称({request.path}) 请求参数({req_body_to_json(request)})"
                )

            return Request.succFcun(msg="添加成功", data=data)
        else:
            return Request.errorFcun(msg="添加失败", data=[])
Exemple #5
0
    def delete(self, request):
        tpl_id = request.GET.get('tpl_id')
        if not tpl_id:
            return Request.errorFcun("参数异常", data=[])

        # 判断tpl_id是否存在
        tpl_obj = Tpl.objects.filter(id=tpl_id).first()

        if not tpl_obj:
            return Request.errorFcun("模板ID不存在", data=[])

        if tpl_obj.is_deleted:
            return Request.succFcun("该模板已删除", data=[])
        else:
            # 备份对象用于记录日志
            old_model_obj = copy.deepcopy(tpl_obj)

            try:
                # 下面的代码在一个事务中执行,一但出现异常,整个with函数内部的数据库操作都会回滚
                with transaction.atomic():
                    # 更改删除状态为1
                    tpl_obj.is_deleted = 1
                    tpl_obj.save()

                    field_names = Log.get_model_field(Tpl)
                    field_names['quotas'] = "巡检指标"
                    Log.operation_log(request,
                                      Tpl._meta.verbose_name,
                                      old_model_obj,
                                      update_fields={},
                                      operation_module_name="模板管理",
                                      field_names=field_names)

                    # 根据模板iD 查询模板关联指标中间表
                    tpl_quota_list = CheckSystemTplQuta.objects.filter(
                        tpl_id=tpl_obj.id).all()
                    for tpl_quota in tpl_quota_list:
                        tpl_quota.is_deleted = 1
                    CheckSystemTplQuta.objects.bulk_update(
                        tpl_quota_list, fields=['is_deleted'])
            except:
                logger.error(
                    f"删除模板失败  接口名称({request.path}) 请求参数({req_body_to_json(request)})"
                )
            return Request.succFcun("删除成功", data=[])
Exemple #6
0
def fetch_user_list(request):
    client = get_client_by_request(request)
    req = {"no_page": True}
    result = client.usermanage.list_users(req)
    data = result.get("data", [])
    if isinstance(data, list):
        return Request.succFcun(data=data)
    else:
        return Request.errorFcun()
Exemple #7
0
    def delete(self, request):
        quota_id = request.GET.get('quota_id')
        if not quota_id:
            return Request.errorFcun("参数异常", data=[])

        # 判断是否存在
        quota_obj = Quota.objects.filter(id=quota_id)
        if not quota_obj.exists():
            return Request.errorFcun("指标不存在", data=[])

        # 判断是否存在模板关联关系
        tpl_quota = CheckSystemTplQuta.objects.filter(quota_id=quota_id,
                                                      is_deleted=0)
        if tpl_quota.exists():
            return Request.succFcun("删除失败,与模板存在关联关系", data=[])

        quota = quota_obj.first()

        if quota.is_deleted:
            return Request.succFcun("该指标已删除", data=[])
        else:
            # 备份对象用于记录日志
            old_model_obj = copy.deepcopy(quota)
            try:
                # 下面的代码在一个事务中执行,一但出现异常,整个with函数内部的数据库操作都会回滚
                with transaction.atomic():
                    # 更改删除状态为1
                    quota.is_deleted = 1
                    quota.save()

                    field_names = Log.get_model_field(Quota)
                    Log.operation_log(request,
                                      Quota._meta.verbose_name,
                                      old_model_obj,
                                      update_fields={},
                                      operation_module_name="自定义巡检",
                                      field_names=field_names)
            except:
                logger.error(
                    f"删除自定义巡检失败  接口名称({request.path}) 请求参数({dict(request.GET)})"
                )
            return Request.succFcun("删除成功", data=[])
Exemple #8
0
def fetch_os_quota(request):
    """
    查询符合系统的指标
    """
    os_id = request.GET.get("os_id", 0)
    if not os_id:
        return Request.errorFcun(msg="参数错误")

    # 查询指标 系统id,通用id
    quotas = Quota.objects.filter(quota_os__in=[os_id, 99]).all()

    return Request.succFcun(data=quota_class(quotas))
Exemple #9
0
    def post(self, request):
        req = req_body_to_json(request)
        quota_name = req.get("quota_name", "")
        quota_os = req.get("quota_os", 0)
        script_type = req.get("script_type", "")
        script_content = req.get("script_content", "")

        quota_handler = req.get("quota_handler", "cmp_show")
        quota_threshold = req.get("quota_threshold", "")
        username = req.get("username", "")

        if not all(
            [quota_name, username, quota_os, script_type, script_content]):
            return Request.errorFcun("参数异常", data=[])

        quota_obj = Quota.objects.filter(quota_name=quota_name,
                                         is_deleted=0).first()
        if quota_obj:
            return Request.errorFcun(msg="添加失败 名称重复", data=[])

        quota = Quota(
            quota_name=quota_name,
            quota_os=quota_os,
            script_type=script_type,
            script_content=script_content,
            quota_handler=quota_handler,
            quota_threshold=quota_threshold,
            author=username,
            quota_class=18,
        )
        if quota:
            try:
                # 下面的代码在一个事务中执行,一但出现异常,整个with函数内部的数据库操作都会回滚
                with transaction.atomic():
                    quota.save()
                    field_names = Log.get_model_field(Quota)
                    req['author'] = username
                    req['quota_os'] = CheckSystemOs.objects.get(
                        pk=quota_os).os_name
                    req['quota_class'] = "自定义巡检"
                    Log.operation_log(request,
                                      table_name=Quota._meta.verbose_name,
                                      update_fields=req,
                                      operation_module_name="自定义巡检",
                                      field_names=field_names)
            except:
                logger.error(
                    f"新增自定义巡检失败  接口名称({request.path}) 请求参数({req_body_to_json(request)})"
                )
            return Request.succFcun(msg="添加成功", data=[])
        else:
            return Request.errorFcun(msg="添加失败", data=[])
Exemple #10
0
def login_username(request):
    """
    @request
    获取登录用户名
    """
    sys_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    username = request.user.username

    return Request.succFcun("hello world",
                            data={
                                "user": username,
                                "time": sys_time
                            })
Exemple #11
0
    def put(self, request):
        req = req_body_to_json(request)
        quota_id = req.get("quota_id", 0)
        quota_name = req.get("quota_name", "")
        quota_os = req.get("quota_os", 0)
        script_type = req.get("script_type", "")
        script_content = req.get("script_content", "")
        quota_handler = req.get("quota_handler", "cmp_show")
        quota_threshold = req.get("quota_threshold", "")

        if not all([
                quota_id, quota_name, quota_os, script_type, script_content,
                quota_handler
        ]):
            return Request.errorFcun("参数异常", data=[])

        # 如果设置了对比方式 但未设置值
        if quota_handler != "cmp_show" and not quota_threshold:
            return Request.errorFcun("请设置阈值", data=[])

        # 判断是否存在
        quota_obj = Quota.objects.filter(id=quota_id)
        if quota_obj.exists():
            quota = Quota.objects.get(pk=quota_id)
            try:
                # 下面的代码在一个事务中执行,一但出现异常,整个with函数内部的数据库操作都会回滚
                with transaction.atomic():
                    req.pop("quota_id")
                    Quota.objects.filter(id=quota_id).update(**req)

                    field_names = Log.get_model_field(Quota)
                    req['quota_threshold'] = quota.quota_threshold
                    req['author'] = quota.author
                    req['quota_os'] = CheckSystemOs.objects.get(
                        pk=quota.quota_os).os_name
                    req['quota_class'] = CheckSystemClass.objects.get(
                        pk=quota.quota_class).class_name

                    Log.operation_log(request,
                                      Quota._meta.verbose_name,
                                      quota,
                                      update_fields=req,
                                      operation_module_name="自定义巡检",
                                      field_names=field_names)
            except:
                logger.error(
                    f"修改自定义巡检失败  接口名称({request.path}) 请求参数({req_body_to_json(request)})"
                )
            return Request.succFcun(msg="修改成功", data=[])
        else:
            return Request.errorFcun(msg="修改失败", data=[])
Exemple #12
0
def execute_task(request):
    """
    执行任务

    按脚本执行
    """
    req = req_body_to_json(request)
    # req = request.GET
    task_id = int(req.get('task_id', 99))

    # 数据校验
    if task_id <= 0:
        return Request.errorFcun(msg='参数错误')

    # 校验数据库是否存在已经执行的任务
    res = redis_link.hget(name="current_task", key=task_id)
    if not res:
        redis_link.hset(name="current_task", key=task_id, value="True")
    else:
        return Request.errorFcun(msg='任务已经在执行中')

    # 查询所在任务数据
    tasks = Task.objects.filter(id=task_id)
    if not tasks.exists():
        return Request.errorFcun(msg='参数错误,找不到这个任务')
    # 获取任务数据行
    task = tasks.first()

    # 查询模板
    tpl = Tpl.objects.filter(id=task.task_tpl_id)
    if not tpl.exists():
        return Request.errorFcun(msg='参数错误,找不到这个模板ID')
    tplLogic = TplLogic()
    tpl_quota_list = tplLogic.getQuotas(task.task_tpl_id)

    if len(tpl_quota_list) == 0:
        return Request.errorFcun(msg='模板的指标是空的,请先添加模板指标')

    # 启动celery任务
    task_celery.delay(task, task.id, request.user)

    field_names = Log.get_model_field(Task)

    Log.operation_log(request,
                      Task._meta.verbose_name,
                      task,
                      update_fields={},
                      operation_module_name="任务管理",
                      field_names=field_names,
                      method="EXECUTE")
    return Request.succFcun()
Exemple #13
0
def task_detail(request):
    """
    任务详情
    :param request:
    :return:
    """
    task_id = request.GET.get('task_id')
    if not task_id:
        return Request.errorFcun(msg='参数获取失败')
    result = Task.objects.filter(id=task_id)
    if len(result) > 0:
        return Request.succFcun(data=[a.to_dict_detail() for a in result][0])
    else:
        return Request.errorFcun()
Exemple #14
0
    def get(self, request):
        notify_conf = SystemConfig.objects.filter(config_type="消息通知").values(
            "config_value", "description")[0]
        config_values = notify_conf["config_value"].split(",")
        description = notify_conf["description"].split(",")
        notify_keys = ["type", "name"]
        descriptions = [
            dict(zip(notify_keys, desc.split(":"))) for desc in description
        ]

        return Request.succFcun('',
                                data={
                                    "config_values": config_values,
                                    "descriptions": descriptions
                                })
Exemple #15
0
def business_list(request):
    """
    业务列表。需要和用户权限关联
    :param request:
    :return:
    """
    kwargs = {
        "fields": ["bk_biz_id", "bk_biz_name"],
    }
    client = get_client_by_user(request.user.username)
    result = client.cc.search_business(kwargs)
    if result["result"]:
        return Request.succFcun(data=result["data"]["info"])
    else:
        return Request.errorFcun()
Exemple #16
0
def fetch_quota_by_tpl(request):
    """
    根据tpl查询指标
    """
    tpl_id = request.GET.get("tpl_id", 0)
    if tpl_id == 0:
        return Request.errorFcun('参数错误')

    tpl = Tpl.objects.filter(id=int(tpl_id))
    if not tpl.exists():
        return Request.errorFcun('模板不存在')

    tplLogic = TplLogic()
    data = tplLogic.getQuotas(tpl_id)
    return Request.succFcun('', data)
Exemple #17
0
def off_button(request):
    task_id = int(request.GET.get('task_id', 181))
    if task_id <= 0:
        return Request.errorFcun(msg='参数获取失败')
    res = redis_link.get(task_id)

    if res != None:
        res_dict = eval(res)
        res_dict['status'] = 'executed'
        redis_link.delete(task_id)
        redis_link.set(task_id, str(res_dict))
        # 改变任务表中的状态
        Task.objects.filter(id=task_id).update(exec_state=0)
    else:
        return Request.errorFcun(msg='获取失败')
    return Request.succFcun(msg='任务停止中')
Exemple #18
0
 def put(self, request):
     req = req_body_to_json(request)
     notify_configs = req.get("notify_configs")
     config_value = ",".join(notify_configs)
     try:
         # 下面的代码在一个事务中执行,一但出现异常,整个with函数内部的数据库操作都会回滚
         with transaction.atomic():
             SystemConfig.objects.filter(config_type="消息通知").update(
                 **{"config_value": config_value})
     except:
         logger.error(
             f"修改通知配置  接口名称({request.path}) 请求参数({req_body_to_json(request)})"
         )
     notify_conf = SystemConfig.objects.filter(config_type="消息通知").first()
     if notify_conf.config_value == config_value:
         return Request.succFcun('更改通知配置成功', data=[])
     else:
         return Request.errorFcun('更改通知配置失败', data=[])
Exemple #19
0
def fetch_check_activity(request):
    """
    首页巡检动态接口
    """
    data = []
    # 获取近7条执行完成和执行失败的日志
    execute_logs = ExecuteLog.objects.filter(exec_state__in=[2, 3]).order_by("-end_time").values_list(
        "id", "end_time", "operator", "exec_state", "task_id")[0:7]
    for execute_log in execute_logs:
        execute_log_id, end_time, operator, exec_state, task_id = execute_log
        task = Task.objects.filter(id=task_id).first()
        temp = {
            "id": execute_log_id,
            "tag": "%s" % task.task_name,
            "content": "%s&nbsp;&nbsp;&nbsp;&nbsp;执行人:%s" % (
                end_time.strftime("%Y-%m-%d %H:%M:%S"), operator if operator else "admin"),
            "type": "success" if exec_state == 2 else "danger"
        }
        data.append(temp)
    return Request.succFcun(data=data)
    def get(self, request):
        # 分页参数
        current = request.GET.get("current", 0)
        limit = request.GET.get("limit", 0)
        os_name = request.GET.get("os_name", "")

        # 封装查询参数
        kwargs = {"is_deleted": 0}
        if os_name:
            kwargs['os_name__icontains'] = os_name

        system_os = CheckSystemOs.objects.filter(**kwargs)

        if current and limit:
            paginator = Paginator(system_os.order_by('id'), int(limit))
            count = paginator.count
            data = [os.to_dict() for os in paginator.page(int(current))]
        else:
            count = system_os.count()
            data = [os.to_dict() for os in system_os.order_by('id')]
        return Request.succFcun('', data={"count": count, "data": data})
Exemple #21
0
def business_hosts(request):
    """
    业务下topo
    :param request:
    :return:
    """
    bk_biz_id = int(request.GET.get('bk_biz_id', 2))

    if bk_biz_id <= 0:
        return Request.errorFcun()
    kwargs = {
        "bk_biz_id": bk_biz_id,  # 业务ID
    }
    client = get_client_by_request(request)
    result = client.cc.search_biz_inst_topo(kwargs)
    print(result)
    if result['message'] == "success":
        # 调用递归方法
        res = Make_Recursion_List(result['data'][0])
        return Request.succFcun(data=res)
    return Request.errorFcun()
Exemple #22
0
    def get(self, request):
        tpl_id = request.GET.get('tpl_id')
        if not tpl_id:
            return Request.errorFcun("参数异常", data=[])

        # 判断tpl_id是否存在
        tpl_obj = Tpl.objects.filter(id=tpl_id).first()
        if not tpl_obj or tpl_obj.is_deleted == 1:
            return Request.errorFcun("模板不存在", data=[])

        # 根据模板iD 查询模板关联指标中间表
        tpl_quota_list = CheckSystemTplQuta.objects.filter(
            tpl_id=tpl_obj.id).all()
        # 查询所有关联指标
        quotas = Quota.objects.filter(id__in=[
            quota.quota_id for quota in tpl_quota_list
        ],
                                      is_deleted=0).all()

        data = tpl_obj.to_dict()
        data['tpl_quotas'] = quota_class(quotas, tpl_quota_list)

        return Request.succFcun("sucess", data=data)
Exemple #23
0
def task_delete(request):
    """
    删除任务
    :param request:
    :return:
    """
    task_id = request.GET.get('task_id')
    if not task_id:
        return Request.errorFcun(msg='参数获取失败')
    result = Task.objects.filter(id=task_id)
    if result.exists():
        with transaction.atomic():
            result.update(is_deleted=1)
            field_names = Log.get_model_field(Task)
            Log.operation_log(request,
                              Task._meta.verbose_name,
                              result.first(),
                              update_fields={},
                              operation_module_name="任务管理",
                              field_names=field_names,
                              method="DELETE")
        return Request.succFcun(msg='删除成功')
    else:
        return Request.errorFcun()
    def get(cls, request, *args, **kwargs):
        """
            获取历史报告列表
            1,获取所有task历史
            2,获取业务,巡检对象,模版
        """
        # 获取参数
        current = request.GET.get("current", 1)
        limit = request.GET.get("limit", 10)
        data_list = list()
        biz_dict = dict()

        # 获取所有业务
        dates = utils.get_all_biz(request)
        # 过滤业务数据,拼装成json
        business_infos = dates.get('data').get('info')
        for info in business_infos:
            biz_dict[info.get('bk_biz_id')] = info.get('bk_biz_name')

        task_kwargs = {
            'task_tpl': request.GET.get("task_tpl", ""),
            'task_os': request.GET.get("task_os", ""),
            'exec_biz_id': request.GET.get("exec_biz_id", "")
        }
        # 删除任务参数空值项
        for task_key in list(task_kwargs.keys()):
            if not task_kwargs[task_key]:
                task_kwargs.pop(task_key)
        # 查询符合条件的任务id
        if task_kwargs:
            task_ids = Task.objects.filter(**task_kwargs).values_list(
                'id', flat=True)
        else:
            task_ids = Task.objects.values_list('id', flat=True)

        execute_kwargs = {
            "exec_state__in": [2, 3],
            "task_id__in": list(task_ids)
        }
        start_time = request.GET.get("start_time", '')
        end_time = request.GET.get("end_time", '')
        if start_time and end_time:
            execute_kwargs["updated_time__gte"] = start_time + " 00:00:00"
            execute_kwargs["end_time__lt"] = end_time + " 23:59:59"
        # 查询执行日志
        execute_logs_queryset = ExecuteLog.objects.filter(**execute_kwargs)
        # 分页数据
        paginator = Paginator(execute_logs_queryset.order_by("-created_time"),
                              int(limit))
        execute_logs = paginator.page(int(current))

        # 以{id:object}形式存储task
        tasks = Task.objects.filter(
            id__in=[execute.task_id for execute in execute_logs])
        tasks = {task.id: task for task in tasks}

        # 业务模板 查询OS模板 查询指标模板
        bk_info_lists, os_info_lists, tpl_info_lists = get_biz_os_tpl(request)
        dict_kwargs = {
            "bk_info_lists": bk_info_lists,
            "os_info_lists": os_info_lists,
            "tpl_info_lists": tpl_info_lists
        }

        # 获取历史报告
        for execute in execute_logs:
            result = tasks[execute.task_id]
            result_dict = result.to_dict(**dict_kwargs)
            result_dict['bk_biz_name'] = biz_dict.get(result.exec_biz_id)
            result_dict['task_os'] = result.task_tpl.get_os_name()
            result_dict['tpl_name'] = result.task_tpl.tpl_name
            execute_dict = execute.to_dict()
            result_dict['start_time'] = execute_dict['updated_time']
            result_dict['end_time'] = execute_dict['end_time']
            result_dict['execute_log_id'] = execute_dict['id']
            data_list.append(result_dict)
        return Request.succFcun(data={
            "count": paginator.count,
            "data": data_list
        })
Exemple #25
0
def fetch_check_statistics(request):
    """
    首页巡检统计接口
    """
    start_time = request.GET.get("start_time", datetime.datetime.now().strftime("%Y-%m-%d 00:00:01"))
    end_time = request.GET.get("end_time", datetime.datetime.now().strftime("%Y-%m-%d 23:59:59"))

    # 巡检汇总数据
    # 开始时间结束之间之间的所有执行日志
    execute_logs = ExecuteLog.objects.filter(end_time__range=[start_time, end_time])
    execute_log_ids = execute_logs.values_list("id", flat=True).distinct()
    task_ids = execute_logs.values_list("task_id", flat=True).distinct()
    # 巡检总业务数
    biz_count = Task.objects.filter(id__in=task_ids).values_list("exec_biz_id", flat=True).distinct().count()
    task_host_results = TaskHostResult.objects.filter(execute_log_id__in=execute_log_ids)
    # 巡检主机总数
    total_host_count = task_host_results.values_list("host_ip", flat=True).distinct().count()
    # 巡检总次数
    execute_count = execute_logs.count()
    # 巡检异常主机总数
    error_host_count = task_host_results.filter(result_status=False).values_list("host_ip",
                                                                                 flat=True).distinct().count()
    statistics = {
        # 巡检业务总数
        "biz_count": biz_count,
        # 巡检主机数
        "total_host_count": total_host_count,
        # 巡检总次数
        "execute_count": execute_count,
        # 巡检异常主机数
        "error_host_count": error_host_count
    }

    # 巡检统计数据(折线图)
    # 获取开始结束时间之间所有日期
    date_list = []
    start_date = datetime.datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S")
    end_date = datetime.datetime.strptime(end_time, "%Y-%m-%d %H:%M:%S")
    while start_date <= end_date:
        date_str = start_date.strftime("%Y-%m-%d")
        date_list.append(date_str)
        start_date += datetime.timedelta(days=1)
    count_data = {
        "biz_count": [],
        "total_host_count": [],
        "execute_count": [],
        "error_host_count": []
    }
    for date_str in date_list:
        # 每日执行日志
        execute_logs_per_day = ExecuteLog.objects.filter(
            end_time__range=[
                datetime.datetime.strptime(date_str + " 00:00:01", "%Y-%m-%d %H:%M:%S"),
                datetime.datetime.strptime(date_str + " 23:59:59", "%Y-%m-%d %H:%M:%S")
            ]
        )
        # 每日执行日志id列表
        execute_log_ids_per_day = execute_logs_per_day.values_list("id", flat=True).distinct()
        # 每日执行日志涉及的任务列表
        task_ids_per_day = execute_logs_per_day.values_list("task_id", flat=True).distinct()
        # 每日巡检业务数
        biz_count_per_day = Task.objects.filter(id__in=task_ids_per_day).values_list("exec_biz_id",
                                                                                     flat=True).distinct().count()
        task_host_results_per_day = TaskHostResult.objects.filter(execute_log_id__in=execute_log_ids_per_day)
        # 每日巡检主机总数
        total_host_count_per_day = task_host_results_per_day.values_list("host_ip", flat=True).distinct().count()
        # 每日巡检总次数
        execute_count_per_day = execute_logs_per_day.count()
        # 每日巡检异常主机总数
        error_host_count_per_day = task_host_results_per_day.filter(result_status=False).values_list("host_ip",
                                                                                                     flat=True).distinct().count()
        count_data["biz_count"].append(biz_count_per_day)
        count_data["total_host_count"].append(total_host_count_per_day)
        count_data["execute_count"].append(execute_count_per_day)
        count_data["error_host_count"].append(error_host_count_per_day)

    data = {
        "statistics": statistics,
        "reports": {
            # 日期清单(x轴)
            "date_list": date_list,
            # 统计数据(y轴)
            "count_data": count_data
        }
    }
    return Request.succFcun(data=data)
def detail(req):
    # 根据execute_id获取任务执行历史
    host = req.get('host')
    execute_id = req.get('execute_id')

    # 返回结果
    data = {}

    # 查询是否有此次日志
    execute_obj = ExecuteLog.objects.filter(pk=execute_id).first()  # 任务历史对象

    if not execute_obj:
        return Request.errorFcun('巡检报告详情不存在')

    execute_dict = execute_obj.to_dict()  # 任务历史json对象
    task_host = {
        'host': host,  # 巡检主机
        'create_time': execute_dict.get('created_time'),  # 开始时间
        'end_time': execute_dict.get('end_time')  # 结束时间
    }
    data['task_host'] = task_host

    # 查询本次详情
    host_results = TaskHostResult.objects.filter(host_ip=host,
                                                 execute_log_id=execute_id)

    quota_total = host_results.count()  # 指标总数
    quota_total_error = host_results.filter(
        result_status=False).count()  # 异常指数
    quota_list = host_results.values("system_class_id").annotate(
        c=Count("system_class_id"))  # 根据class分组
    # print(quota_list)
    # print(host_results.values("system_class_id"))

    system_class_ids = []  # class分类id
    for val in quota_list:
        system_class_ids.append(val['system_class_id'])

    # 查询class分类
    system_class = CheckSystemClass.objects.filter(id__in=system_class_ids)
    class_name_map = {}
    for class_val in system_class:
        class_name_map[class_val.id] = class_val.class_name

    top_list = {}  # 面板参数
    for val in quota_list:
        temp_classname = class_name_map[val['system_class_id']]
        top_list[temp_classname] = val['c']
    # print(top_list)
    data_list = {}  # 参数列表页面
    for val in host_results:
        temp = {"check_result": val.check_result}

        temp_classname = class_name_map.get(val.system_class_id, False)
        if not temp_classname:
            continue

        if temp_classname not in data_list:
            data_list[temp_classname] = []

        data_list[temp_classname].append(temp)

    data = {
        'quota_total': quota_total,
        'quota_total_error': quota_total_error,
        'top_list': top_list,
        'data_list': data_list,
        'task_host': task_host
    }

    # print(data.keys())

    return Request.succFcun(data=data)
Exemple #27
0
def bk_users(request):
    client = get_client_by_request(request)
    kwargs = {"fields": "username,id", "no_page": True}
    res = client.usermanage.list_users(kwargs)
    return Request.succFcun("sucess", data=res['data'])
    def get(cls, request, *args, **kwargs):
        """
        根据历史报告的ID获取巡检报告的详情
        如果存在report_id,则获取指定ID的巡检报告
        不存在ID,则获取最新的巡检报告
        """
        # 定义字典,存放业务,后续报告中根据biz_id获取业务名称
        biz_dict = dict()
        execute_id = request.GET.get("id", '')

        # 获取所有业务
        dates = utils.get_all_biz(request)

        # 过滤业务数据,拼装成json
        business_infos = dates.get('data').get('info')
        for info in business_infos:
            biz_dict[info.get('bk_biz_id')] = info.get('bk_biz_name')

        # 获取执行历史记录,根据execute中的task_id获取task, 如果没有指明id,则获取最新时间的log
        if execute_id:
            execute_result = ExecuteLog.objects.get(pk=execute_id)

        else:
            execute_result = ExecuteLog.objects.filter(
                exec_state__in=[2, 3]).order_by("-end_time")
            if execute_result:
                execute_result = execute_result.first()
                execute_id = execute_result.id

        # 巡检报告历史不存在
        if not execute_result:
            return Request.errorFcun("巡检报告历史不存在")
        task_result = Task.objects.get(pk=execute_result.task_id)
        task_tpl_name = task_result.task_tpl.tpl_name
        result_dict = task_result.to_dict_detail()  # 对象转json

        result_dict['task_os'] = task_result.task_tpl.get_os_name()
        # 业务名称
        result_dict['bk_biz_name'] = biz_dict.get(task_result.exec_biz_id)

        # 匹配主机结果简报规则
        # 1,从历史主机报告中获取对应执行报告ID的信息
        # 2, 去重获取所有host
        # 3,过滤历史报告执行结果为false, 并获取IP,在去重  异常主机
        # 4,过滤历史报告执行结果为false, 异常指标数
        # 5,在host去重的基础上,判断是否有powerOff, 巡检失败主机数
        result_dict['hosts'] = []

        task_host_results = TaskHostResult.objects.filter(
            execute_log_id=execute_id)
        all_ips = task_host_results.values_list('host_ip',
                                                flat=True).distinct()  # ip去重
        # 巡检主机数
        result_dict['all_ips'] = len(all_ips)
        all_error_hosts = task_host_results.filter(
            check_result__icontains='powerOff/')
        # all_error_hosts = task_host_results.filter(check_result='powerOff')
        result_dict['failed_host'] = len(all_error_hosts)  # 巡检失败主机数
        # 巡检失败主机IP
        error_host_list = all_error_hosts.values_list('host_ip', flat=True)

        # 异常指标
        error_quotas = task_host_results.exclude(
            check_result__icontains='powerOff/').filter(result_status=False)
        # error_quotas = task_host_results.exclude(check_result='powerOff').filter(result_status=False)
        result_dict['error_num'] = len(error_quotas)  # 异常指标数
        # 异常主机数
        error_hosts = error_quotas.values_list('host_ip', flat=True).distinct()

        result_dict['error_host'] = len(error_hosts)

        # 将记录和每个主机拼装
        for host in all_ips:
            # 收集主机异常指标
            host_quota = []
            single_host_quotas = error_quotas.filter(host_ip=host)
            for single_host_quota in single_host_quotas:
                host_quota.append({
                    'quota_name':
                    single_host_quota.quota_id.quota_name,
                    'recommend_value':
                    single_host_quota.recommend_value,
                    'check_result':
                    single_host_quota.check_result
                })
            failed_info = ''
            if host in error_host_list:
                error_info = all_error_hosts.filter(host_ip=host).first()
                failed_info = error_info.check_result.split('/')[-1]
            result_dict['hosts'].append({
                'host':
                host,
                'host_status':
                'failed' if host in error_host_list else 'success',
                'bk_biz_name':
                result_dict['bk_biz_name'],
                'task_name':
                result_dict['task_name'],
                'task_os':
                result_dict['task_os'],
                'task_tpl':
                result_dict['task_tpl'],
                'task_tpl_name':
                task_tpl_name,
                'errors':
                host_quota,  # 这里的error是对应机器的异常的列表  #
                'failed_info':
                failed_info
            })

        execute_dict = execute_result.to_dict()
        result_dict['start_time'] = execute_dict['updated_time']
        result_dict['end_time'] = execute_dict['end_time']
        result_dict['execute_log_id'] = execute_dict['id']
        return Request.succFcun(data=result_dict)
def windows_host_detail(req):
    # 根据execute_id获取任务执行历史
    host = req.get("host")
    execute_id = req.get("execute_id")
    # 查询是否有此次日志
    # 任务历史对象
    execute_obj = ExecuteLog.objects.filter(pk=execute_id).first()

    if not execute_obj:
        return Request.errorFcun("巡检报告详情不存在")

    # 基本信息
    execute_dict = execute_obj.to_dict()
    basic_info = {
        # 巡检主机
        "host": host,
        # 开始时间
        "create_time": execute_dict.get("created_time"),
        # 结束时间
        "end_time": execute_dict.get("end_time")
    }

    # 巡检概览信息
    # 查询本次详情
    host_results = TaskHostResult.objects.filter(host_ip=host,
                                                 execute_log_id=execute_id)
    # 指标总数
    quota_total_num = host_results.count()
    # 异常指标数量
    quota_error_num = host_results.filter(result_status=False).count()

    # 将查询结果转化为 [{}, {}]
    host_result_dicts = [host_result.to_json() for host_result in host_results]
    # 根据system_class_id, system_class_name进行排序
    grouper = itemgetter("system_class_id", "system_class_name",
                         "system_class_sort")
    sorted_host_result_dicts = sorted(host_result_dicts, key=grouper)
    # 根据system_class_id进行分组
    grouped_host_result_dicts = groupby(sorted_host_result_dicts, key=grouper)
    # 指标分类
    quota_class_details = []
    for groupby_field_list, items in grouped_host_result_dicts:
        system_class_id, system_class_name, system_class_sort = groupby_field_list
        temp_quota_error_num = 0
        temp_quota_details = []
        for item in items:
            temp_quota_detail = {
                # 指标名称
                "quota_name": item.get("quota_name"),
                # 指标推荐值
                "recommend_value": item.get("recommend_value"),
                # 检查结果
                "check_result": item.get("check_result"),
                # 结果比对状态
                "result_status": item.get("result_status")
            }
            temp_quota_details.append(temp_quota_detail)
            if not item.get("result_status"):
                temp_quota_error_num += 1
        temp = {
            # 巡检分类id
            "quota_class_id": system_class_id,
            # 巡检分类名称
            "quota_class_name": system_class_name,
            # 巡检分类排序值
            "quota_class_sort": system_class_sort,
            # 巡检分类中异常指标数
            "quota_error_num": temp_quota_error_num,
            # 巡检分类中所有指标详情
            "quota_details": temp_quota_details
        }
        quota_class_details.append(temp)

    # 对指标分类按照异常指标数从大到小进行排序(用户巡检概览TOP4)
    sorted_quota_class_details_by_quota_error_num = sorted(
        quota_class_details,
        key=lambda x: x.get("quota_error_num"),
        reverse=True)
    # 截取TOP4
    if len(sorted_quota_class_details_by_quota_error_num) >= 4:
        quota_error_class_top4 = sorted_quota_class_details_by_quota_error_num[:
                                                                               4]
    else:
        quota_error_class_top4 = sorted_quota_class_details_by_quota_error_num

    # 计算异常指标占比(百分比整数)
    if quota_total_num > 0:
        quota_error_percent = int(
            float(
                format(float(quota_error_num) / float(quota_total_num), '.2f'))
            * 100)
    else:
        quota_error_percent = 0
    overview_info = {
        # 巡检总指标数
        "quota_total_num": quota_total_num,
        # 巡检异常指标数
        "quota_error_num": quota_error_num,
        # 异常指标占比
        "quota_error_percent": quota_error_percent,
        # 异常指标分类TOP4
        "quota_error_class_top4": quota_error_class_top4
    }

    # 对指标分类按照数据库设定的排序值进行排序(用于全部展示)
    sorted_quota_class_details_by_quota_class_sort = sorted(
        quota_class_details, key=lambda x: x.get("quota_class_sort"))

    # 处理特殊的指标类
    # 12 磁盘分区信息
    # 5 系统异常服务
    # 14 近七天应用错误日志
    # 16 近七天系统错误日志
    special_system_class_ids = [12, 5, 16, 14]
    for item in sorted_quota_class_details_by_quota_class_sort:
        quota_class_id = item.get("quota_class_id")
        if quota_class_id in special_system_class_ids:
            quota_details = item.get("quota_details")
            if len(quota_details) == 1:
                check_result = quota_details[0].get("check_result")
                try:
                    new_quota_details = json.loads(check_result)
                    if isinstance(new_quota_details, dict):
                        new_quota_details = [new_quota_details]
                except Exception as e:
                    new_quota_details = []
                    error_message = "loads check_result to json failed: %s , result: %s" % (
                        repr(e), check_result)
                    logger.warning(error_message)
                # 磁盘分区信息
                # 盘符输出去掉 :
                # 单位转换 b => GB
                # 计算可用空间百分比
                if quota_class_id in [12]:
                    for new_quota_detail in new_quota_details:
                        device_id = new_quota_detail.get("DeviceID")
                        new_quota_detail["DeviceID"] = device_id.replace(
                            ":", "") if device_id else device_id
                        size = new_quota_detail.get("Size")
                        free_space = new_quota_detail.get("FreeSpace")
                        if isinstance(size, int) and isinstance(
                                free_space, int):
                            new_quota_detail["Size"] = round(size / 1024 /
                                                             1024 / 1024)
                            new_quota_detail["FreeSpace"] = round(
                                free_space / 1024 / 1024 / 1024)
                            new_quota_detail["FreeSpacePercent"] = int(
                                round(free_space / size, 2) * 100)
                    item["quota_details"] = new_quota_details
                # 近七天应用错误日志、近七天系统错误日志 需要将时间戳格式化为 %Y-%m-%d %H:%M:%S 格式时间, 同时生成统计数据
                elif quota_class_id in [14, 16]:
                    # 定义 EntryType 的映射
                    entry_type_map = {1: "Error", 2: "Warning"}
                    # 第一遍遍历,生成 Source 和 Count的映射
                    source_and_count_map = {}
                    for new_quota_detail in new_quota_details:
                        source = new_quota_detail.get("Source")
                        if source:
                            if source not in source_and_count_map:
                                source_and_count_map[source] = 1
                            else:
                                source_and_count_map[source] += 1
                    # 第二遍遍历,格式化TimeGenerated, 插入Count
                    for new_quota_detail in new_quota_details:
                        new_quota_detail["Count"] = source_and_count_map.get(
                            new_quota_detail.get("Source"), 1)
                        new_quota_detail["EntryType"] = entry_type_map.get(
                            new_quota_detail.get("EntryType"),
                            new_quota_detail.get("EntryType"))
                        # time_generated = new_quota_detail.get("TimeGenerated")
                        # try:
                        #     if isinstance(time_generated, str):
                        #         new_time_generated = datetime.datetime.fromtimestamp(
                        #             int(time_generated) / 1000).strftime("%Y-%m-%d %H:%M:%S")
                        #     else:
                        #         new_time_generated = time_generated
                        # except Exception as e:
                        #     new_time_generated = time_generated
                        #     error_message = "format TimeGenerated failed: %s, time_generated: %s" % (repr(e), time_generated)
                        #     logger.warning(error_message)
                        # new_quota_detail["TimeGenerated"] = new_time_generated
                    # 根据Count, TimeGenerated倒序排序
                    sorted_new_quota_details = sorted(
                        new_quota_details,
                        key=lambda x: (x["Count"], x["TimeGenerated"]),
                        reverse=True)
                    item["quota_details"] = sorted_new_quota_details
                else:
                    item["quota_details"] = new_quota_details

    data = {
        # 基本信息
        "basic_info": basic_info,
        # 巡检概览
        "overview_info": overview_info,
        # 巡检详情
        "quota_class_details": sorted_quota_class_details_by_quota_class_sort
    }
    return Request.succFcun(data=data)
def linux_host_detail(req):
    # 根据execute_id获取任务执行历史
    host = req.get('host')
    execute_id = req.get('execute_id')
    try:
        execute_obj = ExecuteLog.objects.get(pk=execute_id)  # 任务历史对象
    except:
        return Request.errorFcun('巡检报告详情不存在')

    execute_dict = execute_obj.to_dict()  # 任务历史json对象
    task_host = {
        'host': host,  # 巡检主机
        'create_time': execute_dict.get('created_time'),  # 开始时间
        'end_time': execute_dict.get('end_time')  # 结束时间
    }

    # 巡检概览
    host_results = TaskHostResult.objects.filter(host_ip=host,
                                                 execute_log_id=execute_id)
    host_result_errors = host_results.filter(result_status=False)

    # 安全配置信息 [账号安全 class_id=4, 系统安全 class_id=7, SSH安全设置 class_id=8, 用户安全 class_id=9, 网络安全 class_id=11]
    # 判断每一种安全配置是否存在,存在则获取数据,不存在则忽略
    # 安全配置信息里面包含(账号安全,系统安全,SSH安全设置,用户安全,网络安全)
    # 逻辑说明,在巡检结果中先获取对应class id的巡检结果,循环放入列表中,然后将错误信息放入统计的列表
    safe_config_error, system_run_status_error, system_performance_error, system_info_error, account_config, \
    system_safe, ssh_safe, user_safe, inter_safe, system_run_status, system_performance, system_performance_info, \
    system_config_info, base_info, custom_info_data_error, custom_info = analysis_configure_info(host_results)

    try:
        error_percent = float(
            format(
                float(host_result_errors.count()) /
                float(host_results.count()), '.2f')) * 100
    except:
        error_percent = 0
    inspection_info_detail = [
        # 系统检查类型  # 异常个数  # 异常信息
        {
            'class_name': '安全配置信息',
            'error_count': len(safe_config_error),
            'error_info': safe_config_error,
            'tag': 'safe_config'
        },
        {
            'class_name': '系统运行状态信息',
            'error_count': len(system_run_status_error),
            'error_info': system_run_status_error,
            'tag': 'system_run_status'
        },
        {
            'class_name': '系统性能信息',
            'error_count': len(system_performance_error),
            'error_info': system_performance_error,
            'tag': 'system_performance'
        },
        {
            'class_name': '系统信息',
            'error_count': len(system_info_error),
            'error_info': system_info_error,
            'tag': 'system_info'
        },
        {
            'class_name': '自定义巡检信息',
            'error_count': len(custom_info_data_error),
            'error_info': custom_info_data_error,
            'tag': 'custom_info'
        }
    ]
    inspection_info_detail_sorted = sorted(inspection_info_detail,
                                           key=lambda r: r['error_count'],
                                           reverse=True)
    inspection_info = {
        'inspection_count': host_results.count(),  # 巡检总指标数
        'inspection_error': host_result_errors.count(),  # 巡检异常数
        'error_percent': int(error_percent),
        # 异常占比
        'error_detail': inspection_info_detail_sorted
    }

    # CPU 物理内存 硬盘空间  inode(使用率)
    host_rate, memory_top = get_obj_by_quota(host_results)

    table_list = [
        system_config_info, account_config, system_safe, ssh_safe, user_safe,
        inter_safe, system_run_status, system_performance, custom_info
    ]
    table_list_sorted = sorted(table_list,
                               key=lambda r: r['error_num'] if r else 0,
                               reverse=True)
    table_list_data = [
        item for item in table_list_sorted if item and len(item['info'])
    ]

    # 将每个信息整合成一个dict
    data_all = {
        'task_host': task_host,
        'inspection_info': inspection_info,
        'host_rate': host_rate,
        'memory_top': memory_top,
        'base_info': base_info,
        'table_list_sorted': table_list_data
    }

    return Request.succFcun(data=data_all)