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={})
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})
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=[])
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=[])
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()
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=[])
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))
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=[])
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 })
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=[])
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()
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()
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 })
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()
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)
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='任务停止中')
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=[])
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 执行人:%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})
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()
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)
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 })
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)
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)