in internal/system/sapdiscovery/sapdiscovery.go [201:317]
func readReplicationConfig(ctx context.Context, user, sid, instID string, exec commandlineexecutor.Execute, sapSystemInterface system.SapSystemDiscoveryInterface) (mode int, exitStatus int64, replicationSites *sapb.HANAReplicaSite, err error) {
cmd := "sudo"
args := "" +
fmt.Sprintf("-i -u %sadm /usr/sap/%s/%s/HDBSettings.sh ", strings.ToLower(sid), sid, instID) +
fmt.Sprintf(" /usr/sap/%s/%s/exe/python_support/systemReplicationStatus.py --sapcontrol=1", sid, instID)
result := exec(ctx, commandlineexecutor.Params{
Executable: cmd,
ArgsToSplit: args,
})
exitStatus = int64(result.ExitCode)
log.CtxLogger(ctx).Debugw("systemReplicationStatus.py returned", "result", result)
cmd = "sudo"
args = fmt.Sprintf("-i -u %sadm hdbnsutil -sr_state", strings.ToLower(sid))
result = exec(ctx, commandlineexecutor.Params{
Executable: cmd,
ArgsToSplit: args,
})
log.CtxLogger(ctx).Debugw("Tool hdbnsutil returned", "exitstatus", exitStatus)
log.CtxLogger(ctx).Debugw("SAP HANA Replication Config result", "stdout", result.StdOut)
if strings.Contains(result.StdOut, "mode: none") {
log.CtxLogger(ctx).Debugw("HANA instance is in standalone mode for instance", "instanceid", instID)
return 0, exitStatus, nil, nil
}
if exitStatus == 10 {
// Since this is a system with replication, as indicated by failing the "mode: none" check, the
// exit status of 10 indicates an error in the system. Since we know it is not standalone, we
// will return 12 to indicate a replication state error.
exitStatus = 12
}
match := sitePattern.FindStringSubmatch(result.StdOut)
if len(match) != 2 {
log.CtxLogger(ctx).Debugw("Error determining SAP HANA Site for instance", "instanceid", instID)
return 0, 0, nil, nil
}
site := match[1]
systems := sapSystemInterface.GetSAPSystems()
var sys *spb.SapDiscovery
for _, s := range systems {
if s.GetDatabaseLayer().GetSid() == sid {
sys = s
break
}
}
mode, err = readMode(ctx, result.StdOut, site, sys)
if err != nil {
return 0, exitStatus, nil, err
}
haHostMap, err := readHAMembers(ctx, result.StdOut, instID)
if err != nil {
log.CtxLogger(ctx).Infow("Error reading HA members", "instanceid", instID, "error", err)
return mode, exitStatus, nil, nil
}
log.CtxLogger(ctx).Debugw("HA Host Map", "haHostMap", haHostMap)
// site may be either the host name or the site name. Utilize the haHostMap to get a site name.
if s, ok := haHostMap[site]; ok {
site = s
}
// Separate sites into tiers.
log.CtxLogger(ctx).Debugw("Separating sites into tiers")
lines := strings.Split(result.StdOut, "\n")
inSiteMappings := false
siteStack := []*sapb.HANAReplicaSite{}
currentDepth := -1
var primarySite *sapb.HANAReplicaSite
for _, line := range lines {
if strings.Contains(line, "Site Mappings") {
inSiteMappings = true
continue
} else if !inSiteMappings {
continue
}
matches := siteMapPattern.FindStringSubmatch(line)
if len(matches) != 5 {
continue
}
siteName := matches[4]
var hostName string
for h, s := range haHostMap {
log.CtxLogger(ctx).Debugw("Checking host name", "siteName", s, "hostName", h)
if s == siteName {
hostName = h
log.CtxLogger(ctx).Debugw("Found host name", "siteName", s, "hostName", h)
break
}
}
log.CtxLogger(ctx).Debugw("Making site for host", "siteName", siteName, "hostName", hostName)
site := &sapb.HANAReplicaSite{Name: hostName}
depth := len(depthPattern.FindAllStringSubmatch(line, -1))
log.CtxLogger(ctx).Debugw("Depth of site", "site", site, "depth", depth, "currentDepth", currentDepth)
for depth <= currentDepth {
log.CtxLogger(ctx).Debugw("Popping site", "site", siteStack[len(siteStack)-1])
siteStack = siteStack[:len(siteStack)-1]
currentDepth--
}
if len(siteStack) > 0 {
currentSite := siteStack[len(siteStack)-1]
log.CtxLogger(ctx).Debugw("Appending site to parent's targets", "currentSite", currentSite, "site", site)
currentSite.Targets = append(currentSite.Targets, site)
}
siteStack = append(siteStack, site)
currentDepth = depth
if primarySite == nil {
primarySite = site
}
}
return mode, exitStatus, primarySite, nil
}