Initial for Backup function

This commit is contained in:
Michel Roegl-Brunner
2025-11-14 08:44:33 +01:00
parent dab2da4b70
commit 4ea49be97d
10 changed files with 1224 additions and 39 deletions

View File

@@ -3,6 +3,8 @@ import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
import { getDatabase } from "~/server/database-prisma";
import { createHash } from "crypto";
import type { Server } from "~/types/server";
import { getStorageService } from "~/server/services/storageService";
import { SSHService } from "~/server/ssh-service";
// Helper function to parse raw LXC config into structured data
function parseRawConfig(rawConfig: string): any {
@@ -2038,5 +2040,113 @@ EOFCONFIG`;
.getLXCConfig({ scriptId: input.scriptId, forceSync: true });
return result;
}),
// Get backup-capable storages for a server
getBackupStorages: publicProcedure
.input(z.object({
serverId: z.number(),
forceRefresh: z.boolean().optional().default(false)
}))
.query(async ({ input }) => {
try {
const db = getDatabase();
const server = await db.getServerById(input.serverId);
if (!server) {
return {
success: false,
error: 'Server not found',
storages: [],
cached: false
};
}
const storageService = getStorageService();
const sshService = new SSHService();
// Test SSH connection first
const connectionTest = await sshService.testSSHConnection(server as Server);
if (!(connectionTest as any).success) {
return {
success: false,
error: `SSH connection failed: ${(connectionTest as any).error ?? 'Unknown error'}`,
storages: [],
cached: false
};
}
// Check if we have cached data
const wasCached = !input.forceRefresh;
// Fetch storages (will use cache if not forcing refresh)
const allStorages = await storageService.getStorages(server as Server, input.forceRefresh);
return {
success: true,
storages: allStorages,
cached: wasCached && allStorages.length > 0
};
} catch (error) {
console.error('Error in getBackupStorages:', error);
return {
success: false,
error: error instanceof Error ? error.message : 'Failed to fetch storages',
storages: [],
cached: false
};
}
}),
// Execute backup for a container
executeBackup: publicProcedure
.input(z.object({
containerId: z.string(),
storage: z.string(),
serverId: z.number()
}))
.mutation(async ({ input }) => {
try {
const db = getDatabase();
const server = await db.getServerById(input.serverId);
if (!server) {
return {
success: false,
error: 'Server not found',
executionId: null
};
}
const sshService = new SSHService();
// Test SSH connection first
const connectionTest = await sshService.testSSHConnection(server as Server);
if (!(connectionTest as any).success) {
return {
success: false,
error: `SSH connection failed: ${(connectionTest as any).error ?? 'Unknown error'}`,
executionId: null
};
}
// Generate execution ID for websocket tracking
const executionId = `backup_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
return {
success: true,
executionId,
containerId: input.containerId,
storage: input.storage,
server: server as Server
};
} catch (error) {
console.error('Error in executeBackup:', error);
return {
success: false,
error: error instanceof Error ? error.message : 'Failed to execute backup',
executionId: null
};
}
})
});