ESXi Shell Task Authoring¶
ESXi Shell Overview¶
- ESXi runs BusyBox shell, NOT bash
- Always use
#!/usr/bin/env shshebang - No prelude template available — error handling must be inlined
- Limited tool availability compared to full Linux
- Two execution models: native (on ESXi) vs context (remote from Linux host)
Shell Constraints¶
- Use POSIX
[ ]test syntax preferred (though modern BusyBox supports[[ ]]) - No bash-specific features: arrays, associative arrays, process substitution
- Available core tools: grep, awk, sed, cut, sort, uniq, printf, echo, mkdir, mount, cp, chmod, rm
- ESXi-specific tools:
esxcli,localcli,openssl,/sbin/chkconfig,/bin/services.sh - No package manager — tools are what's on the ESXi image
python3available on ESXi 7.x and newer
Error Handling¶
Since there's no prelude, define xiterr() inline at the top of every ESXi task:
xiterr() { [[ "$1" =~ ^[0-9]+$ ]] && { XIT=$1; shift; } || XIT=1; printf "FATAL: $*\n"; exit $XIT; }
- Use
set -efor basic error trapping - Always use explicit
exit 0on success,exit 1on failure - Check command results:
STATE=$(localcli system maintenanceMode get)
[[ "$STATE" == "Enabled" ]] && xiterr 1 "System still in maintenance mode"
ESXi Management Commands¶
- User management:
esxcli system account add/set/remove - Permissions:
esxcli system permission set/remove - Maintenance mode:
localcli system maintenanceMode set --enable true/false,localcli system maintenanceMode get - Networking:
- vSwitches:
localcli network vswitch standard add/remove/uplink - Port groups:
localcli network vswitch standard portgroup add/remove - IP config:
localcli network ip interface add,localcli network ip interface ipv4 set
- vSwitches:
- Firewall:
localcli network firewall ruleset set --enabled true --ruleset-id=name - NTP:
esxcli system ntp set/get(ESXi 7.x+) - Services:
/sbin/chkconfig name on/off,/etc/init.d/name start/stop/restart,/bin/services.sh restart - System info:
esxcli system version get,esxcli system hostname get
File System Paths¶
/tmp/— Temporary files (cleared on reboot)/opt/rackn/— Persistent RackN configuration/etc/vmware/— VMware system configuration/etc/vmware/ssl/— TLS certificates (rui.crt, rui.key)/etc/ntp.conf— NTP configuration (ESXi 6.x)- No standard
$HOME— use explicit paths
Context vs Native Execution¶
Native Tasks¶
Native tasks run directly ON the ESXi host:
- Use
#!/usr/bin/env sh(BusyBox) - No prelude template
- Direct access to esxcli, localcli
- Examples: esxi-set-ntp, esxi-manage-users, esxi-exit-maint-mode
Context Tasks¶
Context tasks run on a Linux host and manage ESXi remotely:
- Use
#!/usr/bin/env bashwith{{ template "prelude.tmpl" . }} - Access ESXi via SSH/SCP (
sshpass+scp) or vSphere API (Python) - Task names often prefixed with
esxi-no-vib-* - Examples: esxi-no-vib-enable-ssh (Python vSphere API), esxi-no-vib-place-config-on-host (SCP)
- Run in the
esxi-agent-runnerDocker context (includes govc, pyvmomi, PowerCLI, drpcli)
Using Python on ESXi¶
python3 is available on ESXi 7.x+. Common pattern: render a Python helper template to /tmp/, then call from sh:
Templates:
- Name: "esxi-params.py"
Path: "/tmp/esxi-params.py"
ID: "esxi-params.py.tmpl"
- Name: "my-esxi-task.sh"
Contents: |
#!/usr/bin/env sh
xiterr() { [[ "$1" =~ ^[0-9]+$ ]] && { XIT=$1; shift; } || XIT=1; printf "FATAL: $*\n"; exit $XIT; }
set -e
python3 /tmp/esxi-params.py get 'my/param'
Complete Example¶
---
Name: "example-esxi-configure"
Description: "Configure an ESXi host setting"
Documentation: |
Demonstrates a native ESXi task that checks and sets
maintenance mode status. Uses inline error handling
since no prelude is available on ESXi.
OptionalParams:
- rs-debug-enable
Meta:
icon: "server"
color: "yellow"
title: "VMware Content"
feature-flags: "sane-exit-codes"
Templates:
- Name: "esxi-params.py"
Path: "/tmp/esxi-params.py"
ID: "esxi-params.py.tmpl"
- Name: "example-esxi-configure.sh"
Contents: |
#!/usr/bin/env sh
# Example ESXi native task
xiterr() { [[ "$1" =~ ^[0-9]+$ ]] && { XIT=$1; shift; } || XIT=1; printf "FATAL: $*\n"; exit $XIT; }
{{ if eq (.Param "rs-debug-enable") true }}set -x{{ end }}
set -e
# Check current maintenance mode state
STATE=$(localcli system maintenanceMode get)
echo "Current maintenance mode: $STATE"
if [ "$STATE" = "Disabled" ]; then
echo "Host is not in maintenance mode - no action needed"
exit 0
fi
# Exit maintenance mode
localcli system maintenanceMode set --enable false
NEW_STATE=$(localcli system maintenanceMode get)
[ "$NEW_STATE" = "Disabled" ] || xiterr 1 "Failed to exit maintenance mode"
# Update DRP parameter
python3 /tmp/esxi-params.py delete 'esxi/maintenance-mode'
echo "Successfully exited maintenance mode"
exit 0