Skip to content

Commit

Permalink
Merge branch 'master' into saptune_check_json
Browse files Browse the repository at this point in the history
  • Loading branch information
Sören Schmidt committed Oct 24, 2024
2 parents 30c4c10 + f8bd121 commit ca9c4a6
Show file tree
Hide file tree
Showing 16 changed files with 347 additions and 36 deletions.
9 changes: 7 additions & 2 deletions actions/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ var RPMDate = "undef"
var solutionSelector = system.GetSolutionSelector()

// saptune configuration file
var saptuneSysconfig = "/etc/sysconfig/saptune"
var saptuneSysconfig = system.SaptuneConfigFile()

// set colors for the table and list output
// var setYellowText = "\033[38;5;220m"
Expand All @@ -82,7 +82,7 @@ func SelectAction(writer io.Writer, stApp *app.App, saptuneVers string) {

// check for test packages
if RPMDate != "undef" {
system.NoticeLog("ATTENTION: You are running a test version (%s from %s) of saptune which is not supported for production use", RPMVersion, RPMDate)
system.NoticeLog("ATTENTION: You are running a test version (%s for SLES4SAP %d from %s) of saptune which is not supported for production use", RPMVersion, system.IfdefVers(), RPMDate)
}

switch system.CliArg(1) {
Expand All @@ -94,6 +94,8 @@ func SelectAction(writer io.Writer, stApp *app.App, saptuneVers string) {
NoteAction(writer, system.CliArg(2), system.CliArg(3), system.CliArg(4), stApp)
case "solution":
SolutionAction(writer, system.CliArg(2), system.CliArg(3), system.CliArg(4), stApp)
case "configure":
ConfigureAction(writer, system.CliArg(2), system.CliArgs(3), stApp)
case "revert":
RevertAction(writer, system.CliArg(2), stApp)
case "staging":
Expand Down Expand Up @@ -315,6 +317,9 @@ Staging control:
saptune [--format FORMAT] [--force-color] staging ( status | enable | disable | is-enabled | list )
saptune [--format FORMAT] [--force-color] staging ( analysis | diff ) [ ( NOTEID | SOLUTIONNAME )... | all ]
saptune [--format FORMAT] [--force-color] staging release [--force|--dry-run] [ ( NOTEID | SOLUTIONNAME )... | all ]
Config (re-)settings:
saptune [--format FORMAT] [--force-color] configure ( COLOR_SCHEME | SKIP_SYSCTL_FILES | IGNORE_RELOAD | DEBUG ) Value
saptune [--format FORMAT] [--force-color] configure ( reset | show )
Verify all applied Notes:
saptune [--format FORMAT] [--force-color] verify applied
Revert all parameters tuned by the SAP notes or solutions:
Expand Down
165 changes: 165 additions & 0 deletions actions/configureacts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package actions

import (
"fmt"
"github.com/SUSE/saptune/app"
"github.com/SUSE/saptune/system"
"github.com/SUSE/saptune/txtparser"
"io"
"os"
"strings"
)

var mandatoryConfigKeys = []string{app.TuneForSolutionsKey, app.TuneForNotesKey, app.NoteApplyOrderKey, "SAPTUNE_VERSION", "STAGING", "COLOR_SCHEME", "SKIP_SYSCTL_FILES", "IGNORE_RELOAD"}
var changeableConfigKeys = []string{"COLOR_SCHEME", "SKIP_SYSCTL_FILES", "IGNORE_RELOAD", "DEBUG"}

// MandKeyList returns a list of mandatory configuration parameter, which need
// to be available in the saptune configuration file
func MandKeyList() []string {
return mandatoryConfigKeys
}

// ChangeKeyList returns a list of configuration parameter, which can be set
// or changed by the customer
func ChangeKeyList() []string {
return changeableConfigKeys
}

// ConfigureAction changes entries in the main saptune configuration file
// Replaces the direct editing of the config file
//
// saptune configure STAGING -- not needed because of 'saptune staging enable'
func ConfigureAction(writer io.Writer, configEntry string, configVals []string, tuneApp *app.App) {
if len(configVals) == 0 && !(configEntry == "reset" || configEntry == "show") {
// missing value to be configured
PrintHelpAndExit(writer, 1)
}
switch configEntry {
case "COLOR_SCHEME":
ConfigureActionSetColorScheme(configVals[0])
case "SKIP_SYSCTL_FILES":
ConfigureActionSetSkipSysctlFiles(configVals)
case "IGNORE_RELOAD":
ConfigureActionSetIgnoreReload(configVals[0])
case "DEBUG":
ConfigureActionSetDebug(configVals[0])
case "reset":
ConfigureActionReset(os.Stdin, writer, tuneApp)
case "show":
ConfigureActionShow(writer)
default:
PrintHelpAndExit(writer, 1)
}
}

// ConfigureActionSetColorScheme sets the color scheme
func ConfigureActionSetColorScheme(configVal string) {
switch configVal {
case "", "full-green-zebra", "cmpl-green-zebra", "full-blue-zebra", "cmpl-blue-zebra", "full-red-noncmpl", "red-noncmpl", "full-yellow-noncmpl", "yellow-noncmpl":
writeConfigEntry("COLOR_SCHEME", configVal)
default:
system.ErrorExit("wrong value '%s' for config variable 'COLOR_SCHEME'. Please check.", configVal)
}
}

// ConfigureActionSetIgnoreReload sets the variable IGNORE_RELOAD
func ConfigureActionSetIgnoreReload(configVal string) {
switch configVal {
case "yes", "no":
writeConfigEntry("IGNORE_RELOAD", configVal)
default:
system.ErrorExit("wrong value '%s' for config variable 'IGNORE_RELOAD'. Only 'yes' or 'no' supported. Please check.", configVal)
}
}

// ConfigureActionSetDebug sets the variable DEBUG
func ConfigureActionSetDebug(configVal string) {
switch configVal {
case "on", "off":
writeConfigEntry("DEBUG", configVal)
default:
system.ErrorExit("wrong value '%s' for config variable 'DEBUG'. Only 'on' or 'off' supported. Please check.", configVal)
}
}

// ConfigureActionSetSkipSysctlFiles sets the exclude list for the sysctl
// config warnings
func ConfigureActionSetSkipSysctlFiles(configVals []string) {
if configVals[0] == "" {
writeConfigEntry("SKIP_SYSCTL_FILES", configVals[0])
system.ErrorExit("", 0)
}
confVals := configVals
if len(configVals) == 1 && strings.Contains(configVals[0], ",") {
confVals = strings.Split(configVals[0], ",")
}
confVal := ""
//for _, file := range configVals {
for _, file := range confVals {
file = strings.TrimSuffix(file, ",")
if system.IsValidSysctlLocations(file) {
if confVal == "" {
confVal = file
} else {
confVal = confVal + ", " + file
}
} else {
system.ErrorLog("wrong value '%s' for config variable 'SKIP_SYSCTL_FILES'. sysctl command will not search in this locaction. Skipping.", file)
}
}
if confVal != "" {
writeConfigEntry("SKIP_SYSCTL_FILES", confVal)
} else {
system.ErrorExit("wrong value(s) '%+v' for config variable 'SKIP_SYSCTL_FILES' provided. sysctl command will not search in this locaction(s). Exiting without changing saptune configuration. Please check.", configVals)
}
}

// writeConfigEntry writes the changed config entry setting to the saptune
// config file
func writeConfigEntry(entry, val string) {
sconf, err := txtparser.ParseSysconfigFile(saptuneSysconfig, true)
if err != nil {
system.ErrorExit("Unable to read file '%s': '%v'\n", saptuneSysconfig, err, 128)
}
if val == "" {
system.NoticeLog("Reset '%s' to empty value", entry)
} else {
system.NoticeLog("Set '%s' to '%s'", entry, val)
}
sconf.Set(entry, val)
if err := os.WriteFile(saptuneSysconfig, []byte(sconf.ToText()), 0644); err != nil {
system.ErrorExit("'%s' could not be set to '%s'. - '%v'\n", entry, val, err)
}
}

// ConfigureActionShow shows the content of the saptune configuration file
func ConfigureActionShow(writer io.Writer) {
cont, err := os.ReadFile(saptuneSysconfig)
if err != nil {
system.ErrorExit("Unable to read file '%s': '%v'\n", saptuneSysconfig, err, 128)
}
fmt.Fprintf(writer, "\nContent of saptune configuration file %s:\n\n%s\n", saptuneSysconfig, string(cont))
}

// ConfigureActionReset(writer)
func ConfigureActionReset(reader io.Reader, writer io.Writer, tuneApp *app.App) {
fmt.Fprintf(writer, "\nATTENTION: resetting the main saptune configuration.\nThis will reset the tuning of the system and remove/reset all saptune related configuration and runtime files.\n")
txtConfirm := fmt.Sprintf("Do you really want to reset the main saptune configuration?")
if readYesNo(txtConfirm, reader, writer) {
system.InfoLog("ATTENTION: Resetting main saptune configuration")
// revert all
if err := tuneApp.RevertAll(true); err != nil {
system.ErrorLog("Failed to revert notes: %v", err)
}
// remove saved_state files, if some left over
os.RemoveAll(system.SaptuneSectionDir)
os.RemoveAll(system.SaptuneParameterStateDir)
os.RemoveAll(system.SaptuneSavedStateDir)

// set configuration file back to default/delivery
saptuneTemplate := system.SaptuneConfigTemplate()
if err := system.CopyFile(saptuneTemplate, saptuneSysconfig); err != nil {
system.ErrorLog("Failed to set saptune configuration file '%s' back to delivery state by copying the template file '%s'", saptuneSysconfig, saptuneTemplate)
}
}
}
14 changes: 12 additions & 2 deletions actions/serviceacts.go
Original file line number Diff line number Diff line change
Expand Up @@ -847,11 +847,21 @@ func CheckOrphanedOverrides() {
if err != nil {
system.ErrorExit("Problems reading override directory '%s' (%v). Please check your saptune installation\n", OverrideTuningSheets, err)
}
customName := ""
object := "note"
workDir := NoteTuningSheets
for _, entry := range dirCont {
ovFile := entry.Name()
_, _, err := chkFileName(ovFile, NoteTuningSheets, ExtraTuningSheets)
if strings.HasSuffix(ovFile, ".sol") {
object = "solution"
workDir = SolutionSheets
customName = ovFile
} else {
customName = ovFile + ".conf"
}
_, _, err := chkFileName(ovFile, workDir, ExtraTuningSheets)
if os.IsNotExist(err) {
system.WarningLog("Found an orphaned override file '%s' in '%s'!\n Could not find a note definition file named '%s' in the working area '%s' nor '%s.conf' in the custom location '%s'. Please check and remove the override file, if it is a left over\n", ovFile, OverrideTuningSheets, ovFile, NoteTuningSheets, ovFile, ExtraTuningSheets)
system.WarningLog("Found an orphaned override file '%s' in '%s'!\n Could not find a %s definition file named '%s' in the working area '%s' nor '%s' in the custom location '%s'. Please check and remove the override file, if it is a left over\n", ovFile, OverrideTuningSheets, object, ovFile, workDir, customName, ExtraTuningSheets)
orphanedOverrides = append(orphanedOverrides, ovFile)
}
}
Expand Down
18 changes: 10 additions & 8 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@ import (
"strings"
)

// define saptunes main configuration file and variables
// define saptunes main configuration variables
const (
SysconfigSaptuneFile = "/etc/sysconfig/saptune"
TuneForSolutionsKey = "TUNE_FOR_SOLUTIONS"
TuneForNotesKey = "TUNE_FOR_NOTES"
NoteApplyOrderKey = "NOTE_APPLY_ORDER"
TuneForSolutionsKey = "TUNE_FOR_SOLUTIONS"
TuneForNotesKey = "TUNE_FOR_NOTES"
NoteApplyOrderKey = "NOTE_APPLY_ORDER"
)

// App defines the application configuration and serialised state information.
Expand All @@ -34,6 +33,9 @@ type App struct {
State *State // examine and manage serialised notes.
}

// define saptunes main configuration file
var sysconfigSaptuneFile = system.SaptuneConfigFile()

// InitialiseApp load application configuration. Panic on error.
func InitialiseApp(sysconfigPrefix, stateDirPrefix string, allNotes map[string]note.Note, allSolutions map[string]solution.Solution) (app *App) {
app = &App{
Expand All @@ -42,7 +44,7 @@ func InitialiseApp(sysconfigPrefix, stateDirPrefix string, allNotes map[string]n
AllNotes: allNotes,
AllSolutions: allSolutions,
}
sysconf, err := txtparser.ParseSysconfigFile(path.Join(app.SysconfigPrefix, SysconfigSaptuneFile), true)
sysconf, err := txtparser.ParseSysconfigFile(path.Join(app.SysconfigPrefix, sysconfigSaptuneFile), true)
if err == nil {
app.TuneForSolutions = sysconf.GetStringArray(TuneForSolutionsKey, []string{})
app.TuneForNotes = sysconf.GetStringArray(TuneForNotesKey, []string{})
Expand Down Expand Up @@ -91,14 +93,14 @@ func (app *App) PositionInNoteApplyOrder(noteID string) int {

// SaveConfig save configuration to file /etc/sysconfig/saptune.
func (app *App) SaveConfig() error {
sysconf, err := txtparser.ParseSysconfigFile(path.Join(app.SysconfigPrefix, SysconfigSaptuneFile), true)
sysconf, err := txtparser.ParseSysconfigFile(path.Join(app.SysconfigPrefix, sysconfigSaptuneFile), true)
if err != nil {
return err
}
sysconf.SetStrArray(TuneForSolutionsKey, app.TuneForSolutions)
sysconf.SetStrArray(TuneForNotesKey, app.TuneForNotes)
sysconf.SetStrArray(NoteApplyOrderKey, app.NoteApplyOrder)
return os.WriteFile(path.Join(app.SysconfigPrefix, SysconfigSaptuneFile), []byte(sysconf.ToText()), 0644)
return os.WriteFile(path.Join(app.SysconfigPrefix, sysconfigSaptuneFile), []byte(sysconf.ToText()), 0644)
}

// GetSortedSolutionEnabledNotes returns the number of all solution-enabled
Expand Down
10 changes: 7 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func main() {
}

// get saptune version and log switches from saptune sysconfig file
SaptuneVersion = checkSaptuneConfigFile(os.Stderr, app.SysconfigSaptuneFile, logSwitch)
SaptuneVersion = checkSaptuneConfigFile(os.Stderr, system.SaptuneConfigFile(), logSwitch)

arg1 := system.CliArg(1)
if arg1 == "version" || system.IsFlagSet("version") {
Expand All @@ -63,6 +63,7 @@ func main() {
// now system.ErrorExit can write to log and os.Stderr. No longer extra
// care is needed.
system.InfoLog("saptune (%s) started with '%s'", actions.RPMVersion, strings.Join(os.Args, " "))
system.InfoLog("build for '%d'", system.IfdefVers())

if arg1 == "lock" {
if arg2 := system.CliArg(2); arg2 == "remove" {
Expand Down Expand Up @@ -217,10 +218,10 @@ func checkWorkingArea() {
// returns the saptune version and changes some log switches
func checkSaptuneConfigFile(writer io.Writer, saptuneConf string, lswitch map[string]string) string {
missingKey := []string{}
keyList := []string{app.TuneForSolutionsKey, app.TuneForNotesKey, app.NoteApplyOrderKey, "SAPTUNE_VERSION", "STAGING", "COLOR_SCHEME", "SKIP_SYSCTL_FILES", "IGNORE_RELOAD"}
keyList := actions.MandKeyList()
sconf, err := txtparser.ParseSysconfigFile(saptuneConf, false)
if err != nil {
fmt.Fprintf(writer, "Error: Unable to read file '%s': %v\n", saptuneConf, err)
fmt.Fprintf(writer, "Error: Checking saptune configuration file - Unable to read file '%s': %v\n", saptuneConf, err)
system.ErrorExit("", 128)
}
// check, if all needed variables are available in the saptune
Expand All @@ -243,6 +244,9 @@ func checkSaptuneConfigFile(writer io.Writer, saptuneConf string, lswitch map[st

// set values read from the config file
saptuneVers := sconf.GetString("SAPTUNE_VERSION", "")
if saptuneVers != "1" && saptuneVers != "2" && saptuneVers != "3" {
system.ErrorExit("Wrong saptune version in file '/etc/sysconfig/saptune': %s", SaptuneVersion, 128)
}

// Switch Debug on ("on") or off ("off" - default)
// Switch verbose mode on ("on" - default) or off ("off")
Expand Down
6 changes: 3 additions & 3 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ func TestCheckSaptuneConfigFile(t *testing.T) {
tstwriter = &errExitbuffer

// check missing variable
saptuneConf = fmt.Sprintf("%s/saptune_NoVersion", TstFilesInGOPATH)
matchTxt := fmt.Sprintf("Error: File '%s' is broken. Missing variables 'SAPTUNE_VERSION'\n", saptuneConf)
saptuneConf = fmt.Sprintf("%s/saptune_MissingVar", TstFilesInGOPATH)
matchTxt := fmt.Sprintf("Error: File '%s' is broken. Missing variables 'COLOR_SCHEME'\n", saptuneConf)
lSwitch = logSwitch
_ = checkSaptuneConfigFile(&buffer, saptuneConf, lSwitch)

Expand All @@ -168,7 +168,7 @@ func TestCheckSaptuneConfigFile(t *testing.T) {
}
errExOut := errExitbuffer.String()
if errExOut != "" {
t.Errorf("wrong text returned by ErrorExit: '%v' instead of ''\n", errExOut)
t.Errorf("wrong text returned by ErrorExit: '%v' instead of '%v'\n", errExOut, matchTxt)
}

// initialise next test
Expand Down
15 changes: 13 additions & 2 deletions ospackage/man/saptune-note.5
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
.\" */
.\"

.TH "saptune-note" "5" "July 2024" "" "saptune note file format description"
.TH "saptune-note" "5" "October 2024" "" "saptune note file format description"
.SH NAME
saptune\-note \- Note definition files for saptune version \fB3\fP
.SH DESCRIPTION
Expand Down Expand Up @@ -124,6 +124,17 @@ Example:
[sysctl:csp=azure]
.RE
.TP
.BI virt= <virtualization type>
to define a special \fIvirtualization\fP type (as reported by \fI/usr/bin/systemd-detect-virt -v|-c|-r\fP)
.br
Valid values for \fBvirt=\fP are \fBvm\fP, \fBchroot\fP and \fBcontainer\fP

.RS 4
Example:
.br
[sysctl:virt=vm]
.RE
.TP
.BI DMI interface tag: <filename>= <file content>
.br
Additional every filename from \fI/sys/class/dmi/id/\fP can be used as a tag.
Expand Down Expand Up @@ -603,7 +614,7 @@ Concerning \fBsysstat.service\fP please be in mind: A running sysstat service ca
.br
See sar(1), sa2(8), sa1(8) for more information

If a service is enabled or disabled by default or admin choice, saptune will NOT disable or enable this service, if only '\fBstart\fP' or '\fBstop\fP' is used. In this case it will only start/stop the service. If such a service is started by systemd during a system reboot \fBafter\fP the start of saptune.service it will be possible that a service is stopped/running even if it was started/stopped by saptune. To change this, the service can be additional enabled or disabled by using '\fBenable\fP' or '\fBdisable\fP' in the Note definition file.
If a service is enabled or disabled by default or admin choice, saptune will NOT disable or enable this service, if only '\fBstart\fP' or '\fBstop\fP' is used. In this case it will only start/stop the service. If such a service is started by systemd during a system reboot \fBafter\fP the start of saptune.service it will be possible that a service is stopped/running even if it was started/stopped by saptune. To change this, the service can be additional enabled or disabled by using '\fBenable\fP' or '\fBdisable\fP' in the Note definition or Override file.
\" section sysctl
.SH "[sysctl]"
The section "[sysctl]" can be used to modify kernel parameters. The parameters available are those listed under /proc/sys/.
Expand Down
Loading

0 comments on commit ca9c4a6

Please sign in to comment.