Merge pull request 'fix: show LXC storage in --dry-run summary' (#25) from fix/dry-run-lxc-storage-summary into main
Lint / Python (flake8) (push) Successful in 36s
Security / Python Security (bandit) (push) Successful in 35s
Test / Python Tests (pytest) (push) Successful in 1m1s
Lint / Notify on failure (push) Has been skipped

Reviewed-on: #25
This commit was merged in pull request #25.
This commit is contained in:
2026-07-15 17:03:25 -04:00
2 changed files with 62 additions and 0 deletions
+29
View File
@@ -1038,6 +1038,10 @@ class SystemHealthMonitor:
if health_report['system_health']['issues']:
logger.info(f"\nSystem Issues: {len(health_report['system_health']['issues'])} found")
# LXC container storage (previously omitted from the dry-run summary; issue #23)
for line in self._format_lxc_dry_run(health_report.get('lxc_health', {})):
logger.info(line)
# PBS status
pbs = health_report.get('pbs_health', {})
if pbs.get('is_pbs_node'):
@@ -3998,6 +4002,31 @@ class SystemHealthMonitor:
logger.error(f"Failed to write Prometheus metrics: {e}")
return False
def _format_lxc_dry_run(self, lxc_health: Dict[str, Any]) -> List[str]:
"""Build the LXC-storage lines for the --dry-run summary.
The LXC storage check runs in every mode, but its results were previously
absent from the dry-run summary output, making it look like LXC storage was
not checked (issue #23). Returns a list of log lines (possibly empty).
"""
lines: List[str] = []
containers = lxc_health.get('containers', [])
if containers:
lines.append("\nLXC Storage:")
warn = self.CONFIG['THRESHOLDS']['LXC_WARNING']
for c in containers:
for fs in c.get('filesystems', []):
flag = "⚠️ " if fs.get('usage_percent', 0) >= warn else ""
lines.append(
f" {flag}CT{c['vmid']} {fs['mountpoint']}: "
f"{fs['usage_percent']:.1f}% used"
)
if lxc_health.get('issues'):
lines.append(f" Issues: {len(lxc_health['issues'])} found")
elif lxc_health.get('status') == 'ERROR':
lines.append(f"\nLXC Storage: check error ({len(lxc_health.get('issues', []))} issue(s))")
return lines
def _check_lxc_storage(self) -> Dict[str, Any]:
"""
Check storage utilization for all running LXC containers
+33
View File
@@ -503,3 +503,36 @@ class TestAttributeThresholds:
"""Age is still *tracked* (just not ticketed) — new-drive detection must work."""
assert monitor._is_new_drive(100) is True # ~4 days
assert monitor._is_new_drive(64860) is False # ~7.4 years
# ── _format_lxc_dry_run (LXC storage shown in --dry-run summary; issue #23) ────
class TestLxcDryRunSummary:
def test_includes_container_usage_and_flags_over_threshold(self, monitor):
"""Regression for issue #23: dry-run summary must surface LXC storage."""
lxc = {
'status': 'WARNING',
'issues': ['LXC 105 high storage usage: 84.0% on /'],
'containers': [
{'vmid': '105', 'filesystems': [{'mountpoint': '/', 'usage_percent': 84.0}]},
],
}
text = '\n'.join(monitor._format_lxc_dry_run(lxc))
assert 'LXC Storage:' in text
assert 'CT105 /' in text and '84.0% used' in text
assert '⚠️' in text # flagged: over the 80% warning threshold
assert 'Issues: 1 found' in text
def test_healthy_container_not_flagged(self, monitor):
lxc = {'status': 'OK', 'issues': [],
'containers': [{'vmid': '119', 'filesystems': [{'mountpoint': '/', 'usage_percent': 26.0}]}]}
text = '\n'.join(monitor._format_lxc_dry_run(lxc))
assert 'CT119 /' in text and '26.0% used' in text
assert '⚠️' not in text
def test_empty_when_no_containers(self, monitor):
assert monitor._format_lxc_dry_run({'status': 'OK', 'containers': [], 'issues': []}) == []
def test_error_status_is_reported(self, monitor):
lines = monitor._format_lxc_dry_run({'status': 'ERROR', 'containers': [], 'issues': ['boom']})
assert any('check error' in ln for ln in lines)