clan_cli: Made qmp implementation lazy
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
import json
|
||||
import logging
|
||||
from collections.abc import Generator
|
||||
from contextlib import contextmanager
|
||||
from os import path
|
||||
from pathlib import Path
|
||||
from tempfile import NamedTemporaryFile
|
||||
from time import sleep
|
||||
from tempfile import NamedTemporaryFile, TemporaryDirectory
|
||||
|
||||
from clan_cli.dirs import vm_state_dir
|
||||
from qemu.qmp import QEMUMonitorProtocol
|
||||
|
||||
from ..cmd import run
|
||||
@@ -16,6 +16,39 @@ from ..ssh import Host, parse_deployment_address
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class VMAttr:
|
||||
def __init__(self, machine_name: str) -> None:
|
||||
self.temp_dir = TemporaryDirectory(prefix="clan_vm-", suffix=f"-{machine_name}")
|
||||
self._qmp_socket: Path = Path(self.temp_dir.name) / "qmp.sock"
|
||||
self._qga_socket: Path = Path(self.temp_dir.name) / "qga.sock"
|
||||
self._qmp: QEMUMonitorProtocol | None = None
|
||||
|
||||
@contextmanager
|
||||
def qmp(self) -> Generator[QEMUMonitorProtocol, None, None]:
|
||||
if self._qmp is None:
|
||||
log.debug(f"qmp_socket: {self._qmp_socket}")
|
||||
self._qmp = QEMUMonitorProtocol(path.realpath(self._qmp_socket))
|
||||
self._qmp.connect()
|
||||
try:
|
||||
yield self._qmp
|
||||
finally:
|
||||
self._qmp.close()
|
||||
|
||||
@property
|
||||
def qmp_socket(self) -> Path:
|
||||
if self._qmp is None:
|
||||
log.debug(f"qmp_socket: {self._qmp_socket}")
|
||||
self._qmp = QEMUMonitorProtocol(path.realpath(self._qmp_socket))
|
||||
return self._qmp_socket
|
||||
|
||||
@property
|
||||
def qga_socket(self) -> Path:
|
||||
if self._qmp is None:
|
||||
log.debug(f"qmp_socket: {self.qga_socket}")
|
||||
self._qmp = QEMUMonitorProtocol(path.realpath(self._qmp_socket))
|
||||
return self._qga_socket
|
||||
|
||||
|
||||
class Machine:
|
||||
def __init__(
|
||||
self,
|
||||
@@ -36,14 +69,8 @@ class Machine:
|
||||
self.build_cache: dict[str, Path] = {}
|
||||
|
||||
self._deployment_info: None | dict[str, str] = deployment_info
|
||||
state_dir = vm_state_dir(flake_url=str(self.flake), vm_name=self.name)
|
||||
|
||||
self.qmp_socket: Path = state_dir / "qmp.sock"
|
||||
self.qga_socket: Path = state_dir / "qga.sock"
|
||||
|
||||
log.debug(f"qmp_socket: {self.qmp_socket}")
|
||||
self._qmp = QEMUMonitorProtocol(path.realpath(self.qmp_socket))
|
||||
self._qmp_connected = False
|
||||
self.vm: VMAttr = VMAttr(name)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"Machine(name={self.name}, flake={self.flake})"
|
||||
@@ -60,28 +87,6 @@ class Machine:
|
||||
)
|
||||
return self._deployment_info
|
||||
|
||||
def qmp_connect(self) -> None:
|
||||
if not self._qmp_connected:
|
||||
tries = 100
|
||||
for num in range(tries):
|
||||
try:
|
||||
# the socket file link might be outdated, therefore re-init the qmp object
|
||||
self._qmp = QEMUMonitorProtocol(path.realpath(self.qmp_socket))
|
||||
self._qmp.connect()
|
||||
self._qmp_connected = True
|
||||
log.debug("QMP Connected")
|
||||
return
|
||||
except FileNotFoundError:
|
||||
if num < 99:
|
||||
sleep(0.1)
|
||||
continue
|
||||
else:
|
||||
raise
|
||||
|
||||
def qmp_command(self, command: str) -> dict:
|
||||
self.qmp_connect()
|
||||
return self._qmp.command(command)
|
||||
|
||||
@property
|
||||
def target_host_address(self) -> str:
|
||||
# deploymentAddress is deprecated.
|
||||
|
||||
Reference in New Issue
Block a user