Skip to content

Commit

Permalink
Merge pull request #389 from gwang550/gw-dual-stack-support
Browse files Browse the repository at this point in the history
fix dual stack is not supported
  • Loading branch information
k8s-ci-robot authored Oct 28, 2020
2 parents 22e8563 + 13c8597 commit fd46ff9
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 5 deletions.
11 changes: 11 additions & 0 deletions pkg/cloudprovider/vsphere/cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package vsphere

import (
"errors"
"io"
"io/ioutil"
"os"
Expand Down Expand Up @@ -198,6 +199,16 @@ func buildVSphereFromConfig(cfg *ccfg.CPIConfig, lbcfg *lcfg.LBConfig) (*VSphere
lb = nil
}

// add alpha dual stack feature
for tenant := range cfg.VirtualCenter {
if len(cfg.VirtualCenter[tenant].IPFamilyPriority) > 1 {
if _, ok := os.LookupEnv("ENABLE_ALPHA_DUAL_STACK"); !ok {
klog.Errorf("number of ip family provided for VCenter %s is 2, ENABLE_ALPHA_DUAL_STACK env var is not set", tenant)
return nil, errors.New("two IP families provided, but dual stack feature is not enabled")
}
}
}

vs := VSphere{
cfg: cfg,
cfgLB: lbcfg,
Expand Down
13 changes: 8 additions & 5 deletions pkg/cloudprovider/vsphere/nodemanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,9 @@ func (nm *NodeManager) DiscoverNode(nodeID string, searchBy cm.FindVM) error {
// Must break out of loop in the event of ipv6,ipv4 where the NIC does
// contain a valid IPv6 and IPV4 address
for _, family := range ipFamily {
foundInternal = false
foundExternal = false

ips := returnIPsFromSpecificFamily(family, v.IpAddress)

for _, ip := range ips {
Expand Down Expand Up @@ -330,7 +333,7 @@ func (nm *NodeManager) DiscoverNode(nodeID string, searchBy cm.FindVM) error {
} else if !foundInternal && foundExternal {
klog.Warning("External address found, but internal address not found. Returning what addresses were discovered.")
}
break
continue
}

// Neither internal or external addresses were found. This defaults to the old
Expand All @@ -353,11 +356,11 @@ func (nm *NodeManager) DiscoverNode(nodeID string, searchBy cm.FindVM) error {
foundExternal = true
break
}
}
}

if !foundInternal && !foundExternal {
return fmt.Errorf("unable to find suitable IP address for node %s with IP family %s", nodeID, ipFamily)
if !foundInternal && !foundExternal {
return fmt.Errorf("unable to find suitable IP address for node %s with IP family %s", nodeID, ipFamily)
}
}
}

klog.V(2).Infof("Found node %s as vm=%+v in vc=%s and datacenter=%s",
Expand Down
74 changes: 74 additions & 0 deletions pkg/cloudprovider/vsphere/nodemanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,80 @@ func TestDiscoverNodeByName(t *testing.T) {
}
}

func TestAlphaDualStack(t *testing.T) {
cfg, ok := configFromEnvOrSim(true)
defer ok()

connMgr := cm.NewConnectionManager(cfg, nil, nil)
defer connMgr.Logout()

ipv4Ip := "10.0.0.1"
ipv6Ip := "fd01:0:101:2609:bdd2:ee20:7bd7:5836"

nm := newNodeManager(nil, connMgr)

vm := simulator.Map.Any("VirtualMachine").(*simulator.VirtualMachine)
vm.Guest.HostName = strings.ToLower(vm.Name) // simulator.SearchIndex.FindByDnsName matches against the guest.hostName property
vm.Guest.Net = []vimtypes.GuestNicInfo{
{
Network: "foo-bar",
IpAddress: []string{ipv4Ip, ipv6Ip},
},
}

err := connMgr.Connect(context.Background(), connMgr.VsphereInstanceMap[cfg.Global.VCenterIP])
if err != nil {
t.Errorf("Failed to Connect to vSphere: %s", err)
}

// set config for ip for vc to ipv4, ipv6 (dual-stack)
vcInstance := nm.connectionManager.VsphereInstanceMap[cfg.Global.VCenterIP]
vcInstance.Cfg.IPFamilyPriority = []string{"ipv6", "ipv4"}

name := vm.Name
UUID := vm.Config.Uuid
k8sUUID := ConvertK8sUUIDtoNormal(UUID)

node := &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Status: v1.NodeStatus{
NodeInfo: v1.NodeSystemInfo{
SystemUUID: k8sUUID,
},
},
}

// get node registered so node can be exported
nm.RegisterNode(node)
err = nm.DiscoverNode(name, cm.FindVMByName)
if err != nil {
t.Errorf("Failed DiscoverNode: %s", err)
}

nodeList := make([]*pb.Node, 0)
_ = nm.ExportNodes("", "", &nodeList)

ips := nodeList[0].Addresses

ipv4Ips := returnIPsFromSpecificFamily(vcfg.IPv4Family, ips)
size := len(ipv4Ips)
if size != 1 {
t.Errorf("Should only return single IPv4 address. expected: 1, actual: %d", size)
} else if !strings.EqualFold(ipv4Ips[0], ipv4Ip) {
t.Errorf("IPv6 does not match. expected: %s, actual: %s", ipv4Ip, ipv4Ips[0])
}

ipv6Ips := returnIPsFromSpecificFamily(vcfg.IPv6Family, ips)
size = len(ipv6Ips)
if size != 1 {
t.Errorf("Should only return single IPv6 address. expected: 1, actual: %d", size)
} else if !strings.EqualFold(ipv6Ips[0], ipv6Ip) {
t.Errorf("IPv6 does not match. expected: fd01:0:101:2609:bdd2:ee20:7bd7:5836, actual: %s", ipv6Ips[0])
}
}

func TestExport(t *testing.T) {
cfg, ok := configFromEnvOrSim(true)
defer ok()
Expand Down
94 changes: 94 additions & 0 deletions pkg/cloudprovider/vsphere/vsphere_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"crypto/tls"
"log"
"os"
"testing"

lookup "github.com/vmware/govmomi/lookup/simulator"
Expand Down Expand Up @@ -216,6 +217,99 @@ func TestVSphereLoginByToken(t *testing.T) {
vcInstance.Conn.Logout(ctx)
}

func TestAlphaDualStackConfig(t *testing.T) {
var testCases = []struct {
testName string
conf string
enableDualStackFeature bool
expectedError string
}{
{
testName: "Verifying dual stack env var required when providing two ip families",
conf: `[Global]
user = user
password = password
datacenters = us-west
[VirtualCenter "0.0.0.0"]
user = user
password = password
ip-family = ipv6,ipv4
`,
enableDualStackFeature: false,
expectedError: "two IP families provided, but dual stack feature is not enabled",
},
{
testName: "Verifying dual stack env var existing when providing two ip families",
conf: `[Global]
user = user
password = password
datacenters = us-west
[VirtualCenter "0.0.0.0"]
user = user
password = password
ip-family = ipv6,ipv4
`,
enableDualStackFeature: true,
expectedError: "",
},
{
testName: "Dual stack env var not required when providing single ip family",
conf: `[Global]
user = user
password = password
datacenters = us-west
[VirtualCenter "0.0.0.0"]
user = user
password = password
ip-family = ipv6
`,
enableDualStackFeature: false,
expectedError: "",
},
}
for _, testcase := range testCases {
t.Run(testcase.testName, func(t *testing.T) {
cfg, err := ccfg.ReadCPIConfig([]byte(testcase.conf))
if err != nil {
if testcase.expectedError != "" {
if err.Error() != testcase.expectedError {
t.Fatalf("readConfig: expected err: %s, received err: %s", testcase.expectedError, err)
}
} else {
t.Fatalf("readConfig: unexpected error returned: %v", err)
}
}

if testcase.enableDualStackFeature {
err := os.Setenv("ENABLE_ALPHA_DUAL_STACK", "1")
if err != nil {
t.Fatalf("Received error %s when setting env var ENABLE_ALPHA_DUAL_STACK", err)
}
defer func() {
err := os.Unsetenv("ENABLE_ALPHA_DUAL_STACK")
if err != nil {
t.Fatalf("Received error %s when unsetting env var", err)
}
}()
}

_, err = buildVSphereFromConfig(cfg, nil)
if err != nil {
if testcase.expectedError != "" {
if err.Error() != testcase.expectedError {
t.Fatalf("buildVSphereFromConfig: expected err: %s, receiver err: %s", testcase.expectedError, err)
}
} else {
t.Fatalf("buildVSphereFromConfig: Should succeed when a valid config is provided: %v", err)
}
}
})
}
}

func TestSecretVSphereConfig(t *testing.T) {
var vs *VSphere
var (
Expand Down

0 comments on commit fd46ff9

Please sign in to comment.