clan-vm-manager: Fix ui state desync on build error. Add build progress bar
This commit is contained in:
parent
183c1f4235
commit
0a8b8713d9
@ -99,7 +99,7 @@ def _init_proc(
|
||||
gpid = os.getpgid(pid=pid)
|
||||
print(f"Killing process group pid={pid} gpid={gpid}", file=sys.stderr)
|
||||
os.killpg(gpid, signal.SIGTERM)
|
||||
|
||||
sys.exit(1)
|
||||
# Don't use a finally block here, because we want the exitcode to be set to
|
||||
# 0 if the function returns normally
|
||||
|
||||
|
@ -136,6 +136,11 @@ class VM(GObject.Object):
|
||||
self._logs_id: int = 0
|
||||
self._log_file: IO[str] | None = None
|
||||
|
||||
# To be able to set the switch state programmatically
|
||||
# we need to store the handler id returned by the connect method
|
||||
# and block the signal while we change the state. This is cursed.
|
||||
self.switch_handler_id: int = 0
|
||||
|
||||
# Make sure the VM is killed when the reference to this object is dropped
|
||||
self._finalizer = weakref.finalize(self, self.kill_ref_drop)
|
||||
|
||||
@ -171,15 +176,25 @@ class VM(GObject.Object):
|
||||
with self.create_machine() as machine:
|
||||
# Start building VM
|
||||
log.info(f"Building VM {self.get_id()}")
|
||||
log_dir = Path(str(self.log_dir.name))
|
||||
self.build_process = spawn(
|
||||
on_except=None,
|
||||
out_file=Path(str(self.log_dir.name)) / "build.log",
|
||||
out_file=log_dir / "build.log",
|
||||
func=vms.run.build_vm,
|
||||
machine=machine,
|
||||
tmpdir=log_dir,
|
||||
vm=self.data.flake.vm,
|
||||
)
|
||||
GLib.idle_add(self.emit, "vm_status_changed", self)
|
||||
|
||||
# Start the logs watcher
|
||||
self._logs_id = GLib.timeout_add(
|
||||
50, self._get_logs_task, self.build_process
|
||||
)
|
||||
if self._logs_id == 0:
|
||||
log.error("Failed to start VM log watcher")
|
||||
log.debug(f"Starting logs watcher on file: {self.build_process.out_file}")
|
||||
|
||||
# Start the progress bar and show it
|
||||
self.progress_bar.show()
|
||||
self.prog_bar_id = GLib.timeout_add(100, self._pulse_progress_bar)
|
||||
@ -208,7 +223,7 @@ class VM(GObject.Object):
|
||||
GLib.idle_add(self.emit, "vm_status_changed", self)
|
||||
|
||||
# Start the logs watcher
|
||||
self._logs_id = GLib.timeout_add(50, self._get_logs_task)
|
||||
self._logs_id = GLib.timeout_add(50, self._get_logs_task, self.vm_process)
|
||||
if self._logs_id == 0:
|
||||
log.error("Failed to start VM log watcher")
|
||||
log.debug(f"Starting logs watcher on file: {self.vm_process.out_file}")
|
||||
@ -223,16 +238,17 @@ class VM(GObject.Object):
|
||||
log.warn("VM is already running. Ignoring start request")
|
||||
self.emit("vm_status_changed", self)
|
||||
return
|
||||
log.debug(f"VM state dir {self.log_dir.name}")
|
||||
self._start_thread = threading.Thread(target=self.__start)
|
||||
self._start_thread.start()
|
||||
|
||||
def _get_logs_task(self) -> bool:
|
||||
if not self.vm_process.out_file.exists():
|
||||
def _get_logs_task(self, proc: MPProcess) -> bool:
|
||||
if not proc.out_file.exists():
|
||||
return GLib.SOURCE_CONTINUE
|
||||
|
||||
if not self._log_file:
|
||||
try:
|
||||
self._log_file = open(self.vm_process.out_file)
|
||||
self._log_file = open(proc.out_file)
|
||||
except Exception as ex:
|
||||
log.exception(ex)
|
||||
self._log_file = None
|
||||
@ -242,7 +258,7 @@ class VM(GObject.Object):
|
||||
if len(line) != 0:
|
||||
print(line.decode("utf-8"), end="", flush=True)
|
||||
|
||||
if not self.is_running():
|
||||
if not proc.proc.is_alive():
|
||||
log.debug("Removing logs watcher")
|
||||
self._log_file = None
|
||||
return GLib.SOURCE_REMOVE
|
||||
|
@ -193,11 +193,9 @@ class ClanList(Gtk.Box):
|
||||
box.append(switch_box)
|
||||
box.append(pref_button)
|
||||
|
||||
switch.connect("notify::active", partial(self.on_row_toggle, vm))
|
||||
# def on_switch_state_set(switch: Any, state: bool) -> bool:
|
||||
# return True
|
||||
# switch.connect("state-set", on_switch_state_set)
|
||||
|
||||
vm.switch_handler_id = switch.connect(
|
||||
"notify::active", partial(self.on_row_toggle, vm)
|
||||
)
|
||||
vm.connect("vm_status_changed", partial(self.vm_status_changed, switch))
|
||||
|
||||
# suffix.append(box)
|
||||
@ -304,6 +302,11 @@ class ClanList(Gtk.Box):
|
||||
if switch.get_sensitive() is False and not vm.is_building():
|
||||
switch.set_sensitive(True)
|
||||
|
||||
exitc = vm.vm_process.proc.exitcode
|
||||
exit_vm = vm.vm_process.proc.exitcode
|
||||
exit_build = vm.build_process.proc.exitcode
|
||||
exitc = exit_vm or exit_build
|
||||
if not vm.is_running() and exitc != 0:
|
||||
switch.handler_block(vm.switch_handler_id)
|
||||
switch.set_active(False)
|
||||
switch.handler_unblock(vm.switch_handler_id)
|
||||
log.error(f"VM exited with error. Exitcode: {exitc}")
|
||||
|
Loading…
Reference in New Issue
Block a user