From 8f232ae3e80b8585bd416f9789472d60af301549 Mon Sep 17 00:00:00 2001 From: Ram Uday Kumar <95093687+Ramudaykumar@users.noreply.github.com> Date: Wed, 4 Oct 2023 16:57:44 +0530 Subject: [PATCH] Premium SSD v2 disks in SQL VM recommendations (#24556) * Premium SSD v2 disks in SQL VM recommendations * Resolving review comments. --- extensions/sql-migration/config.json | 2 +- extensions/sql-migration/package.json | 2 +- .../sql-migration/src/constants/strings.ts | 18 +++++- .../skuRecommendationResultsDialog.ts | 56 +++++++++++++++++-- .../sql-migration/src/service/contracts.ts | 14 +++++ .../sql-migration/src/service/features.ts | 21 +++---- .../src/wizard/skuRecommendationPage.ts | 15 +---- 7 files changed, 95 insertions(+), 33 deletions(-) diff --git a/extensions/sql-migration/config.json b/extensions/sql-migration/config.json index 42f90b9593..06b0c4df7c 100644 --- a/extensions/sql-migration/config.json +++ b/extensions/sql-migration/config.json @@ -1,7 +1,7 @@ { "downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/{#version#}/microsoft.sqltools.migration-{#fileName#}", "useDefaultLinuxRuntime": true, - "version": "4.10.0.3", + "version": "4.10.0.9", "downloadFileNames": { "Windows_86": "win-x86-net7.0.zip", "Windows": "win-x64-net7.0.zip", diff --git a/extensions/sql-migration/package.json b/extensions/sql-migration/package.json index 555dbdad8a..47ea012923 100644 --- a/extensions/sql-migration/package.json +++ b/extensions/sql-migration/package.json @@ -2,7 +2,7 @@ "name": "sql-migration", "displayName": "%displayName%", "description": "%description%", - "version": "1.4.10", + "version": "1.4.11", "publisher": "Microsoft", "preview": false, "license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt", diff --git a/extensions/sql-migration/src/constants/strings.ts b/extensions/sql-migration/src/constants/strings.ts index 76cf918be8..f0967bc776 100644 --- a/extensions/sql-migration/src/constants/strings.ts +++ b/extensions/sql-migration/src/constants/strings.ts @@ -8,6 +8,7 @@ import { EOL } from 'os'; import { MigrationSourceAuthenticationType } from '../models/stateMachine'; import { BackupTypeCodes, formatNumber, InternalManagedDatabaseRestoreDetailsBackupSetStatusCodes, InternalManagedDatabaseRestoreDetailsStatusCodes, ParallelCopyTypeCodes, PipelineStatusCodes } from './helper'; import { ValidationError } from '../api/azure'; +import { AzureManagedDiskType } from '../service/contracts'; const localize = nls.loadMessageBundle(); export const serviceName = 'Sql Migration Service'; @@ -250,8 +251,11 @@ export const SOURCE_PROPERTIES = localize('sql.migration.sku.sourceProperties', export const SQL_TEMPDB = localize('sql.migration.sku.sql.temp', "SQL tempdb"); export const SQL_DATA_FILES = localize('sql.migration.sku.sql.dataDisk', "SQL data files"); export const SQL_LOG_FILES = localize('sql.migration.sku.sql.logDisk', "SQL log files"); -export function STORAGE_CONFIGURATION(size: string, count: number): string { - return localize('sql.migration.sku.azureConfiguration.storage', "{0} x {1}", size, count); +export function STORAGE_CONFIGURATION(count: number, diskConfiguration: string): string { + return localize('sql.migration.sku.azureConfiguration.storage', "{0} x {1} ", count, diskConfiguration); +} +export function DISK_CONFIGURATION(type: string, maxSizeInGib: number, maxIOPS: number, maxThroughputInMbps: number): string { + return localize('sql.migration.sku.azureConfiguration.disk', "{0} {1}GB ({2} IOPS, {3} MB/s)", type, maxSizeInGib, maxIOPS, maxThroughputInMbps); } export const RECOMMENDED_TARGET_STORAGE_CONFIGURATION = localize('sql.migration.sku.targetStorageConfiguration', "Recommendation target storage configuration"); export const RECOMMENDED_TARGET_STORAGE_CONFIGURATION_INFO = localize('sql.migration.sku.targetStorageConfiguration.info', "Below is the target storage configuration required to meet your storage performance needs."); @@ -262,6 +266,8 @@ export function STORAGE_GB(storage: number): string { export const RECOMMENDED_STORAGE_CONFIGURATION = localize('sql.migration.sku.targetStorageConfiguration.recommendedStorageConfiguration', "Recommended storage configuration"); export const EPHEMERAL_TEMPDB = localize('sql.migration.sku.targetStorageConfiguration.ephemeralTempdb', "Place tempdb on the local ephemeral SSD (default D:\\) drive"); export const LOCAL_SSD = localize('sql.migration.sku.targetStorageConfiguration.local.SSD', "Local SSD"); +export const UNKNOWN_DISK_TYPE = localize('sql.migration.sku.targetStorageConfiguration.disktype.unknown', 'Unknown disk type'); + export const CACHING = localize('sql.migration.sku.targetStorageConfiguration.caching', "Host caching"); export const CACHING_NA = localize('sql.migration.sku.targetStorageConfiguration.caching.na', "Not applicable"); export const CACHING_NONE = localize('sql.migration.sku.targetStorageConfiguration.caching.none', "None"); @@ -1228,6 +1234,14 @@ export const ParallelCopyType: LookupTable = { [ParallelCopyTypeCodes.DynamicRange]: localize('sql.migration.parallel.copy.type.dynamic', 'Dynamic range'), }; +export const DiskTypeLookup: LookupTable = { + [AzureManagedDiskType.StandardHDD]: localize('sql.migration.sku.targetStorageConfiguration.disktype.standardHdd', 'Standard HDD'), + [AzureManagedDiskType.StandardSSD]: localize('sql.migration.sku.targetStorageConfiguration.disktype.StandardSsd', 'Standard SSD'), + [AzureManagedDiskType.PremiumSSD]: localize('sql.migration.sku.targetStorageConfiguration.disktype.PremiumSsd', 'Premium SSD'), + [AzureManagedDiskType.UltraSSD]: localize('sql.migration.sku.targetStorageConfiguration.disktype.UltraSsd', 'Ultra SSD'), + [AzureManagedDiskType.PremiumSSDV2]: localize('sql.migration.sku.targetStorageConfiguration.disktype.PremiumSsdV2', 'Premium SSD v2'), +}; + export const BackupTypeLookup: LookupTable = { [BackupTypeCodes.Unknown]: localize('sql.migration.restore.backuptype.unknown', 'Unknown'), [BackupTypeCodes.Database]: localize('sql.migration.restore.backuptype.database', 'Database'), diff --git a/extensions/sql-migration/src/dialog/skuRecommendationResults/skuRecommendationResultsDialog.ts b/extensions/sql-migration/src/dialog/skuRecommendationResults/skuRecommendationResultsDialog.ts index 6448ae55f3..8b24713807 100644 --- a/extensions/sql-migration/src/dialog/skuRecommendationResults/skuRecommendationResultsDialog.ts +++ b/extensions/sql-migration/src/dialog/skuRecommendationResults/skuRecommendationResultsDialog.ts @@ -302,12 +302,12 @@ export class SkuRecommendationResultsDialog { const tempTableRow: azdata.DeclarativeTableCellValue[] = [ { value: constants.SQL_TEMPDB }, { - value: recommendation.targetSku.tempDbDiskSizes!.length > 0 - ? constants.STORAGE_CONFIGURATION(recommendation.targetSku.logDiskSizes![0].size, recommendation.targetSku.logDiskSizes!.length) + value: recommendation.targetSku.tempDbDiskSizes!?.length > 0 + ? this.getStorageConfigurationText(recommendation.targetSku.logDiskSizes) : constants.EPHEMERAL_TEMPDB }, { - value: recommendation.targetSku.tempDbDiskSizes!.length > 0 + value: recommendation.targetSku.tempDbDiskSizes!?.length > 0 ? this.getCachingText(recommendation.targetSku.logDiskSizes![0].caching) : constants.CACHING_NA } @@ -315,13 +315,17 @@ export class SkuRecommendationResultsDialog { const dataDiskTableRow: azdata.DeclarativeTableCellValue[] = [ { value: constants.SQL_DATA_FILES }, - { value: constants.STORAGE_CONFIGURATION(recommendation.targetSku.dataDiskSizes![0].size, recommendation.targetSku.dataDiskSizes!.length) }, + { + value: this.getStorageConfigurationText(recommendation.targetSku.dataDiskSizes) + }, { value: this.getCachingText(recommendation.targetSku.dataDiskSizes![0].caching) } ]; const logDiskTableRow: azdata.DeclarativeTableCellValue[] = [ { value: constants.SQL_LOG_FILES }, - { value: constants.STORAGE_CONFIGURATION(recommendation.targetSku.logDiskSizes![0].size, recommendation.targetSku.logDiskSizes!.length) }, + { + value: this.getStorageConfigurationText(recommendation.targetSku.logDiskSizes) + }, { value: this.getCachingText(recommendation.targetSku.logDiskSizes![0].caching) } ]; @@ -365,6 +369,48 @@ export class SkuRecommendationResultsDialog { } } + // This method looks into Disk SKU list and returns storage configuration text. + private getStorageConfigurationText(disks: contracts.AzureManagedDiskSku[]): string { + + const diskTypeCountMap: { [diskConfigurationText: string]: number } = {}; + if (disks!?.length > 0) { + disks.forEach(disk => { + const diskConfigurationText = this.GetDiskConfigurationText(disk); + if (diskConfigurationText in diskTypeCountMap) { + // Check if the key exists in the map + diskTypeCountMap[diskConfigurationText]++; + } else { + // If the key doesn't exist, initialize it with a count of 1 + diskTypeCountMap[diskConfigurationText] = 1; + } + }); + } + + let storageConfigurationText: string = ''; + for (const diskConfigurationText in diskTypeCountMap) { + if (diskTypeCountMap.hasOwnProperty(diskConfigurationText)) { + const count: number = diskTypeCountMap[diskConfigurationText]; + storageConfigurationText = storageConfigurationText.concat(constants.STORAGE_CONFIGURATION(count, diskConfigurationText)); + } + + } + + return storageConfigurationText; + } + + // This method returns single disk configuration text. + private GetDiskConfigurationText(disk: contracts.AzureManagedDiskSku): string { + return disk!?.type === contracts.AzureManagedDiskType.PremiumSSDV2 ? + constants.DISK_CONFIGURATION(this.getDiskTypeText(disk.type), disk.maxSizeInGib, disk.maxIOPS, disk.maxThroughputInMbps) : + disk.size; + } + + // This method returns disk type text from enum value. + private getDiskTypeText(type: contracts.AzureManagedDiskType): string { + const diskTypeText = constants.DiskTypeLookup[type]; + return diskTypeText !== undefined ? diskTypeText : constants.UNKNOWN_DISK_TYPE; + } + private createStoragePropertiesTable(_view: azdata.ModelView, databaseName?: string): azdata.FlexContainer { let instanceRequirements; switch (this._targetType) { diff --git a/extensions/sql-migration/src/service/contracts.ts b/extensions/sql-migration/src/service/contracts.ts index 2f3397a6c0..42819d4c3b 100644 --- a/extensions/sql-migration/src/service/contracts.ts +++ b/extensions/sql-migration/src/service/contracts.ts @@ -115,6 +115,7 @@ export interface SqlMigrationSkuRecommendationsParams { endTime: string; includePreviewSkus: boolean; databaseAllowList: string[]; + isPremiumSSDV2Enabled: boolean; } export interface AzureSqlSkuCategory { @@ -136,6 +137,10 @@ export interface AzureManagedDiskSku { tier: AzureManagedDiskTier; size: string; caching: AzureManagedDiskCaching; + type: AzureManagedDiskType; + maxSizeInGib: number; + maxThroughputInMbps: number; + maxIOPS: number; } export interface AzureVirtualMachineSku { @@ -278,6 +283,15 @@ export const enum AzureManagedDiskTier { Ultra = 2 } +// values from SQL NuGet +export const enum AzureManagedDiskType { + StandardHDD = 1, // Standard HDD + StandardSSD = 2, // Standard SSD + PremiumSSD = 4, // Premium SSD + UltraSSD = 8, // Ultra SSD + PremiumSSDV2 = 16, // Premium SSD V2 +} + export const enum AzureManagedDiskCaching { NotApplicable = 0, None = 1, diff --git a/extensions/sql-migration/src/service/features.ts b/extensions/sql-migration/src/service/features.ts index f061c6ca62..ece5cb002a 100644 --- a/extensions/sql-migration/src/service/features.ts +++ b/extensions/sql-migration/src/service/features.ts @@ -95,16 +95,17 @@ export class SqlMigrationService extends MigrationExtensionService implements co includePreviewSkus: boolean, databaseAllowList: string[]): Promise { let params: contracts.SqlMigrationSkuRecommendationsParams = { - dataFolder, - perfQueryIntervalInSec, - targetPlatforms, - targetSqlInstance, - targetPercentile, - scalingFactor, - startTime, - endTime, - includePreviewSkus, - databaseAllowList + dataFolder: dataFolder, + perfQueryIntervalInSec: perfQueryIntervalInSec, + targetPlatforms: targetPlatforms, + targetSqlInstance: targetSqlInstance, + targetPercentile: targetPercentile, + scalingFactor: scalingFactor, + startTime: startTime, + endTime: endTime, + includePreviewSkus: includePreviewSkus, + databaseAllowList: databaseAllowList, + isPremiumSSDV2Enabled: true, }; try { diff --git a/extensions/sql-migration/src/wizard/skuRecommendationPage.ts b/extensions/sql-migration/src/wizard/skuRecommendationPage.ts index a36eff0886..db957beb82 100644 --- a/extensions/sql-migration/src/wizard/skuRecommendationPage.ts +++ b/extensions/sql-migration/src/wizard/skuRecommendationPage.ts @@ -753,20 +753,7 @@ export class SKURecommendationPage extends MigrationWizardPage { constants.VM_CONFIGURATION( recommendation.targetSku.virtualMachineSize!.sizeName, recommendation.targetSku.virtualMachineSize!.vCPUsAvailable); - - const dataDisk = constants.STORAGE_CONFIGURATION( - recommendation.targetSku.dataDiskSizes![0].size, - recommendation.targetSku.dataDiskSizes!.length); - const storageDisk = constants.STORAGE_CONFIGURATION( - recommendation.targetSku.logDiskSizes![0].size, - recommendation.targetSku.logDiskSizes!.length); - const tempDb = recommendation.targetSku.tempDbDiskSizes!.length > 0 - ? constants.STORAGE_CONFIGURATION( - recommendation.targetSku.logDiskSizes![0].size, - recommendation.targetSku.logDiskSizes!.length) - : constants.LOCAL_SSD; - this._rbg.cards[index].descriptions[CardDescriptionIndex.VM_CONFIGURATIONS].textValue = - constants.VM_CONFIGURATION_PREVIEW(dataDisk, storageDisk, tempDb); + // Removed disk details from summary as per experience requirements. } } break;