mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-13 17:23:02 -05:00
Retrieve Azure SLO details in Database Handler (#2094)
This commit is contained in:
@@ -21,19 +21,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
|
|||||||
[DebuggerDisplay("{Name,nq}")]
|
[DebuggerDisplay("{Name,nq}")]
|
||||||
public class AzureEdition
|
public class AzureEdition
|
||||||
{
|
{
|
||||||
public static readonly AzureEdition Basic = new AzureEdition("Basic", "SR.BasicAzureEdition");
|
public static readonly AzureEdition Basic = new AzureEdition("Basic", SR.BasicAzureEdition);
|
||||||
public static readonly AzureEdition Standard = new AzureEdition("Standard", "SR.StandardAzureEdition");
|
public static readonly AzureEdition Standard = new AzureEdition("Standard", SR.StandardAzureEdition);
|
||||||
public static readonly AzureEdition Premium = new AzureEdition("Premium", "SR.PremiumAzureEdition");
|
public static readonly AzureEdition Premium = new AzureEdition("Premium", SR.PremiumAzureEdition);
|
||||||
public static readonly AzureEdition DataWarehouse = new AzureEdition("DataWarehouse", "SR.DataWarehouseAzureEdition");
|
public static readonly AzureEdition DataWarehouse = new AzureEdition("DataWarehouse", SR.DataWarehouseAzureEdition);
|
||||||
public static readonly AzureEdition GeneralPurpose = new AzureEdition("GeneralPurpose", "SR.GeneralPurposeAzureEdition");
|
public static readonly AzureEdition GeneralPurpose = new AzureEdition("GeneralPurpose", SR.GeneralPurposeAzureEdition);
|
||||||
public static readonly AzureEdition BusinessCritical = new AzureEdition("BusinessCritical", "SR.BusinessCriticalAzureEdition");
|
public static readonly AzureEdition BusinessCritical = new AzureEdition("BusinessCritical", SR.BusinessCriticalAzureEdition);
|
||||||
|
public static readonly AzureEdition Hyperscale = new AzureEdition("Hyperscale", SR.HyperscaleAzureEdition);
|
||||||
public static readonly AzureEdition Hyperscale = new AzureEdition("Hyperscale", "SR.HyperscaleAzureEdition");
|
|
||||||
// Free does not offer DatabaseSize >=1GB, hence it's not "supported".
|
|
||||||
//public static readonly AzureEdition Free = new AzureEdition("Free", SR.FreeAzureEdition);
|
|
||||||
// Stretch and system do not seem to be applicable, so I'm commenting them out
|
|
||||||
//public static readonly AzureEdition Stretch = new AzureEdition("Stretch", SR.StretchAzureEdition);
|
|
||||||
//public static readonly AzureEdition System = new AzureEdition("System", SR.SystemAzureEdition);
|
|
||||||
|
|
||||||
internal string Name { get; private set; }
|
internal string Name { get; private set; }
|
||||||
internal string DisplayName { get; private set; }
|
internal string DisplayName { get; private set; }
|
||||||
@@ -320,6 +314,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
|
|||||||
{ "LRS", "Local" },
|
{ "LRS", "Local" },
|
||||||
{ "ZRS", "Zone" }
|
{ "ZRS", "Zone" }
|
||||||
};
|
};
|
||||||
|
private static readonly string[] backupRedundancyLevels = bsrAPIToUIValueMapping.Values.ToArray();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// All valid backup storage redundancy levels for an Azure SQL database
|
||||||
|
/// </summary>
|
||||||
|
public static string[] BackupStorageRedundancyLevels
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return backupRedundancyLevels;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//KeyValuePair contains the BackupStorageRedundancy values for all azure editions.
|
//KeyValuePair contains the BackupStorageRedundancy values for all azure editions.
|
||||||
private static readonly KeyValuePair<int, string[]> keyValuePair = new KeyValuePair<int, string[]>(0, bsrAPIToUIValueMapping.Values.ToArray());
|
private static readonly KeyValuePair<int, string[]> keyValuePair = new KeyValuePair<int, string[]>(0, bsrAPIToUIValueMapping.Values.ToArray());
|
||||||
@@ -516,7 +522,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
|
|||||||
/// We do this so that the AzureEdition enum can have values such as NONE or DEFAULT added
|
/// We do this so that the AzureEdition enum can have values such as NONE or DEFAULT added
|
||||||
/// without requiring clients to explicitly filter out those values themselves each time.
|
/// without requiring clients to explicitly filter out those values themselves each time.
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IEnumerable<AzureEdition> GetValidAzureEditionOptions(object unused)
|
public static IEnumerable<AzureEdition> GetValidAzureEditionOptions()
|
||||||
{
|
{
|
||||||
yield return AzureEdition.Basic;
|
yield return AzureEdition.Basic;
|
||||||
yield return AzureEdition.Standard;
|
yield return AzureEdition.Standard;
|
||||||
@@ -524,10 +530,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
|
|||||||
yield return AzureEdition.DataWarehouse;
|
yield return AzureEdition.DataWarehouse;
|
||||||
yield return AzureEdition.BusinessCritical;
|
yield return AzureEdition.BusinessCritical;
|
||||||
yield return AzureEdition.GeneralPurpose;
|
yield return AzureEdition.GeneralPurpose;
|
||||||
//yield return AzureEdition.Free;
|
|
||||||
yield return AzureEdition.Hyperscale;
|
yield return AzureEdition.Hyperscale;
|
||||||
//yield return AzureEdition.Stretch;
|
|
||||||
//yield return AzureEdition.System;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ using Microsoft.SqlTools.ServiceLayer.Management;
|
|||||||
using AzureEdition = Microsoft.SqlTools.ServiceLayer.Admin.AzureSqlDbHelper.AzureEdition;
|
using AzureEdition = Microsoft.SqlTools.ServiceLayer.Admin.AzureSqlDbHelper.AzureEdition;
|
||||||
using System;
|
using System;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
|
using Microsoft.SqlTools.Utility;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Microsoft.SqlTools.ServiceLayer.Admin
|
namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||||
{
|
{
|
||||||
@@ -91,58 +93,56 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
|
|||||||
{
|
{
|
||||||
return AzureSqlDbHelper.GetAzureEditionDisplayName(this.currentState.azureEdition);
|
return AzureSqlDbHelper.GetAzureEditionDisplayName(this.currentState.azureEdition);
|
||||||
}
|
}
|
||||||
// set
|
set
|
||||||
// {
|
{
|
||||||
// AzureEdition edition;
|
AzureEdition edition;
|
||||||
// if (AzureSqlDbHelper.TryGetAzureEditionFromDisplayName(value, out edition))
|
if (AzureSqlDbHelper.TryGetAzureEditionFromDisplayName(value, out edition))
|
||||||
// {
|
{
|
||||||
// //Try to get the ServiceLevelObjective from the api,if not the default hardcoded service level objectives will be retrieved.
|
//Try to get the ServiceLevelObjective from the api,if not the default hardcoded service level objectives will be retrieved.
|
||||||
// string serverLevelObjective = AzureServiceLevelObjectiveProvider.TryGetAzureServiceLevelObjective(value, AzureServiceLocation);
|
// string serverLevelObjective = AzureServiceLevelObjectiveProvider.TryGetAzureServiceLevelObjective(value, AzureServiceLocation);
|
||||||
|
|
||||||
// if (!string.IsNullOrEmpty(serverLevelObjective))
|
// if (!string.IsNullOrEmpty(serverLevelObjective))
|
||||||
// {
|
// {
|
||||||
// this.currentState.azureEdition = edition;
|
// this.currentState.azureEdition = edition;
|
||||||
// this.currentState.currentServiceLevelObjective = serverLevelObjective;
|
// this.currentState.currentServiceLevelObjective = serverLevelObjective;
|
||||||
// // Instead of creating db instance with default Edition, update EditionToCreate while selecting Edition from the UI.
|
// // Instead of creating db instance with default Edition, update EditionToCreate while selecting Edition from the UI.
|
||||||
// this.EditionToCreate = MapAzureEditionToDbEngineEdition(edition);
|
// this.EditionToCreate = MapAzureEditionToDbEngineEdition(edition);
|
||||||
// string storageAccountType = AzureServiceLevelObjectiveProvider.TryGetAzureStorageType(value, AzureServiceLocation);
|
// string storageAccountType = AzureServiceLevelObjectiveProvider.TryGetAzureStorageType(value, AzureServiceLocation);
|
||||||
// if (!string.IsNullOrEmpty(storageAccountType))
|
// if (!string.IsNullOrEmpty(storageAccountType))
|
||||||
// {
|
// {
|
||||||
// this.currentState.backupStorageRedundancy = storageAccountType;
|
// this.currentState.backupStorageRedundancy = storageAccountType;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// // Try to get the azure maxsize from the api,if not the default hardcoded maxsize will be retrieved.
|
// // Try to get the azure maxsize from the api,if not the default hardcoded maxsize will be retrieved.
|
||||||
// DbSize dbSize = AzureServiceLevelObjectiveProvider.TryGetAzureMaxSize(value, serverLevelObjective, AzureServiceLocation);
|
// DbSize dbSize = AzureServiceLevelObjectiveProvider.TryGetAzureMaxSize(value, serverLevelObjective, AzureServiceLocation);
|
||||||
// if (!string.IsNullOrEmpty(dbSize.ToString()))
|
// if (!string.IsNullOrEmpty(dbSize.ToString()))
|
||||||
// {
|
// {
|
||||||
// this.currentState.maxSize = new DbSize(dbSize.Size, dbSize.SizeUnit);
|
// this.currentState.maxSize = new DbSize(dbSize.Size, dbSize.SizeUnit);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// else
|
// else
|
||||||
// {
|
// {
|
||||||
// if (edition == this.currentState.azureEdition)
|
if (edition == this.currentState.azureEdition)
|
||||||
// { //No changes, return early since we don't need to do any of the changes below
|
{ // No changes, return early since we don't need to do any of the changes below
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// this.currentState.azureEdition = edition;
|
this.currentState.azureEdition = edition;
|
||||||
// this.EditionToCreate = MapAzureEditionToDbEngineEdition(edition);
|
this.EditionToCreate = MapAzureEditionToDbEngineEdition(edition);
|
||||||
// this.CurrentServiceLevelObjective = AzureSqlDbHelper.GetDefaultServiceObjective(edition);
|
this.CurrentServiceLevelObjective = AzureSqlDbHelper.GetDefaultServiceObjective(edition);
|
||||||
// this.BackupStorageRedundancy = AzureSqlDbHelper.GetDefaultBackupStorageRedundancy(edition);
|
this.BackupStorageRedundancy = AzureSqlDbHelper.GetDefaultBackupStorageRedundancy(edition);
|
||||||
// var defaultSize = AzureSqlDbHelper.GetDatabaseDefaultSize(edition);
|
var defaultSize = AzureSqlDbHelper.GetDatabaseDefaultSize(edition);
|
||||||
|
|
||||||
// this.MaxSize = defaultSize == null ? String.Empty : defaultSize.ToString();
|
this.MaxSize = defaultSize == null ? String.Empty : defaultSize.ToString();
|
||||||
// }
|
// }
|
||||||
// this.NotifyObservers();
|
this.NotifyObservers();
|
||||||
// }
|
}
|
||||||
// else
|
else
|
||||||
// {
|
{
|
||||||
// //Can't really do much if we fail to parse the display name so just leave it as is and log a message
|
// Can't really do much if we fail to parse the display name so just leave it as is and log a message
|
||||||
// System.Diagnostics.Debug.Assert(false,
|
Logger.Write(TraceEventType.Error, $"Failed to parse edition display name '{value}' back into AzureEdition");
|
||||||
// string.Format(CultureInfo.InvariantCulture,
|
}
|
||||||
// "Failed to parse edition display name '{0}' back into AzureEdition", value));
|
}
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -12437,6 +12437,70 @@ namespace Microsoft.SqlTools.ServiceLayer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string BasicAzureEdition
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Keys.GetString(Keys.BasicAzureEdition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string StandardAzureEdition
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Keys.GetString(Keys.StandardAzureEdition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string PremiumAzureEdition
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Keys.GetString(Keys.PremiumAzureEdition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string DataWarehouseAzureEdition
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Keys.GetString(Keys.DataWarehouseAzureEdition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GeneralPurposeAzureEdition
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Keys.GetString(Keys.GeneralPurposeAzureEdition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string BusinessCriticalAzureEdition
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Keys.GetString(Keys.BusinessCriticalAzureEdition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ErrorInvalidEdition
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Keys.GetString(Keys.ErrorInvalidEdition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string HyperscaleAzureEdition
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Keys.GetString(Keys.HyperscaleAzureEdition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static string ConnectionServiceListDbErrorNotConnected(string uri)
|
public static string ConnectionServiceListDbErrorNotConnected(string uri)
|
||||||
{
|
{
|
||||||
return Keys.GetString(Keys.ConnectionServiceListDbErrorNotConnected, uri);
|
return Keys.GetString(Keys.ConnectionServiceListDbErrorNotConnected, uri);
|
||||||
@@ -17794,6 +17858,30 @@ namespace Microsoft.SqlTools.ServiceLayer
|
|||||||
public const string prototype_file_noApplicableFileGroup = "prototype_file_noApplicableFileGroup";
|
public const string prototype_file_noApplicableFileGroup = "prototype_file_noApplicableFileGroup";
|
||||||
|
|
||||||
|
|
||||||
|
public const string BasicAzureEdition = "BasicAzureEdition";
|
||||||
|
|
||||||
|
|
||||||
|
public const string StandardAzureEdition = "StandardAzureEdition";
|
||||||
|
|
||||||
|
|
||||||
|
public const string PremiumAzureEdition = "PremiumAzureEdition";
|
||||||
|
|
||||||
|
|
||||||
|
public const string DataWarehouseAzureEdition = "DataWarehouseAzureEdition";
|
||||||
|
|
||||||
|
|
||||||
|
public const string GeneralPurposeAzureEdition = "GeneralPurposeAzureEdition";
|
||||||
|
|
||||||
|
|
||||||
|
public const string BusinessCriticalAzureEdition = "BusinessCriticalAzureEdition";
|
||||||
|
|
||||||
|
|
||||||
|
public const string ErrorInvalidEdition = "ErrorInvalidEdition";
|
||||||
|
|
||||||
|
|
||||||
|
public const string HyperscaleAzureEdition = "HyperscaleAzureEdition";
|
||||||
|
|
||||||
|
|
||||||
private Keys()
|
private Keys()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|||||||
@@ -6760,4 +6760,36 @@ The Query Processor estimates that implementing the following index could improv
|
|||||||
<value>No Applicable Filegroup</value>
|
<value>No Applicable Filegroup</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="BasicAzureEdition" xml:space="preserve">
|
||||||
|
<value>Basic</value>
|
||||||
|
<comment></comment>
|
||||||
|
</data>
|
||||||
|
<data name="StandardAzureEdition" xml:space="preserve">
|
||||||
|
<value>Standard</value>
|
||||||
|
<comment></comment>
|
||||||
|
</data>
|
||||||
|
<data name="PremiumAzureEdition" xml:space="preserve">
|
||||||
|
<value>Premium</value>
|
||||||
|
<comment></comment>
|
||||||
|
</data>
|
||||||
|
<data name="DataWarehouseAzureEdition" xml:space="preserve">
|
||||||
|
<value>DataWarehouse</value>
|
||||||
|
<comment></comment>
|
||||||
|
</data>
|
||||||
|
<data name="GeneralPurposeAzureEdition" xml:space="preserve">
|
||||||
|
<value>General Purpose</value>
|
||||||
|
<comment></comment>
|
||||||
|
</data>
|
||||||
|
<data name="BusinessCriticalAzureEdition" xml:space="preserve">
|
||||||
|
<value>Business Critical</value>
|
||||||
|
<comment></comment>
|
||||||
|
</data>
|
||||||
|
<data name="ErrorInvalidEdition" xml:space="preserve">
|
||||||
|
<value>Edition value is not valid</value>
|
||||||
|
<comment></comment>
|
||||||
|
</data>
|
||||||
|
<data name="HyperscaleAzureEdition" xml:space="preserve">
|
||||||
|
<value>Hyperscale</value>
|
||||||
|
<comment></comment>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -2801,4 +2801,16 @@ compatibilityLevel_sqlv160 = SQL Server 2022 (160)
|
|||||||
general_containmentType_None = None
|
general_containmentType_None = None
|
||||||
general_containmentType_Partial = Partial
|
general_containmentType_Partial = Partial
|
||||||
filegroups_filestreamFiles = FILESTREAM Files
|
filegroups_filestreamFiles = FILESTREAM Files
|
||||||
prototype_file_noApplicableFileGroup = No Applicable Filegroup
|
prototype_file_noApplicableFileGroup = No Applicable Filegroup
|
||||||
|
|
||||||
|
############################################################################
|
||||||
|
# Azure SQL DB
|
||||||
|
|
||||||
|
BasicAzureEdition = Basic
|
||||||
|
StandardAzureEdition = Standard
|
||||||
|
PremiumAzureEdition = Premium
|
||||||
|
DataWarehouseAzureEdition = DataWarehouse
|
||||||
|
GeneralPurposeAzureEdition = General Purpose
|
||||||
|
BusinessCriticalAzureEdition = Business Critical
|
||||||
|
ErrorInvalidEdition = Edition value is not valid
|
||||||
|
HyperscaleAzureEdition = Hyperscale
|
||||||
@@ -8281,6 +8281,46 @@ The Query Processor estimates that implementing the following index could improv
|
|||||||
<target state="new">No Applicable Filegroup</target>
|
<target state="new">No Applicable Filegroup</target>
|
||||||
<note></note>
|
<note></note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="BasicAzureEdition">
|
||||||
|
<source>Basic</source>
|
||||||
|
<target state="new">Basic</target>
|
||||||
|
<note></note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="StandardAzureEdition">
|
||||||
|
<source>Standard</source>
|
||||||
|
<target state="new">Standard</target>
|
||||||
|
<note></note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="PremiumAzureEdition">
|
||||||
|
<source>Premium</source>
|
||||||
|
<target state="new">Premium</target>
|
||||||
|
<note></note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="DataWarehouseAzureEdition">
|
||||||
|
<source>DataWarehouse</source>
|
||||||
|
<target state="new">DataWarehouse</target>
|
||||||
|
<note></note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="GeneralPurposeAzureEdition">
|
||||||
|
<source>General Purpose</source>
|
||||||
|
<target state="new">General Purpose</target>
|
||||||
|
<note></note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="BusinessCriticalAzureEdition">
|
||||||
|
<source>Business Critical</source>
|
||||||
|
<target state="new">Business Critical</target>
|
||||||
|
<note></note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="ErrorInvalidEdition">
|
||||||
|
<source>Edition value is not valid</source>
|
||||||
|
<target state="new">Edition value is not valid</target>
|
||||||
|
<note></note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="HyperscaleAzureEdition">
|
||||||
|
<source>Hyperscale</source>
|
||||||
|
<target state="new">Hyperscale</target>
|
||||||
|
<note></note>
|
||||||
|
</trans-unit>
|
||||||
</body>
|
</body>
|
||||||
</file>
|
</file>
|
||||||
</xliff>
|
</xliff>
|
||||||
@@ -17,6 +17,7 @@ using Microsoft.SqlTools.ServiceLayer.Connection;
|
|||||||
using Microsoft.SqlTools.ServiceLayer.Management;
|
using Microsoft.SqlTools.ServiceLayer.Management;
|
||||||
using Microsoft.SqlTools.ServiceLayer.ObjectManagement.Contracts;
|
using Microsoft.SqlTools.ServiceLayer.ObjectManagement.Contracts;
|
||||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||||
|
using Microsoft.SqlTools.Utility;
|
||||||
|
|
||||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||||
{
|
{
|
||||||
@@ -37,6 +38,11 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
|||||||
private static readonly Dictionary<string, ContainmentType> containmentTypeEnums = new Dictionary<string, ContainmentType>();
|
private static readonly Dictionary<string, ContainmentType> containmentTypeEnums = new Dictionary<string, ContainmentType>();
|
||||||
private static readonly Dictionary<string, RecoveryModel> recoveryModelEnums = new Dictionary<string, RecoveryModel>();
|
private static readonly Dictionary<string, RecoveryModel> recoveryModelEnums = new Dictionary<string, RecoveryModel>();
|
||||||
|
|
||||||
|
internal static readonly string[] AzureEditionNames;
|
||||||
|
internal static readonly string[] AzureBackupLevels;
|
||||||
|
internal static readonly AzureEditionDetails[] AzureMaxSizes;
|
||||||
|
internal static readonly AzureEditionDetails[] AzureServiceLevels;
|
||||||
|
|
||||||
static DatabaseHandler()
|
static DatabaseHandler()
|
||||||
{
|
{
|
||||||
displayCompatLevels.Add(CompatibilityLevel.Version70, SR.compatibilityLevel_sphinx);
|
displayCompatLevels.Add(CompatibilityLevel.Version70, SR.compatibilityLevel_sphinx);
|
||||||
@@ -71,6 +77,13 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
|||||||
{
|
{
|
||||||
recoveryModelEnums.Add(displayRecoveryModels[key], key);
|
recoveryModelEnums.Add(displayRecoveryModels[key], key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Azure SLO info is invariant of server information, so set up static objects we can return later
|
||||||
|
var editions = AzureSqlDbHelper.GetValidAzureEditionOptions();
|
||||||
|
AzureEditionNames = editions.Select(edition => edition.DisplayName).ToArray();
|
||||||
|
AzureBackupLevels = AzureSqlDbHelper.BackupStorageRedundancyLevels;
|
||||||
|
AzureMaxSizes = GetAzureMaxSizes(editions);
|
||||||
|
AzureServiceLevels = GetAzureServiceLevels(editions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DatabaseHandler(ConnectionService connectionService) : base(connectionService)
|
public DatabaseHandler(ConnectionService connectionService) : base(connectionService)
|
||||||
@@ -99,18 +112,17 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
|||||||
var prototype = taskHelper.Prototype;
|
var prototype = taskHelper.Prototype;
|
||||||
var azurePrototype = prototype as DatabasePrototypeAzure;
|
var azurePrototype = prototype as DatabasePrototypeAzure;
|
||||||
bool isDw = azurePrototype != null && azurePrototype.AzureEdition == AzureEdition.DataWarehouse;
|
bool isDw = azurePrototype != null && azurePrototype.AzureEdition == AzureEdition.DataWarehouse;
|
||||||
|
bool isAzureDB = dataContainer.Server.ServerType == DatabaseEngineType.SqlAzureDatabase;
|
||||||
|
|
||||||
var databaseViewInfo = new DatabaseViewInfo()
|
var databaseViewInfo = new DatabaseViewInfo()
|
||||||
{
|
{
|
||||||
ObjectInfo = new DatabaseInfo()
|
ObjectInfo = new DatabaseInfo(),
|
||||||
|
IsAzureDB = isAzureDB
|
||||||
};
|
};
|
||||||
|
|
||||||
// azure sql db doesn't have a sysadmin fixed role
|
// azure sql db doesn't have a sysadmin fixed role
|
||||||
var compatibilityLevelEnabled = !isDw &&
|
var compatibilityLevelEnabled = !isDw && (dataContainer.LoggedInUserIsSysadmin || isAzureDB);
|
||||||
(dataContainer.LoggedInUserIsSysadmin ||
|
if (isAzureDB)
|
||||||
dataContainer.Server.ServerType ==
|
|
||||||
DatabaseEngineType.SqlAzureDatabase);
|
|
||||||
if (dataContainer.Server.ServerType == DatabaseEngineType.SqlAzureDatabase)
|
|
||||||
{
|
{
|
||||||
// Azure doesn't allow modifying the collation after DB creation
|
// Azure doesn't allow modifying the collation after DB creation
|
||||||
bool collationEnabled = !prototype.Exists;
|
bool collationEnabled = !prototype.Exists;
|
||||||
@@ -133,6 +145,10 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
|||||||
databaseViewInfo.CompatibilityLevels = GetCompatibilityLevels(dataContainer.SqlServerVersion, prototype);
|
databaseViewInfo.CompatibilityLevels = GetCompatibilityLevels(dataContainer.SqlServerVersion, prototype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
databaseViewInfo.AzureBackupRedundancyLevels = AzureBackupLevels;
|
||||||
|
databaseViewInfo.AzureServiceLevelObjectives = AzureServiceLevels;
|
||||||
|
databaseViewInfo.AzureEditions = AzureEditionNames;
|
||||||
|
databaseViewInfo.AzureMaxSizes = AzureMaxSizes;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -148,7 +164,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Skip adding logins if running against an Azure SQL DB
|
// Skip adding logins if running against an Azure SQL DB
|
||||||
if (dataContainer.Server.ServerType != DatabaseEngineType.SqlAzureDatabase)
|
if (!isAzureDB)
|
||||||
{
|
{
|
||||||
var logins = new List<string>();
|
var logins = new List<string>();
|
||||||
foreach (Login login in dataContainer.Server.Logins)
|
foreach (Login login in dataContainer.Server.Logins)
|
||||||
@@ -283,6 +299,27 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
|||||||
db110.DatabaseContainmentType = containmentTypeEnums[database.ContainmentType];
|
db110.DatabaseContainmentType = containmentTypeEnums[database.ContainmentType];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prototype is DatabasePrototypeAzure dbAz)
|
||||||
|
{
|
||||||
|
// Set edition first since the prototype will fill all the Azure fields with default values
|
||||||
|
if (database.AzureEdition != null)
|
||||||
|
{
|
||||||
|
dbAz.AzureEditionDisplay = database.AzureEdition;
|
||||||
|
}
|
||||||
|
if (database.AzureBackupRedundancyLevel != null)
|
||||||
|
{
|
||||||
|
dbAz.BackupStorageRedundancy = database.AzureBackupRedundancyLevel;
|
||||||
|
}
|
||||||
|
if (database.AzureServiceLevelObjective != null)
|
||||||
|
{
|
||||||
|
dbAz.CurrentServiceLevelObjective = database.AzureServiceLevelObjective;
|
||||||
|
}
|
||||||
|
if (database.AzureMaxSize != null)
|
||||||
|
{
|
||||||
|
dbAz.MaxSize = database.AzureMaxSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
string sqlScript = string.Empty;
|
string sqlScript = string.Empty;
|
||||||
using (var actions = new DatabaseActions(dataContainer, configAction, prototype))
|
using (var actions = new DatabaseActions(dataContainer, configAction, prototype))
|
||||||
using (var executionHandler = new ExecutonHandler(actions))
|
using (var executionHandler = new ExecutonHandler(actions))
|
||||||
@@ -583,5 +620,65 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
|||||||
// previous loop did not find the prototype compatibility level in this server's compatability options, so treat compatibility levels as unsupported for this server
|
// previous loop did not find the prototype compatibility level in this server's compatability options, so treat compatibility levels as unsupported for this server
|
||||||
return Array.Empty<string>();
|
return Array.Empty<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get supported service level objectives for this Azure server.
|
||||||
|
/// </summary>
|
||||||
|
private static AzureEditionDetails[] GetAzureServiceLevels(IEnumerable<AzureEdition> editions)
|
||||||
|
{
|
||||||
|
var levels = new List<AzureEditionDetails>();
|
||||||
|
foreach (AzureEdition edition in editions)
|
||||||
|
{
|
||||||
|
if (AzureSqlDbHelper.TryGetServiceObjectiveInfo(edition, out var serviceInfoPair))
|
||||||
|
{
|
||||||
|
// Move default value to the front of the list
|
||||||
|
var serviceLevelsList = new List<string>(serviceInfoPair.Value);
|
||||||
|
var defaultIndex = serviceInfoPair.Key;
|
||||||
|
if (defaultIndex >= 0 && defaultIndex < serviceLevelsList.Count)
|
||||||
|
{
|
||||||
|
var defaultServiceObjective = serviceLevelsList[defaultIndex];
|
||||||
|
serviceLevelsList.RemoveAt(defaultIndex);
|
||||||
|
serviceLevelsList.Insert(0, defaultServiceObjective);
|
||||||
|
}
|
||||||
|
var details = new AzureEditionDetails() { EditionDisplayName = edition.DisplayName, Details = serviceLevelsList.ToArray() };
|
||||||
|
levels.Add(details);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.Error($"Failed to get service level objective info for edition '{edition.Name}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return levels.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get supported maximum sizes for this Azure server.
|
||||||
|
/// </summary>
|
||||||
|
private static AzureEditionDetails[] GetAzureMaxSizes(IEnumerable<AzureEdition> editions)
|
||||||
|
{
|
||||||
|
var sizes = new List<AzureEditionDetails>();
|
||||||
|
foreach (AzureEdition edition in editions)
|
||||||
|
{
|
||||||
|
if (AzureSqlDbHelper.TryGetDatabaseSizeInfo(edition, out var sizeInfoPair))
|
||||||
|
{
|
||||||
|
// Move default value to the front of the list
|
||||||
|
var sizeInfoList = new List<DbSize>(sizeInfoPair.Value);
|
||||||
|
var defaultIndex = sizeInfoPair.Key;
|
||||||
|
if (defaultIndex >= 0 && defaultIndex < sizeInfoList.Count)
|
||||||
|
{
|
||||||
|
var defaultSizeInfo = sizeInfoList[defaultIndex];
|
||||||
|
sizeInfoList.RemoveAt(defaultIndex);
|
||||||
|
sizeInfoList.Insert(0, defaultSizeInfo);
|
||||||
|
}
|
||||||
|
var details = new AzureEditionDetails() { EditionDisplayName = edition.DisplayName, Details = sizeInfoList.Select(info => info.ToString()).ToArray() };
|
||||||
|
sizes.Add(details);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.Error($"Failed to get database size info for edition '{edition.Name}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sizes.ToArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15,5 +15,10 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
|||||||
public string? RecoveryModel { get; set; }
|
public string? RecoveryModel { get; set; }
|
||||||
public string? CompatibilityLevel { get; set; }
|
public string? CompatibilityLevel { get; set; }
|
||||||
public string? ContainmentType { get; set; }
|
public string? ContainmentType { get; set; }
|
||||||
|
|
||||||
|
public string? AzureBackupRedundancyLevel { get; set; }
|
||||||
|
public string? AzureServiceLevelObjective { get; set; }
|
||||||
|
public string? AzureEdition { get; set; }
|
||||||
|
public string? AzureMaxSize { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14,5 +14,17 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
|||||||
public string[] CompatibilityLevels { get; set; }
|
public string[] CompatibilityLevels { get; set; }
|
||||||
public string[] ContainmentTypes { get; set; }
|
public string[] ContainmentTypes { get; set; }
|
||||||
public string[] RecoveryModels { get; set; }
|
public string[] RecoveryModels { get; set; }
|
||||||
|
|
||||||
|
public bool IsAzureDB { get; set; }
|
||||||
|
public string[] AzureBackupRedundancyLevels { get; set; }
|
||||||
|
public AzureEditionDetails[] AzureServiceLevelObjectives { get; set; }
|
||||||
|
public string[] AzureEditions { get; set; }
|
||||||
|
public AzureEditionDetails[] AzureMaxSizes { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AzureEditionDetails
|
||||||
|
{
|
||||||
|
public string EditionDisplayName { get; set; }
|
||||||
|
public string[] Details { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,15 +3,19 @@
|
|||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Data.SqlClient;
|
using Microsoft.Data.SqlClient;
|
||||||
using Microsoft.SqlServer.Management.Common;
|
using Microsoft.SqlServer.Management.Common;
|
||||||
using Microsoft.SqlServer.Management.Smo;
|
using Microsoft.SqlServer.Management.Smo;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Admin;
|
||||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||||
using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility;
|
using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility;
|
||||||
using Microsoft.SqlTools.ServiceLayer.ObjectManagement;
|
using Microsoft.SqlTools.ServiceLayer.ObjectManagement;
|
||||||
using Microsoft.SqlTools.ServiceLayer.Test.Common;
|
using Microsoft.SqlTools.ServiceLayer.Test.Common;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using static Microsoft.SqlTools.ServiceLayer.Admin.AzureSqlDbHelper;
|
||||||
|
|
||||||
namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement
|
namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement
|
||||||
{
|
{
|
||||||
@@ -162,6 +166,102 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GetAzureEditionsTest()
|
||||||
|
{
|
||||||
|
var actualEditionNames = DatabaseHandler.AzureEditionNames;
|
||||||
|
var expectedEditionNames = AzureSqlDbHelper.GetValidAzureEditionOptions().Select(edition => edition.DisplayName);
|
||||||
|
Assert.That(actualEditionNames, Is.EquivalentTo(expectedEditionNames));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GetAzureBackupRedundancyLevelsTest()
|
||||||
|
{
|
||||||
|
var actualLevels = DatabaseHandler.AzureBackupLevels;
|
||||||
|
var expectedLevels = new string[] { "Geo", "Local", "Zone" };
|
||||||
|
Assert.That(actualLevels, Is.EquivalentTo(expectedLevels));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GetAzureServiceLevelObjectivesTest()
|
||||||
|
{
|
||||||
|
var actualLevelsMap = new Dictionary<string, string[]>();
|
||||||
|
foreach (AzureEditionDetails serviceDetails in DatabaseHandler.AzureServiceLevels)
|
||||||
|
{
|
||||||
|
actualLevelsMap.Add(serviceDetails.EditionDisplayName, serviceDetails.Details);
|
||||||
|
}
|
||||||
|
|
||||||
|
var expectedDefaults = new Dictionary<AzureEdition, string>()
|
||||||
|
{
|
||||||
|
{ AzureEdition.Basic, "Basic" },
|
||||||
|
{ AzureEdition.Standard, "S0" },
|
||||||
|
{ AzureEdition.Premium, "P1" },
|
||||||
|
{ AzureEdition.DataWarehouse, "DW400" },
|
||||||
|
{ AzureEdition.BusinessCritical, "BC_Gen5_2" },
|
||||||
|
{ AzureEdition.GeneralPurpose, "GP_Gen5_2" },
|
||||||
|
{ AzureEdition.Hyperscale, "HS_Gen5_2" }
|
||||||
|
};
|
||||||
|
Assert.That(actualLevelsMap.Count, Is.EqualTo(expectedDefaults.Count), "Did not get expected number of editions for DatabaseHandler's service levels");
|
||||||
|
foreach(AzureEdition edition in expectedDefaults.Keys)
|
||||||
|
{
|
||||||
|
if (AzureSqlDbHelper.TryGetServiceObjectiveInfo(edition, out var expectedLevelInfo))
|
||||||
|
{
|
||||||
|
var expectedServiceLevels = expectedLevelInfo.Value;
|
||||||
|
var actualServiceLevels = actualLevelsMap[edition.DisplayName];
|
||||||
|
Assert.That(actualServiceLevels, Is.EquivalentTo(expectedServiceLevels), "Did not get expected SLO list for edition '{0}'", edition.DisplayName);
|
||||||
|
|
||||||
|
var expectedDefaultIndex = expectedLevelInfo.Key;
|
||||||
|
var expectedDefault = expectedServiceLevels[expectedDefaultIndex];
|
||||||
|
var actualDefault = actualServiceLevels[0];
|
||||||
|
Assert.That(actualDefault, Is.EqualTo(expectedDefault), "Did not get expected default SLO for edition '{0}'", edition.DisplayName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Fail("Could not retrieve SLO info for Azure edition '{0}'", edition.DisplayName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GetAzureMaxSizesTest()
|
||||||
|
{
|
||||||
|
var actualSizesMap = new Dictionary<string, string[]>();
|
||||||
|
foreach (AzureEditionDetails sizeDetails in DatabaseHandler.AzureMaxSizes)
|
||||||
|
{
|
||||||
|
actualSizesMap.Add(sizeDetails.EditionDisplayName, sizeDetails.Details);
|
||||||
|
}
|
||||||
|
|
||||||
|
var expectedDefaults = new Dictionary<AzureEdition, string>()
|
||||||
|
{
|
||||||
|
{ AzureEdition.Basic, "2GB" },
|
||||||
|
{ AzureEdition.Standard, "250GB" },
|
||||||
|
{ AzureEdition.Premium, "500GB" },
|
||||||
|
{ AzureEdition.DataWarehouse, "10240GB" },
|
||||||
|
{ AzureEdition.BusinessCritical, "32GB" },
|
||||||
|
{ AzureEdition.GeneralPurpose, "32GB" },
|
||||||
|
{ AzureEdition.Hyperscale, "0MB" }
|
||||||
|
};
|
||||||
|
Assert.That(actualSizesMap.Count, Is.EqualTo(expectedDefaults.Count), "Did not get expected number of editions for DatabaseHandler's max sizes");
|
||||||
|
foreach(AzureEdition edition in expectedDefaults.Keys)
|
||||||
|
{
|
||||||
|
if (AzureSqlDbHelper.TryGetDatabaseSizeInfo(edition, out var expectedSizeInfo))
|
||||||
|
{
|
||||||
|
var expectedSizes = expectedSizeInfo.Value.Select(size => size.ToString()).ToArray();
|
||||||
|
var actualSizes = actualSizesMap[edition.DisplayName];
|
||||||
|
Assert.That(actualSizes, Is.EquivalentTo(expectedSizes), "Did not get expected size list for edition '{0}'", edition.DisplayName);
|
||||||
|
|
||||||
|
var expectedDefaultIndex = expectedSizeInfo.Key;
|
||||||
|
var expectedDefault = expectedSizes[expectedDefaultIndex];
|
||||||
|
var actualDefault = actualSizes[0];
|
||||||
|
Assert.That(actualDefault, Is.EqualTo(expectedDefault.ToString()), "Did not get expected default size for edition '{0}'", edition.DisplayName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Fail("Could not retrieve max size info for Azure edition '{0}'", edition.DisplayName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private bool DatabaseExists(string dbName, Server server)
|
private bool DatabaseExists(string dbName, Server server)
|
||||||
{
|
{
|
||||||
server.Databases.Refresh();
|
server.Databases.Refresh();
|
||||||
|
|||||||
Reference in New Issue
Block a user