Beispiel #1
0
def nodeman_get_plugin_version(request, plugin, os_type):
    """根据系统获取插件版本"""
    client = BKNodeManClient(username=request.user.username)
    kwargs = {"name": plugin, "os": os_type.upper()}
    plugin_version_list = client.plugin_package(**kwargs)

    if not plugin_version_list["result"]:
        message = handle_api_error(_("节点管理(NODEMAN)"),
                                   "nodeman.plugin_package", {},
                                   plugin_version_list)
        logger.error(message)
        return JsonResponse({
            "result": plugin_version_list["result"],
            "code": plugin_version_list.get("code", "-1"),
            "message": message
        })

    data = plugin_version_list["data"]

    result = [{
        "text": version["version"],
        "value": version["version"]
    } for version in data]

    plugin_version_list["data"] = result
    return JsonResponse(plugin_version_list)
Beispiel #2
0
def get_host_id_by_inner_ip(executor, logger, bk_cloud_id: int, bk_biz_id: int,
                            ip_list: list):
    """
    根据inner_ip获取bk_host_id 对应关系dict
    """
    client = BKNodeManClient(username=executor)
    kwargs = {
        "bk_biz_id": [bk_biz_id],
        "pagesize":
        -1,
        "conditions": [{
            "key": "inner_ip",
            "value": ip_list
        }, {
            "key": "bk_cloud_id",
            "value": [bk_cloud_id]
        }],
    }
    result = client.search_host_plugin(**kwargs)

    if not result["result"]:
        error = handle_api_error(__group_name__, "nodeman.search_host_plugin",
                                 kwargs, result)
        logger.error(error)
        return {}

    return {
        host["inner_ip"]: host["bk_host_id"]
        for host in result["data"]["list"]
    }
Beispiel #3
0
    def execute(self, data, parent_data):
        executor = parent_data.inputs.executor
        client = BKNodeManClient(username=executor)
        bk_biz_id = data.inputs.biz_cc_id

        nodeman_op_target = data.inputs.nodeman_plugin_operate
        op_type = nodeman_op_target.get("nodeman_op_type", "")
        plugin = nodeman_op_target.get("nodeman_plugin", "")
        plugin_version = nodeman_op_target.get("nodeman_plugin_version", "")
        install_config = nodeman_op_target.get("install_config", [])

        host_info = data.inputs.nodeman_host_info
        input_type = host_info.get("nodeman_host_input_type", None)

        if not input_type:
            data.set_outputs("ex_data", _("请选择填写方式"))
            return False
        if input_type == "host_ip":
            bk_cloud_id = host_info.get("nodeman_bk_cloud_id", None)
            ip_list = get_ip_by_regex(host_info.get("nodeman_host_ip", ""))
            host_id_dict = get_host_id_by_inner_ip(executor, self.logger, bk_cloud_id, bk_biz_id, ip_list)

            # 过滤出未查询到host_id的ip
            no_host_id_ip = list(set(ip_list).difference(set(host_id_dict.keys())))
            if no_host_id_ip:
                data.set_outputs("ex_data", _("获取bk_host_id失败:{},请确认云区域是否正确".format(",".join(no_host_id_ip))))
                return False
            host = list(host_id_dict.values())
        else:
            host = host_info.get("nodeman_host_id", "").strip().split(",")

        # 拼装参数
        params = {
            "job_type": op_type,
            "bk_biz_id": [bk_biz_id],
            "bk_host_id": host,
            "plugin_params": {"name": plugin},
        }
        if plugin_version:
            params["plugin_params"]["version"] = plugin_version

        if op_type == "MAIN_INSTALL_PLUGIN" and install_config:
            if "keep_config" in install_config:
                params["plugin_params"].update({"keep_config": 1})
            elif "no_restart" in install_config:
                params["plugin_params"].update({"no_restart": 1})

        result = client.plugin_operate(params)

        job_is_plugin = True
        if result["result"]:
            # 这里兼容节点管理新老接口
            if plugin not in result["data"]:
                job_is_plugin = False
            job_id = result["data"].get(plugin, None) or result["data"].get("job_id", None)
            data.outputs.job_url = [get_nodeman_job_url(job_id, host_id) for host_id in host]

        return self.get_job_result(result, data, "plugin_operate", params, job_is_plugin=job_is_plugin)
Beispiel #4
0
def get_nodeman_rsa_public_key(executor, logger):
    """
    拉取节点管理rsa公钥
    """
    client = BKNodeManClient(username=executor)
    get_rsa_result = client.get_rsa_public_key(executor)
    if not get_rsa_result["result"]:
        error = handle_api_error(__group_name__, "nodeman.get_rsa_public_key",
                                 executor, get_rsa_result)
        logger.error(error)
        return False, None
    content = get_rsa_result["data"][0]["content"]
    name = get_rsa_result["data"][0]["name"]
    return True, {"name": name, "content": content}
Beispiel #5
0
def nodeman_get_ap_list(request):
    client = BKNodeManClient(username=request.user.username)
    ap_list = client.ap_list()
    if not ap_list["result"]:
        message = handle_api_error(_("节点管理(NODEMAN)"), "nodeman.ap_list", {},
                                   ap_list)
        logger.error(message)
        return JsonResponse({
            "result": ap_list["result"],
            "code": ap_list.get("code", "-1"),
            "message": message
        })

    data = ap_list["data"]

    result = [{"text": ap["name"], "value": ap["id"]} for ap in data]

    ap_list["data"] = result
    return JsonResponse(ap_list)
Beispiel #6
0
def nodeman_get_plugin_list(request, category):
    """获取插件列表"""
    client = BKNodeManClient(username=request.user.username)
    plugin_list = client.plugin_process(category)

    if not plugin_list["result"]:
        message = handle_api_error(_("节点管理(NODEMAN)"),
                                   "nodeman.plugin_process", {}, plugin_list)
        logger.error(message)
        return JsonResponse({
            "result": plugin_list["result"],
            "code": plugin_list.get("code", "-1"),
            "message": message
        })

    data = plugin_list["data"]

    result = [{"text": ap["name"], "value": ap["name"]} for ap in data]

    plugin_list["data"] = result
    return JsonResponse(plugin_list)
Beispiel #7
0
def nodeman_get_cloud_area(request):
    client = BKNodeManClient(username=request.user.username)
    cloud_area_result = client.cloud_list()
    if not cloud_area_result["result"]:
        message = handle_api_error(_("节点管理(NODEMAN)"), "nodeman.cloud_list",
                                   {}, cloud_area_result)
        logger.error(message)
        return JsonResponse({
            "result": cloud_area_result["result"],
            "code": cloud_area_result.get("code", "-1"),
            "message": message
        })

    data = cloud_area_result["data"]

    result = [{
        "text": cloud["bk_cloud_name"],
        "value": cloud["bk_cloud_id"]
    } for cloud in data]

    cloud_area_result["data"] = result
    return JsonResponse(cloud_area_result)
Beispiel #8
0
    def execute(self, data, parent_data):
        executor = parent_data.inputs.executor
        client = BKNodeManClient(username=executor)
        bk_biz_id = data.inputs.bk_biz_id

        nodeman_op_target = data.inputs.nodeman_op_target
        bk_cloud_id = nodeman_op_target.get("nodeman_bk_cloud_id", "")
        node_type = nodeman_op_target.get("nodeman_node_type", "")

        nodeman_ticket = data.get_one_of_inputs("nodeman_ticket", {})
        nodeman_tjj_ticket = nodeman_ticket.get("nodeman_tjj_ticket", "")
        if nodeman_tjj_ticket:
            try:
                nodeman_tjj_ticket = decrypt_auth_key(nodeman_tjj_ticket, settings.RSA_PRIV_KEY)
            except Exception:
                # password is not encrypted
                pass

        nodeman_op_info = data.inputs.nodeman_op_info
        op_type = nodeman_op_info.get("nodeman_op_type", "")
        nodeman_hosts = nodeman_op_info.get("nodeman_hosts", [])
        ap_id = nodeman_op_info.get("nodeman_ap_id", "")
        ip_str = nodeman_op_info.get("nodeman_ip_str", "")

        data.set_outputs("job_id", "")

        # 拼接任务类型
        job_name = "_".join([op_type, node_type])

        if job_name in itertools.chain.from_iterable([OPERATE_JOB, REMOVE_JOB]):

            # 获取bk_host_id
            ip_list = get_ip_by_regex(ip_str)
            bk_host_id_dict = get_host_id_by_inner_ip(executor, self.logger, bk_cloud_id, bk_biz_id, ip_list)
            bk_host_ids = [bk_host_id for bk_host_id in bk_host_id_dict.values()]
            # 操作类任务(升级、卸载等)
            if job_name in OPERATE_JOB:
                kwargs = {
                    "job_type": job_name,
                    "bk_biz_id": [bk_biz_id],
                    "bk_host_id": bk_host_ids,
                    "action": "job_operate",
                }

            # 移除主机
            elif job_name in REMOVE_JOB:
                kwargs = {
                    "bk_biz_id": [bk_biz_id],
                    "bk_host_id": bk_host_ids,
                    "is_proxy": True if "PROXY" in job_name else False,  # 是否移除PROXY
                    "action": "remove_host",
                }
            else:
                return False

        # 安装类任务
        elif job_name in INSTALL_JOB:

            # 安装主机信息
            all_hosts, row_host_params_list = [], []
            for host in nodeman_hosts:
                auth_type = host["auth_type"]
                auth_key = host["auth_key"]
                inner_ip_list = get_ip_by_regex(host.get("inner_ip"))
                if not inner_ip_list:
                    data.set_outputs("ex_data", _("请确认内网Ip是否合法host_info:{host}".format(host=host["inner_ip"])))
                    return False

                # 处理表格中每行的key/psw
                try:
                    auth_key = decrypt_auth_key(auth_key, settings.RSA_PRIV_KEY)
                except Exception:
                    # password is not encrypted
                    pass
                # auth_key加密
                success, ras_public_key = get_nodeman_rsa_public_key(executor, self.logger)
                if not success:
                    data.set_outputs("ex_data", _("获取节点管理公钥失败,请查看节点日志获取错误详情."))
                    return False
                auth_key = encrypt_auth_key(auth_key, ras_public_key["name"], ras_public_key["content"])
                # 表格每行基础参数
                base_params = {
                    "bk_biz_id": bk_biz_id,
                    "bk_cloud_id": bk_cloud_id,
                    "os_type": host["os_type"],
                    "port": host["port"],
                    "account": host["account"],
                    "auth_type": auth_type,
                    "ap_id": ap_id,
                    "is_manual": False,  # 不手动操作
                    "peer_exchange_switch_for_agent": 0,  # 不加速
                }

                # 支持表格中一行多ip操作, 拼装表格内的inner_ip参数
                for index, inner_ip in enumerate(inner_ip_list):
                    one = {"inner_ip": inner_ip}
                    if auth_type == "PASSWORD":
                        one["password"] = auth_key
                    else:
                        one["key"] = auth_key

                    # 重装必须要bk_host_id
                    if job_name in ["REINSTALL_PROXY", "REINSTALL_AGENT"]:
                        bk_host_id_dict = get_host_id_by_inner_ip(
                            executor, self.logger, bk_cloud_id, bk_biz_id, inner_ip_list
                        )
                        try:
                            one["bk_host_id"] = bk_host_id_dict[inner_ip]
                        except KeyError:
                            data.set_outputs("ex_data", _("获取bk_host_id失败:{},请确认云区域是否正确".format(inner_ip)))
                            return False

                    # 组装其它可选参数, ip数量需要与inner_ip一一对应
                    for ip_type in HOST_EXTRA_PARAMS:
                        if host.get(ip_type, False):
                            others_ip_list = get_ip_by_regex(host[ip_type])
                            if len(others_ip_list) == len(inner_ip_list):
                                one[ip_type] = others_ip_list[index]
                            else:
                                data.set_outputs("ex_data", _("获取{}的{}失败,请确认是否与inner_ip一一对应".format(inner_ip, ip_type)))
                                return False
                    one.update(base_params)

                    row_host_params_list.append(one)

            all_hosts.extend(row_host_params_list)

            kwargs = {"job_type": job_name, "hosts": all_hosts, "action": "job_install"}

            if nodeman_tjj_ticket:
                kwargs.update({"tcoa_ticket": nodeman_tjj_ticket})
        else:
            data.set_outputs("ex_data", _("无效的操作请求:{}".format(job_name)))
            return False

        action = kwargs.pop("action")
        result = getattr(client, action)(**kwargs)

        return self.get_job_result(result, data, action, kwargs)
Beispiel #9
0
    def schedule(self, data, parent_data, callback_data=None):
        executor = parent_data.inputs.executor
        client = BKNodeManClient(username=executor)

        job_id = data.get_one_of_outputs("job_id", "")

        if not job_id:
            self.finish_schedule()
            return True

        job_kwargs = {"job_id": job_id}
        job_result = client.job_details(**job_kwargs)

        # 获取执行结果
        if not self.get_job_result(job_result,
                                   data,
                                   "nodeman.job_details",
                                   job_kwargs,
                                   set_output_job_id=False):
            self.finish_schedule()
            return False

        result_data = job_result["data"]
        job_statistics = result_data["statistics"]
        success_num = job_statistics["success_count"]
        fail_num = job_statistics["failed_count"]
        host_list = result_data["list"]

        data.set_outputs("success_num", success_num)
        data.set_outputs("fail_num", fail_num)

        if result_data["status"] == "SUCCESS":
            self.finish_schedule()
            return True

        # 失败任务信息
        if result_data["status"] in ["FAILED", "PART_FAILED"]:
            fail_infos = [{
                "inner_ip": host["inner_ip"],
                "instance_id": host["instance_id"]
            } for host in host_list if host["status"] == "FAILED"]

            # 查询失败任务日志
            error_log = "<br>{mes}</br>".format(mes=_("操作失败主机日志信息:"))
            for fail_info in fail_infos:
                log_kwargs = {
                    "job_id": job_id,
                    "instance_id": fail_info["instance_id"],
                }
                result = client.get_job_log(**log_kwargs)

                if not result["result"]:
                    result["message"] += json.dumps(result["data"],
                                                    ensure_ascii=False)
                    error = handle_api_error(__group_name__,
                                             "nodeman.get_job_log", log_kwargs,
                                             result)
                    data.set_outputs("ex_data", error)
                    self.finish_schedule()
                    return False

                # 提取出错步骤日志
                log_info = [
                    _log for _log in result["data"]
                    if _log["status"] == "FAILED"
                ]

                error_log = "{error_log}<br><b>{host}{fail_host}</b></br><br>{log}</br>{log_info}".format(
                    error_log=error_log,
                    host=_("主机:"),
                    fail_host=fail_info["inner_ip"],
                    log=_("错误日志:"),
                    log_info="{}\n{}".format(log_info[0]["step"],
                                             log_info[0]["log"]),
                )

            data.set_outputs("ex_data", error_log)
            self.finish_schedule()
            return False
Beispiel #10
0
    def execute(self, data, parent_data):
        executor = parent_data.inputs.executor
        client = BKNodeManClient(username=executor)

        bk_biz_id = data.inputs.biz_cc_id
        bk_cloud_id = data.inputs.nodeman_bk_cloud_id
        node_type = data.inputs.nodeman_node_type
        op_type = data.inputs.nodeman_op_type
        nodeman_hosts = data.inputs.nodeman_hosts

        hosts = []

        for host in nodeman_hosts:
            conn_ips = get_ip_by_regex(host["conn_ips"])
            if len(conn_ips) == 0:
                data.set_outputs("ex_data", _("conn_ips 为空或输入格式错误"))
                return False

            one = {
                "os_type": host["os_type"],
                "has_cygwin": host["has_cygwin"],
                "port": host["port"],
                "account": host["account"],
                "auth_type": host["auth_type"],
            }
            auth_type = host["auth_type"]
            auth_key = host["auth_key"]

            login_ip = get_ip_by_regex(host.get("login_ip", ""))
            data_ip = get_ip_by_regex(host.get("data_ip", ""))
            cascade_ip = get_ip_by_regex(host.get("cascade_ip", ""))

            if login_ip:
                one.update({"login_ip": login_ip[0]})
            if data_ip:
                one.update({"data_ip": data_ip[0]})
            if cascade_ip:
                one.update({"cascade_ip": cascade_ip[0]})

            # 处理key/psw
            try:
                auth_key = rsa_decrypt_password(auth_key,
                                                settings.RSA_PRIV_KEY)
            except Exception:
                # password is not encrypted
                pass
            auth_key = nodeman_rsa_encrypt(auth_key).decode("utf-8")

            one.update({auth_type.lower(): auth_key})

            for conn_ip in conn_ips:
                dict_temp = {"conn_ips": conn_ip}
                dict_temp.update(one)
                hosts.append(dict_temp)

        agent_kwargs = {
            "bk_biz_id": bk_biz_id,
            "bk_cloud_id": bk_cloud_id,
            "node_type": node_type,
            "op_type": op_type,
            "creator": executor,
            "hosts": hosts,
        }

        agent_result = client.create_task(**agent_kwargs)
        self.logger.info(
            "nodeman created task result: {result}, api_kwargs: {kwargs}".
            format(result=agent_result, kwargs=agent_kwargs))
        if agent_result["result"]:
            data.set_outputs("job_id", agent_result["data"]["id"])
            return True
        else:
            message = "create agent install task failed: %s" % agent_result[
                "message"]
            data.set_outputs("ex_data", message)
            return False
Beispiel #11
0
    def schedule(self, data, parent_data, callback_data=None):
        bk_biz_id = data.inputs.biz_cc_id
        executor = parent_data.inputs.executor
        client = BKNodeManClient(username=executor)

        job_id = data.get_one_of_outputs("job_id")

        job_kwargs = {"bk_biz_id": bk_biz_id, "job_id": job_id}
        job_result = client.get_task_info(**job_kwargs)

        self.logger.info(
            "nodeman get task info result: {result}, api_kwargs: {kwargs}".
            format(result=job_result, kwargs=job_kwargs))

        # 任务执行失败
        if not job_result["result"]:
            self.logger.error(
                "nodeman get task info result: {result}, api_kwargs: {kwargs}".
                format(result=job_result, kwargs=job_kwargs))
            data.set_outputs("ex_data", _("查询失败,未能获得任务执行结果"))
            self.finish_schedule()
            return False

        result_data = job_result["data"]
        host_count = result_data["host_count"]
        success_num = result_data["status_count"]["success_count"]
        fail_num = result_data["status_count"]["failed_count"]
        fail_infos = []

        for host in result_data["hosts"]:
            # 安装失败
            if host["status"] == "FAILED":
                fail_infos.append({
                    "host_id": host["host"]["id"],
                    "inner_ip": host["host"]["inner_ip"]
                })

        if success_num + fail_num == host_count:
            data.set_outputs("success_num", success_num)
            data.set_outputs("fail_num", fail_num)
            if success_num == host_count:
                self.finish_schedule()
                return True
            else:
                error_log = "<br>%s</br>" % _("日志信息为:")
                for fail_info in fail_infos:
                    log_kwargs = {
                        "host_id": fail_info["host_id"],
                        "bk_biz_id": bk_biz_id,
                    }
                    result = client.get_log(**log_kwargs)
                    log_info = result["data"]["logs"]
                    error_log = "{error_log}<br><b>{host}{fail_host}</b></br><br>{log}</br>{log_info}".format(
                        error_log=error_log,
                        host=_("主机:"),
                        fail_host=fail_info["inner_ip"],
                        log=_("日志:"),
                        log_info=log_info,
                    )

                data.set_outputs("ex_data", error_log)
                self.finish_schedule()
                return False