mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-01 01:25:38 -05:00
SQL-Migration: enable cross subscription service migration (#22876)
* x subscription migration support * refresh after cutover * fix service irregular status load behavior * queue service status requests, fix typo * add migationTargetServerName helper method * save context before api call
This commit is contained in:
@@ -656,11 +656,6 @@ export async function deleteMigration(account: azdata.Account, subscription: Sub
|
||||
}
|
||||
}
|
||||
|
||||
export async function getLocationDisplayName(location: string): Promise<string> {
|
||||
const api = await getAzureCoreAPI();
|
||||
return api.getRegionDisplayName(location);
|
||||
}
|
||||
|
||||
export async function validateIrSqlDatabaseMigrationSettings(
|
||||
migration: MigrationStateModel,
|
||||
sourceServerName: string,
|
||||
@@ -674,7 +669,7 @@ export async function validateIrSqlDatabaseMigrationSettings(
|
||||
|
||||
const api = await getAzureCoreAPI();
|
||||
const account = migration._azureAccount;
|
||||
const subscription = migration._targetSubscription;
|
||||
const subscription = migration._sqlMigrationServiceSubscription;
|
||||
const serviceId = migration._sqlMigrationService?.id;
|
||||
const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint;
|
||||
const path = encodeURI(`${serviceId}/validateIr?api-version=${DMSV2_API_VERSION}`);
|
||||
@@ -735,11 +730,12 @@ export async function validateIrDatabaseMigrationSettings(
|
||||
|
||||
const api = await getAzureCoreAPI();
|
||||
const account = migration._azureAccount;
|
||||
const subscription = migration._targetSubscription;
|
||||
const serviceSubscription = migration._sqlMigrationServiceSubscription;
|
||||
const targetSubscription = migration._targetSubscription;
|
||||
const serviceId = migration._sqlMigrationService?.id;
|
||||
const host = api.getProviderMetadataForAccount(account).settings.armResource?.endpoint;
|
||||
const path = encodeURI(`${serviceId}/validateIr?api-version=${DMSV2_API_VERSION}`);
|
||||
const storage = await getStorageAccountAccessKeys(account, subscription, networkShare.storageAccount);
|
||||
const storage = await getStorageAccountAccessKeys(account, targetSubscription, networkShare.storageAccount);
|
||||
|
||||
const requestBody: ValdiateIrDatabaseMigrationRequest = {
|
||||
sourceDatabaseName: sourceDatabaseName ?? '',
|
||||
@@ -775,7 +771,7 @@ export async function validateIrDatabaseMigrationSettings(
|
||||
|
||||
const response = await api.makeAzureRestRequest<any>(
|
||||
account,
|
||||
subscription,
|
||||
serviceSubscription,
|
||||
path,
|
||||
azurecore.HttpRequestMethod.POST,
|
||||
requestBody,
|
||||
|
||||
@@ -759,6 +759,12 @@ export function AUTH_KEY_REFRESHED(keyName: string): string {
|
||||
export function SERVICE_NOT_READY(serviceName: string): string {
|
||||
return localize('sql.migration.service.not.ready', "Azure Database Migration Service is not registered. Azure Database Migration Service '{0}' needs to be registered with self-hosted integration runtime on any node.", serviceName);
|
||||
}
|
||||
export function SERVICE_ERROR_NOT_READY(serviceName: string, error: string): string {
|
||||
return localize('sql.migration.service.error.not.ready',
|
||||
"The following error occurred while retrieving registration information for Azure Database Migration Service '{0}'. Please click refresh and try again. Error: '{1}'.",
|
||||
serviceName,
|
||||
error);
|
||||
}
|
||||
export function SERVICE_READY(serviceName: string, host: string): string {
|
||||
return localize('sql.migration.service.ready', "Azure Database Migration Service '{0}' is connected to self-hosted integration runtime running on the node - {1}", serviceName, host);
|
||||
}
|
||||
|
||||
@@ -776,12 +776,12 @@ export class DashboardTab extends TabBase<DashboardTab> {
|
||||
this.serviceContextChangedEvent.event(
|
||||
async (e) => {
|
||||
if (e.connectionId === await getSourceConnectionId()) {
|
||||
await this.updateServiceContext(this._serviceContextButton);
|
||||
await this.updateServiceButtonContext(this._serviceContextButton);
|
||||
await this.refresh();
|
||||
}
|
||||
}
|
||||
));
|
||||
await this.updateServiceContext(this._serviceContextButton);
|
||||
await this.updateServiceButtonContext(this._serviceContextButton);
|
||||
|
||||
return this._serviceContextButton;
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ export abstract class MigrationDetailsTabBase<T> extends TabBase<T> {
|
||||
await this.refresh();
|
||||
const dialog = new ConfirmCutoverDialog(this.model);
|
||||
await dialog.initialize();
|
||||
|
||||
await this.refresh();
|
||||
if (this.model.CutoverError) {
|
||||
await this.statusBar.showError(
|
||||
loc.MIGRATION_CUTOVER_ERROR,
|
||||
|
||||
@@ -78,7 +78,7 @@ export class MigrationsListTab extends TabBase<MigrationsListTab> {
|
||||
}
|
||||
}
|
||||
|
||||
public async refresh(): Promise<void> {
|
||||
public async refresh(initialize?: boolean): Promise<void> {
|
||||
if (this.isRefreshing ||
|
||||
this._refreshLoader === undefined) {
|
||||
|
||||
@@ -91,6 +91,10 @@ export class MigrationsListTab extends TabBase<MigrationsListTab> {
|
||||
|
||||
await this.statusBar.clearError();
|
||||
|
||||
if (initialize) {
|
||||
await this.updateServiceButtonContext(this._serviceContextButton);
|
||||
}
|
||||
|
||||
await this._statusTable.updateProperty('data', []);
|
||||
this._migrations = await getCurrentMigrations();
|
||||
await this._populateMigrationTable();
|
||||
@@ -180,12 +184,11 @@ export class MigrationsListTab extends TabBase<MigrationsListTab> {
|
||||
this.serviceContextChangedEvent.event(
|
||||
async (e) => {
|
||||
if (e.connectionId === await getSourceConnectionId()) {
|
||||
await this.updateServiceContext(this._serviceContextButton);
|
||||
await this.refresh();
|
||||
await this.refresh(true);
|
||||
}
|
||||
}
|
||||
));
|
||||
await this.updateServiceContext(this._serviceContextButton);
|
||||
await this.updateServiceButtonContext(this._serviceContextButton);
|
||||
|
||||
this._searchBox = this.view.modelBuilder.inputBox()
|
||||
.withProps({
|
||||
|
||||
@@ -57,7 +57,7 @@ export class MigrationsTab extends TabBase<MigrationsTab> {
|
||||
switch (this._selectedTabId) {
|
||||
case undefined:
|
||||
case MigrationsListTabId:
|
||||
return this._migrationsListTab.refresh();
|
||||
return this._migrationsListTab.refresh(true);
|
||||
default:
|
||||
return this._migrationDetailsViewTab.refresh();
|
||||
}
|
||||
@@ -155,11 +155,10 @@ export class MigrationsTab extends TabBase<MigrationsTab> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private async _openTab(tab: azdata.Tab): Promise<void> {
|
||||
private async _openTab(tab: TabBase<any>): Promise<void> {
|
||||
if (tab.id === this._selectedTabId) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.statusBar.clearError();
|
||||
this._tab.clearItems();
|
||||
this._tab.addItem(tab.content);
|
||||
|
||||
@@ -82,16 +82,12 @@ export abstract class TabBase<T> implements azdata.Tab, vscode.Disposable {
|
||||
return new Date(stringDate1) > new Date(stringDate2) ? -sortDir : sortDir;
|
||||
}
|
||||
|
||||
protected async updateServiceContext(button: azdata.ButtonComponent): Promise<void> {
|
||||
protected async updateServiceButtonContext(button: azdata.ButtonComponent): Promise<void> {
|
||||
const label = await getSelectedServiceStatus();
|
||||
if (button.label !== label ||
|
||||
button.title !== label) {
|
||||
|
||||
button.label = label;
|
||||
button.title = label;
|
||||
|
||||
await this.refresh();
|
||||
}
|
||||
await button.updateProperty('label', '');
|
||||
await button.updateProperty('title', '');
|
||||
await button.updateProperty('label', label);
|
||||
await button.updateProperty('title', label);
|
||||
}
|
||||
|
||||
protected createNewLoginMigrationButton(): azdata.ButtonComponent {
|
||||
|
||||
@@ -61,7 +61,7 @@ export class CreateSqlMigrationServiceDialog {
|
||||
this._dialogObject.okButton.position = 'left';
|
||||
this._dialogObject.cancelButton.position = 'left';
|
||||
|
||||
let tab = azdata.window.createTab('');
|
||||
const tab = azdata.window.createTab('');
|
||||
this._dialogObject.registerCloseValidator(async () => {
|
||||
return true;
|
||||
});
|
||||
@@ -73,70 +73,64 @@ export class CreateSqlMigrationServiceDialog {
|
||||
width: '80px'
|
||||
}).component();
|
||||
|
||||
this._disposables.push(this._formSubmitButton.onDidClick(async (e) => {
|
||||
this._dialogObject.message = {
|
||||
text: ''
|
||||
};
|
||||
this._statusLoadingComponent.loading = true;
|
||||
this.migrationServiceResourceGroupDropdown.loading = false;
|
||||
this.setFormEnabledState(false);
|
||||
|
||||
|
||||
const subscription = this._model._targetSubscription;
|
||||
const resourceGroup = this._selectedResourceGroup;
|
||||
const location = this._model._targetServerInstance.location;
|
||||
const serviceName = this.migrationServiceNameText.value;
|
||||
|
||||
const formValidationErrors = this.validateCreateServiceForm(subscription, resourceGroup.name, location, serviceName);
|
||||
|
||||
if (formValidationErrors.length > 0) {
|
||||
this.setDialogMessage(formValidationErrors);
|
||||
this._statusLoadingComponent.loading = false;
|
||||
this.setFormEnabledState(true);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this._disposables.push(
|
||||
this._formSubmitButton.onDidClick(async (e) => {
|
||||
utils.clearDialogMessage(this._dialogObject);
|
||||
this._selectedResourceGroup = resourceGroup;
|
||||
this._createdMigrationService = await createSqlMigrationService(
|
||||
this._model._azureAccount,
|
||||
subscription,
|
||||
resourceGroup.name,
|
||||
location,
|
||||
serviceName!,
|
||||
this._model._sessionId);
|
||||
|
||||
if (this._createdMigrationService.error) {
|
||||
this.setDialogMessage(`${this._createdMigrationService.error.code} : ${this._createdMigrationService.error.message}`);
|
||||
this._statusLoadingComponent.loading = false;
|
||||
this._statusLoadingComponent.loading = true;
|
||||
this.migrationServiceResourceGroupDropdown.loading = false;
|
||||
this.setFormEnabledState(false);
|
||||
|
||||
const subscription = this._model._sqlMigrationServiceSubscription;
|
||||
const resourceGroup = this._selectedResourceGroup;
|
||||
const location = this._model._location.name;
|
||||
const serviceName = this.migrationServiceNameText.value;
|
||||
|
||||
const formValidationErrors = this.validateCreateServiceForm(subscription, resourceGroup.name, location, serviceName);
|
||||
|
||||
try {
|
||||
if (formValidationErrors.length > 0) {
|
||||
this.setDialogMessage(formValidationErrors);
|
||||
this.setFormEnabledState(true);
|
||||
return;
|
||||
}
|
||||
|
||||
utils.clearDialogMessage(this._dialogObject);
|
||||
this._createdMigrationService = await createSqlMigrationService(
|
||||
this._model._azureAccount,
|
||||
subscription,
|
||||
resourceGroup.name,
|
||||
location,
|
||||
serviceName!,
|
||||
this._model._sessionId);
|
||||
|
||||
if (this._createdMigrationService.error) {
|
||||
this.setDialogMessage(`${this._createdMigrationService.error.code} : ${this._createdMigrationService.error.message}`);
|
||||
this.setFormEnabledState(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._isBlobContainerUsed && !this._model.isSqlDbTarget) {
|
||||
this._dialogObject.okButton.enabled = true;
|
||||
this._setupContainer.display = 'none';
|
||||
this._dialogObject.message = {
|
||||
text: constants.DATA_MIGRATION_SERVICE_CREATED_SUCCESSFULLY,
|
||||
level: azdata.window.MessageLevel.Information
|
||||
};
|
||||
} else {
|
||||
await this.refreshStatus();
|
||||
await this.refreshAuthTable();
|
||||
this._setupContainer.display = 'inline';
|
||||
this._testConnectionButton.hidden = false;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
this.setDialogMessage(e.message);
|
||||
this.setFormEnabledState(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._isBlobContainerUsed && !this._model.isSqlDbTarget) {
|
||||
this._dialogObject.okButton.enabled = true;
|
||||
this._statusLoadingComponent.loading = false;
|
||||
this._setupContainer.display = 'none';
|
||||
this._dialogObject.message = {
|
||||
text: constants.DATA_MIGRATION_SERVICE_CREATED_SUCCESSFULLY,
|
||||
level: azdata.window.MessageLevel.Information
|
||||
};
|
||||
} else {
|
||||
await this.refreshStatus();
|
||||
await this.refreshAuthTable();
|
||||
this._setupContainer.display = 'inline';
|
||||
this._testConnectionButton.hidden = false;
|
||||
} finally {
|
||||
this._statusLoadingComponent.loading = false;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
this.setDialogMessage(e.message);
|
||||
this._statusLoadingComponent.loading = false;
|
||||
this.setFormEnabledState(true);
|
||||
return;
|
||||
}
|
||||
}));
|
||||
}));
|
||||
|
||||
this._statusLoadingComponent = view.modelBuilder.loadingComponent().withProps({
|
||||
loadingText: constants.LOADING_MIGRATION_SERVICES,
|
||||
@@ -289,7 +283,11 @@ export class CreateSqlMigrationServiceDialog {
|
||||
}).component();
|
||||
|
||||
this._disposables.push(this._createResourceGroupLink.onDidClick(async e => {
|
||||
const createResourceGroupDialog = new CreateResourceGroupDialog(this._model._azureAccount, this._model._targetSubscription, this._model._targetServerInstance.location);
|
||||
const createResourceGroupDialog = new CreateResourceGroupDialog(
|
||||
this._model._azureAccount,
|
||||
this._model._sqlMigrationServiceSubscription,
|
||||
this._model._location.name);
|
||||
|
||||
const createdResourceGroup = await createResourceGroupDialog.initialize();
|
||||
if (createdResourceGroup) {
|
||||
this._resourceGroups.push(createdResourceGroup);
|
||||
@@ -324,7 +322,7 @@ export class CreateSqlMigrationServiceDialog {
|
||||
|
||||
this.migrationServiceLocation = this._view.modelBuilder.text().withProps({
|
||||
enabled: false,
|
||||
value: await this._model.getLocationDisplayName(this._model._targetServerInstance.location),
|
||||
value: this._model._location.displayName,
|
||||
CSSStyles: {
|
||||
'margin': '-1em 0 0'
|
||||
}
|
||||
@@ -386,7 +384,7 @@ export class CreateSqlMigrationServiceDialog {
|
||||
|
||||
private async populateSubscriptions(): Promise<void> {
|
||||
this.migrationServiceResourceGroupDropdown.loading = true;
|
||||
this.migrationServiceSubscription.value = this._model._targetSubscription.name;
|
||||
this.migrationServiceSubscription.value = this._model._sqlMigrationServiceSubscription.name;
|
||||
await this.populateResourceGroups();
|
||||
}
|
||||
|
||||
@@ -395,7 +393,7 @@ export class CreateSqlMigrationServiceDialog {
|
||||
try {
|
||||
this._resourceGroups = await utils.getAllResourceGroups(
|
||||
this._model._azureAccount,
|
||||
this._model._targetSubscription);
|
||||
this._model._sqlMigrationServiceSubscription);
|
||||
this.migrationServiceResourceGroupDropdown.values = utils.getResourceDropdownValues(
|
||||
this._resourceGroups,
|
||||
constants.RESOURCE_GROUP_NOT_FOUND);
|
||||
@@ -510,10 +508,10 @@ export class CreateSqlMigrationServiceDialog {
|
||||
}
|
||||
|
||||
private async refreshStatus(): Promise<void> {
|
||||
const subscription = this._model._targetSubscription;
|
||||
const subscription = this._model._sqlMigrationServiceSubscription;
|
||||
const resourceGroupId = (this.migrationServiceResourceGroupDropdown.value as azdata.CategoryValue).name;
|
||||
const resourceGroup = getResourceName(resourceGroupId);
|
||||
const location = this._model._targetServerInstance.location;
|
||||
const location = this._model._location.name;
|
||||
|
||||
const maxRetries = 5;
|
||||
let migrationServiceStatus!: SqlMigrationService;
|
||||
@@ -558,7 +556,6 @@ export class CreateSqlMigrationServiceDialog {
|
||||
...styles.BODY_CSS
|
||||
}
|
||||
});
|
||||
this._dialogObject.okButton.enabled = true;
|
||||
} else {
|
||||
this._connectionStatus.text = constants.SERVICE_NOT_READY(this._createdMigrationService!.name);
|
||||
await this._connectionStatus.updateProperties(<azdata.InfoBoxComponentProperties>{
|
||||
@@ -568,16 +565,16 @@ export class CreateSqlMigrationServiceDialog {
|
||||
...styles.BODY_CSS
|
||||
}
|
||||
});
|
||||
this._dialogObject.okButton.enabled = false;
|
||||
}
|
||||
this._dialogObject.okButton.enabled = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private async refreshAuthTable(): Promise<void> {
|
||||
const subscription = this._model._targetSubscription;
|
||||
const subscription = this._model._sqlMigrationServiceSubscription;
|
||||
const resourceGroupId = (this.migrationServiceResourceGroupDropdown.value as azdata.CategoryValue).name;
|
||||
const resourceGroup = getResourceName(resourceGroupId);
|
||||
const location = this._model._targetServerInstance.location;
|
||||
const location = this._model._location.name;
|
||||
const keys = await getSqlMigrationServiceAuthKeys(
|
||||
this._model._azureAccount,
|
||||
subscription,
|
||||
|
||||
@@ -74,6 +74,8 @@ export class RestartMigrationDialog {
|
||||
|
||||
// Integration Runtime
|
||||
sqlMigrationService: serviceContext.migrationService,
|
||||
serviceSubscription: null,
|
||||
serviceResourceGroup: null
|
||||
};
|
||||
|
||||
const getStorageAccountResourceGroup = (storageAccountResourceId: string): azureResource.AzureResourceResourceGroup => {
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as azurecore from 'azurecore';
|
||||
import * as vscode from 'vscode';
|
||||
import * as contracts from '../service/contracts';
|
||||
import * as features from '../service/features';
|
||||
import { SqlMigrationService, SqlManagedInstance, startDatabaseMigration, StartDatabaseMigrationRequest, StorageAccount, SqlVMServer, getLocationDisplayName, getSqlManagedInstanceDatabases, AzureSqlDatabaseServer, VirtualMachineInstanceView } from '../api/azure';
|
||||
import { SqlMigrationService, SqlManagedInstance, startDatabaseMigration, StartDatabaseMigrationRequest, StorageAccount, SqlVMServer, getSqlManagedInstanceDatabases, AzureSqlDatabaseServer, VirtualMachineInstanceView } from '../api/azure';
|
||||
import * as constants from '../constants/strings';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
@@ -150,6 +150,8 @@ export interface SavedInfo {
|
||||
blobs: Blob[];
|
||||
targetDatabaseNames: string[];
|
||||
sqlMigrationService: SqlMigrationService | undefined;
|
||||
serviceSubscription: azurecore.azureResource.AzureResourceSubscription | null;
|
||||
serviceResourceGroup: azurecore.azureResource.AzureResourceResourceGroup | null;
|
||||
serverAssessment: ServerAssessment | null;
|
||||
skuRecommendation: SkuRecommendationSavedInfo | null;
|
||||
}
|
||||
@@ -201,6 +203,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
public _targetPassword!: string;
|
||||
public _sourceTargetMapping: Map<string, TargetDatabaseInfo | undefined> = new Map();
|
||||
|
||||
public _sqlMigrationServiceSubscription!: azurecore.azureResource.AzureResourceSubscription;
|
||||
public _sqlMigrationServiceResourceGroup!: azurecore.azureResource.AzureResourceResourceGroup;
|
||||
public _sqlMigrationService!: SqlMigrationService | undefined;
|
||||
public _sqlMigrationServices!: SqlMigrationService[];
|
||||
@@ -342,6 +345,19 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
r.state === ValidateIrState.Succeeded)
|
||||
}
|
||||
|
||||
public get migrationTargetServerName(): string {
|
||||
switch (this._targetType) {
|
||||
case MigrationTargetType.SQLMI:
|
||||
return (this._targetServerInstance as azurecore.azureResource.AzureSqlManagedInstance)?.name;
|
||||
case MigrationTargetType.SQLVM:
|
||||
return (this._targetServerInstance as SqlVMServer)?.name;
|
||||
case MigrationTargetType.SQLDB:
|
||||
return (this._targetServerInstance as AzureSqlDatabaseServer)?.name;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
public get isBackupContainerNetworkShare(): boolean {
|
||||
return this._databaseBackup?.networkContainerType === NetworkContainerType.NETWORK_SHARE;
|
||||
}
|
||||
@@ -927,10 +943,6 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
return this.extensionContext.extensionPath;
|
||||
}
|
||||
|
||||
public getLocationDisplayName(location: string): Promise<string> {
|
||||
return getLocationDisplayName(location);
|
||||
}
|
||||
|
||||
public async getManagedDatabases(): Promise<string[]> {
|
||||
return (
|
||||
await getSqlManagedInstanceDatabases(this._azureAccount,
|
||||
@@ -1107,7 +1119,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
requestBody.properties.sourceDatabaseName = this._databasesForMigration[i];
|
||||
const response = await startDatabaseMigration(
|
||||
this._azureAccount,
|
||||
this._targetSubscription,
|
||||
this._sqlMigrationServiceSubscription,
|
||||
this._sqlMigrationService?.location!,
|
||||
this._targetServerInstance,
|
||||
this._targetDatabaseNames[i],
|
||||
@@ -1131,9 +1143,9 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
{
|
||||
'sessionId': this._sessionId,
|
||||
'tenantId': this._azureAccount.properties.tenants[0].id,
|
||||
'subscriptionId': this._targetSubscription?.id,
|
||||
'resourceGroup': this._resourceGroup?.name,
|
||||
'location': this._targetServerInstance.location,
|
||||
'subscriptionId': this._sqlMigrationServiceSubscription?.id,
|
||||
'resourceGroup': this._sqlMigrationServiceResourceGroup?.name,
|
||||
'location': this._location.name,
|
||||
'targetType': this._targetType,
|
||||
'hashedServerName': hashString(this._assessmentApiResponse?.assessmentResult?.name),
|
||||
'hashedDatabaseName': hashString(this._databasesForMigration[i]),
|
||||
@@ -1197,12 +1209,16 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
sqlMigrationService: undefined,
|
||||
serverAssessment: null,
|
||||
skuRecommendation: null,
|
||||
serviceResourceGroup: null,
|
||||
serviceSubscription: null,
|
||||
};
|
||||
switch (currentPage) {
|
||||
case Page.Summary:
|
||||
|
||||
case Page.IntegrationRuntime:
|
||||
saveInfo.sqlMigrationService = this._sqlMigrationService;
|
||||
saveInfo.serviceSubscription = this._sqlMigrationServiceSubscription;
|
||||
saveInfo.serviceResourceGroup = this._sqlMigrationServiceResourceGroup;
|
||||
saveInfo.migrationMode = this._databaseBackup.migrationMode;
|
||||
saveInfo.networkContainerType = this._databaseBackup.networkContainerType;
|
||||
|
||||
@@ -1282,6 +1298,8 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
this._databaseBackup.subscription = this.savedInfo.subscription || undefined!;
|
||||
|
||||
this._sqlMigrationService = this.savedInfo.sqlMigrationService;
|
||||
this._sqlMigrationServiceSubscription = this.savedInfo.serviceSubscription || undefined!;
|
||||
this._sqlMigrationServiceResourceGroup = this.savedInfo.serviceResourceGroup || undefined!;
|
||||
|
||||
const savedAssessmentResults = this.savedInfo.serverAssessment;
|
||||
if (savedAssessmentResults) {
|
||||
|
||||
@@ -228,7 +228,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
||||
description: constants.DATABASE_BACKUP_NETWORK_SHARE_WINDOWS_USER_INFO,
|
||||
width: WIZARD_INPUT_COMPONENT_WIDTH,
|
||||
requiredIndicator: true,
|
||||
CSSStyles: { ...styles.LABEL_CSS }
|
||||
CSSStyles: { ...styles.LABEL_CSS },
|
||||
}).component();
|
||||
this._windowsUserAccountText = this._view.modelBuilder.inputBox()
|
||||
.withProps({
|
||||
@@ -627,7 +627,13 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
||||
|
||||
// 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))) {
|
||||
if (!(await canTargetConnectToStorageAccount(
|
||||
this.migrationStateModel._targetType,
|
||||
this.migrationStateModel._targetServerInstance,
|
||||
selectedStorageAccount,
|
||||
this.migrationStateModel._azureAccount,
|
||||
this.migrationStateModel._targetSubscription))) {
|
||||
|
||||
this._inaccessibleStorageAccounts = [selectedStorageAccount.name];
|
||||
} else {
|
||||
this._inaccessibleStorageAccounts = [];
|
||||
@@ -661,7 +667,11 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
||||
// 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))) {
|
||||
if (!(await canTargetConnectToStorageAccount(
|
||||
this.migrationStateModel._targetType,
|
||||
this.migrationStateModel._targetServerInstance,
|
||||
selectedStorageAccount, this.migrationStateModel._azureAccount,
|
||||
this.migrationStateModel._targetSubscription))) {
|
||||
this._inaccessibleStorageAccounts = [selectedStorageAccount.name];
|
||||
} else {
|
||||
this._inaccessibleStorageAccounts = [];
|
||||
@@ -1129,7 +1139,13 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
||||
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))) {
|
||||
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);
|
||||
}
|
||||
@@ -1452,10 +1468,10 @@ export class DatabaseBackupPage extends MigrationWizardPage {
|
||||
|
||||
private async getSubscriptionValues(): Promise<void> {
|
||||
this._networkShareContainerSubscription.value = this.migrationStateModel._targetSubscription.name;
|
||||
this._networkShareContainerLocation.value = await this.migrationStateModel.getLocationDisplayName(this.migrationStateModel._targetServerInstance.location);
|
||||
this._networkShareContainerLocation.value = await this.migrationStateModel._location.displayName;
|
||||
|
||||
this._blobContainerSubscription.value = this.migrationStateModel._targetSubscription.name;
|
||||
this._blobContainerLocation.value = await this.migrationStateModel.getLocationDisplayName(this.migrationStateModel._targetServerInstance.location);
|
||||
this._blobContainerLocation.value = this.migrationStateModel._location.displayName;
|
||||
|
||||
this.migrationStateModel._databaseBackup.subscription = this.migrationStateModel._targetSubscription;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import { MigrationMode, MigrationStateModel, NetworkContainerType, StateChangeEv
|
||||
import { CreateSqlMigrationServiceDialog } from '../dialog/createSqlMigrationService/createSqlMigrationServiceDialog';
|
||||
import * as constants from '../constants/strings';
|
||||
import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
|
||||
import { getFullResourceGroupFromId, getLocationDisplayName, getSqlMigrationService, getSqlMigrationServiceAuthKeys, getSqlMigrationServiceMonitoringData, SqlVMServer } from '../api/azure';
|
||||
import { getFullResourceGroupFromId, getSqlMigrationService, getSqlMigrationServiceAuthKeys, getSqlMigrationServiceMonitoringData, SqlVMServer } from '../api/azure';
|
||||
import { IconPathHelper } from '../constants/iconPathHelper';
|
||||
import { logError, TelemetryViews } from '../telemetry';
|
||||
import * as utils from '../api/utils';
|
||||
@@ -19,7 +19,7 @@ import * as styles from '../constants/styles';
|
||||
export class IntergrationRuntimePage extends MigrationWizardPage {
|
||||
private _view!: azdata.ModelView;
|
||||
private _statusLoadingComponent!: azdata.LoadingComponent;
|
||||
private _subscription!: azdata.TextComponent;
|
||||
private _subscriptionDropdown!: azdata.DropDownComponent;
|
||||
private _location!: azdata.TextComponent;
|
||||
private _resourceGroupDropdown!: azdata.DropDownComponent;
|
||||
private _dmsDropdown!: azdata.DropDownComponent;
|
||||
@@ -27,7 +27,6 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
||||
private _dmsStatusInfoBox!: azdata.InfoBoxComponent;
|
||||
private _authKeyTable!: azdata.DeclarativeTableComponent;
|
||||
private _refreshButton!: azdata.ButtonComponent;
|
||||
private _connectionStatusLoader!: azdata.LoadingComponent;
|
||||
private _copy1!: azdata.ButtonComponent;
|
||||
private _copy2!: azdata.ButtonComponent;
|
||||
private _refresh1!: azdata.ButtonComponent;
|
||||
@@ -157,8 +156,13 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
||||
this._networkShareButton.onDidChangeCheckedState(async checked => {
|
||||
if (checked) {
|
||||
this.migrationStateModel._databaseBackup.networkContainerType = NetworkContainerType.NETWORK_SHARE;
|
||||
await utils.updateControlDisplay(this._dmsInfoContainer, true);
|
||||
this.migrationStateModel.refreshDatabaseBackupPage = true;
|
||||
|
||||
const hasService = this.migrationStateModel._sqlMigrationService !== undefined;
|
||||
await utils.updateControlDisplay(this._dmsInfoContainer, hasService);
|
||||
if (hasService) {
|
||||
await this.loadStatus();
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -271,15 +275,13 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
||||
this.migrationStateModel._databaseBackup.networkContainerType = NetworkContainerType.BLOB_CONTAINER;
|
||||
this._blobContainerButton.checked = true;
|
||||
|
||||
this._subscription.value = this.migrationStateModel._targetSubscription.name;
|
||||
this._location.value = await getLocationDisplayName(
|
||||
this.migrationStateModel._targetServerInstance.location);
|
||||
await this.loadSubscriptionsDropdown();
|
||||
|
||||
this._location.value = this.migrationStateModel._location.displayName;
|
||||
|
||||
await utils.updateControlDisplay(
|
||||
this._dmsInfoContainer,
|
||||
isSqlDbTarget || isNetworkShare);
|
||||
|
||||
await this.loadResourceGroupDropdown();
|
||||
}
|
||||
|
||||
public async onPageLeave(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
|
||||
@@ -306,13 +308,32 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
||||
value: constants.SUBSCRIPTION,
|
||||
CSSStyles: { ...styles.LABEL_CSS }
|
||||
}).component();
|
||||
this._subscription = this._view.modelBuilder.text()
|
||||
|
||||
this._subscriptionDropdown = this._view.modelBuilder.dropDown()
|
||||
.withProps({
|
||||
enabled: false,
|
||||
ariaLabel: constants.MIGRATION_SERVICE_SELECT_SERVICE_LABEL,
|
||||
width: WIZARD_INPUT_COMPONENT_WIDTH,
|
||||
editable: true,
|
||||
required: true,
|
||||
fireOnTextChange: true,
|
||||
placeholder: constants.SELECT_A_SERVICE,
|
||||
CSSStyles: { 'margin': '0' }
|
||||
}).component();
|
||||
|
||||
this._disposables.push(
|
||||
this._subscriptionDropdown.onValueChanged(async (value) => {
|
||||
if (value && value !== 'undefined' && value !== constants.SERVICE_NOT_FOUND) {
|
||||
const selectedSubscription = this.migrationStateModel._subscriptions.find(
|
||||
sub => `${sub.name} - ${sub.id}` === value);
|
||||
this.migrationStateModel._sqlMigrationServiceSubscription = (selectedSubscription)
|
||||
? selectedSubscription
|
||||
: undefined!;
|
||||
} else {
|
||||
this.migrationStateModel._sqlMigrationServiceSubscription = undefined!;
|
||||
}
|
||||
await this.loadResourceGroupDropdown();
|
||||
}));
|
||||
|
||||
const locationLabel = this._view.modelBuilder.text()
|
||||
.withProps({
|
||||
value: constants.LOCATION,
|
||||
@@ -349,8 +370,11 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
||||
this.migrationStateModel._sqlMigrationServiceResourceGroup = (selectedResourceGroup)
|
||||
? selectedResourceGroup
|
||||
: undefined!;
|
||||
this.populateDms();
|
||||
}
|
||||
else {
|
||||
this.migrationStateModel._sqlMigrationServiceResourceGroup = undefined!;
|
||||
}
|
||||
this.loadDmsDropdown();
|
||||
}));
|
||||
|
||||
const migrationServiceDropdownLabel = this._view.modelBuilder.text()
|
||||
@@ -379,15 +403,18 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
||||
dms => dms.name === value
|
||||
&& dms.properties.resourceGroup.toLowerCase() === resourceGroupName);
|
||||
|
||||
if (selectedDms) {
|
||||
this.migrationStateModel._sqlMigrationService = selectedDms;
|
||||
await this.loadStatus();
|
||||
}
|
||||
const showShirStatus = selectedDms !== undefined &&
|
||||
(this.migrationStateModel.isSqlDbTarget ||
|
||||
this.migrationStateModel.isBackupContainerNetworkShare);
|
||||
|
||||
this.migrationStateModel._sqlMigrationService = selectedDms;
|
||||
await utils.updateControlDisplay(
|
||||
this._dmsInfoContainer,
|
||||
this.migrationStateModel.isSqlDbTarget ||
|
||||
this.migrationStateModel.isBackupContainerNetworkShare);
|
||||
showShirStatus);
|
||||
|
||||
if (showShirStatus) {
|
||||
await this.loadStatus();
|
||||
}
|
||||
} else {
|
||||
this.migrationStateModel._sqlMigrationService = undefined;
|
||||
await utils.updateControlDisplay(this._dmsInfoContainer, false);
|
||||
@@ -414,15 +441,15 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
||||
|
||||
this.migrationStateModel._sqlMigrationServiceResourceGroup = createdDmsResult.resourceGroup;
|
||||
this.migrationStateModel._sqlMigrationService = createdDmsResult.service;
|
||||
|
||||
await this.loadResourceGroupDropdown();
|
||||
this.populateDms();
|
||||
}));
|
||||
|
||||
return this._view.modelBuilder.flexContainer()
|
||||
.withItems([
|
||||
descriptionText,
|
||||
subscriptionLabel,
|
||||
this._subscription,
|
||||
this._subscriptionDropdown,
|
||||
locationLabel,
|
||||
this._location,
|
||||
resourceGroupLabel,
|
||||
@@ -534,48 +561,71 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
||||
authenticationKeysLabel,
|
||||
this._authKeyTable]);
|
||||
|
||||
this._connectionStatusLoader = this._view.modelBuilder.loadingComponent()
|
||||
.withItem(statusContainer)
|
||||
.withProps({ loading: false })
|
||||
.component();
|
||||
|
||||
container.addItems([
|
||||
connectionLabelContainer,
|
||||
this._connectionStatusLoader]);
|
||||
statusContainer]);
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
public async loadSubscriptionsDropdown(): Promise<void> {
|
||||
try {
|
||||
this._subscriptionDropdown.loading = true;
|
||||
this.migrationStateModel._subscriptions = await utils.getAzureSubscriptions(
|
||||
this.migrationStateModel._azureAccount);
|
||||
|
||||
const sub = this.migrationStateModel._sqlMigrationServiceSubscription
|
||||
?? this.migrationStateModel._targetSubscription;
|
||||
|
||||
this._subscriptionDropdown.values = await utils.getAzureSubscriptionsDropdownValues(
|
||||
this.migrationStateModel._subscriptions);
|
||||
|
||||
utils.selectDefaultDropdownValue(this._subscriptionDropdown, sub?.id, false);
|
||||
} catch (e) {
|
||||
logError(TelemetryViews.IntegrationRuntimePage, 'Error loadSubscriptionsDropdown', e);
|
||||
} finally {
|
||||
this._subscriptionDropdown.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
public async loadResourceGroupDropdown(): Promise<void> {
|
||||
try {
|
||||
this._resourceGroupDropdown.loading = true;
|
||||
this._dmsDropdown.loading = true;
|
||||
const account = this.migrationStateModel._azureAccount;
|
||||
const subscription = this.migrationStateModel._sqlMigrationServiceSubscription;
|
||||
const serviceId = this.migrationStateModel._sqlMigrationService?.id;
|
||||
const resourceGroup = this.migrationStateModel._sqlMigrationServiceResourceGroup?.name ??
|
||||
serviceId !== undefined
|
||||
? getFullResourceGroupFromId(serviceId!)
|
||||
: undefined;
|
||||
|
||||
this.migrationStateModel._sqlMigrationServices = await utils.getAzureSqlMigrationServices(
|
||||
this.migrationStateModel._azureAccount,
|
||||
this.migrationStateModel._targetSubscription);
|
||||
const migrationServices = await utils.getAzureSqlMigrationServices(
|
||||
account,
|
||||
subscription);
|
||||
|
||||
this.migrationStateModel._resourceGroups = utils.getServiceResourceGroupsByLocation(
|
||||
this.migrationStateModel._sqlMigrationServices,
|
||||
const resourceGroups = utils.getServiceResourceGroupsByLocation(
|
||||
migrationServices,
|
||||
this.migrationStateModel._location);
|
||||
|
||||
this._resourceGroupDropdown.values = utils.getResourceDropdownValues(
|
||||
this.migrationStateModel._resourceGroups,
|
||||
resourceGroups,
|
||||
constants.RESOURCE_GROUP_NOT_FOUND);
|
||||
|
||||
const resourceGroup = this.migrationStateModel._sqlMigrationService
|
||||
? getFullResourceGroupFromId(this.migrationStateModel._sqlMigrationService?.id)
|
||||
: undefined;
|
||||
this.migrationStateModel._sqlMigrationServices = migrationServices;
|
||||
this.migrationStateModel._resourceGroups = resourceGroups;
|
||||
utils.selectDefaultDropdownValue(this._resourceGroupDropdown, resourceGroup, false);
|
||||
} catch (e) {
|
||||
logError(TelemetryViews.IntegrationRuntimePage, 'Error loadResourceGroupDropdown', e);
|
||||
} finally {
|
||||
this._dmsDropdown.loading = false;
|
||||
this._resourceGroupDropdown.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
public populateDms(): void {
|
||||
public loadDmsDropdown(): void {
|
||||
try {
|
||||
this._dmsDropdown.loading = true;
|
||||
const serviceId = this.migrationStateModel._sqlMigrationService?.id;
|
||||
|
||||
this._dmsDropdown.values = utils.getAzureResourceDropdownValues(
|
||||
this.migrationStateModel._sqlMigrationServices,
|
||||
this.migrationStateModel._location,
|
||||
@@ -584,53 +634,77 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
||||
|
||||
utils.selectDefaultDropdownValue(
|
||||
this._dmsDropdown,
|
||||
this.migrationStateModel._sqlMigrationService?.id,
|
||||
serviceId,
|
||||
false);
|
||||
} catch (e) {
|
||||
logError(TelemetryViews.IntegrationRuntimePage, 'Error loadDmsDropdown', e);
|
||||
} finally {
|
||||
this._dmsDropdown.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private _lastIn = 0;
|
||||
private async loadStatus(): Promise<void> {
|
||||
const callSequence = ++this._lastIn;
|
||||
let serviceName = '';
|
||||
try {
|
||||
this._statusLoadingComponent.loading = true;
|
||||
if (callSequence === this._lastIn) {
|
||||
this._statusLoadingComponent.loading = true;
|
||||
}
|
||||
|
||||
const service = this.migrationStateModel._sqlMigrationService;
|
||||
if (service) {
|
||||
const account = this.migrationStateModel._azureAccount;
|
||||
const subscription = this.migrationStateModel._sqlMigrationServiceSubscription;
|
||||
const resourceGroup = service.properties.resourceGroup;
|
||||
const location = service.location;
|
||||
serviceName = service.name;
|
||||
if (service?.properties?.integrationRuntimeState) {
|
||||
service.properties.integrationRuntimeState = undefined;
|
||||
}
|
||||
|
||||
if (this.migrationStateModel._sqlMigrationService) {
|
||||
const migrationService = await getSqlMigrationService(
|
||||
this.migrationStateModel._azureAccount,
|
||||
this.migrationStateModel._targetSubscription,
|
||||
this.migrationStateModel._sqlMigrationService.properties.resourceGroup,
|
||||
this.migrationStateModel._sqlMigrationService.location,
|
||||
this.migrationStateModel._sqlMigrationService.name);
|
||||
this.migrationStateModel._sqlMigrationService = migrationService;
|
||||
account,
|
||||
subscription,
|
||||
resourceGroup,
|
||||
location,
|
||||
serviceName);
|
||||
|
||||
// exit if new call has started
|
||||
if (callSequence !== this._lastIn) { return; }
|
||||
|
||||
const migrationServiceMonitoringStatus = await getSqlMigrationServiceMonitoringData(
|
||||
this.migrationStateModel._azureAccount,
|
||||
this.migrationStateModel._targetSubscription,
|
||||
this.migrationStateModel._sqlMigrationService.properties.resourceGroup,
|
||||
this.migrationStateModel._sqlMigrationService.location,
|
||||
this.migrationStateModel._sqlMigrationService!.name);
|
||||
this.migrationStateModel._nodeNames = migrationServiceMonitoringStatus.nodes.map(
|
||||
account,
|
||||
subscription,
|
||||
resourceGroup,
|
||||
location,
|
||||
serviceName);
|
||||
|
||||
const nodeNames = migrationServiceMonitoringStatus.nodes.map(
|
||||
node => node.nodeName);
|
||||
|
||||
// exit if new call has started
|
||||
if (callSequence !== this._lastIn) { return; }
|
||||
|
||||
const migrationServiceAuthKeys = await getSqlMigrationServiceAuthKeys(
|
||||
this.migrationStateModel._azureAccount,
|
||||
this.migrationStateModel._targetSubscription,
|
||||
this.migrationStateModel._sqlMigrationService.properties.resourceGroup,
|
||||
this.migrationStateModel._sqlMigrationService.location,
|
||||
this.migrationStateModel._sqlMigrationService!.name);
|
||||
account,
|
||||
subscription,
|
||||
resourceGroup,
|
||||
location,
|
||||
serviceName);
|
||||
|
||||
// exit if new call has started
|
||||
if (callSequence !== this._lastIn) { return; }
|
||||
|
||||
const state = migrationService.properties.integrationRuntimeState;
|
||||
if (state === 'Online') {
|
||||
await this._dmsStatusInfoBox.updateProperties(<azdata.InfoBoxComponentProperties>{
|
||||
text: constants.SERVICE_READY(
|
||||
this.migrationStateModel._sqlMigrationService!.name,
|
||||
this.migrationStateModel._nodeNames.join(', ')),
|
||||
text: constants.SERVICE_READY(serviceName, nodeNames.join(', ')),
|
||||
style: 'success'
|
||||
});
|
||||
} else {
|
||||
await this._dmsStatusInfoBox.updateProperties(<azdata.InfoBoxComponentProperties>{
|
||||
text: constants.SERVICE_NOT_READY(
|
||||
this.migrationStateModel._sqlMigrationService!.name),
|
||||
text: constants.SERVICE_NOT_READY(serviceName),
|
||||
style: 'error'
|
||||
});
|
||||
}
|
||||
@@ -655,12 +729,26 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
|
||||
}
|
||||
]];
|
||||
|
||||
// exit if new call has started
|
||||
if (callSequence !== this._lastIn) { return; }
|
||||
|
||||
await this._authKeyTable.setDataValues(data);
|
||||
|
||||
this.migrationStateModel._sqlMigrationService = migrationService;
|
||||
this.migrationStateModel._sqlMigrationServiceSubscription = subscription;
|
||||
this.migrationStateModel._nodeNames = nodeNames;
|
||||
}
|
||||
} catch (e) {
|
||||
logError(TelemetryViews.IntegrationRuntimePage, 'ErrorLoadingStatus', e);
|
||||
await this._dmsStatusInfoBox.updateProperties(<azdata.InfoBoxComponentProperties>{
|
||||
text: constants.SERVICE_ERROR_NOT_READY(serviceName, e.message),
|
||||
style: 'error'
|
||||
});
|
||||
|
||||
logError(TelemetryViews.IntegrationRuntimePage, 'Error loadStatus', e);
|
||||
} finally {
|
||||
this._statusLoadingComponent.loading = false;
|
||||
if (callSequence === this._lastIn) {
|
||||
this._statusLoadingComponent.loading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,8 +100,7 @@ export class SummaryPage extends MigrationWizardPage {
|
||||
createInformationRow(
|
||||
this._view,
|
||||
constants.LOCATION,
|
||||
await this.migrationStateModel.getLocationDisplayName(
|
||||
this.migrationStateModel._targetServerInstance.location)),
|
||||
this.migrationStateModel._location.displayName),
|
||||
createInformationRow(
|
||||
this._view,
|
||||
constants.RESOURCE_GROUP,
|
||||
@@ -140,16 +139,15 @@ export class SummaryPage extends MigrationWizardPage {
|
||||
constants.IR_PAGE_TITLE),
|
||||
createInformationRow(
|
||||
this._view, constants.SUBSCRIPTION,
|
||||
this.migrationStateModel._targetSubscription.name),
|
||||
this.migrationStateModel._sqlMigrationServiceSubscription.name),
|
||||
createInformationRow(
|
||||
this._view,
|
||||
constants.LOCATION,
|
||||
await this.migrationStateModel.getLocationDisplayName(
|
||||
this.migrationStateModel._sqlMigrationService?.location!)),
|
||||
this.migrationStateModel._location.displayName),
|
||||
createInformationRow(
|
||||
this._view,
|
||||
constants.RESOURCE_GROUP,
|
||||
this.migrationStateModel._sqlMigrationService?.properties?.resourceGroup!),
|
||||
this.migrationStateModel._sqlMigrationServiceResourceGroup.name),
|
||||
createInformationRow(
|
||||
this._view,
|
||||
constants.IR_PAGE_TITLE,
|
||||
|
||||
@@ -709,7 +709,10 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
||||
|
||||
if (selectedVm) {
|
||||
this.migrationStateModel._targetServerInstance = utils.deepClone(selectedVm)! as SqlVMServer;
|
||||
this.migrationStateModel._vmInstanceView = await getVMInstanceView(this.migrationStateModel._targetServerInstance, this.migrationStateModel._azureAccount, this.migrationStateModel._targetSubscription);
|
||||
this.migrationStateModel._vmInstanceView = await getVMInstanceView(
|
||||
this.migrationStateModel._targetServerInstance,
|
||||
this.migrationStateModel._azureAccount,
|
||||
this.migrationStateModel._targetSubscription);
|
||||
this.wizard.message = { text: '' };
|
||||
|
||||
// validate power state from VM instance view
|
||||
@@ -870,45 +873,45 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
||||
this._azureAccountsDropdown.loading = true;
|
||||
this.migrationStateModel._azureAccounts = await utils.getAzureAccounts();
|
||||
|
||||
this._azureAccountsDropdown.values = await utils.getAzureAccountsDropdownValues(this.migrationStateModel._azureAccounts);
|
||||
} finally {
|
||||
this._azureAccountsDropdown.loading = false;
|
||||
const accountId =
|
||||
this.migrationStateModel._azureAccount?.displayInfo?.userId ??
|
||||
this._serviceContext?.azureAccount?.displayInfo?.userId;
|
||||
this._azureAccountsDropdown.values = await utils.getAzureAccountsDropdownValues(this.migrationStateModel._azureAccounts);
|
||||
|
||||
utils.selectDefaultDropdownValue(
|
||||
this._azureAccountsDropdown,
|
||||
accountId,
|
||||
false);
|
||||
} finally {
|
||||
this._azureAccountsDropdown.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async populateTenantsDropdown(): Promise<void> {
|
||||
try {
|
||||
this._accountTenantDropdown.loading = true;
|
||||
if (!utils.isAccountTokenStale(this.migrationStateModel._azureAccount) &&
|
||||
this.migrationStateModel._azureAccount?.properties?.tenants?.length > 0) {
|
||||
this.migrationStateModel._accountTenants = utils.getAzureTenants(this.migrationStateModel._azureAccount);
|
||||
|
||||
this._accountTenantDropdown.values = utils.getAzureTenantsDropdownValues(this.migrationStateModel._accountTenants);
|
||||
}
|
||||
const tenantId =
|
||||
this.migrationStateModel._azureTenant?.id ??
|
||||
this._serviceContext?.tenant?.id;
|
||||
|
||||
if (!utils.isAccountTokenStale(this.migrationStateModel._azureAccount) &&
|
||||
this.migrationStateModel._azureAccount?.properties?.tenants?.length > 0) {
|
||||
this.migrationStateModel._accountTenants = utils.getAzureTenants(this.migrationStateModel._azureAccount);
|
||||
this._accountTenantDropdown.values = utils.getAzureTenantsDropdownValues(this.migrationStateModel._accountTenants);
|
||||
}
|
||||
|
||||
utils.selectDefaultDropdownValue(
|
||||
this._accountTenantDropdown,
|
||||
tenantId,
|
||||
true);
|
||||
await this._azureAccountsDropdown.validate();
|
||||
} finally {
|
||||
this._accountTenantDropdown.loading = false;
|
||||
await this._accountTenantFlexContainer.updateCssStyles(
|
||||
this.migrationStateModel._azureAccount?.properties?.tenants?.length > 1
|
||||
? { 'display': 'inline' }
|
||||
: { 'display': 'none' }
|
||||
);
|
||||
await this._azureAccountsDropdown.validate();
|
||||
} finally {
|
||||
this._accountTenantDropdown.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -916,19 +919,20 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
||||
try {
|
||||
this._azureSubscriptionDropdown.loading = true;
|
||||
this.migrationStateModel._subscriptions = await utils.getAzureSubscriptions(this.migrationStateModel._azureAccount);
|
||||
this._azureSubscriptionDropdown.values = await utils.getAzureSubscriptionsDropdownValues(this.migrationStateModel._subscriptions);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} finally {
|
||||
this._azureSubscriptionDropdown.loading = false;
|
||||
const subscriptionId =
|
||||
this.migrationStateModel._targetSubscription?.id ??
|
||||
this._serviceContext?.subscription?.id;
|
||||
|
||||
this._azureSubscriptionDropdown.values = await utils.getAzureSubscriptionsDropdownValues(this.migrationStateModel._subscriptions);
|
||||
|
||||
utils.selectDefaultDropdownValue(
|
||||
this._azureSubscriptionDropdown,
|
||||
subscriptionId,
|
||||
false);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} finally {
|
||||
this._azureSubscriptionDropdown.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -964,19 +968,20 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
||||
this.migrationStateModel._targetSqlDatabaseServers);
|
||||
break;
|
||||
}
|
||||
this._azureLocationDropdown.values = utils.getAzureLocationsDropdownValues(this.migrationStateModel._locations);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} finally {
|
||||
this._azureLocationDropdown.loading = false;
|
||||
|
||||
const location =
|
||||
this.migrationStateModel._location?.displayName ??
|
||||
this._serviceContext?.location?.displayName;
|
||||
|
||||
this._azureLocationDropdown.values = utils.getAzureLocationsDropdownValues(this.migrationStateModel._locations);
|
||||
utils.selectDefaultDropdownValue(
|
||||
this._azureLocationDropdown,
|
||||
location,
|
||||
true);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} finally {
|
||||
this._azureLocationDropdown.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1000,24 +1005,29 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
||||
this.migrationStateModel._location);
|
||||
break;
|
||||
}
|
||||
|
||||
const resourceGroupId = this.migrationStateModel._resourceGroup?.id;
|
||||
|
||||
this._azureResourceGroupDropdown.values = utils.getResourceDropdownValues(
|
||||
this.migrationStateModel._resourceGroups,
|
||||
constants.RESOURCE_GROUP_NOT_FOUND);
|
||||
|
||||
utils.selectDefaultDropdownValue(
|
||||
this._azureResourceGroupDropdown,
|
||||
resourceGroupId,
|
||||
false);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} finally {
|
||||
this._azureResourceGroupDropdown.loading = false;
|
||||
|
||||
utils.selectDefaultDropdownValue(
|
||||
this._azureResourceGroupDropdown,
|
||||
this.migrationStateModel._resourceGroup?.id,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
private async populateResourceInstanceDropdown(): Promise<void> {
|
||||
try {
|
||||
this._azureResourceDropdown.loading = true;
|
||||
const targetName = this.migrationStateModel.migrationTargetServerName;
|
||||
|
||||
switch (this.migrationStateModel._targetType) {
|
||||
case MigrationTargetType.SQLMI:
|
||||
this._azureResourceDropdown.values = await utils.getManagedInstancesDropdownValues(
|
||||
@@ -1043,31 +1053,19 @@ export class TargetSelectionPage extends MigrationWizardPage {
|
||||
constants.NO_SQL_DATABASE_SERVER_FOUND);
|
||||
break;
|
||||
}
|
||||
} finally {
|
||||
this._azureResourceDropdown.loading = false;
|
||||
let targetName = '';
|
||||
switch (this.migrationStateModel._targetType) {
|
||||
case MigrationTargetType.SQLMI:
|
||||
targetName = (this.migrationStateModel._targetServerInstance as azureResource.AzureSqlManagedInstance)?.name;
|
||||
break;
|
||||
case MigrationTargetType.SQLVM:
|
||||
targetName = (this.migrationStateModel._targetServerInstance as SqlVMServer)?.name;
|
||||
break;
|
||||
case MigrationTargetType.SQLDB:
|
||||
targetName = (this.migrationStateModel._targetServerInstance as AzureSqlDatabaseServer)?.name;
|
||||
break;
|
||||
}
|
||||
|
||||
utils.selectDefaultDropdownValue(
|
||||
this._azureResourceDropdown,
|
||||
targetName,
|
||||
true);
|
||||
} finally {
|
||||
this._azureResourceDropdown.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private _updateTdeMigrationButtonStatus() {
|
||||
|
||||
this.wizard.customButtons[TDE_MIGRATION_BUTTON_INDEX].enabled = this.migrationStateModel.tdeMigrationConfig.shouldAdsMigrateCertificates() &&
|
||||
this.wizard.customButtons[TDE_MIGRATION_BUTTON_INDEX].enabled =
|
||||
this.migrationStateModel.tdeMigrationConfig.shouldAdsMigrateCertificates() &&
|
||||
this.migrationStateModel._targetManagedInstances.length > 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -272,10 +272,7 @@ export class WizardController {
|
||||
stateModel: MigrationStateModel,
|
||||
serviceContextChangedEvent: vscode.EventEmitter<ServiceContextChangeEvent>): Promise<void> {
|
||||
|
||||
const resourceGroup = this._getResourceGroupByName(
|
||||
stateModel._resourceGroups,
|
||||
stateModel._sqlMigrationService?.properties.resourceGroup);
|
||||
|
||||
const resourceGroup = stateModel._sqlMigrationServiceResourceGroup;
|
||||
const subscription = this._getSubscriptionFromResourceId(
|
||||
stateModel._subscriptions,
|
||||
resourceGroup?.id);
|
||||
@@ -296,13 +293,6 @@ export class WizardController {
|
||||
serviceContextChangedEvent);
|
||||
}
|
||||
|
||||
private _getResourceGroupByName(
|
||||
resourceGroups: azureResource.AzureResourceResourceGroup[],
|
||||
displayName?: string): azureResource.AzureResourceResourceGroup | undefined {
|
||||
|
||||
return resourceGroups.find(rg => rg.name === displayName);
|
||||
}
|
||||
|
||||
private _getLocationByValue(
|
||||
locations: azureResource.AzureLocation[],
|
||||
name?: string): azureResource.AzureLocation | undefined {
|
||||
|
||||
Reference in New Issue
Block a user