@deckyard/virtualbox
Oracle VirtualBox 7 from a Jennifer program, through VBoxManage, the command line every VirtualBox install has. The deck covers what scripts that build and run test machines do by hand:
- Inventory: machines, running machines, OS types, disks, host-only interfaces, NAT networks, the host.
- Machines: their details (state, hardware, NICs, port forwards, storage, shared folders); create, register, unregister, delete; processors, memory, firmware, NICs, storage controllers, disks and DVDs.
- Power: start, power off, ACPI shutdown, pause, resume, reset, save; NAT port forwards on running and stopped machines.
- Snapshots, clones, appliances: take, list, restore, delete; full and linked clones; OVA / OVF import and export.
- The guest: guest properties and the IP address it reports, commands and file copies inside it (with the Guest Additions), shared folders.
virtualbox.run reaches every other VBoxManage subcommand.
Conventions
Snippets assume this import, and add the use lines they need:
import "@deckyard/virtualbox/" as virtualbox;The trailing slash resolves to the entry module.
Every call takes the Host that open returns. open runs VBoxManage --version once and refuses VirtualBox older than 7, so a program fails at its first line instead of halfway through:
use io;
def vb as virtualbox.Host init virtualbox.open(virtualbox.local());
io.printf("VirtualBox %s\n", $vb.version);A machine is named by its name or its UUID. The deck needs the exec capability, so it runs on the default jennifer binary, not jennifer-tiny, and a Linux, macOS or other Unix host: it starts VBoxManage through env LC_ALL=C.UTF-8, since VirtualBox 7 translates its output under some locales and the deck reads the English labels, and it passes a guest password through a named pipe. A host without the C.UTF-8 locale still runs every call, but VBoxManage refuses arguments outside ASCII there (VERR_NO_TRANSLATION).
Errors
Every failure is an Error of kind "virtualbox", its message starting with virtualbox: :
- an argument the deck refuses before running anything: an empty name, a name or path starting with
-, a control character, a number out of range, an unknown option value; VBoxManagecannot be started, or runs past its deadline. It then gets SIGTERM; during an import, export, clone or snapshot it catches that and cancels the operation first, so it gets 5 more seconds, after which the call gives up and says it leftVBoxManagerunning, with its pid;VBoxManageprinted more than 4 Mi characters or 50 000 lines, which no real answer does, so the parsers stay within a few hundred MiB;VBoxManagefails. The message carries its first error line, itsVBOX_E_*/E_*/NS_ERROR_*code and the exit code:virtualbox: startvm web: Could not find a registered machine named 'web' (VBOX_E_OBJECT_NOT_FOUND, exit 1).virtualbox.errorCode(e)returns the code.
use io;
try {
virtualbox.start($vb, "web");
} catch (e) {
if (virtualbox.errorCode($e) == "VBOX_E_INVALID_OBJECT_STATE") {
io.printf("web is already running\n");
} else {
io.printf("%s\n", $e.message);
}
}