SystemFacts.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. namespace RackPeek.Domain.Discovery;
  2. /// <summary>
  3. /// The one place discovery turns bytes into the whole gigabytes RackPeek stores,
  4. /// so every collector reports the same size for the same hardware.
  5. /// </summary>
  6. public static class DiscoveryUnits {
  7. private const double _bytesPerGb = 1024d * 1024 * 1024;
  8. /// <summary>Rounded, floored at 1 — a real device is never zero gigabytes.</summary>
  9. public static double BytesToWholeGb(long bytes) => Math.Max(1, Math.Round(bytes / _bytesPerGb));
  10. }
  11. /// <summary>A physical or virtual disk as reported by the host.</summary>
  12. public sealed record BlockDeviceFact(string Name, long SizeBytes, bool Rotational);
  13. /// <summary>A network interface, reduced to the parts that pick a primary address.</summary>
  14. public sealed record NicFact(
  15. string Name,
  16. bool IsUp,
  17. bool IsLoopback,
  18. bool HasGateway,
  19. string? Ipv4,
  20. string? Mac = null);
  21. /// <summary>
  22. /// Everything a probe managed to read off the host, still in its raw form.
  23. /// Kept deliberately dumb: probes do IO and nothing else, so that every decision
  24. /// made about this data lives in <see cref="SystemFactsParser" /> and is testable
  25. /// on any platform from a captured fixture.
  26. /// </summary>
  27. public sealed record RawSystemSnapshot {
  28. public string Hostname { get; init; } = string.Empty;
  29. public int Cores { get; init; }
  30. public IReadOnlyList<NicFact> Nics { get; init; } = [];
  31. public IReadOnlyList<BlockDeviceFact> BlockDevices { get; init; } = [];
  32. /// <summary>Fallback when the platform-specific read fails; always populated.</summary>
  33. public long FallbackMemoryBytes { get; init; }
  34. // Linux
  35. public string? OsReleaseFile { get; init; }
  36. public string? MemInfoFile { get; init; }
  37. public string? MachineIdFile { get; init; }
  38. public string? CgroupFile { get; init; }
  39. public bool DockerEnvPresent { get; init; }
  40. public string? DmiVendor { get; init; }
  41. public string? DmiProduct { get; init; }
  42. // macOS
  43. public string? OsName { get; init; }
  44. public long? MemoryBytes { get; init; }
  45. public string? PlatformUuid { get; init; }
  46. public bool HypervisorPresent { get; init; }
  47. }
  48. /// <summary>The host, once the raw snapshot has been interpreted.</summary>
  49. public sealed record SystemFacts {
  50. public required string Hostname { get; init; }
  51. /// <summary>Seed for the discovery id. Null when the host offers nothing stable.</summary>
  52. public string? MachineId { get; init; }
  53. public required string Os { get; init; }
  54. public required int Cores { get; init; }
  55. public required double RamGb { get; init; }
  56. /// <summary>One of <see cref="Resources.SystemResources.SystemResource.ValidSystemTypes" />.</summary>
  57. public required string Type { get; init; }
  58. public string? Ip { get; init; }
  59. public IReadOnlyList<DriveFact> Drives { get; init; } = [];
  60. /// <summary>
  61. /// The machine's physical-NIC MACs, normalised. What lets an agent-discovered
  62. /// card and a network-scanned card of the same box find each other.
  63. /// </summary>
  64. public IReadOnlyList<string> Macs { get; init; } = [];
  65. }
  66. public sealed record DriveFact(string Type, int SizeGb);