Name: parasol-app Version: 1.6 Release: 1 Summary: The parasol app package License: FIXME BuildArch: x86_64 Requires: python3.11 BuildRequires: python3-pip, python3, python3-requests, python3-pyyaml, python3-psutil %description The parasol app package. %prep %build cat > parasol-app.service <<"EOF" [Unit] Description=Parasol App After=network.target [Service] Type=simple ExecStart=/usr/bin/parasol-app Restart=on-failure RestartSec=5s StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target EOF cat > parasol-app <<"EOF" #!/usr/bin/python3 import os import socket import syslog import psutil import requests import threading import time import uuid import yaml from requests.exceptions import ConnectionError _webhook_thread = None APP_VERSION = "1.6" CONFIG_PATH = "/etc/parasol-app.conf" CONFIG_D_PATH = "/etc/parasol-app.d/" last_webhook_high_cpu_state = None def get_non_localhost_ips(): """Return list of non-localhost IPv4 addresses. Excludes 127.x.""" ips = [] for addrs in psutil.net_if_addrs().values(): for a in addrs: if a.family == socket.AF_INET and a.address and not a.address.startswith('127.'): ips.append(a.address) return ips def call_webhook(high_cpu): global _webhook_thread if _webhook_thread is not None and _webhook_thread.is_alive(): _webhook_thread.join() ips = get_non_localhost_ips() server_ip = ips[0] if ips else "unknown" headers = {"x-api-key": config['api_key']} session_id = str(uuid.uuid4()) data = {"input_type": "chat", "output_type": "chat", "server_ip": server_ip, "input_value": "Normal CPU load", "session_id": session_id} if high_cpu: data['input_value'] = "High CPU load" data['input_value'] += f" detected on {server_ip}" def _do_post(): try: # wait for the CPU load to rise/fall time.sleep(2) # hidden wording: if high_cpu: keyword = "plugin enabled" else: keyword = "plugin disabled" syslog.syslog(syslog.LOG_INFO, f"'{keyword}' in session '{session_id}'") response = requests.post(config['app_url'], json=data, headers=headers, timeout=600) syslog.syslog(syslog.LOG_INFO, f"Report sent: {response.status_code}") except ConnectionError: syslog.syslog(syslog.LOG_WARNING, "unable to connect to webhook, continuing") _webhook_thread = threading.Thread(target=_do_post) _webhook_thread.start() def read_yaml_file(file_path): with open(file_path, 'r') as file: data = yaml.safe_load(file) return data def conf_d_dir_has_perf_mode(conf_d_path): if len(os.listdir(conf_d_path)) == 0: return False return True config = read_yaml_file(CONFIG_PATH) while True: use_high_cpu = conf_d_dir_has_perf_mode(CONFIG_D_PATH) and APP_VERSION == "1.5" # no update on startup if last_webhook_high_cpu_state is None: last_webhook_high_cpu_state = use_high_cpu # bail out if we already called the webhook and the state didnt change if last_webhook_high_cpu_state != use_high_cpu: call_webhook(high_cpu = use_high_cpu) last_webhook_high_cpu_state = use_high_cpu if not use_high_cpu: time.sleep(2) EOF pip3 install pyinstaller pyinstaller -F parasol-app %install mkdir -p %{buildroot}/etc/systemd/system install -m 644 parasol-app.service %{buildroot}/etc/systemd/system/ mkdir -p %{buildroot}/usr/bin install -m 755 dist/parasol-app %{buildroot}/usr/bin/ mkdir -p %{buildroot}/etc mkdir -p %{buildroot}/etc/parasol-app.d/ %files /etc/systemd/system/parasol-app.service /usr/bin/parasol-app %post systemctl daemon-reload %changelog * Tue Feb 17 2026 Example User - 1.5-1 new package