|
36 | 36 | import shutil |
37 | 37 | import asyncio |
38 | 38 |
|
| 39 | +import configparser |
| 40 | + |
39 | 41 | # web framework |
40 | 42 | import requests |
41 | 43 | from fastapi import FastAPI, Request, File, UploadFile, Depends, APIRouter, Response |
|
62 | 64 | sse_messages: queue.Queue = queue.Queue() |
63 | 65 |
|
64 | 66 |
|
| 67 | +def create_logging_ini(): |
| 68 | + """Fallback in case the ini doesn't exist, set to default settings. Only really comes up during github tests.""" |
| 69 | + ini = '/var/log/logging.ini' |
| 70 | + tmp = '/tmp/logging.ini.tmp' |
| 71 | + |
| 72 | + if not os.path.exists(ini): |
| 73 | + conf = configparser.ConfigParser(strict=False, allow_no_value=True) |
| 74 | + with open(tmp, "+w", encoding="utf-8") as file: |
| 75 | + conf.read(file) |
| 76 | + conf.add_section("logging") |
| 77 | + conf.set("logging", "auto_off_delay", "14") |
| 78 | + conf.write(file) |
| 79 | + subprocess.run(['sudo', 'mv', tmp, ini], check=True) |
| 80 | + |
| 81 | + |
65 | 82 | class ReleaseInfo(BaseModel): |
66 | 83 | """ Software Release Information """ |
67 | 84 | url: str |
@@ -95,6 +112,93 @@ class ReleaseInfo(BaseModel): |
95 | 112 | logger.exception(f'Error loading identity file: {e}') |
96 | 113 |
|
97 | 114 |
|
| 115 | +class Persist_Logs(BaseModel): |
| 116 | + """Basemodel that consists of a bool and int, used to change different config files around the system via POST /settings/persist_logs""" |
| 117 | + persist_logs: bool |
| 118 | + auto_off_delay: int |
| 119 | + |
| 120 | + |
| 121 | +@router.get("/settings/persist_logs") |
| 122 | +def get_log_persist_state(): |
| 123 | + """ |
| 124 | + Checks /etc/systemd/journald.conf to find if the current storage setting is persistent and returns a bool |
| 125 | + Note that returning false doesn't necessarily mean that logs are set to volatile, and could just mean that the config file is missing the line being read |
| 126 | + """ |
| 127 | + create_logging_ini() |
| 128 | + |
| 129 | + journalconf = configparser.ConfigParser(strict=False, allow_no_value=True) |
| 130 | + journalconf.read('/etc/systemd/journald.conf') |
| 131 | + |
| 132 | + logconf = configparser.ConfigParser(strict=False, allow_no_value=True) |
| 133 | + logconf.read('/var/log/logging.ini') |
| 134 | + |
| 135 | + # Fallback set is the default value of the Storage variable under the Journal header of the conf file |
| 136 | + # Used when the variable cannot be read but the file itself can (implying that the variable is missing, and should be set to a default) |
| 137 | + ret = Persist_Logs(persist_logs=journalconf.get("Journal", "Storage", fallback="volatile") == "persistent", auto_off_delay=logconf.get("logging", "auto_off_delay", fallback="14"),) |
| 138 | + return ret |
| 139 | + |
| 140 | + |
| 141 | +@router.post("/settings/persist_logs") |
| 142 | +def toggle_persist_logs(data: Persist_Logs): |
| 143 | + """Toggles the option within journald to save logs to memory or storage, and sets the length of time before that setting is reset to volatile""" |
| 144 | + try: |
| 145 | + create_logging_ini() # Just in case |
| 146 | + state = get_log_persist_state() |
| 147 | + |
| 148 | + if state.persist_logs != data.persist_logs: |
| 149 | + journalconf = '/etc/systemd/journald.conf' |
| 150 | + journaltmp = '/tmp/journald.conf.tmp' |
| 151 | + journal = configparser.ConfigParser(strict=False, allow_no_value=True) |
| 152 | + journal.read(journalconf) |
| 153 | + |
| 154 | + if not journal.has_section("Journal"): |
| 155 | + journal.add_section('Journal') |
| 156 | + |
| 157 | + # goal_value is true if you wish to turn persistent logging on and false if you wish to turn it off |
| 158 | + if data.persist_logs: # Set persist |
| 159 | + journal.set('Journal', 'Storage', 'persistent') |
| 160 | + journal.set('Journal', 'SyncIntervalSec', '30s') |
| 161 | + journal.set('Journal', 'SystemMaxUse', '64M') |
| 162 | + |
| 163 | + journal.remove_option('Journal', 'RuntimeMaxUse') |
| 164 | + journal.remove_option('Journal', 'ForwardToConsole') |
| 165 | + journal.remove_option('Journal', 'ForwardToWall') |
| 166 | + else: # Reset config to default as seen in configure.py |
| 167 | + journal.set('Journal', 'Storage', 'volatile') |
| 168 | + journal.set('Journal', 'RuntimeMaxUse', '64M') |
| 169 | + journal.set('Journal', 'ForwardToConsole', 'no') |
| 170 | + journal.set('Journal', 'ForwardToWall', 'no') |
| 171 | + |
| 172 | + journal.remove_option('Journal', 'SyncIntervalSec') |
| 173 | + journal.remove_option('Journal', 'SystemMaxUse') |
| 174 | + |
| 175 | + with open(journaltmp, 'w', encoding="utf-8") as conf_file: |
| 176 | + journal.write(conf_file) |
| 177 | + |
| 178 | + subprocess.run(['sudo', 'mv', journaltmp, journalconf], check=True) |
| 179 | + subprocess.run(['sudo', 'systemctl', 'restart', 'systemd-journald'], check=True) |
| 180 | + logger.info(f"persist_logs set to {data.persist_logs}") |
| 181 | + else: |
| 182 | + logger.info("persist_logs unchanged") |
| 183 | + |
| 184 | + if state.auto_off_delay != data.auto_off_delay: |
| 185 | + logconf = '/var/log/logging.ini' |
| 186 | + logtmp = '/tmp/logging.ini.tmp' |
| 187 | + log = configparser.ConfigParser(strict=False, allow_no_value=True) |
| 188 | + log.read(logconf) |
| 189 | + log.set('logging', 'auto_off_delay', f"{data.auto_off_delay}") # Accept auto_off_delay as an int for type checking, parse to str for configParser validity |
| 190 | + with open(logtmp, 'w', encoding='utf-8') as file: |
| 191 | + log.write(file) |
| 192 | + subprocess.run(['sudo', 'mv', logtmp, logconf], check=True) |
| 193 | + logger.info(f"auto_off_delay set to {data.auto_off_delay}") |
| 194 | + |
| 195 | + else: |
| 196 | + logger.info("auto_off_delay unchanged") |
| 197 | + except Exception as exc: |
| 198 | + logger.exception(str(exc)) |
| 199 | + return 500 |
| 200 | + |
| 201 | + |
98 | 202 | @router.get('/update') |
99 | 203 | def get_index(): |
100 | 204 | """ Get the update website """ |
|
0 commit comments