Skip to content
This repository was archived by the owner on Nov 24, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
- Changed the access logs in Traffic Ops to now show the route ID with every API endpoint call. The Route ID is appended to the end of the access log line.
- With the addition of multiple server interfaces, interface data is constructed from IP Address/Gateway/Netmask (and their IPv6 counterparts) and Interface Name and Interface MTU fields on services. These **MUST** have proper, valid data before attempting to upgrade or the upgrade **WILL** fail. In particular IP fields need to be valid IP addresses/netmasks, and MTU must only be positive integers of at least 1280.
- The `/servers` and `/servers/{{ID}}}` API endpoints have been updated to use and reflect multi-interface servers.
- CDN Snapshots now use a server's "service addresses" to provide its IP addresses

### Deprecated
- Deprecated the non-nullable `DeliveryService` Go struct and other structs that use it. `DeliveryServiceNullable` structs should be used instead.
Expand Down
13 changes: 11 additions & 2 deletions traffic_ops/traffic_ops_golang/ats/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -612,12 +612,21 @@ func GetServerInfo(tx *sql.Tx, qry string, qryParams []interface{}) (*atscfg.Ser
return nil, false, errors.New("querying server info: " + err.Error())
}

infs, err := dbhelpers.GetServerInterfaces(s.ID, tx)
infs, err := dbhelpers.GetServersInterfaces([]int{s.ID}, tx)
if err != nil {
return nil, false, fmt.Errorf("querying server info interfaces: %v", err)
}

legacyInfo, err := tc.InterfaceInfoToLegacyInterfaces(infs)
interfaces, ok := infs[s.ID]
if !ok || len(interfaces) < 1 {
return nil, false, fmt.Errorf("server #%d has no interfaces", s.ID)
}

ifaces := make([]tc.ServerInterfaceInfo, 0, len(interfaces))
for _, inf := range interfaces {
ifaces = append(ifaces, inf)
}
legacyInfo, err := tc.InterfaceInfoToLegacyInterfaces(ifaces)
if err != nil {
return nil, false, fmt.Errorf("converting server info interfaces to legacy: %v", err)
}
Expand Down
153 changes: 96 additions & 57 deletions traffic_ops/traffic_ops_golang/crconfig/servers.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ import (
"database/sql"
"errors"
"fmt"
"github.com/apache/trafficcontrol/lib/go-util"
"strconv"
"strings"

"github.com/apache/trafficcontrol/lib/go-log"
"github.com/apache/trafficcontrol/lib/go-tc"

"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
)

const RouterTypeName = "CCR"
Expand Down Expand Up @@ -99,100 +100,92 @@ type ServerUnion struct {
SecureAPIPort *string
}

type ServerAndHost struct {
Server ServerUnion
Host string
}

const DefaultWeightMultiplier = 1000.0
const DefaultWeight = 0.999

func getAllServers(cdn string, tx *sql.Tx) (map[string]ServerUnion, error) {
servers := map[string]ServerUnion{}

serverParams, err := getServerParams(cdn, tx)
if err != nil {
return nil, errors.New("Error getting server params: " + err.Error())
}

// TODO select deliveryservices as array?
q := `
select s.host_name,
cg.name as cachegroup,
concat(s.host_name, '.', s.domain_name) as fqdn,
s.xmpp_id as hashid,
s.https_port,
s.interface_name,
s.ip_address_is_service,
s.ip6_address_is_service,
s.ip_address,
s.ip6_address,
s.tcp_port,
p.name as profile_name,
cast(p.routing_disabled as int),
st.name as status,
t.name as type
from server as s
inner join cachegroup as cg ON cg.id = s.cachegroup
inner join type as t on t.id = s.type
inner join profile as p ON p.id = s.profile
inner join status as st ON st.id = s.status
where cdn_id = (select id from cdn where name = $1)
and (st.name = 'REPORTED' or st.name = 'ONLINE' or st.name = 'ADMIN_DOWN')
`
SELECT
s.id,
s.host_name,
cg.name as cachegroup,
concat(s.host_name, '.', s.domain_name) AS fqdn,
s.xmpp_id AS hashid,
s.https_port,
s.tcp_port,
p.name AS profile_name,
cast(p.routing_disabled AS int),
st.name AS status,
t.name AS type
FROM server AS s
INNER JOIN cachegroup AS cg ON cg.id = s.cachegroup
INNER JOIN type AS t on t.id = s.type
INNER JOIN profile AS p ON p.id = s.profile
INNER JOIN status AS st ON st.id = s.status
WHERE cdn_id = (SELECT id FROM cdn WHERE name = $1)
AND (st.name = 'REPORTED' OR st.name = 'ONLINE' OR st.name = 'ADMIN_DOWN')
`
rows, err := tx.Query(q, cdn)
if err != nil {
return nil, errors.New("Error querying servers: " + err.Error())
}
defer rows.Close()

servers := map[int]ServerAndHost{}
ids := []int{}
for rows.Next() {
port := sql.NullInt64{}
ip6 := sql.NullString{}
hashId := sql.NullString{}
httpsPort := sql.NullInt64{}
var port sql.NullInt64
var hashId sql.NullString
var httpsPort sql.NullInt64

ipIsService := false
ip6IsService := false
var s ServerAndHost

s := ServerUnion{}

host := ""
status := ""
if err := rows.Scan(&host, &s.CacheGroup, &s.Fqdn, &hashId, &httpsPort, &s.InterfaceName, &ipIsService, &ip6IsService, &s.Ip, &ip6, &port, &s.Profile, &s.RoutingDisabled, &status, &s.ServerType); err != nil {
var status string
var id int
if err := rows.Scan(&id, &s.Host, &s.Server.CacheGroup, &s.Server.Fqdn, &hashId, &httpsPort, &port, &s.Server.Profile, &s.Server.RoutingDisabled, &status, &s.Server.ServerType); err != nil {
return nil, errors.New("Error scanning server: " + err.Error())
}
if !ipIsService {
s.Ip = util.StrPtr("")
}
if !ip6IsService {
s.Ip6 = util.StrPtr("")
} else {
s.Ip6 = &ip6.String // Don't check valid, assign empty string if null
}

s.LocationId = s.CacheGroup
ids = append(ids, id)

s.Server.LocationId = s.Server.CacheGroup

serverStatus := tc.CRConfigServerStatus(status)
s.ServerStatus = &serverStatus
s.Server.ServerStatus = &serverStatus
if port.Valid {
i := int(port.Int64)
s.Port = &i
s.Server.Port = &i
}

if hashId.String != "" {
s.HashId = &hashId.String
s.Server.HashId = &hashId.String
} else {
s.HashId = &host
s.Server.HashId = &s.Host
}

if httpsPort.Valid {
i := int(httpsPort.Int64)
s.HttpsPort = &i
s.Server.HttpsPort = &i
}

params, hasParams := serverParams[host]
params, hasParams := serverParams[s.Host]
if hasParams && params.APIPort != nil {
s.APIPort = params.APIPort
s.Server.APIPort = params.APIPort
}

if hasParams && params.SecureAPIPort != nil {
s.SecureAPIPort = params.SecureAPIPort
s.Server.SecureAPIPort = params.SecureAPIPort
}

weightMultiplier := DefaultWeightMultiplier
Expand All @@ -204,15 +197,61 @@ and (st.name = 'REPORTED' or st.name = 'ONLINE' or st.name = 'ADMIN_DOWN')
weight = *params.Weight
}
hashCount := int(weight * weightMultiplier)
s.HashCount = &hashCount
s.Server.HashCount = &hashCount

servers[host] = s
servers[id] = s
}
if err := rows.Err(); err != nil {
return nil, errors.New("Error iterating router param rows: " + err.Error())
}

return servers, nil
interfaces, err := dbhelpers.GetServersInterfaces(ids, tx)
if err != nil {
return nil, fmt.Errorf("getting interfaces for servers: %v", err)
}

hostToServerMap := make(map[string]ServerUnion, len(servers))
for id, server := range servers {
ifaces, ok := interfaces[id]
if !ok {
log.Warnf("server '%s' (#%d) has no interfaces", server.Host, id)
server.Server.InterfaceName = new(string)
server.Server.Ip = new(string)
server.Server.Ip6 = new(string)
hostToServerMap[server.Host] = server.Server
continue
}

infs := make([]tc.ServerInterfaceInfo, 0, len(ifaces))
for _, inf := range ifaces {
infs = append(infs, inf)
}

legacyNet, err := tc.InterfaceInfoToLegacyInterfaces(infs)
if err != nil {
return nil, fmt.Errorf("Error converting interfaces to legacy data for server '%s' (#%d): %v", server.Host, id, err)
}

server.Server.Ip = legacyNet.IPAddress
server.Server.Ip6 = legacyNet.IP6Address

if server.Server.Ip == nil {
server.Server.Ip = new(string)
}
if server.Server.Ip6 == nil {
server.Server.Ip6 = new(string)
}

server.Server.InterfaceName = legacyNet.InterfaceName
if server.Server.InterfaceName == nil {
server.Server.InterfaceName = new(string)
log.Warnf("Server %s (#%d) had no service-address-containing interfaces", server.Host, id)
}

hostToServerMap[server.Host] = server.Server
}

return hostToServerMap, nil
}

func getServerDSNames(cdn string, tx *sql.Tx) (map[tc.CacheName][]tc.DeliveryServiceName, error) {
Expand Down
Loading