diff --git a/distribution/debian/postinst b/distribution/debian/postinst index 80b212e8f..e12d78b92 100644 --- a/distribution/debian/postinst +++ b/distribution/debian/postinst @@ -95,7 +95,7 @@ chown -R $USER:$GROUP /usr/lib/sonarr sed -i "s:User=sonarr:User=$USER:g; s:Group=sonarr:Group=$GROUP:g; s:-data=/var/lib/sonarr:-data=$CONFDIR:g" /lib/systemd/system/sonarr.service #BEGIN BUILTIN UPDATER -if [ $1 = "upgrade" ] && [ "$UPDATER" = "BuiltIn" ]; then +if [ "$UPDATER" = "BuiltIn" ]; then # If we upgraded, signal Sonarr to do an update check on startup instead of scheduled. touch $CONFDIR/update_required chown $USER:$GROUP $CONFDIR/update_required diff --git a/src/NzbDrone.Core/Lifecycle/ApplicationStartingEvent.cs b/src/NzbDrone.Core/Lifecycle/ApplicationStartingEvent.cs new file mode 100644 index 000000000..99aa40422 --- /dev/null +++ b/src/NzbDrone.Core/Lifecycle/ApplicationStartingEvent.cs @@ -0,0 +1,9 @@ +using NzbDrone.Common.Messaging; + +namespace NzbDrone.Core.Lifecycle +{ + public class ApplicationStartingEvent : IEvent + { + + } +} diff --git a/src/NzbDrone.Core/Update/InstallUpdateService.cs b/src/NzbDrone.Core/Update/InstallUpdateService.cs index a57a7eb8a..19c28a6ab 100644 --- a/src/NzbDrone.Core/Update/InstallUpdateService.cs +++ b/src/NzbDrone.Core/Update/InstallUpdateService.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; +using System.Threading; using NLog; using NzbDrone.Common; using NzbDrone.Common.Disk; @@ -11,12 +13,14 @@ using NzbDrone.Common.Instrumentation.Extensions; using NzbDrone.Common.Processes; using NzbDrone.Core.Backup; using NzbDrone.Core.Configuration; +using NzbDrone.Core.Lifecycle; using NzbDrone.Core.Messaging.Commands; +using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Update.Commands; namespace NzbDrone.Core.Update { - public class InstallUpdateService : IExecute + public class InstallUpdateService : IExecute, IHandle { private readonly ICheckUpdateService _checkUpdateService; private readonly Logger _logger; @@ -70,7 +74,7 @@ namespace NzbDrone.Core.Update _logger = logger; } - private void InstallUpdate(UpdatePackage updatePackage) + private bool InstallUpdate(UpdatePackage updatePackage) { EnsureAppDataSafety(); @@ -93,7 +97,7 @@ namespace NzbDrone.Core.Update if (_appFolderInfo.StartUpFolder.EndsWith("_output")) { _logger.ProgressDebug("Running in developer environment, not updating."); - return; + return false; } var updateSandboxFolder = _appFolderInfo.GetUpdateSandboxFolder(); @@ -131,7 +135,7 @@ namespace NzbDrone.Core.Update if (OsInfo.IsNotWindows && _configFileProvider.UpdateMechanism == UpdateMechanism.Script) { InstallUpdateWithScript(updateSandboxFolder); - return; + return true; } _logger.Info("Preparing client"); @@ -141,6 +145,8 @@ namespace NzbDrone.Core.Update _logger.ProgressInfo("Sonarr will restart shortly."); _processProvider.Start(_appFolderInfo.GetUpdateClientExePath(), GetUpdaterArgs(updateSandboxFolder)); + + return true; } private void EnsureValidBranch(UpdatePackage package) @@ -252,5 +258,65 @@ namespace NzbDrone.Core.Update throw new CommandFailedException(ex); } } + + public void Handle(ApplicationStartingEvent message) + { + // Check if we have to do an application update on startup + + try + { + // Don't do a prestartup update check unless BuiltIn update is enabled + if (_configFileProvider.UpdateAutomatically || + _configFileProvider.UpdateMechanism != UpdateMechanism.BuiltIn || + _deploymentInfoProvider.IsExternalUpdateMechanism) + { + return; + } + + var updateMarker = Path.Combine(_appFolderInfo.AppDataFolder, "update_required"); + if (!_diskProvider.FileExists(updateMarker)) + { + return; + } + + _logger.Debug("Post-install update check requested"); + + var latestAvailable = _checkUpdateService.AvailableUpdate(); + if (latestAvailable == null) + { + _logger.Debug("No post-install update available"); + _diskProvider.DeleteFile(updateMarker); + return; + } + + + _logger.Info("Installing post-install update from {0} to {1}", BuildInfo.Version, latestAvailable.Version); + _diskProvider.DeleteFile(updateMarker); + + var installing = InstallUpdate(latestAvailable); + + if (installing) + { + _logger.Debug("Install in progress, giving installer 30 seconds."); + + var watch = Stopwatch.StartNew(); + + while (watch.Elapsed < TimeSpan.FromSeconds(30)) + { + Thread.Sleep(1000); + } + + _logger.Error("Post-install update not completed within 30 seconds. Attempting to continue normal operation."); + } + else + { + _logger.Debug("Post-install update cancelled for unknown reason. Attempting to continue normal operation."); + } + } + catch (Exception ex) + { + _logger.Error(ex, "Failed to perform the post-install update check. Attempting to continue normal operation."); + } + } } } diff --git a/src/NzbDrone.Host/ApplicationServer.cs b/src/NzbDrone.Host/ApplicationServer.cs index fbd0f1480..c904a637f 100644 --- a/src/NzbDrone.Host/ApplicationServer.cs +++ b/src/NzbDrone.Host/ApplicationServer.cs @@ -58,6 +58,14 @@ namespace NzbDrone.Host _runtimeInfo.IsExiting = false; DbFactory.RegisterDatabase(_container); + + _container.Resolve().PublishEvent(new ApplicationStartingEvent()); + + if (_runtimeInfo.IsExiting) + { + return; + } + _hostController.StartServer(); if (!_startupContext.Flags.Contains(StartupContext.NO_BROWSER)