various improvements
This commit is contained in:
@ -14,8 +14,8 @@ from .base import VMBase
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
DEFAULT_WAIT_TIMEOUT = 60 # seconds
|
||||
POLL_INTERVAL = 0.3
|
||||
QEMU_TIMEOUT = 60 # seconds
|
||||
POLL_INTERVAL = 0.3 # also seconds
|
||||
|
||||
|
||||
class QemuAgent(VMBase):
|
||||
@ -33,7 +33,7 @@ class QemuAgent(VMBase):
|
||||
_get_cmd_result()
|
||||
Intended for long-time commands. This function loops and every
|
||||
POLL_INTERVAL calls 'guest-exec-status' for specified guest PID.
|
||||
Polling ends on command exited or on timeout.
|
||||
Polling ends if command exited or on timeout.
|
||||
_return_tuple()
|
||||
This method transforms JSON command output to tuple and decode
|
||||
base64 encoded strings optionally.
|
||||
@ -46,7 +46,7 @@ class QemuAgent(VMBase):
|
||||
flags: int | None = None
|
||||
):
|
||||
super().__init__(session, name)
|
||||
self.timeout = timeout or DEFAULT_WAIT_TIMEOUT # timeout for guest agent
|
||||
self.timeout = timeout or QEMU_TIMEOUT # timeout for guest agent
|
||||
self.flags = flags or libvirt_qemu.VIR_DOMAIN_QEMU_MONITOR_COMMAND_DEFAULT
|
||||
|
||||
def execute(
|
||||
@ -56,7 +56,7 @@ class QemuAgent(VMBase):
|
||||
capture_output: bool = False,
|
||||
decode_output: bool = False,
|
||||
wait: bool = True,
|
||||
timeout: int = DEFAULT_WAIT_TIMEOUT,
|
||||
timeout: int = QEMU_TIMEOUT,
|
||||
):
|
||||
"""
|
||||
Execute command on guest and return output if capture_output is True.
|
||||
@ -99,7 +99,7 @@ class QemuAgent(VMBase):
|
||||
capture_output: bool = False,
|
||||
decode_output: bool = False,
|
||||
wait: bool = True,
|
||||
timeout: int = DEFAULT_WAIT_TIMEOUT,
|
||||
timeout: int = QEMU_TIMEOUT,
|
||||
):
|
||||
"""
|
||||
Execute command on guest with selected shell. /bin/sh by default.
|
||||
@ -139,7 +139,7 @@ class QemuAgent(VMBase):
|
||||
pid: int,
|
||||
decode_output: bool = False,
|
||||
wait: bool = True,
|
||||
timeout: int = DEFAULT_WAIT_TIMEOUT,
|
||||
timeout: int = QEMU_TIMEOUT,
|
||||
):
|
||||
"""Get executed command result. See GuestAgent.execute() for info."""
|
||||
exited = exitcode = stdout = stderr = None
|
||||
|
@ -13,7 +13,7 @@ class VirtualMachine(VMBase):
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.domain.name()
|
||||
return self.domname
|
||||
|
||||
@property
|
||||
def status(self) -> str:
|
||||
@ -21,7 +21,12 @@ class VirtualMachine(VMBase):
|
||||
Return VM state: 'running', 'shutoff', etc. Reference:
|
||||
https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainState
|
||||
"""
|
||||
state = self.domain.info()[0]
|
||||
try:
|
||||
# libvirt returns list [state: int, reason: int]
|
||||
# https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainGetState
|
||||
state = self.domain.state()[0]
|
||||
except libvirt.libvirtError as err:
|
||||
raise VMError(f'Cannot fetch VM status vm={self.domname}: {err}') from err
|
||||
match state:
|
||||
case libvirt.VIR_DOMAIN_NOSTATE:
|
||||
return 'nostate'
|
||||
@ -48,6 +53,16 @@ class VirtualMachine(VMBase):
|
||||
return False
|
||||
return True
|
||||
|
||||
@property
|
||||
def is_autostart(self) -> bool:
|
||||
"""Return True if VM autostart is enabled, else return False."""
|
||||
try:
|
||||
if self.domain.autostart() == 1:
|
||||
return True
|
||||
return False
|
||||
except libvirt.libvirtError as err:
|
||||
raise VMError(f'Cannot get autostart status vm={self.domname}: {err}') from err
|
||||
|
||||
def start(self) -> None:
|
||||
"""Start defined VM."""
|
||||
logger.info('Starting VM: vm=%s', self.domname)
|
||||
@ -57,9 +72,7 @@ class VirtualMachine(VMBase):
|
||||
try:
|
||||
ret = self.domain.create()
|
||||
except libvirt.libvirtError as err:
|
||||
raise VMError(err) from err
|
||||
if ret != 0:
|
||||
raise VMError('Cannot start VM: vm=%s exit_code=%s', self.domname, ret)
|
||||
raise VMError(f'Cannot start vm={self.domname} return_code={ret}: {err}') from err
|
||||
|
||||
def shutdown(self, force=False, sigkill=False) -> None:
|
||||
"""
|
||||
@ -71,41 +84,56 @@ class VirtualMachine(VMBase):
|
||||
flags = libvirt.VIR_DOMAIN_DESTROY_DEFAULT
|
||||
else:
|
||||
flags = libvirt.VIR_DOMAIN_DESTROY_GRACEFUL
|
||||
if force:
|
||||
ret = self.domain.destroyFlags(flags=flags)
|
||||
else:
|
||||
# Normal VM shutdown via ACPI signal, OS may ignore this.
|
||||
ret = self.domain.shutdown()
|
||||
if ret != 0:
|
||||
try:
|
||||
if force:
|
||||
self.domain.destroyFlags(flags=flags)
|
||||
else:
|
||||
# Normal VM shutdown via ACPI signal, OS may ignore this.
|
||||
self.domain.shutdown()
|
||||
except libvirt.libvirtError as err:
|
||||
raise VMError(
|
||||
f'Cannot shutdown VM, try force or sigkill: %s', self.domname
|
||||
)
|
||||
f'Cannot shutdown vm={self.domname} '
|
||||
f'force={force} sigkill={sigkill}: {err}'
|
||||
) from err
|
||||
|
||||
def reset(self):
|
||||
"""
|
||||
Copypaste from libvirt doc::
|
||||
Copypaste from libvirt doc:
|
||||
|
||||
Reset a domain immediately without any guest OS shutdown.
|
||||
Reset emulates the power reset button on a machine, where all
|
||||
hardware sees the RST line set and reinitializes internal state.
|
||||
Reset a domain immediately without any guest OS shutdown.
|
||||
Reset emulates the power reset button on a machine, where all
|
||||
hardware sees the RST line set and reinitializes internal state.
|
||||
|
||||
Note that there is a risk of data loss caused by reset without any
|
||||
guest OS shutdown.
|
||||
Note that there is a risk of data loss caused by reset without any
|
||||
guest OS shutdown.
|
||||
"""
|
||||
ret = self.domian.reset()
|
||||
if ret != 0:
|
||||
raise VMError('Cannot reset VM: %s', self.domname)
|
||||
try:
|
||||
self.domian.reset()
|
||||
except libvirt.libvirtError as err:
|
||||
raise VMError(f'Cannot reset vm={self.domname}: {err}') from err
|
||||
|
||||
def reboot(self) -> None:
|
||||
"""Send ACPI signal to guest OS to reboot. OS may ignore this."""
|
||||
ret = self.domain.reboot()
|
||||
if ret != 0:
|
||||
raise VMError('Cannot reboot: %s', self.domname)
|
||||
try:
|
||||
self.domain.reboot()
|
||||
except libvirt.libvirtError as err:
|
||||
raise VMError(f'Cannot reboot vm={self.domname}: {err}') from err
|
||||
|
||||
def set_autostart(self) -> None:
|
||||
ret = self.domain.autostart()
|
||||
if ret != 0:
|
||||
raise VMError('Cannot set : %s', self.domname)
|
||||
def autostart(self, enabled: bool) -> None:
|
||||
"""
|
||||
Configure VM to be automatically started when the host machine boots.
|
||||
"""
|
||||
if enabled:
|
||||
autostart_flag = 1
|
||||
else:
|
||||
autostart_flag = 0
|
||||
try:
|
||||
self.domain.setAutostart(autostart_flag)
|
||||
except libvirt.libvirtError as err:
|
||||
raise VMError(
|
||||
f'Cannot set autostart vm={self.domname} '
|
||||
f'autostart={autostart_flag}: {err}'
|
||||
) from err
|
||||
|
||||
def vcpu_set(self, count: int):
|
||||
pass
|
||||
|
Reference in New Issue
Block a user