Files
herolib/lib/threefold/models_tfgrid/node.v
2025-10-12 12:30:19 +03:00

446 lines
13 KiB
V

module models_tfgrid
import incubaid.herolib.data.encoder
import incubaid.herolib.data.ourtime
import incubaid.herolib.hero.db
// Storage device information
pub struct StorageDevice {
pub mut:
id string // can be used in node
size_gb f64 // Size of the storage device in gigabytes
description string // Description of the storage device
}
// Memory device information
pub struct MemoryDevice {
pub mut:
id string // can be used in node
size_gb f64 // Size of the memory device in gigabytes
description string // Description of the memory device
}
// CPU device information
pub struct CPUDevice {
pub mut:
id string // can be used in node
cores int // Number of CPU cores
passmark int
description string // Description of the CPU
cpu_brand string // Brand of the CPU
cpu_version string // Version of the CPU
}
// GPU device information
pub struct GPUDevice {
pub mut:
id string // can be used in node
cores int // Number of GPU cores
memory_gb f64 // Size of the GPU memory in gigabytes
description string // Description of the GPU
gpu_brand string
gpu_version string
}
// Network device information
pub struct NetworkDevice {
pub mut:
id string // can be used in node
speed_mbps int // Network speed in Mbps
description string // Description of the network device
}
// Aggregated device info for a node
pub struct DeviceInfo {
pub mut:
vendor string
storage []StorageDevice
memory []MemoryDevice
cpu []CPUDevice
gpu []GPUDevice
network []NetworkDevice
}
// NodeCapacity represents the hardware capacity details of a node
pub struct NodeCapacity {
pub mut:
storage_gb f64 // Total storage in gigabytes
mem_gb f64 // Total memory in gigabytes
mem_gb_gpu f64 // Total GPU memory in gigabytes
passmark int // Passmark score for the node
vcores int // Total virtual cores
}
// Pricing policy for slices
pub struct PricingPolicy {
pub mut:
name string // Human friendly policy name (e.g. "fixed", "market")
details string // Optional free-form details as JSON-encoded string
marketplace_year_discounts []int // e.g. [30, 40, 50] means if user has more CC than 1Y utilization, 30% discount, etc.
}
// SLA policy for slices
pub struct SLAPolicy {
pub mut:
uptime f32 // Uptime in percentage (0..100)
max_response_time_ms u32 // Max response time in ms
sla_bandwidth_mbit int // minimal mbits we can expect avg over 1h per node, 0 means we don't guarantee
sla_penalty int // 0-100, percent of money given back in relation to month if sla breached
}
// Compute slice (typically represents a base unit of compute)
pub struct ComputeSlice {
pub mut:
id int // the id of the slice in the node
mem_gb f64
storage_gb f64
passmark int
vcores int
cpu_oversubscription int
storage_oversubscription int
price_range []f64 // Min/max allowed price range for validation
gpus u8 // nr of GPU's see node to know what GPU's are
price_cc f64 // price per slice in cloud credits
pricing_policy PricingPolicy
sla_policy SLAPolicy
}
// Storage slice (typically 1GB of storage)
pub struct StorageSlice {
pub mut:
id int // the id of the slice in the node
price_cc f64 // price per slice in cloud credits
pricing_policy PricingPolicy
sla_policy SLAPolicy
}
// Grid4 Node model - ROOT OBJECT
@[heap]
pub struct Node {
db.Base
pub mut:
nodegroupid int // Link to node group
uptime int // Uptime percentage 0..100
computeslices []ComputeSlice
storageslices []StorageSlice
devices DeviceInfo
country string // 2 letter code
capacity NodeCapacity // Hardware capacity details
birthtime u32 // first time node was active
pubkey string
signature_node string // signature done on node to validate pubkey with privkey
signature_farmer string // signature as done by farmers to validate their identity
}
pub struct DBNode {
pub mut:
db &db.DB @[skip; str: skip]
}
pub fn (self Node) type_name() string {
return 'node'
}
pub fn (self Node) description(methodname string) string {
match methodname {
'set' {
return 'Create or update a node. Returns the ID of the node.'
}
'get' {
return 'Retrieve a node by ID. Returns the node object.'
}
'delete' {
return 'Delete a node by ID. Returns true if successful.'
}
'exist' {
return 'Check if a node exists by ID. Returns true or false.'
}
'list' {
return 'List all nodes. Returns an array of node objects.'
}
else {
return 'Node management methods for Grid4 infrastructure.'
}
}
}
pub fn (self Node) example(methodname string) (string, string) {
match methodname {
'set' {
return '{"node": {"name": "node-001", "nodegroupid": 1, "uptime": 99, "country": "BE", "devices": {"vendor": "Dell"}, "capacity": {"storage_gb": 1000, "mem_gb": 64, "vcores": 16, "passmark": 15000}}}', '1'
}
'get' {
return '{"id": 1}', '{"name": "node-001", "nodegroupid": 1, "uptime": 99, "country": "BE"}'
}
'delete' {
return '{"id": 1}', 'true'
}
'exist' {
return '{"id": 1}', 'true'
}
'list' {
return '{}', '[{"name": "node-001", "nodegroupid": 1, "uptime": 99, "country": "BE"}]'
}
else {
return '{}', '{}'
}
}
}
pub fn (self Node) dump(mut e encoder.Encoder) ! {
e.add_int(self.nodegroupid)
e.add_int(self.uptime)
// Encode compute slices
e.add_int(self.computeslices.len)
for slice in self.computeslices {
e.add_int(slice.id)
e.add_f64(slice.mem_gb)
e.add_f64(slice.storage_gb)
e.add_int(slice.passmark)
e.add_int(slice.vcores)
e.add_int(slice.cpu_oversubscription)
e.add_int(slice.storage_oversubscription)
e.add_list_f64(slice.price_range)
e.add_u8(slice.gpus)
e.add_f64(slice.price_cc)
e.add_string(slice.pricing_policy.name)
e.add_string(slice.pricing_policy.details)
e.add_list_int(slice.pricing_policy.marketplace_year_discounts)
e.add_f32(slice.sla_policy.uptime)
e.add_u32(slice.sla_policy.max_response_time_ms)
e.add_int(slice.sla_policy.sla_bandwidth_mbit)
e.add_int(slice.sla_policy.sla_penalty)
}
// Encode storage slices
e.add_int(self.storageslices.len)
for slice in self.storageslices {
e.add_int(slice.id)
e.add_f64(slice.price_cc)
e.add_string(slice.pricing_policy.name)
e.add_string(slice.pricing_policy.details)
e.add_list_int(slice.pricing_policy.marketplace_year_discounts)
e.add_f32(slice.sla_policy.uptime)
e.add_u32(slice.sla_policy.max_response_time_ms)
e.add_int(slice.sla_policy.sla_bandwidth_mbit)
e.add_int(slice.sla_policy.sla_penalty)
}
// Encode devices
e.add_string(self.devices.vendor)
e.add_int(self.devices.storage.len)
for device in self.devices.storage {
e.add_string(device.id)
e.add_f64(device.size_gb)
e.add_string(device.description)
}
e.add_int(self.devices.memory.len)
for device in self.devices.memory {
e.add_string(device.id)
e.add_f64(device.size_gb)
e.add_string(device.description)
}
e.add_int(self.devices.cpu.len)
for device in self.devices.cpu {
e.add_string(device.id)
e.add_int(device.cores)
e.add_int(device.passmark)
e.add_string(device.description)
e.add_string(device.cpu_brand)
e.add_string(device.cpu_version)
}
e.add_int(self.devices.gpu.len)
for device in self.devices.gpu {
e.add_string(device.id)
e.add_int(device.cores)
e.add_f64(device.memory_gb)
e.add_string(device.description)
e.add_string(device.gpu_brand)
e.add_string(device.gpu_version)
}
e.add_int(self.devices.network.len)
for device in self.devices.network {
e.add_string(device.id)
e.add_int(device.speed_mbps)
e.add_string(device.description)
}
e.add_string(self.country)
e.add_f64(self.capacity.storage_gb)
e.add_f64(self.capacity.mem_gb)
e.add_f64(self.capacity.mem_gb_gpu)
e.add_int(self.capacity.passmark)
e.add_int(self.capacity.vcores)
e.add_u32(self.birthtime)
e.add_string(self.pubkey)
e.add_string(self.signature_node)
e.add_string(self.signature_farmer)
}
fn (mut self DBNode) load(mut o Node, mut e encoder.Decoder) ! {
o.nodegroupid = e.get_int()!
o.uptime = e.get_int()!
// Decode compute slices
compute_slices_len := e.get_int()!
o.computeslices = []ComputeSlice{len: compute_slices_len}
for i in 0 .. compute_slices_len {
o.computeslices[i].id = e.get_int()!
o.computeslices[i].mem_gb = e.get_f64()!
o.computeslices[i].storage_gb = e.get_f64()!
o.computeslices[i].passmark = e.get_int()!
o.computeslices[i].vcores = e.get_int()!
o.computeslices[i].cpu_oversubscription = e.get_int()!
o.computeslices[i].storage_oversubscription = e.get_int()!
o.computeslices[i].price_range = e.get_list_f64()!
o.computeslices[i].gpus = e.get_u8()!
o.computeslices[i].price_cc = e.get_f64()!
o.computeslices[i].pricing_policy.name = e.get_string()!
o.computeslices[i].pricing_policy.details = e.get_string()!
o.computeslices[i].pricing_policy.marketplace_year_discounts = e.get_list_int()!
o.computeslices[i].sla_policy.uptime = e.get_f32()!
o.computeslices[i].sla_policy.max_response_time_ms = e.get_u32()!
o.computeslices[i].sla_policy.sla_bandwidth_mbit = e.get_int()!
o.computeslices[i].sla_policy.sla_penalty = e.get_int()!
}
// Decode storage slices
storage_slices_len := e.get_int()!
o.storageslices = []StorageSlice{len: storage_slices_len}
for i in 0 .. storage_slices_len {
o.storageslices[i].id = e.get_int()!
o.storageslices[i].price_cc = e.get_f64()!
o.storageslices[i].pricing_policy.name = e.get_string()!
o.storageslices[i].pricing_policy.details = e.get_string()!
o.storageslices[i].pricing_policy.marketplace_year_discounts = e.get_list_int()!
o.storageslices[i].sla_policy.uptime = e.get_f32()!
o.storageslices[i].sla_policy.max_response_time_ms = e.get_u32()!
o.storageslices[i].sla_policy.sla_bandwidth_mbit = e.get_int()!
o.storageslices[i].sla_policy.sla_penalty = e.get_int()!
}
// Decode devices
o.devices.vendor = e.get_string()!
storage_devices_len := e.get_int()!
o.devices.storage = []StorageDevice{len: storage_devices_len}
for i in 0 .. storage_devices_len {
o.devices.storage[i].id = e.get_string()!
o.devices.storage[i].size_gb = e.get_f64()!
o.devices.storage[i].description = e.get_string()!
}
memory_devices_len := e.get_int()!
o.devices.memory = []MemoryDevice{len: memory_devices_len}
for i in 0 .. memory_devices_len {
o.devices.memory[i].id = e.get_string()!
o.devices.memory[i].size_gb = e.get_f64()!
o.devices.memory[i].description = e.get_string()!
}
cpu_devices_len := e.get_int()!
o.devices.cpu = []CPUDevice{len: cpu_devices_len}
for i in 0 .. cpu_devices_len {
o.devices.cpu[i].id = e.get_string()!
o.devices.cpu[i].cores = e.get_int()!
o.devices.cpu[i].passmark = e.get_int()!
o.devices.cpu[i].description = e.get_string()!
o.devices.cpu[i].cpu_brand = e.get_string()!
o.devices.cpu[i].cpu_version = e.get_string()!
}
gpu_devices_len := e.get_int()!
o.devices.gpu = []GPUDevice{len: gpu_devices_len}
for i in 0 .. gpu_devices_len {
o.devices.gpu[i].id = e.get_string()!
o.devices.gpu[i].cores = e.get_int()!
o.devices.gpu[i].memory_gb = e.get_f64()!
o.devices.gpu[i].description = e.get_string()!
o.devices.gpu[i].gpu_brand = e.get_string()!
o.devices.gpu[i].gpu_version = e.get_string()!
}
network_devices_len := e.get_int()!
o.devices.network = []NetworkDevice{len: network_devices_len}
for i in 0 .. network_devices_len {
o.devices.network[i].id = e.get_string()!
o.devices.network[i].speed_mbps = e.get_int()!
o.devices.network[i].description = e.get_string()!
}
o.country = e.get_string()!
o.capacity.storage_gb = e.get_f64()!
o.capacity.mem_gb = e.get_f64()!
o.capacity.mem_gb_gpu = e.get_f64()!
o.capacity.passmark = e.get_int()!
o.capacity.vcores = e.get_int()!
o.birthtime = e.get_u32()!
o.pubkey = e.get_string()!
o.signature_node = e.get_string()!
o.signature_farmer = e.get_string()!
}
@[params]
pub struct NodeArg {
pub mut:
name string
description string
nodegroupid int
uptime int
computeslices []ComputeSlice
storageslices []StorageSlice
devices DeviceInfo
country string
capacity NodeCapacity
birthtime u32
pubkey string
signature_node string
signature_farmer string
}
pub fn (mut self DBNode) new(args NodeArg) !Node {
mut o := Node{
nodegroupid: args.nodegroupid
uptime: args.uptime
computeslices: args.computeslices
storageslices: args.storageslices
devices: args.devices
country: args.country
capacity: args.capacity
birthtime: args.birthtime
pubkey: args.pubkey
signature_node: args.signature_node
signature_farmer: args.signature_farmer
}
o.name = args.name
o.description = args.description
o.updated_at = ourtime.now().unix()
return o
}
pub fn (mut self DBNode) set(o Node) !Node {
return self.db.set[Node](o)!
}
pub fn (mut self DBNode) delete(id u32) ! {
self.db.delete[Node](id)!
}
pub fn (mut self DBNode) exist(id u32) !bool {
return self.db.exists[Node](id)!
}
pub fn (mut self DBNode) get(id u32) !Node {
mut o, data := self.db.get_data[Node](id)!
mut e_decoder := encoder.decoder_new(data)
self.load(mut o, mut e_decoder)!
return o
}
pub fn (mut self DBNode) list() ![]Node {
return self.db.list[Node]()!.map(self.get(it)!)
}