diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs index 887baaca..b2478274 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs @@ -12946,6 +12946,11 @@ namespace Microsoft.SqlTools.ServiceLayer return Keys.GetString(Keys.ServiceNotFound, serviceName); } + public static string PropertyNotInitialized(string propertyName) + { + return Keys.GetString(Keys.PropertyNotInitialized, propertyName); + } + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class Keys { @@ -17898,6 +17903,9 @@ namespace Microsoft.SqlTools.ServiceLayer public const string HyperscaleAzureEdition = "HyperscaleAzureEdition"; + public const string PropertyNotInitialized = "PropertyNotInitialized"; + + private Keys() { } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx index 336e93be..82dee144 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx @@ -6802,4 +6802,9 @@ The Query Processor estimates that implementing the following index could improv Hyperscale + + Property '{0}' was set before initialization. + . + Parameters: 0 - propertyName (string) + diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings index 97eb2e91..edba298e 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings @@ -2814,4 +2814,10 @@ DataWarehouseAzureEdition = DataWarehouse GeneralPurposeAzureEdition = General Purpose BusinessCriticalAzureEdition = Business Critical ErrorInvalidEdition = Edition value is not valid -HyperscaleAzureEdition = Hyperscale \ No newline at end of file +HyperscaleAzureEdition = Hyperscale + +############################################################################# +# Server Properties + +############################################################################ +PropertyNotInitialized(string propertyName) = Property '{0}' was set before initialization. \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf index 8b4344ab..c1f895ef 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf @@ -8321,6 +8321,12 @@ The Query Processor estimates that implementing the following index could improv None + + Property '{0}' was set before initialization. + Property '{0}' was set before initialization. + . + Parameters: 0 - propertyName (string) + CREATE TABLE permission denied in database '{0}'. CREATE TABLE permission denied in database '{0}'. diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Server/ServerActions.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Server/ServerActions.cs new file mode 100644 index 00000000..cdb52285 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Server/ServerActions.cs @@ -0,0 +1,40 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + + +using Microsoft.SqlTools.ServiceLayer.Management; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement +{ + internal class ServerActions : ManagementActionBase + { + #region Variables + private ServerPrototype serverData; + private ConfigAction configAction; + #endregion + + #region Constructor + public ServerActions( + CDataContainer context, + ServerPrototype server, + ConfigAction configAction) + { + this.DataContainer = context; + this.serverData = server; + this.configAction = configAction; + } + + #endregion + + /// + /// called on background thread by the framework to execute the action + /// + /// + public override void OnRunNow(object sender) + { + this.serverData.SendDataToServer(); + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Server/ServerData.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Server/ServerData.cs new file mode 100644 index 00000000..cc1334e3 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Server/ServerData.cs @@ -0,0 +1,971 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using Microsoft.SqlServer.Management.Smo; +using Microsoft.SqlTools.ServiceLayer.Management; +using Microsoft.SqlServer.Management.Common; +using Microsoft.SqlTools.ServiceLayer.ServerConfigurations; +using Microsoft.SqlTools.Utility; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement +{ + internal class ServerPrototype + { + #region Members + + /// + /// data container member that contains data specific information like + /// connection infor, SMO server object or an AMO server object as well + /// as a hash table where one can manipulate custom data + /// + private CDataContainer dataContainer; + private ServerConnection sqlConnection; + private ServerConfigService configService; + + + private ServerPrototypeData currentState; + private ServerPrototypeData originalState; + + private ConfigProperty serverMinMemoryProperty; + private ConfigProperty serverMaxMemoryProperty; + #endregion + + #region Trace support + private const string componentName = "Server"; + + public string ComponentName + { + get + { + return componentName; + } + } + #endregion + + #region Properties + public string Name + { + get + { + return this.currentState.ServerName; + } + set + { + this.currentState.ServerName = value; + } + } + + public string Product + { + get + { + return this.currentState.Product; + } + set + { + this.currentState.Product = value; + } + } + + public string OperatingSystem + { + get + { + return this.currentState.OperatingSystem; + } + set + { + this.currentState.OperatingSystem = value; + } + } + + public string Version + { + get + { + return this.currentState.Version; + } + set + { + this.currentState.Version = value; + } + } + + public string Language + { + get + { + return this.currentState.Language; + } + set + { + this.currentState.Language = value; + } + } + + public string Platform + { + get + { + return this.currentState.Platform; + } + set + { + this.currentState.Platform = value; + } + } + + public int MemoryInMB + { + get + { + return this.currentState.MemoryInMB; + } + set + { + this.currentState.MemoryInMB = value; + } + } + + public int Processors + { + get + { + return this.currentState.Processors; + } + set + { + this.currentState.Processors = value; + } + } + + public string RootDirectory + { + get + { + return this.currentState.RootDirectory; + } + set + { + this.currentState.RootDirectory = value; + } + } + + public string ServerCollation + { + get + { + return this.currentState.ServerCollation; + } + set + { + this.currentState.ServerCollation = value; + } + } + + public bool IsClustered + { + get + { + return this.currentState.IsClustered; + } + set + { + this.currentState.IsClustered = value; + } + } + + public bool IsHadrEnabled + { + get + { + return this.currentState.IsHadrEnabled; + } + set + { + this.currentState.IsHadrEnabled = value; + } + } + + public bool IsXTPSupported + { + get + { + return this.currentState.IsXTPSupported; + } + set + { + this.currentState.IsXTPSupported = value; + } + } + + public bool IsPolyBaseInstalled + { + get + { + return this.currentState.IsPolyBaseInstalled; + } + set + { + this.currentState.IsPolyBaseInstalled = value; + } + } + + + public string HardwareGeneration + { + get + { + return this.currentState.HardwareGeneration; + } + set + { + this.currentState.HardwareGeneration = value; + } + } + + public string ServiceTier + { + get + { + return this.currentState.ServiceTier; + } + set + { + this.currentState.ServiceTier = value; + } + } + + public int StorageSpaceUsageInMB + { + get + { + return this.currentState.StorageSpaceUsageInMB; + } + set + { + this.currentState.StorageSpaceUsageInMB = value; + } + } + + + public int ReservedStorageSizeMB + { + get + { + return this.currentState.ReservedStorageSizeMB; + } + set + { + this.currentState.ReservedStorageSizeMB = value; + } + } + + public int MaxServerMemory + { + get + { + return this.currentState.MaxMemory; + } + set + { + this.currentState.MaxMemory = value; + } + } + + public int MinServerMemory + { + get + { + return this.currentState.MinMemory; + } + set + { + this.currentState.MinMemory = value; + } + + } + #endregion + + + #region Constructors / Dispose + + /// + /// ServerPrototype for editing an existing server + /// + public ServerPrototype(CDataContainer context) + { + this.dataContainer = context; + this.sqlConnection = context.ServerConnection; + this.configService = new ServerConfigService(); + this.currentState = new ServerPrototypeData(context, context.Server, this.configService); + this.originalState = (ServerPrototypeData)this.currentState.Clone(); + this.serverMaxMemoryProperty = this.configService.GetServerSmoConfig(context.Server, this.configService.MaxServerMemoryPropertyNumber); + this.serverMinMemoryProperty = this.configService.GetServerSmoConfig(context.Server, this.configService.MinServerMemoryPropertyNumber); + } + + #endregion + + #region Implementation: SendDataToServer() + /// + /// SendDataToServer + /// + /// here we talk with server via smo and do the actual data changing + /// + public void SendDataToServer() + { + if (this.dataContainer.Server != null) + { + Microsoft.SqlServer.Management.Smo.Server server = this.dataContainer.Server; + bool changesMade = false; + + changesMade = UpdateMemoryValues(this.dataContainer.Server); + + if (changesMade) + { + server.Configuration.Alter(true); + } + } + } + + public bool UpdateMemoryValues(Microsoft.SqlServer.Management.Smo.Server server) + { + bool changesMade = false; + + if (this.currentState.MinMemory != this.originalState.MinMemory) + { + changesMade = true; + ConfigProperty serverConfig = this.configService.GetServerSmoConfig(server, this.configService.MinServerMemoryPropertyNumber); + serverConfig.ConfigValue = this.currentState.MinMemory; + } + + if (this.currentState.MaxMemory != this.originalState.MaxMemory) + { + changesMade = true; + ConfigProperty serverConfig = this.configService.GetServerSmoConfig(server, this.configService.MaxServerMemoryPropertyNumber); + serverConfig.ConfigValue = this.currentState.MaxMemory; + } + return changesMade; + } + #endregion + + public void ApplyInfoToPrototype(ServerInfo serverInfo) + { + this.Name = serverInfo.Name; + this.Language = serverInfo.Language; + this.MemoryInMB = serverInfo.MemoryInMB; + this.OperatingSystem = serverInfo.OperatingSystem; + this.Platform = serverInfo.Platform; + this.Version = serverInfo.Version; + this.Processors = serverInfo.Processors; + this.Version = serverInfo.Version; + this.IsClustered = serverInfo.IsClustered; + this.IsHadrEnabled = serverInfo.IsHadrEnabled; + this.IsPolyBaseInstalled = serverInfo.IsPolyBaseInstalled; + this.IsXTPSupported = (bool)(serverInfo.IsXTPSupported); + this.Product = serverInfo.Product; + this.ReservedStorageSizeMB = (int)(serverInfo.ReservedStorageSizeMB); + this.RootDirectory = serverInfo.RootDirectory; + this.ServerCollation = serverInfo.ServerCollation; + this.ServiceTier = serverInfo.ServiceTier; + this.StorageSpaceUsageInMB = (int)(serverInfo.StorageSpaceUsageInMB); + this.MaxServerMemory = serverInfo.MaxServerMemory; + this.MinServerMemory = serverInfo.MinServerMemory; + } + + /// + /// Private class encapsulating the data that is changed by the UI. + /// + /// + /// Isolating this data allows for an easy implementation of Reset() and + /// simplifies difference detection when committing changes to the server. + /// + private class ServerPrototypeData : ICloneable + { + #region data members + private string serverName = string.Empty; + private string hardwareGeneration = String.Empty; + private string language = String.Empty; + private int memoryInMB = 0; + private string operatingSystem = String.Empty; + private string platform = String.Empty; + private int processors = 0; + private bool isClustered = false; + private bool isHadrEnabled = false; + private bool isPolyBaseInstalled = false; + private bool isXTPSupported = false; + private string product = String.Empty; + private string rootDirectory = String.Empty; + private string serverCollation = String.Empty; + private string version = String.Empty; + private string serviceTier = String.Empty; + private int reservedStorageSizeMB = 0; + private int storageSpaceUsageInMB = 0; + private int minMemory = 0; + private int maxMemory = 0; + + private bool initialized = false; + private Server server; + private CDataContainer context; + private ServerConfigService configService; + private bool isYukonOrLater = false; + + ConfigProperty serverMaxMemoryProperty; + ConfigProperty serverMinMemoryProperty; + #endregion + + #region Properties + + // General properties + + + public string ServerName + { + get + { + if (!this.initialized) + { + LoadData(); + } + + return this.serverName; + } + + set + { + if (this.initialized) + { + Logger.Error(SR.PropertyNotInitialized("ServerName")); + } + this.serverName = value; + } + } + + public string HardwareGeneration + { + get + { + if (!this.initialized) + { + LoadData(); + } + + return this.hardwareGeneration; + } + + set + { + if (this.initialized) + { + Logger.Error(SR.PropertyNotInitialized("HardwareGeneration")); + } + this.hardwareGeneration = value; + } + } + + public string Language + { + get + { + if (!this.initialized) + { + LoadData(); + } + + return this.language; + } + + set + { + if (this.initialized) + { + Logger.Error(SR.PropertyNotInitialized("Language")); + } + this.language = value; + } + } + + public int MemoryInMB + { + get + { + if (!this.initialized) + { + LoadData(); + } + + return this.memoryInMB; + } + + set + { + if (this.initialized) + { + Logger.Error(SR.PropertyNotInitialized("MemoryInMB")); + } + this.memoryInMB = value; + } + } + + public string OperatingSystem + { + get + { + if (!this.initialized) + { + LoadData(); + } + + return this.operatingSystem; + } + + set + { + if (this.initialized) + { + Logger.Error(SR.PropertyNotInitialized("OperatingSystem")); + } + this.operatingSystem = value; + } + } + + public string Platform + { + get + { + if (!this.initialized) + { + LoadData(); + } + + return this.platform; + } + + set + { + if (this.initialized) + { + Logger.Error(SR.PropertyNotInitialized("Platform")); + } + this.platform = value; + } + } + + public int Processors + { + get + { + if (!this.initialized) + { + LoadData(); + } + + return this.processors; + } + + set + { + if (this.initialized) + { + Logger.Error(SR.PropertyNotInitialized("Processors")); + } + this.processors = value; + } + } + + public bool IsClustered + { + get + { + if (!this.initialized) + { + LoadData(); + } + + return this.isClustered; + } + + set + { + if (this.initialized) + { + Logger.Error(SR.PropertyNotInitialized("IsClustered")); + } + this.isClustered = value; + } + } + + public bool IsHadrEnabled + { + get + { + if (!this.initialized) + { + LoadData(); + } + + return this.isHadrEnabled; + } + + set + { + if (this.initialized) + { + Logger.Error(SR.PropertyNotInitialized("IsHadrEnabled")); + } + this.isHadrEnabled = value; + } + } + + public bool IsPolyBaseInstalled + { + get + { + if (!this.initialized) + { + LoadData(); + } + + return this.isPolyBaseInstalled; + } + + set + { + if (this.initialized) + { + Logger.Error(SR.PropertyNotInitialized("IsPolyBaseInstalled")); + } + this.isPolyBaseInstalled = value; + } + } + + public bool IsXTPSupported + { + get + { + if (!this.initialized) + { + LoadData(); + } + + return this.isXTPSupported; + } + + set + { + if (this.initialized) + { + Logger.Error(SR.PropertyNotInitialized("IsXTPSupported")); + } + this.isXTPSupported = value; + } + } + + + public string Product + { + get + { + if (!this.initialized) + { + LoadData(); + } + + return this.product; + } + + set + { + if (this.initialized) + { + Logger.Error(SR.PropertyNotInitialized("Product")); + } + this.product = value; + } + } + + public string RootDirectory + { + get + { + if (!this.initialized) + { + LoadData(); + } + + return this.rootDirectory; + } + + set + { + if (this.initialized) + { + Logger.Error(SR.PropertyNotInitialized("RootDirectory")); + } + this.rootDirectory = value; + } + } + + public string ServerCollation + { + get + { + if (!this.initialized) + { + LoadData(); + } + + return this.serverCollation; + } + + set + { + if (this.initialized) + { + Logger.Error(SR.PropertyNotInitialized("ServerCollation")); + } + this.serverCollation = value; + } + } + + public string Version + { + get + { + if (!this.initialized) + { + LoadData(); + } + + return this.version; + } + + set + { + if (this.initialized) + { + Logger.Error(SR.PropertyNotInitialized("Version")); + } + this.version = value; + } + } + + public string ServiceTier + { + get + { + if (!this.initialized) + { + LoadData(); + } + + return this.serviceTier; + } + + set + { + if (this.initialized) + { + Logger.Error(SR.PropertyNotInitialized("ServiceTier")); + } + this.serviceTier = value; + } + } + + public int StorageSpaceUsageInMB + { + get + { + if (!this.initialized) + { + LoadData(); + } + + return this.storageSpaceUsageInMB; + } + + set + { + if (this.initialized) + { + Logger.Error(SR.PropertyNotInitialized("StorageSpaceUsageInMB")); + } + this.storageSpaceUsageInMB = value; + } + } + + + public int ReservedStorageSizeMB + { + get + { + if (!this.initialized) + { + LoadData(); + } + + return this.reservedStorageSizeMB; + } + + set + { + if (this.initialized) + { + Logger.Error(SR.PropertyNotInitialized("ReservedStorageSizeMB")); + } + this.reservedStorageSizeMB = value; + } + } + + + public int MinMemory + { + get + { + if (!this.initialized) + { + LoadData(); + } + + return this.minMemory; + } + + set + { + if (this.initialized) + { + Logger.Error(SR.PropertyNotInitialized("MinMemory")); + } + + this.minMemory = value; + } + } + + public int MaxMemory + { + get + { + if (!this.initialized) + { + LoadData(); + } + + return this.maxMemory; + } + + set + { + if (this.initialized) + { + Logger.Error(SR.PropertyNotInitialized("MaxMemory")); + } + + this.maxMemory = value; + } + } + + + public Microsoft.SqlServer.Management.Smo.Server Server + { + get + { + return this.server; + } + } + + public bool IsYukonOrLater + { + get + { + return this.isYukonOrLater; + } + } + + #endregion + + /// + /// private default constructor - used by Clone() + /// + private ServerPrototypeData() + { + } + + + /// + /// constructor + /// + /// The context in which we are modifying an existing server + /// The server we are modifying + public ServerPrototypeData(CDataContainer context, Server server, ServerConfigService service) + { + this.server = context.Server; + this.context = context; + this.configService = service; + this.isYukonOrLater = (this.server.Information.Version.Major >= 9); + this.serverMaxMemoryProperty = this.configService.GetServerSmoConfig(server, this.configService.MaxServerMemoryPropertyNumber); + this.serverMinMemoryProperty = this.configService.GetServerSmoConfig(server, this.configService.MinServerMemoryPropertyNumber); + LoadData(); + } + + /// + /// Create a clone of this ServerRolePrototypeData object + /// + /// The clone ServerRolePrototypeData object + public object Clone() + { + ServerPrototypeData result = new ServerPrototypeData(); + result.serverName = this.serverName; + result.initialized = this.initialized; + result.hardwareGeneration = this.hardwareGeneration; + result.language = this.language; + result.memoryInMB = this.memoryInMB; + result.operatingSystem = this.operatingSystem; + result.platform = this.platform; + result.processors = this.processors; + result.isClustered = this.isClustered; + result.isHadrEnabled = this.isHadrEnabled; + result.isPolyBaseInstalled = this.isPolyBaseInstalled; + result.isXTPSupported = this.isXTPSupported; + result.product = this.product; + result.reservedStorageSizeMB = this.reservedStorageSizeMB; + result.rootDirectory = this.rootDirectory; + result.serverCollation = this.serverCollation; + result.serviceTier = this.serviceTier; + result.storageSpaceUsageInMB = this.storageSpaceUsageInMB; + result.version = this.version; + result.maxMemory = this.maxMemory; + result.minMemory = this.minMemory; + result.server = this.server; + return result; + } + + private void LoadData() + { + this.initialized = true; + this.serverName = server.Name; + this.hardwareGeneration = server.HardwareGeneration; + this.language = server.Language; + this.memoryInMB = server.PhysicalMemory; + this.operatingSystem = server.HostDistribution; + this.platform = server.HostPlatform; + this.processors = server.Processors; + this.isClustered = server.IsClustered; + this.isHadrEnabled = server.IsHadrEnabled; + this.isPolyBaseInstalled = server.IsPolyBaseInstalled; + this.isXTPSupported = server.IsXTPSupported; + this.product = server.Product; + this.rootDirectory = server.RootDirectory; + this.serverCollation = server.Collation; + this.version = server.VersionString; + this.reservedStorageSizeMB = server.ReservedStorageSizeMB; + this.serviceTier = server.ServiceTier; + this.storageSpaceUsageInMB = server.UsedStorageSizeMB; + this.maxMemory = serverMaxMemoryProperty.ConfigValue; + this.minMemory = serverMinMemoryProperty.ConfigValue; + } + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Server/ServerHandler.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Server/ServerHandler.cs index f3df457f..7105f09c 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Server/ServerHandler.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Server/ServerHandler.cs @@ -5,13 +5,11 @@ using System; using System.Threading.Tasks; -using Microsoft.SqlServer.Management.Common; -using Microsoft.SqlServer.Management.Smo; using Microsoft.SqlTools.ServiceLayer.Connection; +using Microsoft.SqlTools.ServiceLayer.Management; using Microsoft.SqlTools.ServiceLayer.ObjectManagement.Contracts; using Microsoft.SqlTools.ServiceLayer.ObjectManagement.ObjectTypes.Server; using Microsoft.SqlTools.ServiceLayer.ServerConfigurations; -using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement { @@ -22,7 +20,6 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement { private ServerViewInfo serverViewInfo = new ServerViewInfo(); private ServerConfigService configService = new ServerConfigService(); - private Server server = null; public ServerHandler(ConnectionService connectionService) : base(connectionService) { @@ -36,60 +33,78 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement public override Task InitializeObjectView(InitializeViewRequestParams requestParams) { ConnectionInfo connInfo = this.GetConnectionInfo(requestParams.ConnectionUri); - ServerConnection serverConnection = ConnectionService.OpenServerConnection(connInfo, ObjectManagementService.ApplicationName); - using (var context = new ServerViewContext(requestParams, serverConnection)) + using (var context = new ServerViewContext(requestParams, ConnectionService.OpenServerConnection(connInfo, ObjectManagementService.ApplicationName))) { - this.server = new Server(context.Connection); - if (this.server != null) + CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true); + + ServerPrototype prototype = new ServerPrototype(dataContainer); + + if (prototype != null) { this.serverViewInfo.ObjectInfo = new ServerInfo() { - Name = server.Name, - HardwareGeneration = server.HardwareGeneration, - Language = server.Language, - MemoryInMB = server.PhysicalMemory, - OperatingSystem = server.HostDistribution, - Platform = server.HostPlatform, - Processors = server.Processors, - IsClustered = server.IsClustered, - IsHadrEnabled = server.IsHadrEnabled, - IsPolyBaseInstalled = server.IsPolyBaseInstalled, - IsXTPSupported = server.IsXTPSupported, - Product = server.Product, - ReservedStorageSizeMB = server.ReservedStorageSizeMB, - RootDirectory = server.RootDirectory, - ServerCollation = server.Collation, - ServiceTier = server.ServiceTier, - StorageSpaceUsageInGB = (int)ByteConverter.ConvertMbtoGb(server.UsedStorageSizeMB), - Version = server.Version.ToString(), - MinServerMemory = GetServerMinMemory(), - MaxServerMemory = GetServerMaxMemory() + Name = prototype.Name, + HardwareGeneration = prototype.HardwareGeneration, + Language = prototype.Language, + MemoryInMB = prototype.MemoryInMB, + OperatingSystem = prototype.OperatingSystem, + Platform = prototype.Platform, + Processors = prototype.Processors, + IsClustered = prototype.IsClustered, + IsHadrEnabled = prototype.IsHadrEnabled, + IsPolyBaseInstalled = prototype.IsPolyBaseInstalled, + IsXTPSupported = prototype.IsXTPSupported, + Product = prototype.Product, + ReservedStorageSizeMB = prototype.ReservedStorageSizeMB, + RootDirectory = prototype.RootDirectory, + ServerCollation = prototype.ServerCollation, + ServiceTier = prototype.ServiceTier, + StorageSpaceUsageInMB = prototype.StorageSpaceUsageInMB, + Version = prototype.Version, + MinServerMemory = prototype.MinServerMemory, + MaxServerMemory = prototype.MaxServerMemory }; } - return Task.FromResult(new InitializeViewResult { ViewInfo = this.serverViewInfo, Context = context }); } - } + } - public override Task Save(ServerViewContext context, ServerInfo serverInfo) - { - throw new NotSupportedException("ServerHandler does not support Save method"); - } + public override Task Save(ServerViewContext context, ServerInfo obj) + { + UpdateServerProperties(context.Parameters, obj); + return Task.CompletedTask; + } - public override Task Script(ServerViewContext context, ServerInfo obj) - { - throw new NotSupportedException("ServerHandler does not support Script method"); - } + public override Task Script(ServerViewContext context, ServerInfo obj) + { + throw new NotSupportedException("ServerHandler does not support Script method"); + } - private int GetServerMaxMemory() + private void UpdateServerProperties(InitializeViewRequestParams viewParams, ServerInfo serverInfo) + { + if (viewParams != null) { - return configService.GetServerSmoConfig(server, configService.MaxServerMemoryPropertyNumber).ConfigValue; - } + ConnectionInfo connInfo = this.GetConnectionInfo(viewParams.ConnectionUri); + CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo); - private int GetServerMinMemory() - { - return configService.GetServerSmoConfig(server, configService.MinServerMemoryPropertyNumber).ConfigValue; + ServerPrototype prototype = new ServerPrototype(dataContainer); + prototype.ApplyInfoToPrototype(serverInfo); + ConfigureServer(dataContainer, ConfigAction.Update, RunType.RunNow, prototype); } } + + private void ConfigureServer(CDataContainer dataContainer, ConfigAction configAction, RunType runType, ServerPrototype prototype) + { + using (var actions = new ServerActions(dataContainer, prototype, configAction)) + { + var executionHandler = new ExecutonHandler(actions); + executionHandler.RunNow(runType, this); + if (executionHandler.ExecutionResult == ExecutionMode.Failure) + { + throw executionHandler.ExecutionFailureException; + } + } + } +} } \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Server/ServerInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Server/ServerInfo.cs index ecd2d432..b806a2dc 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Server/ServerInfo.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Server/ServerInfo.cs @@ -26,7 +26,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement public string RootDirectory { get; set; } public string ServerCollation { get; set; } public string? ServiceTier { get; set; } - public int? StorageSpaceUsageInGB { get; set; } + public int? StorageSpaceUsageInMB { get; set; } public string Version { get; set; } public int MaxServerMemory { get; set; } public int MinServerMemory { get; set; } diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/ObjectManagement/ServerHandlerTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/ObjectManagement/ServerHandlerTests.cs index 1a856b99..20c622b4 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/ObjectManagement/ServerHandlerTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/ObjectManagement/ServerHandlerTests.cs @@ -9,11 +9,13 @@ using Microsoft.SqlServer.Management.Common; using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility; using Microsoft.SqlTools.ServiceLayer.ObjectManagement; using Microsoft.SqlTools.ServiceLayer.Connection; -using Microsoft.SqlServer.Management.Smo; using NUnit.Framework; using Microsoft.SqlTools.ServiceLayer.Test.Common; +using Server = Microsoft.SqlServer.Management.Smo.Server; +using Microsoft.SqlTools.ServiceLayer.ServerConfigurations; + namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement { /// @@ -47,5 +49,59 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement Assert.That(((ServerInfo)result.ViewInfo.ObjectInfo).IsPolyBaseInstalled, Is.Not.Null, $"Server isPolyBaseInstalled property should not be null"); } } + + /// + /// Test SetMemoryProperties for Sql Server + /// + [Test] + public async Task SetMemoryProperties() + { + var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", serverType: TestServerType.OnPrem); + using (SqlConnection sqlConn = ConnectionService.OpenSqlConnection(connectionResult.ConnectionInfo)) + { + var server = new Server(new ServerConnection(sqlConn)); + var serverHandler = new ServerHandler(ConnectionService.Instance); + var serverConfig = new ServerConfigService(); + + var requestParams = ObjectManagementTestUtils.GetInitializeViewRequestParams(connectionResult.ConnectionInfo.OwnerUri, "master", true, SqlObjectType.Server, "", ""); + var result = (ServerInfo)(await serverHandler.InitializeObjectView(requestParams)).ViewInfo.ObjectInfo; + ServerInfo serverInfo = new ServerInfo() + { + Name = result.Name, + HardwareGeneration = result.HardwareGeneration, + Language = result.Language, + MemoryInMB = result.MemoryInMB, + OperatingSystem = result.OperatingSystem, + Platform = result.Platform, + Processors = result.Processors, + IsClustered = result.IsClustered, + IsHadrEnabled = result.IsHadrEnabled, + IsPolyBaseInstalled = result.IsPolyBaseInstalled, + IsXTPSupported = result.IsXTPSupported, + Product = result.Product, + ReservedStorageSizeMB = result.ReservedStorageSizeMB, + RootDirectory = result.RootDirectory, + ServerCollation = result.ServerCollation, + ServiceTier = result.ServiceTier, + StorageSpaceUsageInMB = result.StorageSpaceUsageInMB, + Version = result.Version, + MinServerMemory = result.MinServerMemory, + MaxServerMemory = result.MaxServerMemory + }; + + // Change memory settings + serverInfo.MinServerMemory = 10; + serverInfo.MaxServerMemory = 500; + + Assert.AreNotEqual(result.MinServerMemory, serverInfo.MinServerMemory, "Server property should not be equal after update"); + Assert.AreNotEqual(result.MaxServerMemory, serverInfo.MaxServerMemory, "Server property should not be equal after update"); + + await ObjectManagementTestUtils.SaveObject(requestParams, serverInfo); + result = (ServerInfo)(await serverHandler.InitializeObjectView(requestParams)).ViewInfo.ObjectInfo; + Assert.IsNotNull(result); + Assert.AreEqual(result.MinServerMemory, serverInfo.MinServerMemory, "Server property should not be different after update"); + Assert.AreEqual(result.MaxServerMemory, serverInfo.MaxServerMemory, "Server property should not be different after update"); + } + } } }