Modifying the migration extension to use its own service. (#21781)

* Adding migration service to sql migrations

* enabling auto flush log

* Adding support for env variable

* Adding TDE Migration service

* code cleanup

* updating service downloader

* Removing custom output channel

* remove unnecessary await

* Updated service version to get latest code

* Consolidate TDE into migration service

* Sync to latest main

* Update sql-migration package version

* Fix merge conflict error

* Fixing all merge conflicts

* Fixing stuff

* removing extra whitespace

* Cleaning up

---------

Co-authored-by: Akshay Mata <akma@microsoft.com>
This commit is contained in:
Aasim Khan
2023-02-12 09:59:09 -08:00
committed by GitHub
parent 12a3bf6b3b
commit 837236be0f
18 changed files with 1569 additions and 69 deletions

View File

@@ -0,0 +1,320 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { SqlOpsDataClient, SqlOpsFeature } from 'dataprotocol-client';
import {
ClientCapabilities,
RPCMessageType,
ServerCapabilities,
} from 'vscode-languageclient';
import * as UUID from 'vscode-languageclient/lib/utils/uuid';
import { Disposable } from 'vscode';
import * as contracts from './contracts';
import { migrationServiceProvider } from './provider';
export enum ApiType {
SqlMigrationProvider = 'SqlMigrationProvider',
}
export abstract class MigrationExtensionService extends SqlOpsFeature<undefined> {
abstract providerId: ApiType;
}
export class SqlMigrationService extends MigrationExtensionService implements contracts.ISqlMigrationService {
private _reportUpdate: ((dbName: string, succeeded: boolean, error: string) => void) | undefined = undefined;
override providerId = ApiType.SqlMigrationProvider;
private static readonly messagesTypes: RPCMessageType[] = [
contracts.GetSqlMigrationAssessmentItemsRequest.type,
contracts.GetSqlMigrationSkuRecommendationsRequest.type,
contracts.SqlMigrationStartPerfDataCollectionRequest.type,
contracts.SqlMigrationRefreshPerfDataCollectionRequest.type,
contracts.SqlMigrationStopPerfDataCollectionRequest.type,
contracts.StartLoginMigrationRequest.type,
contracts.ValidateLoginMigrationRequest.type,
contracts.MigrateLoginsRequest.type,
contracts.EstablishUserMappingRequest.type,
contracts.MigrateServerRolesAndSetPermissionsRequest.type,
contracts.TdeMigrateRequest.type
];
constructor(client: SqlOpsDataClient) {
super(client, SqlMigrationService.messagesTypes);
}
public initialize(capabilities: ServerCapabilities): void {
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: undefined
});
this._client.onNotification(contracts.TdeMigrateProgressEvent.type, e => {
if (this._reportUpdate === undefined) {
return;
}
this._reportUpdate(e.name, e.success, e.message);
});
}
protected registerProvider(options: undefined): Disposable {
migrationServiceProvider.addService(this);
return this;
}
public fillClientCapabilities(capabilities: ClientCapabilities): void {
// this isn't explicitly necessary
}
async getAssessments(connectionString: string, databases: string[], xEventsFilesFolderPath: string): Promise<contracts.AssessmentResult | undefined> {
let params: contracts.SqlMigrationAssessmentParams = { connectionString: connectionString, databases: databases, xEventsFilesFolderPath: xEventsFilesFolderPath };
try {
return this._client.sendRequest(contracts.GetSqlMigrationAssessmentItemsRequest.type, params);
}
catch (e) {
this._client.logFailedRequest(contracts.GetSqlMigrationAssessmentItemsRequest.type, e);
}
return undefined;
}
async getSkuRecommendations(
dataFolder: string,
perfQueryIntervalInSec: number,
targetPlatforms: string[],
targetSqlInstance: string,
targetPercentile: number,
scalingFactor: number,
startTime: string,
endTime: string,
includePreviewSkus: boolean,
databaseAllowList: string[]): Promise<contracts.SkuRecommendationResult | undefined> {
let params: contracts.SqlMigrationSkuRecommendationsParams = {
dataFolder,
perfQueryIntervalInSec,
targetPlatforms,
targetSqlInstance,
targetPercentile,
scalingFactor,
startTime,
endTime,
includePreviewSkus,
databaseAllowList
};
try {
return this._client.sendRequest(contracts.GetSqlMigrationSkuRecommendationsRequest.type, params);
}
catch (e) {
this._client.logFailedRequest(contracts.GetSqlMigrationSkuRecommendationsRequest.type, e);
}
return undefined;
}
async startPerfDataCollection(
connectionString: string,
dataFolder: string,
perfQueryIntervalInSec: number,
staticQueryIntervalInSec: number,
numberOfIterations: number): Promise<contracts.StartPerfDataCollectionResult | undefined> {
let params: contracts.SqlMigrationStartPerfDataCollectionParams = {
connectionString: connectionString,
dataFolder,
perfQueryIntervalInSec,
staticQueryIntervalInSec,
numberOfIterations
};
try {
return this._client.sendRequest(contracts.SqlMigrationStartPerfDataCollectionRequest.type, params);
}
catch (e) {
this._client.logFailedRequest(contracts.SqlMigrationStartPerfDataCollectionRequest.type, e);
}
return undefined;
}
async stopPerfDataCollection(): Promise<contracts.StopPerfDataCollectionResult | undefined> {
let params: contracts.SqlMigrationStopPerfDataCollectionParams = {};
try {
return this._client.sendRequest(contracts.SqlMigrationStopPerfDataCollectionRequest.type, params);
}
catch (e) {
this._client.logFailedRequest(contracts.SqlMigrationStopPerfDataCollectionRequest.type, e);
}
return undefined;
}
async refreshPerfDataCollection(lastRefreshedTime: Date): Promise<contracts.RefreshPerfDataCollectionResult | undefined> {
let params: contracts.SqlMigrationStopPerfDataCollectionParams = {
lastRefreshedTime
};
try {
return this._client.sendRequest(contracts.SqlMigrationRefreshPerfDataCollectionRequest.type, params);
}
catch (e) {
this._client.logFailedRequest(contracts.SqlMigrationRefreshPerfDataCollectionRequest.type, e);
}
return undefined;
}
async startLoginMigration(
sourceConnectionString: string,
targetConnectionString: string,
loginList: string[],
aadDomainName: string): Promise<contracts.StartLoginMigrationResult | undefined> {
let params: contracts.StartLoginMigrationsParams = {
sourceConnectionString,
targetConnectionString,
loginList,
aadDomainName
};
try {
return this._client.sendRequest(contracts.StartLoginMigrationRequest.type, params);
}
catch (e) {
this._client.logFailedRequest(contracts.StartLoginMigrationRequest.type, e);
}
return undefined;
}
async validateLoginMigration(
sourceConnectionString: string,
targetConnectionString: string,
loginList: string[],
aadDomainName: string): Promise<contracts.StartLoginMigrationResult | undefined> {
let params: contracts.StartLoginMigrationsParams = {
sourceConnectionString,
targetConnectionString,
loginList,
aadDomainName
};
try {
return this._client.sendRequest(contracts.ValidateLoginMigrationRequest.type, params);
}
catch (e) {
this._client.logFailedRequest(contracts.ValidateLoginMigrationRequest.type, e);
}
return undefined;
}
async migrateLogins(
sourceConnectionString: string,
targetConnectionString: string,
loginList: string[],
aadDomainName: string): Promise<contracts.StartLoginMigrationResult | undefined> {
let params: contracts.StartLoginMigrationsParams = {
sourceConnectionString,
targetConnectionString,
loginList,
aadDomainName
};
try {
return this._client.sendRequest(contracts.MigrateLoginsRequest.type, params);
}
catch (e) {
this._client.logFailedRequest(contracts.MigrateLoginsRequest.type, e);
}
return undefined;
}
async establishUserMapping(
sourceConnectionString: string,
targetConnectionString: string,
loginList: string[],
aadDomainName: string): Promise<contracts.StartLoginMigrationResult | undefined> {
let params: contracts.StartLoginMigrationsParams = {
sourceConnectionString,
targetConnectionString,
loginList,
aadDomainName
};
try {
return this._client.sendRequest(contracts.EstablishUserMappingRequest.type, params);
}
catch (e) {
this._client.logFailedRequest(contracts.EstablishUserMappingRequest.type, e);
}
return undefined;
}
async migrateServerRolesAndSetPermissions(
sourceConnectionString: string,
targetConnectionString: string,
loginList: string[],
aadDomainName: string): Promise<contracts.StartLoginMigrationResult | undefined> {
let params: contracts.StartLoginMigrationsParams = {
sourceConnectionString,
targetConnectionString,
loginList,
aadDomainName
};
try {
return this._client.sendRequest(contracts.MigrateServerRolesAndSetPermissionsRequest.type, params);
}
catch (e) {
this._client.logFailedRequest(contracts.MigrateServerRolesAndSetPermissionsRequest.type, e);
}
return undefined;
}
async migrateCertificate(
tdeEnabledDatabases: string[],
sourceSqlConnectionString: string,
targetSubscriptionId: string,
targetResourceGroupName: string,
targetManagedInstanceName: string,
networkSharePath: string,
accessToken: string,
reportUpdate: (dbName: string, succeeded: boolean, message: string) => void): Promise<contracts.TdeMigrationResult | undefined> {
this._reportUpdate = reportUpdate;
let params: contracts.TdeMigrationParams = {
encryptedDatabases: tdeEnabledDatabases,
sourceSqlConnectionString: sourceSqlConnectionString,
targetSubscriptionId: targetSubscriptionId,
targetResourceGroupName: targetResourceGroupName,
targetManagedInstanceName: targetManagedInstanceName,
networkSharePath: networkSharePath,
networkShareDomain: 'a', // Will remove this on the next STS version
networkShareUserName: 'b',
networkSharePassword: 'c',
accessToken: accessToken
};
try {
// This call needs to be awaited so, the updates are sent during the execution of the task.
// If the task is not await, the finally block will execute and no update will be sent.
const result = await this._client.sendRequest(contracts.TdeMigrateRequest.type, params);
return result;
}
catch (e) {
this._client.logFailedRequest(contracts.TdeMigrateRequest.type, e);
}
return undefined;
}
}