NAME
App::FuguVM::State - what FuguVM remembers about one VM between runs
SYNOPSIS
use App::FuguVM::State;
my $state = App::FuguVM::State->new($state_dir, 'default')
or die "cannot open the state of 'default'\n";
$state->mark_running;
if ($state->was_unclean_shutdown) {
check_the_disk();
}
DESCRIPTION
Each VM has a directory under the state directory:
<state_dir>/<vm>/status the JSON state, mode 0600
<state_dir>/<vm>/vm.pid the QEMU process
<state_dir>/<vm>/proxy.pid the proxy child
<state_dir>/<vm>/autoinstall.pid the responder child
<state_dir>/<vm>/disk.qcow2 the working disk
The JSON blob rides on Fugu::StateFile. The two process IDs ride on Fugu::Pidfile, which takes its lock before it truncates and reaps a zombie before it answers "running". A QEMU that became a zombie therefore reads as stopped, which is what a caller that is about to start a second one needs to know.
The module is persistence only. It starts nothing and stops nothing: the proxy lifecycle belongs to App::FuguVM::Guest. That split is what removed the require cycle between the two modules.
METHODS
new
App::FuguVM::State->new($state_dir, $vm_name)
Open the state of one VM, and create its directory when it is absent.
The VM name becomes a directory name, so it must be one safe path component: no separator, no NUL byte, and not one of the two directory entries. A name that is not returns undef and a message in the log. The method also returns undef when the directory is a symlink, is not a directory, or cannot be created.
load, save
Read and write the JSON state. new loads. A corrupt file gives empty state and does not stop the program that would rewrite it.
store, state_dir, vm_state_dir, vm_name, data
store returns the Fugu::StateFile. App::FuguVM::Guest gives it to the proxy, which keeps its port there.
state_dir returns the directory that holds every VM's state, and vm_state_dir the one that holds this VM's. data returns the state hash reference for a caller that changes several keys at once.
vm_pidfile, proxy_pidfile, autoinstall_pidfile
Return the Fugu::Pidfile objects. QEMU writes the first itself, through its -pidfile option; the proxy supervisor owns the second, and the autoinstall responder supervisor owns the third. Each file lives in the state directory of the guest, so an interrupted run leaves no child that nothing owns.
get_vm_pid, clear_vm_pid, is_vm_running
The QEMU process. QEMU writes the pid file itself, through its -pidfile option, so there is no setter.
disk_path, disk_exists
The working disk of the VM.
set_runtime, get_runtime, clear_runtime
The runtime record: the facts of one run of one guest. The record holds accel and the resolved ssh_port and console_port. App::FuguVM::Guest writes it before it spawns QEMU, and reads it back for status and for the guest connections.
get_runtime returns the facts as a hash reference, and an empty hash reference when the guest never ran. The stop verbs call clear_runtime beside clear_vm_pid, so the record dies with the run. destroy needs no call, because it empties the whole store.
is_installed, mark_installed, get_installed_arch
Whether OpenBSD is installed on the disk. An installed system boots its own disk and never attaches the miniroot again.
mark_installed takes the architecture of the installed disk. The argument is required, so no path can forget it. get_installed_arch returns the recorded architecture, or undef. App::FuguVM::Guest compares it with the configured value before it boots an existing disk.
set_root_password, get_root_password
The password that the installer set. The store writes at mode 0600.
mark_ssh_key_installed, get_installed_ssh_pubkey
Which SSH public key the guest holds. The state records the key itself, not only that there is one. Thus a key that changed in the configuration is installed again on the next fuguvm up.
mark_running, mark_clean_shutdown, mark_unclean_shutdown, was_unclean_shutdown, clear_shutdown_state
Whether the last stop was clean. was_unclean_shutdown also reports true when the state says running and the process is gone: the VM crashed or was killed, and the disk may need a check.
SEE ALSO
Fugu::Pidfile, Fugu::StateFile, App::FuguVM::Guest
AUTHOR
Dick Olsson <hi@senzilla.io>