def post(self, request): form, error = JsonParser( Argument('id', type=int, required=False), Argument('group_ids', type=list, filter=lambda x: len(x), help='请选择主机分组'), Argument('name', help='请输主机名称'), Argument('username', handler=str.strip, help='请输入登录用户名'), Argument('hostname', handler=str.strip, help='请输入主机名或IP'), Argument('port', type=int, help='请输入SSH端口'), Argument('pkey', required=False), Argument('desc', required=False), Argument('password', required=False), ).parse(request.body) if error is None: password = form.pop('password') private_key, public_key = AppSetting.get_ssh_key() try: if form.pkey: private_key = form.pkey elif password: with SSH(form.hostname, form.port, form.username, password=password) as ssh: ssh.add_public_key(public_key) with SSH(form.hostname, form.port, form.username, private_key) as ssh: ssh.ping() except BadAuthenticationType: return json_response(error='该主机不支持密钥认证,请参考官方文档,错误代码:E01') except AuthenticationException: if password: return json_response(error='密钥认证失败,请参考官方文档,错误代码:E02') return json_response('auth fail') group_ids = form.pop('group_ids') other = Host.objects.filter(name=form.name).first() if other and (not form.id or other.id != form.id): return json_response(error=f'已存在的主机名称【{form.name}】') if form.id: Host.objects.filter(pk=form.id).update(is_verified=True, **form) host = Host.objects.get(pk=form.id) else: host = Host.objects.create(created_by=request.user, is_verified=True, **form) _sync_host_extend(host, ssh=ssh) host.groups.set(group_ids) response = host.to_view() response['group_ids'] = group_ids return json_response(response) return json_response(error=error)
def batch_sync_host(token, hosts, password): private_key, public_key = AppSetting.get_ssh_key() threads, latest_exception, rds = [], None, get_redis_connection() max_workers = max(10, os.cpu_count() * 5) with futures.ThreadPoolExecutor(max_workers=max_workers) as executor: for host in hosts: t = executor.submit(_sync_host_extend, host, private_key, public_key, password) t.host = host threads.append(t) for t in futures.as_completed(threads): exception = t.exception() if exception: rds.rpush(token, json.dumps({'key': t.host.id, 'status': 'fail', 'message': f'{exception}'})) else: rds.rpush(token, json.dumps({'key': t.host.id, 'status': 'ok'})) t.host.is_verified = True t.host.save() rds.expire(token, 60)