first commit to github

This commit is contained in:
pycook
2015-12-29 10:35:10 +08:00
committed by pycook
parent 755725a1b7
commit a91f409525
55 changed files with 5210 additions and 0 deletions

11
cmdb-api/core/__init__.py Normal file
View File

@@ -0,0 +1,11 @@
# -*- coding:utf-8 -*-
from attribute import attribute
from ci_type import citype
from ci_type_relation import cityperelation
from ci_relation import cirelation
from ci import ci
from history import history
from account import account
from special import special

98
cmdb-api/core/account.py Normal file
View File

@@ -0,0 +1,98 @@
# -*- coding:utf-8 -*-
from flask import Blueprint
from flask import request
from flask import g
from flask import abort
from flask import jsonify
from models import row2dict
from lib.account import AccountManager
from lib.auth import auth_with_key
account = Blueprint('account', __name__)
@account.route("/<int:uid>", methods=["GET"])
@auth_with_key
def get_user(uid=None):
manager = AccountManager()
user = manager.get_user_by_uid(uid)
if user:
return jsonify(rolenames=user.rolenames, user=row2dict(user))
else:
return jsonify(user=None)
@account.route("", methods=["POST"])
@auth_with_key
def create_user():
manager = AccountManager()
params = {}
for k, v in request.values.iteritems():
params[k] = v
user = manager.create_user(**params)
return jsonify(user=row2dict(user))
@account.route("/<int:uid>", methods=["PUT"])
@auth_with_key
def update_user(uid=None):
manager = AccountManager()
params = {}
for k, v in request.values.iteritems():
params[k] = v
ret, res = manager.update_user(uid, **params)
if not ret:
abort(res[0], res[1])
return jsonify(user=row2dict(res), rolenames=res.rolenames)
@account.route("/<int:uid>", methods=["DELETE"])
@auth_with_key
def delete_user(uid=None):
manager = AccountManager()
ret, res = manager.delete_user(uid)
if not ret:
abort(res[0], res[1])
return jsonify(uid=uid)
@account.route("/validate", methods=["POST"])
@auth_with_key
def validate():
username = request.values.get("username")
password = request.values.get("password")
manager = AccountManager()
user, authenticated = manager.validate(username, password)
if user and not authenticated:
return jsonify(code=401, user=row2dict(user), rolenames=user.rolenames)
elif not user:
return jsonify(code=404, message="user is not existed")
return jsonify(code=200, user=row2dict(user), rolenames=user.rolenames)
@account.route("/key", methods=["PUT"])
@auth_with_key
def update_key():
manager = AccountManager()
ret, res = manager.reset_key(g.user.uid)
if not ret:
abort(res[0], res[1])
return jsonify(user=row2dict(res), rolenames=res.rolenames)
@account.route("/password", methods=["PUT"])
@auth_with_key
def update_password():
manager = AccountManager()
old = request.values.get("password")
new = request.values.get("new_password")
confirm = request.values.get("confirm")
ret, res = manager.update_password(g.user.uid, old, new, confirm)
if not ret:
abort(res[0], res[1])
return jsonify(user=row2dict(res), rolenames=res.rolenames)

145
cmdb-api/core/attribute.py Normal file
View File

@@ -0,0 +1,145 @@
# -*- coding:utf-8 -*-
from flask import jsonify
from flask import request
from flask import Blueprint
from flask import abort
from flask import current_app
from lib.attribute import AttributeManager
from lib.ci_type import CITypeAttributeManager
from lib.decorator import argument_required
from lib.exception import InvalidUsageError
from lib.auth import auth_with_key
attribute = Blueprint("attribute", __name__)
@attribute.route("", methods=["GET"])
def get_attributes():
q = request.values.get("q")
attrs = AttributeManager().get_attributes(name=q)
count = len(attrs)
return jsonify(numfound=count, attributes=attrs)
@attribute.route("/<string:attr_name>", methods=["GET"])
@attribute.route("/<int:attr_id>", methods=["GET"])
def get_attribute(attr_name=None, attr_id=None):
attr_manager = AttributeManager()
attr_dict = None
if attr_name is not None:
attr_dict = attr_manager.get_attribute_by_name(attr_name)
if attr_dict is None:
attr_dict = attr_manager.get_attribute_by_alias(attr_name)
elif attr_id is not None:
attr_dict = attr_manager.get_attribute_by_id(attr_id)
if attr_dict is not None:
return jsonify(attribute=attr_dict)
abort(404, "attribute not found")
@attribute.route("", methods=["POST"])
@auth_with_key
def create_attribute():
with argument_required("attr_name"):
attr_name = request.values.get("attr_name")
current_app.logger.info(attr_name)
attr_alias = request.values.get("attr_alias", attr_name)
choice_value = request.values.get("choice_value")
is_multivalue = request.values.get("is_multivalue", False)
is_uniq = request.values.get("is_uniq", False)
is_index = request.values.get("is_index", False)
value_type = request.values.get("value_type", "text")
try:
is_multivalue = int(is_multivalue)
is_uniq = int(is_uniq)
is_index = int(is_index)
except ValueError:
raise InvalidUsageError("argument format is error")
attr_manager = AttributeManager()
kwargs = {"choice_value": choice_value, "is_multivalue": is_multivalue,
"is_uniq": is_uniq, "value_type": value_type,
"is_index": is_index}
ret, res = attr_manager.add(attr_name, attr_alias, **kwargs)
if not ret:
return abort(500, res)
return jsonify(attr_id=res)
@attribute.route("/<int:attr_id>", methods=["PUT"])
@auth_with_key
def update_attribute(attr_id=None):
with argument_required("attr_name"):
attr_name = request.values.get("attr_name")
attr_alias = request.values.get("attr_alias", attr_name)
choice_value = request.values.get("choice_value")
is_multivalue = request.values.get("is_multivalue", False)
is_uniq = request.values.get("is_uniq", False)
value_type = request.values.get("value_type", "text")
try:
is_multivalue = int(is_multivalue)
is_uniq = int(is_uniq)
except ValueError:
raise InvalidUsageError("argument format is error")
attr_manager = AttributeManager()
kwargs = {"choice_value": choice_value, "is_multivalue": is_multivalue,
"is_uniq": is_uniq, "value_type": value_type}
ret, res = attr_manager.update(attr_id, attr_name,
attr_alias, **kwargs)
if not ret:
return abort(500, res)
return jsonify(attr_id=res)
@attribute.route("/<int:attr_id>", methods=["DELETE"])
@auth_with_key
def delete_attribute(attr_id=None):
attr_manager = AttributeManager()
res = attr_manager.delete(attr_id)
return jsonify(message="attribute {0} deleted".format(res))
@attribute.route("/citype/<int:type_id>", methods=["GET"])
def get_attributes_by_type(type_id=None):
manager = CITypeAttributeManager()
from models.cmdb import CITypeCache, CIAttributeCache
t = CITypeCache.get(type_id)
if not t:
return abort(400, "CIType {0} is not existed".format(type_id))
uniq_id = t.uniq_id
unique = CIAttributeCache.get(uniq_id).attr_name
return jsonify(attributes=manager.get_attributes_by_type_id(type_id),
type_id=type_id, uniq_id=uniq_id, unique=unique)
@attribute.route("/citype/<int:type_id>", methods=["POST"])
@auth_with_key
def create_attributes_to_citype(type_id=None):
with argument_required("attr_id"):
attr_ids = request.values.get("attr_id", "")
is_required = request.values.get("is_required", False)
attr_id_list = attr_ids.strip().split(",")
if "" in attr_id_list:
attr_id_list.remove("")
attr_id_list = map(int, attr_id_list)
try:
is_required = int(is_required)
except ValueError:
abort(500, "argument format is error")
manager = CITypeAttributeManager()
manager.add(type_id, attr_id_list, is_required=is_required)
return jsonify(attributes=attr_id_list)
@attribute.route("/citype/<int:type_id>", methods=["DELETE"])
@auth_with_key
def delete_attribute_in_type(type_id=None):
with argument_required("attr_id"):
attr_ids = request.values.get("attr_id", "")
attr_id_list = attr_ids.strip().split(",")
manager = CITypeAttributeManager()
manager.delete(type_id, attr_id_list)
return jsonify(attributes=attr_id_list)

189
cmdb-api/core/ci.py Normal file
View File

@@ -0,0 +1,189 @@
# -*- coding:utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
import time
import urllib
from flask import Blueprint
from flask import request
from flask import jsonify
from flask import current_app
from flask import make_response
from flask import render_template
from flask import abort
from lib.auth import auth_with_key
from lib.ci import CIManager
from lib.search import Search
from lib.search import SearchError
from lib.utils import get_page
from lib.utils import get_per_page
from models.ci_type import CITypeCache
ci = Blueprint("ci", __name__)
@ci.route("/type/<int:type_id>", methods=["GET"])
def get_cis_by_type(type_id=None):
fields = request.args.get("fields", "").strip().split(",")
fields = filter(lambda x: x != "", fields)
ret_key = request.args.get("ret_key", "name")
if ret_key not in ('name', 'alias', 'id'):
ret_key = 'name'
page = get_page(request.values.get("page", 1))
count = get_per_page(request.values.get("count"))
manager = CIManager()
res = manager.get_cis_by_type(type_id, ret_key=ret_key,
fields=fields, page=page, per_page=count)
return jsonify(type_id=type_id, numfound=res[0],
total=len(res[2]), page=res[1], cis=res[2])
@ci.route("/<int:ci_id>", methods=['GET'])
def get_ci(ci_id=None):
fields = request.args.get("fields", "").strip().split(",")
fields = filter(lambda x: x != "", fields)
ret_key = request.args.get("ret_key", "name")
if ret_key not in ('name', 'alias', 'id'):
ret_key = 'name'
manager = CIManager()
ci = manager.get_ci_by_id(ci_id, ret_key=ret_key, fields=fields)
return jsonify(ci_id=ci_id, ci=ci)
@ci.route("/s", methods=["GET"])
@ci.route("/search", methods=["GET"])
def search():
"""@params: q: query statement
fl: filter by column
count: the number of ci
ret_key: id, name, alias
facet: statistic
wt: result format
"""
page = get_page(request.values.get("page", 1))
count = get_per_page(request.values.get("count"))
query = request.values.get('q', "")
fl = request.values.get('fl', "").split(",")
ret_key = request.values.get('ret_key', "name")
if ret_key not in ('name', 'alias', 'id'):
ret_key = 'name'
facet = request.values.get("facet", "").split(",")
wt = request.values.get('wt', 'json')
fl = filter(lambda x: x != "", fl)
facet = filter(lambda x: x != "", facet)
sort = request.values.get("sort")
start = time.time()
s = Search(query, fl, facet, page, ret_key, count, sort)
try:
response, counter, total, page, numfound, facet = s.search()
except SearchError, e:
return abort(400, str(e))
except Exception, e:
current_app.logger.error(str(e))
return abort(500, "search unknown error")
if wt == 'xml':
res = make_response(
render_template("search.xml",
counter=counter,
total=total,
result=response,
page=page,
numfound=numfound,
facet=facet))
res.headers['Content-type'] = 'text/xml'
return res
current_app.logger.debug("search time is :{0}".format(
time.time() - start))
return jsonify(numfound=numfound,
total=total,
page=page,
facet=facet,
counter=counter,
result=response)
@ci.route("", methods=["POST"])
@auth_with_key
def create_ci():
ci_type = request.values.get("ci_type")
_no_attribute_policy = request.values.get("_no_attribute_policy", "ignore")
ci_dict = dict()
for k, v in request.values.iteritems():
if k != "ci_type" and not k.startswith("_"):
ci_dict[k] = v.strip()
manager = CIManager()
current_app.logger.debug(ci_dict)
ci_id = manager.add(ci_type, exist_policy="reject",
_no_attribute_policy=_no_attribute_policy, **ci_dict)
return jsonify(ci_id=ci_id)
@ci.route("", methods=["PUT"])
@auth_with_key
def update_ci():
if request.data:
args = dict()
_args = request.data.split("&")
for arg in _args:
if arg:
args[arg.split("=")[0]] = \
urllib.unquote(urllib.unquote(arg.split("=")[1]))
else:
args = request.values
ci_type = args.get("ci_type")
_no_attribute_policy = args.get("_no_attribute_policy", "ignore")
ci_dict = dict()
for k, v in args.items():
if k != "ci_type" and not k.startswith("_"):
ci_dict[k] = v.strip()
manager = CIManager()
ci_id = manager.add(ci_type, exist_policy="replace",
_no_attribute_policy=_no_attribute_policy, **ci_dict)
return jsonify(ci_id=ci_id)
@ci.route("/<int:ci_id>", methods=["DELETE"])
@auth_with_key
def delete_ci(ci_id=None):
manager = CIManager()
manager.delete(ci_id)
return jsonify(message="ok")
@ci.route("/heartbeat/<string:ci_type>/<string:unique>", methods=["POST"])
def add_heartbeat(ci_type, unique):
if not unique or not ci_type:
return jsonify(message="error")
# return jsonify(message="ok")
return jsonify(message=CIManager().add_heartbeat(ci_type, unique))
@ci.route("/heartbeat", methods=["GET"])
def get_heartbeat():
page = get_page(request.values.get("page", 1))
ci_type = request.values.get("ci_type", "").strip()
try:
ci_type = CITypeCache.get(ci_type).type_id
except:
return jsonify(numfound=0, result=[])
agent_status = request.values.get("agent_status", None)
if agent_status:
agent_status = int(agent_status)
numfound, result = CIManager().get_heartbeat(page,
ci_type,
agent_status=agent_status)
return jsonify(numfound=numfound, result=result)

View File

@@ -0,0 +1,70 @@
# -*- coding:utf-8 -*-
from flask import Blueprint
from flask import jsonify
from flask import request
from lib.ci import CIRelationManager
from lib.utils import get_page
from lib.utils import get_per_page
from lib.auth import auth_with_key
cirelation = Blueprint("cirelation", __name__)
@cirelation.route("/types", methods=["GET"])
def get_types():
manager = CIRelationManager()
return jsonify(relation_types=manager.relation_types)
@cirelation.route("/<int:first_ci>/second_cis", methods=["GET"])
def get_second_cis_by_first_ci(first_ci=None):
page = get_page(request.values.get("page", 1))
count = get_per_page(request.values.get("count"))
relation_type = request.values.get("relation_type", "contain")
manager = CIRelationManager()
numfound, total, second_cis = manager.get_second_cis(
first_ci, page=page, per_page=count, relation_type=relation_type)
return jsonify(numfound=numfound, total=total,
page=page, second_cis=second_cis)
@cirelation.route("/<int:second_ci>/first_cis", methods=["GET"])
def get_first_cis_by_second_ci(second_ci=None):
page = get_page(request.values.get("page", 1))
count = get_per_page(request.values.get("count"))
relation_type = request.values.get("relation_type", "contain")
manager = CIRelationManager()
numfound, total, first_cis = manager.get_first_cis(
second_ci, per_page=count, page=page, relation_type=relation_type)
return jsonify(numfound=numfound, total=total,
page=page, first_cis=first_cis)
@cirelation.route("/<int:first_ci>/<int:second_ci>", methods=["POST"])
@auth_with_key
def create_ci_relation(first_ci=None, second_ci=None):
relation_type = request.values.get("relation_type", "contain")
manager = CIRelationManager()
res = manager.add(first_ci, second_ci, relation_type=relation_type)
return jsonify(cr_id=res)
@cirelation.route("/<int:cr_id>", methods=["DELETE"])
@auth_with_key
def delete_ci_relation(cr_id=None):
manager = CIRelationManager()
manager.delete(cr_id)
return jsonify(message="CIType Relation is deleted")
@cirelation.route("/<int:first_ci>/<int:second_ci>", methods=["DELETE"])
@auth_with_key
def delete_ci_relation_2(first_ci, second_ci):
manager = CIRelationManager()
manager.delete_2(first_ci, second_ci)
return jsonify(message="CIType Relation is deleted")

89
cmdb-api/core/ci_type.py Normal file
View File

@@ -0,0 +1,89 @@
# -*- coding:utf-8 -*-
from flask import Blueprint
from flask import jsonify
from flask import request
from flask import abort
from lib.ci_type import CITypeManager
from lib.decorator import argument_required
from lib.auth import auth_with_key
citype = Blueprint("citype", __name__)
@citype.route("", methods=["GET"])
def get_citypes():
type_name = request.args.get("type_name")
manager = CITypeManager()
citypes = manager.get_citypes(type_name)
count = len(citypes)
return jsonify(numfound=count, citypes=citypes)
@citype.route("/query", methods=["GET"])
def query():
with argument_required("type"):
_type = request.args.get("type")
manager = CITypeManager()
res = manager.query(_type)
return jsonify(citype=res)
@citype.route("", methods=["POST"])
@auth_with_key
def create_citype():
with argument_required("type_name"):
type_name = request.values.get("type_name")
type_alias = request.values.get("type_alias")
if type_alias is None:
type_alias = type_name
_id = request.values.get("_id")
unique = request.values.get("unique")
enabled = request.values.get("enabled", True)
icon_url = request.values.get("icon_url", "")
manager = CITypeManager()
ret, res = manager.add(type_name, type_alias, _id=_id,
unique=unique, enabled=enabled,
icon_url=icon_url)
if ret:
return jsonify(type_id=res)
abort(500, res)
@citype.route("/<int:type_id>", methods=["PUT"])
@auth_with_key
def update_citype(type_id=None):
type_name = request.values.get("type_name")
type_alias = request.values.get("type_alias")
_id = request.values.get("_id")
unique = request.values.get("unique")
icon_url = request.values.get("icon_url")
enabled = request.values.get("enabled")
enabled = False if enabled in (0, "0") else True \
if enabled is not None else None
manager = CITypeManager()
ret, res = manager.update(type_id, type_name, type_alias, _id=_id,
unique=unique, icon_url=icon_url,
enabled=enabled)
if ret:
return jsonify(type_id=type_id)
abort(500, res)
@citype.route("/<int:type_id>", methods=["DELETE"])
@auth_with_key
def delete_citype(type_id=None):
manager = CITypeManager()
res = manager.delete(type_id)
return jsonify(message=res)
@citype.route("/enable/<int:type_id>", methods=["GET", "POST"])
def enable(type_id=None):
enable = request.values.get("enable", True)
manager = CITypeManager()
manager.set_enabled(type_id, enabled=enable)
return jsonify(type_id=type_id)

View File

@@ -0,0 +1,55 @@
# -*- coding:utf-8 -*-
from flask import Blueprint
from flask import jsonify
from flask import request
from lib.ci_type import CITypeRelationManager
from lib.auth import auth_with_key
cityperelation = Blueprint("cityperelation", __name__)
@cityperelation.route("/types", methods=["GET"])
def get_types():
manager = CITypeRelationManager()
return jsonify(relation_types=manager.relation_types)
@cityperelation.route("/<int:parent>/children", methods=["GET"])
def get_children_by_parent(parent=None):
manager = CITypeRelationManager()
return jsonify(children=manager.get_children(parent))
@cityperelation.route("/<int:child>/parents", methods=["GET"])
def get_parents_by_child(child=None):
manager = CITypeRelationManager()
return jsonify(parents=manager.get_parents(child))
@cityperelation.route("/<int:parent>/<int:child>", methods=["POST"])
@auth_with_key
def create_citype_realtions(parent=None, child=None):
relation_type = request.values.get("relation_type", "contain")
manager = CITypeRelationManager()
res = manager.add(parent, child, relation_type=relation_type)
return jsonify(ctr_id=res)
@cityperelation.route("/<int:ctr_id>", methods=["DELETE"])
@auth_with_key
def delete_citype_relation(ctr_id=None):
manager = CITypeRelationManager()
manager.delete(ctr_id)
return jsonify(message="CIType Relation is deleted")
@cityperelation.route("/<int:parent>/<int:child>", methods=["DELETE"])
@auth_with_key
def delete_citype_relation_2(parent=None, child=None):
manager = CITypeRelationManager()
manager.delete_2(parent, child)
return jsonify(message="CIType Relation is deleted")

116
cmdb-api/core/history.py Normal file
View File

@@ -0,0 +1,116 @@
# -*- coding:utf-8 -*-
import datetime
from flask import jsonify
from flask import current_app
from flask import Blueprint
from flask import request
from flask import abort
from models.history import OperationRecord
from models.history import CIRelationHistory
from models.history import CIAttributeHistory
from models.attribute import CIAttributeCache
from extensions import db
from models import row2dict
from models.account import UserCache
from lib.ci import CIManager
from lib.utils import get_page
history = Blueprint("history", __name__)
@history.route("/record", methods=["GET"])
def get_record():
page = get_page(request.values.get("page", 1))
_start = request.values.get("start")
_end = request.values.get("end")
username = request.values.get("username", "")
per_page_cnt = current_app.config.get("DEFAULT_PAGE_COUNT")
start, end = None, None
if _start:
try:
start = datetime.datetime.strptime(_start, '%Y-%m-%d %H:%M:%S')
except ValueError:
abort(400, 'incorrect start date time')
if _end:
try:
end = datetime.datetime.strptime(_end, '%Y-%m-%d %H:%M:%S')
except ValueError:
abort(400, 'incorrect end date time')
records = db.session.query(OperationRecord)
numfound = db.session.query(db.func.count(OperationRecord.record_id))
if start:
records = records.filter(OperationRecord.timestamp >= start)
numfound = numfound.filter(OperationRecord.timestamp >= start)
if end:
records = records.filter(OperationRecord.timestamp <= end)
numfound = records.filter(OperationRecord.timestamp <= end)
if username:
user = UserCache.get(username)
if user:
records = records.filter(OperationRecord.uid == user.uid)
else:
return jsonify(numfound=0, records=[],
page=1, total=0, start=_start,
end=_end, username=username)
records = records.order_by(-OperationRecord.record_id).offset(
per_page_cnt * (page - 1)).limit(per_page_cnt).all()
total = len(records)
numfound = numfound.first()[0]
res = []
for record in records:
_res = row2dict(record)
_res["user"] = UserCache.get(_res.get("uid")).nickname \
if UserCache.get(_res.get("uid")).nickname \
else UserCache.get(_res.get("uid")).username
attr_history = db.session.query(CIAttributeHistory.attr_id).filter(
CIAttributeHistory.record_id == _res.get("record_id")).all()
_res["attr_history"] = [CIAttributeCache.get(h.attr_id).attr_alias
for h in attr_history]
rel_history = db.session.query(CIRelationHistory.operate_type).filter(
CIRelationHistory.record_id == _res.get("record_id")).all()
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.res.operate_type] += 1
_res["rel_history"] = rel_statis
res.append(_res)
return jsonify(numfound=numfound, records=res, page=page, total=total,
start=_start, end=_end, username=username)
@history.route("/<int:record_id>", methods=["GET"])
def get_detail_by_record(record_id=None):
record = db.session.query(OperationRecord).filter(
OperationRecord.record_id == record_id).first()
if record is None:
abort(404, "record is not found")
username = UserCache.get(record.uid).nickname \
if UserCache.get(record.uid).nickname \
else UserCache.get(record.uid).username
timestamp = record.timestamp.strftime("%Y-%m-%d %H:%M:%S")
attr_history = db.session.query(CIAttributeHistory).filter(
CIAttributeHistory.record_id == record_id).all()
rel_history = db.session.query(CIRelationHistory).filter(
CIRelationHistory.record_id == record_id).all()
attr_dict, rel_dict = dict(), {"add": [], "delete": []}
for attr_h in attr_history:
attr_dict[CIAttributeCache.get(attr_h.attr_id).attr_alias] = {
"old": attr_h.old, "new": attr_h.new,
"operate_type": attr_h.operate_type}
manager = CIManager()
for rel_h in rel_history:
_, first = manager.get_ci_by_id(rel_h.first_ci_id)
_, second = manager.get_ci_by_id(rel_h.second_ci_id)
rel_dict[rel_h.operate_type].append(
(first, rel_h.relation_type, second))
return jsonify(username=username, timestamp=timestamp,
attr_history=attr_dict,
rel_history=rel_dict)

16
cmdb-api/core/special.py Normal file
View File

@@ -0,0 +1,16 @@
# -*- coding:utf-8 -*-
from flask import Blueprint
from flask import jsonify
special = Blueprint(__name__, "special")
@special.route("/api/v0.1/special", methods=["GET"])
def index():
"""
定义专用接口
"""
return jsonify(code=200)

12
cmdb-api/core/statis.py Normal file
View File

@@ -0,0 +1,12 @@
# -*- coding:utf-8 -*-
from flask import Blueprint
statis = Blueprint("statis", __name__)
@statis.route("")
def statis():
pass