SUSE/saptune

View on GitHub
actions/footnote.go

Summary

Maintainability
A
1 hr
Test Coverage
C
70%
package actions

import (
    "github.com/SUSE/saptune/sap/note"
    "github.com/SUSE/saptune/system"
    "regexp"
    "runtime"
    "strconv"
    "strings"
)

// define footnote texts
const (
    footnote1X86 = " [1] setting is not supported by the system"
    footnote1IBM = " [1] setting is not relevant for the system"
    footnote1AZR = " [1] setting is not available on Azure instances (see SAP Note 2993054)."
    footnote1AWS = " [1] setting is not available on AWS instances (see SAP Note 1656250)."
    footnote2    = " [2] setting is not available on the system"
    footnote3    = " [3] value is only checked, but NOT set"
    footnote4    = " [4] cpu idle state settings differ"
    footnote5    = " [5] expected value does not contain a supported scheduler"
    footnote6    = " [6] grub settings are mostly covered by other settings. See man page saptune-note(5) for details"
    footnote7    = " [7] parameter value is untouched by default"
    footnote8    = " [8] cannot set Perf Bias because SecureBoot is enabled"
    footnote9    = " [9] expected value limited to 'max_hw_sectors_kb'"
    footnote10   = "[10] parameter is defined twice, see section SECT"
    footnote11   = "[11] parameter is additional defined in SYSCTLLIST"
    footnote12   = "[12] option FSOPT"
    footnote13   = "[13] The SAP recommendation for nr_request does not work in the context of multiqueue block framework (scheduler=none).\n      Maximal supported value by the hardware is MAXVAL"
    footnote14   = "[14] the parameter value exceeds the maximum possible number of open files. Check and increase fs.nr_open if really needed."
    footnote15   = "[15] the parameter is only used to calculate the size of tmpfs (/dev/shm)"
    footnote16   = "[16] parameter not available on the system, setting not possible"
)

// set 'unsupported' footnote regarding the architecture
var footnote1 = footnote1X86

// prepFN checks, if we need to prepare the footnote for a parameter
// if the command line flage '--show-non-compliant' is used only non compliant
// parameter rows will be printed and that has to be reflected to the footnotes
// too.
func prepFN(comparison note.FieldComparison, compliant, inform string) bool {
    prep := true
    if system.IsFlagSet("show-non-compliant") {
        // skip preparation of footnotes, if compliant state is not 'no'
        if strings.Contains(compliant, "yes") || strings.Contains(compliant, "-") {
            prep = false
        }
        // and now define the exceptions, which need a special handling
        if comparison.ReflectMapKey == "force_latency" && inform == "hasDiffs" {
            // compliant will be set to 'no' during footnote preparation
            prep = true
        }
        if comparison.ReflectMapKey == "VSZ_TMPFS_PERCENT" {
            // compliant will be set to '-' during footnote preparation
            prep = true
        }
        if strings.Contains(comparison.ReflectMapKey, "xfsopt_") {
            prep = true
        }
    }
    return prep
}

// prepareFootnote prepares the content of the last column and the
// corresponding footnotes
func prepareFootnote(comparison note.FieldComparison, compliant, comment, inform string, footnote []string) (string, string, []string) {
    if !prepFN(comparison, compliant, inform) {
        return compliant, comment, footnote
    }
    // set 'unsupported' footnote regarding the architecture
    if runtime.GOARCH == "ppc64le" {
        footnote1 = footnote1IBM
    }
    if system.GetCSP() == "azure" {
        footnote1 = footnote1AZR
    }
    if system.GetCSP() == "aws" {
        footnote1 = footnote1AWS
    }
    // set footnote for unsupported or not available parameter [1],[2]
    compliant, comment, footnote = setUsNa(comparison.ActualValue.(string), compliant, comment, footnote)
    // set footnote for rpm or grub parameter [3],[6]
    compliant, comment, footnote = setRpmGrub(comparison, compliant, comment, footnote)
    // set footnote for diffs in force_latency parameter [4]
    compliant, comment, footnote = setFLdiffs(comparison.ReflectMapKey, compliant, comment, inform, footnote)
    // set footnote for unsupported scheduler [5]
    compliant, comment, footnote = setUnSched(comparison.ReflectMapKey, compliant, comment, inform, footnote)
    // set footnote for untouched parameter [7]
    compliant, comment, footnote = setUntouched(comparison.ExpectedValue.(string), compliant, comment, footnote)
    // set footnote for secure boot [8]
    compliant, comment, footnote = setSecBoot(comparison.ReflectMapKey, compliant, comment, footnote)
    // set footnote for limited parameter value [9]
    compliant, comment, footnote = setLimited(comparison.ReflectMapKey, compliant, comment, inform, footnote)
    // set footnote for double defined parameters [10]
    compliant, comment, footnote = setDouble(comparison.ReflectMapKey, compliant, comment, inform, footnote)
    // set footnote for system wide (global) defines sysctl parameter [11]
    compliant, comment, footnote = setSysctlGlobal(compliant, comment, inform, footnote)
    // set footnote for filesystem options [12]
    compliant, comment, footnote = setFSOptions(comparison, compliant, comment, inform, footnote)
    // set footnote for unsupported nr_request value [13]
    compliant, comment, footnote = setUnNRR(comparison.ReflectMapKey, compliant, comment, inform, footnote)
    // set footnote for unsupported nofile limit value [14]
    compliant, comment, footnote = setNofile(comparison.ReflectMapKey, compliant, comment, inform, footnote)
    // set footnote for VSZ_TMPFS_PERCENT parameter from mem section
    compliant, comment, footnote = setMem(comparison.ReflectMapKey, compliant, comment, footnote)
    return compliant, comment, footnote
}

// setUsNa sets footnote for unsupported or not available parameter
func setUsNa(actVal, compliant, comment string, footnote []string) (string, string, []string) {
    switch actVal {
    case "all:none":
        compliant = compliant + " [1]"
        comment = comment + " [1]"
        footnote[0] = footnote1
    case "NA":
        compliant = compliant + " [2]"
        comment = comment + " [2]"
        footnote[1] = footnote2
    case "PNA":
        compliant = compliant + " [16]"
        compliant = strings.Replace(compliant, "no ", " - ", 1)
        comment = comment + " [16]"
        if !system.IsFlagSet("show-non-compliant") {
            footnote[15] = footnote16
        }
    }
    return compliant, comment, footnote
}

// setRpmGrub sets footnote for rpm or grub parameter
func setRpmGrub(comparison note.FieldComparison, compliant, comment string, footnote []string) (string, string, []string) {
    mapKey := comparison.ReflectMapKey
    if strings.Contains(mapKey, "rpm") || strings.Contains(mapKey, "grub") {
        compliant = compliant + " [3]"
        comment = comment + " [3]"
        footnote[2] = footnote3
    }
    if strings.Contains(mapKey, "grub") {
        compliant = compliant + " [6]"
        if comparison.ActualValue.(string) == "NA" {
            compliant = strings.Replace(compliant, "no ", " - ", 1)
        }
        comment = comment + " [6]"
        footnote[5] = footnote6
    }
    return compliant, comment, footnote
}

// setUntouched sets footnote for untouched parameter
func setUntouched(expVal, compliant, comment string, footnote []string) (string, string, []string) {
    if expVal == "" {
        compliant = compliant + " [7]"
        comment = comment + " [7]"
        footnote[6] = footnote7
    }
    return compliant, comment, footnote
}

// setSecBoot sets footnote for secure boot affected parameter
func setSecBoot(mapKey, compliant, comment string, footnote []string) (string, string, []string) {
    if mapKey == "energy_perf_bias" && system.SecureBootEnabled() {
        compliant = compliant + " [8]"
        comment = comment + " [8]"
        footnote[7] = footnote8
    }
    return compliant, comment, footnote
}

// setFLdiffs sets footnote for diffs in force_latency parameter
func setFLdiffs(mapKey, compliant, comment, info string, footnote []string) (string, string, []string) {
    if mapKey == "force_latency" && info == "hasDiffs" {
        compliant = compliant + " [4]"
        compliant = strings.Replace(compliant, " - ", "no ", 1)
        comment = comment + " [4]"
        footnote[3] = footnote4
    }
    return compliant, comment, footnote
}

// setUnSched sets footnote for unsupported scheduler
func setUnSched(mapKey, compliant, comment, info string, footnote []string) (string, string, []string) {
    if system.IsSched.MatchString(mapKey) && strings.Contains(info, "NA") {
        compliant = compliant + " [5]"
        comment = comment + " [5]"
        footnote[4] = footnote5
    }
    return compliant, comment, footnote
}

// setUnNRR sets footnote for unsupported nr_request values
func setUnNRR(mapKey, compliant, comment, info string, footnote []string) (string, string, []string) {
    if system.IsNrreq.MatchString(mapKey) && strings.Contains(info, "wrongVal") {
        compliant = compliant + " [13]"
        comment = comment + " [13]"
        maxVal, _, _ := system.GetNrTags(mapKey)
        footnote[12] = writeFN(footnote[12], footnote13, strconv.Itoa(maxVal), "MAXVAL")
    }
    return compliant, comment, footnote
}

// setLimit sets footnote for limited parameter value
func setLimited(mapKey, compliant, comment, info string, footnote []string) (string, string, []string) {
    if system.IsMsect.MatchString(mapKey) && strings.Contains(info, "limited") {
        compliant = compliant + " [9]"
        comment = comment + " [9]"
        footnote[8] = footnote9
    }
    return compliant, comment, footnote
}

// setDouble sets footnote for double defined sys parameters
func setDouble(mapKey, compliant, comment, info string, footnote []string) (string, string, []string) {
    if (system.IsSched.MatchString(mapKey) || system.IsNrreq.MatchString(mapKey) || system.IsRahead.MatchString(mapKey) || system.IsMsect.MatchString(mapKey)) && info != "" {
        // check for double defined parameters
        sect := regexp.MustCompile(`.*\[\w+\].*`)
        inf := strings.Split(info, "ยง")
        if len(inf) > 1 {
            if inf[0] != "limited" && inf[0] != "NA" {
                info = inf[0]
            } else {
                info = inf[1]
            }
        }
        if info != "limited" && info != "NA" && sect.MatchString(info) {
            compliant = compliant + " [10]"
            comment = comment + " [10]"
            footnote[9] = writeFN(footnote[9], footnote10, info, "SECT")
        }
    }
    if (strings.Contains(mapKey, "THP") || strings.Contains(mapKey, "KSM")) && info != "" {
        compliant = compliant + " [10]"
        comment = comment + " [10]"
        footnote[9] = writeFN(footnote[9], footnote10, info, "SECT")
    }
    if strings.Contains(mapKey, "sys:") && info != "" {
        compliant = compliant + " [10]"
        comment = comment + " [10]"
        footnote[9] = writeFN(footnote[9], footnote10, info, "SECT")
    }
    return compliant, comment, footnote
}

// setSysctlGlobal sets footnote for global defined sysctl parameters
func setSysctlGlobal(compliant, comment, info string, footnote []string) (string, string, []string) {
    // check if the sysctl parameter is additional set in a sysctl system
    // configuration file
    if strings.HasPrefix(info, "sysctl config file ") {
        // sysctl info
        compliant = compliant + " [11]"
        comment = comment + " [11]"
        footnote[10] = writeFN(footnote[10], footnote11, info, "SYSCTLLIST")
    }
    return compliant, comment, footnote
}

// setFSOptions sets footnote for not matching filesystem options
func setFSOptions(comparison note.FieldComparison, compliant, comment, info string, footnote []string) (string, string, []string) {
    // check if there are mount points with wrong FS option settings
    if strings.Contains(comparison.ReflectMapKey, "xfsopt_") {
        if !system.IsFlagSet("show-non-compliant") && info != "" {
            // fs option info
            compliant = compliant + " [12]"
            comment = comment + " [12]"
            footnote[11] = writeFN(footnote[11], footnote12, info, "FSOPT")
        }
        if comparison.ActualValue.(string) == "NA" {
            compliant = strings.Replace(compliant, "no ", " - ", 1)
        }
    }
    return compliant, comment, footnote
}

// setNofile sets footnote for unsupported nofile limit value
func setNofile(mapKey, compliant, comment, info string, footnote []string) (string, string, []string) {
    if strings.Contains(mapKey, "LIMIT_") && info == "limit_exceeded" {
        compliant = compliant + " [14]"
        comment = comment + " [14]"
        footnote[13] = footnote14
    }
    return compliant, comment, footnote
}

// setMem sets footnote for VSZ_TMPFS_PERCENT parameter from mem section
func setMem(mapKey, compliant, comment string, footnote []string) (string, string, []string) {
    if mapKey == "VSZ_TMPFS_PERCENT" {
        if system.IsFlagSet("show-non-compliant") {
            compliant = " - "
        } else {
            compliant = " -  [15]"
            comment = comment + " [15]"
            footnote[14] = footnote15
        }
    }
    return compliant, comment, footnote
}

// writeFN customizes the text for footnotes by replacing strings/placeholder
func writeFN(footnote, fntxt, info, pat string) string {
    if footnote == "" {
        footnote = strings.Replace(fntxt, pat, info, 1)
    } else {
        footnote = footnote + "\n " + strings.Replace(fntxt, pat, info, 1)
    }
    return footnote
}