diff options
-rwxr-xr-x | .gitignore | 2 | ||||
-rwxr-xr-x | app.py | 13 | ||||
-rwxr-xr-x | requirements.txt | 8 | ||||
-rwxr-xr-x | services.py | 74 | ||||
-rwxr-xr-x | static/index.md | 2 | ||||
-rwxr-xr-x | templates/services.html.j2 | 106 |
6 files changed, 123 insertions, 82 deletions
@@ -1,3 +1,5 @@ +*.pem +*.pub homelab-wiki/wiki.env homelab-wiki/images/* edaweb.conf @@ -2,7 +2,7 @@ from paste.translogger import TransLogger from waitress import serve from PIL import Image import configparser -import webbrowser +import transmission_rpc import downloader import datetime import database @@ -78,6 +78,17 @@ def index(): def robots(): return flask.send_from_directory("static", "robots.txt") +@app.route("/services") +def serve_services(): + with database.Database() as db: + return flask.render_template( + "services.html.j2", + **get_template_items("services", db), + docker = services.get_all_docker_containers(CONFIG.get("ssh", "docker_key_path")), + trans = services.get_torrent_stats(), + pihole = services.get_pihole_stats() + ) + @app.route("/discord") def discord(): with database.Database() as db: diff --git a/requirements.txt b/requirements.txt index 0ce280b..581cd7c 100755 --- a/requirements.txt +++ b/requirements.txt @@ -1,15 +1,13 @@ itsdangerous==2.0.1 PyMySQL==1.0.2 -python_qbittorrent==0.4.2 +transmission_rpc==4.1.0 Werkzeug==2.3.7 Flask==2.2.2 PiHole_api -transmission-clutch dataclasses docker -PiHole-api +APiHole Pillow==9.4.0 -python-qbittorrent==0.4.2 PyGithub lxml requests @@ -19,3 +17,5 @@ houdini.py Pygments mistune==2.0.3 twython==3.8.2 +fabric +paramiko
\ No newline at end of file diff --git a/services.py b/services.py index b56a07d..5fb7d81 100755 --- a/services.py +++ b/services.py @@ -3,8 +3,9 @@ from io import StringIO from lxml import html, etree from github import Github import multiprocessing -import pihole as ph -import qbittorrent +import paramiko.client +from APiHole import PiHole +import transmission_rpc import configparser import math as maths import requests @@ -12,6 +13,8 @@ import datetime import urllib import docker import random +import subprocess +import fabric import queue import json import time @@ -266,6 +269,68 @@ def scrape_whispa(whispa_url, since): }) return qnas +def get_docker_containers(host, ssh_key_path): + result = fabric.Connection( + host = host, + user = "root", + connect_kwargs = { + "key_filename": ssh_key_path, + "look_for_keys": False + } + ).run('docker ps -a -s --format "table {{.Names}};{{.Status}};{{.Image}}"', hide = True) + return [line.split(";") for line in result.stdout.split("\n")[1:-1]] + +def get_all_docker_containers(ssh_key_path): + containers = {} + for host, name in CONFIG["docker_hosts"].items(): + print(host) + containers[(host, name)] = get_docker_containers(host, ssh_key_path) + return containers + +def timeout(func): + # cant get this to work with queue.Queue() for some reason? + # this works but Manager() uses an extra thread than Queue() + manager = multiprocessing.Manager() + returnVan = manager.list() + # ti = time.time() + + def runFunc(q, func): + q.append(func()) + + def beginTimeout(): + t = multiprocessing.Process(target = runFunc, args = (returnVan, func)) + t.start() + + t.join(timeout = CONFIG["servicetimeout"].getint("seconds")) + + # print("Request took:", time.time() - ti) + try: + return returnVan[0] + except IndexError: + if t.is_alive(): + t.terminate() + + return beginTimeout + +@timeout +def get_torrent_stats(): + client = transmission_rpc.client.Client( + host = CONFIG.get("transmission", "host") + ) + s = vars(client.session_stats())["fields"] + return { + "Active torrents:": s["activeTorrentCount"], + "Downloaded:": humanbytes(s["cumulative-stats"]["downloadedBytes"]), + "Uploaded:": humanbytes(s["cumulative-stats"]["uploadedBytes"]), + "Active time:": str(datetime.timedelta(seconds = s["cumulative-stats"]["secondsActive"])), + "Files added:": s["cumulative-stats"]["filesAdded"], + "Current upload speed": humanbytes(s["uploadSpeed"]) + "s/S", + "Current download speed:": humanbytes(s["downloadSpeed"]) + "s/S" + } + +@timeout +def get_pihole_stats(): + return PiHole.GetSummary(CONFIG.get("pihole", "url"), CONFIG.get("pihole", "key"), True) if __name__ == "__main__": # print(get_trans_stats()) @@ -277,4 +342,7 @@ if __name__ == "__main__": # print(request_recent_commits(since = datetime.datetime.now() - datetime.timedelta(days=30))) - print(scrape_whispa(CONFIG.get("qnas", "url"), datetime.datetime.fromtimestamp(0.0))) + # print(scrape_whispa(CONFIG.get("qnas", "url"), datetime.datetime.fromtimestamp(0.0))) + # print(get_all_docker_containers(os.path.join(os.path.dirname(__file__), "edaweb-docker.pem"))) + + print(get_torrent_stats()) diff --git a/static/index.md b/static/index.md index 99bfa0c..39bbc7c 100755 --- a/static/index.md +++ b/static/index.md @@ -16,6 +16,8 @@ i'll post my thoughts on here sometimes, and use this site to link to other stuf - [git server - github alternative](https://git.eda.gay/) - [jellyfin - web player for ~~legally downloaded~~ TV and films](https://jellyfin.eda.gay) - RIP emby! +[see the services im running right now](/services) (takes a couple seconds to load) + these sites are hosted on my [homelab system](https://wiki.eda.gay)  diff --git a/templates/services.html.j2 b/templates/services.html.j2 index ebf8ebd..9c9e5ec 100755 --- a/templates/services.html.j2 +++ b/templates/services.html.j2 @@ -3,96 +3,54 @@ <article id=statusTables> <section id=docker> <h2>docker</h2> - {% if docker == None %} - <p>Couldn't access the docker API. Is sherpa running?</p> - {% else %} - <table> - {% for name, status in docker.items() %} - <tr> - <td>{{name}}</td> - {% if status == "running" %} - <td class=running>{{status}}</td> - {% else %} - <td class=notRunning>{{status}}</td> - {% endif %} - </tr> - {% endfor %} - </table> - {% endif %} + <ul> + {% for host, containers in docker.items() %} + <h4>{{ "%s - %s" % (host[0], host[1]) }}</h4> + <table> + {% for name, status, image in containers %} + <tr> + <td>{{ name }}</td> + {% if "Up" in status %} + <td class=running>{{ status }}</td> + {% else %} + <td class=notRunning>{{ status }}</td> + {% endif %} + <td>{{ image }}</td> + </tr> + {% endfor %} + </table> + {% endfor %} + </ul> </section> + <section id="torrents"> <h2>transmission</h2> {% if trans == None %} <p>Couldn't access the transmission API. Is docker container running?</p> {% else %} <table> - <tr> - <td>downloaded</td> - <td>{{trans["bytes_dl"]}}</td> - </tr> - <tr> - <td>uploaded</td> - <td>{{trans["bytes_up"]}}</td> - </tr> - <tr> - <td>torrents</td> - <td>{{trans["num"]}}</td> - </tr> - <tr> - <td>ratio</td> - <td>{{trans["ratio"]}}</td> - </tr> - <tr> - <td>active for</td> - <td>{{trans["active_for"]}}</td> - </tr> + {% for k, v in trans.items() %} + <tr> + <td>{{ k }}</td> + <td>{{ v }}</td> + </tr> + {% endfor %} </table> {% endif %} - <br> - <a>statistics of some old torrent clients which were shut down recently ;_;</a> - <br> - <img src="https://nitter.eda.gay/pic/media%2FFRnF3kcXwAAHE6v.png%3Fname%3Dorig"> - <img src="https://nitter.eda.gay/pic/media%2FFRnF6I0WUAEq4FD.png%3Fname%3Dorig"> - <img src="/img/photo_2022-12-07_14-06-03.jpg"> </section> + <section id=pihole> <h2>pihole</h2> {% if pihole == None %} <p>Couldn't access the pihole API. Is docker container running?</p> {% else %} <table> - <tr> - <td>status</td> - {% if pihole["status"] == "enabled" %} - <td class=running>{{pihole["status"]}}</td> - {% else %} - <td class=notRunning>{{pihole["status"]}}</td> - {% endif %} - </tr> - <tr> - <td>queries</td> - <td>{{pihole["queries"]}}</td> - </tr> - <tr> - <td>clients</td> - <td>{{pihole["clients"]}}</td> - </tr> - <tr> - <td>percentage blocked</td> - <td>{{pihole["percentage"]}}%</td> - </tr> - <tr> - <td>blocked requests</td> - <td>{{pihole["blocked"]}}</td> - </tr> - <tr> - <td>domains in blocklist</td> - <td>{{pihole["domains"]}}</td> - </tr> - <tr> - <td>last updated</td> - <td>{{pihole["last_updated"]}}</td> - </tr> + {% for k, v in pihole.items() %} + <tr> + <td>{{ k }}</td> + <td>{{ v }}</td> + </tr> + {% endfor %} </table> {% endif %} </section> |