Files
proxui/migrations/0006_vmid_allocator.up.sql
T

72 lines
2.0 KiB
PL/PgSQL

CREATE TYPE public.vmid_reservation_status AS ENUM ('reserved', 'released');
CREATE TABLE public.cluster_vmid_allocators (
cluster_id uuid PRIMARY KEY REFERENCES public.clusters(id) ON DELETE CASCADE,
next_vmid integer NOT NULL DEFAULT 100,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
CONSTRAINT cluster_vmid_allocators_next_vmid_check CHECK (next_vmid > 0)
);
CREATE TABLE public.vmid_reservations (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
cluster_id uuid NOT NULL REFERENCES public.clusters(id) ON DELETE CASCADE,
proxmox_vmid integer NOT NULL,
status public.vmid_reservation_status NOT NULL DEFAULT 'reserved',
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
CONSTRAINT vmid_reservations_proxmox_vmid_check CHECK (proxmox_vmid > 0)
);
CREATE UNIQUE INDEX vmid_reservations_reserved_key
ON public.vmid_reservations (cluster_id, proxmox_vmid)
WHERE status = 'reserved';
CREATE INDEX vmid_reservations_cluster_id_idx ON public.vmid_reservations (cluster_id);
CREATE OR REPLACE FUNCTION public.reserve_next_vmid(p_cluster_id uuid)
RETURNS integer
LANGUAGE plpgsql
AS $$
DECLARE
candidate integer;
BEGIN
INSERT INTO public.cluster_vmid_allocators (cluster_id)
VALUES (p_cluster_id)
ON CONFLICT (cluster_id) DO NOTHING;
SELECT next_vmid
INTO candidate
FROM public.cluster_vmid_allocators
WHERE cluster_id = p_cluster_id
FOR UPDATE;
LOOP
EXIT WHEN NOT EXISTS (
SELECT 1
FROM public.vms
WHERE cluster_id = p_cluster_id
AND proxmox_vmid = candidate
) AND NOT EXISTS (
SELECT 1
FROM public.vmid_reservations
WHERE cluster_id = p_cluster_id
AND proxmox_vmid = candidate
AND status = 'reserved'
);
candidate := candidate + 1;
END LOOP;
INSERT INTO public.vmid_reservations (cluster_id, proxmox_vmid)
VALUES (p_cluster_id, candidate);
UPDATE public.cluster_vmid_allocators
SET next_vmid = candidate + 1,
updated_at = now()
WHERE cluster_id = p_cluster_id;
RETURN candidate;
END;
$$;