This commit is contained in:
2020-05-19 23:54:57 +00:00
parent 337482714d
commit 81270c45de
4 changed files with 104 additions and 47 deletions

View File

@@ -8,7 +8,8 @@
working on: BACKUP finish routes, on demand and download and listing
Then test with actual attachments to ensure it's working for that part as well
Upload backup file so can restore?
only works if we have automated restore which is doubtful at any point
todo: OPS routes (SERVER AND CLIENT)
- Backup, restore https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3369

View File

@@ -1,10 +1,14 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;
using AyaNova.Models;
using AyaNova.Api.ControllerHelpers;
using AyaNova.Biz;
using System.Threading.Tasks;
using AyaNova.Biz;
using Newtonsoft.Json.Linq;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//************************************************************************************************************** */
@@ -41,7 +45,7 @@ namespace AyaNova.Api.Controllers
private readonly AyContext ct;
private readonly ILogger<BackupController> log;
private readonly ApiServerState serverState;
/// <summary>
@@ -57,21 +61,61 @@ namespace AyaNova.Api.Controllers
serverState = apiServerState;
}
/*
LOOKAT:
A backup archive consists of a similar format to the v7 data dumper utility, json file per object in subdirectories corresponding to object type all in a zip archive
Route to trigger restore from selected file
Route to force immediate backup
Backup code in biz objects "IBackup" interface (which in turn is probably going to implement an IExport interface as it serves dual purpose
of exporting data, or maybe that's special purpose custom objects for exporting like csv etc since there is likely a graph of data involved)
- object is exported / backed up to json
Restore code in biz objects "IRestore" interface
- object(s) imported via restore and data given to them or file or whatever (See discource project)
/// <summary>
/// Trigger immediate system backup
///
/// </summary>
/// <returns>Job Id</returns>
[HttpPost("backup-now")]
[Authorize]
public async Task<IActionResult> PostServerState()
{
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());
//TODO: Copy the code from ImportAyaNova7Controller upload method instead of this old crap
var JobName = $"Backup (on demand)";
OpsJob j = new OpsJob();
j.Name = JobName;
j.ObjectType = AyaType.NoType;
j.JobType = JobType.Backup;
j.SubType = JobSubType.NotSet;
j.Exclusive = true;
await JobsBiz.AddJobAsync(j, ct);
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.ServerJob, AyaEvent.Created, JobName), ct);
return Accepted(new { JobId = j.GId });
}
#region old shit
/*
LOOKAT:
A backup archive consists of a similar format to the v7 data dumper utility, json file per object in subdirectories corresponding to object type all in a zip archive
Route to trigger restore from selected file
Route to force immediate backup
Backup code in biz objects "IBackup" interface (which in turn is probably going to implement an IExport interface as it serves dual purpose
of exporting data, or maybe that's special purpose custom objects for exporting like csv etc since there is likely a graph of data involved)
- object is exported / backed up to json
Restore code in biz objects "IRestore" interface
- object(s) imported via restore and data given to them or file or whatever (See discource project)
*/
//TODO: Copy the code from ImportAyaNova7Controller upload method instead of this old crap
// /// <summary>
// /// Upload AyaNova backup files
@@ -85,7 +129,7 @@ Restore code in biz objects "IRestore" interface
// public async Task<IActionResult> Upload()
// {
// //Adapted from the example found here: https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads#uploading-large-files-with-streaming
// try
// {
// if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
@@ -158,7 +202,7 @@ Restore code in biz objects "IRestore" interface
// section = await reader.ReadNextSectionAsync();
// }
// }
@@ -183,7 +227,7 @@ Restore code in biz objects "IRestore" interface
// }
// return mediaType.Encoding;
// }
#endregion old shit
}//eoc
}//eons

View File

@@ -407,6 +407,10 @@ namespace AyaNova.Biz
switch (job.JobType)
{
case JobType.Backup:
//This is called when on demand only, normal backups are processed above with normal system jobs
await CoreJobBackup.DoWorkAsync(ct, true);
break;
case JobType.TestWidgetJob:
o = (IJobObject)BizObjectFactory.GetBizObject(AyaType.Widget, ct);
break;
@@ -422,7 +426,8 @@ namespace AyaNova.Biz
throw new System.NotSupportedException($"ProcessJobAsync type {job.JobType.ToString()} is not supported");
}
await o.HandleJobAsync(job);
if (o != null)
await o.HandleJobAsync(job);
log.LogDebug($"ProcessJobAsync -> Job completed {JobDescription}");
}

View File

@@ -22,45 +22,47 @@ namespace AyaNova.Biz
////////////////////////////////////////////////////////////////////////////////////////////////
//
//
public static async Task DoWorkAsync(AyContext ct)
public static async Task DoWorkAsync(AyContext ct, bool OnDemand = false)
{
if (BackupIsRunning) return;
log.LogTrace("Checking if backup should run");
//get NOW in utc
DateTime utcNow = DateTime.UtcNow;
//what time should we backup today?
DateTime todayBackupTime = new DateTime(utcNow.Year, utcNow.Month, utcNow.Day, ServerGlobalOpsSettings.BackupTime.Hour, ServerGlobalOpsSettings.BackupTime.Minute, 0, DateTimeKind.Utc);//first start with NOW
//Are we there yet?
if (utcNow < todayBackupTime)
if (!OnDemand)
{
log.LogTrace("Not past backup time yet"); return;//nope
log.LogTrace("Checking if backup should run");
//what time should we backup today?
DateTime todayBackupTime = new DateTime(utcNow.Year, utcNow.Month, utcNow.Day, ServerGlobalOpsSettings.BackupTime.Hour, ServerGlobalOpsSettings.BackupTime.Minute, 0, DateTimeKind.Utc);//first start with NOW
//Are we there yet?
if (utcNow < todayBackupTime)
{
log.LogTrace("Not past backup time yet"); return;//nope
}
//Yes, we've passed into the backup window time, but that's also true if we just ran the backup as well so
//need to check for that as well...
//Has last backup run more than 24 hours ago?
if (ServerGlobalOpsSettings.LastBackup > utcNow.AddHours(-24))
{
log.LogTrace("Hasn't been 24 hours since last backup yet"); return;//nope//nope, so we have already run today's backup
}
//Ok, we're into backup time and it's been more than 24 hours since it last ran so let's do this...
}
//Yes, we've passed into the backup window time, but that's also true if we just ran the backup as well so
//need to check for that as well...
//Has last backup run more than 24 hours ago?
if (ServerGlobalOpsSettings.LastBackup > utcNow.AddHours(-24))
{
log.LogTrace("Hasn't been 24 hours since last backup yet"); return;//nope//nope, so we have already run today's backup
}
//Ok, we're into backup time and it's been more than 24 hours since it last ran so let's do this...
AyaNova.Api.ControllerHelpers.ApiServerState apiServerState = null;
try
{
BackupIsRunning = true;
//LOCK DOWN SERVER
apiServerState = (AyaNova.Api.ControllerHelpers.ApiServerState)ServiceProviderProvider.Provider.GetService(typeof(AyaNova.Api.ControllerHelpers.ApiServerState));
apiServerState.SetClosed("BACKUP JOB RUNNING");
apiServerState.SetClosed("BACKUP RUNNING");
log.LogDebug("Backup starting");
//*************
//DO DATA BACKUP
//build command
//this is valid:
//this is valid on windows
//C:\data\code\PostgreSQLPortable_12.0\App\PgSQL\bin\pg_dump --dbname=postgresql://postgres:raven@127.0.0.1:5432/AyaNova -Fc > huge_new.backup
//"AYANOVA_DB_CONNECTION": "Server=localhost;Username=postgres;Password=raven;Database=AyaNova;",
Npgsql.NpgsqlConnectionStringBuilder PostgresConnectionString = new Npgsql.NpgsqlConnectionStringBuilder(ServerBootConfig.AYANOVA_DB_CONNECTION);
var DBNameParameter = $"--dbname=postgresql://{PostgresConnectionString.Username}:{PostgresConnectionString.Password}@{PostgresConnectionString.Host}:{PostgresConnectionString.Port}/{PostgresConnectionString.Database}";
@@ -80,6 +82,7 @@ namespace AyaNova.Biz
else
log.LogError($"BACKUP ERROR: {Result}");
//PRUNE DATA BACKUP SETS NOT KEPT
FileUtil.DatabaseBackupCleanUp(ServerGlobalOpsSettings.BackupSetsToKeep);
@@ -96,13 +99,14 @@ namespace AyaNova.Biz
//v.next - COPY TO ONLINE STORAGE
//***************
//Update last backup
var biz = GlobalOpsSettingsBiz.GetBiz(ct);
var OpSet = await biz.GetAsync(false);
OpSet.LastBackup = utcNow;
await biz.ReplaceAsync(OpSet);
if (!OnDemand)
{
//Update last backup
var biz = GlobalOpsSettingsBiz.GetBiz(ct);
var OpSet = await biz.GetAsync(false);
OpSet.LastBackup = utcNow;
await biz.ReplaceAsync(OpSet);
}
log.LogDebug("Backup completed");
}
catch (Exception ex)
@@ -116,6 +120,9 @@ namespace AyaNova.Biz
BackupIsRunning = false;
}
}
/////////////////////////////////////////////////////////////////////
}//eoc
}//eons