diff --git a/actions/configureacts.go b/actions/configureacts.go index c656b3e..8cf4634 100644 --- a/actions/configureacts.go +++ b/actions/configureacts.go @@ -143,6 +143,7 @@ func ConfigureActionShow(writer io.Writer) { // ConfigureActionReset(writer) func ConfigureActionReset(reader io.Reader, writer io.Writer, tuneApp *app.App) { + errcnt := 0 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) { @@ -150,6 +151,7 @@ func ConfigureActionReset(reader io.Reader, writer io.Writer, tuneApp *app.App) // revert all if err := tuneApp.RevertAll(true); err != nil { system.ErrorLog("Failed to revert notes: %v", err) + errcnt = errcnt + 1 } // remove saved_state files, if some left over os.RemoveAll(system.SaptuneSectionDir) @@ -160,6 +162,10 @@ func ConfigureActionReset(reader io.Reader, writer io.Writer, tuneApp *app.App) 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) + errcnt = errcnt + 1 } } + if errcnt != 0 { + system.ErrorExit("", 1) + } } diff --git a/actions/serviceacts.go b/actions/serviceacts.go index 3a13eb7..5ec17ae 100644 --- a/actions/serviceacts.go +++ b/actions/serviceacts.go @@ -857,6 +857,8 @@ func CheckOrphanedOverrides() { workDir = SolutionSheets customName = ovFile } else { + object = "note" + workDir = NoteTuningSheets customName = ovFile + ".conf" } _, _, err := chkFileName(ovFile, workDir, ExtraTuningSheets) diff --git a/main.go b/main.go index 36ff790..8294067 100644 --- a/main.go +++ b/main.go @@ -139,6 +139,10 @@ func checkUpdateLeftOvers() { system.WarningLog("found file '/etc/tuned/saptune/tuned.conf' left over from the migration of saptune version 1 to saptune version 3. Please check and remove this file as it may work against the settings of some SAP Notes. For more information refer to the man page saptune-migrate(7)") } + if system.CliArg(1) == "configure" && system.CliArg(2) == "reset" { + return + } + // check if old solution or notes are applied if tuneApp != nil && (len(tuneApp.NoteApplyOrder) == 0 && (len(tuneApp.TuneForNotes) != 0 || len(tuneApp.TuneForSolutions) != 0)) { system.ErrorExit("There are 'old' solutions or notes defined in file '/etc/sysconfig/saptune'. Seems there were some steps missed during the migration from saptune version 1 to version 3. Please check. Refer to saptune-migrate(7) for more information") @@ -160,13 +164,19 @@ func checkForTuned() { // running as root func callSaptuneCheckScript(arg string) { if arg == "check" { - system.JnotSupportedYet() - // call external scrip saptune_check - cmd := exec.Command(saptcheck) - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - err := cmd.Run() + var err error + if system.GetFlagVal("format") == "json" { + var cmdOut []byte + cmdOut, err = exec.Command(saptcheck, "--json").CombinedOutput() + system.Jcollect(cmdOut) + } else { + // call external scrip saptune_check + cmd := exec.Command(saptcheck) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err = cmd.Run() + } if err != nil { system.ErrorExit("command '%+s' failed with error '%v'\n", saptcheck, err) } else { @@ -217,6 +227,19 @@ func checkWorkingArea() { // checks, if the values is valid // returns the saptune version and changes some log switches func checkSaptuneConfigFile(writer io.Writer, saptuneConf string, lswitch map[string]string) string { + if system.CliArg(1) == "configure" && system.CliArg(2) == "reset" { + if lswitch["debug"] == "" { + lswitch["debug"] = "off" + } + if lswitch["verbose"] == "" { + lswitch["verbose"] = "on" + } + if lswitch["error"] == "" { + lswitch["error"] = "on" + } + return "3" + } + missingKey := []string{} keyList := actions.MandKeyList() sconf, err := txtparser.ParseSysconfigFile(saptuneConf, false) @@ -245,7 +268,8 @@ 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) + fmt.Fprintf(writer, "Error: Wrong saptune version in file '/etc/sysconfig/saptune': %s\n", saptuneVers) + system.ErrorExit("", 128) } // Switch Debug on ("on") or off ("off" - default) diff --git a/ospackage/man/saptune-note.5 b/ospackage/man/saptune-note.5 index dbe70f7..8a0c6bb 100644 --- a/ospackage/man/saptune-note.5 +++ b/ospackage/man/saptune-note.5 @@ -125,9 +125,9 @@ Example: .RE .TP .BI virt= -to define a special \fIvirtualization\fP type (as reported by \fI/usr/bin/systemd-detect-virt -v|-c|-r\fP) +to define a special \fIvirtualization\fP class or type .br -Valid values for \fBvirt=\fP are \fBvm\fP, \fBchroot\fP and \fBcontainer\fP +Valid class values for \fBvirt=\fP are \fBvm\fP, \fBchroot\fP and \fBcontainer\fP. Valid type values for \fBvirt=\fP are the output reported by \fI/usr/bin/systemd-detect-virt\fP .RS 4 Example: diff --git a/ospackage/usr/share/saptune/notes/1680803 b/ospackage/usr/share/saptune/notes/1680803 index ab5356d..6b358ea 100644 --- a/ospackage/usr/share/saptune/notes/1680803 +++ b/ospackage/usr/share/saptune/notes/1680803 @@ -5,104 +5,29 @@ # 'Best Practice for SAP Business Suite and SAP BW' linked in the # 'Solution' section of the related SAP Note 1680803 on SAP launchpad # -# chapter 3.2 Configuration for Linux +# chapter Operating System Configuration - Prerequisites # # SAP Applications on SAP Adaptive Server Enterprise # - Best Practices for Migration and Runtime -# Version 3.0 from 2020-07-31 # # SAP ASE (Sybase) -# Version 27 from 04.11.2021 in English +# Version 28 from 26.10.2023 in English # [version] -VERSION=27 -DATE=04.11.2021 +VERSION=28 +DATE=26.10.2023 DESCRIPTION=Sybase - SAP Adaptive Server Enterprise REFERENCES=https://launchpad.support.sap.com/#/notes/1680803 -[block] -## Type: string -## Default: noop, none -# -# The default I/O scheduler for single-queued block layer devices offers -# satisfactory performance for wide range of I/O task, however choosing an -# alternative scheduler may potentially yield better latency characteristics -# and throughput. -# "noop" is an alternative scheduler, in comparison to other schedulers it -# may offer more consistent performance, lower computation overhead, and -# potentially higher throughput. -# For most SAP environments (RAID, storage arrays, virtualizaton) 'noop' is -# the better choice. -# With the new introduced multi-queue scheduler for block layer devices the -# recommended I/O scheduler is 'none' as an equivalent to 'noop' for -# single-queued block layer devices. -# -# So IO_SCHEDULER can now contain a comma separated list of possible -# schedulers, which are checked from left to right. The first one which is -# available in /sys/block//queue/scheduler will be used as new -# scheduler setting for the respective block device. -# -# When set, all block devices on the system will be switched to one of the -# chosen schedulers. -IO_SCHEDULER=noop, none - -## Type: integer -## Default: depends on the used I/O scheduler -# -# IO nr_requests -# Increasing the value will improve the I/O throughput, but will also -# increase the memory usage. -# Decreasing the value will benefit the real-time applications that are -# sensitive to latency, but it also decreases the I/O throughput. -# -# possible maximum value depends on the chosen scheduler -# When set, the number of requests for all block devices on the system will -# be switched to the chosen value -NRREQ= - -[vm] -# Disable transparent hugepages (THP) -# changes /sys/kernel/mm/transparent_hugepage/enabled -# 'never' to disable, 'always' to enable -THP=never - [sysctl] -# maximum number of asynchronous I/Os. -fs.aio-max-nr = 1048576 - -# Increase system file descriptor limit -fs.file-max = 6291456 - -# Increase Linux autotuning TCP buffer limits -# Set max to 16MB (16777216) for 1GE and 32M (33554432) or 54M (56623104) for 10GE -# Don't set tcp_mem itself! Let the kernel scale it based on RAM. -net.core.rmem_max = 16777216 -net.core.wmem_max = 16777216 -net.core.rmem_default = 16777216 -net.core.wmem_default = 16777216 -net.ipv4.tcp_rmem = 4096 87380 16777216 -net.ipv4.tcp_wmem = 4096 65536 16777216 - # Set the keepalive interval to a value higher than 1200 seconds. # The ABAP dispatcher initiates an empty network request to the database # connection every 1200 seconds. If the keepalive interval is lower, the # operating system might close the database connection. net.ipv4.tcp_keepalive_time = 1250 -# Increase the max packet backlog -net.core.netdev_max_backlog = 30000 - -# Discourage Linux from swapping idle processes to disk (default = 60) -# value between 20 and 10 -vm.swappiness = 15 - [sysctl:csp=azure] net.ipv4.tcp_keepalive_time = [reminder] -# DBMS data storage settings: use ext4 or xfs file system. -# For best performance, disable the journal via tune2fs ^has_journal. -# For ext4 the recommended mount options are 'noatime,nodiratime', if journaling is disabled or 'noatime,nodiratime,cache=writeback,barrier=0', if journaling is not disabled -# For xfs the recommended mount options are 'noatime,nodiratime,logbufs=8'. -# network tuning including transmit queue (ifconfig txqueuelen ). See the current online version of the best practice document 'Best Practice for SAP Business Suite and SAP BW' linked in the 'Solution' section of the related SAP Note 1680803 on SAP launchpad diff --git a/ospackage/usr/share/saptune/notes/2578899 b/ospackage/usr/share/saptune/notes/2578899 index e883f35..71cae3a 100644 --- a/ospackage/usr/share/saptune/notes/2578899 +++ b/ospackage/usr/share/saptune/notes/2578899 @@ -11,6 +11,14 @@ REFERENCES=https://launchpad.support.sap.com/#/notes/2578899 # start the related services uuidd.socket=start sysstat.service=start + +[service:os=15-SP4] +sysctl-logger.service=start + +[service:os=15-SP5] +sysctl-logger.service=start + +[service:os=15-SP6] sysctl-logger.service=start [block] diff --git a/system/commandsMap.go b/system/commandsMap.go index 993f511..03c1ae4 100644 --- a/system/commandsMap.go +++ b/system/commandsMap.go @@ -2,63 +2,70 @@ package system // defaultCommand contains all available 'command - action' combinations var defaultCommand = map[string]bool{ - "daemon start": false, - "daemon status": false, - "daemon stop": false, - "service apply": false, - "service start": false, - "service status": false, - "service stop": false, - "service restart": false, - "service revert": false, - "service reload": false, - "service takeover": false, - "service enable": false, - "service disable": false, - "service enablestart": false, - "service disablestop": false, - "note list": false, - "note revertall": false, - "note enabled": false, - "note applied": false, - "note apply": false, - "note simulate": false, - "note customise": false, - "note create": false, - "note edit": false, - "note revert": false, - "note show": false, - "note delete": false, - "note verify": false, - "note rename": false, - "solution list": false, - "solution verify": false, - "solution enabled": false, - "solution applied": false, - "solution apply": false, - "solution change": false, - "solution simulate": false, - "solution customise": false, - "solution create": false, - "solution edit": false, - "solution revert": false, - "solution show": false, - "solution delete": false, - "solution rename": false, - "staging status": false, - "staging enable": false, - "staging disable": false, - "staging is-enabled": false, - "staging list": false, - "staging diff": false, - "staging analysis": false, - "staging release": false, - "revert all": false, - "lock remove": false, - "check": false, - "status": false, - "version": false, - "help": false, + "daemon start": false, + "daemon status": false, + "daemon stop": false, + "service apply": false, + "service start": false, + "service status": false, + "service stop": false, + "service restart": false, + "service revert": false, + "service reload": false, + "service takeover": false, + "service enable": false, + "service disable": false, + "service enablestart": false, + "service disablestop": false, + "note list": false, + "note revertall": false, + "note enabled": false, + "note applied": false, + "note apply": false, + "note simulate": false, + "note customise": false, + "note create": false, + "note edit": false, + "note revert": false, + "note show": false, + "note delete": false, + "note verify": false, + "note rename": false, + "solution list": false, + "solution verify": false, + "solution enabled": false, + "solution applied": false, + "solution apply": false, + "solution change": false, + "solution simulate": false, + "solution customise": false, + "solution create": false, + "solution edit": false, + "solution revert": false, + "solution show": false, + "solution delete": false, + "solution rename": false, + "staging status": false, + "staging enable": false, + "staging disable": false, + "staging is-enabled": false, + "staging list": false, + "staging diff": false, + "staging analysis": false, + "staging release": false, + "configure COLOR_SCHEME": false, + "configure SKIP_SYSCTL_FILES": false, + "configure IGNORE_RELOAD": false, + "configure DEBUG": false, + "configure reset": false, + "configure show": false, + "verify applied": false, + "revert all": false, + "lock remove": false, + "check": false, + "status": false, + "version": false, + "help": false, } // newDefaultCommandsMap creates a new 'command - action' map @@ -87,6 +94,7 @@ func supportedRACMap() map[string]bool { supportedRAC["solution applied"] = true supportedRAC["status"] = true supportedRAC["version"] = true + supportedRAC["check"] = true return supportedRAC } @@ -131,6 +139,7 @@ func lockCommandsMap() map[string]bool { lockCommand["staging diff"] = true lockCommand["staging analysis"] = true lockCommand["staging release"] = true + lockCommand["configure reset"] = true lockCommand["revert all"] = true return lockCommand diff --git a/system/json.go b/system/json.go index 3922bcb..6b60339 100644 --- a/system/json.go +++ b/system/json.go @@ -321,6 +321,9 @@ func Jcollect(data interface{}) { case JSolList, JNoteList, JStatus, JPNotes: //"solution list", "note list", "status", "daemon status", "service status", "note verify", "solution verify", "note simulate", "solution simulate": jentry.CmdResult = res + case []byte: + // "saptune check" - "saptune_check --json" - []uint8 + jentry.CmdResult = json.RawMessage(string(res)) default: WarningLog("Unknown data type '%T' for command '%s' in Jcollect, skipping", data, rac) } diff --git a/txtparser/tags.go b/txtparser/tags.go index 55f928a..d3e0a73 100644 --- a/txtparser/tags.go +++ b/txtparser/tags.go @@ -138,7 +138,28 @@ func chkCspTags(tagField string, secFields []string) bool { // chkVirtTags checks if the virtualization type section tag is valid or not func chkVirtTags(tagField string, secFields []string) bool { ret := true - chkVirt := system.GetVirtStatus() + vopt := "" + switch tagField { + case "vm": + vopt = "-v" + case "chroot": + vopt = "-r" + case "container": + vopt = "-c" + } + virt, chkVirt, err := system.SystemdDetectVirt(vopt) + if vopt != "" { + if !virt { + ret = false + system.InfoLog("virtualization class type '%s' in section definition '%v' does not match the virtualization class type of the running system. Skipping whole section with all lines till next valid section definition", tagField, secFields) + } + return ret + } + // order of vopt and err check is by intention + if err != nil { + system.InfoLog("No virtualization detected - bare metal system or error with systemd-detect-virt. Skipping whole section '%v' with all lines till next valid section definition", secFields) + return false + } if tagField != chkVirt { // virtualization type does not match system.InfoLog("virtualization type '%s' in section definition '%v' does not match the virtualization type of the running system ('%s'). Skipping whole section with all lines till next valid section definition", tagField, secFields, chkVirt)