108 lines
3.4 KiB
Python
Executable File
108 lines
3.4 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
# Required Raycast metadata parameters:
|
|
# @raycast.schemaVersion 1
|
|
# @raycast.title Home Lab Status
|
|
# @raycast.mode fullOutput
|
|
# @raycast.packageName Dashboard
|
|
# @raycast.icon 🖥️
|
|
|
|
import json
|
|
import urllib.request
|
|
import sys
|
|
|
|
# Configuration
|
|
TRUENAS_IP = "192.168.1.135"
|
|
API_KEY = "1-sk8ocSHrEEsrD64HBi00kTkEfVQy6itnv3X75jSHXfZzIc0gnOXkJeszMXQ8YNg4"
|
|
|
|
def fetch_truenas_data(endpoint):
|
|
url = f"http://{TRUENAS_IP}/api/v2.0/{endpoint}"
|
|
req = urllib.request.Request(url)
|
|
req.add_header("Authorization", f"Bearer {API_KEY}")
|
|
req.add_header("Content-Type", "application/json")
|
|
|
|
try:
|
|
with urllib.request.urlopen(req, timeout=5) as response:
|
|
return json.loads(response.read().decode())
|
|
except Exception as e:
|
|
return None
|
|
|
|
def bytes_to_human(size_bytes):
|
|
if size_bytes == 0:
|
|
return "0 B"
|
|
units = ["B", "KiB", "MiB", "GiB", "TiB"]
|
|
i = 0
|
|
while size_bytes >= 1024 and i < len(units) - 1:
|
|
size_bytes /= 1024
|
|
i += 1
|
|
return f"{size_bytes:.2f} {units[i]}"
|
|
|
|
def main():
|
|
print("# Home Lab Infrastructure Status\n")
|
|
print("---")
|
|
|
|
# Fetch Data from TrueNAS Endpoints
|
|
pools = fetch_truenas_data("pool")
|
|
datasets = fetch_truenas_data("pool/dataset")
|
|
apps = fetch_truenas_data("app")
|
|
|
|
if pools is None or datasets is None:
|
|
print("❌ **Error:** Unable to connect to TrueNAS SCALE API. Check network or API token.")
|
|
sys.exit(0)
|
|
|
|
# 1. Process and Display ZFS Storage Pool Info
|
|
dataset_metrics = {}
|
|
for ds in datasets:
|
|
ds_id = ds.get("id")
|
|
used = ds.get("used", {}).get("parsed", 0)
|
|
available = ds.get("available", {}).get("parsed", 0)
|
|
dataset_metrics[ds_id] = {
|
|
"used": used,
|
|
"total": used + available
|
|
}
|
|
|
|
print("## 💾 Storage Pools")
|
|
print("| Pool Name | Status | Used Space | Total Capacity |")
|
|
print("| :--- | :--- | :--- | :--- |")
|
|
|
|
for pool in pools:
|
|
pool_name = pool.get("name", "Unknown")
|
|
status = pool.get("status", "UNKNOWN")
|
|
status_emoji = "🟢 HEALTHY" if status == "ONLINE" else "🔴 DEGRADED"
|
|
|
|
metrics = dataset_metrics.get(pool_name, {"used": 0, "total": 0})
|
|
used_str = bytes_to_human(metrics["used"])
|
|
total_str = bytes_to_human(metrics["total"])
|
|
|
|
print(f"| {pool_name} | {status_emoji} | {used_str} | {total_str} |")
|
|
|
|
print("\n---")
|
|
|
|
# 2. Process and Display Real TrueNAS Installed Apps
|
|
print("## 🚀 TrueNAS Catalog Applications")
|
|
|
|
if not apps:
|
|
print("*No installed applications found or Apps service is initializing.*")
|
|
else:
|
|
print("| Application Name | Status | Version |")
|
|
print("| :--- | :--- | :--- |")
|
|
|
|
for app in apps:
|
|
app_id = app.get("id", "Unknown")
|
|
state = app.get("state", "UNKNOWN")
|
|
version = app.get("version", "N/A")
|
|
|
|
# Map state strings to status indicators
|
|
if state == "RUNNING":
|
|
state_emoji = "🟢 Running"
|
|
elif state == "STOPPED":
|
|
state_emoji = "🛑 Stopped"
|
|
elif state == "DEPLOYING":
|
|
state_emoji = "🟡 Deploying"
|
|
else:
|
|
state_emoji = f"❓ {state}"
|
|
|
|
print(f"| {app_id} | {state_emoji} | {version} |")
|
|
|
|
if __name__ == "__main__":
|
|
main() |