]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
pybind/mgr/pg_autoscaler: noautoscale flag retains individual pool configs
authorKamoltat <ksirivad@redhat.com>
Thu, 13 Jul 2023 18:23:13 +0000 (18:23 +0000)
committerKamoltat <ksirivad@redhat.com>
Tue, 19 Sep 2023 15:03:07 +0000 (15:03 +0000)
Problem:

The pg_autoscaler `noautoscale flag` doesn't retain individual pool states of
`autoscale mode`. For example turn the flag `ON` and then `OFF` again all
the pools will have `autoscale mode on` which is inconvenience for the user
because sometimes the user just want to temporary disable the autoscaler on
all pools and will enable it back after a period of time while retaining
individual pool states of `autoscale mode`

Solution:

We store noautoscale flag in the OSDMAP such that it is
persistent. We then get rid of noautoscale MODULE OPTION
in the pg_autoscaler module since we do not need it anymore.
Everytime we set, unset or get the flag we rely on looking up
the OSDMAP, we did this because we want to avoid inconsistancy
between the `noautoscale flag`. This is because `noautoscale flag`
can easily be set by doing `ceph osd set noautoscale`.

Fixes: https://tracker.ceph.com/issues/61922
Signed-off-by: Kamoltat <ksirivad@redhat.com>
src/include/rados.h
src/mon/MonCommands.h
src/mon/OSDMonitor.cc
src/osd/OSDMap.cc
src/pybind/mgr/pg_autoscaler/module.py

index 55cfdcb7871e683b39fa4cbe6ccfdb4cdf166500..eac3a2159bf8803a5f486714e7c360d7f891c42b 100644 (file)
@@ -172,6 +172,7 @@ extern const char *ceph_osd_state_name(int s);
 #define CEPH_OSDMAP_PURGED_SNAPDIRS  (1<<20) /* osds have converted snapsets */
 #define CEPH_OSDMAP_NOSNAPTRIM       (1<<21) /* disable snap trimming */
 #define CEPH_OSDMAP_PGLOG_HARDLIMIT  (1<<22) /* put a hard limit on pg log length */
+#define CEPH_OSDMAP_NOAUTOSCALE      (1<<23)  /* block pg autoscale */
 
 /* these are hidden in 'ceph status' view */
 #define CEPH_OSDMAP_SEMIHIDDEN_FLAGS (CEPH_OSDMAP_REQUIRE_JEWEL|       \
index 05fda59b1735b55976d844fc43652682e1ebbce6..74ef2206c02bf9402b72846ca52faf427332bc0b 100644 (file)
@@ -843,13 +843,13 @@ COMMAND("osd erasure-code-profile ls",
 COMMAND("osd set "
        "name=key,type=CephChoices,strings=full|pause|noup|nodown|"
        "noout|noin|nobackfill|norebalance|norecover|noscrub|nodeep-scrub|"
-       "notieragent|nosnaptrim|pglog_hardlimit "
+       "notieragent|nosnaptrim|pglog_hardlimit|noautoscale "
         "name=yes_i_really_mean_it,type=CephBool,req=false",
        "set <key>", "osd", "rw")
 COMMAND("osd unset "
        "name=key,type=CephChoices,strings=full|pause|noup|nodown|"\
        "noout|noin|nobackfill|norebalance|norecover|noscrub|nodeep-scrub|"
-       "notieragent|nosnaptrim",
+       "notieragent|nosnaptrim|noautoscale",
        "unset <key>", "osd", "rw")
 COMMAND("osd require-osd-release "\
        "name=release,type=CephChoices,strings=octopus|pacific|quincy|reef "
index 4e3f862b77eb3c3745757cb1f97d8807da54b115..879448f77e7cd5da2711480f288ef4fb6af1fab8 100644 (file)
@@ -11598,6 +11598,8 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
        err = -EPERM;
        goto reply_no_propose;
       }
+    } else if (key == "noautoscale") {
+      return prepare_set_flag(op, CEPH_OSDMAP_NOAUTOSCALE);
     } else {
       ss << "unrecognized flag '" << key << "'";
       err = -EINVAL;
@@ -11630,6 +11632,8 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       return prepare_unset_flag(op, CEPH_OSDMAP_NOTIERAGENT);
     else if (key == "nosnaptrim")
       return prepare_unset_flag(op, CEPH_OSDMAP_NOSNAPTRIM);
+    else if (key == "noautoscale")
+      return prepare_unset_flag(op, CEPH_OSDMAP_NOAUTOSCALE);
     else {
       ss << "unrecognized flag '" << key << "'";
       err = -EINVAL;
index 29af378f9654e1409669bf073ad3228c1a245b2e..4a2d400b6703486e387599c17125204a9569341b 100644 (file)
@@ -4108,6 +4108,8 @@ string OSDMap::get_flag_string(unsigned f)
     s += ",purged_snapdirs";
   if (f & CEPH_OSDMAP_PGLOG_HARDLIMIT)
     s += ",pglog_hardlimit";
+  if (f & CEPH_OSDMAP_NOAUTOSCALE)
+    s += ",noautoscale";
   if (s.length())
     s.erase(0, 1);
   return s;
index 52fd549317e1ddcfc670dd6f750728d16a0ada01..7cda39a06e976597416cb4fb7eaaa3e162ef7923 100644 (file)
@@ -135,12 +135,6 @@ class PgAutoscaler(MgrModule):
                        '`PG_NUM` before being accepted. Cannot be less than 1.0'),
             default=3.0,
             min=1.0),
-        Option(
-            name='noautoscale',
-            type='bool',
-            desc='global autoscale flag',
-            long_desc=('Option to turn on/off the autoscaler for all pools'),
-            default=False),
     ]
 
     def __init__(self, *args: Any, **kwargs: Any) -> None:
@@ -155,7 +149,6 @@ class PgAutoscaler(MgrModule):
             self.sleep_interval = 60
             self.mon_target_pg_per_osd = 0
             self.threshold = 3.0
-            self.noautoscale = False
 
     def config_notify(self) -> None:
         for opt in self.NATIVE_OPTIONS:
@@ -238,7 +231,7 @@ class PgAutoscaler(MgrModule):
                     p['pg_num_target'],
 #                    p['pg_num_ideal'],
                     final,
-                    p['pg_autoscale_mode'],
+                    'off' if self.has_noautoscale_flag() else p['pg_autoscale_mode'],
                     str(p['bulk'])
                 ])
             return 0, table.get_string(), ''
@@ -260,16 +253,13 @@ class PgAutoscaler(MgrModule):
             self.remote('progress', 'complete', ev.ev_id)
             del self._event[pool_id]
 
-    def set_autoscale_mode_all_pools(self, status: str) -> None:
-        osdmap = self.get_osdmap()
-        pools = osdmap.get_pools_by_name()
-        for pool_name, _ in pools.items():
-            self.mon_command({
-                'prefix': 'osd pool set',
-                'pool': pool_name,
-                'var': 'pg_autoscale_mode',
-                'val': status
-            })
+    def has_noautoscale_flag(self) -> bool:
+        flags = self.get_osdmap().dump().get('flags', '')
+        if 'noautoscale' in flags:
+            return True
+        else:
+            return False
+
     @CLIWriteCommand("osd pool get noautoscale")
     def get_noautoscale(self) -> Tuple[int, str, str]:
         """
@@ -277,10 +267,7 @@ class PgAutoscaler(MgrModule):
         are setting the autoscaler on or off as well
         as newly created pools in the future.
         """
-
-        if self.noautoscale == None:
-            raise TypeError("noautoscale cannot be None")
-        elif self.noautoscale:
+        if self.has_noautoscale_flag():
             return 0, "", "noautoscale is on"
         else:
             return 0, "", "noautoscale is off"
@@ -289,21 +276,23 @@ class PgAutoscaler(MgrModule):
     def unset_noautoscale(self) -> Tuple[int, str, str]:
         """
         Unset the noautoscale flag so all pools will
-        have autoscale enabled (including newly created
-        pools in the future).
+        go back to its previous mode. Newly created
+        pools in the future will autoscaler on by default.
         """
-        if not self.noautoscale:
+        if not self.has_noautoscale_flag():
             return 0, "", "noautoscale is already unset!"
         else:
-            self.set_module_option("noautoscale", False)
             self.mon_command({
                 'prefix': 'config set',
                 'who': 'global',
                 'name': 'osd_pool_default_pg_autoscale_mode',
                 'value': 'on'
             })
-            self.set_autoscale_mode_all_pools("on")
-            return 0, "", "noautoscale is unset, all pools now have autoscale on"
+            self.mon_command({
+                'prefix': 'osd unset',
+                'key': 'noautoscale'
+            })
+            return 0, "", "noautoscale is unset, all pools now back to its previous mode"
 
     @CLIWriteCommand("osd pool set noautoscale")
     def set_noautoscale(self) -> Tuple[int, str, str]:
@@ -313,24 +302,26 @@ class PgAutoscaler(MgrModule):
         and complete all on-going progress events
         regarding PG-autoscaling.
         """
-        if self.noautoscale:
+        if self.has_noautoscale_flag():
             return 0, "", "noautoscale is already set!"
         else:
-            self.set_module_option("noautoscale", True)
             self.mon_command({
                 'prefix': 'config set',
                 'who': 'global',
                 'name': 'osd_pool_default_pg_autoscale_mode',
                 'value': 'off'
             })
-            self.set_autoscale_mode_all_pools("off")
+            self.mon_command({
+                'prefix': 'osd set',
+                'key': 'noautoscale'
+            })
             self.complete_all_progress_events()
             return 0, "", "noautoscale is set, all pools now have autoscale off"
 
     def serve(self) -> None:
         self.config_notify()
         while not self._shutdown.is_set():
-            if not self.noautoscale:
+            if not self.has_noautoscale_flag():
                 osdmap = self.get_osdmap()
                 pools = osdmap.get_pools_by_name()
                 self._maybe_adjust(osdmap, pools)
@@ -689,6 +680,9 @@ class PgAutoscaler(MgrModule):
                                 osdmap: OSDMap,
                                 pools: Dict[str, Dict[str, Any]]) -> None:
         # Update progress events if necessary
+        if self.has_noautoscale_flag():
+            self.log.debug("noautoscale_flag is set.")
+            return
         for pool_id in list(self._event):
             ev = self._event[pool_id]
             pool_data = self._get_pool_by_id(pools, pool_id)
@@ -708,7 +702,9 @@ class PgAutoscaler(MgrModule):
                       pools: Dict[str, Dict[str, Any]]) -> None:
         # Figure out which pool needs pg adjustments
         self.log.info('_maybe_adjust')
-
+        if self.has_noautoscale_flag():
+            self.log.debug("noautoscale_flag is set.")
+            return
         if osdmap.get_require_osd_release() < 'nautilus':
             return