Adding blob storage support (WIP) (#15477)

Bumping version
Fixing cancel migration bug
This commit is contained in:
Aasim Khan
2021-05-14 17:24:36 +00:00
committed by GitHub
parent 12e0f24ef8
commit 71db7ed101
11 changed files with 575 additions and 505 deletions

View File

@@ -2,7 +2,7 @@
"name": "sql-migration", "name": "sql-migration",
"displayName": "%displayName%", "displayName": "%displayName%",
"description": "%description%", "description": "%description%",
"version": "0.0.12", "version": "0.0.13",
"publisher": "Microsoft", "publisher": "Microsoft",
"preview": true, "preview": true,
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt", "license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt",

View File

@@ -347,11 +347,11 @@ export interface StartDatabaseMigrationRequest {
sourceDatabaseName: string, sourceDatabaseName: string,
migrationService: string, migrationService: string,
backupConfiguration: { backupConfiguration: {
targetLocation: { targetLocation?: {
storageAccountResourceId: string, storageAccountResourceId: string,
accountKey: string, accountKey: string,
}, },
sourceLocation: SourceLocation sourceLocation?: SourceLocation
}, },
sourceSqlConnection: { sourceSqlConnection: {
authentication: string, authentication: string,
@@ -416,8 +416,8 @@ export interface SqlConnectionInfo {
} }
export interface BackupConfiguration { export interface BackupConfiguration {
sourceLocation: SourceLocation; sourceLocation?: SourceLocation;
targetLocation: TargetLocation; targetLocation?: TargetLocation;
} }
export interface AutoCutoverConfiguration { export interface AutoCutoverConfiguration {
@@ -454,7 +454,7 @@ export interface TargetLocation {
export interface BackupFileInfo { export interface BackupFileInfo {
fileName: string; fileName: string;
status: string; status: 'Arrived' | 'Uploading' | 'Uploaded' | 'Restoring' | 'Restored' | 'Cancelled' | 'Ignored';
} }
export interface DatabaseMigrationFileShare { export interface DatabaseMigrationFileShare {

View File

@@ -51,7 +51,8 @@ export const VIEW_SELECT_BUTTON_LABEL = localize('sql.migration.view.select.butt
export function TOTAL_DATABASES_SELECTED(selectedDbCount: number, totalDbCount: number): string { export function TOTAL_DATABASES_SELECTED(selectedDbCount: number, totalDbCount: number): string {
return localize('total.databases.selected', "{0} of {1} Database(s) selected.", selectedDbCount, totalDbCount); return localize('total.databases.selected', "{0} of {1} Database(s) selected.", selectedDbCount, totalDbCount);
} }
export const SELECT_TARGET_TO_CONTINUE = localize('sql.migration.select.target.to.continue', "Please select a target to continue");
export const SELECT_DATABASE_TO_MIGRATE = localize('sql.migration.select.database.to.migrate', "Please select databases to migrate");
export const ASSESSMENT_COMPLETED = (serverName: string): string => { export const ASSESSMENT_COMPLETED = (serverName: string): string => {
return localize('sql.migration.generic.congratulations', "We have completed the assessment of your SQL Server Instance '{0}'.", serverName); return localize('sql.migration.generic.congratulations', "We have completed the assessment of your SQL Server Instance '{0}'.", serverName);
}; };
@@ -83,6 +84,8 @@ export const DATABASE_BACKUP_NC_NETWORK_SHARE_RADIO_LABEL = localize('sql.migrat
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 (Coming soon)");
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)"); 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)");
export const DATABASE_BACKUP_NETWORK_SHARE_HEADER_TEXT = localize('sql.migration.network.share.header.text', "Network share details"); export const DATABASE_BACKUP_NETWORK_SHARE_HEADER_TEXT = localize('sql.migration.network.share.header.text', "Network share details");
export const DATABASE_BACKUP_NC_NETWORK_SHARE_HELP_TEXT = localize('sql.migration.network.share.help.text', "Provide the network share location that contains backups and the user credentials that has read access to the share"); export const DATABASE_BACKUP_NC_NETWORK_SHARE_HELP_TEXT = localize('sql.migration.network.share.help.text', "Provide the network share location that contains backups and the user credentials that has read access to the share");
export const DATABASE_BACKUP_NETWORK_SHARE_LOCATION_LABEL = localize('sql.migration.network.share.location.label', "Network share location that contains backups."); export const DATABASE_BACKUP_NETWORK_SHARE_LOCATION_LABEL = localize('sql.migration.network.share.location.label', "Network share location that contains backups.");
@@ -97,8 +100,8 @@ export const DATABASE_BACKUP_SUBSCRIPTION_PLACEHOLDER = localize('sql.migration.
export const DATABASE_BACKUP_NETWORK_SHARE_NETWORK_STORAGE_ACCOUNT_LABEL = localize('sql.migration.network.share.storage.account.label', "Select the storage account where backup files will be copied."); export const DATABASE_BACKUP_NETWORK_SHARE_NETWORK_STORAGE_ACCOUNT_LABEL = localize('sql.migration.network.share.storage.account.label', "Select the storage account where backup files will be copied.");
export const DATABASE_BACKUP_STORAGE_ACCOUNT_PLACEHOLDER = localize('sql.migration.network.share.storage.account.placeholder', "Select account"); export const DATABASE_BACKUP_STORAGE_ACCOUNT_PLACEHOLDER = localize('sql.migration.network.share.storage.account.placeholder', "Select account");
export const DUPLICATE_NAME_ERROR = localize('sql.migration.unique.name', "Select a unique name for this target database"); export const DUPLICATE_NAME_ERROR = localize('sql.migration.unique.name', "Select a unique name for this target database");
export function DATABASE_ALREADY_EXISTS_MI(targetName: string): string { export function DATABASE_ALREADY_EXISTS_MI(dbName: string, targetName: string): string {
return localize('sql.migration.database.already.exists', "Database with the same name already exists on target Managed Instance '{0}'", targetName); return localize('sql.migration.database.already.exists', "Database '{0}' already exists on target Managed Instance '{1}'.", dbName, targetName);
} }
export const DATABASE_BACKUP_BLOB_STORAGE_SUBSCRIPTION_LABEL = localize('sql.migration.blob.storage.subscription.label', "Select the subscription that contains the storage account."); export const DATABASE_BACKUP_BLOB_STORAGE_SUBSCRIPTION_LABEL = localize('sql.migration.blob.storage.subscription.label', "Select the subscription that contains the storage account.");
export const DATABASE_BACKUP_BLOB_STORAGE_ACCOUNT_LABEL = localize('sql.migration.blob.storage.account.label', "Select the storage account that contains the backup files."); export const DATABASE_BACKUP_BLOB_STORAGE_ACCOUNT_LABEL = localize('sql.migration.blob.storage.account.label', "Select the storage account that contains the backup files.");
@@ -128,9 +131,6 @@ export const INVALID_FILESHARE_ERROR = localize('sql.migration.invalid.fileShare
export const INVALID_BLOBCONTAINER_ERROR = localize('sql.migration.invalid.blobContainer.error', "Please select a valid blob container to proceed."); export const INVALID_BLOBCONTAINER_ERROR = localize('sql.migration.invalid.blobContainer.error', "Please select a valid blob container to proceed.");
export const INVALID_NETWORK_SHARE_LOCATION = localize('sql.migration.invalid.network.share.location', "Invalid network share location format. Example: {0}", '\\\\Servername.domainname.com\\Backupfolder'); export const INVALID_NETWORK_SHARE_LOCATION = localize('sql.migration.invalid.network.share.location', "Invalid network share location format. Example: {0}", '\\\\Servername.domainname.com\\Backupfolder');
export const INVALID_USER_ACCOUNT = localize('sql.migration.invalid.user.account', "Invalid user account format. Example: {0}", 'Domain\\username'); export const INVALID_USER_ACCOUNT = localize('sql.migration.invalid.user.account', "Invalid user account format. Example: {0}", 'Domain\\username');
export function TARGET_NAME_FOR_DATABASE(dbName: string): string {
return localize('sql.migration.target.name.for.database', 'Target name for database {0}', dbName);
}
export function TARGET_NETWORK_SHARE_LOCATION(dbName: string): string { export function TARGET_NETWORK_SHARE_LOCATION(dbName: string): string {
return localize('sql.migration.network.share.location', "Network share location to read backups for database {0}", dbName); return localize('sql.migration.network.share.location', "Network share location to read backups for database {0}", dbName);
} }
@@ -236,6 +236,7 @@ export const MODE = localize('sql.migration.mode', "Mode");
export const BACKUP_LOCATION = localize('sql.migration.backup.location', "Backup Location"); export const BACKUP_LOCATION = localize('sql.migration.backup.location', "Backup Location");
export const AZURE_STORAGE_ACCOUNT_TO_UPLOAD_BACKUPS = localize('sql.migration.azure.storage.account.to.upload.backups', "Azure Storage Account to Upload Backups"); export const AZURE_STORAGE_ACCOUNT_TO_UPLOAD_BACKUPS = localize('sql.migration.azure.storage.account.to.upload.backups', "Azure Storage Account to Upload Backups");
export const SHIR = localize('sql.migration.shir', "Self-hosted Integration Runtime node"); export const SHIR = localize('sql.migration.shir', "Self-hosted Integration Runtime node");
export const TARGET_NAME = localize('sql.migration.summary.target.name', "Target Databases:");
// Open notebook quick pick string // Open notebook quick pick string
export const NOTEBOOK_QUICK_PICK_PLACEHOLDER = localize('sql.migration.quick.pick.placeholder', "Select the operation you'd like to perform"); export const NOTEBOOK_QUICK_PICK_PLACEHOLDER = localize('sql.migration.quick.pick.placeholder', "Select the operation you'd like to perform");

View File

@@ -538,7 +538,11 @@ export class MigrationCutoverDialog {
}); });
if (migrationStatusTextValue === MigrationStatus.InProgress) { if (migrationStatusTextValue === MigrationStatus.InProgress) {
this._cutoverButton.enabled = tableData.length > 0; const restoredCount = (this._model.migrationStatus.properties.migrationStatusDetails?.activeBackupSets.filter(a => a.listOfBackupFiles[0].status === 'Restored'))?.length!;
if (restoredCount > 0) {
this._cutoverButton.enabled = true;
}
this._cancelButton.enabled = true;
} else { } else {
this._cutoverButton.enabled = false; this._cutoverButton.enabled = false;
this._cancelButton.enabled = false; this._cancelButton.enabled = false;

View File

@@ -28,11 +28,13 @@ export class MigrationLocalStorage {
if (refreshStatus) { if (refreshStatus) {
try { try {
const backupConfiguration = migration.migrationContext.properties.backupConfiguration; const backupConfiguration = migration.migrationContext.properties.backupConfiguration;
const sourceDatabase = migration.migrationContext.properties.sourceDatabaseName;
migration.migrationContext = await getMigrationStatus( migration.migrationContext = await getMigrationStatus(
migration.azureAccount, migration.azureAccount,
migration.subscription, migration.subscription,
migration.migrationContext migration.migrationContext
); );
migration.migrationContext.properties.sourceDatabaseName = sourceDatabase;
migration.migrationContext.properties.backupConfiguration = backupConfiguration; migration.migrationContext.properties.backupConfiguration = backupConfiguration;
if (migration.asyncUrl) { if (migration.asyncUrl) {
migration.asyncOperationResult = await getMigrationAsyncOperationDetails( migration.asyncOperationResult = await getMigrationAsyncOperationDetails(

View File

@@ -55,26 +55,29 @@ export enum NetworkContainerType {
NETWORK_SHARE NETWORK_SHARE
} }
export interface DatabaseBackupModel {
migrationMode: MigrationMode;
networkContainerType: NetworkContainerType;
storageKey: string;
networkShare: NetworkShare;
subscription: azureResource.AzureResourceSubscription;
blob: Blob;
}
export interface NetworkShare { export interface NetworkShare {
networkShareLocation: string; networkShareLocation: string;
windowsUser: string; windowsUser: string;
password: string; password: string;
}
export interface DatabaseBackupModel {
migrationMode: MigrationMode;
networkContainerType: NetworkContainerType;
networkShareLocation: string;
windowsUser: string;
password: string;
subscription: azureResource.AzureResourceSubscription;
resourceGroup: azureResource.AzureResourceResourceGroup; resourceGroup: azureResource.AzureResourceResourceGroup;
storageAccount: StorageAccount; storageAccount: StorageAccount;
storageKey: string;
azureSecurityToken: string;
fileShares: azureResource.FileShare[];
blobContainers: azureResource.BlobContainer[];
} }
export interface Blob {
resourceGroup: azureResource.AzureResourceResourceGroup;
storageAccount: StorageAccount;
blobContainer: azureResource.BlobContainer;
}
export interface Model { export interface Model {
readonly sourceConnectionId: string; readonly sourceConnectionId: string;
readonly currentState: State; readonly currentState: State;
@@ -140,6 +143,8 @@ export class MigrationStateModel implements Model, vscode.Disposable {
) { ) {
this._currentState = State.INIT; this._currentState = State.INIT;
this._databaseBackup = {} as DatabaseBackupModel; this._databaseBackup = {} as DatabaseBackupModel;
this._databaseBackup.networkShare = {} as NetworkShare;
this._databaseBackup.blob = {} as Blob;
} }
public get sourceConnectionId(): string { public get sourceConnectionId(): string {
@@ -490,15 +495,15 @@ export class MigrationStateModel implements Model, vscode.Disposable {
return this._targetSqlVirtualMachines[index]; return this._targetSqlVirtualMachines[index];
} }
public async getStorageAccountValues(subscription: azureResource.AzureResourceSubscription): Promise<azdata.CategoryValue[]> { public async getStorageAccountValues(subscription: azureResource.AzureResourceSubscription, resourceGroup: azureResource.AzureResourceResourceGroup): Promise<azdata.CategoryValue[]> {
let storageAccountValues: azdata.CategoryValue[] = []; let storageAccountValues: azdata.CategoryValue[] = [];
if (!this._databaseBackup.resourceGroup) { if (!resourceGroup) {
return storageAccountValues; return storageAccountValues;
} }
try { try {
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() === this._databaseBackup.resourceGroup.name.toLowerCase(); return sa.location.toLowerCase() === this._targetServerInstance.location.toLowerCase() && sa.resourceGroup?.toLowerCase() === resourceGroup.name.toLowerCase();
}); });
this._storageAccounts.forEach((storageAccount) => { this._storageAccounts.forEach((storageAccount) => {
storageAccountValues.push({ storageAccountValues.push({
@@ -652,19 +657,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
properties: { properties: {
sourceDatabaseName: '', sourceDatabaseName: '',
migrationService: this._sqlMigrationService?.id!, migrationService: this._sqlMigrationService?.id!,
backupConfiguration: { backupConfiguration: {},
targetLocation: {
storageAccountResourceId: this._databaseBackup.storageAccount.id,
accountKey: this._databaseBackup.storageKey,
},
sourceLocation: {
fileShare: {
path: this._databaseBackup.networkShareLocation,
username: this._databaseBackup.windowsUser,
password: this._databaseBackup.password,
}
},
},
sourceSqlConnection: { sourceSqlConnection: {
dataSource: currentConnection?.serverName!, dataSource: currentConnection?.serverName!,
authentication: this._authenticationType, authentication: this._authenticationType,
@@ -674,11 +667,39 @@ export class MigrationStateModel implements Model, vscode.Disposable {
scope: this._targetServerInstance.id scope: this._targetServerInstance.id
} }
}; };
switch (this._databaseBackup.networkContainerType) {
case NetworkContainerType.BLOB_CONTAINER:
requestBody.properties.backupConfiguration = {
targetLocation: undefined!,
sourceLocation: {
azureBlob: {
storageAccountResourceId: this._databaseBackup.blob.storageAccount.id,
accountKey: this._databaseBackup.storageKey,
blobContainerName: this._databaseBackup.blob.blobContainer.name
}
}
};
break;
case NetworkContainerType.NETWORK_SHARE:
requestBody.properties.backupConfiguration = {
targetLocation: {
storageAccountResourceId: this._databaseBackup.networkShare.storageAccount.id,
accountKey: this._databaseBackup.storageKey,
},
sourceLocation: {
fileShare: {
path: this._databaseBackup.networkShare.networkShareLocation,
username: this._databaseBackup.networkShare.windowsUser,
password: this._databaseBackup.networkShare.password,
}
}
};
break;
}
for (let i = 0; i < this._migrationDbs.length; i++) { for (let i = 0; i < this._migrationDbs.length; i++) {
requestBody.properties.sourceDatabaseName = this._migrationDbs[i];
try { try {
requestBody.properties.backupConfiguration.sourceLocation.fileShare!.path = this._databaseBackup.networkShareLocation; requestBody.properties.sourceDatabaseName = this._migrationDbs[i];
const response = await startDatabaseMigration( const response = await startDatabaseMigration(
this._azureAccount, this._azureAccount,
this._targetSubscription, this._targetSubscription,
@@ -687,6 +708,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
this._targetDatabaseNames[i], this._targetDatabaseNames[i],
requestBody requestBody
); );
response.databaseMigration.properties.sourceDatabaseName = this._migrationDbs[i];
response.databaseMigration.properties.backupConfiguration = requestBody.properties.backupConfiguration!; response.databaseMigration.properties.backupConfiguration = requestBody.properties.backupConfiguration!;
if (response.status === 201 || response.status === 200) { if (response.status === 201 || response.status === 200) {
MigrationLocalStorage.saveMigration( MigrationLocalStorage.saveMigration(

File diff suppressed because it is too large Load Diff

View File

@@ -33,6 +33,7 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
private _refresh1!: azdata.ButtonComponent; private _refresh1!: azdata.ButtonComponent;
private _refresh2!: azdata.ButtonComponent; private _refresh2!: azdata.ButtonComponent;
private _firstEnter: boolean = true;
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) { constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
super(wizard, azdata.window.createWizardPage(constants.IR_PAGE_TITLE), migrationStateModel); super(wizard, azdata.window.createWizardPage(constants.IR_PAGE_TITLE), migrationStateModel);
@@ -75,7 +76,10 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
} }
public async onPageEnter(): Promise<void> { public async onPageEnter(): Promise<void> {
this.populateMigrationService(); if (this._firstEnter) {
this.populateMigrationService();
this._firstEnter = false;
}
this.wizard.registerNavigationValidator((pageChangeInfo) => { this.wizard.registerNavigationValidator((pageChangeInfo) => {
if (pageChangeInfo.newPage < pageChangeInfo.lastPage) { if (pageChangeInfo.newPage < pageChangeInfo.lastPage) {
this.wizard.message = { this.wizard.message = {

View File

@@ -45,6 +45,7 @@ export class MigrationModePage extends MigrationWizardPage {
label: constants.DATABASE_BACKUP_MIGRATION_MODE_ONLINE_LABEL, label: constants.DATABASE_BACKUP_MIGRATION_MODE_ONLINE_LABEL,
name: buttonGroup, name: buttonGroup,
CSSStyles: { CSSStyles: {
'font-size': '13px',
'font-weight': 'bold' 'font-weight': 'bold'
}, },
checked: true checked: true
@@ -53,6 +54,7 @@ export class MigrationModePage extends MigrationWizardPage {
const onlineDescription = view.modelBuilder.text().withProps({ const onlineDescription = view.modelBuilder.text().withProps({
value: constants.DATABASE_BACKUP_MIGRATION_MODE_ONLINE_DESCRIPTION, value: constants.DATABASE_BACKUP_MIGRATION_MODE_ONLINE_DESCRIPTION,
CSSStyles: { CSSStyles: {
'font-size': '13px',
'margin': '0 0 10px 20px' 'margin': '0 0 10px 20px'
} }
}).component(); }).component();
@@ -69,6 +71,7 @@ export class MigrationModePage extends MigrationWizardPage {
label: constants.DATABASE_BACKUP_MIGRATION_MODE_OFFLINE_LABEL, label: constants.DATABASE_BACKUP_MIGRATION_MODE_OFFLINE_LABEL,
name: buttonGroup, name: buttonGroup,
CSSStyles: { CSSStyles: {
'font-size': '13px',
'font-weight': 'bold' 'font-weight': 'bold'
}, },
}).component(); }).component();
@@ -76,6 +79,7 @@ export class MigrationModePage extends MigrationWizardPage {
const offlineDescription = view.modelBuilder.text().withProps({ const offlineDescription = view.modelBuilder.text().withProps({
value: constants.DATABASE_BACKUP_MIGRATION_MODE_OFFLINE_DESCRIPTION, value: constants.DATABASE_BACKUP_MIGRATION_MODE_OFFLINE_DESCRIPTION,
CSSStyles: { CSSStyles: {
'font-size': '13px',
'margin': '0 0 10px 20px' 'margin': '0 0 10px 20px'
} }
}).component(); }).component();

View File

@@ -477,9 +477,12 @@ export class SKURecommendationPage extends MigrationWizardPage {
if (pageChangeInfo.newPage < pageChangeInfo.lastPage) { if (pageChangeInfo.newPage < pageChangeInfo.lastPage) {
return true; return true;
} }
if (this.migrationStateModel._migrationDbs.length === 0) {
errors.push('Please select databases to migrate');
if (this._rbg.selectedCardId === undefined || this._rbg.selectedCardId === '') {
errors.push(constants.SELECT_TARGET_TO_CONTINUE);
}
if (this.migrationStateModel._migrationDbs.length === 0) {
errors.push(constants.SELECT_DATABASE_TO_MIGRATE);
} }
if ((<azdata.CategoryValue>this._managedInstanceSubscriptionDropdown.value)?.displayName === constants.NO_SUBSCRIPTIONS_FOUND) { if ((<azdata.CategoryValue>this._managedInstanceSubscriptionDropdown.value)?.displayName === constants.NO_SUBSCRIPTIONS_FOUND) {
errors.push(constants.INVALID_SUBSCRIPTION_ERROR); errors.push(constants.INVALID_SUBSCRIPTION_ERROR);

View File

@@ -86,46 +86,40 @@ export class SummaryPage extends MigrationWizardPage {
flexContainer.addItems( flexContainer.addItems(
[ [
createInformationRow(this._view, constants.BACKUP_LOCATION, constants.NETWORK_SHARE), createInformationRow(this._view, constants.BACKUP_LOCATION, constants.NETWORK_SHARE),
createInformationRow(this._view, constants.NETWORK_SHARE, this.migrationStateModel._databaseBackup.networkShareLocation), createInformationRow(this._view, constants.NETWORK_SHARE, this.migrationStateModel._databaseBackup.networkShare.networkShareLocation),
createInformationRow(this._view, constants.USER_ACCOUNT, this.migrationStateModel._databaseBackup.windowsUser), createInformationRow(this._view, constants.USER_ACCOUNT, this.migrationStateModel._databaseBackup.networkShare.windowsUser),
createHeadingTextComponent(this._view, constants.AZURE_STORAGE_ACCOUNT_TO_UPLOAD_BACKUPS), createHeadingTextComponent(this._view, constants.AZURE_STORAGE_ACCOUNT_TO_UPLOAD_BACKUPS),
createInformationRow(this._view, constants.SUBSCRIPTION, this.migrationStateModel._databaseBackup.subscription.name), createInformationRow(this._view, constants.SUBSCRIPTION, this.migrationStateModel._databaseBackup.subscription.name),
createInformationRow(this._view, constants.LOCATION, this.migrationStateModel._databaseBackup.storageAccount.location), createInformationRow(this._view, constants.LOCATION, this.migrationStateModel._databaseBackup.networkShare.storageAccount.location),
createInformationRow(this._view, constants.RESOURCE_GROUP, this.migrationStateModel._databaseBackup.storageAccount.resourceGroup!), createInformationRow(this._view, constants.RESOURCE_GROUP, this.migrationStateModel._databaseBackup.networkShare.storageAccount.resourceGroup!),
createInformationRow(this._view, constants.STORAGE_ACCOUNT, this.migrationStateModel._databaseBackup.storageAccount.name!), createInformationRow(this._view, constants.STORAGE_ACCOUNT, this.migrationStateModel._databaseBackup.networkShare.storageAccount.name!),
createHeadingTextComponent(this._view, 'Target Databases:')
] ]
); );
this.migrationStateModel._migrationDbs.forEach((db, index) => {
flexContainer.addItem(createInformationRow(this._view, constants.TARGET_NAME_FOR_DATABASE(db), this.migrationStateModel._targetDatabaseNames[index]));
});
break; break;
case NetworkContainerType.FILE_SHARE: case NetworkContainerType.FILE_SHARE:
flexContainer.addItems( flexContainer.addItems(
[ [
createInformationRow(this._view, constants.TYPE, constants.FILE_SHARE), createInformationRow(this._view, constants.TYPE, constants.FILE_SHARE),
createInformationRow(this._view, constants.SUMMARY_AZURE_STORAGE_SUBSCRIPTION, this.migrationStateModel._databaseBackup.subscription.name), createInformationRow(this._view, constants.SUMMARY_AZURE_STORAGE_SUBSCRIPTION, this.migrationStateModel._databaseBackup.subscription.name),
createInformationRow(this._view, constants.SUMMARY_AZURE_STORAGE, this.migrationStateModel._databaseBackup.storageAccount.name),
] ]
); );
this.migrationStateModel._migrationDbs.forEach((db, index) => {
flexContainer.addItem(createInformationRow(this._view, constants.TARGET_NAME_FOR_DATABASE(db), this.migrationStateModel._targetDatabaseNames[index]));
flexContainer.addItem(createInformationRow(this._view, constants.TARGET_FILE_SHARE(db), this.migrationStateModel._databaseBackup.fileShares[index].name));
});
break; break;
case NetworkContainerType.BLOB_CONTAINER: case NetworkContainerType.BLOB_CONTAINER:
flexContainer.addItems( flexContainer.addItems(
[ [
createInformationRow(this._view, constants.TYPE, constants.BLOB_CONTAINER), createInformationRow(this._view, constants.TYPE, constants.BLOB_CONTAINER),
createInformationRow(this._view, constants.SUMMARY_AZURE_STORAGE_SUBSCRIPTION, this.migrationStateModel._databaseBackup.subscription.name), createInformationRow(this._view, constants.SUMMARY_AZURE_STORAGE_SUBSCRIPTION, this.migrationStateModel._databaseBackup.subscription.name),
createInformationRow(this._view, constants.SUMMARY_AZURE_STORAGE, this.migrationStateModel._databaseBackup.storageAccount.name), createInformationRow(this._view, constants.LOCATION, this.migrationStateModel._databaseBackup.blob.storageAccount.location),
createInformationRow(this._view, constants.RESOURCE_GROUP, this.migrationStateModel._databaseBackup.blob.storageAccount.resourceGroup!),
createInformationRow(this._view, constants.SUMMARY_AZURE_STORAGE, this.migrationStateModel._databaseBackup.blob.storageAccount.name),
createInformationRow(this._view, constants.BLOB_CONTAINER, this.migrationStateModel._databaseBackup.blob.blobContainer.name)
] ]
); );
this.migrationStateModel._migrationDbs.forEach((db, index) => {
flexContainer.addItem(createInformationRow(this._view, constants.TARGET_NAME_FOR_DATABASE(db), this.migrationStateModel._targetDatabaseNames[index]));
flexContainer.addItem(createInformationRow(this._view, constants.TARGET_FILE_SHARE(db), this.migrationStateModel._databaseBackup.blobContainers[index].name));
});
} }
flexContainer.addItem(createHeadingTextComponent(this._view, constants.TARGET_NAME));
this.migrationStateModel._migrationDbs.forEach((db, index) => {
flexContainer.addItem(createInformationRow(this._view, db, this.migrationStateModel._targetDatabaseNames[index]));
});
return flexContainer; return flexContainer;
} }
} }