Esempio n. 1
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)
Esempio n. 2
0
def get_biz_ip_from_frontend(ip_str,
                             executor,
                             biz_cc_id,
                             data,
                             logger_handle,
                             is_across=False,
                             ip_is_exist=False,
                             ignore_ex_data=False):
    """
    从前端表单中获取有效IP
    """
    # ip 字符串为空时不做处理
    if ip_str is None or not ip_str.strip():
        return True, []

    # 跨业务,不校验IP归属
    if is_across:
        plat_ip = [match.group() for match in plat_ip_reg.finditer(ip_str)]
        ip_list = [{
            "ip": _ip.split(":")[1],
            "bk_cloud_id": _ip.split(":")[0]
        } for _ip in plat_ip]
        err_msg = _("允许跨业务时IP格式需满足:【云区域ID:IP】。失败 IP: {}")
    else:
        var_ip = cc_get_ips_info_by_str(username=executor,
                                        biz_cc_id=biz_cc_id,
                                        ip_str=ip_str,
                                        use_cache=False)
        ip_list = [{
            "ip": _ip["InnerIP"],
            "bk_cloud_id": _ip["Source"]
        } for _ip in var_ip["ip_result"]]
        err_msg = _("无法从配置平台(CMDB)查询到对应 IP,请确认输入的 IP 是否合法。查询失败 IP: {}")

    # 校验Ip是否存在, 格式是否符合要求
    input_ip_set = get_ip_by_regex(ip_str)
    logger_handle.info(
        "The valid IP list is:{}, User input IP list is:{}".format(
            ip_list, input_ip_set))
    difference_ip_list = list(
        get_difference_ip_list(input_ip_set,
                               [ip_item["ip"] for ip_item in ip_list]))

    if len(ip_list) != len(set(input_ip_set)):
        difference_ip_list.sort()
        if not ignore_ex_data:
            data.outputs.ex_data = err_msg.format(",".join(difference_ip_list))
        return False, ip_list
    if not ip_list:
        if not ignore_ex_data:
            data.outputs.ex_data = _(
                "IP 为空,请确认是否输入IP,请检查IP格式是否正确:{}".format(ip_str))
        return False, ip_list
    return True, ip_list
Esempio n. 3
0
    def execute(self, data, parent_data):
        executor = parent_data.get_one_of_inputs("executor")

        client = get_client_by_user(executor)
        if parent_data.get_one_of_inputs("language"):
            setattr(client, "language", parent_data.get_one_of_inputs("language"))
            translation.activate(parent_data.get_one_of_inputs("language"))

        biz_cc_id = data.get_one_of_inputs("biz_cc_id", parent_data.inputs.biz_cc_id)
        supplier_account = supplier_account_for_business(biz_cc_id)

        # 查询主机id
        ip_list = get_ip_by_regex(data.get_one_of_inputs("cc_host_ip"))
        # 获取主机id列表
        host_result = cc_get_host_id_by_innerip(executor, biz_cc_id, ip_list, supplier_account)
        if not host_result["result"]:
            data.set_outputs("ex_data", host_result["message"])
            return False

        cc_is_increment = data.get_one_of_inputs("cc_is_increment")
        cc_module_select_method = data.get_one_of_inputs("cc_module_select_method")
        if cc_module_select_method == SelectMethod.TOPO.value:
            cc_module_select = data.get_one_of_inputs("cc_module_select_topo") or []
            filtered_modules = [module for module in cc_module_select if module.startswith("module")]
            cc_module_select = cc_format_tree_mode_id(filtered_modules)
        elif cc_module_select_method == SelectMethod.TEXT.value:
            cc_module_select_text = data.get_one_of_inputs("cc_module_select_text")
            cc_list_select_node_inst_id_return = cc_list_select_node_inst_id(
                executor, biz_cc_id, supplier_account, BkObjType.MODULE, cc_module_select_text
            )
            if not cc_list_select_node_inst_id_return["result"]:
                data.set_outputs("ex_data", cc_list_select_node_inst_id_return["message"])
                return False
            cc_module_select = cc_list_select_node_inst_id_return["data"]
        else:
            data.set_outputs("ex_data", _("请选择填参方式"))
            return False

        cc_kwargs = {
            "bk_biz_id": biz_cc_id,
            "bk_supplier_account": supplier_account,
            "bk_host_id": [int(host_id) for host_id in host_result["data"]],
            "bk_module_id": cc_module_select,
            "is_increment": True if cc_is_increment == "true" else False,
        }
        cc_result = client.cc.transfer_host_module(cc_kwargs)
        if cc_result["result"]:
            return True
        else:
            message = cc_handle_api_error("cc.transfer_host_module", cc_kwargs, cc_result)
            self.logger.error(message)
            data.set_outputs("ex_data", message)
            return False
Esempio n. 4
0
    def exec_transfer_host_module(self, data, parent_data, transfer_cmd):
        executor = parent_data.get_one_of_inputs("executor")
        supplier_account = parent_data.get_one_of_inputs(
            "biz_supplier_account")
        biz_cc_id = data.get_one_of_inputs("biz_cc_id",
                                           parent_data.inputs.biz_cc_id)

        client = get_client_by_user(executor)
        if parent_data.get_one_of_inputs("language"):
            setattr(client, "language",
                    parent_data.get_one_of_inputs("language"))
            translation.activate(parent_data.get_one_of_inputs("language"))

        # 查询主机id
        ip_list = get_ip_by_regex(data.get_one_of_inputs("cc_host_ip"))
        host_result = cc_get_host_id_by_innerip(executor, biz_cc_id, ip_list,
                                                supplier_account)
        if not host_result["result"]:
            data.set_outputs("ex_data", host_result["message"])
            return False

        transfer_kwargs = {
            "bk_supplier_account": supplier_account,
            "bk_biz_id": biz_cc_id,
            "bk_host_id": [int(host_id) for host_id in host_result["data"]],
        }

        transfer_result = getattr(client.cc, transfer_cmd)(transfer_kwargs)

        if transfer_result["result"]:
            return True
        else:
            message = cc_handle_api_error("cc.{}".format(transfer_cmd),
                                          transfer_kwargs, transfer_result)
            self.logger.error(message)
            data.set_outputs("ex_data", message)
            return False
Esempio n. 5
0
    def get_value(self):
        """
        @summary: 返回 dict 对象,将每个可从CMDB查询到的输入IP作为键,将从CMDB查询到的主机属性封装成字典作为值
        @note: 引用127.0.0.1的所有属性,如 ${value["127.0.0.1"]} -> {"bk_host_id": 999, "import_from": 3, ...}
        @note: 引用127.0.0.1的bk_host_id属性,如 ${value["127.0.0.1"]["bk_host_id"]} -> 999
        @return:
        """
        if "executor" not in self.pipeline_data or "project_id" not in self.pipeline_data:
            return "ERROR: executor and project_id of pipeline is needed"
        username = self.pipeline_data["executor"]
        project_id = self.pipeline_data["project_id"]
        project = Project.objects.get(id=project_id)
        bk_biz_id = project.bk_biz_id if project.from_cmdb else ""
        bk_supplier_account = supplier_account_for_project(project_id)
        ip_list = get_ip_by_regex(self.value)
        if not ip_list:
            return {}

        hosts_list = get_business_host(
            username,
            bk_biz_id,
            bk_supplier_account,
            [
                "bk_cpu",
                "bk_isp_name",
                "bk_os_name",
                "bk_province_name",
                "bk_host_id",
                "import_from",
                "bk_os_version",
                "bk_disk",
                "operator",
                "bk_mem",
                "bk_host_name",
                "bk_host_innerip",
                "bk_comment",
                "bk_os_bit",
                "bk_outer_mac",
                "bk_asset_id",
                "bk_service_term",
                "bk_sla",
                "bk_cpu_mhz",
                "bk_host_outerip",
                "bk_state_name",
                "bk_os_type",
                "bk_mac",
                "bk_bak_operator",
                "bk_supplier_account",
                "bk_sn",
                "bk_cpu_module",
            ],
            ip_list,
        )

        hosts = {}
        for host in hosts_list:
            ip = host["bk_host_innerip"]
            # bk_cloud_id as a dict is not needed
            if "bk_cloud_id" in host:
                host.pop("bk_cloud_id")
            hosts[ip] = host
        return hosts
Esempio n. 6
0
    def execute(self, data, parent_data):
        executor = parent_data.get_one_of_inputs("executor")
        client = get_client_by_user(executor)
        if parent_data.get_one_of_inputs("language"):
            setattr(client, "language",
                    parent_data.get_one_of_inputs("language"))
            translation.activate(parent_data.get_one_of_inputs("language"))
        biz_cc_id = int(data.get_one_of_inputs("all_biz_cc_id"))
        data.inputs.biz_cc_id = biz_cc_id
        upload_speed_limit = data.get_one_of_inputs("upload_speed_limit")
        download_speed_limit = data.get_one_of_inputs("download_speed_limit")
        job_timeout = data.get_one_of_inputs("job_timeout")

        file_source = [{
            "files": [
                _file.strip() for _file in item["files"].split("\n")
                if _file.strip()
            ],
            "ip_list": [{
                "ip":
                item["ip"],
                "bk_cloud_id":
                int(item["bk_cloud_id"]) if item["bk_cloud_id"] else 0
            }],
            "account":
            loose_strip(item["account"]),
        } for item in data.get_one_of_inputs("job_source_files", [])]

        # 拼装参数列表
        params_list = []
        for source in file_source:
            for attr in data.get_one_of_inputs("job_dispatch_attr"):
                job_account = attr["job_target_account"]
                job_target_path = attr["job_target_path"]
                ip_list = [{
                    "ip":
                    _ip,
                    "bk_cloud_id":
                    int(attr["bk_cloud_id"]) if attr["bk_cloud_id"] else 0
                } for _ip in get_ip_by_regex(attr["job_ip_list"])]
                job_kwargs = {
                    "bk_scope_type": JobBizScopeType.BIZ_SET.value,
                    "bk_scope_id": str(biz_cc_id),
                    "bk_biz_id": biz_cc_id,
                    "file_source": [source],
                    "ip_list": ip_list,
                    "account": job_account,
                    "file_target_path": job_target_path,
                }
                if upload_speed_limit:
                    job_kwargs["upload_speed_limit"] = int(upload_speed_limit)
                if download_speed_limit:
                    job_kwargs["download_speed_limit"] = int(
                        download_speed_limit)
                if job_timeout:
                    job_kwargs["timeout"] = int(job_timeout)
                params_list.append(job_kwargs)
        task_count = len(params_list)
        # 并发请求接口
        job_result_list = batch_execute_func(client.job.fast_push_file,
                                             params_list,
                                             interval_enabled=True)
        job_instance_id_list, job_inst_name, job_inst_url = [], [], []
        data.outputs.requests_error = ""
        for index, res in enumerate(job_result_list):
            job_result = res["result"]
            if job_result["result"]:
                job_instance_id_list.append(
                    job_result["data"]["job_instance_id"])
                job_inst_name.append(job_result["data"]["job_instance_name"])
                job_inst_url.append(
                    get_job_instance_url(biz_cc_id, job_instance_id_list))
            else:
                message = job_handle_api_error("job.fast_push_file",
                                               params_list[index], job_result)
                self.logger.error(message)
                data.outputs.requests_error += "{}\n".format(message)
        if data.outputs.requests_error:
            data.outputs.requests_error = "Request Error:\n{}".format(
                data.outputs.requests_error)

        # 总任务数
        data.outputs.task_count = task_count
        data.outputs.job_instance_id_list = job_instance_id_list
        # 批量请求使用
        data.outputs.job_id_of_batch_execute = job_instance_id_list
        data.outputs.job_inst_url = [
            get_job_instance_url(biz_cc_id, job_id)
            for job_id in job_instance_id_list
        ]
        # 请求成功数
        data.outputs.request_success_count = len(job_instance_id_list)
        # 执行成功数
        data.outputs.success_count = 0
        # 所有请求都失败,则返回
        if not data.outputs.request_success_count:
            data.outputs.ex_data = data.outputs.requests_error
            return False
        data.outputs.final_res = task_count == len(job_instance_id_list)
        return True
Esempio n. 7
0
    def execute(self, data, parent_data):
        executor = parent_data.get_one_of_inputs("executor")

        client = get_client_by_user(executor)
        if parent_data.get_one_of_inputs("language"):
            setattr(client, "language",
                    parent_data.get_one_of_inputs("language"))
            translation.activate(parent_data.get_one_of_inputs("language"))

        biz_cc_id = data.get_one_of_inputs("biz_cc_id",
                                           parent_data.inputs.biz_cc_id)
        supplier_account = supplier_account_for_business(biz_cc_id)
        cc_hosts = data.get_one_of_inputs("cc_host_replace_detail")
        copy_attrs = data.get_one_of_inputs("copy_attributes", True)

        # 查询主机可编辑属性
        search_attr_kwargs = {
            "bk_obj_id": "host",
            "bk_supplier_account": supplier_account
        }
        search_attr_result = client.cc.search_object_attribute(
            search_attr_kwargs)
        if not search_attr_result["result"]:
            message = cc_handle_api_error("cc.search_object_attribute",
                                          search_attr_kwargs,
                                          search_attr_result)
            self.logger.error(message)
            data.outputs.ex_data = message
            return False

        editable_attrs = []
        for item in search_attr_result["data"]:
            if item["editable"]:
                editable_attrs.append(item["bk_property_id"])

        # 拉取所有主机信息
        fault_replace_ip_map = {}
        for item in cc_hosts:
            fault_replace_ip_map["".join(get_ip_by_regex(
                item["cc_fault_ip"]))] = "".join(
                    get_ip_by_regex(item["cc_new_ip"]))

        all_hosts = []
        all_hosts.extend(list(fault_replace_ip_map.keys()))
        all_hosts.extend(list(fault_replace_ip_map.values()))

        host_attrs = editable_attrs + ["bk_host_innerip"]
        hosts_topo = cmdb.get_business_host_topo(executor, biz_cc_id,
                                                 supplier_account, host_attrs,
                                                 all_hosts)

        if not hosts_topo:
            data.outputs.ex_data = "fetch host topo for {} failed".format(
                all_hosts)
            return False

        # 只有复制故障机属性时才用到
        batch_update_kwargs = {
            "bk_obj_id": "host",
            "bk_supplier_account": supplier_account,
            "update": []
        }

        host_dict = {
            host_info["host"]["bk_host_innerip"]: host_info["host"]
            for host_info in hosts_topo
        }
        host_id_to_ip = {
            host_info["host"]["bk_host_id"]:
            host_info["host"]["bk_host_innerip"]
            for host_info in hosts_topo
        }
        fault_replace_id_map = {}

        for fault_ip, new_ip in list(fault_replace_ip_map.items()):
            fault_host = host_dict.get(fault_ip)
            new_host = host_dict.get(new_ip)

            if not fault_host:
                data.outputs.ex_data = _(
                    "无法查询到 %s 机器信息,请确认该机器是否在当前业务下") % fault_ip
                return False

            if not new_host:
                data.outputs.ex_data = _(
                    "无法查询到 %s 机器信息,请确认该机器是否在当前业务下") % new_ip
                return False

            if copy_attrs:
                update_item = {
                    "properties": {},
                    "bk_host_id": new_host["bk_host_id"]
                }
                for attr in [
                        attr for attr in editable_attrs if attr in fault_host
                ]:
                    update_item["properties"][attr] = fault_host[attr]
                batch_update_kwargs["update"].append(update_item)

            fault_replace_id_map[
                fault_host["bk_host_id"]] = new_host["bk_host_id"]

        # 更新替换机信息
        if copy_attrs:
            update_result = client.cc.batch_update_host(batch_update_kwargs)
            if not update_result["result"]:
                message = cc_handle_api_error("cc.batch_update_host",
                                              batch_update_kwargs,
                                              update_result)
                self.logger.error(message)
                data.outputs.ex_data = message
                return False

        # 将主机上交至故障机模块
        fault_transfer_kwargs = {
            "bk_supplier_account": supplier_account,
            "bk_biz_id": biz_cc_id,
            "bk_host_id": list(fault_replace_id_map.keys()),
        }
        fault_transfer_result = client.cc.transfer_host_to_faultmodule(
            fault_transfer_kwargs)
        if not fault_transfer_result["result"]:
            message = cc_handle_api_error("cc.transfer_host_to_faultmodule",
                                          fault_transfer_kwargs,
                                          fault_transfer_result)
            self.logger.error(message)
            data.set_outputs("ex_data", message)
            return False

        # 转移主机模块
        transfer_kwargs_list = []
        for host_info in hosts_topo:
            new_host_id = fault_replace_id_map.get(
                host_info["host"]["bk_host_id"])

            if new_host_id:
                transfer_kwargs_list.append({
                    "bk_biz_id":
                    biz_cc_id,
                    "bk_supplier_account":
                    supplier_account,
                    "bk_host_id": [new_host_id],
                    "bk_module_id": [
                        module_info["bk_module_id"]
                        for module_info in host_info["module"]
                    ],
                    "is_increment":
                    True,
                })

        success = []
        for kwargs in transfer_kwargs_list:
            transfer_result = client.cc.transfer_host_module(kwargs)
            if not transfer_result["result"]:
                message = cc_handle_api_error("cc.transfer_host_module",
                                              kwargs, transfer_result)
                self.logger.error(message)
                data.outputs.ex_data = "{msg}\n{success}".format(
                    msg=message, success=_("成功替换的机器: %s") % ",".join(success))
                return False

            success.append(host_id_to_ip[kwargs["bk_host_id"][0]])
Esempio n. 8
0
 def test__check_ipv4(self):
     self.assertEqual(get_ip_by_regex("256.255.2.1,10.2.1.256,10.2.1.255"), ["10.2.1.255"])
Esempio n. 9
0
 def test__empty_string(self):
     self.assertEqual(get_ip_by_regex(""), [])
Esempio n. 10
0
 def test__normal(self):
     self.assertEqual(get_ip_by_regex("1.1.1.1,2.2.2.2,3.3.3.3"), ["1.1.1.1", "2.2.2.2", "3.3.3.3"])
Esempio n. 11
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)
Esempio n. 12
0
def cc_get_ips_info_by_str(username, biz_cc_id, ip_str, use_cache=True):
    """
    @summary: 从ip_str中匹配出IP信息
    @param username
    @param biz_cc_id
    @param ip_str
    @param use_cache(deprecated)
    @note: 需要兼容的ip_str格式有
        1: IP,纯IP格式
        2: 集群名称|模块名称|IP,集群名称|模块名称|IP  这种格式可以唯一定位到一
            个IP(如果业务把相同IP放到同一模块,还是有问题)
        3: 云区域ID:IP,云区域ID:IP  这种格式可以唯一定位到一个IP,主要是兼容Job组件
            传参需要和获取Job作业模板步骤参数
    @return: {'result': True or False, 'data': [{'InnerIP': ,'HostID': ,
        'Source': , 'SetID': , 'SetName': , 'ModuleID': , 'ModuleName': , 'Sets': , 'Module': },{}]}
    """

    ip_input_list = get_ip_by_regex(ip_str)

    supplier_account = supplier_account_for_business(biz_cc_id)

    ip_list = cmdb.get_business_host_topo(
        username=username,
        bk_biz_id=biz_cc_id,
        supplier_account=supplier_account,
        host_fields=["bk_host_innerip", "bk_host_id", "bk_cloud_id"],
        ip_list=ip_input_list,
    )
    ip_result = []

    # 如果是格式2 集群名称|模块名称|IP,暂时不支持这种格式bk_host_innerip有多个值的情况
    if set_module_ip_reg.match(ip_str):
        set_module_ip_list = []
        for match in set_module_ip_reg.finditer(ip_str):
            set_module_ip_list.append(match.group())

        for ip_info in ip_list:
            match = False
            for parent_set in ip_info["set"]:
                if match:
                    break

                for parent_module in ip_info["module"]:
                    if match:
                        break

                    topo_ip = "{set}|{module}|{ip}".format(
                        set=parent_set["bk_set_name"],
                        module=parent_module["bk_module_name"],
                        ip=ip_info["host"].get("bk_host_innerip", ""),
                    )

                    if topo_ip in set_module_ip_list:
                        match = True
                        ip_result.append({
                            "InnerIP":
                            ip_info["host"].get("bk_host_innerip", ""),
                            "HostID":
                            ip_info["host"]["bk_host_id"],
                            "Source":
                            ip_info["host"].get("bk_cloud_id", -1),
                            "SetID":
                            parent_set["bk_set_id"],
                            "SetName":
                            parent_set["bk_set_name"],
                            "ModuleID":
                            parent_module["bk_module_id"],
                            "ModuleName":
                            parent_module["bk_module_name"],
                            "Sets":
                            ip_info["set"],
                            "Modules":
                            ip_info["module"],
                        })

    # 格式3 云区域ID:IP
    elif plat_ip_reg.match(ip_str):
        plat_ip = []
        for match in plat_ip_reg.finditer(ip_str):
            plat_ip.append(match.group())

        for ip_info in ip_list:
            valid_hosts = [
                x
                for x in ip_info["host"].get("bk_host_innerip", "").split(",")
                if x
                and f'{ip_info["host"].get("bk_cloud_id", -1)}:{x}' in plat_ip
            ]
            if valid_hosts:
                ip_result.append({
                    "InnerIP":
                    valid_hosts[0],  # 即使多个host命中,也都是同一个主机id,这里以第一个合法host为标识
                    "HostID":
                    ip_info["host"]["bk_host_id"],
                    "Source":
                    ip_info["host"].get("bk_cloud_id", -1),
                    "Sets":
                    ip_info["set"],
                    "Modules":
                    ip_info["module"],
                })

    # 格式1 纯IP格式
    else:
        ip = []
        for match in ip_pattern.finditer(ip_str):
            ip.append(match.group())

        proccessed = set()
        for ip_info in ip_list:
            valid_hosts = [
                x
                for x in ip_info["host"].get("bk_host_innerip", "").split(",")
                if x and x in ip
            ]
            if valid_hosts and ip_info["host"]["bk_host_id"] not in proccessed:
                ip_result.append({
                    "InnerIP":
                    valid_hosts[0],  # 即使多个host命中,也都是同一个主机id,这里以第一个合法host为标识
                    "HostID":
                    ip_info["host"]["bk_host_id"],
                    "Source":
                    ip_info["host"].get("bk_cloud_id", -1),
                    "Sets":
                    ip_info["set"],
                    "Modules":
                    ip_info["module"],
                })
                proccessed.add(ip_info["host"]["bk_host_id"])

    valid_ip = [ip_info["InnerIP"] for ip_info in ip_result]
    invalid_ip = list(set(ip_input_list) - set(valid_ip))
    result = {
        "result": True,
        "ip_result": ip_result,
        "ip_count": len(ip_result),
        "invalid_ip": invalid_ip,
    }
    return result
Esempio n. 13
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