diff --git a/server/AyaNova/Controllers/BackupController.cs b/server/AyaNova/Controllers/BackupController.cs index dd8c2495..edc7c225 100644 --- a/server/AyaNova/Controllers/BackupController.cs +++ b/server/AyaNova/Controllers/BackupController.cs @@ -76,17 +76,18 @@ namespace AyaNova.Api.Controllers /// - /// Get list of backup files + /// Get status of backup /// /// - [HttpGet("list")] - public ActionResult ListBackupFiles() + [HttpGet("status")] + public ActionResult BackupStatus() { + //Need size and more info if (serverState.IsClosed) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); if (!Authorized.HasAnyRole(HttpContext.Items, AuthorizationRoles.OpsAdminFull | AuthorizationRoles.OpsAdminLimited)) return StatusCode(403, new ApiNotAuthorizedResponse()); - return Ok(ApiOkResponse.Response(FileUtil.UtilityFileList())); + return Ok(ApiOkResponse.Response(FileUtil.BackupStatusReport())); } /// @@ -123,9 +124,8 @@ namespace AyaNova.Api.Controllers await Task.Delay(nFailedAuthDelay);//DOS protection return StatusCode(403, new ApiNotAuthorizedResponse()); } - - var AvailableFiles = FileUtil.UtilityFileList(); - if (!AvailableFiles.Contains(fileName)) + + if (!FileUtil.UtilityFileExists(fileName)) { await Task.Delay(nFailedAuthDelay);//fishing protection return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); diff --git a/server/AyaNova/generator/CoreJobBackup.cs b/server/AyaNova/generator/CoreJobBackup.cs index 7e5d2a8b..b632f7cd 100644 --- a/server/AyaNova/generator/CoreJobBackup.cs +++ b/server/AyaNova/generator/CoreJobBackup.cs @@ -25,6 +25,7 @@ namespace AyaNova.Biz public static async Task DoWorkAsync(AyContext ct, bool OnDemand = false) { if (BackupIsRunning) return; + FileUtil.DatabaseBackupCleanUp(ServerGlobalOpsSettingsCache.Backup.BackupSetsToKeep); //get NOW in utc DateTime utcNow = DateTime.UtcNow; if (!OnDemand) @@ -83,17 +84,12 @@ namespace AyaNova.Biz log.LogError($"BACKUP ERROR: {Result}"); - //PRUNE DATA BACKUP SETS NOT KEPT - FileUtil.DatabaseBackupCleanUp(ServerGlobalOpsSettingsCache.Backup.BackupSetsToKeep); - - //DO FILE BACKUP IF ATTACHMENTS BACKED UP if (ServerGlobalOpsSettingsCache.Backup.BackupAttachments) FileUtil.BackupAttachments(); //PRUNE DATA BACKUP SETS NOT KEPT - FileUtil.AttachmentBackupCleanUp(ServerGlobalOpsSettingsCache.Backup.BackupSetsToKeep); - + FileUtil.DatabaseBackupCleanUp(ServerGlobalOpsSettingsCache.Backup.BackupSetsToKeep); //v.next - COPY TO ONLINE STORAGE @@ -103,9 +99,9 @@ namespace AyaNova.Biz { //Update last backup var biz = GlobalOpsBackupSettingsBiz.GetBiz(ct); - var OpSet = await biz.GetAsync(false); + var OpSet = await biz.GetAsync(false); await biz.PutAsync(OpSet); - ServerGlobalOpsSettingsCache.Backup.LastBackup=utcNow; + ServerGlobalOpsSettingsCache.Backup.LastBackup = utcNow; } log.LogDebug("Backup completed"); } diff --git a/server/AyaNova/models/GlobalOpsBackupSettings.cs b/server/AyaNova/models/GlobalOpsBackupSettings.cs index 17e6cf80..f49ad00c 100644 --- a/server/AyaNova/models/GlobalOpsBackupSettings.cs +++ b/server/AyaNova/models/GlobalOpsBackupSettings.cs @@ -17,7 +17,8 @@ namespace AyaNova.Models public GlobalOpsBackupSettings() { Id = 1;//always 1 - BackupTime = new DateTime(2020, 5, 19, 23, 59, 0, DateTimeKind.Local).ToUniversalTime();//date doesn't matter it only uses hour + BackupTime = new DateTime(2020, 5, 19, 23, 59, 0, DateTimeKind.Local).ToUniversalTime();//date doesn't matter it only uses hour + // BackupTime = DateTime.UtcNow.AddMinutes(-10);//for testing, above is regular BackupSetsToKeep = 3; } } diff --git a/server/AyaNova/util/FileUtil.cs b/server/AyaNova/util/FileUtil.cs index e5948e9d..1de9d981 100644 --- a/server/AyaNova/util/FileUtil.cs +++ b/server/AyaNova/util/FileUtil.cs @@ -87,38 +87,89 @@ namespace AyaNova.Util } - /// - /// Delete a utility file (backup folder file) - /// - /// - internal static void DeleteUtilityFile(string fileName) + // /// + // /// Delete a utility file (backup folder file) + // /// + // /// + // internal static void DeleteUtilityFile(string fileName) + // { + // var utilityFilePath = GetFullPathForUtilityFile(fileName); + // if (File.Exists(utilityFilePath)) + // { + // File.Delete(utilityFilePath); + // } + // } + + public class BackupFileInfo { - var utilityFilePath = GetFullPathForUtilityFile(fileName); - if (File.Exists(utilityFilePath)) + public long length { get; set; } + public string Name { get; set; } + public DateTime Created { get; set; } + + } + + public class BackupStatus + { + public long AvailableFreeSpace { get; set; } + public List BackupFiles { get; set; } + public BackupStatus() { - File.Delete(utilityFilePath); + AvailableFreeSpace = 0; + BackupFiles = new List(); } } - /// - /// Get a list of files in the utility folder - /// - /// - /// search pattern for files desired, leave blank for any + /// Get a status report of backup + /// for reporting to ops user in UI + /// /// - internal static List UtilityFileList(string searchPattern = "*") + internal static BackupStatus BackupStatusReport() { - List returnList = new List(); - foreach (string file in Directory.EnumerateFiles(UtilityFilesFolder, searchPattern)) + BackupStatus statusReport = new BackupStatus(); + try { - returnList.Add(Path.GetFileName(file)); + statusReport.AvailableFreeSpace = new System.IO.DriveInfo(Path.GetPathRoot(UtilityFilesFolder)).AvailableFreeSpace; } - returnList.Sort(); - return returnList; + catch (Exception ex) + { + statusReport.AvailableFreeSpace = -1; + ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger("FileUtil::BackupStatus"); + log.LogError(ex, "FileUtil::BackupStatusReport error getting available space"); + } + + var backupFiles = Directory.EnumerateFiles(UtilityFilesFolder, "*"); + + foreach (string file in backupFiles) + { + var fi = new FileInfo(file); + statusReport.BackupFiles.Add(new BackupFileInfo() + { + Name = Path.GetFileName(file), + length = fi.Length, + Created = fi.CreationTimeUtc + }); + } + + return statusReport; } + + + + + + // List returnList = new List(); + // foreach (string file in Directory.EnumerateFiles(UtilityFilesFolder, "*")) + // { + // var fi = new FileInfo(file); + // returnList.Add(fi.Length); + // } + // returnList.Sort(); + // return returnList; + + /// /// Get date of newest backup file or minvalue if not found /// @@ -130,7 +181,7 @@ namespace AyaNova.Util var BackupPath = UtilityFilesFolder; foreach (string file in Directory.EnumerateFiles(UtilityFilesFolder, "*.backup")) { - var ThisFileTime = File.GetCreationTimeUtc(Path.Combine(BackupPath, file)); + var ThisFileTime = File.GetCreationTimeUtc(file); if (ThisFileTime > LastBackup) { LastBackup = ThisFileTime; @@ -180,41 +231,37 @@ namespace AyaNova.Util internal static void DatabaseBackupCleanUp(int keepCount) { if (keepCount < 1) keepCount = 1; - var BackupFileList = UtilityFileList("db-*.backup"); - if (BackupFileList.Count > keepCount) + //Database backups + var BackupFileList = Directory.EnumerateFiles(UtilityFilesFolder, "db-*.backup"); + if (BackupFileList.Count() > keepCount) { //sort, skip newest x (keepcount) delete the rest - var DeleteCount = BackupFileList.Count - keepCount; + var DeleteCount = BackupFileList.Count() - keepCount; var DeleteFileList = BackupFileList.OrderByDescending(m => m).Skip(keepCount).ToList(); foreach (string ExtraBackupFile in DeleteFileList) { - DeleteUtilityFile(ExtraBackupFile); + File.Delete(ExtraBackupFile); } } - } - /// - /// Cleanup excess backups (backup folder file) - /// - /// - internal static void AttachmentBackupCleanUp(int keepCount) - { - if (keepCount < 1) keepCount = 1; - var BackupFileList = UtilityFileList("at-*.zip"); - - if (BackupFileList.Count > keepCount) + //Attachment backups + BackupFileList = Directory.EnumerateFiles(UtilityFilesFolder, "at-*.zip"); + if (BackupFileList.Count() > keepCount) { //sort, skip newest x (keepcount) delete the rest - var DeleteCount = BackupFileList.Count - keepCount; + var DeleteCount = BackupFileList.Count() - keepCount; var DeleteFileList = BackupFileList.OrderByDescending(m => m).Skip(keepCount).ToList(); foreach (string ExtraBackupFile in DeleteFileList) { - DeleteUtilityFile(ExtraBackupFile); + File.Delete(ExtraBackupFile); } } + } + + #endregion Utility file handling #region Zip handling