using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Data.Entity; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using Ionic.Zip; using Microsoft.Azure.Management.AppService.Fluent; using Microsoft.Azure.Management.Fluent; using Tango.AzureUtils.Database; using Tango.AzureUtils.Storage; using Tango.BL; using Tango.BL.Entities; using Tango.BL.Enumerations; using Tango.PMR.FirmwareUpgrade; using Tango.PPC.Common.Publish; namespace Tango.AzureUtils.Firmware { public class FirmwareManager : AzureUtilsComponentBase { private DatabaseManager _databaseManager; private StorageManager _storageManager; public FirmwareManager(IAzure azure) : base(azure) { _databaseManager = CreateManager(); _storageManager = CreateManager(); } #region Firmware Injection public async Task InjectFirmwarePackage(IWebAppBase slot, MachineTypes machineType, String tfpFile, String versionTag) { OnProgress(AzureUtilsStage.Firmware, $"Validating TFP package..."); VersionPackageDescriptor tfpPackage = null; try { tfpPackage = await GetVersionPackageDescriptor(tfpFile); tfpPackage.Validate(); } catch (Exception ex) { throw new ValidationException($"The specified TFP package is invalid.\n{ex.FlattenMessage()}"); } TangoVersion version = await _databaseManager.GetLatestTangoVersion(slot, machineType, null); if (Version.Parse(version.FirmwareVersion) >= tfpPackage.GetMcuVersion()) { await RequestConfirmation($"The specified firmware version is '{tfpPackage.GetMcuVersion()}' while latest version is '{version.FirmwareVersion}'. Do you wish to continue?"); } OnProgress(AzureUtilsStage.Firmware, $"Retrieving '{slot.Name}' settings..."); var settings = await slot.GetMachineServiceSettingsAsync(); await _storageManager.Connect(settings.STORAGE_ACCOUNT); var zipFile = TemporaryManager.CreateImaginaryFile(".zip"); await _storageManager.DownloadLatestTangoVersion(slot, machineType, zipFile, versionTag); OnProgress(AzureUtilsStage.Firmware, $"Replacing firmware_package.tfp..."); await Task.Factory.StartNew(() => { using (ZipFile zip = new ZipFile(zipFile)) { var versionReader = zip.Entries.SingleOrDefault(x => x.FileName == "version.json").OpenReader(); String versionJson = null; using (StreamReader reader = new StreamReader(versionReader)) { versionJson = reader.ReadToEnd(); } PublishInfo publishInfo = PublishInfo.FromJson(versionJson); publishInfo.Firmware = tfpPackage; zip.UpdateEntry("version.json", Encoding.Default.GetBytes(publishInfo.ToJson())); zip.UpdateEntry("firmware_package.tfp", File.ReadAllBytes(tfpFile)); zip.Save(); } }); await _storageManager.ReplaceLatestTangoVersion(slot, machineType, zipFile, versionTag); OnProgress(AzureUtilsStage.Firmware, $"Updating firmware version on database..."); using (ObservablesContext db = ObservablesContext.CreateDefault(settings.ToDataSource())) { var v = await db.TangoVersions.SingleOrDefaultAsync(x => x.Guid == version.Guid); v.FirmwareVersion = tfpPackage.GetMcuVersion().ToString(); await db.SaveChangesAsync(); } OnCompleted("Firmware version injected successfully."); } public Task GetVersionPackageDescriptor(String tfpFile) { return Task.Factory.StartNew(() => { using (ZipFile zip = ZipFile.Read(tfpFile)) { var reader = zip.Entries.SingleOrDefault(x => x.FileName == "package.cfg").OpenReader(); return VersionPackageDescriptor.Parser.ParseFrom(reader); } }); } public async Task GetFirmwareVersion(String tfpFile) { var desc = await GetVersionPackageDescriptor(tfpFile); return desc.GetMcuVersion().ToString(); } #endregion } }