Add custom homelab dashboard stack
This commit is contained in:
@@ -0,0 +1 @@
|
||||
"""Pydantic models for API and domain data."""
|
||||
@@ -0,0 +1,23 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Literal
|
||||
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
|
||||
SourceStatus = Literal["online", "offline", "unsupported"]
|
||||
OverallStatus = Literal["online", "degraded", "offline"]
|
||||
HealthStatus = Literal["healthy", "warning", "offline"]
|
||||
DiskStatus = Literal["online", "warning", "critical", "offline"]
|
||||
ServiceKind = Literal["core", "service"]
|
||||
ServiceSource = Literal["home_assistant", "uptime_kuma", "docker", "manual"]
|
||||
DockerContainerState = Literal["running", "stopped", "unhealthy", "unknown"]
|
||||
|
||||
|
||||
class APIModel(BaseModel):
|
||||
model_config = ConfigDict(extra="ignore", populate_by_name=True)
|
||||
|
||||
|
||||
class TimestampedResponse(APIModel):
|
||||
generated_at: datetime
|
||||
@@ -0,0 +1,44 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from app.models.common import APIModel, OverallStatus, SourceStatus, TimestampedResponse
|
||||
|
||||
|
||||
class OverviewServicesSummary(APIModel):
|
||||
online: int
|
||||
degraded: int
|
||||
offline: int
|
||||
total: int
|
||||
|
||||
|
||||
class OverviewDockerSummary(APIModel):
|
||||
running: int
|
||||
stopped: int
|
||||
unhealthy: int
|
||||
total: int
|
||||
source_status: SourceStatus
|
||||
|
||||
|
||||
class OverviewSystemSummary(APIModel):
|
||||
cpu_percent: float
|
||||
ram_percent: float
|
||||
root_storage_percent: float
|
||||
network_rx_mbps: float
|
||||
network_tx_mbps: float
|
||||
uptime_seconds: int
|
||||
|
||||
|
||||
class OverviewHomeAssistantSummary(APIModel):
|
||||
status: SourceStatus
|
||||
label: str
|
||||
version: str | None = None
|
||||
response_time_ms: int | None = None
|
||||
last_checked: str | None = None
|
||||
|
||||
|
||||
class OverviewResponse(TimestampedResponse):
|
||||
overall_status: OverallStatus
|
||||
refresh_hint_seconds: int
|
||||
services: OverviewServicesSummary
|
||||
docker: OverviewDockerSummary
|
||||
system: OverviewSystemSummary
|
||||
home_assistant: OverviewHomeAssistantSummary
|
||||
@@ -0,0 +1,52 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from app.models.common import (
|
||||
APIModel,
|
||||
DockerContainerState,
|
||||
HealthStatus,
|
||||
OverallStatus,
|
||||
ServiceKind,
|
||||
ServiceSource,
|
||||
SourceStatus,
|
||||
TimestampedResponse,
|
||||
)
|
||||
|
||||
|
||||
class ServicesDockerSummary(APIModel):
|
||||
running: int
|
||||
stopped: int
|
||||
unhealthy: int
|
||||
total: int
|
||||
source_status: SourceStatus
|
||||
|
||||
|
||||
class ServicesUptimeKumaSummary(APIModel):
|
||||
monitors_up: int
|
||||
monitors_down: int
|
||||
monitors_paused: int
|
||||
total: int
|
||||
source_status: SourceStatus
|
||||
|
||||
|
||||
class ServicesSummary(APIModel):
|
||||
overall_status: OverallStatus
|
||||
docker: ServicesDockerSummary
|
||||
uptime_kuma: ServicesUptimeKumaSummary
|
||||
|
||||
|
||||
class ServiceItem(APIModel):
|
||||
id: str
|
||||
name: str
|
||||
kind: ServiceKind
|
||||
status: OverallStatus
|
||||
health: HealthStatus
|
||||
latency_ms: int | None = None
|
||||
docker_state: DockerContainerState
|
||||
url: str | None = None
|
||||
source: ServiceSource
|
||||
last_checked: str | None = None
|
||||
|
||||
|
||||
class ServicesResponse(TimestampedResponse):
|
||||
summary: ServicesSummary
|
||||
services: list[ServiceItem]
|
||||
@@ -0,0 +1,85 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import Field
|
||||
|
||||
from app.models.common import APIModel, DockerContainerState, OverallStatus, SourceStatus
|
||||
|
||||
|
||||
class BeszelDiskMetric(APIModel):
|
||||
name: str
|
||||
mount: str
|
||||
used_gb: float
|
||||
total_gb: float
|
||||
free_gb: float
|
||||
usage_percent: float
|
||||
|
||||
|
||||
class BeszelSystemSnapshot(APIModel):
|
||||
source_name: str = "beszel"
|
||||
source_status: SourceStatus = "offline"
|
||||
host_name: str = "unknown"
|
||||
agent_name: str = "beszel-agent"
|
||||
cpu_usage_percent: float = 0.0
|
||||
cpu_cores: int = 0
|
||||
load_1: float = 0.0
|
||||
load_5: float = 0.0
|
||||
load_15: float = 0.0
|
||||
memory_used_gb: float = 0.0
|
||||
memory_total_gb: float = 0.0
|
||||
memory_available_gb: float = 0.0
|
||||
memory_usage_percent: float = 0.0
|
||||
primary_interface: str = "unknown"
|
||||
network_rx_mbps: float = 0.0
|
||||
network_tx_mbps: float = 0.0
|
||||
uptime_seconds: int = 0
|
||||
platform: str = "unknown"
|
||||
kernel: str = "unknown"
|
||||
disks: list[BeszelDiskMetric] = Field(default_factory=list)
|
||||
|
||||
|
||||
class DockerContainerSummary(APIModel):
|
||||
id: str
|
||||
name: str
|
||||
state: DockerContainerState
|
||||
status_text: str
|
||||
image: str
|
||||
health: str | None = None
|
||||
|
||||
|
||||
class DockerSnapshot(APIModel):
|
||||
source_name: str = "docker"
|
||||
source_status: SourceStatus = "offline"
|
||||
running: int = 0
|
||||
stopped: int = 0
|
||||
unhealthy: int = 0
|
||||
total: int = 0
|
||||
containers: list[DockerContainerSummary] = Field(default_factory=list)
|
||||
|
||||
|
||||
class UptimeKumaMonitor(APIModel):
|
||||
id: str
|
||||
name: str
|
||||
status: OverallStatus
|
||||
latency_ms: int | None = None
|
||||
monitor_type: str | None = None
|
||||
|
||||
|
||||
class UptimeKumaSnapshot(APIModel):
|
||||
source_name: str = "uptime_kuma"
|
||||
source_status: SourceStatus = "offline"
|
||||
monitors_up: int = 0
|
||||
monitors_down: int = 0
|
||||
monitors_paused: int = 0
|
||||
total: int = 0
|
||||
monitors: list[UptimeKumaMonitor] = Field(default_factory=list)
|
||||
|
||||
|
||||
class HomeAssistantSnapshot(APIModel):
|
||||
source_name: str = "home_assistant"
|
||||
status: SourceStatus = "offline"
|
||||
label: str = "Home Assistant"
|
||||
version: str | None = None
|
||||
response_time_ms: int | None = None
|
||||
last_checked: datetime | None = None
|
||||
@@ -0,0 +1,27 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from app.models.common import APIModel, DiskStatus, OverallStatus, SourceStatus, TimestampedResponse
|
||||
|
||||
|
||||
class StorageSummary(APIModel):
|
||||
overall_status: OverallStatus
|
||||
source_status: SourceStatus
|
||||
critical_disks: int
|
||||
warning_disks: int
|
||||
total_disks: int
|
||||
|
||||
|
||||
class StorageDisk(APIModel):
|
||||
name: str
|
||||
mount: str
|
||||
used_gb: float
|
||||
total_gb: float
|
||||
free_gb: float
|
||||
usage_percent: float
|
||||
status: DiskStatus
|
||||
|
||||
|
||||
class StorageResponse(TimestampedResponse):
|
||||
summary: StorageSummary
|
||||
root: StorageDisk
|
||||
disks: list[StorageDisk]
|
||||
@@ -0,0 +1,45 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from app.models.common import APIModel, SourceStatus, TimestampedResponse
|
||||
|
||||
|
||||
class SystemSource(APIModel):
|
||||
name: str
|
||||
status: SourceStatus
|
||||
host_name: str
|
||||
agent_name: str
|
||||
|
||||
|
||||
class SystemCPU(APIModel):
|
||||
usage_percent: float
|
||||
cores: int
|
||||
load_1: float
|
||||
load_5: float
|
||||
load_15: float
|
||||
|
||||
|
||||
class SystemMemory(APIModel):
|
||||
used_gb: float
|
||||
total_gb: float
|
||||
available_gb: float
|
||||
usage_percent: float
|
||||
|
||||
|
||||
class SystemNetwork(APIModel):
|
||||
primary_interface: str
|
||||
rx_mbps: float
|
||||
tx_mbps: float
|
||||
|
||||
|
||||
class SystemHost(APIModel):
|
||||
uptime_seconds: int
|
||||
platform: str
|
||||
kernel: str
|
||||
|
||||
|
||||
class SystemResponse(TimestampedResponse):
|
||||
source: SystemSource
|
||||
cpu: SystemCPU
|
||||
memory: SystemMemory
|
||||
network: SystemNetwork
|
||||
host: SystemHost
|
||||
Reference in New Issue
Block a user