diff --git a/pkg/volume/vsphere_volume/vsphere_volume_util.go b/pkg/volume/vsphere_volume/vsphere_volume_util.go index c3a878d0f02..ab229b980fc 100644 --- a/pkg/volume/vsphere_volume/vsphere_volume_util.go +++ b/pkg/volume/vsphere_volume/vsphere_volume_util.go @@ -40,15 +40,22 @@ const ( checkSleepDuration = time.Second diskByIDPath = "/dev/disk/by-id/" diskSCSIPrefix = "wwn-0x" - diskformat = "diskformat" - datastore = "datastore" - StoragePolicyName = "storagepolicyname" + // diskformat parameter is deprecated as of Kubernetes v1.21.0 + diskformat = "diskformat" + datastore = "datastore" + StoragePolicyName = "storagepolicyname" - HostFailuresToTolerateCapability = "hostfailurestotolerate" - ForceProvisioningCapability = "forceprovisioning" - CacheReservationCapability = "cachereservation" - DiskStripesCapability = "diskstripes" - ObjectSpaceReservationCapability = "objectspacereservation" + // hostfailurestotolerate parameter is deprecated as of Kubernetes v1.19.0 + HostFailuresToTolerateCapability = "hostfailurestotolerate" + // forceprovisioning parameter is deprecated as of Kubernetes v1.19.0 + ForceProvisioningCapability = "forceprovisioning" + // cachereservation parameter is deprecated as of Kubernetes v1.19.0 + CacheReservationCapability = "cachereservation" + // diskstripes parameter is deprecated as of Kubernetes v1.19.0 + DiskStripesCapability = "diskstripes" + // objectspacereservation parameter is deprecated as of Kubernetes v1.19.0 + ObjectSpaceReservationCapability = "objectspacereservation" + // iopslimit parameter is deprecated as of Kubernetes v1.19.0 IopsLimitCapability = "iopslimit" HostFailuresToTolerateCapabilityMin = 0 HostFailuresToTolerateCapabilityMax = 3 diff --git a/staging/src/k8s.io/legacy-cloud-providers/go.mod b/staging/src/k8s.io/legacy-cloud-providers/go.mod index 2c52274338c..7ddbd51b436 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/go.mod +++ b/staging/src/k8s.io/legacy-cloud-providers/go.mod @@ -14,6 +14,7 @@ require ( github.com/Azure/go-autorest/autorest/validation v0.1.0 // indirect github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20200415212048-7901bc822317 github.com/aws/aws-sdk-go v1.35.24 + github.com/blang/semver v3.5.1+incompatible github.com/dnaeon/go-vcr v1.0.1 // indirect github.com/golang/mock v1.4.4 github.com/google/go-cmp v0.5.2 diff --git a/staging/src/k8s.io/legacy-cloud-providers/vsphere/nodemanager.go b/staging/src/k8s.io/legacy-cloud-providers/vsphere/nodemanager.go index 04c49a1aba3..791c9e204f7 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/vsphere/nodemanager.go +++ b/staging/src/k8s.io/legacy-cloud-providers/vsphere/nodemanager.go @@ -25,10 +25,12 @@ import ( "sync" "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/vim25/mo" + "k8s.io/klog/v2" + v1 "k8s.io/api/core/v1" k8stypes "k8s.io/apimachinery/pkg/types" cloudprovider "k8s.io/cloud-provider" - "k8s.io/klog/v2" "k8s.io/legacy-cloud-providers/vsphere/vclib" ) @@ -201,7 +203,21 @@ func (nm *NodeManager) DiscoverNode(node *v1.Node) error { if vm != nil { klog.V(4).Infof("Found node %s as vm=%+v in vc=%s and datacenter=%s", node.Name, vm, res.vc, res.datacenter.Name()) - + var vmObj mo.VirtualMachine + err := vm.Properties(ctx, vm.Reference(), []string{"config"}, &vmObj) + if err != nil || vmObj.Config == nil { + klog.Errorf("failed to retrieve guest vmconfig for node: %s Err: %v", node.Name, err) + } else { + klog.V(4).Infof("vm hardware version for node:%s is %s", node.Name, vmObj.Config.Version) + // vmconfig.Version returns vm hardware version as vmx-11, vmx-13, vmx-14, vmx-15 etc. + vmhardwaredeprecated, err := isGuestHardwareVersionDeprecated(vmObj.Config.Version) + if err != nil { + klog.Errorf("failed to check if vm hardware version is deprecated. VM Hardware Version: %s Err: %v", vmObj.Config.Version, err) + } + if vmhardwaredeprecated { + klog.Warningf("VM Hardware version: %s from node: %s is deprecated. Please consider upgrading virtual machine hardware version to vmx-15 or higher", vmObj.Config.Version, node.Name) + } + } // Get the node zone information nodeFd := node.ObjectMeta.Labels[v1.LabelFailureDomainBetaZone] nodeRegion := node.ObjectMeta.Labels[v1.LabelFailureDomainBetaRegion] diff --git a/staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/BUILD b/staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/BUILD index 22c3ece53be..be4f817f713 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/BUILD +++ b/staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/BUILD @@ -29,6 +29,7 @@ go_library( "//staging/src/k8s.io/client-go/pkg/version:go_default_library", "//staging/src/k8s.io/component-base/metrics:go_default_library", "//staging/src/k8s.io/component-base/metrics/legacyregistry:go_default_library", + "//vendor/github.com/blang/semver:go_default_library", "//vendor/github.com/vmware/govmomi/find:go_default_library", "//vendor/github.com/vmware/govmomi/object:go_default_library", "//vendor/github.com/vmware/govmomi/pbm:go_default_library", diff --git a/staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/connection.go b/staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/connection.go index d4ad68b024d..601d5bf9aea 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/connection.go +++ b/staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/connection.go @@ -29,8 +29,9 @@ import ( "github.com/vmware/govmomi/sts" "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/soap" - "k8s.io/client-go/pkg/version" "k8s.io/klog/v2" + + "k8s.io/client-go/pkg/version" ) // VSphereConnection contains information for connecting to vCenter @@ -84,7 +85,6 @@ func (connection *VSphereConnection) Connect(ctx context.Context) error { klog.Errorf("Failed to create govmomi client. err: %+v", err) return err } - setVCenterInfoMetric(connection) return nil } @@ -217,6 +217,13 @@ func (connection *VSphereConnection) NewClient(ctx context.Context) (*vim25.Clie connection.RoundTripperCount = RoundTripperDefaultCount } client.RoundTripper = vim25.Retry(client.RoundTripper, vim25.TemporaryNetworkError(int(connection.RoundTripperCount))) + vcdeprecated, err := isvCenterDeprecated(client.ServiceContent.About.Version, client.ServiceContent.About.ApiVersion) + if err != nil { + klog.Errorf("failed to check if vCenter version:%v and api version: %s is deprecated. Error: %v", client.ServiceContent.About.Version, client.ServiceContent.About.ApiVersion, err) + } + if vcdeprecated { + klog.Warningf("vCenter is deprecated. version: %s, api verson: %s Please consider upgrading vCenter and ESXi servers to 6.7u3 or higher", client.ServiceContent.About.Version, client.ServiceContent.About.ApiVersion) + } return client, nil } diff --git a/staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/constants.go b/staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/constants.go index 2209898c6f6..4aa7f5f4846 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/constants.go +++ b/staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/constants.go @@ -53,6 +53,7 @@ const ( ClusterComputeResourceType = "ClusterComputeResource" HostSystemType = "HostSystem" NameProperty = "name" + MinvCenterVersion = "6.7.0" ) // Test Constants diff --git a/staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/utils.go b/staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/utils.go index 86dd0ea6d58..ac19f9b8f1b 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/utils.go +++ b/staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/utils.go @@ -22,6 +22,7 @@ import ( "regexp" "strings" + "github.com/blang/semver" "github.com/vmware/govmomi/find" "github.com/vmware/govmomi/object" "github.com/vmware/govmomi/vim25/soap" @@ -199,3 +200,34 @@ func VerifyVolumePathsForVMDevices(vmDevices object.VirtualDeviceList, volPaths } } + +// isvCenterDeprecated takes vCenter version and vCenter API version as input and return true if vCenter is deprecated +func isvCenterDeprecated(vCenterVersion string, vCenerAPIVersion string) (bool, error) { + minvcversion, err := semver.New(MinvCenterVersion) + vcdeprecated := false + if err != nil { + return false, fmt.Errorf("failed to get parse vCenter version: %s. err: %+v", MinvCenterVersion, err) + } else { + vcversion, err := semver.New(vCenterVersion) + if err != nil { + return false, fmt.Errorf("failed to parse vCenter version: %s. err: %+v", vCenterVersion, err) + } else { + result := vcversion.Compare(*minvcversion) + if result == -1 { + // vcversion is less than minvcversion + vcdeprecated = true + } else if result == 0 { + // vcversion is equal to minvcversion + // check patch version + vcapiversion, err := semver.ParseTolerant(vCenerAPIVersion) + if err != nil { + return false, fmt.Errorf("failed to parse vCenter api version: %s. err: %+v", vCenerAPIVersion, err) + } + if vcapiversion.Patch < 3 { + vcdeprecated = true + } + } + } + } + return vcdeprecated, nil +} diff --git a/staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/utils_test.go b/staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/utils_test.go index 436055cf172..b955d45e59a 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/utils_test.go +++ b/staging/src/k8s.io/legacy-cloud-providers/vsphere/vclib/utils_test.go @@ -69,3 +69,73 @@ func TestUtils(t *testing.T) { t.Errorf("unexpected error: %s", err) } } + +func TestIsvCenter70update1Deprecated(t *testing.T) { + vcdeprecated, err := isvCenterDeprecated("7.0.1", "7.0.1.1") + if err != nil { + t.Fatal(err) + } + if vcdeprecated { + t.Fatal("vSphere 7.0 update1 should not be deprecated") + } +} + +func TestIsvCenter70Deprecated(t *testing.T) { + vcdeprecated, err := isvCenterDeprecated("7.0.0", "7.0.0.0") + if err != nil { + t.Fatal(err) + } + if vcdeprecated { + t.Fatal("vSphere 7.0 should not be deprecated") + } +} + +func TestIsvCenter67u3Deprecated(t *testing.T) { + vcdeprecated, err := isvCenterDeprecated("6.7.0", "6.7.3") + if err != nil { + t.Fatal(err) + } + if vcdeprecated { + t.Fatal("vSphere 67u3 should not be deprecated") + } +} + +func TestIsvCenter67Deprecated(t *testing.T) { + vcdeprecated, err := isvCenterDeprecated("6.7.0", "6.7") + if err != nil { + t.Fatal(err) + } + if !vcdeprecated { + t.Fatal("vSphere 6.7 should be deprecated") + } +} + +func TestIsvCenter67u2Deprecated(t *testing.T) { + vcdeprecated, err := isvCenterDeprecated("6.7.0", "6.7.2") + if err != nil { + t.Fatal(err) + } + if !vcdeprecated { + t.Fatal("vSphere 6.7 update 2 should be deprecated") + } +} + +func TestIsvCenter67u1Deprecated(t *testing.T) { + vcdeprecated, err := isvCenterDeprecated("6.7.0", "6.7.1") + if err != nil { + t.Fatal(err) + } + if !vcdeprecated { + t.Fatal("vSphere 6.7 update 1 should be deprecated") + } +} + +func TestIsvCenter65Deprecated(t *testing.T) { + vcdeprecated, err := isvCenterDeprecated("6.5.0", "6.5") + if err != nil { + t.Fatal(err) + } + if !vcdeprecated { + t.Fatal("vSphere 6.5 should be deprecated") + } +} diff --git a/staging/src/k8s.io/legacy-cloud-providers/vsphere/vsphere.go b/staging/src/k8s.io/legacy-cloud-providers/vsphere/vsphere.go index 83337adc7c2..75b6164c2c7 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/vsphere/vsphere.go +++ b/staging/src/k8s.io/legacy-cloud-providers/vsphere/vsphere.go @@ -411,6 +411,9 @@ func populateVsphereInstanceMap(cfg *VSphereConfig) (map[string]*VSphereInstance klog.Error(msg) return nil, errors.New(msg) } + if len(cfg.VirtualCenter) > 1 { + klog.Warning("Multi vCenter support is deprecated. vSphere CSI Driver does not support Kubernetes nodes spread across multiple vCenter servers. Please consider moving all Kubernetes nodes to single vCenter server") + } for vcServer, vcConfig := range cfg.VirtualCenter { klog.V(4).Infof("Initializing vc server %s", vcServer) diff --git a/staging/src/k8s.io/legacy-cloud-providers/vsphere/vsphere_util.go b/staging/src/k8s.io/legacy-cloud-providers/vsphere/vsphere_util.go index c0d474ab557..0b778a6a7cc 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/vsphere/vsphere_util.go +++ b/staging/src/k8s.io/legacy-cloud-providers/vsphere/vsphere_util.go @@ -25,6 +25,7 @@ import ( "math/rand" "os" "path/filepath" + "strconv" "strings" "sync" "time" @@ -768,6 +769,21 @@ func IsUUIDSupportedNode(node *v1.Node) (bool, error) { return false, nil } +func isGuestHardwareVersionDeprecated(vmHardwareversion string) (bool, error) { + vmHardwareDeprecated := false + // vmconfig.Version returns vm hardware version as vmx-11, vmx-13, vmx-14, vmx-15 etc. + version := strings.Trim(vmHardwareversion, "vmx-") + value, err := strconv.ParseInt(version, 0, 64) + if err != nil { + return false, fmt.Errorf("failed to parse vm hardware version: %v Err: %v", version, err) + } else { + if value < 15 { + vmHardwareDeprecated = true + } + } + return vmHardwareDeprecated, nil +} + func GetNodeUUID(node *v1.Node) (string, error) { oldNode, err := IsUUIDSupportedNode(node) if err != nil { diff --git a/staging/src/k8s.io/legacy-cloud-providers/vsphere/vsphere_util_test.go b/staging/src/k8s.io/legacy-cloud-providers/vsphere/vsphere_util_test.go index 3ddb478825d..18fec5c4121 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/vsphere/vsphere_util_test.go +++ b/staging/src/k8s.io/legacy-cloud-providers/vsphere/vsphere_util_test.go @@ -72,3 +72,63 @@ func TestGetPathFromFileNotFound(t *testing.T) { t.Errorf("expected err when calling getPathFromFileNotFound with nil err") } } + +func TestVMX15Deprecated(t *testing.T) { + vmhardwaredeprecated, err := isGuestHardwareVersionDeprecated("vmx-15") + if err != nil { + t.Fatal(err) + } + if vmhardwaredeprecated { + t.Fatal("vmx-15 should not be deprecated") + } +} + +func TestVMX14Deprecated(t *testing.T) { + vmhardwaredeprecated, err := isGuestHardwareVersionDeprecated("vmx-14") + if err != nil { + t.Fatal(err) + } + if !vmhardwaredeprecated { + t.Fatal("vmx-14 should be deprecated") + } +} + +func TestVMX13Deprecated(t *testing.T) { + vmhardwaredeprecated, err := isGuestHardwareVersionDeprecated("vmx-13") + if err != nil { + t.Fatal(err) + } + if !vmhardwaredeprecated { + t.Fatal("vmx-13 should be deprecated") + } +} + +func TestVMX11Deprecated(t *testing.T) { + vmhardwaredeprecated, err := isGuestHardwareVersionDeprecated("vmx-11") + if err != nil { + t.Fatal(err) + } + if !vmhardwaredeprecated { + t.Fatal("vmx-11 should be deprecated") + } +} + +func TestVMX17Deprecated(t *testing.T) { + vmhardwaredeprecated, err := isGuestHardwareVersionDeprecated("vmx-17") + if err != nil { + t.Fatal(err) + } + if vmhardwaredeprecated { + t.Fatal("vmx-17 should not be deprecated") + } +} + +func TestVMX18Deprecated(t *testing.T) { + vmhardwaredeprecated, err := isGuestHardwareVersionDeprecated("vmx-18") + if err != nil { + t.Fatal(err) + } + if vmhardwaredeprecated { + t.Fatal("vmx-18 should not be deprecated") + } +}