]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
cephadm: Make sysctl conf writing idempotent 46648/head
authorZack Cerza <zack@redhat.com>
Mon, 13 Jun 2022 17:12:23 +0000 (11:12 -0600)
committerZack Cerza <zack@redhat.com>
Tue, 14 Jun 2022 16:28:08 +0000 (10:28 -0600)
By checking the system's actual settings against our desired settings
before writing out the config file.

Fixes: https://tracker.ceph.com/issues/56026
Signed-off-by: Zack Cerza <zack@redhat.com>
src/cephadm/cephadm
src/cephadm/tests/test_cephadm.py

index a238087a00edd907b6f68d7f0892d78d1b5a2847..f6a625d1db5997a9c370edd5e33091ad2824693e 100755 (executable)
@@ -3532,7 +3532,7 @@ def install_sysctl(ctx: CephadmContext, fsid: str, daemon_type: str) -> None:
             f.write('\n'.join(lines))
 
     conf = Path(ctx.sysctl_dir).joinpath(f'90-ceph-{fsid}-{daemon_type}.conf')
-    lines: Optional[List] = None
+    lines: List = []
 
     if daemon_type == 'osd':
         lines = OSD.get_sysctl_settings()
@@ -3540,6 +3540,7 @@ def install_sysctl(ctx: CephadmContext, fsid: str, daemon_type: str) -> None:
         lines = HAproxy.get_sysctl_settings()
     elif daemon_type == 'keepalived':
         lines = Keepalived.get_sysctl_settings()
+    lines = filter_sysctl_settings(ctx, lines)
 
     # apply the sysctl settings
     if lines:
@@ -3548,6 +3549,35 @@ def install_sysctl(ctx: CephadmContext, fsid: str, daemon_type: str) -> None:
         call_throws(ctx, ['sysctl', '--system'])
 
 
+def sysctl_get(ctx: CephadmContext, variable: str) -> Union[str, None]:
+    """
+    Read a sysctl setting by executing 'sysctl -b {variable}'
+    """
+    out, err, code = call(ctx, ['sysctl', '-b', variable])
+    return out or None
+
+
+def filter_sysctl_settings(ctx: CephadmContext, lines: List[str]) -> List[str]:
+    """
+    Given a list of sysctl settings, examine the system's current configuration
+    and return those which are not currently set as described.
+    """
+    def test_setting(desired_line: str) -> bool:
+        # Remove any comments
+        comment_start = desired_line.find('#')
+        if comment_start != -1:
+            desired_line = desired_line[:comment_start]
+        desired_line = desired_line.strip()
+        if not desired_line or desired_line.isspace():
+            return False
+        setting, desired_value = map(lambda s: s.strip(), desired_line.split('='))
+        if not setting or not desired_value:
+            return False
+        actual_value = sysctl_get(ctx, setting)
+        return desired_value != actual_value
+    return list(filter(test_setting, lines))
+
+
 def migrate_sysctl_dir(ctx: CephadmContext, fsid: str) -> None:
     """
     Cephadm once used '/usr/lib/sysctl.d' for storing sysctl configuration.
index 604d0234492542546b73ac35bce74703e9865653..58701e43db6ff5ffced857bc5852fb39addee7f8 100644 (file)
@@ -2323,4 +2323,44 @@ class TestNetworkValidation:
 
         # invalid IPv6 and valid subnets list
         with pytest.raises(Exception):
-            rc = cd.ip_in_sublets('fe80:2030:31:24', 'fe80::/64')
\ No newline at end of file
+            rc = cd.ip_in_sublets('fe80:2030:31:24', 'fe80::/64')
+
+
+class TestSysctl:
+    @mock.patch('cephadm.sysctl_get')
+    def test_filter_sysctl_settings(self, sysctl_get):
+        ctx = cd.CephadmContext()
+        input = [
+            # comment-only lines should be ignored
+            "# just a comment",
+            # As should whitespace-only lines",
+            "   \t ",
+            "   =  \t  ",
+            # inline comments are stripped when querying
+            "something = value # inline comment",
+            "fs.aio-max-nr = 1048576",
+            "kernel.pid_max = 4194304",
+            "vm.lowmem_reserve_ratio = 256\t256\t32\t0\t0",
+            "  vm.max_map_count       =            65530    ",
+            "  vm.max_map_count       =            65530    ",
+        ]
+        sysctl_get.side_effect = [
+            "value",
+            "1",
+            "4194304",
+            "256\t256\t32\t0\t0",
+            "65530",
+            "something else",
+        ]
+        result = cd.filter_sysctl_settings(ctx, input)
+        assert len(sysctl_get.call_args_list) == 6
+        assert sysctl_get.call_args_list[0].args[1] == "something"
+        assert sysctl_get.call_args_list[1].args[1] == "fs.aio-max-nr"
+        assert sysctl_get.call_args_list[2].args[1] == "kernel.pid_max"
+        assert sysctl_get.call_args_list[3].args[1] == "vm.lowmem_reserve_ratio"
+        assert sysctl_get.call_args_list[4].args[1] == "vm.max_map_count"
+        assert sysctl_get.call_args_list[5].args[1] == "vm.max_map_count"
+        assert result == [
+            "fs.aio-max-nr = 1048576",
+            "  vm.max_map_count       =            65530    ",
+        ]