如何确定远程 ESXI 主机是否已完全启动?

How to determine if remote ESXI Host has booted fully?

我正在编写一个 Python 脚本来远程完全启动少数 ESXI 主机,但我无法确定 ESXI 何时完成启动并准备好接收通过 SSH 发送的命令。我在 windows 主机上 运行 将脚本连接到每个 ESXI 主机,系统是 air-gapped,因此没有防火墙,也没有安全软件会干扰。

目前我正在这样做:我通过 SSH 远程进入机箱并将电源命令发送到 ESXI 主机 - 这有效并且一直有效。然后,我尝试通过 SSH 连接到每个 blade 并发送以下命令

esxcli system stats uptime get

命令无关紧要,我只需要一个响应以确保主机已启动。下面是我用来发送 SSH 命令的函数,希望得到响应

def send_command(ip, port, timeout, retry_interval, cmd, user, password):
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    retry_interval = float(retry_interval)
    timeout = int(timeout)
    timeout_start = time.time()
    worked = False 
    while worked == False:
        time.sleep(retry_interval)
        try:
            ssh.connect(ip, port, user, password, timeout=5)
            stdin,stdout,stderr=ssh.exec_command(cmd)
            outlines=stdout.readlines()
            resp=''.join(outlines)
            print(resp)
            worked = True 
            return (resp) 
        except socket_error as e:
            worked = False 
            print(e)
            continue
        except paramiko.ssh_exception.SSHException as e:
            worked = False 
            # socket is open, but not SSH service responded
            print(e) 
            continue
        except TimeoutError as e: 
            print(e)
            worked = False 
            pass
        except socket.timeout as e: 
            print(e)
            worked = False 
            continue
        except paramiko.ssh_exception.NoValidConnectionsError as e:
            print(e)
            worked = False 
            continue
        except socket.error as serr:
            print(serr)
            worked = False 
            continue 
        except IOError as e:
            print(e)
            worked = False 
            continue 
        except: 
            print(e)
            worked = False 
            continue 

我的目标是捕获所有异常足够长的时间,以便主机完成启动,然后接收响应。问题是有时它会循环几分钟(像这样启动系统时预期的那样),然后它会打印

IO error: [Errno 111] Connection refused

然后退出 function/try catch 块,永远不会建立连接。我知道这是我的异常处理的错误,因为当发生这种情况时,我停止脚本,等待几分钟,运行 再次执行它而不触及任何其他内容,esxcli 命令将完美运行并且脚本将运行良好.

如何防止 Errno 111 错误破坏我的循环?非常感谢任何帮助

编辑:一种可能的胶带解决方案是将命令更改为“esxcli system hostname get”并检查对“域”一词的响应。这可能有效,因为 IOError 似乎是一个响应而不是一个异常,不过我必须等到星期一才能测试该解决方案。

我解决了。我突然想到我正在处理任何 python 代码可能抛出的所有可能的异常,所以我的缺陷不是 python 错误,这就是为什么我在网上找不到任何关于Python、SSH 和 Errno 111 错误之间的关系。

打印输出实际上是来自 ESXI 主机的响应,我的代码正在寻找任何响应。所以我只是将 esxcli 命令从请求正常运行时间更改为

esxcli system hostname get

然后通过这个进入函数

substring = "Domain"
if substring not in resp: 
    print(resp)
    continue

我正在寻找“域”这个词,因为如果调用成功,那肯定在那里。

我是怎么想的:我在旧的英特尔 Nuc 上安装了 ESXI 7,在 kickstart 脚本中打开 SSH,启动脚本,然后打开 nuc。我使用 NUC 的原因是因为在简单的硬件上进行全新安装比 Dell Blades 启动速度更快、更安静!此外,我将 resp 变量包装在 print(type(OBJECT)) 行中,并且能够确定它实际上是一个字符串而不是错误对象。

这可能对那些有合法 Errno 111 错误的人没有帮助,我知道每次我 运行 代码时我都会 运行 进入这个错误,我只需要知道如何处理它并保持循环直到我得到我想要的响应。

编辑:我想只过滤世界“errno”然后继续循环而不是使用不同的子字符串会更容易。这将处理我所有的用例并消除对不同功能的需要。