cmdb/cmdb-api/api/views/cmdb/ci.py

243 lines
8.2 KiB
Python

# -*- coding:utf-8 -*-
import time
import six
from flask import abort
from flask import current_app
from flask import request
from api.lib.cmdb.cache import CITypeCache
from api.lib.cmdb.ci import CIManager
from api.lib.cmdb.ci import CIRelationManager
from api.lib.cmdb.const import ExistPolicy
from api.lib.cmdb.const import ResourceTypeEnum, PermEnum
from api.lib.cmdb.const import RetKey
from api.lib.cmdb.perms import has_perm_for_ci
from api.lib.cmdb.search import SearchError
from api.lib.cmdb.search.ci import search
from api.lib.perm.acl.acl import has_perm_from_args
from api.lib.utils import get_page
from api.lib.utils import get_page_size
from api.lib.utils import handle_arg_list
from api.models.cmdb import CI
from api.resource import APIView
class CIsByTypeView(APIView):
url_prefix = "/ci/type/<int:type_id>"
def get(self, type_id):
fields = handle_arg_list(request.values.get("fields", ""))
ret_key = request.values.get("ret_key", RetKey.NAME)
if ret_key not in (RetKey.NAME, RetKey.ALIAS, RetKey.ID):
ret_key = RetKey.NAME
page = get_page(request.values.get("page", 1))
count = get_page_size(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 self.jsonify(type_id=type_id,
numfound=res[0],
total=len(res[2]),
page=res[1],
cis=res[2])
class CIView(APIView):
url_prefix = ("/ci/<int:ci_id>", "/ci")
def get(self, ci_id):
fields = handle_arg_list(request.values.get("fields", ""))
ret_key = request.values.get("ret_key", RetKey.NAME)
if ret_key not in (RetKey.NAME, RetKey.ALIAS, RetKey.ID):
ret_key = RetKey.NAME
manager = CIManager()
ci = manager.get_ci_by_id_from_db(ci_id, ret_key=ret_key, fields=fields, valid=True)
return self.jsonify(ci_id=ci_id, ci=ci)
@staticmethod
def _wrap_ci_dict():
ci_dict = {k: v.strip() if isinstance(v, six.string_types) else v for k, v in request.values.items()
if k != "ci_type" and not k.startswith("_")}
return ci_dict
@has_perm_for_ci("ci_type", ResourceTypeEnum.CI, PermEnum.ADD, lambda x: CITypeCache.get(x))
def post(self):
ci_type = request.values.get("ci_type")
_no_attribute_policy = request.values.get("no_attribute_policy", ExistPolicy.IGNORE)
exist_policy = request.values.pop('exist_policy', None)
ci_dict = self._wrap_ci_dict()
manager = CIManager()
current_app.logger.debug(ci_dict)
ci_id = manager.add(ci_type,
exist_policy=exist_policy or ExistPolicy.REJECT,
_no_attribute_policy=_no_attribute_policy,
_is_admin=request.values.pop('__is_admin', False),
**ci_dict)
return self.jsonify(ci_id=ci_id)
@has_perm_for_ci("ci_id", ResourceTypeEnum.CI, PermEnum.UPDATE, CIManager.get_type)
def put(self, ci_id=None):
args = request.values
current_app.logger.info(args)
ci_type = args.get("ci_type")
_no_attribute_policy = args.get("no_attribute_policy", ExistPolicy.IGNORE)
ci_dict = self._wrap_ci_dict()
manager = CIManager()
if ci_id is not None:
manager.update(ci_id,
_is_admin=request.values.pop('__is_admin', False),
**ci_dict)
else:
ci_id = manager.add(ci_type,
exist_policy=ExistPolicy.REPLACE,
_no_attribute_policy=_no_attribute_policy,
_is_admin=request.values.pop('__is_admin', False),
**ci_dict)
return self.jsonify(ci_id=ci_id)
@has_perm_for_ci("ci_id", ResourceTypeEnum.CI, PermEnum.DELETE, CIManager.get_type)
def delete(self, ci_id):
manager = CIManager()
manager.delete(ci_id)
return self.jsonify(message="ok")
class CIDetailView(APIView):
url_prefix = "/ci/<int:ci_id>/detail"
def get(self, ci_id):
_ci = CI.get_by_id(ci_id).to_dict()
return self.jsonify(**_ci)
class CISearchView(APIView):
url_prefix = ("/ci/s", "/ci/search")
def get(self):
"""@params: q: query statement
fl: filter by column
count/page_size: the number of ci
ret_key: id, name, alias
facet: statistic
"""
page = get_page(request.values.get("page", 1))
count = get_page_size(request.values.get("count") or request.values.get("page_size"))
query = request.values.get('q', "")
fl = handle_arg_list(request.values.get('fl', ""))
excludes = handle_arg_list(request.values.get('excludes', ""))
ret_key = request.values.get('ret_key', RetKey.NAME)
if ret_key not in (RetKey.NAME, RetKey.ALIAS, RetKey.ID):
ret_key = RetKey.NAME
facet = handle_arg_list(request.values.get("facet", ""))
sort = request.values.get("sort")
start = time.time()
s = search(query, fl, facet, page, ret_key, count, sort, excludes)
try:
response, counter, total, page, numfound, facet = s.search()
except SearchError as e:
return abort(400, str(e))
if request.values.get('need_children') in current_app.config.get('BOOL_TRUE') and len(response) == 1:
children = CIRelationManager.get_children(response[0]['_id'], ret_key=ret_key) # one floor
response[0].update(children)
current_app.logger.debug("search time is: {0}".format(time.time() - start))
return self.jsonify(numfound=numfound,
total=total,
page=page,
facet=facet,
counter=counter,
result=response)
def post(self):
return self.get()
class CIUnique(APIView):
url_prefix = "/ci/<int:ci_id>/unique"
@has_perm_from_args("ci_id", ResourceTypeEnum.CI, PermEnum.UPDATE, CIManager.get_type_name)
def put(self, ci_id):
params = request.values
unique_name = params.keys()[0]
unique_value = params.values()[0]
CIManager.update_unique_value(ci_id, unique_name, unique_value)
return self.jsonify(ci_id=ci_id)
class CIHeartbeatView(APIView):
url_prefix = ("/ci/heartbeat", "/ci/heartbeat/<string:ci_type>/<string:unique>")
def get(self):
page = get_page(request.values.get("page", 1))
ci_type = request.values.get("ci_type", "").strip()
try:
type_id = CITypeCache.get(ci_type).type_id
except AttributeError:
return self.jsonify(numfound=0, result=[])
agent_status = request.values.get("agent_status")
if agent_status:
agent_status = int(agent_status)
numfound, result = CIManager.get_heartbeat(page, type_id, agent_status=agent_status)
return self.jsonify(numfound=numfound, result=result)
def post(self, ci_type, unique):
if not unique or not ci_type:
return self.jsonify(message="error")
msg, cmd = CIManager().add_heartbeat(ci_type, unique)
return self.jsonify(message=msg, cmd=cmd)
class CIFlushView(APIView):
url_prefix = ("/ci/flush", "/ci/<int:ci_id>/flush")
# @auth_abandoned
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)
class CIAutoDiscoveryStatisticsView(APIView):
url_prefix = "/ci/adc/statistics"
def get(self):
return self.jsonify(CIManager.get_ad_statistics())