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 #2
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 #3
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 #4
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 #5
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 #6
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 #7
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 #8
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 #9
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 #10
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 #11
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 #12
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 #13
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 #14
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 #15
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()
Exemple #16
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 #17
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 #18
0
    def get(self, request):
        """
        查询系统/模板/自定义 指标
        """
        os_id = request.GET.get("os_id", 0)
        tpl_id = request.GET.get("tpl_id", 0)
        customize = request.GET.get("customize", {})

        # 分页参数
        current = request.GET.get("current", 1)
        limit = request.GET.get("limit", 10)

        if os_id:
            os_id = int(os_id)
            # 根据os_id查询指标
            os_ids = [os_id]
            # 如果是centos 或 Ubuntu 添加99为Linux通用
            if os_id == 1 or os_id == 2:
                os_ids.append(99)
            # 过滤os指标
            quota_query_set = Quota.objects.filter(quota_os__in=os_ids,
                                                   is_deleted=0)
            quotas = quota_query_set.all()
            return Request.succFcun('', data=quota_class(quotas))

        if tpl_id:
            # 根据tpl_id查询指标
            tpl = Tpl.objects.filter(id=int(tpl_id), is_deleted=0)
            if not tpl.exists():
                return Request.errorFcun('模板不存在')

            # 根据模板iD 查询模板关联指标中间表
            tpl_quota_list = CheckSystemTplQuta.objects.filter(
                tpl_id=tpl_id).all()
            # 查询模板关联指标
            quotas = Quota.objects.filter(
                id__in=[quota.quota_id for quota in tpl_quota_list]).all()
            return Request.succFcun('',
                                    data=quota_class(quotas, tpl_quota_list))

        # 查询巡检项
        if customize:
            kwargs = json.loads(customize)
            # 如果存在指标名 变为模糊查询指标
            if 'quota_name' in kwargs:
                kwargs['quota_name__icontains'] = kwargs.pop('quota_name')

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

            # 查询指标
            quotas = Quota.objects.filter(**kwargs)
            paginator = Paginator(
                quotas.order_by("quota_os", "id", "-created_time"), int(limit))
            data = [quota.to_dict() for quota in paginator.page(int(current))]
            return Request.succFcun('',
                                    data={
                                        "count": paginator.count,
                                        "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)
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 #21
0
def TopoHost(request):
    """
    节点下的主机
    :param request:
    :return:
    """
    bk_obj_id = request.GET.get('bk_obj_id')
    bk_inst_id = int(request.GET.get('bk_inst_id', 0))
    bk_biz_id = int(request.GET.get('bk_biz_id', 0))
    # 获取对象,筛掉不符合要求的主机
    # (1, centos) (2, ubuntu) (3, windows)

    os_id = int(request.GET.get('os_id', 0))

    client = get_client_by_request(request)
    result = dict()
    if bk_biz_id <= 0 or bk_inst_id <= 0 or bk_obj_id == "":
        return Request.errorFcun(msg='缺少参数')
    if bk_obj_id == "biz":
        result = client.cc.list_biz_hosts({
            "page": {
                "start": 0,
                "limit": 10,
                "sort": "bk_host_id"
            },
            "bk_biz_id":
            bk_biz_id,
            "fields":
            ["bk_cloud_id", 'bk_host_innerip', "bk_os_name", "bk_host_name"],
        })
    else:
        # 获取集群或者模块下的
        result = client.cc.find_host_by_topo({
            "bk_biz_id":
            bk_biz_id,
            "bk_obj_id":
            bk_obj_id,
            "bk_inst_id":
            bk_inst_id,
            "page": {
                "start": 0,
                "limit": 10
            },
            "fields":
            ["bk_cloud_id", 'bk_host_innerip', "bk_os_name", "bk_host_name"],
        })
    # print(result['data']['info'])
    res_data = []
    for os in result['data']['info']:
        if os_id == 1:
            os_res = os['bk_os_name'].find("centos")
            if os_res < 0:
                continue
            else:
                res_data.append(os)
        if os_id == 2:
            os_res = os['bk_os_name'].find("ubuntu")
            if os_res < 0:
                continue
            else:
                res_data.append(os)
        if os_id == 3:
            os_res = os['bk_os_name'].find("Windows")
            if os_res < 0:
                continue
            else:
                res_data.append(os)

    if result['result']:
        return Request.succFcun(data=res_data)
    return Request.errorFcun(msg='获取主机失败')
Exemple #22
0
def task_add(request):
    """
    新增任务
    """
    # req = request.POST
    # 获取参数
    req = req_body_to_json(request)
    task_tpl_id = int(req.get("task_tpl_id", -1))  # 模板ID
    ip_list = req.get("exec_hosts", [])  # ip列表
    exec_hosts = str(ip_list)  # [{'bk_host_innerip': "127.0.0.1",....}]
    # 主机系统
    task_os = int(req.get("task_os", 0))
    # 通知人列表
    notify_usernames = req.get("notify_usernames", "")

    # exec_schedule的注释
    # 1. instant 立即执行
    # 2. interval 定期执行 示例: interval,2020-12-31 (表示从什么时候开始)
    # 3. crontab 周期执行 示例: crontab,1 (表示1天执行一次)
    exec_schedule = req.get("exec_schedule", 0)
    exec_start_time = req.get("exec_start_time", "")
    exec_timece = req.get("exec_timec", 0)
    old_task_id = int(req.get('task_id', 0))

    # 数据校验
    if task_tpl_id <= 0 or exec_schedule == "" or int(req.get(
            "biz_id", 0)) <= 0 or exec_start_time == "" or int(task_os) <= 0:
        return Request.errorFcun(msg="参数错误")

    # 查询模板
    tpl = Tpl.objects.filter(id=task_tpl_id)
    if not tpl.exists():
        return Request.errorFcun(msg="参数错误,找不到模板ID")
    tpl_obj = tpl.first()

    # # 模板的指标列表
    # tpl_quota_list = eval(tpl_obj.tpl_quotas)

    # 根据模板iD 查询模板关联指标中间表

    tpl_quota_list = CheckSystemTplQuta.objects.filter(tpl_id=tpl_obj.id).all()
    if len(tpl_quota_list) == 0:
        return Request.errorFcun(msg="参数错误,模板指标是空")

    fields = {
        'task_name': req.get("task_name", tpl_obj.tpl_name),
        'task_tpl': tpl_obj,
        'task_op': request.user.username,
        'task_os': task_os,
        'exec_hosts': exec_hosts,
        'exec_biz_id': req.get("biz_id", 0),
        'exec_acc': req.get(
            "exec_acc",
            "root"),  # 此处写死了root,但后期应该修改为可以配置的 因为系统可能是windows,或者有专门的系统用户执行脚本
        'exec_schedule': exec_schedule,
        'exec_state': 0,
        'exec_progress': 0,
        'exec_quota_total': len(tpl_quota_list),
        'exec_start_time': exec_start_time,
        'exec_timece': exec_timece,
        'start_time': datetime.datetime.now()
    }
    task_obj = {}
    if old_task_id > 0:
        with transaction.atomic():
            old_task_obj = Task.objects.get(pk=old_task_id)
            task_obj = Task.objects.filter(id=old_task_id)
            task_obj.update(**fields)
            old_task_notifys = TaskNotify.objects.filter(
                task_id=old_task_id).all()
            old_notify_username_list = [
                old_task_notify.username
                for old_task_notify in old_task_notifys
            ]
            to_delete_notify_username_list = []
            to_add_notify_username_list = []
            for old_notify_username in old_notify_username_list:
                if old_notify_username not in notify_usernames:
                    to_delete_notify_username_list.append(old_notify_username)
            for new_notify_username in notify_usernames:
                if new_notify_username not in old_notify_username_list:
                    to_add_notify_username_list.append(new_notify_username)
            TaskNotify.objects.filter(
                Q(task_id=old_task_id)
                & Q(username__in=to_delete_notify_username_list)).delete()
            to_add_task_notify_list = []
            for username in to_add_notify_username_list:
                new_task_notify = TaskNotify(task_id=old_task_id,
                                             username=username)
                to_add_task_notify_list.append(new_task_notify)
            TaskNotify.objects.bulk_create(to_add_task_notify_list)

            fields['start_time'] = fields['start_time'].strftime(
                "%Y-%m-%d %H:%M:%S")
            fields['end_time'] = ''
            fields['task_tpl'] = fields['task_tpl'].id
            fields['task_os'] = CheckSystemOs.objects.get(pk=task_os).os_name
            field_names = Log.get_model_field(Task)
            Log.operation_log(request,
                              Task._meta.verbose_name,
                              old_task_obj,
                              update_fields=fields,
                              operation_module_name="任务管理",
                              method="PUT",
                              field_names=field_names)
    else:
        # 校验任务名称是否已经存在
        task_name = Task.objects.filter(task_name=req.get("task_name", ''))

        if len([x for x in task_name]) >= 1:
            return Request.errorFcun(msg="任务名重复")
        with transaction.atomic():
            task = Task.objects.create(**fields)
            task_obj = Task.objects.filter(id=task.id)
            task_notify_list = []
            for username in notify_usernames:
                task_notify = TaskNotify(task_id=task.id, username=username)
                task_notify_list.append(task_notify)
            TaskNotify.objects.bulk_create(task_notify_list)
            fields['start_time'] = fields['start_time'].strftime(
                "%Y-%m-%d %H:%M:%S")
            fields['end_time'] = ''
            fields['task_tpl'] = fields['task_tpl'].id
            fields['task_os'] = CheckSystemOs.objects.get(pk=task_os).os_name
            field_names = Log.get_model_field(Task)
            Log.operation_log(request,
                              table_name=Task._meta.verbose_name,
                              update_fields=fields,
                              operation_module_name="任务管理",
                              field_names=field_names)
    return Request.succFcun(data=[info.to_dict_detail() for info in task_obj])
    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)
Exemple #24
0
def fetch_task_list(request):
    """
    任务列表
    :param request:
    :return:
    """
    exec_biz_id = request.GET.get('biz_id', "")
    task_os = request.GET.get('os_id', "")
    exec_state = request.GET.get('exec_state', "")
    task_tpl_id = request.GET.get('tpl_id', "")

    # 分页
    # 获取当前页
    page = int(request.GET.get('page', 1))
    # 获取总页数
    size = int(request.GET.get('size', 10))
    # 模糊查询
    keywords = request.GET.get('keywords', '')
    # 日期查询
    date = request.GET.get('date', '')

    old_filed = {
        "is_deleted": 0,
        "exec_biz_id": exec_biz_id,
        "exec_state": exec_state,
        "task_os": task_os,
        "task_name__contains": keywords,
        "task_tpl_id": task_tpl_id,
        "start_time__range": date.split(',') if date != "" else ""
    }
    filed = {}
    for key, value in old_filed.items():
        if value != "":
            filed[key] = value

    result = Task.objects.filter(**filed).order_by('-created_time')

    if result.exists():
        try:
            # 获取前端传来的页码数(需要分几页)
            paginator = Paginator(result, int(size))
            # 获取分好后数据的某一页
            scripts_ = paginator.page(int(page))
        except Exception as err:
            # 没传参则默认分页
            paginator = Paginator(result, 10)
            scripts_ = paginator.page(1)

        # 获取对应的模板数据,OS数据,业务数据
        kwargs = {
            # 'bk_token': 'G6nuRLYKeKF2SKV2toXRNQVL9GWhOetUafkIMcsSSOM',
            "fields": ["bk_biz_id", "bk_biz_name"],
        }
        client = get_client_by_request(request)
        res = client.cc.search_business(kwargs)
        # 业务模板
        bk_info_lists = {
            bk['bk_biz_id']: bk['bk_biz_name']
            for bk in res['data']['info']
        }
        # 查询OS模板
        os_info_lists = {
            os.id: os.to_dict()['os_name']
            for os in CheckSystemOs.objects.all()
        }
        # 查询指标模板
        tpl_info_lists = {
            tpl.id: tpl.to_dict_name()['tpl_name']
            for tpl in Tpl.objects.all()
        }

        data = [
            x.to_dict(
                bk_info_lists=bk_info_lists,
                os_info_lists=os_info_lists,
                tpl_info_lists=tpl_info_lists,
            ) for x in scripts_
        ]
        return Request.succFcun(data={'data': data, 'count': paginator.count})
    else:
        return Request.errorFcun()
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)
Exemple #26
0
    def put(self, request):
        req = req_body_to_json(request)
        tpl_id = req.get("tpl_id", '')
        tpl_name = req.get("tpl_name", '')
        tpl_os = req.get("tpl_os", '')
        description = req.get("description", '')
        quotas = req.get("quotas", '')

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

        tpl_obj = Tpl.objects.filter(id=tpl_id).first()

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

        quota_objs = list()

        for quota in quotas:
            # 新添加
            quota_objs.append(
                CheckSystemTplQuta(tpl_id=tpl_obj.id,
                                   quota_id=quota['id'],
                                   quota_threshold=str(
                                       quota['quota_threshold'])))

        if len(quota_objs):
            # 备份对象用于记录日志
            old_model_obj = copy.deepcopy(tpl_obj)

            # 如果系统更改
            tasks = list()
            if tpl_os != tpl_obj.tpl_os:
                for task in tpl_obj.task_set.all():
                    task.task_os = tpl_os
                    tasks.append(task)

            tpl_obj.tpl_os = tpl_os
            tpl_obj.tpl_name = tpl_name
            tpl_obj.description = description

            try:
                # 下面的代码在一个事务中执行,一但出现异常,整个with函数内部的数据库操作都会回滚
                with transaction.atomic():
                    # 删除旧系统指标
                    CheckSystemTplQuta.objects.filter(
                        tpl_id=tpl_obj.id).delete()
                    # 批量创建新系统指标
                    CheckSystemTplQuta.objects.bulk_create(quota_objs)
                    if tasks:
                        Task.objects.bulk_update(tasks, fields=["task_os"])
                    tpl_obj.save()

                    dict_update_fields = {
                        "tpl_name": tpl_name,
                        "tpl_os": CheckSystemOs.objects.get(pk=tpl_os).os_name,
                        "author": tpl_obj.author,
                        "description": description,
                        "quotas": tpl_quotas(quotas)
                    }
                    field_names = Log.get_model_field(Tpl)
                    field_names['quotas'] = "巡检指标"
                    Log.operation_log(request,
                                      Tpl._meta.verbose_name,
                                      old_model_obj,
                                      update_fields=dict_update_fields,
                                      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=[])