183 lines
4.4 KiB
Plaintext
Raw Permalink Normal View History

# VM State Persistence
#
# File-based VM state tracking. Stores metadata in JSON files.
# Rule 1: Single purpose, Rule 4: Pure functions, Rule 10: Stream large data
export def "record-vm-creation" [
vm_config: record # VM configuration
]: record {
"""Record a new VM in state tracking"""
let state_dir = (get-vm-state-dir)
bash -c $"mkdir -p ($state_dir)"
let state_file = $"($state_dir)/($vm_config.name).json"
let state = {
name: $vm_config.name
state: "stopped"
permanent: ($vm_config.permanent // false)
temporary: ($vm_config.temporary // false)
auto_cleanup: ($vm_config.auto_cleanup // false)
auto_cleanup_hours: ($vm_config.auto_cleanup_hours // 24)
cpu: $vm_config.cpu
memory_mb: $vm_config.memory_mb
disk_gb: $vm_config.disk_gb
base_image: $vm_config.base_image
backend: ($vm_config.backend // "libvirt")
taskservs: ($vm_config.taskservs // [])
created_at: (date now | date to-record | debug)
ip_address: ""
mac_address: ""
}
try {
bash -c $"cat > ($state_file) << 'EOF'\n($state | to json)\nEOF"
{success: true}
} catch {|err|
{success: false, error: $err}
}
}
export def "get-vm-state" [
vm_name: string # VM name
]: record {
"""Get VM state from file"""
let state_dir = (get-vm-state-dir)
let state_file = $"($state_dir)/($vm_name).json"
try {
open $state_file | from json
} catch {
{}
}
}
export def "update-vm-state" [
vm_name: string # VM name
new_state: string # New state (running, stopped, etc.)
]: record {
"""Update VM state"""
let current = (get-vm-state $vm_name)
if ($current | is-empty) {
return {success: false, error: "VM not found"}
}
let updated = (
$current
| upsert state $new_state
| upsert last_action (date now | date to-record | debug)
)
let state_dir = (get-vm-state-dir)
let state_file = $"($state_dir)/($vm_name).json"
try {
bash -c $"cat > ($state_file) << 'EOF'\n($updated | to json)\nEOF"
{success: true}
} catch {|err|
{success: false, error: $err}
}
}
export def "remove-vm-state" [
vm_name: string # VM name
]: record {
"""Remove VM from state tracking"""
let state_dir = (get-vm-state-dir)
let state_file = $"($state_dir)/($vm_name).json"
try {
bash -c $"rm -f ($state_file)"
{success: true}
} catch {|err|
{success: false, error: $err}
}
}
export def "list-all-vms" []: table {
"""List all VMs from state tracking"""
let state_dir = (get-vm-state-dir)
if not ($state_dir | path exists) {
return []
}
try {
bash -c $"ls -1 ($state_dir)/*.json 2>/dev/null"
| lines
| where {|f| ($f | length) > 0}
| map {|f|
try {
open $f | from json
} catch {
{}
}
}
| where {|v| ($v | length) > 0}
} catch {
[]
}
}
def get-vm-state-dir []: string {
"""Get VM state directory"""
$"{{paths.workspace}}/vms/state"
}
export def "get-vm-stats" []: record {
"""Get VM statistics"""
let all_vms = (list-all-vms)
let permanent = ($all_vms | where permanent == true | length)
let temporary = ($all_vms | where temporary == true | length)
let total = ($all_vms | length)
{
total_vms: $total
permanent_vms: $permanent
temporary_vms: $temporary
running_vms: ($all_vms | where state == "running" | length)
stopped_vms: ($all_vms | where state == "stopped" | length)
}
}
export def "cleanup-temporary-vms" [
--older-than: int = 24 # Hours
]: record {
"""Cleanup temporary VMs older than specified hours"""
let all_vms = (list-all-vms)
let now = (date now | date to-record | debug)
let to_cleanup = (
$all_vms
| filter {|vm|
($vm.temporary // false) and \
($vm.auto_cleanup // false)
}
)
let results = (
$to_cleanup
| map {|vm|
{
name: $vm.name
result: "skipped" # Placeholder for Phase 2
}
}
)
{
total_checked: ($to_cleanup | length)
cleaned_up: 0
skipped: ($to_cleanup | length)
results: $results
}
}