Merge pull request #555 from MarSik/fix-sysctl-path
RHEL-3707: Add support for sysctl names with slash
This commit is contained in:
commit
96819b967c
2 changed files with 111 additions and 99 deletions
|
|
@ -66,7 +66,7 @@ class SysctlPlugin(base.Plugin):
|
|||
|
||||
def _instance_apply_static(self, instance):
|
||||
for option, value in list(instance._sysctl.items()):
|
||||
original_value = _read_sysctl(option)
|
||||
original_value = self._read_sysctl(option)
|
||||
if original_value is None:
|
||||
log.error("sysctl option %s will not be set, failed to read the original value."
|
||||
% option)
|
||||
|
|
@ -77,21 +77,21 @@ class SysctlPlugin(base.Plugin):
|
|||
new_value, original_value)
|
||||
if new_value is not None:
|
||||
instance._sysctl_original[option] = original_value
|
||||
_write_sysctl(option, new_value)
|
||||
self._write_sysctl(option, new_value)
|
||||
|
||||
storage_key = self._storage_key(instance.name)
|
||||
self._storage.set(storage_key, instance._sysctl_original)
|
||||
|
||||
if self._global_cfg.get_bool(consts.CFG_REAPPLY_SYSCTL, consts.CFG_DEF_REAPPLY_SYSCTL):
|
||||
log.info("reapplying system sysctl")
|
||||
_apply_system_sysctl(instance._sysctl)
|
||||
self._apply_system_sysctl(instance._sysctl)
|
||||
|
||||
def _instance_verify_static(self, instance, ignore_missing, devices):
|
||||
ret = True
|
||||
# override, so always skip missing
|
||||
ignore_missing = True
|
||||
for option, value in list(instance._sysctl.items()):
|
||||
curr_val = _read_sysctl(option)
|
||||
curr_val = self._read_sysctl(option)
|
||||
value = self._process_assignment_modifiers(self._variables.expand(value), curr_val)
|
||||
if value is not None:
|
||||
if self._verify_value(option, self._cmd.remove_ws(value), self._cmd.remove_ws(curr_val), ignore_missing) == False:
|
||||
|
|
@ -100,107 +100,110 @@ class SysctlPlugin(base.Plugin):
|
|||
|
||||
def _instance_unapply_static(self, instance, rollback = consts.ROLLBACK_SOFT):
|
||||
for option, value in list(instance._sysctl_original.items()):
|
||||
_write_sysctl(option, value)
|
||||
self._write_sysctl(option, value)
|
||||
|
||||
|
||||
def _apply_system_sysctl(instance_sysctl):
|
||||
files = {}
|
||||
for d in SYSCTL_CONFIG_DIRS:
|
||||
try:
|
||||
flist = os.listdir(d)
|
||||
except OSError:
|
||||
continue
|
||||
for fname in flist:
|
||||
if not fname.endswith(".conf"):
|
||||
def _apply_system_sysctl(self, instance_sysctl):
|
||||
files = {}
|
||||
for d in SYSCTL_CONFIG_DIRS:
|
||||
try:
|
||||
flist = os.listdir(d)
|
||||
except OSError:
|
||||
continue
|
||||
if fname not in files:
|
||||
files[fname] = d
|
||||
for fname in flist:
|
||||
if not fname.endswith(".conf"):
|
||||
continue
|
||||
if fname not in files:
|
||||
files[fname] = d
|
||||
|
||||
for fname in sorted(files.keys()):
|
||||
d = files[fname]
|
||||
path = "%s/%s" % (d, fname)
|
||||
_apply_sysctl_config_file(path, instance_sysctl)
|
||||
_apply_sysctl_config_file("/etc/sysctl.conf", instance_sysctl)
|
||||
for fname in sorted(files.keys()):
|
||||
d = files[fname]
|
||||
path = "%s/%s" % (d, fname)
|
||||
self._apply_sysctl_config_file(path, instance_sysctl)
|
||||
self._apply_sysctl_config_file("/etc/sysctl.conf", instance_sysctl)
|
||||
|
||||
def _apply_sysctl_config_file(path, instance_sysctl):
|
||||
log.debug("Applying sysctl settings from file %s" % path)
|
||||
try:
|
||||
with open(path, "r") as f:
|
||||
for lineno, line in enumerate(f, 1):
|
||||
_apply_sysctl_config_line(path, lineno, line, instance_sysctl)
|
||||
log.debug("Finished applying sysctl settings from file %s"
|
||||
% path)
|
||||
except (OSError, IOError) as e:
|
||||
if e.errno != errno.ENOENT:
|
||||
log.error("Error reading sysctl settings from file %s: %s"
|
||||
% (path, str(e)))
|
||||
def _apply_sysctl_config_file(self, path, instance_sysctl):
|
||||
log.debug("Applying sysctl settings from file %s" % path)
|
||||
try:
|
||||
with open(path, "r") as f:
|
||||
for lineno, line in enumerate(f, 1):
|
||||
self._apply_sysctl_config_line(path, lineno, line, instance_sysctl)
|
||||
log.debug("Finished applying sysctl settings from file %s"
|
||||
% path)
|
||||
except (OSError, IOError) as e:
|
||||
if e.errno != errno.ENOENT:
|
||||
log.error("Error reading sysctl settings from file %s: %s"
|
||||
% (path, str(e)))
|
||||
|
||||
def _apply_sysctl_config_line(path, lineno, line, instance_sysctl):
|
||||
line = line.strip()
|
||||
if len(line) == 0 or line[0] == "#" or line[0] == ";":
|
||||
return
|
||||
tmp = line.split("=", 1)
|
||||
if len(tmp) != 2:
|
||||
log.error("Syntax error in file %s, line %d"
|
||||
% (path, lineno))
|
||||
return
|
||||
option, value = tmp
|
||||
option = option.strip()
|
||||
if len(option) == 0:
|
||||
log.error("Syntax error in file %s, line %d"
|
||||
% (path, lineno))
|
||||
return
|
||||
value = value.strip()
|
||||
if option in instance_sysctl and instance_sysctl[option] != value:
|
||||
log.info("Overriding sysctl parameter '%s' from '%s' to '%s'"
|
||||
% (option, instance_sysctl[option], value))
|
||||
def _apply_sysctl_config_line(self, path, lineno, line, instance_sysctl):
|
||||
line = line.strip()
|
||||
if len(line) == 0 or line[0] == "#" or line[0] == ";":
|
||||
return
|
||||
tmp = line.split("=", 1)
|
||||
if len(tmp) != 2:
|
||||
log.error("Syntax error in file %s, line %d"
|
||||
% (path, lineno))
|
||||
return
|
||||
option, value = tmp
|
||||
option = option.strip()
|
||||
if len(option) == 0:
|
||||
log.error("Syntax error in file %s, line %d"
|
||||
% (path, lineno))
|
||||
return
|
||||
value = value.strip()
|
||||
if option in instance_sysctl and instance_sysctl[option] != value:
|
||||
log.info("Overriding sysctl parameter '%s' from '%s' to '%s'"
|
||||
% (option, instance_sysctl[option], value))
|
||||
|
||||
_write_sysctl(option, value, ignore_missing = True)
|
||||
self._write_sysctl(option, value, ignore_missing = True)
|
||||
|
||||
def _get_sysctl_path(option):
|
||||
return "/proc/sys/%s" % option.replace(".", "/")
|
||||
def _get_sysctl_path(self, option):
|
||||
# The sysctl name in sysctl tool and in /proc/sys differs.
|
||||
# All dots (.) in sysctl name are represented by /proc/sys
|
||||
# directories and all slashes in the name (/) are converted
|
||||
# to dots (.) in the /proc/sys filenames.
|
||||
return "/proc/sys/%s" % self._cmd.tr(option, "./", "/.")
|
||||
|
||||
def _read_sysctl(option):
|
||||
path = _get_sysctl_path(option)
|
||||
try:
|
||||
with open(path, "r") as f:
|
||||
line = ""
|
||||
for i, line in enumerate(f):
|
||||
if i > 0:
|
||||
log.error("Failed to read sysctl parameter '%s', multi-line values are unsupported"
|
||||
% option)
|
||||
return None
|
||||
value = line.strip()
|
||||
log.debug("Value of sysctl parameter '%s' is '%s'"
|
||||
% (option, value))
|
||||
return value
|
||||
except (OSError, IOError) as e:
|
||||
if e.errno == errno.ENOENT:
|
||||
log.error("Failed to read sysctl parameter '%s', the parameter does not exist"
|
||||
% option)
|
||||
else:
|
||||
log.error("Failed to read sysctl parameter '%s': %s"
|
||||
% (option, str(e)))
|
||||
return None
|
||||
|
||||
def _write_sysctl(option, value, ignore_missing = False):
|
||||
path = _get_sysctl_path(option)
|
||||
if os.path.basename(path) in DEPRECATED_SYSCTL_OPTIONS:
|
||||
log.error("Refusing to set deprecated sysctl option %s"
|
||||
% option)
|
||||
return False
|
||||
try:
|
||||
log.debug("Setting sysctl parameter '%s' to '%s'"
|
||||
% (option, value))
|
||||
with open(path, "w") as f:
|
||||
f.write(value)
|
||||
return True
|
||||
except (OSError, IOError) as e:
|
||||
if e.errno == errno.ENOENT:
|
||||
log_func = log.debug if ignore_missing else log.error
|
||||
log_func("Failed to set sysctl parameter '%s' to '%s', the parameter does not exist"
|
||||
def _read_sysctl(self, option):
|
||||
path = self._get_sysctl_path(option)
|
||||
try:
|
||||
with open(path, "r") as f:
|
||||
line = ""
|
||||
for i, line in enumerate(f):
|
||||
if i > 0:
|
||||
log.error("Failed to read sysctl parameter '%s', multi-line values are unsupported"
|
||||
% option)
|
||||
return None
|
||||
value = line.strip()
|
||||
log.debug("Value of sysctl parameter '%s' is '%s'"
|
||||
% (option, value))
|
||||
else:
|
||||
log.error("Failed to set sysctl parameter '%s' to '%s': %s"
|
||||
% (option, value, str(e)))
|
||||
return False
|
||||
return value
|
||||
except (OSError, IOError) as e:
|
||||
if e.errno == errno.ENOENT:
|
||||
log.error("Failed to read sysctl parameter '%s', the parameter does not exist"
|
||||
% option)
|
||||
else:
|
||||
log.error("Failed to read sysctl parameter '%s': %s"
|
||||
% (option, str(e)))
|
||||
return None
|
||||
|
||||
def _write_sysctl(self, option, value, ignore_missing = False):
|
||||
path = self._get_sysctl_path(option)
|
||||
if os.path.basename(path) in DEPRECATED_SYSCTL_OPTIONS:
|
||||
log.error("Refusing to set deprecated sysctl option %s"
|
||||
% option)
|
||||
return False
|
||||
try:
|
||||
log.debug("Setting sysctl parameter '%s' to '%s'"
|
||||
% (option, value))
|
||||
with open(path, "w") as f:
|
||||
f.write(value)
|
||||
return True
|
||||
except (OSError, IOError) as e:
|
||||
if e.errno == errno.ENOENT:
|
||||
log_func = log.debug if ignore_missing else log.error
|
||||
log_func("Failed to set sysctl parameter '%s' to '%s', the parameter does not exist"
|
||||
% (option, value))
|
||||
else:
|
||||
log.error("Failed to set sysctl parameter '%s' to '%s': %s"
|
||||
% (option, value, str(e)))
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -523,3 +523,12 @@ class commands:
|
|||
f.write(profile_name + "\n")
|
||||
except (OSError,IOError) as e:
|
||||
raise TunedException("Failed to save the active post-loaded profile: %s" % e.strerror)
|
||||
|
||||
# Translates characters in 'text' from 'source_chars' to 'dest_chars'
|
||||
def tr(self, text, source_chars, dest_chars):
|
||||
try:
|
||||
trans = str.maketrans(source_chars, dest_chars)
|
||||
except AttributeError:
|
||||
import string
|
||||
trans = string.maketrans(source_chars, dest_chars)
|
||||
return text.translate(trans)
|
||||
|
|
|
|||
Loading…
Reference in a new issue