proxmox: Delete with seed cleanup, health Checker, CRD type comment
Delete stops and destroys a VM of ours under the per-name lock, then deletes its seed on the VM's node, or on every node when no VM of ours was left. A hibernated VM of ours is Permanent, as in Create. The Checker verifies each node concurrently (version, node status, ISO storage, templates) and adds CertificateInvalid, CredentialsUnavailable, StorageNotFound and TemplateNotFound to the shared reasons. The ProviderHealth type comment gains proxmox. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -381,22 +381,35 @@ the seed ISO; the VM's disks are removed by the destroy call itself, with
|
||||
`purge=1&destroy-unreferenced-disks=1`. Under the per-name lock:
|
||||
|
||||
1. Parse the ID (`ErrPermanent` if malformed).
|
||||
2. `/cluster/resources`. VMID absent: skip to step 7, trying every configured
|
||||
node because the VM's node is no longer known.
|
||||
3. `lock` set or `status: unknown`: `ErrTransient`. A clone or another task
|
||||
still running finishes first; the reconciler calls Delete again after
|
||||
`DeletionPoll`.
|
||||
4. Read the config. `does not exist`: skip to step 7. A different name, or
|
||||
no mark: the VM is not ours; log it and skip to step 7 without touching
|
||||
it.
|
||||
5. Status other than `stopped`: `POST …/status/stop`, wait (stop budget).
|
||||
Stop works on a paused VM too.
|
||||
2. `/cluster/resources`. VMID absent, or held by a container: skip to
|
||||
step 7, trying every configured node because the VM's node is no longer
|
||||
known.
|
||||
3. `lock` set, other than `suspended`, or `status: unknown`: `ErrTransient`.
|
||||
A clone or another task still running finishes first; the reconciler
|
||||
calls Delete again after `DeletionPoll`.
|
||||
4. Read the config. `does not exist`: skip to step 7 on every node. A
|
||||
different name, or no mark: the VM is not ours; log it at V(1) and skip
|
||||
to step 7 on every node without touching it. Our VM with a `lock` other
|
||||
than `suspended` (taken since the listing): `ErrTransient`. Our VM with
|
||||
`lock: suspended` (hibernated): `ErrPermanent` asking the admin to resume
|
||||
or destroy it, the same answer Create's ownership check gives. The
|
||||
destroy refuses a locked VM, and that lock never clears on its own, so
|
||||
Transient would retry forever; Permanent puts the admin action in the
|
||||
Proxy's status, where `reconcileManaged` latches it and the finalizer
|
||||
path keeps retrying it visibly. A hibernated VM that is not ours is left
|
||||
alone like any other.
|
||||
5. Status (from the listing) other than `stopped`: `POST …/status/stop`,
|
||||
wait (stop budget). Stop works on a paused VM too, which the listing
|
||||
shows as `running`. `does not exist` means the VM is gone.
|
||||
6. `DELETE /nodes/{node}/qemu/{vmid}?purge=1&destroy-unreferenced-disks=1`,
|
||||
wait (destroy budget). `does not exist` is success.
|
||||
7. `DELETE /nodes/{node}/storage/{isoStorage}/content/<isoStorage>:iso/<name>-seed.iso`,
|
||||
wait (seed-delete budget). A missing volume is still a successful task,
|
||||
so no message is matched. On the try-every-node path a node whose
|
||||
request fails is logged and skipped.
|
||||
wait (seed-delete budget), on the VM's node when steps 5 and 6 ran on a
|
||||
VM of ours, and on every configured node in config order otherwise. A
|
||||
missing volume is still a successful task, so no message is matched. On
|
||||
the every-node path a node whose request or task fails is logged at V(1)
|
||||
and skipped, unless ctx ended, which fails the call; on the VM's node a
|
||||
failure fails the call (a 403 for `Datastore.Allocate` is Permanent).
|
||||
8. Return nil.
|
||||
|
||||
Everything is gone when Delete returns nil, so `Get` afterwards is
|
||||
@@ -593,18 +606,31 @@ failed for a network reason, or pveproxy answered 595 or 596);
|
||||
`APIError` (any other failure). Provider-specific, each fixed differently by
|
||||
an admin:
|
||||
|
||||
- `CertificateInvalid`: TLS verification failed. Fix `url` or `caFile`, not
|
||||
the host.
|
||||
- `CertificateInvalid`: TLS verification failed, or `caFile` is missing or
|
||||
holds no certificate. Fix `url` or `caFile`, not the host.
|
||||
- `CredentialsUnavailable`: the token file is missing or malformed. Fix the
|
||||
Secret, not Proxmox.
|
||||
- `StorageNotFound`: `isoStorage` is missing, inactive, or has no `iso`
|
||||
content. Fix the storage on the node.
|
||||
content. Fix the storage on the node. Any 500 from the storage status
|
||||
call counts as missing, whatever its wording (it does not exist, is not
|
||||
enabled on that node, or is offline; no missing-storage response was
|
||||
captured, so no text is matched), and the message carries Proxmox's
|
||||
text. A 401, 403, 595 or 596 there keeps its shared reason.
|
||||
- `TemplateNotFound`: a configured template VMID does not exist or is not a
|
||||
template. Fix the template or the catalogue.
|
||||
|
||||
Details: `pveVersion`, `kernel`, `tokenID` (the part before `=`, never the
|
||||
secret), `isoStorage`, `isoStorageAvailGiB`, `templates`, filled as far as
|
||||
the check got. Cost: four requests per node per round. The `status.type`
|
||||
the check got; `isoStorage` is always there. `templates` counts catalogue
|
||||
entries. The Checker reads `tokenFile` itself, before the first request,
|
||||
with the client's `readToken`: the seam stays one method per endpoint, and
|
||||
a missing or malformed file answers `CredentialsUnavailable` without a
|
||||
request. Only the part before `=` is kept.
|
||||
|
||||
`Timeout` also covers a request that runs out of its own timeout while the
|
||||
round is still running. A dial or a connection cut mid-response is
|
||||
`Unreachable`, even when the dial ran out of its own 10 s budget, because
|
||||
the node did not answer. Cost: four requests per node per round. The `status.type`
|
||||
comment in `api/v1alpha1/providerhealth_types.go` gains `proxmox` and the
|
||||
CRD is regenerated.
|
||||
|
||||
@@ -713,14 +739,16 @@ named `proxmox`, with `provider` on every line and `vmid`, `name` and
|
||||
`node` on every line about an instance.
|
||||
|
||||
- V(1): one line per operation outcome (`proxmox vm ensured running`,
|
||||
`proxmox vm fetched` with state, ip and uid, `proxmox vm deleted`,
|
||||
`proxmox vm fetched` with state, ip and uid, `proxmox vm deleted` with
|
||||
`destroyed` (false when no VM of ours was left to destroy),
|
||||
`proxmox vms listed` with counts, `proxmox node checked` with the reason),
|
||||
one `proxmox api call` line per seam call from the decorator (`call`,
|
||||
`node`, `vmid`, `storage`, `upid`, `duration`, plus `newid` and `name`
|
||||
on a clone, `filename` on an upload and `volid` on a volume delete, and
|
||||
on failure `httpStatus` and `error`), a `proxmox task failed` line with the UPID and
|
||||
`exitstatus`, and the no-op lines of Delete and ListByTag (foreign VM
|
||||
left alone, unreadable candidate skipped).
|
||||
`exitstatus`, and the no-op lines of Delete and ListByTag (VM already
|
||||
gone, foreign or unmarked VM left alone, seed delete skipped on a node,
|
||||
unreadable candidate skipped).
|
||||
- V(2): request parameters (without `description`'s content at V(1) and
|
||||
never the upload body), config summaries, agent addresses, the resolved
|
||||
Create parameters with `cloudInitBytes`.
|
||||
|
||||
Reference in New Issue
Block a user