aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs
diff options
context:
space:
mode:
authorVictoria Plitt <Victoria.Plitt@twine-s.com>2019-12-09 17:00:30 +0200
committerVictoria Plitt <Victoria.Plitt@twine-s.com>2019-12-09 17:00:30 +0200
commit31ece903df45b0ab8ffb61fdd290d9fbea2a6836 (patch)
tree180be785ceb98fb828009eeae4dfa3bbc8a738b7 /Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs
parent4417c2eccb3795330144afa39e3bf271652bd31f (diff)
parentaeabb681d16451e191a1620d4eebf40549771491 (diff)
downloadTango-31ece903df45b0ab8ffb61fdd290d9fbea2a6836.tar.gz
Tango-31ece903df45b0ab8ffb61fdd290d9fbea2a6836.zip
Merge branch 'master' of https://twinetfs.visualstudio.com/Tango/_git/Tango
Diffstat (limited to 'Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs')
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs210
1 files changed, 194 insertions, 16 deletions
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs
index dacd1b69a..5296a9f34 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs
@@ -9,6 +9,7 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using Tango.BL;
using Tango.Core;
using Tango.Core.DB;
using Tango.Core.ExtensionMethods;
@@ -16,9 +17,12 @@ using Tango.Core.Helpers;
using Tango.Core.IO;
using Tango.Integration.Operation;
using Tango.Integration.Upgrade;
+using Tango.Logging;
using Tango.PMR.Synchronization;
using Tango.PPC.Common.Application;
using Tango.PPC.Common.Connection;
+using Tango.PPC.Common.Navigation;
+using Tango.PPC.Common.UpdatePackages;
using Tango.PPC.Common.Web;
using Tango.Settings;
using Tango.SharedUI.Helpers;
@@ -31,11 +35,20 @@ namespace Tango.PPC.Common.MachineUpdate
{
private IPPCApplicationManager _app_manager;
private IMachineProvider _machineProvider;
+ private IPackageRunner _packageRunner;
private PPCWebClient _client;
+ private List<LogItemBase> _logs;
+ private System.Timers.Timer _checkForUpdateTimer;
+ private bool _isUpdating;
#region Events
/// <summary>
+ /// Occurs when an application update is available.
+ /// </summary>
+ public event EventHandler<CheckForUpdateResponse> UpdateAvailable;
+
+ /// <summary>
/// Occurs when there is a text log message available.
/// </summary>
public event EventHandler<string> ProgressLog;
@@ -50,12 +63,25 @@ namespace Tango.PPC.Common.MachineUpdate
#region Properties
private MachineUpdateProgress _status;
+ /// <summary>
+ /// Gets the current machine update progress status.
+ /// </summary>
public MachineUpdateProgress Status
{
get { return _status; }
private set { _status = value; RaisePropertyChangedAuto(); }
}
+ private bool _autoCheckForUpdates;
+ /// <summary>
+ /// Gets or sets a value indicating whether to automatically check for new application updates.
+ /// </summary>
+ public bool AutoCheckForUpdates
+ {
+ get { return _autoCheckForUpdates; }
+ set { _autoCheckForUpdates = value; RaisePropertyChangedAuto(); }
+ }
+
#endregion
#region Constructors
@@ -64,11 +90,34 @@ namespace Tango.PPC.Common.MachineUpdate
/// Initializes a new instance of the <see cref="MachineUpdateManager"/> class.
/// </summary>
/// <param name="applicationManager">The application manager.</param>
- public MachineUpdateManager(PPCWebClient ppcWebClient, IPPCApplicationManager applicationManager, IMachineProvider machineProvider)
+ public MachineUpdateManager(PPCWebClient ppcWebClient, IPPCApplicationManager applicationManager, IMachineProvider machineProvider, IPackageRunner packageRunner)
{
_client = ppcWebClient;
_machineProvider = machineProvider;
_app_manager = applicationManager;
+ _packageRunner = packageRunner;
+ _packageRunner.PackageStateChanged += _packageRunner_PackageStateChanged;
+
+ _logs = new List<LogItemBase>();
+ LogManager.NewLog += LogManager_NewLog;
+
+ _checkForUpdateTimer = new System.Timers.Timer(TimeSpan.FromMinutes(1).TotalMilliseconds);
+ _checkForUpdateTimer.Elapsed += _checkForUpdateTimer_Elapsed;
+ _checkForUpdateTimer.Start();
+ }
+
+ #endregion
+
+ #region Event Handlers
+
+ private void _packageRunner_PackageStateChanged(object sender, PackageStateChangedEventArgs e)
+ {
+ UpdateProgress(e.PackageType == PackageType.Pre ? "Preparing" : "Finalizing", e.PackageName);
+ }
+
+ private void LogManager_NewLog(object sender, LogItemBase e)
+ {
+ _logs.Add(e);
}
#endregion
@@ -127,6 +176,7 @@ namespace Tango.PPC.Common.MachineUpdate
Token = response.NotifyCompletedToken,
Status = BL.Enumerations.TangoUpdateStatuses.UpdateFailed,
FailedReason = ex.FlattenMessage(),
+ FailedLog = GetLogsStringAndClear(),
});
}
catch (Exception xx)
@@ -134,6 +184,8 @@ namespace Tango.PPC.Common.MachineUpdate
LogManager.Log(xx, "Error notifying update failed.");
}
}
+
+ _isUpdating = false;
}
private async void OnCompleted(MachineUpdateResult result, TaskCompletionSource<MachineUpdateResult> completionSource, DownloadUpdateResponse response, String dbBackupFile)
@@ -161,6 +213,8 @@ namespace Tango.PPC.Common.MachineUpdate
LogManager.Log(ex, "Error notifying update completed.");
}
}
+
+ _isUpdating = false;
}
private void OnCompleted(UpdateDBResponse response)
@@ -180,6 +234,8 @@ namespace Tango.PPC.Common.MachineUpdate
LogManager.Log(ex, "Error notifying database completed.");
}
}
+
+ _isUpdating = false;
}
private void OnFailed(Exception ex, UpdateDBResponse response, bool performDatabaseRollback, String dbBackupFile, Tango.Core.DataSource localDataSource)
@@ -223,6 +279,7 @@ namespace Tango.PPC.Common.MachineUpdate
Token = response.NotifyCompletedToken,
Status = BL.Enumerations.TangoUpdateStatuses.DatabaseFailed,
FailedReason = ex.FlattenMessage(),
+ FailedLog = GetLogsStringAndClear(),
}).Result;
}
catch (Exception xx)
@@ -230,6 +287,15 @@ namespace Tango.PPC.Common.MachineUpdate
LogManager.Log(xx, "Error notifying database failed.");
}
}
+
+ _isUpdating = false;
+ }
+
+ private String GetLogsStringAndClear()
+ {
+ String logsString = String.Join(Environment.NewLine, _logs.ToList().Select(x => x.ToString()));
+ _logs.Clear();
+ return logsString;
}
#endregion
@@ -251,6 +317,8 @@ namespace Tango.PPC.Common.MachineUpdate
/// <exception cref="System.InvalidProgramException">Database tango does not exists.</exception>
public async Task<MachineUpdateResult> Update(String serialNumber, bool setupFirmware, bool setupFPGA)
{
+ _logs.Clear();
+
TaskCompletionSource<MachineUpdateResult> result = new TaskCompletionSource<MachineUpdateResult>();
var localDataSource = SettingsManager.Default.GetOrCreate<CoreSettings>().DataSource;
@@ -260,6 +328,8 @@ namespace Tango.PPC.Common.MachineUpdate
try
{
+ _isUpdating = true;
+
var machineServiceAddress = SettingsManager.Default.GetOrCreate<PPCSettings>().GetMachineServiceAddress();
LogManager.Log($"Starting machine update for serial number {serialNumber}...");
@@ -281,7 +351,7 @@ namespace Tango.PPC.Common.MachineUpdate
{
throw LogManager.Log(new InvalidOperationException("Could not perform an update while the machine is not connected."));
}
- if (op.IsPrinting)
+ if (op.Status != MachineStatuses.ReadyToDye)
{
throw LogManager.Log(new InvalidOperationException($"Could not perform an update while the machine is in {op.Status} status."));
}
@@ -314,22 +384,30 @@ namespace Tango.PPC.Common.MachineUpdate
LogManager.Log("Downloading software package...");
- long fileSize = 0;
UpdateProgress("Downloading software package", "Downloading...", false);
- using (FileStreamWrapper fs = new FileStreamWrapper(tempFile.Path, FileMode.Create, (current) =>
+ using (AutoFileDownloader downloader = new AutoFileDownloader(update_response.BlobAddress, update_response.CdnAddress, tempFile))
{
- UpdateProgress("Downloading software package", "Downloading...", false, current, fileSize);
- }))
- {
- LogManager.Log($"Connecting to storage blob with address {update_response.BlobAddress}");
- CloudBlockBlob blob = new CloudBlockBlob(new Uri(update_response.BlobAddress));
- LogManager.Log("Fetching blob attributes...");
- blob.FetchAttributes();
- fileSize = blob.Properties.Length;
- LogManager.Log("Download size: " + fileSize + " bytes.");
- LogManager.Log("Starting blob download...");
- blob.DownloadToStream(fs);
+ await downloader.ResolveMode();
+
+ if (downloader.Mode == AutoFileDownloader.DownloadMode.Standard)
+ {
+ LogManager.Log($"Connecting to storage CDN with address {downloader.Address}");
+ }
+ else
+ {
+ LogManager.Log($"Connecting to storage blob with address {downloader.Address}");
+ }
+
+ downloader.Progress += (x, e) =>
+ {
+ UpdateProgress("Downloading software package", "Downloading...", false, e.Current, e.Total);
+ };
+
+ var size = await downloader.GetFileSize();
+ LogManager.Log("Download size: " + size + " bytes.");
+ LogManager.Log("Starting file download...");
+ await downloader.Download();
}
UpdateProgress("Downloading software package", "Extracting package...");
@@ -338,11 +416,33 @@ namespace Tango.PPC.Common.MachineUpdate
//Extract software package.
ZipFile.ExtractToDirectory(tempFile, _newPackageTempFolder);
-
LogManager.Log("Copying latest updater utility to application path...");
//Copy new updater utility to app path.
File.Copy(Path.Combine(_newPackageTempFolder, "Tango.PPC.Updater.exe"), Path.Combine(PathHelper.GetStartupPath(), "Tango.PPC.Updater.exe"), true);
+ //Run pre-update packages.
+ try
+ {
+ UpdateProgress("Preparing", "Running update packages...");
+ LogManager.Log("Running pre-update packages...");
+ var packagesFolder = Path.Combine(_newPackageTempFolder, "Packages");
+
+ Version updateVersion = new Version(1, 0, 0, 0);
+ try
+ {
+ updateVersion = Version.Parse(update_response.Version);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error parsing new version string for package runner.");
+ }
+
+ await _packageRunner.Run(PackageType.Pre, updateVersion, packagesFolder);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error running pre-update packages...");
+ }
//Synchronize database
UpdateProgress("Updating Database", "Initializing...");
@@ -495,6 +595,8 @@ namespace Tango.PPC.Common.MachineUpdate
{
return Task.Factory.StartNew<CheckForUpdateResponse>(() =>
{
+ _isUpdating = true;
+
var machineServiceAddress = SettingsManager.Default.GetOrCreate<PPCSettings>().GetMachineServiceAddress();
LogManager.Log($"Connecting to machine service on {machineServiceAddress}...");
@@ -507,12 +609,28 @@ namespace Tango.PPC.Common.MachineUpdate
request.SerialNumber = serialNumber;
request.Version = _app_manager.Version.ToString();
+ try
+ {
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ request.Rmls = db.Rmls.ToList().Select(x => new UpdatedEntity(x)).ToList();
+ request.HardwareVersions = db.HardwareVersions.ToList().Select(x => new UpdatedEntity(x)).ToList();
+ request.Catalogs = db.ColorCatalogs.ToList().Select(x => new UpdatedEntity(x)).ToList();
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "An error occurred while trying to fill the existing database entities before checking for updates.");
+ }
+
CheckForUpdateResponse update_response = null;
update_response = _client.CheckForUpdates(request).Result;
LogManager.Log($"Check for update response received: {Environment.NewLine}{update_response.ToJsonString()}");
+ _isUpdating = false;
+
return update_response;
});
}
@@ -525,8 +643,11 @@ namespace Tango.PPC.Common.MachineUpdate
/// <returns></returns>
public Task UpdateDB(DbCompareResult dbCompareResult, String serialNumber)
{
+ _logs.Clear();
+
return Task.Factory.StartNew(() =>
{
+ _isUpdating = true;
UpdateDBResponse update_response = null;
var localDataSource = SettingsManager.Default.GetOrCreate<CoreSettings>().DataSource;
bool performDatabaseRollback = false;
@@ -808,6 +929,37 @@ namespace Tango.PPC.Common.MachineUpdate
});
}
+ /// <summary>
+ /// Checks whether any post update packages needs to be installed.
+ /// </summary>
+ /// <returns></returns>
+ public Task<bool> PostUpdatePackagesRequired()
+ {
+ String packagesFolder = Path.Combine(AssemblyHelper.GetCurrentAssemblyFolder(), "packages");
+ return _packageRunner.IsPackageInstallationRequired(PackageType.Post, packagesFolder);
+ }
+
+ /// <summary>
+ /// Runs all post update packages.
+ /// </summary>
+ /// <returns></returns>
+ public Task<PackageRunnerResult> RunPostUpdatePackages()
+ {
+ String packagesFolder = Path.Combine(AssemblyHelper.GetCurrentAssemblyFolder(), "packages");
+
+ Version previousVersion = null;
+ String str = SettingsManager.Default.GetOrCreate<PPCSettings>().PreviousApplicationVersion;
+
+ if (Version.TryParse(str, out previousVersion))
+ {
+ return _packageRunner.Run(PackageType.Post, previousVersion, packagesFolder);
+ }
+ else
+ {
+ throw new InvalidCastException($"Error parsing the previous version string '{str}'.");
+ }
+ }
+
#endregion
#region Protected Methods
@@ -832,5 +984,31 @@ namespace Tango.PPC.Common.MachineUpdate
}
#endregion
+
+ #region Auto Check For Update
+
+ private async void _checkForUpdateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
+ {
+ if (AutoCheckForUpdates && !_isUpdating)
+ {
+ _checkForUpdateTimer.Stop();
+
+ try
+ {
+ var response = await CheckForUpdate(_machineProvider.Machine.SerialNumber);
+ if (response.IsUpdateAvailable || response.IsDatabaseUpdateAvailable)
+ {
+ _checkForUpdateTimer.Interval = TimeSpan.FromMinutes(60).TotalMilliseconds;
+ LogManager.Log($"New {(response.IsDatabaseUpdateAvailable ? "database updates" : "application version")} detected ({response.Version}). Raising event...");
+ UpdateAvailable?.Invoke(this, response);
+ }
+ }
+ catch { }
+
+ _checkForUpdateTimer.Start();
+ }
+ }
+
+ #endregion
}
}