mirror of https://github.com/veops/cmdb.git
170 lines
6.6 KiB
Python
170 lines
6.6 KiB
Python
# -*- coding:utf-8 -*-
|
|
|
|
|
|
import datetime
|
|
|
|
from flask import current_app
|
|
|
|
from extensions import db
|
|
from models.attribute import CIAttributeCache
|
|
from lib.attribute import AttributeManager
|
|
from lib.const import type_map
|
|
from lib.const import TableMap
|
|
|
|
|
|
class AttributeValueManager(object):
|
|
"""
|
|
manage CI attribute values
|
|
"""
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
def _get_attr(self, key):
|
|
"""key is one of attr_id, attr_name and attr_alias
|
|
"""
|
|
attr = CIAttributeCache.get(key)
|
|
return attr
|
|
|
|
def _get_attr_values(self, fields, ci_id,
|
|
ret_key="name",
|
|
uniq_key=None,
|
|
use_master=False):
|
|
res = dict()
|
|
for field in fields:
|
|
attr = CIAttributeCache.get(field)
|
|
if not attr:
|
|
current_app.logger.warn('attribute %s not found' % field)
|
|
return res
|
|
table = TableMap(attr_name=attr.attr_name).table
|
|
if use_master:
|
|
rs = db.session().using_bind("master").query(
|
|
table.value).filter_by(ci_id=ci_id).filter_by(
|
|
attr_id=attr.attr_id)
|
|
else:
|
|
rs = db.session.query(table.value).filter_by(
|
|
ci_id=ci_id).filter_by(attr_id=attr.attr_id)
|
|
field_name = getattr(attr, "attr_{0}".format(ret_key))
|
|
try:
|
|
if attr.is_multivalue:
|
|
if attr.value_type == 'datetime':
|
|
res[field_name] = [datetime.datetime.strftime(
|
|
x.value, '%Y-%m-%d %H:%M:%S') for x in rs.all()]
|
|
else:
|
|
res[field_name] = [x.value for x in rs.all()]
|
|
else:
|
|
x = rs.first()
|
|
if x:
|
|
if attr.value_type == 'datetime':
|
|
res[field_name] = datetime.datetime.strftime(
|
|
rs.first().value, '%Y-%m-%d %H:%M:%S')
|
|
else:
|
|
res[field_name] = rs.first().value
|
|
else:
|
|
res[field_name] = None
|
|
except AttributeError as e:
|
|
current_app.logger.warn("get ci by id error, {0}".format(e))
|
|
if attr.is_multivalue:
|
|
res[field_name] = list()
|
|
else:
|
|
res[field_name] = ""
|
|
if uniq_key is not None and attr.attr_id == uniq_key.attr_id \
|
|
and rs.first() is not None:
|
|
res['unique'] = uniq_key.attr_name
|
|
return res
|
|
|
|
def _validate(self, attr, value, table, ci_id):
|
|
converter = type_map.get("converter").get(attr.value_type)
|
|
try:
|
|
v = converter(value)
|
|
except ValueError:
|
|
return False, "attribute value {0} converter fail".format(value)
|
|
if attr.is_choice:
|
|
choice_list = AttributeManager()._get_choice_value(
|
|
attr.attr_id, attr.value_type)
|
|
if v not in choice_list:
|
|
return False, "{0} is not existed in choice values".format(
|
|
value)
|
|
elif attr.is_uniq:
|
|
old_value = db.session.query(table.attr_id).filter(
|
|
table.attr_id == attr.attr_id).filter(
|
|
table.value == v).filter(table.ci_id != ci_id).first()
|
|
if old_value is not None:
|
|
return False, "attribute {0} value {1} must be unique".format(
|
|
attr.attr_name, value)
|
|
return True, v
|
|
|
|
def add_attr_value(self, key, value, ci_id, ci_type,
|
|
_no_attribute_policy="ignore", ci_existed=False):
|
|
"""key is one of attr_id, attr_name and attr_alias
|
|
"""
|
|
attr = self._get_attr(key)
|
|
if attr is None:
|
|
if _no_attribute_policy == 'ignore':
|
|
return True, None
|
|
if _no_attribute_policy == 'reject':
|
|
return False, 'attribute {0} not exist'.format(key)
|
|
table, old_value, old_value_table = TableMap(
|
|
attr_name=attr.attr_name).table, None, None
|
|
if ci_existed:
|
|
old_value_table = db.session.query(table).filter(
|
|
table.attr_id == attr.attr_id).filter(
|
|
table.ci_id == ci_id).first()
|
|
if old_value_table is not None:
|
|
old_value = old_value_table.value
|
|
if not value and ci_existed:
|
|
db.session.query(table).filter(
|
|
table.attr_id == attr.attr_id).filter(
|
|
table.ci_id == ci_id).delete()
|
|
if old_value:
|
|
return True, (attr.attr_id, "delete", old_value, None)
|
|
else:
|
|
return True, None
|
|
elif not value:
|
|
return True, None
|
|
if not attr.is_multivalue:
|
|
ret, res = self._validate(attr, value, table, ci_id)
|
|
if not ret:
|
|
return False, res
|
|
value_table = table()
|
|
if ci_existed: # for history
|
|
old = db.session.query(table).filter(
|
|
table.attr_id == attr.attr_id).filter(
|
|
table.value == value).filter(
|
|
table.ci_id == ci_id).first()
|
|
if old is not None:
|
|
return True, None
|
|
elif old_value_table:
|
|
value_table = old_value_table
|
|
value_table.ci_id = ci_id
|
|
value_table.attr_id = attr.attr_id
|
|
value_table.value = res
|
|
db.session.add(value_table)
|
|
elif attr.is_multivalue:
|
|
if ci_existed:
|
|
db.session.query(table).filter(
|
|
table.attr_id == attr.attr_id).filter(
|
|
table.ci_id == ci_id).delete()
|
|
|
|
for v in value.strip().split(","):
|
|
ret, res = self._validate(attr, v, table, ci_id)
|
|
if not ret:
|
|
return False, res
|
|
value_table = table()
|
|
value_table.ci_id = ci_id
|
|
value_table.attr_id = attr.attr_id
|
|
value_table.value = res
|
|
db.session.add(value_table)
|
|
try:
|
|
db.session.commit()
|
|
except Exception as e:
|
|
db.session.rollback()
|
|
current_app.logger.error(
|
|
"add attribute value is error, {0}".format(str(e)))
|
|
return False, "add attribute value is error, {0}".format(str(e))
|
|
if ci_existed:
|
|
if old_value != value:
|
|
return True, (attr.attr_id, "update", old_value, value)
|
|
else:
|
|
return True, None
|
|
return True, (attr.attr_id, "add", None, value) |