mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
[Sql Migration] Stabilize save and close logic and fix related ux bugs (#18579)
* add loadSavedInfo function in stateMachine; only open wizard if didLoadSavedInfo * * add loadSavedInfo function in stateMachine; only open wizard if didLoadSavedInfo * replaced savedInfo.miggrationServiceId string with sqlMigrationServer object * selectDatbasesFromList helper function to check previously selected dbs in dbSelectorPage and sqlDatabaseTree * * remove savedInfo references from targetSelectionPage, migrationModePage * add selectDefaultDropdownValue helper to stateMachine to handle unify savedInfo selection logic * add updateDropdownLoadingStatus to targetSelectionPage * check if values exist before making api calls in statemachine * removed savedInfo references from databaseBackupPage, integrationRuntimePage * databaseBackupPage - targetDatabaseNames, networkShares, blobs need to rely on savedInfo as user may update the list of migrationdbs during the retry/saveAndClose * re-add serverAssessments to savedInfo; only getAssessments if it does not exist or needs to be updated; fix networkShare type savedInfo * rename _assessmentDbs to _databasesForAssessment; _migrationDbs to _databasesForMigration * load blobs/networkshares savedinfo; move selectDefaultDropdownValue to utils * fix selectDefaultDropdownValue; refreshDatabaseBackupPage when user changes target subscription or location
This commit is contained in:
@@ -146,6 +146,15 @@ export function convertIsoTimeToLocalTime(isoTime: string): Date {
|
|||||||
|
|
||||||
export type SupportedAutoRefreshIntervals = -1 | 15000 | 30000 | 60000 | 180000 | 300000;
|
export type SupportedAutoRefreshIntervals = -1 | 15000 | 30000 | 60000 | 180000 | 300000;
|
||||||
|
|
||||||
|
export function selectDefaultDropdownValue(dropDown: DropDownComponent, value?: string, useDisplayName: boolean = true): void {
|
||||||
|
const selectedIndex = value ? findDropDownItemIndex(dropDown, value, useDisplayName) : -1;
|
||||||
|
if (selectedIndex > -1) {
|
||||||
|
selectDropDownIndex(dropDown, selectedIndex);
|
||||||
|
} else {
|
||||||
|
selectDropDownIndex(dropDown, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function selectDropDownIndex(dropDown: DropDownComponent, index: number): void {
|
export function selectDropDownIndex(dropDown: DropDownComponent, index: number): void {
|
||||||
if (index >= 0 && dropDown.values && index <= dropDown.values.length - 1) {
|
if (index >= 0 && dropDown.values && index <= dropDown.values.length - 1) {
|
||||||
const value = dropDown.values[index];
|
const value = dropDown.values[index];
|
||||||
@@ -153,10 +162,15 @@ export function selectDropDownIndex(dropDown: DropDownComponent, index: number):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function findDropDownItemIndex(dropDown: DropDownComponent, value: string): number {
|
export function findDropDownItemIndex(dropDown: DropDownComponent, value: string, useDisplayName: boolean = true): number {
|
||||||
if (dropDown.values) {
|
if (dropDown.values) {
|
||||||
|
if (useDisplayName) {
|
||||||
return dropDown.values.findIndex((v: any) =>
|
return dropDown.values.findIndex((v: any) =>
|
||||||
(v as CategoryValue)?.displayName?.toLowerCase() === value?.toLowerCase());
|
(v as CategoryValue)?.displayName?.toLowerCase() === value?.toLowerCase());
|
||||||
|
} else {
|
||||||
|
return dropDown.values.findIndex((v: any) =>
|
||||||
|
(v as CategoryValue)?.name?.toLowerCase() === value?.toLowerCase());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import * as azdata from 'azdata';
|
||||||
import { MigrationContext, MigrationStatus } from '../models/migrationLocalStorage';
|
import { MigrationContext, MigrationStatus } from '../models/migrationLocalStorage';
|
||||||
import { MigrationMode, MigrationTargetType } from '../models/stateMachine';
|
import { MigrationMode, MigrationTargetType } from '../models/stateMachine';
|
||||||
import * as loc from './strings';
|
import * as loc from './strings';
|
||||||
@@ -48,3 +49,20 @@ export function canRetryMigration(status: string | undefined): boolean {
|
|||||||
status === MigrationStatus.Succeeded ||
|
status === MigrationStatus.Succeeded ||
|
||||||
status === MigrationStatus.Canceled;
|
status === MigrationStatus.Canceled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const TABLE_CHECKBOX_INDEX = 0;
|
||||||
|
const TABLE_DB_NAME_INDEX = 1;
|
||||||
|
export function selectDatabasesFromList(selectedDbs: string[], databaseTableValues: azdata.DeclarativeTableCellValue[][]): azdata.DeclarativeTableCellValue[][] {
|
||||||
|
const sourceDatabaseNames = selectedDbs?.map(dbName => dbName.toLocaleLowerCase()) || [];
|
||||||
|
if (sourceDatabaseNames?.length > 0) {
|
||||||
|
for (let i in databaseTableValues) {
|
||||||
|
const row = databaseTableValues[i];
|
||||||
|
const dbName = (row[TABLE_DB_NAME_INDEX].value as string).toLocaleLowerCase();
|
||||||
|
if (sourceDatabaseNames.indexOf(dbName) > -1) {
|
||||||
|
row[TABLE_CHECKBOX_INDEX].value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return databaseTableValues;
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,10 +17,13 @@ export function WIZARD_TITLE(instanceName: string): string {
|
|||||||
}
|
}
|
||||||
// //#endregion
|
// //#endregion
|
||||||
|
|
||||||
// Resume Migration Dialog
|
// Save and close
|
||||||
|
export const SAVE_AND_CLOSE = localize('sql.migration.save.close', "Save and close");
|
||||||
|
export const SAVE_AND_CLOSE_POPUP = localize('sql.migration.save.close.popup', "Configuration saved. Performance data collection will remain running in the background. You can stop the collection when you want to.");
|
||||||
export const RESUME_TITLE = localize('sql.migration.resume.title', "Run migration workflow again");
|
export const RESUME_TITLE = localize('sql.migration.resume.title', "Run migration workflow again");
|
||||||
export const START_MIGRATION = localize('sql.migration.resume.start', "Start a new session");
|
export const START_NEW_SESSION = localize('sql.migration.start.session', "Start a new session");
|
||||||
export const CONTINUE_MIGRATION = localize('sql.migration.resume.continue', "Resume previously saved session");
|
export const RESUME_SESSION = localize('sql.migration.resume.session', "Resume previously saved session");
|
||||||
|
export const OPEN_SAVED_INFO_ERROR = localize("sql.migration.invalid.savedInfo", 'Cannot retrieve saved session. Try again by selecting new session.');
|
||||||
|
|
||||||
// Databases for assessment
|
// Databases for assessment
|
||||||
export const DATABASE_FOR_ASSESSMENT_PAGE_TITLE = localize('sql.migration.database.assessment.title', "Databases for assessment");
|
export const DATABASE_FOR_ASSESSMENT_PAGE_TITLE = localize('sql.migration.database.assessment.title', "Databases for assessment");
|
||||||
@@ -267,6 +270,8 @@ export const ACCOUNTS_SELECTION_PAGE_TITLE = localize('sql.migration.wizard.acco
|
|||||||
export const ACCOUNTS_SELECTION_PAGE_DESCRIPTION = localize('sql.migration.wizard.account.description', "Select an Azure account linked to Azure Data Studio, or link one now.");
|
export const ACCOUNTS_SELECTION_PAGE_DESCRIPTION = localize('sql.migration.wizard.account.description', "Select an Azure account linked to Azure Data Studio, or link one now.");
|
||||||
export const ACCOUNT_SELECTION_PAGE_NO_LINKED_ACCOUNTS_ERROR = localize('sql.migration.wizard.account.noAccount.error', "Add a linked account and then try again.");
|
export const ACCOUNT_SELECTION_PAGE_NO_LINKED_ACCOUNTS_ERROR = localize('sql.migration.wizard.account.noAccount.error', "Add a linked account and then try again.");
|
||||||
export const ACCOUNT_LINK_BUTTON_LABEL = localize('sql.migration.wizard.account.add.button.label', "Link account");
|
export const ACCOUNT_LINK_BUTTON_LABEL = localize('sql.migration.wizard.account.add.button.label', "Link account");
|
||||||
|
export const INVALID_ACCOUNT_ERROR = localize('sql.migration.invalid.account.error', "To continue, select a valid Azure account.");
|
||||||
|
|
||||||
export function accountLinkedMessage(count: number): string {
|
export function accountLinkedMessage(count: number): string {
|
||||||
return count === 1 ? localize('sql.migration.wizard.account.count.single.message', '{0} account linked', count) : localize('sql.migration.wizard.account.count.multiple.message', '{0} accounts linked', count);
|
return count === 1 ? localize('sql.migration.wizard.account.count.single.message', '{0} account linked', count) : localize('sql.migration.wizard.account.count.multiple.message', '{0} accounts linked', count);
|
||||||
}
|
}
|
||||||
@@ -665,8 +670,6 @@ export const SQL_MIGRATION_SERVICE_DETAILS_AUTH_KEYS_TITLE = localize('sql.migra
|
|||||||
export const SQL_MIGRATION_SERVICE_DETAILS_STATUS_UNAVAILABLE = localize('sql.migration.service.details.status.unavailable', "-- unavailable --");
|
export const SQL_MIGRATION_SERVICE_DETAILS_STATUS_UNAVAILABLE = localize('sql.migration.service.details.status.unavailable', "-- unavailable --");
|
||||||
|
|
||||||
//Source Credentials page.
|
//Source Credentials page.
|
||||||
export const SAVE_AND_CLOSE = localize('sql.migration.save.close', "Save and close");
|
|
||||||
export const SAVE_AND_CLOSE_POPUP = localize('sql.migration.save.close.popup', "Configuration saved. Performance data collection will remain running in the background. You can stop the collection when you want to.");
|
|
||||||
export const SOURCE_CONFIGURATION = localize('sql.migration.source.configuration', "Source configuration");
|
export const SOURCE_CONFIGURATION = localize('sql.migration.source.configuration', "Source configuration");
|
||||||
export const SOURCE_CREDENTIALS = localize('sql.migration.source.credentials', "Source credentials");
|
export const SOURCE_CREDENTIALS = localize('sql.migration.source.credentials', "Source credentials");
|
||||||
export const ENTER_YOUR_SQL_CREDS = localize('sql.migration.enter.your.sql.cred', "Enter the credentials for the source SQL Server instance. These credentials will be used while migrating databases to Azure SQL.");
|
export const ENTER_YOUR_SQL_CREDS = localize('sql.migration.enter.your.sql.cred', "Enter the credentials for the source SQL Server instance. These credentials will be used while migrating databases to Azure SQL.");
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { MigrationStateModel, MigrationTargetType, Page } from '../../models/stateMachine';
|
import { MigrationStateModel, MigrationTargetType } from '../../models/stateMachine';
|
||||||
import { SqlDatabaseTree } from './sqlDatabasesTree';
|
import { SqlDatabaseTree } from './sqlDatabasesTree';
|
||||||
import { SqlMigrationImpactedObjectInfo } from '../../../../mssql/src/mssql';
|
import { SqlMigrationImpactedObjectInfo } from '../../../../mssql/src/mssql';
|
||||||
import { SKURecommendationPage } from '../../wizard/skuRecommendationPage';
|
import { SKURecommendationPage } from '../../wizard/skuRecommendationPage';
|
||||||
@@ -32,9 +32,6 @@ export class AssessmentResultsDialog {
|
|||||||
|
|
||||||
constructor(public ownerUri: string, public model: MigrationStateModel, public title: string, private _skuRecommendationPage: SKURecommendationPage, private _targetType: MigrationTargetType) {
|
constructor(public ownerUri: string, public model: MigrationStateModel, public title: string, private _skuRecommendationPage: SKURecommendationPage, private _targetType: MigrationTargetType) {
|
||||||
this._model = model;
|
this._model = model;
|
||||||
if (this._model.resumeAssessment && this._model.savedInfo.closedPage >= Page.DatabaseBackup) {
|
|
||||||
this._model._databaseAssessment = <string[]>this._model.savedInfo.databaseAssessment;
|
|
||||||
}
|
|
||||||
this._tree = new SqlDatabaseTree(this._model, this._targetType);
|
this._tree = new SqlDatabaseTree(this._model, this._targetType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,16 +84,31 @@ export class AssessmentResultsDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async execute() {
|
protected async execute() {
|
||||||
if (this._targetType === MigrationTargetType.SQLVM) {
|
const selectedDbs = this._tree.selectedDbs();
|
||||||
this._model._vmDbs = this._tree.selectedDbs();
|
switch (this._targetType) {
|
||||||
} else {
|
case MigrationTargetType.SQLMI: {
|
||||||
this._model._miDbs = this._tree.selectedDbs();
|
this.didUpdateDatabasesForMigration(this._model._miDbs, selectedDbs);
|
||||||
|
this._model._miDbs = selectedDbs;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MigrationTargetType.SQLVM: {
|
||||||
|
this.didUpdateDatabasesForMigration(this._model._vmDbs, selectedDbs);
|
||||||
|
this._model._vmDbs = selectedDbs;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await this._skuRecommendationPage.refreshCardText();
|
await this._skuRecommendationPage.refreshCardText();
|
||||||
this.model.refreshDatabaseBackupPage = true;
|
this.model.refreshDatabaseBackupPage = true;
|
||||||
this._isOpen = false;
|
this._isOpen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private didUpdateDatabasesForMigration(priorDbs: string[], selectedDbs: string[]) {
|
||||||
|
this._model._didUpdateDatabasesForMigration = selectedDbs.length === 0
|
||||||
|
|| selectedDbs.length !== priorDbs.length
|
||||||
|
|| priorDbs.some(db => selectedDbs.indexOf(db) < 0);
|
||||||
|
}
|
||||||
|
|
||||||
protected async cancel() {
|
protected async cancel() {
|
||||||
this._isOpen = false;
|
this._isOpen = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,16 @@ export class SavedAssessmentDialog {
|
|||||||
reject(ex);
|
reject(ex);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
dialog.registerCloseValidator(async () => {
|
||||||
|
if (this.stateModel.resumeAssessment) {
|
||||||
|
if (!this.stateModel.loadSavedInfo()) {
|
||||||
|
void vscode.window.showInformationMessage(constants.OPEN_SAVED_INFO_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,14 +77,8 @@ export class SavedAssessmentDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async execute() {
|
protected async execute() {
|
||||||
if (this.stateModel.resumeAssessment) {
|
|
||||||
const wizardController = new WizardController(this.context, this.stateModel);
|
const wizardController = new WizardController(this.context, this.stateModel);
|
||||||
await wizardController.openWizard(this.stateModel.sourceConnectionId);
|
await wizardController.openWizard(this.stateModel.sourceConnectionId);
|
||||||
} else {
|
|
||||||
// normal flow
|
|
||||||
const wizardController = new WizardController(this.context, this.stateModel);
|
|
||||||
await wizardController.openWizard(this.stateModel.sourceConnectionId);
|
|
||||||
}
|
|
||||||
this._isOpen = false;
|
this._isOpen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +94,7 @@ export class SavedAssessmentDialog {
|
|||||||
const buttonGroup = 'resumeMigration';
|
const buttonGroup = 'resumeMigration';
|
||||||
|
|
||||||
const radioStart = view.modelBuilder.radioButton().withProps({
|
const radioStart = view.modelBuilder.radioButton().withProps({
|
||||||
label: constants.START_MIGRATION,
|
label: constants.START_NEW_SESSION,
|
||||||
name: buttonGroup,
|
name: buttonGroup,
|
||||||
CSSStyles: {
|
CSSStyles: {
|
||||||
...styles.BODY_CSS,
|
...styles.BODY_CSS,
|
||||||
@@ -105,7 +109,7 @@ export class SavedAssessmentDialog {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
const radioContinue = view.modelBuilder.radioButton().withProps({
|
const radioContinue = view.modelBuilder.radioButton().withProps({
|
||||||
label: constants.CONTINUE_MIGRATION,
|
label: constants.RESUME_SESSION,
|
||||||
name: buttonGroup,
|
name: buttonGroup,
|
||||||
CSSStyles: {
|
CSSStyles: {
|
||||||
...styles.BODY_CSS,
|
...styles.BODY_CSS,
|
||||||
@@ -122,11 +126,9 @@ export class SavedAssessmentDialog {
|
|||||||
const flex = view.modelBuilder.flexContainer()
|
const flex = view.modelBuilder.flexContainer()
|
||||||
.withLayout({
|
.withLayout({
|
||||||
flexFlow: 'column',
|
flexFlow: 'column',
|
||||||
height: '100%',
|
|
||||||
width: '100%',
|
|
||||||
}).withProps({
|
}).withProps({
|
||||||
CSSStyles: {
|
CSSStyles: {
|
||||||
'margin': '20px 15px',
|
'padding': '20px 15px',
|
||||||
}
|
}
|
||||||
}).component();
|
}).component();
|
||||||
flex.addItem(radioStart, { flex: '0 0 auto' });
|
flex.addItem(radioStart, { flex: '0 0 auto' });
|
||||||
@@ -134,5 +136,4 @@ export class SavedAssessmentDialog {
|
|||||||
|
|
||||||
return flex;
|
return flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,13 @@
|
|||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { SqlMigrationAssessmentResultItem, SqlMigrationImpactedObjectInfo } from '../../../../mssql/src/mssql';
|
import { SqlMigrationAssessmentResultItem, SqlMigrationImpactedObjectInfo } from '../../../../mssql/src/mssql';
|
||||||
import { MigrationStateModel, MigrationTargetType, Page } from '../../models/stateMachine';
|
import { MigrationStateModel, MigrationTargetType } from '../../models/stateMachine';
|
||||||
import * as constants from '../../constants/strings';
|
import * as constants from '../../constants/strings';
|
||||||
import { debounce } from '../../api/utils';
|
import { debounce } from '../../api/utils';
|
||||||
import { IconPath, IconPathHelper } from '../../constants/iconPathHelper';
|
import { IconPath, IconPathHelper } from '../../constants/iconPathHelper';
|
||||||
import * as styles from '../../constants/styles';
|
import * as styles from '../../constants/styles';
|
||||||
import { EOL } from 'os';
|
import { EOL } from 'os';
|
||||||
|
import { selectDatabasesFromList } from '../../constants/helper';
|
||||||
|
|
||||||
const styleLeft: azdata.CssStyles = {
|
const styleLeft: azdata.CssStyles = {
|
||||||
'border': 'none',
|
'border': 'none',
|
||||||
@@ -142,7 +143,7 @@ export class SqlDatabaseTree {
|
|||||||
...styles.BOLD_NOTE_CSS,
|
...styles.BOLD_NOTE_CSS,
|
||||||
'margin': '0px 15px 0px 15px'
|
'margin': '0px 15px 0px 15px'
|
||||||
},
|
},
|
||||||
value: constants.DATABASES(0, this._model._databaseAssessment?.length)
|
value: constants.DATABASES(0, this._model._databasesForAssessment?.length)
|
||||||
}).component();
|
}).component();
|
||||||
return this._databaseCount;
|
return this._databaseCount;
|
||||||
}
|
}
|
||||||
@@ -881,7 +882,7 @@ export class SqlDatabaseTree {
|
|||||||
public async initialize(): Promise<void> {
|
public async initialize(): Promise<void> {
|
||||||
let instanceTableValues: azdata.DeclarativeTableCellValue[][] = [];
|
let instanceTableValues: azdata.DeclarativeTableCellValue[][] = [];
|
||||||
this._databaseTableValues = [];
|
this._databaseTableValues = [];
|
||||||
this._dbNames = this._model._databaseAssessment;
|
this._dbNames = this._model._databasesForAssessment;
|
||||||
const selectedDbs = (this._targetType === MigrationTargetType.SQLVM) ? this._model._vmDbs : this._model._miDbs;
|
const selectedDbs = (this._targetType === MigrationTargetType.SQLVM) ? this._model._vmDbs : this._model._miDbs;
|
||||||
this._serverName = (await this._model.getSourceConnectionProfile()).serverName;
|
this._serverName = (await this._model.getSourceConnectionProfile()).serverName;
|
||||||
|
|
||||||
@@ -959,25 +960,16 @@ export class SqlDatabaseTree {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
await this._instanceTable.setDataValues(instanceTableValues);
|
await this._instanceTable.setDataValues(instanceTableValues);
|
||||||
if (this._model.resumeAssessment && this._model.savedInfo.closedPage >= Page.SKURecommendation && this._targetType === this._model.savedInfo.migrationTargetType) {
|
|
||||||
await this._databaseTable.setDataValues(this._model.savedInfo.migrationDatabases);
|
|
||||||
} else {
|
|
||||||
if (this._model.retryMigration && this._targetType === this._model.savedInfo.migrationTargetType) {
|
|
||||||
const sourceDatabaseName = this._model.savedInfo.databaseList[0];
|
|
||||||
const sourceDatabaseIndex = this._dbNames.indexOf(sourceDatabaseName);
|
|
||||||
this._databaseTableValues[sourceDatabaseIndex][0].value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
this._databaseTableValues = selectDatabasesFromList(this._model._databasesForMigration, this._databaseTableValues);
|
||||||
await this._databaseTable.setDataValues(this._databaseTableValues);
|
await this._databaseTable.setDataValues(this._databaseTableValues);
|
||||||
await this.updateValuesOnSelection();
|
await this.updateValuesOnSelection();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private async updateValuesOnSelection() {
|
private async updateValuesOnSelection() {
|
||||||
await this._databaseCount.updateProperties({
|
await this._databaseCount.updateProperties({
|
||||||
'value': constants.DATABASES(this.selectedDbs()?.length, this._model._databaseAssessment?.length)
|
'value': constants.DATABASES(this.selectedDbs()?.length, this._model._databasesForAssessment?.length)
|
||||||
});
|
});
|
||||||
this._model._databaseSelection = <azdata.DeclarativeTableCellValue[][]>this._databaseTable.dataValues;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// undo when bug #16445 is fixed
|
// undo when bug #16445 is fixed
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { MigrationMode, MigrationStateModel, NetworkContainerType, SavedInfo } f
|
|||||||
import { MigrationContext } from '../../models/migrationLocalStorage';
|
import { MigrationContext } from '../../models/migrationLocalStorage';
|
||||||
import { WizardController } from '../../wizard/wizardController';
|
import { WizardController } from '../../wizard/wizardController';
|
||||||
import { getMigrationModeEnum, getMigrationTargetTypeEnum } from '../../constants/helper';
|
import { getMigrationModeEnum, getMigrationTargetTypeEnum } from '../../constants/helper';
|
||||||
|
import * as constants from '../../constants/strings';
|
||||||
|
|
||||||
export class RetryMigrationDialog {
|
export class RetryMigrationDialog {
|
||||||
private _context: vscode.ExtensionContext;
|
private _context: vscode.ExtensionContext;
|
||||||
@@ -30,21 +31,18 @@ export class RetryMigrationDialog {
|
|||||||
savedInfo = {
|
savedInfo = {
|
||||||
closedPage: 0,
|
closedPage: 0,
|
||||||
|
|
||||||
// AzureAccount
|
|
||||||
azureAccount: migration.azureAccount,
|
|
||||||
azureTenant: migration.azureAccount.properties.tenants[0],
|
|
||||||
|
|
||||||
// DatabaseSelector
|
// DatabaseSelector
|
||||||
selectedDatabases: [],
|
databaseAssessment: [sourceDatabaseName],
|
||||||
|
|
||||||
// SKURecommendation
|
// SKURecommendation
|
||||||
databaseAssessment: [],
|
|
||||||
databaseList: [sourceDatabaseName],
|
databaseList: [sourceDatabaseName],
|
||||||
migrationDatabases: [],
|
|
||||||
serverAssessment: null,
|
serverAssessment: null,
|
||||||
skuRecommendation: null,
|
skuRecommendation: null,
|
||||||
|
|
||||||
migrationTargetType: getMigrationTargetTypeEnum(migration)!,
|
migrationTargetType: getMigrationTargetTypeEnum(migration)!,
|
||||||
|
|
||||||
|
// TargetSelection
|
||||||
|
azureAccount: migration.azureAccount,
|
||||||
|
azureTenant: migration.azureAccount.properties.tenants[0],
|
||||||
subscription: migration.subscription,
|
subscription: migration.subscription,
|
||||||
location: location,
|
location: location,
|
||||||
resourceGroup: {
|
resourceGroup: {
|
||||||
@@ -58,14 +56,13 @@ export class RetryMigrationDialog {
|
|||||||
migrationMode: getMigrationModeEnum(migration),
|
migrationMode: getMigrationModeEnum(migration),
|
||||||
|
|
||||||
// DatabaseBackup
|
// DatabaseBackup
|
||||||
targetSubscription: migration.subscription,
|
|
||||||
targetDatabaseNames: [migration.migrationContext.name],
|
targetDatabaseNames: [migration.migrationContext.name],
|
||||||
networkContainerType: null,
|
networkContainerType: null,
|
||||||
networkShares: [],
|
networkShares: [],
|
||||||
blobs: [],
|
blobs: [],
|
||||||
|
|
||||||
// Integration Runtime
|
// Integration Runtime
|
||||||
migrationServiceId: migration.migrationContext.properties.migrationService,
|
sqlMigrationService: migration.controller,
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStorageAccountResourceGroup = (storageAccountResourceId: string) => {
|
const getStorageAccountResourceGroup = (storageAccountResourceId: string) => {
|
||||||
@@ -151,7 +148,11 @@ export class RetryMigrationDialog {
|
|||||||
const api = (await vscode.extensions.getExtension(mssql.extension.name)?.activate()) as mssql.IExtension;
|
const api = (await vscode.extensions.getExtension(mssql.extension.name)?.activate()) as mssql.IExtension;
|
||||||
const stateModel = this.createMigrationStateModel(this._migration, connectionId, serverName, api, location!);
|
const stateModel = this.createMigrationStateModel(this._migration, connectionId, serverName, api, location!);
|
||||||
|
|
||||||
|
if (stateModel.loadSavedInfo()) {
|
||||||
const wizardController = new WizardController(this._context, stateModel);
|
const wizardController = new WizardController(this._context, stateModel);
|
||||||
await wizardController.openWizard(stateModel.sourceConnectionId);
|
await wizardController.openWizard(stateModel.sourceConnectionId);
|
||||||
|
} else {
|
||||||
|
void vscode.window.showInformationMessage(constants.MIGRATION_CANNOT_RETRY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export class TargetDatabaseSummaryDialog {
|
|||||||
this._view = view;
|
this._view = view;
|
||||||
|
|
||||||
const databaseCount = this._view.modelBuilder.text().withProps({
|
const databaseCount = this._view.modelBuilder.text().withProps({
|
||||||
value: constants.COUNT_DATABASES(this._model._migrationDbs.length),
|
value: constants.COUNT_DATABASES(this._model._databasesForMigration.length),
|
||||||
CSSStyles: {
|
CSSStyles: {
|
||||||
...styles.BODY_CSS,
|
...styles.BODY_CSS,
|
||||||
'margin-bottom': '20px'
|
'margin-bottom': '20px'
|
||||||
@@ -132,7 +132,7 @@ export class TargetDatabaseSummaryDialog {
|
|||||||
|
|
||||||
const tableRows: azdata.DeclarativeTableCellValue[][] = [];
|
const tableRows: azdata.DeclarativeTableCellValue[][] = [];
|
||||||
|
|
||||||
this._model._migrationDbs.forEach((db, index) => {
|
this._model._databasesForMigration.forEach((db, index) => {
|
||||||
const tableRow: azdata.DeclarativeTableCellValue[] = [];
|
const tableRow: azdata.DeclarativeTableCellValue[] = [];
|
||||||
tableRow.push({
|
tableRow.push({
|
||||||
value: db
|
value: db
|
||||||
|
|||||||
@@ -118,25 +118,22 @@ export interface StateChangeEvent {
|
|||||||
|
|
||||||
export interface SavedInfo {
|
export interface SavedInfo {
|
||||||
closedPage: number;
|
closedPage: number;
|
||||||
serverAssessment: ServerAssessment | null;
|
databaseAssessment: string[];
|
||||||
|
databaseList: string[];
|
||||||
|
migrationTargetType: MigrationTargetType | null;
|
||||||
azureAccount: azdata.Account | null;
|
azureAccount: azdata.Account | null;
|
||||||
azureTenant: azurecore.Tenant | null;
|
azureTenant: azurecore.Tenant | null;
|
||||||
selectedDatabases: azdata.DeclarativeTableCellValue[][];
|
|
||||||
migrationTargetType: MigrationTargetType | null;
|
|
||||||
migrationDatabases: azdata.DeclarativeTableCellValue[][];
|
|
||||||
databaseList: string[];
|
|
||||||
subscription: azureResource.AzureResourceSubscription | null;
|
subscription: azureResource.AzureResourceSubscription | null;
|
||||||
location: azureResource.AzureLocation | null;
|
location: azureResource.AzureLocation | null;
|
||||||
resourceGroup: azureResource.AzureResourceResourceGroup | null;
|
resourceGroup: azureResource.AzureResourceResourceGroup | null;
|
||||||
targetServerInstance: azureResource.AzureSqlManagedInstance | SqlVMServer | null;
|
targetServerInstance: azureResource.AzureSqlManagedInstance | SqlVMServer | null;
|
||||||
migrationMode: MigrationMode | null;
|
migrationMode: MigrationMode | null;
|
||||||
databaseAssessment: string[] | null;
|
|
||||||
networkContainerType: NetworkContainerType | null;
|
networkContainerType: NetworkContainerType | null;
|
||||||
networkShares: NetworkShare[];
|
networkShares: NetworkShare[];
|
||||||
targetSubscription: azureResource.AzureResourceSubscription | null;
|
|
||||||
blobs: Blob[];
|
blobs: Blob[];
|
||||||
targetDatabaseNames: string[];
|
targetDatabaseNames: string[];
|
||||||
migrationServiceId: string | null;
|
sqlMigrationService: SqlMigrationService | undefined;
|
||||||
|
serverAssessment: ServerAssessment | null;
|
||||||
skuRecommendation: SkuRecommendationSavedInfo | null;
|
skuRecommendation: SkuRecommendationSavedInfo | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,10 +157,8 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
public _authenticationType!: MigrationSourceAuthenticationType;
|
public _authenticationType!: MigrationSourceAuthenticationType;
|
||||||
public _sqlServerUsername!: string;
|
public _sqlServerUsername!: string;
|
||||||
public _sqlServerPassword!: string;
|
public _sqlServerPassword!: string;
|
||||||
public _databaseAssessment!: string[];
|
|
||||||
|
|
||||||
public _subscriptions!: azureResource.AzureResourceSubscription[];
|
public _subscriptions!: azureResource.AzureResourceSubscription[];
|
||||||
|
|
||||||
public _targetSubscription!: azureResource.AzureResourceSubscription;
|
public _targetSubscription!: azureResource.AzureResourceSubscription;
|
||||||
public _locations!: azureResource.AzureLocation[];
|
public _locations!: azureResource.AzureLocation[];
|
||||||
public _location!: azureResource.AzureLocation;
|
public _location!: azureResource.AzureLocation;
|
||||||
@@ -173,11 +168,11 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
public _targetSqlVirtualMachines!: SqlVMServer[];
|
public _targetSqlVirtualMachines!: SqlVMServer[];
|
||||||
public _targetServerInstance!: SqlManagedInstance | SqlVMServer;
|
public _targetServerInstance!: SqlManagedInstance | SqlVMServer;
|
||||||
public _databaseBackup!: DatabaseBackupModel;
|
public _databaseBackup!: DatabaseBackupModel;
|
||||||
public _migrationDbs: string[] = [];
|
|
||||||
public _storageAccounts!: StorageAccount[];
|
public _storageAccounts!: StorageAccount[];
|
||||||
public _fileShares!: azureResource.FileShare[];
|
public _fileShares!: azureResource.FileShare[];
|
||||||
public _blobContainers!: azureResource.BlobContainer[];
|
public _blobContainers!: azureResource.BlobContainer[];
|
||||||
public _lastFileNames!: azureResource.Blob[];
|
public _lastFileNames!: azureResource.Blob[];
|
||||||
|
public _sourceDatabaseNames!: string[];
|
||||||
public _targetDatabaseNames!: string[];
|
public _targetDatabaseNames!: string[];
|
||||||
|
|
||||||
public _sqlMigrationServiceResourceGroup!: string;
|
public _sqlMigrationServiceResourceGroup!: string;
|
||||||
@@ -189,11 +184,19 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
private _currentState: State;
|
private _currentState: State;
|
||||||
private _gatheringInformationError: string | undefined;
|
private _gatheringInformationError: string | undefined;
|
||||||
|
|
||||||
|
public _databasesForAssessment!: string[];
|
||||||
public _assessmentResults!: ServerAssessment;
|
public _assessmentResults!: ServerAssessment;
|
||||||
|
public _assessedDatabaseList!: string[];
|
||||||
public _runAssessments: boolean = true;
|
public _runAssessments: boolean = true;
|
||||||
private _assessmentApiResponse!: mssql.AssessmentResult;
|
private _assessmentApiResponse!: mssql.AssessmentResult;
|
||||||
public mementoString: string;
|
public mementoString: string;
|
||||||
|
|
||||||
|
public _databasesForMigration: string[] = [];
|
||||||
|
public _didUpdateDatabasesForMigration: boolean = false;
|
||||||
|
public _vmDbs: string[] = [];
|
||||||
|
public _miDbs: string[] = [];
|
||||||
|
public _targetType!: MigrationTargetType;
|
||||||
|
|
||||||
public _skuRecommendationResults!: SkuRecommendation;
|
public _skuRecommendationResults!: SkuRecommendation;
|
||||||
public _skuRecommendationPerformanceDataSource!: PerformanceDataSourceOptions;
|
public _skuRecommendationPerformanceDataSource!: PerformanceDataSourceOptions;
|
||||||
private _skuRecommendationApiResponse!: mssql.SkuRecommendationResult;
|
private _skuRecommendationApiResponse!: mssql.SkuRecommendationResult;
|
||||||
@@ -225,12 +228,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
public _skuTargetPercentile!: number;
|
public _skuTargetPercentile!: number;
|
||||||
public _skuEnablePreview!: boolean;
|
public _skuEnablePreview!: boolean;
|
||||||
|
|
||||||
public _vmDbs: string[] = [];
|
|
||||||
public _miDbs: string[] = [];
|
|
||||||
public _targetType!: MigrationTargetType;
|
|
||||||
public refreshDatabaseBackupPage!: boolean;
|
public refreshDatabaseBackupPage!: boolean;
|
||||||
|
|
||||||
public _databaseSelection!: azdata.DeclarativeTableCellValue[][];
|
|
||||||
public retryMigration!: boolean;
|
public retryMigration!: boolean;
|
||||||
public resumeAssessment!: boolean;
|
public resumeAssessment!: boolean;
|
||||||
public savedInfo!: SavedInfo;
|
public savedInfo!: SavedInfo;
|
||||||
@@ -244,7 +242,6 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
'model'
|
'model'
|
||||||
];
|
];
|
||||||
public serverName!: string;
|
public serverName!: string;
|
||||||
public databaseSelectorTableValues!: azdata.DeclarativeTableCellValue[][];
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public extensionContext: vscode.ExtensionContext,
|
public extensionContext: vscode.ExtensionContext,
|
||||||
@@ -255,6 +252,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
this._databaseBackup = {} as DatabaseBackupModel;
|
this._databaseBackup = {} as DatabaseBackupModel;
|
||||||
this._databaseBackup.networkShares = [];
|
this._databaseBackup.networkShares = [];
|
||||||
this._databaseBackup.blobs = [];
|
this._databaseBackup.blobs = [];
|
||||||
|
this._targetDatabaseNames = [];
|
||||||
this.mementoString = 'sqlMigration.assessmentResults';
|
this.mementoString = 'sqlMigration.assessmentResults';
|
||||||
|
|
||||||
this._skuScalingFactor = 100;
|
this._skuScalingFactor = 100;
|
||||||
@@ -282,7 +280,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
}
|
}
|
||||||
public hasRecommendedDatabaseListChanged(): boolean {
|
public hasRecommendedDatabaseListChanged(): boolean {
|
||||||
const oldDbList = this._skuRecommendationRecommendedDatabaseList;
|
const oldDbList = this._skuRecommendationRecommendedDatabaseList;
|
||||||
const newDbList = this._databaseAssessment;
|
const newDbList = this._databasesForAssessment;
|
||||||
|
|
||||||
if (!oldDbList || !newDbList) {
|
if (!oldDbList || !newDbList) {
|
||||||
return false;
|
return false;
|
||||||
@@ -295,8 +293,10 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
public async getDatabaseAssessments(targetType: MigrationTargetType): Promise<ServerAssessment> {
|
public async getDatabaseAssessments(targetType: MigrationTargetType): Promise<ServerAssessment> {
|
||||||
const ownerUri = await azdata.connection.getUriForConnection(this.sourceConnectionId);
|
const ownerUri = await azdata.connection.getUriForConnection(this.sourceConnectionId);
|
||||||
try {
|
try {
|
||||||
const response = (await this.migrationService.getAssessments(ownerUri, this._databaseAssessment))!;
|
const response = (await this.migrationService.getAssessments(ownerUri, this._databasesForAssessment))!;
|
||||||
this._assessmentApiResponse = response;
|
this._assessmentApiResponse = response;
|
||||||
|
this._assessedDatabaseList = this._databasesForAssessment.slice();
|
||||||
|
|
||||||
if (response?.assessmentResult) {
|
if (response?.assessmentResult) {
|
||||||
response.assessmentResult.items = response.assessmentResult.items?.filter(
|
response.assessmentResult.items = response.assessmentResult.items?.filter(
|
||||||
issue => issue.appliesToMigrationTargetPlatform === targetType);
|
issue => issue.appliesToMigrationTargetPlatform === targetType);
|
||||||
@@ -318,7 +318,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
} else {
|
} else {
|
||||||
this._assessmentResults = {
|
this._assessmentResults = {
|
||||||
issues: [],
|
issues: [],
|
||||||
databaseAssessments: this._databaseAssessment?.map(database => {
|
databaseAssessments: this._databasesForAssessment?.map(database => {
|
||||||
return {
|
return {
|
||||||
name: database,
|
name: database,
|
||||||
issues: [],
|
issues: [],
|
||||||
@@ -332,7 +332,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
this._assessmentResults = {
|
this._assessmentResults = {
|
||||||
issues: [],
|
issues: [],
|
||||||
databaseAssessments: this._databaseAssessment?.map(database => {
|
databaseAssessments: this._databasesForAssessment?.map(database => {
|
||||||
return {
|
return {
|
||||||
name: database,
|
name: database,
|
||||||
issues: [],
|
issues: [],
|
||||||
@@ -364,11 +364,11 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
this._defaultDataPointStartTime,
|
this._defaultDataPointStartTime,
|
||||||
this._defaultDataPointEndTime,
|
this._defaultDataPointEndTime,
|
||||||
this._skuEnablePreview,
|
this._skuEnablePreview,
|
||||||
this._databaseAssessment))!;
|
this._databasesForAssessment))!;
|
||||||
this._skuRecommendationApiResponse = response;
|
this._skuRecommendationApiResponse = response;
|
||||||
|
|
||||||
// clone list of databases currently being assessed and store them, so that if the user ever changes the list we can refresh new recommendations
|
// clone list of databases currently being assessed and store them, so that if the user ever changes the list we can refresh new recommendations
|
||||||
this._skuRecommendationRecommendedDatabaseList = this._databaseAssessment.slice();
|
this._skuRecommendationRecommendedDatabaseList = this._databasesForAssessment.slice();
|
||||||
|
|
||||||
if (response?.sqlDbRecommendationResults || response?.sqlMiRecommendationResults || response?.sqlVmRecommendationResults) {
|
if (response?.sqlDbRecommendationResults || response?.sqlMiRecommendationResults || response?.sqlVmRecommendationResults) {
|
||||||
this._skuRecommendationResults = {
|
this._skuRecommendationResults = {
|
||||||
@@ -862,9 +862,12 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
public async getSubscriptionsDropdownValues(): Promise<azdata.CategoryValue[]> {
|
public async getSubscriptionsDropdownValues(): Promise<azdata.CategoryValue[]> {
|
||||||
let subscriptionsValues: azdata.CategoryValue[] = [];
|
let subscriptionsValues: azdata.CategoryValue[] = [];
|
||||||
try {
|
try {
|
||||||
if (!this._subscriptions) {
|
if (this._azureAccount) {
|
||||||
this._subscriptions = await getSubscriptions(this._azureAccount);
|
this._subscriptions = await getSubscriptions(this._azureAccount);
|
||||||
|
} else {
|
||||||
|
this._subscriptions = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
this._subscriptions.forEach((subscription) => {
|
this._subscriptions.forEach((subscription) => {
|
||||||
subscriptionsValues.push({
|
subscriptionsValues.push({
|
||||||
name: subscription.id,
|
name: subscription.id,
|
||||||
@@ -900,7 +903,12 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
public async getAzureLocationDropdownValues(subscription: azureResource.AzureResourceSubscription): Promise<azdata.CategoryValue[]> {
|
public async getAzureLocationDropdownValues(subscription: azureResource.AzureResourceSubscription): Promise<azdata.CategoryValue[]> {
|
||||||
let locationValues: azdata.CategoryValue[] = [];
|
let locationValues: azdata.CategoryValue[] = [];
|
||||||
try {
|
try {
|
||||||
|
if (this._azureAccount && subscription) {
|
||||||
this._locations = await getLocations(this._azureAccount, subscription);
|
this._locations = await getLocations(this._azureAccount, subscription);
|
||||||
|
} else {
|
||||||
|
this._locations = [];
|
||||||
|
}
|
||||||
|
|
||||||
this._locations.forEach((loc) => {
|
this._locations.forEach((loc) => {
|
||||||
locationValues.push({
|
locationValues.push({
|
||||||
name: loc.name,
|
name: loc.name,
|
||||||
@@ -911,7 +919,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
if (locationValues.length === 0) {
|
if (locationValues.length === 0) {
|
||||||
locationValues = [
|
locationValues = [
|
||||||
{
|
{
|
||||||
displayName: constants.INVALID_LOCATION_ERROR,
|
displayName: constants.NO_LOCATION_FOUND,
|
||||||
name: ''
|
name: ''
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@@ -920,7 +928,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
console.log(e);
|
console.log(e);
|
||||||
locationValues = [
|
locationValues = [
|
||||||
{
|
{
|
||||||
displayName: constants.INVALID_LOCATION_ERROR,
|
displayName: constants.NO_LOCATION_FOUND,
|
||||||
name: ''
|
name: ''
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@@ -940,7 +948,12 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
public async getAzureResourceGroupDropdownValues(subscription: azureResource.AzureResourceSubscription): Promise<azdata.CategoryValue[]> {
|
public async getAzureResourceGroupDropdownValues(subscription: azureResource.AzureResourceSubscription): Promise<azdata.CategoryValue[]> {
|
||||||
let resourceGroupValues: azdata.CategoryValue[] = [];
|
let resourceGroupValues: azdata.CategoryValue[] = [];
|
||||||
try {
|
try {
|
||||||
|
if (this._azureAccount && subscription) {
|
||||||
this._resourceGroups = await getResourceGroups(this._azureAccount, subscription);
|
this._resourceGroups = await getResourceGroups(this._azureAccount, subscription);
|
||||||
|
} else {
|
||||||
|
this._resourceGroups = [];
|
||||||
|
}
|
||||||
|
|
||||||
this._resourceGroups.forEach((rg) => {
|
this._resourceGroups.forEach((rg) => {
|
||||||
resourceGroupValues.push({
|
resourceGroupValues.push({
|
||||||
name: rg.id,
|
name: rg.id,
|
||||||
@@ -974,16 +987,18 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
|
|
||||||
public async getManagedInstanceValues(subscription: azureResource.AzureResourceSubscription, location: azureResource.AzureLocation, resourceGroup: azureResource.AzureResourceResourceGroup): Promise<azdata.CategoryValue[]> {
|
public async getManagedInstanceValues(subscription: azureResource.AzureResourceSubscription, location: azureResource.AzureLocation, resourceGroup: azureResource.AzureResourceResourceGroup): Promise<azdata.CategoryValue[]> {
|
||||||
let managedInstanceValues: azdata.CategoryValue[] = [];
|
let managedInstanceValues: azdata.CategoryValue[] = [];
|
||||||
if (!this._azureAccount || !subscription) {
|
|
||||||
return managedInstanceValues;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
|
if (this._azureAccount && subscription && location && resourceGroup) {
|
||||||
this._targetManagedInstances = (await getAvailableManagedInstanceProducts(this._azureAccount, subscription)).filter((mi) => {
|
this._targetManagedInstances = (await getAvailableManagedInstanceProducts(this._azureAccount, subscription)).filter((mi) => {
|
||||||
if (mi.location.toLowerCase() === location?.name.toLowerCase() && mi.resourceGroup?.toLowerCase() === resourceGroup?.name.toLowerCase()) {
|
if (mi.location.toLowerCase() === location?.name.toLowerCase() && mi.resourceGroup?.toLowerCase() === resourceGroup?.name.toLowerCase()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
this._targetManagedInstances = [];
|
||||||
|
}
|
||||||
|
|
||||||
this._targetManagedInstances.forEach((managedInstance) => {
|
this._targetManagedInstances.forEach((managedInstance) => {
|
||||||
managedInstanceValues.push({
|
managedInstanceValues.push({
|
||||||
name: managedInstance.id,
|
name: managedInstance.id,
|
||||||
@@ -1024,7 +1039,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
public async getSqlVirtualMachineValues(subscription: azureResource.AzureResourceSubscription, location: azureResource.AzureLocation, resourceGroup: azureResource.AzureResourceResourceGroup): Promise<azdata.CategoryValue[]> {
|
public async getSqlVirtualMachineValues(subscription: azureResource.AzureResourceSubscription, location: azureResource.AzureLocation, resourceGroup: azureResource.AzureResourceResourceGroup): Promise<azdata.CategoryValue[]> {
|
||||||
let virtualMachineValues: azdata.CategoryValue[] = [];
|
let virtualMachineValues: azdata.CategoryValue[] = [];
|
||||||
try {
|
try {
|
||||||
if (this._azureAccount && subscription && resourceGroup) {
|
if (this._azureAccount && subscription && location && resourceGroup) {
|
||||||
this._targetSqlVirtualMachines = (await getAvailableSqlVMs(this._azureAccount, subscription, resourceGroup)).filter((virtualMachine) => {
|
this._targetSqlVirtualMachines = (await getAvailableSqlVMs(this._azureAccount, subscription, resourceGroup)).filter((virtualMachine) => {
|
||||||
if (virtualMachine?.location?.toLowerCase() === location?.name?.toLowerCase()) {
|
if (virtualMachine?.location?.toLowerCase() === location?.name?.toLowerCase()) {
|
||||||
if (virtualMachine.properties.sqlImageOffer) {
|
if (virtualMachine.properties.sqlImageOffer) {
|
||||||
@@ -1074,10 +1089,15 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
return storageAccountValues;
|
return storageAccountValues;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
if (this._azureAccount && subscription && resourceGroup) {
|
||||||
const storageAccount = (await getAvailableStorageAccounts(this._azureAccount, subscription));
|
const storageAccount = (await getAvailableStorageAccounts(this._azureAccount, subscription));
|
||||||
this._storageAccounts = storageAccount.filter(sa => {
|
this._storageAccounts = storageAccount.filter(sa => {
|
||||||
return sa.location.toLowerCase() === this._targetServerInstance.location.toLowerCase() && sa.resourceGroup?.toLowerCase() === resourceGroup.name.toLowerCase();
|
return sa.location.toLowerCase() === this._targetServerInstance.location.toLowerCase() && sa.resourceGroup?.toLowerCase() === resourceGroup.name.toLowerCase();
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
this._storageAccounts = [];
|
||||||
|
}
|
||||||
|
|
||||||
this._storageAccounts.forEach((storageAccount) => {
|
this._storageAccounts.forEach((storageAccount) => {
|
||||||
storageAccountValues.push({
|
storageAccountValues.push({
|
||||||
name: storageAccount.id,
|
name: storageAccount.id,
|
||||||
@@ -1112,7 +1132,12 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
public async getFileShareValues(subscription: azureResource.AzureResourceSubscription, storageAccount: StorageAccount): Promise<azdata.CategoryValue[]> {
|
public async getFileShareValues(subscription: azureResource.AzureResourceSubscription, storageAccount: StorageAccount): Promise<azdata.CategoryValue[]> {
|
||||||
let fileShareValues: azdata.CategoryValue[] = [];
|
let fileShareValues: azdata.CategoryValue[] = [];
|
||||||
try {
|
try {
|
||||||
|
if (this._azureAccount && subscription && storageAccount) {
|
||||||
this._fileShares = await getFileShares(this._azureAccount, subscription, storageAccount);
|
this._fileShares = await getFileShares(this._azureAccount, subscription, storageAccount);
|
||||||
|
} else {
|
||||||
|
this._fileShares = [];
|
||||||
|
}
|
||||||
|
|
||||||
this._fileShares.forEach((fileShare) => {
|
this._fileShares.forEach((fileShare) => {
|
||||||
fileShareValues.push({
|
fileShareValues.push({
|
||||||
name: fileShare.id,
|
name: fileShare.id,
|
||||||
@@ -1146,17 +1171,13 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
|
|
||||||
public async getBlobContainerValues(subscription: azureResource.AzureResourceSubscription, storageAccount: StorageAccount): Promise<azdata.CategoryValue[]> {
|
public async getBlobContainerValues(subscription: azureResource.AzureResourceSubscription, storageAccount: StorageAccount): Promise<azdata.CategoryValue[]> {
|
||||||
let blobContainerValues: azdata.CategoryValue[] = [];
|
let blobContainerValues: azdata.CategoryValue[] = [];
|
||||||
if (!this._azureAccount || !subscription || !storageAccount) {
|
|
||||||
blobContainerValues = [
|
|
||||||
{
|
|
||||||
displayName: constants.NO_BLOBCONTAINERS_FOUND,
|
|
||||||
name: ''
|
|
||||||
}
|
|
||||||
];
|
|
||||||
return blobContainerValues;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
|
if (this._azureAccount && subscription && storageAccount) {
|
||||||
this._blobContainers = await getBlobContainers(this._azureAccount, subscription, storageAccount);
|
this._blobContainers = await getBlobContainers(this._azureAccount, subscription, storageAccount);
|
||||||
|
} else {
|
||||||
|
this._blobContainers = [];
|
||||||
|
}
|
||||||
|
|
||||||
this._blobContainers.forEach((blobContainer) => {
|
this._blobContainers.forEach((blobContainer) => {
|
||||||
blobContainerValues.push({
|
blobContainerValues.push({
|
||||||
name: blobContainer.id,
|
name: blobContainer.id,
|
||||||
@@ -1191,21 +1212,26 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
public async getBlobLastBackupFileNameValues(subscription: azureResource.AzureResourceSubscription, storageAccount: StorageAccount, blobContainer: azureResource.BlobContainer): Promise<azdata.CategoryValue[]> {
|
public async getBlobLastBackupFileNameValues(subscription: azureResource.AzureResourceSubscription, storageAccount: StorageAccount, blobContainer: azureResource.BlobContainer): Promise<azdata.CategoryValue[]> {
|
||||||
let blobLastBackupFileValues: azdata.CategoryValue[] = [];
|
let blobLastBackupFileValues: azdata.CategoryValue[] = [];
|
||||||
try {
|
try {
|
||||||
|
if (this._azureAccount && subscription && storageAccount && blobContainer) {
|
||||||
this._lastFileNames = await getBlobs(this._azureAccount, subscription, storageAccount, blobContainer.name);
|
this._lastFileNames = await getBlobs(this._azureAccount, subscription, storageAccount, blobContainer.name);
|
||||||
if (this._lastFileNames.length === 0) {
|
|
||||||
blobLastBackupFileValues = [
|
|
||||||
{
|
|
||||||
displayName: constants.NO_BLOBFILES_FOUND,
|
|
||||||
name: ''
|
|
||||||
}
|
|
||||||
];
|
|
||||||
} else {
|
} else {
|
||||||
|
this._lastFileNames = [];
|
||||||
|
}
|
||||||
|
|
||||||
this._lastFileNames.forEach((blob) => {
|
this._lastFileNames.forEach((blob) => {
|
||||||
blobLastBackupFileValues.push({
|
blobLastBackupFileValues.push({
|
||||||
name: blob.name,
|
name: blob.name,
|
||||||
displayName: `${blob.name}`,
|
displayName: `${blob.name}`,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (blobLastBackupFileValues.length === 0) {
|
||||||
|
blobLastBackupFileValues = [
|
||||||
|
{
|
||||||
|
displayName: constants.NO_BLOBFILES_FOUND,
|
||||||
|
name: ''
|
||||||
|
}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
@@ -1220,13 +1246,18 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getBlobLastBackupFileName(index: number): string {
|
public getBlobLastBackupFileName(index: number): string {
|
||||||
return this._lastFileNames[index].name;
|
return this._lastFileNames[index]?.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getSqlMigrationServiceValues(subscription: azureResource.AzureResourceSubscription, managedInstance: SqlManagedInstance, resourceGroupName: string): Promise<azdata.CategoryValue[]> {
|
public async getSqlMigrationServiceValues(subscription: azureResource.AzureResourceSubscription, resourceGroupName: string): Promise<azdata.CategoryValue[]> {
|
||||||
let sqlMigrationServiceValues: azdata.CategoryValue[] = [];
|
let sqlMigrationServiceValues: azdata.CategoryValue[] = [];
|
||||||
try {
|
try {
|
||||||
|
if (this._azureAccount && subscription && resourceGroupName && this._targetServerInstance) {
|
||||||
this._sqlMigrationServices = (await getSqlMigrationServices(this._azureAccount, subscription, resourceGroupName?.toLowerCase(), this._sessionId)).filter(sms => sms.location.toLowerCase() === this._targetServerInstance.location.toLowerCase());
|
this._sqlMigrationServices = (await getSqlMigrationServices(this._azureAccount, subscription, resourceGroupName?.toLowerCase(), this._sessionId)).filter(sms => sms.location.toLowerCase() === this._targetServerInstance.location.toLowerCase());
|
||||||
|
} else {
|
||||||
|
this._sqlMigrationServices = [];
|
||||||
|
}
|
||||||
|
|
||||||
this._sqlMigrationServices.forEach((sqlMigrationService) => {
|
this._sqlMigrationServices.forEach((sqlMigrationService) => {
|
||||||
sqlMigrationServiceValues.push({
|
sqlMigrationServiceValues.push({
|
||||||
name: sqlMigrationService.id,
|
name: sqlMigrationService.id,
|
||||||
@@ -1289,7 +1320,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let i = 0; i < this._migrationDbs.length; i++) {
|
for (let i = 0; i < this._databasesForMigration.length; i++) {
|
||||||
try {
|
try {
|
||||||
switch (this._databaseBackup.networkContainerType) {
|
switch (this._databaseBackup.networkContainerType) {
|
||||||
case NetworkContainerType.BLOB_CONTAINER:
|
case NetworkContainerType.BLOB_CONTAINER:
|
||||||
@@ -1327,7 +1358,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
requestBody.properties.sourceDatabaseName = this._migrationDbs[i];
|
requestBody.properties.sourceDatabaseName = this._databasesForMigration[i];
|
||||||
const response = await startDatabaseMigration(
|
const response = await startDatabaseMigration(
|
||||||
this._azureAccount,
|
this._azureAccount,
|
||||||
this._targetSubscription,
|
this._targetSubscription,
|
||||||
@@ -1337,7 +1368,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
requestBody,
|
requestBody,
|
||||||
this._sessionId
|
this._sessionId
|
||||||
);
|
);
|
||||||
response.databaseMigration.properties.sourceDatabaseName = this._migrationDbs[i];
|
response.databaseMigration.properties.sourceDatabaseName = this._databasesForMigration[i];
|
||||||
response.databaseMigration.properties.backupConfiguration = requestBody.properties.backupConfiguration!;
|
response.databaseMigration.properties.backupConfiguration = requestBody.properties.backupConfiguration!;
|
||||||
response.databaseMigration.properties.offlineConfiguration = requestBody.properties.offlineConfiguration!;
|
response.databaseMigration.properties.offlineConfiguration = requestBody.properties.offlineConfiguration!;
|
||||||
|
|
||||||
@@ -1359,7 +1390,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
'location': this._targetServerInstance.location,
|
'location': this._targetServerInstance.location,
|
||||||
'targetType': this._targetType,
|
'targetType': this._targetType,
|
||||||
'hashedServerName': hashString(this._assessmentApiResponse?.assessmentResult?.name),
|
'hashedServerName': hashString(this._assessmentApiResponse?.assessmentResult?.name),
|
||||||
'hashedDatabaseName': hashString(this._migrationDbs[i]),
|
'hashedDatabaseName': hashString(this._databasesForMigration[i]),
|
||||||
'migrationMode': isOfflineMigration ? 'offline' : 'online',
|
'migrationMode': isOfflineMigration ? 'offline' : 'online',
|
||||||
'migrationStartTime': new Date().toString(),
|
'migrationStartTime': new Date().toString(),
|
||||||
'targetDatabaseName': this._targetDatabaseNames[i],
|
'targetDatabaseName': this._targetDatabaseNames[i],
|
||||||
@@ -1382,7 +1413,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
response.asyncUrl,
|
response.asyncUrl,
|
||||||
this._sessionId
|
this._sessionId
|
||||||
);
|
);
|
||||||
void vscode.window.showInformationMessage(localize("sql.migration.starting.migration.message", 'Starting migration for database {0} to {1} - {2}', this._migrationDbs[i], this._targetServerInstance.name, this._targetDatabaseNames[i]));
|
void vscode.window.showInformationMessage(localize("sql.migration.starting.migration.message", 'Starting migration for database {0} to {1} - {2}', this._databasesForMigration[i], this._targetServerInstance.name, this._targetDatabaseNames[i]));
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
void vscode.window.showErrorMessage(
|
void vscode.window.showErrorMessage(
|
||||||
@@ -1404,37 +1435,33 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
let saveInfo: SavedInfo;
|
let saveInfo: SavedInfo;
|
||||||
saveInfo = {
|
saveInfo = {
|
||||||
closedPage: currentPage,
|
closedPage: currentPage,
|
||||||
serverAssessment: null,
|
databaseAssessment: [],
|
||||||
|
databaseList: [],
|
||||||
|
migrationTargetType: null,
|
||||||
azureAccount: null,
|
azureAccount: null,
|
||||||
azureTenant: null,
|
azureTenant: null,
|
||||||
selectedDatabases: [],
|
|
||||||
migrationTargetType: null,
|
|
||||||
migrationDatabases: [],
|
|
||||||
databaseList: [],
|
|
||||||
subscription: null,
|
subscription: null,
|
||||||
location: null,
|
location: null,
|
||||||
resourceGroup: null,
|
resourceGroup: null,
|
||||||
targetServerInstance: null,
|
targetServerInstance: null,
|
||||||
migrationMode: null,
|
migrationMode: null,
|
||||||
databaseAssessment: null,
|
|
||||||
networkContainerType: null,
|
networkContainerType: null,
|
||||||
networkShares: [],
|
networkShares: [],
|
||||||
targetSubscription: null,
|
|
||||||
blobs: [],
|
blobs: [],
|
||||||
targetDatabaseNames: [],
|
targetDatabaseNames: [],
|
||||||
migrationServiceId: null,
|
sqlMigrationService: undefined,
|
||||||
|
serverAssessment: null,
|
||||||
skuRecommendation: null,
|
skuRecommendation: null,
|
||||||
};
|
};
|
||||||
switch (currentPage) {
|
switch (currentPage) {
|
||||||
case Page.Summary:
|
case Page.Summary:
|
||||||
|
|
||||||
case Page.IntegrationRuntime:
|
case Page.IntegrationRuntime:
|
||||||
saveInfo.migrationServiceId = this._sqlMigrationService?.id!;
|
saveInfo.sqlMigrationService = this._sqlMigrationService;
|
||||||
|
|
||||||
case Page.DatabaseBackup:
|
case Page.DatabaseBackup:
|
||||||
saveInfo.networkContainerType = this._databaseBackup.networkContainerType;
|
saveInfo.networkContainerType = this._databaseBackup.networkContainerType;
|
||||||
saveInfo.networkShares = this._databaseBackup.networkShares;
|
saveInfo.networkShares = this._databaseBackup.networkShares;
|
||||||
saveInfo.targetSubscription = this._databaseBackup.subscription;
|
|
||||||
saveInfo.blobs = this._databaseBackup.blobs;
|
saveInfo.blobs = this._databaseBackup.blobs;
|
||||||
saveInfo.targetDatabaseNames = this._targetDatabaseNames;
|
saveInfo.targetDatabaseNames = this._targetDatabaseNames;
|
||||||
|
|
||||||
@@ -1451,10 +1478,8 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
|
|
||||||
case Page.SKURecommendation:
|
case Page.SKURecommendation:
|
||||||
saveInfo.migrationTargetType = this._targetType;
|
saveInfo.migrationTargetType = this._targetType;
|
||||||
saveInfo.databaseAssessment = this._databaseAssessment;
|
saveInfo.databaseList = this._databasesForMigration;
|
||||||
saveInfo.serverAssessment = this._assessmentResults;
|
saveInfo.serverAssessment = this._assessmentResults;
|
||||||
saveInfo.migrationDatabases = this._databaseSelection;
|
|
||||||
saveInfo.databaseList = this._migrationDbs;
|
|
||||||
|
|
||||||
if (this._skuRecommendationPerformanceDataSource) {
|
if (this._skuRecommendationPerformanceDataSource) {
|
||||||
let skuRecommendation: SkuRecommendationSavedInfo = {
|
let skuRecommendation: SkuRecommendationSavedInfo = {
|
||||||
@@ -1470,10 +1495,68 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case Page.DatabaseSelector:
|
case Page.DatabaseSelector:
|
||||||
saveInfo.selectedDatabases = this.databaseSelectorTableValues;
|
saveInfo.databaseAssessment = this._databasesForAssessment;
|
||||||
await this.extensionContext.globalState.update(`${this.mementoString}.${serverName}`, saveInfo);
|
await this.extensionContext.globalState.update(`${this.mementoString}.${serverName}`, saveInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public loadSavedInfo(): Boolean {
|
||||||
|
try {
|
||||||
|
this._targetType = this.savedInfo.migrationTargetType || undefined!;
|
||||||
|
|
||||||
|
this._databasesForAssessment = this.savedInfo.databaseAssessment;
|
||||||
|
this._databasesForMigration = this.savedInfo.databaseList;
|
||||||
|
this._didUpdateDatabasesForMigration = true;
|
||||||
|
switch (this._targetType) {
|
||||||
|
case MigrationTargetType.SQLMI:
|
||||||
|
this._miDbs = this._databasesForMigration;
|
||||||
|
break;
|
||||||
|
case MigrationTargetType.SQLVM:
|
||||||
|
this._vmDbs = this._databasesForMigration;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._azureAccount = this.savedInfo.azureAccount || undefined!;
|
||||||
|
this._azureTenant = this.savedInfo.azureTenant || undefined!;
|
||||||
|
|
||||||
|
this._targetSubscription = this.savedInfo.subscription || undefined!;
|
||||||
|
this._location = this.savedInfo.location || undefined!;
|
||||||
|
this._resourceGroup = this.savedInfo.resourceGroup || undefined!;
|
||||||
|
this._targetServerInstance = this.savedInfo.targetServerInstance || undefined!;
|
||||||
|
|
||||||
|
this._databaseBackup.migrationMode = this.savedInfo.migrationMode || undefined!;
|
||||||
|
|
||||||
|
this.refreshDatabaseBackupPage = true;
|
||||||
|
this._sourceDatabaseNames = this._databasesForMigration;
|
||||||
|
this._targetDatabaseNames = this.savedInfo.targetDatabaseNames;
|
||||||
|
this._databaseBackup.networkContainerType = this.savedInfo.networkContainerType || undefined!;
|
||||||
|
this._databaseBackup.networkShares = this.savedInfo.networkShares;
|
||||||
|
this._databaseBackup.blobs = this.savedInfo.blobs;
|
||||||
|
this._databaseBackup.subscription = this.savedInfo.subscription || undefined!;
|
||||||
|
|
||||||
|
this._sqlMigrationService = this.savedInfo.sqlMigrationService;
|
||||||
|
|
||||||
|
const savedAssessmentResults = this.savedInfo.serverAssessment;
|
||||||
|
if (savedAssessmentResults) {
|
||||||
|
this._assessmentResults = savedAssessmentResults;
|
||||||
|
this._assessedDatabaseList = this.savedInfo.databaseAssessment;
|
||||||
|
}
|
||||||
|
|
||||||
|
const savedSkuRecommendation = this.savedInfo.skuRecommendation;
|
||||||
|
if (savedSkuRecommendation) {
|
||||||
|
this._skuRecommendationPerformanceDataSource = savedSkuRecommendation.skuRecommendationPerformanceDataSource;
|
||||||
|
this._skuRecommendationPerformanceLocation = savedSkuRecommendation.skuRecommendationPerformanceLocation;
|
||||||
|
this._perfDataCollectionStartDate = savedSkuRecommendation.perfDataCollectionStartDate;
|
||||||
|
this._perfDataCollectionStopDate = savedSkuRecommendation.perfDataCollectionStopDate;
|
||||||
|
this._skuTargetPercentile = savedSkuRecommendation.skuTargetPercentile;
|
||||||
|
this._skuScalingFactor = savedSkuRecommendation.skuScalingFactor;
|
||||||
|
this._skuEnablePreview = savedSkuRecommendation.skuEnablePreview;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ServerAssessment {
|
export interface ServerAssessment {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export enum TelemetryViews {
|
|||||||
MigrationCutoverDialog = 'MigrationCutoverDialog',
|
MigrationCutoverDialog = 'MigrationCutoverDialog',
|
||||||
MigrationStatusDialog = 'MigrationStatusDialog',
|
MigrationStatusDialog = 'MigrationStatusDialog',
|
||||||
MigrationWizardAccountSelectionPage = 'MigrationWizardAccountSelectionPage',
|
MigrationWizardAccountSelectionPage = 'MigrationWizardAccountSelectionPage',
|
||||||
|
MigrationWizardTaSkuRecommendationPage = 'MigrationWizardTaSkuRecommendationPage',
|
||||||
MigrationWizardTargetSelectionPage = 'MigrationWizardTargetSelectionPage',
|
MigrationWizardTargetSelectionPage = 'MigrationWizardTargetSelectionPage',
|
||||||
MigrationWizardIntegrationRuntimePage = 'MigrationWizardIntegrationRuntimePage',
|
MigrationWizardIntegrationRuntimePage = 'MigrationWizardIntegrationRuntimePage',
|
||||||
MigrationWizardSummaryPage = 'MigrationWizardSummaryPage',
|
MigrationWizardSummaryPage = 'MigrationWizardSummaryPage',
|
||||||
|
|||||||
@@ -6,15 +6,14 @@
|
|||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { EOL } from 'os';
|
import { EOL } from 'os';
|
||||||
import { getStorageAccountAccessKeys, SqlManagedInstance, SqlVMServer, Subscription } from '../api/azure';
|
import { getStorageAccountAccessKeys } from '../api/azure';
|
||||||
import { MigrationWizardPage } from '../models/migrationWizardPage';
|
import { MigrationWizardPage } from '../models/migrationWizardPage';
|
||||||
import { Blob, MigrationMode, MigrationSourceAuthenticationType, MigrationStateModel, MigrationTargetType, NetworkContainerType, NetworkShare, Page, StateChangeEvent } from '../models/stateMachine';
|
import { Blob, MigrationMode, MigrationSourceAuthenticationType, MigrationStateModel, MigrationTargetType, NetworkContainerType, NetworkShare, StateChangeEvent } from '../models/stateMachine';
|
||||||
import * as constants from '../constants/strings';
|
import * as constants from '../constants/strings';
|
||||||
import { IconPathHelper } from '../constants/iconPathHelper';
|
import { IconPathHelper } from '../constants/iconPathHelper';
|
||||||
import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
|
import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
|
||||||
import { findDropDownItemIndex, selectDropDownIndex } from '../api/utils';
|
import { findDropDownItemIndex, selectDropDownIndex, selectDefaultDropdownValue } from '../api/utils';
|
||||||
import { logError, TelemetryViews } from '../telemtery';
|
import { logError, TelemetryViews } from '../telemtery';
|
||||||
import { azureResource } from 'azureResource';
|
|
||||||
import * as styles from '../constants/styles';
|
import * as styles from '../constants/styles';
|
||||||
|
|
||||||
const WIZARD_TABLE_COLUMN_WIDTH = '200px';
|
const WIZARD_TABLE_COLUMN_WIDTH = '200px';
|
||||||
@@ -128,6 +127,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
.withProps({
|
.withProps({
|
||||||
name: buttonGroup,
|
name: buttonGroup,
|
||||||
label: constants.DATABASE_BACKUP_NC_NETWORK_SHARE_RADIO_LABEL,
|
label: constants.DATABASE_BACKUP_NC_NETWORK_SHARE_RADIO_LABEL,
|
||||||
|
checked: this.migrationStateModel._databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE,
|
||||||
CSSStyles: {
|
CSSStyles: {
|
||||||
...styles.BODY_CSS,
|
...styles.BODY_CSS,
|
||||||
'margin': '0'
|
'margin': '0'
|
||||||
@@ -144,6 +144,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
.withProps({
|
.withProps({
|
||||||
name: buttonGroup,
|
name: buttonGroup,
|
||||||
label: constants.DATABASE_BACKUP_NC_BLOB_STORAGE_RADIO_LABEL,
|
label: constants.DATABASE_BACKUP_NC_BLOB_STORAGE_RADIO_LABEL,
|
||||||
|
checked: this.migrationStateModel._databaseBackup.networkContainerType === NetworkContainerType.BLOB_CONTAINER,
|
||||||
CSSStyles: {
|
CSSStyles: {
|
||||||
...styles.BODY_CSS,
|
...styles.BODY_CSS,
|
||||||
'margin': '0'
|
'margin': '0'
|
||||||
@@ -298,9 +299,6 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}).component();
|
}).component();
|
||||||
if (this.migrationStateModel.retryMigration || (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.DatabaseBackup)) {
|
|
||||||
this._windowsUserAccountText.value = this.migrationStateModel.savedInfo.networkShares[0].windowsUser;
|
|
||||||
}
|
|
||||||
this._disposables.push(this._windowsUserAccountText.onTextChanged((value) => {
|
this._disposables.push(this._windowsUserAccountText.onTextChanged((value) => {
|
||||||
for (let i = 0; i < this.migrationStateModel._databaseBackup.networkShares.length; i++) {
|
for (let i = 0; i < this.migrationStateModel._databaseBackup.networkShares.length; i++) {
|
||||||
this.migrationStateModel._databaseBackup.networkShares[i].windowsUser = value;
|
this.migrationStateModel._databaseBackup.networkShares[i].windowsUser = value;
|
||||||
@@ -545,7 +543,11 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
this._networkTableContainer = this._view.modelBuilder.flexContainer().withItems([
|
this._networkTableContainer = this._view.modelBuilder.flexContainer().withItems([
|
||||||
networkShareTableText,
|
networkShareTableText,
|
||||||
this._networkShareTargetDatabaseNamesTable
|
this._networkShareTargetDatabaseNamesTable
|
||||||
]).component();
|
]).withProps({
|
||||||
|
CSSStyles: {
|
||||||
|
'display': 'none',
|
||||||
|
}
|
||||||
|
}).component();
|
||||||
|
|
||||||
const allFieldsRequiredLabel = this._view.modelBuilder.text()
|
const allFieldsRequiredLabel = this._view.modelBuilder.text()
|
||||||
.withProps({
|
.withProps({
|
||||||
@@ -559,7 +561,11 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
blobTableText,
|
blobTableText,
|
||||||
allFieldsRequiredLabel,
|
allFieldsRequiredLabel,
|
||||||
this._blobContainerTargetDatabaseNamesTable
|
this._blobContainerTargetDatabaseNamesTable
|
||||||
]).component();
|
]).withProps({
|
||||||
|
CSSStyles: {
|
||||||
|
'display': 'none',
|
||||||
|
}
|
||||||
|
}).component();
|
||||||
|
|
||||||
const container = this._view.modelBuilder.flexContainer().withLayout({
|
const container = this._view.modelBuilder.flexContainer().withLayout({
|
||||||
flexFlow: 'column'
|
flexFlow: 'column'
|
||||||
@@ -567,7 +573,9 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
this._networkTableContainer,
|
this._networkTableContainer,
|
||||||
this._blobTableContainer
|
this._blobTableContainer
|
||||||
]).withProps({
|
]).withProps({
|
||||||
display: 'none'
|
CSSStyles: {
|
||||||
|
'display': 'none',
|
||||||
|
}
|
||||||
}).component();
|
}).component();
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
@@ -736,18 +744,8 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async onPageEnter(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
|
public async onPageEnter(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
|
||||||
if (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.DatabaseBackup) {
|
|
||||||
this.migrationStateModel._databaseBackup.networkContainerType = <NetworkContainerType>this.migrationStateModel.savedInfo.networkContainerType;
|
|
||||||
this.migrationStateModel._databaseBackup.networkShares = this.migrationStateModel.savedInfo.networkShares;
|
|
||||||
this.migrationStateModel._databaseBackup.subscription = <Subscription>this.migrationStateModel.savedInfo.targetSubscription;
|
|
||||||
this.migrationStateModel._databaseBackup.blobs = this.migrationStateModel.savedInfo.blobs;
|
|
||||||
this.migrationStateModel._targetDatabaseNames = this.migrationStateModel.savedInfo.targetDatabaseNames;
|
|
||||||
}
|
|
||||||
if (this.migrationStateModel.refreshDatabaseBackupPage) {
|
if (this.migrationStateModel.refreshDatabaseBackupPage) {
|
||||||
try {
|
try {
|
||||||
if (this.migrationStateModel.retryMigration || (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.DatabaseBackup)) {
|
|
||||||
this.migrationStateModel._migrationDbs = this.migrationStateModel.savedInfo.databaseList;
|
|
||||||
}
|
|
||||||
const isOfflineMigration = this.migrationStateModel._databaseBackup?.migrationMode === MigrationMode.OFFLINE;
|
const isOfflineMigration = this.migrationStateModel._databaseBackup?.migrationMode === MigrationMode.OFFLINE;
|
||||||
const lastBackupFileColumnIndex = this._blobContainerTargetDatabaseNamesTable.columns.length - 1;
|
const lastBackupFileColumnIndex = this._blobContainerTargetDatabaseNamesTable.columns.length - 1;
|
||||||
this._blobContainerTargetDatabaseNamesTable.columns[lastBackupFileColumnIndex].hidden = !isOfflineMigration;
|
this._blobContainerTargetDatabaseNamesTable.columns[lastBackupFileColumnIndex].hidden = !isOfflineMigration;
|
||||||
@@ -755,30 +753,8 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
column.width = isOfflineMigration ? WIZARD_TABLE_COLUMN_WIDTH_SMALL : WIZARD_TABLE_COLUMN_WIDTH;
|
column.width = isOfflineMigration ? WIZARD_TABLE_COLUMN_WIDTH_SMALL : WIZARD_TABLE_COLUMN_WIDTH;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.migrationStateModel.retryMigration || (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.DatabaseBackup)) {
|
await this.switchNetworkContainerFields(this.migrationStateModel._databaseBackup.networkContainerType);
|
||||||
if (this.migrationStateModel.savedInfo.networkContainerType === NetworkContainerType.NETWORK_SHARE) {
|
|
||||||
this._networkShareButton.checked = true;
|
|
||||||
} else {
|
|
||||||
this._networkShareButton.checked = false;
|
|
||||||
this._networkTableContainer.display = 'none';
|
|
||||||
await this._networkShareContainer.updateCssStyles({ 'display': 'none' });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.migrationStateModel.retryMigration || (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.DatabaseBackup)) {
|
|
||||||
if (this.migrationStateModel.savedInfo.networkContainerType === NetworkContainerType.BLOB_CONTAINER) {
|
|
||||||
this._blobContainerButton.checked = true;
|
|
||||||
} else {
|
|
||||||
this._blobContainerButton.checked = false;
|
|
||||||
this._blobTableContainer.display = 'none';
|
|
||||||
await this._blobContainer.updateCssStyles({ 'display': 'none' });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.DatabaseBackup)) {
|
|
||||||
await this._targetDatabaseContainer.updateCssStyles({ 'display': 'none' });
|
|
||||||
await this._networkShareStorageAccountDetails.updateCssStyles({ 'display': 'none' });
|
|
||||||
}
|
|
||||||
const connectionProfile = await this.migrationStateModel.getSourceConnectionProfile();
|
const connectionProfile = await this.migrationStateModel.getSourceConnectionProfile();
|
||||||
const queryProvider = azdata.dataprotocol.getProvider<azdata.QueryProvider>((await this.migrationStateModel.getSourceConnectionProfile()).providerId, azdata.DataProviderType.QueryProvider);
|
const queryProvider = azdata.dataprotocol.getProvider<azdata.QueryProvider>((await this.migrationStateModel.getSourceConnectionProfile()).providerId, azdata.DataProviderType.QueryProvider);
|
||||||
const query = 'select SUSER_NAME()';
|
const query = 'select SUSER_NAME()';
|
||||||
@@ -788,6 +764,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
this._sourceHelpText.value = constants.SQL_SOURCE_DETAILS(this.migrationStateModel._authenticationType, connectionProfile.serverName);
|
this._sourceHelpText.value = constants.SQL_SOURCE_DETAILS(this.migrationStateModel._authenticationType, connectionProfile.serverName);
|
||||||
this._sqlSourceUsernameInput.value = username;
|
this._sqlSourceUsernameInput.value = username;
|
||||||
this._sqlSourcePassword.value = (await azdata.connection.getCredentials(this.migrationStateModel.sourceConnectionId)).password;
|
this._sqlSourcePassword.value = (await azdata.connection.getCredentials(this.migrationStateModel.sourceConnectionId)).password;
|
||||||
|
this._windowsUserAccountText.value = this.migrationStateModel.savedInfo?.networkShares[0]?.windowsUser;
|
||||||
|
|
||||||
this._networkShareTargetDatabaseNames = [];
|
this._networkShareTargetDatabaseNames = [];
|
||||||
this._networkShareLocations = [];
|
this._networkShareLocations = [];
|
||||||
@@ -800,16 +777,45 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
if (this.migrationStateModel._targetType === MigrationTargetType.SQLMI) {
|
if (this.migrationStateModel._targetType === MigrationTargetType.SQLMI) {
|
||||||
this._existingDatabases = await this.migrationStateModel.getManagedDatabases();
|
this._existingDatabases = await this.migrationStateModel.getManagedDatabases();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let originalTargetDatabaseNames = this.migrationStateModel._targetDatabaseNames;
|
||||||
|
let originalNetworkShares = this.migrationStateModel._databaseBackup.networkShares;
|
||||||
|
let originalBlobs = this.migrationStateModel._databaseBackup.blobs;
|
||||||
|
if (this.migrationStateModel._didUpdateDatabasesForMigration) {
|
||||||
this.migrationStateModel._targetDatabaseNames = [];
|
this.migrationStateModel._targetDatabaseNames = [];
|
||||||
this.migrationStateModel._databaseBackup.blobs = [];
|
|
||||||
this.migrationStateModel._databaseBackup.networkShares = [];
|
this.migrationStateModel._databaseBackup.networkShares = [];
|
||||||
this.migrationStateModel._migrationDbs.forEach((db, index) => {
|
this.migrationStateModel._databaseBackup.blobs = [];
|
||||||
this.migrationStateModel._targetDatabaseNames.push(db);
|
}
|
||||||
this.migrationStateModel._databaseBackup.blobs.push(<Blob>{});
|
|
||||||
this.migrationStateModel._databaseBackup.networkShares.push(<NetworkShare>{});
|
this.migrationStateModel._databasesForMigration.forEach((db, index) => {
|
||||||
|
let targetDatabaseName = db;
|
||||||
|
let networkShare = <NetworkShare>{};
|
||||||
|
let blob = <Blob>{};
|
||||||
|
|
||||||
|
if (this.migrationStateModel._didUpdateDatabasesForMigration) {
|
||||||
|
const dbIndex = this.migrationStateModel._sourceDatabaseNames?.indexOf(db);
|
||||||
|
if (dbIndex > -1) {
|
||||||
|
targetDatabaseName = originalTargetDatabaseNames[dbIndex] ?? targetDatabaseName;
|
||||||
|
networkShare = originalNetworkShares[dbIndex] ?? networkShare;
|
||||||
|
blob = originalBlobs[dbIndex] ?? blob;
|
||||||
|
} else {
|
||||||
|
// network share values are uniform for all dbs in the same migration, except for networkShareLocation
|
||||||
|
const previouslySelectedNetworkShare = originalNetworkShares[0];
|
||||||
|
if (previouslySelectedNetworkShare) {
|
||||||
|
networkShare = {
|
||||||
|
...previouslySelectedNetworkShare,
|
||||||
|
networkShareLocation: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.migrationStateModel._targetDatabaseNames[index] = targetDatabaseName;
|
||||||
|
this.migrationStateModel._databaseBackup.networkShares[index] = networkShare;
|
||||||
|
this.migrationStateModel._databaseBackup.blobs[index] = blob;
|
||||||
|
|
||||||
const targetDatabaseInput = this._view.modelBuilder.inputBox().withProps({
|
const targetDatabaseInput = this._view.modelBuilder.inputBox().withProps({
|
||||||
required: true,
|
required: true,
|
||||||
value: db,
|
value: targetDatabaseName,
|
||||||
width: WIZARD_TABLE_COLUMN_WIDTH
|
width: WIZARD_TABLE_COLUMN_WIDTH
|
||||||
}).withValidation(c => {
|
}).withValidation(c => {
|
||||||
if (this._networkShareTargetDatabaseNames.filter(t => t.value === c.value).length > 1) { //Making sure no databases have duplicate values.
|
if (this._networkShareTargetDatabaseNames.filter(t => t.value === c.value).length > 1) { //Making sure no databases have duplicate values.
|
||||||
@@ -830,11 +836,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
this.migrationStateModel._targetDatabaseNames[index] = value.trim();
|
this.migrationStateModel._targetDatabaseNames[index] = value.trim();
|
||||||
await this.validateFields();
|
await this.validateFields();
|
||||||
}));
|
}));
|
||||||
if (this.migrationStateModel.retryMigration || (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.DatabaseBackup)) {
|
|
||||||
targetDatabaseInput.value = this.migrationStateModel.savedInfo.targetDatabaseNames[index];
|
|
||||||
} else {
|
|
||||||
targetDatabaseInput.value = this.migrationStateModel._targetDatabaseNames[index];
|
targetDatabaseInput.value = this.migrationStateModel._targetDatabaseNames[index];
|
||||||
}
|
|
||||||
this._networkShareTargetDatabaseNames.push(targetDatabaseInput);
|
this._networkShareTargetDatabaseNames.push(targetDatabaseInput);
|
||||||
|
|
||||||
const networkShareLocationInput = this._view.modelBuilder.inputBox().withProps({
|
const networkShareLocationInput = this._view.modelBuilder.inputBox().withProps({
|
||||||
@@ -856,16 +858,12 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
this.migrationStateModel._databaseBackup.networkShares[index].networkShareLocation = value.trim();
|
this.migrationStateModel._databaseBackup.networkShares[index].networkShareLocation = value.trim();
|
||||||
await this.validateFields();
|
await this.validateFields();
|
||||||
}));
|
}));
|
||||||
if (this.migrationStateModel.retryMigration || (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.DatabaseBackup)) {
|
|
||||||
networkShareLocationInput.value = this.migrationStateModel.savedInfo.networkShares[index].networkShareLocation;
|
|
||||||
} else {
|
|
||||||
networkShareLocationInput.value = this.migrationStateModel._databaseBackup.networkShares[index]?.networkShareLocation;
|
networkShareLocationInput.value = this.migrationStateModel._databaseBackup.networkShares[index]?.networkShareLocation;
|
||||||
}
|
|
||||||
this._networkShareLocations.push(networkShareLocationInput);
|
this._networkShareLocations.push(networkShareLocationInput);
|
||||||
|
|
||||||
const blobTargetDatabaseInput = this._view.modelBuilder.inputBox().withProps({
|
const blobTargetDatabaseInput = this._view.modelBuilder.inputBox().withProps({
|
||||||
required: true,
|
required: true,
|
||||||
value: db,
|
value: targetDatabaseName,
|
||||||
}).withValidation(c => {
|
}).withValidation(c => {
|
||||||
if (this._blobContainerTargetDatabaseNames.filter(t => t.value === c.value).length > 1) { //Making sure no databases have duplicate values.
|
if (this._blobContainerTargetDatabaseNames.filter(t => t.value === c.value).length > 1) { //Making sure no databases have duplicate values.
|
||||||
c.validationErrorMessage = constants.DUPLICATE_NAME_ERROR;
|
c.validationErrorMessage = constants.DUPLICATE_NAME_ERROR;
|
||||||
@@ -884,11 +882,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
this._disposables.push(blobTargetDatabaseInput.onTextChanged((value) => {
|
this._disposables.push(blobTargetDatabaseInput.onTextChanged((value) => {
|
||||||
this.migrationStateModel._targetDatabaseNames[index] = value.trim();
|
this.migrationStateModel._targetDatabaseNames[index] = value.trim();
|
||||||
}));
|
}));
|
||||||
if (this.migrationStateModel.retryMigration || (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.DatabaseBackup)) {
|
|
||||||
blobTargetDatabaseInput.value = this.migrationStateModel.savedInfo.targetDatabaseNames[index];
|
|
||||||
} else {
|
|
||||||
targetDatabaseInput.value = this.migrationStateModel._targetDatabaseNames[index];
|
targetDatabaseInput.value = this.migrationStateModel._targetDatabaseNames[index];
|
||||||
}
|
|
||||||
this._blobContainerTargetDatabaseNames.push(blobTargetDatabaseInput);
|
this._blobContainerTargetDatabaseNames.push(blobTargetDatabaseInput);
|
||||||
|
|
||||||
const blobContainerResourceDropdown = this._view.modelBuilder.dropDown().withProps({
|
const blobContainerResourceDropdown = this._view.modelBuilder.dropDown().withProps({
|
||||||
@@ -970,10 +964,11 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
this._blobContainerLastBackupFileDropdowns.push(blobContainerLastBackupFileDropdown);
|
this._blobContainerLastBackupFileDropdowns.push(blobContainerLastBackupFileDropdown);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.migrationStateModel._sourceDatabaseNames = this.migrationStateModel._databasesForMigration;
|
||||||
|
|
||||||
|
|
||||||
let data: azdata.DeclarativeTableCellValue[][] = [];
|
let data: azdata.DeclarativeTableCellValue[][] = [];
|
||||||
this.migrationStateModel._migrationDbs.forEach((db, index) => {
|
this.migrationStateModel._databasesForMigration.forEach((db, index) => {
|
||||||
const targetRow: azdata.DeclarativeTableCellValue[] = [];
|
const targetRow: azdata.DeclarativeTableCellValue[] = [];
|
||||||
targetRow.push({
|
targetRow.push({
|
||||||
value: db
|
value: db
|
||||||
@@ -989,7 +984,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
await this._networkShareTargetDatabaseNamesTable.setDataValues(data);
|
await this._networkShareTargetDatabaseNamesTable.setDataValues(data);
|
||||||
|
|
||||||
data = [];
|
data = [];
|
||||||
this.migrationStateModel._migrationDbs.forEach((db, index) => {
|
this.migrationStateModel._databasesForMigration.forEach((db, index) => {
|
||||||
const targetRow: azdata.DeclarativeTableCellValue[] = [];
|
const targetRow: azdata.DeclarativeTableCellValue[] = [];
|
||||||
targetRow.push({
|
targetRow.push({
|
||||||
value: db
|
value: db
|
||||||
@@ -1037,7 +1032,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
const errors: string[] = [];
|
const errors: string[] = [];
|
||||||
|
|
||||||
switch (this.migrationStateModel._databaseBackup.networkContainerType) {
|
switch (this.migrationStateModel._databaseBackup.networkContainerType) {
|
||||||
case NetworkContainerType.NETWORK_SHARE:
|
case NetworkContainerType.NETWORK_SHARE: {
|
||||||
if ((<azdata.CategoryValue>this._networkShareStorageAccountResourceGroupDropdown.value)?.displayName === constants.RESOURCE_GROUP_NOT_FOUND) {
|
if ((<azdata.CategoryValue>this._networkShareStorageAccountResourceGroupDropdown.value)?.displayName === constants.RESOURCE_GROUP_NOT_FOUND) {
|
||||||
errors.push(constants.INVALID_RESOURCE_GROUP_ERROR);
|
errors.push(constants.INVALID_RESOURCE_GROUP_ERROR);
|
||||||
}
|
}
|
||||||
@@ -1045,27 +1040,29 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
errors.push(constants.INVALID_STORAGE_ACCOUNT_ERROR);
|
errors.push(constants.INVALID_STORAGE_ACCOUNT_ERROR);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NetworkContainerType.BLOB_CONTAINER:
|
}
|
||||||
|
|
||||||
|
case NetworkContainerType.BLOB_CONTAINER: {
|
||||||
this._blobContainerResourceGroupDropdowns.forEach((v, index) => {
|
this._blobContainerResourceGroupDropdowns.forEach((v, index) => {
|
||||||
if (this.shouldDisplayBlobDropdownError(v, [constants.RESOURCE_GROUP_NOT_FOUND])) {
|
if (this.shouldDisplayBlobDropdownError(v, [constants.RESOURCE_GROUP_NOT_FOUND])) {
|
||||||
errors.push(constants.INVALID_BLOB_RESOURCE_GROUP_ERROR(this.migrationStateModel._migrationDbs[index]));
|
errors.push(constants.INVALID_BLOB_RESOURCE_GROUP_ERROR(this.migrationStateModel._databasesForMigration[index]));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this._blobContainerStorageAccountDropdowns.forEach((v, index) => {
|
this._blobContainerStorageAccountDropdowns.forEach((v, index) => {
|
||||||
if (this.shouldDisplayBlobDropdownError(v, [constants.NO_STORAGE_ACCOUNT_FOUND, constants.SELECT_RESOURCE_GROUP_PROMPT])) {
|
if (this.shouldDisplayBlobDropdownError(v, [constants.NO_STORAGE_ACCOUNT_FOUND, constants.SELECT_RESOURCE_GROUP_PROMPT])) {
|
||||||
errors.push(constants.INVALID_BLOB_STORAGE_ACCOUNT_ERROR(this.migrationStateModel._migrationDbs[index]));
|
errors.push(constants.INVALID_BLOB_STORAGE_ACCOUNT_ERROR(this.migrationStateModel._databasesForMigration[index]));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this._blobContainerDropdowns.forEach((v, index) => {
|
this._blobContainerDropdowns.forEach((v, index) => {
|
||||||
if (this.shouldDisplayBlobDropdownError(v, [constants.NO_BLOBCONTAINERS_FOUND, constants.SELECT_STORAGE_ACCOUNT])) {
|
if (this.shouldDisplayBlobDropdownError(v, [constants.NO_BLOBCONTAINERS_FOUND, constants.SELECT_STORAGE_ACCOUNT])) {
|
||||||
errors.push(constants.INVALID_BLOB_CONTAINER_ERROR(this.migrationStateModel._migrationDbs[index]));
|
errors.push(constants.INVALID_BLOB_CONTAINER_ERROR(this.migrationStateModel._databasesForMigration[index]));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.migrationStateModel._databaseBackup.migrationMode === MigrationMode.OFFLINE) {
|
if (this.migrationStateModel._databaseBackup.migrationMode === MigrationMode.OFFLINE) {
|
||||||
this._blobContainerLastBackupFileDropdowns.forEach((v, index) => {
|
this._blobContainerLastBackupFileDropdowns.forEach((v, index) => {
|
||||||
if (this.shouldDisplayBlobDropdownError(v, [constants.NO_BLOBFILES_FOUND, constants.SELECT_BLOB_CONTAINER])) {
|
if (this.shouldDisplayBlobDropdownError(v, [constants.NO_BLOBFILES_FOUND, constants.SELECT_BLOB_CONTAINER])) {
|
||||||
errors.push(constants.INVALID_BLOB_LAST_BACKUP_FILE_ERROR(this.migrationStateModel._migrationDbs[index]));
|
errors.push(constants.INVALID_BLOB_LAST_BACKUP_FILE_ERROR(this.migrationStateModel._databasesForMigration[index]));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1082,15 +1079,18 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
}
|
}
|
||||||
duplicates.forEach((d) => {
|
duplicates.forEach((d) => {
|
||||||
if (d.length > 1) {
|
if (d.length > 1) {
|
||||||
const dupString = `${d.map(index => this.migrationStateModel._migrationDbs[index]).join(', ')}`;
|
const dupString = `${d.map(index => this.migrationStateModel._databasesForMigration[index]).join(', ')}`;
|
||||||
errors.push(constants.PROVIDE_UNIQUE_CONTAINERS + dupString);
|
errors.push(constants.PROVIDE_UNIQUE_CONTAINERS + dupString);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
this.migrationStateModel._targetDatabaseNames.forEach(t => {
|
this.migrationStateModel._targetDatabaseNames.forEach(t => {
|
||||||
if (this.migrationStateModel._targetType === MigrationTargetType.SQLMI && this._existingDatabases.includes(t)) { // Making sure if database with same name is not present on the target Azure SQL
|
if (this.migrationStateModel._targetType === MigrationTargetType.SQLMI && this._existingDatabases.includes(t)) { // Making sure if database with same name is not present on the target Azure SQL
|
||||||
errors.push(constants.DATABASE_ALREADY_EXISTS_MI(t, this.migrationStateModel._targetServerInstance.name));
|
errors.push(constants.DATABASE_ALREADY_EXISTS_MI(t, this.migrationStateModel._targetServerInstance.name));
|
||||||
@@ -1123,7 +1123,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
break;
|
break;
|
||||||
case NetworkContainerType.NETWORK_SHARE:
|
case NetworkContainerType.NETWORK_SHARE:
|
||||||
// All network share migrations use the same storage account
|
// All network share migrations use the same storage account
|
||||||
const storageAccount = this.migrationStateModel._databaseBackup.networkShares[0].storageAccount;
|
const storageAccount = this.migrationStateModel._databaseBackup.networkShares[0]?.storageAccount;
|
||||||
const storageKey = (await getStorageAccountAccessKeys(
|
const storageKey = (await getStorageAccountAccessKeys(
|
||||||
this.migrationStateModel._azureAccount,
|
this.migrationStateModel._azureAccount,
|
||||||
this.migrationStateModel._databaseBackup.subscription,
|
this.migrationStateModel._databaseBackup.subscription,
|
||||||
@@ -1152,16 +1152,29 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
|
|
||||||
this.wizard.nextButton.enabled = true;
|
this.wizard.nextButton.enabled = true;
|
||||||
this.migrationStateModel._databaseBackup.networkContainerType = containerType;
|
this.migrationStateModel._databaseBackup.networkContainerType = containerType;
|
||||||
await this._blobContainer.updateCssStyles({ 'display': (containerType === NetworkContainerType.BLOB_CONTAINER) ? 'inline' : 'none' });
|
|
||||||
await this._networkShareContainer.updateCssStyles({ 'display': (containerType === NetworkContainerType.NETWORK_SHARE) ? 'inline' : 'none' });
|
|
||||||
await this._networkShareStorageAccountDetails.updateCssStyles({ 'display': (containerType === NetworkContainerType.NETWORK_SHARE) ? 'inline' : 'none' });
|
|
||||||
await this._targetDatabaseContainer.updateCssStyles({ 'display': 'inline' });
|
await this._targetDatabaseContainer.updateCssStyles({ 'display': 'inline' });
|
||||||
this._networkTableContainer.display = (containerType === NetworkContainerType.NETWORK_SHARE) ? 'inline' : 'none';
|
|
||||||
this._blobTableContainer.display = (containerType === NetworkContainerType.BLOB_CONTAINER) ? 'inline' : 'none';
|
|
||||||
|
|
||||||
//Preserving the database Names between the 2 tables.
|
switch (containerType) {
|
||||||
if (this.migrationStateModel.retryMigration || (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.DatabaseBackup)) {
|
case NetworkContainerType.NETWORK_SHARE: {
|
||||||
this.migrationStateModel._targetDatabaseNames = this.migrationStateModel.savedInfo.targetDatabaseNames;
|
await this._networkShareContainer.updateCssStyles({ 'display': 'inline' });
|
||||||
|
await this._networkShareStorageAccountDetails.updateCssStyles({ 'display': 'inline' });
|
||||||
|
await this._networkTableContainer.updateCssStyles({ 'display': 'inline' });
|
||||||
|
|
||||||
|
await this._blobContainer.updateCssStyles({ 'display': 'none' });
|
||||||
|
await this._blobTableContainer.updateCssStyles({ 'display': 'none' });
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NetworkContainerType.BLOB_CONTAINER: {
|
||||||
|
await this._networkShareContainer.updateCssStyles({ 'display': 'none' });
|
||||||
|
await this._networkShareStorageAccountDetails.updateCssStyles({ 'display': 'none' });
|
||||||
|
await this._networkTableContainer.updateCssStyles({ 'display': 'none' });
|
||||||
|
|
||||||
|
await this._blobContainer.updateCssStyles({ 'display': 'inline' });
|
||||||
|
await this._blobTableContainer.updateCssStyles({ 'display': 'inline' });
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await this._windowsUserAccountText.updateProperties({
|
await this._windowsUserAccountText.updateProperties({
|
||||||
@@ -1203,11 +1216,6 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async getSubscriptionValues(): Promise<void> {
|
private async getSubscriptionValues(): Promise<void> {
|
||||||
if (this.migrationStateModel.retryMigration || (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.DatabaseBackup)) {
|
|
||||||
this.migrationStateModel._targetSubscription = <azureResource.AzureResourceSubscription>this.migrationStateModel.savedInfo.targetSubscription;
|
|
||||||
this.migrationStateModel._targetServerInstance = <SqlManagedInstance | SqlVMServer>this.migrationStateModel.savedInfo.targetServerInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._networkShareContainerSubscription.value = this.migrationStateModel._targetSubscription.name;
|
this._networkShareContainerSubscription.value = this.migrationStateModel._targetSubscription.name;
|
||||||
this._networkShareContainerLocation.value = await this.migrationStateModel.getLocationDisplayName(this.migrationStateModel._targetServerInstance.location);
|
this._networkShareContainerLocation.value = await this.migrationStateModel.getLocationDisplayName(this.migrationStateModel._targetServerInstance.location);
|
||||||
|
|
||||||
@@ -1224,15 +1232,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
this._networkShareStorageAccountResourceGroupDropdown.loading = true;
|
this._networkShareStorageAccountResourceGroupDropdown.loading = true;
|
||||||
try {
|
try {
|
||||||
this._networkShareStorageAccountResourceGroupDropdown.values = await this.migrationStateModel.getAzureResourceGroupDropdownValues(this.migrationStateModel._databaseBackup.subscription);
|
this._networkShareStorageAccountResourceGroupDropdown.values = await this.migrationStateModel.getAzureResourceGroupDropdownValues(this.migrationStateModel._databaseBackup.subscription);
|
||||||
if (this.hasSavedInfo(NetworkContainerType.NETWORK_SHARE, this._networkShareStorageAccountResourceGroupDropdown.values)) {
|
selectDefaultDropdownValue(this._networkShareStorageAccountResourceGroupDropdown, this.migrationStateModel._databaseBackup?.networkShares[0]?.resourceGroup?.id, false);
|
||||||
this._networkShareStorageAccountResourceGroupDropdown.values.forEach((resource, index) => {
|
|
||||||
if ((<azdata.CategoryValue>resource).name.toLowerCase() === this.migrationStateModel.savedInfo?.networkShares[0].resourceGroup?.id?.toLowerCase()) {
|
|
||||||
selectDropDownIndex(this._networkShareStorageAccountResourceGroupDropdown, index);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
selectDropDownIndex(this._networkShareStorageAccountResourceGroupDropdown, 0);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logError(TelemetryViews.DatabaseBackupPage, 'ErrorLoadingNetworkStorageResourceGroup', error);
|
logError(TelemetryViews.DatabaseBackupPage, 'ErrorLoadingNetworkStorageResourceGroup', error);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1243,13 +1243,15 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
|
|
||||||
private async loadNetworkShareStorageDropdown(): Promise<void> {
|
private async loadNetworkShareStorageDropdown(): Promise<void> {
|
||||||
this._networkShareContainerStorageAccountDropdown.loading = true;
|
this._networkShareContainerStorageAccountDropdown.loading = true;
|
||||||
|
this._networkShareStorageAccountResourceGroupDropdown.loading = true;
|
||||||
try {
|
try {
|
||||||
this._networkShareContainerStorageAccountDropdown.values = await this.migrationStateModel.getStorageAccountValues(this.migrationStateModel._databaseBackup.subscription, this.migrationStateModel._databaseBackup.networkShares[0].resourceGroup);
|
this._networkShareContainerStorageAccountDropdown.values = await this.migrationStateModel.getStorageAccountValues(this.migrationStateModel._databaseBackup.subscription, this.migrationStateModel._databaseBackup.networkShares[0]?.resourceGroup);
|
||||||
selectDropDownIndex(this._networkShareContainerStorageAccountDropdown, 0);
|
selectDefaultDropdownValue(this._networkShareContainerStorageAccountDropdown, this.migrationStateModel?._databaseBackup?.networkShares[0]?.storageAccount?.id, false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logError(TelemetryViews.DatabaseBackupPage, 'ErrorLoadingNetworkShareStorageDropdown', error);
|
logError(TelemetryViews.DatabaseBackupPage, 'ErrorLoadingNetworkShareStorageDropdown', error);
|
||||||
} finally {
|
} finally {
|
||||||
this._networkShareContainerStorageAccountDropdown.loading = false;
|
this._networkShareContainerStorageAccountDropdown.loading = false;
|
||||||
|
this._networkShareStorageAccountResourceGroupDropdown.loading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1259,15 +1261,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
const resourceGroupValues = await this.migrationStateModel.getAzureResourceGroupDropdownValues(this.migrationStateModel._databaseBackup.subscription);
|
const resourceGroupValues = await this.migrationStateModel.getAzureResourceGroupDropdownValues(this.migrationStateModel._databaseBackup.subscription);
|
||||||
this._blobContainerResourceGroupDropdowns.forEach((dropDown, index) => {
|
this._blobContainerResourceGroupDropdowns.forEach((dropDown, index) => {
|
||||||
dropDown.values = resourceGroupValues;
|
dropDown.values = resourceGroupValues;
|
||||||
if (this.hasSavedInfo(NetworkContainerType.BLOB_CONTAINER, dropDown.values)) {
|
selectDefaultDropdownValue(dropDown, this.migrationStateModel._databaseBackup?.blobs[index]?.resourceGroup?.id, false);
|
||||||
dropDown.values.forEach((resource, resourceIndex) => {
|
|
||||||
if ((<azdata.CategoryValue>resource).name.toLowerCase() === this.migrationStateModel.savedInfo?.blobs[index]?.resourceGroup?.id?.toLowerCase()) {
|
|
||||||
selectDropDownIndex(dropDown, resourceIndex);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
selectDropDownIndex(dropDown, 0);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logError(TelemetryViews.DatabaseBackupPage, 'ErrorLoadingBlobResourceGroup', error);
|
logError(TelemetryViews.DatabaseBackupPage, 'ErrorLoadingBlobResourceGroup', error);
|
||||||
@@ -1280,15 +1274,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
this._blobContainerStorageAccountDropdowns[index].loading = true;
|
this._blobContainerStorageAccountDropdowns[index].loading = true;
|
||||||
try {
|
try {
|
||||||
this._blobContainerStorageAccountDropdowns[index].values = await this.migrationStateModel.getStorageAccountValues(this.migrationStateModel._databaseBackup.subscription, this.migrationStateModel._databaseBackup.blobs[index]?.resourceGroup);
|
this._blobContainerStorageAccountDropdowns[index].values = await this.migrationStateModel.getStorageAccountValues(this.migrationStateModel._databaseBackup.subscription, this.migrationStateModel._databaseBackup.blobs[index]?.resourceGroup);
|
||||||
if (this.hasSavedInfo(NetworkContainerType.BLOB_CONTAINER, this._blobContainerStorageAccountDropdowns[index].values && this.migrationStateModel.savedInfo.blobs[index]?.storageAccount)) {
|
selectDefaultDropdownValue(this._blobContainerStorageAccountDropdowns[index], this.migrationStateModel._databaseBackup?.blobs[index]?.storageAccount?.id, false);
|
||||||
this._blobContainerStorageAccountDropdowns[index].values!.forEach((resource, resourceIndex) => {
|
|
||||||
if ((<azdata.CategoryValue>resource).name.toLowerCase() === this.migrationStateModel.savedInfo?.blobs[index]?.storageAccount?.id?.toLowerCase()) {
|
|
||||||
selectDropDownIndex(this._blobContainerStorageAccountDropdowns[index], resourceIndex);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
selectDropDownIndex(this._blobContainerStorageAccountDropdowns[index], 0);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logError(TelemetryViews.DatabaseBackupPage, 'ErrorLoadingBlobStorageDropdown', error);
|
logError(TelemetryViews.DatabaseBackupPage, 'ErrorLoadingBlobStorageDropdown', error);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1301,15 +1287,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
try {
|
try {
|
||||||
const blobContainerValues = await this.migrationStateModel.getBlobContainerValues(this.migrationStateModel._databaseBackup.subscription, this.migrationStateModel._databaseBackup.blobs[index]?.storageAccount);
|
const blobContainerValues = await this.migrationStateModel.getBlobContainerValues(this.migrationStateModel._databaseBackup.subscription, this.migrationStateModel._databaseBackup.blobs[index]?.storageAccount);
|
||||||
this._blobContainerDropdowns[index].values = blobContainerValues;
|
this._blobContainerDropdowns[index].values = blobContainerValues;
|
||||||
if (this.hasSavedInfo(NetworkContainerType.BLOB_CONTAINER, this._blobContainerDropdowns[index].values && this.migrationStateModel.savedInfo.blobs[index]?.blobContainer)) {
|
selectDefaultDropdownValue(this._blobContainerDropdowns[index], this.migrationStateModel._databaseBackup?.blobs[index]?.blobContainer?.id, false);
|
||||||
this._blobContainerDropdowns[index].values!.forEach((resource, resourceIndex) => {
|
|
||||||
if ((<azdata.CategoryValue>resource).name.toLowerCase() === this.migrationStateModel.savedInfo?.blobs[index]?.blobContainer?.id?.toLowerCase()) {
|
|
||||||
selectDropDownIndex(this._blobContainerDropdowns[index], resourceIndex);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
selectDropDownIndex(this._blobContainerDropdowns[index], 0);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logError(TelemetryViews.DatabaseBackupPage, 'ErrorLoadingBlobContainers', error);
|
logError(TelemetryViews.DatabaseBackupPage, 'ErrorLoadingBlobContainers', error);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1322,15 +1300,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
try {
|
try {
|
||||||
const blobLastBackupFileValues = await this.migrationStateModel.getBlobLastBackupFileNameValues(this.migrationStateModel._databaseBackup.subscription, this.migrationStateModel._databaseBackup.blobs[index]?.storageAccount, this.migrationStateModel._databaseBackup.blobs[index]?.blobContainer);
|
const blobLastBackupFileValues = await this.migrationStateModel.getBlobLastBackupFileNameValues(this.migrationStateModel._databaseBackup.subscription, this.migrationStateModel._databaseBackup.blobs[index]?.storageAccount, this.migrationStateModel._databaseBackup.blobs[index]?.blobContainer);
|
||||||
this._blobContainerLastBackupFileDropdowns[index].values = blobLastBackupFileValues;
|
this._blobContainerLastBackupFileDropdowns[index].values = blobLastBackupFileValues;
|
||||||
if (this.hasSavedInfo(NetworkContainerType.BLOB_CONTAINER, this._blobContainerLastBackupFileDropdowns[index].values && this.migrationStateModel.savedInfo.blobs[index]?.lastBackupFile)) {
|
selectDefaultDropdownValue(this._blobContainerLastBackupFileDropdowns[index], this.migrationStateModel._databaseBackup?.blobs[index]?.lastBackupFile, false);
|
||||||
this._blobContainerLastBackupFileDropdowns[index].values!.forEach((resource, resourceIndex) => {
|
|
||||||
if ((<azdata.CategoryValue>resource).name.toLowerCase() === this.migrationStateModel.savedInfo?.blobs[index]?.lastBackupFile!.toLowerCase()) {
|
|
||||||
selectDropDownIndex(this._blobContainerLastBackupFileDropdowns[index], resourceIndex);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
selectDropDownIndex(this._blobContainerLastBackupFileDropdowns[index], 0);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logError(TelemetryViews.DatabaseBackupPage, 'ErrorLoadingBlobLastBackupFiles', error);
|
logError(TelemetryViews.DatabaseBackupPage, 'ErrorLoadingBlobLastBackupFiles', error);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1362,12 +1332,4 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
|||||||
selectDropDownIndex(this._blobContainerStorageAccountDropdowns[rowIndex], 0);
|
selectDropDownIndex(this._blobContainerStorageAccountDropdowns[rowIndex], 0);
|
||||||
await this._blobContainerStorageAccountDropdowns[rowIndex].updateProperties(dropdownProps);
|
await this._blobContainerStorageAccountDropdowns[rowIndex].updateProperties(dropdownProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
private hasSavedInfo(networkContainerType: NetworkContainerType, values: any): boolean {
|
|
||||||
if (this.migrationStateModel._databaseBackup.networkContainerType === networkContainerType &&
|
|
||||||
(this.migrationStateModel.retryMigration || (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.DatabaseBackup) && values)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,12 @@
|
|||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { MigrationWizardPage } from '../models/migrationWizardPage';
|
import { MigrationWizardPage } from '../models/migrationWizardPage';
|
||||||
import { MigrationStateModel, Page, StateChangeEvent } from '../models/stateMachine';
|
import { MigrationStateModel, StateChangeEvent } from '../models/stateMachine';
|
||||||
import * as constants from '../constants/strings';
|
import * as constants from '../constants/strings';
|
||||||
import { IconPath, IconPathHelper } from '../constants/iconPathHelper';
|
import { IconPath, IconPathHelper } from '../constants/iconPathHelper';
|
||||||
import { debounce } from '../api/utils';
|
import { debounce } from '../api/utils';
|
||||||
import * as styles from '../constants/styles';
|
import * as styles from '../constants/styles';
|
||||||
|
import { selectDatabasesFromList } from '../constants/helper';
|
||||||
|
|
||||||
const styleLeft: azdata.CssStyles = {
|
const styleLeft: azdata.CssStyles = {
|
||||||
'border': 'none',
|
'border': 'none',
|
||||||
@@ -89,12 +90,14 @@ export class DatabaseSelectorPage extends MigrationWizardPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async onPageLeave(): Promise<void> {
|
public async onPageLeave(): Promise<void> {
|
||||||
const assessedDatabases = this.migrationStateModel._databaseAssessment ?? [];
|
const assessedDatabases = this.migrationStateModel._assessedDatabaseList ?? [];
|
||||||
const selectedDatabases = this.selectedDbs();
|
const selectedDatabases = this.migrationStateModel._databasesForAssessment;
|
||||||
// run assessment if
|
// run assessment if
|
||||||
|
// * no prior assessment
|
||||||
// * the prior assessment had an error or
|
// * the prior assessment had an error or
|
||||||
// * the assessed databases list is different from the selected databases list
|
// * the assessed databases list is different from the selected databases list
|
||||||
this.migrationStateModel._runAssessments = !!this.migrationStateModel._assessmentResults?.assessmentError
|
this.migrationStateModel._runAssessments = !this.migrationStateModel._assessmentResults
|
||||||
|
|| !!this.migrationStateModel._assessmentResults?.assessmentError
|
||||||
|| assessedDatabases.length === 0
|
|| assessedDatabases.length === 0
|
||||||
|| assessedDatabases.length !== selectedDatabases.length
|
|| assessedDatabases.length !== selectedDatabases.length
|
||||||
|| assessedDatabases.some(db => selectedDatabases.indexOf(db) < 0);
|
|| assessedDatabases.some(db => selectedDatabases.indexOf(db) < 0);
|
||||||
@@ -268,20 +271,8 @@ export class DatabaseSelectorPage extends MigrationWizardPage {
|
|||||||
}
|
}
|
||||||
).component();
|
).component();
|
||||||
|
|
||||||
if (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.DatabaseSelector) {
|
this._databaseTableValues = selectDatabasesFromList(this.migrationStateModel._databasesForAssessment, this._databaseTableValues);
|
||||||
await this._databaseSelectorTable.setDataValues(this.migrationStateModel.savedInfo.selectedDatabases);
|
|
||||||
} else {
|
|
||||||
if (this.migrationStateModel.retryMigration) {
|
|
||||||
const sourceDatabaseName = this.migrationStateModel.savedInfo.databaseList[0];
|
|
||||||
this._databaseTableValues.forEach((row, index) => {
|
|
||||||
const dbName = row[1].value as string;
|
|
||||||
if (dbName?.toLowerCase() === sourceDatabaseName?.toLowerCase()) {
|
|
||||||
row[0].value = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
await this._databaseSelectorTable.setDataValues(this._databaseTableValues);
|
await this._databaseSelectorTable.setDataValues(this._databaseTableValues);
|
||||||
}
|
|
||||||
await this.updateValuesOnSelection();
|
await this.updateValuesOnSelection();
|
||||||
|
|
||||||
this._disposables.push(this._databaseSelectorTable.onDataChanged(async () => {
|
this._disposables.push(this._databaseSelectorTable.onDataChanged(async () => {
|
||||||
@@ -300,7 +291,6 @@ export class DatabaseSelectorPage extends MigrationWizardPage {
|
|||||||
flex.addItem(this._dbCount, { flex: '0 0 auto' });
|
flex.addItem(this._dbCount, { flex: '0 0 auto' });
|
||||||
flex.addItem(this._databaseSelectorTable);
|
flex.addItem(this._databaseSelectorTable);
|
||||||
return flex;
|
return flex;
|
||||||
// insert names of databases into table
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public selectedDbs(): string[] {
|
public selectedDbs(): string[] {
|
||||||
@@ -317,8 +307,7 @@ export class DatabaseSelectorPage extends MigrationWizardPage {
|
|||||||
await this._dbCount.updateProperties({
|
await this._dbCount.updateProperties({
|
||||||
'value': constants.DATABASES_SELECTED(this.selectedDbs().length, this._databaseTableValues.length)
|
'value': constants.DATABASES_SELECTED(this.selectedDbs().length, this._databaseTableValues.length)
|
||||||
});
|
});
|
||||||
this.migrationStateModel._databaseAssessment = this.selectedDbs();
|
this.migrationStateModel._databasesForAssessment = this.selectedDbs();
|
||||||
this.migrationStateModel.databaseSelectorTableValues = <azdata.DeclarativeTableCellValue[][]>this._databaseSelectorTable.dataValues;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// undo when bug #16445 is fixed
|
// undo when bug #16445 is fixed
|
||||||
|
|||||||
@@ -5,16 +5,15 @@
|
|||||||
|
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { azureResource } from 'azureResource';
|
|
||||||
import { MigrationWizardPage } from '../models/migrationWizardPage';
|
import { MigrationWizardPage } from '../models/migrationWizardPage';
|
||||||
import { MigrationStateModel, NetworkContainerType, Page, StateChangeEvent } from '../models/stateMachine';
|
import { MigrationStateModel, NetworkContainerType, StateChangeEvent } from '../models/stateMachine';
|
||||||
import { CreateSqlMigrationServiceDialog } from '../dialog/createSqlMigrationService/createSqlMigrationServiceDialog';
|
import { CreateSqlMigrationServiceDialog } from '../dialog/createSqlMigrationService/createSqlMigrationServiceDialog';
|
||||||
import * as constants from '../constants/strings';
|
import * as constants from '../constants/strings';
|
||||||
import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
|
import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
|
||||||
import { getFullResourceGroupFromId, getLocationDisplayName, getSqlMigrationService, getSqlMigrationServiceAuthKeys, getSqlMigrationServiceMonitoringData, SqlManagedInstance, SqlVMServer } from '../api/azure';
|
import { getFullResourceGroupFromId, getLocationDisplayName, getSqlMigrationService, getSqlMigrationServiceAuthKeys, getSqlMigrationServiceMonitoringData } from '../api/azure';
|
||||||
import { IconPathHelper } from '../constants/iconPathHelper';
|
import { IconPathHelper } from '../constants/iconPathHelper';
|
||||||
import { logError, TelemetryViews } from '../telemtery';
|
import { logError, TelemetryViews } from '../telemtery';
|
||||||
import { findDropDownItemIndex, selectDropDownIndex } from '../api/utils';
|
import { findDropDownItemIndex, selectDefaultDropdownValue } from '../api/utils';
|
||||||
import * as styles from '../constants/styles';
|
import * as styles from '../constants/styles';
|
||||||
|
|
||||||
export class IntergrationRuntimePage extends MigrationWizardPage {
|
export class IntergrationRuntimePage extends MigrationWizardPage {
|
||||||
@@ -76,11 +75,6 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async onPageEnter(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
|
public async onPageEnter(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
|
||||||
if (this.migrationStateModel.retryMigration || (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.IntegrationRuntime)) {
|
|
||||||
this.migrationStateModel._targetSubscription = <azureResource.AzureResourceSubscription>this.migrationStateModel.savedInfo.targetSubscription;
|
|
||||||
this.migrationStateModel._targetServerInstance = <SqlManagedInstance | SqlVMServer>this.migrationStateModel.savedInfo.targetServerInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._subscription.value = this.migrationStateModel._targetSubscription.name;
|
this._subscription.value = this.migrationStateModel._targetSubscription.name;
|
||||||
this._location.value = await getLocationDisplayName(this.migrationStateModel._targetServerInstance.location);
|
this._location.value = await getLocationDisplayName(this.migrationStateModel._targetServerInstance.location);
|
||||||
this._dmsInfoContainer.display = (this.migrationStateModel._databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE && this.migrationStateModel._sqlMigrationService) ? 'inline' : 'none';
|
this._dmsInfoContainer.display = (this.migrationStateModel._databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE && this.migrationStateModel._sqlMigrationService) ? 'inline' : 'none';
|
||||||
@@ -183,10 +177,13 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
|||||||
}).component();
|
}).component();
|
||||||
this._disposables.push(this._resourceGroupDropdown.onValueChanged(async (value) => {
|
this._disposables.push(this._resourceGroupDropdown.onValueChanged(async (value) => {
|
||||||
const selectedIndex = findDropDownItemIndex(this._resourceGroupDropdown, value);
|
const selectedIndex = findDropDownItemIndex(this._resourceGroupDropdown, value);
|
||||||
|
if (selectedIndex > -1 &&
|
||||||
|
value !== constants.RESOURCE_GROUP_NOT_FOUND) {
|
||||||
this.migrationStateModel._sqlMigrationServiceResourceGroup = this.migrationStateModel.getAzureResourceGroup(selectedIndex).name;
|
this.migrationStateModel._sqlMigrationServiceResourceGroup = this.migrationStateModel.getAzureResourceGroup(selectedIndex).name;
|
||||||
if (selectedIndex > -1) {
|
} else {
|
||||||
await this.populateDms(value);
|
this.migrationStateModel._sqlMigrationServiceResourceGroup = undefined!;
|
||||||
}
|
}
|
||||||
|
await this.populateDms();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const migrationServiceDropdownLabel = this._view.modelBuilder.text().withProps({
|
const migrationServiceDropdownLabel = this._view.modelBuilder.text().withProps({
|
||||||
@@ -216,8 +213,10 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
|||||||
text: ''
|
text: ''
|
||||||
};
|
};
|
||||||
const selectedIndex = findDropDownItemIndex(this._dmsDropdown, value);
|
const selectedIndex = findDropDownItemIndex(this._dmsDropdown, value);
|
||||||
|
if (selectedIndex > -1) {
|
||||||
this.migrationStateModel._sqlMigrationService = this.migrationStateModel.getMigrationService(selectedIndex);
|
this.migrationStateModel._sqlMigrationService = this.migrationStateModel.getMigrationService(selectedIndex);
|
||||||
await this.loadMigrationServiceStatus();
|
await this.loadMigrationServiceStatus();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.migrationStateModel._sqlMigrationService = undefined;
|
this.migrationStateModel._sqlMigrationService = undefined;
|
||||||
this._dmsInfoContainer.display = 'none';
|
this._dmsInfoContainer.display = 'none';
|
||||||
@@ -238,7 +237,7 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
|||||||
this.migrationStateModel._sqlMigrationServiceResourceGroup = createdDmsResult.resourceGroup;
|
this.migrationStateModel._sqlMigrationServiceResourceGroup = createdDmsResult.resourceGroup;
|
||||||
this.migrationStateModel._sqlMigrationService = createdDmsResult.service;
|
this.migrationStateModel._sqlMigrationService = createdDmsResult.service;
|
||||||
await this.loadResourceGroupDropdown();
|
await this.loadResourceGroupDropdown();
|
||||||
await this.populateDms(createdDmsResult.resourceGroup);
|
await this.populateDms();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const flexContainer = this._view.modelBuilder.flexContainer().withItems([
|
const flexContainer = this._view.modelBuilder.flexContainer().withItems([
|
||||||
@@ -376,38 +375,26 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
|||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async loadResourceGroupDropdown(): Promise<void> {
|
public async loadResourceGroupDropdown(): Promise<void> {
|
||||||
this._resourceGroupDropdown.loading = true;
|
this._resourceGroupDropdown.loading = true;
|
||||||
|
this._dmsDropdown.loading = true;
|
||||||
try {
|
try {
|
||||||
this._resourceGroupDropdown.values = await this.migrationStateModel.getAzureResourceGroupDropdownValues(this.migrationStateModel._targetSubscription);
|
this._resourceGroupDropdown.values = await this.migrationStateModel.getAzureResourceGroupDropdownValues(this.migrationStateModel._targetSubscription);
|
||||||
if (this.migrationStateModel.retryMigration || (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.IntegrationRuntime && this._resourceGroupDropdown.values)) {
|
const resourceGroup = (this.migrationStateModel._sqlMigrationService)
|
||||||
this._resourceGroupDropdown.values.forEach((resource, resourceIndex) => {
|
? getFullResourceGroupFromId(this.migrationStateModel._sqlMigrationService?.id)
|
||||||
const resourceId = this.migrationStateModel.savedInfo?.migrationServiceId?.toLowerCase();
|
: undefined;
|
||||||
if (resourceId && (<azdata.CategoryValue>resource).name.toLowerCase() === getFullResourceGroupFromId(resourceId)) {
|
selectDefaultDropdownValue(this._resourceGroupDropdown, resourceGroup, false);
|
||||||
selectDropDownIndex(this._resourceGroupDropdown, resourceIndex);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
this._resourceGroupDropdown.loading = false;
|
this._resourceGroupDropdown.loading = false;
|
||||||
|
this._dmsDropdown.loading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async populateDms(resourceGroupName: string): Promise<void> {
|
public async populateDms(): Promise<void> {
|
||||||
this._dmsDropdown.loading = true;
|
this._dmsDropdown.loading = true;
|
||||||
try {
|
try {
|
||||||
this._dmsDropdown.values = await this.migrationStateModel.getSqlMigrationServiceValues(this.migrationStateModel._targetSubscription, <SqlManagedInstance>this.migrationStateModel._targetServerInstance, resourceGroupName);
|
this._dmsDropdown.values = await this.migrationStateModel.getSqlMigrationServiceValues(this.migrationStateModel._targetSubscription, this.migrationStateModel._sqlMigrationServiceResourceGroup);
|
||||||
const selectedSqlMigrationService = this._dmsDropdown.values.find(v => v.displayName.toLowerCase() === this.migrationStateModel._sqlMigrationService?.name?.toLowerCase());
|
selectDefaultDropdownValue(this._dmsDropdown, this.migrationStateModel._sqlMigrationService?.id, false);
|
||||||
if (this.migrationStateModel.retryMigration || (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.IntegrationRuntime && this._dmsDropdown.values)) {
|
|
||||||
this._dmsDropdown.values.forEach((resource, resourceIndex) => {
|
|
||||||
if ((<azdata.CategoryValue>resource).name.toLowerCase() === this.migrationStateModel.savedInfo?.migrationServiceId?.toLowerCase()) {
|
|
||||||
selectDropDownIndex(this._dmsDropdown, resourceIndex);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this._dmsDropdown.value = (selectedSqlMigrationService) ? selectedSqlMigrationService : this._dmsDropdown.values[0];
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
this._dmsDropdown.loading = false;
|
this._dmsDropdown.loading = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { MigrationWizardPage } from '../models/migrationWizardPage';
|
import { MigrationWizardPage } from '../models/migrationWizardPage';
|
||||||
import { MigrationMode, MigrationStateModel, Page, StateChangeEvent } from '../models/stateMachine';
|
import { MigrationMode, MigrationStateModel, StateChangeEvent } from '../models/stateMachine';
|
||||||
import * as constants from '../constants/strings';
|
import * as constants from '../constants/strings';
|
||||||
import * as styles from '../constants/styles';
|
import * as styles from '../constants/styles';
|
||||||
|
|
||||||
@@ -17,6 +17,7 @@ export class MigrationModePage extends MigrationWizardPage {
|
|||||||
|
|
||||||
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
|
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
|
||||||
super(wizard, azdata.window.createWizardPage(constants.DATABASE_BACKUP_MIGRATION_MODE_LABEL, 'MigrationModePage'), migrationStateModel);
|
super(wizard, azdata.window.createWizardPage(constants.DATABASE_BACKUP_MIGRATION_MODE_LABEL, 'MigrationModePage'), migrationStateModel);
|
||||||
|
this.migrationStateModel._databaseBackup.migrationMode = this.migrationStateModel._databaseBackup.migrationMode || MigrationMode.ONLINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async registerContent(view: azdata.ModelView): Promise<void> {
|
protected async registerContent(view: azdata.ModelView): Promise<void> {
|
||||||
@@ -59,7 +60,7 @@ export class MigrationModePage extends MigrationWizardPage {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
public async onPageLeave(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
|
public async onPageLeave(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
|
||||||
if (this.originalMigrationMode !== this.migrationStateModel._databaseBackup.migrationMode || this.migrationStateModel.resumeAssessment) {
|
if (this.originalMigrationMode !== this.migrationStateModel._databaseBackup.migrationMode) {
|
||||||
this.migrationStateModel.refreshDatabaseBackupPage = true;
|
this.migrationStateModel.refreshDatabaseBackupPage = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,15 +72,15 @@ export class MigrationModePage extends MigrationWizardPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private migrationModeContainer(): azdata.FormComponent {
|
private migrationModeContainer(): azdata.FormComponent {
|
||||||
const buttonGroup = 'cutoverContainer';
|
const buttonGroup = 'migrationMode';
|
||||||
|
|
||||||
const onlineButton = this._view.modelBuilder.radioButton().withProps({
|
const onlineButton = this._view.modelBuilder.radioButton().withProps({
|
||||||
label: constants.DATABASE_BACKUP_MIGRATION_MODE_ONLINE_LABEL,
|
label: constants.DATABASE_BACKUP_MIGRATION_MODE_ONLINE_LABEL,
|
||||||
name: buttonGroup,
|
name: buttonGroup,
|
||||||
|
checked: this.migrationStateModel._databaseBackup.migrationMode === MigrationMode.ONLINE,
|
||||||
CSSStyles: {
|
CSSStyles: {
|
||||||
...styles.LABEL_CSS,
|
...styles.LABEL_CSS,
|
||||||
},
|
},
|
||||||
checked: true
|
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
const onlineDescription = this._view.modelBuilder.text().withProps({
|
const onlineDescription = this._view.modelBuilder.text().withProps({
|
||||||
@@ -99,6 +100,7 @@ export class MigrationModePage extends MigrationWizardPage {
|
|||||||
const offlineButton = this._view.modelBuilder.radioButton().withProps({
|
const offlineButton = this._view.modelBuilder.radioButton().withProps({
|
||||||
label: constants.DATABASE_BACKUP_MIGRATION_MODE_OFFLINE_LABEL,
|
label: constants.DATABASE_BACKUP_MIGRATION_MODE_OFFLINE_LABEL,
|
||||||
name: buttonGroup,
|
name: buttonGroup,
|
||||||
|
checked: this.migrationStateModel._databaseBackup.migrationMode === MigrationMode.OFFLINE,
|
||||||
CSSStyles: {
|
CSSStyles: {
|
||||||
...styles.LABEL_CSS,
|
...styles.LABEL_CSS,
|
||||||
'margin-top': '12px'
|
'margin-top': '12px'
|
||||||
@@ -113,16 +115,6 @@ export class MigrationModePage extends MigrationWizardPage {
|
|||||||
}
|
}
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
if (this.migrationStateModel.retryMigration || (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.MigrationMode)) {
|
|
||||||
if (this.migrationStateModel.savedInfo.migrationMode === MigrationMode.ONLINE) {
|
|
||||||
onlineButton.checked = true;
|
|
||||||
offlineButton.checked = false;
|
|
||||||
} else {
|
|
||||||
onlineButton.checked = false;
|
|
||||||
offlineButton.checked = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this._disposables.push(offlineButton.onDidChangeCheckedState((e) => {
|
this._disposables.push(offlineButton.onDidChangeCheckedState((e) => {
|
||||||
if (e) {
|
if (e) {
|
||||||
this.migrationStateModel._databaseBackup.migrationMode = MigrationMode.OFFLINE;
|
this.migrationStateModel._databaseBackup.migrationMode = MigrationMode.OFFLINE;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import * as azdata from 'azdata';
|
|||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as mssql from '../../../mssql';
|
import * as mssql from '../../../mssql';
|
||||||
import { MigrationWizardPage } from '../models/migrationWizardPage';
|
import { MigrationWizardPage } from '../models/migrationWizardPage';
|
||||||
import { MigrationStateModel, MigrationTargetType, Page, PerformanceDataSourceOptions, ServerAssessment, StateChangeEvent } from '../models/stateMachine';
|
import { MigrationStateModel, MigrationTargetType, PerformanceDataSourceOptions, StateChangeEvent } from '../models/stateMachine';
|
||||||
import { AssessmentResultsDialog } from '../dialog/assessmentResults/assessmentResultsDialog';
|
import { AssessmentResultsDialog } from '../dialog/assessmentResults/assessmentResultsDialog';
|
||||||
import { SkuRecommendationResultsDialog } from '../dialog/skuRecommendationResults/skuRecommendationResultsDialog';
|
import { SkuRecommendationResultsDialog } from '../dialog/skuRecommendationResults/skuRecommendationResultsDialog';
|
||||||
import { GetAzureRecommendationDialog } from '../dialog/skuRecommendationResults/getAzureRecommendationDialog';
|
import { GetAzureRecommendationDialog } from '../dialog/skuRecommendationResults/getAzureRecommendationDialog';
|
||||||
@@ -17,6 +17,7 @@ import { IconPath, IconPathHelper } from '../constants/iconPathHelper';
|
|||||||
import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
|
import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
|
||||||
import * as styles from '../constants/styles';
|
import * as styles from '../constants/styles';
|
||||||
import { SkuEditParametersDialog } from '../dialog/skuRecommendationResults/skuEditParametersDialog';
|
import { SkuEditParametersDialog } from '../dialog/skuRecommendationResults/skuEditParametersDialog';
|
||||||
|
import { logError, TelemetryViews } from '../telemtery';
|
||||||
|
|
||||||
export interface Product {
|
export interface Product {
|
||||||
type: MigrationTargetType;
|
type: MigrationTargetType;
|
||||||
@@ -153,7 +154,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
|||||||
|
|
||||||
this._disposables.push(refreshAssessmentButton.onDidClick(async () => {
|
this._disposables.push(refreshAssessmentButton.onDidClick(async () => {
|
||||||
await this.startCardLoading();
|
await this.startCardLoading();
|
||||||
await this.migrationStateModel.getSkuRecommendations();
|
this.migrationStateModel._runAssessments = true;
|
||||||
await this.constructDetails();
|
await this.constructDetails();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -382,12 +383,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
|||||||
}
|
}
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
let serverName = '';
|
let serverName = this.migrationStateModel.serverName || (await this.migrationStateModel.getSourceConnectionProfile()).serverName;
|
||||||
if (this.migrationStateModel.retryMigration || (this.migrationStateModel.resumeAssessment && this.migrationStateModel.serverName)) {
|
|
||||||
serverName = this.migrationStateModel.serverName;
|
|
||||||
} else {
|
|
||||||
serverName = (await this.migrationStateModel.getSourceConnectionProfile()).serverName;
|
|
||||||
}
|
|
||||||
|
|
||||||
let miDialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, constants.ASSESSMENT_TILE(serverName), this, MigrationTargetType.SQLMI);
|
let miDialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, constants.ASSESSMENT_TILE(serverName), this, MigrationTargetType.SQLMI);
|
||||||
let vmDialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, constants.ASSESSMENT_TILE(serverName), this, MigrationTargetType.SQLVM);
|
let vmDialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, constants.ASSESSMENT_TILE(serverName), this, MigrationTargetType.SQLVM);
|
||||||
@@ -419,37 +415,31 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async changeTargetType(newTargetType: string) {
|
private async changeTargetType(newTargetType: string) {
|
||||||
if (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.SKURecommendation) {
|
switch (newTargetType) {
|
||||||
this.migrationStateModel._databaseAssessment = <string[]>this.migrationStateModel.savedInfo.databaseAssessment;
|
case MigrationTargetType.SQLMI: {
|
||||||
}
|
|
||||||
// remove assessed databases that have been removed from the source selection list
|
|
||||||
const miDbs = this.migrationStateModel._miDbs.filter(
|
const miDbs = this.migrationStateModel._miDbs.filter(
|
||||||
db => this.migrationStateModel._databaseAssessment.findIndex(
|
db => this.migrationStateModel._databasesForAssessment.findIndex(
|
||||||
dba => dba === db) >= 0);
|
dba => dba === db) >= 0);
|
||||||
|
|
||||||
const vmDbs = this.migrationStateModel._vmDbs.filter(
|
|
||||||
db => this.migrationStateModel._databaseAssessment.findIndex(
|
|
||||||
dba => dba === db) >= 0);
|
|
||||||
|
|
||||||
if (newTargetType === MigrationTargetType.SQLMI) {
|
|
||||||
this._viewAssessmentsHelperText.value = constants.SKU_RECOMMENDATION_VIEW_ASSESSMENT_MI;
|
this._viewAssessmentsHelperText.value = constants.SKU_RECOMMENDATION_VIEW_ASSESSMENT_MI;
|
||||||
if (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.SKURecommendation) {
|
|
||||||
this._databaseSelectedHelperText.value = constants.TOTAL_DATABASES_SELECTED(this.migrationStateModel.savedInfo.databaseList.length, this.migrationStateModel._databaseAssessment.length);
|
|
||||||
} else {
|
|
||||||
this._databaseSelectedHelperText.value = constants.TOTAL_DATABASES_SELECTED(miDbs.length, this.migrationStateModel._databaseAssessment.length);
|
|
||||||
}
|
|
||||||
this.migrationStateModel._targetType = MigrationTargetType.SQLMI;
|
this.migrationStateModel._targetType = MigrationTargetType.SQLMI;
|
||||||
this.migrationStateModel._migrationDbs = miDbs;
|
this.migrationStateModel._databasesForMigration = miDbs;
|
||||||
} else {
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MigrationTargetType.SQLVM: {
|
||||||
|
const vmDbs = this.migrationStateModel._vmDbs.filter(
|
||||||
|
db => this.migrationStateModel._databasesForAssessment.findIndex(
|
||||||
|
dba => dba === db) >= 0);
|
||||||
|
|
||||||
this._viewAssessmentsHelperText.value = constants.SKU_RECOMMENDATION_VIEW_ASSESSMENT_VM;
|
this._viewAssessmentsHelperText.value = constants.SKU_RECOMMENDATION_VIEW_ASSESSMENT_VM;
|
||||||
if ((this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.SKURecommendation)) {
|
|
||||||
this._databaseSelectedHelperText.value = constants.TOTAL_DATABASES_SELECTED(this.migrationStateModel.savedInfo.databaseList.length, this.migrationStateModel._databaseAssessment.length);
|
|
||||||
} else {
|
|
||||||
this._databaseSelectedHelperText.value = constants.TOTAL_DATABASES_SELECTED(vmDbs.length, this.migrationStateModel._databaseAssessment.length);
|
|
||||||
}
|
|
||||||
this.migrationStateModel._targetType = MigrationTargetType.SQLVM;
|
this.migrationStateModel._targetType = MigrationTargetType.SQLVM;
|
||||||
this.migrationStateModel._migrationDbs = vmDbs;
|
this.migrationStateModel._databasesForMigration = vmDbs;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._databaseSelectedHelperText.value = constants.TOTAL_DATABASES_SELECTED(this.migrationStateModel._databasesForMigration.length, this.migrationStateModel._databasesForAssessment.length);
|
||||||
this.migrationStateModel.refreshDatabaseBackupPage = true;
|
this.migrationStateModel.refreshDatabaseBackupPage = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -459,17 +449,13 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
|||||||
level: azdata.window.MessageLevel.Error
|
level: azdata.window.MessageLevel.Error
|
||||||
};
|
};
|
||||||
|
|
||||||
await this._setAssessmentState(true, false);
|
|
||||||
|
|
||||||
const serverName = (await this.migrationStateModel.getSourceConnectionProfile()).serverName;
|
const serverName = (await this.migrationStateModel.getSourceConnectionProfile()).serverName;
|
||||||
const errors: string[] = [];
|
|
||||||
try {
|
|
||||||
if (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage) {
|
|
||||||
this.migrationStateModel._assessmentResults = <ServerAssessment>this.migrationStateModel.savedInfo.serverAssessment;
|
|
||||||
} else {
|
|
||||||
await this.migrationStateModel.getDatabaseAssessments(MigrationTargetType.SQLMI);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (this.migrationStateModel._runAssessments) {
|
||||||
|
const errors: string[] = [];
|
||||||
|
await this._setAssessmentState(true, false);
|
||||||
|
try {
|
||||||
|
await this.migrationStateModel.getDatabaseAssessments(MigrationTargetType.SQLMI);
|
||||||
const assessmentError = this.migrationStateModel._assessmentResults?.assessmentError;
|
const assessmentError = this.migrationStateModel._assessmentResults?.assessmentError;
|
||||||
if (assessmentError) {
|
if (assessmentError) {
|
||||||
errors.push(`message: ${assessmentError.message}${EOL}stack: ${assessmentError.stack}`);
|
errors.push(`message: ${assessmentError.message}${EOL}stack: ${assessmentError.stack}`);
|
||||||
@@ -479,8 +465,8 @@ 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}`)!);
|
e => `message: ${e.message}${EOL}errorSummary: ${e.errorSummary}${EOL}possibleCauses: ${e.possibleCauses}${EOL}guidance: ${e.guidance}${EOL}errorId: ${e.errorId}`)!);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
|
||||||
errors.push(constants.SKU_RECOMMENDATION_ASSESSMENT_UNEXPECTED_ERROR(serverName, e));
|
errors.push(constants.SKU_RECOMMENDATION_ASSESSMENT_UNEXPECTED_ERROR(serverName, e));
|
||||||
|
logError(TelemetryViews.MigrationWizardTaSkuRecommendationPage, 'SkuRecommendationUnexpectedError', e);
|
||||||
} finally {
|
} finally {
|
||||||
this.migrationStateModel._runAssessments = errors.length > 0;
|
this.migrationStateModel._runAssessments = errors.length > 0;
|
||||||
if (errors.length > 0) {
|
if (errors.length > 0) {
|
||||||
@@ -498,37 +484,27 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
|||||||
this._detailsComponent.value = constants.SKU_RECOMMENDATION_ALL_SUCCESSFUL(this.migrationStateModel._assessmentResults?.databaseAssessments?.length);
|
this._detailsComponent.value = constants.SKU_RECOMMENDATION_ALL_SUCCESSFUL(this.migrationStateModel._assessmentResults?.databaseAssessments?.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.hasRecommendations() && this.migrationStateModel.hasRecommendedDatabaseListChanged()) {
|
|
||||||
await this.migrationStateModel.getSkuRecommendations();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.hasSavedInfo()) {
|
|
||||||
if (this.migrationStateModel.savedInfo.migrationTargetType) {
|
|
||||||
this._rbg.selectedCardId = this.migrationStateModel.savedInfo.migrationTargetType;
|
|
||||||
await this.refreshCardText();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.migrationStateModel.savedInfo.migrationTargetType === MigrationTargetType.SQLMI) {
|
|
||||||
this.migrationStateModel._miDbs = this.migrationStateModel.savedInfo.databaseList;
|
|
||||||
} else {
|
} else {
|
||||||
this.migrationStateModel._vmDbs = this.migrationStateModel.savedInfo.databaseList;
|
// use prior assessment results
|
||||||
|
this._assessmentStatusIcon.iconPath = IconPathHelper.completedMigration;
|
||||||
|
this._igComponent.value = constants.ASSESSMENT_COMPLETED(serverName);
|
||||||
|
this._detailsComponent.value = constants.SKU_RECOMMENDATION_ALL_SUCCESSFUL(this.migrationStateModel._assessmentResults?.databaseAssessments?.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.migrationStateModel.savedInfo.skuRecommendation) {
|
if (this.migrationStateModel.savedInfo?.migrationTargetType) {
|
||||||
const skuRecommendationSavedInfo = this.migrationStateModel.savedInfo.skuRecommendation;
|
this._rbg.selectedCardId = this.migrationStateModel._targetType;
|
||||||
this.migrationStateModel._skuRecommendationPerformanceDataSource = skuRecommendationSavedInfo.skuRecommendationPerformanceDataSource!;
|
}
|
||||||
this.migrationStateModel._skuRecommendationPerformanceLocation = skuRecommendationSavedInfo.skuRecommendationPerformanceLocation!;
|
|
||||||
|
|
||||||
this.migrationStateModel._skuScalingFactor = skuRecommendationSavedInfo.skuScalingFactor!;
|
let shouldGetSkuRecommendations = false;
|
||||||
this.migrationStateModel._skuTargetPercentile = skuRecommendationSavedInfo.skuTargetPercentile!;
|
if (this.hasRecommendations() && this.migrationStateModel.hasRecommendedDatabaseListChanged()) {
|
||||||
this.migrationStateModel._skuEnablePreview = skuRecommendationSavedInfo.skuEnablePreview!;
|
shouldGetSkuRecommendations = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.migrationStateModel.savedInfo?.skuRecommendation) {
|
||||||
await this.refreshSkuParameters();
|
await this.refreshSkuParameters();
|
||||||
|
|
||||||
switch (this.migrationStateModel._skuRecommendationPerformanceDataSource) {
|
switch (this.migrationStateModel._skuRecommendationPerformanceDataSource) {
|
||||||
case PerformanceDataSourceOptions.CollectData: {
|
case PerformanceDataSourceOptions.CollectData: {
|
||||||
this.migrationStateModel._perfDataCollectionStartDate = skuRecommendationSavedInfo.perfDataCollectionStartDate;
|
|
||||||
|
|
||||||
// check if collector is still running
|
// check if collector is still running
|
||||||
await this.migrationStateModel.refreshPerfDataCollection();
|
await this.migrationStateModel.refreshPerfDataCollection();
|
||||||
if (this.migrationStateModel._perfDataCollectionIsCollecting) {
|
if (this.migrationStateModel._perfDataCollectionIsCollecting) {
|
||||||
@@ -542,17 +518,20 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
|||||||
// user started collecting data, but collector is stopped
|
// user started collecting data, but collector is stopped
|
||||||
// set stop date to some date value
|
// set stop date to some date value
|
||||||
this.migrationStateModel._perfDataCollectionStopDate = this.migrationStateModel._perfDataCollectionStopDate || new Date();
|
this.migrationStateModel._perfDataCollectionStopDate = this.migrationStateModel._perfDataCollectionStopDate || new Date();
|
||||||
await this.migrationStateModel.getSkuRecommendations();
|
shouldGetSkuRecommendations = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case PerformanceDataSourceOptions.OpenExisting: {
|
case PerformanceDataSourceOptions.OpenExisting: {
|
||||||
await this.migrationStateModel.getSkuRecommendations();
|
shouldGetSkuRecommendations = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (shouldGetSkuRecommendations) {
|
||||||
|
await this.migrationStateModel.getSkuRecommendations();
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.refreshSkuRecommendationComponents();
|
await this.refreshSkuRecommendationComponents();
|
||||||
@@ -582,7 +561,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
|||||||
|
|
||||||
display = (this._rbg.selectedCardId
|
display = (this._rbg.selectedCardId
|
||||||
&& (!failedAssessment || this._skipAssessmentCheckbox.checked)
|
&& (!failedAssessment || this._skipAssessmentCheckbox.checked)
|
||||||
&& this.migrationStateModel._migrationDbs.length > 0)
|
&& this.migrationStateModel._databasesForMigration?.length > 0)
|
||||||
? 'inline'
|
? 'inline'
|
||||||
: 'none';
|
: 'none';
|
||||||
|
|
||||||
@@ -603,7 +582,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
|||||||
if (this._rbg.selectedCardId === undefined || this._rbg.selectedCardId === '') {
|
if (this._rbg.selectedCardId === undefined || this._rbg.selectedCardId === '') {
|
||||||
errors.push(constants.SELECT_TARGET_TO_CONTINUE);
|
errors.push(constants.SELECT_TARGET_TO_CONTINUE);
|
||||||
}
|
}
|
||||||
if (this.migrationStateModel._migrationDbs.length === 0) {
|
if (this.migrationStateModel._databasesForMigration.length === 0) {
|
||||||
errors.push(constants.SELECT_DATABASE_TO_MIGRATE);
|
errors.push(constants.SELECT_DATABASE_TO_MIGRATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,9 +617,9 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
|||||||
public async refreshCardText(showLoadingIcon: boolean = true): Promise<void> {
|
public async refreshCardText(showLoadingIcon: boolean = true): Promise<void> {
|
||||||
this._rbgLoader.loading = showLoadingIcon && true;
|
this._rbgLoader.loading = showLoadingIcon && true;
|
||||||
if (this._rbg.selectedCardId === MigrationTargetType.SQLMI) {
|
if (this._rbg.selectedCardId === MigrationTargetType.SQLMI) {
|
||||||
this.migrationStateModel._migrationDbs = this.migrationStateModel._miDbs;
|
this.migrationStateModel._databasesForMigration = this.migrationStateModel._miDbs;
|
||||||
} else {
|
} else {
|
||||||
this.migrationStateModel._migrationDbs = this.migrationStateModel._vmDbs;
|
this.migrationStateModel._databasesForMigration = this.migrationStateModel._vmDbs;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dbCount = this.migrationStateModel._assessmentResults?.databaseAssessments?.length;
|
const dbCount = this.migrationStateModel._assessmentResults?.databaseAssessments?.length;
|
||||||
@@ -1188,10 +1167,6 @@ export class SKURecommendationPage extends MigrationWizardPage {
|
|||||||
await this.refreshCardText(false);
|
await this.refreshCardText(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private hasSavedInfo(): boolean {
|
|
||||||
return this.migrationStateModel.retryMigration || (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.SKURecommendation);
|
|
||||||
}
|
|
||||||
|
|
||||||
private hasRecommendations(): boolean {
|
private hasRecommendations(): boolean {
|
||||||
return this.migrationStateModel._skuRecommendationResults?.recommendations && !this.migrationStateModel._skuRecommendationResults?.recommendationError ? true : false;
|
return this.migrationStateModel._skuRecommendationResults?.recommendations && !this.migrationStateModel._skuRecommendationResults?.recommendationError ? true : false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,12 @@
|
|||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { MigrationWizardPage } from '../models/migrationWizardPage';
|
import { MigrationWizardPage } from '../models/migrationWizardPage';
|
||||||
import { MigrationMode, MigrationStateModel, MigrationTargetType, NetworkContainerType, Page, StateChangeEvent } from '../models/stateMachine';
|
import { MigrationMode, MigrationStateModel, MigrationTargetType, NetworkContainerType, StateChangeEvent } from '../models/stateMachine';
|
||||||
import * as constants from '../constants/strings';
|
import * as constants from '../constants/strings';
|
||||||
import { createHeadingTextComponent, createInformationRow, createLabelTextComponent } from './wizardController';
|
import { createHeadingTextComponent, createInformationRow, createLabelTextComponent } from './wizardController';
|
||||||
import { getResourceGroupFromId, Subscription } from '../api/azure';
|
import { getResourceGroupFromId } from '../api/azure';
|
||||||
import { TargetDatabaseSummaryDialog } from '../dialog/targetDatabaseSummary/targetDatabaseSummaryDialog';
|
import { TargetDatabaseSummaryDialog } from '../dialog/targetDatabaseSummary/targetDatabaseSummaryDialog';
|
||||||
import * as styles from '../constants/styles';
|
import * as styles from '../constants/styles';
|
||||||
import { azureResource } from 'azureResource';
|
|
||||||
import { Tenant } from 'azurecore';
|
|
||||||
|
|
||||||
export class SummaryPage extends MigrationWizardPage {
|
export class SummaryPage extends MigrationWizardPage {
|
||||||
private _view!: azdata.ModelView;
|
private _view!: azdata.ModelView;
|
||||||
@@ -47,30 +45,10 @@ export class SummaryPage extends MigrationWizardPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async onPageEnter(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
|
public async onPageEnter(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
|
||||||
if (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.Summary) {
|
|
||||||
this.migrationStateModel._databaseBackup.networkContainerType = <NetworkContainerType>this.migrationStateModel.savedInfo.networkContainerType;
|
|
||||||
this.migrationStateModel._databaseBackup.networkShares = this.migrationStateModel.savedInfo.networkShares;
|
|
||||||
this.migrationStateModel._databaseBackup.subscription = <Subscription>this.migrationStateModel.savedInfo.targetSubscription;
|
|
||||||
this.migrationStateModel._databaseBackup.blobs = this.migrationStateModel.savedInfo.blobs;
|
|
||||||
this.migrationStateModel._targetDatabaseNames = this.migrationStateModel.savedInfo.targetDatabaseNames;
|
|
||||||
|
|
||||||
this.migrationStateModel._targetType = <MigrationTargetType>this.migrationStateModel.savedInfo.migrationTargetType;
|
|
||||||
this.migrationStateModel._databaseAssessment = <string[]>this.migrationStateModel.savedInfo.databaseAssessment;
|
|
||||||
this.migrationStateModel._migrationDbs = this.migrationStateModel.savedInfo.databaseList;
|
|
||||||
this.migrationStateModel._targetSubscription = <azureResource.AzureResourceSubscription>this.migrationStateModel.savedInfo.subscription;
|
|
||||||
this.migrationStateModel._location = <azureResource.AzureLocation>this.migrationStateModel.savedInfo.location;
|
|
||||||
this.migrationStateModel._resourceGroup = <azureResource.AzureResourceResourceGroup>this.migrationStateModel.savedInfo.resourceGroup;
|
|
||||||
this.migrationStateModel._targetServerInstance = <azureResource.AzureSqlManagedInstance>this.migrationStateModel.savedInfo.targetServerInstance;
|
|
||||||
|
|
||||||
this.migrationStateModel.databaseSelectorTableValues = this.migrationStateModel.savedInfo.selectedDatabases;
|
|
||||||
|
|
||||||
this.migrationStateModel._azureAccount = <azdata.Account>this.migrationStateModel.savedInfo.azureAccount;
|
|
||||||
this.migrationStateModel._azureTenant = <Tenant>this.migrationStateModel.savedInfo.azureTenant;
|
|
||||||
}
|
|
||||||
const targetDatabaseSummary = new TargetDatabaseSummaryDialog(this.migrationStateModel);
|
const targetDatabaseSummary = new TargetDatabaseSummaryDialog(this.migrationStateModel);
|
||||||
const targetDatabaseHyperlink = this._view.modelBuilder.hyperlink().withProps({
|
const targetDatabaseHyperlink = this._view.modelBuilder.hyperlink().withProps({
|
||||||
url: '',
|
url: '',
|
||||||
label: this.migrationStateModel._migrationDbs.length.toString(),
|
label: this.migrationStateModel._databasesForMigration?.length.toString(),
|
||||||
CSSStyles: {
|
CSSStyles: {
|
||||||
...styles.BODY_CSS,
|
...styles.BODY_CSS,
|
||||||
'margin': '0px',
|
'margin': '0px',
|
||||||
@@ -128,7 +106,7 @@ export class SummaryPage extends MigrationWizardPage {
|
|||||||
|
|
||||||
await createHeadingTextComponent(this._view, constants.IR_PAGE_TITLE),
|
await createHeadingTextComponent(this._view, constants.IR_PAGE_TITLE),
|
||||||
createInformationRow(this._view, constants.SUBSCRIPTION, this.migrationStateModel._targetSubscription.name),
|
createInformationRow(this._view, constants.SUBSCRIPTION, this.migrationStateModel._targetSubscription.name),
|
||||||
createInformationRow(this._view, constants.LOCATION, this.migrationStateModel._sqlMigrationService?.location!),
|
createInformationRow(this._view, constants.LOCATION, await this.migrationStateModel.getLocationDisplayName(this.migrationStateModel._sqlMigrationService?.location!)),
|
||||||
createInformationRow(this._view, constants.RESOURCE_GROUP, this.migrationStateModel._sqlMigrationService?.properties?.resourceGroup!),
|
createInformationRow(this._view, constants.RESOURCE_GROUP, this.migrationStateModel._sqlMigrationService?.properties?.resourceGroup!),
|
||||||
createInformationRow(this._view, constants.IR_PAGE_TITLE, this.migrationStateModel._sqlMigrationService?.name!)
|
createInformationRow(this._view, constants.IR_PAGE_TITLE, this.migrationStateModel._sqlMigrationService?.name!)
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import * as azdata from 'azdata';
|
|||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { EOL } from 'os';
|
import { EOL } from 'os';
|
||||||
import { MigrationWizardPage } from '../models/migrationWizardPage';
|
import { MigrationWizardPage } from '../models/migrationWizardPage';
|
||||||
import { MigrationStateModel, MigrationTargetType, Page, StateChangeEvent } from '../models/stateMachine';
|
import { MigrationStateModel, MigrationTargetType, StateChangeEvent } from '../models/stateMachine';
|
||||||
import * as constants from '../constants/strings';
|
import * as constants from '../constants/strings';
|
||||||
import * as styles from '../constants/styles';
|
import * as styles from '../constants/styles';
|
||||||
import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
|
import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
|
||||||
import { deepClone, findDropDownItemIndex, selectDropDownIndex } from '../api/utils';
|
import { deepClone, findDropDownItemIndex, selectDropDownIndex, selectDefaultDropdownValue } from '../api/utils';
|
||||||
|
|
||||||
export class TargetSelectionPage extends MigrationWizardPage {
|
export class TargetSelectionPage extends MigrationWizardPage {
|
||||||
private _view!: azdata.ModelView;
|
private _view!: azdata.ModelView;
|
||||||
@@ -27,7 +27,6 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
|||||||
private _azureResourceDropdownLabel!: azdata.TextComponent;
|
private _azureResourceDropdownLabel!: azdata.TextComponent;
|
||||||
private _azureResourceDropdown!: azdata.DropDownComponent;
|
private _azureResourceDropdown!: azdata.DropDownComponent;
|
||||||
|
|
||||||
|
|
||||||
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
|
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
|
||||||
super(wizard, azdata.window.createWizardPage(constants.AZURE_SQL_TARGET_PAGE_TITLE), migrationStateModel);
|
super(wizard, azdata.window.createWizardPage(constants.AZURE_SQL_TARGET_PAGE_TITLE), migrationStateModel);
|
||||||
}
|
}
|
||||||
@@ -73,19 +72,21 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async onPageEnter(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
|
public async onPageEnter(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
|
||||||
|
|
||||||
switch (this.migrationStateModel._targetType) {
|
switch (this.migrationStateModel._targetType) {
|
||||||
case MigrationTargetType.SQLMI:
|
case MigrationTargetType.SQLMI:
|
||||||
this._pageDescription.value = constants.AZURE_SQL_TARGET_PAGE_DESCRIPTION(constants.SKU_RECOMMENDATION_MI_CARD_TEXT);
|
this._pageDescription.value = constants.AZURE_SQL_TARGET_PAGE_DESCRIPTION(constants.SKU_RECOMMENDATION_MI_CARD_TEXT);
|
||||||
this._azureResourceDropdownLabel.value = constants.AZURE_SQL_DATABASE_MANAGED_INSTANCE;
|
this._azureResourceDropdownLabel.value = constants.AZURE_SQL_DATABASE_MANAGED_INSTANCE;
|
||||||
|
this._azureResourceDropdown.ariaLabel = constants.AZURE_SQL_DATABASE_MANAGED_INSTANCE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MigrationTargetType.SQLVM:
|
case MigrationTargetType.SQLVM:
|
||||||
this._pageDescription.value = constants.AZURE_SQL_TARGET_PAGE_DESCRIPTION(constants.SKU_RECOMMENDATION_VM_CARD_TEXT);
|
this._pageDescription.value = constants.AZURE_SQL_TARGET_PAGE_DESCRIPTION(constants.SKU_RECOMMENDATION_VM_CARD_TEXT);
|
||||||
this._azureResourceDropdownLabel.value = constants.AZURE_SQL_DATABASE_VIRTUAL_MACHINE;
|
this._azureResourceDropdownLabel.value = constants.AZURE_SQL_DATABASE_VIRTUAL_MACHINE;
|
||||||
|
this._azureResourceDropdown.ariaLabel = constants.AZURE_SQL_DATABASE_VIRTUAL_MACHINE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.populateResourceInstanceDropdown();
|
||||||
await this.populateAzureAccountsDropdown();
|
await this.populateAzureAccountsDropdown();
|
||||||
|
|
||||||
this.wizard.registerNavigationValidator((pageChangeInfo) => {
|
this.wizard.registerNavigationValidator((pageChangeInfo) => {
|
||||||
@@ -99,23 +100,40 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((<azdata.CategoryValue>this._azureSubscriptionDropdown.value)?.displayName === constants.NO_SUBSCRIPTIONS_FOUND) {
|
if (!this.migrationStateModel._azureAccount) {
|
||||||
|
errors.push(constants.INVALID_ACCOUNT_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.migrationStateModel._targetSubscription ||
|
||||||
|
(<azdata.CategoryValue>this._azureSubscriptionDropdown.value)?.displayName === constants.NO_SUBSCRIPTIONS_FOUND) {
|
||||||
errors.push(constants.INVALID_SUBSCRIPTION_ERROR);
|
errors.push(constants.INVALID_SUBSCRIPTION_ERROR);
|
||||||
}
|
}
|
||||||
if ((<azdata.CategoryValue>this._azureLocationDropdown.value)?.displayName === constants.NO_LOCATION_FOUND) {
|
if (!this.migrationStateModel._location ||
|
||||||
|
(<azdata.CategoryValue>this._azureLocationDropdown.value)?.displayName === constants.NO_LOCATION_FOUND) {
|
||||||
errors.push(constants.INVALID_LOCATION_ERROR);
|
errors.push(constants.INVALID_LOCATION_ERROR);
|
||||||
}
|
}
|
||||||
if ((<azdata.CategoryValue>this._azureResourceGroupDropdown.value)?.displayName === constants.RESOURCE_GROUP_NOT_FOUND) {
|
if (!this.migrationStateModel._resourceGroup ||
|
||||||
|
(<azdata.CategoryValue>this._azureResourceGroupDropdown.value)?.displayName === constants.RESOURCE_GROUP_NOT_FOUND) {
|
||||||
errors.push(constants.INVALID_RESOURCE_GROUP_ERROR);
|
errors.push(constants.INVALID_RESOURCE_GROUP_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
const resourceDropdownValue = (<azdata.CategoryValue>this._azureResourceDropdown.value)?.displayName;
|
const resourceDropdownValue = (<azdata.CategoryValue>this._azureResourceDropdown.value)?.displayName;
|
||||||
if (resourceDropdownValue === constants.NO_MANAGED_INSTANCE_FOUND) {
|
switch (this.migrationStateModel._targetType) {
|
||||||
|
case MigrationTargetType.SQLMI: {
|
||||||
|
if (!this.migrationStateModel._targetServerInstance ||
|
||||||
|
resourceDropdownValue === constants.NO_MANAGED_INSTANCE_FOUND) {
|
||||||
errors.push(constants.INVALID_MANAGED_INSTANCE_ERROR);
|
errors.push(constants.INVALID_MANAGED_INSTANCE_ERROR);
|
||||||
}
|
}
|
||||||
else if (resourceDropdownValue === constants.NO_VIRTUAL_MACHINE_FOUND) {
|
break;
|
||||||
|
}
|
||||||
|
case MigrationTargetType.SQLVM: {
|
||||||
|
if (!this.migrationStateModel._targetServerInstance ||
|
||||||
|
resourceDropdownValue === constants.NO_VIRTUAL_MACHINE_FOUND) {
|
||||||
errors.push(constants.INVALID_VIRTUAL_MACHINE_ERROR);
|
errors.push(constants.INVALID_VIRTUAL_MACHINE_ERROR);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (errors.length > 0) {
|
if (errors.length > 0) {
|
||||||
this.wizard.message = {
|
this.wizard.message = {
|
||||||
@@ -175,8 +193,10 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
await this._azureAccountsDropdown.validate();
|
await this._azureAccountsDropdown.validate();
|
||||||
await this.populateSubscriptionDropdown();
|
} else {
|
||||||
|
this.migrationStateModel._azureAccount = undefined!;
|
||||||
}
|
}
|
||||||
|
await this.populateSubscriptionDropdown();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const linkAccountButton = this._view.modelBuilder.hyperlink()
|
const linkAccountButton = this._view.modelBuilder.hyperlink()
|
||||||
@@ -236,11 +256,7 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
|||||||
this.migrationStateModel._azureTenant = deepClone(selectedTenant);
|
this.migrationStateModel._azureTenant = deepClone(selectedTenant);
|
||||||
if (selectedIndex > -1) {
|
if (selectedIndex > -1) {
|
||||||
this.migrationStateModel._azureAccount.properties.tenants = [this.migrationStateModel.getTenant(selectedIndex)];
|
this.migrationStateModel._azureAccount.properties.tenants = [this.migrationStateModel.getTenant(selectedIndex)];
|
||||||
this.migrationStateModel._subscriptions = undefined!;
|
|
||||||
this.migrationStateModel._targetSubscription = undefined!;
|
|
||||||
this.migrationStateModel._databaseBackup.subscription = undefined!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this._accountTenantFlexContainer = this._view.modelBuilder.flexContainer()
|
this._accountTenantFlexContainer = this._view.modelBuilder.flexContainer()
|
||||||
@@ -285,10 +301,12 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
|||||||
if (selectedIndex > -1 &&
|
if (selectedIndex > -1 &&
|
||||||
value !== constants.NO_SUBSCRIPTIONS_FOUND) {
|
value !== constants.NO_SUBSCRIPTIONS_FOUND) {
|
||||||
this.migrationStateModel._targetSubscription = this.migrationStateModel.getSubscription(selectedIndex);
|
this.migrationStateModel._targetSubscription = this.migrationStateModel.getSubscription(selectedIndex);
|
||||||
this.migrationStateModel._targetServerInstance = undefined!;
|
} else {
|
||||||
this.migrationStateModel._sqlMigrationService = undefined!;
|
this.migrationStateModel._targetSubscription = undefined!;
|
||||||
await this.populateLocationDropdown();
|
|
||||||
}
|
}
|
||||||
|
this.migrationStateModel.refreshDatabaseBackupPage = true;
|
||||||
|
await this.populateLocationDropdown();
|
||||||
|
await this.populateResourceGroupDropdown();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const azureLocationLabel = this._view.modelBuilder.text().withProps({
|
const azureLocationLabel = this._view.modelBuilder.text().withProps({
|
||||||
@@ -315,8 +333,11 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
|||||||
if (selectedIndex > -1 &&
|
if (selectedIndex > -1 &&
|
||||||
value !== constants.NO_LOCATION_FOUND) {
|
value !== constants.NO_LOCATION_FOUND) {
|
||||||
this.migrationStateModel._location = this.migrationStateModel.getLocation(selectedIndex);
|
this.migrationStateModel._location = this.migrationStateModel.getLocation(selectedIndex);
|
||||||
await this.populateResourceGroupDropdown();
|
} else {
|
||||||
|
this.migrationStateModel._location = undefined!;
|
||||||
}
|
}
|
||||||
|
this.migrationStateModel.refreshDatabaseBackupPage = true;
|
||||||
|
await this.populateResourceInstanceDropdown();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const azureResourceGroupLabel = this._view.modelBuilder.text().withProps({
|
const azureResourceGroupLabel = this._view.modelBuilder.text().withProps({
|
||||||
@@ -340,12 +361,13 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
|||||||
}).component();
|
}).component();
|
||||||
this._disposables.push(this._azureResourceGroupDropdown.onValueChanged(async (value) => {
|
this._disposables.push(this._azureResourceGroupDropdown.onValueChanged(async (value) => {
|
||||||
const selectedIndex = findDropDownItemIndex(this._azureResourceGroupDropdown, value);
|
const selectedIndex = findDropDownItemIndex(this._azureResourceGroupDropdown, value);
|
||||||
if (selectedIndex > -1) {
|
if (selectedIndex > -1 &&
|
||||||
if (value !== constants.RESOURCE_GROUP_NOT_FOUND) {
|
value !== constants.RESOURCE_GROUP_NOT_FOUND) {
|
||||||
this.migrationStateModel._resourceGroup = this.migrationStateModel.getAzureResourceGroup(selectedIndex);
|
this.migrationStateModel._resourceGroup = this.migrationStateModel.getAzureResourceGroup(selectedIndex);
|
||||||
|
} else {
|
||||||
|
this.migrationStateModel._resourceGroup = undefined!;
|
||||||
}
|
}
|
||||||
await this.populateResourceInstanceDropdown();
|
await this.populateResourceInstanceDropdown();
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this._azureResourceDropdownLabel = this._view.modelBuilder.text().withProps({
|
this._azureResourceDropdownLabel = this._view.modelBuilder.text().withProps({
|
||||||
@@ -367,7 +389,7 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
|||||||
'margin-top': '-1em'
|
'margin-top': '-1em'
|
||||||
},
|
},
|
||||||
}).component();
|
}).component();
|
||||||
this._disposables.push(this._azureResourceDropdown.onValueChanged(value => {
|
this._disposables.push(this._azureResourceDropdown.onValueChanged(async (value) => {
|
||||||
const selectedIndex = findDropDownItemIndex(this._azureResourceDropdown, value);
|
const selectedIndex = findDropDownItemIndex(this._azureResourceDropdown, value);
|
||||||
if (selectedIndex > -1 &&
|
if (selectedIndex > -1 &&
|
||||||
value !== constants.NO_MANAGED_INSTANCE_FOUND &&
|
value !== constants.NO_MANAGED_INSTANCE_FOUND &&
|
||||||
@@ -383,6 +405,8 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
|||||||
this.migrationStateModel._targetServerInstance = this.migrationStateModel.getManagedInstance(selectedIndex);
|
this.migrationStateModel._targetServerInstance = this.migrationStateModel.getManagedInstance(selectedIndex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
this.migrationStateModel._targetServerInstance = undefined!;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -404,145 +428,91 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
|||||||
|
|
||||||
private async populateAzureAccountsDropdown(): Promise<void> {
|
private async populateAzureAccountsDropdown(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
this._azureAccountsDropdown.loading = true;
|
this.updateDropdownLoadingStatus(TargetDropDowns.AzureAccount, true);
|
||||||
this._azureSubscriptionDropdown.loading = true;
|
|
||||||
this._azureLocationDropdown.loading = true;
|
|
||||||
this._azureResourceGroupDropdown.loading = true;
|
|
||||||
this._azureResourceDropdown.loading = true;
|
|
||||||
|
|
||||||
this._azureAccountsDropdown.values = await this.migrationStateModel.getAccountValues();
|
this._azureAccountsDropdown.values = await this.migrationStateModel.getAccountValues();
|
||||||
|
selectDefaultDropdownValue(this._azureAccountsDropdown, this.migrationStateModel._azureAccount?.displayInfo?.userId, false);
|
||||||
if (this.hasSavedInfo() && this._azureAccountsDropdown.values) {
|
|
||||||
(<azdata.CategoryValue[]>this._azureAccountsDropdown.values)?.forEach((account, index) => {
|
|
||||||
if ((<azdata.CategoryValue>account).name.toLowerCase() === this.migrationStateModel.savedInfo.azureAccount?.displayInfo.userId.toLowerCase()) {
|
|
||||||
selectDropDownIndex(this._azureAccountsDropdown, index);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
selectDropDownIndex(this._azureAccountsDropdown, 0);
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
this._azureAccountsDropdown.loading = false;
|
this.updateDropdownLoadingStatus(TargetDropDowns.AzureAccount, false);
|
||||||
this._azureSubscriptionDropdown.loading = false;
|
|
||||||
this._azureLocationDropdown.loading = false;
|
|
||||||
this._azureResourceGroupDropdown.loading = false;
|
|
||||||
this._azureResourceDropdown.loading = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async populateSubscriptionDropdown(): Promise<void> {
|
private async populateSubscriptionDropdown(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
this._azureSubscriptionDropdown.loading = true;
|
this.updateDropdownLoadingStatus(TargetDropDowns.Subscription, true);
|
||||||
this._azureLocationDropdown.loading = true;
|
|
||||||
this._azureResourceGroupDropdown.loading = true;
|
|
||||||
this._azureResourceDropdown.loading = true;
|
|
||||||
|
|
||||||
this._azureSubscriptionDropdown.values = await this.migrationStateModel.getSubscriptionsDropdownValues();
|
this._azureSubscriptionDropdown.values = await this.migrationStateModel.getSubscriptionsDropdownValues();
|
||||||
if (this.hasSavedInfo() && this._azureSubscriptionDropdown.values) {
|
selectDefaultDropdownValue(this._azureSubscriptionDropdown, this.migrationStateModel._targetSubscription?.id, false);
|
||||||
this._azureSubscriptionDropdown.values!.forEach((subscription, index) => {
|
|
||||||
if ((<azdata.CategoryValue>subscription).name.toLowerCase() === this.migrationStateModel.savedInfo?.subscription?.id.toLowerCase()) {
|
|
||||||
selectDropDownIndex(this._azureSubscriptionDropdown, index);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
selectDropDownIndex(this._azureSubscriptionDropdown, 0);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
} finally {
|
} finally {
|
||||||
this._azureSubscriptionDropdown.loading = false;
|
this.updateDropdownLoadingStatus(TargetDropDowns.Subscription, false);
|
||||||
this._azureLocationDropdown.loading = false;
|
|
||||||
this._azureResourceGroupDropdown.loading = false;
|
|
||||||
this._azureResourceDropdown.loading = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async populateLocationDropdown(): Promise<void> {
|
public async populateLocationDropdown(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
this._azureLocationDropdown.loading = true;
|
this.updateDropdownLoadingStatus(TargetDropDowns.Location, true);
|
||||||
this._azureResourceGroupDropdown.loading = true;
|
|
||||||
this._azureResourceDropdown.loading = true;
|
|
||||||
|
|
||||||
this._azureLocationDropdown.values = await this.migrationStateModel.getAzureLocationDropdownValues(this.migrationStateModel._targetSubscription);
|
this._azureLocationDropdown.values = await this.migrationStateModel.getAzureLocationDropdownValues(this.migrationStateModel._targetSubscription);
|
||||||
if (this.hasSavedInfo() && this._azureLocationDropdown.values) {
|
selectDefaultDropdownValue(this._azureLocationDropdown, this.migrationStateModel._location?.displayName, true);
|
||||||
this._azureLocationDropdown.values.forEach((location, index) => {
|
|
||||||
if ((<azdata.CategoryValue>location)?.displayName.toLowerCase() === this.migrationStateModel.savedInfo?.location?.displayName.toLowerCase()) {
|
|
||||||
selectDropDownIndex(this._azureLocationDropdown, index);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
selectDropDownIndex(this._azureLocationDropdown, 0);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
} finally {
|
} finally {
|
||||||
this._azureLocationDropdown.loading = false;
|
this.updateDropdownLoadingStatus(TargetDropDowns.Location, false);
|
||||||
this._azureResourceGroupDropdown.loading = false;
|
|
||||||
this._azureResourceDropdown.loading = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async populateResourceGroupDropdown(): Promise<void> {
|
public async populateResourceGroupDropdown(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
this._azureResourceGroupDropdown.loading = true;
|
this.updateDropdownLoadingStatus(TargetDropDowns.ResourceGroup, true);
|
||||||
this._azureResourceDropdown.loading = true;
|
|
||||||
|
|
||||||
this._azureResourceGroupDropdown.values = await this.migrationStateModel.getAzureResourceGroupDropdownValues(this.migrationStateModel._targetSubscription);
|
this._azureResourceGroupDropdown.values = await this.migrationStateModel.getAzureResourceGroupDropdownValues(this.migrationStateModel._targetSubscription);
|
||||||
if (this.hasSavedInfo() && this._azureResourceGroupDropdown.values) {
|
selectDefaultDropdownValue(this._azureResourceGroupDropdown, this.migrationStateModel._resourceGroup?.id, false);
|
||||||
this._azureResourceGroupDropdown.values.forEach((resourceGroup, index) => {
|
|
||||||
if ((<azdata.CategoryValue>resourceGroup)?.name.toLowerCase() === this.migrationStateModel.savedInfo?.resourceGroup?.id.toLowerCase()) {
|
|
||||||
selectDropDownIndex(this._azureResourceGroupDropdown, index);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
selectDropDownIndex(this._azureResourceGroupDropdown, 0);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
} finally {
|
} finally {
|
||||||
this._azureResourceGroupDropdown.loading = false;
|
this.updateDropdownLoadingStatus(TargetDropDowns.ResourceGroup, false);
|
||||||
this._azureResourceDropdown.loading = false;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async populateResourceInstanceDropdown(): Promise<void> {
|
private async populateResourceInstanceDropdown(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
this._azureResourceDropdown.loading = true;
|
this.updateDropdownLoadingStatus(TargetDropDowns.ResourceInstance, true);
|
||||||
|
|
||||||
switch (this.migrationStateModel._targetType) {
|
switch (this.migrationStateModel._targetType) {
|
||||||
case MigrationTargetType.SQLVM:
|
case MigrationTargetType.SQLMI: {
|
||||||
this._azureResourceDropdown.values = await this.migrationStateModel.getSqlVirtualMachineValues(
|
this._azureResourceDropdown.values = await this.migrationStateModel.getManagedInstanceValues(this.migrationStateModel._targetSubscription, this.migrationStateModel._location, this.migrationStateModel._resourceGroup);
|
||||||
this.migrationStateModel._targetSubscription,
|
|
||||||
this.migrationStateModel._location,
|
|
||||||
this.migrationStateModel._resourceGroup);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MigrationTargetType.SQLMI:
|
|
||||||
this._azureResourceDropdown.values = await this.migrationStateModel.getManagedInstanceValues(
|
|
||||||
this.migrationStateModel._targetSubscription,
|
|
||||||
this.migrationStateModel._location,
|
|
||||||
this.migrationStateModel._resourceGroup);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MigrationTargetType.SQLVM: {
|
||||||
if (this.hasSavedInfo() && this._azureResourceDropdown.values) {
|
this._azureResourceDropdown.values = await this.migrationStateModel.getSqlVirtualMachineValues(this.migrationStateModel._targetSubscription, this.migrationStateModel._location, this.migrationStateModel._resourceGroup);
|
||||||
this._azureResourceDropdown.values.forEach((resource, index) => {
|
break;
|
||||||
if ((<azdata.CategoryValue>resource).name.toLowerCase() === this.migrationStateModel.savedInfo?.targetServerInstance?.name.toLowerCase()) {
|
|
||||||
selectDropDownIndex(this._azureResourceDropdown, index);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
} else {
|
|
||||||
selectDropDownIndex(this._azureResourceDropdown, 0);
|
|
||||||
}
|
}
|
||||||
|
selectDefaultDropdownValue(this._azureResourceDropdown, this.migrationStateModel._targetServerInstance?.name, true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
} finally {
|
} finally {
|
||||||
this._azureResourceDropdown.loading = false;
|
this.updateDropdownLoadingStatus(TargetDropDowns.ResourceInstance, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private hasSavedInfo(): boolean {
|
private updateDropdownLoadingStatus(dropdown: TargetDropDowns, loading: boolean): void {
|
||||||
return this.migrationStateModel.retryMigration || (this.migrationStateModel.resumeAssessment && this.migrationStateModel.savedInfo.closedPage >= Page.TargetSelection);
|
switch (dropdown) {
|
||||||
|
case TargetDropDowns.AzureAccount:
|
||||||
|
this._azureAccountsDropdown.loading = loading;
|
||||||
|
case TargetDropDowns.Subscription:
|
||||||
|
this._azureSubscriptionDropdown.loading = loading;
|
||||||
|
case TargetDropDowns.Location:
|
||||||
|
this._azureLocationDropdown.loading = loading;
|
||||||
|
case TargetDropDowns.ResourceGroup:
|
||||||
|
this._azureResourceGroupDropdown.loading = loading;
|
||||||
|
case TargetDropDowns.ResourceInstance:
|
||||||
|
this._azureResourceDropdown.loading = loading;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum TargetDropDowns {
|
||||||
|
AzureAccount,
|
||||||
|
Subscription,
|
||||||
|
Location,
|
||||||
|
ResourceGroup,
|
||||||
|
ResourceInstance,
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user