feat(nodes): add High Availability management UI
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 13s

Surface the existing HA backend endpoints (cluster HA status, add/remove
resource) in a new HAResources panel on the node detail page. Lists
HA-managed guests with state/group/restart limits, supports adding a guest
to HA (state, group, max_restart/relocate, comment) and removing it.
Shows a cluster-only notice on standalone nodes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-13 21:38:21 +05:00
parent 681aa2f303
commit 14aeba41d0
6 changed files with 359 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { apiClient } from '@/lib/api-client';
import type { HAStatus } from '@/types';
export const haKeys = {
status: (serverId: number) => ['ha-status', serverId] as const,
};
export interface AddToHAArgs {
vmType: 'vm' | 'ct';
vmid: number;
state: string;
group?: string;
max_restart: number;
max_relocate: number;
comment?: string;
}
export function useHAStatus(serverId: number) {
return useQuery({
queryKey: haKeys.status(serverId),
queryFn: () => apiClient.get<HAStatus>(`/proxmox/api/${serverId}/ha/status`),
enabled: serverId > 0,
});
}
export function useAddToHA(serverId: number) {
const qc = useQueryClient();
return useMutation({
// The backend expects these as query params, not a JSON body.
mutationFn: ({ vmType, vmid, state, group, max_restart, max_relocate, comment }: AddToHAArgs) => {
const qs = new URLSearchParams();
qs.set('state', state);
qs.set('max_restart', String(max_restart));
qs.set('max_relocate', String(max_relocate));
if (group) qs.set('group', group);
if (comment) qs.set('comment', comment);
return apiClient.post(`/proxmox/api/${serverId}/ha/${vmType}/${vmid}/add?${qs}`, {});
},
onSuccess: () => qc.invalidateQueries({ queryKey: haKeys.status(serverId) }),
});
}
export function useRemoveFromHA(serverId: number) {
const qc = useQueryClient();
return useMutation({
mutationFn: ({ vmType, vmid }: { vmType: 'vm' | 'ct'; vmid: number }) =>
apiClient.delete(`/proxmox/api/${serverId}/ha/${vmType}/${vmid}/remove`),
onSuccess: () => qc.invalidateQueries({ queryKey: haKeys.status(serverId) }),
});
}