1 ## @defgroup modules Module 2 ## @brief Verwaltung der Opennet-Module für verschiedene Funktionen/Rollen 3 # Beginn der Doku-Gruppe 6 # Basis-URL für Opennet-Paketinstallationen 7 ON_OPKG_REPOSITORY_URL_PREFIX=
"https://downloads.opennet-initiative.de/openwrt" 8 # temporäre Datei für Installation von Opennet-Paketen 9 ON_OPKG_CONF_PATH=
"${IPKG_INSTROOT:-}/tmp/opkg-opennet.conf" 10 # shellcheck disable=SC2034 11 DEFAULT_MODULES_ENABLED=
"on-olsr2" 14 # Erzeuge die uci-Sektion "on-core.modules" und aktiviere Standard-Module. 15 _prepare_on_modules() {
16 [ -n
"$(uci_get "on-core.modules
")" ] &&
return 17 uci
set "on-core.modules=modules" 21 ## @fn is_on_module_installed_and_enabled() 22 ## @brief Pruefe ob ein Modul sowohl installiert, als auch aktiv ist. 23 ## @param module Eins der Opennet-Pakete (siehe 'get_on_modules'). 24 ## @details Die Aktivierung eines Modules wird anhand der uci-Einstellung "${module}.settings.enabled" geprueft. 25 ## Der Standardwert ist "false" (ausgeschaltet). 27 trap
'error_trap is_on_module_installed_and_enabled "$*"' EXIT
30 is_on_module_installed
"$module" && _is_on_module_enabled
"$module" &&
return 0
31 trap
"" EXIT &&
return 1
35 _is_on_module_enabled() {
39 trap
"" EXIT &&
return 1
43 is_on_module_installed() {
46 is_package_installed
"$module" &&
return 0
47 trap
"" EXIT &&
return 1
51 ## @fn enable_on_module() 52 ## @brief Aktiviere ein Opennet-Modul 53 ## @param module Eins der Opennet-Pakete (siehe 'get_on_modules'). 55 trap
'error_trap enable_on_module "$*"' EXIT
59 warn_if_not_installed_module
"$module" 61 apply_changes
"on-core" "$module" 65 ## @fn disable_on_module() 66 ## @brief Deaktiviere ein Opennet-Modul 67 ## @param module Eins der Opennet-Pakete (siehe 'get_on_modules'). 69 trap
'error_trap disable_on_module "$*"' EXIT
72 _is_on_module_enabled
"$module" ||
return 0
74 apply_changes
"on-core" "$module" 78 ## @fn warn_if_unknown_module() 79 ## @brief Gib eine Warnung aus, falls der angegebene Modul-Name unbekannt ist. 80 ## @details Das Ergebnis der Prüfung ist nur für Warnmeldungen geeignet, da es im Laufe der Zeit 81 ## Veränderungen in der Liste der bekannten Module geben kann. 85 echo >&2
"The opennet module name '$module' is unknown - probably misspelled?" 86 echo >&2
"The following module names are known: $(get_on_modules | xargs echo)" 90 warn_if_not_installed_module() {
92 is_on_module_installed
"$module" &&
return 0
93 echo >&2
"The opennet module name '$module' is not installed - maybe you want to install it?" 97 ## @fn get_on_modules() 98 ## @brief Liefere die Namen aller bekannten Opennet-Module zeilenweise getrennt zurück. 99 ## @details Die Liste kann in der Datei ON_CORE_DEFAULTS_FILE angepasst werden. 101 # zeilenweise splitten (wir erwarten nur kleine Buchstaben und Zahlen im Namen) 102 get_on_core_default
"on_modules" | sed
's/[^a-z0-9-]/\n/g' | grep -v
"^$" ||
true 106 ## @fn get_not_installed_on_modules() 107 ## @brief Ermittle diejenigen Module, die aktuell nicht installiert sind. 111 is_package_installed
"$module" || echo
"$module" 116 ## @fn was_on_module_installed_before() 117 ## @brief Prüfe ob ein Modul "früher" (vor der letzten manuellen Änderung durch den Benutzer) installiert war. 118 ## @details Diese Prüfung ist hilfreich für die Auswahl von nachträglich zu installierenden Paketen. 122 trap
"" EXIT &&
return 1
126 ## @fn get_missing_modules() 127 ## @brief Collect the names of modules that were probably installed before the last upgrade. 132 is_package_installed
"$module" &&
continue 139 ## @fn install_from_opennet_repository() 140 ## @param packages Ein oder mehrere zu installierende Software-Pakete 141 ## @returns Eventuelle Fehlermeldungen werden auf die Standardausgabe geschrieben. Der Exitcode ist immer Null. 142 ## @brief Installiere ein Paket aus den Opennet-Repositories. 143 ## @details Für die Installation von Opennet-relevanten Paketen wird eine separate opkg.conf-Datei verwendet. 144 ## Alle nicht-opennet-relevanten Pakete sollten - wie gewohnt - aus den openwrt-Repositories heraus installiert 145 ## werden, da deren Paket-Liste umfassender ist. 146 ## Die opkg.conf wird im tmpfs erzeugt, falls sie noch nicht vorhanden ist. Eventuelle manuelle Nachkorrekturen 147 ## bleiben also bis zum nächsten Reboot erhalten. 149 trap
'error_trap install_from_opennet_repository "$*"' EXIT
151 local not_installed_packages
152 not_installed_packages=$(get_not_installed_on_modules)
153 run_opennet_opkg "update" && run_opennet_opkg "install" "$
@" 154 for package in "$
@"; do 155 if get_on_modules | grep -qwF "$package"; then
156 # Eventuell schlug die Installation fehl? 157 is_package_installed
"$package" ||
continue 158 # Falls es ein opennet-Modul ist, dann aktiviere es automatisch nach der Installation. 159 # Dies dürfte für den Nutzer am wenigsten überraschend sein. 160 # Wichtig: "enable" in einem neuen Skript-Kontext ausführen, damit sichergestellt ist, 161 # dass die "apply_changes"-Aktion mit den eventuell neuen Funktionen 162 # ausgeführt werden kann. 166 # wir wollen auch indirekt installierte Pakete aktivieren (z.B. on-openvpn via on-captive-portal) 167 for package in $not_installed_packages;
do 168 # unveraendert nicht installiert? Ignorieren ... 169 is_package_installed
"$package" ||
continue 172 # anschließend speichern wir den aktuellen Zustand, falls _alle_ Pakete installiert wurden 173 for package in "$
@"; do 174 # Paket fehlt? aktuelle Liste nicht speichern, sondern einfach abbrechen 175 is_package_installed "$package" || return 0
181 ## @fn remove_opennet_module()
182 ## @param module Name des oder der zu entfernenden Module
183 remove_opennet_modules() {
184 # "--force-remove" ist für on-monitoring notwendig, da sonst xinetd wegen einer Änderung
185 # /etc/xinet.d/munin nicht entfernt wird
186 run_opennet_opkg --autoremove --force-remove remove "$
@" 191 ## @fn redirect_to_opkg_opennet_logfile() 192 ## @brief Führe die gegebene Aktion aus und lenke ihre Ausgabe in die opennet-opkg-Logdatei um. 193 ## @details Als irrelevant bekannte Meldungen werden herausgefiltert. 194 redirect_to_opkg_opennet_logfile() { 196 log_file=$(get_custom_log_filename "opkg_opennet")
198 | grep -vE 'resolve_conffiles: Existing conffile /etc/config/(openvpn|olsrd2) is different from the conffile in the new package\. The new conffile will be placed at /etc/config/(openvpn|olsrd2)-opkg\.' \ 199 | grep -v '^Collected errors:$' >>"$log_file"
203 # Ausführung eines opkg-Kommnados mit der opennet-Repository-Konfiguration und minimaler Ausgabe (nur Fehler) auf stdout.
205 trap 'error_trap run_opennet_opkg "$*"' EXIT
206 # erzeuge Konfiguration, falls sie noch nicht vorhanden ist
207 [ -e "$ON_OPKG_CONF_PATH" ] || generate_opennet_opkg_config >"$ON_OPKG_CONF_PATH"
208 # Vor der opkg-Ausführung müssen wir das Verzeichnis /etc/opkg verdecken, da opkg fehlerhafterweise
209 # auch bei Verwendung von "--conf" die üblichen Orte nach Konfigurationsdateien durchsucht.
210 # TODO: opkg-Bug upstream berichten
211 mount -t tmpfs -o size=32k tmpfs /etc/opkg
212 # opkg ausfuehren und dabei die angegebene Fehlermeldung ignorieren (typisch fuer Paket-Installation nach Upgrade)
213 opkg --verbosity=1 --conf "$ON_OPKG_CONF_PATH" "$
@" || true 218 ## @fn save_on_modules_list() 219 ## @brief Speichere die aktuelle Liste der installierten opennet-Module in der uci-Konfiguration. 220 ## @details Nach einer Aktualisierung ermöglicht diese Sicherung die Nachinstallation fehlender Pakete. 221 save_on_modules_list() { 224 [ -z "$(uci_get "on-core.modules")" ] && uci set "on-core.modules=modules"
225 for modname in $(get_on_modules);
do 226 if is_package_installed
"$modname"; then
230 apply_changes on-core
234 ## @fn clear_cache_opennet_opkg() 235 ## @brief Lösche die eventuell vorhandene opennet-opkg-Konfiguration (z.B. nach einem Update). 236 clear_cache_opennet_opkg() {
237 rm -f
"$ON_OPKG_CONF_PATH" 241 ## @fn get_default_opennet_opkg_repository_base_url() 242 ## @brief Ermittle die automatisch ermittelte URL für die Nachinstallation von Paketen. 243 ## @returns Liefert die Basis-URL zurueck. Anzuhängen sind im Anschluss z.B. /packages/${arch_cpu_type} oder /targets/${arch}/generic/packages 244 get_default_opennet_opkg_repository_base_url() {
245 trap
'error_trap get_default_opennet_opkg_repository_base_url "$*"' EXIT
246 # ermittle die Firmware-Repository-URL 247 local firmware_version
248 firmware_version=$(get_on_firmware_version)
249 # leere Versionsnummer? Damit können wir nichts anfangen.
250 [ -z
"$firmware_version" ] &&
msg_error "Failed to retrieve opennet firmware version for opkg repository URL" &&
return 0
251 # snapshots erkennen wir aktuell daran, dass auch Buchstaben in der Versionsnummer vorkommen
253 if echo
"$firmware_version" | grep -q
"[a-zA-Z]"; then
254 # ein Buchstabe wurde entdeckt: unstable
255 version_path=
"testing/$firmware_version" 257 # kein Buchstabe wurde entdeckt: stable
258 # wir schneiden alles ab dem ersten Bindestrich ab
259 version_path=
"stable/$(echo "$firmware_version
" | cut -f 1 -d -)" 261 echo
"$ON_OPKG_REPOSITORY_URL_PREFIX/$version_path" 265 ## @fn get_configured_opennet_opkg_repository_base_url() 266 ## @brief Ermittle die aktuell konfigurierte Repository-URL. 267 get_configured_opennet_opkg_repository_base_url() {
270 url=$(uci_get
"on-core.modules.repository_url")
271 if [ -n
"$url" ]; then
274 get_default_opennet_opkg_repository_base_url
279 ## @fn set_configured_opennet_opkg_repository_url() 280 ## @param repo_url Die neue Repository-URL (bis einschliesslich "/packages"). 281 ## @brief Ändere die aktuell konfigurierte Repository-URL. 282 ## @details Die URL wird via uci gespeichert. Falls sie identisch mit der Standard-URL ist, wird die Einstellung gelöscht. 283 set_configured_opennet_opkg_repository_url() {
286 if [ -z
"$repo_url" ] || [
"$repo_url" =
"$(get_default_opennet_opkg_repository_base_url "opennet
")" ]; then
287 # Standard-Wert: loeschen 290 uci
set "on-core.modules.repository_url=$repo_url" 292 clear_cache_opennet_opkg
296 ## @fn generate_opennet_opkg_config() 297 ## @brief Liefere den Inhalt einer opkg.conf für das Opennet-Paket-Repository zurück. 298 ## @details Die aktuelle Version wird aus dem openwrt-Versionsstring gelesen. 299 generate_opennet_opkg_config() {
300 trap
'error_trap generate_opennet_opkg_config "$*"' EXIT
301 # schreibe den Inahlt der neuen OPKG-Konfiguration 304 echo
"lists_dir ext /var/opkg-lists-opennet" 305 echo
"option overlay_root /overlay" 309 base_url=$(get_configured_opennet_opkg_repository_base_url)
311 # Füge non-core package hinzu (z.B. feeds routing,opennet,luci,...)
312 # Hole Architektur und CPU Type 314 arch_cpu_type=$(opkg status base-files | awk
'/Architecture/ {print $2}')
315 local noncore_pkgs_url=
"$base_url/packages/$arch_cpu_type" 318 for feed in base packages routing luci opennet;
do 319 echo
"src/gz on_$feed $noncore_pkgs_url/$feed" 322 # Fuege zusaetzlich eine URL mit core packages hinzu (beinhaltet Kernel Module). 324 # shellcheck source=openwrt/package/base-files/files/etc/openwrt_release 325 arch_path=$(. /etc/openwrt_release; echo
"$DISTRIB_TARGET")
326 local core_pkgs_url=
"$base_url/targets/$arch_path/packages" 327 echo
"src/gz on_core $core_pkgs_url" 331 ## @fn is_package_installed()
332 ## @brief Prüfe, ob ein opkg-Paket installiert ist. 333 ## @param package Name des Pakets 334 is_package_installed() {
335 trap
'error_trap is_package_installed "$*"' EXIT
338 # Korrekte Prüfung: via "opkg list-installed" - leider erzeugt sie locking-Fehlermeldung 339 # bei parallelen Abläufen (z.B. Status-Seite). 340 #opkg list-installed | grep -q -w "^$package" && return 0 341 # schneller als via opkg 342 status=$(grep -A 10
"^Package: $package$" "${IPKG_INSTROOT:-}/usr/lib/opkg/status" \
343 | grep
"^Status:" | head -1 | cut -f 2- -
d :)
344 [ -z
"$status" ] && trap
"" EXIT &&
return 1
345 echo
"$status" | grep -qE
"(deinstall|not-installed)" && trap
"" EXIT &&
return 1
350 ## @fn on_opkg_postinst_default()
351 ## @brief Übliche Nachbereitung einer on-Paket-Installation. 352 ## @details Caches löschen, uci-defaults anwenden, on-core-Bootskript ausführen 353 on_opkg_postinst_default() {
354 # Reset des Luci-Cache und Shell-Cache 356 # Paket-Initialisierungen durchfuehren, falls wir in einem echten System sind. 357 # In der Paket-Bau-Phase funktioniert die untenstehende Aktion nicht, da eine 358 # Datei fehlt, die in der /etc/init.d/boot geladen wird. 359 if [ -z
"${IPKG_INSTROOT:-}" ]; then
360 msg_info "Applying uci-defaults after package installation" 361 # Die Angabe von IPKG_INSTROOT ist hier muessig - aber vielleicht 362 # koennen wir die obige Bedingung irgendwann entfernen. 364 # der Rest sollte ohne Vorsicht stattfinden 366 # shellcheck source=openwrt/package/base-files/files/etc/init.d/boot 367 .
"${IPKG_INSTROOT:-}/etc/init.d/boot" 369 # Boot-Skript aktivieren und ausführen (falls noch nicht geschehen) 370 /etc/init.d/on-core enable 2>/dev/
null ||
true 371 /etc/init.d/on-core start
379 ## @fn on_opkg_postrm_default()
380 ## @brief Übliche Nachbereitung einer on-Paket-Entfernung 381 ## @details Caches löschen 382 on_opkg_postrm_default() {
387 # Ende der Doku-Gruppe get_on_modules()
Liefere die Namen aller bekannten Opennet-Module zeilenweise getrennt zurück.
uci_delete(uci_path)
Lösche ein UCI-Element.
uci_is_in_list(uci_path, item)
Prüfe ob ein Element in einer Liste vorkommt.
enable_on_module(module)
Aktiviere ein Opennet-Modul.
disable_on_module(module)
Deaktiviere ein Opennet-Modul.
uci_add_list(uci_path, new_item)
Füge einen neuen Wert zu einer UCI-Liste hinzu und achte dabei auf Einmaligkeit.
uci_replace_list()
Replace the items in a list. Wanted items are expected via stdin (one per line, uci_path).
get_missing_modules()
Collect the names of modules that were probably installed before the last upgrade.
set eu grep root::etc shadow exit if command v chpasswd dev null
msg_info(message)
Informationen und Fehlermeldungen ins syslog schreiben.
uci_delete_list(uci_path, value)
Lösche ein Element einer UCI-Liste.
get_not_installed_on_modules()
Ermittle diejenigen Module, die aktuell nicht installiert sind.
warn_if_unknown_module()
Gib eine Warnung aus, falls der angegebene Modul-Name unbekannt ist.
set eu on function print_services services log for dir in etc on services d var on services volatile d
msg_error(message)
Die Fehlermeldungen werden in die Standard-Fehlerausgabe und ins syslog geschrieben.
is_on_module_installed_and_enabled(module)
Pruefe ob ein Modul sowohl installiert, als auch aktiv ist.
was_on_module_installed_before()
Prüfe ob ein Modul "früher" (vor der letzten manuellen Änderung durch den Benutzer) installiert war...
clean_luci_restart()
Starte den Webserver neu und lösche alle luci-Cache-Dateien und Kompilate.
install_from_opennet_repository(packages)
Installiere ein Paket aus den Opennet-Repositories.