Exemple #1
0
    def batch_update(cls, ci_ids, parents):
        """
        only for many to one
        :param ci_ids: 
        :param parents: 
        :return: 
        """
        from api.lib.cmdb.utils import TableMap

        if parents is not None and isinstance(parents, dict):
            for attr_name in parents:
                if parents[attr_name]:
                    attr = AttributeCache.get(attr_name)
                    value_table = TableMap(attr_name=attr.name).table
                    parent = value_table.get_by(attr_id=attr.id,
                                                value=parents[attr_name],
                                                first=True,
                                                to_dict=False)
                    if not parent:
                        return abort(
                            404, "{0}: {1} is not found".format(
                                attr_name, parents[attr_name]))
                    parent_id = parent.ci_id
                    for ci_id in ci_ids:
                        cls.add(parent_id, ci_id, many_to_one=True)
Exemple #2
0
    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):
            ci_relation_delete.apply_async(args=(item.first_ci_id,
                                                 item.second_ci_id),
                                           queue=CMDB_QUEUE)
            item.delete()

        for item in CIRelation.get_by(second_ci_id=ci_id, to_dict=False):
            ci_relation_delete.apply_async(args=(item.first_ci_id,
                                                 item.second_ci_id),
                                           queue=CMDB_QUEUE)
            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
Exemple #3
0
    def get_attr_values(self, fields, ci_id, ret_key="name", unique_key=None, use_master=False):
        """

        :param fields:
        :param ci_id:
        :param ret_key: It can be name or alias
        :param unique_key: primary attribute
        :param use_master: Only for master-slave read-write separation
        :return:
        """
        res = dict()
        for field in fields:
            attr = self._get_attr(field)
            if not attr:
                continue

            value_table = TableMap(attr_name=attr.name).table
            rs = value_table.get_by(ci_id=ci_id,
                                    attr_id=attr.id,
                                    use_master=use_master,
                                    to_dict=False)
            field_name = getattr(attr, ret_key)

            if attr.is_list:
                res[field_name] = [ValueTypeMap.serialize[attr.value_type](i.value) for i in rs]
            else:
                res[field_name] = ValueTypeMap.serialize[attr.value_type](rs[0].value) if rs else None

            if unique_key is not None and attr.id == unique_key.id and rs:
                res['unique'] = unique_key.name

        return res
Exemple #4
0
 def delete_attr_value(attr_id, ci_id):
     attr = AttributeCache.get(attr_id)
     if attr is not None:
         value_table = TableMap(attr_name=attr.name).table
         for item in value_table.get_by(attr_id=attr.id,
                                        ci_id=ci_id,
                                        to_dict=False):
             item.delete()
Exemple #5
0
 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)
Exemple #6
0
    def create_or_update_attr_value(self,
                                    key,
                                    value,
                                    ci,
                                    _no_attribute_policy=ExistPolicy.IGNORE):
        """
        add or update attribute value, then write history
        :param key: id, name or alias
        :param value:
        :param ci: instance object
        :param _no_attribute_policy: ignore or reject
        :return:
        """
        attr = self._get_attr(key)
        if attr is None:
            if _no_attribute_policy == ExistPolicy.IGNORE:
                return
            if _no_attribute_policy == ExistPolicy.REJECT:
                return abort(400, 'attribute {0} does not exist'.format(key))

        value_table = TableMap(attr_name=attr.name).table

        if attr.is_list:
            value_list = [
                self._validate(attr, i, value_table, ci)
                for i in handle_arg_list(value)
            ]
            if not value_list:
                self.__check_is_required(ci.type_id, attr, '')

            existed_attrs = value_table.get_by(attr_id=attr.id,
                                               ci_id=ci.id,
                                               to_dict=False)
            existed_values = [i.value for i in existed_attrs]
            added = set(value_list) - set(existed_values)
            deleted = set(existed_values) - set(value_list)
            for v in added:
                value_table.create(ci_id=ci.id, attr_id=attr.id, value=v)
                self._write_change(ci.id, attr.id, OperateType.ADD, None, v)

            for v in deleted:
                existed_attr = existed_attrs[existed_values.index(v)]
                existed_attr.delete()
                self._write_change(ci.id, attr.id, OperateType.DELETE, v, None)
        else:
            value = self._validate(attr, value, value_table, ci)
            existed_attr = value_table.get_by(attr_id=attr.id,
                                              ci_id=ci.id,
                                              first=True,
                                              to_dict=False)
            existed_value = existed_attr and existed_attr.value
            if existed_value is None:
                value_table.create(ci_id=ci.id, attr_id=attr.id, value=value)
                self._write_change(ci.id, attr.id, OperateType.ADD, None,
                                   value)
            else:
                existed_attr.update(value=value)
                self._write_change(ci.id, attr.id, OperateType.UPDATE,
                                   existed_value, value)
Exemple #7
0
    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())
Exemple #8
0
    def create_or_update_attr_value(self,
                                    key,
                                    value,
                                    ci_id,
                                    _no_attribute_policy=ExistPolicy.IGNORE):
        """
        add or update attribute value, then write history
        :param key: id, name or alias
        :param value:
        :param ci_id:
        :param _no_attribute_policy: ignore or reject
        :return:
        """
        attr = self._get_attr(key)
        if attr is None:
            if _no_attribute_policy == ExistPolicy.IGNORE:
                return
            if _no_attribute_policy == ExistPolicy.REJECT:
                return abort(400, 'attribute {0} does not exist'.format(key))

        value_table = TableMap(attr_name=attr.name).table
        existed_attr = value_table.get_by(attr_id=attr.id,
                                          ci_id=ci_id,
                                          first=True,
                                          to_dict=False)
        existed_value = existed_attr and existed_attr.value
        operate_type = OperateType.ADD if existed_attr is None else OperateType.UPDATE

        value_list = handle_arg_list(value) if attr.is_list else [value]
        if not isinstance(value, list):
            value_list = [value]

        for v in value_list:
            v = self._validate(attr, v, value_table, ci_id)
            if not v and attr.value_type != ValueTypeEnum.TEXT:
                v = None

            if operate_type == OperateType.ADD:
                if v is not None:
                    value_table.create(ci_id=ci_id, attr_id=attr.id, value=v)
                    self._write_change(ci_id, attr.id, operate_type, None, v)
            elif existed_attr.value != v:
                if v is not None:
                    existed_attr.update(value=v)
                else:
                    existed_attr.delete()
                self._write_change(ci_id, attr.id, operate_type, existed_value,
                                   v)
Exemple #9
0
    def _sort_handler(sort_by, query_sql):

        if sort_by.startswith("+"):
            sort_type = "asc"
            sort_by = sort_by[1:]
        elif sort_by.startswith("-"):
            sort_type = "desc"
            sort_by = sort_by[1:]
        else:
            sort_type = "asc"
        attr = AttributeCache.get(sort_by)
        if attr is None:
            return query_sql

        attr_id = attr.id
        value_table = TableMap(attr_name=sort_by).table

        ci_table = query_sql.subquery()
        query_sql = db.session.query(ci_table.c.id, value_table.value).join(
            value_table, value_table.ci_id == ci_table.c.id).filter(
                value_table.attr_id == attr_id).filter(
                    ci_table.deleted.is_(False)).order_by(
                        getattr(value_table.value, sort_type)())

        return query_sql
Exemple #10
0
    def _query_wrap_for_device(self, query_sql, **kwargs):
        _type = kwargs.pop("_type", False) or kwargs.pop("type", False) or kwargs.pop("ci_type", False)
        if _type:
            ci_type = CITypeCache.get(_type)
            if ci_type is None:
                return
            query_sql = query_sql.filter(CI.type_id == ci_type.id)

        for k, v in kwargs.items():
            attr = AttributeCache.get(k)
            if attr is None:
                continue

            value_table = TableMap(attr_name=k).table
            ci_table = query_sql.subquery()
            query_sql = db.session.query(ci_table.c.id).join(
                value_table, value_table.ci_id == ci_table.c.id).filter(
                value_table.attr_id == attr.id).filter(ci_table.deleted.is_(False)).filter(
                value_table.value.ilike(v.replace("*", "%")))

        # current_app.logger.debug(query_sql)
        sort_by = kwargs.pop("sort", "")
        if sort_by:
            query_sql = self._sort_handler(sort_by, query_sql)

        return query_sql
Exemple #11
0
    def __sort_by_field(self, field, sort_type, query_sql):
        attr = AttributeCache.get(field)
        attr_id = attr.id

        table_name = TableMap(attr_name=attr.name).table_name
        _v_query_sql = """SELECT {0}.ci_id, {1}.value 
                          FROM ({2}) AS {0} INNER JOIN {1} ON {1}.ci_id = {0}.ci_id
                          WHERE {1}.attr_id = {3}""".format("ALIAS", table_name, query_sql, attr_id)
        new_table = _v_query_sql

        if self.only_type_query or not self.type_id_list:
            return "SELECT SQL_CALC_FOUND_ROWS DISTINCT C.ci_id, C.value " \
                   "FROM ({0}) AS C " \
                   "ORDER BY C.value {2} " \
                   "LIMIT {1:d}, {3};".format(new_table, (self.page - 1) * self.count, sort_type, self.count)

        elif self.type_id_list:
            self.query_sql = """SELECT C.ci_id
                                FROM ({0}) AS C
                                INNER JOIN c_cis on c_cis.id=C.ci_id
                                WHERE c_cis.type_id IN ({1})""".format(new_table, ",".join(self.type_id_list))

            return """SELECT SQL_CALC_FOUND_ROWS DISTINCT C.ci_id, C.value
                      FROM ({0}) AS C
                      INNER JOIN c_cis on c_cis.id=C.ci_id
                      WHERE c_cis.type_id IN ({4})
                      ORDER BY C.value {2}
                      LIMIT {1:d}, {3};""".format(new_table,
                                                  (self.page - 1) * self.count,
                                                  sort_type, self.count,
                                                  ",".join(self.type_id_list))
Exemple #12
0
 def _comparison_query_handler(attr, v):
     table_name = TableMap(attr_name=attr.name).table_name
     if v.startswith(">=") or v.startswith("<="):
         comparison_query = "{0} '{1}'".format(v[:2], v[2:].replace("*", "%"))
     else:
         comparison_query = "{0} '{1}'".format(v[0], v[1:].replace("*", "%"))
     _query_sql = QUERY_CI_BY_ATTR_NAME.format(table_name, attr.id, comparison_query)
     return _query_sql
Exemple #13
0
    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
Exemple #14
0
    def _facet_build(self):
        facet = {}
        for f in self.facet_field:
            k, field_type, _, attr = self._attr_name_proc(f)
            if k:
                table_name = TableMap(attr_name=k).table_name
                query_sql = FACET_QUERY.format(table_name, self.query_sql, attr.id)
                current_app.logger.debug(query_sql)
                result = db.session.execute(query_sql).fetchall()
                facet[k] = result

        facet_result = dict()
        for k, v in facet.items():
            if not k.startswith('_'):
                a = getattr(AttributeCache.get(k), self.ret_key)
                facet_result[a] = [(f[0], f[1], a) for f in v]

        return facet_result
Exemple #15
0
 def _range_query_handler(attr, v):
     start, end = [x.strip() for x in v[1:-1].split("_TO_")]
     table_name = TableMap(attr_name=attr.name).table_name
     range_query = "BETWEEN '{0}' AND '{1}'".format(start.replace("*", "%"), end.replace("*", "%"))
     _query_sql = QUERY_CI_BY_ATTR_NAME.format(table_name, attr.id, range_query)
     return _query_sql
Exemple #16
0
 def _in_query_handler(attr, v):
     new_v = v[1:-1].split(";")
     table_name = TableMap(attr_name=attr.name).table_name
     in_query = " OR {0}.value ".format(table_name).join(['LIKE "{0}"'.format(_v.replace("*", "%")) for _v in new_v])
     _query_sql = QUERY_CI_BY_ATTR_NAME.format(table_name, attr.id, in_query)
     return _query_sql