api/machine checks: rename, add checkResult
This commit is contained in:
@@ -98,7 +98,7 @@ def find_reachable_host(deploy_info: DeployInfo) -> Remote | None:
|
|||||||
return deploy_info.addrs[0]
|
return deploy_info.addrs[0]
|
||||||
|
|
||||||
for addr in deploy_info.addrs:
|
for addr in deploy_info.addrs:
|
||||||
if addr.is_ssh_reachable():
|
if addr.check_machine_ssh_reachable():
|
||||||
return addr
|
return addr
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ from dataclasses import dataclass, field
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from shlex import quote
|
from shlex import quote
|
||||||
from tempfile import TemporaryDirectory
|
from tempfile import TemporaryDirectory
|
||||||
from typing import Literal
|
|
||||||
|
|
||||||
from clan_lib.api import API
|
from clan_lib.api import API
|
||||||
from clan_lib.cmd import ClanCmdError, ClanCmdTimeoutError, CmdOut, RunOpts, run
|
from clan_lib.cmd import ClanCmdError, ClanCmdTimeoutError, CmdOut, RunOpts, run
|
||||||
@@ -74,9 +73,9 @@ class Remote:
|
|||||||
private_key=private_key if private_key is not None else self.private_key,
|
private_key=private_key if private_key is not None else self.private_key,
|
||||||
password=password if password is not None else self.password,
|
password=password if password is not None else self.password,
|
||||||
forward_agent=self.forward_agent,
|
forward_agent=self.forward_agent,
|
||||||
host_key_check=host_key_check
|
host_key_check=(
|
||||||
if host_key_check is not None
|
host_key_check if host_key_check is not None else self.host_key_check
|
||||||
else self.host_key_check,
|
),
|
||||||
verbose_ssh=self.verbose_ssh,
|
verbose_ssh=self.verbose_ssh,
|
||||||
ssh_options=self.ssh_options,
|
ssh_options=self.ssh_options,
|
||||||
tor_socks=tor_socks if tor_socks is not None else self.tor_socks,
|
tor_socks=tor_socks if tor_socks is not None else self.tor_socks,
|
||||||
@@ -425,8 +424,8 @@ class Remote:
|
|||||||
|
|
||||||
self.check_sshpass_errorcode(res)
|
self.check_sshpass_errorcode(res)
|
||||||
|
|
||||||
def is_ssh_reachable(self) -> bool:
|
def check_machine_ssh_reachable(self) -> bool:
|
||||||
return is_ssh_reachable(self)
|
return check_machine_ssh_reachable(self).ok
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
@@ -435,10 +434,16 @@ class ConnectionOptions:
|
|||||||
retries: int = 10
|
retries: int = 10
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class CheckResult:
|
||||||
|
ok: bool
|
||||||
|
reason: str | None = None
|
||||||
|
|
||||||
|
|
||||||
@API.register
|
@API.register
|
||||||
def can_ssh_login(
|
def check_machine_ssh_login(
|
||||||
remote: Remote, opts: ConnectionOptions | None = None
|
remote: Remote, opts: ConnectionOptions | None = None
|
||||||
) -> Literal["Online", "Offline"]:
|
) -> CheckResult:
|
||||||
if opts is None:
|
if opts is None:
|
||||||
opts = ConnectionOptions()
|
opts = ConnectionOptions()
|
||||||
|
|
||||||
@@ -449,7 +454,7 @@ def can_ssh_login(
|
|||||||
["true"],
|
["true"],
|
||||||
RunOpts(timeout=opts.timeout, needs_user_terminal=True),
|
RunOpts(timeout=opts.timeout, needs_user_terminal=True),
|
||||||
)
|
)
|
||||||
return "Online"
|
return CheckResult(True)
|
||||||
except ClanCmdTimeoutError:
|
except ClanCmdTimeoutError:
|
||||||
pass
|
pass
|
||||||
except ClanCmdError as e:
|
except ClanCmdError as e:
|
||||||
@@ -458,11 +463,13 @@ def can_ssh_login(
|
|||||||
else:
|
else:
|
||||||
time.sleep(opts.timeout)
|
time.sleep(opts.timeout)
|
||||||
|
|
||||||
return "Offline"
|
return CheckResult(False, f"failed after {opts.retries} attempts")
|
||||||
|
|
||||||
|
|
||||||
@API.register
|
@API.register
|
||||||
def is_ssh_reachable(remote: Remote, opts: ConnectionOptions | None = None) -> bool:
|
def check_machine_ssh_reachable(
|
||||||
|
remote: Remote, opts: ConnectionOptions | None = None
|
||||||
|
) -> CheckResult:
|
||||||
if opts is None:
|
if opts is None:
|
||||||
opts = ConnectionOptions()
|
opts = ConnectionOptions()
|
||||||
|
|
||||||
@@ -472,10 +479,10 @@ def is_ssh_reachable(remote: Remote, opts: ConnectionOptions | None = None) -> b
|
|||||||
sock.settimeout(opts.timeout)
|
sock.settimeout(opts.timeout)
|
||||||
try:
|
try:
|
||||||
sock.connect((remote.address, remote.port or 22))
|
sock.connect((remote.address, remote.port or 22))
|
||||||
return True
|
return CheckResult(True)
|
||||||
except (TimeoutError, OSError):
|
except (TimeoutError, OSError):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
time.sleep(opts.timeout)
|
time.sleep(opts.timeout)
|
||||||
|
|
||||||
return False
|
return CheckResult(False, f"failed after {opts.retries} attempts")
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ from clan_lib.nix_models.clan import (
|
|||||||
)
|
)
|
||||||
from clan_lib.nix_models.clan import InventoryMachineDeploy as MachineDeploy
|
from clan_lib.nix_models.clan import InventoryMachineDeploy as MachineDeploy
|
||||||
from clan_lib.persist.util import set_value_by_path
|
from clan_lib.persist.util import set_value_by_path
|
||||||
from clan_lib.ssh.remote import Remote, can_ssh_login
|
from clan_lib.ssh.remote import Remote, check_machine_ssh_login
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -190,8 +190,9 @@ def test_clan_create_api(
|
|||||||
target_host = machine.target_host().override(
|
target_host = machine.target_host().override(
|
||||||
private_key=private_key, host_key_check="none"
|
private_key=private_key, host_key_check="none"
|
||||||
)
|
)
|
||||||
result = can_ssh_login(target_host)
|
assert check_machine_ssh_login(target_host).ok, (
|
||||||
assert result == "Online", f"Machine {machine.name} is not online"
|
f"Machine {machine.name} is not online"
|
||||||
|
)
|
||||||
|
|
||||||
ssh_keys = [
|
ssh_keys = [
|
||||||
SSHKeyPair(
|
SSHKeyPair(
|
||||||
|
|||||||
Reference in New Issue
Block a user