1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct TenantConfig {
7 pub tenant_id: String,
8 pub quotas: TenantQuota,
9 pub net: TenantNet,
10 pub secrets_epoch: u64,
11 pub config_version: u64,
12 pub pinned: bool,
14 pub audit_retention_days: u32,
16 pub created_at: String,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct TenantQuota {
21 pub max_vcpus: u32,
22 pub max_mem_mib: u64,
23 pub max_running: u32,
24 pub max_warm: u32,
25 pub max_pools: u32,
26 pub max_instances_per_pool: u32,
27 pub max_disk_gib: u64,
28}
29
30impl Default for TenantQuota {
31 fn default() -> Self {
32 Self {
33 max_vcpus: 16,
34 max_mem_mib: 32768,
35 max_running: 8,
36 max_warm: 4,
37 max_pools: 4,
38 max_instances_per_pool: 16,
39 max_disk_gib: 100,
40 }
41 }
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
47pub struct TenantNet {
48 pub tenant_net_id: u16,
50 pub ipv4_subnet: String,
52 pub gateway_ip: String,
54 pub bridge_name: String,
56}
57
58impl TenantNet {
59 pub fn new(tenant_net_id: u16, ipv4_subnet: &str, gateway_ip: &str) -> Self {
61 Self {
62 tenant_net_id,
63 ipv4_subnet: ipv4_subnet.to_string(),
64 gateway_ip: gateway_ip.to_string(),
65 bridge_name: format!("br-tenant-{}", tenant_net_id),
66 }
67 }
68}
69
70pub const TENANT_BASE: &str = "/var/lib/mvm/tenants";
72
73pub fn tenant_dir(id: &str) -> String {
74 format!("{}/{}", TENANT_BASE, id)
75}
76
77pub fn tenant_config_path(id: &str) -> String {
78 format!("{}/tenant.json", tenant_dir(id))
79}
80
81pub fn tenant_secrets_path(id: &str) -> String {
82 format!("{}/secrets.json", tenant_dir(id))
83}
84
85pub fn tenant_audit_log_path(id: &str) -> String {
86 format!("{}/audit.log", tenant_dir(id))
87}
88
89pub fn tenant_ssh_key_path(id: &str) -> String {
90 format!("{}/ssh_key", tenant_dir(id))
91}
92
93pub fn tenant_pools_dir(id: &str) -> String {
94 format!("{}/pools", tenant_dir(id))
95}