OmniCube Reference Manualqemu-monitor-command(8)

qemu-monitor-command(8)

System Administration Commands · OmniCube · August 10, 2026

NAME

qemu-monitor-command - send QEMU guest-agent commands to a zone-hosted VM

SYNOPSIS

/opt/omnicube/sbin/qemu-monitor-command -z zone [options]

qemu-monitor-command -z|--zone zone [-c|--command command] [-j|--json json] [--arguments.key value ...] [-f|--format] [-d|--debug] [-e|--expect|--no-expect]

DESCRIPTION

qemu-monitor-command talks to the QEMU guest agent (org.qemu.guest_agent) running inside a guest hosted by an OmniCube zone, and prints the agent's raw JSON reply on standard output. It is the low-level building block used by manage_zone.sh(8) and by the zone monitors to query or control a guest without going through the guest's network stack.

The command name given with -c is normalised by stripping a leading guest- prefix, then wrapped in a QMP-style request object:

{"execute":"guest-<command>"}
{"execute":"guest-<command>","arguments":<json>}

With no -c the request defaults to guest-info.

Socket discovery

The agent socket is not configured directly; it is derived from the zone configuration read with zonecfg(8). The zone path comes from zonecfg -z zone info zonepath, and every candidate socket path is built as zonepath/root followed by the trailing component of the attribute value (the text after the last , or = in it). Candidates are produced in priority order:

1.

the first of the attributes virtio-console, virtio-console0, virtio-console1, virtio-console2, virtio-console3 whose value mentions org.qemu.guest_agent;

2.

the com2 attribute, which is always emitted as a fallback and never replaces the virtio-console candidate.

A zone should expose exactly one guest-agent socket. When both candidates exist the query still succeeds, but the ambiguity is reported on standard error, naming the socket that was used and the ones that were ignored, so that standard output stays parseable JSON.

Socket selection

Before anything is sent, the zone must be running: this is checked with zoneadm -z zone list -v filtered through the GNU grep at /usr/bin/ggrep. For an ordinary command the candidates are then tried in order and the first non-empty reply wins, which is how a dead socket is skipped.

That heuristic cannot work for the silent commands listed in SILENT_COMMANDS: shutdown, suspend-disk, suspend-ram and suspend-hybrid. These return nothing even on success, so "no output" would cause the request to be delivered to every candidate in turn. For them the live socket is selected with a bare {execute:guest-ping} probe instead - sent without the caller's own arguments, since guest-ping accepts none - and a candidate is accepted only when the whitespace-stripped reply is exactly {return:{}}. The real command is then sent to that socket, once. If it produces output (the agent objected to it) that output is printed; otherwise the ping reply is printed, which is the normal silent success.

Transports

Two transports can carry the request, both reaching the socket through pfexec:

expect

Uses /opt/ooce/bin/expect to spawn socat connected to the socket with UNIX-CONNECT, sends the payload, reads until end of file or a two-second timeout, and strips the echoed request out of the response. The socket path and the payload are handed to the interpreter in the OC_QA_SOCKET and OC_QA_COMMAND environment variables and read back with $env(), never interpolated into the script text.

socat

The payload is echoed into /usr/bin/socat STDIO UNIX-CONNECT: directly, followed by a one-second grace period for the reply.

The transport is autodetected: expect is used when both /opt/ooce/bin/expect and /usr/bin/socat exist as regular files, plain socat otherwise. -e and --no-expect pin the choice, and are resolved after option parsing so the option always wins over what happens to be installed. A pinned transport whose binaries are missing is a fatal error rather than an empty reply that would look like an absent guest agent.

OPTIONS

-z, --zone zone

Zone hosting the guest. Required. The name must start with an alphanumeric character and may otherwise contain alphanumerics, ., _ and -; anything else is refused before zonecfg is called.

-c, --command command

Guest-agent command, with or without the guest- prefix, for example info, ping, get-osinfo, shutdown. Default info. It is validated against the same character set as the zone name.

-j, --json json

Literal JSON value to use as the arguments member of the request. It is inserted verbatim and is not validated. Ignored, with a warning, when any --arguments.key option is also given.

--arguments.key value

Build the arguments object one member at a time, without writing JSON by hand. Repeating the same key turns that member into an array, in the order given. Values true, false and null, plain integers and simple decimals are emitted unquoted; everything else is emitted as a string with \\ and " escaped. Dot notation takes precedence over -j.

-f, --format

Pretty-print the reply by piping it through /opt/ooce/bin/jq. Default is to print the agent's reply unchanged.

-d, --debug

Trace candidate enumeration, the selected transport, the payload and every reply to standard error, and stop suppressing transport errors from candidates that still have a fallback. Standard output stays pure JSON either way.

-e, --expect

Force the expect transport even when autodetection would not pick it.

--no-expect

Force plain socat. Useful when expect is installed but suspect, since it is the transport that passes the socket path and payload through the environment.

-h, --help

Print the usage summary and exit 2.

--

End option processing.

EXAMPLES

Example 1: query the agent and the guest OS

qemu-monitor-command -z win2022 -f
qemu-monitor-command -z win2022 -c get-osinfo -f

Example 2: freeze filesystems before a snapshot

qemu-monitor-command -z sql01 -c fsfreeze-freeze
qemu-monitor-command -z sql01 -c fsfreeze-thaw

Example 3: a silent command with dot-notation arguments

The socket is selected by a guest-ping probe first, then the shutdown request is delivered to it exactly once:

qemu-monitor-command -z win2022 -c shutdown \\
    --arguments.mode powerdown

Example 4: equivalent literal-JSON form, with tracing

qemu-monitor-command -z win2022 -c shutdown \\
    -j '{"mode":"powerdown"}' -d

DIAGNOSTICS

Errors that concern the zone or the agent are reported on standard output as a JSON object so that a calling script can parse success and failure the same way:

{"error":{"class":"QA_CMD","desc":"<zone>: <message>"}}

Usage errors, invalid names, missing transport binaries, the --json override warning and all -d tracing are plain text.

EXIT STATUS

0

The agent replied, or a silent command was delivered to a socket that answered the ping probe.

2

Usage error: no -z, an unknown option, a missing option value, an invalid zone or command name, or a transport pinned with -e or --no-expect whose binaries are missing. -h also exits 2.

3

No such zone configured (no zone path).

4

No virtual console/serial or com2 configured for the zone.

5

The zone is not running.

6

The QEMU guest agent does not seem to be running or configured: no candidate socket answered.

FILES

/opt/omnicube/sbin/qemu-monitor-command

This command.

zonepath/root/...

The guest-agent UNIX socket, named by the zone's virtio-console* or com2 attribute. Root-owned; it is deliberately not pre-tested with a stat, so that an unprivileged caller does not skip every candidate.

/usr/bin/socat

Transport to the socket, required by both transports.

/opt/ooce/bin/expect

Driver for the expect transport.

/opt/ooce/bin/jq

Used by -f.

/etc/security/exec_attr.d/omnicube

Grants uid=0 execution of socat and expect to the OmniCube Administration profile.

ENVIRONMENT

OC_QA_SOCKET, OC_QA_COMMAND

Set by the command itself to hand the socket path and the JSON payload to the expect interpreter as data. They are not user-serviceable inputs.

SECURITY

The socket lives under a root-owned zone path, so both transports are invoked with pfexec; the required uid=0 entries for /usr/bin/socat and /opt/ooce/bin/expect are part of the OmniCube Administration profile. Because that interpreter runs privileged, the zone name and command name are constrained to their real character sets before use, and the socket path and payload are passed to expect through the environment rather than being interpolated into the Tcl script: brace quoting in Tcl ends at the first unbalanced }, so an interpolated payload containing that character would be evaluated as code by a process running as root. Note that granting the OmniCube Administration profile is root-equivalent, precisely because it includes socat and expect.

SEE ALSO

omnicube_utils(3), omnicube(7), manage_zone.sh(8), restart_windows_server(8), shutdown_windows_server(8), zone_monitor.sh(8).

NOTES

The value given to -j is inserted into the request without being parsed, so malformed JSON reaches the agent and is rejected by it, not by this command.

Ordinary commands are tried against each candidate socket in turn, which means a command that legitimately returns nothing and is not in SILENT_COMMANDS would be delivered more than once; add such a command to that list rather than relying on the reply heuristic.

The expect transport gives up on a socket after two seconds, so a guest whose agent is alive but slow to answer (a freeze under load, for example) can look like a dead socket.

man8/qemu-monitor-command.8generated 2026-09-02 05:17 CEST