Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

redesign installer logs #4539

Merged
merged 52 commits into from
Apr 11, 2021
Merged

Conversation

hgy59
Copy link
Contributor

@hgy59 hgy59 commented Apr 2, 2021

Motivation: Installation scripts using >> ${INST_LOG} do not work with DSM7
Linked issues: #4524, #4494, #4527, #4537, #4545, #4153

Checklist

Documentation that needs update:

Remarks

It is time to redesign the package installation logs, as appending output with >> ${INST_LOG} is not supported with DSM7.
In DSM7 write access to the new DSM installation log file /var/log/packages/{package-name.log} is not allowed.
With DSM7 all stderr output during installation is written to the logfile by the system and output to stdout is presented in a modal dialog to notify the user.

The purpose of this PR is to realize installation logging independently on the DSM version.

Finally the new function install_log is used internally by the generic installer only.
For all packages with custom installer functions (service_*) the only change is to remove the output redirections >> ${INST_LOG} and >> ${INST_LOG} 2>&1.
All output in the package specific installer functions will be written to the DSM dependent installer log file.

Packages that use exit 1 and/or user notifications in the installation process by writing to stdout, must use the new validate-functions to do so. User notification is not supported for DSM < 6.

The new validate functions are:

  • validate_preinst
  • validate_preunint
  • validate_preupgrade

The benefit of negative validation (exit1) is, that the user can navigate in the wizard to fix the installation parameters and try again. This might be mysql administration password, shared folder that must exist, etc.

For the rare case a package needs to download or install code before the validation, a validate function must be used and the install_log function can be used there for regular installation logs.

Installer log file

The install log with INST_LOG was introduced for pre DSM 6 packages, where DSM system did not create log file for package installation scripts.
Finally the /var/log/packages/{package-name}.log is not new for DSM7 but is provided since DSM6. So this PR modifies all DSM6 packages to use the /var/log/packages/{package-name}.log and do not create /var/package/{package-name}/target/var/{package-name}_install.log anymore.
The standard for installer log is now /var/log/packages/{package-name}.log.
Only for DSM < 6 the /var/package/{package-name}/target/var/{package-name}_install.log is still in use.

Affected Packages

most of the Comments below are for building arch-x64-7.0

✔️: validation of installer log fixed for DSM7
✔️✔️: validation of installer log fixed for DSM7 and DSM6

fixed:

  • remove >> ${INST_LOG}
  • firewall rules for DSM7 (@publicarray)
  • replace /usr/local/{package-name}by /var/packages/{package-name}/target

not fixed in this PR:

  • remove busybox and deprecated user management at installation (DSM 5 to DSM 6 migration is not supported anymore!)
  • not all packages use the new var folder with DSM7, some use it only for log and pid of service)
  • package warnings like has not been updated to DSM7 yet as function ... is no longer supported.
  • SERVICE_WIZARD_SHARE implementation needs update vor DSM7
Package WIP Comment
✔️✔️ beets noarch
✔️✔️ borgbackup
✔️✔️ couchpotatoserver noarch
✔️✔️ couchpotatoserver-custom noarch
✔️✔️ deluge #4153 compile error: expected primary-expression before ‘float’
✔️✔️ demoservice noarch, created link to @installer.log does not work on DSM6, but works on DSM7
✔️✔️ dnscrypt-proxy not installable, requires root permissions, DSM6 has logs about missing localized string for several languages
✔️✔️ fish #4494 fails to compile for DSM7, error: ‘__builtin_isnan’ is not a member of ‘std’
✔️✔️ fishnet no wizard to enter fishnet_key
✔️✔️ flexget service log has all entries doubled
✔️✔️ gateone service log has all entries doubled, DSM7: certificate cannot be installed, start fails
✔️✔️ headphones noarch
✔️✔️ headphones-custom noarch
✔️✔️ homeassistant
✔️✔️ itools not installable, requires root permissions, depends on python module
✔️✔️ lazylibrarian noarch
✔️✔️ lidarr
✔️✔️ minio DSM7: migrate SERVICE_EXE (start-stop-daemon) to SERVICE_COMMAND
✔️✔️ mono
✔️✔️ mosquitto mosquitto.conf and *.pid in wrong var folder
✔️✔️ mutt
✔️✔️ mylar datadir in wrong var folder, fails to start on DSM6
✔️✔️ nzbget with multistage validation and and print logfile name to stdout, must not use su anymore
✔️✔️ nzbget-testing with multistage validation and print logfile name to stdout, must not use su anymore, package is obsolete, as stable / testing (beta) is provided by the wizard of nzbget package
✔️✔️ nzbhydra noarch
✔️✔️ plexpy-custom noarch
✔️ pyload
✔️✔️ python3
✔️✔️ python38
✔️✔️ rabbitmq
✔️✔️ radarr dsm7-packages
✔️✔️ rdiff-backup usr/local links do not work
✔️✔️ rsnapshot noarch, configure: error: rsync not found (DSM 6 and 7)
✔️✔️ rutorrent libtorrent: error: ‘__builtin_isnan’ is not a member of ‘std’
✔️✔️ sabnzbd #4537 installation fails, /var/log/messages: failed to alloc share, failed to get defualt status for share, failed to create share, failed to acquire resource after install
✔️✔️ salt-minion installation stays installing...
✔️✔️ sickbeard-custom noarch
✔️✔️ sickrage noarch, fails to install: missing apispec==4.0.0
✔️✔️ sonarr (nzbdrone)
✔️✔️ stockfish web app must not access /var/services/web/{package-name}
✔️✔️ syncthing #4527 DSM7: migrate SERVICE_EXE (start-stop-daemon) to SERVICE_COMMAND
✔️✔️ synocli-monitor
✔️✔️ transmission dsm7-packages installation fails, /var/log/messages: failed to alloc share, failed to get defualt status for share, failed to create share, failed to acquire resource after install
✔️✔️ tvheadend #4545, dsm7-packages configure ERROR: ffmpeg development support not found, ffmpeg: error: ‘__builtin_isnan’ is not a member of ‘std’
✔️✔️ umurmur certificate generation failed, /var/packages/umurmur/target/openssl.cnf is missing

Copy link
Member

@publicarray publicarray left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! It was on my low priority todo list 👍

With DSM7 all stdout during installation is written to the logfile by the system and output to stderror is presented to the user in a modal dialog.

From my testing it's the other way around. stderr is logged and stdout is presented to the user.

1>&2 redirects stdout to stderr

mk/spksrc.service.installer Outdated Show resolved Hide resolved
mkdir -p "$(dirname /usr/local/${cmd})" >> "${INST_LOG}" 2>&1
echo "create link: /usr/local/${cmd} -> ${SYNOPKG_PKGDEST}/${cmd}" >> "${INST_LOG}"
ln -s "${SYNOPKG_PKGDEST}/${cmd}" "/usr/local/${cmd}" >> "${INST_LOG}" 2>&1
mkdir -p "$(dirname /usr/local/${cmd})" 2>&1 | install_log
Copy link
Member

@publicarray publicarray Apr 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we remove the duplicate redirections everywhere? (your function would need to read both stdin and stderr but makes it clearer everywhere else)

Suggested change
mkdir -p "$(dirname /usr/local/${cmd})" 2>&1 | install_log
mkdir -p "$(dirname /usr/local/${cmd})" | install_log

EDIT: Unfortunately It might not be possible, unless we forgo the date prefix string and just let the command print to stderr directly. The reason I think I almost prefer this as it simplifies a lot of code. I can imagine a scenario where most of the log commands are not needed.

Maybe we can use install_log to encapsulate all package scripts but allow a switch or function to disable it in case a package wants to notify the user. IMHO logs should always be written and not something a package author should worry about. At the moment packages have various syles/standards of logging. If a package needs to ignore logs for some reason they can still redirect to /dev/null

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can use install_log to encapsulate all package scripts but allow a switch or function to disable it in case a package wants to notify the user. IMHO logs should always be written and not something a package author should worry about.

I like the idea to always write to the installer log file and it is easy to implement.
But I did not find any solution on how to disable this and write to stdout while all output is captured for the installer log (I tried to collect notification output in a global variable or to use file descriptor 3 - nothing worked).

The only solution I can imagine for user notification (i.e. writing to stdout) is to implement additional service functions that are not redirected to the installer log like validate_preinst or validate_preupgrade and that must be used for such validations.
This would work at least for validation of wizard variables, but not for complex installers that have multiple installation steps with extra validation (if we have any).
The real benefit of user notification is for preinst, preuninst and preupgrade anyway, as the user can navigate back in the wizard and fix the configuration before starting the installation/uninstallation.
Further a validate_postinst could notify when additional manual configuration might be required.

@hgy59
Copy link
Contributor Author

hgy59 commented Apr 3, 2021

Nice work! It was on my low priority todo list

And for me it is on the high priority list, as a couple of packages fail to install (ambigous redirect) when I tried to build and install all packages for arch-x64-7.0 (see #4524)
This is high priority for packages that others depend on (python2, python3, python38, and maybe mono).

@publicarray
Copy link
Member

Oh, I don't remember single package to fail with that error. Thanks for fixing it. Before my NAS died, I had my own compiled python3 and mono installed.

@th0ma7
Copy link
Contributor

th0ma7 commented Apr 4, 2021

This is good work indeed.
Is the intent to also adapt all src/service-setup.sh scripts as well right away to migrate them to the new logging facility?

And, out of curiosity, I wonder if it could be possible to alter default syslog configuration through a generic default synocommunity.spk to add a new logging facility channel to redirect synoCommunity package logs to our own log files, thus having the ability to capture the stderr?

Just a thought.

@hgy59
Copy link
Contributor Author

hgy59 commented Apr 4, 2021

Is the intent to also adapt all src/service-setup.sh scripts as well right away to migrate them to the new logging facility?

Yes, this is my intention to update all packages, in spite of those that are WIP on branches (or - maybe it is better not to touch such packages and advise the maintainers after this one is merged).

@th0ma7 regarding sc specific syslog configuration I propose to work on a different branch. After my redesign here there will be no need to modify each package for such a feature....

@publicarray
Copy link
Member

Unfortunately using the | pipe or call_func negates the exit status. I can't find a way to manually exit on an error.

service_preinst ()
{
    echo "****************"
    exit 1
}

I tried to grab it and pass it on with local _exit_code_="$?" local _exit_code_="${PIPESTATUS[0]}" but no success so far

@hgy59
Copy link
Contributor Author

hgy59 commented Apr 5, 2021

Unfortunately using the | pipe or call_func negates the exit status. I can't find a way to manually exit on an error.

service_preinst ()
{
    echo "****************"
    exit 1
}

I tried to grab it and pass it on with local _exit_code_="$?" local _exit_code_="${PIPESTATUS[0]}" but no success so far

This works with the provided validate_ functions:

validate_preinst ()
{
    echo "****************"
    exit 1
}

So far I only found one package with user notifications that cannot be easyly migrated to validate-functions (nzbget/nzbget-testing).
Others can use this validation straight forward (headphones/headphones-custom, transmission, ...)

@publicarray
Copy link
Member

publicarray commented Apr 5, 2021

Sorry my point is that if a command fails then the script will continue to run instead of exiting.

@hgy59
Copy link
Contributor Author

hgy59 commented Apr 5, 2021

Sorry my point is that if a command fails then the script will continue to run instead of exiting.

IMHO this was always the case. You must use exit to break a function.
If you want to exit with user notification, you must now implement a validate-function.

@publicarray
Copy link
Member

@hgy59 It seems you are right. I just found it surprising that exit 1 no longer stops the installation in the service functions.

@hgy59 hgy59 added this to To do in DSM 7 Support via automation Apr 5, 2021
@hgy59 hgy59 moved this from To do to In progress in DSM 7 Support Apr 5, 2021
@th0ma7
Copy link
Contributor

th0ma7 commented Apr 6, 2021

@th0ma7 regarding sc specific syslog configuration I propose to work on a different branch. After my redesign here there will be no need to modify each package for such a feature....

Page 115 of the dev guide, part of the resource list there are hooks available to add syslog-ng configurations. Definitively something worth investigating (but my cycles are rather limited currently)

@publicarray
Copy link
Member

publicarray commented Apr 6, 2021

INST_VAR is only used in 4 packages, so I'm also happy to remove it 👍

$ rg -g '**/*.sh' INST_VAR -l
spk/minio/src/service-setup.sh
spk/minio/src/wizard/upgrade_uifile.sh
spk/sonarr/src/service-setup.sh
spk/lidarr/src/service-setup.sh
spk/lidarr/src/service-setup-mono.sh
spk/radarr/src/service-setup.sh

I noticed another oversight on my part, the firewall rules on the DSM7 are also defined in the resource file. I'll happily send a PR
once the 2 current ones are merged.

spk.service.mk

+ ifeq ($(strip $(FWPORTS)),)
+ 	@jq '."port-config"."protocol-file" = "$(SPK_NAME)"' $@ 1<>$@
+ endif

spk.service.installer.dsm7

- # Add firewall config
-  if [ -r "${FWPORTS_FILE}" ]; then
-        install_log "Installing service configuration ${FWPORTS_FILE}"
-        servicetool --install-configure-file --package "${FWPORTS_FILE}" 2>&1 | install_log
-  fi

- # Remove firewall config
- if [ -r "${FWPORTS_FILE}" ]; then
-        install_log "Removing service configuration ${SYNOPKG_PKGNAME}.sc"
-        servicetool --remove-configure-file --package "${SYNOPKG_PKGNAME}.sc" 2>&1 | install_log
- fi

@hgy59
Copy link
Contributor Author

hgy59 commented Apr 6, 2021

I noticed another oversight on my part, the firewall rules on the DSM7 are also defined in the resource file. I'll happily send a PR
once the 2 current ones are merged.

Yes, I noticed install errors like
install configue file fail! (/var/packages/rabbitmq/conf/rabbitmq.sc)

So shall I commit all the package fixes and then we merge it - or can I cherry pick the DSM7 firwall rules fix somewhere?

For now I am holding back, as I have to test the installation of 61 packages (12 noarch/49 arch specific) on DSM 7 and DSM 6.1 and evtl. DSM 5.2.

@hgy59
Copy link
Contributor Author

hgy59 commented Apr 6, 2021

$ rg -g '**/*.sh' INST_VAR -l
spk/minio/src/service-setup.sh
spk/minio/src/wizard/upgrade_uifile.sh
spk/sonarr/src/service-setup.sh
spk/lidarr/src/service-setup.sh
spk/lidarr/src/service-setup-mono.sh
spk/radarr/src/service-setup.sh

A search for INST_VAR as whole word omits minio, as it contains INST_VARIABLES and not INST_VAR.
$ rg -g '**/*.sh' INST_VAR -lw

@publicarray
Copy link
Member

publicarray commented Apr 6, 2021

The firewall rule is a bit more complicated than I thought. Using the resource worker it expects the firewall file to reside in /var/package/{$package}/target/ so I've moved it to /var/packages/${SYNOPKG_PKGNAME}/target/app/${SYNOPKG_PKGNAME}.sc feel free to change it. I've tested the SERVICE_PORT option but have not tested the FWPORTS option yet.

port

@publicarray
Copy link
Member

publicarray commented Apr 7, 2021

Sorry I had these changes locally and missed pushing them earlier.

@@ -196,10 +196,16 @@ ifeq ($(call version_ge, ${TCVERSION}, 7.0),1)
$(DSM_SCRIPTS_DIR)/installer: $(SPKSRC_MK)spksrc.service.installer.dsm7
@$(dsm_script_copy)
else
ifeq ($(call version_lt, ${TCVERSION}, 6.0),1)
Copy link
Member

@publicarray publicarray Apr 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this could be written more consistently e.g. as greater than or equal to 7.0; dsm7 stuff, else greater than or equal to 6.0; dsm6 stuff else dsm5 stuff. Or the reverse. Nice work otherwise 👍 on separating the dns5 stuff.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@publicarray i have a question regarding your comment in the servive.mk for DSM7
# STARTABLE needs to be yes, Resource linking and unlinking works on start and stop

I wanted to fix this, as only SPK_COMMANDS was tested here and SPK_USR_LOCAL_LINKS was ignored.
But my findings are, that it is not needed to omit ctl_stop=no (i.e. use default ctl_stop=yes) for resource linker to work.
The packages with ctl_stop=no are started by the system at installation time (and on every restart) and are stopped at uninstall.
This would simplify the code as it will depend on DSM >= 6.1 only to use ctl_stop=no or startable=no.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@publicarray the implementation of ctl_stop=no is in spksrc.spk.mk and not in spksrc.service.mk but your comment is in both.

Copy link
Member

@publicarray publicarray Apr 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the optimisation. The downside is that most CLI apps have STARTABLE=no set. I just tested it again and CLI packages (I use zsh for testing) that have ctl_stop=no will still work but the start/stop button is obviously missing. IMHO we should override and remove the ctl_stop=no if SPK_COMMANDS is set. SPK_USR_LOCAL_LINKS doesn't guarantee an executable but yes it probably should also apply then.
Since this is a minor issue we can just ignore it for now.

spksrc on  redesign_install_log [📦📝🤷‍] 
❯ rg -g '**/*Makefile' --pcre2 -U --multiline-dotall '(?=.*STARTABLE = no)(?=.*SPK_COMMANDS)' -l | wc
     61      61    1329

Thanks SO: https://stackoverflow.com/questions/469913/regular-expressions-is-there-an-and-operator

@hgy59
Copy link
Contributor Author

hgy59 commented Apr 10, 2021

@publicarray now I still only problems with demoservice on DSM7.
The installation log does not show any error (or ret != 0) but package fails to install. Only /var/log/message shows the following error (json formatted for better reading).

Failed to install package, pkg=[demoservice] 
result = [{
        "action": "install",
        "beta": false,
        "betaIncoming": false,
        "error": {
            "code": 276,
            "description": "failed to acquire postinst worker",
            "worker_msg": []
        },
        "finished": true,
        "installReboot": false,
        "installing": true,
        "language": "ger",
        "last_stage": "postreplace",
        "package": "demoservice",
        "packageName": "DemoService",
        "pid": 18788,
        "scripts": [{
                "code": 0,
                "message": "",
                "type": "preinst"
            }, {
                "code": 0,
                "message": "",
                "type": "postinst"
            }
        ],
        "spk": "/volume1/@tmp/upload_tmp.180930",
        "stage": "install_failed",
        "status": "stop",
        "success": false,
        "username": "xxxxxxxx"
    }
]

Did you ever get the error "failed to acquire postinst worker" ?

EDIT:
just found the reason for this error:
SERVICE_WIZARD_SHARE is not supported for DSM7 yet and produces the error above.

@hgy59
Copy link
Contributor Author

hgy59 commented Apr 10, 2021

I have added a note for packages using SERVICE_WIZARD_SHARE in #4524.
@publicarray: as transmission uses this, you might have solved this in the dsm7-packages branch?

hgy59 and others added 11 commits April 12, 2021 00:07
- use validate_preinst
- avoid use of /usr/local/{package-name}
- make wget less verbose to avoid download progress in log file
- dsm5: rename INST_LOG to INST_LOG_TEMP for unified INST_LOG
@hgy59 hgy59 merged commit 0eaccc5 into SynoCommunity:master Apr 11, 2021
DSM 7 Support automation moved this from In progress to Done Apr 11, 2021
hgy59 added a commit that referenced this pull request Apr 11, 2021
update for redesign of installer log (#4539)
@hgy59
Copy link
Contributor Author

hgy59 commented Apr 11, 2021

@publicarray there is now some rework on the dsm7-packages branch required.

for radarr in service-setup.sh in the function service_preupgrade:

  • replace INST_VAR by SYNOPKG_PKGVAR
  • remove >> ${INSTLOG}

TODO for transmission in service-setup.sh

  • rename service_preinst to validate_preinst
  • the >> ${INST_LOG} have to be removed (service_postint)
  • and for DSM7 compatibility use: PYTHON_DIR="/var/packages/python/target"

I think by #4545 that tvheadend is outdated on the dsm7-packages branch (I posted a note in #4545).

hgy59 added a commit that referenced this pull request Apr 11, 2021
@hgy59 hgy59 mentioned this pull request Apr 11, 2021
3 tasks
@hgy59 hgy59 deleted the redesign_install_log branch April 13, 2021 15:41
hgy59 added a commit to hgy59/spksrc that referenced this pull request Apr 14, 2021
- revert overwriting files in ${SYNOPKG_PKGVAR} folder from target/var (introduced with SynoCommunity#4539)
@hgy59 hgy59 mentioned this pull request Apr 14, 2021
3 tasks
hgy59 added a commit that referenced this pull request Apr 14, 2021
* DSM7: revert var overwrite
- revert overwriting files in ${SYNOPKG_PKGVAR} folder from target/var (introduced with #4539)
@hgy59 hgy59 mentioned this pull request Apr 25, 2021
3 tasks
hgy59 added a commit to hgy59/spksrc that referenced this pull request May 2, 2021
- use different privilege files for DSM 7 and DSM < 7
- adjust installer logs (SynoCommunity#4539)
- link ejabberdctl to target/bin
hgy59 added a commit that referenced this pull request May 2, 2021
* update ejabberd
- update ejabberd to 21.01
- prepare for generic service setup
- activate install wizard
* fix ejabberd service configuration and startup
* fix SPK_COMMANDS
* adjust ejabberd for DSM7
- use different privilege files for DSM 7 and DSM < 7
- adjust installer logs (#4539)
- link ejabberdctl to target/bin
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
DSM 7 Support
  
Done
Development

Successfully merging this pull request may close these issues.

None yet

3 participants