feat: import hosts/VMs/LXC from Proxmox VE with optional auto-sync
Add a Proxmox VE importer that reads the /api2/json REST API with a read-only
API token and drops hosts (proxmox), VMs (vm) and LXC containers (lxc) onto the
canvas as typed nodes with run state and hardware specs (vCPU/RAM/disk).
- Backend: proxmox_service (httpx) + proxmox routes (test-connection, import,
import-pending, config). Two-tier dedupe — merge onto an existing scanned node
by IP, else synthetic pve-{host}-{vmid} identity. Update-in-place, never
deletes. Host->guest rendered as a 'virtual' edge via the pending-link flow.
- Security: token is env-only (PROXMOX_TOKEN_*), never written to disk by the
app, never returned by any endpoint; errors are credential-sanitized.
- Auto-sync: optional scheduled re-import into pending (APScheduler job).
- PendingDevice.properties carries specs through approve (+ migration).
- Frontend: ProxmoxImportModal, sidebar entry, pending inventory source filter,
Settings auto-sync section, proxmoxApi client.
- Docs: docs/proxmox-import.md, README + FEATURES sections, .env.example keys.
- Tests: backend service/router/scheduler, frontend modal/client/pending.
ha-relevant: maybe
This commit is contained in:
@@ -120,6 +120,51 @@ export const settingsApi = {
|
||||
save: (data: AppSettings) => api.post<AppSettings>('/settings', data),
|
||||
}
|
||||
|
||||
export interface ProxmoxConnection {
|
||||
host: string
|
||||
port: number
|
||||
token_id?: string
|
||||
token_secret?: string
|
||||
verify_tls?: boolean
|
||||
}
|
||||
|
||||
export interface ProxmoxConfigData {
|
||||
host: string
|
||||
port: number
|
||||
verify_tls: boolean
|
||||
sync_enabled: boolean
|
||||
sync_interval: number
|
||||
token_configured: boolean
|
||||
}
|
||||
|
||||
export const proxmoxApi = {
|
||||
testConnection: (data: ProxmoxConnection) =>
|
||||
api.post<{ connected: boolean; message: string }>('/proxmox/test-connection', data),
|
||||
|
||||
importNetwork: (data: ProxmoxConnection) =>
|
||||
api.post<{
|
||||
nodes: import('@/components/proxmox/types').ProxmoxNode[]
|
||||
edges: import('@/components/proxmox/types').ProxmoxEdge[]
|
||||
device_count: number
|
||||
}>('/proxmox/import', data),
|
||||
|
||||
importToPending: (data: ProxmoxConnection) =>
|
||||
api.post<{
|
||||
id: string
|
||||
status: string
|
||||
kind: string
|
||||
ranges: string[]
|
||||
devices_found: number
|
||||
started_at: string
|
||||
finished_at: string | null
|
||||
error: string | null
|
||||
}>('/proxmox/import-pending', data),
|
||||
|
||||
getConfig: () => api.get<ProxmoxConfigData>('/proxmox/config'),
|
||||
saveConfig: (data: Omit<ProxmoxConfigData, 'token_configured'>) =>
|
||||
api.post<ProxmoxConfigData>('/proxmox/config', data),
|
||||
}
|
||||
|
||||
export const designsApi = {
|
||||
list: () => api.get<import('@/types').Design[]>('/designs'),
|
||||
create: (data: { name: string; icon?: string; design_type?: string }) =>
|
||||
|
||||
Reference in New Issue
Block a user