mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-18 17:22:45 -05:00
[SQL Migration] SKU recommendation improvements + SQL DB integration bug fixes (#20174)
* WIP - show error message for failed SKU recommendation * WIP - run query to get correct instance name * WIP - integrate elastic model recommendation * Remove private endpoint restriction text * Add feature switch for elastic recommendation * Clean up * Clean up * Misc UI fixes * Update package.json with updated azdata dependency * Remove unused lines * Fix broken next button * Vbump extension to 1.0.6 * Update SQL DB card to show number of recommendations for correct model
This commit is contained in:
@@ -413,14 +413,6 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
||||
CSSStyles: { ...styles.SECTION_HEADER_CSS }
|
||||
}).component();
|
||||
|
||||
const azureStoragePrivateEndpointInfoBox = this._view.modelBuilder.infoBox()
|
||||
.withProps({
|
||||
text: constants.DATABASE_BACKUP_PRIVATE_ENDPOINT_INFO_TEXT,
|
||||
style: 'information',
|
||||
width: WIZARD_INPUT_COMPONENT_WIDTH,
|
||||
CSSStyles: { ...styles.BODY_CSS }
|
||||
}).component();
|
||||
|
||||
this._networkShareTargetDatabaseNamesTable = this._view.modelBuilder.declarativeTable()
|
||||
.withProps({
|
||||
columns: [
|
||||
@@ -523,7 +515,6 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
||||
.withItems([
|
||||
blobTableText,
|
||||
allFieldsRequiredLabel,
|
||||
azureStoragePrivateEndpointInfoBox,
|
||||
this._blobContainerTargetDatabaseNamesTable])
|
||||
.withProps({ CSSStyles: { 'display': 'none', } })
|
||||
.component();
|
||||
@@ -553,14 +544,6 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
||||
CSSStyles: { ...styles.BODY_CSS, 'margin-bottom': '12px' }
|
||||
}).component();
|
||||
|
||||
const azureStoragePrivateEndpointInfoBox = this._view.modelBuilder.infoBox()
|
||||
.withProps({
|
||||
text: constants.DATABASE_BACKUP_PRIVATE_ENDPOINT_INFO_TEXT,
|
||||
style: 'information',
|
||||
width: WIZARD_INPUT_COMPONENT_WIDTH,
|
||||
CSSStyles: { ...styles.BODY_CSS }
|
||||
}).component();
|
||||
|
||||
const subscriptionLabel = this._view.modelBuilder.text()
|
||||
.withProps({
|
||||
value: constants.SUBSCRIPTION,
|
||||
@@ -673,7 +656,6 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
||||
.withItems([
|
||||
azureAccountHeader,
|
||||
azureAccountHelpText,
|
||||
azureStoragePrivateEndpointInfoBox,
|
||||
subscriptionLabel,
|
||||
this._networkShareContainerSubscription,
|
||||
locationLabel,
|
||||
|
||||
@@ -68,10 +68,12 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
private _skuScaleFactorText!: azdata.TextComponent;
|
||||
private _skuTargetPercentileText!: azdata.TextComponent;
|
||||
private _skuEnablePreviewSkuText!: azdata.TextComponent;
|
||||
private _skuEnableElasticRecommendationsText!: azdata.TextComponent;
|
||||
|
||||
private assessmentGroupContainer!: azdata.FlexContainer;
|
||||
private _disposables: vscode.Disposable[] = [];
|
||||
|
||||
private _serverName: string = '';
|
||||
private _supportedProducts: Product[] = [
|
||||
{
|
||||
type: MigrationTargetType.SQLMI,
|
||||
@@ -357,11 +359,11 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
CSSStyles: { 'margin': '12px 0' }
|
||||
}).component();
|
||||
|
||||
const serverName = this.migrationStateModel.serverName || (await this.migrationStateModel.getSourceConnectionProfile()).serverName;
|
||||
this._serverName = this.migrationStateModel.serverName || (await this.migrationStateModel.getSourceConnectionProfile()).serverName;
|
||||
|
||||
const miDialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, constants.ASSESSMENT_TILE(serverName), this, MigrationTargetType.SQLMI);
|
||||
const vmDialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, constants.ASSESSMENT_TILE(serverName), this, MigrationTargetType.SQLVM);
|
||||
const dbDialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, constants.ASSESSMENT_TILE(serverName), this, MigrationTargetType.SQLDB);
|
||||
const miDialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, constants.ASSESSMENT_TILE(this._serverName), this, MigrationTargetType.SQLMI);
|
||||
const vmDialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, constants.ASSESSMENT_TILE(this._serverName), this, MigrationTargetType.SQLVM);
|
||||
const dbDialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, constants.ASSESSMENT_TILE(this._serverName), this, MigrationTargetType.SQLDB);
|
||||
|
||||
this._disposables.push(button.onDidClick(async (e) => {
|
||||
switch (this._rbg.selectedCardId) {
|
||||
@@ -437,8 +439,6 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
|
||||
const serverName = (await this.migrationStateModel.getSourceConnectionProfile()).serverName;
|
||||
|
||||
if (this.migrationStateModel._runAssessments) {
|
||||
const errors: string[] = [];
|
||||
await this._setAssessmentState(true, false);
|
||||
@@ -453,22 +453,22 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
e => `message: ${e.message}${EOL}errorSummary: ${e.errorSummary}${EOL}possibleCauses: ${e.possibleCauses}${EOL}guidance: ${e.guidance}${EOL}errorId: ${e.errorId}`)!);
|
||||
}
|
||||
} catch (e) {
|
||||
errors.push(constants.SKU_RECOMMENDATION_ASSESSMENT_UNEXPECTED_ERROR(serverName, e));
|
||||
errors.push(constants.SKU_RECOMMENDATION_ASSESSMENT_UNEXPECTED_ERROR(this._serverName, e));
|
||||
logError(TelemetryViews.MigrationWizardSkuRecommendationPage, 'SkuRecommendationUnexpectedError', e);
|
||||
} finally {
|
||||
this.migrationStateModel._runAssessments = errors.length > 0;
|
||||
if (errors.length > 0) {
|
||||
this.wizard.message = {
|
||||
text: constants.SKU_RECOMMENDATION_ASSESSMENT_ERROR(serverName),
|
||||
text: constants.SKU_RECOMMENDATION_ASSESSMENT_ERROR(this._serverName),
|
||||
description: errors.join(EOL),
|
||||
level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
this._assessmentStatusIcon.iconPath = IconPathHelper.error;
|
||||
this._igComponent.value = constants.ASSESSMENT_FAILED(serverName);
|
||||
this._detailsComponent.value = constants.SKU_RECOMMENDATION_ASSESSMENT_ERROR(serverName);
|
||||
this._igComponent.value = constants.ASSESSMENT_FAILED(this._serverName);
|
||||
this._detailsComponent.value = constants.SKU_RECOMMENDATION_ASSESSMENT_ERROR(this._serverName);
|
||||
} else {
|
||||
this._assessmentStatusIcon.iconPath = IconPathHelper.completedMigration;
|
||||
this._igComponent.value = constants.ASSESSMENT_COMPLETED(serverName);
|
||||
this._igComponent.value = constants.ASSESSMENT_COMPLETED(this._serverName);
|
||||
this._detailsComponent.value = constants.SKU_RECOMMENDATION_ALL_SUCCESSFUL(
|
||||
this.migrationStateModel._assessmentResults?.databaseAssessments?.length);
|
||||
}
|
||||
@@ -476,7 +476,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
} else {
|
||||
// use prior assessment results
|
||||
this._assessmentStatusIcon.iconPath = IconPathHelper.completedMigration;
|
||||
this._igComponent.value = constants.ASSESSMENT_COMPLETED(serverName);
|
||||
this._igComponent.value = constants.ASSESSMENT_COMPLETED(this._serverName);
|
||||
this._detailsComponent.value = constants.SKU_RECOMMENDATION_ALL_SUCCESSFUL(
|
||||
this.migrationStateModel._assessmentResults?.databaseAssessments?.length);
|
||||
}
|
||||
@@ -529,20 +529,30 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
}
|
||||
|
||||
private async _setAssessmentState(assessing: boolean, failedAssessment: boolean): Promise<void> {
|
||||
await utils.updateControlDisplay(this._assessmentComponent, assessing);
|
||||
await utils.updateControlDisplay(this._skipAssessmentCheckbox, !assessing && failedAssessment);
|
||||
await utils.updateControlDisplay(
|
||||
this._assessmentComponent,
|
||||
assessing,
|
||||
'block');
|
||||
await utils.updateControlDisplay(
|
||||
this._skipAssessmentCheckbox,
|
||||
!assessing && failedAssessment,
|
||||
'block');
|
||||
await utils.updateControlDisplay(
|
||||
this._skipAssessmentSubText,
|
||||
!assessing && failedAssessment,
|
||||
'block');
|
||||
await utils.updateControlDisplay(this._formContainer.component(), !assessing);
|
||||
await utils.updateControlDisplay(
|
||||
this._formContainer.component(),
|
||||
!assessing,
|
||||
'block');
|
||||
await utils.updateControlDisplay(
|
||||
this._chooseTargetComponent,
|
||||
!failedAssessment || this._skipAssessmentCheckbox.checked === true);
|
||||
|
||||
!failedAssessment || this._skipAssessmentCheckbox.checked === true,
|
||||
'block');
|
||||
await utils.updateControlDisplay(
|
||||
this.assessmentGroupContainer,
|
||||
this._rbg.selectedCardId !== undefined && (!failedAssessment || this._skipAssessmentCheckbox.checked === true));
|
||||
this._rbg.selectedCardId !== undefined && (!failedAssessment || this._skipAssessmentCheckbox.checked === true),
|
||||
'inline');
|
||||
|
||||
this._assessmentLoader.loading = assessing;
|
||||
}
|
||||
@@ -611,8 +621,6 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
if (!this.migrationStateModel._assessmentResults) {
|
||||
this._rbg.cards[index].descriptions[CardDescriptionIndex.ASSESSMENT_STATUS].textValue = '';
|
||||
} else {
|
||||
// TO-DO: add the assessed db counts
|
||||
// this._rbg.cards[index].descriptions[5].textValue = constants.ASSESSED_DBS(dbCount);
|
||||
if (this.hasRecommendations()) {
|
||||
this._rbg.cards[index].descriptions[CardDescriptionIndex.VIEW_SKU_DETAILS].linkDisplayValue = constants.VIEW_DETAILS;
|
||||
this._rbg.cards[index].descriptions[CardDescriptionIndex.SKU_RECOMMENDATION].textStyles = {
|
||||
@@ -641,7 +649,11 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
constants.CAN_BE_MIGRATED(dbWithoutIssuesCount, dbCount);
|
||||
|
||||
if (this.hasRecommendations()) {
|
||||
recommendation = this.migrationStateModel._skuRecommendationResults.recommendations.sqlMiRecommendationResults[0];
|
||||
if (this.migrationStateModel._skuEnableElastic) {
|
||||
recommendation = this.migrationStateModel._skuRecommendationResults.recommendations?.elasticSqlMiRecommendationResults[0];
|
||||
} else {
|
||||
recommendation = this.migrationStateModel._skuRecommendationResults.recommendations?.sqlMiRecommendationResults[0];
|
||||
}
|
||||
|
||||
// result returned but no SKU recommended
|
||||
if (!recommendation?.targetSku) {
|
||||
@@ -672,7 +684,8 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
constants.CAN_BE_MIGRATED(dbCount, dbCount);
|
||||
|
||||
if (this.hasRecommendations()) {
|
||||
recommendation = this.migrationStateModel._skuRecommendationResults.recommendations.sqlVmRecommendationResults[0];
|
||||
// elastic model currently doesn't support SQL VM, so show the baseline model results regardless of user preference
|
||||
recommendation = this.migrationStateModel._skuRecommendationResults.recommendations?.sqlVmRecommendationResults[0];
|
||||
|
||||
// result returned but no SKU recommended
|
||||
if (!recommendation?.targetSku) {
|
||||
@@ -708,9 +721,10 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
constants.CAN_BE_MIGRATED(dbWithoutIssuesCount, dbCount);
|
||||
|
||||
if (this.hasRecommendations()) {
|
||||
const successfulRecommendationsCount =
|
||||
this.migrationStateModel._skuRecommendationResults.recommendations.sqlDbRecommendationResults
|
||||
.filter(r => r.targetSku !== null).length;
|
||||
const recommendations = this.migrationStateModel._skuEnableElastic
|
||||
? this.migrationStateModel._skuRecommendationResults.recommendations!.elasticSqlDbRecommendationResults
|
||||
: this.migrationStateModel._skuRecommendationResults.recommendations!.sqlDbRecommendationResults;
|
||||
const successfulRecommendationsCount = recommendations.filter(r => r.targetSku !== null).length;
|
||||
this._rbg.cards[index].descriptions[CardDescriptionIndex.SKU_RECOMMENDATION].textValue =
|
||||
constants.RECOMMENDATIONS_AVAILABLE(successfulRecommendationsCount);
|
||||
}
|
||||
@@ -768,7 +782,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
private async createAssessmentInfo(): Promise<azdata.TextComponent> {
|
||||
this._assessmentInfo = this._view.modelBuilder.text()
|
||||
.withProps({
|
||||
value: constants.ASSESSMENT_IN_PROGRESS_CONTENT((await this.migrationStateModel.getSourceConnectionProfile()).serverName),
|
||||
value: constants.ASSESSMENT_IN_PROGRESS_CONTENT(this._serverName),
|
||||
CSSStyles: {
|
||||
...styles.BODY_CSS,
|
||||
'width': '660px'
|
||||
@@ -1070,6 +1084,9 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
this.migrationStateModel._skuEnablePreview ? constants.YES : constants.NO);
|
||||
this._skuEnablePreviewSkuText = skuEnablePreviewParameterGroup.text;
|
||||
|
||||
const skuEnableElasticRecommendationsParameterGroup = createParameterGroup(constants.ELASTIC_RECOMMENDATION_LABEL, this.migrationStateModel._skuEnableElastic ? constants.YES : constants.NO);
|
||||
this._skuEnableElasticRecommendationsText = skuEnableElasticRecommendationsParameterGroup.text;
|
||||
|
||||
const parametersContainer = _view.modelBuilder.flexContainer()
|
||||
.withProps({
|
||||
CSSStyles: {
|
||||
@@ -1082,6 +1099,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
scaleFactorParameterGroup.flexContainer,
|
||||
skuTargetPercentileParameterGroup.flexContainer,
|
||||
skuEnablePreviewParameterGroup.flexContainer,
|
||||
skuEnableElasticRecommendationsParameterGroup.flexContainer
|
||||
]);
|
||||
|
||||
container.addItems([
|
||||
@@ -1096,6 +1114,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
this._skuScaleFactorText.value = this.migrationStateModel._skuScalingFactor.toString();
|
||||
this._skuTargetPercentileText.value = constants.PERCENTAGE(this.migrationStateModel._skuTargetPercentile);
|
||||
this._skuEnablePreviewSkuText.value = this.migrationStateModel._skuEnablePreview ? constants.YES : constants.NO;
|
||||
this._skuEnableElasticRecommendationsText.value = this.migrationStateModel._skuEnableElastic ? constants.YES : constants.NO;
|
||||
await this.refreshAzureRecommendation();
|
||||
}
|
||||
|
||||
@@ -1103,6 +1122,16 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
||||
await this.startCardLoading();
|
||||
this._skuLastRefreshTimeText.value = constants.LAST_REFRESHED_TIME();
|
||||
await this.migrationStateModel.getSkuRecommendations();
|
||||
|
||||
const skuRecommendationError = this.migrationStateModel._skuRecommendationResults?.recommendationError;
|
||||
if (skuRecommendationError) {
|
||||
this.wizard.message = {
|
||||
text: constants.SKU_RECOMMENDATION_ERROR(this._serverName),
|
||||
description: skuRecommendationError.message,
|
||||
level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
}
|
||||
|
||||
await this.refreshSkuRecommendationComponents();
|
||||
this._skuLastRefreshTimeText.value = constants.LAST_REFRESHED_TIME(new Date().toLocaleString());
|
||||
}
|
||||
|
||||
@@ -109,7 +109,6 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
||||
// and came back, forcibly reload the location/resource group/resource values since they will now be different
|
||||
this._migrationTargetPlatform = this.migrationStateModel._targetType;
|
||||
|
||||
await this._azureResourceTable.setDataValues([]);
|
||||
this._targetPasswordInputBox.value = '';
|
||||
this.migrationStateModel._sqlMigrationServices = undefined!;
|
||||
this.migrationStateModel._targetServerInstance = undefined!;
|
||||
@@ -119,7 +118,6 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
||||
}
|
||||
|
||||
if (this.migrationStateModel._didUpdateDatabasesForMigration) {
|
||||
await this._azureResourceTable.setDataValues([]);
|
||||
this._initializeSourceTargetDatabaseMap();
|
||||
this._updateConnectionButtonState();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user