mirror of https://github.com/veops/cmdb.git
316 lines
10 KiB
Python
316 lines
10 KiB
Python
# -*- coding:utf-8 -*-
|
|
|
|
from __future__ import unicode_literals
|
|
|
|
import requests
|
|
from flask import current_app
|
|
|
|
from api.extensions import cache
|
|
from api.extensions import db
|
|
from api.lib.cmdb.custom_dashboard import CustomDashboardManager
|
|
from api.models.cmdb import Attribute
|
|
from api.models.cmdb import CI
|
|
from api.models.cmdb import CIType
|
|
from api.models.cmdb import CITypeAttribute
|
|
from api.models.cmdb import RelationType
|
|
|
|
|
|
class AttributeCache(object):
|
|
PREFIX_ID = 'Field::ID::{0}'
|
|
PREFIX_NAME = 'Field::Name::{0}'
|
|
PREFIX_ALIAS = 'Field::Alias::{0}'
|
|
|
|
@classmethod
|
|
def get(cls, key):
|
|
if key is None:
|
|
return
|
|
attr = cache.get(cls.PREFIX_NAME.format(key))
|
|
attr = attr or cache.get(cls.PREFIX_ID.format(key))
|
|
attr = attr or cache.get(cls.PREFIX_ALIAS.format(key))
|
|
|
|
if attr is None:
|
|
attr = Attribute.get_by(name=key, first=True, to_dict=False)
|
|
attr = attr or Attribute.get_by_id(key)
|
|
attr = attr or Attribute.get_by(alias=key, first=True, to_dict=False)
|
|
if attr is not None:
|
|
cls.set(attr)
|
|
return attr
|
|
|
|
@classmethod
|
|
def set(cls, attr):
|
|
cache.set(cls.PREFIX_ID.format(attr.id), attr)
|
|
cache.set(cls.PREFIX_NAME.format(attr.name), attr)
|
|
cache.set(cls.PREFIX_ALIAS.format(attr.alias), attr)
|
|
|
|
@classmethod
|
|
def clean(cls, attr):
|
|
cache.delete(cls.PREFIX_ID.format(attr.id))
|
|
cache.delete(cls.PREFIX_NAME.format(attr.name))
|
|
cache.delete(cls.PREFIX_ALIAS.format(attr.alias))
|
|
|
|
|
|
class CITypeCache(object):
|
|
PREFIX_ID = "CIType::ID::{0}"
|
|
PREFIX_NAME = "CIType::Name::{0}"
|
|
PREFIX_ALIAS = "CIType::Alias::{0}"
|
|
|
|
@classmethod
|
|
def get(cls, key):
|
|
if key is None:
|
|
return
|
|
ct = cache.get(cls.PREFIX_NAME.format(key))
|
|
ct = ct or cache.get(cls.PREFIX_ID.format(key))
|
|
ct = ct or cache.get(cls.PREFIX_ALIAS.format(key))
|
|
if ct is None:
|
|
ct = CIType.get_by(name=key, first=True, to_dict=False)
|
|
ct = ct or CIType.get_by_id(key)
|
|
ct = ct or CIType.get_by(alias=key, first=True, to_dict=False)
|
|
if ct is not None:
|
|
cls.set(ct)
|
|
return ct
|
|
|
|
@classmethod
|
|
def set(cls, ct):
|
|
cache.set(cls.PREFIX_NAME.format(ct.name), ct)
|
|
cache.set(cls.PREFIX_ID.format(ct.id), ct)
|
|
cache.set(cls.PREFIX_ALIAS.format(ct.alias), ct)
|
|
|
|
@classmethod
|
|
def clean(cls, key):
|
|
ct = cls.get(key)
|
|
if ct is not None:
|
|
cache.delete(cls.PREFIX_NAME.format(ct.name))
|
|
cache.delete(cls.PREFIX_ID.format(ct.id))
|
|
cache.delete(cls.PREFIX_ALIAS.format(ct.alias))
|
|
|
|
|
|
class RelationTypeCache(object):
|
|
PREFIX_ID = "RelationType::ID::{0}"
|
|
PREFIX_NAME = "RelationType::Name::{0}"
|
|
|
|
@classmethod
|
|
def get(cls, key):
|
|
if key is None:
|
|
return
|
|
ct = cache.get(cls.PREFIX_NAME.format(key))
|
|
ct = ct or cache.get(cls.PREFIX_ID.format(key))
|
|
if ct is None:
|
|
ct = RelationType.get_by(name=key, first=True, to_dict=False) or RelationType.get_by_id(key)
|
|
if ct is not None:
|
|
cls.set(ct)
|
|
return ct
|
|
|
|
@classmethod
|
|
def set(cls, ct):
|
|
cache.set(cls.PREFIX_NAME.format(ct.name), ct)
|
|
cache.set(cls.PREFIX_ID.format(ct.id), ct)
|
|
|
|
@classmethod
|
|
def clean(cls, key):
|
|
ct = cls.get(key)
|
|
if ct is not None:
|
|
cache.delete(cls.PREFIX_NAME.format(ct.name))
|
|
cache.delete(cls.PREFIX_ID.format(ct.id))
|
|
|
|
|
|
class CITypeAttributesCache(object):
|
|
"""
|
|
key is type_id or type_name
|
|
"""
|
|
|
|
PREFIX_ID = "CITypeAttributes::TypeID::{0}"
|
|
PREFIX_NAME = "CITypeAttributes::TypeName::{0}"
|
|
|
|
PREFIX_ID2 = "CITypeAttributes2::TypeID::{0}"
|
|
PREFIX_NAME2 = "CITypeAttributes2::TypeName::{0}"
|
|
|
|
@classmethod
|
|
def get(cls, key):
|
|
if key is None:
|
|
return
|
|
|
|
attrs = cache.get(cls.PREFIX_NAME.format(key))
|
|
attrs = attrs or cache.get(cls.PREFIX_ID.format(key))
|
|
if not attrs:
|
|
attrs = CITypeAttribute.get_by(type_id=key, to_dict=False)
|
|
if not attrs:
|
|
ci_type = CIType.get_by(name=key, first=True, to_dict=False)
|
|
if ci_type is not None:
|
|
attrs = CITypeAttribute.get_by(type_id=ci_type.id, to_dict=False)
|
|
if attrs is not None:
|
|
cls.set(key, attrs)
|
|
return attrs
|
|
|
|
@classmethod
|
|
def get2(cls, key):
|
|
"""
|
|
return [(type_attr, attr), ]
|
|
:param key:
|
|
:return:
|
|
"""
|
|
if key is None:
|
|
return
|
|
|
|
attrs = cache.get(cls.PREFIX_NAME2.format(key))
|
|
attrs = attrs or cache.get(cls.PREFIX_ID2.format(key))
|
|
if not attrs:
|
|
attrs = CITypeAttribute.get_by(type_id=key, to_dict=False)
|
|
if not attrs:
|
|
ci_type = CIType.get_by(name=key, first=True, to_dict=False)
|
|
if ci_type is not None:
|
|
attrs = CITypeAttribute.get_by(type_id=ci_type.id, to_dict=False)
|
|
if attrs is not None:
|
|
attrs = [(i, AttributeCache.get(i.attr_id)) for i in attrs]
|
|
cls.set2(key, attrs)
|
|
return attrs
|
|
|
|
@classmethod
|
|
def set(cls, key, values):
|
|
ci_type = CITypeCache.get(key)
|
|
if ci_type is not None:
|
|
cache.set(cls.PREFIX_ID.format(ci_type.id), values)
|
|
cache.set(cls.PREFIX_NAME.format(ci_type.name), values)
|
|
|
|
@classmethod
|
|
def set2(cls, key, values):
|
|
ci_type = CITypeCache.get(key)
|
|
if ci_type is not None:
|
|
cache.set(cls.PREFIX_ID2.format(ci_type.id), values)
|
|
cache.set(cls.PREFIX_NAME2.format(ci_type.name), values)
|
|
|
|
@classmethod
|
|
def clean(cls, key):
|
|
ci_type = CITypeCache.get(key)
|
|
attrs = cls.get(key)
|
|
if attrs is not None and ci_type:
|
|
cache.delete(cls.PREFIX_ID.format(ci_type.id))
|
|
cache.delete(cls.PREFIX_NAME.format(ci_type.name))
|
|
|
|
attrs2 = cls.get2(key)
|
|
if attrs2 is not None and ci_type:
|
|
cache.delete(cls.PREFIX_ID2.format(ci_type.id))
|
|
cache.delete(cls.PREFIX_NAME2.format(ci_type.name))
|
|
|
|
|
|
class CITypeAttributeCache(object):
|
|
"""
|
|
key is type_id & attr_id
|
|
"""
|
|
|
|
PREFIX_ID = "CITypeAttribute::TypeID::{0}::AttrID::{1}"
|
|
|
|
@classmethod
|
|
def get(cls, type_id, attr_id):
|
|
|
|
attr = cache.get(cls.PREFIX_ID.format(type_id, attr_id))
|
|
attr = attr or cache.get(cls.PREFIX_ID.format(type_id, attr_id))
|
|
if not attr:
|
|
attr = CITypeAttribute.get_by(type_id=type_id, attr_id=attr_id, first=True, to_dict=False)
|
|
if attr is not None:
|
|
cls.set(type_id, attr_id, attr)
|
|
return attr
|
|
|
|
@classmethod
|
|
def set(cls, type_id, attr_id, attr):
|
|
cache.set(cls.PREFIX_ID.format(type_id, attr_id), attr)
|
|
|
|
@classmethod
|
|
def clean(cls, type_id, attr_id):
|
|
cache.delete(cls.PREFIX_ID.format(type_id, attr_id))
|
|
|
|
|
|
class CMDBCounterCache(object):
|
|
KEY = 'CMDB::Counter'
|
|
|
|
@classmethod
|
|
def get(cls):
|
|
result = cache.get(cls.KEY) or {}
|
|
|
|
if not result:
|
|
result = cls.reset()
|
|
|
|
return result
|
|
|
|
@classmethod
|
|
def set(cls, result):
|
|
cache.set(cls.KEY, result, timeout=0)
|
|
|
|
@classmethod
|
|
def reset(cls):
|
|
customs = CustomDashboardManager.get()
|
|
result = {}
|
|
for custom in customs:
|
|
if custom['category'] == 0:
|
|
result[custom['id']] = cls.summary_counter(custom['type_id'])
|
|
elif custom['category'] == 1:
|
|
result[custom['id']] = cls.attribute_counter(custom['type_id'], custom['attr_id'])
|
|
elif custom['category'] == 2:
|
|
result[custom['id']] = cls.relation_counter(custom['type_id'], custom['level'])
|
|
|
|
cls.set(result)
|
|
|
|
return result
|
|
|
|
@classmethod
|
|
def update(cls, custom):
|
|
result = cache.get(cls.KEY) or {}
|
|
if not result:
|
|
result = cls.reset()
|
|
|
|
if custom['category'] == 0:
|
|
result[custom['id']] = cls.summary_counter(custom['type_id'])
|
|
elif custom['category'] == 1:
|
|
result[custom['id']] = cls.attribute_counter(custom['type_id'], custom['attr_id'])
|
|
elif custom['category'] == 2:
|
|
result[custom['id']] = cls.relation_counter(custom['type_id'], custom['level'])
|
|
|
|
cls.set(result)
|
|
|
|
@staticmethod
|
|
def summary_counter(type_id):
|
|
return db.session.query(CI.id).filter(CI.deleted.is_(False)).filter(CI.type_id == type_id).count()
|
|
|
|
@staticmethod
|
|
def relation_counter(type_id, level):
|
|
|
|
uri = current_app.config.get('CMDB_API')
|
|
|
|
type_names = requests.get("{}/ci/s?q=_type:{}&count=10000".format(uri, type_id)).json().get('result')
|
|
type_id_names = [(str(i.get('_id')), i.get(i.get('unique'))) for i in type_names]
|
|
|
|
url = "{}/ci_relations/statistics?root_ids={}&level={}".format(
|
|
uri, ','.join([i[0] for i in type_id_names]), level)
|
|
stats = requests.get(url).json()
|
|
|
|
id2name = dict(type_id_names)
|
|
type_ids = set()
|
|
for i in (stats.get('detail') or []):
|
|
for j in stats['detail'][i]:
|
|
type_ids.add(j)
|
|
|
|
for type_id in type_ids:
|
|
_type = CITypeCache.get(type_id)
|
|
id2name[type_id] = _type and _type.alias
|
|
|
|
result = dict(summary={}, detail={})
|
|
for i in stats:
|
|
if i == "detail":
|
|
for j in stats['detail']:
|
|
if id2name[j]:
|
|
result['detail'][id2name[j]] = stats['detail'][j]
|
|
result['detail'][id2name[j]] = dict()
|
|
for _j in stats['detail'][j]:
|
|
result['detail'][id2name[j]][id2name[_j]] = stats['detail'][j][_j]
|
|
elif id2name.get(i):
|
|
result['summary'][id2name[i]] = stats[i]
|
|
|
|
return result
|
|
|
|
@staticmethod
|
|
def attribute_counter(type_id, attr_id):
|
|
uri = current_app.config.get('CMDB_API')
|
|
url = "{}/ci/s?q=_type:{}&fl={}&facet={}".format(uri, type_id, attr_id, attr_id)
|
|
res = requests.get(url).json()
|
|
if res.get('facet'):
|
|
return dict([i[:2] for i in list(res.get('facet').values())[0]])
|