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>/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

Return the Fugu::Pidfile objects. QEMU writes the first itself, through its -pidfile option; the proxy supervisor owns the second.

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.

is_installed, mark_installed

Whether OpenBSD is installed on the disk. An installed system boots its own disk and never attaches the miniroot again.

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>