Class: CFA::Sysctl

Inherits:
BaseModel
  • Object
show all
Includes:
Yast::Logger
Defined in:
library/general/src/lib/cfa/sysctl.rb

Overview

CFA based API to adjust the sysctl tool configuration

This class does not modify the running kernel configuration. It just writes the desired values into the configuration file (PATH).

Although in the previous example we enabled the IPv4 forwarding using by setting +forward_ipv4+ to true. However, under the hood, the kernel maps boolean values to "1" or "0". If you want to access to that raw value, you can prepend "raw_" to the method's name.

NOTE: This class only handles "/etc/sysctl.d/70-yast.conf" and /etc/sysctl.conf. But sysctl values will also be handled by other files/directories. This will be managed by class SysctlConfig. So please use SysctlConfig in order to read/write sysctl values.

Examples:

Enabling IPv4 forwarding

sysctl = Sysctl.new
sysctl.forward_ipv4 = true
sysctl.save

Accessing the raw value of a setting

sysctl = Sysctl.new
sysctl.load
sysctl.raw_forward_ipv6 #=> "0"
sysctl.raw_forward_ipv6 = "1"

Constant Summary collapse

PATH =
"/etc/sysctl.d/70-yast.conf".freeze
ATTRIBUTES =
{
  kernel_sysrq:            "kernel.sysrq",
  forward_ipv4:            "net.ipv4.ip_forward",
  # FIXME: alias for ipv6_forwarding_all
  forward_ipv6:            "net.ipv6.conf.all.forwarding",
  ipv4_forwarding_default: "net.ipv4.conf.default.forwarding",
  ipv4_forwarding_all:     "net.ipv4.conf.all.forwarding",
  ipv6_forwarding_default: "net.ipv6.conf.default.forwarding",
  ipv6_forwarding_all:     "net.ipv6.conf.all.forwarding",
  tcp_syncookies:          "net.ipv4.tcp_syncookies",
  disable_ipv6:            "net.ipv6.conf.all.disable_ipv6"
}.freeze
BOOLEAN_ATTRIBUTES =
[
  :forward_ipv4, :forward_ipv6, :tcp_syncookies, :disable_ipv6,
  :ipv4_forwarding_default, :ipv4_forwarding_all, :ipv6_forwarding_default,
  :ipv6_forwarding_all
].freeze
KNOWN_KEYS =

Keys that are handled by this class

ATTRIBUTES.values.uniq.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file_handler: Yast::TargetFile, file_path: PATH) ⇒ Sysctl

Returns a new instance of Sysctl.



117
118
119
# File 'library/general/src/lib/cfa/sysctl.rb', line 117

def initialize(file_handler: Yast::TargetFile, file_path: PATH)
  super(AugeasParser.new("sysctl.lns"), file_path, file_handler: file_handler)
end

Instance Attribute Details

#file_pathObject (readonly)

Returns the value of attribute file_path.



110
111
112
# File 'library/general/src/lib/cfa/sysctl.rb', line 110

def file_path
  @file_path
end

Class Method Details

.boolean_attr(*attrs) ⇒ Object

Modifies default CFA methods to handle boolean values

When getting or setting the value, a boolean value will be expected. Under the hood, it will be translated into "1" or "0". Additionally, to access to the raw value ("1", "0" or +nil+), just prepend "raw_" to the name of the method. Bear in mind that if the raw value is +nil+, it will be considered +false+.

Parameters:

  • attrs (Array<Symbol>)

    Attribute name



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'library/general/src/lib/cfa/sysctl.rb', line 71

def boolean_attr(*attrs)
  attrs.each do |attr|
    raw_attr = "raw_#{attr}"
    alias_method raw_attr, attr
    define_method attr do
      public_send(raw_attr) == "1"
    end
    alias_method "#{attr}?", attr

    alias_method "#{raw_attr}=", "#{attr}="
    define_method "#{attr}=" do |value|
      str_value = value ? "1" : "0"
      public_send("#{raw_attr}=", str_value)
    end
  end
end

.known_attributesObject



58
59
60
61
# File 'library/general/src/lib/cfa/sysctl.rb', line 58

def known_attributes
  # Returning all attributes
  ATTRIBUTES.keys
end

Instance Method Details

#conflicts(other) ⇒ Array<Symbol>

Determines the list of conflicting attributes for two files

Two attributes are conflicting when both of them are defined with different values.

Parameters:

  • other (BaseModel)

    The file to compare with

Returns:

  • (Array<Symbol>)

    List of conflicting attributes



179
180
181
182
# File 'library/general/src/lib/cfa/sysctl.rb', line 179

def conflicts(other)
  conflicting_attrs = present_attributes & other.present_attributes
  conflicting_attrs.reject { |a| public_send(a) == other.public_send(a) }
end

#empty?Boolean

Returns:

  • (Boolean)


121
122
123
124
# File 'library/general/src/lib/cfa/sysctl.rb', line 121

def empty?
  # FIXME: AugeasTree should implement #empty?
  data.data.empty?
end

#loadObject

Loads sysctl content

This method reads PATH and uses +/etc/sysctl.conf+ values as fallback.



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'library/general/src/lib/cfa/sysctl.rb', line 129

def load
  begin
    super
  rescue Errno::ENOENT # PATH does not exist yet
    self.data = @parser.empty
    @loaded = true
  end

  KNOWN_KEYS.each do |key|
    next if data[key]

    old_value = Yast::SCR.Read(SYSCTL_AGENT_PATH + key)
    data[key] = old_value if old_value
  end
  nil
end

#present?(attr) ⇒ Boolean

Returns:

  • (Boolean)


160
161
162
# File 'library/general/src/lib/cfa/sysctl.rb', line 160

def present?(attr)
  !send(method_name(attr)).nil?
end

#present_attributesArray<Symbol>

Returns the list of attributes

Returns:

  • (Array<Symbol>)

    List of attribute names

See Also:



168
169
170
# File 'library/general/src/lib/cfa/sysctl.rb', line 168

def present_attributes
  self.class.known_attributes.select { |a| present?(a) }
end

#saveObject

Writes sysctl configuration

Apart from writing the values to PATH, it cleans up the same entries in +/etc/sysctl.conf+ to avoid confusion.



150
151
152
153
154
155
156
157
158
# File 'library/general/src/lib/cfa/sysctl.rb', line 150

def save
  super

  # we cannot update /etc/sysctl.conf in first stage as it is on ro filesystem
  # we also cannot use File.stat("/etc/sysctl.conf").writable? as it only checks
  # file attributes. However, attributes are fine in inst-sys but the file is on
  # ro filesystem.
  clean_old_values if !Yast::Stage.initial
end