Sunil Mohan Adapa 61ff15a04f
*: Use action_utils.run instead of subprocess.run
- This is to capture stdout and stderr and transmit that from privileged daemon
back to the service to be displayed in HTML.

Tests:

- Unit tests and code checks pass.

- Some of the modified actions work as expected.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Veiko Aasa <veiko17@disroot.org>
2025-09-29 16:58:53 +03:00

92 lines
2.8 KiB
Python

# SPDX-License-Identifier: AGPL-3.0-or-later
"""Configure minidlna server."""
from os import chmod, fdopen, remove, stat
from shutil import move
from tempfile import mkstemp
import augeas
from plinth import action_utils
from plinth.actions import privileged
from plinth.utils import grep
CONFIG_PATH = '/etc/minidlna.conf'
SYSCTL_CONF = '''# This file is managed and overwritten by FreedomBox.
# Helps minidlna monitor changes in large media directories
fs.inotify.max_user_watches = 100000
'''
def _undo_old_configuration_changes():
"""Restore /etc/sysctl.conf to before our changes.
Older version of minidlna app in FreedomBox < 20.9 wrote to
/etc/sysctl.conf directly. This will cause conffile prompt during upgrade
of procps package. Undo the changes so that upgrade can happen smoothly.
"""
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
augeas.Augeas.NO_MODL_AUTOLOAD)
aug.set('/augeas/load/Sysctl/lens', 'Sysctl.lns')
aug.set('/augeas/load/Sysctl/incl[last() + 1]', '/etc/sysctl.conf')
aug.load()
key_path = '/files/etc/sysctl.conf/fs.inotify.max_user_watches'
if aug.get(key_path) == '100000':
aug.remove(key_path)
aug.save()
@privileged
def setup():
"""Increase inotify watches per folder.
This is to allow minidlna to monitor changes in large media-dirs.
"""
_undo_old_configuration_changes()
with open('/etc/sysctl.d/50-freedombox-minidlna.conf', 'w',
encoding='utf-8') as conf:
conf.write(SYSCTL_CONF)
action_utils.run(['systemctl', 'restart', 'systemd-sysctl'], check=True)
@privileged
def get_media_dir() -> str:
"""Retrieve media directory from minidlna.conf."""
line = grep('^media_dir=', CONFIG_PATH)
return line[0].split('=')[1]
@privileged
def set_media_dir(media_dir: str):
"""Set media directory in minidlna.conf."""
line = grep('^media_dir=', CONFIG_PATH)[0]
new_line = 'media_dir=%s\n' % media_dir
replace_in_config_file(CONFIG_PATH, line, new_line)
if action_utils.service_is_running('minidlna'):
action_utils.service_restart('minidlna')
def replace_in_config_file(file_path, pattern, subst):
"""Replace a directive in configuration file.
- Create a temporary minidlna.conf file
- Replace the media dir config
- Remove original one and move the temporary file
- Preserve permissions as the original file
"""
temp_file, temp_file_path = mkstemp()
with fdopen(temp_file, 'w') as new_file:
with open(file_path, encoding='utf-8') as old_file:
for line in old_file:
new_file.write(line.replace(pattern, subst))
old_st_mode = stat(file_path).st_mode
remove(file_path)
move(temp_file_path, file_path)
chmod(file_path, old_st_mode)