aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoy Ben Shabat <Roy.mail.net@gmail.com>2020-04-11 05:02:18 +0300
committerRoy Ben Shabat <Roy.mail.net@gmail.com>2020-04-11 05:02:18 +0300
commitbf5cbf5a6972cd8d725cc03fd6375b1eccbfe31c (patch)
tree0902fda382956c1b749cf856d2a4d950f0196190
parentcb1b51c238c64f570d73b7dca6a2eee205b2da01 (diff)
downloadTango-bf5cbf5a6972cd8d725cc03fd6375b1eccbfe31c.tar.gz
Tango-bf5cbf5a6972cd8d725cc03fd6375b1eccbfe31c.zip
Started working on FSE TUP management.
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/CacheEntities/CachedTangoVersion.cs15
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServicesContainer.cs6
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/Services/TangoVersionsService.cs99
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/Tango.FSE.BL.csproj2
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/Web/FSEWebClientBase.cs9
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs7
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/RemoteUpgrade/IRemoteUpgradeManager.cs35
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/RemoteUpgrade/RemoteUpgradeProgressEventArgs.cs16
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj5
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/packages.config1
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/RemoteUpgrade/DefaultRemoteUpgradeManager.cs351
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj8
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs4
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/DownloadTangoVersionRequest.cs14
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/DownloadTangoVersionResponse.cs18
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Web/Tango.FSE.Web.csproj2
-rw-r--r--Software/Visual_Studio/Utilities/Tango.WebClientGenerator/Program.cs2
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs62
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs2
19 files changed, 656 insertions, 2 deletions
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/CacheEntities/CachedTangoVersion.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/CacheEntities/CachedTangoVersion.cs
new file mode 100644
index 000000000..6d0d6cade
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/CacheEntities/CachedTangoVersion.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL.DTO;
+
+namespace Tango.FSE.BL.CacheEntities
+{
+ public class CachedTangoVersion
+ {
+ public String EnvironmentID { get; set; }
+ public TangoVersionDTO TangoVersion { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServicesContainer.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServicesContainer.cs
index 2fa6cae53..60d0fb372 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServicesContainer.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServicesContainer.cs
@@ -38,6 +38,11 @@ namespace Tango.FSE.BL
public BugReportingService BugReportingService { get; set; }
/// <summary>
+ /// Gets or sets the tango versions service.
+ /// </summary>
+ public TangoVersionsService TangoVersionsService { get; set; }
+
+ /// <summary>
/// Initializes a new instance of the <see cref="FSEServicesContainer"/> class.
/// </summary>
/// <param name="authentication">The authentication.</param>
@@ -48,6 +53,7 @@ namespace Tango.FSE.BL
GatewayService = new GatewayService();
AuthenticationService = new AuthenticationService();
BugReportingService = new BugReportingService();
+ TangoVersionsService = new TangoVersionsService();
}
}
}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/Services/TangoVersionsService.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/Services/TangoVersionsService.cs
new file mode 100644
index 000000000..ed0a2a356
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/Services/TangoVersionsService.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL;
+using Tango.BL.DTO;
+using Tango.BL.Entities;
+using Tango.FSE.BL.CacheEntities;
+
+namespace Tango.FSE.BL.Services
+{
+ public class TangoVersionsService : FSEServiceBase
+ {
+ private const string TANGO_VERSIONS_COLLECTION = "TangoVersions";
+ private ConcurrentDictionary<String, CachedTangoVersion> _tangoVersionsCache;
+
+ public TangoVersionsService()
+ {
+ _tangoVersionsCache = new ConcurrentDictionary<string, CachedTangoVersion>();
+ }
+
+ /// <summary>
+ /// Gets all the available PPC/Firmware versions history.
+ /// </summary>
+ /// <returns></returns>
+ public Task<List<TangoVersion>> GetAllTangoVersions()
+ {
+ return DataResolver<List<TangoVersion>>.Builder.New()
+ .ConfigureCascade(DataResolverNode.InMemoryCache, DataResolverNode.Online, DataResolverNode.DiskCache)
+ .InMemoryCache((context) =>
+ {
+ var tangoVersions = _tangoVersionsCache
+ .ToList()
+ .Select(x => x.Value)
+ .Where(x => x.EnvironmentID == Authentication.CurrentEnvironment.ID)
+ .Select(x => x.TangoVersion.ToObservable())
+ .ToList();
+
+ if (tangoVersions.Count == 0)
+ {
+ throw new IndexOutOfRangeException("The memory cache did contain any Tango versions.");
+ }
+
+ return tangoVersions;
+ })
+ .Online((context) =>
+ {
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ var tangoVersions = db.TangoVersions.ToList().OrderByDescending(x => Version.Parse(x.Version)).ToList();
+
+ using (var cache = DiskCache.CreateContext())
+ {
+ var collection = cache.GetCollection<CachedTangoVersion>(TANGO_VERSIONS_COLLECTION);
+
+ foreach (var tangoVersion in tangoVersions)
+ {
+ try
+ {
+ var tangoVersionDTO = TangoVersionDTO.FromObservable(tangoVersion);
+ CachedTangoVersion cachedTangoVersion = new CachedTangoVersion();
+ cachedTangoVersion.EnvironmentID = Authentication.CurrentEnvironment.ID;
+ cachedTangoVersion.TangoVersion = tangoVersionDTO;
+
+ _tangoVersionsCache[tangoVersion.Version + " " + Authentication.CurrentEnvironment.ID] = cachedTangoVersion;
+
+ collection.Upsert(cachedTangoVersion);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, $"Error caching Tango version '{tangoVersion.Version}' on disk.");
+ }
+ }
+ }
+
+ return tangoVersions;
+ }
+ })
+ .DiskCache((context) =>
+ {
+ using (var cache = DiskCache.CreateContext())
+ {
+ var collection = cache.GetCollection<CachedTangoVersion>(TANGO_VERSIONS_COLLECTION);
+
+ return collection
+ .Find(x => x.EnvironmentID == Authentication.CurrentEnvironment.ID)
+ .ToList()
+ .Select(x => x.TangoVersion.ToObservable())
+ .ToList()
+ .OrderByDescending(x => Version.Parse(x.Version))
+ .ToList();
+ }
+ })
+ .BuildExecuteAsync();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/Tango.FSE.BL.csproj b/Software/Visual_Studio/FSE/Tango.FSE.BL/Tango.FSE.BL.csproj
index 0eae2baa3..ad514c09c 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.BL/Tango.FSE.BL.csproj
+++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/Tango.FSE.BL.csproj
@@ -75,6 +75,7 @@
<Compile Include="CacheEntities\CachedConfiguration.cs" />
<Compile Include="CacheEntities\CachedLoginResponse.cs" />
<Compile Include="CacheEntities\CachedMachine.cs" />
+ <Compile Include="CacheEntities\CachedTangoVersion.cs" />
<Compile Include="CacheEntities\CachedUser.cs" />
<Compile Include="CacheManager.cs" />
<Compile Include="Connectivity\DefaultConnectivityProvider.cs" />
@@ -91,6 +92,7 @@
<Compile Include="Services\BugReportingService.cs" />
<Compile Include="Services\GatewayService.cs" />
<Compile Include="Services\MachinesService.cs" />
+ <Compile Include="Services\TangoVersionsService.cs" />
<Compile Include="Services\UsersService.cs" />
<Compile Include="Web\FSEWebClient.cs" />
<Compile Include="Web\FSEWebClientBase.cs" />
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/Web/FSEWebClientBase.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/Web/FSEWebClientBase.cs
index fbfd1e647..51e8777f7 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.BL/Web/FSEWebClientBase.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/Web/FSEWebClientBase.cs
@@ -48,5 +48,14 @@ namespace Tango.FSE.BL.Web
return Post<Tango.FSE.Web.Messages.BugReportingInfoRequest, Tango.FSE.Web.Messages.BugReportingInfoResponse>("GetBugReportInfo", request);
}
+ /// <summary>
+ /// Executes the DownloadTangoVersion action and returns Tango.FSE.Web.Messages.DownloadTangoVersionResponse.
+ /// </summary>
+ /// <returns></returns>
+ public Task<Tango.FSE.Web.Messages.DownloadTangoVersionResponse> DownloadTangoVersion(Tango.FSE.Web.Messages.DownloadTangoVersionRequest request)
+ {
+ return Post<Tango.FSE.Web.Messages.DownloadTangoVersionRequest, Tango.FSE.Web.Messages.DownloadTangoVersionResponse>("DownloadTangoVersion", request);
+ }
+
}
}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs
index 01b27c8ea..d790a54a1 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs
@@ -33,6 +33,7 @@ using Tango.SharedUI;
using static Tango.SharedUI.Controls.NavigationControl;
using Tango.FSE.BL.Connectivity;
using Tango.FSE.Common.BugReporting;
+using Tango.FSE.Common.RemoteUpgrade;
namespace Tango.FSE.Common
{
@@ -147,6 +148,12 @@ namespace Tango.FSE.Common
public IBugReporter BugReporter { get; set; }
/// <summary>
+ /// Gets or sets the remote upgrade manager.
+ /// </summary>
+ [TangoInject]
+ public IRemoteUpgradeManager RemoteUpgradeManager { get; set; }
+
+ /// <summary>
/// Gets or sets the FSE service.
/// </summary>
[TangoInject]
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/RemoteUpgrade/IRemoteUpgradeManager.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/RemoteUpgrade/IRemoteUpgradeManager.cs
new file mode 100644
index 000000000..9bbfb83f9
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/RemoteUpgrade/IRemoteUpgradeManager.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL.Entities;
+using Tango.FSE.Common.MachineUpdates;
+
+namespace Tango.FSE.Common.RemoteUpgrade
+{
+ public interface IRemoteUpgradeManager
+ {
+ /// <summary>
+ /// Occurs when a TUP creation has made progress.
+ /// </summary>
+ event EventHandler<RemoteUpgradeProgressEventArgs> Progress;
+
+ /// <summary>
+ /// Creates a Tango Update Package for the current connected machine.
+ /// </summary>
+ /// <param name="tangoVersion">The tango version.</param>
+ /// <param name="filePath">The file path.</param>
+ /// <returns></returns>
+ Task CreateTupFile(TangoVersion tangoVersion, String filePath);
+
+ /// <summary>
+ /// Creates a Tango Update Package for specified machine.
+ /// </summary>
+ /// <param name="tangoVersion">The tango version.</param>
+ /// <param name="serialNumber">The machine serial number.</param>
+ /// <param name="filePath">The file path.</param>
+ /// <returns></returns>
+ Task CreateTupFile(TangoVersion tangoVersion, String serialNumber, String filePath);
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/RemoteUpgrade/RemoteUpgradeProgressEventArgs.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/RemoteUpgrade/RemoteUpgradeProgressEventArgs.cs
new file mode 100644
index 000000000..31f79d682
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/RemoteUpgrade/RemoteUpgradeProgressEventArgs.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.FSE.Common.RemoteUpgrade
+{
+ public class RemoteUpgradeProgressEventArgs
+ {
+ public double Progress { get; set; }
+ public double Total { get; set; }
+ public bool IsIntermediate { get; set; }
+ public String Message { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj b/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj
index d9b61f425..2628f2299 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj
@@ -50,6 +50,9 @@
<Reference Include="GridExtra.Wpf, Version=0.4.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\GridExtra.0.4.0\lib\net45\GridExtra.Wpf.dll</HintPath>
</Reference>
+ <Reference Include="Ionic.Zip, Version=1.9.1.8, Culture=neutral, PublicKeyToken=edbe51ad942a3f5c, processorArchitecture=MSIL">
+ <HintPath>..\..\packages\Ionic.Zip.1.9.1.8\lib\Ionic.Zip.dll</HintPath>
+ </Reference>
<Reference Include="MahApps.Metro, Version=1.6.5.1, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\MahApps.Metro.1.6.5\lib\net46\MahApps.Metro.dll</HintPath>
</Reference>
@@ -157,6 +160,7 @@
<Compile Include="MachineUpdates\MachineUpdatesResult.cs" />
<Compile Include="RemoteDesktop\DesktopFrameReceivedEventArgs.cs" />
<Compile Include="RemoteDesktop\IRemoteDesktopProvider.cs" />
+ <Compile Include="RemoteUpgrade\IRemoteUpgradeManager.cs" />
<Compile Include="Resolution\IResolutionService.cs" />
<Compile Include="Resolution\ResolutionHelper.cs" />
<Compile Include="Resolution\ResolutionMode.cs" />
@@ -167,6 +171,7 @@
<Compile Include="Storage\StorageMode.cs" />
<Compile Include="SystemInfo\ISystemInfoProvider.cs" />
<Compile Include="Threading\IDispatcherProvider.cs" />
+ <Compile Include="RemoteUpgrade\RemoteUpgradeProgressEventArgs.cs" />
<Page Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/packages.config b/Software/Visual_Studio/FSE/Tango.FSE.Common/packages.config
index 56b04f9e4..d020563f0 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.Common/packages.config
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/packages.config
@@ -4,6 +4,7 @@
<package id="EntityFramework" version="6.2.0" targetFramework="net461" />
<package id="Google.Protobuf" version="3.4.1" targetFramework="net461" />
<package id="GridExtra" version="0.4.0" targetFramework="net461" />
+ <package id="Ionic.Zip" version="1.9.1.8" targetFramework="net461" />
<package id="MahApps.Metro" version="1.6.5" targetFramework="net461" />
<package id="MaterialDesignColors" version="1.2.2" targetFramework="net461" />
<package id="MaterialDesignThemes" version="3.0.1" targetFramework="net461" />
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/RemoteUpgrade/DefaultRemoteUpgradeManager.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/RemoteUpgrade/DefaultRemoteUpgradeManager.cs
new file mode 100644
index 000000000..bb808e685
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/RemoteUpgrade/DefaultRemoteUpgradeManager.cs
@@ -0,0 +1,351 @@
+using Ionic.Zip;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using Tango.BL.Entities;
+using Tango.Core;
+using Tango.Core.Components;
+using Tango.Core.DB;
+using Tango.Core.DI;
+using Tango.Core.ExtensionMethods;
+using Tango.FSE.BL.Web;
+using Tango.FSE.Common;
+using Tango.FSE.Common.Authentication;
+using Tango.FSE.Common.Connection;
+using Tango.FSE.Common.MachineUpdates;
+using Tango.FSE.Common.RemoteUpgrade;
+using Tango.FSE.Web.Messages;
+using Tango.PPC.Common.Publish;
+using Tango.PPC.Shared.Updates;
+using Tango.SQLExaminer;
+using Tango.Transport;
+using Tango.Transport.Web;
+using Tango.Web;
+
+namespace Tango.FSE.UI.RemoteUpgrade
+{
+ /// <summary>
+ /// Represents the <see cref="IMachineUpdatesProvider"/> default implementation.
+ /// </summary>
+ /// <seealso cref="Tango.FSE.Common.MachineUpdates.IMachineUpdatesProvider" />
+ public class DefaultRemoteUpgradeManager : FSEExtendedObject, IRemoteUpgradeManager
+ {
+ private bool _isGeneratingTup;
+ private IMachineProvider MachineProvider { get; set; }
+ private FSEWebClient WebClient { get; set; }
+ private IAuthenticationProvider AuthenticationProvider { get; set; }
+
+ /// <summary>
+ /// Occurs when a TUP creation has made progress.
+ /// </summary>
+ public event EventHandler<RemoteUpgradeProgressEventArgs> Progress;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DefaultRemoteUpgradeManager"/> class.
+ /// </summary>
+ /// <param name="authenticationProvider">The authentication provider.</param>
+ /// <param name="machineProvider">The machine provider.</param>
+ /// <param name="webClient">The web client.</param>
+ public DefaultRemoteUpgradeManager(IAuthenticationProvider authenticationProvider, IMachineProvider machineProvider, FSEWebClient webClient)
+ {
+ AuthenticationProvider = authenticationProvider;
+ MachineProvider = machineProvider;
+ WebClient = webClient;
+ }
+
+ /// <summary>
+ /// Creates a Tango Update Package for the current connected machine.
+ /// </summary>
+ /// <param name="tangoVersion">The tango version.</param>
+ /// <param name="filePath">The file path.</param>
+ /// <returns></returns>
+ public Task CreateTupFile(TangoVersion tangoVersion, string filePath)
+ {
+ if (MachineProvider.Machine == null)
+ {
+ throw new InvalidOperationException("Could not create a TUP file while machine is disconnected.");
+ }
+
+ return CreateTupFile(tangoVersion, MachineProvider.Machine.SerialNumber);
+ }
+
+ /// <summary>
+ /// Creates a Tango Update Package for specified machine.
+ /// </summary>
+ /// <param name="tangoVersion">The tango version.</param>
+ /// <param name="serialNumber">The machine serial number.</param>
+ /// <param name="targetFilePath">The file path.</param>
+ /// <returns></returns>
+ public Task CreateTupFile(TangoVersion tangoVersion, string serialNumber, string targetFilePath)
+ {
+ if (_isGeneratingTup)
+ {
+ throw new InvalidOperationException("Only one TUP file can be created at a time.");
+ }
+
+ _isGeneratingTup = true;
+
+ return Task.Factory.StartNew(() =>
+ {
+ String tempDbName = "Tango_TUP";
+ var tempPackageFolder = TemporaryManager.CreateFolder();
+ String tempBackupFolder = "C:\\FSE_TUP";
+ String tempBackupFile = Path.Combine(tempBackupFolder, tempDbName + ".bak");
+ var tempZipFile = TemporaryManager.CreateImaginaryFile();
+ DbManager dbManager = null;
+
+ LogManager.Log("Generating tup file...");
+ LogManager.Log($"Tup file: '{targetFilePath}.'");
+ LogManager.Log($"Temporary db name: '{tempDbName}'.");
+ LogManager.Log($"Temporary package folder: '{tempPackageFolder}'.");
+ LogManager.Log($"Temporary db backup folder: '{tempBackupFolder}'.");
+ LogManager.Log($"Temporary db backup file: '{tempBackupFile}'.");
+ LogManager.Log($"Temporary zip file: '{tempZipFile}'.");
+
+ try
+ {
+ LogManager.Log("Initializing...");
+
+ OnProgress("Initializing...");
+
+ Tango.Core.DataSource localDataSource = new Tango.Core.DataSource()
+ {
+ Address = "localhost\\SQLEXPRESS",
+ IntegratedSecurity = true,
+ Type = DataSourceType.SQLServer,
+ Catalog = null,
+ };
+
+ try
+ {
+ LogManager.Log($"Trying to connect via SQLEXPRESS:\n{localDataSource.ToJsonString()}");
+ dbManager = DbManager.FromDataSource(localDataSource);
+ }
+ catch (Exception ex)
+ {
+ try
+ {
+ LogManager.Log(ex, "Could not connect using SQLEXPRESS. Trying local DB...");
+
+ CmdCommand command = new CmdCommand("sqllocaldb", "start \"MSSQLLocalDB\"");
+ var result = command.Run().Result;
+
+ command = new CmdCommand("sqllocaldb", "info \"MSSQLLocalDB\"");
+ result = command.Run().Result;
+
+ String pattern = "np:.+";
+ Regex reg = new Regex(pattern);
+ var match = reg.Match(result.StandardOutput);
+ String address = match.ToString();
+ if (address.Contains("np:"))
+ {
+ localDataSource.Address = address;
+ address = address.Trim().Replace("\r", "");
+ }
+ else
+ {
+ throw new ArgumentException("Could not parse LocalDB address string.");
+ }
+
+ LogManager.Log($"Trying to connect via LocalDB:\n{localDataSource.ToJsonString()}");
+ dbManager = DbManager.FromDataSource(localDataSource);
+ }
+ catch (Exception x)
+ {
+ LogManager.Log(x, "Could not find any database service for this operation.");
+ throw x;
+ }
+ }
+
+
+
+ OnProgress($"Downloading Tango version '{tangoVersion.Version}'...");
+
+ LogManager.Log("Connecting to machine service...");
+
+ LogManager.Log("Requesting version download from machine service...");
+ var response = WebClient.DownloadTangoVersion(new DownloadTangoVersionRequest() { TangoVersionGuid = tangoVersion.Guid }).Result;
+
+ LogManager.Log($"Machine service response:\n{response.ToJsonString()}");
+
+ var remoteDataSource = response.DataSource;
+
+ using (AutoFileDownloader downloader = new AutoFileDownloader(response.BlobAddress, response.CdnAddress, tempZipFile))
+ {
+ downloader.Progress += (x, e) =>
+ {
+ OnProgress($"Downloading Tango version '{response.Version}'...", false, e.Current, e.Total);
+ };
+
+ downloader.ResolveMode().GetAwaiter().GetResult();
+
+ LogManager.Log($"Downloading Tango version from: '{downloader.Address}'");
+
+ downloader.Download().Wait();
+ }
+
+ LogManager.Log("Extracting version package...");
+
+ OnProgress("Extracting package...");
+
+ using (ZipFile zip = new ZipFile(tempZipFile))
+ {
+ int currentEntry = 0;
+
+ zip.ExtractProgress += (x, args) =>
+ {
+ if (args.EventType == ZipProgressEventType.Extracting_AfterExtractEntry)
+ {
+ OnProgress("Extracting package...", false, currentEntry++, zip.Entries.Count);
+ }
+ };
+
+ zip.ExtractAll(tempPackageFolder);
+ }
+
+ OnProgress("Extracting version information...");
+ LogManager.Log("Extracting publish information...");
+ PublishInfo publishInfo = PublishInfo.FromJson(File.ReadAllText(Path.Combine(tempPackageFolder, "version.json")));
+ LogManager.Log($"Publish Information:\n{publishInfo}");
+
+ LogManager.Log("Modifying publish information to custom tup file...");
+ publishInfo.IsMachineTupPackage = true;
+ publishInfo.MachineSerialNumber = serialNumber;
+ publishInfo.MachineDeploymentSlot = (DeploymentSlot)Enum.Parse(typeof(DeploymentSlot), AuthenticationProvider.CurrentEnvironment.Name);
+
+ OnProgress("Creating temporary database...");
+
+ LogManager.Log($"Creating temporary db backup directory '{tempBackupFolder}'");
+
+ Directory.CreateDirectory(tempBackupFolder);
+
+ LogManager.Log($"Creating new database: '{tempDbName}'");
+
+ //Create temp db
+ dbManager.Create(tempDbName, Path.Combine(tempBackupFolder, tempDbName + ".mdf"));
+
+ OnProgress("Generating database snapshot...");
+
+ LogManager.Log("Starting database synchronization...");
+
+ Thread.Sleep(2000);
+
+ localDataSource.Catalog = tempDbName;
+
+ ExaminerSequenceConfigurationRunner runner = new ExaminerSequenceConfigurationRunner(
+ Path.Combine(tempPackageFolder, "Provision Scripts", "config.xml"),
+ Path.Combine(tempPackageFolder, "Provision Scripts"),
+ remoteDataSource,
+ localDataSource,
+ serialNumber);
+
+ runner.ScriptExecuting += (x, item) =>
+ {
+ LogManager.Log($"Executing script '{item.FileName}'...");
+ OnProgress($"{item.Name}...");
+ };
+
+ runner.Log += (x, log) =>
+ {
+ LogManager.Log(log);
+ };
+
+ runner.Run().GetAwaiter().GetResult();
+
+ OnProgress("Generating database snapshot...");
+
+ if (File.Exists(tempBackupFile))
+ {
+ LogManager.Log($"Deleting file '{tempBackupFile}'");
+ File.Delete(tempBackupFile);
+ }
+
+ LogManager.Log($"Generating backup for '{tempDbName}' to '{tempBackupFile}'...");
+
+ dbManager.Backup(tempDbName, tempBackupFile);
+
+ OnProgress("Injecting database snapshot to PPC package...");
+
+ using (ZipFile zip = new ZipFile(tempZipFile))
+ {
+ LogManager.Log($"Injecting file '{tempBackupFile}' to original package at '{tempZipFile}'...");
+ zip.AddFile(tempBackupFile, "/");
+
+ LogManager.Log($"Injecting modified publish information...");
+ zip.UpdateEntry("version.json", publishInfo.ToJson());
+
+ zip.Save();
+ }
+
+ LogManager.Log($"Copying '{tempZipFile}' to '{targetFilePath}'...");
+
+ File.Copy(tempZipFile, targetFilePath, true);
+
+ OnProgress("Completed", false, 100, 100);
+
+ LogManager.Log("TUP file generation completed successfully.");
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "TUP file generation failed.");
+ OnProgress("Failed", false, 0, 100);
+ throw ex;
+ }
+ finally
+ {
+ _isGeneratingTup = false;
+ LogManager.Log($"Removing '{tempZipFile}'.");
+ tempZipFile.Delete();
+ LogManager.Log($"Removing '{tempPackageFolder}'.");
+ tempPackageFolder.Delete();
+
+ try
+ {
+ LogManager.Log($"Removing database '{tempDbName}'.");
+ dbManager.SetOffline(tempDbName);
+ dbManager.SetOnline(tempDbName);
+ dbManager.Delete(tempDbName);
+ dbManager.Dispose();
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, $"Error removing temp database '{tempDbName}'.");
+ }
+
+ try
+ {
+ LogManager.Log($"Removing '{tempBackupFolder}'.");
+ Directory.Delete(tempBackupFolder, true);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, $"Error removing folder '{tempBackupFolder}'.");
+ }
+ }
+ });
+ }
+
+ /// <summary>
+ /// Called when the TUP creation has made some progress.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ /// <param name="isIntermediate">if set to <c>true</c> [is intermediate].</param>
+ /// <param name="progress">The progress.</param>
+ /// <param name="total">The total.</param>
+ protected virtual void OnProgress(String message, bool isIntermediate = true, double progress = 0, double total = 100)
+ {
+ Progress?.Invoke(this, new RemoteUpgradeProgressEventArgs()
+ {
+ Message = message,
+ IsIntermediate = isIntermediate,
+ Progress = progress,
+ Total = total,
+ });
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj
index 24fbc3ae9..140c5b22c 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj
@@ -121,6 +121,9 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
+ <Compile Include="..\..\PPC\Tango.PPC.Common\Publish\PublishInfo.cs">
+ <Link>RemoteUpgrade\PublishInfo.cs</Link>
+ </Compile>
<Compile Include="Authentication\DefaultAuthenticationProvider.cs" />
<Compile Include="BugReporting\DefaultBugReporter.cs" />
<Compile Include="BugReporting\SystemInformationModel.cs" />
@@ -179,6 +182,7 @@
<Compile Include="Performance\DefaultPerformanceProvider.cs" />
<Compile Include="MachineUpdates\DefaultMachineUpdatesProvider.cs" />
<Compile Include="RemoteDesktop\DefaultRemoteDesktopProvider.cs" />
+ <Compile Include="RemoteUpgrade\DefaultRemoteUpgradeManager.cs" />
<Compile Include="Resolution\DefaultResolutionService.cs" />
<Compile Include="Storage\DefaultStorageProvider.cs" />
<Compile Include="Storage\ExplorerControlDialog.xaml.cs">
@@ -405,6 +409,10 @@
<Project>{8491d07b-c1f6-4b62-a412-41b9fd2d6538}</Project>
<Name>Tango.SharedUI</Name>
</ProjectReference>
+ <ProjectReference Include="..\..\Tango.SQLExaminer\Tango.SQLExaminer.csproj">
+ <Project>{e1e66ed9-597d-45fa-8048-de90a6930484}</Project>
+ <Name>Tango.SQLExaminer</Name>
+ </ProjectReference>
<ProjectReference Include="..\..\Tango.TFS\Tango.TFS.csproj">
<Project>{998f8471-dc1b-41b6-9d96-354e1b4e7a32}</Project>
<Name>Tango.TFS</Name>
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs
index 4d9c49a74..bd012aea0 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs
@@ -46,6 +46,8 @@ using Tango.FSE.UI.Threading;
using Tango.FSE.UI.ViewModels;
using Tango.FSE.Common.BugReporting;
using Tango.FSE.UI.BugReporting;
+using Tango.FSE.Common.RemoteUpgrade;
+using Tango.FSE.UI.RemoteUpgrade;
namespace Tango.FSE.UI
{
@@ -74,6 +76,7 @@ namespace Tango.FSE.UI
TangoIOC.Default.Unregister<FSEServicesContainer>();
TangoIOC.Default.Unregister<IMachineUpdatesProvider>();
TangoIOC.Default.Unregister<IBugReporter>();
+ TangoIOC.Default.Unregister<IRemoteUpgradeManager>();
//TangoIOC.Default.Unregister<ExternalBridgeScanner>();
//TangoIOC.Default.Unregister<IDiagnosticsFrameProvider>();
//TangoIOC.Default.Unregister<IEventLogger>();
@@ -102,6 +105,7 @@ namespace Tango.FSE.UI
TangoIOC.Default.Register<ILoggingProvider, DefaultLoggingProvider>();
TangoIOC.Default.Register<IStorageProvider, DefaultStorageProvider>();
TangoIOC.Default.Register<IMachineUpdatesProvider, DefaultMachineUpdatesProvider>();
+ TangoIOC.Default.Register<IRemoteUpgradeManager, DefaultRemoteUpgradeManager>();
TangoIOC.Default.Register<MainWindowVM>();
TangoIOC.Default.Register<MainViewVM>();
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/DownloadTangoVersionRequest.cs b/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/DownloadTangoVersionRequest.cs
new file mode 100644
index 000000000..ffe0910cb
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/DownloadTangoVersionRequest.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Transport.Web;
+
+namespace Tango.FSE.Web.Messages
+{
+ public class DownloadTangoVersionRequest : WebRequestMessage
+ {
+ public String TangoVersionGuid { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/DownloadTangoVersionResponse.cs b/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/DownloadTangoVersionResponse.cs
new file mode 100644
index 000000000..d44859e8d
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/DownloadTangoVersionResponse.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core;
+using Tango.Transport.Web;
+
+namespace Tango.FSE.Web.Messages
+{
+ public class DownloadTangoVersionResponse : WebResponseMessage
+ {
+ public String Version { get; set; }
+ public String BlobAddress { get; set; }
+ public String CdnAddress { get; set; }
+ public DataSource DataSource { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Web/Tango.FSE.Web.csproj b/Software/Visual_Studio/FSE/Tango.FSE.Web/Tango.FSE.Web.csproj
index 299240d60..bd42e54f5 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.Web/Tango.FSE.Web.csproj
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Web/Tango.FSE.Web.csproj
@@ -43,6 +43,8 @@
<ItemGroup>
<Compile Include="Messages\BugReportingInfoRequest.cs" />
<Compile Include="Messages\BugReportingInfoResponse.cs" />
+ <Compile Include="Messages\DownloadTangoVersionRequest.cs" />
+ <Compile Include="Messages\DownloadTangoVersionResponse.cs" />
<Compile Include="Messages\LoginRequest.cs" />
<Compile Include="Messages\LoginResponse.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
diff --git a/Software/Visual_Studio/Utilities/Tango.WebClientGenerator/Program.cs b/Software/Visual_Studio/Utilities/Tango.WebClientGenerator/Program.cs
index 36c88bffb..501058016 100644
--- a/Software/Visual_Studio/Utilities/Tango.WebClientGenerator/Program.cs
+++ b/Software/Visual_Studio/Utilities/Tango.WebClientGenerator/Program.cs
@@ -24,6 +24,8 @@ namespace Tango.WebClientGenerator
//Generate FSE client.
GenerateWebClientV2<FSE.Web.Messages.LoginRequest, FSE.Web.Messages.LoginResponse, MachineService.Controllers.FSEController>("Tango.FSE.BL.Web", "FSEWebClientBase", PathHelper.GetSolutionFolder() + @"\FSE\Tango.FSE.BL\Web");
+
+ Console.WriteLine("Done");
}
private static void GenerateWebClient<TLoginRequest, TLoginResponse, TController>(String nameSpace, String name, String path) where TLoginRequest : WebRequestMessage where TLoginResponse : WebTokenResponse where TController : TangoController
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs
index dccf2d24c..27d93f467 100644
--- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs
@@ -4,17 +4,22 @@ using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Authentication;
+using System.Threading.Tasks;
using System.Web.Http;
+using Tango.BL;
using Tango.BL.Builders;
using Tango.BL.Entities;
using Tango.Core;
using Tango.Core.Cryptography;
+using Tango.Core.DB;
using Tango.FSE.Web.Messages;
using Tango.MachineService.Filters;
using Tango.Web.Controllers;
using Tango.Web.Helpers;
using Tango.Web.Security;
+using Tango.Web.SMO;
using Tango.Web.SQLServer;
+using Tango.Web.Storage;
namespace Tango.MachineService.Controllers
{
@@ -117,5 +122,62 @@ namespace Tango.MachineService.Controllers
UserEmail = MachineServiceConfig.FSE_TFS_USER_EMAIL
};
}
+
+ [HttpPost]
+ [JwtTokenFilter]
+ public DownloadTangoVersionResponse DownloadTangoVersion(DownloadTangoVersionRequest request)
+ {
+ DownloadTangoVersionResponse response = new DownloadTangoVersionResponse();
+
+ using (ObservablesContext db = ObservablesContextHelper.CreateContext())
+ {
+ var tangoVersion = db.TangoVersions.SingleOrDefault(x => x.Guid == request.TangoVersionGuid);
+
+ if (tangoVersion == null)
+ {
+ throw new ArgumentException("Could not locate the specified Tango version.");
+ }
+
+ response.Version = tangoVersion.Version;
+
+ var manager = new BlobStorageManager();
+ var container = manager.GetContainer(MachineServiceConfig.TANGO_VERSIONS_CONTAINER);
+ var blob = container.GetBlockBlobReference(tangoVersion.BlobName);
+
+ response.BlobAddress = blob.GenerateReadSignature(TimeSpan.FromMinutes(60));
+
+ if (!String.IsNullOrWhiteSpace(MachineServiceConfig.CDN_ENDPOINT))
+ {
+ response.CdnAddress = MachineServiceConfig.CDN_ENDPOINT + blob.Uri.AbsolutePath;
+ }
+
+ DbCredentials credentials = new DbCredentials();
+
+ using (SmoManager smo = new SmoManager())
+ {
+ credentials = smo.CreateRandomLoginAndUser();
+
+ Task.Delay(TimeSpan.FromMinutes(PPCController.SQL_TEMP_CREDENTIALS_EXP_MINUTS)).ContinueWith((x) =>
+ {
+ using (SmoManager m = new SmoManager())
+ {
+ m.DeleteLoginAndUser(credentials.UserName);
+ }
+ });
+ }
+
+ response.DataSource = new DataSource()
+ {
+ Address = MachineServiceConfig.DB_ADDRESS,
+ Catalog = MachineServiceConfig.DB_CATALOG,
+ UserName = credentials.UserName,
+ Password = credentials.Password,
+ IntegratedSecurity = false,
+ Type = DataSourceType.SQLServer,
+ };
+ }
+
+ return response;
+ }
}
}
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs
index f508fea15..5f697f979 100644
--- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs
@@ -120,8 +120,6 @@ namespace Tango.MachineService.Controllers
[JwtTokenFilter]
public DownloadLatestVersionResponse DownloadLatestVersion(DownloadLatestVersionRequest request)
{
- LogManager.Log("Request received...");
-
DownloadLatestVersionResponse response = new DownloadLatestVersionResponse();
using (ObservablesContext db = ObservablesContextHelper.CreateContext())