From 367fae95c455919b14e8191c4f34f5097062f3b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Wed, 12 Feb 2025 21:03:24 +0100 Subject: [PATCH] mscluster: restore support for Windows Server 2016-2019 (#1882) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- internal/collector/hyperv/hyperv.go | 13 ++- .../collector/mscluster/mscluster_cluster.go | 82 +++++++++++-------- .../collector/mscluster/mscluster_network.go | 2 +- .../collector/mscluster/mscluster_node.go | 10 ++- .../collector/mscluster/mscluster_resource.go | 2 +- .../mscluster/mscluster_resourcegroup.go | 2 +- internal/mi/callbacks.go | 4 + internal/types/const.go | 5 -- 8 files changed, 68 insertions(+), 52 deletions(-) diff --git a/internal/collector/hyperv/hyperv.go b/internal/collector/hyperv/hyperv.go index 6184a83e..ea4aeb8c 100644 --- a/internal/collector/hyperv/hyperv.go +++ b/internal/collector/hyperv/hyperv.go @@ -23,11 +23,10 @@ import ( "strings" "sync" + "github.com/Microsoft/hcsshim/osversion" "github.com/alecthomas/kingpin/v2" "github.com/prometheus-community/windows_exporter/internal/mi" - "github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus/client_golang/prometheus" - "golang.org/x/sys/windows" ) const ( @@ -157,19 +156,17 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { return nil } - version := windows.RtlGetVersion() - subCollectors := map[string]struct { build func() error collect func(ch chan<- prometheus.Metric) error close func() - minBuildNumber uint32 + minBuildNumber uint16 }{ subCollectorDataStore: { build: c.buildDataStore, collect: c.collectDataStore, close: c.perfDataCollectorDataStore.Close, - minBuildNumber: types.BuildNumberWindowsServer2022, + minBuildNumber: osversion.LTSC2022, }, subCollectorDynamicMemoryBalancer: { build: c.buildDynamicMemoryBalancer, @@ -243,6 +240,8 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { }, } + buildNumber := osversion.Build() + // Result must order, to prevent test failures. sort.Strings(c.config.CollectorsEnabled) @@ -253,7 +252,7 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { return fmt.Errorf("unknown collector: %s", name) } - if version.BuildNumber < subCollectors[name].minBuildNumber { + if buildNumber < subCollectors[name].minBuildNumber { errs = append(errs, fmt.Errorf("collector %s requires Windows Server 2022 or newer", name)) continue diff --git a/internal/collector/mscluster/mscluster_cluster.go b/internal/collector/mscluster/mscluster_cluster.go index e7f8a528..0099779b 100644 --- a/internal/collector/mscluster/mscluster_cluster.go +++ b/internal/collector/mscluster/mscluster_cluster.go @@ -18,6 +18,7 @@ package mscluster import ( "fmt" + "github.com/Microsoft/hcsshim/osversion" "github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus/client_golang/prometheus" @@ -192,7 +193,14 @@ type msClusterCluster struct { } func (c *Collector) buildCluster() error { - clusterMIQuery, err := mi.NewQuery("SELECT * FROM MSCluster_Cluster") + buildNumber := osversion.Build() + + wmiSelect := "AddEvictDelay,AdminAccessPoint,AutoAssignNodeSite,AutoBalancerLevel,AutoBalancerMode,BackupInProgress,BlockCacheSize,ClusSvcHangTimeout,ClusSvcRegroupOpeningTimeout,ClusSvcRegroupPruningTimeout,ClusSvcRegroupStageTimeout,ClusSvcRegroupTickInMilliseconds,ClusterEnforcedAntiAffinity,ClusterFunctionalLevel,ClusterGroupWaitDelay,ClusterLogLevel,ClusterLogSize,ClusterUpgradeVersion,CrossSiteDelay,CrossSiteThreshold,CrossSubnetDelay,CrossSubnetThreshold,CsvBalancer,DatabaseReadWriteMode,DefaultNetworkRole,DisableGroupPreferredOwnerRandomization,DrainOnShutdown,DynamicQuorumEnabled,EnableSharedVolumes,FixQuorum,GracePeriodEnabled,GracePeriodTimeout,GroupDependencyTimeout,HangRecoveryAction,IgnorePersistentStateOnStartup,LogResourceControls,LowerQuorumPriorityNodeId,MessageBufferLength,MinimumNeverPreemptPriority,MinimumPreemptorPriority,NetftIPSecEnabled,PlacementOptions,PlumbAllCrossSubnetRoutes,PreventQuorum,QuarantineDuration,QuarantineThreshold,QuorumArbitrationTimeMax,QuorumArbitrationTimeMin,QuorumLogFileSize,QuorumTypeValue,RequestReplyTimeout,ResiliencyDefaultPeriod,ResiliencyLevel,ResourceDllDeadlockPeriod,RootMemoryReserved,RouteHistoryLength,S2DBusTypes,S2DCacheDesiredState,S2DCacheFlashReservePercent,S2DCachePageSizeKBytes,S2DEnabled,S2DIOLatencyThreshold,S2DOptimizations,SameSubnetDelay,SameSubnetThreshold,SecurityLevel,SharedVolumeVssWriterOperationTimeout,ShutdownTimeoutInMinutes,UseClientAccessNetworksForSharedVolumes,WitnessDatabaseWriteTimeout,WitnessDynamicWeight,WitnessRestartInterval" + if buildNumber >= osversion.LTSC2022 { + wmiSelect += ",DetectManagedEvents,SecurityLevelForStorage,MaxNumberOfNodes,DetectManagedEventsThreshold,DetectedCloudPlatform" + } + + clusterMIQuery, err := mi.NewQuery(fmt.Sprintf("SELECT %s FROM MSCluster_Cluster", wmiSelect)) if err != nil { return fmt.Errorf("failed to create WMI query: %w", err) } @@ -852,27 +860,6 @@ func (c *Collector) collectCluster(ch chan<- prometheus.Metric) error { v.Name, ) - ch <- prometheus.MustNewConstMetric( - c.clusterDetectedCloudPlatform, - prometheus.GaugeValue, - float64(v.DetectedCloudPlatform), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.clusterDetectManagedEvents, - prometheus.GaugeValue, - float64(v.DetectManagedEvents), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.clusterDetectManagedEventsThreshold, - prometheus.GaugeValue, - float64(v.DetectManagedEventsThreshold), - v.Name, - ) - ch <- prometheus.MustNewConstMetric( c.clusterDisableGroupPreferredOwnerRandomization, prometheus.GaugeValue, @@ -957,13 +944,6 @@ func (c *Collector) collectCluster(ch chan<- prometheus.Metric) error { v.Name, ) - ch <- prometheus.MustNewConstMetric( - c.clusterMaxNumberOfNodes, - prometheus.GaugeValue, - float64(v.MaxNumberOfNodes), - v.Name, - ) - ch <- prometheus.MustNewConstMetric( c.clusterMessageBufferLength, prometheus.GaugeValue, @@ -1167,13 +1147,6 @@ func (c *Collector) collectCluster(ch chan<- prometheus.Metric) error { v.Name, ) - ch <- prometheus.MustNewConstMetric( - c.clusterSecurityLevelForStorage, - prometheus.GaugeValue, - float64(v.SecurityLevelForStorage), - v.Name, - ) - ch <- prometheus.MustNewConstMetric( c.clusterSharedVolumeVssWriterOperationTimeout, prometheus.GaugeValue, @@ -1215,6 +1188,43 @@ func (c *Collector) collectCluster(ch chan<- prometheus.Metric) error { float64(v.WitnessRestartInterval), v.Name, ) + + if osversion.Build() >= osversion.LTSC2022 { + ch <- prometheus.MustNewConstMetric( + c.clusterDetectManagedEvents, + prometheus.GaugeValue, + float64(v.DetectManagedEvents), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.clusterDetectManagedEventsThreshold, + prometheus.GaugeValue, + float64(v.DetectManagedEventsThreshold), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.clusterSecurityLevelForStorage, + prometheus.GaugeValue, + float64(v.SecurityLevelForStorage), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.clusterMaxNumberOfNodes, + prometheus.GaugeValue, + float64(v.MaxNumberOfNodes), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.clusterDetectedCloudPlatform, + prometheus.GaugeValue, + float64(v.DetectedCloudPlatform), + v.Name, + ) + } } return nil diff --git a/internal/collector/mscluster/mscluster_network.go b/internal/collector/mscluster/mscluster_network.go index 28267947..c986d163 100644 --- a/internal/collector/mscluster/mscluster_network.go +++ b/internal/collector/mscluster/mscluster_network.go @@ -48,7 +48,7 @@ type msClusterNetwork struct { } func (c *Collector) buildNetwork() error { - networkMIQuery, err := mi.NewQuery("SELECT * FROM MSCluster_Network") + networkMIQuery, err := mi.NewQuery("SELECT Characteristics,Flags,Metric,Role,State FROM MSCluster_Network") if err != nil { return fmt.Errorf("failed to create WMI query: %w", err) } diff --git a/internal/collector/mscluster/mscluster_node.go b/internal/collector/mscluster/mscluster_node.go index 09aa6b74..3b45370f 100644 --- a/internal/collector/mscluster/mscluster_node.go +++ b/internal/collector/mscluster/mscluster_node.go @@ -18,6 +18,7 @@ package mscluster import ( "fmt" + "github.com/Microsoft/hcsshim/osversion" "github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus/client_golang/prometheus" @@ -66,7 +67,14 @@ type msClusterNode struct { } func (c *Collector) buildNode() error { - nodeMIQuery, err := mi.NewQuery("SELECT * FROM MSCluster_Node") + buildNumber := osversion.Build() + + wmiSelect := "BuildNumber,Characteristics,DynamicWeight,Flags,MajorVersion,MinorVersion,NeedsPreventQuorum,NodeDrainStatus,NodeHighestVersion,NodeLowestVersion,NodeWeight,State,StatusInformation" + if buildNumber >= osversion.LTSC2022 { + wmiSelect += ",DetectedCloudPlatform" + } + + nodeMIQuery, err := mi.NewQuery(fmt.Sprintf("SELECT %s FROM MSCluster_Node", wmiSelect)) if err != nil { return fmt.Errorf("failed to create WMI query: %w", err) } diff --git a/internal/collector/mscluster/mscluster_resource.go b/internal/collector/mscluster/mscluster_resource.go index 9334d8b5..cf71ccba 100644 --- a/internal/collector/mscluster/mscluster_resource.go +++ b/internal/collector/mscluster/mscluster_resource.go @@ -74,7 +74,7 @@ type msClusterResource struct { } func (c *Collector) buildResource() error { - resourceMIQuery, err := mi.NewQuery("SELECT * FROM MSCluster_Resource") + resourceMIQuery, err := mi.NewQuery("SELECT Name,Type,OwnerGroup,OwnerNode,Characteristics,DeadlockTimeout,EmbeddedFailureAction,Flags,IsAlivePollInterval,LooksAlivePollInterval,MonitorProcessId,PendingTimeout,ResourceClass,RestartAction,RestartDelay,RestartPeriod,RestartThreshold,RetryPeriodOnFailure,State,Subclass FROM MSCluster_Resource") if err != nil { return fmt.Errorf("failed to create WMI query: %w", err) } diff --git a/internal/collector/mscluster/mscluster_resourcegroup.go b/internal/collector/mscluster/mscluster_resourcegroup.go index 6e725007..287c35bf 100644 --- a/internal/collector/mscluster/mscluster_resourcegroup.go +++ b/internal/collector/mscluster/mscluster_resourcegroup.go @@ -66,7 +66,7 @@ type msClusterResourceGroup struct { } func (c *Collector) buildResourceGroup() error { - resourceGroupMIQuery, err := mi.NewQuery("SELECT * FROM MSCluster_ResourceGroup") + resourceGroupMIQuery, err := mi.NewQuery("SELECT AutoFailbackType,Characteristics,ColdStartSetting,DefaultOwner,FailbackWindowEnd,FailbackWindowStart,FailoverPeriod,FailoverThreshold,Flags,GroupType,OwnerNode,Priority,ResiliencyPeriod,State FROM MSCluster_ResourceGroup") if err != nil { return fmt.Errorf("failed to create WMI query: %w", err) } diff --git a/internal/mi/callbacks.go b/internal/mi/callbacks.go index c9a293c8..a8bfffe3 100644 --- a/internal/mi/callbacks.go +++ b/internal/mi/callbacks.go @@ -138,6 +138,10 @@ func (o *OperationUnmarshalCallbacks) InstanceResult( element, err := instance.GetElement(miTag) if err != nil { + if errors.Is(err, MI_RESULT_NO_SUCH_PROPERTY) { + continue + } + o.errCh <- fmt.Errorf("failed to get element %s: %w", miTag, err) return 0 diff --git a/internal/types/const.go b/internal/types/const.go index 02c1067f..8aa123fe 100644 --- a/internal/types/const.go +++ b/internal/types/const.go @@ -16,10 +16,5 @@ package types const ( - BuildNumberWindowsServer2025 uint32 = 26100 - BuildNumberWindowsServer2022 uint32 = 20348 - BuildNumberWindowsServer2019 uint32 = 17763 - BuildNumberWindowsServer2016 uint32 = 14393 - Namespace = "windows" )