diff --git a/Packages.props b/Packages.props
index 64fcaa34..57cdecbd 100644
--- a/Packages.props
+++ b/Packages.props
@@ -26,6 +26,7 @@
+
diff --git a/bin/nuget/Microsoft.SqlServer.Migration.Tde.1.0.20230110.39.nupkg b/bin/nuget/Microsoft.SqlServer.Migration.Tde.1.0.20230110.39.nupkg
new file mode 100644
index 00000000..b3d57e0d
Binary files /dev/null and b/bin/nuget/Microsoft.SqlServer.Migration.Tde.1.0.20230110.39.nupkg differ
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Microsoft.SqlTools.ServiceLayer.csproj b/src/Microsoft.SqlTools.ServiceLayer/Microsoft.SqlTools.ServiceLayer.csproj
index 725d9674..7b5b427a 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Microsoft.SqlTools.ServiceLayer.csproj
+++ b/src/Microsoft.SqlTools.ServiceLayer/Microsoft.SqlTools.ServiceLayer.csproj
@@ -54,6 +54,7 @@
+
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Migration/Contracts/CertificateMigrationProgressEvent.cs b/src/Microsoft.SqlTools.ServiceLayer/Migration/Contracts/CertificateMigrationProgressEvent.cs
new file mode 100644
index 00000000..cd987c86
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/Migration/Contracts/CertificateMigrationProgressEvent.cs
@@ -0,0 +1,44 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.SqlTools.Hosting.Protocol.Contracts;
+
+namespace Microsoft.SqlTools.ServiceLayer.Migration.Contracts
+{
+ ///
+ /// Parameters for the certificate migration progress event
+ ///
+ public class CertificateMigrationProgressParams
+ {
+ ///
+ /// Database name
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Message related to the success status. true should describe a positive outcome. false should have an error.
+ ///
+ public string Message { get; set; }
+
+ ///
+ /// Result of migration
+ ///
+ public bool Success { get; set; }
+ }
+
+
+ ///
+ /// Create a certificate migration request. This should be register at the client.
+ ///
+ public class CertificateMigrationProgressEvent
+ {
+ ///
+ /// Name and parameters for the event definition.
+ ///
+ public static readonly
+ EventType Type =
+ EventType.Create("migration/tdemigrationprogress");
+ }
+}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Migration/Contracts/CertificateMigrationRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/Migration/Contracts/CertificateMigrationRequest.cs
new file mode 100644
index 00000000..2e4d117c
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/Migration/Contracts/CertificateMigrationRequest.cs
@@ -0,0 +1,111 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System.Collections.Generic;
+using Microsoft.SqlTools.Hosting.Protocol.Contracts;
+
+namespace Microsoft.SqlTools.ServiceLayer.Migration.Contracts
+{
+ ///
+ /// Parameters for the certificate migration operation
+ ///
+ public class CertificateMigrationParams
+ {
+ ///
+ /// List of databses to migrate the certificates
+ ///
+ public List EncryptedDatabases { get; set; } = new List();
+
+ ///
+ /// Source connection string to the server
+ ///
+ public string SourceSqlConnectionString { get; set; }
+
+ ///
+ /// Target subscription id
+ ///
+ public string TargetSubscriptionId { get; set; }
+
+ ///
+ /// Target resource group name
+ ///
+ public string TargetResourceGroupName { get; set; }
+
+ ///
+ /// Target manages instance name
+ ///
+ public string TargetManagedInstanceName { get; set; }
+
+ ///
+ /// Place where certificates will be exported
+ ///
+ public string NetworkSharePath { get; set; }
+
+ ///
+ /// Domain for the user credentials able to read from the shared path
+ ///
+ public string NetworkShareDomain { get; set; }
+
+ ///
+ /// Username for the credentials able to read from the shared path
+ ///
+ public string NetworkShareUserName { get; set; }
+
+ ///
+ /// Password for the credentials able to read from the shared path
+ ///
+ public string NetworkSharePassword { get; set; }
+
+ ///
+ /// Access token for the ARM client
+ ///
+ public string AccessToken { get; set; }
+ }
+
+ ///
+ /// Result for the certificate migration operation
+ ///
+ public class CertificateMigrationResult
+ {
+ ///
+ /// List of the status of each certificate migration result attempted.
+ ///
+ public List MigrationStatuses { get; set; } = new List();
+ }
+
+ ///
+ /// Result for an individual database certificate migration
+ ///
+ public class CertificateMigrationEntryResult
+ {
+ ///
+ /// The name of the database this result represent
+ ///
+ public string DbName { get; set; }
+
+ ///
+ /// The result of the migration.
+ ///
+ public bool Success { get; set; }
+
+ ///
+ /// Description of the success status or the error message encountered when the migration was not successful
+ ///
+ public string Message { get; set; }
+ }
+
+ ///
+ /// Certificate migration request definition
+ ///
+ public class CertificateMigrationRequest
+ {
+ ///
+ /// Name, parameter and return type for the certicate migration operation
+ ///
+ public static readonly
+ RequestType Type =
+ RequestType.Create("migration/tdemigration");
+ }
+}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Migration/MigrationService.cs b/src/Microsoft.SqlTools.ServiceLayer/Migration/MigrationService.cs
index 4f6c1f1b..e62f951a 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Migration/MigrationService.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/Migration/MigrationService.cs
@@ -46,6 +46,9 @@ using Microsoft.SqlServer.Migration.Logins.Contracts;
using Microsoft.SqlServer.Migration.Assessment.Common.Models;
using Microsoft.SqlServer.Migration.Assessment.Common.Utils;
using Microsoft.SqlTools.ServiceLayer.Migration.Utils;
+using Microsoft.SqlServer.Migration.Tde;
+using Microsoft.SqlServer.Migration.Tde.Common;
+using Microsoft.SqlTools.ServiceLayer.Migration.Models;
namespace Microsoft.SqlTools.ServiceLayer.Migration
{
@@ -131,6 +134,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Migration
this.ServiceHost.SetRequestHandler(MigrateLoginsRequest.Type, HandleMigrateLogins, true);
this.ServiceHost.SetRequestHandler(EstablishUserMappingRequest.Type, HandleEstablishUserMapping, true);
this.ServiceHost.SetRequestHandler(MigrateServerRolesAndSetPermissionsRequest.Type, HandleMigrateServerRolesAndSetPermissions, true);
+ this.ServiceHost.SetRequestHandler(CertificateMigrationRequest.Type, HandleTdeCertificateMigrationRequest);
}
///
@@ -316,7 +320,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Migration
ElasticSqlDbRecommendationDurationInMs = elasticResults.sqlDbDurationInMs,
ElasticSqlMiRecommendationResults = elasticResults.sqlMiResults,
ElasticSqlMiRecommendationDurationInMs = elasticResults.sqlMiDurationInMs,
- ElasticSqlVmRecommendationResults = elasticResults.sqlVmResults,
+ ElasticSqlVmRecommendationResults = elasticResults.sqlVmResults,
ElasticSqlVmRecommendationDurationInMs = elasticResults.sqlVmDurationInMs,
InstanceRequirements = req,
SkuRecommendationReportPaths = new List { baselineResults.sqlDbReportPath, baselineResults.sqlMiReportPath, baselineResults.sqlVmReportPath },
@@ -336,23 +340,23 @@ namespace Microsoft.SqlTools.ServiceLayer.Migration
}
internal async Task HandleStartLoginMigration(
- StartLoginMigrationParams parameters,
+ StartLoginMigrationParams parameters,
RequestContext requestContext)
{
try
{
ILoginsMigration loginMigration = new LoginsMigration(parameters.SourceConnectionString, parameters.TargetConnectionString,
null, parameters.LoginList, parameters.AADDomainName);
-
+
IDictionary> exceptionMap = new Dictionary>();
- exceptionMap.AddExceptions( await loginMigration.StartValidations(CancellationToken.None) );
- exceptionMap.AddExceptions( await loginMigration.MigrateLogins(CancellationToken.None) );
- exceptionMap.AddExceptions( loginMigration.MigrateServerRoles(CancellationToken.None) );
- exceptionMap.AddExceptions( loginMigration.EstablishUserMapping(CancellationToken.None) );
- exceptionMap.AddExceptions( await loginMigration.EstablishServerRoleMapping(CancellationToken.None) );
- exceptionMap.AddExceptions( loginMigration.SetLoginPermissions(CancellationToken.None) );
- exceptionMap.AddExceptions( loginMigration.SetServerRolePermissions(CancellationToken.None) );
+ exceptionMap.AddExceptions(await loginMigration.StartValidations(CancellationToken.None));
+ exceptionMap.AddExceptions(await loginMigration.MigrateLogins(CancellationToken.None));
+ exceptionMap.AddExceptions(loginMigration.MigrateServerRoles(CancellationToken.None));
+ exceptionMap.AddExceptions(loginMigration.EstablishUserMapping(CancellationToken.None));
+ exceptionMap.AddExceptions(await loginMigration.EstablishServerRoleMapping(CancellationToken.None));
+ exceptionMap.AddExceptions(loginMigration.SetLoginPermissions(CancellationToken.None));
+ exceptionMap.AddExceptions(loginMigration.SetServerRolePermissions(CancellationToken.None));
LoginMigrationResult results = new LoginMigrationResult()
{
@@ -370,7 +374,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Migration
internal async Task HandleValidateLoginMigration(
StartLoginMigrationParams parameters,
RequestContext requestContext)
- {
+ {
try
{
ILoginsMigration loginMigration = new LoginsMigration(parameters.SourceConnectionString, parameters.TargetConnectionString,
@@ -379,7 +383,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Migration
IDictionary> exceptionMap = new Dictionary>();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
- exceptionMap.AddExceptions( await loginMigration.StartValidations(CancellationToken.None) );
+ exceptionMap.AddExceptions(await loginMigration.StartValidations(CancellationToken.None));
stopWatch.Stop();
TimeSpan elapsedTime = stopWatch.Elapsed;
@@ -411,8 +415,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Migration
IDictionary> exceptionMap = new Dictionary>();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
- exceptionMap.AddExceptions( await loginMigration.StartValidations(CancellationToken.None) );
- exceptionMap.AddExceptions( await loginMigration.MigrateLogins(CancellationToken.None) );
+ exceptionMap.AddExceptions(await loginMigration.StartValidations(CancellationToken.None));
+ exceptionMap.AddExceptions(await loginMigration.MigrateLogins(CancellationToken.None));
stopWatch.Stop();
TimeSpan elapsedTime = stopWatch.Elapsed;
@@ -441,11 +445,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Migration
null, parameters.LoginList, parameters.AADDomainName);
IDictionary> exceptionMap = new Dictionary>();
-
+
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
- exceptionMap.AddExceptions( await loginMigration.StartValidations(CancellationToken.None) );
- exceptionMap.AddExceptions( loginMigration.EstablishUserMapping(CancellationToken.None) );
+ exceptionMap.AddExceptions(await loginMigration.StartValidations(CancellationToken.None));
+ exceptionMap.AddExceptions(loginMigration.EstablishUserMapping(CancellationToken.None));
stopWatch.Stop();
TimeSpan elapsedTime = stopWatch.Elapsed;
@@ -501,7 +505,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Migration
ExceptionMap = exceptionMap,
CompletedStep = LoginMigrationStep.MigrateServerRoles,
ElapsedTime = MigrationServiceHelper.FormatTimeSpan(elapsedTime)
- });
+ });
stopWatch.Restart();
exceptionMap.AddExceptions(await loginMigration.EstablishServerRoleMapping(CancellationToken.None));
@@ -560,120 +564,123 @@ namespace Microsoft.SqlTools.ServiceLayer.Migration
}
}
- internal RecommendationResultSet GenerateBaselineRecommendations(SqlInstanceRequirements req, GetSkuRecommendationsParams parameters) {
- RecommendationResultSet resultSet = new RecommendationResultSet();
+ internal RecommendationResultSet GenerateBaselineRecommendations(SqlInstanceRequirements req, GetSkuRecommendationsParams parameters)
+ {
+ RecommendationResultSet resultSet = new RecommendationResultSet();
- SkuRecommendationServiceProvider provider = new SkuRecommendationServiceProvider(new AzureSqlSkuBillingServiceProvider());
- AzurePreferences prefs = new AzurePreferences() {
- EligibleSkuCategories = null, // eligible SKU list will be adjusted with each recommendation type
- ScalingFactor = parameters.ScalingFactor / 100.0,
- TargetEnvironment = TargetEnvironmentType.Production
- };
-
- // generate SQL DB recommendations, if applicable
- if (parameters.TargetPlatforms.Contains("AzureSqlDatabase"))
+ SkuRecommendationServiceProvider provider = new SkuRecommendationServiceProvider(new AzureSqlSkuBillingServiceProvider());
+ AzurePreferences prefs = new AzurePreferences()
+ {
+ EligibleSkuCategories = null, // eligible SKU list will be adjusted with each recommendation type
+ ScalingFactor = parameters.ScalingFactor / 100.0,
+ TargetEnvironment = TargetEnvironmentType.Production
+ };
+
+ // generate SQL DB recommendations, if applicable
+ if (parameters.TargetPlatforms.Contains("AzureSqlDatabase"))
+ {
+ Stopwatch sqlDbStopwatch = new Stopwatch();
+ sqlDbStopwatch.Start();
+
+ prefs.EligibleSkuCategories = GetEligibleSkuCategories("AzureSqlDatabase", parameters.IncludePreviewSkus);
+ resultSet.sqlDbResults = provider.GetSkuRecommendation(prefs, req);
+
+ sqlDbStopwatch.Stop();
+ resultSet.sqlDbDurationInMs = sqlDbStopwatch.ElapsedMilliseconds;
+
+ SkuRecommendationReport sqlDbReport = new SkuRecommendationReport(
+ new Dictionary> { { req, resultSet.sqlDbResults } },
+ AzureSqlTargetPlatform.AzureSqlDatabase.ToString());
+ var sqlDbRecommendationReportFileName = String.Format("SkuRecommendationReport-AzureSqlDatabase-Baseline-{0}", DateTime.UtcNow.ToString("yyyyMMddHH-mmss", CultureInfo.InvariantCulture));
+ var sqlDbRecommendationReportFullPath = Path.Combine(SqlAssessmentConfiguration.ReportsAndLogsRootFolderPath, sqlDbRecommendationReportFileName);
+ ExportRecommendationResultsAction.ExportRecommendationResults(sqlDbReport, SqlAssessmentConfiguration.ReportsAndLogsRootFolderPath, false, sqlDbRecommendationReportFileName);
+ resultSet.sqlDbReportPath = sqlDbRecommendationReportFullPath + ".html";
+ }
+
+ // generate SQL MI recommendations, if applicable
+ if (parameters.TargetPlatforms.Contains("AzureSqlManagedInstance"))
+ {
+ Stopwatch sqlMiStopwatch = new Stopwatch();
+ sqlMiStopwatch.Start();
+
+ prefs.EligibleSkuCategories = GetEligibleSkuCategories("AzureSqlManagedInstance", parameters.IncludePreviewSkus);
+ resultSet.sqlMiResults = provider.GetSkuRecommendation(prefs, req);
+
+ // if no result was generated, create a result with a null SKU
+ if (!resultSet.sqlMiResults.Any())
{
- Stopwatch sqlDbStopwatch = new Stopwatch();
- sqlDbStopwatch.Start();
-
- prefs.EligibleSkuCategories = GetEligibleSkuCategories("AzureSqlDatabase", parameters.IncludePreviewSkus);
- resultSet.sqlDbResults = provider.GetSkuRecommendation(prefs, req);
-
- sqlDbStopwatch.Stop();
- resultSet.sqlDbDurationInMs = sqlDbStopwatch.ElapsedMilliseconds;
-
- SkuRecommendationReport sqlDbReport = new SkuRecommendationReport(
- new Dictionary> { { req, resultSet.sqlDbResults } },
- AzureSqlTargetPlatform.AzureSqlDatabase.ToString());
- var sqlDbRecommendationReportFileName = String.Format("SkuRecommendationReport-AzureSqlDatabase-Baseline-{0}", DateTime.UtcNow.ToString("yyyyMMddHH-mmss", CultureInfo.InvariantCulture));
- var sqlDbRecommendationReportFullPath = Path.Combine(SqlAssessmentConfiguration.ReportsAndLogsRootFolderPath, sqlDbRecommendationReportFileName);
- ExportRecommendationResultsAction.ExportRecommendationResults(sqlDbReport, SqlAssessmentConfiguration.ReportsAndLogsRootFolderPath, false, sqlDbRecommendationReportFileName);
- resultSet.sqlDbReportPath = sqlDbRecommendationReportFullPath + ".html";
- }
-
- // generate SQL MI recommendations, if applicable
- if (parameters.TargetPlatforms.Contains("AzureSqlManagedInstance"))
- {
- Stopwatch sqlMiStopwatch = new Stopwatch();
- sqlMiStopwatch.Start();
-
- prefs.EligibleSkuCategories = GetEligibleSkuCategories("AzureSqlManagedInstance", parameters.IncludePreviewSkus);
- resultSet.sqlMiResults = provider.GetSkuRecommendation(prefs, req);
-
- // if no result was generated, create a result with a null SKU
- if (!resultSet.sqlMiResults.Any())
+ resultSet.sqlMiResults.Add(new SkuRecommendationResult()
{
- resultSet.sqlMiResults.Add(new SkuRecommendationResult()
- {
- SqlInstanceName = parameters.TargetSqlInstance,
- DatabaseName = null,
- TargetSku = null,
- MonthlyCost = null,
- Ranking = -1,
- PositiveJustifications = null,
- NegativeJustifications = null,
- });
- }
-
- sqlMiStopwatch.Stop();
- resultSet.sqlMiDurationInMs = sqlMiStopwatch.ElapsedMilliseconds;
-
- SkuRecommendationReport sqlMiReport = new SkuRecommendationReport(
- new Dictionary> { { req, resultSet.sqlMiResults } },
- AzureSqlTargetPlatform.AzureSqlManagedInstance.ToString());
- var sqlMiRecommendationReportFileName = String.Format("SkuRecommendationReport-AzureSqlManagedInstance-Baseline-{0}", DateTime.UtcNow.ToString("yyyyMMddHH-mmss", CultureInfo.InvariantCulture));
- var sqlMiRecommendationReportFullPath = Path.Combine(SqlAssessmentConfiguration.ReportsAndLogsRootFolderPath, sqlMiRecommendationReportFileName);
- ExportRecommendationResultsAction.ExportRecommendationResults(sqlMiReport, SqlAssessmentConfiguration.ReportsAndLogsRootFolderPath, false, sqlMiRecommendationReportFileName);
- resultSet.sqlMiReportPath = sqlMiRecommendationReportFullPath + ".html";
+ SqlInstanceName = parameters.TargetSqlInstance,
+ DatabaseName = null,
+ TargetSku = null,
+ MonthlyCost = null,
+ Ranking = -1,
+ PositiveJustifications = null,
+ NegativeJustifications = null,
+ });
}
- // generate SQL VM recommendations, if applicable
- if (parameters.TargetPlatforms.Contains("AzureSqlVirtualMachine"))
+ sqlMiStopwatch.Stop();
+ resultSet.sqlMiDurationInMs = sqlMiStopwatch.ElapsedMilliseconds;
+
+ SkuRecommendationReport sqlMiReport = new SkuRecommendationReport(
+ new Dictionary> { { req, resultSet.sqlMiResults } },
+ AzureSqlTargetPlatform.AzureSqlManagedInstance.ToString());
+ var sqlMiRecommendationReportFileName = String.Format("SkuRecommendationReport-AzureSqlManagedInstance-Baseline-{0}", DateTime.UtcNow.ToString("yyyyMMddHH-mmss", CultureInfo.InvariantCulture));
+ var sqlMiRecommendationReportFullPath = Path.Combine(SqlAssessmentConfiguration.ReportsAndLogsRootFolderPath, sqlMiRecommendationReportFileName);
+ ExportRecommendationResultsAction.ExportRecommendationResults(sqlMiReport, SqlAssessmentConfiguration.ReportsAndLogsRootFolderPath, false, sqlMiRecommendationReportFileName);
+ resultSet.sqlMiReportPath = sqlMiRecommendationReportFullPath + ".html";
+ }
+
+ // generate SQL VM recommendations, if applicable
+ if (parameters.TargetPlatforms.Contains("AzureSqlVirtualMachine"))
+ {
+ Stopwatch sqlVmStopwatch = new Stopwatch();
+ sqlVmStopwatch.Start();
+
+ prefs.EligibleSkuCategories = GetEligibleSkuCategories("AzureSqlVirtualMachine", parameters.IncludePreviewSkus);
+ resultSet.sqlVmResults = provider.GetSkuRecommendation(prefs, req);
+
+ // if no result was generated, create a result with a null SKU
+ if (!resultSet.sqlVmResults.Any())
{
- Stopwatch sqlVmStopwatch = new Stopwatch();
- sqlVmStopwatch.Start();
-
- prefs.EligibleSkuCategories = GetEligibleSkuCategories("AzureSqlVirtualMachine", parameters.IncludePreviewSkus);
- resultSet.sqlVmResults = provider.GetSkuRecommendation(prefs, req);
-
- // if no result was generated, create a result with a null SKU
- if (!resultSet.sqlVmResults.Any())
+ resultSet.sqlVmResults.Add(new SkuRecommendationResult()
{
- resultSet.sqlVmResults.Add(new SkuRecommendationResult()
- {
- SqlInstanceName = parameters.TargetSqlInstance,
- DatabaseName = null,
- TargetSku = null,
- MonthlyCost = null,
- Ranking = -1,
- PositiveJustifications = null,
- NegativeJustifications = null,
- });
- }
-
- sqlVmStopwatch.Stop();
- resultSet.sqlVmDurationInMs = sqlVmStopwatch.ElapsedMilliseconds;
-
- SkuRecommendationReport sqlVmReport = new SkuRecommendationReport(
- new Dictionary> { { req, resultSet.sqlVmResults } },
- AzureSqlTargetPlatform.AzureSqlVirtualMachine.ToString());
- var sqlVmRecommendationReportFileName = String.Format("SkuRecommendationReport-AzureSqlVirtualMachine-Baseline-{0}", DateTime.UtcNow.ToString("yyyyMMddHH-mmss", CultureInfo.InvariantCulture));
- var sqlVmRecommendationReportFullPath = Path.Combine(SqlAssessmentConfiguration.ReportsAndLogsRootFolderPath, sqlVmRecommendationReportFileName);
- ExportRecommendationResultsAction.ExportRecommendationResults(sqlVmReport, SqlAssessmentConfiguration.ReportsAndLogsRootFolderPath, false, sqlVmRecommendationReportFileName);
- resultSet.sqlVmReportPath = sqlVmRecommendationReportFullPath + ".html";
+ SqlInstanceName = parameters.TargetSqlInstance,
+ DatabaseName = null,
+ TargetSku = null,
+ MonthlyCost = null,
+ Ranking = -1,
+ PositiveJustifications = null,
+ NegativeJustifications = null,
+ });
}
- return resultSet;
+ sqlVmStopwatch.Stop();
+ resultSet.sqlVmDurationInMs = sqlVmStopwatch.ElapsedMilliseconds;
+
+ SkuRecommendationReport sqlVmReport = new SkuRecommendationReport(
+ new Dictionary> { { req, resultSet.sqlVmResults } },
+ AzureSqlTargetPlatform.AzureSqlVirtualMachine.ToString());
+ var sqlVmRecommendationReportFileName = String.Format("SkuRecommendationReport-AzureSqlVirtualMachine-Baseline-{0}", DateTime.UtcNow.ToString("yyyyMMddHH-mmss", CultureInfo.InvariantCulture));
+ var sqlVmRecommendationReportFullPath = Path.Combine(SqlAssessmentConfiguration.ReportsAndLogsRootFolderPath, sqlVmRecommendationReportFileName);
+ ExportRecommendationResultsAction.ExportRecommendationResults(sqlVmReport, SqlAssessmentConfiguration.ReportsAndLogsRootFolderPath, false, sqlVmRecommendationReportFileName);
+ resultSet.sqlVmReportPath = sqlVmRecommendationReportFullPath + ".html";
+ }
+
+ return resultSet;
}
- internal RecommendationResultSet GenerateElasticRecommendations(SqlInstanceRequirements req, GetSkuRecommendationsParams parameters) {
+ internal RecommendationResultSet GenerateElasticRecommendations(SqlInstanceRequirements req, GetSkuRecommendationsParams parameters)
+ {
RecommendationResultSet resultSet = new RecommendationResultSet();
CsvAggregatorForElasticStrategy elasticaggregator = new CsvAggregatorForElasticStrategy(
instanceId: parameters.TargetSqlInstance,
- directory: parameters.DataFolder,
- queryInterval: parameters.PerfQueryIntervalInSec,
- logger: null,
+ directory: parameters.DataFolder,
+ queryInterval: parameters.PerfQueryIntervalInSec,
+ logger: null,
dbsToInclude: new HashSet(parameters.DatabaseAllowList));
// generate SQL DB recommendations, if applicable
@@ -698,7 +705,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Migration
resultSet.sqlDbDurationInMs = sqlDbStopwatch.ElapsedMilliseconds;
SkuRecommendationReport sqlDbReport = new SkuRecommendationReport(
- new Dictionary> { { req, resultSet.sqlDbResults } },
+ new Dictionary> { { req, resultSet.sqlDbResults } },
AzureSqlTargetPlatform.AzureSqlDatabase.ToString());
var sqlDbRecommendationReportFileName = String.Format("SkuRecommendationReport-AzureSqlDatabase-Elastic-{0}", DateTime.UtcNow.ToString("yyyyMMddHH-mmss", CultureInfo.InvariantCulture));
var sqlDbRecommendationReportFullPath = Path.Combine(SqlAssessmentConfiguration.ReportsAndLogsRootFolderPath, sqlDbRecommendationReportFileName);
@@ -989,7 +996,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Migration
AzureSqlPaaSHardwareType.PremiumSeries));
if (includePreviewSkus)
- {
+ {
// Premium Memory Optimized BC/GP
eligibleSkuCategories.Add(new AzureSqlSkuPaaSCategory(
AzureSqlTargetPlatform.AzureSqlManagedInstance,
@@ -1043,6 +1050,78 @@ namespace Microsoft.SqlTools.ServiceLayer.Migration
return eligibleSkuCategories;
}
+ ///
+ /// Request handler for the certifica migration operation
+ ///
+ /// Parameters for the operation, as register during the type definition
+ /// Context provided by the framework
+ ///
+ internal async Task HandleTdeCertificateMigrationRequest(
+ CertificateMigrationParams parameters,
+ RequestContext requestContext)
+ {
+ var result = new CertificateMigrationResult();
+
+ var credentials = new StaticTokenCredential(parameters.AccessToken); //New token provided, will change to shared ADS cache later.
+
+ // Reuse the tde migration client
+ var tdeMigrationClient = new TdeMigration(
+ parameters.SourceSqlConnectionString,
+ parameters.TargetSubscriptionId,
+ parameters.TargetResourceGroupName,
+ parameters.TargetManagedInstanceName,
+ parameters.NetworkSharePath,
+ parameters.NetworkShareDomain,
+ parameters.NetworkShareUserName,
+ parameters.NetworkSharePassword,
+ credentials
+ );
+
+ foreach (var dbName in parameters.EncryptedDatabases)
+ {
+ var migrationResult = await MigrateCertificate(tdeMigrationClient, dbName);
+
+ var eventData = new CertificateMigrationProgressParams
+ {
+ Name = dbName,
+ Success = migrationResult.Success,
+ Message = migrationResult.Message
+ };
+ await requestContext.SendEvent(CertificateMigrationProgressEvent.Type, eventData);
+
+ result.MigrationStatuses.Add(migrationResult);
+ }
+
+ await requestContext.SendResult(result);
+ }
+
+ ///
+ /// Individual certificate migration operation
+ ///
+ /// Instance of the migration client
+ /// Name of the database to migrate
+ ///
+ private async Task MigrateCertificate(TdeMigration tdeMigrationClient, string dbName)
+ {
+ try
+ {
+ var result = await tdeMigrationClient.MigrateTdeCertificate(dbName, CancellationToken.None);
+
+ if (result is TdeExceptionResult tdeExceptionResult)
+ {
+ return new CertificateMigrationEntryResult { DbName = dbName, Success = result.IsSuccess, Message = tdeExceptionResult.Exception.Message };
+ }
+ else
+ {
+ return new CertificateMigrationEntryResult { DbName = dbName, Success = result.IsSuccess, Message = result.UserFriendlyMessage };
+ }
+ }
+ catch (Exception ex)
+ {
+ return new CertificateMigrationEntryResult { DbName = dbName, Success = false, Message = ex.Message };
+ }
+ }
+
///
/// Disposes the Migration Service
///
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Migration/Models/StaticTokenCredential.cs b/src/Microsoft.SqlTools.ServiceLayer/Migration/Models/StaticTokenCredential.cs
new file mode 100644
index 00000000..2723e69a
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/Migration/Models/StaticTokenCredential.cs
@@ -0,0 +1,35 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Azure.Core;
+
+namespace Microsoft.SqlTools.ServiceLayer.Migration.Models
+{
+ ///
+ /// Temp token creadentials to interact with ArmClient class.
+ /// The token passed to this class should be a newly request token, because this class doesn't renew the token.
+ /// Once MSAL is rolled out on ADS, we will implement a way to use the same ADS token cache configured by ADS.
+ ///
+ internal class StaticTokenCredential : TokenCredential
+ {
+ private readonly AccessToken _token;
+
+ ///
+ /// Build credentials using a token that will not change.
+ ///
+ /// Newly created token that should last for the duration of the whole operation.
+ public StaticTokenCredential(string accessToken) => _token = new AccessToken(
+ accessToken: accessToken,
+ expiresOn: DateTimeOffset.Now.AddHours(1)); //Default to an hour, the current duration of a newly create token.
+
+ public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken)
+ => _token;
+
+ public override ValueTask GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
+ => new ValueTask(_token);
+ }
+}