diff --git a/src/NzbDrone.Api/System/SystemModule.cs b/src/NzbDrone.Api/System/SystemModule.cs index b56f1d14b..e951a8da0 100644 --- a/src/NzbDrone.Api/System/SystemModule.cs +++ b/src/NzbDrone.Api/System/SystemModule.cs @@ -5,6 +5,8 @@ using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Core.Configuration; using NzbDrone.Core.Datastore; +using NzbDrone.Core.Lifecycle; +using NzbDrone.Core.Lifecycle.Commands; namespace NzbDrone.Api.System { @@ -15,12 +17,14 @@ public class SystemModule : NzbDroneApiModule private readonly IRouteCacheProvider _routeCacheProvider; private readonly IConfigFileProvider _configFileProvider; private readonly IDatabase _database; + private readonly ILifecycleService _lifecycleService; public SystemModule(IAppFolderInfo appFolderInfo, IRuntimeInfo runtimeInfo, IRouteCacheProvider routeCacheProvider, IConfigFileProvider configFileProvider, - IDatabase database) + IDatabase database, + ILifecycleService lifecycleService) : base("system") { _appFolderInfo = appFolderInfo; @@ -28,8 +32,11 @@ public SystemModule(IAppFolderInfo appFolderInfo, _routeCacheProvider = routeCacheProvider; _configFileProvider = configFileProvider; _database = database; + _lifecycleService = lifecycleService; Get["/status"] = x => GetStatus(); Get["/routes"] = x => GetRoutes(); + Post["/shutdown"] = x => Shutdown(); + Post["/restart"] = x => Restart(); } private Response GetStatus() @@ -62,5 +69,18 @@ private Response GetRoutes() { return _routeCacheProvider.GetCache().Values.AsResponse(); } + + private Response Shutdown() + { + _lifecycleService.Shutdown(); + return "".AsResponse(); + } + + private Response Restart() + { + _lifecycleService.Restart(); + return "".AsResponse(); + } } } + \ No newline at end of file diff --git a/src/NzbDrone.Core/Lifecycle/LifecycleService.cs b/src/NzbDrone.Core/Lifecycle/LifecycleService.cs index df5c017b1..9fb5c4b32 100644 --- a/src/NzbDrone.Core/Lifecycle/LifecycleService.cs +++ b/src/NzbDrone.Core/Lifecycle/LifecycleService.cs @@ -1,4 +1,5 @@ -using NLog; +using System; +using NLog; using NzbDrone.Common; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Processes; @@ -9,40 +10,43 @@ namespace NzbDrone.Core.Lifecycle { - public class LifecycleService: IExecute, IExecute + public interface ILifecycleService + { + void Shutdown(); + void Restart(); + } + + public class LifecycleService : ILifecycleService, IExecute, IExecute { private readonly IEventAggregator _eventAggregator; private readonly IRuntimeInfo _runtimeInfo; private readonly IServiceProvider _serviceProvider; - private readonly IProcessProvider _processProvider; private readonly Logger _logger; public LifecycleService(IEventAggregator eventAggregator, IRuntimeInfo runtimeInfo, IServiceProvider serviceProvider, - IProcessProvider processProvider, Logger logger) { _eventAggregator = eventAggregator; _runtimeInfo = runtimeInfo; _serviceProvider = serviceProvider; - _processProvider = processProvider; _logger = logger; } - public void Execute(ShutdownCommand message) + public void Shutdown() { _logger.Info("Shutdown requested."); _eventAggregator.PublishEvent(new ApplicationShutdownRequested()); - + if (_runtimeInfo.IsWindowsService) { _serviceProvider.Stop(ServiceProvider.NZBDRONE_SERVICE_NAME); } } - public void Execute(RestartCommand message) + public void Restart() { _logger.Info("Restart requested."); @@ -53,5 +57,15 @@ public void Execute(RestartCommand message) _serviceProvider.Restart(ServiceProvider.NZBDRONE_SERVICE_NAME); } } + + public void Execute(ShutdownCommand message) + { + Shutdown(); + } + + public void Execute(RestartCommand message) + { + Restart(); + } } } diff --git a/src/NzbDrone/SysTray/SysTrayApp.cs b/src/NzbDrone/SysTray/SysTrayApp.cs index 730ea346f..2b730e180 100644 --- a/src/NzbDrone/SysTray/SysTrayApp.cs +++ b/src/NzbDrone/SysTray/SysTrayApp.cs @@ -2,6 +2,7 @@ using System.ComponentModel; using System.Windows.Forms; using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Processes; using NzbDrone.Host; namespace NzbDrone.SysTray @@ -14,13 +15,17 @@ public interface ISystemTrayApp public class SystemTrayApp : Form, ISystemTrayApp { private readonly IBrowserService _browserService; + private readonly IRuntimeInfo _runtimeInfo; + private readonly IProcessProvider _processProvider; private readonly NotifyIcon _trayIcon = new NotifyIcon(); private readonly ContextMenu _trayMenu = new ContextMenu(); - public SystemTrayApp(IBrowserService browserService) + public SystemTrayApp(IBrowserService browserService, IRuntimeInfo runtimeInfo, IProcessProvider processProvider) { _browserService = browserService; + _runtimeInfo = runtimeInfo; + _processProvider = processProvider; } public void Start() @@ -98,6 +103,11 @@ private void LaunchBrowser(object sender, EventArgs e) private void OnApplicationExit(object sender, EventArgs e) { + if (_runtimeInfo.RestartPending) + { + _processProvider.SpawnNewProcess(_runtimeInfo.ExecutingApplication, "--restart --nobrowser"); + } + DisposeTrayIcon(); } diff --git a/src/UI/System/SystemLayout.js b/src/UI/System/SystemLayout.js index 7a5d51368..3500681c7 100644 --- a/src/UI/System/SystemLayout.js +++ b/src/UI/System/SystemLayout.js @@ -1,18 +1,20 @@ 'use strict'; define( [ + 'jquery', 'backbone', 'marionette', 'System/Info/SystemInfoLayout', 'System/Logs/LogsLayout', 'System/Update/UpdateLayout', - 'Commands/CommandController' - ], function (Backbone, + 'Shared/Messenger' + ], function ($, + Backbone, Marionette, SystemInfoLayout, LogsLayout, UpdateLayout, - CommandController) { + Messenger) { return Marionette.Layout.extend({ template: 'System/SystemLayoutTemplate', @@ -90,14 +92,26 @@ define( }, _shutdown: function () { - CommandController.Execute('shutdown', { - name : 'shutdown' + $.ajax({ + url: window.NzbDrone.ApiRoot + '/system/shutdown', + type: 'POST' + }); + + Messenger.show({ + message: 'NzbDrone will shutdown shortly', + type: 'info' }); }, _restart: function () { - CommandController.Execute('restart', { - name : 'restart' + $.ajax({ + url: window.NzbDrone.ApiRoot + '/system/restart', + type: 'POST' + }); + + Messenger.show({ + message: 'NzbDrone will restart shortly', + type: 'info' }); } });