mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-25 17:23:10 -05:00
add error banner for failed migration cutover and cancel migration (#17106)
This commit is contained in:
@@ -89,7 +89,7 @@ export class AssessmentResultsDialog {
|
||||
} else {
|
||||
this._model._miDbs = this._tree.selectedDbs();
|
||||
}
|
||||
this._skuRecommendationPage.refreshCardText();
|
||||
await this._skuRecommendationPage.refreshCardText();
|
||||
this.model.refreshDatabaseBackupPage = true;
|
||||
this._isOpen = false;
|
||||
}
|
||||
|
||||
@@ -183,8 +183,8 @@ export class SqlDatabaseTree {
|
||||
}
|
||||
).component();
|
||||
|
||||
this._disposables.push(this._databaseTable.onDataChanged(() => {
|
||||
this._databaseCount.updateProperties({
|
||||
this._disposables.push(this._databaseTable.onDataChanged(async () => {
|
||||
await this._databaseCount.updateProperties({
|
||||
'value': constants.DATABASES(this.selectedDbs().length, this._model._databaseAssessment.length)
|
||||
});
|
||||
}));
|
||||
@@ -198,10 +198,10 @@ export class SqlDatabaseTree {
|
||||
this._dbName.value = this._dbNames[e.row];
|
||||
this._recommendationTitle.value = constants.ISSUES_COUNT(this._activeIssues.length);
|
||||
this._recommendation.value = constants.ISSUES_DETAILS;
|
||||
this._resultComponent.updateCssStyles({
|
||||
await this._resultComponent.updateCssStyles({
|
||||
'display': 'block'
|
||||
});
|
||||
this._dbMessageContainer.updateCssStyles({
|
||||
await this._dbMessageContainer.updateCssStyles({
|
||||
'display': 'none'
|
||||
});
|
||||
await this.refreshResults();
|
||||
@@ -296,10 +296,10 @@ export class SqlDatabaseTree {
|
||||
this._disposables.push(this._instanceTable.onRowSelected(async (e) => {
|
||||
this._activeIssues = this._model._assessmentResults?.issues;
|
||||
this._dbName.value = this._serverName;
|
||||
this._resultComponent.updateCssStyles({
|
||||
await this._resultComponent.updateCssStyles({
|
||||
'display': 'block'
|
||||
});
|
||||
this._dbMessageContainer.updateCssStyles({
|
||||
await this._dbMessageContainer.updateCssStyles({
|
||||
'display': 'none'
|
||||
});
|
||||
this._recommendation.value = constants.WARNINGS_DETAILS;
|
||||
@@ -778,37 +778,37 @@ export class SqlDatabaseTree {
|
||||
if (this._targetType === MigrationTargetType.SQLMI) {
|
||||
if (this._activeIssues.length === 0) {
|
||||
/// show no issues here
|
||||
this._assessmentsTable.updateCssStyles({
|
||||
await this._assessmentsTable.updateCssStyles({
|
||||
'display': 'none',
|
||||
'border-right': 'none'
|
||||
});
|
||||
this._assessmentContainer.updateCssStyles({
|
||||
await this._assessmentContainer.updateCssStyles({
|
||||
'display': 'none'
|
||||
});
|
||||
this._noIssuesContainer.updateCssStyles({
|
||||
await this._noIssuesContainer.updateCssStyles({
|
||||
'display': 'flex'
|
||||
});
|
||||
} else {
|
||||
this._assessmentContainer.updateCssStyles({
|
||||
await this._assessmentContainer.updateCssStyles({
|
||||
'display': 'flex'
|
||||
});
|
||||
this._assessmentsTable.updateCssStyles({
|
||||
await this._assessmentsTable.updateCssStyles({
|
||||
'display': 'flex',
|
||||
'border-right': 'solid 1px'
|
||||
});
|
||||
this._noIssuesContainer.updateCssStyles({
|
||||
await this._noIssuesContainer.updateCssStyles({
|
||||
'display': 'none'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this._assessmentsTable.updateCssStyles({
|
||||
await this._assessmentsTable.updateCssStyles({
|
||||
'display': 'none',
|
||||
'border-right': 'none'
|
||||
});
|
||||
this._assessmentContainer.updateCssStyles({
|
||||
await this._assessmentContainer.updateCssStyles({
|
||||
'display': 'none'
|
||||
});
|
||||
this._noIssuesContainer.updateCssStyles({
|
||||
await this._noIssuesContainer.updateCssStyles({
|
||||
'display': 'flex'
|
||||
});
|
||||
this._recommendationTitle.value = constants.ASSESSMENT_RESULTS;
|
||||
|
||||
@@ -65,8 +65,8 @@ export class CreateResourceGroupDialog {
|
||||
return valid;
|
||||
}).component();
|
||||
|
||||
this._disposables.push(resourceGroupName.onTextChanged(e => {
|
||||
errorBox.updateCssStyles({
|
||||
this._disposables.push(resourceGroupName.onTextChanged(async e => {
|
||||
await errorBox.updateCssStyles({
|
||||
'display': 'none'
|
||||
});
|
||||
}));
|
||||
@@ -78,7 +78,7 @@ export class CreateResourceGroupDialog {
|
||||
}).component();
|
||||
|
||||
this._disposables.push(okButton.onDidClick(async e => {
|
||||
errorBox.updateCssStyles({
|
||||
await errorBox.updateCssStyles({
|
||||
'display': 'none'
|
||||
});
|
||||
okButton.enabled = false;
|
||||
@@ -88,12 +88,12 @@ export class CreateResourceGroupDialog {
|
||||
const resourceGroup = await createResourceGroup(this._azureAccount, this._subscription, resourceGroupName.value!, this._location);
|
||||
this._creationEvent.emit('done', resourceGroup);
|
||||
} catch (e) {
|
||||
errorBox.updateCssStyles({
|
||||
await errorBox.updateCssStyles({
|
||||
'display': 'inline'
|
||||
});
|
||||
errorBox.text = e.toString();
|
||||
cancelButton.enabled = true;
|
||||
resourceGroupName.validate();
|
||||
await resourceGroupName.validate();
|
||||
} finally {
|
||||
loading.loading = false;
|
||||
}
|
||||
@@ -182,8 +182,8 @@ export class CreateResourceGroupDialog {
|
||||
d => { try { d.dispose(); } catch { } });
|
||||
}));
|
||||
|
||||
return view.initializeModel(form).then(v => {
|
||||
resourceGroupName.focus();
|
||||
return view.initializeModel(form).then(async v => {
|
||||
await resourceGroupName.focus();
|
||||
});
|
||||
});
|
||||
this._dialogObject.okButton.label = constants.APPLY;
|
||||
|
||||
@@ -158,8 +158,8 @@ export class CreateSqlMigrationServiceDialog {
|
||||
d => { try { d.dispose(); } catch { } });
|
||||
}));
|
||||
|
||||
return view.initializeModel(form).then(() => {
|
||||
this.populateSubscriptions();
|
||||
return view.initializeModel(form).then(async () => {
|
||||
await this.populateSubscriptions();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -167,15 +167,15 @@ export class CreateSqlMigrationServiceDialog {
|
||||
this._testConnectionButton.hidden = true;
|
||||
this._disposables.push(this._testConnectionButton.onClick(async (e) => {
|
||||
this._refreshLoadingComponent.loading = true;
|
||||
this._connectionStatus.updateCssStyles({
|
||||
await this._connectionStatus.updateCssStyles({
|
||||
'display': 'none'
|
||||
});
|
||||
try {
|
||||
await this.refreshStatus();
|
||||
} catch (e) {
|
||||
vscode.window.showErrorMessage(e);
|
||||
void vscode.window.showErrorMessage(e);
|
||||
}
|
||||
this._connectionStatus.updateCssStyles({
|
||||
await this._connectionStatus.updateCssStyles({
|
||||
'display': 'inline'
|
||||
});
|
||||
this._refreshLoadingComponent.loading = false;
|
||||
@@ -275,7 +275,7 @@ export class CreateSqlMigrationServiceDialog {
|
||||
name: createdResourceGroup.name
|
||||
};
|
||||
this.migrationServiceResourceGroupDropdown.loading = false;
|
||||
this.migrationServiceResourceGroupDropdown.focus();
|
||||
await this.migrationServiceResourceGroupDropdown.focus();
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -547,7 +547,7 @@ export class CreateSqlMigrationServiceDialog {
|
||||
const state = migrationServiceStatus.properties.integrationRuntimeState;
|
||||
|
||||
if (state === 'Online') {
|
||||
this._connectionStatus.updateProperties(<azdata.InfoBoxComponentProperties>{
|
||||
await this._connectionStatus.updateProperties(<azdata.InfoBoxComponentProperties>{
|
||||
text: constants.SERVICE_READY(this._createdMigrationService!.name, this.irNodes.join(', ')),
|
||||
style: 'success',
|
||||
CSSStyles: {
|
||||
@@ -557,7 +557,7 @@ export class CreateSqlMigrationServiceDialog {
|
||||
this._dialogObject.okButton.enabled = true;
|
||||
} else {
|
||||
this._connectionStatus.text = constants.SERVICE_NOT_READY(this._createdMigrationService!.name);
|
||||
this._connectionStatus.updateProperties(<azdata.InfoBoxComponentProperties>{
|
||||
await this._connectionStatus.updateProperties(<azdata.InfoBoxComponentProperties>{
|
||||
text: constants.SERVICE_NOT_READY(this._createdMigrationService!.name),
|
||||
style: 'warning',
|
||||
CSSStyles: {
|
||||
@@ -581,9 +581,9 @@ export class CreateSqlMigrationServiceDialog {
|
||||
ariaLabel: constants.COPY_KEY1,
|
||||
}).component();
|
||||
|
||||
this._disposables.push(this._copyKey1Button.onDidClick((e) => {
|
||||
vscode.env.clipboard.writeText(<string>this.migrationServiceAuthKeyTable.dataValues![0][1].value);
|
||||
vscode.window.showInformationMessage(constants.SERVICE_KEY1_COPIED_HELP);
|
||||
this._disposables.push(this._copyKey1Button.onDidClick(async (e) => {
|
||||
await vscode.env.clipboard.writeText(<string>this.migrationServiceAuthKeyTable.dataValues![0][1].value);
|
||||
void vscode.window.showInformationMessage(constants.SERVICE_KEY1_COPIED_HELP);
|
||||
}));
|
||||
|
||||
this._copyKey2Button = this._view.modelBuilder.button().withProps({
|
||||
@@ -592,9 +592,9 @@ export class CreateSqlMigrationServiceDialog {
|
||||
ariaLabel: constants.COPY_KEY2,
|
||||
}).component();
|
||||
|
||||
this._disposables.push(this._copyKey2Button.onDidClick((e) => {
|
||||
vscode.env.clipboard.writeText(<string>this.migrationServiceAuthKeyTable.dataValues![1][1].value);
|
||||
vscode.window.showInformationMessage(constants.SERVICE_KEY2_COPIED_HELP);
|
||||
this._disposables.push(this._copyKey2Button.onDidClick(async (e) => {
|
||||
await vscode.env.clipboard.writeText(<string>this.migrationServiceAuthKeyTable.dataValues![1][1].value);
|
||||
void vscode.window.showInformationMessage(constants.SERVICE_KEY2_COPIED_HELP);
|
||||
}));
|
||||
|
||||
this._refreshKey1Button = this._view.modelBuilder.button().withProps({
|
||||
@@ -617,7 +617,7 @@ export class CreateSqlMigrationServiceDialog {
|
||||
//TODO: add refresh logic
|
||||
}));
|
||||
|
||||
this.migrationServiceAuthKeyTable.updateProperties({
|
||||
await this.migrationServiceAuthKeyTable.updateProperties({
|
||||
dataValues: [
|
||||
[
|
||||
{
|
||||
|
||||
@@ -115,9 +115,9 @@ export class ConfirmCutoverDialog {
|
||||
|
||||
this._dialogObject.okButton.enabled = false;
|
||||
this._dialogObject.okButton.label = constants.COMPLETE_CUTOVER;
|
||||
this._disposables.push(this._dialogObject.okButton.onClick((e) => {
|
||||
this.migrationCutoverModel.startCutover();
|
||||
vscode.window.showInformationMessage(constants.CUTOVER_IN_PROGRESS(this.migrationCutoverModel._migration.migrationContext.properties.sourceDatabaseName));
|
||||
this._disposables.push(this._dialogObject.okButton.onClick(async (e) => {
|
||||
await this.migrationCutoverModel.startCutover();
|
||||
void vscode.window.showInformationMessage(constants.CUTOVER_IN_PROGRESS(this.migrationCutoverModel._migration.migrationContext.properties.sourceDatabaseName));
|
||||
}));
|
||||
|
||||
const formBuilder = view.modelBuilder.formContainer().withFormItems(
|
||||
@@ -235,14 +235,14 @@ export class ConfirmCutoverDialog {
|
||||
if (expanded) {
|
||||
containerHeading.iconPath = IconPathHelper.expandButtonClosed;
|
||||
containerHeading.iconHeight = 12;
|
||||
fileTable.updateCssStyles({
|
||||
await fileTable.updateCssStyles({
|
||||
'display': 'none'
|
||||
});
|
||||
|
||||
} else {
|
||||
containerHeading.iconPath = IconPathHelper.expandButtonOpen;
|
||||
containerHeading.iconHeight = 8;
|
||||
fileTable.updateCssStyles({
|
||||
await fileTable.updateCssStyles({
|
||||
'display': 'inline'
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import { IconPathHelper } from '../../constants/iconPathHelper';
|
||||
import { MigrationContext, MigrationStatus } from '../../models/migrationLocalStorage';
|
||||
import { BackupFileInfoStatus, MigrationContext, MigrationStatus } from '../../models/migrationLocalStorage';
|
||||
import { MigrationCutoverDialogModel } from './migrationCutoverDialogModel';
|
||||
import * as loc from '../../constants/strings';
|
||||
import { convertByteSizeToReadableUnit, convertIsoTimeToLocalTime, getSqlServerName, getMigrationStatusImage, SupportedAutoRefreshIntervals, clearDialogMessage } from '../../api/utils';
|
||||
import { convertByteSizeToReadableUnit, convertIsoTimeToLocalTime, getSqlServerName, getMigrationStatusImage, SupportedAutoRefreshIntervals, clearDialogMessage, displayDialogErrorMessage } from '../../api/utils';
|
||||
import { EOL } from 'os';
|
||||
import { ConfirmCutoverDialog } from './confirmCutoverDialog';
|
||||
|
||||
@@ -201,7 +201,7 @@ export class MigrationCutoverDialog {
|
||||
let formItems = [
|
||||
{ component: this.migrationContainerHeader() },
|
||||
{ component: this._view.modelBuilder.separator().withProps({ width: 1000 }).component() },
|
||||
{ component: this.migrationInfoGrid() },
|
||||
{ component: await this.migrationInfoGrid() },
|
||||
{ component: this._view.modelBuilder.separator().withProps({ width: 1000 }).component() },
|
||||
{ component: this._fileCount },
|
||||
{ component: this._fileTable },
|
||||
@@ -316,6 +316,10 @@ export class MigrationCutoverDialog {
|
||||
const dialog = new ConfirmCutoverDialog(this._model);
|
||||
await dialog.initialize();
|
||||
await this.refreshStatus();
|
||||
|
||||
if (this._model.CutoverError) {
|
||||
displayDialogErrorMessage(this._dialogObject, loc.MIGRATION_CUTOVER_ERROR, this._model.CutoverError);
|
||||
}
|
||||
}));
|
||||
|
||||
headerActions.addItem(this._cutoverButton, {
|
||||
@@ -336,10 +340,13 @@ export class MigrationCutoverDialog {
|
||||
}).component();
|
||||
|
||||
this._disposables.push(this._cancelButton.onDidClick((e) => {
|
||||
vscode.window.showInformationMessage(loc.CANCEL_MIGRATION_CONFIRMATION, { modal: true }, loc.YES, loc.NO).then(async (v) => {
|
||||
void vscode.window.showInformationMessage(loc.CANCEL_MIGRATION_CONFIRMATION, { modal: true }, loc.YES, loc.NO).then(async (v) => {
|
||||
if (v === loc.YES) {
|
||||
await this._model.cancelMigration();
|
||||
await this.refreshStatus();
|
||||
if (this._model.CancelMigrationError) {
|
||||
displayDialogErrorMessage(this._dialogObject, loc.MIGRATION_CANCELLATION_ERROR, this._model.CancelMigrationError);
|
||||
}
|
||||
}
|
||||
});
|
||||
}));
|
||||
@@ -382,9 +389,9 @@ export class MigrationCutoverDialog {
|
||||
|
||||
this._disposables.push(this._copyDatabaseMigrationDetails.onDidClick(async (e) => {
|
||||
await this.refreshStatus();
|
||||
vscode.env.clipboard.writeText(this.getMigrationDetails());
|
||||
await vscode.env.clipboard.writeText(this.getMigrationDetails());
|
||||
|
||||
vscode.window.showInformationMessage(loc.DETAILS_COPIED);
|
||||
void vscode.window.showInformationMessage(loc.DETAILS_COPIED);
|
||||
}));
|
||||
|
||||
headerActions.addItem(this._copyDatabaseMigrationDetails, {
|
||||
@@ -451,7 +458,7 @@ export class MigrationCutoverDialog {
|
||||
return header;
|
||||
}
|
||||
|
||||
private migrationInfoGrid(): azdata.FlexContainer {
|
||||
private async migrationInfoGrid(): Promise<azdata.FlexContainer> {
|
||||
const addInfoFieldToContainer = (infoField: InfoFieldSchema, container: azdata.FlexContainer): void => {
|
||||
container.addItem(infoField.flexContainer, {
|
||||
CSSStyles: {
|
||||
@@ -463,9 +470,9 @@ export class MigrationCutoverDialog {
|
||||
const flexServer = this._view.modelBuilder.flexContainer().withLayout({
|
||||
flexFlow: 'column'
|
||||
}).component();
|
||||
this._sourceDatabaseInfoField = this.createInfoField(loc.SOURCE_DATABASE, '');
|
||||
this._sourceDetailsInfoField = this.createInfoField(loc.SOURCE_SERVER, '');
|
||||
this._sourceVersionInfoField = this.createInfoField(loc.SOURCE_VERSION, '');
|
||||
this._sourceDatabaseInfoField = await this.createInfoField(loc.SOURCE_DATABASE, '');
|
||||
this._sourceDetailsInfoField = await this.createInfoField(loc.SOURCE_SERVER, '');
|
||||
this._sourceVersionInfoField = await this.createInfoField(loc.SOURCE_VERSION, '');
|
||||
addInfoFieldToContainer(this._sourceDatabaseInfoField, flexServer);
|
||||
addInfoFieldToContainer(this._sourceDetailsInfoField, flexServer);
|
||||
addInfoFieldToContainer(this._sourceVersionInfoField, flexServer);
|
||||
@@ -473,9 +480,9 @@ export class MigrationCutoverDialog {
|
||||
const flexTarget = this._view.modelBuilder.flexContainer().withLayout({
|
||||
flexFlow: 'column'
|
||||
}).component();
|
||||
this._targetDatabaseInfoField = this.createInfoField(loc.TARGET_DATABASE_NAME, '');
|
||||
this._targetServerInfoField = this.createInfoField(loc.TARGET_SERVER, '');
|
||||
this._targetVersionInfoField = this.createInfoField(loc.TARGET_VERSION, '');
|
||||
this._targetDatabaseInfoField = await this.createInfoField(loc.TARGET_DATABASE_NAME, '');
|
||||
this._targetServerInfoField = await this.createInfoField(loc.TARGET_SERVER, '');
|
||||
this._targetVersionInfoField = await this.createInfoField(loc.TARGET_VERSION, '');
|
||||
addInfoFieldToContainer(this._targetDatabaseInfoField, flexTarget);
|
||||
addInfoFieldToContainer(this._targetServerInfoField, flexTarget);
|
||||
addInfoFieldToContainer(this._targetVersionInfoField, flexTarget);
|
||||
@@ -484,9 +491,9 @@ export class MigrationCutoverDialog {
|
||||
const flexStatus = this._view.modelBuilder.flexContainer().withLayout({
|
||||
flexFlow: 'column'
|
||||
}).component();
|
||||
this._migrationStatusInfoField = this.createInfoField(loc.MIGRATION_STATUS, '', false, ' ');
|
||||
this._fullBackupFileOnInfoField = this.createInfoField(loc.FULL_BACKUP_FILES, '', isBlobMigration);
|
||||
this._backupLocationInfoField = this.createInfoField(loc.BACKUP_LOCATION, '');
|
||||
this._migrationStatusInfoField = await this.createInfoField(loc.MIGRATION_STATUS, '', false, ' ');
|
||||
this._fullBackupFileOnInfoField = await this.createInfoField(loc.FULL_BACKUP_FILES, '', isBlobMigration);
|
||||
this._backupLocationInfoField = await this.createInfoField(loc.BACKUP_LOCATION, '');
|
||||
addInfoFieldToContainer(this._migrationStatusInfoField, flexStatus);
|
||||
addInfoFieldToContainer(this._fullBackupFileOnInfoField, flexStatus);
|
||||
addInfoFieldToContainer(this._backupLocationInfoField, flexStatus);
|
||||
@@ -494,9 +501,9 @@ export class MigrationCutoverDialog {
|
||||
const flexFile = this._view.modelBuilder.flexContainer().withLayout({
|
||||
flexFlow: 'column'
|
||||
}).component();
|
||||
this._lastLSNInfoField = this.createInfoField(loc.LAST_APPLIED_LSN, '', isBlobMigration);
|
||||
this._lastAppliedBackupInfoField = this.createInfoField(loc.LAST_APPLIED_BACKUP_FILES, '');
|
||||
this._lastAppliedBackupTakenOnInfoField = this.createInfoField(loc.LAST_APPLIED_BACKUP_FILES_TAKEN_ON, '', isBlobMigration);
|
||||
this._lastLSNInfoField = await this.createInfoField(loc.LAST_APPLIED_LSN, '', isBlobMigration);
|
||||
this._lastAppliedBackupInfoField = await this.createInfoField(loc.LAST_APPLIED_BACKUP_FILES, '');
|
||||
this._lastAppliedBackupTakenOnInfoField = await this.createInfoField(loc.LAST_APPLIED_BACKUP_FILES_TAKEN_ON, '', isBlobMigration);
|
||||
addInfoFieldToContainer(this._lastLSNInfoField, flexFile);
|
||||
addInfoFieldToContainer(this._lastAppliedBackupInfoField, flexFile);
|
||||
addInfoFieldToContainer(this._lastAppliedBackupTakenOnInfoField, flexFile);
|
||||
@@ -558,7 +565,7 @@ export class MigrationCutoverDialog {
|
||||
clearDialogMessage(this._dialogObject);
|
||||
|
||||
if (this._isOnlineMigration()) {
|
||||
this._cutoverButton.updateCssStyles({
|
||||
await this._cutoverButton.updateCssStyles({
|
||||
'display': 'inline'
|
||||
});
|
||||
}
|
||||
@@ -660,22 +667,22 @@ export class MigrationCutoverDialog {
|
||||
this._lastAppliedBackupTakenOnInfoField.text.value = lastAppliedBackupFileTakenOn! ? convertIsoTimeToLocalTime(lastAppliedBackupFileTakenOn).toLocaleString() : '-';
|
||||
|
||||
if (this._shouldDisplayBackupFileTable()) {
|
||||
this._fileCount.updateCssStyles({
|
||||
await this._fileCount.updateCssStyles({
|
||||
display: 'inline'
|
||||
});
|
||||
this._fileTable.updateCssStyles({
|
||||
await this._fileTable.updateCssStyles({
|
||||
display: 'inline'
|
||||
});
|
||||
|
||||
this._fileCount.value = loc.ACTIVE_BACKUP_FILES_ITEMS(tableData.length);
|
||||
|
||||
if (tableData.length === 0) {
|
||||
this._emptyTableFill.updateCssStyles({
|
||||
await this._emptyTableFill.updateCssStyles({
|
||||
'display': 'flex'
|
||||
});
|
||||
this._fileTable.height = '50px';
|
||||
} else {
|
||||
this._emptyTableFill.updateCssStyles({
|
||||
await this._emptyTableFill.updateCssStyles({
|
||||
'display': 'none'
|
||||
});
|
||||
this._fileTable.height = '300px';
|
||||
@@ -698,25 +705,21 @@ export class MigrationCutoverDialog {
|
||||
}
|
||||
}
|
||||
|
||||
this._cutoverButton.enabled = false;
|
||||
if (migrationStatusTextValue === MigrationStatus.InProgress) {
|
||||
const restoredCount = (this._model.migrationStatus.properties.migrationStatusDetails?.activeBackupSets?.filter(a => a.listOfBackupFiles[0].status === 'Restored'))?.length ?? 0;
|
||||
const restoredCount = this._model.migrationStatus.properties.migrationStatusDetails?.activeBackupSets?.filter(
|
||||
(a) => a.listOfBackupFiles[0].status === BackupFileInfoStatus.Restored)?.length ?? 0;
|
||||
|
||||
if (restoredCount > 0 || isBlobMigration) {
|
||||
this._cutoverButton.enabled = true;
|
||||
}
|
||||
} else {
|
||||
this._cutoverButton.enabled = false;
|
||||
}
|
||||
|
||||
this._cancelButton.enabled =
|
||||
migrationStatusTextValue === MigrationStatus.Creating ||
|
||||
migrationStatusTextValue === MigrationStatus.InProgress;
|
||||
|
||||
} catch (e) {
|
||||
this._dialogObject.message = {
|
||||
level: azdata.window.MessageLevel.Error,
|
||||
text: loc.MIGRATION_STATUS_REFRESH_ERROR,
|
||||
description: e.message
|
||||
};
|
||||
displayDialogErrorMessage(this._dialogObject, loc.MIGRATION_STATUS_REFRESH_ERROR, e);
|
||||
console.log(e);
|
||||
} finally {
|
||||
this.isRefreshing = false;
|
||||
@@ -724,17 +727,17 @@ export class MigrationCutoverDialog {
|
||||
}
|
||||
}
|
||||
|
||||
private createInfoField(label: string, value: string, defaultHidden: boolean = false, iconPath?: azdata.IconPath): {
|
||||
private async createInfoField(label: string, value: string, defaultHidden: boolean = false, iconPath?: azdata.IconPath): Promise<{
|
||||
flexContainer: azdata.FlexContainer,
|
||||
text: azdata.TextComponent,
|
||||
icon?: azdata.ImageComponent
|
||||
} {
|
||||
}> {
|
||||
const flexContainer = this._view.modelBuilder.flexContainer().withLayout({
|
||||
flexFlow: 'column'
|
||||
}).component();
|
||||
|
||||
if (defaultHidden) {
|
||||
flexContainer.updateCssStyles({
|
||||
await flexContainer.updateCssStyles({
|
||||
'display': 'none'
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,12 +4,14 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { getMigrationStatus, DatabaseMigration, startMigrationCutover, stopMigration, getMigrationAsyncOperationDetails, AzureAsyncOperationResource, BackupFileInfo, getResourceGroupFromId } from '../../api/azure';
|
||||
import { MigrationContext } from '../../models/migrationLocalStorage';
|
||||
import { BackupFileInfoStatus, MigrationContext } from '../../models/migrationLocalStorage';
|
||||
import { sendSqlMigrationActionEvent, TelemetryAction, TelemetryViews } from '../../telemtery';
|
||||
import * as constants from '../../constants/strings';
|
||||
import { getMigrationTargetType, getMigrationMode } from '../../constants/helper';
|
||||
|
||||
export class MigrationCutoverDialogModel {
|
||||
public CutoverError?: Error;
|
||||
public CancelMigrationError?: Error;
|
||||
|
||||
public migrationStatus!: DatabaseMigration;
|
||||
public migrationOpStatus!: AzureAsyncOperationResource;
|
||||
@@ -47,6 +49,7 @@ export class MigrationCutoverDialogModel {
|
||||
|
||||
public async startCutover(): Promise<DatabaseMigration | undefined> {
|
||||
try {
|
||||
this.CutoverError = undefined;
|
||||
if (this.migrationStatus) {
|
||||
const cutover = await startMigrationCutover(
|
||||
this._migration.azureAccount,
|
||||
@@ -66,6 +69,7 @@ export class MigrationCutoverDialogModel {
|
||||
return cutover;
|
||||
}
|
||||
} catch (error) {
|
||||
this.CutoverError = error;
|
||||
console.log(error);
|
||||
}
|
||||
return undefined!;
|
||||
@@ -73,6 +77,7 @@ export class MigrationCutoverDialogModel {
|
||||
|
||||
public async cancelMigration(): Promise<void> {
|
||||
try {
|
||||
this.CancelMigrationError = undefined;
|
||||
if (this.migrationStatus) {
|
||||
const cutoverStartTime = new Date().toString();
|
||||
await stopMigration(
|
||||
@@ -93,6 +98,7 @@ export class MigrationCutoverDialogModel {
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
this.CancelMigrationError = error;
|
||||
console.log(error);
|
||||
}
|
||||
return undefined!;
|
||||
@@ -126,7 +132,7 @@ export class MigrationCutoverDialogModel {
|
||||
const files: BackupFileInfo[] = [];
|
||||
this.migrationStatus.properties.migrationStatusDetails?.activeBackupSets?.forEach(abs => {
|
||||
abs.listOfBackupFiles.forEach(f => {
|
||||
if (f.status !== 'Restored') {
|
||||
if (f.status !== BackupFileInfoStatus.Restored) {
|
||||
files.push(f);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ import { MigrationContext, MigrationLocalStorage, MigrationStatus } from '../../
|
||||
import { MigrationCutoverDialog } from '../migrationCutover/migrationCutoverDialog';
|
||||
import { AdsMigrationStatus, MigrationStatusDialogModel } from './migrationStatusDialogModel';
|
||||
import * as loc from '../../constants/strings';
|
||||
import { clearDialogMessage, convertTimeDifferenceToDuration, filterMigrations, getMigrationStatusImage, SupportedAutoRefreshIntervals } from '../../api/utils';
|
||||
import { clearDialogMessage, convertTimeDifferenceToDuration, displayDialogErrorMessage, filterMigrations, getMigrationStatusImage, SupportedAutoRefreshIntervals } from '../../api/utils';
|
||||
import { SqlMigrationServiceDetailsDialog } from '../sqlMigrationService/sqlMigrationServiceDetailsDialog';
|
||||
import { ConfirmCutoverDialog } from '../migrationCutover/confirmCutoverDialog';
|
||||
import { MigrationCutoverDialogModel } from '../migrationCutover/migrationCutoverDialogModel';
|
||||
@@ -103,8 +103,8 @@ export class MigrationStatusDialog {
|
||||
width: '360px'
|
||||
}).component();
|
||||
|
||||
this._disposables.push(this._searchBox.onTextChanged((value) => {
|
||||
this.populateMigrationTable();
|
||||
this._disposables.push(this._searchBox.onTextChanged(async (value) => {
|
||||
await this.populateMigrationTable();
|
||||
}));
|
||||
|
||||
this._refresh = this._view.modelBuilder.button().withProps({
|
||||
@@ -136,8 +136,8 @@ export class MigrationStatusDialog {
|
||||
width: '220px'
|
||||
}).component();
|
||||
|
||||
this._disposables.push(this._statusDropdown.onValueChanged((value) => {
|
||||
this.populateMigrationTable();
|
||||
this._disposables.push(this._statusDropdown.onValueChanged(async (value) => {
|
||||
await this.populateMigrationTable();
|
||||
}));
|
||||
|
||||
if (this._filter) {
|
||||
@@ -204,16 +204,14 @@ export class MigrationStatusDialog {
|
||||
await cutoverDialogModel.fetchStatus();
|
||||
const dialog = new ConfirmCutoverDialog(cutoverDialogModel);
|
||||
await dialog.initialize();
|
||||
if (cutoverDialogModel.CutoverError) {
|
||||
displayDialogErrorMessage(this._dialogObject, loc.MIGRATION_CUTOVER_ERROR, cutoverDialogModel.CutoverError);
|
||||
}
|
||||
} else {
|
||||
await vscode.window.showInformationMessage(loc.MIGRATION_CANNOT_CUTOVER);
|
||||
}
|
||||
} catch (e) {
|
||||
this._dialogObject.message = {
|
||||
text: loc.MIGRATION_STATUS_REFRESH_ERROR,
|
||||
description: e.message,
|
||||
level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
|
||||
displayDialogErrorMessage(this._dialogObject, loc.MIGRATION_CUTOVER_ERROR, e);
|
||||
console.log(e);
|
||||
}
|
||||
}));
|
||||
@@ -273,12 +271,7 @@ export class MigrationStatusDialog {
|
||||
|
||||
await vscode.window.showInformationMessage(loc.DETAILS_COPIED);
|
||||
} catch (e) {
|
||||
this._dialogObject.message = {
|
||||
text: loc.MIGRATION_STATUS_REFRESH_ERROR,
|
||||
description: e.message,
|
||||
level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
|
||||
displayDialogErrorMessage(this._dialogObject, loc.MIGRATION_STATUS_REFRESH_ERROR, e);
|
||||
console.log(e);
|
||||
}
|
||||
}));
|
||||
@@ -290,23 +283,22 @@ export class MigrationStatusDialog {
|
||||
clearDialogMessage(this._dialogObject);
|
||||
const migration = this._model._migrations.find(migration => migration.migrationContext.id === migrationId);
|
||||
if (this.canCancelMigration(migration?.migrationContext.properties.migrationStatus)) {
|
||||
vscode.window.showInformationMessage(loc.CANCEL_MIGRATION_CONFIRMATION, loc.YES, loc.NO).then(async (v) => {
|
||||
void vscode.window.showInformationMessage(loc.CANCEL_MIGRATION_CONFIRMATION, loc.YES, loc.NO).then(async (v) => {
|
||||
if (v === loc.YES) {
|
||||
const cutoverDialogModel = new MigrationCutoverDialogModel(migration!);
|
||||
await cutoverDialogModel.fetchStatus();
|
||||
await cutoverDialogModel.cancelMigration();
|
||||
|
||||
if (cutoverDialogModel.CancelMigrationError) {
|
||||
displayDialogErrorMessage(this._dialogObject, loc.MIGRATION_CANNOT_CANCEL, cutoverDialogModel.CancelMigrationError);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
await vscode.window.showInformationMessage(loc.MIGRATION_CANNOT_CANCEL);
|
||||
}
|
||||
} catch (e) {
|
||||
this._dialogObject.message = {
|
||||
text: loc.MIGRATION_CANCELLATION_ERROR,
|
||||
description: e.message,
|
||||
level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
|
||||
displayDialogErrorMessage(this._dialogObject, loc.MIGRATION_CANCELLATION_ERROR, e);
|
||||
console.log(e);
|
||||
}
|
||||
}));
|
||||
@@ -508,12 +500,7 @@ export class MigrationStatusDialog {
|
||||
this._model._migrations = await MigrationLocalStorage.getMigrationsBySourceConnections(currentConnection, true);
|
||||
await this.populateMigrationTable();
|
||||
} catch (e) {
|
||||
this._dialogObject.message = {
|
||||
text: loc.MIGRATION_STATUS_REFRESH_ERROR,
|
||||
description: e.message,
|
||||
level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
|
||||
displayDialogErrorMessage(this._dialogObject, loc.MIGRATION_STATUS_REFRESH_ERROR, e);
|
||||
console.log(e);
|
||||
} finally {
|
||||
this.isRefreshing = false;
|
||||
|
||||
@@ -249,9 +249,9 @@ export class SqlMigrationServiceDetailsDialog {
|
||||
})
|
||||
.component();
|
||||
|
||||
this._disposables.push(copyKey1Button.onDidClick((e) => {
|
||||
vscode.env.clipboard.writeText(keys.authKey1);
|
||||
vscode.window.showInformationMessage(constants.SERVICE_KEY1_COPIED_HELP);
|
||||
this._disposables.push(copyKey1Button.onDidClick(async (e) => {
|
||||
await vscode.env.clipboard.writeText(keys.authKey1);
|
||||
void vscode.window.showInformationMessage(constants.SERVICE_KEY1_COPIED_HELP);
|
||||
}));
|
||||
|
||||
const copyKey2Button = view.modelBuilder
|
||||
@@ -265,9 +265,9 @@ export class SqlMigrationServiceDetailsDialog {
|
||||
})
|
||||
.component();
|
||||
|
||||
this._disposables.push(copyKey2Button.onDidClick((e) => {
|
||||
vscode.env.clipboard.writeText(keys.authKey2);
|
||||
vscode.window.showInformationMessage(constants.SERVICE_KEY2_COPIED_HELP);
|
||||
this._disposables.push(copyKey2Button.onDidClick(async (e) => {
|
||||
await vscode.env.clipboard.writeText(keys.authKey2);
|
||||
void vscode.window.showInformationMessage(constants.SERVICE_KEY2_COPIED_HELP);
|
||||
}));
|
||||
|
||||
const refreshKey1Button = view.modelBuilder
|
||||
@@ -296,7 +296,7 @@ export class SqlMigrationServiceDetailsDialog {
|
||||
this._disposables.push(refreshKey2Button.onDidClick(
|
||||
async (e) => await this._regenerateAuthKey(view, migrationContext, AUTH_KEY2)));
|
||||
|
||||
this._migrationServiceAuthKeyTable.updateProperties({
|
||||
await this._migrationServiceAuthKeyTable.updateProperties({
|
||||
dataValues: [
|
||||
[
|
||||
{ value: constants.SERVICE_KEY1_LABEL },
|
||||
|
||||
Reference in New Issue
Block a user