diff --git a/completions/bash/crio b/completions/bash/crio index ce387c5026d..c09a57759cd 100755 --- a/completions/bash/crio +++ b/completions/bash/crio @@ -57,6 +57,7 @@ h --insecure-registry --internal-wipe --irqbalance-config-file +--irqbalance-config-restore-file --listen --log --log-dir diff --git a/completions/fish/crio.fish b/completions/fish/crio.fish index a27c45063b3..ad1b42d50d1 100644 --- a/completions/fish/crio.fish +++ b/completions/fish/crio.fish @@ -94,6 +94,7 @@ complete -c crio -n '__fish_crio_no_subcommand' -f -l insecure-registry -r -d 'E \'--insecure-registry\'.' complete -c crio -n '__fish_crio_no_subcommand' -f -l internal-wipe -d 'Whether CRI-O should wipe containers after a reboot and images after an upgrade when the server starts. If set to false, one must run `crio wipe` to wipe the containers and images in these situations. This option is deprecated, and will be removed in the future.' complete -c crio -n '__fish_crio_no_subcommand' -f -l irqbalance-config-file -r -d 'The irqbalance service config file which is used by CRI-O.' +complete -c crio -n '__fish_crio_no_subcommand' -f -l irqbalance-config-restore-file -r -d 'Determines if CRI-O should attempt to restore the irqbalance config at startup with the mask in this file. Use empty value to disable the restore flow entirely.' complete -c crio -n '__fish_crio_no_subcommand' -l listen -r -d 'Path to the CRI-O socket' complete -c crio -n '__fish_crio_no_subcommand' -l log -r -d 'Set the log file path where internal debug information is written' complete -c crio -n '__fish_crio_no_subcommand' -l log-dir -r -d 'Default log directory where all logs will go unless directly specified by the kubelet' diff --git a/completions/zsh/_crio b/completions/zsh/_crio index 1d18ea7ede1..f3bf6de332a 100644 --- a/completions/zsh/_crio +++ b/completions/zsh/_crio @@ -64,6 +64,7 @@ it later with **--config**. Global options will modify the output.' '--insecure-registry' '--internal-wipe' '--irqbalance-config-file' + '--irqbalance-config-restore-file' '--listen' '--log' '--log-dir' diff --git a/docs/crio.8.md b/docs/crio.8.md index 8f810633895..1fa891e8632 100644 --- a/docs/crio.8.md +++ b/docs/crio.8.md @@ -56,6 +56,7 @@ crio [--insecure-registry]=[value] [--internal-wipe] [--irqbalance-config-file]=[value] +[--irqbalance-config-restore-file]=[value] [--listen]=[value] [--log-dir]=[value] [--log-filter]=[value] @@ -266,6 +267,8 @@ crio [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...] **--irqbalance-config-file**="": The irqbalance service config file which is used by CRI-O. (default: /etc/sysconfig/irqbalance) +**--irqbalance-config-restore-file**="": Determines if CRI-O should attempt to restore the irqbalance config at startup with the mask in this file. Use empty value to disable the restore flow entirely. (default: /etc/sysconfig/orig_irq_banned_cpus) + **--listen**="": Path to the CRI-O socket (default: /var/run/crio/crio.sock) **--log**="": Set the log file path where internal debug information is written diff --git a/docs/crio.conf.5.md b/docs/crio.conf.5.md index dfb213daf9c..3f6831048f9 100644 --- a/docs/crio.conf.5.md +++ b/docs/crio.conf.5.md @@ -283,6 +283,9 @@ the container runtime configuration. **device_ownership_from_security_context**=false Changes the default behavior of setting container devices uid/gid from CRI's SecurityContext (RunAsUser/RunAsGroup) instead of taking host's uid/gid. +**irqbalance_config_restore_file**="/etc/sysconfig/orig_irq_banned_cpus" + Used to set the irqbalance banned cpu mask to restore at CRI-O startup. If empty, no restoration attempt will be done. + ### CRIO.RUNTIME.RUNTIMES TABLE The "crio.runtime.runtimes" table defines a list of OCI compatible runtimes. The runtime to use is picked based on the runtime handler provided by the CRI. If no runtime handler is provided, the runtime will be picked based on the level of trust of the workload. diff --git a/internal/criocli/criocli.go b/internal/criocli/criocli.go index 04a5f64fede..3d9c3e55642 100644 --- a/internal/criocli/criocli.go +++ b/internal/criocli/criocli.go @@ -326,6 +326,9 @@ func mergeConfig(config *libconfig.Config, ctx *cli.Context) error { if ctx.IsSet("absent-mount-sources-to-reject") { config.AbsentMountSourcesToReject = StringSliceTrySplit(ctx, "absent-mount-sources-to-reject") } + if ctx.IsSet("irqbalance-config-restore-file") { + config.IrqBalanceConfigRestoreFile = ctx.String("irqbalance-config-restore-file") + } if ctx.IsSet("internal-wipe") { config.InternalWipe = ctx.Bool("internal-wipe") } @@ -1012,6 +1015,11 @@ func getCrioFlags(defConf *libconfig.Config) []cli.Flag { Usage: "The number of seconds between collecting pod and container stats. If set to 0, the stats are collected on-demand instead.", EnvVars: []string{"CONTAINER_STATS_COLLECTION_PERIOD"}, }, + &cli.StringFlag{ + Name: "irqbalance-config-restore-file", + Value: defConf.IrqBalanceConfigRestoreFile, + Usage: "Determines if CRI-O should attempt to restore the irqbalance config at startup with the mask in this file. Use empty value to disable the restore flow entirely.", + }, } } diff --git a/internal/runtimehandlerhooks/high_performance_hooks.go b/internal/runtimehandlerhooks/high_performance_hooks.go index 2b7ecba4c85..c55751256bf 100644 --- a/internal/runtimehandlerhooks/high_performance_hooks.go +++ b/internal/runtimehandlerhooks/high_performance_hooks.go @@ -20,7 +20,6 @@ import ( "github.com/cri-o/cri-o/utils/cmdrunner" "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/cgroups/systemd" - "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/kubernetes/pkg/kubelet/cm/cpuset" @@ -29,8 +28,6 @@ import ( const ( // HighPerformance contains the high-performance runtime handler name HighPerformance = "high-performance" - // IrqBannedCPUConfigFile contains the original banned cpu mask configuration - IrqBannedCPUConfigFile = "/etc/sysconfig/orig_irq_banned_cpus" // IrqSmpAffinityProcFile contains the default smp affinity mask configuration IrqSmpAffinityProcFile = "/proc/irq/default_smp_affinity" ) @@ -78,7 +75,7 @@ func (h *HighPerformanceHooks) PreStart(ctx context.Context, c *oci.Container, s // disable the IRQ smp load balancing for the container CPUs if shouldIRQLoadBalancingBeDisabled(s.Annotations()) { log.Infof(ctx, "Disable irq smp balancing for container %q", c.ID()) - if err := setIRQLoadBalancing(c, false, IrqSmpAffinityProcFile, h.irqBalanceConfigFile); err != nil { + if err := setIRQLoadBalancing(ctx, c, false, IrqSmpAffinityProcFile, h.irqBalanceConfigFile); err != nil { return fmt.Errorf("set IRQ load balancing: %w", err) } } @@ -151,7 +148,7 @@ func (h *HighPerformanceHooks) PreStop(ctx context.Context, c *oci.Container, s // enable the IRQ smp balancing for the container CPUs if shouldIRQLoadBalancingBeDisabled(s.Annotations()) { - if err := setIRQLoadBalancing(c, true, IrqSmpAffinityProcFile, h.irqBalanceConfigFile); err != nil { + if err := setIRQLoadBalancing(ctx, c, true, IrqSmpAffinityProcFile, h.irqBalanceConfigFile); err != nil { return fmt.Errorf("set IRQ load balancing: %w", err) } } @@ -306,7 +303,7 @@ func setCPUSLoadBalancing(c *oci.Container, enable bool, schedDomainDir string) return nil } -func setIRQLoadBalancing(c *oci.Container, enable bool, irqSmpAffinityFile, irqBalanceConfigFile string) error { +func setIRQLoadBalancing(ctx context.Context, c *oci.Container, enable bool, irqSmpAffinityFile, irqBalanceConfigFile string) error { lspec := c.Spec().Linux if lspec == nil || lspec.Resources == nil || @@ -339,7 +336,7 @@ func setIRQLoadBalancing(c *oci.Container, enable bool, irqSmpAffinityFile, irqB if !isServiceEnabled(irqBalancedName) || !isIrqConfigExists { if _, err := exec.LookPath(irqBalancedName); err != nil { // irqbalance is not installed, skip the rest; pod should still start, so return nil instead - logrus.Warnf("Irqbalance binary not found: %v", err) + log.Warnf(ctx, "Irqbalance binary not found: %v", err) return nil } // run irqbalance in daemon mode, so this won't cause delay @@ -350,7 +347,7 @@ func setIRQLoadBalancing(c *oci.Container, enable bool, irqSmpAffinityFile, irqB } if err := restartIrqBalanceService(); err != nil { - logrus.Warnf("Irqbalance service restart failed: %v", err) + log.Warnf(ctx, "Irqbalance service restart failed: %v", err) } return nil } @@ -598,7 +595,7 @@ func doSetCPUFreqGovernor(c *oci.Container, governor, cpuDir, cpuSaveDir string) } // RestoreIrqBalanceConfig restores irqbalance service with original banned cpu mask settings -func RestoreIrqBalanceConfig(irqBalanceConfigFile, irqBannedCPUConfigFile, irqSmpAffinityProcFile string) error { +func RestoreIrqBalanceConfig(ctx context.Context, irqBalanceConfigFile, irqBannedCPUConfigFile, irqSmpAffinityProcFile string) error { content, err := os.ReadFile(irqSmpAffinityProcFile) if err != nil { return err @@ -612,15 +609,19 @@ func RestoreIrqBalanceConfig(irqBalanceConfigFile, irqBannedCPUConfigFile, irqSm } if !isAllBitSet(currentMaskArray) { // not system reboot scenario, just return it. + log.Infof(ctx, "Restore irqbalance config: not system reboot, ignoring") return nil } bannedCPUMasks, err := retrieveIrqBannedCPUMasks(irqBalanceConfigFile) if err != nil { // Ignore returning err as given irqBalanceConfigFile may not exist. + log.Infof(ctx, "Restore irqbalance config: failed to get current CPU ban list, ignoring") return nil } + if !fileExists(irqBannedCPUConfigFile) { + log.Infof(ctx, "Creating banned CPU list file %q", irqBannedCPUConfigFile) irqBannedCPUsConfig, err := os.Create(irqBannedCPUConfigFile) if err != nil { return err @@ -630,6 +631,7 @@ func RestoreIrqBalanceConfig(irqBalanceConfigFile, irqBannedCPUConfigFile, irqSm if err != nil { return err } + log.Infof(ctx, "Restore irqbalance config: created backup file") return nil } @@ -640,14 +642,17 @@ func RestoreIrqBalanceConfig(irqBalanceConfigFile, irqBannedCPUConfigFile, irqSm origBannedCPUMasks := strings.TrimSpace(string(content)) if bannedCPUMasks == origBannedCPUMasks { + log.Infof(ctx, "Restore irqbalance config: nothing to do") return nil } + + log.Infof(ctx, "Restore irqbalance banned CPU list in %q to %q", irqBalanceConfigFile, origBannedCPUMasks) if err := updateIrqBalanceConfigFile(irqBalanceConfigFile, origBannedCPUMasks); err != nil { return err } if isServiceEnabled(irqBalancedName) { if err := restartIrqBalanceService(); err != nil { - logrus.Warnf("Irqbalance service restart failed: %v", err) + log.Warnf(ctx, "Irqbalance service restart failed: %v", err) } } return nil diff --git a/internal/runtimehandlerhooks/high_performance_hooks_test.go b/internal/runtimehandlerhooks/high_performance_hooks_test.go index fbf7e6bfcad..7c76043603c 100644 --- a/internal/runtimehandlerhooks/high_performance_hooks_test.go +++ b/internal/runtimehandlerhooks/high_performance_hooks_test.go @@ -111,7 +111,7 @@ var _ = Describe("high_performance_hooks", func() { irqSmpAffinityFile := filepath.Join(fixturesDir, "irq_smp_affinity") irqBalanceConfigFile := filepath.Join(fixturesDir, "irqbalance") verifySetIRQLoadBalancing := func(enabled bool, expected string) { - err := setIRQLoadBalancing(container, enabled, irqSmpAffinityFile, irqBalanceConfigFile) + err := setIRQLoadBalancing(context.TODO(), container, enabled, irqSmpAffinityFile, irqBalanceConfigFile) Expect(err).To(BeNil()) content, err := os.ReadFile(irqSmpAffinityFile) @@ -164,7 +164,7 @@ var _ = Describe("high_performance_hooks", func() { irqSmpAffinityFile := filepath.Join(fixturesDir, "irq_smp_affinity") irqBalanceConfigFile := filepath.Join(fixturesDir, "irqbalance") verifySetIRQLoadBalancing := func(enabled bool, expectedSmp, expectedBan string) { - err = setIRQLoadBalancing(container, enabled, irqSmpAffinityFile, irqBalanceConfigFile) + err = setIRQLoadBalancing(context.TODO(), container, enabled, irqSmpAffinityFile, irqBalanceConfigFile) Expect(err).To(BeNil()) content, err := os.ReadFile(irqSmpAffinityFile) @@ -511,16 +511,16 @@ var _ = Describe("high_performance_hooks", func() { irqBalanceConfigFile := filepath.Join(fixturesDir, "irqbalance") irqBannedCPUConfigFile := filepath.Join(fixturesDir, "orig_irq_banned_cpus") verifyRestoreIrqBalanceConfig := func(expectedOrigBannedCPUs, expectedBannedCPUs string) { - err = RestoreIrqBalanceConfig(irqBalanceConfigFile, irqBannedCPUConfigFile, irqSmpAffinityFile) - Expect(err).To(BeNil()) + err = RestoreIrqBalanceConfig(context.TODO(), irqBalanceConfigFile, irqBannedCPUConfigFile, irqSmpAffinityFile) + ExpectWithOffset(1, err).To(BeNil()) content, err := os.ReadFile(irqBannedCPUConfigFile) - Expect(err).To(BeNil()) - Expect(strings.Trim(string(content), "\n")).To(Equal(expectedOrigBannedCPUs)) + ExpectWithOffset(1, err).To(BeNil()) + ExpectWithOffset(1, strings.Trim(string(content), "\n")).To(Equal(expectedOrigBannedCPUs)) bannedCPUs, err := retrieveIrqBannedCPUMasks(irqBalanceConfigFile) - Expect(err).To(BeNil()) - Expect(bannedCPUs).To(Equal(expectedBannedCPUs)) + ExpectWithOffset(1, err).To(BeNil()) + ExpectWithOffset(1, bannedCPUs).To(Equal(expectedBannedCPUs)) } JustBeforeEach(func() { diff --git a/pkg/config/config.go b/pkg/config/config.go index de0c6786f62..db30370ef4b 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -122,6 +122,8 @@ const ( const ( // DefaultIrqBalanceConfigFile default irqbalance service configuration file path DefaultIrqBalanceConfigFile = "/etc/sysconfig/irqbalance" + // DefaultIrqBalanceConfigRestoreFile contains the banned cpu mask configuration to restore. Name due to backward compatibility. + DefaultIrqBalanceConfigRestoreFile = "/etc/sysconfig/orig_irq_banned_cpus" ) // This structure is necessary to fake the TOML tables when parsing, @@ -397,6 +399,10 @@ type RuntimeConfig struct { // will cause a container creation to fail (as opposed to the current behavior of creating a directory). AbsentMountSourcesToReject []string `toml:"absent_mount_sources_to_reject"` + // IrqBalanceConfigRestoreFile is the irqbalance service banned CPU list to restore. + // If empty, no restoration attempt will be done. + IrqBalanceConfigRestoreFile string `toml:"irqbalance_config_restore_file"` + // seccompConfig is the internal seccomp configuration seccompConfig *seccomp.Config @@ -782,34 +788,35 @@ func DefaultConfig() (*Config, error) { Runtimes: Runtimes{ defaultRuntime: defaultRuntimeHandler(), }, - SELinux: selinuxEnabled(), - ApparmorProfile: apparmor.DefaultProfile, - BlockIOConfigFile: DefaultBlockIOConfigFile, - IrqBalanceConfigFile: DefaultIrqBalanceConfigFile, - RdtConfigFile: rdt.DefaultRdtConfigFile, - CgroupManagerName: cgroupManager.Name(), - PidsLimit: DefaultPidsLimit, - ContainerExitsDir: containerExitsDir, - ContainerAttachSocketDir: conmonconfig.ContainerAttachSocketDir, - MinimumMappableUID: -1, - MinimumMappableGID: -1, - LogSizeMax: DefaultLogSizeMax, - CtrStopTimeout: defaultCtrStopTimeout, - DefaultCapabilities: capabilities.Default(), - LogLevel: "info", - HooksDir: []string{hooks.DefaultDir}, - CDISpecDirs: cdi.DefaultSpecDirs, - NamespacesDir: defaultNamespacesDir, - DropInfraCtr: true, - SeccompUseDefaultWhenEmpty: seccompConfig.UseDefaultWhenEmpty(), - seccompConfig: seccomp.New(), - apparmorConfig: apparmor.New(), - blockioConfig: blockio.New(), - cgroupManager: cgroupManager, - deviceConfig: device.New(), - namespaceManager: nsmgr.New(defaultNamespacesDir, ""), - rdtConfig: rdt.New(), - ulimitsConfig: ulimits.New(), + SELinux: selinuxEnabled(), + ApparmorProfile: apparmor.DefaultProfile, + BlockIOConfigFile: DefaultBlockIOConfigFile, + IrqBalanceConfigFile: DefaultIrqBalanceConfigFile, + RdtConfigFile: rdt.DefaultRdtConfigFile, + CgroupManagerName: cgroupManager.Name(), + PidsLimit: DefaultPidsLimit, + ContainerExitsDir: containerExitsDir, + ContainerAttachSocketDir: conmonconfig.ContainerAttachSocketDir, + MinimumMappableUID: -1, + MinimumMappableGID: -1, + LogSizeMax: DefaultLogSizeMax, + CtrStopTimeout: defaultCtrStopTimeout, + DefaultCapabilities: capabilities.Default(), + LogLevel: "info", + HooksDir: []string{hooks.DefaultDir}, + CDISpecDirs: cdi.DefaultSpecDirs, + NamespacesDir: defaultNamespacesDir, + DropInfraCtr: true, + SeccompUseDefaultWhenEmpty: seccompConfig.UseDefaultWhenEmpty(), + IrqBalanceConfigRestoreFile: DefaultIrqBalanceConfigRestoreFile, + seccompConfig: seccomp.New(), + apparmorConfig: apparmor.New(), + blockioConfig: blockio.New(), + cgroupManager: cgroupManager, + deviceConfig: device.New(), + namespaceManager: nsmgr.New(defaultNamespacesDir, ""), + rdtConfig: rdt.New(), + ulimitsConfig: ulimits.New(), }, ImageConfig: ImageConfig{ DefaultTransport: "docker://", diff --git a/pkg/config/template.go b/pkg/config/template.go index 9c60408ee75..12aac836e40 100644 --- a/pkg/config/template.go +++ b/pkg/config/template.go @@ -427,6 +427,11 @@ func initCrioTemplateConfig(c *Config) ([]*templateConfigValue, error) { group: crioRuntimeConfig, isDefaultValue: WorkloadsEqual(dc.Workloads, c.Workloads), }, + { + templateString: templateStringIrqBalanceConfigRestoreFile, + group: crioRuntimeConfig, + isDefaultValue: simpleEqual(dc.IrqBalanceConfigRestoreFile, c.IrqBalanceConfigRestoreFile), + }, { templateString: templateStringCrioImageDefaultTransport, group: crioImageConfig, @@ -1022,6 +1027,13 @@ const templateStringCrioRuntimeDropInfraCtr = `# drop_infra_ctr determines wheth ` +const templateStringIrqBalanceConfigRestoreFile = `# irqbalance_config_restore_file allows to set a cpu mask CRI-O should +# restore as irqbalance config at startup. Set to empty string to disable this flow entirely. +# By default, CRI-O manages the irqbalance configuration to enable dynamic IRQ pinning. +{{ $.Comment }}irqbalance_config_restore_file = "{{ .IrqBalanceConfigRestoreFile }}" + +` + const templateStringCrioRuntimeInfraCtrCpuset = `# infra_ctr_cpuset determines what CPUs will be used to run infra containers. # You can use linux CPU list format to specify desired CPUs. # To get better isolation for guaranteed pods, set this parameter to be equal to kubelet reserved-cpus. diff --git a/server/server.go b/server/server.go index b96461bcae0..95ff865e2d9 100644 --- a/server/server.go +++ b/server/server.go @@ -395,9 +395,12 @@ func New( return nil, err } - err = runtimehandlerhooks.RestoreIrqBalanceConfig(config.IrqBalanceConfigFile, runtimehandlerhooks.IrqBannedCPUConfigFile, runtimehandlerhooks.IrqSmpAffinityProcFile) - if err != nil { - return nil, err + if config.IrqBalanceConfigRestoreFile != "" { + log.Infof(ctx, "Attempting to restore irqbalance config from %s", config.IrqBalanceConfigRestoreFile) + err = runtimehandlerhooks.RestoreIrqBalanceConfig(context.TODO(), config.IrqBalanceConfigFile, config.IrqBalanceConfigRestoreFile, runtimehandlerhooks.IrqSmpAffinityProcFile) + if err != nil { + return nil, err + } } hostportManager := hostport.NewMetaHostportManager() diff --git a/test/irqbalance.bats b/test/irqbalance.bats new file mode 100644 index 00000000000..c4d57357b3d --- /dev/null +++ b/test/irqbalance.bats @@ -0,0 +1,99 @@ +#!/usr/bin/env bats +# vim: set syntax=sh: + +load helpers + +function detect_irqbalance_config() { + # debian/ubuntu + [ -f /etc/default/irqbalance ] && echo "/etc/default/irqbalance" + # fedora/centos/RHEL + [ -f /etc/sysconfig/irqbalance ] && echo "/etc/sysconfig/irqbalance" + # default - we need to have something! + echo "/etc/sysconfig/irqbalance" +} + +CONFIGLET="$CRIO_CONFIG_DIR/99-irqbalance.conf" +IRQBALANCE_CONF=$(detect_irqbalance_config) +# default setting +BANNEDCPUS_CONF="/etc/sysconfig/orig_irq_banned_cpus" + +function setup() { + setup_test + start_crio + # we don't uncondintionally restore because the irqbalance package may be missing + # from the test system. if this is the case, one less thing to worry about, we can't + # pollute the system state anyway :) + if [ -f "$IRQBALANCE_CONF" ]; then + cp -v "$IRQBALANCE_CONF" "$IRQBALANCE_CONF".bkp + else + # placeholder to make the rest of the suite simpler. + # note it's intentionally commented. + echo "# IRQBALANCE_BANNED_CPUS=" > "$IRQBALANCE_CONF" + touch /tmp/.test_owns_irqbalance_conf + fi + if [ -f ${BANNEDCPUS_CONF} ]; then + cp -v "$BANNEDCPUS_CONF" "$BANNEDCPUS_CONF".bkp + else + # empty file is fine and meaningful + touch "$BANNEDCPUS_CONF" + touch /tmp/.test_owns_bannedcpus_conf + fi +} + +function teardown() { + cleanup_test + # see setup about why we have these conditionals + if [ -f "$IRQBALANCE_CONF".bkp ]; then + mv -v "$IRQBALANCE_CONF".bkp "$IRQBALANCE_CONF" + elif [ -f /tmp/.test_owns_irqbalance_conf ]; then + rm -f "$IRQBALANCE_CONF" + rm -f /tmp/.test_owns_irqbalance_conf + # else how come? + fi + if [ -f "$BANNEDCPUS_CONF".bkp ]; then + mv -v "$BANNEDCPUS_CONF".bkp "$BANNEDCPUS_CONF" + elif [ -f /tmp/.test_owns_bannedcpus_conf ]; then + rm -f "$BANNEDCPUS_CONF" + rm -f /tmp/.test_owns_bannedcpus_conf + fi +} + +@test "irqbalance cpu ban list save" { + # given + if ! grep -Eq '^f{1,}$' /proc/irq/default_irq_smp_affinity; then + skip "requires default IRQ smp affinity (not banned CPUs)" + fi + [ -f "$CONFIGLET" ] && rm -f "$CONFIGLET" + + [ -f "$BANNEDCPUS_CONF" ] && rm -f "$BANNEDCPUS_CONF" + + # when + restart_crio + + # then + len=$(awk 'END {print NR}' "$BANNEDCPUS_CONF") + [ "$len" -eq 0 ] +} + +@test "irqbalance cpu ban list restore - default" { + # given + if ! grep -Eq '^f{1,}$' /proc/irq/default_irq_smp_affinity; then + skip "requires default IRQ smp affinity (not banned CPUs)" + fi + [ -f "$CONFIGLET" ] && rm -f "$CONFIGLET" + + truncate -s 0 "$BANNEDCPUS_CONF" + + # whem + restart_crio + + # then + len=$(awk 'END {print NR}' "$BANNEDCPUS_CONF") + [ "$len" -eq 0 ] + banned_cpus=$(sed -n 's/^IRQBALANCE_BANNED_CPUS=\(.*\)/\1/p' "$IRQBALANCE_CONF") + [ -z "$banned_cpus" ] +} + +# disable restore file, check it does NOT clear the irqbalance config + +# explicit restore file, check it does SET the irqbalance config accordingly