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
}