OmniCube Reference Manualmanage_zone.sh(8)

manage_zone.sh(8)

System Administration Commands · OmniCube · August 25, 2026

NAME

manage_zone.sh - manage the configuration and lifecycle of zones and VMs

SYNOPSIS

/opt/omnicube/sbin/manage_zone.sh -z zone -b|-s|-r
manage_zone.sh -z zone -l -h node
manage_zone.sh -z zone -S -h node -U user -D parent_remote_dataset
manage_zone.sh -z zone -a|-d -c iso
manage_zone.sh -z zone -a|-d -w wwn [-w wwn ...]
manage_zone.sh -z zone -a|-d -W file
manage_zone.sh -z zone -L
manage_zone.sh -z zone [-m ram] [-p vcpus] [-n on|off]
manage_zone.sh [-i name | --instance name] other options

DESCRIPTION

manage_zone.sh is the operator entry point for OmniCube zones, native (lipkg, lx) as well as VM brands (bhyve, kvm). It performs one operation per invocation, selected by -b, -s, -r, -l, -S, -a, -d or -L, and it can patch the RAM, VCPU and VNC attributes of a zone configuration with -m, -p and -n. -a and -d are qualified by what they act on: -c for an installation image, or -w (one or more WWNs, repeating the option) or -W (a file of them) for SCSI LUNs passed through to a VM.

The script sources /opt/omnicube/lib/common/utils.sh and inherits the shared run-level guard: at run level 0, 1, 5, 6, S or s, or when /etc/nologin exists, it logs one message and exits 0 without touching anything. Because this is an interactive tool the OC_IGNORE_RUNLEVEL=1 override matters here: an administrator doing single-user maintenance can still drive a zone by hand.

Two classes of zone are distinguished throughout, by the existence of the SMF instance svc:/service/omnicube/zone:zone:

cluster managed

The instance exists, and its config/adm_status, config/type and config/zpools properties are the authority for the desired state of the zone and for the pools carrying its data. Options -b and -s update config/adm_status and leave autoboot=false in the zone configuration, so that SMF decides when the zone runs, and -l is what moves the zone.

local

No instance exists. The zone is booted directly with autoboot=true in its own configuration, it is never included in the configuration synchronisation done by -r, and -S is what moves it.

Cluster operations use ssh. The peer list is the SMF property config/nodes of svc:/omnicube/sysadm:instance, read by the shared library into the nodes array; the local host, as returned by hostname, is always skipped. Connections use BatchMode=yes, StrictHostKeyChecking=yes and a short connect timeout, so every peer's host key must already be in /etc/ssh/ssh_known_hosts or in the invoking account's known_hosts. Remote privileged commands run under pfexec on the peer rather than by elevating the local ssh client, and every operation that depends on a peer first probes the whole ssh path by running true there, so an unusable peer aborts the command instead of stranding the zone half way.

Start (-b) and shutdown (-s)

-b sets autoboot=true for a local zone, or autoboot=false, config/adm_status = started and a refresh of the instance for a cluster managed one, then boots the zone with zoneadm boot. -s always sets autoboot=false, and for a cluster managed zone sets config/adm_status = stopped and refreshes the instance; if the zone is running, its type attribute is read and a windows guest is asked to stop first through shutdown_windows_server(8), then zoneadm shutdown runs, with zoneadm halt as a fallback when it fails.

Synchronise the configuration (-r)

Exports the zone configuration of a cluster managed zone and installs it on every other node of config/nodes; local zones are skipped, and an unreachable peer is logged and skipped so the remaining ones are still updated. On each peer the zone must be absent or in state configured, read from zoneadm list -pnic; any other state is reported and that peer skipped, so a running zone is never overwritten. The file is staged under a name created by mktemp on the peer (/tmp/manage_zone_config.XXXXXX), where pfexec zonecfg delete -F, scp and pfexec zonecfg -f then run; both staging files are removed whatever happens. The same synchronisation runs at the end of any invocation in which -m, -p or -n changed the configuration.

Relocate a SYNC zone (-l -h node)

Moves a zone whose storage the target can already reach. The target must not be the local host and the zone must be configured locally. For a cluster managed zone the three SMF properties are read first, every pool in config/zpools is locked (see ZFS lock property below), the instance is disabled with svcadm disable -s - whose stop method halts the zone, stops its VNC console relay and exports the pools - the exported configuration is pushed to the target, the local configuration and the local instance are deleted, the instance is recreated on the target with the same adm_status, type and zpools values, and svcadm enable -s is run there. For a local zone the pool named after the zone is locked, the zone is shut down (halted if it does not stop), its configuration is written to zonepath/config, the zone is detached, its configuration deleted, the VNC console relay stopped and the pool exported; the target then imports the pool, applies zonepath/config, attaches and boots the zone.

Stopping the console relay is not housekeeping: it is a precondition for the export. The relay holds zonepath/log/vnc.log open, a file inside the pool, so an export while it runs fails with "pool is busy". Both paths go through kill_zone_console (see oc_console(3)), which waits for the processes to actually exit rather than signalling and moving on.

Whether a console was published here is recorded before the teardown, and if it was, the console is re-published on the target once the zone is running there, by running activate_zone_vnc.sh(1) over ssh. A zone that had no console gets none, so a relocate neither hands an operator a console they never asked for nor silently drops one they were using. The port is not carried across because it does not need to be: it lives in the zone configuration, which travelled with the zone. TLS is deliberately not mirrored - the target's own config/vnc_tls, config/vnc_cafile and config/vnc_verify_client decide, so a node whose policy requires mutual TLS is never downgraded by a zone arriving from a laxer one. A failure to re-publish is a warning naming the command to run by hand, never a failed relocate: the zone has already moved and is running. Under -S the re-publish additionally requires that the zone was running before the move, since a zone that was stopped here is attached but not booted there.

A zone with directly attached SCSI LUNs has them checked and initialized on the target first; see Moving a zone that has LUNs attached below.

Send an ASYNC zone (-S -h node -U user -D parent)

Replicates a local zone to another node with zfs send and zfs recv, and refuses any zone that has an SMF instance. The data root is the dataset mounted at the zone's zonepath, truncated at the first path component equal to the zone name; the target is parent/leaf, the leaf being the last component of that root, that is the zone name. The root is locked, the pre-shutdown running state is recorded, and for lipkg so are the active boot environment mounted at /zones/zone/root/root and the delegated datasets named in the configuration; the zone is then shut down, the configuration blob is written to zonepath/config with its set name= dataset paths rewritten to the remote namespace, and the zone is detached, unconfigured and its console process killed. Five reported steps follow: a best-effort autosync(8) pass, whose failure is only a warning; capture of the locally set *:remotebackup, *:snapshotting, *:bckcandel, *:is_locked and *:snappolicy properties over the whole subtree, plus mountpoint and zoned for lipkg; a local zfs inherit of those properties except *:is_locked; a recursive @SEND snapshot and the transfer itself, which is a single zfs send -R piped into zfs recv -u -F when the target dataset does not exist yet, and otherwise a per-dataset walk sending each dataset incrementally from its newest snapshot marked insync=yes, or in full when it has no such base; and finally the brand-specific remote setup, where VM brands get zfs set mountpoint, zfs mount -a, zonecfg -f and zoneadm attach, while lipkg zones get a canmount=off/on bracketed replay of every source mountpoint and of zoned=on, a legacy mount of the active boot environment, then zonecfg -f and zoneadm attach. Either way the zone is booted on the target only if it was running before the send.

Afterwards the remote @SEND snapshot is destroyed, every received snapshot is marked insync=yes once per config/site prefix found among the local svc:/omnicube/sysadm instances, *:snapshotting and *:remotebackup are reapplied on the target, and both locks are released. The source datasets and their snapshots are left in place on purpose, for the operator to remove once the target is confirmed healthy.

As with -l, a zone with directly attached SCSI LUNs has them checked and initialized on the target before the zone is shut down; see Moving a zone that has LUNs attached below.

Add or remove an ISO (-a, -d with -c)

The image must exist as /iso/iso. Adding appends a read-only, nodevices lofs file system entry for that path plus a cdromN attribute; removing deletes the matching fs and attr entries. Both end with verify and commit.

Attach or detach SCSI LUNs (-a, -d with -w or -W; -L to list)

A SAN LUN can be handed to a bhyve VM directly, as a uscsi passthrough target behind an emulated virtio-scsi controller, instead of being copied into a file or a zvol. The LUN is named by its WWN and the raw device path is derived from it as /dev/rdsk/c0twwnd0p0. Both spellings of the WWN are accepted: illumos multipathing names LUNs in upper case hexadecimal while inventories and operators usually write them in lower case, so the script tries the spelling given, then upper, then lower, and records the path that actually exists on the node.

-a with -w refuses to continue when no such device node exists, which is the usual sign that the LUN is not mapped to this node or that devfsadm -Cv has not been run, and it refuses a WWN already present in the configuration under either spelling. It then writes, in one zonecfg transaction ending in verify and commit:

scsiM

The controller, with value backend=uscsi, created only when the last controller in the configuration already carries sixteen LUNs, which is the site standard and applies to both conventions below, or when the zone has no controller at all. Controller, disk and target indices are chosen as the highest in use plus one, never by filling a gap left by an earlier removal, because those indices become PCI function numbers and SCSI target IDs inside the guest.

the association

One of two forms, chosen by the installed sysadm version; see below.

device

A device resource matching the raw path, without which the node is not present inside the zone and bhyve cannot open it.

Initializing a LUN before it is attached

Every LUN of an attach is first put through

pfexec mpathadm modify lu -b none /dev/rdsk/c0twwnd0p0

which disables multipath load balancing on the logical unit. A LUN handed to bhyve while the mpxio layer is still balancing across its paths does not behave as the site expects, so this is a prerequisite rather than a tuning step, and nothing else performs it at attach time — the bhyve launcher does not.

On a loaded array a single call can take tens of seconds, and a batch of sixteen can therefore run for minutes with nothing else to show for itself. The step is narrated for that reason: a line naming the LUN is printed before each call, so whatever is being worked on is on screen during the wait, and a second line reports it with the elapsed time in whole seconds. An apparently hung command is almost always this, and interrupting it is not necessary — a run that does not finish leaves the zone configuration untouched.

Initialization runs after the batch has been validated and planned, so a list that was never going to fit does not first spend minutes in mpathadm, and before anything is committed, so a LUN never appears in a zone configuration until it has actually been initialized. A failure on any LUN abandons the whole attach and writes nothing; LUNs initialized before it keep -b none, which is harmless by itself and is re-applied idempotently on the next run. When /usr/sbin/mpathadm is absent the attach is refused rather than performed without initialization. Detaching does not restore load balancing.

The setting is not persistent

mpathadm modify lu sets a property of the logical unit at run time. It does not survive a reboot, and it is per node: it says nothing about the same logical unit as another node sees it. Three things therefore cover the three moments a LUN can need it.

-a -w/-W

at attach, so a LUN is never written into a zone configuration before it has been initialized.

-l, -S

on the target node before a move, since the setting does not travel with the zone (see Moving a zone that has LUNs attached).

svc:/service/omnicube/lun-init:default

once per system boot, before the zones start.

An individual zone restart needs nothing: the node has not rebooted, so whichever of the three ran last still stands.

The lun-init service

svc:/service/omnicube/lun-init:default walks every configured zone on the node once per boot, collects the /dev/rdsk devices each one passes through — by the same rules -L uses, so all three attribute conventions are covered — and runs mpathadm modify lu -b none on each. A device shared by two zones is initialized once and reported against both. The global zone is skipped.

Its manifest makes svc:/system/zones:default and svc:/service/omnicube/zone depend on it with grouping optional_all, which is the whole design: the zone services wait for this one to reach a terminal state, so the LUNs are ready before a guest touches them, but a failure here can never keep a node's zones from booting. Starting a zone on an uninitialized LUN is bad; refusing to start any zone on the node because one LUN of one zone is unreachable is worse.

Two properties tune it.

config/max_seconds

Seconds the whole pass may take, 900 by default. When the budget is spent the remaining devices are named in the log and skipped, rather than dropped quietly, and the service still comes online. Those zones start as they would have without the service, with the difference recorded. The bound exists because a sick array could otherwise hold every zone on the node for an hour.

config/strict

When true, a device that could not be initialized puts the service in maintenance so it appears in svcs -x. It is not an interlock: the injected dependency is optional_all, which a service in maintenance satisfies, so the zones boot either way. Default false.

Everything the pass does, including each device it could not initialize and the zones affected, goes to the service log and to syslog under the tag oc-lun-init. Read it with svcs -L omnicube/lun-init.

Moving a zone that has LUNs attached (-l, -S)

A zone whose disks are SAN LUNs passed straight through can only run on a node that can see those LUNs, and nothing in the move itself establishes that. Both -l and -S therefore pre-flight the LUNs on the target before any teardown starts here. The check runs after the ssh path has been proven and before the pools are locked, the instance disabled or the zone shut down, so a target that cannot take the zone costs a message and leaves the zone running where it is.

Every /dev/rdsk path the zone's configuration names is collected — from disk<n>, scsi<m>-target<j>, the raw extra<n> form, and the device resources that back them, so a zone configured under any of the conventions is covered — and each is checked on the target, in this order:

Any of the three failing refuses the move with nothing changed locally. A zone with no passed-through LUNs is unaffected and says nothing.

OC_LUN_SKIP_TARGET_CHECK=1 skips the whole pre-flight, for a move an operator has reason to start anyway — masking scheduled to complete inside the window, for instance. The LUNs then have to be checked and initialized on the target by hand.

Which attr convention is written

The bhyve launcher, /opt/omnicube/lib/illumos/boot, changed how a LUN is bound to its controller in sysadm 1.12, so the form to write is not a matter of taste:

legacy

sysadm strictly below 1.12. diskN carries the raw path and diskifN names the controller.

target

sysadm 1.12 or above. scsiM-targetJ carries the raw path, and the launcher folds it into the controller's target list.

Exactly one form is written, never both. The legacy pair is not merely redundant on a 1.12+ launcher: that launcher's additional-disk loop passes diskifN straight through as a bhyve device-emulation name, so diskif3=scsi0 is emitted as -s 5:3,scsi0,path, which bhyve does not parse.

The version is read with pkg list -H omnicube/sysadm and the version field is located by shape rather than by column, because IPS inserts a publisher column when the package does not come from the preferred publisher. When it cannot be read the command aborts rather than guess.

Because -r pushes one configuration to every node, the peers listed in config/nodes are probed the same way and a cluster whose nodes straddle 1.12 is refused: no single configuration can satisfy launchers on both sides. A peer that cannot be reached is only warned about, since the synchronisation would skip it too. OC_LUN_ATTR_MODE=legacy or OC_LUN_ATTR_MODE=target forces the form and skips every probe, which is the way through a mid-upgrade cluster and the way to write a configuration deliberately for the other convention. -L honours it too, so a listing made in the same shell describes the form an attach would actually write rather than the one the version implies.

Attaching or listing also warns when the zone already carries attributes of the other convention, which is what an upgrade leaves behind: the attributes survive it untouched but the launcher stops reading them, so those disks quietly stop reaching the guest. Detaching and re-attaching each affected LUN rewrites it in the current form. Detach itself is convention-independent, so a zone configured before an upgrade stays manageable after one.

The two conventions roll over identically but NUMBER differently, and the difference is not cosmetic:

legacy

diskN counts across the whole zone. The seventeenth LUN is disk16 and its diskif16 names scsi1.

target

scsiM-targetJ counts within each controller, because J is a SCSI target ID on that HBA and every HBA numbers its own from zero. The seventeenth LUN is scsi1-target0.

On scsi0 the two coincide for the first sixteen LUNs — disk14 with diskif14=scsi0 corresponds to scsi0-target14 — which makes them easy to conflate. They part at the first rollover.

A zone tops out at controllers times LUNs per controller, so eight times sixteen, or 128 LUNs, under either convention. A data disk already occupying a diskN slot counts against the legacy total.

An attach measures the whole batch against the remaining capacity first and reports the arithmetic:

capacity: 113 slot(s) free, 11 requested (legacy convention)

A batch larger than that is refused there, before any LUN is initialized, rather than partway through the plan — some LUNs reported as planned and a later one failing reads like a partial success, and none of them were written. -L reports the same headroom without attempting anything.

-d with -w removes every attribute naming that path, together with the diskifN partner of each diskN it removes, and the device resource. It works from the configuration rather than from the filesystem, so a LUN already unmapped on the SAN is still removable. The controller itself is left in place even when its last target goes, so that the next attach cannot reuse an index for an unrelated set of disks.

Both mark the configuration as changed and therefore trigger the synchronisation described under -r, and both warn, without failing, when the zone is running: zonecfg edits the persistent configuration, and a running bhyve process was built from the configuration as it stood at boot, so the change takes effect at the next boot of the zone.

-L prints the current map, controller by controller, showing both forms of the association so that a configuration left inconsistent by an upgrade is visible at a glance, and names the convention this node would write. It is read only, and it does not probe the peers.

It reports the remaining headroom for the convention in effect, so how many more can this zone take? is answerable without attempting an attach and reading the refusal — in the legacy convention that ceiling belongs to the zone, so a zone already carrying a dozen disks cannot take a large batch whichever controller is nominated, and reverting it to an earlier state does not necessarily help.

It also reports three inconsistencies that nothing else notices, because zonecfg type-checks none of this and the launcher does what it is told:

the same path presented twice

Two attrs carrying one path. The guest is handed the same LUN as two disks, and whichever attr was meant to name a different LUN is not naming it — so a LUN believed to be attached is absent. This is what a copy-paste in a hand-written configuration looks like.

an attr with no device resource

The zone cannot open the raw node, so the disk never appears in the guest.

a delegated LUN nothing presents

A /dev/rdsk device resource that no diskN or scsiM-targetJ attr names: the LUN reaches the zone and never reaches the guest. Usually the companion of the first case, being the LUN the duplicated attr should have named.

Only /dev/rdsk values participate, so bootdisk — a path relative to the zonepath — and any non-LUN device resource cannot produce a false report.

Attaching many LUNs at once (repeated -w, or -W)

Several LUNs can be given either by repeating -w or by naming a file with -W. The two are equivalent past the point where the list is built, and both are subject to everything described below.

-W takes a file instead of WWNs on the command line, one WWN per line. The path is checked before it is read: it must be a regular file, readable, no larger than a megabyte, and free of NUL bytes. That last test is what distinguishes text from binary here, rather than file(1)'s verdict, whose wording differs between illumos and GNU; when file(1) is installed its classification is quoted in the error message, but it is never the test. The point is that a mistyped or tab-completed path landing on a tarball, an image or a core file is rejected outright instead of producing a line-numbered complaint per line of binary. A short binary containing no NUL falls through to the per-line check, which rejects it by line number. Blank lines are ignored, and so is any line whose first non-blank character is #, so a list can be annotated and individual entries commented out. A trailing comment on a line that carries a WWN is not stripped: quietly ignoring the tail of a line that is about to become a device path is how a typo becomes the wrong LUN. A carriage return at end of line is tolerated, so a file edited on Windows works. The whole file is parsed before anything is attempted and every bad or repeated line is reported with its number, rather than only the first.

A batch is applied all or nothing. Every WWN is resolved and checked — device node present, not already attached, controller and index limits not exceeded — and only then is a single zonecfg transaction built and committed. One unmapped LUN in a list of fifty therefore leaves the configuration exactly as it was, which is what makes a failed run safe to repeat once the list is fixed. Controllers roll over within the batch, so a list of twenty LUNs against an empty zone fills scsi0 with sixteen and puts the remaining four on scsi1.

-W works with -d as well, and is subject to the same all-or-nothing rule: if any listed WWN is not attached to the zone, none of them are detached.

RAM, VCPUs and VNC (-m, -p, -n)

Each rewrites an existing zone attribute with zonecfg select attr name=...; the attribute must already be present in the configuration, as created from vm_tpl.cfg(5). A successful change triggers the synchronisation described under -r.

ZFS lock property

-l and -S take an advisory lock by setting the ZFS user property PROPPREFIX:is_locked to true on the datasets they are about to move, where PROPPREFIX is the value of the SMF property config/site. If a target already reads true, the operation reports that the pool is locked by another process and aborts without changing anything. While set, the property makes autosnap(8), autocleansnap(8) and autosync(8) skip those datasets.

Every error path releases the property with a recursive zfs inherit -r, locally while the pool is still imported here or over ssh on the target once it has been handed over, and verifies the result by value; the recursion matters because on a received dataset the property can sit deeper in the tree with SOURCE=received. When the pool is between export and import, or the peer is unreachable, the release is best effort and a warning names the datasets and the exact pfexec zfs inherit -r command to run by hand. Only a SIGKILL during a move can leave the property set.

-S additionally installs an EXIT, HUP, INT and TERM trap that destroys data_root@SEND however the script terminates, and destroys a stale @SEND before taking a new one, so an interrupted run never blocks the next. There is no lock directory under /var/run/omnicube: this property is the only concurrency control in the command.

OPTIONS

-i name, --instance name

Read configuration from svc:/omnicube/sysadm:name instead of :default, which selects the config/site, config/nodes and config/lock_group values used for the whole run, and is forwarded to autosync(8) by -S. Accepted as -i name , as --instance name, or as --instance=name. It is parsed and removed from the argument list before the option loop and before the shared library is sourced, so it may appear anywhere on the command line; a missing argument is fatal. The OC_SMF_INSTANCE environment variable is a fallback for cron and SMF wrappers, and the command line wins over it.

-z zone

Zone name, mandatory for every operation. Must match [a-zA-Z0-9][a-zA-Z0-9._-]*.

-b

Boot the zone.

-s

Shut the zone down.

-r

Synchronise the zone configuration onto the other cluster nodes.

-l

Relocate a SYNC zone; requires -h.

-S

Send an ASYNC, non-SMF zone to another node; requires -h, -U and -D, all three checked before any work starts.

-h node

Target node for -l and -S, which must not be the local host.

-U user

ssh user for -S. Mandatory and explicit, so that a "Host * User ..." rule in ssh_config cannot silently rewrite the connection user.

-D parent_remote_dataset

Remote parent dataset for -S. The target is parent_remote_dataset/leaf, the leaf being the zone name: with a source root of sr02beio-nvme/zones/zfoo and -D tank/zones, the data lands in tank/zones/zfoo.

-a

Add an ISO or attach a SCSI LUN, according to whether -c or -w is given. Neither takes an argument to -a itself.

-d

Remove an ISO or detach a SCSI LUN; again qualified by -c or -w.

-c iso

Name of an image inside /iso, restricted to [a-zA-Z0-9][a-zA-Z0-9._-]* so it cannot escape that directory. Combining -c with an action other than -a or -d is an error.

-w wwn

WWN of a SCSI LUN to attach or detach, restricted to hexadecimal digits so it cannot escape the /dev/rdsk path or the zonecfg command line. May be given more than once: every WWN is acted on, as a single all-or-nothing batch, exactly as though they had been listed in a -W file. Repeating the same WWN is an error rather than a no-op. On attach the LUN is initialized with mpathadm first; see Initializing a LUN before it is attached. Both the alphabet and the length are checked: a SCSI page 83 identifier is 8, 12 or 16 bytes, so 16, 24 or 32 hex digits. The length matters because the alphabet alone admits the commonest paste error — copying a WWN out of a device path brings the trailing d0 with it, and d and 0 are both hex, so <wwn>d0 would validate and then fail much later as “no device node”, blaming the SAN for a typo. Whichever check fails, the value is stripped of any path, any c0t prefix and any dNpN tail, and if what remains is a valid WWN the message names it. Requires -a or -d, and cannot be combined with -c.

-W file

File of WWNs, one per line, to attach or detach in a single all-or-nothing batch. Must be a readable regular text file under a megabyte, and every line is put through the same alphabet and length checks as -w, reported by line number; see Attaching many LUNs at once.Blanklinesandlinesstartingwith # are ignored; every other line must be a bare WWN, and a WWN repeated in the file is an error naming both line numbers. Requires -a or -d, and cannot be combined with -w or -c.

-L

List the SCSI LUNs attached to the zone. Read only; it neither changes the configuration nor triggers a synchronisation, and it does not contact the peers.

-m ram

Set the ram attribute in GB: a positive integer only, the G suffix being appended by the script.

-p vcpus

Set the vcpus attribute, as a count or a comma separated list of numbers. Only digits and commas are accepted.

-n on|off

Turn the VNC server attribute on or off. No other value is accepted.

EXAMPLES

Example 1: start and stop a zone

manage_zone.sh -z zbeio01 -b
manage_zone.sh -z zbeio01 -s

Example 2: resize a VM and enable its VNC console

manage_zone.sh -z zbeio01 -m 16 -p 8
manage_zone.sh -z zbeio01 -n on

Both rewrite an existing attribute and, for a cluster managed zone, push the configuration to the other nodes by themselves, so no separate -r is needed.

Example 3: relocate a SYNC zone, then send an ASYNC one

manage_zone.sh -z zbeio01 -l -h sr02beio
manage_zone.sh -z zfoo -S -h sr01prbw -U ocadm -D tank/zones

Example 4: attach an installation ISO, then detach it

manage_zone.sh -z zfoo -a -c debian-12.iso
manage_zone.sh -z zfoo -d -c debian-12.iso

Example 5: pass a SAN LUN through to a VM

manage_zone.sh -z zfoo -a -w 618d6dd100f277ffa20bdeaa0000011e
manage_zone.sh -z zfoo -L
manage_zone.sh -z zfoo -d -w 618d6dd100f277ffa20bdeaa0000011e

The first command resolves the WWN to /dev/rdsk/c0t618D6DD100F277FFA20BDEAA0000011Ed0p0 if that is how multipathing spelled it, hangs it off the last SCSI controller of the zone or off a new one when that controller is full, delegates the device node into the zone and, for a cluster managed zone, pushes the configuration to the other nodes by itself. The VM picks the disk up at its next boot. On sysadm 1.11.6 it writes diskN and diskifN; on 1.13.1 it writes scsi0-targetJ.

Example 6: attach a tray of LUNs from a list

$ cat /root/zfoo-luns.txt
# DG7 data volumes for zfoo
618d6dd100f277ffa20bdeaa0000011e
618d6dd100f277ffa20bdeaa0000011f
# 618d6dd100f277ffa20bdeaa00000120   not migrated yet
618d6dd100f277ffa20bdeaa00000121

$ manage_zone.sh -z zfoo -a -W /root/zfoo-luns.txt

# equivalently, for a handful of LUNs and no file:
$ manage_zone.sh -z zfoo -a -w 618d6dd100f277ffa20bdeaa0000011e \\
                          -w 618d6dd100f277ffa20bdeaa0000011f \\
                          -w 618d6dd100f277ffa20bdeaa00000121

Three LUNs are attached in one commit. Had any of them been unmapped on this node, already attached, or over a limit, nothing at all would have been written and the same command could be repeated after fixing the list. Twenty LUNs in the file would fill scsi0 with sixteen and put the remaining four on a freshly created scsi1.

Example 7: attach during a rolling upgrade

OC_LUN_ATTR_MODE=legacy manage_zone.sh -z zfoo -a -w 618d6dd100f277ffa20bdeaa0000011e

Needed only while the nodes straddle sysadm 1.12, when the version probe refuses to choose for the cluster. Pick the form the node that will actually boot the zone can read.

EXIT STATUS

0

The operation completed, or the run-level guard stopped the command before it started.

1

Usage error (no -z, an unknown option, or -S without -h, -U or -D), a failed ISO, LUN or attribute update, or a failed relocate or send. A zone that is not configured on this node is rejected here, before any device is touched.

2

A missing argument to -i or --instance, or a rejected value for -z, -h, -U, -D, -n, -m or -p.

78

Raised while sourcing the shared library when config/site is not set on the selected SMF instance.

For -b and -s the status is that of the last zoneadm, svcadm or zonecfg command run. -r returns 0 unless staging or the local configuration export failed; a failure on an individual peer is logged and skipped without changing the status.

FILES

/opt/omnicube/sbin/manage_zone.sh

This command.

/opt/omnicube/lib/common/utils.sh

Shared library: SMF configuration, node list, logging, ssh helpers, validation, run-level guard.

/opt/omnicube/backup/autosync

Run by -S as the pre-send pass.

/opt/omnicube/sbin/shutdown_windows_server

Run by -s for a zone whose type attribute is windows.

/iso

Images usable with -c.

zonepath/config

Configuration blob written inside the zone data by -l (local zones) and by -S, and re-applied on the target. For lipkg the zonepath is /zones/zone/root, not /zones/zone.

/tmp/manage_zone_config.XXXXXX

Staging file for a zone configuration, created by mktemp locally and, separately, on each peer; removed on both sides whatever the outcome.

/tmp/manage_zone_cfg.XXXXXX

Temporary file used to rewrite dataset paths in the exported configuration during -S.

/usr/sbin/mpathadm

Multipathing utility used to initialize each LUN for passthrough before it is attached. Its absence makes -a -w/-W fail rather than attach an uninitialized LUN.

/opt/omnicube/lib/common/lun.sh

Shared library holding the answer to "which raw devices does this zone pass through", together with the case folding of a device name. Sourced by this command and by the lun-init method, so the operator tool and the boot pass cannot disagree about it.

/lib/svc/method/omnicube/lun-init

Method of svc:/service/omnicube/lun-init:default, which re-applies mpathadm modify lu -b none to every zone's passthrough devices once per boot.

/lib/svc/manifest/omnicube/lun-init.xml

Manifest for that service, including the optional_all dependency it injects into the zone services.

ENVIRONMENT

OC_SMF_INSTANCE

Fallback for -i/--instance, selecting the svc:/omnicube/sysadm instance whose config/site, config/nodes and config/lock_group properties are used, and forwarded to autosync(8) during -S.

OC_IGNORE_RUNLEVEL

When non-empty, bypasses the run-level guard so the command can be used during single-user maintenance.

OC_LUN_ATTR_MODE

legacy or target. Forces the LUN attribute convention written by -a -w/-W and skips the sysadm version probe on this node and on the peers. Intended for a cluster mid-upgrade, or a node whose package version cannot be read; any other value is an error. Every use is logged as a warning, since the attributes written may not match the launcher that has to read them.

It is read from the environment, so the usual prefix form (OC_LUN_ATTR_MODE=legacy manage_zone.sh ...) is enough and export is not required; a bare assignment on its own line, without export and without being a prefix to the command, sets only a shell variable and the script never sees it. A misspelt name is silent by construction — the script reads the correct name, finds it unset, and falls through to the version probe — so any variable within an edit distance of two of the real name, upper-cased, is reported as having no effect. That covers a wrong, missing or extra letter, a missing or extra underscore, a trailing character and a difference of case only. The run continues with the probed convention.

OC_LUN_SKIP_TARGET_CHECK

When set to anything other than 0, skips the SCSI LUN pre-flight that -l and -S otherwise run on the target node (see Moving a zone that has LUNs attached). Neither the visibility of the LUNs on the target nor their mpathadm initialization there is then verified, so the zone may not boot after the move; the skip is logged as a warning naming the number of LUNs and the commands to run by hand. Intended for a move whose SAN masking is expected to complete during the window.

SECURITY

Every privileged action goes through pfexec, locally and on the peers, under the OmniCube Administration profile from /etc/security/exec_attr.d/omnicube and /etc/security/prof_attr.d/omnicube; that profile is root-equivalent, so grant it only to accounts you would trust with the root password. Zone names, host names, ssh users, dataset names, ISO file names and the ram, vcpus and vnc values are validated before they reach a zonecfg, zfs, zpool or ssh command line, and every dataset name derived by a source-to-target path translation is re-validated. Configuration blobs are written with | pfexec tee rather than a privileged shell, so the profile never has to grant sh.

SEE ALSO

activate_zone_vnc.sh(1), omnicube_utils(3), oc_lock(3), oc_ssh(3), oc_validate(3), vm_tpl.cfg(5), omnicube(7), autocleansnap(8), autosnap(8), autosync(8), create_zone_config.sh(8), create_zone_pool.sh(8), isolate_node.sh(8), shutdown_windows_server(8), sync_pool.sh(8), zone_monitor.sh(8), zone_save.sh(8), zones_srv_monitor.sh(8).

NOTES

-a and -d never take the name of what they act on as an argument: an ISO is named with -c and a LUN with -w. An ISO change does not mark the configuration as changed, so it is not propagated to the other nodes; run -r afterwards for a cluster managed zone. A LUN change does mark it, and is propagated by itself.

The LUN attribute convention is a property of the installed sysadm, not of the zone: upgrading a node past 1.12 leaves every zone's existing diskN/diskifN attributes in place while the launcher stops reading them, so the disks disappear from the guest at its next boot without anything in the configuration looking wrong. -a -w/-W and -L both warn when they see it. The repair is to detach and re-attach each affected LUN, which rewrites it in the current form; there is no in-place conversion.

OC_LUN_ATTR_MODE is also how a test configuration is produced on purpose: on a node running sysadm 1.12 or later,

OC_LUN_ATTR_MODE=legacy manage_zone.sh -z zone -a -w wwn

writes diskN and diskifN even though that node's launcher cannot read them. Everything else about the attach is real — the device node is resolved and checked, mpathadm runs, the configuration is committed and, for a cluster managed zone, pushed to the peers — so the resulting VM will not boot. That is the point of the option, not a side effect, and each use is logged as a warning saying so. The warning about a zone carrying attributes of both conventions is likewise expected here rather than a fault to repair.

An attach that appears to have hung is almost always inside mpathadm modify lu -b none, which the tool reports per LUN precisely so that this is visible. It is safe to wait: nothing is written to the zone configuration until every LUN of the batch has been initialized.

Do not run -a -w/-W against a zone that is going to be moved with -l or -S to a node on the other side of 1.12: the attributes travel with the configuration and will not be understood on arrival.

-p accepts only digits and commas, so the keyword form used in the bhyve template, for instance sockets=1,cores=2,threads=1, cannot be set with this command; edit the vcpus attribute with zonecfg directly, then run -r.

-l and -S are not interchangeable: -l only makes sense for a zone whose storage the target can already import, and rejects nothing but a target equal to the local host, while -S refuses any zone that has an SMF instance. Both are destructive on the source before they are constructive on the target; when a step fails in between, the error message names the exact zonecfg and zoneadm commands that reinstate the zone locally from zonepath/config. After a successful -S, the source datasets and snapshots still exist and must be removed by hand, and the command assumes every dataset of a zone lives below a path component equal to the zone name, aborting when that convention is not met.

man8/manage_zone.sh.8generated 2026-09-02 05:17 CEST