def update_unique_value(ci_id, unique_name, unique_value): CI.get_by_id(ci_id) or abort(404, "CI <{0}> is not found".format(ci_id)) AttributeValueManager().create_or_update_attr_value( unique_name, unique_value, ci_id) ci_cache.apply_async([ci_id], queue=CMDB_QUEUE)
def add(cls, ci_type_name, exist_policy=ExistPolicy.REPLACE, _no_attribute_policy=ExistPolicy.IGNORE, **ci_dict): """ :param ci_type_name: :param exist_policy: replace or reject or need :param _no_attribute_policy: ignore or reject :param ci_dict: :return: """ ci_type = CITypeManager.check_is_existed(ci_type_name) unique_key = AttributeCache.get(ci_type.unique_id) or abort( 400, 'illegality unique attribute') unique_value = ci_dict.get(unique_key.name) unique_value = unique_value or ci_dict.get(unique_key.alias) unique_value = unique_value or ci_dict.get(unique_key.id) unique_value = unique_value or abort( 400, '{0} missing'.format(unique_key.name)) existed = cls.ci_is_exist(unique_key, unique_value) if existed is not None: if exist_policy == ExistPolicy.REJECT: return abort(400, 'CI is already existed') if existed.type_id != ci_type.id: existed.update(type_id=ci_type.id) ci = existed else: if exist_policy == ExistPolicy.NEED: return abort(404, 'CI <{0}> does not exist'.format(unique_value)) ci = CI.create(type_id=ci_type.id) ci_type_attrs_name = [ attr["name"] for attr in CITypeAttributeManager().get_attributes_by_type_id(ci_type.id) ] value_manager = AttributeValueManager() for p, v in ci_dict.items(): if p not in ci_type_attrs_name: current_app.logger.warning( 'ci_type: {0} not has attribute {1}, please check!'.format( ci_type_name, p)) continue try: value_manager.create_or_update_attr_value( p, v, ci, _no_attribute_policy) except BadRequest as e: if existed is None: cls.delete(ci.id) raise e ci_cache.apply_async([ci.id], queue=CMDB_QUEUE) return ci.id
def get_ci_by_id_from_db(ci_id, ret_key=RetKey.NAME, fields=None, need_children=True, use_master=False): """ :param ci_id: :param ret_key: name, id or alias :param fields: list :param need_children: :param use_master: whether to use master db :return: """ ci = CI.get_by_id(ci_id) or abort(404, "CI <{0}> is not existed".format(ci_id)) res = dict() if need_children: children = CIRelationManager.get_children(ci_id, ret_key=ret_key) # one floor res.update(children) ci_type = CITypeCache.get(ci.type_id) res["ci_type"] = ci_type.name fields = CITypeAttributeManager.get_attr_names_by_type_id(ci.type_id) if not fields else fields unique_key = AttributeCache.get(ci_type.unique_id) _res = AttributeValueManager().get_attr_values(fields, ci_id, ret_key=ret_key, unique_key=unique_key, use_master=use_master) res.update(_res) res['type_id'] = ci_type.id res['ci_id'] = ci_id return res
def get_ci_by_id(cls, ci_id, ret_key=RetKey.NAME, fields=None, need_children=True): """ :param ci_id: :param ret_key: name, id, or alias :param fields: attribute list :param need_children: :return: """ ci = CI.get_by_id(ci_id) or abort( 404, "CI <{0}> is not existed".format(ci_id)) res = dict() if need_children: children = CIRelationManager.get_children( ci_id, ret_key=ret_key) # one floor res.update(children) ci_type = CITypeCache.get(ci.type_id) res["ci_type"] = ci_type.name res.update( cls.get_cis_by_ids([str(ci_id)], fields=fields, ret_key=ret_key)) res['_type'] = ci_type.id res['_id'] = ci_id return res
def delete(ci_id): ci = CI.get_by_id(ci_id) or abort( 404, "CI <{0}> is not found".format(ci_id)) attrs = CITypeAttribute.get_by(type_id=ci.type_id, to_dict=False) attr_names = set( [AttributeCache.get(attr.attr_id).name for attr in attrs]) for attr_name in attr_names: value_table = TableMap(attr_name=attr_name).table for item in value_table.get_by(ci_id=ci_id, to_dict=False): item.delete() for item in CIRelation.get_by(first_ci_id=ci_id, to_dict=False): item.delete() for item in CIRelation.get_by(second_ci_id=ci_id, to_dict=False): item.delete() ci.delete() # TODO: soft delete AttributeHistoryManger.add(ci_id, [(None, OperateType.DELETE, None, None)]) ci_delete.apply_async([ci.id], queue=CMDB_QUEUE) return ci_id
def delete(cls, type_id, attr_ids=None): """ delete attributes from CIType :param type_id: :param attr_ids: list :return: """ from api.tasks.cmdb import ci_cache cls._check(type_id, attr_ids) for attr_id in attr_ids: existed = CITypeAttribute.get_by(type_id=type_id, attr_id=attr_id, first=True, to_dict=False) if existed is not None: existed.soft_delete() for ci in CI.get_by(type_id=type_id, to_dict=False): AttributeValueManager.delete_attr_value(attr_id, ci.id) ci_cache.apply_async([ci.id], queue=CMDB_QUEUE) CITypeAttributeCache.clean(type_id, attr_id) CITypeAttributesCache.clean(type_id)
def delete(cls, type_id): ci_type = cls.check_is_existed(type_id) if CI.get_by(type_id=type_id, first=True, to_dict=False) is not None: return abort(400, "cannot delete, because CI instance exists") for item in CITypeRelation.get_by(parent_id=type_id, to_dict=False): item.soft_delete() for item in CITypeRelation.get_by(child_id=type_id, to_dict=False): item.soft_delete() for item in PreferenceTreeView.get_by(type_id=type_id, to_dict=False): item.soft_delete() for item in PreferenceShowAttributes.get_by(type_id=type_id, to_dict=False): item.soft_delete() ci_type.soft_delete() CITypeCache.clean(type_id) if current_app.config.get("USE_ACL"): from api.lib.perm.acl.acl import ACLManager from api.lib.cmdb.const import ResourceTypeEnum, RoleEnum, PermEnum ACLManager().del_resource(ci_type.name, ResourceTypeEnum.CI)
def search(self): ids = [self.root_id ] if not isinstance(self.root_id, list) else self.root_id cis = [ CI.get_by_id(_id) or abort(404, "CI <{0}> does not exist".format(_id)) for _id in ids ] merge_ids = [] for level in self.level: ids = [self.root_id ] if not isinstance(self.root_id, list) else self.root_id for _ in range(0, level): _tmp = list( map( lambda x: list(json.loads(x).keys()), filter(lambda x: x is not None, rd.get(ids, REDIS_PREFIX_CI_RELATION) or []))) ids = [j for i in _tmp for j in i] merge_ids.extend(ids) if not self.orig_query or ("_type:" not in self.orig_query and "type_id:" not in self.orig_query and "ci_type:" not in self.orig_query): type_ids = [] for level in self.level: for ci in cis: type_ids.extend( CITypeRelationManager.get_child_type_ids( ci.type_id, level)) type_ids = list(set(type_ids)) if self.orig_query: self.orig_query = "_type:({0}),{1}".format( ";".join(list(map(str, type_ids))), self.orig_query) else: self.orig_query = "_type:({0})".format(";".join( list(map(str, type_ids)))) if not merge_ids: # cis, counter, total, self.page, numfound, facet_ return [], {}, 0, self.page, 0, {} if current_app.config.get("USE_ES"): return SearchFromES(self.orig_query, fl=self.fl, facet_field=self.facet_field, page=self.page, count=self.count, sort=self.sort, ci_ids=merge_ids).search() else: return SearchFromDB(self.orig_query, fl=self.fl, facet_field=self.facet_field, page=self.page, count=self.count, sort=self.sort, ci_ids=merge_ids).search()
def init_cache(): db.session.remove() if current_app.config.get("USE_ES"): from api.extensions import es from api.models.cmdb import Attribute from api.lib.cmdb.utils import ValueTypeMap attributes = Attribute.get_by(to_dict=False) for attr in attributes: other = dict() other['index'] = True if attr.is_index else False if attr.value_type == ValueTypeEnum.TEXT: other['analyzer'] = 'ik_max_word' other['search_analyzer'] = 'ik_smart' if attr.is_index: other["fields"] = { "keyword": { "type": "keyword", "ignore_above": 256 } } try: es.update_mapping(attr.name, ValueTypeMap.es_type[attr.value_type], other) except Exception as e: print(e) cis = CI.get_by(to_dict=False) for ci in cis: if current_app.config.get("USE_ES"): res = es.get_index_id(ci.id) if res: continue else: res = rd.get([ci.id], REDIS_PREFIX_CI) if res and list(filter(lambda x: x, res)): continue m = api.lib.cmdb.ci.CIManager() ci_dict = m.get_ci_by_id_from_db(ci.id, need_children=False, use_master=False) if current_app.config.get("USE_ES"): es.create(ci_dict) else: rd.create_or_update({ci.id: json.dumps(ci_dict)}, REDIS_PREFIX_CI) ci_relations = CIRelation.get_by(to_dict=False) relations = dict() for cr in ci_relations: relations.setdefault(cr.first_ci_id, {}).update( {cr.second_ci_id: cr.second_ci.type_id}) for i in relations: relations[i] = json.dumps(relations[i]) if relations: rd.create_or_update(relations, REDIS_PREFIX_CI_RELATION) db.session.remove()
def __query_build_by_field(self, queries): query_sql, alias, operator = "", "A", "&" is_first, only_type_query_special = True, True for q in queries: _query_sql = "" if ":" in q: k = q.split(":")[0].strip() v = ":".join(q.split(":")[1:]).strip() current_app.logger.debug(v) field, field_type, operator, attr = self._attr_name_proc(k) if field == "_type": _query_sql = self._type_query_handler(v) current_app.logger.debug(_query_sql) elif field == "_id": # exclude all others ci = CI.get_by_id(v) if ci is not None: return 1, [str(v)] elif field: if attr is None: raise SearchError("{0} is not found".format(field)) # in query if v.startswith("(") and v.endswith(")"): _query_sql = self._in_query_handler(attr, v) # range query elif v.startswith("[") and v.endswith("]") and "_TO_" in v: _query_sql = self._range_query_handler(attr, v) # comparison query elif v.startswith(">=") or v.startswith( "<=") or v.startswith(">") or v.startswith("<"): _query_sql = self._comparison_query_handler(attr, v) else: table_name = TableMap(attr_name=attr.name).table_name _query_sql = QUERY_CI_BY_ATTR_NAME.format( table_name, attr.id, 'LIKE "{0}"'.format(v.replace("*", "%"))) else: raise SearchError( "argument q format invalid: {0}".format(q)) elif q: raise SearchError("argument q format invalid: {0}".format(q)) if is_first and _query_sql and not self.only_type_query: query_sql = "SELECT * FROM ({0}) AS {1}".format( _query_sql, alias) is_first = False alias += "A" elif self.only_type_query and only_type_query_special: is_first = False only_type_query_special = False query_sql = _query_sql elif _query_sql: query_sql = self._wrap_sql(operator, alias, _query_sql, query_sql) alias += "AA" return None, query_sql
def get(self, ci_id=None): from api.tasks.cmdb import ci_cache from api.lib.cmdb.const import CMDB_QUEUE if ci_id is not None: ci_cache.apply_async([ci_id], queue=CMDB_QUEUE) else: cis = CI.get_by(to_dict=False) for ci in cis: ci_cache.apply_async([ci.id], queue=CMDB_QUEUE) return self.jsonify(code=200)
def ci_is_exist(unique_key, unique_value): """ :param unique_key: is a attribute :param unique_value: :return: """ value_table = TableMap(attr_name=unique_key.name).table unique = value_table.get_by(attr_id=unique_key.id, value=unique_value, to_dict=False, first=True) if unique: return CI.get_by_id(unique.ci_id)
def get_children(cls, ci_id, ret_key=RetKey.NAME): second_cis = CIRelation.get_by(first_ci_id=ci_id, to_dict=False) second_ci_ids = (second_ci.second_ci_id for second_ci in second_cis) ci_type2ci_ids = dict() for ci_id in second_ci_ids: type_id = CI.get_by_id(ci_id).type_id ci_type2ci_ids.setdefault(type_id, []).append(ci_id) res = {} for type_id in ci_type2ci_ids: ci_type = CITypeCache.get(type_id) children = CIManager.get_cis_by_ids(list(map(str, ci_type2ci_ids[type_id])), ret_key=ret_key) res[ci_type.name] = children return res
def add_heartbeat(ci_type, unique_value): ci_type = CITypeManager().check_is_existed(ci_type) unique_key = AttributeCache.get(ci_type.unique_id) value_table = TableMap(attr_name=unique_key.name).table v = value_table.get_by(attr_id=unique_key.id, value=unique_value, to_dict=False, first=True) \ or abort(404, "not found") ci = CI.get_by_id(v.ci_id) or abort(404, "CI <{0}> is not found".format(v.ci_id)) ci.update(heartbeat=datetime.datetime.now())
def delete(cls, type_id): ci_type = cls.check_is_existed(type_id) if CI.get_by(type_id=type_id, first=True, to_dict=False) is not False: return abort(400, "cannot delete, because CI instance exists") for item in CITypeRelation.get_by(parent_id=type_id, to_dict=False): item.soft_delete() for item in CITypeRelation.get_by(child_id=type_id, to_dict=False): item.soft_delete() for item in PreferenceTreeView.get_by(type_id=type_id, to_dict=False): item.soft_delete() for item in PreferenceShowAttributes.get_by(type_id=type_id, to_dict=False): item.soft_delete() ci_type.soft_delete() CITypeCache.clean(type_id)
def confirm_ci_existed(ci_id): CI.get_by_id(ci_id) or abort(404, "CI <{0}> is not existed".format(ci_id))
def get_type_name(ci_id): ci = CI.get_by_id(ci_id) or abort( 404, "CI <{0}> is not existed".format(ci_id)) return CITypeCache.get(ci.type_id).name
def _delete_ci_by_id(ci_id): ci = CI.get_by_id(ci_id) ci.delete() # TODO: soft delete
def get(self, ci_id): _ci = CI.get_by_id(ci_id).to_dict() return self.jsonify(**_ci)