mirror of
https://github.com/unraid/api.git
synced 2025-12-31 13:39:52 -06:00
feat: hypervisor async imports
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { ConnectListAllDomainsFlags } from '@vmngr/libvirt';
|
||||
import { getHypervisor } from '@app/core/utils/vms/get-hypervisor';
|
||||
import { VmState, type VmDomain } from '@app/graphql/generated/api/types';
|
||||
import { GraphQLError } from 'graphql';
|
||||
|
||||
import type { VmDomain } from '@app/graphql/generated/api/types';
|
||||
import { VmState } from '@app/graphql/generated/api/types';
|
||||
|
||||
const states = {
|
||||
0: 'NOSTATE',
|
||||
1: 'RUNNING',
|
||||
@@ -17,10 +17,11 @@ const states = {
|
||||
/**
|
||||
* Get vm domains.
|
||||
*/
|
||||
export const getDomains =async () => {
|
||||
|
||||
export const getDomains = async () => {
|
||||
const { ConnectListAllDomainsFlags } = await import('@vmngr/libvirt');
|
||||
const { UnraidHypervisor } = await import('@app/core/utils/vms/get-hypervisor');
|
||||
try {
|
||||
const hypervisor = await getHypervisor();
|
||||
const hypervisor = await UnraidHypervisor.getInstance().getHypervisor();
|
||||
if (!hypervisor) {
|
||||
throw new GraphQLError('VMs Disabled');
|
||||
}
|
||||
@@ -30,9 +31,7 @@ export const getDomains =async () => {
|
||||
);
|
||||
|
||||
const autoStartDomainNames = await Promise.all(
|
||||
autoStartDomains.map(async (domain) =>
|
||||
hypervisor.domainGetName(domain)
|
||||
)
|
||||
autoStartDomains.map(async (domain) => hypervisor.domainGetName(domain))
|
||||
);
|
||||
|
||||
// Get all domains
|
||||
@@ -53,9 +52,11 @@ export const getDomains =async () => {
|
||||
})
|
||||
);
|
||||
|
||||
return resolvedDomains;
|
||||
return resolvedDomains;
|
||||
} catch (error: unknown) {
|
||||
// If we hit an error expect libvirt to be offline
|
||||
throw new GraphQLError(`Failed to fetch domains with error: ${error instanceof Error ? error.message : 'Unknown Error'}`);
|
||||
throw new GraphQLError(
|
||||
`Failed to fetch domains with error: ${error instanceof Error ? error.message : 'Unknown Error'}`
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { access } from 'fs/promises';
|
||||
import { constants } from 'fs';
|
||||
import { access } from 'fs/promises';
|
||||
|
||||
import type { Hypervisor as HypervisorType } from '@vmngr/libvirt';
|
||||
|
||||
import { Hypervisor } from '@vmngr/libvirt';
|
||||
import { libvirtLogger } from '@app/core/log';
|
||||
|
||||
const uri = process.env.LIBVIRT_URI ?? 'qemu:///system';
|
||||
|
||||
let hypervisor: Hypervisor | null;
|
||||
|
||||
const libvirtPid = '/var/run/libvirt/libvirtd.pid';
|
||||
|
||||
const isLibvirtRunning = async (): Promise<boolean> => {
|
||||
@@ -19,29 +18,40 @@ const isLibvirtRunning = async (): Promise<boolean> => {
|
||||
}
|
||||
};
|
||||
|
||||
export const getHypervisor = async (): Promise<Hypervisor> => {
|
||||
// Return hypervisor if it's already connected
|
||||
const running = await isLibvirtRunning();
|
||||
export class UnraidHypervisor {
|
||||
private static instance: UnraidHypervisor | null = null;
|
||||
private hypervisor: HypervisorType | null = null;
|
||||
private constructor() {}
|
||||
|
||||
if (hypervisor && running) {
|
||||
return hypervisor;
|
||||
public static getInstance(): UnraidHypervisor {
|
||||
if (this.instance === null) {
|
||||
this.instance = new UnraidHypervisor();
|
||||
}
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
if (!running) {
|
||||
hypervisor = null;
|
||||
throw new Error('Libvirt is not running');
|
||||
}
|
||||
public async getHypervisor(): Promise<HypervisorType | null> {
|
||||
// Return hypervisor if it's already connected
|
||||
const running = await isLibvirtRunning();
|
||||
|
||||
hypervisor = new Hypervisor({ uri });
|
||||
await hypervisor.connectOpen().catch((error: unknown) => {
|
||||
libvirtLogger.error(
|
||||
`Failed starting VM hypervisor connection with "${
|
||||
(error as Error).message
|
||||
}"`
|
||||
);
|
||||
if (this.hypervisor && running) {
|
||||
return this.hypervisor;
|
||||
}
|
||||
|
||||
throw error;
|
||||
});
|
||||
if (!running) {
|
||||
this.hypervisor = null;
|
||||
throw new Error('Libvirt is not running');
|
||||
}
|
||||
const { Hypervisor } = await import('@vmngr/libvirt');
|
||||
this.hypervisor = new Hypervisor({ uri });
|
||||
await this.hypervisor.connectOpen().catch((error: unknown) => {
|
||||
libvirtLogger.error(
|
||||
`Failed starting VM hypervisor connection with "${(error as Error).message}"`
|
||||
);
|
||||
|
||||
return hypervisor;
|
||||
};
|
||||
throw error;
|
||||
});
|
||||
|
||||
return this.hypervisor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { type Domain } from '@app/core/types';
|
||||
import { getHypervisor } from '@app/core/utils/vms/get-hypervisor';
|
||||
|
||||
export type DomainLookupType = 'id' | 'uuid' | 'name';
|
||||
|
||||
@@ -21,7 +20,8 @@ export const parseDomain = async (type: DomainLookupType, id: string): Promise<D
|
||||
throw new Error(`Type must be one of [${Object.keys(types).join(', ')}], ${type} given.`);
|
||||
}
|
||||
|
||||
const client = await getHypervisor();
|
||||
const { UnraidHypervisor } = await import('@app/core/utils/vms/get-hypervisor');
|
||||
const client = await UnraidHypervisor.getInstance().getHypervisor();
|
||||
const method = types[type];
|
||||
const domain = await client[method](id);
|
||||
const info = await domain.getInfoAsync();
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Command, CommandRunner, Option } from 'nest-commander';
|
||||
|
||||
import { ECOSYSTEM_PATH, PM2_PATH } from '@app/consts';
|
||||
import { levels, type LogLevel } from '@app/core/log';
|
||||
import { LogService } from '@app/unraid-api/cli/log.service';
|
||||
import type { LogService } from '@app/unraid-api/cli/log.service';
|
||||
|
||||
interface StartCommandOptions {
|
||||
'log-level'?: string;
|
||||
|
||||
Reference in New Issue
Block a user