372 lines
9.1 KiB
Text
372 lines
9.1 KiB
Text
# VM Lifecycle Commands (Phase 2)
|
|
#
|
|
# User-facing commands for permanent/temporary VM management with cleanup.
|
|
# Error handling: Result pattern (hybrid, no try-catch)
|
|
|
|
use primitives/result.nu *
|
|
use platform/vm/ {
|
|
"register-permanent-vm"
|
|
"register-temporary-vm"
|
|
"list-permanent-vms"
|
|
"list-temporary-vms"
|
|
"find-expired-vms"
|
|
"cleanup-expired-vms"
|
|
"get-vm-uptime"
|
|
"get-vm-time-to-cleanup"
|
|
"extend-vm-ttl"
|
|
"recover-vms-on-boot"
|
|
"start-cleanup-scheduler"
|
|
"stop-cleanup-scheduler"
|
|
"get-cleanup-scheduler-status"
|
|
"get-cleanup-queue"
|
|
"create-vm-recovery-script"
|
|
}
|
|
|
|
export def "vm list-permanent" []: table {
|
|
"""
|
|
List all permanent VMs.
|
|
|
|
Permanent VMs persist across reboots and host shutdowns.
|
|
|
|
Examples:
|
|
provisioning vm list-permanent
|
|
"""
|
|
|
|
let permanent = (list-permanent-vms)
|
|
|
|
if ($permanent | length) == 0 {
|
|
print "No permanent VMs registered"
|
|
return []
|
|
}
|
|
|
|
$permanent
|
|
| map {|vm|
|
|
{
|
|
name: $vm.vm_name
|
|
created: $vm.created_at
|
|
auto_start: ($vm.auto_start // false)
|
|
restart_policy: ($vm.restart_policy // "always")
|
|
}
|
|
}
|
|
}
|
|
|
|
export def "vm list-temporary" []: table {
|
|
"""
|
|
List all temporary VMs.
|
|
|
|
Temporary VMs are automatically cleaned up after TTL expires.
|
|
|
|
Examples:
|
|
provisioning vm list-temporary
|
|
"""
|
|
|
|
let temporary = (list-temporary-vms)
|
|
|
|
if ($temporary | length) == 0 {
|
|
print "No temporary VMs registered"
|
|
return []
|
|
}
|
|
|
|
$temporary
|
|
| map {|vm|
|
|
let time_info = (get-vm-time-to-cleanup $vm.vm_name)
|
|
|
|
{
|
|
name: $vm.vm_name
|
|
ttl_hours: $vm.ttl_hours
|
|
created: $vm.created_at
|
|
scheduled_cleanup: $vm.scheduled_cleanup_at
|
|
status: $vm.cleanup_status
|
|
time_remaining: ($time_info.time_remaining_formatted // "expired")
|
|
}
|
|
}
|
|
}
|
|
|
|
export def "vm make-permanent" [
|
|
name: string # VM name
|
|
--auto-start = true # Auto-start on boot
|
|
]: table {
|
|
"""
|
|
Convert temporary VM to permanent.
|
|
|
|
Cancels scheduled cleanup and registers for autostart.
|
|
|
|
Examples:
|
|
provisioning vm make-permanent test-vm
|
|
"""
|
|
|
|
let result = (register-permanent-vm {name: $name, permanent: true})
|
|
|
|
if $result.success {
|
|
print $"✓ VM '($name)' registered as permanent"
|
|
print $" Auto-start: ($auto_start)"
|
|
} else {
|
|
print $"✗ Failed: ($result.error)"
|
|
}
|
|
|
|
[$result]
|
|
}
|
|
|
|
export def "vm make-temporary" [
|
|
name: string # VM name
|
|
--ttl-hours: int = 24 # Time to live
|
|
]: table {
|
|
"""
|
|
Convert permanent VM to temporary.
|
|
|
|
Schedules automatic cleanup after TTL.
|
|
|
|
Examples:
|
|
provisioning vm make-temporary dev-vm --ttl-hours 48
|
|
"""
|
|
|
|
let result = (register-temporary-vm {name: $name, temporary: true} $ttl_hours)
|
|
|
|
if $result.success {
|
|
print $"✓ VM '($name)' registered as temporary"
|
|
print $" TTL: ($ttl_hours) hours"
|
|
print $" Cleanup scheduled at: ($result.cleanup_scheduled_at)"
|
|
} else {
|
|
print $"✗ Failed: ($result.error)"
|
|
}
|
|
|
|
[$result]
|
|
}
|
|
|
|
export def "vm info-lifecycle" [
|
|
name: string # VM name
|
|
]: record {
|
|
"""
|
|
Get lifecycle information for a VM.
|
|
|
|
Shows persistence mode, uptime, cleanup schedule, etc.
|
|
|
|
Examples:
|
|
provisioning vm info-lifecycle dev-rust
|
|
"""
|
|
|
|
# Guard: Input validation
|
|
if ($name | is-empty) {
|
|
print "Error: VM name is required"
|
|
return {}
|
|
}
|
|
|
|
let uptime = (get-vm-uptime $name)
|
|
|
|
# Guard: Optional cleanup info (may not exist for permanent VMs)
|
|
# Using optional operator instead of try-catch
|
|
let time_to_cleanup = (try-wrap {
|
|
get-vm-time-to-cleanup $name
|
|
} | unwrap-or {error: "Not a temporary VM"})
|
|
|
|
{
|
|
vm_name: $name
|
|
uptime: $uptime
|
|
cleanup_info: $time_to_cleanup
|
|
}
|
|
}
|
|
|
|
export def "vm cleanup-now" [
|
|
--dry-run = false # Simulate without deleting
|
|
--force = false # Force shutdown before cleanup
|
|
]: table {
|
|
"""
|
|
Cleanup expired temporary VMs now.
|
|
|
|
Immediately deletes VMs that have exceeded their TTL.
|
|
|
|
Examples:
|
|
# Dry-run (show what would be deleted)
|
|
provisioning vm cleanup-now --dry-run
|
|
|
|
# Force cleanup
|
|
provisioning vm cleanup-now --force
|
|
"""
|
|
|
|
let result = (cleanup-expired-vms --dry-run=$dry_run --force=$force)
|
|
|
|
if $result.cleaned_up > 0 {
|
|
print $"✓ Cleaned up ($result.cleaned_up) VMs"
|
|
} else if $dry_run {
|
|
print "No VMs pending cleanup"
|
|
}
|
|
|
|
print $"Total processed: ($result.total_expired)"
|
|
print $"Successful: ($result.cleaned_up)"
|
|
print $"Failed: ($result.failed)"
|
|
|
|
$result.details
|
|
}
|
|
|
|
export def "vm extend-ttl" [
|
|
name: string # VM name
|
|
hours: int # Hours to add
|
|
]: table {
|
|
"""
|
|
Extend TTL for a temporary VM.
|
|
|
|
Delays cleanup by adding more hours to the original TTL.
|
|
|
|
Examples:
|
|
provisioning vm extend-ttl test-vm 24 # Add 24 hours
|
|
provisioning vm extend-ttl test-vm 72 # Add 3 days
|
|
"""
|
|
|
|
# Guards: Input validation
|
|
if ($name | is-empty) {
|
|
print "Error: VM name is required"
|
|
return [{success: false, error: "VM name is required"}]
|
|
}
|
|
if $hours <= 0 {
|
|
print "Error: Hours must be positive"
|
|
return [{success: false, error: "Hours must be positive"}]
|
|
}
|
|
|
|
# Main operation: Use try-wrap to convert exceptions to Result
|
|
let result = (
|
|
use platform/vm/vm_persistence.nu extend-vm-ttl
|
|
try-wrap {
|
|
extend-vm-ttl $name $hours
|
|
}
|
|
)
|
|
|
|
# Handle result explicitly
|
|
if (is-ok $result) {
|
|
let extended = $result.ok
|
|
print $"✓ Extended TTL for '($name)' by ($hours) hours"
|
|
let new_cleanup = (try-wrap { get-vm-time-to-cleanup $name } | unwrap-or {time_remaining_formatted: "unknown"})
|
|
print $" New cleanup time: ($new_cleanup.time_remaining_formatted)"
|
|
[{success: true, error: null} | merge $extended]
|
|
} else {
|
|
print $"✗ Failed: ($result.err)"
|
|
[{success: false, error: $result.err}]
|
|
}
|
|
}
|
|
|
|
export def "vm scheduler start" [
|
|
--interval-minutes: int = 60 # Check interval
|
|
]: table {
|
|
"""
|
|
Start automatic cleanup scheduler.
|
|
|
|
Runs in background and periodically cleans up expired VMs.
|
|
|
|
Examples:
|
|
provisioning vm scheduler start
|
|
provisioning vm scheduler start --interval-minutes 30
|
|
"""
|
|
|
|
let result = (start-cleanup-scheduler --check-interval-minutes=$interval_minutes --background)
|
|
|
|
if $result.success {
|
|
print $"✓ Cleanup scheduler started (PID: ($result.pid))"
|
|
print $" Check interval: ($interval_minutes) minutes"
|
|
} else {
|
|
print $"✗ Failed: ($result.error)"
|
|
}
|
|
|
|
[$result]
|
|
}
|
|
|
|
export def "vm scheduler stop" []: table {
|
|
"""
|
|
Stop automatic cleanup scheduler.
|
|
|
|
Examples:
|
|
provisioning vm scheduler stop
|
|
"""
|
|
|
|
# Main operation: Use try-wrap to convert exceptions to Result
|
|
let result = (
|
|
use platform/vm/cleanup_scheduler.nu stop-cleanup-scheduler
|
|
try-wrap {
|
|
stop-cleanup-scheduler
|
|
}
|
|
)
|
|
|
|
# Handle result explicitly
|
|
if (is-ok $result) {
|
|
print $"✓ Cleanup scheduler stopped"
|
|
[{success: true, error: null}]
|
|
} else {
|
|
print $"✗ Failed: ($result.err)"
|
|
[{success: false, error: $result.err}]
|
|
}
|
|
|
|
[$result]
|
|
}
|
|
|
|
export def "vm scheduler status" []: record {
|
|
"""
|
|
Check cleanup scheduler status.
|
|
|
|
Examples:
|
|
provisioning vm scheduler status
|
|
"""
|
|
|
|
get-cleanup-scheduler-status
|
|
}
|
|
|
|
export def "vm cleanup-queue" []: table {
|
|
"""
|
|
Show VMs pending cleanup.
|
|
|
|
Examples:
|
|
provisioning vm cleanup-queue
|
|
"""
|
|
|
|
let queue = (get-cleanup-queue)
|
|
|
|
if ($queue | length) == 0 {
|
|
print "No VMs pending cleanup"
|
|
return []
|
|
}
|
|
|
|
print $"($queue | length) VMs pending cleanup:"
|
|
$queue
|
|
}
|
|
|
|
export def "vm recovery-enable" []: table {
|
|
"""
|
|
Enable VM recovery on system reboot.
|
|
|
|
Creates systemd service for automatic VM recovery.
|
|
|
|
Examples:
|
|
provisioning vm recovery-enable
|
|
"""
|
|
|
|
let result = (create-vm-recovery-script)
|
|
|
|
if $result.success {
|
|
print $"✓ VM recovery service created"
|
|
print $" Script: ($result.script_path)"
|
|
print $" Service: ($result.service_path)"
|
|
print " Run 'systemctl status vm-recovery' to check status"
|
|
} else {
|
|
print $"✗ Failed: ($result.error)"
|
|
}
|
|
|
|
[$result]
|
|
}
|
|
|
|
export def "vm lifecycle-stats" []: record {
|
|
"""
|
|
Show VM lifecycle statistics.
|
|
|
|
Examples:
|
|
provisioning vm lifecycle-stats
|
|
"""
|
|
|
|
use platform/vm/vm_persistence.nu get-vm-persistence-stats
|
|
|
|
let stats = (get-vm-persistence-stats)
|
|
|
|
print $"Total VMs: ($stats.total_vms)"
|
|
print $" Permanent: ($stats.permanent_vms)"
|
|
print $" Temporary: ($stats.temporary_vms)"
|
|
print $" Expired: ($stats.expired_vms)"
|
|
print $" Auto-cleanup enabled: ($stats.auto_cleanup_enabled)"
|
|
|
|
$stats
|
|
}
|