src/Discovery/Discover.cs (264 lines of code) (raw):
using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
using System.Threading.Tasks;
using Azure.Migrate.Export.Common;
using Azure.Migrate.Export.Excel;
using Azure.Migrate.Export.HttpRequestHelper;
using Azure.Migrate.Export.Models;
namespace Azure.Migrate.Export.Discovery
{
public class Discover
{
private UserInput UserInputObj;
public List<DiscoveryData> DiscoveredData;
public vCenterHostDiscovery VCenterHostData;
public Discover(UserInput userInputObj)
{
UserInputObj = userInputObj;
DiscoveredData = new List<DiscoveryData>();
VCenterHostData = new vCenterHostDiscovery();
}
public bool BeginDiscovery()
{
if (UserInputObj == null)
throw new Exception("User input provided is null");
UserInputObj.LoggerObj.LogInformation("Initiating discovered data retrieval");
DeletePreviousDiscoveryReport();
string masterSitesUrl = Routes.ProtocolScheme + Routes.AzureManagementApiHostname + Routes.ForwardSlash +
Routes.SubscriptionPath + Routes.ForwardSlash + UserInputObj.Subscription.Key + Routes.ForwardSlash +
Routes.ResourceGroupPath + Routes.ForwardSlash + UserInputObj.ResourceGroupName.Value + Routes.ForwardSlash +
Routes.ProvidersPath + Routes.ForwardSlash + Routes.OffAzureProvidersPath + Routes.ForwardSlash +
Routes.MasterSitesPath + Routes.ForwardSlash + UserInputObj.DiscoverySiteName +
Routes.QueryStringQuestionMark + Routes.QueryParameterApiVersion + Routes.QueryStringEquals + Routes.MasterSiteApiVersion;
string masterSitesJsonResponse = "";
try
{
masterSitesJsonResponse = new HttpClientHelper().GetHttpRequestJsonStringResponse(masterSitesUrl, UserInputObj).Result;
}
catch (OperationCanceledException)
{
throw;
}
catch (AggregateException aeMasterSites)
{
string errorMessage = "";
foreach (var e in aeMasterSites.Flatten().InnerExceptions)
{
if (e is OperationCanceledException)
throw e;
else
{
errorMessage = errorMessage + e.Message + " ";
}
}
UserInputObj.LoggerObj.LogError($"Failed to retrieve master sites: {errorMessage}");
return false;
}
catch (Exception exMasterSitesHttpResponse)
{
UserInputObj.LoggerObj.LogError($"Failed to retrieve master sites: {exMasterSitesHttpResponse.Message}");
return false;
}
MasterSitesJSON masterSitesObj = JsonConvert.DeserializeObject<MasterSitesJSON>(masterSitesJsonResponse);
UserInputObj.LoggerObj.LogInformation(3, "Received discovery sites"); // 8 % complete
if (UserInputObj.CancellationContext.IsCancellationRequested)
UtilityFunctions.InitiateCancellation(UserInputObj);
int excelCreationPercentProgress = 0;
if (UserInputObj.AzureMigrateSourceAppliances.Contains("import"))
excelCreationPercentProgress = PerformImportDiscovery(masterSitesObj);
else
excelCreationPercentProgress = PerformApplianceDiscovery(masterSitesObj);
if (DiscoveredData.Count == 0)
{
UserInputObj.LoggerObj.LogError($"Consolidated discovery data has no discovered machines");
return false;
}
UserInputObj.LoggerObj.LogInformation($"Retrieved discovery data for {DiscoveredData.Count.ToString()} machines");
DiscoveryProperties discoveryProperties = new DiscoveryProperties();
CreateDiscoveryPropertiesModel(discoveryProperties);
ExportDiscoveryReport exporter = new ExportDiscoveryReport(DiscoveredData, VCenterHostData, discoveryProperties);
exporter.GenerateDiscoveryReportExcel();
UserInputObj.LoggerObj.LogInformation(excelCreationPercentProgress, "Discovery report excel created successfully"); // IsExpressWorkflow ? 20 : 100 % Complete
return true;
}
private void DeletePreviousDiscoveryReport()
{
UserInputObj.LoggerObj.LogInformation("Deleting previous discovery reports, if any");
var directory = DiscoveryReportConstants.DiscoveryReportDirectory;
if (!Directory.Exists(directory))
{
UserInputObj.LoggerObj.LogInformation("No discovery reports found");
return;
}
UserInputObj.LoggerObj.LogInformation("Discovery report found, please ensure the file is closed otherwise deleting it won't be possible and process will terminate");
Directory.Delete(directory, true);
}
private void CreateDiscoveryPropertiesModel(DiscoveryProperties discoveryProperites)
{
UserInputObj.LoggerObj.LogInformation("Generating model for discovery properties");
discoveryProperites.TenantId = UserInputObj.TenantId;
discoveryProperites.Subscription = UserInputObj.Subscription.Value;
discoveryProperites.ResourceGroup = UserInputObj.ResourceGroupName.Value;
discoveryProperites.AzureMigrateProjectName = UserInputObj.AzureMigrateProjectName.Value;
discoveryProperites.DiscoverySiteName = UserInputObj.DiscoverySiteName;
discoveryProperites.Workflow = UserInputObj.WorkflowObj.IsExpressWorkflow ? "Express" : "Custom - Discovery";
discoveryProperites.SourceAppliances = string.Join(",", UserInputObj.AzureMigrateSourceAppliances);
}
private int PerformApplianceDiscovery(MasterSitesJSON masterSitesObj)
{
List<string> vmwareSites = new List<string>();
List<string> hypervSites = new List<string>();
List<string> serverSites = new List<string>();
foreach (string site in masterSitesObj.Properties.Sites)
{
if (site.Contains("vmwaresites"))
vmwareSites.Add(site);
else if (site.Contains("hypervsites"))
hypervSites.Add(site);
else if (site.Contains("serversites"))
serverSites.Add(site);
}
UserInputObj.LoggerObj.LogInformation(2, "Finished parsing discovery sites"); // 10 % complete
int discoveryDataPerSitePercentProgress = UserInputObj.WorkflowObj.IsExpressWorkflow ? 3 : 25;
int excelCreationPercentProgress = UserInputObj.WorkflowObj.IsExpressWorkflow ? 1 : 15;
if (UserInputObj.AzureMigrateSourceAppliances.Count == 2)
{
discoveryDataPerSitePercentProgress = UserInputObj.WorkflowObj.IsExpressWorkflow ? 4 : 40;
excelCreationPercentProgress = UserInputObj.WorkflowObj.IsExpressWorkflow ? 2 : 10;
}
else if (UserInputObj.AzureMigrateSourceAppliances.Count == 1)
{
discoveryDataPerSitePercentProgress = UserInputObj.WorkflowObj.IsExpressWorkflow ? 7 : 70;
excelCreationPercentProgress = UserInputObj.WorkflowObj.IsExpressWorkflow ? 3 : 20;
}
List<DiscoveryData> vmwareMachinesDiscovery = new List<DiscoveryData>();
List<DiscoveryData> hypervMachinesDiscovery = new List<DiscoveryData>();
List<DiscoveryData> physicalMachinesDiscovery = new List<DiscoveryData>();
try
{
Parallel.For(0, UserInputObj.AzureMigrateSourceAppliances.Count, i =>
{
if (UserInputObj.AzureMigrateSourceAppliances[i].Equals("vmware"))
{
UserInputObj.LoggerObj.LogInformation("Retrieving discovery data from VMWare sites");
vmwareMachinesDiscovery = new RetrieveDiscoveryData().BeginRetrieval(UserInputObj, vmwareSites, DiscoverySites.VMWare);
CalculateVCenterHostDiscoveryData(UserInputObj, vmwareSites);
UserInputObj.LoggerObj.LogInformation(discoveryDataPerSitePercentProgress, $"Retrieved discovery data for {vmwareMachinesDiscovery.Count.ToString()} machines from VMWare sites");
}
else if (UserInputObj.AzureMigrateSourceAppliances[i].Equals("hyperv"))
{
UserInputObj.LoggerObj.LogInformation("Retrieving discovery data from HyperV sites");
hypervMachinesDiscovery = new RetrieveDiscoveryData().BeginRetrieval(UserInputObj, hypervSites, DiscoverySites.HyperV);
UserInputObj.LoggerObj.LogInformation(discoveryDataPerSitePercentProgress, $"Retrieved discovery data for {hypervMachinesDiscovery.Count.ToString()} machines from HyperV sites");
}
else if (UserInputObj.AzureMigrateSourceAppliances[i].Equals("physical"))
{
UserInputObj.LoggerObj.LogInformation("Retrieving discovery data from Physical sites");
physicalMachinesDiscovery = new RetrieveDiscoveryData().BeginRetrieval(UserInputObj, serverSites, DiscoverySites.Physical);
UserInputObj.LoggerObj.LogInformation(discoveryDataPerSitePercentProgress, $"Retrieved discovery data for {physicalMachinesDiscovery.Count.ToString()} machines from Physical sites");
}
});
}
catch (AggregateException ae)
{
string errorMessage = "";
foreach (var e in ae.Flatten().InnerExceptions)
{
if (e is OperationCanceledException)
throw e;
else
{
errorMessage = errorMessage + e.Message + " ";
}
}
throw new Exception(errorMessage);
}
catch (Exception exDiscover)
{
throw exDiscover;
}
try
{
DiscoveredData.AddRange(vmwareMachinesDiscovery);
}
catch (Exception exConsolidateVmware)
{
UserInputObj.LoggerObj.LogWarning($"Failed data consolidation from VMWare sites: {exConsolidateVmware.Message}");
}
try
{
DiscoveredData.AddRange(hypervMachinesDiscovery);
}
catch (Exception exConsolidateHyperv)
{
UserInputObj.LoggerObj.LogWarning($"Failed data consolidation from HyperV sites: {exConsolidateHyperv.Message}");
}
try
{
DiscoveredData.AddRange(physicalMachinesDiscovery);
}
catch (Exception exConsolidatePhysical)
{
UserInputObj.LoggerObj.LogWarning($"Failed data consolidation from Physical sites: {exConsolidatePhysical.Message}");
}
return excelCreationPercentProgress;
}
private int PerformImportDiscovery(MasterSitesJSON masterSitesObj)
{
List<string> importSites = new List<string>();
foreach (string site in masterSitesObj.Properties.Sites)
{
if (site.Contains("importsites"))
importSites.Add(site);
}
UserInputObj.LoggerObj.LogInformation(2, "Finished parsing discovery sites"); // 10 % complete
int discoveryDataPerSitePercentProgress = UserInputObj.WorkflowObj.IsExpressWorkflow ? 7 : 70;
int excelCreationPercentProgress = UserInputObj.WorkflowObj.IsExpressWorkflow ? 3 : 20;
List<DiscoveryData> importMachinesDiscovery = new List<DiscoveryData>();
try
{
UserInputObj.LoggerObj.LogInformation("Retrieving discovery data from Import sites");
importMachinesDiscovery = new RetrieveDiscoveryData().BeginRetrieval(UserInputObj, importSites, DiscoverySites.Import);
UserInputObj.LoggerObj.LogInformation(discoveryDataPerSitePercentProgress, $"Retrieved discovery data for {importMachinesDiscovery.Count.ToString()} machines from Import sites");
}
catch (AggregateException ae)
{
string errorMessage = "";
foreach (var e in ae.Flatten().InnerExceptions)
{
if (e is OperationCanceledException)
throw e;
else
{
errorMessage = errorMessage + e.Message + " ";
}
}
throw new Exception(errorMessage);
}
catch (Exception exDiscover)
{
throw exDiscover;
}
try
{
DiscoveredData.AddRange(importMachinesDiscovery);
}
catch (Exception exConsolidateImport)
{
UserInputObj.LoggerObj.LogWarning($"Failed data consolidation from Import sites: {exConsolidateImport.Message}");
}
return excelCreationPercentProgress;
}
private void CalculateVCenterHostDiscoveryData(UserInput userInputObj, List<string> vmwareSiteUrls)
{
foreach (string siteUrl in vmwareSiteUrls)
{
List<KeyValuePair<string, int>> hostAndVCenterList = RetrieveDiscoveryData.RetrieveHostvCenterData(userInputObj, siteUrl);
VCenterHostData.Hosts += hostAndVCenterList[0].Value;
VCenterHostData.vCenters += hostAndVCenterList[1].Value;
};
}
}
}