# -*- coding:utf-8 -*- import json from flask import abort from flask import g from api.extensions import db from api.lib.cmdb.cache import AttributeCache from api.lib.cmdb.cache import RelationTypeCache from api.lib.cmdb.const import OperateType from api.lib.perm.acl.cache import UserCache from api.models.cmdb import Attribute from api.models.cmdb import AttributeHistory from api.models.cmdb import CIRelationHistory from api.models.cmdb import OperationRecord class AttributeHistoryManger(object): @staticmethod def get_records(start, end, username, page, page_size): records = db.session.query(OperationRecord).filter(OperationRecord.deleted.is_(False)) numfound = db.session.query(db.func.count(OperationRecord.id)).filter(OperationRecord.deleted.is_(False)) if start: records = records.filter(OperationRecord.created_at >= start) numfound = numfound.filter(OperationRecord.created_at >= start) if end: records = records.filter(OperationRecord.created_at <= end) numfound = records.filter(OperationRecord.created_at <= end) if username: user = UserCache.get(username) if user: records = records.filter(OperationRecord.uid == user.uid) else: return abort(404, "User <{0}> is not found".format(username)) records = records.order_by(-OperationRecord.id).offset(page_size * (page - 1)).limit(page_size).all() total = len(records) numfound = numfound.first()[0] res = [] for record in records: _res = record.to_dict() _res["user"] = UserCache.get(_res.get("uid")).nickname or UserCache.get(_res.get("uid")).username attr_history = AttributeHistory.get_by(record_id=_res.get("id"), to_dict=False) _res["attr_history"] = [AttributeCache.get(h.attr_id).attr_alias for h in attr_history] rel_history = CIRelationHistory.get_by(record_id=_res.get("id"), to_dict=False) rel_statis = {} for rel in rel_history: if rel.operate_type not in rel_statis: rel_statis[rel.operate_type] = 1 else: rel_statis[rel.operate_type] += 1 _res["rel_history"] = rel_statis res.append(_res) return numfound, total, res @staticmethod def get_by_ci_id(ci_id): res = db.session.query(AttributeHistory, Attribute, OperationRecord).join( Attribute, Attribute.id == AttributeHistory.attr_id).join( OperationRecord, OperationRecord.id == AttributeHistory.record_id).filter( AttributeHistory.ci_id == ci_id).order_by(OperationRecord.id.desc()) return [dict(attr_name=i.Attribute.name, attr_alias=i.Attribute.alias, operate_type=i.AttributeHistory.operate_type, username=UserCache.get(i.OperationRecord.uid).nickname, old=i.AttributeHistory.old, new=i.AttributeHistory.new, created_at=i.OperationRecord.created_at.strftime('%Y-%m-%d %H:%M:%S'), record_id=i.OperationRecord.id, hid=i.AttributeHistory.id ) for i in res] @staticmethod def get_record_detail(record_id): from api.lib.cmdb.ci import CIManager record = OperationRecord.get_by_id(record_id) or abort(404, "Record <{0}> is not found".format(record_id)) username = UserCache.get(record.uid).nickname or UserCache.get(record.uid).username timestamp = record.created_at.strftime("%Y-%m-%d %H:%M:%S") attr_history = AttributeHistory.get_by(record_id=record_id, to_dict=False) rel_history = CIRelationHistory.get_by(record_id=record_id, to_dict=False) attr_dict, rel_dict = dict(), {"add": [], "delete": []} for attr_h in attr_history: attr_dict[AttributeCache.get(attr_h.attr_id).alias] = dict( old=attr_h.old, new=attr_h.new, operate_type=attr_h.operate_type) for rel_h in rel_history: first = CIManager.get_ci_by_id(rel_h.first_ci_id) second = CIManager.get_ci_by_id(rel_h.second_ci_id) rel_dict[rel_h.operate_type].append((first, RelationTypeCache.get(rel_h.relation_type_id).name, second)) return username, timestamp, attr_dict, rel_dict @staticmethod def add(ci_id, history_list): record = OperationRecord.create(uid=g.user.uid) for attr_id, operate_type, old, new in history_list or []: AttributeHistory.create(attr_id=attr_id, operate_type=operate_type, old=json.dumps(old) if isinstance(old, (dict, list)) else old, new=json.dumps(new) if isinstance(new, (dict, list)) else new, ci_id=ci_id, record_id=record.id) class CIRelationHistoryManager(object): @staticmethod def add(rel_obj, operate_type=OperateType.ADD): record = OperationRecord.create(uid=g.user.uid) CIRelationHistory.create(relation_id=rel_obj.id, record_id=record.id, operate_type=operate_type, first_ci_id=rel_obj.first_ci_id, second_ci_id=rel_obj.second_ci_id, relation_type_id=rel_obj.relation_type_id)