omni_orchestrator/worker_autoscaler/
vm.rs

1use std::collections::HashMap;
2use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
3use serde::{Serialize, Deserialize, Serializer, Deserializer};
4
5/// Represents a VM managed by the autoscaler
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct VM {
8    /// Unique identifier for the VM
9    pub id: String,
10    /// Human-readable name for the VM
11    pub name: String,
12    /// ID of the node hosting this VM
13    pub node_id: String,
14    /// CPU cores allocated to this VM
15    pub cpu: u32,
16    /// Memory in MB allocated to this VM
17    pub memory: u32,
18    /// Storage in GB allocated to this VM
19    pub storage: u32,
20    /// Current state of the VM
21    pub state: VMState,
22    /// When the VM was created (as milliseconds since UNIX epoch)
23    #[serde(with = "timestamp_serde")]
24    pub created_at: Instant,
25    /// Last time the VM state was updated (as milliseconds since UNIX epoch)
26    #[serde(with = "timestamp_serde")]
27    pub updated_at: Instant,
28    /// Additional properties specific to this VM
29    pub properties: HashMap<String, String>,
30}
31
32mod timestamp_serde {
33    use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
34    use serde::{Deserialize, Deserializer, Serializer};
35
36    pub fn serialize<S>(instant: &Instant, serializer: S) -> Result<S::Ok, S::Error>
37    where
38        S: Serializer,
39    {
40        let duration = instant.duration_since(Instant::now()) + SystemTime::now()
41            .duration_since(UNIX_EPOCH)
42            .unwrap_or(Duration::from_secs(0));
43        serializer.serialize_u64(duration.as_millis() as u64)
44    }
45
46    pub fn deserialize<'de, D>(deserializer: D) -> Result<Instant, D::Error>
47    where
48        D: Deserializer<'de>,
49    {
50        let millis = u64::deserialize(deserializer)?;
51        let duration = Duration::from_millis(millis);
52        let system_now = SystemTime::now()
53            .duration_since(UNIX_EPOCH)
54            .unwrap_or(Duration::from_secs(0));
55        Ok(Instant::now() - (system_now - duration))
56    }
57}
58
59impl VM {
60    /// Create a new VM
61    pub fn new(id: String, name: String, node_id: String, cpu: u32, memory: u32, storage: u32) -> Self {
62        let now = Instant::now();
63        Self {
64            id,
65            name,
66            node_id,
67            cpu,
68            memory,
69            storage,
70            state: VMState::Creating,
71            created_at: now,
72            updated_at: now,
73            properties: HashMap::new(),
74        }
75    }
76}
77
78/// Possible states for a VM
79#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
80pub enum VMState {
81    /// VM is being created
82    Creating,
83    /// VM is running
84    Running,
85    /// VM is stopped
86    Stopped,
87    /// VM is being terminated
88    Terminating,
89    /// VM has been terminated
90    Terminated,
91    /// VM is in error state
92    Error,
93}
94
95/// Configuration for VM creation
96#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct VMConfig {
98    /// CPU cores for each VM
99    pub cpu: u32,
100    /// Memory in MB for each VM
101    pub memory: u32,
102    /// Storage in GB for each VM
103    pub storage: u32,
104    /// Additional configuration options
105    pub options: HashMap<String, String>,
106}
107
108impl Default for VMConfig {
109    fn default() -> Self {
110        Self {
111            cpu: 2,
112            memory: 4096, // 4 GB
113            storage: 80,  // 80 GB
114            options: HashMap::new(),
115        }
116    }
117}
118
119/// Template for creating new VMs
120#[derive(Debug, Clone, Serialize, Deserialize)]
121pub struct VMTemplate {
122    /// Base name for VMs created from this template
123    pub base_name: String,
124    /// VM configuration
125    pub config: VMConfig,
126    /// Additional tags to apply to VMs
127    pub tags: HashMap<String, String>,
128}
129
130impl Default for VMTemplate {
131    fn default() -> Self {
132        Self {
133            base_name: "worker".to_string(),
134            config: VMConfig::default(),
135            tags: HashMap::new(),
136        }
137    }
138}