]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/balancer: document and specify options
authorSage Weil <sage@redhat.com>
Mon, 17 Dec 2018 20:47:06 +0000 (14:47 -0600)
committerSage Weil <sage@redhat.com>
Fri, 21 Dec 2018 04:11:40 +0000 (22:11 -0600)
Signed-off-by: Sage Weil <sage@redhat.com>
src/pybind/mgr/balancer/module.py

index 711922ddb233a100c805fdd0fd8dabe4c0a2ad02..c6c5e80b473b64f186b024aef0cd934de79d74df 100644 (file)
@@ -14,10 +14,6 @@ from mgr_module import MgrModule, CommandResult
 from threading import Event
 from mgr_module import CRUSHMap
 
-# available modes: 'none', 'crush', 'crush-compat', 'upmap', 'osd_weight'
-default_mode = 'none'
-default_sleep_interval = 60   # seconds
-
 TIME_FORMAT = '%Y-%m-%d_%H:%M:%S'
 
 class MappingState:
@@ -202,17 +198,94 @@ class Eval:
 
 class Module(MgrModule):
     MODULE_OPTIONS = [
-            {'name': 'active'},
-            {'name': 'begin_time'},
-            {'name': 'crush_compat_max_iterations'},
-            {'name': 'crush_compat_metrics'},
-            {'name': 'crush_compat_step'},
-            {'name': 'end_time'},
-            {'name': 'min_score'},
-            {'name': 'mode'},
-            {'name': 'sleep_interval'},
-            {'name': 'upmap_max_iterations'},
-            {'name': 'upmap_max_deviation'},
+        {
+            'name': 'active',
+            'type': 'bool',
+            'default': False,
+            'desc': 'automatically balance PGs across cluster',
+            'runtime': True,
+        },
+        {
+            'name': 'begin_time',
+            'type': 'str',
+            'default': '0000',
+            'desc': 'beginning time of day to automatically balance',
+            'long_desc': 'This is a time of day in the format HHMM.',
+            'runtime': True,
+        },
+        {
+            'name': 'end_time',
+            'type': 'str',
+            'default': '2400',
+            'desc': 'ending time of day to automatically balance',
+            'long_desc': 'This is a time of day in the format HHMM.',
+            'runtime': True,
+        },
+        {
+            'name': 'crush_compat_max_iterations',
+            'type': 'uint',
+            'default': 25,
+            'min': '1',
+            'max': '250',
+            'desc': 'maximum number of iterations to attempt optimization',
+            'runtime': True,
+        },
+        {
+            'name': 'crush_compat_metrics',
+            'type': 'str',
+            'default': 'pgs,objects,bytes',
+            'desc': 'metrics with which to calculate OSD utilization',
+            'long_desc': 'Value is a list of one or more of "pgs", "objects", or "bytes", and indicates which metrics to use to balance utilization.',
+            'runtime': True,
+        },
+        {
+            'name': 'crush_compat_step',
+            'type': 'float',
+            'default': .5,
+            'min': '.001',
+            'max': '.999',
+            'desc': 'aggressiveness of optimization',
+            'long_desc': '.99 is very aggressive, .01 is less aggressive',
+            'runtime': True,
+        },
+        {
+            'name': 'min_score',
+            'type': 'float',
+            'default': 0,
+            'desc': 'minimum score, below which no optimization is attempted',
+            'runtime': True,
+        },
+        {
+            'name': 'mode',
+            'desc': 'Balancer mode',
+            'default': 'none',
+            'enum_allowed': ['none', 'crush-compat', 'upmap'],
+            'runtime': True,
+        },
+        {
+            'name': 'sleep_interval',
+            'type': 'secs',
+            'default': 60,
+            'desc': 'how frequently to wake up and attempt optimization',
+            'runtime': True,
+        },
+        {
+            'name': 'upmap_max_iterations',
+            'type': 'uint',
+            'default': 10,
+            'desc': 'maximum upmap optimization iterations',
+            'runtime': True,
+        },
+        {
+            'name': 'upmap_max_deviation',
+            'type': 'float',
+            'default': .01,
+            'min': 0,
+            'max': 1,
+            'desc': 'deviation below which no optimization is attempted',
+            'long_desc': 'If the ratio between the fullest and least-full OSD is below this value then we stop trying to optimize placement.',
+            'runtime': True,
+        },
     ]
 
     COMMANDS = [
@@ -297,7 +370,7 @@ class Module(MgrModule):
             s = {
                 'plans': list(self.plans.keys()),
                 'active': self.active,
-                'mode': self.get_module_option('mode', default_mode),
+                'mode': self.get_module_option('mode'),
             }
             return (0, json.dumps(s, indent=4), '')
         elif command['prefix'] == 'balancer mode':
@@ -305,13 +378,13 @@ class Module(MgrModule):
             return (0, '', '')
         elif command['prefix'] == 'balancer on':
             if not self.active:
-                self.set_module_option('active', '1')
+                self.set_module_option('active', 'true')
                 self.active = True
             self.event.set()
             return (0, '', '')
         elif command['prefix'] == 'balancer off':
             if self.active:
-                self.set_module_option('active', '')
+                self.set_module_option('active', 'false')
                 self.active = False
             self.event.set()
             return (0, '', '')
@@ -399,15 +472,14 @@ class Module(MgrModule):
     def serve(self):
         self.log.info('Starting')
         while self.run:
-            self.active = self.get_module_option('active', '') is not ''
-            begin_time = self.get_module_option('begin_time') or '0000'
-            end_time = self.get_module_option('end_time') or '2400'
+            self.active = self.get_module_option('active')
+            begin_time = self.get_module_option('begin_time')
+            end_time = self.get_module_option('end_time')
             timeofday = time.strftime('%H%M', time.localtime())
             self.log.debug('Waking up [%s, scheduled for %s-%s, now %s]',
                            "active" if self.active else "inactive",
                            begin_time, end_time, timeofday)
-            sleep_interval = float(self.get_module_option('sleep_interval',
-                                                   default_sleep_interval))
+            sleep_interval = self.get_module_option('sleep_interval')
             if self.active and self.time_in_interval(timeofday, begin_time, end_time):
                 self.log.debug('Running')
                 name = 'auto_%s' % time.strftime(TIME_FORMAT, time.gmtime())
@@ -629,7 +701,7 @@ class Module(MgrModule):
         self.log.debug('score_by_root %s' % pe.score_by_root)
 
         # get the list of score metrics, comma separated
-        metrics = self.get_module_option('crush_compat_metrics', 'pgs,objects,bytes').split(',')
+        metrics = self.get_module_option('crush_compat_metrics').split(',')
 
         # total score is just average of normalized stddevs
         pe.score = 0.0
@@ -646,7 +718,7 @@ class Module(MgrModule):
 
     def optimize(self, plan):
         self.log.info('Optimize plan %s' % plan.name)
-        plan.mode = self.get_module_option('mode', default_mode)
+        plan.mode = self.get_module_option('mode')
         max_misplaced = float(self.get_ceph_option('target_max_misplaced_ratio'))
         self.log.info('Mode %s, max misplaced %f' %
                       (plan.mode, max_misplaced))
@@ -692,8 +764,8 @@ class Module(MgrModule):
 
     def do_upmap(self, plan):
         self.log.info('do_upmap')
-        max_iterations = int(self.get_module_option('upmap_max_iterations', 10))
-        max_deviation = float(self.get_module_option('upmap_max_deviation', .01))
+        max_iterations = self.get_module_option('upmap_max_iterations')
+        max_deviation = self.get_module_option('upmap_max_deviation')
 
         ms = plan.initial
         if len(plan.pools):
@@ -725,10 +797,10 @@ class Module(MgrModule):
 
     def do_crush_compat(self, plan):
         self.log.info('do_crush_compat')
-        max_iterations = int(self.get_module_option('crush_compat_max_iterations', 25))
+        max_iterations = self.get_module_option('crush_compat_max_iterations')
         if max_iterations < 1:
             return -errno.EINVAL, '"crush_compat_max_iterations" must be >= 1'
-        step = float(self.get_module_option('crush_compat_step', .5))
+        step = self.get_module_option('crush_compat_step')
         if step <= 0 or step >= 1.0:
             return -errno.EINVAL, '"crush_compat_step" must be in (0, 1)'
         max_misplaced = float(self.get_ceph_option('target_max_misplaced_ratio'))
@@ -738,7 +810,7 @@ class Module(MgrModule):
         osdmap = ms.osdmap
         crush = osdmap.get_crush()
         pe = self.calc_eval(ms, plan.pools)
-        min_score_to_optimize = float(self.get_module_option('min_score', 0))
+        min_score_to_optimize = self.get_module_option('min_score')
         if pe.score <= min_score_to_optimize:
             if pe.score == 0:
                 detail = 'Distribution is already perfect'
@@ -781,7 +853,7 @@ class Module(MgrModule):
             return -errno.EOPNOTSUPP, detail
 
         # rebalance by pgs, objects, or bytes
-        metrics = self.get_module_option('crush_compat_metrics', 'pgs,objects,bytes').split(',')
+        metrics = self.get_module_option('crush_compat_metrics').split(',')
         key = metrics[0] # balancing using the first score metric
         if key not in ['pgs', 'bytes', 'objects']:
             self.log.warn("Invalid crush_compat balancing key %s. Using 'pgs'." % key)