import { useQuery, useMutation, useQueryClient } from '@tanstack/vue-query'; import { computed } from 'vue'; import type { ComputedRef } from 'vue'; import api from '@/store/api'; import { useRedfishRoot } from '@/api/composables/useRedfishRoot'; import { shouldRetry } from '@/api/composables/useAllSubResources'; import type { Manager } from '@/api/types/redfish'; export const rebootBmcQueryKey = ['redfish', 'bmcManager'] as const; export interface UseRebootBmcReturn { lastBmcRebootTime: ComputedRef; rebootBmc: () => Promise; isBusy: ComputedRef; isError: ComputedRef; isLoading: ComputedRef; isRebootEnabled: ComputedRef; } export function useRebootBmc(): UseRebootBmcReturn { const queryClient = useQueryClient(); const { data: serviceRoot, isLoading: rootLoading } = useRedfishRoot(); const managerProvidingServiceUri = computed( () => serviceRoot.value?.ManagerProvidingService?.['@odata.id'] ?? null, ); const managersCollectionUri = computed( () => serviceRoot.value?.Managers?.['@odata.id'] ?? null, ); const bmcQuery = useQuery({ queryKey: computed(() => [ ...rebootBmcQueryKey, managerProvidingServiceUri.value ?? managersCollectionUri.value, ]), queryFn: async ({ signal }) => { let managerUri = managerProvidingServiceUri.value; if (!managerUri) { const collectionUri = managersCollectionUri.value; if (!collectionUri) return null; const { data: collection } = await api.get<{ Members?: { '@odata.id': string }[]; }>(collectionUri, { signal }); managerUri = collection.Members?.[0]?.['@odata.id'] ?? null; } if (!managerUri) return null; const { data } = await api.get(managerUri, { signal }); return data; }, enabled: computed( () => !!managerProvidingServiceUri.value || !!managersCollectionUri.value, ), staleTime: Infinity, gcTime: Infinity, refetchOnMount: true, refetchOnWindowFocus: false, refetchOnReconnect: true, retry: shouldRetry, retryDelay: (attemptIndex: number) => Math.min(1000 * 2 ** attemptIndex, 30000), }); const mutation = useMutation({ mutationFn: async () => { const manager = bmcQuery.data.value; if (!manager) throw new Error('Manager resource not available'); const resetTarget = manager.Actions?.['#Manager.Reset']?.target ?? `${manager['@odata.id']}/Actions/Manager.Reset`; await api.post(resetTarget, { ResetType: 'GracefulRestart' }); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: rebootBmcQueryKey }); }, }); const lastBmcRebootTime = computed(() => { const lastReset = bmcQuery.data.value?.LastResetTime; return lastReset ? new Date(lastReset) : null; }); const isBusy = computed(() => mutation.isPending.value); const isError = computed(() => bmcQuery.isError.value); const isLoading = computed( () => rootLoading.value || bmcQuery.isLoading.value, ); const isRebootEnabled = computed( () => !isBusy.value && !isError.value && !!bmcQuery.data.value, ); async function rebootBmc(): Promise { await mutation.mutateAsync(); } return { lastBmcRebootTime, rebootBmc, isBusy, isError, isLoading, isRebootEnabled, }; }