Sunil Mohan Adapa 9747051a8b
minidlna: Use privileged decorator for actions
Tests:

- Functional tests work
- Setting the media directory updates the configuration file. Newly set
  directory is shown on the app page after update.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2022-10-08 18:52:28 -04:00

93 lines
2.8 KiB
Python

# SPDX-License-Identifier: AGPL-3.0-or-later
"""Configure minidlna server."""
import subprocess
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)
subprocess.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)