func getMonitoringServers()

in traffic_ops/traffic_ops_golang/monitoring/monitoring.go [183:395]


func getMonitoringServers(tx *sql.Tx, cdn string) ([]Monitor, []Cache, []Router, error) {
	serversQuery := `
SELECT
	me.host_name as hostName,
	CONCAT(me.host_name, '.', me.domain_name) as fqdn,
	status.name as status,
	cachegroup.name as cachegroup,
	me.tcp_port as port,
	(SELECT STRING_AGG(sp.profile_name, ' ' ORDER by sp.priority ASC) FROM server_profile AS sp where sp.server=me.id group by sp.server) as profile,
	type.name as type,
	me.xmpp_id as hashID,
    me.id as serverID
FROM server me
JOIN type type ON type.id = me.type
JOIN status status ON status.id = me.status
JOIN cachegroup cachegroup ON cachegroup.id = me.cachegroup
JOIN profile profile ON profile.id = me.profile
JOIN cdn cdn ON cdn.id = me.cdn_id
WHERE cdn.name = $1
`

	interfacesQuery := `
SELECT
   i.name, i.max_bandwidth, i.mtu, i.monitor, i.server
FROM interface i
WHERE i.server in (
	SELECT
		s.id
	FROM "server" s
	JOIN cdn c
		on c.id = s.cdn_id
	WHERE c.name = $1
)`

	ipAddressQuery := `
SELECT
	ip.address, ip.gateway, ip.service_address, ip.server, ip.interface
FROM ip_address ip
JOIN server s
	ON s.id = ip.server
JOIN cdn cdn
	ON cdn.id = s.cdn_id
WHERE ip.server = ANY($1)
AND ip.interface = ANY($2)
AND cdn.name = $3
`

	interfaceRows, err := tx.Query(interfacesQuery, cdn)
	if err != nil {
		return nil, nil, nil, err
	}
	defer interfaceRows.Close()

	//For constant time lookup of which interface/server belongs to the ipAddress
	var interfacesByNameAndServer = make(map[int]map[string]tc.ServerInterfaceInfo)
	var serverIDs []int
	var interfaceNames []string
	var interfaceName string
	var serverID int
	for interfaceRows.Next() {
		interf := tc.ServerInterfaceInfo{}
		if err := interfaceRows.Scan(&interf.Name, &interf.MaxBandwidth, &interf.MTU, &interf.Monitor, &serverID); err != nil {
			return nil, nil, nil, err
		}
		if _, ok := interfacesByNameAndServer[serverID]; !ok {
			interfacesByNameAndServer[serverID] = make(map[string]tc.ServerInterfaceInfo)
		}
		interfacesByNameAndServer[serverID][interf.Name] = interf
		serverIDs = append(serverIDs, serverID)
		interfaceNames = append(interfaceNames, interf.Name)
	}

	ipAddressRows, err := tx.Query(ipAddressQuery, pq.Array(serverIDs), pq.Array(interfaceNames), cdn)
	if err != nil {
		return nil, nil, nil, err
	}
	defer ipAddressRows.Close()
	for ipAddressRows.Next() {
		address := tc.ServerIPAddress{}
		if err := ipAddressRows.Scan(&address.Address, &address.Gateway, &address.ServiceAddress, &serverID, &interfaceName); err != nil {
			return nil, nil, nil, err
		}
		found := false
		var addresses []tc.ServerIPAddress
		if _, ok := interfacesByNameAndServer[serverID]; ok {
			if _, ok := interfacesByNameAndServer[serverID][interfaceName]; ok {
				addresses = append(addresses, address)
				found = ok
			}
		}
		if !found {
			log.Errorf("ip_address exists without corresponding interface; server: %v, interfaceName: %v!", serverID, interfaceName)
			continue
		}
		interf := interfacesByNameAndServer[serverID][interfaceName]
		interf.IPAddresses = append(interf.IPAddresses, addresses...)
		interfacesByNameAndServer[serverID][interfaceName] = interf
	}

	serverDSNames, err := dbhelpers.GetServerDSNamesByCDN(tx, cdn)
	if err != nil {
		return nil, nil, nil, err
	}
	serverDSes := make(map[tc.CacheName][]tc.TSDeliveryService, len(serverDSNames))
	for c, dsNames := range serverDSNames {
		tsDS := make([]tc.TSDeliveryService, 0, len(dsNames))
		for _, n := range dsNames {
			tsDS = append(tsDS, tc.TSDeliveryService{XmlId: n})
		}
		serverDSes[c] = tsDS
	}

	rows, err := tx.Query(serversQuery, cdn)
	if err != nil {
		return nil, nil, nil, err
	}
	defer rows.Close()

	monitors := []Monitor{}
	caches := []Cache{}
	routers := []Router{}

	for rows.Next() {
		var hostName sql.NullString
		var fqdn sql.NullString
		var status sql.NullString
		var cachegroup sql.NullString
		var port sql.NullInt64
		var profile sql.NullString
		var ttype sql.NullString
		var hashID sql.NullString
		var serverID sql.NullInt64

		if err := rows.Scan(&hostName, &fqdn, &status, &cachegroup, &port, &profile, &ttype, &hashID, &serverID); err != nil {
			return nil, nil, nil, err
		}
		cacheStatus := tc.CacheStatusFromString(status.String)

		if ttype.String == tc.MonitorTypeName {
			var ipStr, ipStr6 string
			var gotBothIPs bool
			if _, ok := interfacesByNameAndServer[int(serverID.Int64)]; ok {
				for _, interf := range interfacesByNameAndServer[int(serverID.Int64)] {
					for _, ipAddress := range interf.IPAddresses {
						ipAddress.Address = strings.Split(ipAddress.Address, "/")[0]
						ip := net.ParseIP(ipAddress.Address)
						if ip == nil {
							continue
						}
						if ipStr == "" && ip.To4() != nil {
							ipStr = ipAddress.Address
						} else if ipStr6 == "" && ip.To16() != nil {
							ipStr6 = ipAddress.Address
						}
						if ipStr != "" && ipStr6 != "" {
							gotBothIPs = true
							break
						}
					}
					if gotBothIPs {
						break
					}
				}
			}
			monitors = append(monitors, Monitor{
				BasicServer: BasicServer{
					CommonServerProperties: CommonServerProperties{
						Profile:    profile.String,
						Status:     status.String,
						Port:       int(port.Int64),
						Cachegroup: cachegroup.String,
						HostName:   hostName.String,
						FQDN:       fqdn.String,
					},
					IP:  ipStr,
					IP6: ipStr6,
				},
			})
		} else if (strings.HasPrefix(ttype.String, "EDGE") || strings.HasPrefix(ttype.String, "MID")) &&
			(cacheStatus == tc.CacheStatusOnline || cacheStatus == tc.CacheStatusReported || cacheStatus == tc.CacheStatusAdminDown) {
			var cacheInterfaces []tc.ServerInterfaceInfo
			if _, ok := interfacesByNameAndServer[int(serverID.Int64)]; ok {
				for _, interf := range interfacesByNameAndServer[int(serverID.Int64)] {
					cacheInterfaces = append(cacheInterfaces, interf)
				}
			}
			if len(cacheInterfaces) == 0 {
				log.Errorf("cache with hashID: %v, has no interfaces!", hashID.String)
			}
			cache := Cache{
				CommonServerProperties: CommonServerProperties{
					Profile:    profile.String,
					Status:     status.String,
					Port:       int(port.Int64),
					Cachegroup: cachegroup.String,
					HostName:   hostName.String,
					FQDN:       fqdn.String,
				},
				Interfaces:       cacheInterfaces,
				Type:             ttype.String,
				HashID:           hashID.String,
				DeliveryServices: serverDSes[tc.CacheName(hostName.String)],
			}
			caches = append(caches, cache)
		} else if ttype.String == tc.RouterTypeName {
			routers = append(routers, Router{
				Type:    ttype.String,
				Profile: profile.String,
			})
		}
	}
	return monitors, caches, routers, nil
}