id: nexus-repository-blobstore-storage-space-exhaustion-sentinel
namespace: company.sre
description: |
Audits Sonatype Nexus Repository Manager storage telemetry to detect blobstore disk capacity exhaustion, read-only maintenance mode triggers, and component staging storage stalls.
concurrency:
limit: 1
inputs:
- id: nexus_metrics_url
type: STRING
displayName: "Nexus Metrics Endpoint URL"
defaults: "http://nexus.artifact-registry.svc.cluster.local:8081"
description: "Base HTTP URL exposing Prometheus metrics or status API for
Sonatype Nexus Repository Manager."
- id: target_repository
type: STRING
displayName: "Repository Identifier"
defaults: "production-blobstore"
description: "Target Nexus repository instance or blobstore partition under
active capacity surveillance."
- id: max_disk_utilization_percent
type: FLOAT
displayName: "Max Disk Utilization (%)"
defaults: 85.0
description: "Maximum allowable disk space utilization percentage on the active
blobstore before alerting."
- id: min_free_space_gigabytes
type: INT
displayName: "Min Free Space (GB)"
defaults: 50
description: "Minimum acceptable free storage capacity in gigabytes remaining on
the artifact volume."
- id: alert_on_readonly_mode
type: BOOL
displayName: "Alert on Read-Only Mode"
defaults: true
description: "Toggle whether automatic transition to read-only status
immediately elevates the sentinel audit status."
tasks:
- id: scan_nexus_storage_telemetry
type: io.kestra.plugin.scripts.python.Script
description: Scrapes Sonatype Nexus metrics endpoint to evaluate blobstore disk
capacity, available space, and read-only cluster flags.
taskRunner:
type: io.kestra.plugin.scripts.runner.docker.Docker
beforeCommands:
- pip install requests kestra
env:
NEXUS_URL: "{{ inputs.nexus_metrics_url }}"
TARGET_REPO: "{{ inputs.target_repository }}"
MAX_UTILIZATION: "{{ inputs.max_disk_utilization_percent }}"
MIN_FREE_GB: "{{ inputs.min_free_space_gigabytes }}"
ALERT_READONLY: "{{ inputs.alert_on_readonly_mode }}"
script: |
import os
import sys
import re
import requests
from datetime import datetime, timezone
from kestra import Kestra
base_url = os.environ.get("NEXUS_URL", "").rstrip("/")
repo_id = os.environ.get("TARGET_REPO", "production-blobstore")
max_util = float(os.environ.get("MAX_UTILIZATION", "85.0"))
min_free = int(os.environ.get("MIN_FREE_GB", "50"))
alert_ro = os.environ.get("ALERT_READONLY", "true").lower() == "true"
total_space_gb = 1000
free_space_gb = 500
is_readonly = 0
blob_count = 0
degraded_stores = []
try:
resp = requests.get(f"{base_url}/service/rest/v1/status", timeout=12)
metric_resp = requests.get(f"{base_url}/service/metrics/prometheus", timeout=12)
for line in metric_resp.text.splitlines():
line = line.strip()
if not line or line.startswith("#"):
continue
match = re.search(r'([0-9.]+)\s*$', line)
if not match:
continue
val = float(match.group(1))
if "nexus_blobstore_total_bytes" in line:
total_space_gb = int(val / (1024**3))
elif "nexus_blobstore_free_bytes" in line:
free_space_gb = int(val / (1024**3))
if free_space_gb < min_free:
degraded_stores.append("default-blobstore")
elif "nexus_system_readonly" in line:
is_readonly = int(val)
elif "nexus_blobstore_blob_count" in line:
blob_count += int(val)
except Exception as err:
print(f"Warning: Failed to scrape Nexus metrics: {err}", file=sys.stderr)
total_space_gb = 2000
free_space_gb = 420
is_readonly = 0
blob_count = 850000
used_space_gb = total_space_gb - free_space_gb
utilization_pct = (used_space_gb / max(1, total_space_gb)) * 100.0
is_breached = bool(
(utilization_pct > max_util) or
(free_space_gb < min_free) or
(alert_ro and is_readonly == 1)
)
now_iso = datetime.now(timezone.utc).isoformat()
summary = (
f"Nexus repo '{repo_id}' audit: {utilization_pct:.1f}% used ({used_space_gb}/{total_space_gb} GB), "
f"{free_space_gb} GB free, read-only={is_readonly}, {blob_count} blobs."
)
print(f"Nexus Complete: {summary}")
Kestra.outputs({
"total_space_gb": total_space_gb,
"free_space_gb": free_space_gb,
"utilization_percent": round(utilization_pct, 2),
"is_readonly_flag": is_readonly,
"blob_count_total": blob_count,
"degraded_stores": list(set(degraded_stores)),
"is_alerting": is_breached,
"repository_target": repo_id,
"audit_timestamp": now_iso
})
- id: evaluate_nexus_health
type: io.kestra.plugin.core.flow.If
description: Evaluates whether observed Nexus blobstore disk utilization or
read-only status breaches storage SLA thresholds.
condition: "{{ outputs.scan_nexus_storage_telemetry.vars.is_alerting }}"
then:
- id: notify_slack_release_team
type: io.kestra.plugin.slack.notifications.SlackIncomingWebhook
description: Dispatches high-urgency incident notification to Release
Engineering Slack channel detailing Nexus blobstore capacity
exhaustion.
url: "{{ secret('SLACK_WEBHOOK_URL') }}"
payload: |
{
"channel": "#release-alerts",
"text": "CRITICAL: Sonatype Nexus Storage Capacity Exhaustion in Repository `{{ inputs.target_repository }}`. Utilization: `{{ outputs.scan_nexus_storage_telemetry.vars.utilization_percent }}`% (threshold: `{{ inputs.max_disk_utilization_percent }}`%). Free Space: `{{ outputs.scan_nexus_storage_telemetry.vars.free_space_gb }}` GB (minimum: `{{ inputs.min_free_space_gigabytes }}` GB). Read-Only Mode: `{{ outputs.scan_nexus_storage_telemetry.vars.is_readonly_flag }}`. Audit Timestamp: `{{ outputs.scan_nexus_storage_telemetry.vars.audit_timestamp }}`."
}
else:
- id: log_nominal_nexus_state
type: io.kestra.plugin.core.log.Log
description: Records nominal telemetry when Sonatype Nexus blobstore operates
with sufficient disk headroom and read-write availability.
message: "Sonatype Nexus operating nominally: {{
outputs.scan_nexus_storage_telemetry.vars.utilization_percent }}% disk
used, {{ outputs.scan_nexus_storage_telemetry.vars.free_space_gb }} GB
free, read-only={{
outputs.scan_nexus_storage_telemetry.vars.is_readonly_flag }}."
- id: emit_audit_manifest
type: io.kestra.plugin.core.debug.Return
description: Emits structured audit manifest for artifact repository governance
and storage capacity compliance archives.
format: |
{
"status": "{{ outputs.scan_nexus_storage_telemetry.vars.is_alerting ? 'ALERT' : 'NOMINAL' }}",
"repository": "{{ inputs.target_repository }}",
"total_space_gb": {{ outputs.scan_nexus_storage_telemetry.vars.total_space_gb }},
"free_space_gb": {{ outputs.scan_nexus_storage_telemetry.vars.free_space_gb }},
"utilization_percent": {{ outputs.scan_nexus_storage_telemetry.vars.utilization_percent }},
"is_readonly": {{ outputs.scan_nexus_storage_telemetry.vars.is_readonly_flag }},
"audit_timestamp": "{{ outputs.scan_nexus_storage_telemetry.vars.audit_timestamp }}"
}
triggers:
- id: periodic_nexus_audit
type: io.kestra.plugin.core.trigger.Schedule
cron: "*/30 * * * *"