代码极思精致的瞬间(其二)
一 数据库插入数据 进行类型 转换
1,influxdb 数据库表名 转换成 postgresql 数据库表名称
2,influxdb 数据库字段类型转化!
fpga_type_mapping={ 'node_fpga_type':str, 'node_fpga_errors':int } fpga_field_mapping={ 'node_fpga_type':'type', 'node_fpga_errors':'errors', } @shared_task(ignore_result=True) def node_fpga_summaries(): results = cache.get(_FPGA_SQL) fpga_caches = dict() for result in results: for k, v in result.items(): host = k[1]["host"] field = k[0] for item in v: index = int( item['index']) # influx 数据库表名 转换成 postgresql 数据库表名称 val = fpga_type_mapping[field](item['value']) fpga_caches[host] = fpgas = fpga_caches.get( host, dict()) fpgas[index] = fpgas = fpgas.get( index, dict()) # 字段类型转化! fpgas.update( {fpga_field_mapping[field]: val}) try: with transaction.atomic(): update_ids = [] for k_host, v_fpgas in fpga_caches.iteritems(): try: node = Node.objects.get(hostname=k_host) except Node.DoesNotExist: continue for k_idx, v_fpga in v_fpgas.iteritems(): fpga, ret = node.fpga.update_or_create( index=k_idx, defaults=v_fpga ) update_ids.append(fpga.id) Fpga.objects.exclude(id__in=update_ids).delete() except IntegrityError: logger.exception("Failed for node Fpga summaries")
二,显示节点的所有信息:
1,前端 args 指定字段类型 后台根据类型进行查找
2,很方便的查询到 外键字段 具有高扩展性!
class NodeBase(object): columns_mapping = {} def get_range(self, *args, **kwargs): return Node.objects.all() def get_node_status_preference(self, user): logger.info("Get preference for node status") name = "monitor.policy.node.status" try: preference = Preference.objects.get(name=name) except Preference.DoesNotExist as e: logger.exception('Preference name %s does not exist', name) raise_from(CheckPreferenceException, e) else: if preference.user in [None, user]: # 'cpu_core' or 'cpu_util' for value return preference.value else: return "cpu_util" def convert_cpu_status(self, preference, cpu_util, node_id): if preference == "cpu_util": util = int(cpu_util) if util < IDLE_THRESHOLD: return "idle" elif util > BUSY_THRESHOLD: return "busy" else: return "used" else: if RunningJob.objects.filter(node__id=node_id).count() > 0: return "busy" else: return "idle" def search(self, query, argss): if 'search' not in argss: return query else: search = argss['search'] props = search['props'] keyword = search['keyword'].strip() if keyword == "": return query q = Q() for field in props: prop = field if field in self.columns_mapping: prop = self.columns_mapping[field] q |= Q(**{prop + "__icontains": keyword}) return query.filter(q) def sort_fields(self, argss): if 'sort' not in argss: return ['id'], True order = argss["sort"] prop = order['prop'] if prop in self.columns_mapping: prop = self.columns_mapping[order['prop']] if order['order'] != "ascending": prop = "-" + prop return prop # 字段排序! def sort(self, query, argss): return query.order_by(self.sort_fields(argss)) # 字段 过滤! def filters(self, query, filters): if len(filters) > 0 and filters is not None: for field in filters: if field['prop'] in self.columns_mapping: prop = self.columns_mapping[field['prop']] else: prop = field['prop'] if len(field["values"]) > 0: key = prop + "__{}".format(field["type"]) query = query.filter( **{ key: field["values"] } ) return query def params(self, args): return args class NodeList(NodeBase, APIView): permission_classes = (AsUserRole,) columns_mapping = { "status": "cpu_util", "groups": "groups__name" } def get(self, request): argss = json.loads( request.GET["args"] ) argss = self.params(argss) query = self.get_range() # 根据 args中 filters 指定的字段进行过滤! query = self.filters(query, argss['filters']) # 根据字段进行查找 query = self.search(query, argss) # 根据指定的字段进行排序! query = self.sort(query, argss) # 根据指定的数量进行返回数据!如果指定的个数多的话 按照最大进行返回 # 如果小于 那么就按照指定的数量进行返回! filtered_total = query.count() offset = argss['offset'] \ if int(argss['offset']) < filtered_total else 0 results = query[offset:offset + int(argss['length'])] offset = offset + len(results) preference = self.get_node_status_preference(request.user) return Response( { 'offset': offset, 'total': filtered_total, 'data': [self.trans_result(result, preference) for result in results], } ) # 可以根据外键进行 查找其他 返回! def trans_result(self, result, preference): groups = [] for grp in result.groups.iterator(): groups.append(grp.name) if result.gpu: gpus = result.gpu.all() gpu_cnt = gpus.count() gpu_used = [0] * gpu_cnt gpu_type = [""] * gpu_cnt for gpu in gpus: gpu_used[gpu.index] = int(gpu.occupation) gpu_type[gpu.index] = gpu.type else: gpu_used = [] gpu_type = [] if result.fpga: fpgas = result.fpga.all() fpga_cnt = fpgas.count() fpga_type = [""] * fpga_cnt for fpga in fpgas: fpga_type[fpga.index] = fpga.type else: fpga_type = [] power_status = status = "off" if result.power_status is True: power_status = "on" status = self.convert_cpu_status( preference, result.cpu_util, result.id ) return { "id": result.id, "hostname": result.hostname, "bmc_ipv4": result.bmc_ipv4, "disk_total": int(result.disk_total), "memory_total": int(result.memory_total), "mgt_ipv4": result.mgt_ipv4, "type": result.type, "processors_total": result.cpu_total, "power_status": power_status, "groups": ",".join(groups), "status": status, "gpus": { "used": gpu_used, "type": gpu_type }, "fpgas": { "type": fpga_type, } }