refactor: system API

refs #11
This commit is contained in:
Stefan Stammberger 2021-09-05 20:23:59 +02:00
parent 79be6eaf34
commit c673394fa8
No known key found for this signature in database
GPG key ID: 645FA807E935D9D5
4 changed files with 127 additions and 5 deletions

View file

@ -1,7 +1,11 @@
from typing import Optional
from enum import Enum
from typing import List, Optional
from app.models.lightning import LnInfo
from fastapi import Query
from fastapi.param_functions import Query
from pydantic import BaseModel
from pydantic.types import conint, constr
from pydantic.types import constr
class LoginInput(BaseModel):
@ -9,3 +13,103 @@ class LoginInput(BaseModel):
one_time_password: Optional[
constr(min_length=6, max_length=6, regex="^[0-9]+$")
] = None
class HealthMessagePriority(str, Enum):
INFO = "info" # FYI, can normally be ignored.
WARNING = (
"warning" # Potential problem might occur, user interaction possibly required.
)
ERROR = "error" # Something bad happened. User interaction deinitely required.
class HealthMessage(BaseModel):
id: int = Query(
None,
description="""ID of the message.
Idea behind the ID is that messages can be replacable on the client.
To prevent spamming the user with multiple messages, message with ID 25 will be replaced with never data of ID 25
""",
example="""
```{
id: 25,
level: "warning",
message: "HDD is 89.3% full"
}```
""",
)
level: HealthMessagePriority = Query(
HealthMessagePriority.INFO,
description="""Priority level of the message. For more info see `message`.
`INFO`: FYI, can normally be ignored.\n
`WARNING`: Potential problem might occur, user interaction possibly required.\n
`ERROR`: Something bad happened. User interaction definitely required.
If there are multiple messages with different priorities, the most severe level will be shown.
""",
)
message: str = Query(..., description="Detailed message description")
class HealthState(str, Enum):
# All systems work nominally
GOOD = "good"
# Some event requires users attention (Software update, HDD nearly full)
ATTENTION_REQUIRED = "attention_required"
# An error happened which prevents the node from working properly
# (Hardware failure, DB corruption, Internet connection not available, ...)
STOPPED = "stopped"
class SystemInfo(BaseModel):
alias: str = Query("", description="Name of the node (same as Lightning alias)")
color: str = Query(
..., description="The color of the current node in hex code format"
)
version: str = Query(..., description="The software version of this RaspiBlitz")
health: HealthState = Query(
..., description="General health state of the Raspiblitz"
)
health_messages: List[HealthMessage] = Query(
[], description="List of all messages regarding node health."
)
tor_web_ui: str = Query("", description="WebUI TOR address")
tor_api: str = Query("", description="API TOR address")
lan_web_ui: str = Query("", description="WebUI LAN address")
lan_api: str = Query("", description="API LAN address")
ssh_address: str = Query(
...,
description="Address to ssh into on local LAN (e.g. `ssh admin@192.168.1.28`",
)
# This is here to avoid having duplicated entries in BtcStatus and LnStatus
# The chain status will always be the same between Bitcoin Core
# and the Lightning Implementation
chain: str = Query(
...,
description="The current chain this node is connected to (mainnet, testnet or signet)",
)
@classmethod
def from_rpc(cls, lninfo: LnInfo):
# TODO: implement rest of the calls
return cls(
alias=lninfo.alias,
color=lninfo.color,
version="v1.8.0",
health=HealthState.ATTENTION_REQUIRED,
health_messages=[
HealthMessage(
id=25, level=HealthMessagePriority.WARNING, message="HDD 85% full"
)
],
tor_web_ui="arg6ybal4b7dszmsncsrudcpdfkxadzfdi24ktceodah7tgmdopgpyfd.onion",
tor_api="arg6ybal4b7dszmsncsrudcpdfkxadzfdi24ktceodah7tgmdopgpyfd.onion/api",
lan_web_ui="http://192.168.1.12/",
lan_api="http://192.168.1.12/api",
ssh_address="http://192.168.1.12/",
chain=lninfo.chains[
0
].network, # for now, assume we are only on bitcoin chain
)

View file

@ -1,6 +1,8 @@
import asyncio
import psutil
from app.models.system import SystemInfo
from app.repositories.lightning import get_ln_info
from app.utils import SSE, send_sse_message
from decouple import config
from fastapi import Request
@ -10,6 +12,11 @@ CPU_AVG_PERIOD = config("cpu_usage_averaging_period", default=0.5, cast=float)
HW_INFO_YIELD_TIME = SLEEP_TIME + CPU_AVG_PERIOD
async def get_system_info() -> SystemInfo:
lninfo = await get_ln_info()
return SystemInfo.from_rpc(lninfo)
async def subscribe_hardware_info(request: Request):
while True:
if await request.is_disconnected():

View file

@ -1,9 +1,10 @@
from app.auth.auth_bearer import JWTBearer
from app.auth.auth_handler import signJWT
from app.models.system import LoginInput
from app.repositories.hardware_info import (
from app.models.system import LoginInput, SystemInfo
from app.repositories.system import (
HW_INFO_YIELD_TIME,
get_hardware_info,
get_system_info,
subscribe_hardware_info,
)
from app.routers.system_docs import get_hw_info_json
@ -28,6 +29,16 @@ def login(i: LoginInput):
raise HTTPException(status.HTTP_401_UNAUTHORIZED, detail="Password is wrong")
@router.get(
"/get_system_info",
summary="Get system status information",
dependencies=[Depends(JWTBearer())],
response_model=SystemInfo,
)
async def get_system_info_path():
return await get_system_info()
@router.get(
"/hardware_info",
summary="Get hardware status information.",

View file

@ -17,7 +17,7 @@ from app.repositories.bitcoin import (
register_bitcoin_status_gatherer,
register_bitcoin_zmq_sub,
)
from app.repositories.hardware_info import register_hardware_info_gatherer
from app.repositories.system import register_hardware_info_gatherer
from app.repositories.lightning import register_lightning_listener
from app.routers import apps, bitcoin, lightning, setup, system
from app.sse_starlette import EventSourceResponse