Skip to content

Commit

Permalink
Merge pull request #148 from angelabriel/master
Browse files Browse the repository at this point in the history
jsc#TEAM-8703, jsc#SAPSOL-331 - saptune configure
  • Loading branch information
angelabriel authored Oct 22, 2024
2 parents 0826ec3 + e4475bc commit f8bd121
Show file tree
Hide file tree
Showing 10 changed files with 296 additions and 25 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)
}
}
}
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
7 changes: 4 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 Down
36 changes: 35 additions & 1 deletion ospackage/man/saptune.8
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
.\" * GNU General Public License for more details.
.\" */
.\"
.TH saptune "8" "July 2024" "" "System optimization For SAP"
.TH saptune "8" "October 2024" "" "System optimization For SAP"
.SH NAME
saptune \- Comprehensive system optimization management for SAP solutions (\fBVersion 3\fP)

Expand Down Expand Up @@ -63,6 +63,12 @@ rename SOLUTIONNAME NEWSOLUTIONNAME
\fBsaptune\fP [--format FORMAT] [--force-color] \fBstaging\fP
release [--force|--dry-run] [ ( NOTEID | SOLUTIONNAME )... | all ]

\fBsaptune\fP [--format FORMAT] [--force-color] \fBconfigure\fP
( COLOR_SCHEME | SKIP_SYSCTL_FILES | IGNORE_RELOAD | DEBUG ) Value

\fBsaptune\fP [--format FORMAT] [--force-color] \fBconfigure\fP
( reset | show )

\fBsaptune\fP [--format FORMAT] [--force-color] \fBverify\fP
applied

Expand Down Expand Up @@ -690,6 +696,29 @@ First the command will show an analysis of the objects going to be released to m

Because the release is irreversible, the user has to confirm the action.

.SH CONFIGURE ACTIONS
Replaces the direct editing of the saptune configuration file /etc/sysconfig/saptune, which will be replaced by an intern configuration file and not be present in future versions.
.br
Not all of the former variables will be available as configure option, only those who should be changeable by the user.
.br
.SS
.TP
.B COLOR_SCHEME SCHEME
Default color scheme. See saptune verify --colorscheme SCHEME for available schemes.
.TP
.B SKIP_SYSCTL_FILES FILE[,FILE...]
Comma-separated list of sysctl config files or directories which should be excluded when checking if parameters handled by saptune are handled by sysctl as well.
Input is checked, if the given files are in a location which is searched by sysctl command. If not, the files will be skipped.
.TP
.B IGNORE_RELOAD yes||no
Controls behavior of systemctl reload saptune.service and the systemctl try-restart saptune.service during package installation.
.TP
.B reset
Reverts the tuning and reset the content of the saptune configuration file to the installation default. Asks for confirmation.
.TP
.B show
Shows the content of the saptune configuration file

.SH VERIFY ACTIONS
.TP
.B verify applied
Expand Down Expand Up @@ -886,6 +915,11 @@ the saptune SAP Note or solution definitions, which are present in the Package A
\fI/etc/sysconfig/saptune\fP
.RS 4
the central saptune configuration file containing the information about the currently enabled notes and solutions, the order in which these notes are applied and the version of saptune currently used.
.br
ATTENTION:
the manual editing of this file will be \fBdeprecated\fP as the main configuration file will be (re)moved in the near future.
.br
Please use \fBsaptune configure\fP command instead of editing the file directly.
.RE
.PP
\fI/etc/saptune/extra\fP
Expand Down
2 changes: 1 addition & 1 deletion sap/note/ini.go
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ func (vend INISettings) useOverrides(key, scheds, val string) (bool, string, str
// till now for /sys parameter settings
// like KSM, THP and /sys/block/*/queue
func (vend INISettings) chkDoubles(key, info string) string {
paramFiles := system.GetFiles(SaptuneParameterStateDir)
paramFiles := system.GetFiles(system.SaptuneParameterStateDir)

syskey := key
inf := ""
Expand Down
5 changes: 0 additions & 5 deletions sap/note/note.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@ import (
"strings"
)

// SaptuneParameterStateDir defines the directory where to store the
// parameter state files
// separated from the note state file directory
const SaptuneParameterStateDir = "/run/saptune/parameter"

// Note defines the structure and actions for a SAP Note
// An SAP note consisting of a series of tunable parameters that can be
// applied and reverted.
Expand Down
Loading

0 comments on commit f8bd121

Please sign in to comment.