diff --git a/__pycache__/main.cpython-313.pyc b/__pycache__/main.cpython-313.pyc index c868ef3..55cae70 100644 Binary files a/__pycache__/main.cpython-313.pyc and b/__pycache__/main.cpython-313.pyc differ diff --git a/main.py b/main.py index 83124f7..51da36d 100644 --- a/main.py +++ b/main.py @@ -9,45 +9,20 @@ from fastapi import HTTPException import os from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles +import threading if os.environ.get("DATABASE_URL") == None: os.environ["DATABASE_URL"] = "sqlite:///./wall_messages.db" app = FastAPI() -start_time = time.time() -@app.get("/uptime") -def get_uptime(): - uptime_seconds = int(time.time() - start_time) - uptime_str = str(datetime.timedelta(seconds=uptime_seconds)) - return {"uptime_seconds": uptime_seconds, "uptime": uptime_str} - -@app.get("/disk") -def get_disk_usage(): - usage = psutil.disk_usage('/') - return { - "total": usage.total, - "used": usage.used, - "free": usage.free, - "percent": usage.percent - } - -@app.get("/ram") -def get_ram_usage(): - mem = psutil.virtual_memory() - return { - "total": mem.total, - "available": mem.available, - "used": mem.used, - "percent": mem.percent - } -@app.get("/cpu") -def get_cpu_usage(): - cpu_percent = psutil.cpu_percent(interval=1) - return {"cpu_percent": cpu_percent} - - +cpu_threshold = 80 +ram_threshold = 80 +disk_threshold = 80 +cpu_normal = True +ram_normal = True +disk_normal = True DATABASE_URL = "sqlite:///./wall_messages.db" @@ -55,89 +30,184 @@ engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False}) SessionLocal = sessionmaker(bind=engine) Base = declarative_base() -class WallMessageDB(Base): - __tablename__ = "wall_messages" +class LimitsModel(Base): + __tablename__ = "limits" id = Column(Integer, primary_key=True, index=True) - text = Column(String, nullable=False) - timestamp = Column(DateTime, default=datetime.datetime.utcnow(), nullable=False) + cpu_threshold = Column(Integer, default=80) + ram_threshold = Column(Integer, default=80) + disk_threshold = Column(Integer, default=80) -Base.metadata.create_all(bind=engine) +class OverageEventModel(Base): + __tablename__ = "overages" + id = Column(Integer, primary_key=True, index=True) + cpu_overage = Column(Integer, default=0) + ram_overage = Column(Integer, default=0) + disk_overage = Column(Integer, default=0) + timestamp = Column(DateTime, default=datetime.datetime.now(), nullable=False) -class WallMessageCreate(BaseModel): - text: str - -class WallMessageRead(BaseModel): +class OverageEvent(BaseModel): id: int - text: str + cpu_overage: int + ram_overage: int + disk_overage: int timestamp: datetime.datetime class Config: orm_mode = True -@app.post("/wall", response_model=WallMessageRead) -def post_wall_message(msg: WallMessageCreate): - db = SessionLocal() - db_msg = WallMessageDB(text=msg.text) - db.add(db_msg) - db.commit() - db.refresh(db_msg) - db.close() - return db_msg +Base.metadata.create_all(bind=engine) -@app.get("/wall", response_model=list[WallMessageRead]) -def get_wall_messages(): - db = SessionLocal() - messages = db.query(WallMessageDB).order_by(WallMessageDB.timestamp.desc()).all() - db.close() - return messages -@app.get("/wall/{msg_id}", response_model=WallMessageRead) -def get_wall_message(msg_id: int): +@app.on_event("startup") +def startup_event(): db = SessionLocal() - msg = db.query(WallMessageDB).filter(WallMessageDB.id == msg_id).first() + if not db.query(LimitsModel).first(): + limits = LimitsModel( + cpu_threshold=50, + ram_threshold=50, + disk_threshold=80 + ) + db.add(limits) + db.commit() db.close() - if not msg: - raise HTTPException(status_code=404, detail="Message not found") - return msg -@app.put("/wall/{msg_id}", response_model=WallMessageRead) -def update_wall_message(msg_id: int, msg: WallMessageCreate): - db = SessionLocal() - db_msg = db.query(WallMessageDB).filter(WallMessageDB.id == msg_id).first() - if not db_msg: +def check_and_log_overages(): + while True: + db = SessionLocal() + limits = db.query(LimitsModel).first() + if limits: + cpu_limit = limits.cpu_threshold + ram_limit = limits.ram_threshold + disk_limit = limits.disk_threshold + + cpu = psutil.cpu_percent(interval=0.5) + ram = psutil.virtual_memory().percent + disk = psutil.disk_usage('/').percent + + cpu_over = int(cpu > cpu_limit) + ram_over = int(ram > ram_limit) + disk_over = int(disk > disk_limit) + + last_event = db.query(OverageEventModel).order_by(OverageEventModel.timestamp.desc()).first() + should_log = False + + if last_event is None: + should_log = True + else: + if ( + last_event.cpu_overage != cpu_over or + last_event.ram_overage != ram_over or + last_event.disk_overage != disk_over + ): + should_log = True + + if should_log: + event = OverageEventModel( + cpu_overage=cpu_over, + ram_overage=ram_over, + disk_overage=disk_over, + timestamp=datetime.datetime.now() + ) + db.add(event) + db.commit() db.close() - raise HTTPException(status_code=404, detail="Message not found") - db_msg.text = msg.text - db.commit() - db.refresh(db_msg) - db.close() - return db_msg + time.sleep(10) -@app.delete("/wall/{msg_id}") -def delete_wall_message(msg_id: int): - db = SessionLocal() - db_msg = db.query(WallMessageDB).filter(WallMessageDB.id == msg_id).first() - if not db_msg: - db.close() - raise HTTPException(status_code=404, detail="Message not found") - db.delete(db_msg) - db.commit() - db.close() - return {"status": "success", "message": f"Deleted message {msg_id}"} +threading.Thread(target=check_and_log_overages, daemon=True).start() -class WallMessage(BaseModel): - message: str + + +start_time = time.time() +class Info(BaseModel): + uptime: datetime.datetime + cpu: float + ram: float + disk: float + cpu_threshold: int + ram_threshold: int + disk_threshold: int + cpu_normal: bool + ram_normal: bool + disk_normal: bool -wall_messages = [] +class Thresholds(BaseModel): + cpu_threshold: int + ram_threshold: int + disk_threshold: int -@app.post("/wall") -def post_wall_message(msg: WallMessage): - wall_messages.append(msg.message) - return {"status": "success", "message": msg.message} -@app.get("/wall") -def get_wall_messages(): - return wall_messages +@app.get("/info", response_class=Info) +def get_info(): + cpu = psutil.cpu_percent(interval=0.5) + ram = psutil.virtual_memory().percent + disk = psutil.disk_usage('/').percent + uptime = time.time() - start_time + info = Info( + uptime=uptime, + cpu=cpu, + ram=ram, + disk=disk, + cpu_threshold=cpu_threshold, + ram_threshold=ram_threshold, + disk_threshold=disk_threshold, + cpu_normal=cpu <= cpu_threshold, + ram_normal=ram <= ram_threshold, + disk_normal=disk <= disk_threshold + ) + return info + +@app.get("/limits", response_model=Thresholds) +def get_limits(): + return { + "cpu_threshold": cpu_threshold, + "ram_threshold": ram_threshold, + "disk_threshold": disk_threshold + } + +@app.post("/limits") +def set_limits(thresholds: Thresholds): + db = SessionLocal() + limits = db.query(LimitsModel).first() + if limits: + limits.cpu_threshold = thresholds.cpu_threshold + limits.ram_threshold = thresholds.ram_threshold + limits.disk_threshold = thresholds.disk_threshold + db.commit() + db.refresh(limits) + db.close() + + return { + "cpu": cpu_threshold, + "ram": ram_threshold, + "disk": disk_threshold + } +@app.get("/overages", response_model=list[OverageEvent]) +def get_overages(): + db = SessionLocal() + overages = db.query(OverageEventModel).order_by(OverageEventModel.timestamp.desc()).all() + db.close() + return overages + +@app.get("/overages/{overage_id}", response_model=OverageEvent) +def get_overage(overage_id: int): + db = SessionLocal() + overage = db.query(OverageEventModel).filter(OverageEventModel.id == overage_id).first() + db.close() + if not overage: + raise HTTPException(status_code=404, detail="Overage event not found") + return overage + +@app.delete("/overages/{overage_id}") +def delete_overage(overage_id: int): + db = SessionLocal() + overage = db.query(OverageEventModel).filter(OverageEventModel.id == overage_id).first() + if not overage: + db.close() + raise HTTPException(status_code=404, detail="Overage event not found") + db.delete(overage) + db.commit() + db.close() + return {"detail": "Overage event deleted"} app.add_middleware( CORSMiddleware, @@ -146,4 +216,5 @@ app.add_middleware( allow_methods=["*"], allow_headers=["*"], ) -app.mount("/", StaticFiles(directory=".", html=True), name="static") \ No newline at end of file + +app.mount("/", StaticFiles(directory="./webroot", html=True), name="static") \ No newline at end of file diff --git a/wall_messages.db b/wall_messages.db index aa94765..a86a9ae 100644 Binary files a/wall_messages.db and b/wall_messages.db differ diff --git a/index.html b/webroot/index.html similarity index 59% rename from index.html rename to webroot/index.html index 4904066..cdbe140 100644 --- a/index.html +++ b/webroot/index.html @@ -17,7 +17,7 @@