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)
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
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
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
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
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
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]])
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"])
def test__empty_string(self): self.assertEqual(get_ip_by_regex(""), [])
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"])
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)
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
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