Files
herolib/lib/mycelium/grid3/deployer/vmachine.v
2025-12-01 20:53:20 +01:00

153 lines
3.8 KiB
V

module deployer
import incubaid.herolib.ui.console
import json
import os
import rand
@[params]
pub struct Mycelium {
hex_seed string = rand.hex(12)
}
// MachineNetworkReq struct to represent network access configuration
@[params]
pub struct VMRequirements {
pub mut:
name string
description string
cpu int // vcores
size u64
memory int // gbyte
public_ip4 bool
public_ip6 bool
planetary bool
mycelium ?Mycelium
flist string = 'https://hub.grid.tf/tf-official-vms/ubuntu-24.04-latest.flist'
entrypoint string = '/sbin/zinit init'
env map[string]string
// if set will chose a node from the list to deploy on
nodes []u32
// will deploy on one of hetzner nodes
use_hetzner_node bool
}
// MachineModel struct to represent a machine and its associat ed details
pub struct VMachine {
pub mut:
tfchain_id string
contract_id u64
requirements VMRequirements
node_id u32
planetary_ip string
mycelium_ip string
public_ip4 string
wireguard_ip string
public_ip6 string
}
// Helper function to encode a VMachine
fn (self VMachine) encode() ![]u8 {
return json.encode(self).bytes()
}
// Helper function to decode a VMachine
fn decode_vmachine(data []u8) !VMachine {
data_string := data.bytestr()
return json.decode(VMachine, data_string)
}
// Call zos to get the zos version running on the node
fn (self VMachine) check_node_up() !bool {
console.print_header('Pinging node: ${self.node_id}')
mut deployer := get_deployer()!
node_twin_id := deployer.client.get_node_twin(self.node_id) or {
return error('faild to get the node twin ID due to: ${err}')
}
deployer.client.get_zos_version(node_twin_id) or { return false }
console.print_header('Node ${self.node_id} is reachable.')
return true
}
fn ping(ip string) bool {
res := os.execute('ping -c 1 -W 2 ${ip}')
return res.exit_code == 0
}
// Ping the VM supported interfaces
fn (self VMachine) check_vm_up() bool {
if self.public_ip4 != '' {
console.print_header('Pinging public IPv4: ${self.public_ip4}')
pingable := ping(self.public_ip4)
if !pingable {
console.print_stderr("The public IPv4 isn't pingable.")
}
return pingable
}
if self.public_ip6 != '' {
console.print_header('Pinging public IPv6: ${self.public_ip6}')
pingable := ping(self.public_ip6)
if !pingable {
console.print_stderr("The public IPv6 isn't pingable.")
}
return pingable
}
if self.planetary_ip != '' {
console.print_header('Pinging planetary IP: ${self.planetary_ip}')
pingable := ping(self.planetary_ip)
if !pingable {
console.print_stderr("The planetary IP isn't pingable.")
}
return pingable
}
if self.mycelium_ip != '' {
console.print_header('Pinging mycelium IP: ${self.mycelium_ip}')
pingable := ping(self.mycelium_ip)
if !pingable {
console.print_stderr("The mycelium IP isn't pingable.")
}
return pingable
}
return false
}
pub fn (self VMachine) healthcheck() !bool {
console.print_header('Doing a healthcheck on machine ${self.requirements.name}')
is_vm_up := self.check_node_up()!
if !is_vm_up {
console.print_stderr("The VM isn't reachable, pinging node ${self.node_id}")
is_node_up := self.check_node_up()!
if !is_node_up {
console.print_stderr("The VM node isn't reachable.")
return false
}
return false
}
console.print_header('The VM is up and reachable.')
return true
}
// // NetworkInfo struct to represent network details
// pub struct RecoverArgs {
// pub mut:
// reinstall bool // reinstall if needed and run heroscript
// }
// fn (self VMachine) recover(args RecoverArgs) ! {
// }
// // NetworkInfo struct to represent network details
// pub struct DeployArgs {
// pub mut:
// reset bool // careful will delete existing machine if true
// }
// fn (self VMachine) deploy(args DeployArgs) ! {
// // check the machine is there, if yes and reset used then delete the machine before deploying a new one
// }