diff options
| author | Victoria Plitt <Victoria.Plitt@twine-s.com> | 2019-12-09 17:00:30 +0200 |
|---|---|---|
| committer | Victoria Plitt <Victoria.Plitt@twine-s.com> | 2019-12-09 17:00:30 +0200 |
| commit | 31ece903df45b0ab8ffb61fdd290d9fbea2a6836 (patch) | |
| tree | 180be785ceb98fb828009eeae4dfa3bbc8a738b7 /Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs | |
| parent | 4417c2eccb3795330144afa39e3bf271652bd31f (diff) | |
| parent | aeabb681d16451e191a1620d4eebf40549771491 (diff) | |
| download | Tango-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.cs | 210 |
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 } } |
