OK-5484 Add bulk VM lifecycle script for Semaphore REST API#62
Conversation
Adds semaphore/bulk_vm_lifecycle.py for customers who need to provision,
configure, manage, and tear down groups of VMs sharing a common name
prefix without clicking through each Semaphore template by hand.
Subcommands hit the Semaphore REST API to drive the existing playbook
templates:
- deploy Bulk-creates N VMs named <prefix>-<random hex>, in
parallel, and writes a manifest at
semaphore/.bulk_vms_<prefix>.json.
- list / manage / delete
Use the underlying playbooks' built-in ^prefix regex
match so a single Semaphore task covers the whole group.
'delete' wraps 'manage --state absent' and clears the
manifest on success.
- provision-user
Reads the manifest and runs the Provision User to VM
template per VM in parallel (the playbook uses exact
vm_name matching).
- install-citrix
Same pattern for the Install Citrix VDA template;
installer URL and hostname suffix come from the existing
Base VM Credentials environment.
Includes semaphore/BULK_VM_LIFECYCLE.md with usage guidelines, and
cross-references the new doc from both the root README and
semaphore/README.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ybenchouaf
left a comment
There was a problem hiding this comment.
From a product perspective, this sufficiently addresses the need for core bulk VM lifecycle operations for now. Will validate with key customers and revisit the UI-driven flow (and potentially group primitives if required) if necessary.
Note: I'm rebuilding my sandbox environment, so I have not executed this against MSVDI hosts myself.
|
Something I am thinking about - do we want this as a separate Python script? This means the user must run the script outside of the Semaphore UI, which defeats the purpose of having the UI. (I know we have a few scripts like this already, but they are mainly for bootstrapping/setup purposes, not common operations) Should we consider having this as something that can be run via Ansible through the Semaphore UI instead? It also depends on how commonly this will be used as well. If it's not often used, maybe the script is OK |
|
@spikeburton I'm inclined to keep it as a separate script, since I'm not sure it's the key flow we're accommodating for in the Semaphore UI. I'm totally down to graduate this to something we can run in Ansible once we've got a stronger signal. For now, this is a workaround to keep the UI simple while allowing this new flow. |
We can assume this will be commonly run, at least during initial setup, for organizations with sizable fleets of hosts they need to deploy VMs on. While this as a standalone python script is a step in the right direction for an improved UX for mass provisioning, I would love to see a way to execute this from within the UI. |
I'm okay with that approach. Let's get this out the door as it's an incremental, meaningful improvement that we can test with our first customers. |
|
|
||
| `semaphore/bulk_vm_lifecycle.py` drives the Semaphore UI REST API to manage groups of Orka VMs that share a common name prefix. It is intended for customers who need to spin up, configure, manage, or tear down many VMs at once without clicking through the UI for each one — including day-2 operations such as provisioning a user across the group and installing the Citrix VDA on every VM. | ||
|
|
||
| Every VM created by `deploy` is named `<prefix>-<random>` (e.g. `demo-a1b2c3d4`). The script tracks the names it generated in a manifest at `semaphore/.bulk_vms_<prefix>.json`, which later subcommands read to target the same set of VMs. |
There was a problem hiding this comment.
I would suggest we add semaphore/.bulk_vms_*.json to the .gitignore


Summary
semaphore/bulk_vm_lifecycle.py, a uv-runnable CLI that drives the Semaphore REST API to provision, configure, manage, and tear down groups of VMs sharing a common name prefix. Subcommands:deploy,list,manage,delete,provision-user,install-citrix.deployparallelizes one task per generated<prefix>-<random hex>name and tracks them in a local manifest;manage/deletelean on the existing^prefixregex match invm.yml/list.ymlso one Semaphore task covers the whole group;provision-userandinstall-citrixread the manifest and fan out per-VM tasks because their playbooks require exact name matches.semaphore/BULK_VM_LIFECYCLE.mdwith usage guidelines (prereqs, examples for every subcommand, REST flow, common flags, manifest format, operational notes including Citrix-specific prereqs in theBase VM Credentialsenv and the post-install reboot).README.mdandsemaphore/README.md.Test plan
uv run semaphore/bulk_vm_lifecycle.py --helpand each<subcommand> --helpparse cleanlydeploy --prefix demo --count 2 --vm-image <url>creates 2 VMs and writessemaphore/.bulk_vms_demo.jsonlist --prefix demoreturns only the prefix-matched VMsmanage --prefix demo --state stoppedthen--state runningtoggles the groupprovision-user --prefix demo --username u --password pprovisions on each manifest VMinstall-citrix --prefix demoinstalls the VDA on each manifest VM (requirescitrix_installer_url+hostname_suffixset viaconfigure_semaphore.py)delete --prefix demo --yesremoves the VMs and clears the manifest🤖 Generated with Claude Code