Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/cron/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ interface Env {

const METER_PATH = '/api/internal/billing/meter';
const IPAM_RECONCILE_PATH = '/api/internal/ipam/reconcile';
const IMAGES_RECONCILE_PATH = '/api/internal/images/reconcile';

async function runInternalCronRoute(env: Env, path: string, label: string): Promise<void> {
const response = await env.DASHBOARD.fetch(`https://dashboard.internal${path}`, {
Expand Down Expand Up @@ -37,6 +38,7 @@ export default {
ctx.waitUntil(runInternalCronRoute(env, METER_PATH, 'billing meter'));
}
ctx.waitUntil(runInternalCronRoute(env, IPAM_RECONCILE_PATH, 'ipam reconcile'));
ctx.waitUntil(runInternalCronRoute(env, IMAGES_RECONCILE_PATH, 'images reconcile'));
},
fetch(): Response {
return new Response('stack-dashboard-cron: billing meter worker', { status: 200 });
Expand Down
7 changes: 7 additions & 0 deletions apps/dashboard/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,10 @@ PROXMOX_SNIPPETS_ENDPOINT_USERNAME="dev"
PROXMOX_SNIPPETS_ENDPOINT_PASSWORD="dev"
PROXMOX_SNIPPETS_STORAGE="stack-volumes"
PROXMOX_SNIPPETS_ENDPOINT_VERIFY_SSL="false"

# Custom images (project imports from URL)
# Proxmox downloads user-supplied qcow2 URLs into this storage. It must be shared
# across nodes, have only the "import" content type, and hold nothing else.
# Put a filesystem quota on it (e.g. a CephFS directory quota): Proxmox has no
# download size limit, so the quota is what bounds a hostile URL.
PROXMOX_CUSTOM_IMAGE_STORAGE="stack-user-images"
19 changes: 19 additions & 0 deletions apps/dashboard/drizzle/0034_custom_images.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
CREATE TYPE "public"."image_status" AS ENUM('importing', 'ready', 'failed');--> statement-breakpoint
DROP VIEW "analytics"."base_images";--> statement-breakpoint
ALTER TABLE "base_images" ADD COLUMN "owner_project_id" text;--> statement-breakpoint
ALTER TABLE "base_images" ADD COLUMN "status" "image_status" DEFAULT 'ready' NOT NULL;--> statement-breakpoint
ALTER TABLE "base_images" ADD COLUMN "status_error" text;--> statement-breakpoint
ALTER TABLE "base_images" ADD COLUMN "size_bytes" bigint;--> statement-breakpoint
ALTER TABLE "base_images" ADD COLUMN "virtual_size_bytes" bigint;--> statement-breakpoint
ALTER TABLE "base_images" ADD COLUMN "source_url" text;--> statement-breakpoint
ALTER TABLE "base_images" ADD COLUMN "import_node" text;--> statement-breakpoint
ALTER TABLE "base_images" ADD COLUMN "import_upid" text;--> statement-breakpoint
ALTER TABLE "base_images" ADD COLUMN "created_by_user_id" text;--> statement-breakpoint
ALTER TABLE "base_images" ADD COLUMN "created_at" bigint DEFAULT (extract(epoch from now()) * 1000)::bigint NOT NULL;--> statement-breakpoint
ALTER TABLE "base_images" ADD COLUMN "updated_at" bigint DEFAULT (extract(epoch from now()) * 1000)::bigint NOT NULL;--> statement-breakpoint
ALTER TABLE "vms" ADD COLUMN "source_image_id" text;--> statement-breakpoint
ALTER TABLE "base_images" ADD CONSTRAINT "base_images_owner_project_id_organization_id_fk" FOREIGN KEY ("owner_project_id") REFERENCES "public"."organization"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "base_images_owner_project_id_index" ON "base_images" USING btree ("owner_project_id");--> statement-breakpoint
CREATE INDEX "base_images_status_updated_at_index" ON "base_images" USING btree ("status","updated_at");--> statement-breakpoint
CREATE INDEX "vms_source_image_status_index" ON "vms" USING btree ("source_image_id","status");--> statement-breakpoint
CREATE VIEW "analytics"."base_images" AS (select "id", "file_path", "name", "version", "description", "short_name", "icon", "color", "is_official", "logo_svg", "accent_color", "image_type", "secure_boot", "isa", "sort_order", "owner_project_id", "status", "size_bytes", "virtual_size_bytes", "created_at" from "base_images");
Loading
Loading