NAME
omnicube_utils - shared shell function library for OmniCube commands
SYNOPSIS
amp;. /opt/omnicube/lib/common/utils.sh
DESCRIPTION
utils.sh is the common shell library sourced by nearly every OmniCube command: autosnap(8), autosync(8), autocleansnap(8), manage_zone.sh(8), sync_pool.sh(8), pool_monitor.sh(8), sys_monitor(8), zone_monitor.sh(8), zones_srv_monitor.sh(8), isolate_node.sh(8), create_zone_pool.sh(8), create_zone_config.sh(8), create_iscsi_lun.sh(8) and the other members of the suite. It provides logging with syslog and throttled alert mail, a mkdir-based single-instance lock discipline, a run-level guard, argument validation for values that reach privileged command lines, an SSH pre-flight probe, and backup-policy resolution.
The library must be sourced and never executed: it tests ${BASH_SOURCE[0]} against ${0} and, when they are equal, prints utils.sh must be sourced, not executed on standard error and exits 1.
Source-time actions
Sourcing the library is not side-effect free. In order, it:
Every directory creation and every chgrp(1)/chmod(1) normalization is best-effort and silent: failures are discarded so that sourcing the library never aborts a caller running under set -e. Both directory helpers refuse to operate on a path that is a symbolic link, so that a link planted by an unprivileged user on tmpfs cannot be followed by a later root invocation.
Reading configuration
Every SMF property this suite reads goes through oc_svcprop(), and every property it reads is declared in the service manifest, even when its default is "unset". The two halves are one convention.
Declaring a property gives it a type, so an operator can write
svccfg -s ${OC_SMF} setprop config/vnc_bind = 127.0.0.1
without repeating astring:, and svccfg listprop config/* shows the full set of knobs rather than only the ones somebody has already changed. A property that is meant to default to "unset" is declared with no value - <property name='x' type='astring'/>- never with <propval value=''/>, because svcprop(1) prints an empty astring value as a literal pair of double quotes. A <propval> with an empty value therefore hands every reader the two-character string instead of nothing, which [ -n ... ] reads as set. In zone-mgt that would invert the meaning of the config/nfs_opts test.
oc_svcprop() closes the same gap from the reading side, for the property an operator clears by hand with setprop config/x = \\: it turns that back into an empty string, so a cleared property behaves exactly like one that was never set. Multi-value properties pass through untouched, so arr=($(oc_svcpropconfig/nodes)) keeps working. It is defined above the source-time reads in utils.sh because those run while the file is being sourced.
When adding a property: declare it in /lib/svc/manifest/omnicube/sysadm.xml, document it in the SMF PROPERTIES section of omnicube(7), and read it with oc_svcprop().
Global variables
The following variables are set at source time and are part of the interface; consumers read them directly.
_SSH_PROBE_CACHE is an associative array holding per-process probe verdicts and is private to oc_ssh(3).
Function index
Names beginning with an underscore are internal helpers; they are documented because their behaviour is visible in logs and in policy files, not because they are meant to be called from new code.
Portability
The library is bash code and is sourced by #!/usr/bin/bash scripts. It depends on bash features that ksh93 either lacks or interprets differently: ${BASH_SOURCE[0]} for the execute guard, ${HOSTNAME} in the mail sender, declare -A for the probe cache, [[ ... =~ ... ]] for every validation pattern, ${script/.*/} pattern substitution for logtag, and name=(...) array assignment for nodes, host_zones and MAIL_DOMAIN. Under ksh93 the same array syntax creates a compound variable, and $0 inside a function name { ... } block is the function name rather than the script, which would corrupt script and logtag. Members of the suite that are not bash, such as qemu-monitor-command(8) (ksh) and logadm(8) (sh), therefore do not source this library.
Two functions carry a calling-convention restriction that follows from being shell state or from calling exit: ssh_reachable() must be called as a statement and not inside $(), where cache updates would be discarded with the subshell, and abort_if_shutting_down() must not be called inside $() or a pipeline, where exit would only leave the subshell.
EXIT STATUS
Sourcing the library succeeds silently, or terminates the caller with:
FILES
ENVIRONMENT
EXAMPLES
Example 1: standard prologue of a cron or SMF job
#!/usr/bin/bash
amp;. /opt/omnicube/lib/common/utils.sh
LOCK_DIR=${LOCK_BASE}/${logtag}.myjob.lock
acquire_lock_or_exit "${LOCK_DIR}"
trap '[[ -d ${LOCK_DIR} ]] && rmdir ${LOCK_DIR} 2>/dev/null' EXIT HUP INT TERM
abort_if_shutting_down
info "starting"
Example 2: reading configuration from a non-default instance
OC_SMF_INSTANCE=offsite
amp;. /opt/omnicube/lib/common/utils.sh
info "using ${OC_SMF} with prefix ${PROPPREFIX}"
Example 3: a privileged local command and a remote one
${PFEXEC} zfs set ${PROPPREFIX}:is_locked=true "${pool}"
${_SSH_CMD} "${node}" "pfexec zpool import ${pool}"
SEE ALSO
oc_log(3), oc_lock(3), oc_runlevel(3), oc_validate(3), oc_ssh(3), oc_policy(3), default.conf(5), autosnap(8), autosync(8), manage_zone.sh(8), sync_pool.sh(8), isolate_node.sh(8), omnicube(7).
NOTES
host_zones and nodes are snapshots taken at source time; a zone installed or a node added while a long-running monitor is in its loop is not seen until the next invocation.
The library reads SMF properties with svcprop(1) at source time only. Changing config/site, config/nodes, config/lock_group or config/mail_throttle_window has no effect on processes that are already running.
Sourcing is deliberately tolerant: only a missing config/site aborts. A failure to create ${LOCK_BASE} is not reported at source time; it surfaces later as a lock acquisition failure from acquire_lock_or_exit().