diff --git a/extensions/sql-migration/.vscodeignore b/extensions/sql-migration/.vscodeignore
new file mode 100644
index 0000000000..f8160b9539
--- /dev/null
+++ b/extensions/sql-migration/.vscodeignore
@@ -0,0 +1,3 @@
+src/**
+tsconfig.json
+images/ADSMigration.gif
diff --git a/extensions/sql-migration/images/info.svg b/extensions/sql-migration/images/info.svg
new file mode 100644
index 0000000000..23d4b62d1c
--- /dev/null
+++ b/extensions/sql-migration/images/info.svg
@@ -0,0 +1,5 @@
+
diff --git a/extensions/sql-migration/media/ads.svg b/extensions/sql-migration/media/ads.svg
deleted file mode 100644
index a9f6620868..0000000000
--- a/extensions/sql-migration/media/ads.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-
\ No newline at end of file
diff --git a/extensions/sql-migration/package.json b/extensions/sql-migration/package.json
index 97ecc25f31..d9e5414a8c 100644
--- a/extensions/sql-migration/package.json
+++ b/extensions/sql-migration/package.json
@@ -2,7 +2,7 @@
"name": "sql-migration",
"displayName": "%displayName%",
"description": "%description%",
- "version": "0.0.13",
+ "version": "0.1.0",
"publisher": "Microsoft",
"preview": true,
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt",
diff --git a/extensions/sql-migration/src/constants/iconPathHelper.ts b/extensions/sql-migration/src/constants/iconPathHelper.ts
index 338ee60f11..fc348b100a 100644
--- a/extensions/sql-migration/src/constants/iconPathHelper.ts
+++ b/extensions/sql-migration/src/constants/iconPathHelper.ts
@@ -29,6 +29,7 @@ export class IconPathHelper {
public static sqlDatabaseWarningLogo: IconPath;
public static cancel: IconPath;
public static warning: IconPath;
+ public static info: IconPath;
public static setExtensionContext(context: vscode.ExtensionContext) {
IconPathHelper.copy = {
@@ -103,5 +104,9 @@ export class IconPathHelper {
light: context.asAbsolutePath('images/warning.svg'),
dark: context.asAbsolutePath('images/warning.svg')
};
+ IconPathHelper.info = {
+ light: context.asAbsolutePath('images/info.svg'),
+ dark: context.asAbsolutePath('images/infoBox.svg')
+ };
}
}
diff --git a/extensions/sql-migration/src/constants/strings.ts b/extensions/sql-migration/src/constants/strings.ts
index 0cfa75c887..1ed2bafb86 100644
--- a/extensions/sql-migration/src/constants/strings.ts
+++ b/extensions/sql-migration/src/constants/strings.ts
@@ -81,7 +81,7 @@ export const DATABASE_BACKUP_PAGE_TITLE = localize('sql.migration.database.page.
export const DATABASE_BACKUP_PAGE_DESCRIPTION = localize('sql.migration.database.page.description', "Select the location of your database backups to use for migration.");
export const DATABASE_BACKUP_NC_NETWORK_SHARE_RADIO_LABEL = localize('sql.migration.nc.network.share.radio.label', "My database backups are on a network share");
-export const DATABASE_BACKUP_NC_BLOB_STORAGE_RADIO_LABEL = localize('sql.migration.nc.blob.storage.radio.label', "My database backups are in an Azure Storage Blob Container (Coming soon)");
+export const DATABASE_BACKUP_NC_BLOB_STORAGE_RADIO_LABEL = localize('sql.migration.nc.blob.storage.radio.label', "My database backups are in an Azure Storage Blob Container");
export const DATABASE_BACKUP_NC_FILE_SHARE_RADIO_LABEL = localize('sql.migration.nc.file.share.radio.label', "My database backups are in an Azure Storage File Share (Coming soon)");
@@ -160,6 +160,7 @@ export const AUTHENTICATION_KEYS = localize('sql.migration.authentication.types'
export function SQL_MIGRATION_SERVICE_DETAILS_HEADER(sqlMigrationServiceName: string) {
return localize('sql.migration.service.header', "Azure Database Migration Service \"{0}\" details:`", sqlMigrationServiceName);
}
+export const DMS_PORTAL_INFO = localize('sql.migration.dms.portal.info', "Please note that any existing Azure Database Migration Service (DMS) in Azure portal will not show up in Azure Data Studio. DMS created in Azure Data Studio will not be visible in Azure portal yet.");
// create migration service dialog
export const CREATE_MIGRATION_SERVICE_TITLE = localize('sql.migration.services.dialog.title', "Create Azure Database Migration Service");
diff --git a/extensions/sql-migration/src/dialog/migrationCutover/migrationCutoverDialog.ts b/extensions/sql-migration/src/dialog/migrationCutover/migrationCutoverDialog.ts
index 2af17aa4c7..918a432778 100644
--- a/extensions/sql-migration/src/dialog/migrationCutover/migrationCutoverDialog.ts
+++ b/extensions/sql-migration/src/dialog/migrationCutover/migrationCutoverDialog.ts
@@ -515,7 +515,15 @@ export class MigrationCutoverDialog {
this._migrationStatus.value = migrationStatusTextValue ?? '---';
this._fullBackupFile.value = fullBackupFileName! ?? '-';
- this._backupLocation.value = this._model._migration.migrationContext.properties.backupConfiguration?.sourceLocation?.fileShare?.path! ?? '-';
+ let backupLocation;
+
+ // Displaying storage accounts and blob container for azure blob backups.
+ if (this._model._migration.migrationContext.properties.backupConfiguration.sourceLocation?.azureBlob) {
+ backupLocation = `${this._model._migration.migrationContext.properties.backupConfiguration.sourceLocation.azureBlob.storageAccountResourceId.split('/').pop()} - ${this._model._migration.migrationContext.properties.backupConfiguration.sourceLocation.azureBlob.blobContainerName}`;
+ } else {
+ backupLocation = this._model._migration.migrationContext.properties.backupConfiguration?.sourceLocation?.fileShare?.path! ?? '-';
+ }
+ this._backupLocation.value = backupLocation ?? '-';
this._lastAppliedLSN.value = lastAppliedSSN! ?? '-';
this._lastAppliedBackupFile.value = this._model.migrationStatus.properties.migrationStatusDetails?.lastRestoredFilename ?? '-';
@@ -538,7 +546,7 @@ export class MigrationCutoverDialog {
});
if (migrationStatusTextValue === MigrationStatus.InProgress) {
- const restoredCount = (this._model.migrationStatus.properties.migrationStatusDetails?.activeBackupSets.filter(a => a.listOfBackupFiles[0].status === 'Restored'))?.length!;
+ const restoredCount = (this._model.migrationStatus.properties.migrationStatusDetails?.activeBackupSets?.filter(a => a.listOfBackupFiles[0].status === 'Restored'))?.length ?? 0;
if (restoredCount > 0) {
this._cutoverButton.enabled = true;
}
diff --git a/extensions/sql-migration/src/wizard/databaseBackupPage.ts b/extensions/sql-migration/src/wizard/databaseBackupPage.ts
index 82a719759c..9685c9e69b 100644
--- a/extensions/sql-migration/src/wizard/databaseBackupPage.ts
+++ b/extensions/sql-migration/src/wizard/databaseBackupPage.ts
@@ -115,7 +115,6 @@ export class DatabaseBackupPage extends MigrationWizardPage {
.withProps({
name: buttonGroup,
label: constants.DATABASE_BACKUP_NC_BLOB_STORAGE_RADIO_LABEL,
- enabled: false,
CSSStyles: {
'font-size': '13px'
}
diff --git a/extensions/sql-migration/src/wizard/integrationRuntimePage.ts b/extensions/sql-migration/src/wizard/integrationRuntimePage.ts
index e070260b48..da517d64f7 100644
--- a/extensions/sql-migration/src/wizard/integrationRuntimePage.ts
+++ b/extensions/sql-migration/src/wizard/integrationRuntimePage.ts
@@ -57,6 +57,15 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
this._statusLoadingComponent = view.modelBuilder.loadingComponent().withItem(this.createDMSDetailsContainer()).component();
+ const dmsPortalInfo = this._view.modelBuilder.infoBox().withProps({
+ text: constants.DMS_PORTAL_INFO,
+ style: 'information',
+ CSSStyles: {
+ 'font-size': '13px'
+ },
+ width: WIZARD_INPUT_COMPONENT_WIDTH
+ }).component();
+
this._form = view.modelBuilder.formContainer()
.withFormItems(
[
@@ -66,6 +75,9 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
{
component: createNewMigrationService
},
+ {
+ component: dmsPortalInfo
+ },
{
component: this._statusLoadingComponent
}
diff --git a/extensions/sql-migration/src/wizard/migrationModePage.ts b/extensions/sql-migration/src/wizard/migrationModePage.ts
index 9634d57f3d..cf6f7fa68c 100644
--- a/extensions/sql-migration/src/wizard/migrationModePage.ts
+++ b/extensions/sql-migration/src/wizard/migrationModePage.ts
@@ -10,16 +10,19 @@ import { MigrationMode, MigrationStateModel, StateChangeEvent } from '../models/
import * as constants from '../constants/strings';
export class MigrationModePage extends MigrationWizardPage {
+ private _view!: azdata.ModelView;
+
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
super(wizard, azdata.window.createWizardPage(constants.DATABASE_BACKUP_MIGRATION_MODE_LABEL, 'MigrationModePage'), migrationStateModel);
this.wizardPage.description = constants.DATABASE_BACKUP_MIGRATION_MODE_DESCRIPTION;
}
protected async registerContent(view: azdata.ModelView): Promise {
+ this._view = view;
const form = view.modelBuilder.formContainer()
.withFormItems(
[
- this.migrationModeContainer(view),
+ this.migrationModeContainer(),
]
);
await view.initializeModel(form.component());
@@ -38,10 +41,10 @@ export class MigrationModePage extends MigrationWizardPage {
protected async handleStateChange(e: StateChangeEvent): Promise {
}
- private migrationModeContainer(view: azdata.ModelView): azdata.FormComponent {
+ private migrationModeContainer(): azdata.FormComponent {
const buttonGroup = 'cutoverContainer';
- const onlineButton = view.modelBuilder.radioButton().withProps({
+ const onlineButton = this._view.modelBuilder.radioButton().withProps({
label: constants.DATABASE_BACKUP_MIGRATION_MODE_ONLINE_LABEL,
name: buttonGroup,
CSSStyles: {
@@ -51,7 +54,7 @@ export class MigrationModePage extends MigrationWizardPage {
checked: true
}).component();
- const onlineDescription = view.modelBuilder.text().withProps({
+ const onlineDescription = this._view.modelBuilder.text().withProps({
value: constants.DATABASE_BACKUP_MIGRATION_MODE_ONLINE_DESCRIPTION,
CSSStyles: {
'font-size': '13px',
@@ -67,7 +70,7 @@ export class MigrationModePage extends MigrationWizardPage {
}
});
- const offlineButton = view.modelBuilder.radioButton().withProps({
+ const offlineButton = this._view.modelBuilder.radioButton().withProps({
label: constants.DATABASE_BACKUP_MIGRATION_MODE_OFFLINE_LABEL,
name: buttonGroup,
CSSStyles: {
@@ -76,7 +79,7 @@ export class MigrationModePage extends MigrationWizardPage {
},
}).component();
- const offlineDescription = view.modelBuilder.text().withProps({
+ const offlineDescription = this._view.modelBuilder.text().withProps({
value: constants.DATABASE_BACKUP_MIGRATION_MODE_OFFLINE_DESCRIPTION,
CSSStyles: {
'font-size': '13px',
@@ -93,7 +96,7 @@ export class MigrationModePage extends MigrationWizardPage {
}
});
- const flexContainer = view.modelBuilder.flexContainer().withItems(
+ const flexContainer = this._view.modelBuilder.flexContainer().withItems(
[
onlineButton,
onlineDescription,