Day-2: Image Management (vLCM Images) via the API
Managing vLCM cluster images in VCF Operations 9.1 with the SDDC Manager API — get a token, list the images (personalities), and delete a custom exported image the GUI won't let you remove. Postman- and curl-friendly.
Draft — VCF 9.1 lab series. Hostnames are from the
pgvcf1lab (pgvcf1sddcm.pgnet.io); swap them for your own. Live secrets — the admin password and the service-accountapiKey— stay as<PLACEHOLDER>; never paste those into a shared doc. Sits between Operations and Lifecycle & Updates as a Day-2 task.
📘 Official documentation. vLCM image management is documented by Broadcom. This page just shows the API flow for one common Day-2 gap. Always defer to the vendor docs — see Sources. Where they differ, the official docs win.
Why the API for images?
In VCF 9.1, a vLCM cluster image — the desired-state ESX version + vendor add-on + firmware/components a cluster runs — is exposed in the SDDC Manager API as a personality. If you’ve moved a cluster from the old vLCM baselines model to images (see the transition doc), you’re already managing personalities whether you call them that or not.
Most image work happens in the UI. One thing does not: you can export a cluster’s image to a reusable custom image, but VCF Operations 9.1 gives you no button to delete an exported / custom image again. They accumulate. The supported way to remove one is a single API call — Broadcom documents exactly this in KB 321672.
So this page is the practical Day-2 loop for anyone driving it from Postman (or curl):
| Step | Call | Purpose |
|---|---|---|
| 1 | POST /v1/tokens | Get a bearer token |
| 2 | GET /v1/personalities | List images, find the id / name |
| 3 | DELETE /v1/personalities | Remove the custom / exported image |
What you need
- The SDDC Manager FQDN — in 9.1 this is the appliance that fronts the Fleet / lifecycle APIs, e.g.
https://pgvcf1sddcm.pgnet.io. - An account that can authenticate to it — either
admin@local(or your admin user) with its password, or a SERVICE accountapiKeyif you’ve minted one for automation. - TLS: production callers should pin the SDDC Manager CA. In a lab it’s common to skip verification (
-kin curl, Settings → SSL certificate verification → off in Postman). Pin the CA if you can.
All calls below use
https://pgvcf1sddcm.pgnet.ioas the base URL. In Postman, set it once as a collection variable{{base}}so you can point the same collection at any environment.
Step 1 — Get a token
POST {{base}}/v1/tokens. The body is JSON. Two ways to authenticate — pick one:
A. Username + password (simplest for interactive Postman use):
{
"username": "admin@local",
"password": "<ADMIN_PASSWORD>"
}
B. SERVICE account apiKey (what automation uses — long-lived key, short-lived token):
{
"apiKey": "<SERVICE_ACCOUNT_API_KEY>"
}
Headers: Accept: application/json and Content-Type: application/json. The response gives you a short-lived bearer plus a refresh token:
{
"accessToken": "eyJhbGciOi...",
"refreshToken": "abc123..."
}
📸 Screenshot: Postman —
POST /v1/tokenswith the username/password body and the 200 response showingaccessToken.
Capture it automatically in Postman. Add this to the request’s Scripts → Post-response (formerly Tests) tab so every later call inherits the token:
const body = pm.response.json();
pm.collectionVariables.set("token", body.accessToken);
Then set the collection (or folder) Authorization to Bearer Token with value {{token}}, and leave every other request on Inherit auth from parent. Now steps 2 and 3 are just send-and-go.
Token lifetime. The
accessTokenis short-lived — if a later call returns 401, re-run Step 1 to mint a fresh one (or use therefreshTokenagainst/v1/tokens/access-token). Automation should re-mint on expiry rather than caching a token.
Step 2 — List the images
GET {{base}}/v1/personalities with Authorization: Bearer {{token}}. The response is a page of elements; each element is one image:
{
"elements": [
{
"personalityId": "b1f2...-...",
"personalityName": "prod-cluster-image",
"baseImageVersion": "9.1.0-24000000",
"source": "EXPORTED"
}
],
"pageMetadata": { "totalElements": 1 }
}
Note the personalityId (GUID) and personalityName of the image you want to remove — either one is enough for Step 3. Exported/custom images typically show a source of EXPORTED (vs a cluster-derived image), which is how you tell the disposable ones apart.
📸 Screenshot: Postman —
GET /v1/personalitiesresponse, highlightingpersonalityName/personalityIdof the exported image.
Step 3 — Delete the custom / exported image
DELETE {{base}}/v1/personalities with the target passed as a query parameter — by name or id:
DELETE {{base}}/v1/personalities?personalityName=prod-cluster-image
or
DELETE {{base}}/v1/personalities?personalityId=b1f2...-...
Header: Authorization: Bearer {{token}}. A 200 / 202 / 204 means it’s gone. Re-run Step 2 to confirm it’s no longer in the list.
📸 Screenshot: Postman —
DELETE /v1/personalities?personalityName=...returning 204, then the empty/updated list.
Careful — this is a delete. There’s no undo. Delete only images you exported and no longer need. An image a cluster is actively using shouldn’t be removed out from under it; remove the disposable exported copies. Confirm the name/id against Step 2 before you send.
Quick reference — curl
The same three calls without Postman. Lab-style (skip TLS verify with -k); pin the CA in production.
SM=https://pgvcf1sddcm.pgnet.io
# 1. Token (username/password shown; swap the body for {"apiKey":"..."} for a service account)
TOKEN=$(curl -sk -X POST $SM/v1/tokens -H 'Content-Type: application/json' \
-d '{"username":"admin@local","password":"<ADMIN_PASSWORD>"}' \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["accessToken"])')
# 2. List images (personalities) — find the id/name
curl -sk $SM/v1/personalities -H "Authorization: Bearer $TOKEN" | python3 -m json.tool
# 3. Delete the exported/custom image (by name or id)
curl -sk -X DELETE "$SM/v1/personalities?personalityName=prod-cluster-image" \
-H "Authorization: Bearer $TOKEN" -i
Automating with Salt (pgnet)
In the lab this is wrapped in the sddc_api runner so it’s a one-liner and confirm-gated. The token is minted from the svc-salt-sddc SERVICE account’s apiKey, read straight from OpenBao (never a password on the CLI):
# list images (personalities)
salt-run sddc_api.report kind=personalities
# delete one — confirm-gated and idempotent
salt-run sddc_api.personality_delete personality_name=prod-cluster-image confirm=yes
The runner mints a short-lived bearer via sddc_rest.mint_token, re-mints on expiry, and pins the SDDC Manager CA — the same three calls above, just made safe to run unattended. The Salt wiring is intentionally kept out of the step-by-step so the API flow stays readable.
Sources
- Broadcom KB 321672 — How to delete a Custom Exported Image in Image Management from SDDC Manager (the delete this page automates)
- Broadcom — Transitioning from vLCM Baselines to vLCM Images