Period: from the start of integration testing on the real ESXi environment.
- Fixed govc check in preflight/doctor:
- before:
govc about(unstable/incompatible in this environment) - after:
govc version
- before:
- Hardened govc binary resolution:
GOVC_BIN->shutil.which('govc')->/usr/local/bin/govc
- Added strict helper check in doctor:
- success only when
rc == 0andstdout == "OK"
- success only when
- Added warning check
cloudinit_vmware_datasource_hint:- detects managed VM with IP but without
guestinfo.vmctl.cloudinit_status=ready - provides explicit remediation for VMware datasource in the template.
- detects managed VM with IP but without
- bootstrap-esxi-side.sh:
- expanded
PATHfor non-interactive shell (/bin:/sbin:/usr/bin:/usr/sbin) - made root-check more robust
- expanded
- Idempotent ESXi account synchronization:
- if user already exists, now runs
esxcli system account setto sync password - removed drift between
esxi.envand actual ESXi credentials
- if user already exists, now runs
- Helper heredoc switched to quoted
<<'HELPER_EOF'+ placeholders - authorized_keys append moved to safe
grep -qFlogic.
- Removed helper-dependent path
write-vmx-b64from critical chain- reason: ESXi reported
base64: not found - replacement: generate VMX locally + upload via
govc datastore.upload
- reason: ESXi reported
- Fixed guest OS for alma10:
- correct
guest_os: rhel9-64
- correct
- Added/fixed VMX compatibility flags:
vhv.enable = TRUEvvtd.enable = TRUEvcpu.hotadd = TRUEmem.hotadd = TRUEfloppy0.present = FALSE- correct PCIe bridge layout
- Fixed firmware/NIC mode for template-based create:
firmware = efiethernet0.addressType = generated(MAC assigned by ESXi)
- Standardized DHCP path for template-based provisioning
- Changed IP wait to IPv4-only:
govc vm.ip -wait=... -v4- avoids treating link-local IPv6 as success.
- Redefined successful create-test criteria:
powered on + ipis not enough- required:
- IPv4 acquired
- marker
guestinfo.vmctl.cloudinit_status=ready - SSH login with injected key
- Confirmed root cause of SSH failures during test phase:
- VMware datasource was missing/not enabled in template
- After enabling datasource in template:
readymarker appears- key-based SSH works consistently.
- Added
--datastoreto create - Fallback to
esxi.default_datastorewhen flag is not provided - Validation for
config.datastores+ placement viatemplate.allowed_datastores - State now stores:
template_datastoretarget_datastoredatastoreas alias
- delete/purge read datastore only from state/tombstone, not from CLI.
- Added PyYAML sanity-check in install flow:
python3 -c "import yaml" - ESXi bootstrap parameters are passed through temporary env file (
/tmp/vmctl-bootstrap.env), not inline with sensitive values - Tightened permissions:
/opt/hermes-vmctl=750/opt/hermes-vmctl/secrets=700- secret files =
600
- Standardized
DRY_RUNvia${DRY_RUN:-0} - Added install log:
/var/log/hermes-vmctl-install.log ALLOW_DIRECT_ESXI=0kept as secure default.
govc aboutfalse-red / incompatibility -> resolved by switching togovc version- helper
write-vmx-b64failed due to missingbase64-> resolved via upload path Cannot complete login due to incorrect user/password-> resolved via account-set sync in bootstrapunsupportedGuestOS-> resolved withrhel9-64No PCIe slot available for SCSI0/Ethernet0-> resolved by VMX layout correction- DHCP false-hang on IPv6 -> resolved by IPv4-only wait + nested network check
- SSH
Permission denieddespite guestinfo marker -> resolved by enabling VMware datasource in template.
preflight: greendoctor: green + datasource hint check- E2E cycle passes:
- create -> marker ready -> SSH -> sudo/install check -> delete -> purge
- Verified on created VM:
- key-based passwordless login
sudo -n- package installation (
dnf install ...).
- Automate VMware datasource in template build pipeline (Packer/Ansible) to avoid manual edits for each new image.
- Optionally split
doctorinto strict and advisory sections (currently the hint does not fail overallok).