Skip to content

feat(orion): catalog VM images in RustFS/mono and pick by image_id - #2185

Merged
genedna merged 4 commits into
gitmono-dev:mainfrom
benjamin-747:main
Sep 10, 2026
Merged

genedna merged 4 commits into
gitmono-dev:mainfrom
benjamin-747:main

Conversation

@benjamin-747

Copy link
Copy Markdown
Member

No description provided.

Upload built qcow2 blobs to object storage, register metadata for list/delete,
resolve image_id to a signed URL on start-runner, and stop needrestart from
SIGTERM-killing overnight VMs.
Split catalog UI under Orion Client, add presigned PUT + register flow,
and set RustFS CORS for local moon origins.
Allow build-custom-image to upload/register across envs, avoid Start
Runner hangs behind the update lock, and sign Orion image URLs with an
optional public RustFS host so out-of-cluster schedulers can download.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0cd7182183

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +1581 to +1583
PUBLISH_SOURCE="$PUBLISHED_IMAGE"
if [ ! -f "$PUBLISH_SOURCE" ]; then
PUBLISH_SOURCE="$CUSTOM_IMAGE"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Upload the artifact whose digest was calculated

When an existing flat image is locked by a running VM, the publish block deliberately skips overwriting PUBLISHED_IMAGE, and NEW_DIGEST is subsequently computed from the newly built CUSTOM_IMAGE; this selection still chooses the existing old PUBLISHED_IMAGE merely because it exists. Stage 8 therefore uploads old bytes under the new image's digest and registers that mismatched digest, causing qlean's integrity verification to reject every runner start using the new catalog entry. Use CUSTOM_IMAGE after a skipped publish, or compute the digest from the selected upload source.

Useful? React with 👍 / 👎.

Comment on lines +355 to +356
if let Some(client) = state.orion_scheduler_client()
&& let Ok(list) = client.list_vms().await

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fail closed when the scheduler usage lookup fails

When the configured scheduler's /status request times out, returns an error, or produces invalid JSON, let Ok(list) silently skips the in-use check and proceeds to delete both storage objects and the catalog row. Thus a transient scheduler outage turns an operation documented to return 409 for referenced images into a destructive success; propagate the lookup failure instead of treating it as an empty VM list.

Useful? React with 👍 / 👎.

Comment on lines +203 to +209
let image_name = req
.image_name
.as_deref()
.map(str::trim)
.filter(|s| !s.is_empty())
.unwrap_or("debian-13-buck2");
let (object_key, info_object_key) = OrionVmImageService::object_keys(&digest, image_name);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Encode or reject reserved characters in upload URLs

When an admin selects a qcow2 whose derived image name contains # or ?, the unvalidated name is interpolated directly into this URL. XMLHttpRequest treats those characters as a fragment or query delimiter, so mono stores the upload under a truncated key while registration retains the full returned object_key; subsequent signed GETs target an object that does not exist. Percent-encode path segments or restrict image names to a safe character set before constructing both keys and URLs.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ae8f131a1f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".


for f in "$SCRIPT_DIR/bin/orion-scheduler" \
"$SCRIPT_DIR/etc/target_config.json.template" \
"$SCRIPT_DIR/etc/needrestart-orion-scheduler.conf" \

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Include the needrestart config in release bundles

Every bundle produced by the Stage bundle section of .github/workflows/orion-scheduler-release.yml copies the binary, target config, systemd unit, and installer, but not etc/needrestart-orion-scheduler.conf. This newly required preflight entry therefore makes install.sh exit with “missing bundle file” for every published release; stage the new config in the bundle or make this optional.

Useful? React with 👍 / 👎.

Comment on lines +374 to +376
let deleted = svc
.delete(&id)
.await

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Serialize catalog deletion with runner startup

When an admin starts a runner and deletes its selected image concurrently, startup can resolve the catalog row and generate its signed URL before the scheduler has recorded the VM; deletion then observes no matching VM and removes the object here. The accepted runner subsequently fails when qlean opens the now-missing URL, despite the endpoint's advertised in-use protection. Mark or lock the catalog row before signing so deletion and startup cannot pass each other.

Useful? React with 👍 / 👎.

Comment on lines +69 to +71
let mut am = existing.into_active_model();
am.object_key = Set(input.object_key);
am.info_object_key = Set(input.info_object_key);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove the superseded object when changing an upserted key

If an admin uploads the same image bytes again under a different editable image name, the digest lookup finds the existing row and replaces object_key, but nothing deletes the prior multi-gigabyte qcow2. Later deletion only removes the new key, leaving the old object permanently orphaned in storage; preserve a canonical key or explicitly clean up the displaced key when it changes.

Useful? React with 👍 / 👎.

Comment on lines +450 to +452
NEW_DIGEST=$(shasum -a 256 "$PUBLISHED_IMAGE" 2>/dev/null | awk '{print $1}')
if [ -z "$NEW_DIGEST" ]; then
NEW_DIGEST=$(sha256sum "$PUBLISHED_IMAGE" | awk '{print $1}')

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Allow the mock hash fallback to run without shasum

On Linux hosts that provide sha256sum but not the optional shasum utility, this assignment fails and set -e -o pipefail terminates the script immediately, so the fallback on the next line is never reached. This breaks the advertised dependency-light MOCK_UPLOAD=1 path; test command availability first or place the shasum attempt in a conditional that is exempt from errexit.

Useful? React with 👍 / 👎.

@genedna
genedna added this pull request to the merge queue Sep 10, 2026
Merged via the queue into gitmono-dev:main with commit c26d409 Sep 10, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants