mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-19 09:35:36 -05:00
[SQL Migration] Add storage/MI connectivity validation (#22410)
* wip * Add SQL VM POC * Undo azurecore changes * Add warning banner instead of blocking on next * Fix warning banner behavior * Add private endpoint support * Fix navigation issue * Add offline scenario * Address PR comments * Fix merge conflicts
This commit is contained in:
@@ -18,7 +18,7 @@ import { logError, TelemetryViews } from '../telemetry';
|
||||
import * as styles from '../constants/styles';
|
||||
import { TableMigrationSelectionDialog } from '../dialog/tableMigrationSelection/tableMigrationSelectionDialog';
|
||||
import { ValidateIrDialog } from '../dialog/validationResults/validateIrDialog';
|
||||
import { getSourceConnectionCredentials, getSourceConnectionProfile, getSourceConnectionQueryProvider, getSourceConnectionUri } from '../api/sqlUtils';
|
||||
import { canTargetConnectToStorageAccount, getSourceConnectionCredentials, getSourceConnectionProfile, getSourceConnectionQueryProvider, getSourceConnectionUri } from '../api/sqlUtils';
|
||||
|
||||
const WIZARD_TABLE_COLUMN_WIDTH = '200px';
|
||||
const WIZARD_TABLE_COLUMN_WIDTH_SMALL = '170px';
|
||||
@@ -71,6 +71,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
||||
|
||||
private _existingDatabases: string[] = [];
|
||||
private _nonPageBlobErrors: string[] = [];
|
||||
private _inaccessibleStorageAccounts: string[] = [];
|
||||
private _disposables: vscode.Disposable[] = [];
|
||||
|
||||
// SQL DB table selection
|
||||
@@ -605,7 +606,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
||||
fireOnTextChange: true,
|
||||
}).component();
|
||||
this._disposables.push(
|
||||
this._networkShareContainerStorageAccountDropdown.onValueChanged((value) => {
|
||||
this._networkShareContainerStorageAccountDropdown.onValueChanged(async (value) => {
|
||||
if (value && value !== 'undefined') {
|
||||
const selectedStorageAccount = this.migrationStateModel._storageAccounts.find(sa => sa.name === value);
|
||||
if (selectedStorageAccount) {
|
||||
@@ -613,6 +614,22 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
||||
this.migrationStateModel._databaseBackup.networkShares[i].storageAccount = selectedStorageAccount;
|
||||
}
|
||||
this.migrationStateModel.resetIrValidationResults();
|
||||
|
||||
// check for storage account connectivity
|
||||
if ((this.migrationStateModel.isSqlMiTarget || this.migrationStateModel.isSqlVmTarget)) {
|
||||
if (!(await canTargetConnectToStorageAccount(this.migrationStateModel._targetType, this.migrationStateModel._targetServerInstance, selectedStorageAccount, this.migrationStateModel._azureAccount, this.migrationStateModel._targetSubscription))) {
|
||||
this._inaccessibleStorageAccounts = [selectedStorageAccount.name];
|
||||
} else {
|
||||
this._inaccessibleStorageAccounts = [];
|
||||
}
|
||||
|
||||
this.wizard.message = {
|
||||
text: this._inaccessibleStorageAccounts.length > 0
|
||||
? constants.STORAGE_ACCOUNT_CONNECTIVITY_WARNING(this.migrationStateModel._targetServerInstance.name, this._inaccessibleStorageAccounts)
|
||||
: '',
|
||||
level: azdata.window.MessageLevel.Warning
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
@@ -628,7 +645,26 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
||||
|
||||
this._disposables.push(
|
||||
this._networkShareContainerStorageAccountRefreshButton.onDidClick(
|
||||
value => this.loadNetworkShareStorageDropdown()));
|
||||
async () => {
|
||||
this.loadNetworkShareStorageDropdown();
|
||||
|
||||
// check for storage account connectivity
|
||||
const selectedStorageAccount = this.migrationStateModel._storageAccounts.find(sa => sa.name === (this._networkShareContainerStorageAccountDropdown.value as azdata.CategoryValue).displayName);
|
||||
if ((this.migrationStateModel.isSqlMiTarget || this.migrationStateModel.isSqlVmTarget) && selectedStorageAccount) {
|
||||
if (!(await canTargetConnectToStorageAccount(this.migrationStateModel._targetType, this.migrationStateModel._targetServerInstance, selectedStorageAccount, this.migrationStateModel._azureAccount, this.migrationStateModel._targetSubscription))) {
|
||||
this._inaccessibleStorageAccounts = [selectedStorageAccount.name];
|
||||
} else {
|
||||
this._inaccessibleStorageAccounts = [];
|
||||
}
|
||||
|
||||
this.wizard.message = {
|
||||
text: this._inaccessibleStorageAccounts.length > 0
|
||||
? constants.STORAGE_ACCOUNT_CONNECTIVITY_WARNING(this.migrationStateModel._targetServerInstance.name, this._inaccessibleStorageAccounts)
|
||||
: '',
|
||||
level: azdata.window.MessageLevel.Warning
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
const storageAccountContainer = this._view.modelBuilder.flexContainer()
|
||||
.withProps({ CSSStyles: { 'margin-top': '-1em' } })
|
||||
@@ -825,10 +861,6 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
||||
}
|
||||
this._blobContainerTargetDatabaseNamesTable.columns[folderColumnIndex].hidden = folderColumnNewHidden;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const connectionProfile = await getSourceConnectionProfile();
|
||||
const queryProvider = await getSourceConnectionQueryProvider();
|
||||
let username = '';
|
||||
@@ -871,6 +903,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
||||
this._blobContainerDropdowns = [];
|
||||
this._blobContainerLastBackupFileDropdowns = [];
|
||||
this._blobContainerFolderDropdowns = [];
|
||||
this._inaccessibleStorageAccounts = [];
|
||||
|
||||
if (this.migrationStateModel.isSqlMiTarget) {
|
||||
this._existingDatabases = await this.migrationStateModel.getManagedDatabases();
|
||||
@@ -1073,7 +1106,28 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
||||
if (value && value !== 'undefined') {
|
||||
const selectedStorageAccount = this.migrationStateModel._storageAccounts.find(sa => sa.name === value);
|
||||
if (selectedStorageAccount && !blobStorageAccountErrorStrings.includes(value)) {
|
||||
const oldSelectedStorageAccount = this.migrationStateModel._databaseBackup.blobs[index].storageAccount ? this.migrationStateModel._databaseBackup.blobs[index].storageAccount.name : '';
|
||||
this.migrationStateModel._databaseBackup.blobs[index].storageAccount = selectedStorageAccount;
|
||||
|
||||
// check for storage account connectivity
|
||||
if ((this.migrationStateModel.isSqlMiTarget || this.migrationStateModel.isSqlVmTarget)) {
|
||||
if (this.migrationStateModel._databaseBackup.blobs.filter((e, i) => i !== index).every(blob => blob.storageAccount && blob.storageAccount.name.toLowerCase() !== oldSelectedStorageAccount.toLowerCase())) {
|
||||
this._inaccessibleStorageAccounts = this._inaccessibleStorageAccounts.filter(storageAccountName => storageAccountName.toLowerCase() !== oldSelectedStorageAccount.toLowerCase());
|
||||
}
|
||||
|
||||
if (!(await canTargetConnectToStorageAccount(this.migrationStateModel._targetType, this.migrationStateModel._targetServerInstance, selectedStorageAccount, this.migrationStateModel._azureAccount, this.migrationStateModel._targetSubscription))) {
|
||||
this._inaccessibleStorageAccounts = this._inaccessibleStorageAccounts.filter(storageAccountName => storageAccountName.toLowerCase() !== selectedStorageAccount.name.toLowerCase());
|
||||
this._inaccessibleStorageAccounts.push(selectedStorageAccount.name);
|
||||
}
|
||||
|
||||
this.wizard.message = {
|
||||
text: this._inaccessibleStorageAccounts.length > 0
|
||||
? constants.STORAGE_ACCOUNT_CONNECTIVITY_WARNING(this.migrationStateModel._targetServerInstance.name, this._inaccessibleStorageAccounts)
|
||||
: '',
|
||||
level: azdata.window.MessageLevel.Warning
|
||||
}
|
||||
}
|
||||
|
||||
await this.loadBlobContainerDropdown(index);
|
||||
await blobContainerDropdown.updateProperties({ enabled: true });
|
||||
} else {
|
||||
@@ -1090,6 +1144,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
||||
if (selectedBlobContainer && !blobContainerErrorStrings.includes(value)) {
|
||||
this.migrationStateModel._databaseBackup.blobs[index].blobContainer = selectedBlobContainer;
|
||||
|
||||
// check for block blobs for SQL VM <= 2014
|
||||
if (this.migrationStateModel.isSqlVmTarget && utils.isTargetSqlVm2014OrBelow(this.migrationStateModel._targetServerInstance as SqlVMServer)) {
|
||||
const backups = await utils.getBlobLastBackupFileNames(
|
||||
this.migrationStateModel._azureAccount,
|
||||
@@ -1137,7 +1192,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
||||
this._disposables.push(
|
||||
blobContainerFolderDropdown.onValueChanged(value => {
|
||||
if (value && value !== 'undefined') {
|
||||
if (this.migrationStateModel._blobContainerFolders.includes(value) && !blobFolderErrorStrings.includes(value)) {
|
||||
if (this.migrationStateModel._blobContainerFolders && this.migrationStateModel._blobContainerFolders.includes(value) && !blobFolderErrorStrings.includes(value)) {
|
||||
const selectedFolder = value;
|
||||
this.migrationStateModel._databaseBackup.blobs[index].folderName = selectedFolder;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user