From 4c4d6584b3a79d9e1fe8e80fd8eb369f93da2422 Mon Sep 17 00:00:00 2001
From: Barbara Valdez <34872381+barbaravaldez@users.noreply.github.com>
Date: Thu, 6 Jul 2023 17:25:45 -0700
Subject: [PATCH] Update memory settings and implement ServerPrototype (#2126)
---
.../Localization/sr.cs | 8 +
.../Localization/sr.resx | 5 +
.../Localization/sr.strings | 8 +-
.../Localization/sr.xlf | 6 +
.../ObjectTypes/Server/ServerActions.cs | 40 +
.../ObjectTypes/Server/ServerData.cs | 971 ++++++++++++++++++
.../ObjectTypes/Server/ServerHandler.cs | 103 +-
.../ObjectTypes/Server/ServerInfo.cs | 2 +-
.../ObjectManagement/ServerHandlerTests.cs | 58 +-
9 files changed, 1154 insertions(+), 47 deletions(-)
create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Server/ServerActions.cs
create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Server/ServerData.cs
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");
+ }
+ }
}
}