diff --git a/common/services/ASC.Data.Backup/Controllers/BackupController.cs b/common/services/ASC.Data.Backup/Api/BackupController.cs similarity index 70% rename from common/services/ASC.Data.Backup/Controllers/BackupController.cs rename to common/services/ASC.Data.Backup/Api/BackupController.cs index 67b805a5d32..59c3bb92748 100644 --- a/common/services/ASC.Data.Backup/Controllers/BackupController.cs +++ b/common/services/ASC.Data.Backup/Api/BackupController.cs @@ -6,8 +6,7 @@ using ASC.Common; using ASC.Core; using ASC.Data.Backup.Contracts; -using ASC.Data.Backup.ModelApi; -using ASC.Data.Backup.Models; +using ASC.Data.Backup.ApiModels; using ASC.Web.Api.Routing; using ASC.Web.Studio.Utility; @@ -22,18 +21,18 @@ namespace ASC.Data.Backup.Controllers [ApiController] public class BackupController { - private BackupAjaxHandler BackupHandler { get; } - private CoreBaseSettings CoreBaseSettings { get; } - private TenantExtra TenantExtra { get; } + private readonly BackupAjaxHandler _backupHandler; + private readonly CoreBaseSettings _coreBaseSettings; + private readonly TenantExtra _tenantExtra; public BackupController( BackupAjaxHandler backupAjaxHandler, CoreBaseSettings coreBaseSettings, TenantExtra tenantExtra) { - BackupHandler = backupAjaxHandler; - CoreBaseSettings = coreBaseSettings; - TenantExtra = tenantExtra; + _backupHandler = backupAjaxHandler; + _coreBaseSettings = coreBaseSettings; + _tenantExtra = tenantExtra; } /// /// Returns the backup schedule of the current portal @@ -43,12 +42,12 @@ public BackupController( [Read("getbackupschedule")] public BackupAjaxHandler.Schedule GetBackupSchedule() { - if (CoreBaseSettings.Standalone) + if (_coreBaseSettings.Standalone) { - TenantExtra.DemandControlPanelPermission(); + _tenantExtra.DemandControlPanelPermission(); } - return BackupHandler.GetSchedule(); + return _backupHandler.GetSchedule(); } /// @@ -61,23 +60,23 @@ public BackupAjaxHandler.Schedule GetBackupSchedule() /// Include mail in the backup /// Backup [Create("createbackupschedule")] - public bool CreateBackupScheduleFromBody([FromBody]BackupSchedule backupSchedule) + public bool CreateBackupScheduleFromBody([FromBody]BackupScheduleDto backupSchedule) { return CreateBackupSchedule(backupSchedule); } [Create("createbackupschedule")] [Consumes("application/x-www-form-urlencoded")] - public bool CreateBackupScheduleFromForm([FromForm]BackupSchedule backupSchedule) + public bool CreateBackupScheduleFromForm([FromForm]BackupScheduleDto backupSchedule) { return CreateBackupSchedule(backupSchedule); } - private bool CreateBackupSchedule(BackupSchedule backupSchedule) + private bool CreateBackupSchedule(BackupScheduleDto backupSchedule) { - if (CoreBaseSettings.Standalone) + if (_coreBaseSettings.Standalone) { - TenantExtra.DemandControlPanelPermission(); + _tenantExtra.DemandControlPanelPermission(); } var storageType = backupSchedule.StorageType == null ? BackupStorageType.Documents : (BackupStorageType)Int32.Parse(backupSchedule.StorageType); var storageParams = backupSchedule.StorageParams == null ? new Dictionary() : backupSchedule.StorageParams.ToDictionary(r => r.Key.ToString(), r => r.Value.ToString()); @@ -88,7 +87,7 @@ private bool CreateBackupSchedule(BackupSchedule backupSchedule) Hour = backupSchedule.CronParams.Hour == null ? 0 : Int32.Parse(backupSchedule.CronParams.Hour), Day = backupSchedule.CronParams.Day == null ? 0 : Int32.Parse(backupSchedule.CronParams.Day), }; - BackupHandler.CreateSchedule(storageType, storageParams, backupStored, cron, backupSchedule.BackupMail); + _backupHandler.CreateSchedule(storageType, storageParams, backupStored, cron, backupSchedule.BackupMail); return true; } @@ -99,12 +98,12 @@ private bool CreateBackupSchedule(BackupSchedule backupSchedule) [Delete("deletebackupschedule")] public bool DeleteBackupSchedule() { - if (CoreBaseSettings.Standalone) + if (_coreBaseSettings.Standalone) { - TenantExtra.DemandControlPanelPermission(); + _tenantExtra.DemandControlPanelPermission(); } - BackupHandler.DeleteSchedule(); + _backupHandler.DeleteSchedule(); return true; } @@ -118,28 +117,28 @@ public bool DeleteBackupSchedule() /// Backup /// Backup Progress [Create("startbackup")] - public BackupProgress StartBackupFromBody([FromBody]Models.Backup backup) + public BackupProgress StartBackupFromBody([FromBody]BackupDto backup) { return StartBackup(backup); } [Create("startbackup")] [Consumes("application/x-www-form-urlencoded")] - public BackupProgress StartBackupFromForm([FromForm]Models.Backup backup) + public BackupProgress StartBackupFromForm([FromForm]BackupDto backup) { return StartBackup(backup); } - private BackupProgress StartBackup(Models.Backup backup) + private BackupProgress StartBackup(BackupDto backup) { - if (CoreBaseSettings.Standalone) + if (_coreBaseSettings.Standalone) { - TenantExtra.DemandControlPanelPermission(); + _tenantExtra.DemandControlPanelPermission(); } var storageType = backup.StorageType == null ? BackupStorageType.Documents : (BackupStorageType)Int32.Parse(backup.StorageType); var storageParams = backup.StorageParams == null ? new Dictionary() : backup.StorageParams.ToDictionary(r => r.Key.ToString(), r => r.Value.ToString()); - BackupHandler.StartBackup(storageType, storageParams, backup.BackupMail); - return BackupHandler.GetBackupProgress(); + _backupHandler.StartBackup(storageType, storageParams, backup.BackupMail); + return _backupHandler.GetBackupProgress(); } /// @@ -150,12 +149,12 @@ private BackupProgress StartBackup(Models.Backup backup) [Read("getbackupprogress")] public BackupProgress GetBackupProgress() { - if (CoreBaseSettings.Standalone) + if (_coreBaseSettings.Standalone) { - TenantExtra.DemandControlPanelPermission(); + _tenantExtra.DemandControlPanelPermission(); } - return BackupHandler.GetBackupProgress(); + return _backupHandler.GetBackupProgress(); } /// @@ -166,12 +165,12 @@ public BackupProgress GetBackupProgress() [Read("getbackuphistory")] public List GetBackupHistory() { - if (CoreBaseSettings.Standalone) + if (_coreBaseSettings.Standalone) { - TenantExtra.DemandControlPanelPermission(); + _tenantExtra.DemandControlPanelPermission(); } - return BackupHandler.GetBackupHistory(); + return _backupHandler.GetBackupHistory(); } /// @@ -181,12 +180,12 @@ public List GetBackupHistory() [Delete("deletebackup/{id}")] public bool DeleteBackup(Guid id) { - if (CoreBaseSettings.Standalone) + if (_coreBaseSettings.Standalone) { - TenantExtra.DemandControlPanelPermission(); + _tenantExtra.DemandControlPanelPermission(); } - BackupHandler.DeleteBackup(id); + _backupHandler.DeleteBackup(id); return true; } @@ -198,12 +197,12 @@ public bool DeleteBackup(Guid id) [Delete("deletebackuphistory")] public bool DeleteBackupHistory() { - if (CoreBaseSettings.Standalone) + if (_coreBaseSettings.Standalone) { - TenantExtra.DemandControlPanelPermission(); + _tenantExtra.DemandControlPanelPermission(); } - BackupHandler.DeleteAllBackups(); + _backupHandler.DeleteAllBackups(); return true; } @@ -217,27 +216,27 @@ public bool DeleteBackupHistory() /// Backup /// Restore Progress [Create("startrestore")] - public BackupProgress StartBackupRestoreFromBody([FromBody]BackupRestore backupRestore) + public BackupProgress StartBackupRestoreFromBody([FromBody]BackupRestoreDto backupRestore) { return StartBackupRestore(backupRestore); } [Create("startrestore")] [Consumes("application/x-www-form-urlencoded")] - public BackupProgress StartBackupRestoreFromForm([FromForm]BackupRestore backupRestore) + public BackupProgress StartBackupRestoreFromForm([FromForm]BackupRestoreDto backupRestore) { return StartBackupRestore(backupRestore); } - private BackupProgress StartBackupRestore(BackupRestore backupRestore) + private BackupProgress StartBackupRestore(BackupRestoreDto backupRestore) { - if (CoreBaseSettings.Standalone) + if (_coreBaseSettings.Standalone) { - TenantExtra.DemandControlPanelPermission(); + _tenantExtra.DemandControlPanelPermission(); } var storageParams = backupRestore.StorageParams == null ? new Dictionary() : backupRestore.StorageParams.ToDictionary(r => r.Key.ToString(), r => r.Value.ToString()); - BackupHandler.StartRestore(backupRestore.BackupId, (BackupStorageType)Int32.Parse(backupRestore.StorageType.ToString()), storageParams, backupRestore.Notify); - return BackupHandler.GetBackupProgress(); + _backupHandler.StartRestore(backupRestore.BackupId, (BackupStorageType)Int32.Parse(backupRestore.StorageType.ToString()), storageParams, backupRestore.Notify); + return _backupHandler.GetBackupProgress(); } /// @@ -248,24 +247,24 @@ private BackupProgress StartBackupRestore(BackupRestore backupRestore) [Read("getrestoreprogress", true)] //NOTE: this method doesn't check payment!!! public BackupProgress GetRestoreProgress() { - if (CoreBaseSettings.Standalone) + if (_coreBaseSettings.Standalone) { - TenantExtra.DemandControlPanelPermission(); + _tenantExtra.DemandControlPanelPermission(); } - return BackupHandler.GetRestoreProgress(); + return _backupHandler.GetRestoreProgress(); } ///false [Read("backuptmp")] public object GetTempPath() { - if (CoreBaseSettings.Standalone) + if (_coreBaseSettings.Standalone) { - TenantExtra.DemandControlPanelPermission(); + _tenantExtra.DemandControlPanelPermission(); } - return BackupHandler.GetTmpFolder(); + return _backupHandler.GetTmpFolder(); } } } diff --git a/common/services/ASC.Data.Backup/ModelApi/Backup.cs b/common/services/ASC.Data.Backup/ApiModels/BackupDto.cs similarity index 80% rename from common/services/ASC.Data.Backup/ModelApi/Backup.cs rename to common/services/ASC.Data.Backup/ApiModels/BackupDto.cs index edd9583d3da..a79f9fe271f 100644 --- a/common/services/ASC.Data.Backup/ModelApi/Backup.cs +++ b/common/services/ASC.Data.Backup/ApiModels/BackupDto.cs @@ -3,11 +3,10 @@ using ASC.Api.Collections; -namespace ASC.Data.Backup.Models +namespace ASC.Data.Backup.ApiModels { - public class Backup + public class BackupDto { - public string StorageType { get; set; } public bool BackupMail { get; set; } public IEnumerable> StorageParams { get; set; } diff --git a/common/services/ASC.Data.Backup/ModelApi/BackupRestore.cs b/common/services/ASC.Data.Backup/ApiModels/BackupRestoreDto.cs similarity index 81% rename from common/services/ASC.Data.Backup/ModelApi/BackupRestore.cs rename to common/services/ASC.Data.Backup/ApiModels/BackupRestoreDto.cs index f34503b7dfd..694252a55ba 100644 --- a/common/services/ASC.Data.Backup/ModelApi/BackupRestore.cs +++ b/common/services/ASC.Data.Backup/ApiModels/BackupRestoreDto.cs @@ -2,9 +2,9 @@ using ASC.Api.Collections; -namespace ASC.Data.Backup.Models +namespace ASC.Data.Backup.ApiModels { - public class BackupRestore + public class BackupRestoreDto { public string BackupId { get; set; } public object StorageType { get; set; } diff --git a/common/services/ASC.Data.Backup/ModelApi/BackupSchedule.cs b/common/services/ASC.Data.Backup/ApiModels/BackupScheduleDto.cs similarity index 87% rename from common/services/ASC.Data.Backup/ModelApi/BackupSchedule.cs rename to common/services/ASC.Data.Backup/ApiModels/BackupScheduleDto.cs index 3d21bea195c..b4569fc525c 100644 --- a/common/services/ASC.Data.Backup/ModelApi/BackupSchedule.cs +++ b/common/services/ASC.Data.Backup/ApiModels/BackupScheduleDto.cs @@ -2,9 +2,9 @@ using ASC.Api.Collections; -namespace ASC.Data.Backup.ModelApi +namespace ASC.Data.Backup.ApiModels { - public class BackupSchedule + public class BackupScheduleDto { public string StorageType { get; set; } public IEnumerable> StorageParams { get; set; } diff --git a/common/services/ASC.Data.Backup/BackupCleanerService.cs b/common/services/ASC.Data.Backup/BackupCleanerService.cs deleted file mode 100644 index eccf93f26dd..00000000000 --- a/common/services/ASC.Data.Backup/BackupCleanerService.cs +++ /dev/null @@ -1,192 +0,0 @@ -/* - * - * (c) Copyright Ascensio System Limited 2010-2020 - * - * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU - * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). - * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that - * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights. - * - * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR - * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html - * - * You can contact Ascensio System SIA by email at sales@onlyoffice.com - * - * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display - * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3. - * - * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains - * relevant author attributions when distributing the software. If the display of the logo in its graphic - * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" - * in every copy of the program you distribute. - * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. - * -*/ - - -using System; -using System.Linq; -using System.Threading; - -using ASC.Common; -using ASC.Common.Logging; -using ASC.Data.Backup.Storage; -using ASC.Files.Core; - -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; - -namespace ASC.Data.Backup.Service -{ - [Scope] - internal class BackupCleanerHelperService - { - private readonly ILog log; - - private BackupRepository BackupRepository { get; } - private BackupStorageFactory BackupStorageFactory { get; } - - public BackupCleanerHelperService( - IOptionsMonitor options, - BackupRepository backupRepository, - BackupStorageFactory backupStorageFactory) - { - log = options.CurrentValue; - BackupRepository = backupRepository; - BackupStorageFactory = backupStorageFactory; - } - - - internal void DeleteExpiredBackups(BackupCleanerService backupCleanerService) - { - log.Debug("started to clean expired backups"); - - var backupsToRemove = BackupRepository.GetExpiredBackupRecords(); - log.DebugFormat("found {0} backups which are expired", backupsToRemove.Count); - - if (!backupCleanerService.IsStarted) return; - foreach (var scheduledBackups in BackupRepository.GetScheduledBackupRecords().GroupBy(r => r.TenantId)) - { - if (!backupCleanerService.IsStarted) return; - var schedule = BackupRepository.GetBackupSchedule(scheduledBackups.Key); - if (schedule != null) - { - var scheduledBackupsToRemove = scheduledBackups.OrderByDescending(r => r.CreatedOn).Skip(schedule.BackupsStored).ToList(); - if (scheduledBackupsToRemove.Any()) - { - log.DebugFormat("only last {0} scheduled backup records are to keep for tenant {1} so {2} records must be removed", schedule.BackupsStored, schedule.TenantId, scheduledBackupsToRemove.Count); - backupsToRemove.AddRange(scheduledBackupsToRemove); - } - } - else - { - backupsToRemove.AddRange(scheduledBackups); - } - } - - foreach (var backupRecord in backupsToRemove) - { - if (!backupCleanerService.IsStarted) return; - try - { - var backupStorage = BackupStorageFactory.GetBackupStorage(backupRecord); - if (backupStorage == null) continue; - - backupStorage.Delete(backupRecord.StoragePath); - - BackupRepository.DeleteBackupRecord(backupRecord.Id); - } - catch (ProviderInfoArgumentException error) - { - log.Warn("can't remove backup record " + backupRecord.Id, error); - if (DateTime.UtcNow > backupRecord.CreatedOn.AddMonths(6)) - { - BackupRepository.DeleteBackupRecord(backupRecord.Id); - } - } - catch (Exception error) - { - log.Warn("can't remove backup record: " + backupRecord.Id, error); - } - } - } - } - - [Singletone(Additional = typeof(BackupCleanerServiceExtension))] - public class BackupCleanerService - { - private readonly object cleanerLock = new object(); - private Timer CleanTimer { get; set; } - internal bool IsStarted { get; set; } - private ILog Log { get; set; } - public TimeSpan Period { get; set; } - private IServiceProvider ServiceProvider { get; set; } - - public BackupCleanerService( - IOptionsMonitor options, - IServiceProvider serviceProvider) - { - ServiceProvider = serviceProvider; - Log = options.CurrentValue; - Period = TimeSpan.FromMinutes(15); - } - - - public void Start() - { - if (!IsStarted && Period > TimeSpan.Zero) - { - Log.Info("starting backup cleaner service..."); - CleanTimer = new Timer(_ => DeleteExpiredBackups(), null, TimeSpan.Zero, Period); - Log.Info("backup cleaner service started"); - IsStarted = true; - } - } - - public void Stop() - { - if (IsStarted) - { - Log.Info("stopping backup cleaner service..."); - if (CleanTimer != null) - { - CleanTimer.Change(Timeout.Infinite, Timeout.Infinite); - CleanTimer.Dispose(); - CleanTimer = null; - } - Log.Info("backup cleaner service stopped"); - IsStarted = false; - } - } - - private void DeleteExpiredBackups() - { - if (Monitor.TryEnter(cleanerLock)) - { - try - { - - using var scope = ServiceProvider.CreateScope(); - var backupCleanerHelperService = scope.ServiceProvider.GetService(); - backupCleanerHelperService.DeleteExpiredBackups(this); - } - catch (Exception error) - { - Log.Error("error while cleaning expired backup records: {0}", error); - } - finally - { - Monitor.Exit(cleanerLock); - } - } - } - } - - public class BackupCleanerServiceExtension - { - public static void Register(DIHelper services) - { - services.TryAdd(); - } - } -} diff --git a/common/services/ASC.Data.Backup/BackupSchedulerService.cs b/common/services/ASC.Data.Backup/BackupSchedulerService.cs deleted file mode 100644 index b26a3033f51..00000000000 --- a/common/services/ASC.Data.Backup/BackupSchedulerService.cs +++ /dev/null @@ -1,187 +0,0 @@ -/* - * - * (c) Copyright Ascensio System Limited 2010-2020 - * - * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU - * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). - * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that - * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights. - * - * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR - * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html - * - * You can contact Ascensio System SIA by email at sales@onlyoffice.com - * - * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display - * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3. - * - * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains - * relevant author attributions when distributing the software. If the display of the logo in its graphic - * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" - * in every copy of the program you distribute. - * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. - * -*/ - - -using System; -using System.Linq; -using System.Threading; - -using ASC.Common; -using ASC.Common.Logging; -using ASC.Core; -using ASC.Core.Billing; -using ASC.Data.Backup.Storage; - -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; - -namespace ASC.Data.Backup.Service -{ - [Scope] - internal class BackupSchedulerServiceHelper - { - private ILog Log { get; } - private PaymentManager PaymentManager { get; } - private BackupWorker BackupWorker { get; } - private BackupRepository BackupRepository { get; } - private Schedule Schedule { get; } - private TenantManager TenantManager { get; } - private CoreBaseSettings CoreBaseSettings { get; } - - public BackupSchedulerServiceHelper( - IOptionsMonitor options, - PaymentManager paymentManager, - BackupWorker backupWorker, - BackupRepository backupRepository, - Schedule schedule, - TenantManager tenantManager, - CoreBaseSettings coreBaseSettings) - { - PaymentManager = paymentManager; - BackupWorker = backupWorker; - BackupRepository = backupRepository; - Schedule = schedule; - TenantManager = tenantManager; - CoreBaseSettings = coreBaseSettings; - Log = options.CurrentValue; - } - - public void ScheduleBackupTasks(BackupSchedulerService backupSchedulerService) - { - Log.DebugFormat("started to schedule backups"); - var backupsToSchedule = BackupRepository.GetBackupSchedules().Where(schedule => Schedule.IsToBeProcessed(schedule)).ToList(); - Log.DebugFormat("{0} backups are to schedule", backupsToSchedule.Count); - foreach (var schedule in backupsToSchedule) - { - if (!backupSchedulerService.IsStarted) - { - return; - } - try - { - if (CoreBaseSettings.Standalone || TenantManager.GetTenantQuota(schedule.TenantId).AutoBackup) - { - var tariff = PaymentManager.GetTariff(schedule.TenantId); - if (tariff.State < TariffState.Delay) - { - schedule.LastBackupTime = DateTime.UtcNow; - BackupRepository.SaveBackupSchedule(schedule); - Log.DebugFormat("Start scheduled backup: {0}, {1}, {2}, {3}", schedule.TenantId, schedule.BackupMail, schedule.StorageType, schedule.StorageBasePath); - BackupWorker.StartScheduledBackup(schedule); - } - else - { - Log.DebugFormat("Skip portal {0} not paid", schedule.TenantId); - } - } - else - { - Log.DebugFormat("Skip portal {0} haven't access", schedule.TenantId); - } - } - catch (Exception error) - { - Log.Error("error while scheduling backups: {0}", error); - } - } - } - } - - [Singletone(Additional = typeof(BackupSchedulerServiceExtension))] - public class BackupSchedulerService - { - private readonly object schedulerLock = new object(); - private Timer SchedulerTimer { get; set; } - internal bool IsStarted { get; set; } - public TimeSpan Period { get; set; } - private ILog Log { get; } - private IServiceProvider ServiceProvider { get; } - - public BackupSchedulerService( - IOptionsMonitor options, - IServiceProvider serviceProvider) - { - Log = options.CurrentValue; - Period = TimeSpan.FromMinutes(15); - ServiceProvider = serviceProvider; - } - - public void Start() - { - if (!IsStarted && Period > TimeSpan.Zero) - { - Log.Info("staring backup scheduler service..."); - SchedulerTimer = new Timer(_ => ScheduleBackupTasks(), null, TimeSpan.Zero, Period); - Log.Info("backup scheduler service service started"); - IsStarted = true; - } - } - - public void Stop() - { - if (IsStarted) - { - Log.Info("stoping backup scheduler service..."); - if (SchedulerTimer != null) - { - SchedulerTimer.Change(Timeout.Infinite, Timeout.Infinite); - SchedulerTimer.Dispose(); - SchedulerTimer = null; - } - Log.Info("backup scheduler service stoped"); - IsStarted = false; - } - } - - private void ScheduleBackupTasks() - { - if (Monitor.TryEnter(schedulerLock)) - { - try - { - using var scope = ServiceProvider.CreateScope(); - var backupSchedulerServiceHelper = scope.ServiceProvider.GetService(); - backupSchedulerServiceHelper.ScheduleBackupTasks(this); - } - catch (Exception error) - { - Log.Error("error while scheduling backups: {0}", error); - } - finally - { - Monitor.Exit(schedulerLock); - } - } - } - } - - public class BackupSchedulerServiceExtension - { - public static void Register(DIHelper services) - { - services.TryAdd(); - } - } -} diff --git a/common/services/ASC.Data.Backup/Services/BackupCleanerService.cs b/common/services/ASC.Data.Backup/Services/BackupCleanerService.cs new file mode 100644 index 00000000000..d90b9efbaf6 --- /dev/null +++ b/common/services/ASC.Data.Backup/Services/BackupCleanerService.cs @@ -0,0 +1,150 @@ +/* + * + * (c) Copyright Ascensio System Limited 2010-2020 + * + * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). + * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that + * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights. + * + * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html + * + * You can contact Ascensio System SIA by email at sales@onlyoffice.com + * + * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display + * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3. + * + * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains + * relevant author attributions when distributing the software. If the display of the logo in its graphic + * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" + * in every copy of the program you distribute. + * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. + * +*/ + + +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +using ASC.Common; +using ASC.Common.Logging; +using ASC.Common.Utils; +using ASC.Data.Backup.Storage; +using ASC.Files.Core; + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Options; + +namespace ASC.Data.Backup.Service +{ + [Scope] + public class BackupCleanerService : IHostedService, IDisposable + { + private Timer _timer; + private readonly ILog _logger; + private readonly TimeSpan _period; + + private IServiceScopeFactory _scopeFactory; + private IServiceScope _serviceScope; + + public BackupCleanerService( + ConfigurationExtension configuration, + IOptionsMonitor options, + IServiceScopeFactory scopeFactory) + { + _scopeFactory = scopeFactory; + _logger = options.CurrentValue; + _period = configuration.GetSetting("backup").Cleaner.Period; + } + + public Task StartAsync(CancellationToken cancellationToken) + { + _logger.Info("starting backup cleaner service..."); + + _serviceScope = _scopeFactory.CreateScope(); + _timer = new Timer(DeleteExpiredBackups, null, TimeSpan.Zero, _period); + + _logger.Info("backup cleaner service started"); + + return Task.CompletedTask; + } + + public void DeleteExpiredBackups(object state) + { + var backupRepository = _serviceScope.ServiceProvider.GetRequiredService(); + var backupStorageFactory = _serviceScope.ServiceProvider.GetRequiredService(); + + _logger.Debug("started to clean expired backups"); + + var backupsToRemove = backupRepository.GetExpiredBackupRecords(); + + _logger.DebugFormat("found {0} backups which are expired", backupsToRemove.Count); + + foreach (var scheduledBackups in backupRepository.GetScheduledBackupRecords().GroupBy(r => r.TenantId)) + { + var schedule = backupRepository.GetBackupSchedule(scheduledBackups.Key); + + if (schedule != null) + { + var scheduledBackupsToRemove = scheduledBackups.OrderByDescending(r => r.CreatedOn).Skip(schedule.BackupsStored).ToList(); + if (scheduledBackupsToRemove.Any()) + { + _logger.DebugFormat("only last {0} scheduled backup records are to keep for tenant {1} so {2} records must be removed", schedule.BackupsStored, schedule.TenantId, scheduledBackupsToRemove.Count); + backupsToRemove.AddRange(scheduledBackupsToRemove); + } + } + else + { + backupsToRemove.AddRange(scheduledBackups); + } + } + + foreach (var backupRecord in backupsToRemove) + { + try + { + var backupStorage = backupStorageFactory.GetBackupStorage(backupRecord); + if (backupStorage == null) continue; + + backupStorage.Delete(backupRecord.StoragePath); + + backupRepository.DeleteBackupRecord(backupRecord.Id); + } + catch (ProviderInfoArgumentException error) + { + _logger.Warn("can't remove backup record " + backupRecord.Id, error); + + if (DateTime.UtcNow > backupRecord.CreatedOn.AddMonths(6)) + { + backupRepository.DeleteBackupRecord(backupRecord.Id); + } + } + catch (Exception error) + { + _logger.Warn("can't remove backup record: " + backupRecord.Id, error); + } + } + } + + public Task StopAsync(CancellationToken cancellationToken) + { + _logger.Info("stopping backup cleaner service..."); + + _timer?.Change(Timeout.Infinite, 0); + + _logger.Info("backup cleaner service stopped"); + + return Task.CompletedTask; + } + + public void Dispose() + { + _timer?.Dispose(); + _serviceScope?.Dispose(); + } + } +} \ No newline at end of file diff --git a/common/services/ASC.Data.Backup/BackupServiceLauncher.cs b/common/services/ASC.Data.Backup/Services/BackupLauncherService.cs similarity index 57% rename from common/services/ASC.Data.Backup/BackupServiceLauncher.cs rename to common/services/ASC.Data.Backup/Services/BackupLauncherService.cs index 991dccefa6d..b5a415294bc 100644 --- a/common/services/ASC.Data.Backup/BackupServiceLauncher.cs +++ b/common/services/ASC.Data.Backup/Services/BackupLauncherService.cs @@ -37,63 +37,42 @@ namespace ASC.Data.Backup.Service { [Singletone] - internal class BackupServiceLauncher : IHostedService + internal class BackupLauncherService : IHostedService { - private BackupCleanerService CleanerService { get; set; } - private BackupSchedulerService SchedulerService { get; set; } - private BackupWorker BackupWorker { get; set; } - private ConfigurationExtension Configuration { get; set; } - private BackupListener BackupListener { get; set; } - public NotifyConfiguration NotifyConfiguration { get; } + private readonly BackupWorker _backupWorker; + private readonly ConfigurationExtension _configuration; + private readonly BackupListener _backupListener; + private readonly NotifyConfiguration _notifyConfiguration; - public BackupServiceLauncher( - BackupCleanerService cleanerService, - BackupSchedulerService schedulerService, + public BackupLauncherService( BackupWorker backupWorker, ConfigurationExtension configuration, BackupListener backupListener, NotifyConfiguration notifyConfiguration) { - CleanerService = cleanerService; - SchedulerService = schedulerService; - BackupWorker = backupWorker; - Configuration = configuration; - BackupListener = backupListener; - NotifyConfiguration = notifyConfiguration; + _backupWorker = backupWorker; + _configuration = configuration; + _backupListener = backupListener; + _notifyConfiguration = notifyConfiguration; } public Task StartAsync(CancellationToken cancellationToken) { - NotifyConfiguration.Configure(); + _notifyConfiguration.Configure(); - var settings = Configuration.GetSetting("backup"); + var settings = _configuration.GetSetting("backup"); - BackupWorker.Start(settings); - BackupListener.Start(); - - CleanerService.Period = settings.Cleaner.Period; - CleanerService.Start(); - - SchedulerService.Period = settings.Scheduler.Period; - SchedulerService.Start(); + _backupWorker.Start(settings); + _backupListener.Start(); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { - BackupWorker.Stop(); - BackupListener.Stop(); - if (CleanerService != null) - { - CleanerService.Stop(); - CleanerService = null; - } - if (SchedulerService != null) - { - SchedulerService.Stop(); - SchedulerService = null; - } + _backupWorker.Stop(); + _backupListener.Stop(); + return Task.CompletedTask; } } diff --git a/common/services/ASC.Data.Backup/Services/BackupSchedulerService.cs b/common/services/ASC.Data.Backup/Services/BackupSchedulerService.cs new file mode 100644 index 00000000000..a4515bcbad0 --- /dev/null +++ b/common/services/ASC.Data.Backup/Services/BackupSchedulerService.cs @@ -0,0 +1,141 @@ +/* + * + * (c) Copyright Ascensio System Limited 2010-2020 + * + * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). + * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that + * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights. + * + * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html + * + * You can contact Ascensio System SIA by email at sales@onlyoffice.com + * + * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display + * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3. + * + * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains + * relevant author attributions when distributing the software. If the display of the logo in its graphic + * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" + * in every copy of the program you distribute. + * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. + * +*/ + + +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +using ASC.Common; +using ASC.Common.Logging; +using ASC.Common.Utils; +using ASC.Core; +using ASC.Core.Billing; +using ASC.Data.Backup.Storage; + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Options; + +namespace ASC.Data.Backup.Service +{ + [Scope] + public class BackupSchedulerService : IHostedService, IDisposable + { + private readonly TimeSpan _period; + private Timer _timer; + private readonly ILog _logger; + + private IServiceScopeFactory _scopeFactory; + private IServiceScope _serviceScope; + + public BackupSchedulerService( + IOptionsMonitor options, + IServiceScopeFactory scopeFactory, + ConfigurationExtension configuration) + { + _logger = options.CurrentValue; + _period = configuration.GetSetting("backup").Scheduler.Period; + _scopeFactory = scopeFactory; + } + + public Task StartAsync(CancellationToken cancellationToken) + { + _logger.Info("starting backup scheduler service..."); + + _serviceScope = _scopeFactory.CreateScope(); + _timer = new Timer(ScheduleBackupTasks, null, TimeSpan.Zero, _period); + + _logger.Info("backup scheduler service started"); + + return Task.CompletedTask; + } + + public void ScheduleBackupTasks(object state) + { + var paymentManager = _serviceScope.ServiceProvider.GetRequiredService(); + var backupWorker = _serviceScope.ServiceProvider.GetRequiredService(); + var backupRepository = _serviceScope.ServiceProvider.GetRequiredService(); ; + var backupSchedule = _serviceScope.ServiceProvider.GetRequiredService(); + var tenantManager = _serviceScope.ServiceProvider.GetRequiredService(); + var coreBaseSettings = _serviceScope.ServiceProvider.GetRequiredService(); + + _logger.DebugFormat("started to schedule backups"); + + var backupsToSchedule = backupRepository.GetBackupSchedules().Where(schedule => backupSchedule.IsToBeProcessed(schedule)).ToList(); + + _logger.DebugFormat("{0} backups are to schedule", backupsToSchedule.Count); + + foreach (var schedule in backupsToSchedule) + { + try + { + if (coreBaseSettings.Standalone || tenantManager.GetTenantQuota(schedule.TenantId).AutoBackup) + { + var tariff = paymentManager.GetTariff(schedule.TenantId); + if (tariff.State < TariffState.Delay) + { + schedule.LastBackupTime = DateTime.UtcNow; + + backupRepository.SaveBackupSchedule(schedule); + _logger.DebugFormat("Start scheduled backup: {0}, {1}, {2}, {3}", schedule.TenantId, schedule.BackupMail, schedule.StorageType, schedule.StorageBasePath); + backupWorker.StartScheduledBackup(schedule); + } + else + { + _logger.DebugFormat("Skip portal {0} not paid", schedule.TenantId); + } + } + else + { + _logger.DebugFormat("Skip portal {0} haven't access", schedule.TenantId); + } + } + catch (Exception error) + { + _logger.Error("error while scheduling backups: {0}", error); + } + } + + } + + public Task StopAsync(CancellationToken cancellationToken) + { + _logger.Info("stopping backup cleaner service..."); + + _timer?.Change(Timeout.Infinite, 0); + + _logger.Info("backup cleaner service stopped"); + + return Task.CompletedTask; + } + public void Dispose() + { + _timer?.Dispose(); + _serviceScope?.Dispose(); + } + } +} diff --git a/common/services/ASC.Data.Backup/Startup.cs b/common/services/ASC.Data.Backup/Startup.cs index 755b494f123..b5c7fa395f6 100644 --- a/common/services/ASC.Data.Backup/Startup.cs +++ b/common/services/ASC.Data.Backup/Startup.cs @@ -41,7 +41,8 @@ namespace ASC.Data.Backup { public class Startup : BaseStartup { - public Startup(IConfiguration configuration, IHostEnvironment hostEnvironment) : base(configuration, hostEnvironment) + public Startup(IConfiguration configuration, IHostEnvironment hostEnvironment) + : base(configuration, hostEnvironment) { } @@ -56,11 +57,17 @@ public override void ConfigureServices(IServiceCollection services) DIHelper.TryAdd(); DIHelper.TryAdd(); - DIHelper.TryAdd(); + DIHelper.TryAdd(); + DIHelper.TryAdd(); + DIHelper.TryAdd(); + DIHelper.TryAdd(); + NotifyConfigurationExtension.Register(DIHelper); - services.AddHostedService(); + services.AddHostedService(); + services.AddHostedService(); + services.AddStackExchangeRedisExtensions(Configuration.GetSection("Redis").Get()); } }