1use crate::Result;
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct VirtualizationInfo {
13 pub environment_type: VirtualizationType,
15 pub hypervisor: Option<String>,
17 pub container_runtime: Option<ContainerRuntime>,
19 pub resource_limits: ResourceLimits,
21 pub gpu_passthrough: GPUPassthroughInfo,
23 pub performance_impact: f64,
25 pub nested_virtualization: bool,
27 pub security_features: Vec<SecurityFeature>,
29 pub platform_specific: HashMap<String, String>,
31}
32
33#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
35pub enum VirtualizationType {
36 Native,
38 Docker,
40 Kubernetes,
42 LXC,
44 Podman,
46 VirtualMachine,
48 WSL,
50 WSL2,
52 Wine,
54 MacOSVirtualization,
56 Unknown,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct ContainerRuntime {
63 pub name: String,
65 pub version: Option<String>,
67 pub container_id: Option<String>,
69 pub image: Option<String>,
71 pub orchestrator: Option<String>,
73 pub security_context: SecurityContext,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
79pub struct SecurityContext {
80 pub privileged: bool,
82 pub user_namespace: bool,
84 pub security_profile: Option<String>,
86 pub capabilities: Vec<String>,
88 pub isolation_level: IsolationLevel,
90}
91
92#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
94pub enum IsolationLevel {
95 Full,
97 Partial,
99 Minimal,
101 None,
103}
104
105#[derive(Debug, Clone, Serialize, Deserialize)]
107pub struct ResourceLimits {
108 pub cpu_limits: CPULimits,
110 pub memory_limits: MemoryLimits,
112 pub io_limits: IOLimits,
114 pub network_limits: NetworkLimits,
116 pub gpu_limits: GPULimits,
118}
119
120#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct CPULimits {
123 pub max_cores: Option<u32>,
125 pub quota_percent: Option<f32>,
127 pub shares: Option<u32>,
129 pub affinity_mask: Option<String>,
131 pub disabled_features: Vec<String>,
133}
134
135#[derive(Debug, Clone, Serialize, Deserialize)]
137pub struct MemoryLimits {
138 pub max_memory_bytes: Option<u64>,
140 pub max_swap_bytes: Option<u64>,
142 pub reservation_bytes: Option<u64>,
144 pub oom_kill_disabled: bool,
146 pub numa_policy: Option<String>,
148}
149
150#[derive(Debug, Clone, Serialize, Deserialize)]
152pub struct IOLimits {
153 pub max_read_iops: Option<u64>,
155 pub max_write_iops: Option<u64>,
157 pub max_read_bps: Option<u64>,
159 pub max_write_bps: Option<u64>,
161 pub device_weights: HashMap<String, u32>,
163}
164
165#[derive(Debug, Clone, Serialize, Deserialize)]
167pub struct NetworkLimits {
168 pub max_bandwidth_bps: Option<u64>,
170 pub network_namespace: bool,
172 pub port_restrictions: Vec<PortRestriction>,
174 pub network_policies: Vec<String>,
176}
177
178#[derive(Debug, Clone, Serialize, Deserialize)]
180pub struct PortRestriction {
181 pub port: String,
183 pub protocol: String,
185 pub access: AccessType,
187}
188
189#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
191pub enum AccessType {
192 Allow,
193 Deny,
194}
195
196#[derive(Debug, Clone, Serialize, Deserialize)]
198pub struct GPULimits {
199 pub gpu_access: bool,
201 pub accessible_devices: Vec<String>,
203 pub memory_limits: HashMap<String, u64>,
205 pub capability_restrictions: Vec<String>,
207}
208
209#[derive(Debug, Clone, Serialize, Deserialize)]
211pub struct GPUPassthroughInfo {
212 pub available: bool,
214 pub passthrough_type: GPUPassthroughType,
216 pub devices: Vec<PassthroughDevice>,
218 pub performance_overhead: f64,
220}
221
222#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
224pub enum GPUPassthroughType {
225 Full,
227 SRIOV,
229 Shared,
231 Emulated,
233 None,
235}
236
237#[derive(Debug, Clone, Serialize, Deserialize)]
239pub struct PassthroughDevice {
240 pub device_id: String,
242 pub device_name: String,
244 pub pci_address: Option<String>,
246 pub driver: Option<String>,
248}
249
250#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
252pub enum SecurityFeature {
253 SecureBoot,
255 TrustedExecution,
257 IOMMU,
259 KGT,
261 CFI,
263 ASLR,
265 DEP,
267 HVCI,
269 MPK,
271 CET,
273}
274
275impl VirtualizationInfo {
276 pub fn detect() -> Result<Self> {
278 let environment_type = Self::detect_environment_type()?;
279 let hypervisor = Self::detect_hypervisor()?;
280 let container_runtime = Self::detect_container_runtime()?;
281 let resource_limits = Self::detect_resource_limits()?;
282 let gpu_passthrough = Self::detect_gpu_passthrough()?;
283 let performance_impact = Self::calculate_performance_impact(&environment_type);
284 let nested_virtualization = Self::detect_nested_virtualization()?;
285 let security_features = Self::detect_security_features()?;
286 let platform_specific = Self::gather_platform_specific_info()?;
287
288 Ok(Self {
289 environment_type,
290 hypervisor,
291 container_runtime,
292 resource_limits,
293 gpu_passthrough,
294 performance_impact,
295 nested_virtualization,
296 security_features,
297 platform_specific,
298 })
299 }
300
301 pub fn is_virtualized(&self) -> bool {
303 self.environment_type != VirtualizationType::Native
304 }
305
306 pub fn is_containerized(&self) -> bool {
308 matches!(
309 self.environment_type,
310 VirtualizationType::Docker
311 | VirtualizationType::Kubernetes
312 | VirtualizationType::LXC
313 | VirtualizationType::Podman
314 )
315 }
316
317 pub fn is_virtual_machine(&self) -> bool {
319 matches!(
320 self.environment_type,
321 VirtualizationType::VirtualMachine | VirtualizationType::WSL | VirtualizationType::WSL2
322 )
323 }
324
325 pub fn get_performance_factor(&self) -> f64 {
327 self.performance_impact
328 }
329
330 pub fn has_gpu_access(&self) -> bool {
332 self.gpu_passthrough.available || self.resource_limits.gpu_limits.gpu_access
333 }
334
335 pub fn get_security_recommendations(&self) -> Vec<String> {
337 let mut recommendations = Vec::new();
338
339 if self.is_containerized() {
340 if let Some(runtime) = &self.container_runtime {
341 if runtime.security_context.privileged {
342 recommendations.push(
343 "Consider running container in non-privileged mode for better security"
344 .to_string(),
345 );
346 }
347
348 if !runtime.security_context.user_namespace {
349 recommendations.push(
350 "Enable user namespace mapping for better isolation".to_string(),
351 );
352 }
353
354 if runtime.security_context.security_profile.is_none() {
355 recommendations.push(
356 "Apply AppArmor/SELinux security profile".to_string(),
357 );
358 }
359 }
360 }
361
362 if self.is_virtual_machine() && !self.security_features.contains(&SecurityFeature::SecureBoot) {
363 recommendations.push("Enable Secure Boot for enhanced security".to_string());
364 }
365
366 if self.gpu_passthrough.available
367 && matches!(
368 self.gpu_passthrough.passthrough_type,
369 GPUPassthroughType::Full
370 )
371 {
372 recommendations.push(
373 "GPU passthrough detected - ensure IOMMU isolation is properly configured"
374 .to_string(),
375 );
376 }
377
378 recommendations
379 }
380
381 fn detect_environment_type() -> Result<VirtualizationType> {
382 if Self::check_docker_container()? {
387 return Ok(VirtualizationType::Docker);
388 }
389
390 if Self::check_kubernetes_pod()? {
391 return Ok(VirtualizationType::Kubernetes);
392 }
393
394 if Self::check_wsl()? {
395 return Ok(VirtualizationType::WSL);
396 }
397
398 if Self::check_virtual_machine()? {
400 return Ok(VirtualizationType::VirtualMachine);
401 }
402
403 Ok(VirtualizationType::Native)
404 }
405
406 fn check_docker_container() -> Result<bool> {
407 Ok(std::path::Path::new("/.dockerenv").exists())
409 }
410
411 fn check_kubernetes_pod() -> Result<bool> {
412 Ok(std::env::var("KUBERNETES_SERVICE_HOST").is_ok())
414 }
415
416 fn check_wsl() -> Result<bool> {
417 #[cfg(target_os = "linux")]
419 {
420 if let Ok(version) = std::fs::read_to_string("/proc/version") {
421 return Ok(version.to_lowercase().contains("microsoft"));
422 }
423 }
424 Ok(false)
425 }
426
427 fn check_virtual_machine() -> Result<bool> {
428 Ok(false)
430 }
431
432 fn detect_hypervisor() -> Result<Option<String>> {
433 Ok(None)
435 }
436
437 fn detect_container_runtime() -> Result<Option<ContainerRuntime>> {
438 Ok(None)
440 }
441
442 fn detect_resource_limits() -> Result<ResourceLimits> {
443 Ok(ResourceLimits {
445 cpu_limits: CPULimits {
446 max_cores: None,
447 quota_percent: None,
448 shares: None,
449 affinity_mask: None,
450 disabled_features: Vec::new(),
451 },
452 memory_limits: MemoryLimits {
453 max_memory_bytes: None,
454 max_swap_bytes: None,
455 reservation_bytes: None,
456 oom_kill_disabled: false,
457 numa_policy: None,
458 },
459 io_limits: IOLimits {
460 max_read_iops: None,
461 max_write_iops: None,
462 max_read_bps: None,
463 max_write_bps: None,
464 device_weights: HashMap::new(),
465 },
466 network_limits: NetworkLimits {
467 max_bandwidth_bps: None,
468 network_namespace: false,
469 port_restrictions: Vec::new(),
470 network_policies: Vec::new(),
471 },
472 gpu_limits: GPULimits {
473 gpu_access: true,
474 accessible_devices: Vec::new(),
475 memory_limits: HashMap::new(),
476 capability_restrictions: Vec::new(),
477 },
478 })
479 }
480
481 fn detect_gpu_passthrough() -> Result<GPUPassthroughInfo> {
482 Ok(GPUPassthroughInfo {
484 available: false,
485 passthrough_type: GPUPassthroughType::None,
486 devices: Vec::new(),
487 performance_overhead: 0.0,
488 })
489 }
490
491 fn calculate_performance_impact(env_type: &VirtualizationType) -> f64 {
492 match env_type {
493 VirtualizationType::Native => 1.0,
494 VirtualizationType::Docker | VirtualizationType::LXC | VirtualizationType::Podman => 0.95,
495 VirtualizationType::Kubernetes => 0.92,
496 VirtualizationType::WSL2 => 0.90,
497 VirtualizationType::VirtualMachine => 0.85,
498 VirtualizationType::WSL => 0.80,
499 VirtualizationType::Wine => 0.75,
500 _ => 0.70,
501 }
502 }
503
504 fn detect_nested_virtualization() -> Result<bool> {
505 Ok(false)
507 }
508
509 fn detect_security_features() -> Result<Vec<SecurityFeature>> {
510 Ok(Vec::new())
512 }
513
514 fn gather_platform_specific_info() -> Result<HashMap<String, String>> {
515 Ok(HashMap::new())
517 }
518}
519
520impl std::fmt::Display for VirtualizationType {
521 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
522 match self {
523 VirtualizationType::Native => write!(f, "Native"),
524 VirtualizationType::Docker => write!(f, "Docker"),
525 VirtualizationType::Kubernetes => write!(f, "Kubernetes"),
526 VirtualizationType::LXC => write!(f, "LXC"),
527 VirtualizationType::Podman => write!(f, "Podman"),
528 VirtualizationType::VirtualMachine => write!(f, "Virtual Machine"),
529 VirtualizationType::WSL => write!(f, "WSL"),
530 VirtualizationType::WSL2 => write!(f, "WSL2"),
531 VirtualizationType::Wine => write!(f, "Wine"),
532 VirtualizationType::MacOSVirtualization => write!(f, "macOS Virtualization"),
533 VirtualizationType::Unknown => write!(f, "Unknown"),
534 }
535 }
536}