From 95be09d42b8380ca5870c034772eb2f619f0e35c Mon Sep 17 00:00:00 2001 From: Kevin Allioli Date: Thu, 23 Apr 2026 09:31:03 +0200 Subject: [PATCH] docs(adr): record server boot-mode policy (ADR-0009) Documents the non-obvious default shift introduced by PR #3 and PR #4: `orca server create` and `orca server clone` now boot from image on the compute's local disk by default, falling back to boot-from-volume only when the flavor has `disk == 0`. Records the alternatives considered (unconditional ephemeral, the `--ephemeral / --boot-from-volume` pairing that was tried first) so a future contributor reading the diff does not silently undo the choice. --- docs/adr/0009-server-boot-mode-policy.md | 97 ++++++++++++++++++++++++ docs/adr/README.md | 1 + 2 files changed, 98 insertions(+) create mode 100644 docs/adr/0009-server-boot-mode-policy.md diff --git a/docs/adr/0009-server-boot-mode-policy.md b/docs/adr/0009-server-boot-mode-policy.md new file mode 100644 index 0000000..9bc8b53 --- /dev/null +++ b/docs/adr/0009-server-boot-mode-policy.md @@ -0,0 +1,97 @@ +# ADR-0009: Server boot mode defaults to boot-from-image + +**Status**: Accepted +**Date**: 2026-04-23 + +## Context + +Until v2.0.1, `orca server create` and `orca server clone` built an +unconditional `block_device_mapping_v2` with +`source_type=image, destination_type=volume`, asking Nova to create a +Cinder volume from the image for every boot. The docstring even advertised +this as *"Create a new server (boot from volume)"*. + +Forcing boot-from-volume (BFV) uniformly has real costs on any cloud where +the flavor can carry a local root disk: + +- **Cinder quota is consumed per VM**, even for a 5-minute test instance. + A cleanup run on 2026-04-23 with 30 ephemeral test VMs left 30 boot + volumes attached; they cascaded as 404s during `project cleanup`. +- **Provisioning is slower**: Cinder must materialise the volume from the + image before Nova schedules the VM (3–10 s typical, more on a busy + backend). +- **The flavor's `disk` field becomes dead** — allocated but unused. +- **Horizon and the dashboard default** is boot-from-image with an + opt-in checkbox for boot-from-volume; an `openstack`-trained user + expects `orca server create --image X` to behave the same way. + +The one case where BFV is actually required is flavors declared with +`disk == 0`. Nova refuses to schedule an ephemeral boot on such a +flavor because there is no root-disk allocation; Cinder is the only +backing available. + +## Decision + +**`orca server create` and `orca server clone` boot from image by +default.** The Nova body uses `imageRef` and no +`block_device_mapping_v2`; Nova sizes the root disk from the flavor. + +The policy lives in a single helper `_resolve_boot_mode(client, +flavor_id, boot_from_image, boot_from_volume)` that both commands call. +Precedence: + +1. `--boot-from-volume` explicit → BFV, regardless of flavor. +2. `--boot-from-image` explicit → ephemeral; errors with a clear + message if `flavor.disk == 0`. +3. Neither flag → auto: ephemeral when `flavor.disk > 0`, BFV when + `flavor.disk == 0`. + +The two flags are mutually exclusive. When the flavor lookup itself +fails (transient Nova error, missing permissions), the explicit flag +is honoured; without one the helper falls back to BFV, which works on +every deployment. + +`--disk-size` keeps its meaning on the BFV path (boot volume size in +GB) and is ignored on the ephemeral path (Nova sizes the root disk +from the flavor — `--disk-size` there would silently have no effect, +not surface an error). + +## Consequences + +- **Positive**: default behaviour matches Horizon, `openstack server + create`, and user expectations. No silent Cinder quota drain per VM. +- **Positive**: faster server creation on flavors with `disk > 0`. +- **Positive**: `project cleanup` output shrinks — no more wave of + cascaded boot-volume 404s after deleting test fleets. +- **Negative / trade-off**: **backwards-incompatible** for pipelines + that relied on the root Cinder volume being auto-created. Migration + is a single flag (`--boot-from-volume`); documented in the PRs that + landed the change and in `--help` output. +- **Negative / trade-off**: the command now issues one extra `GET + /flavors/` on auto-detection. This is ~10 ms and cached by + Nova — acceptable. +- **Neutral**: the interactive wizard (`-i`) does not prompt for boot + mode; it follows the same auto-detection. A future change could + surface the choice if users request it, but keeping the wizard + mirror of the non-interactive defaults keeps the two paths aligned. + +## Alternatives considered + +1. **Keep BFV unconditional (status quo)**. Rejected: silently wastes + Cinder quota and provisioning time on the majority case. +2. **Flip to ephemeral unconditionally**. Rejected: breaks any flavor + with `disk=0` without recourse. Auto-detection is the minimum + required to stay operable on every cloud. +3. **Expose the flag as `--ephemeral / --boot-from-volume`**. + Rejected: mixes a storage-type term (`ephemeral`) with an action + term (`boot-from-volume`). The Horizon and docs vocabulary is + `boot from image` / `boot from volume`; the flag pair should + mirror that. + +## Implementation + +- `orca_cli/commands/server.py` — `_resolve_boot_mode` + two flags on + `server create` and `server clone`. +- `tests/test_server_create_boot_mode.py` — 8 tests. +- `tests/test_server_clone_boot_mode.py` — 6 tests. +- Initial landing: PR #3 (create), PR #4 (clone). diff --git a/docs/adr/README.md b/docs/adr/README.md index 95e3b76..37cdf2e 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -38,3 +38,4 @@ of the documentation. - [ADR-0006 — Idempotent-only HTTP retries](0006-idempotent-only-retries.md) - [ADR-0007 — Incremental services layer with typed models](0007-incremental-services-layer.md) - [ADR-0008 — Command naming follows openstackclient convention](0008-command-naming-convention.md) +- [ADR-0009 — Server boot mode defaults to boot-from-image](0009-server-boot-mode-policy.md)