예제 #1
0
def send_status(src,
                task_id,
                msg='',
                status=1,
                init=False,
                f_type=None,
                center_level=0):
    data = {"msg": msg, "task_id": task_id, 'src': src, 'status': status}

    cached_key = 'system:node_upgrade:task_{}'.format(task_id)
    # if status is None:
    #     data['status'] = 1
    # else:
    #     data['status'] = status

    self = Node.objects.get(role='self')
    if init and src == self.uuid:
        all_step = 7 + center_level
        if f_type == 'system':
            # 系统更新
            all_step += 5
        else:
            # 功能组件更新
            all_step += 2

        data['all_step'] = all_step
        data['now_step'] = 0
        cache.delete(cached_key)
        cache.set(cached_key, data)
    else:
        if data['status'] == 0:
            data['status'] = 1

    cache_data = cache.get(cached_key, {})
    cache_data.update(data)

    cache_data['now_step'] = cache_data.get('now_step', 0) + 1
    progress = round(
        cache_data.get('now_step') / float(cache_data.get('all_step')),
        2) * 100
    cache_data['progress'] = int(progress)
    if src == self.uuid:
        cache.set(cached_key, cache_data)
        # 更新数据库
        update_db(cache_data)
    else:
        parent = Node.objects.get(role='parent')
        if parent.api_url:
            url = parent.api_url
        else:
            url = "http://{}".format(parent.ip)
        api = NodeApi(base_url=url,
                      secret_id=parent.secret_id,
                      secret_key=parent.secret_key)
        api.request('/api/system/upgrade/progress', params=data)
    logger.error(json.dumps(cache_data, encoding="UTF-8", ensure_ascii=False))
예제 #2
0
    def process_request(cls, request):
        """
        通过查询前端传递的参数中是否为调用子节点 直接在中间件中调用子节点API并返回数据
        """
        if request.method == "GET":
            data = request.GET
        elif request.method == "POST":
            data = request.POST
        else:
            return
        sub_id = data.get('node_parent_id')  # 跨级子中心对应的上级中心 ID
        node_uuid = data.get('node_uuid')  # 所属中心的uuid
        # 无对应参数,pass该请求
        if not node_uuid:
            return
        agent = request.user.userinfo.agent
        try:
            sub_id = int(sub_id)
        except (TypeError, ValueError):
            sub_id = 0

        try:
            node_obj = models.Node.objects.get(uuid=node_uuid)
            role = node_obj.role
        except models.Node.DoesNotExist:
            node_obj = None
            role = None
        # 如果为当前中心 pass
        if role == 'self':
            return
        # 如果为当前中心的下级
        if node_obj:
            data = data.copy()
            data.pop("node_uuid")
        # 如果为当前中心的下下级
        else:
            try:
                node_obj = models.Node.objects.get(id=sub_id, agent=agent)
            except models.Node.DoesNotExist:
                return JsonResponse({
                    "status": 500,
                    "msg": "该中心不存在",
                    "error": "该三级中心不存在"
                })
            data = data.copy()
            data.pop("node_parent_id")

        node_api = NodeApi(base_url='http://{}:{}'.format(
            node_obj.ip, node_obj.port),
                           secret_id=node_obj.secret_id,
                           secret_key=node_obj.secret_key)
        result = node_api.fetch(method=request.method,
                                api=request.path,
                                params=data)
        return JsonResponse(result)
예제 #3
0
def upgrade_child(child_center, bin_file, targets, src, task_id, f_type):
    """升级下级"""
    bin_file = get_real_path(bin_file)
    for target in targets:
        if not target.get("id"):
            target['id'] = target.get("device_id")
    logger.error("start upgrade_child, child_center: {}".format(
        child_center.name))
    data = {
        "src": src,
        "type": f_type,
        "targets": targets,
        "task_id": task_id,
    }

    if child_center.api_url:
        url = child_center.api_url
    else:
        url = "http://{}".format(child_center.ip)
    api = NodeApi(base_url=url,
                  secret_id=child_center.secret_id,
                  secret_key=child_center.secret_key)
    files = {'upgrade_file': open(bin_file, 'rb')}
    send_status(src, task_id, msg='向下发送更新包')
    logger.error("start upgrade_child, child_center: {} 向下发送更新包".format(
        child_center.name))
    req = api.request('/api/system/upgrade/file/upload',
                      files=files,
                      headers={})
    # os.remove(bin_file)
    if req.get("status") != 200:
        error = json.dumps(req, encoding="UTF-8", ensure_ascii=False)
        send_status(src, task_id, status=3, msg='向下发送更新包失败')
        logger.error(
            "start upgrade_child, child_center: {} 向下发送更新包失败, errors: {}".
            format(child_center.name, error))
        return False
    send_status(src, task_id, msg='向下发送更新指令')
    logger.error("start upgrade_child, child_center: {} 向下发送更新指令".format(
        child_center.name))

    logger.debug(req)
    data['file_id'] = req['data']['file_id']
    data['u_type'] = req['data']['u_type']
    req = api.request('/api/system/upgrade', params=data)
    if req.get("status") != 200:
        error = json.dumps(req, encoding="UTF-8", ensure_ascii=False)
        params = json.dumps(data, encoding="UTF-8", ensure_ascii=False)
        send_status(src, task_id, status=3, msg='向下发送更新指令失败')
        logger.error(
            "start upgrade_child, child_center: {} 向下发送更新指令失败, 参数: {} error: {}"
            .format(child_center.name, params, error))
예제 #4
0
def get_node_detailed_status(node):
    """
    获取中心状态
    :param node: node_obj
    :return:
    """
    if not node.secret_id or not node.secret_key:
        return {}, (500, '中心配置错误')
    node_api = NodeApi(base_url='http://' + node.ip,
                       secret_id=node.secret_id,
                       secret_key=node.secret_key)
    data, msg = node_api.get_detailed_status()
    return data, msg
예제 #5
0
def get_node_status(node):
    """
    获取中心状态
    :param node: node_obj
    :return:
    """
    if not node.secret_id or not node.secret_key:
        return 0, '中心配置错误'
    node_api = NodeApi(base_url='http://' + node.ip,
                       secret_id=node.secret_id,
                       secret_key=node.secret_key)
    status, msg = node_api.get_status()
    return status, msg
예제 #6
0
 def check_parent_heartbeat(self, node):
     """
     查看上级中心的状态,以及角色变化
     :param node:
     :return:
     """
     self_node = models.Node.objects.filter(agent=node.agent,
                                            role='self').first()
     if not self_node:
         return False
     # 使用本中心的 key 作为认证
     node_api = NodeApi(base_url='http://' + node.ip,
                        auth_key=self_node.auth_key)
     data, msg = node_api.get_parent_status()
     return data
예제 #7
0
    def delete(self, request, node_id):
        """
        删除中心信息
        :param request:
        :param node_id:
        :return:
        """
        node = self.get_object(request, node_id)
        if not node:
            context = {
                "status": 500,
                "msg": "获取中心错误",
                "error": "获取中心错误",
            }
            return Response(context)
        if node.role == "self":
            context = {
                "status": 500,
                "msg": "中心删除错误",
                "error": "中心删除错误",
            }
            return Response(context)
        node.delete()
        agent_now = request.user.userinfo.agent
        self_node = models.Node.objects.filter(agent=agent_now, role='self').last()
        if node.role == 'child':
            node_api = NodeApi(
                base_url='http://' + node.ip, secret_id=node.secret_id, secret_key=node.secret_key)

            params = json.dumps({'node_type': 'parent'})
            status = node_api.clear_node(params)
            if status == 200:
                context = {
                    "status": 200,
                    "msg": "删除中心成功",
                }
            else:
                context = {
                    "status": 500,
                    "msg": "删除错误",
                }
        else:
            context = {
                "status": 500,
                "msg": "删除错误",
            }
        return Response(context)
예제 #8
0
 def get_node_api(self, node):
     """
     api
     :param node:
     :return:
     """
     api = NodeApi(base_url='http://' + node.ip,
                   secret_id=node.secret_id,
                   secret_key=node.secret_key)
     return api
예제 #9
0
 def fetch_node_topo(self, node):
     """
     获取中心 topo
     :param node:
     :return:
     """
     node_api = NodeApi(base_url='http://' + node.ip,
                        secret_id=node.secret_id,
                        secret_key=node.secret_key)
     topo = node_api.get_topo()
     if topo.get('role') == 'parent':
         topo = topo.get("children")
         if len(topo) == 1:
             topo = topo[0].get("children", [])
         else:
             topo = []
     elif topo.get('role') == 'self':
         topo = topo.get("children", [])
     else:
         topo = []
     return topo
예제 #10
0
 def delete(self, request):
     """清除上下级级联关系"""
     node_type = request.DATA.get('node_type')
     msg = ''
     agent = request.user.userinfo.agent
     self_node = models.Node.objects.filter(agent=agent, role='self').last()
     if node_type == 'parent':
         parents = models.Node.objects.filter(agent=agent, role='parent')
         for pa in parents:
             node_api = NodeApi(
                 base_url='http://' + pa.ip, auth_key=self_node.auth_key)
             status = node_api.clear_node_parent()
             if status == 200:
                 pa.delete()
         msg = '上级中心解除成功'
     elif node_type == 'children':
         children = models.Node.objects.filter(agent=request.user.userinfo.agent, role='child')
         for chi in children:
             node_api = NodeApi(
                 base_url='http://' + chi.ip, secret_id=chi.secret_id, secret_key=chi.secret_key)
             params = json.dumps({'node_type': 'parent'})
             status = node_api.clear_node(params)
             if status == 200:
                 chi.delete()
         msg = '下级中心解除成功'
     return Response({
         "status": 200,
         "msg": msg,
     })
예제 #11
0
    def post(self, request):
        """
        调用子中心API接口
        """
        api = request.data.get("api")
        node_uuid = request.data.get("uuid")
        params = request.data.get("params")
        method = request.data.get("method")

        agent = request.user.userinfo.agent
        try:
            node_obj = models.Node.objects.get(uuid=node_uuid, agent=agent)
        except models.Node.DoesNotExist:
            return Response({"status": 500, "msg": "该中心不存在", "error": "该中心不存在"})
        node_api = NodeApi(base_url='http://{}:{}'.format(node_obj.ip, node_obj.port),
                           secret_id=node_obj.secret_id, secret_key=node_obj.secret_key)
        try:
            params = json.loads(params)
        except (TypeError, ValueError):
            params = None
        result = node_api.fetch(method=method, api=api, params=params)
        return Response(result)
예제 #12
0
    def get(self, request):
        """
        级联树状拓扑
        """
        try:
            # 级联树从当前中心开下
            node_tree = models.Node.objects.get(role="self").get_dict()
        except models.Node.DoesNotExist:
            node_tree = {"name": "本中心"}
        del node_tree['auth_key']
        # 当前中心为二级中心 从数据库获取三级中心
        if node_tree['type'] == "sub_center":
            childrens = models.Node.objects.filter(agent=request.user.userinfo.agent, role='child')
            children_list = []
            for children in childrens:
                children_dict = children.get_dict()
                del children_dict['auth_key']
                children_list.append(children.get_dict())
            node_tree['children'] = children_list
    
        # 当前中心为一级中心, 从数据库获取二级中心,从API接口获取三级中心
        if node_tree['type'] == "center":
            childrens = models.Node.objects.filter(agent=request.user.userinfo.agent, role='child')
            children_list = []
            for children in childrens:
                children_dict = children.get_dict()
                del children_dict['auth_key']
                if children.type == "sub_center":                 
                    node_api = NodeApi(base_url='http://{}:{}'.format(children.ip, children.port),
                           secret_id=children.secret_id, secret_key=children.secret_key)
                    result = node_api.fetch(method="get", api=request.path)
                    status = result['status']
                    if status == 200:
                        children_dict['children'] = result['data']['children']
                children_list.append(children_dict)

            node_tree['children'] = children_list

        return Response({"status": 200, "data": node_tree})
예제 #13
0
    def get(self, request):
        """
        获取当前中心信息
        :param request:
        :return:
        """
        self_node = self.get_object(request)

        if self_node:
            data = self_node.get_dict()
        else:
            data = {
                "accept_parent_connection": 0,
                "accept_apply_policy": 0,
                "accept_apply_event_db": 0,
                "accept_apply_engine": 0,
                "accept_apply_center": 0,
                "ip": "127.0.0.1",
                "role": "self",
                "name": "127.0.0.1",
            }
        status_code = 200
        # 处理 API 请求
        if request.is_api:
            node_api = NodeApi(base_url="http://127.0.0.1:80", auth_key=self_node.auth_key)
            # todo 判断级联状态
            # 401: "下级中心不允许级联管理",
            # 403: "中心版本需要升级",
            # 404: "上级中心未添加级联",
            if data["accept_parent_connection"] == 0:
                status_code = 401
                return Response({
                    "status": status_code,
                    "msg": "下级中心不允许级联",
                    "error": "下级中心不允许级联"
                })

        context = {
            "status": status_code,
            "msg": "获取成功",
            "data": data
        }
        return Response(context)
예제 #14
0
    def send_heartbeat(self, node):
        """
        心跳检测
        :param node: obj
        :return:
        """
        if not node.auth_key:
            # 没有配置级联秘钥
            node.status = 2
            node.save()
            self.update_next_check_time(node)
            self.send_node_alert(node, "级联秘钥错误")
            return False
        if not node.secret_key or not node.secret_id:
            # fetch secret_key and secret_id
            node_api = NodeApi(base_url='http://' + node.ip,
                               auth_key=node.auth_key)
            result = node_api.fetch_auth(self_node_info=node.get_dict())
            if result["status"] == 200:
                node.secret_id = result["data"]["secret_id"]
                node.secret_key = result["data"]["secret_key"]
                node.save()
            else:
                # 级联秘钥获取 token 错误
                node.status = 2
                node.save()
                self.update_next_check_time(node)
                self.send_node_alert(node, "级联秘钥错误")
                return False
        # check status
        node_api = NodeApi(base_url='http://' + node.ip,
                           secret_id=node.secret_id,
                           secret_key=node.secret_key)
        data, msg = node_api.get_detailed_status()
        if not data:
            node.status = 2
            node.save()
            self.send_node_alert(node, msg[1])
            return False
        # 更新状态和信息
        node.status = 1
        node.last_heartbeat = timezone.now()
        node.type = data['type']
        node.save()

        self.update_next_check_time(node)

        return True