Smartura/sql migrate tde improvements (#23631)

* Automatically migrate certs on last page of wizard

* Updated TDE configuration dialog wording

* Added ConfigDialogSetting to track user selection

* Added numberOfDbsWithTde telemetry prop

* Migrate certs button moved back to target page

* Enable next button on cert migration success

* Reset TDE migration result if target changes

* Addressed PR feedback

* Added TDE navigation validator

* Fixed typo
This commit is contained in:
Steven Marturano
2023-07-12 15:32:28 -04:00
committed by GitHub
parent 8d1a7265ee
commit b595115c8a
8 changed files with 210 additions and 124 deletions

View File

@@ -23,6 +23,7 @@ import { logError, TelemetryViews, TelemetryAction, sendSqlMigrationActionEvent,
import { TdeConfigurationDialog } from '../dialog/tdeConfiguration/tdeConfigurationDialog';
import { TdeMigrationModel } from '../models/tdeModels';
import { getSourceConnectionProfile } from '../api/sqlUtils';
import { ConfigDialogSetting } from '../models/tdeModels'
export interface Product {
type: MigrationTargetType;
@@ -382,7 +383,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
'margin': '0',
}
}).component();
this._tdeConfigurationDialog = new TdeConfigurationDialog(this, this.wizard, this.migrationStateModel, () => this._onTdeConfigClosed());
this._tdeConfigurationDialog = new TdeConfigurationDialog(this.migrationStateModel, () => this._onTdeConfigClosed());
this._disposables.push(this._tdeEditButton.onDidClick(
async (e) => await this._tdeConfigurationDialog.openDialog()));
@@ -845,16 +846,32 @@ export class SKURecommendationPage extends MigrationWizardPage {
}
private _onTdeConfigClosed(): Thenable<void> {
const tdeMsg = (this.migrationStateModel.tdeMigrationConfig.isTdeMigrationMethodAdsConfirmed()) ? constants.TDE_WIZARD_MSG_TDE : constants.TDE_WIZARD_MSG_MANUAL;
const tdeMsg = (this.migrationStateModel.tdeMigrationConfig.getAppliedConfigDialogSetting() === ConfigDialogSetting.ExportCertificates) ? constants.TDE_WIZARD_MSG_TDE : constants.TDE_WIZARD_MSG_MANUAL;
this._tdedatabaseSelectedHelperText.value = constants.TDE_MSG_DATABASES_SELECTED(this.migrationStateModel.tdeMigrationConfig.getTdeEnabledDatabasesCount(), tdeMsg);
const tdeTelemetryAction = (this.migrationStateModel.tdeMigrationConfig.isTdeMigrationMethodAdsConfirmed()) ? TelemetryAction.TdeConfigurationUseADS : TelemetryAction.TdeConfigurationIgnoreADS;
let tdeTelemetryAction: TelemetryAction;
switch (this.migrationStateModel.tdeMigrationConfig.getAppliedConfigDialogSetting()) {
case ConfigDialogSetting.ExportCertificates:
tdeTelemetryAction = TelemetryAction.TdeConfigurationUseADS;
break;
case ConfigDialogSetting.DoNotExport:
tdeTelemetryAction = TelemetryAction.TdeConfigurationAlreadyMigrated;
break;
case ConfigDialogSetting.NoSelection:
tdeTelemetryAction = TelemetryAction.TdeConfigurationCancelled;
break;
default:
tdeTelemetryAction = TelemetryAction.TdeConfigurationCancelled;
break;
}
sendSqlMigrationActionEvent(
TelemetryViews.TdeConfigurationDialog,
tdeTelemetryAction,
{
...getTelemetryProps(this.migrationStateModel)
...getTelemetryProps(this.migrationStateModel),
'numberOfDbsWithTde': this.migrationStateModel.tdeMigrationConfig.getTdeEnabledDatabasesCount().toString()
},
{}
);

View File

@@ -17,8 +17,9 @@ import { azureResource } from 'azurecore';
import { AzureSqlDatabaseServer, getVMInstanceView, SqlVMServer } from '../api/azure';
import { collectTargetDatabaseInfo, TargetDatabaseInfo } from '../api/sqlUtils';
import { MigrationLocalStorage, MigrationServiceContext } from '../models/migrationLocalStorage';
import { TdeMigrationDialog } from '../dialog/tdeConfiguration/tdeMigrationDialog';
import { ValidationErrorCodes } from '../constants/helper';
import { TdeMigrationDialog } from '../dialog/tdeConfiguration/tdeMigrationDialog';
import { TdeMigrationResult, TdeMigrationState } from '../models/tdeModels';
const TDE_MIGRATION_BUTTON_INDEX = 1;
@@ -45,6 +46,7 @@ export class TargetSelectionPage extends MigrationWizardPage {
private _connectionResultsInfoBox!: azdata.InfoBoxComponent;
private _migrationTargetPlatform!: utils.MigrationTargetType;
private _serviceContext!: MigrationServiceContext;
private _certMigrationEventEmitter: vscode.EventEmitter<TdeMigrationResult>;
constructor(
wizard: azdata.window.Wizard,
@@ -53,6 +55,10 @@ export class TargetSelectionPage extends MigrationWizardPage {
wizard,
azdata.window.createWizardPage(constants.AZURE_SQL_TARGET_PAGE_TITLE),
migrationStateModel);
this._certMigrationEventEmitter = new vscode.EventEmitter();
this._certMigrationEventEmitter.event(() => this._updateNextButton());
}
protected async registerContent(view: azdata.ModelView): Promise<void> {
@@ -82,25 +88,20 @@ export class TargetSelectionPage extends MigrationWizardPage {
d => { try { d.dispose(); } catch { } });
}));
if (this.migrationStateModel.resumeAssessment) {
await this.populateAzureAccountsDropdown();
}
this._disposables.push(
this.wizard.customButtons[TDE_MIGRATION_BUTTON_INDEX].onClick(
async e => await this._startTdeMigration()));
if (this.migrationStateModel.resumeAssessment) {
await this.populateAzureAccountsDropdown();
}
await this._view.initializeModel(form);
}
private async _startTdeMigration(): Promise<void> {
const dialog = new TdeMigrationDialog(this.migrationStateModel);
await dialog.openDialog();
}
public async onPageEnter(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
this.wizard.customButtons[TDE_MIGRATION_BUTTON_INDEX].hidden = !this.migrationStateModel.tdeMigrationConfig.shouldAdsMigrateCertificates();
this._updateNextButton();
this._updateTdeMigrationButtonStatus();
if (pageChangeInfo.newPage < pageChangeInfo.lastPage) {
@@ -163,6 +164,10 @@ export class TargetSelectionPage extends MigrationWizardPage {
if (targetMi && targetMi.properties?.state.toLowerCase() !== 'Ready'.toLowerCase()) {
errors.push(constants.MI_NOT_READY_ERROR(targetMi.name, targetMi.properties?.state));
}
if (this.migrationStateModel.tdeMigrationConfig.shouldAdsMigrateCertificates() &&
this.migrationStateModel.tdeMigrationConfig.lastTdeMigrationResult().state !== TdeMigrationState.Succeeded) {
errors.push(constants.TDE_MIGRATE_REQUIRED);
}
break;
case MigrationTargetType.SQLVM:
const targetVm = this.migrationStateModel._targetServerInstance as SqlVMServer;
@@ -281,7 +286,6 @@ export class TargetSelectionPage extends MigrationWizardPage {
public async onPageLeave(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
this.wizard.registerNavigationValidator(pageChangeInfo => true);
this.wizard.message = { text: '' };
this.wizard.customButtons[TDE_MIGRATION_BUTTON_INDEX].hidden = true;
}
@@ -759,7 +763,6 @@ export class TargetSelectionPage extends MigrationWizardPage {
}
this.migrationStateModel.tdeMigrationConfig.resetTdeMigrationResult();
break;
case MigrationTargetType.SQLDB:
const sqlDatabaseServer = this.migrationStateModel._targetSqlDatabaseServers?.find(
@@ -792,6 +795,8 @@ export class TargetSelectionPage extends MigrationWizardPage {
}
}
this._resetTdeMigrationResult();
this.migrationStateModel._sqlMigrationServices = undefined!;
if (isSqlDbTarget) {
await this._resetTargetMapping();
@@ -1046,7 +1051,6 @@ export class TargetSelectionPage extends MigrationWizardPage {
this.migrationStateModel._targetManagedInstances,
this.migrationStateModel._location,
this.migrationStateModel._resourceGroup);
this._updateTdeMigrationButtonStatus();
break;
case MigrationTargetType.SQLVM:
@@ -1075,12 +1079,6 @@ export class TargetSelectionPage extends MigrationWizardPage {
}
}
private _updateTdeMigrationButtonStatus() {
this.wizard.customButtons[TDE_MIGRATION_BUTTON_INDEX].enabled =
this.migrationStateModel.tdeMigrationConfig.shouldAdsMigrateCertificates() &&
this.migrationStateModel._targetManagedInstances.length > 0;
}
private async _populateResourceMappingTable(targetDatabases: TargetDatabaseInfo[]): Promise<void> {
// populate target database list
const databaseValues = this._getTargetDatabaseDropdownValues(
@@ -1218,4 +1216,32 @@ export class TargetSelectionPage extends MigrationWizardPage {
targetDatabaseCollation.length > 0 &&
sourceDatabaseCollation.toLocaleLowerCase() === targetDatabaseCollation.toLocaleLowerCase();
}
private _updateNextButton() {
if (this.migrationStateModel.tdeMigrationConfig.shouldAdsMigrateCertificates() &&
this.migrationStateModel.tdeMigrationConfig.lastTdeMigrationResult().state !== TdeMigrationState.Succeeded) {
this.wizard.pages[this.wizard.currentPage + 1].enabled = false;
this.wizard.nextButton.enabled = false;
} else {
this.wizard.pages[this.wizard.currentPage + 1].enabled = true;
this.wizard.nextButton.enabled = true;
}
}
private _updateTdeMigrationButtonStatus() {
this.wizard.customButtons[TDE_MIGRATION_BUTTON_INDEX].enabled =
this.migrationStateModel.tdeMigrationConfig.shouldAdsMigrateCertificates() &&
this.migrationStateModel._targetManagedInstances.length > 0;
}
private _resetTdeMigrationResult() {
this.migrationStateModel.tdeMigrationConfig.resetTdeMigrationResult();
this._updateNextButton();
}
private async _startTdeMigration(): Promise<void> {
this._resetTdeMigrationResult();
const dialog = new TdeMigrationDialog(this.migrationStateModel, this._certMigrationEventEmitter);
await dialog.openDialog();
}
}