func readReplicationConfig()

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
}