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 2021/01/08 20:18:33 UTC

[trafficcontrol] branch master updated: Limit which Topology parent CacheGroup Servers to check for updates (#5416)

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 ba7bed0  Limit which Topology parent CacheGroup Servers to check for updates (#5416)
ba7bed0 is described below

commit ba7bed0ee52c6583dfd467b0cd1dadf58af6ace7
Author: Zach Hoffman <zr...@apache.org>
AuthorDate: Fri Jan 8 13:18:20 2021 -0700

    Limit which Topology parent CacheGroup Servers to check for updates (#5416)
    
    * Only check the update status of EDGE_LOC and MID_LOC-type parent
    CacheGroups
    
    * Only check the update status of ONLINE or REPORTED Topology parent
    CacheGroup Servers
    
    * Fix some whitespace
    
    * Use the API v3 GET servers/{host_name}/update_status handler for API v1
    and API v2
    
    * Add an ORG server to multiOriginCachegroup for cdn2
    
    * Add an Origin Server Profile for CDN 2
    
    * Add denver-mso-org-02 to list of expected servers for topology
    mso-topology
    
    * Only require that the CacheGroup type starts with EDGE and MID rather
    than needing to specifically be EDGE_LOC or MID_LOC
    
    * Check parent Cache Group status for ADMIN_DOWN caches
    
    * - Build CacheGroupEdgeTypeName const from EdgeTypePrefix
      - Build CacheGroupMidTypeName const from MidTypePrefix
      - Build CacheGroupOriginTypeName const from OriginTypeName
    
    * Use EdgeTypePrefix and MidTypePrefix to check for Cache Group type
    prefixes
---
 lib/go-tc/enum.go                                  |   6 +-
 traffic_ops/testing/api/v3/servers_test.go         |   1 +
 traffic_ops/testing/api/v3/tc-fixtures.json        |  72 +++++++++-
 traffic_ops/traffic_ops_golang/routing/routes.go   |   4 +-
 .../server/servers_update_status.go                | 147 +++++----------------
 5 files changed, 103 insertions(+), 127 deletions(-)

diff --git a/lib/go-tc/enum.go b/lib/go-tc/enum.go
index f0abc5b..0eb5b4a 100644
--- a/lib/go-tc/enum.go
+++ b/lib/go-tc/enum.go
@@ -83,9 +83,9 @@ const MidTypePrefix = "MID"
 const OriginTypeName = "ORG"
 
 const (
-	CacheGroupEdgeTypeName   = "EDGE_LOC"
-	CacheGroupMidTypeName    = "MID_LOC"
-	CacheGroupOriginTypeName = "ORG_LOC"
+	CacheGroupEdgeTypeName   = EdgeTypePrefix + "_LOC"
+	CacheGroupMidTypeName    = MidTypePrefix + "_LOC"
+	CacheGroupOriginTypeName = OriginTypeName + "_LOC"
 )
 
 const GlobalProfileName = "GLOBAL"
diff --git a/traffic_ops/testing/api/v3/servers_test.go b/traffic_ops/testing/api/v3/servers_test.go
index 67374a0..17d67e0 100644
--- a/traffic_ops/testing/api/v3/servers_test.go
+++ b/traffic_ops/testing/api/v3/servers_test.go
@@ -631,6 +631,7 @@ func GetTestServersQueryParameters(t *testing.T) {
 	params.Add("topology", topology)
 	expectedHostnames = map[string]bool{
 		originHostname:                   false,
+		"denver-mso-org-02":              false,
 		"edge1-cdn1-cg3":                 false,
 		"edge2-cdn1-cg3":                 false,
 		"atlanta-mid-16":                 false,
diff --git a/traffic_ops/testing/api/v3/tc-fixtures.json b/traffic_ops/testing/api/v3/tc-fixtures.json
index 7e8fd55..c371cd1 100644
--- a/traffic_ops/testing/api/v3/tc-fixtures.json
+++ b/traffic_ops/testing/api/v3/tc-fixtures.json
@@ -2186,6 +2186,13 @@
         },
         {
             "cdnName": "cdn2",
+            "description": "mso origin description",
+            "name": "MSO-CDN2",
+            "routing_disabled": false,
+            "type": "ORG_PROFILE"
+        },
+        {
+            "cdnName": "cdn2",
             "description": "cdn2 mid description",
             "name": "CDN2_MID",
             "routing_disabled": false,
@@ -3010,17 +3017,66 @@
             "physLocation": "Denver",
             "profile": "MSO",
             "rack": "RR 119.02",
-            "revalPending": false,
+            "revalPending": true,
             "routerHostName": "",
             "routerPortName": "",
             "status": "REPORTED",
             "tcpPort": 80,
             "type": "ORG",
-            "updPending": false,
+            "updPending": true,
             "xmppId": "denver-mso-org-01\\\\@ocdn.kabletown.net",
             "xmppPasswd": "X"
         },
         {
+            "cachegroup": "multiOriginCachegroup",
+            "cdnName": "cdn2",
+            "domainName": "ga.denver.kabletown.net",
+            "guid": null,
+            "hostName": "denver-mso-org-02",
+            "httpsPort": 443,
+            "iloIpAddress": "",
+            "iloIpGateway": "",
+            "iloIpNetmask": "",
+            "iloPassword": "",
+            "iloUsername": "",
+            "interfaces": [
+                {
+                    "ipAddresses": [
+                        {
+                            "address": "127.0.0.1/30",
+                            "gateway": "127.0.0.1",
+                            "serviceAddress": true
+                        },
+                        {
+                            "address": "2345:1234:12:8::20/64",
+                            "gateway": "2345:1234:12:8::20",
+                            "serviceAddress": false
+                        }
+                    ],
+                    "maxBandwidth": null,
+                    "monitor": true,
+                    "mtu": 9000,
+                    "name": "bond0"
+                }
+            ],
+            "mgmtIpAddress": "",
+            "mgmtIpGateway": "",
+            "mgmtIpNetmask": "",
+            "offlineReason": null,
+            "physLocation": "Denver",
+            "profile": "MSO-CDN2",
+            "rack": "RR 119.02",
+            "revalPending": true,
+            "routerHostName": "",
+            "routerPortName": "",
+            "status": "REPORTED",
+            "tcpPort": 80,
+            "type": "ORG",
+            "updPending": true,
+            "xmppId": "denver-mso-org-02\\\\@ocdn.kabletown.net",
+            "xmppPasswd": "X"
+        },
+        {
             "cachegroup": "cachegroup3",
             "cdnName": "cdn1",
             "domainName": "kabletown2.net",
@@ -4182,11 +4238,11 @@
             "physLocation": "Denver",
             "profile": "CDN2_MID",
             "rack": "RR 119.02",
-            "revalPending": false,
-            "status": "REPORTED",
+            "revalPending": true,
+            "status": "OFFLINE",
             "tcpPort": 80,
             "type": "MID",
-            "updPending": false
+            "updPending": true
         },
         {
             "cachegroup": "topology-mid-cg-06",
@@ -4639,6 +4695,12 @@
                 },
                 {
                     "cachegroup": "topology-mid-cg-07",
+                    "parents": [
+                        9
+                    ]
+                },
+                {
+                    "cachegroup": "multiOriginCachegroup",
                     "parents": []
                 }
             ]
diff --git a/traffic_ops/traffic_ops_golang/routing/routes.go b/traffic_ops/traffic_ops_golang/routing/routes.go
index 7e98b33..b42748c 100644
--- a/traffic_ops/traffic_ops_golang/routing/routes.go
+++ b/traffic_ops/traffic_ops_golang/routing/routes.go
@@ -696,7 +696,7 @@ func Routes(d ServerData) ([]Route, []RawRoute, http.Handler, error) {
 		//Server status
 		{api.Version{2, 0}, http.MethodPut, `servers/{id}/status$`, server.UpdateStatusHandler, auth.PrivLevelOperations, Authenticated, nil, 276663851, noPerlBypass},
 		{api.Version{2, 0}, http.MethodPost, `servers/{id}/queue_update$`, server.QueueUpdateHandler, auth.PrivLevelOperations, Authenticated, nil, 2189471, noPerlBypass},
-		{api.Version{2, 0}, http.MethodGet, `servers/{host_name}/update_status$`, server.GetServerUpdateStatusHandlerV2, auth.PrivLevelReadOnly, Authenticated, nil, 238451599, noPerlBypass},
+		{api.Version{2, 0}, http.MethodGet, `servers/{host_name}/update_status$`, server.GetServerUpdateStatusHandler, auth.PrivLevelReadOnly, Authenticated, nil, 238451599, noPerlBypass},
 		{api.Version{2, 0}, http.MethodPost, `servers/{id-or-name}/update$`, server.UpdateHandler, auth.PrivLevelOperations, Authenticated, nil, 14381323, noPerlBypass},
 
 		//Server: CRUD
@@ -1094,7 +1094,7 @@ func Routes(d ServerData) ([]Route, []RawRoute, http.Handler, error) {
 		//Server status
 		{api.Version{1, 1}, http.MethodPut, `servers/{id}/status$`, server.UpdateStatusHandler, auth.PrivLevelOperations, Authenticated, nil, 776663851, perlBypass},
 		{api.Version{1, 1}, http.MethodPost, `servers/{id}/queue_update$`, server.QueueUpdateHandler, auth.PrivLevelOperations, Authenticated, nil, 9189471, perlBypass},
-		{api.Version{1, 3}, http.MethodGet, `servers/{host_name}/update_status$`, server.GetServerUpdateStatusHandlerV1, auth.PrivLevelReadOnly, Authenticated, nil, 438451599, noPerlBypass},
+		{api.Version{1, 3}, http.MethodGet, `servers/{host_name}/update_status$`, server.GetServerUpdateStatusHandler, auth.PrivLevelReadOnly, Authenticated, nil, 438451599, noPerlBypass},
 
 		//Server: CRUD
 		{api.Version{1, 1}, http.MethodGet, `servers/?(\.json)?$`, server.Read, auth.PrivLevelReadOnly, Authenticated, nil, 1720959285, noPerlBypass},
diff --git a/traffic_ops/traffic_ops_golang/server/servers_update_status.go b/traffic_ops/traffic_ops_golang/server/servers_update_status.go
index 392d997..e0ca033 100644
--- a/traffic_ops/traffic_ops_golang/server/servers_update_status.go
+++ b/traffic_ops/traffic_ops_golang/server/servers_update_status.go
@@ -23,6 +23,8 @@ import (
 	"database/sql"
 	"net/http"
 
+	"github.com/lib/pq"
+
 	"github.com/apache/trafficcontrol/lib/go-log"
 	"github.com/apache/trafficcontrol/lib/go-tc"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
@@ -51,39 +53,44 @@ func getServerUpdateStatus(tx *sql.Tx, cfg *config.Config, hostName string) ([]t
 
 	selectQuery := `
 /* topology_ancestors finds the ancestor topology nodes of the topology node for
- * the cachegroup containing server $4.
+ * the cachegroup containing server $5.
  */
 WITH RECURSIVE topology_ancestors AS (
 /* This is the base case of the recursive CTE, the topology node for the
- * cachegroup containing server $4.
+ * cachegroup containing server $5.
  */
 	SELECT tcp.child parent, NULL cachegroup, s.id base_server_id
 	FROM "server" s
 	JOIN cachegroup c ON s.cachegroup = c.id
 	JOIN topology_cachegroup tc ON c."name" = tc.cachegroup
 	JOIN topology_cachegroup_parents tcp ON tc.id = tcp.child
-	WHERE s.host_name = $4
+	WHERE s.host_name = $5
 UNION ALL
 /* Find all direct topology parent nodes tc of a given topology ancestor ta. */
 	SELECT tcp.parent, tc.cachegroup, ta.base_server_id
 	FROM topology_ancestors ta, topology_cachegroup_parents tcp
 	JOIN topology_cachegroup tc ON tcp.parent = tc.id
+	JOIN cachegroup c ON tc.cachegroup = c."name"
+	JOIN "type" t ON c."type" = t.id
 	WHERE ta.parent = tcp.child
+	AND t."name" LIKE ANY($4::TEXT[])
 /* server_topology_ancestors is the set of every server whose cachegroup is an
  * ancestor topology node found by topology_ancestors.
  */
 ), server_topology_ancestors AS (
 SELECT s.id, s.cachegroup, s.cdn_id, s.upd_pending, s.reval_pending, s.status, ta.base_server_id
-FROM server s
-JOIN cachegroup c ON s.cachegroup = c.id
-JOIN topology_ancestors ta ON c."name" = ta.cachegroup
+	FROM server s
+	JOIN cachegroup c ON s.cachegroup = c.id
+	JOIN topology_ancestors ta ON c."name" = ta.cachegroup
+	JOIN status ON status.id = s.status
+	WHERE status.name = ANY($1::TEXT[])
 ), parentservers AS (
-	SELECT ps.id, ps.cachegroup, ps.cdn_id, ps.upd_pending, ps.reval_pending, ps.status
+SELECT ps.id, ps.cachegroup, ps.cdn_id, ps.upd_pending, ps.reval_pending, ps.status
 		FROM server ps
 	LEFT JOIN status AS pstatus ON pstatus.id = ps.status
-	WHERE pstatus.name != $1
+	WHERE pstatus.name = ANY($1::TEXT[])
 ), use_reval_pending AS (
-	SELECT value::BOOLEAN
+SELECT value::BOOLEAN
 	FROM parameter
 	WHERE name = $2
 	AND config_file = $3
@@ -97,16 +104,16 @@ SELECT
 	use_reval_pending.value,
 	s.upd_pending,
 	status.name AS status,
-		/* True if the cachegroup parent or any ancestor topology node has pending updates. */
-		TRUE IN (
-			SELECT sta.upd_pending FROM server_topology_ancestors sta WHERE sta.base_server_id = s.id
-			UNION SELECT COALESCE(BOOL_OR(ps.upd_pending), FALSE)
-		) AS parent_upd_pending,
-		/* True if the cachegroup parent or any ancestor topology node has pending revalidation. */
-		TRUE IN (
-			SELECT sta.reval_pending FROM server_topology_ancestors sta WHERE sta.base_server_id = s.id
-			UNION SELECT COALESCE(BOOL_OR(ps.reval_pending), FALSE)
-		) AS parent_reval_pending
+	/* True if the cachegroup parent or any ancestor topology node has pending updates. */
+	TRUE IN (
+		SELECT sta.upd_pending FROM server_topology_ancestors sta WHERE sta.base_server_id = s.id
+		UNION SELECT COALESCE(BOOL_OR(ps.upd_pending), FALSE)
+	) AS parent_upd_pending,
+	/* True if the cachegroup parent or any ancestor topology node has pending revalidation. */
+	TRUE IN (
+		SELECT sta.reval_pending FROM server_topology_ancestors sta WHERE sta.base_server_id = s.id
+		UNION SELECT COALESCE(BOOL_OR(ps.reval_pending), FALSE)
+	) AS parent_reval_pending
 	FROM use_reval_pending,
 		 server s
 LEFT JOIN status ON s.status = status.id
@@ -114,12 +121,14 @@ LEFT JOIN cachegroup cg ON s.cachegroup = cg.id
 LEFT JOIN type ON type.id = s.type
 LEFT JOIN parentservers ps ON ps.cachegroup = cg.parent_cachegroup_id
 	AND ps.cdn_id = s.cdn_id
-WHERE s.host_name = $4
+WHERE s.host_name = $5
 GROUP BY s.id, s.host_name, type.name, server_reval_pending, use_reval_pending.value, s.upd_pending, status.name
 ORDER BY s.id
 `
 
-	rows, err := tx.Query(selectQuery, tc.CacheStatusOffline, tc.UseRevalPendingParameterName, tc.GlobalConfigFileName, hostName)
+	cacheStatusesToCheck := []tc.CacheStatus{tc.CacheStatusOnline, tc.CacheStatusReported, tc.CacheStatusAdminDown}
+	cacheGroupTypes := []string{tc.EdgeTypePrefix + "%", tc.MidTypePrefix + "%"}
+	rows, err := tx.Query(selectQuery, pq.Array(cacheStatusesToCheck), tc.UseRevalPendingParameterName, tc.GlobalConfigFileName, pq.Array(cacheGroupTypes), hostName)
 	if err != nil {
 		log.Errorf("could not execute query: %s\n", err)
 		return nil, tc.DBError
@@ -137,99 +146,3 @@ ORDER BY s.id
 	}
 	return updateStatuses, nil
 }
-
-func GetServerUpdateStatusHandlerV2(w http.ResponseWriter, r *http.Request) {
-	GetServerUpdateStatusHandlerV1(w, r)
-}
-
-func GetServerUpdateStatusHandlerV1(w http.ResponseWriter, r *http.Request) {
-	inf, userErr, sysErr, errCode := api.NewInfo(r, []string{"host_name"}, nil)
-	if userErr != nil || sysErr != nil {
-		api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
-		return
-	}
-	defer inf.Close()
-
-	serverUpdateStatus, err := getServerUpdateStatusV1(inf.Tx.Tx, inf.Config, inf.Params["host_name"])
-	if err != nil {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, err)
-		return
-	}
-	api.WriteRespRaw(w, r, serverUpdateStatus)
-}
-
-// getServerUpdateStatusV1 supports /servers/all/update_status (believed to be used nowhere) in addition to /servers/{host_name}/update_status.
-func getServerUpdateStatusV1(tx *sql.Tx, cfg *config.Config, hostName string) ([]tc.ServerUpdateStatus, error) {
-	// language=SQL
-	baseSelectStatement := `
-WITH parentservers AS (
-	SELECT ps.id, ps.cachegroup, ps.cdn_id, ps.upd_pending, ps.reval_pending
-	FROM server ps
-	LEFT JOIN status AS pstatus ON pstatus.id = ps.status
-	WHERE pstatus.name != $1
-), use_reval_pending AS (
-	SELECT value::BOOLEAN
-	FROM parameter
-	WHERE name = $2
-	AND config_file = $3
-	UNION ALL SELECT FALSE FETCH FIRST 1 ROW ONLY
-)
-SELECT
-	s.id,
-	s.host_name,
-	type.name AS type,
-	(s.reval_pending::BOOLEAN) AS server_reval_pending,
-	use_reval_pending.value,
-	s.upd_pending,
-	status.name AS status,
-	COALESCE(BOOL_OR(ps.upd_pending), FALSE) AS parent_upd_pending,
-	COALESCE(BOOL_OR(ps.reval_pending), FALSE) AS parent_reval_pending
-	FROM use_reval_pending,
-		 server s
-LEFT JOIN status ON s.status = status.id
-LEFT JOIN cachegroup cg ON s.cachegroup = cg.id
-LEFT JOIN type ON type.id = s.type
-LEFT JOIN parentservers ps ON ps.cachegroup = cg.parent_cachegroup_id
-	AND ps.cdn_id = s.cdn_id
-	AND type.name = 'EDGE'
-` // remove the EDGE reference if other server types should have their parents processed
-
-	// language=SQL
-	groupBy := `
-GROUP BY s.id, s.host_name, type.name, server_reval_pending, use_reval_pending.value, s.upd_pending, status.name
-ORDER BY s.id
-`
-
-	updateStatuses := []tc.ServerUpdateStatus{}
-	var rows *sql.Rows
-	var err error
-	if hostName == "all" {
-		rows, err = tx.Query(baseSelectStatement+groupBy, tc.CacheStatusOffline, tc.UseRevalPendingParameterName, tc.GlobalConfigFileName)
-		if err != nil {
-			log.Errorf("could not execute select server update status query: %s\n", err)
-			return nil, tc.DBError
-		}
-	} else {
-		rows, err = tx.Query(baseSelectStatement+` WHERE s.host_name = $4`+groupBy, tc.CacheStatusOffline, tc.UseRevalPendingParameterName, tc.GlobalConfigFileName, hostName)
-		if err != nil {
-			log.Errorf("could not execute select server update status by hostname query: %s\n", err)
-			return nil, tc.DBError
-		}
-	}
-	defer rows.Close()
-
-	for rows.Next() {
-		var us tc.ServerUpdateStatus
-		var serverType string
-		if err := rows.Scan(&us.HostId, &us.HostName, &serverType, &us.RevalPending, &us.UseRevalPending, &us.UpdatePending, &us.Status, &us.ParentPending, &us.ParentRevalPending); err != nil {
-			log.Errorf("could not scan server update status: %s\n", err)
-			return nil, tc.DBError
-		}
-		if hostName == "all" { //if we want to return the parent data for servers when all is used remove this block
-			us.ParentRevalPending = false
-			us.ParentPending = false
-		}
-		updateStatuses = append(updateStatuses, us)
-	}
-	return updateStatuses, nil
-}