aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs
diff options
context:
space:
mode:
authorRoy Ben-Shabat <Roy@Twine-s.com>2018-08-30 19:04:18 +0300
committerRoy Ben-Shabat <Roy@Twine-s.com>2018-08-30 19:04:18 +0300
commit37e5138e6acac4a9b93e018087fe9c50d36c4b34 (patch)
tree4acec95a8e5362c67f0e0fc5444c40c23791776d /Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs
parent3d9beda13daccac78fb05dc94d1430a0a47e9db6 (diff)
downloadTango-37e5138e6acac4a9b93e018087fe9c50d36c4b34.tar.gz
Tango-37e5138e6acac4a9b93e018087fe9c50d36c4b34.zip
Implemented machine update on PPC !!!
Need to verify update scripts...
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.cs287
1 files changed, 287 insertions, 0 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
new file mode 100644
index 000000000..b86fb88d4
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs
@@ -0,0 +1,287 @@
+using FluentFTP;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.Compression;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Tango.Core;
+using Tango.Core.DB;
+using Tango.Core.Helpers;
+using Tango.Core.IO;
+using Tango.PMR.Synchronization;
+using Tango.PPC.Common.Application;
+using Tango.Settings;
+using Tango.SQLExaminer;
+using Tango.Transport.Web;
+
+namespace Tango.PPC.Common.MachineUpdate
+{
+ public class MachineUpdateManager : ExtendedObject, IMachineUpdateManager
+ {
+ private IPPCApplicationManager _app_manager;
+
+ #region Events
+
+ /// <summary>
+ /// Occurs when there is a text log message available.
+ /// </summary>
+ public event EventHandler<string> ProgressLog;
+
+ /// <summary>
+ /// Occurs when the <see cref="CurrentStep" /> has changed.
+ /// </summary>
+ public event EventHandler<MachineUpdateSteps> ProgressStep;
+
+ #endregion
+
+ #region Properties
+
+ private MachineUpdateSteps _currentStep;
+ /// <summary>
+ /// Gets the current setup step.
+ /// </summary>
+ public MachineUpdateSteps CurrentStep
+ {
+ get { return _currentStep; }
+ set
+ {
+ if (_currentStep != value)
+ {
+ _currentStep = value;
+ RaisePropertyChangedAuto();
+ ProgressStep?.Invoke(this, _currentStep);
+ LogManager.Log("Machine Setup Manager Step: " + value.ToString());
+ }
+ }
+ }
+
+ private double _downloadProgress;
+ /// <summary>
+ /// Gets the downloading packages step progress.
+ /// </summary>
+ public double DownloadingPackagesProgress
+ {
+ get { return _downloadProgress; }
+ private set { _downloadProgress = value; RaisePropertyChangedAuto(); }
+ }
+
+ private String _updatingPackagesStatus;
+ /// <summary>
+ /// Gets the downloading packages step status.
+ /// </summary>
+ public String DownloadingPackagesStatus
+ {
+ get { return _updatingPackagesStatus; }
+ set { _updatingPackagesStatus = value; RaisePropertyChangedAuto(); }
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MachineUpdateManager"/> class.
+ /// </summary>
+ /// <param name="applicationManager">The application manager.</param>
+ public MachineUpdateManager(IPPCApplicationManager applicationManager)
+ {
+ _app_manager = applicationManager;
+ }
+
+ #region Public Methods
+
+ /// <summary>
+ /// Performs a machine setup using the specified serial number and machine service address.
+ /// </summary>
+ /// <param name="serialNumber">The serial number.</param>
+ /// <param name="machineServiceAddress">The machine service address.</param>
+ /// <returns></returns>
+ public Task<MachineUpdateResult> Update(string serialNumber, string machineServiceAddress)
+ {
+ return Task.Factory.StartNew<MachineUpdateResult>(() =>
+ {
+
+ LogManager.Log($"Starting machine update for serial number {serialNumber}...");
+
+ //Connect to machine service and get matching packages for this machine.
+ CurrentStep = MachineUpdateSteps.DownloadingPackage;
+ DownloadingPackagesProgress = 0;
+ DownloadingPackagesStatus = "Connecting to machine service...";
+
+ LogManager.Log($"Connecting to machine service on {machineServiceAddress}...");
+
+ DownloadUpdateRequest request = new DownloadUpdateRequest();
+ request.SerialNumber = serialNumber;
+
+ DownloadUpdateResponse update_response = null;
+
+ using (var http = new ProtoWebClient())
+ {
+ update_response = http.Post<DownloadUpdateRequest, DownloadUpdateResponse>(machineServiceAddress + "/api/Synchronization/MachineUpdate", request).Result;
+ }
+
+ 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.
+ var tempFile = TemporaryManager.CreateFile(".zip");
+
+ LogManager.Log($"Temporary package zip file created: {tempFile}.");
+
+ DownloadingPackagesStatus = "Downloading software package...";
+
+ LogManager.Log("Downloading software package...");
+
+ int fileSize = 0;
+ DownloadingPackagesProgress = 0;
+
+ using (FileStreamWrapper fs = new FileStreamWrapper(tempFile.Path, FileMode.Create, (current) =>
+ {
+ InvokeUINow(() =>
+ {
+ Thread.Sleep(2); //TODO: this is necessary only for visibility...
+ DownloadingPackagesProgress = ((double)current / (double)fileSize) * 100d;
+ });
+ }))
+ {
+ using (FtpClient ftp = new FtpClient(update_response.FtpAddress, update_response.FtpUserName, update_response.FtpPassword))
+ {
+ LogManager.Log("FTP: Connecting to site: " + update_response.FtpAddress);
+ ftp.ConnectAsync().Wait();
+ LogManager.Log("FTP: Retrieving download size...");
+ fileSize = (int)ftp.GetFileSize(update_response.FtpFilePath);
+ LogManager.Log("FTP: Download size: " + fileSize + " bytes.");
+ LogManager.Log("FTP: Starting download...");
+ ftp.DownloadAsync(fs, update_response.FtpFilePath).Wait();
+ }
+ }
+
+ LogManager.Log("Extracting downloaded zip file...");
+ //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);
+
+
+ //Synchronize database
+ CurrentStep = MachineUpdateSteps.SynchronizingSchema;
+
+ String db_name = "Tango";
+ String localAddress = SettingsManager.Default.GetOrCreate<CoreSettings>().DataSource.Address;
+ String remote_address = update_response.DbAddress;
+
+ LogManager.Log($"Synchronizing database '{remote_address}\\{db_name}' => '{localAddress}\\{db_name}'...");
+
+ LogManager.Log("Initializing database manager...");
+ DbManager db = DbManager.FromAddressAndName(localAddress, db_name);
+
+ LogManager.Log("Checking Tango database exists on the local machine...");
+ if (!db.Exists(db_name))
+ {
+ throw new InvalidProgramException("Database tango does not exists.");
+ }
+
+ LogManager.Log("Disposing database manager.");
+ db.Dispose();
+
+ LogManager.Log($"Initializing {nameof(ExaminerSequenceConfigurationRunner)}...");
+
+ ExaminerSequenceConfigurationRunner runner = new ExaminerSequenceConfigurationRunner(
+ Path.Combine(_newPackageTempFolder, "Update Scripts", "config.xml"),
+ Path.Combine(_newPackageTempFolder, "Update Scripts"),
+ new ExaminerSequenceDataSource()
+ {
+ Address = remote_address,
+ DataBaseName = db_name,
+ IntegratedSecurity = false,
+ UserName = update_response.DbUserName,
+ Password = update_response.DbPassword,
+ },
+ new ExaminerSequenceDataSource()
+ {
+ Address = localAddress,
+ DataBaseName = db_name,
+ IntegratedSecurity = true,
+ }, serialNumber);
+
+ runner.Log += (x, msg) =>
+ {
+ LogManager.Log(msg);
+ ProgressLog?.Invoke(this, msg);
+ };
+
+ runner.ScriptExecuting += (x, item) =>
+ {
+ LogManager.Log($"Executing script {item.ToString()}...");
+
+ if (item.Type == ExaminerSequenceItemType.Data && item.RequiresSerialNumber)
+ {
+ CurrentStep = MachineUpdateSteps.SynchronizingMachineConfiguration;
+ }
+ else if (item.Type == ExaminerSequenceItemType.Data)
+ {
+ CurrentStep = MachineUpdateSteps.SynchronizingData;
+ }
+ };
+
+ LogManager.Log("Starting synchronization process...");
+
+ try
+ {
+ runner.Run().Wait();
+ LogManager.Log("Synchronization completed successfully!");
+ }
+ catch (Exception ex)
+ {
+ throw LogManager.Log(ex, "Setup manager error while trying to synchronize database.");
+ }
+
+ return new MachineUpdateResult()
+ {
+ UpdatePackagePath = _newPackageTempFolder,
+ };
+ });
+ }
+
+ /// <summary>
+ /// Checks if any update are available for the specified machine serial number.
+ /// </summary>
+ /// <param name="serialNumber">The serial number.</param>
+ /// <param name="machineServiceAddress">The machine service address.</param>
+ /// <returns></returns>
+ public Task<CheckForUpdateResponse> CheckForUpdate(string serialNumber, string machineServiceAddress)
+ {
+ return Task.Factory.StartNew<CheckForUpdateResponse>(() =>
+ {
+ LogManager.Log($"Connecting to machine service on {machineServiceAddress}...");
+ LogManager.Log($"Checking if updates available...");
+
+ CheckForUpdateRequest request = new CheckForUpdateRequest();
+ request.SerialNumber = serialNumber;
+ request.Version = _app_manager.Version.ToString();
+
+ CheckForUpdateResponse update_response = null;
+
+ using (var http = new ProtoWebClient())
+ {
+ update_response = http.Post<CheckForUpdateRequest, CheckForUpdateResponse>(machineServiceAddress + "/api/Synchronization/CheckForUpdate", request).Result;
+ }
+
+ LogManager.Log($"Check for update response received: {Environment.NewLine}{update_response.ToJsonString()}");
+
+ return update_response;
+ });
+ }
+
+ #endregion
+ }
+}