You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by ra...@apache.org on 2020/11/05 19:17:28 UTC

[trafficcontrol] branch master updated: fixed peer polling to include ipv4 and ipv6 correctly (#5239)

This is an automated email from the ASF dual-hosted git repository.

rawlin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git


The following commit(s) were added to refs/heads/master by this push:
     new 784e6fa  fixed peer polling to include ipv4 and ipv6 correctly (#5239)
784e6fa is described below

commit 784e6fa7d8957e20d936a717b6f1c46280bba62a
Author: mattjackson220 <33...@users.noreply.github.com>
AuthorDate: Thu Nov 5 12:17:14 2020 -0700

    fixed peer polling to include ipv4 and ipv6 correctly (#5239)
    
    * fixed peer polling to include ipv4 and ipv6 correctly
    
    * fixed changelog after rebase
---
 CHANGELOG.md                                  |   1 +
 traffic_monitor/manager/statecombiner.go      |  38 ++++---
 traffic_monitor/manager/statecombiner_test.go | 156 ++++++++++++++++++++++++++
 3 files changed, 177 insertions(+), 18 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 24e1829..396b005 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -122,6 +122,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
 - Fixed an issue where partial upgrades of the database would occasionally fail to apply 2020081108261100_add_server_ip_profile_trigger.
 - Fixed #5197 - Allows users to assign topology-based DS to ORG servers [Related Github issue](https://github.com/apache/trafficcontrol/issues/5197)
 - Fixed #5161 - Fixes topology name character validation [Related Github issue](https://github.com/apache/trafficcontrol/issues/5161)
+- Fixed an issue with Traffic Monitor to fix peer polling to work as expected
 
 ### Changed
 - Changed some Traffic Ops Go Client methods to use `DeliveryServiceNullable` inputs and outputs.
diff --git a/traffic_monitor/manager/statecombiner.go b/traffic_monitor/manager/statecombiner.go
index dc743d0..6949139 100644
--- a/traffic_monitor/manager/statecombiner.go
+++ b/traffic_monitor/manager/statecombiner.go
@@ -65,18 +65,25 @@ func StartStateCombiner(events health.ThreadsafeEvents, peerStates peer.CRStates
 	return combinedStates, combineState
 }
 
-func combineCacheState(cacheName tc.CacheName, localCacheState tc.IsAvailable, events health.ThreadsafeEvents, peerOptimistic bool, peerStates peer.CRStatesPeersThreadsafe, localStates tc.CRStates, combinedStates peer.CRStatesThreadsafe, overrideMap map[tc.CacheName]bool, toData todata.TOData) {
+func combineCacheState(
+	cacheName tc.CacheName,
+	localCacheState tc.IsAvailable,
+	events health.ThreadsafeEvents,
+	peerOptimistic bool,
+	peerStates peer.CRStatesPeersThreadsafe,
+	combinedStates peer.CRStatesThreadsafe,
+	overrideMap map[tc.CacheName]bool,
+	toData todata.TOData,
+) {
+
 	overrideCondition := ""
-	available := false
-	ipv4Available := false
-	ipv6Available := false
+	available := localCacheState.Ipv4Available || localCacheState.Ipv6Available
+	ipv4Available := localCacheState.Ipv4Available
+	ipv6Available := localCacheState.Ipv6Available
 	override := overrideMap[cacheName]
 
-	if localCacheState.IsAvailable {
-		available = true // we don't care about the peers, we got a "good one", and we're optimistic
-		ipv4Available = localCacheState.Ipv4Available
-		ipv6Available = localCacheState.Ipv6Available
-
+	if localCacheState.Ipv4Available && localCacheState.Ipv6Available {
+		// we don't care about the peers, we got a "good one", and we're optimistic
 		if override {
 			overrideCondition = "cleared; healthy locally"
 			overrideMap[cacheName] = false
@@ -108,8 +115,8 @@ func combineCacheState(cacheName tc.CacheName, localCacheState tc.IsAvailable, e
 
 			if len(onlineOnPeers) > 0 {
 				available = true
-				ipv4Available = len(ipv4OnlineOnPeers) > 0
-				ipv6Available = len(ipv6OnlineOnPeers) > 0
+				ipv4Available = ipv4Available || len(ipv4OnlineOnPeers) > 0 // optimistically accept true from local or peer
+				ipv6Available = ipv6Available || len(ipv6OnlineOnPeers) > 0 // optimistically accept true from local or peer
 
 				if !override {
 					overrideCondition = fmt.Sprintf("detected; healthy on (at least) %s", strings.Join(onlineOnPeers, ", "))
@@ -134,13 +141,8 @@ func combineCacheState(cacheName tc.CacheName, localCacheState tc.IsAvailable, e
 func combineDSState(
 	deliveryServiceName tc.DeliveryServiceName,
 	localDeliveryService tc.CRStatesDeliveryService,
-	events health.ThreadsafeEvents,
-	peerOptimistic bool,
 	peerStates peer.CRStatesPeersThreadsafe,
-	localStates tc.CRStates,
 	combinedStates peer.CRStatesThreadsafe,
-	overrideMap map[tc.CacheName]bool,
-	toData todata.TOData,
 ) {
 	deliveryService := tc.CRStatesDeliveryService{IsAvailable: false, DisabledLocations: []tc.CacheGroupName{}} // important to initialize DisabledLocations, so JSON is `[]` not `null`
 	if localDeliveryService.IsAvailable {
@@ -199,11 +201,11 @@ func pruneCombinedCaches(combinedStates peer.CRStatesThreadsafe, localStates tc.
 
 func combineCrStates(events health.ThreadsafeEvents, peerOptimistic bool, peerStates peer.CRStatesPeersThreadsafe, localStates tc.CRStates, combinedStates peer.CRStatesThreadsafe, overrideMap map[tc.CacheName]bool, toData todata.TOData) {
 	for cacheName, localCacheState := range localStates.Caches { // localStates gets pruned when servers are disabled, it's the source of truth
-		combineCacheState(cacheName, localCacheState, events, peerOptimistic, peerStates, localStates, combinedStates, overrideMap, toData)
+		combineCacheState(cacheName, localCacheState, events, peerOptimistic, peerStates, combinedStates, overrideMap, toData)
 	}
 
 	for deliveryServiceName, localDeliveryService := range localStates.DeliveryService {
-		combineDSState(deliveryServiceName, localDeliveryService, events, peerOptimistic, peerStates, localStates, combinedStates, overrideMap, toData)
+		combineDSState(deliveryServiceName, localDeliveryService, peerStates, combinedStates)
 	}
 
 	pruneCombinedDSState(combinedStates, localStates, peerStates)
diff --git a/traffic_monitor/manager/statecombiner_test.go b/traffic_monitor/manager/statecombiner_test.go
new file mode 100644
index 0000000..3803d79
--- /dev/null
+++ b/traffic_monitor/manager/statecombiner_test.go
@@ -0,0 +1,156 @@
+package manager
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+import (
+	"github.com/apache/trafficcontrol/lib/go-tc"
+	"github.com/apache/trafficcontrol/traffic_monitor/health"
+	"github.com/apache/trafficcontrol/traffic_monitor/peer"
+	"github.com/apache/trafficcontrol/traffic_monitor/todata"
+	"math/rand"
+	"testing"
+	"time"
+)
+
+func TestCombineCacheState(t *testing.T) {
+	cacheName := tc.CacheName("testCache")
+	localCacheStates := []tc.IsAvailable{
+		tc.IsAvailable{
+			IsAvailable:   true,
+			Ipv4Available: true,
+			Ipv6Available: true,
+		},
+		tc.IsAvailable{
+			IsAvailable:   true,
+			Ipv4Available: false,
+			Ipv6Available: true,
+		},
+		tc.IsAvailable{
+			IsAvailable:   true,
+			Ipv4Available: true,
+			Ipv6Available: false,
+		},
+		tc.IsAvailable{
+			IsAvailable:   false,
+			Ipv4Available: false,
+			Ipv6Available: false,
+		},
+	}
+	events := health.NewThreadsafeEvents(1)
+	peerOptimistic := true
+	peerStates := peer.NewCRStatesPeersThreadsafe(1)
+	peerStates.SetTimeout(time.Duration(rand.Int63()))
+	peerResult := peer.Result{
+		ID:        tc.TrafficMonitorName("TestTM-01"),
+		Available: true,
+		PeerStates: tc.CRStates{
+			Caches: map[tc.CacheName]tc.IsAvailable{
+				tc.CacheName(cacheName): tc.IsAvailable{
+					IsAvailable:   true,
+					Ipv4Available: true,
+					Ipv6Available: true,
+				},
+			},
+		},
+		Time: time.Now(),
+	}
+	peerStates.Set(peerResult)
+	peerSet := map[tc.TrafficMonitorName]struct{}{
+		tc.TrafficMonitorName("TestTM-01"): struct{}{},
+	}
+	peerStates.SetPeers(peerSet)
+	peerStates.SetTimeout(time.Duration(rand.Int()))
+
+	combinedStates := peer.NewCRStatesThreadsafe()
+	overrideMap := map[tc.CacheName]bool{}
+	overrideMap[cacheName] = false
+	toData := todata.TOData{}
+	toData.ServerTypes = map[tc.CacheName]tc.CacheType{
+		cacheName: tc.CacheTypeEdge,
+	}
+
+	for _, localCacheState := range localCacheStates {
+		combineCacheState(cacheName, localCacheState, events, peerOptimistic, peerStates, combinedStates, overrideMap, toData)
+
+		if !combinedStates.Get().Caches[cacheName].IsAvailable {
+			t.Fatalf("cache is unavailable and should be available")
+		}
+		if !combinedStates.Get().Caches[cacheName].Ipv4Available {
+			t.Fatalf("cache IPv4 is unavailable and should be available")
+		}
+		if !combinedStates.Get().Caches[cacheName].Ipv6Available {
+			t.Fatalf("cache IPv6 is unavailable and should be available")
+		}
+	}
+}
+
+func TestCombineCacheStateCacheDown(t *testing.T) {
+	cacheName := tc.CacheName("testCache")
+	localCacheState := tc.IsAvailable{
+		IsAvailable:   false,
+		Ipv4Available: false,
+		Ipv6Available: false,
+	}
+
+	events := health.NewThreadsafeEvents(1)
+	peerOptimistic := true
+	peerStates := peer.NewCRStatesPeersThreadsafe(1)
+	peerStates.SetTimeout(time.Duration(rand.Int63()))
+	peerResult := peer.Result{
+		ID:        tc.TrafficMonitorName("TestTM-01"),
+		Available: true,
+		PeerStates: tc.CRStates{
+			Caches: map[tc.CacheName]tc.IsAvailable{
+				tc.CacheName(cacheName): tc.IsAvailable{
+					IsAvailable:   true,
+					Ipv4Available: false,
+					Ipv6Available: true,
+				},
+			},
+		},
+		Time: time.Now(),
+	}
+	peerStates.Set(peerResult)
+	peerSet := map[tc.TrafficMonitorName]struct{}{
+		tc.TrafficMonitorName("TestTM-01"): struct{}{},
+	}
+	peerStates.SetPeers(peerSet)
+	peerStates.SetTimeout(time.Duration(rand.Int()))
+
+	combinedStates := peer.NewCRStatesThreadsafe()
+	overrideMap := map[tc.CacheName]bool{}
+	overrideMap[cacheName] = false
+	toData := todata.TOData{}
+	toData.ServerTypes = map[tc.CacheName]tc.CacheType{
+		cacheName: tc.CacheTypeEdge,
+	}
+
+	combineCacheState(cacheName, localCacheState, events, peerOptimistic, peerStates, combinedStates, overrideMap, toData)
+
+	if !combinedStates.Get().Caches[cacheName].IsAvailable {
+		t.Fatalf("cache is unavailable and should be available")
+	}
+	if combinedStates.Get().Caches[cacheName].Ipv4Available {
+		t.Fatalf("cache IPv4 is available and should be unavailable")
+	}
+	if !combinedStates.Get().Caches[cacheName].Ipv6Available {
+		t.Fatalf("cache IPv6 is unavailable and should be available")
+	}
+}