From b4ba8cf18858e05ee7aaae31fb38ee2a2295b9d0 Mon Sep 17 00:00:00 2001 From: gab-satchi Date: Thu, 24 Oct 2019 18:05:25 +0100 Subject: [PATCH] Adds Windows build information as a label on the node --- pkg/kubelet/kubelet_node_status.go | 4 + pkg/kubelet/kubelet_node_status_others.go | 27 ++++ pkg/kubelet/kubelet_node_status_windows.go | 33 +++++ pkg/kubelet/winstats/perfcounter_nodestats.go | 11 +- pkg/kubelet/winstats/version.go | 120 ++++++------------ .../k8s.io/api/core/v1/well_known_labels.go | 2 + 6 files changed, 111 insertions(+), 86 deletions(-) create mode 100644 pkg/kubelet/kubelet_node_status_others.go create mode 100644 pkg/kubelet/kubelet_node_status_windows.go diff --git a/pkg/kubelet/kubelet_node_status.go b/pkg/kubelet/kubelet_node_status.go index e0e27b32b7c..efba9666679 100644 --- a/pkg/kubelet/kubelet_node_status.go +++ b/pkg/kubelet/kubelet_node_status.go @@ -230,6 +230,10 @@ func (kl *Kubelet) initialNode(ctx context.Context) (*v1.Node, error) { Unschedulable: !kl.registerSchedulable, }, } + if err := addOSSpecificLabels(node); err != nil { + return nil, err + } + nodeTaints := make([]v1.Taint, 0) if len(kl.registerWithTaints) > 0 { taints := make([]v1.Taint, len(kl.registerWithTaints)) diff --git a/pkg/kubelet/kubelet_node_status_others.go b/pkg/kubelet/kubelet_node_status_others.go new file mode 100644 index 00000000000..30d3dd2f84f --- /dev/null +++ b/pkg/kubelet/kubelet_node_status_others.go @@ -0,0 +1,27 @@ +// +build !windows + +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kubelet + +import ( + v1 "k8s.io/api/core/v1" +) + +func addOSSpecificLabels(n *v1.Node) error { + return nil +} diff --git a/pkg/kubelet/kubelet_node_status_windows.go b/pkg/kubelet/kubelet_node_status_windows.go new file mode 100644 index 00000000000..9ee3ac81d07 --- /dev/null +++ b/pkg/kubelet/kubelet_node_status_windows.go @@ -0,0 +1,33 @@ +// +build windows + +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kubelet + +import ( + v1 "k8s.io/api/core/v1" + "k8s.io/kubernetes/pkg/kubelet/winstats" +) + +func addOSSpecificLabels(n *v1.Node) error { + osInfo, err := winstats.GetOSInfo() + if err != nil { + return err + } + n.Labels[v1.LabelWindowsBuild] = osInfo.GetBuild() + return nil +} diff --git a/pkg/kubelet/winstats/perfcounter_nodestats.go b/pkg/kubelet/winstats/perfcounter_nodestats.go index 317c08bf028..4d8a2355197 100644 --- a/pkg/kubelet/winstats/perfcounter_nodestats.go +++ b/pkg/kubelet/winstats/perfcounter_nodestats.go @@ -78,19 +78,14 @@ func (p *perfCounterNodeStatsClient) startMonitoring() error { return err } - kernelVersion, err := getKernelVersion() - if err != nil { - return err - } - - osImageVersion, err := getOSImageVersion() + osInfo, err := GetOSInfo() if err != nil { return err } p.nodeInfo = nodeInfo{ - kernelVersion: kernelVersion, - osImageVersion: osImageVersion, + kernelVersion: osInfo.GetPatchVersion(), + osImageVersion: osInfo.ProductName, memoryPhysicalCapacityBytes: memory, startTime: time.Now(), } diff --git a/pkg/kubelet/winstats/version.go b/pkg/kubelet/winstats/version.go index 8020b297368..66c8926f3e4 100644 --- a/pkg/kubelet/winstats/version.go +++ b/pkg/kubelet/winstats/version.go @@ -20,96 +20,60 @@ package winstats import ( "fmt" - "unsafe" - - "golang.org/x/sys/windows" + "golang.org/x/sys/windows/registry" ) -// getCurrentVersionVal gets value of specified key from registry. -func getCurrentVersionVal(key string) (string, error) { - var h windows.Handle - if err := windows.RegOpenKeyEx(windows.HKEY_LOCAL_MACHINE, - windows.StringToUTF16Ptr(`SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\`), - 0, - windows.KEY_READ, - &h); err != nil { - return "", err - } - defer windows.RegCloseKey(h) - - var buf [128]uint16 - var typ uint32 - n := uint32(len(buf) * int(unsafe.Sizeof(buf[0]))) // api expects array of bytes, not uint16 - if err := windows.RegQueryValueEx(h, - windows.StringToUTF16Ptr(key), - nil, - &typ, - (*byte)(unsafe.Pointer(&buf[0])), - &n); err != nil { - return "", err - } - - return windows.UTF16ToString(buf[:]), nil +type OSInfo struct { + BuildNumber, ProductName string + MajorVersion, MinorVersion, UBR uint64 } -// getVersionRevision gets revision from UBR registry. -func getVersionRevision() (uint16, error) { - revisionString, err := getCurrentVersionVal("UBR") +// GetOSInfo reads Windows version information from the registry +func GetOSInfo() (*OSInfo, error) { + k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE) if err != nil { - return 0, err + return nil, err + } + defer k.Close() + + buildNumber, _, err := k.GetStringValue("CurrentBuildNumber") + if err != nil { + return nil, err } - revision, err := windows.UTF16FromString(revisionString) + majorVersionNumber, _, err := k.GetIntegerValue("CurrentMajorVersionNumber") if err != nil { - return 0, err + return nil, err } - return revision[0], nil + minorVersionNumber, _, err := k.GetIntegerValue("CurrentMinorVersionNumber") + if err != nil { + return nil, err + } + + revision, _, err := k.GetIntegerValue("UBR") + if err != nil { + return nil, err + } + + productName, _, err := k.GetStringValue("ProductName") + if err != nil { + return nil, nil + } + + return &OSInfo{ + BuildNumber: buildNumber, + ProductName: productName, + MajorVersion: majorVersionNumber, + MinorVersion: minorVersionNumber, + UBR: revision, + }, nil } -// getKernelVersion gets the version of windows kernel. -func getKernelVersion() (string, error) { - // Get CurrentBuildNumber. - buildNumber, err := getCurrentVersionVal("CurrentBuildNumber") - if err != nil { - return "", err - } - - // Get CurrentMajorVersionNumber. - majorVersionNumberString, err := getCurrentVersionVal("CurrentMajorVersionNumber") - if err != nil { - return "", err - } - majorVersionNumber, err := windows.UTF16FromString(majorVersionNumberString) - if err != nil { - return "", err - } - - // Get CurrentMinorVersionNumber. - minorVersionNumberString, err := getCurrentVersionVal("CurrentMinorVersionNumber") - if err != nil { - return "", err - } - minorVersionNumber, err := windows.UTF16FromString(minorVersionNumberString) - if err != nil { - return "", err - } - - // Get UBR. - revision, err := getVersionRevision() - if err != nil { - return "", err - } - - return fmt.Sprintf("%d.%d.%s.%d", majorVersionNumber[0], minorVersionNumber[0], buildNumber, revision), nil +func (o *OSInfo) GetPatchVersion() string { + return fmt.Sprintf("%d.%d.%s.%d", o.MajorVersion, o.MinorVersion, o.BuildNumber, o.UBR) } -// getOSImageVersion gets the osImage name and version. -func getOSImageVersion() (string, error) { - productName, err := getCurrentVersionVal("ProductName") - if err != nil { - return "", nil - } - - return productName, nil +func (o *OSInfo) GetBuild() string { + return fmt.Sprintf("%d.%d.%s", o.MajorVersion, o.MinorVersion, o.BuildNumber) } diff --git a/staging/src/k8s.io/api/core/v1/well_known_labels.go b/staging/src/k8s.io/api/core/v1/well_known_labels.go index 3287fb51fc2..55ddbb1cafb 100644 --- a/staging/src/k8s.io/api/core/v1/well_known_labels.go +++ b/staging/src/k8s.io/api/core/v1/well_known_labels.go @@ -26,6 +26,8 @@ const ( LabelOSStable = "kubernetes.io/os" LabelArchStable = "kubernetes.io/arch" + LabelWindowsBuild = "node.kubernetes.io/windows-build" + // LabelNamespaceSuffixKubelet is an allowed label namespace suffix kubelets can self-set ([*.]kubelet.kubernetes.io/*) LabelNamespaceSuffixKubelet = "kubelet.kubernetes.io" // LabelNamespaceSuffixNode is an allowed label namespace suffix kubelets can self-set ([*.]node.kubernetes.io/*)