mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-28 17:23:19 -05:00
Add SQL DB offline migration wizard experience (#20403)
* sql db wizard with target selection * add database table selection * add sqldb to service and IR page * Code complete * navigation bug fixes * fix target db selection * improve sqldb error and status reporting * fix error count bug * remove table status inference * address review feedback * update resource strings and content * fix migraton status string, use localized value * fix ux navigation issues * fix back/fwd w/o changes from changing data
This commit is contained in:
@@ -24,134 +24,204 @@ export class SummaryPage extends MigrationWizardPage {
|
||||
|
||||
protected async registerContent(view: azdata.ModelView): Promise<void> {
|
||||
this._view = view;
|
||||
this._flexContainer = view.modelBuilder.flexContainer().withLayout({
|
||||
flexFlow: 'column'
|
||||
}).component();
|
||||
this._flexContainer = view.modelBuilder.flexContainer()
|
||||
.withLayout({ flexFlow: 'column' })
|
||||
.component();
|
||||
const form = view.modelBuilder.formContainer()
|
||||
.withFormItems(
|
||||
[
|
||||
{
|
||||
component: this._flexContainer
|
||||
}
|
||||
]
|
||||
);
|
||||
.withFormItems([{ component: this._flexContainer }])
|
||||
.component();
|
||||
|
||||
this._disposables.push(this._view.onClosed(e => {
|
||||
this._disposables.forEach(
|
||||
d => { try { d.dispose(); } catch { } });
|
||||
}));
|
||||
this._disposables.push(
|
||||
this._view.onClosed(e =>
|
||||
this._disposables.forEach(
|
||||
d => { try { d.dispose(); } catch { } })));
|
||||
|
||||
await view.initializeModel(form.component());
|
||||
await view.initializeModel(form);
|
||||
}
|
||||
|
||||
public async onPageEnter(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
|
||||
const targetDatabaseSummary = new TargetDatabaseSummaryDialog(this.migrationStateModel);
|
||||
const targetDatabaseHyperlink = this._view.modelBuilder.hyperlink().withProps({
|
||||
url: '',
|
||||
label: this.migrationStateModel._databasesForMigration?.length.toString(),
|
||||
CSSStyles: {
|
||||
...styles.BODY_CSS,
|
||||
'margin': '0px',
|
||||
'width': '300px',
|
||||
}
|
||||
}).component();
|
||||
const isSqlVmTarget = this.migrationStateModel._targetType === MigrationTargetType.SQLVM;
|
||||
const isSqlMiTarget = this.migrationStateModel._targetType === MigrationTargetType.SQLMI;
|
||||
const isSqlDbTarget = this.migrationStateModel._targetType === MigrationTargetType.SQLDB;
|
||||
const isNetworkShare = this.migrationStateModel._databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE;
|
||||
|
||||
this._disposables.push(targetDatabaseHyperlink.onDidClick(async e => {
|
||||
await targetDatabaseSummary.initialize();
|
||||
}));
|
||||
const targetDatabaseHyperlink = this._view.modelBuilder.hyperlink()
|
||||
.withProps({
|
||||
url: '',
|
||||
label: (this.migrationStateModel._databasesForMigration?.length ?? 0).toString(),
|
||||
CSSStyles: { ...styles.BODY_CSS, 'margin': '0px', 'width': '300px', }
|
||||
}).component();
|
||||
|
||||
this._disposables.push(
|
||||
targetDatabaseHyperlink.onDidClick(
|
||||
async e => await targetDatabaseSummary.initialize()));
|
||||
|
||||
const targetDatabaseRow = this._view.modelBuilder.flexContainer()
|
||||
.withLayout(
|
||||
{
|
||||
flexFlow: 'row',
|
||||
alignItems: 'center',
|
||||
})
|
||||
.withItems(
|
||||
[
|
||||
createLabelTextComponent(this._view, constants.SUMMARY_DATABASE_COUNT_LABEL,
|
||||
{
|
||||
...styles.BODY_CSS,
|
||||
'width': '300px',
|
||||
}
|
||||
),
|
||||
targetDatabaseHyperlink
|
||||
],
|
||||
{
|
||||
CSSStyles: {
|
||||
'margin-right': '5px'
|
||||
}
|
||||
})
|
||||
.withLayout({ flexFlow: 'row', alignItems: 'center', })
|
||||
.withItems([
|
||||
createLabelTextComponent(
|
||||
this._view,
|
||||
constants.SUMMARY_DATABASE_COUNT_LABEL,
|
||||
{ ...styles.BODY_CSS, 'width': '300px' }),
|
||||
targetDatabaseHyperlink],
|
||||
{ CSSStyles: { 'margin-right': '5px' } })
|
||||
.component();
|
||||
|
||||
this._flexContainer.addItems(
|
||||
[
|
||||
await createHeadingTextComponent(this._view, constants.ACCOUNTS_SELECTION_PAGE_TITLE, true),
|
||||
createInformationRow(this._view, constants.ACCOUNTS_SELECTION_PAGE_TITLE, this.migrationStateModel._azureAccount.displayInfo.displayName),
|
||||
|
||||
await createHeadingTextComponent(this._view, constants.SOURCE_DATABASES),
|
||||
this._flexContainer
|
||||
.addItems([
|
||||
await createHeadingTextComponent(
|
||||
this._view,
|
||||
constants.SOURCE_DATABASES),
|
||||
targetDatabaseRow,
|
||||
|
||||
await createHeadingTextComponent(this._view, constants.AZURE_SQL_TARGET_PAGE_TITLE),
|
||||
createInformationRow(this._view, constants.AZURE_SQL_TARGET_PAGE_TITLE, (this.migrationStateModel._targetType === MigrationTargetType.SQLVM) ? constants.SUMMARY_VM_TYPE : constants.SUMMARY_MI_TYPE),
|
||||
createInformationRow(this._view, constants.SUBSCRIPTION, this.migrationStateModel._targetSubscription.name),
|
||||
createInformationRow(this._view, constants.LOCATION, await this.migrationStateModel.getLocationDisplayName(this.migrationStateModel._targetServerInstance.location)),
|
||||
createInformationRow(this._view, constants.RESOURCE_GROUP, getResourceGroupFromId(this.migrationStateModel._targetServerInstance.id)),
|
||||
createInformationRow(this._view, (this.migrationStateModel._targetType === MigrationTargetType.SQLVM) ? constants.SUMMARY_VM_TYPE : constants.SUMMARY_MI_TYPE, await this.migrationStateModel.getLocationDisplayName(this.migrationStateModel._targetServerInstance.name!)),
|
||||
await createHeadingTextComponent(
|
||||
this._view,
|
||||
constants.AZURE_SQL_TARGET_PAGE_TITLE),
|
||||
createInformationRow(
|
||||
this._view,
|
||||
constants.ACCOUNTS_SELECTION_PAGE_TITLE,
|
||||
this.migrationStateModel._azureAccount.displayInfo.displayName),
|
||||
createInformationRow(
|
||||
this._view,
|
||||
constants.AZURE_SQL_TARGET_PAGE_TITLE,
|
||||
isSqlVmTarget
|
||||
? constants.SUMMARY_VM_TYPE
|
||||
: isSqlMiTarget
|
||||
? constants.SUMMARY_MI_TYPE
|
||||
: constants.SUMMARY_SQLDB_TYPE),
|
||||
createInformationRow(
|
||||
this._view,
|
||||
constants.SUBSCRIPTION,
|
||||
this.migrationStateModel._targetSubscription.name),
|
||||
createInformationRow(
|
||||
this._view,
|
||||
constants.LOCATION,
|
||||
await this.migrationStateModel.getLocationDisplayName(
|
||||
this.migrationStateModel._targetServerInstance.location)),
|
||||
createInformationRow(
|
||||
this._view,
|
||||
constants.RESOURCE_GROUP,
|
||||
getResourceGroupFromId(
|
||||
this.migrationStateModel._targetServerInstance.id)),
|
||||
createInformationRow(
|
||||
this._view,
|
||||
(isSqlVmTarget)
|
||||
? constants.SUMMARY_VM_TYPE
|
||||
: (isSqlMiTarget)
|
||||
? constants.SUMMARY_MI_TYPE
|
||||
: constants.SUMMARY_SQLDB_TYPE,
|
||||
await this.migrationStateModel.getLocationDisplayName(
|
||||
this.migrationStateModel._targetServerInstance.name!)),
|
||||
await createHeadingTextComponent(
|
||||
this._view,
|
||||
constants.DATABASE_BACKUP_MIGRATION_MODE_LABEL),
|
||||
createInformationRow(
|
||||
this._view,
|
||||
constants.MODE,
|
||||
this.migrationStateModel._databaseBackup.migrationMode === MigrationMode.ONLINE
|
||||
? constants.DATABASE_BACKUP_MIGRATION_MODE_ONLINE_LABEL
|
||||
: constants.DATABASE_BACKUP_MIGRATION_MODE_OFFLINE_LABEL),
|
||||
]);
|
||||
|
||||
await createHeadingTextComponent(this._view, constants.DATABASE_BACKUP_MIGRATION_MODE_LABEL),
|
||||
createInformationRow(this._view, constants.MODE, this.migrationStateModel._databaseBackup.migrationMode === MigrationMode.ONLINE ? constants.DATABASE_BACKUP_MIGRATION_MODE_ONLINE_LABEL : constants.DATABASE_BACKUP_MIGRATION_MODE_OFFLINE_LABEL),
|
||||
if (this.migrationStateModel._targetType !== MigrationTargetType.SQLDB) {
|
||||
this._flexContainer.addItems([
|
||||
await createHeadingTextComponent(
|
||||
this._view,
|
||||
constants.DATABASE_BACKUP_PAGE_TITLE),
|
||||
await this.createNetworkContainerRows()]);
|
||||
}
|
||||
|
||||
await createHeadingTextComponent(this._view, constants.DATABASE_BACKUP_PAGE_TITLE),
|
||||
await this.createNetworkContainerRows(),
|
||||
this._flexContainer.addItems([
|
||||
|
||||
await createHeadingTextComponent(this._view, constants.IR_PAGE_TITLE),
|
||||
createInformationRow(this._view, constants.SUBSCRIPTION, this.migrationStateModel._targetSubscription.name),
|
||||
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.IR_PAGE_TITLE, this.migrationStateModel._sqlMigrationService?.name!)
|
||||
]
|
||||
);
|
||||
|
||||
if (this.migrationStateModel._databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE && this.migrationStateModel._nodeNames?.length > 0) {
|
||||
this._flexContainer.addItem(createInformationRow(this._view, constants.SHIR, this.migrationStateModel._nodeNames.join(', ')));
|
||||
await createHeadingTextComponent(
|
||||
this._view,
|
||||
constants.IR_PAGE_TITLE),
|
||||
createInformationRow(
|
||||
this._view, constants.SUBSCRIPTION,
|
||||
this.migrationStateModel._targetSubscription.name),
|
||||
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.IR_PAGE_TITLE,
|
||||
this.migrationStateModel._sqlMigrationService?.name!)]);
|
||||
|
||||
if (isSqlDbTarget ||
|
||||
(isNetworkShare && this.migrationStateModel._nodeNames?.length > 0)) {
|
||||
|
||||
this._flexContainer.addItem(
|
||||
createInformationRow(
|
||||
this._view,
|
||||
constants.SHIR,
|
||||
this.migrationStateModel._nodeNames.join(', ')));
|
||||
}
|
||||
}
|
||||
|
||||
public async onPageLeave(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
|
||||
this._flexContainer.clearItems();
|
||||
this.wizard.registerNavigationValidator(async (pageChangeInfo) => {
|
||||
return true;
|
||||
});
|
||||
this.wizard.registerNavigationValidator(async (pageChangeInfo) => true);
|
||||
}
|
||||
|
||||
protected async handleStateChange(e: StateChangeEvent): Promise<void> {
|
||||
}
|
||||
|
||||
private async createNetworkContainerRows(): Promise<azdata.FlexContainer> {
|
||||
const flexContainer = this._view.modelBuilder.flexContainer().withLayout({
|
||||
flexFlow: 'column'
|
||||
}).component();
|
||||
const flexContainer = this._view.modelBuilder.flexContainer()
|
||||
.withLayout({ flexFlow: 'column' })
|
||||
.component();
|
||||
|
||||
const networkShare = this.migrationStateModel._databaseBackup.networkShares[0];
|
||||
switch (this.migrationStateModel._databaseBackup.networkContainerType) {
|
||||
case NetworkContainerType.NETWORK_SHARE:
|
||||
flexContainer.addItems(
|
||||
[
|
||||
createInformationRow(this._view, constants.BACKUP_LOCATION, constants.NETWORK_SHARE),
|
||||
createInformationRow(this._view, constants.USER_ACCOUNT, this.migrationStateModel._databaseBackup.networkShares[0].windowsUser),
|
||||
await createHeadingTextComponent(this._view, constants.AZURE_STORAGE_ACCOUNT_TO_UPLOAD_BACKUPS),
|
||||
createInformationRow(this._view, constants.SUBSCRIPTION, this.migrationStateModel._databaseBackup.subscription.name),
|
||||
createInformationRow(this._view, constants.LOCATION, this.migrationStateModel._databaseBackup.networkShares[0].storageAccount?.location),
|
||||
createInformationRow(this._view, constants.RESOURCE_GROUP, this.migrationStateModel._databaseBackup.networkShares[0].storageAccount?.resourceGroup!),
|
||||
createInformationRow(this._view, constants.STORAGE_ACCOUNT, this.migrationStateModel._databaseBackup.networkShares[0].storageAccount?.name!),
|
||||
]
|
||||
);
|
||||
flexContainer.addItems([
|
||||
createInformationRow(
|
||||
this._view,
|
||||
constants.BACKUP_LOCATION,
|
||||
constants.NETWORK_SHARE),
|
||||
createInformationRow(
|
||||
this._view,
|
||||
constants.USER_ACCOUNT,
|
||||
networkShare.windowsUser),
|
||||
await createHeadingTextComponent(
|
||||
this._view,
|
||||
constants.AZURE_STORAGE_ACCOUNT_TO_UPLOAD_BACKUPS),
|
||||
createInformationRow(
|
||||
this._view,
|
||||
constants.SUBSCRIPTION,
|
||||
this.migrationStateModel._databaseBackup.subscription.name),
|
||||
createInformationRow(
|
||||
this._view,
|
||||
constants.LOCATION,
|
||||
networkShare.storageAccount?.location),
|
||||
createInformationRow(
|
||||
this._view,
|
||||
constants.RESOURCE_GROUP,
|
||||
networkShare.storageAccount?.resourceGroup!),
|
||||
createInformationRow(
|
||||
this._view,
|
||||
constants.STORAGE_ACCOUNT,
|
||||
networkShare.storageAccount?.name!),
|
||||
]);
|
||||
break;
|
||||
case NetworkContainerType.BLOB_CONTAINER:
|
||||
flexContainer.addItems(
|
||||
[
|
||||
createInformationRow(this._view, constants.TYPE, constants.BLOB_CONTAINER),
|
||||
createInformationRow(this._view, constants.SUMMARY_AZURE_STORAGE_SUBSCRIPTION, this.migrationStateModel._databaseBackup.subscription.name)
|
||||
]
|
||||
);
|
||||
flexContainer.addItems([
|
||||
createInformationRow(
|
||||
this._view,
|
||||
constants.TYPE,
|
||||
constants.BLOB_CONTAINER),
|
||||
createInformationRow(
|
||||
this._view,
|
||||
constants.SUMMARY_AZURE_STORAGE_SUBSCRIPTION,
|
||||
this.migrationStateModel._databaseBackup.subscription.name)]);
|
||||
}
|
||||
return flexContainer;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user