Merge pull request #120101 from lowang-bh/Hotfix

fix: concurrent map writes in e2e test
This commit is contained in:
Kubernetes Prow Robot 2023-08-28 23:19:20 -07:00 committed by GitHub
commit 27c9d32d46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 15 deletions

View File

@ -51,7 +51,7 @@ func bootstrapOnce(f *framework.Framework) {
if err != nil { if err != nil {
framework.Failf("Failed to get nodes: %v", err) framework.Failf("Failed to get nodes: %v", err)
} }
TestContext = Context{NodeMapper: &NodeMapper{}, VSphereInstances: vsphereInstances} TestContext = Context{NodeMapper: NewNodeMapper(), VSphereInstances: vsphereInstances}
// 3. Get Node to VSphere mapping // 3. Get Node to VSphere mapping
err = TestContext.NodeMapper.GenerateNodeMap(vsphereInstances, *nodeList) err = TestContext.NodeMapper.GenerateNodeMap(vsphereInstances, *nodeList)
if err != nil { if err != nil {

View File

@ -36,6 +36,9 @@ import (
// NodeMapper contains information to generate nameToNodeInfo and vcToZoneDatastore maps // NodeMapper contains information to generate nameToNodeInfo and vcToZoneDatastore maps
type NodeMapper struct { type NodeMapper struct {
nodeInfoRWLock *sync.RWMutex
nameToNodeInfo map[string]*NodeInfo
vcToZoneDatastoresMap map[string](map[string][]string)
} }
// NodeInfo contains information about vcenter nodes // NodeInfo contains information about vcenter nodes
@ -54,10 +57,14 @@ const (
hostSystemType = "HostSystem" hostSystemType = "HostSystem"
) )
var ( // NewNodeMapper returns a new NodeMapper
nameToNodeInfo = make(map[string]*NodeInfo) func NewNodeMapper() *NodeMapper {
vcToZoneDatastoresMap = make(map[string](map[string][]string)) return &NodeMapper{
) nodeInfoRWLock: &sync.RWMutex{},
nameToNodeInfo: make(map[string]*NodeInfo),
vcToZoneDatastoresMap: make(map[string](map[string][]string)),
}
}
// GenerateNodeMap populates node name to node info map // GenerateNodeMap populates node name to node info map
func (nm *NodeMapper) GenerateNodeMap(vSphereInstances map[string]*VSphere, nodeList v1.NodeList) error { func (nm *NodeMapper) GenerateNodeMap(vSphereInstances map[string]*VSphere, nodeList v1.NodeList) error {
@ -108,6 +115,7 @@ func (nm *NodeMapper) GenerateNodeMap(vSphereInstances map[string]*VSphere, node
for _, node := range nodeList.Items { for _, node := range nodeList.Items {
n := node n := node
wg.Add(1)
go func() { go func() {
nodeUUID := getUUIDFromProviderID(n.Spec.ProviderID) nodeUUID := getUUIDFromProviderID(n.Spec.ProviderID)
framework.Logf("Searching for node with UUID: %s", nodeUUID) framework.Logf("Searching for node with UUID: %s", nodeUUID)
@ -132,11 +140,10 @@ func (nm *NodeMapper) GenerateNodeMap(vSphereInstances map[string]*VSphere, node
} }
wg.Done() wg.Done()
}() }()
wg.Add(1)
} }
wg.Wait() wg.Wait()
if len(nameToNodeInfo) != len(nodeList.Items) { if len(nm.nameToNodeInfo) != len(nodeList.Items) {
return errors.New("all nodes not mapped to respective vSphere") return errors.New("all nodes not mapped to respective vSphere")
} }
return nil return nil
@ -220,7 +227,7 @@ func (nm *NodeMapper) GenerateZoneToDatastoreMap() error {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
// 3. Populate vcToZoneHostsMap and vcToHostDatastoresMap // 3. Populate vcToZoneHostsMap and vcToHostDatastoresMap
for _, nodeInfo := range nameToNodeInfo { for _, nodeInfo := range nm.nameToNodeInfo {
vc := nodeInfo.VSphere.Config.Hostname vc := nodeInfo.VSphere.Config.Hostname
host := nodeInfo.HostSystemRef.Value host := nodeInfo.HostSystemRef.Value
for _, zone := range nodeInfo.Zones { for _, zone := range nodeInfo.Zones {
@ -247,13 +254,13 @@ func (nm *NodeMapper) GenerateZoneToDatastoreMap() error {
for vc, zoneToHostsMap := range vcToZoneHostsMap { for vc, zoneToHostsMap := range vcToZoneHostsMap {
for zone, hosts := range zoneToHostsMap { for zone, hosts := range zoneToHostsMap {
commonDatastores := retrieveCommonDatastoresAmongHosts(hosts, vcToHostDatastoresMap[vc]) commonDatastores := retrieveCommonDatastoresAmongHosts(hosts, vcToHostDatastoresMap[vc])
if vcToZoneDatastoresMap[vc] == nil { if nm.vcToZoneDatastoresMap[vc] == nil {
vcToZoneDatastoresMap[vc] = make(map[string][]string) nm.vcToZoneDatastoresMap[vc] = make(map[string][]string)
} }
vcToZoneDatastoresMap[vc][zone] = commonDatastores nm.vcToZoneDatastoresMap[vc][zone] = commonDatastores
} }
} }
framework.Logf("Zone to datastores map : %+v", vcToZoneDatastoresMap) framework.Logf("Zone to datastores map : %+v", nm.vcToZoneDatastoresMap)
return nil return nil
} }
@ -277,15 +284,21 @@ func retrieveCommonDatastoresAmongHosts(hosts []string, hostToDatastoresMap map[
// GetDatastoresInZone returns all the datastores in the specified zone // GetDatastoresInZone returns all the datastores in the specified zone
func (nm *NodeMapper) GetDatastoresInZone(vc string, zone string) []string { func (nm *NodeMapper) GetDatastoresInZone(vc string, zone string) []string {
return vcToZoneDatastoresMap[vc][zone] nm.nodeInfoRWLock.RLock()
defer nm.nodeInfoRWLock.RUnlock()
return nm.vcToZoneDatastoresMap[vc][zone]
} }
// GetNodeInfo returns NodeInfo for given nodeName // GetNodeInfo returns NodeInfo for given nodeName
func (nm *NodeMapper) GetNodeInfo(nodeName string) *NodeInfo { func (nm *NodeMapper) GetNodeInfo(nodeName string) *NodeInfo {
return nameToNodeInfo[nodeName] nm.nodeInfoRWLock.RLock()
defer nm.nodeInfoRWLock.RUnlock()
return nm.nameToNodeInfo[nodeName]
} }
// SetNodeInfo sets NodeInfo for given nodeName. This function is not thread safe. Users need to handle concurrency. // SetNodeInfo sets NodeInfo for given nodeName. This function is not thread safe. Users need to handle concurrency.
func (nm *NodeMapper) SetNodeInfo(nodeName string, nodeInfo *NodeInfo) { func (nm *NodeMapper) SetNodeInfo(nodeName string, nodeInfo *NodeInfo) {
nameToNodeInfo[nodeName] = nodeInfo nm.nodeInfoRWLock.Lock()
defer nm.nodeInfoRWLock.Unlock()
nm.nameToNodeInfo[nodeName] = nodeInfo
} }