Renaming controller to migration service and other bug fixes/ validations. (#14751)

* - Added coming soon message for learn more.
- Potential fix for learn more message

* Renaming of controller to sqlMigrationService

* Surfacing some errors
-Azure account is stale error
-Migration Service creation error.

* Adding refresh azure token validation.

* Fixing some errors pointed during PR
-Fixing property names
-Fixing count

* Fixing migration status
- Adding special error handling for resource not found error
- Deleting unfound migrations from local cache
- Using prefetched migration status for view all

Misc fixes:
- Using SQL server version name instead of number
- Fixing Icons on sku recommendation page
- Fixing table column width in cutover dialog
- Adding spinner button to refresh.

* Fixing all strings in migration service page and dialog

* fixed a string error in create service dialog
This commit is contained in:
Aasim Khan
2021-03-17 14:55:24 -07:00
committed by GitHub
parent 5917f869ef
commit c7cca7e9f0
16 changed files with 558 additions and 418 deletions

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { azureResource } from 'azureResource';
import { DatabaseMigration, SqlMigrationController, SqlManagedInstance } from '../api/azure';
import { DatabaseMigration, SqlMigrationService, SqlManagedInstance, getDatabaseMigration } from '../api/azure';
import * as azdata from 'azdata';
@@ -16,23 +16,39 @@ export class MigrationLocalStorage {
MigrationLocalStorage.context = context;
}
public static getMigrationsBySourceConnections(connectionProfile: azdata.connection.ConnectionProfile): MigrationContext[] {
public static async getMigrationsBySourceConnections(connectionProfile: azdata.connection.ConnectionProfile, refreshStatus?: boolean): Promise<MigrationContext[]> {
let dataBaseMigrations: MigrationContext[] = [];
try {
const migrationMementos: MigrationContext[] = this.context.globalState.get(this.mementoToken) || [];
const result: MigrationContext[] = [];
const validMigrations: MigrationContext[] = [];
dataBaseMigrations = migrationMementos.filter((memento) => {
return memento.sourceConnectionProfile.serverName === connectionProfile.serverName;
}).map((memento) => {
return memento;
});
} catch (e) {
console.log(e);
const migrationMementos: MigrationContext[] = this.context.globalState.get(this.mementoToken) || [];
for (let i = 0; i < migrationMementos.length; i++) {
const migration = migrationMementos[i];
if (migration.sourceConnectionProfile.serverName === connectionProfile.serverName) {
if (refreshStatus) {
try {
migration.migrationContext = await getDatabaseMigration(
migration.azureAccount,
migration.subscription,
migration.targetManagedInstance.location,
migration.migrationContext.id
);
}
catch (e) {
// Keeping only valid migrations in cache. Clearing all the migrations which return ResourceDoesNotExit error.
if (e.message === 'ResourceDoesNotExist') {
continue;
} else {
console.log(e);
}
}
}
result.push(migration);
}
validMigrations.push(migration);
}
return dataBaseMigrations;
this.context.globalState.update(this.mementoToken, validMigrations);
return result;
}
public static saveMigration(
@@ -41,7 +57,7 @@ export class MigrationLocalStorage {
targetMI: SqlManagedInstance,
azureAccount: azdata.Account,
subscription: azureResource.AzureResourceSubscription,
controller: SqlMigrationController): void {
controller: SqlMigrationService): void {
try {
const migrationMementos: MigrationContext[] = this.context.globalState.get(this.mementoToken) || [];
migrationMementos.push({
@@ -69,5 +85,5 @@ export interface MigrationContext {
targetManagedInstance: SqlManagedInstance,
azureAccount: azdata.Account,
subscription: azureResource.AzureResourceSubscription,
controller: SqlMigrationController
controller: SqlMigrationService
}

View File

@@ -2,6 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IconPath } from 'azdata';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
@@ -23,11 +24,11 @@ export interface Checks {
export interface Product extends MigrationProduct {
readonly name: string;
readonly learnMoreLink?: string;
readonly icon?: string;
readonly icon?: IconPath;
}
export class Product implements Product {
constructor(public readonly type: MigrationProductType, public readonly name: string, public readonly icon?: string, public readonly learnMoreLink?: string) {
constructor(public readonly type: MigrationProductType, public readonly name: string, public readonly icon?: IconPath, public readonly learnMoreLink?: string) {
}

View File

@@ -8,7 +8,7 @@ import { azureResource } from 'azureResource';
import * as azurecore from 'azurecore';
import * as vscode from 'vscode';
import * as mssql from '../../../mssql';
import { getAvailableManagedInstanceProducts, getAvailableStorageAccounts, getBlobContainers, getFileShares, getMigrationControllers, getSubscriptions, SqlMigrationController, SqlManagedInstance, startDatabaseMigration, StartDatabaseMigrationRequest, StorageAccount, getAvailableSqlVMs, SqlVMServer } from '../api/azure';
import { getAvailableManagedInstanceProducts, getAvailableStorageAccounts, getBlobContainers, getFileShares, getSqlMigrationServices, getSubscriptions, SqlMigrationService, SqlManagedInstance, startDatabaseMigration, StartDatabaseMigrationRequest, StorageAccount, getAvailableSqlVMs, SqlVMServer } from '../api/azure';
import { SKURecommendations } from './externalContract';
import * as constants from '../constants/strings';
import { MigrationLocalStorage } from './migrationLocalStorage';
@@ -96,8 +96,8 @@ export class MigrationStateModel implements Model, vscode.Disposable {
public _refreshNetworkShareLocation!: azureResource.BlobContainer[];
public _targetDatabaseNames!: string[];
public _migrationController!: SqlMigrationController;
public _migrationControllers!: SqlMigrationController[];
public _sqlMigrationService!: SqlMigrationService;
public _sqlMigrationServices!: SqlMigrationService[];
public _nodeNames!: string[];
private _stateChangeEventEmitter = new vscode.EventEmitter<StateChangeEvent>();
@@ -426,39 +426,39 @@ export class MigrationStateModel implements Model, vscode.Disposable {
}
public async getMigrationControllerValues(subscription: azureResource.AzureResourceSubscription, managedInstance: SqlManagedInstance): Promise<azdata.CategoryValue[]> {
let migrationControllerValues: azdata.CategoryValue[] = [];
public async getSqlMigrationServiceValues(subscription: azureResource.AzureResourceSubscription, managedInstance: SqlManagedInstance): Promise<azdata.CategoryValue[]> {
let sqlMigrationServiceValues: azdata.CategoryValue[] = [];
try {
this._migrationControllers = await getMigrationControllers(this._azureAccount, subscription, managedInstance.resourceGroup!, managedInstance.location);
this._migrationControllers.forEach((migrationController) => {
migrationControllerValues.push({
name: migrationController.id,
displayName: `${migrationController.name}`
this._sqlMigrationServices = await getSqlMigrationServices(this._azureAccount, subscription, managedInstance.location);
this._sqlMigrationServices.forEach((sqlMigrationService) => {
sqlMigrationServiceValues.push({
name: sqlMigrationService.id,
displayName: `${sqlMigrationService.name}`
});
});
if (migrationControllerValues.length === 0) {
migrationControllerValues = [
if (sqlMigrationServiceValues.length === 0) {
sqlMigrationServiceValues = [
{
displayName: constants.MIGRATION_CONTROLLER_NOT_FOUND_ERROR,
displayName: constants.SQL_MIGRATION_SERVICE_NOT_FOUND_ERROR,
name: ''
}
];
}
} catch (e) {
console.log(e);
migrationControllerValues = [
sqlMigrationServiceValues = [
{
displayName: constants.MIGRATION_CONTROLLER_NOT_FOUND_ERROR,
displayName: constants.SQL_MIGRATION_SERVICE_NOT_FOUND_ERROR,
name: ''
}
];
}
return migrationControllerValues;
return sqlMigrationServiceValues;
}
public getMigrationController(index: number): SqlMigrationController {
return this._migrationControllers[index];
public getMigrationService(index: number): SqlMigrationService {
return this._sqlMigrationServices[index];
}
public async startMigration() {
@@ -473,41 +473,41 @@ export class MigrationStateModel implements Model, vscode.Disposable {
const connectionPassword = await azdata.connection.getCredentials(this.sourceConnectionId);
const requestBody: StartDatabaseMigrationRequest = {
location: this._migrationController?.properties.location!,
location: this._sqlMigrationService?.properties.location!,
properties: {
SourceDatabaseName: '',
MigrationController: this._migrationController?.id!,
BackupConfiguration: {
TargetLocation: {
StorageAccountResourceId: this._databaseBackup.storageAccount.id,
AccountKey: this._databaseBackup.storageKey,
sourceDatabaseName: '',
migrationService: this._sqlMigrationService?.id!,
backupConfiguration: {
targetLocation: {
storageAccountResourceId: this._databaseBackup.storageAccount.id,
accountKey: this._databaseBackup.storageKey,
},
SourceLocation: {
FileShare: {
Path: '',
Username: this._databaseBackup.windowsUser,
Password: this._databaseBackup.password,
sourceLocation: {
fileShare: {
path: '',
username: this._databaseBackup.windowsUser,
password: this._databaseBackup.password,
}
},
},
SourceSqlConnection: {
DataSource: currentConnection?.serverName!,
Username: currentConnection?.userName!,
Password: connectionPassword.password
sourceSqlConnection: {
dataSource: currentConnection?.serverName!,
username: currentConnection?.userName!,
password: connectionPassword.password
},
Scope: this._targetServerInstance.id
scope: this._targetServerInstance.id
}
};
this._migrationDbs.forEach(async (db, index) => {
requestBody.properties.SourceDatabaseName = db;
requestBody.properties.sourceDatabaseName = db;
try {
requestBody.properties.BackupConfiguration.SourceLocation.FileShare.Path = this._databaseBackup.networkShareLocations[index];
requestBody.properties.backupConfiguration.sourceLocation.fileShare!.path = this._databaseBackup.networkShareLocations[index];
const response = await startDatabaseMigration(
this._azureAccount,
this._targetSubscription,
this._migrationController?.properties.location!,
this._sqlMigrationService?.properties.location!,
this._targetServerInstance,
this._targetDatabaseNames[index],
requestBody
@@ -519,9 +519,9 @@ export class MigrationStateModel implements Model, vscode.Disposable {
this._targetServerInstance,
this._azureAccount,
this._targetSubscription,
this._migrationController
this._sqlMigrationService
);
vscode.window.showInformationMessage(localize("sql.migration.starting.migration.message", 'Starting migration for database {0} to {1}', db, this._targetServerInstance.name));
vscode.window.showInformationMessage(localize("sql.migration.starting.migration.message", 'Starting migration for database {0} to {1} - {2}', db, this._targetServerInstance.name, this._targetDatabaseNames[index]));
}
} catch (e) {
console.log(e);