aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs
diff options
context:
space:
mode:
authorAvi Levkovich <avi@twine-s.com>2019-12-17 14:37:38 +0200
committerAvi Levkovich <avi@twine-s.com>2019-12-17 14:37:38 +0200
commit8a7e65715ef393a08cc39d1b5d4a3da22799c852 (patch)
treef71065b4c0000aafad1356ff2ab6b17f8287476b /Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs
parentc653fa2077b6118c2ace3b7bcc8bc91c9a9ed4f5 (diff)
parent3ed7e9cc55e10888d84aa53abcb5e765a317ddb1 (diff)
downloadTango-8a7e65715ef393a08cc39d1b5d4a3da22799c852.tar.gz
Tango-8a7e65715ef393a08cc39d1b5d4a3da22799c852.zip
merge conflicts
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.cs1153
1 files changed, 992 insertions, 161 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 b7573ec60..d0424254b 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,8 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using Tango.BL;
+using Tango.BL.Entities;
using Tango.Core;
using Tango.Core.DB;
using Tango.Core.ExtensionMethods;
@@ -16,14 +18,19 @@ 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.Publish;
+using Tango.PPC.Common.UpdatePackages;
using Tango.PPC.Common.Web;
using Tango.Settings;
using Tango.SharedUI.Helpers;
using Tango.SQLExaminer;
using Tango.Transport.Web;
+using System.Data.Entity;
namespace Tango.PPC.Common.MachineUpdate
{
@@ -31,11 +38,22 @@ 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;
+ private PPCSettings _settings;
+ private DateTime _updateStartDate;
#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 +68,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 EnableAutoCheckForUpdates
+ {
+ get { return _autoCheckForUpdates; }
+ set { _autoCheckForUpdates = value; RaisePropertyChangedAuto(); }
+ }
+
#endregion
#region Constructors
@@ -64,11 +95,39 @@ 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.PackageProgress += _packageRunner_PackageProgress;
+
+ _logs = new List<LogItemBase>();
+ LogManager.NewLog += LogManager_NewLog;
+
+ _checkForUpdateTimer = new System.Timers.Timer(TimeSpan.FromMinutes(1).TotalMilliseconds);
+ _checkForUpdateTimer.Elapsed += _checkForUpdateTimer_Elapsed;
+ _checkForUpdateTimer.Start();
+
+ _settings = SettingsManager.Default.GetOrCreate<PPCSettings>();
+ }
+
+ #endregion
+
+ #region Event Handlers
+
+ private void _packageRunner_PackageProgress(object sender, PackageProgressEventArgs e)
+ {
+ UpdateProgress(e.PackageName, e.Message, e.IsIntermediate, e.Progress, e.Total);
+ }
+
+ private void LogManager_NewLog(object sender, LogItemBase e)
+ {
+ if (_isUpdating)
+ {
+ _logs.Add(e);
+ }
}
#endregion
@@ -84,6 +143,387 @@ namespace Tango.PPC.Common.MachineUpdate
});
}
+ private async void OnFailed(Exception ex, TaskCompletionSource<MachineUpdateResult> completionSource, DownloadUpdateResponse response, bool performDatabaseRollback, String dbBackupFile, String backupsFolder, String tempDbName, Tango.Core.DataSource localDataSource, String tempUpdatePackageFolder = null, PublishInfo tupPublishInfo = null)
+ {
+ LogManager.Log(ex, "An error occurred in machine update.");
+
+ await Task.Factory.StartNew(() =>
+ {
+
+ if (performDatabaseRollback)
+ {
+ LogManager.Log("Rolling back database changes...");
+
+ using (DbManager db = DbManager.FromDataSource(localDataSource))
+ {
+ try
+ {
+ UpdateProgress("Rollback", "Rolling back database changes...");
+ db.Restore(localDataSource.Catalog, dbBackupFile);
+ LogManager.Log("Database restored successfully.");
+ }
+ catch (Exception e)
+ {
+ LogManager.Log(e, "Could not rollback the database.");
+ }
+ finally
+ {
+ try
+ {
+ File.Delete(dbBackupFile);
+ }
+ catch { }
+ }
+ }
+ }
+
+ if (tempDbName != null)
+ {
+ try
+ {
+ LogManager.Log($"Removing temporary database '{tempDbName}'...");
+ using (DbManager dbManager = DbManager.FromDataSource(localDataSource))
+ {
+ dbManager.SetOffline(tempDbName);
+ dbManager.SetOnline(tempDbName);
+ dbManager.Delete(tempDbName);
+ }
+ }
+ catch (Exception exx)
+ {
+ LogManager.Log(exx, "Error removing temporary database.");
+ }
+ }
+
+ try
+ {
+ Directory.Delete(backupsFolder, true);
+ }
+ catch (Exception ee)
+ {
+ LogManager.Log(ee, $"Error deleting backups folder '{backupsFolder}'.");
+ }
+
+ if (tempUpdatePackageFolder != null)
+ {
+ try
+ {
+ Directory.Delete(tempUpdatePackageFolder, true);
+ }
+ catch (Exception eee)
+ {
+ LogManager.Log(eee, "Error removing temporary package folder.");
+ }
+ }
+
+ });
+
+ completionSource.SetException(ex);
+
+ String logs = GetLogsStringAndClear();
+
+ if (response != null)
+ {
+ try
+ {
+ var result = await _client.NotifyUpdateCompleted(new MachineUpdateCompletedRequest()
+ {
+ Token = response.NotifyCompletedToken,
+ Status = BL.Enumerations.TangoUpdateStatuses.UpdateFailed,
+ FailedReason = ex.FlattenMessage(),
+ FailedLog = logs,
+ });
+ }
+ catch (Exception xx)
+ {
+ LogManager.Log(xx, "Error notifying update failed.");
+ }
+
+ try
+ {
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ TangoUpdate update = new TangoUpdate();
+ update.ApplicationVersion = response.Version;
+ update.FirmwareVersion = response.FirmwareVersion;
+ update.MachineGuid = _machineProvider.Machine.Guid;
+ update.UpdateStatus = BL.Enumerations.TangoUpdateStatuses.UpdateFailed;
+ update.StartDate = _updateStartDate;
+ update.EndDate = DateTime.UtcNow;
+ update.FailedReason = ex.FlattenMessage();
+ update.FailedLog = logs;
+ await db.SaveChangesAsync();
+ }
+ }
+ catch (Exception xxx)
+ {
+ LogManager.Log(xxx, "Error saving tango update information to database.");
+ }
+ }
+
+
+ if (tupPublishInfo != null)
+ {
+ try
+ {
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ TangoUpdate update = new TangoUpdate();
+ update.ApplicationVersion = tupPublishInfo.ApplicationVersion;
+ update.FirmwareVersion = tupPublishInfo.GetFirmwareVersion();
+ update.MachineGuid = _machineProvider.Machine.Guid;
+ update.UpdateStatus = BL.Enumerations.TangoUpdateStatuses.OfflineUpdateFailed;
+ update.StartDate = _updateStartDate;
+ update.EndDate = DateTime.UtcNow;
+ update.FailedReason = ex.FlattenMessage();
+ update.FailedLog = logs;
+ await db.SaveChangesAsync();
+ }
+ }
+ catch (Exception xxx)
+ {
+ LogManager.Log(xxx, "Error saving tango offline update information to database.");
+ }
+ }
+
+ _isUpdating = false;
+ }
+
+ private async void OnCompleted(MachineUpdateResult result, TaskCompletionSource<MachineUpdateResult> completionSource, DownloadUpdateResponse response, String tempDbName, String backupsFolder, Core.DataSource localDataSource, PublishInfo tupPublishInfo = null)
+ {
+ await Task.Factory.StartNew(() =>
+ {
+ if (tempDbName != null)
+ {
+ try
+ {
+ LogManager.Log($"Removing temporary database '{tempDbName}'...");
+ using (DbManager dbManager = DbManager.FromDataSource(localDataSource))
+ {
+ dbManager.SetOffline(tempDbName);
+ dbManager.SetOnline(tempDbName);
+ dbManager.Delete(tempDbName);
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error removing temporary database.");
+ }
+ }
+
+ try
+ {
+ Directory.Delete(backupsFolder, true);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, $"Error deleting backups folder '{backupsFolder}'.");
+ }
+
+ if (!result.RequiresBinariesUpdate)
+ {
+ try
+ {
+ Directory.Delete(result.UpdatePackagePath, true);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error removing temporary package folder.");
+ }
+ }
+
+ });
+
+ completionSource.SetResult(result);
+
+ if (response != null)
+ {
+ try
+ {
+ var r = await _client.NotifyUpdateCompleted(new MachineUpdateCompletedRequest()
+ {
+ Token = response.NotifyCompletedToken,
+ Status = BL.Enumerations.TangoUpdateStatuses.UpdateCompleted,
+ });
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error notifying update completed.");
+ }
+
+ try
+ {
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ TangoUpdate update = new TangoUpdate();
+ update.ApplicationVersion = response.Version;
+ update.FirmwareVersion = response.FirmwareVersion;
+ update.MachineGuid = (await db.Machines.FirstAsync()).Guid;
+ update.UpdateStatus = BL.Enumerations.TangoUpdateStatuses.UpdateCompleted;
+ update.StartDate = _updateStartDate;
+ update.EndDate = DateTime.UtcNow;
+ await db.SaveChangesAsync();
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error saving tango update information to database.");
+ }
+ }
+
+
+ if (tupPublishInfo != null)
+ {
+ try
+ {
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ TangoUpdate update = new TangoUpdate();
+ update.ApplicationVersion = tupPublishInfo.ApplicationVersion;
+ update.FirmwareVersion = tupPublishInfo.GetFirmwareVersion();
+ update.MachineGuid = _machineProvider.Machine.Guid;
+ update.UpdateStatus = BL.Enumerations.TangoUpdateStatuses.OfflineUpdateCompleted;
+ update.StartDate = _updateStartDate;
+ update.EndDate = DateTime.UtcNow;
+ await db.SaveChangesAsync();
+ }
+ }
+ catch (Exception xxx)
+ {
+ LogManager.Log(xxx, "Error saving tango offline update information to database.");
+ }
+ }
+
+ _isUpdating = false;
+ }
+
+ private void OnFailed(Exception ex, UpdateDBResponse response, bool performDatabaseRollback, String dbBackupFile, Tango.Core.DataSource localDataSource)
+ {
+ LogManager.Log(ex, "An error occurred in database update.");
+
+ if (performDatabaseRollback)
+ {
+ LogManager.Log("Rolling back database changes...");
+
+ using (DbManager db = DbManager.FromDataSource(localDataSource))
+ {
+ try
+ {
+ UpdateProgress("Rollback", "Rolling back database changes...");
+ db.Restore(localDataSource.Catalog, dbBackupFile);
+ LogManager.Log("Database restored successfully.");
+ }
+ catch (Exception e)
+ {
+ LogManager.Log(e, "Could not rollback the database.");
+ throw ex;
+ }
+ finally
+ {
+ try
+ {
+ File.Delete(dbBackupFile);
+ }
+ catch { }
+ }
+ }
+ }
+
+ String logs = GetLogsStringAndClear();
+
+ if (response != null)
+ {
+ try
+ {
+ var r = _client.NotifyUpdateCompleted(new MachineUpdateCompletedRequest()
+ {
+ Token = response.NotifyCompletedToken,
+ Status = BL.Enumerations.TangoUpdateStatuses.DatabaseFailed,
+ FailedReason = ex.FlattenMessage(),
+ FailedLog = logs,
+ }).Result;
+ }
+ catch (Exception xx)
+ {
+ LogManager.Log(xx, "Error notifying database failed.");
+ }
+
+ try
+ {
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ TangoUpdate update = new TangoUpdate();
+ update.ApplicationVersion = _app_manager.Version.ToString();
+ update.FirmwareVersion = _app_manager.FirmwareVersion.ToString();
+ update.MachineGuid = _machineProvider.Machine.Guid;
+ update.UpdateStatus = BL.Enumerations.TangoUpdateStatuses.DatabaseFailed;
+ update.StartDate = _updateStartDate;
+ update.EndDate = DateTime.UtcNow;
+ update.FailedReason = ex.FlattenMessage();
+ update.FailedLog = logs;
+ db.SaveChanges();
+ }
+ }
+ catch (Exception exx)
+ {
+ LogManager.Log(exx, "Error saving database update information to database.");
+ }
+ }
+
+ _isUpdating = false;
+ }
+
+ private void OnCompleted(UpdateDBResponse response, bool completedWithNoDifferences = false)
+ {
+ if (response != null)
+ {
+ try
+ {
+ var r = _client.NotifyUpdateCompleted(new MachineUpdateCompletedRequest()
+ {
+ Token = response.NotifyCompletedToken,
+ Status = BL.Enumerations.TangoUpdateStatuses.DatabaseCompleted,
+ ReportsAboutDbCheckNoDifferences = completedWithNoDifferences,
+ }).Result;
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error notifying database completed.");
+ }
+
+ if (!completedWithNoDifferences)
+ {
+ try
+ {
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ TangoUpdate update = new TangoUpdate();
+ update.ApplicationVersion = _app_manager.Version.ToString();
+ update.FirmwareVersion = _app_manager.FirmwareVersion.ToString();
+ update.MachineGuid = _machineProvider.Machine.Guid;
+ update.UpdateStatus = BL.Enumerations.TangoUpdateStatuses.DatabaseCompleted;
+ update.StartDate = _updateStartDate;
+ update.EndDate = DateTime.UtcNow;
+ db.SaveChanges();
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error saving database update information to database.");
+ }
+ }
+ }
+
+ _isUpdating = false;
+ }
+
+ private String GetLogsStringAndClear()
+ {
+ String logsString = String.Join(Environment.NewLine, _logs.ToList().Select(x => x.ToString()));
+ _logs.Clear();
+ return logsString;
+ }
+
#endregion
#region Public Methods
@@ -101,17 +541,30 @@ namespace Tango.PPC.Common.MachineUpdate
/// or
/// </exception>
/// <exception cref="System.InvalidProgramException">Database tango does not exists.</exception>
- public async Task<MachineUpdateResult> Update(String serialNumber, bool setupFirmware, bool setupFPGA)
+ public async Task<MachineUpdateResult> Update(bool setupFirmware, bool setupFPGA)
{
+ _updateStartDate = DateTime.UtcNow;
+ _logs.Clear();
+
TaskCompletionSource<MachineUpdateResult> result = new TaskCompletionSource<MachineUpdateResult>();
var localDataSource = SettingsManager.Default.GetOrCreate<CoreSettings>().DataSource;
bool performDatabaseRollback = false;
String dbBackupFile = null;
+ DownloadUpdateResponse update_response = null;
+ String backupsFolder = "C:\\Backups";
+
+ //Create temporary folders for packages.
+ var _newPackageTempFolder = TemporaryManager.CreateFolder();
+ _newPackageTempFolder.Persist = true;
+
+ String serialNumber = _machineProvider.Machine.SerialNumber;
try
{
- var machineServiceAddress = SettingsManager.Default.GetOrCreate<PPCSettings>().GetMachineServiceAddress();
+ _isUpdating = true;
+
+ var machineServiceAddress = _settings.GetMachineServiceAddress();
LogManager.Log($"Starting machine update for serial number {serialNumber}...");
@@ -132,7 +585,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."));
}
@@ -148,16 +601,10 @@ namespace Tango.PPC.Common.MachineUpdate
DownloadUpdateRequest request = new DownloadUpdateRequest();
request.SerialNumber = serialNumber;
- DownloadUpdateResponse update_response = null;
-
update_response = await _client.MachineUpdate(request);
LogManager.Log($"Machine update response received: {Environment.NewLine}{update_response.ToJsonString()}");
- //Create temporary folders for packages.
- var _newPackageTempFolder = TemporaryManager.CreateFolder();
- _newPackageTempFolder.Persist = true;
-
LogManager.Log($"Temporary package folder created: {_newPackageTempFolder}.");
//Download software package.
@@ -167,35 +614,69 @@ 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) =>
- {
- UpdateProgress("Downloading software package", "Downloading...", false, current, fileSize);
- }))
+ using (AutoFileDownloader downloader = new AutoFileDownloader(update_response.BlobAddress, update_response.CdnAddress, tempFile))
{
- 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...");
LogManager.Log("Extracting downloaded zip file...");
- //Extract software package.
- ZipFile.ExtractToDirectory(tempFile, _newPackageTempFolder);
+ await Task.Factory.StartNew(() =>
+ {
+ //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...");
@@ -212,25 +693,24 @@ namespace Tango.PPC.Common.MachineUpdate
throw new InvalidProgramException("Database tango does not exists.");
}
- if (setupFirmware)
- {
- LogManager.Log("Setup firmware is active so a database rollback procedure should be configured.");
- UpdateProgress("Updating Database", "Creating database backup...");
+ UpdateProgress("Updating Database", "Creating database backup...");
- try
- {
- Directory.CreateDirectory("C:\\Backups");
- dbBackupFile = $"C:\\Backups\\{Path.GetRandomFileName()}.bak";
- LogManager.Log($"Creating database backup to '{dbBackupFile}'...");
- await Task.Factory.StartNew(() => db.Backup(localDataSource.Catalog, dbBackupFile));
- LogManager.Log("Database backup created successfully.");
- }
- catch (Exception ex)
- {
- throw LogManager.Log(ex, "Setup manager error while trying to create a database backup.");
- }
+ //Create Database Backup
+ try
+ {
+ Directory.CreateDirectory(backupsFolder);
+ dbBackupFile = $"{backupsFolder}\\{Path.GetRandomFileName()}.bak";
+ LogManager.Log($"Creating database backup to '{dbBackupFile}'...");
+ await Task.Factory.StartNew(() => db.Backup(localDataSource.Catalog, dbBackupFile));
+ performDatabaseRollback = true;
+ LogManager.Log("Database backup created successfully.");
+ }
+ catch (Exception ex)
+ {
+ throw LogManager.Log(ex, "Update manager error while trying to create a database backup.");
}
+
LogManager.Log("Disposing database manager.");
db.Dispose();
@@ -267,14 +747,12 @@ namespace Tango.PPC.Common.MachineUpdate
}
catch (Exception ex)
{
- throw LogManager.Log(ex, "Setup manager error while trying to synchronize database.");
+ throw LogManager.Log(ex, "Update manager error while trying to synchronize database.");
}
//Updating firmware
if (setupFirmware)
{
- performDatabaseRollback = true;
-
UpdateProgress("Updating Firmware", "Connecting to firmware device...");
LogManager.Log("");
LogManager.Log("-------------------------------------------------------------------------");
@@ -284,34 +762,41 @@ namespace Tango.PPC.Common.MachineUpdate
var tfpPath = Path.Combine(_newPackageTempFolder, "firmware_package.tfp");
var stream = new FileStream(tfpPath, FileMode.Open);
- if (setupFPGA)
+ if (!_machineProvider.Machine.IsDemo)
{
- op.FirmwareUpgradeMode = FirmwareUpgradeModes.DFU | FirmwareUpgradeModes.TFP_PACKAGE;
+ if (setupFPGA)
+ {
+ op.FirmwareUpgradeMode = FirmwareUpgradeModes.DFU | FirmwareUpgradeModes.TFP_PACKAGE;
+ }
+ else
+ {
+ op.FirmwareUpgradeMode = FirmwareUpgradeModes.DFU;
+ }
}
else
{
- op.FirmwareUpgradeMode = FirmwareUpgradeModes.DFU;
+ op.FirmwareUpgradeMode = FirmwareUpgradeModes.TFP_PACKAGE;
}
var handler = await op.UpgradeFirmware(stream);
handler.Failed += (_, ex) =>
{
stream.Dispose();
- throw ex;
+ OnFailed(ex, result, update_response, performDatabaseRollback, dbBackupFile, backupsFolder, null, localDataSource, _newPackageTempFolder);
};
handler.Completed += (_, __) =>
{
UpdateProgress("Updating Firmware", "Firmware update completed successfully.");
stream.Dispose();
- result.SetResult(new MachineUpdateResult()
+ OnCompleted(new MachineUpdateResult()
{
UpdatePackagePath = _newPackageTempFolder,
- });
+ }, result, update_response, null, backupsFolder, localDataSource);
};
handler.Canceled += (_, __) =>
{
stream.Dispose();
- throw new Exception("The operation has been canceled.");
+ OnFailed(new Exception("The operation has been canceled."), result, update_response, performDatabaseRollback, dbBackupFile, backupsFolder, null, localDataSource, _newPackageTempFolder);
};
handler.Progress += (_, e) =>
{
@@ -320,53 +805,15 @@ namespace Tango.PPC.Common.MachineUpdate
}
else
{
- result.SetResult(new MachineUpdateResult()
+ OnCompleted(new MachineUpdateResult()
{
UpdatePackagePath = _newPackageTempFolder,
- });
+ }, result, update_response, null, backupsFolder, localDataSource);
}
}
catch (Exception ex)
{
- LogManager.Log(ex, "An error occurred in machine update.");
-
- if (performDatabaseRollback)
- {
- LogManager.Log("Rolling back database changes...");
-
- using (DbManager db = DbManager.FromDataSource(localDataSource))
- {
- try
- {
- UpdateProgress("Rollback", "Rolling back database changes...");
- await Task.Factory.StartNew(() => db.Restore(localDataSource.Catalog, dbBackupFile));
- LogManager.Log("Database restored successfully.");
- }
- catch (Exception e)
- {
- LogManager.Log(e, "Could not rollback the database.");
- throw ex;
- }
- finally
- {
- try
- {
- File.Delete(dbBackupFile);
- }
- catch { }
- }
- }
- }
-
- result.SetException(ex);
- }
- finally
- {
- try
- {
- File.Delete(dbBackupFile);
- }
- catch { }
+ OnFailed(ex, result, update_response, performDatabaseRollback, dbBackupFile, backupsFolder, null, localDataSource, _newPackageTempFolder);
}
return await result.Task;
@@ -382,7 +829,9 @@ namespace Tango.PPC.Common.MachineUpdate
{
return Task.Factory.StartNew<CheckForUpdateResponse>(() =>
{
- var machineServiceAddress = SettingsManager.Default.GetOrCreate<PPCSettings>().GetMachineServiceAddress();
+ _isUpdating = true;
+
+ var machineServiceAddress = _settings.GetMachineServiceAddress();
LogManager.Log($"Connecting to machine service on {machineServiceAddress}...");
@@ -394,12 +843,30 @@ namespace Tango.PPC.Common.MachineUpdate
request.SerialNumber = serialNumber;
request.Version = _app_manager.Version.ToString();
+ try
+ {
+ request.MachineLastUpdated = _machineProvider.Machine.LastUpdated;
+
+ 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;
});
}
@@ -412,75 +879,121 @@ namespace Tango.PPC.Common.MachineUpdate
/// <returns></returns>
public Task UpdateDB(DbCompareResult dbCompareResult, String serialNumber)
{
+ _updateStartDate = DateTime.UtcNow;
+ _logs.Clear();
+
return Task.Factory.StartNew(() =>
{
- LogManager.Log("Starting database update...");
+ _isUpdating = true;
+ UpdateDBResponse update_response = null;
+ var localDataSource = SettingsManager.Default.GetOrCreate<CoreSettings>().DataSource;
+ bool performDatabaseRollback = false;
+ String dbBackupFile = null;
- UpdateProgress("Updating Database", "Initializing...");
+ try
+ {
+ LogManager.Log("Starting database update...");
- LogManager.Log("Looking for update scripts configuration on application path...");
+ UpdateProgress("Updating Database", "Initializing...");
- String config_file = Path.Combine(PathHelper.GetStartupPath(), "Update Scripts", "config.xml");
+ LogManager.Log("Looking for update scripts configuration on application path...");
- if (!File.Exists(config_file))
- {
- throw LogManager.Log(new FileNotFoundException($"Could not locate '{config_file}' file on application folder."));
- }
+ String config_file = Path.Combine(PathHelper.GetStartupPath(), "Update Scripts", "config.xml");
- UpdateDBResponse update_response = dbCompareResult.UpdateDBResponse;
+ if (!File.Exists(config_file))
+ {
+ throw LogManager.Log(new FileNotFoundException($"Could not locate '{config_file}' file on application folder."));
+ }
- var localDataSource = SettingsManager.Default.GetOrCreate<CoreSettings>().DataSource;
+ update_response = dbCompareResult.UpdateDBResponse;
- LogManager.Log($"Updating database '{update_response.DataSource.ToString()}' => '{localDataSource.ToString()}'...");
+ LogManager.Log($"Updating database '{update_response.DataSource.ToString()}' => '{localDataSource.ToString()}'...");
- UpdateProgress("Updating Database", "Initializing update sequence...");
+ UpdateProgress("Updating Database", "Initializing update sequence...");
- ExaminerSequenceConfiguration config_sequence = ExaminerSequenceConfiguration.FromFile(config_file);
+ ExaminerSequenceConfiguration config_sequence = ExaminerSequenceConfiguration.FromFile(config_file);
- foreach (var item in config_sequence.Items.Where(x => x.Type == ExaminerSequenceItemType.Data || update_response.PerformSchemaUpdate).OrderBy(x => x.Index))
- {
- LogManager.Log($"Executing update script '{item.FileName}...'");
-
- ExaminerConfigurationBuilder builder = new ExaminerConfigurationBuilder(Path.Combine(Path.GetDirectoryName(config_file), item.FileName));
- builder.SetSource(update_response.DataSource);
- builder.SetTarget(localDataSource);
+ UpdateProgress("Updating Database", "Connecting to local database...");
+ LogManager.Log("Initializing database manager...");
+ DbManager db = DbManager.FromDataSource(localDataSource);
- if (item.RequiresSerialNumber)
+ LogManager.Log("Checking Tango database exists on the local machine...");
+ if (!db.Exists(localDataSource.Catalog))
{
- builder.SetMachineSerialNumber(serialNumber);
+ throw new InvalidProgramException("Database tango does not exists.");
}
- builder.Synchronize();
-
- var config = builder.Build();
+ UpdateProgress("Updating Database", "Creating database backup...");
- ExaminerProcess process = new ExaminerProcess(config, item.Type == ExaminerSequenceItemType.Data ? ExaminerProcessType.Data : ExaminerProcessType.Schema);
- process.Progress += (x, msg) =>
+ //Create Database Backup
+ try
{
- LogManager.Log(msg);
- };
+ Directory.CreateDirectory("C:\\Backups");
+ dbBackupFile = $"C:\\Backups\\{Path.GetRandomFileName()}.bak";
+ LogManager.Log($"Creating database backup to '{dbBackupFile}'...");
+ db.Backup(localDataSource.Catalog, dbBackupFile);
+ performDatabaseRollback = true;
+ LogManager.Log("Database backup created successfully.");
+ }
+ catch (Exception ex)
+ {
+ throw LogManager.Log(ex, "Update manager error while trying to create a database backup.");
+ }
- try
+ LogManager.Log("Disposing database manager.");
+ db.Dispose();
+
+ foreach (var item in config_sequence.Items.Where(x => x.Type == ExaminerSequenceItemType.Data || update_response.PerformSchemaUpdate).OrderBy(x => x.Index))
{
- UpdateProgress("Updating Database", item.Name + "...");
+ LogManager.Log($"Executing update script '{item.FileName}...'");
- var result = process.Execute().Result;
+ ExaminerConfigurationBuilder builder = new ExaminerConfigurationBuilder(Path.Combine(Path.GetDirectoryName(config_file), item.FileName));
+ builder.SetSource(update_response.DataSource);
+ builder.SetTarget(localDataSource);
- if (result.ExitCode != ExaminerProcessExitCode.Success)
+ if (item.RequiresSerialNumber)
{
- throw LogManager.Log(new InvalidDataException($"{item.FileName} script has terminated with exit code '{result.ExitCode}'."));
+ builder.SetMachineSerialNumber(serialNumber);
}
- LogManager.Log("Script executed successfully.");
- }
- catch (Exception ex)
- {
- throw LogManager.Log(ex, "Setup manager error while trying to update the database.");
+ builder.Synchronize();
+
+ var config = builder.Build();
+
+ ExaminerProcess process = new ExaminerProcess(config, item.Type == ExaminerSequenceItemType.Data ? ExaminerProcessType.Data : ExaminerProcessType.Schema);
+ process.Progress += (x, msg) =>
+ {
+ LogManager.Log(msg);
+ };
+
+ try
+ {
+ UpdateProgress("Updating Database", item.Name + "...");
+
+ var result = process.Execute().Result;
+
+ if (result.ExitCode != ExaminerProcessExitCode.Success)
+ {
+ throw LogManager.Log(new InvalidDataException($"{item.FileName} script has terminated with exit code '{result.ExitCode}'."));
+ }
+
+ LogManager.Log("Script executed successfully.");
+ }
+ catch (Exception ex)
+ {
+ throw LogManager.Log(ex, "Upudate manager error while trying to update the database.");
+ }
}
- }
- UpdateProgress("Updating Database", "Database synchronization completed successfully.");
- LogManager.Log("Update completed successfully.");
+ UpdateProgress("Updating Database", "Database synchronization completed successfully.");
+ LogManager.Log("Update completed successfully.");
+ OnCompleted(update_response);
+ }
+ catch (Exception ex)
+ {
+ OnFailed(ex, update_response, performDatabaseRollback, dbBackupFile, localDataSource);
+ throw ex;
+ }
});
}
@@ -494,7 +1007,7 @@ namespace Tango.PPC.Common.MachineUpdate
{
return Task.Factory.StartNew<DbCompareResult>(() =>
{
- var machineServiceAddress = SettingsManager.Default.GetOrCreate<PPCSettings>().GetMachineServiceAddress();
+ var machineServiceAddress = _settings.GetMachineServiceAddress();
LogManager.Log($"Checking if database update is required for serial number {serialNumber}...");
@@ -513,6 +1026,8 @@ namespace Tango.PPC.Common.MachineUpdate
UpdateDBRequest request = new UpdateDBRequest();
request.SerialNumber = serialNumber;
+ request.ApplicationVersion = _app_manager.Version.ToString();
+ request.FirmwareVersion = _app_manager.FirmwareVersion.ToString();
UpdateDBResponse update_response = null;
@@ -580,12 +1095,18 @@ namespace Tango.PPC.Common.MachineUpdate
}
catch (Exception ex)
{
+ OnFailed(ex, update_response, false, null, null);
throw LogManager.Log(ex, "Update manager error while trying to compare the database.");
}
}
LogManager.Log("Comparison completed successfully.");
+ if (!has_differences)
+ {
+ OnCompleted(update_response, true);
+ }
+
return new DbCompareResult()
{
RequiresUpdate = has_differences,
@@ -599,31 +1120,286 @@ namespace Tango.PPC.Common.MachineUpdate
/// </summary>
/// <param name="fileName">Name of the file.</param>
/// <returns></returns>
- public Task<MachineUpdateResult> UpdateFromTUP(string fileName)
+ public async Task<MachineUpdateResult> UpdateFromTUP(string fileName, bool setupFirmware, bool setupFPGA)
{
- return Task.Factory.StartNew<MachineUpdateResult>(() =>
+ _updateStartDate = DateTime.UtcNow;
+ _logs.Clear();
+
+ TaskCompletionSource<MachineUpdateResult> result = new TaskCompletionSource<MachineUpdateResult>();
+
+ var localDataSource = SettingsManager.Default.GetOrCreate<CoreSettings>().DataSource;
+ bool performDatabaseRollback = false;
+ String dbBackupFile = null;
+ String tempDbName = "Tango_TUP";
+ String tempDbFileName = tempDbName + ".bak";
+ String backupsFolder = "C:\\Backups";
+ bool replaceBinaries = false;
+ PublishInfo publishInfo = null;
+
+ String serialNumber = _machineProvider.Machine.SerialNumber;
+
+ //Create temporary folders for packages.
+ var _newPackageTempFolder = TemporaryManager.CreateFolder();
+ _newPackageTempFolder.Persist = true;
+
+ try
{
- LogManager.Log($"Starting machine update from update package '{fileName}'...");
+ _isUpdating = true;
- //Create temporary folders for packages.
- var _newPackageTempFolder = TemporaryManager.CreateFolder();
- _newPackageTempFolder.Persist = true;
+ LogManager.Log($"Starting machine update for serial number {serialNumber}...");
- LogManager.Log("Extracting downloaded zip file...");
- //Extract software package.
- ZipFile.ExtractToDirectory(fileName, _newPackageTempFolder);
+ //Connecting to machine...
+ LogManager.Log("Verifying machine connection and state...");
+
+ UpdateProgress("Verifying machine state", "Initializing...");
+
+ await Task.Delay(1000);
+
+ IMachineOperator op = _machineProvider.MachineOperator;
+
+ if (setupFirmware)
+ {
+ LogManager.Log("Machine is configured to update firmware...");
+
+ if (op.State != Transport.TransportComponentState.Connected)
+ {
+ throw LogManager.Log(new InvalidOperationException("Could not perform an update while the machine is not connected."));
+ }
+ if (op.Status != MachineStatuses.ReadyToDye)
+ {
+ throw LogManager.Log(new InvalidOperationException($"Could not perform an update while the machine is in {op.Status} status."));
+ }
+ }
+
+ UpdateProgress("Exploring package", "Extracting...");
+ LogManager.Log("Extracting package...");
+
+ LogManager.Log($"Temporary package folder created: {_newPackageTempFolder}.");
+
+ await Task.Factory.StartNew(() =>
+ {
+ //Extract software package.
+ ZipFile.ExtractToDirectory(fileName, _newPackageTempFolder);
+ });
+
+ //Extracting publish info
+ UpdateProgress("Exploring package", "Verifying...");
+ publishInfo = PublishInfo.FromJson(File.ReadAllText(Path.Combine(_newPackageTempFolder, "version.json")));
+
+ if (!publishInfo.IsMachineTupPackage)
+ {
+ throw new InvalidOperationException("The specified tup file is invalid. Updating a machine from a tup file requires a custom generated package.");
+ }
+
+ if (publishInfo.MachineSerialNumber != serialNumber)
+ {
+ throw new InvalidOperationException("The specified tup file is invalid. The package was generated for a different machine.");
+ }
+
+ if (publishInfo.MachineDeploymentSlot != _settings.DeploymentSlot)
+ {
+ throw new InvalidOperationException("The specified tup file is invalid. The package was generated on a different environment.");
+ }
+
+ replaceBinaries = _app_manager.Version.ToString() != publishInfo.ApplicationVersion;
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);
- LogManager.Log("Update operation completed!");
+ //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(publishInfo.ApplicationVersion);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error parsing new version string for package runner.");
+ }
- return new MachineUpdateResult()
+ await _packageRunner.Run(PackageType.Pre, updateVersion, packagesFolder);
+ }
+ catch (Exception ex)
{
- UpdatePackagePath = _newPackageTempFolder,
+ LogManager.Log(ex, "Error running pre-update packages...");
+ }
+
+ //Synchronize database
+ UpdateProgress("Updating Database", "Initializing...");
+
+ UpdateProgress("Updating Database", "Connecting to local database...");
+ LogManager.Log("Initializing database manager...");
+ DbManager db = DbManager.FromDataSource(localDataSource);
+
+ LogManager.Log("Checking Tango database exists on the local machine...");
+ if (!db.Exists(localDataSource.Catalog))
+ {
+ throw new InvalidProgramException("Database tango does not exists.");
+ }
+
+ UpdateProgress("Updating Database", "Creating database backup...");
+
+ //Create Database Backup
+ try
+ {
+ Directory.CreateDirectory(backupsFolder);
+ dbBackupFile = $"{backupsFolder}\\{Path.GetRandomFileName()}.bak";
+ LogManager.Log($"Creating database backup to '{dbBackupFile}'...");
+ await Task.Factory.StartNew(() => db.Backup(localDataSource.Catalog, dbBackupFile));
+ performDatabaseRollback = true;
+ LogManager.Log("Database backup created successfully.");
+ }
+ catch (Exception ex)
+ {
+ throw LogManager.Log(ex, "Update manager error while trying to create a database backup.");
+ }
+
+ LogManager.Log("Extracting database file from package...");
+ File.Copy(Path.Combine(_newPackageTempFolder, tempDbFileName), Path.Combine(backupsFolder, tempDbFileName));
+
+ LogManager.Log("Restoring package database as a new database...");
+ db.RestoreAsNew(tempDbName, Path.Combine(backupsFolder, tempDbFileName), backupsFolder);
+
+ Core.DataSource tempDbDataSource = new Core.DataSource();
+ tempDbDataSource.Address = localDataSource.Address;
+ tempDbDataSource.IntegratedSecurity = localDataSource.IntegratedSecurity;
+ tempDbDataSource.Type = localDataSource.Type;
+ tempDbDataSource.Catalog = tempDbName;
+
+ LogManager.Log("Disposing database manager.");
+ db.Dispose();
+
+ LogManager.Log($"Initializing {nameof(ExaminerSequenceConfigurationRunner)}...");
+
+ UpdateProgress("Updating Database", "Initializing update sequence...");
+
+ ExaminerSequenceConfigurationRunner runner = new ExaminerSequenceConfigurationRunner(
+ Path.Combine(_newPackageTempFolder, "Update Scripts", "config.xml"),
+ Path.Combine(_newPackageTempFolder, "Update Scripts"),
+ tempDbDataSource,
+ localDataSource,
+ serialNumber);
+
+ runner.Log += (x, msg) =>
+ {
+ LogManager.Log(msg);
+ ProgressLog?.Invoke(this, msg);
};
- });
+
+ runner.ScriptExecuting += (x, item) =>
+ {
+ LogManager.Log($"Executing script {item.ToString()}...");
+ UpdateProgress("Updating Database", item.Name + "...");
+ };
+
+ LogManager.Log("Starting synchronization process...");
+
+ try
+ {
+ await runner.Run();
+ LogManager.Log("Synchronization completed successfully!");
+ UpdateProgress("Updating Database", "Database synchronization completed successfully.");
+ }
+ catch (Exception ex)
+ {
+ throw LogManager.Log(ex, "Update manager error while trying to synchronize database.");
+ }
+
+ LogManager.Log("Getting setup firmware/fpga directly from db..");
+
+ using (var dbManager = DbManager.FromDataSource(localDataSource))
+ {
+ try
+ {
+ String firmware = dbManager.GetValue($"SELECT TOP 1 * FROM MACHINES WHERE SERIAL_NUMBER = '{serialNumber}'", "SETUP_FIRMWARE");
+ String fpga = dbManager.GetValue($"SELECT TOP 1 * FROM MACHINES WHERE SERIAL_NUMBER = '{serialNumber}'", "SETUP_FPGA");
+
+ setupFirmware = bool.Parse(firmware);
+ setupFPGA = bool.Parse(fpga);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error getting new values of SETUP_FIRMWARE and SETUP_FPGA.");
+ }
+ }
+
+ //Updating firmware
+ if (setupFirmware)
+ {
+ UpdateProgress("Updating Firmware", "Connecting to firmware device...");
+ LogManager.Log("");
+ LogManager.Log("-------------------------------------------------------------------------");
+ LogManager.Log("Updating Firmware...");
+
+ UpdateProgress("Updating Firmware", "Loading firmware package...");
+ var tfpPath = Path.Combine(_newPackageTempFolder, "firmware_package.tfp");
+ var stream = new FileStream(tfpPath, FileMode.Open);
+
+ if (!_machineProvider.Machine.IsDemo)
+ {
+ if (setupFPGA)
+ {
+ op.FirmwareUpgradeMode = FirmwareUpgradeModes.DFU | FirmwareUpgradeModes.TFP_PACKAGE;
+ }
+ else
+ {
+ op.FirmwareUpgradeMode = FirmwareUpgradeModes.DFU;
+ }
+ }
+ else
+ {
+ op.FirmwareUpgradeMode = FirmwareUpgradeModes.TFP_PACKAGE;
+ }
+
+ var handler = await op.UpgradeFirmware(stream);
+ handler.Failed += (_, ex) =>
+ {
+ stream.Dispose();
+ OnFailed(ex, result, null, performDatabaseRollback, dbBackupFile, backupsFolder, tempDbName, localDataSource, _newPackageTempFolder, publishInfo);
+ };
+ handler.Completed += (_, __) =>
+ {
+ UpdateProgress("Updating Firmware", "Firmware update completed successfully.");
+ stream.Dispose();
+ OnCompleted(new MachineUpdateResult()
+ {
+ UpdatePackagePath = _newPackageTempFolder,
+ RequiresBinariesUpdate = replaceBinaries,
+ }, result, null, tempDbName, backupsFolder, localDataSource, publishInfo);
+ };
+ handler.Canceled += (_, __) =>
+ {
+ stream.Dispose();
+ OnFailed(new Exception("The operation has been canceled."), result, null, performDatabaseRollback, dbBackupFile, backupsFolder, tempDbName, localDataSource, _newPackageTempFolder, publishInfo);
+ };
+ handler.Progress += (_, e) =>
+ {
+ UpdateProgress("Updating Firmware", e.Message, false, e.Current, e.Total);
+ };
+ }
+ else
+ {
+ OnCompleted(new MachineUpdateResult()
+ {
+ UpdatePackagePath = _newPackageTempFolder,
+ RequiresBinariesUpdate = replaceBinaries,
+ }, result, null, tempDbName, backupsFolder, localDataSource, publishInfo);
+ }
+ }
+ catch (Exception ex)
+ {
+ OnFailed(ex, result, null, performDatabaseRollback, dbBackupFile, backupsFolder, tempDbName, localDataSource, _newPackageTempFolder, publishInfo);
+ }
+
+ return await result.Task;
}
/// <summary>
@@ -631,26 +1407,55 @@ namespace Tango.PPC.Common.MachineUpdate
/// </summary>
/// <param name="filePath">The file path.</param>
/// <returns></returns>
- public Task<UpdatePackageFile> GetUpdatePackageFileInfo(string filePath)
+ public Task<PublishInfo> GetUpdatePackageFileInfo(string filePath)
{
- return Task.Factory.StartNew<UpdatePackageFile>(() =>
+ return Task.Factory.StartNew<PublishInfo>(() =>
{
- UpdatePackageFile file = new UpdatePackageFile();
- var tempFolder = TemporaryManager.CreateFolder();
-
using (Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile(filePath))
{
- var appEntry = zip.Entries.SingleOrDefault(x => x.FileName == "Tango.PPC.UI.exe");
- appEntry.Extract(tempFolder);
+ var appEntry = zip.Entries.SingleOrDefault(x => x.FileName == "version.json");
+ var reader = appEntry.OpenReader();
+
+ using (StreamReader stReader = new StreamReader(reader))
+ {
+ String json = stReader.ReadToEnd();
+ reader.Dispose();
+
+ return PublishInfo.FromJson(json);
+ }
}
+ });
+ }
+
+ /// <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);
+ }
- FileVersionInfo info = FileVersionInfo.GetVersionInfo(Path.Combine(tempFolder, "Tango.PPC.UI.exe"));
- file.Version = Version.Parse(info.ProductVersion);
+ /// <summary>
+ /// Runs all post update packages.
+ /// </summary>
+ /// <returns></returns>
+ public Task<PackageRunnerResult> RunPostUpdatePackages()
+ {
+ String packagesFolder = Path.Combine(AssemblyHelper.GetCurrentAssemblyFolder(), "packages");
- tempFolder.Delete();
+ Version previousVersion = null;
+ String str = _settings.PreviousApplicationVersion;
- return file;
- });
+ 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
@@ -677,5 +1482,31 @@ namespace Tango.PPC.Common.MachineUpdate
}
#endregion
+
+ #region Auto Check For Update
+
+ private async void _checkForUpdateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
+ {
+ if (EnableAutoCheckForUpdates && _settings.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
}
}