From 675c3525b8f3395981569c725823f4519687e477 Mon Sep 17 00:00:00 2001 From: xie xingguo Date: Tue, 30 Jan 2018 11:31:39 +0800 Subject: [PATCH] mgr/balancer: pool-specific optimization for crush-compat Signed-off-by: xie xingguo --- src/pybind/mgr/balancer/module.py | 36 ++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/pybind/mgr/balancer/module.py b/src/pybind/mgr/balancer/module.py index f21805ba0e17c..797a5e4eef9f7 100644 --- a/src/pybind/mgr/balancer/module.py +++ b/src/pybind/mgr/balancer/module.py @@ -287,17 +287,19 @@ class Module(MgrModule): return (0, '', '') elif command['prefix'] == 'balancer eval' or command['prefix'] == 'balancer eval-verbose': verbose = command['prefix'] == 'balancer eval-verbose' + pools = [] if 'plan' in command: plan = self.plans.get(command['plan']) if not plan: return (-errno.ENOENT, '', 'plan %s not found' % command['plan']) + pools = plan.pools ms = plan.final_state() else: ms = MappingState(self.get_osdmap(), self.get("pg_dump"), 'current cluster') - return (0, self.evaluate(ms, verbose=verbose), '') + return (0, self.evaluate(ms, pools, verbose=verbose), '') elif command['prefix'] == 'balancer optimize': pools = [] if 'pools' in command: @@ -387,18 +389,19 @@ class Module(MgrModule): if name in self.plans: del self.plans[name] - def calc_eval(self, ms): + def calc_eval(self, ms, pools): pe = Eval(ms) pool_rule = {} pool_info = {} for p in ms.osdmap_dump.get('pools',[]): + if len(pools) and p['pool_name'] not in pools: + continue pe.pool_name[p['pool']] = p['pool_name'] pe.pool_id[p['pool_name']] = p['pool'] pool_rule[p['pool_name']] = p['crush_rule'] pe.pool_roots[p['pool_name']] = [] pool_info[p['pool_name']] = p - pools = pe.pool_id.keys() - if len(pools) == 0: + if len(pool_info) == 0: return pe self.log.debug('pool_name %s' % pe.pool_name) self.log.debug('pool_id %s' % pe.pool_id) @@ -413,14 +416,21 @@ class Module(MgrModule): rootids = ms.crush.find_takes() roots = [] for rootid in rootids: - root = ms.crush.get_item_name(rootid) - pe.root_ids[root] = rootid - roots.append(root) ls = ms.osdmap.get_pools_by_take(rootid) + want = [] + # find out roots associating with pools we are passed in + for candidate in ls: + if candidate in pe.pool_name: + want.append(candidate) + if len(want) == 0: + continue + root = ms.crush.get_item_name(rootid) pe.root_pools[root] = [] - for poolid in ls: + for poolid in want: pe.pool_roots[pe.pool_name[poolid]].append(root) pe.root_pools[root].append(pe.pool_name[poolid]) + pe.root_ids[root] = rootid + roots.append(root) weight_map = ms.crush.get_take_weight_osd_map(rootid) adjusted_map = { osd: cw * osd_weight.get(osd, 1.0) @@ -558,6 +568,7 @@ class Module(MgrModule): pe.total_by_root[a] ) for a, b in pe.count_by_root.iteritems() } + self.log.debug('stats_by_root %s' % pe.stats_by_root) # the scores are already normalized pe.score_by_root = { @@ -567,6 +578,7 @@ class Module(MgrModule): 'bytes': pe.stats_by_root[r]['bytes']['score'], } for r in pe.total_by_root.keys() } + self.log.debug('score_by_root %s' % pe.score_by_root) # total score is just average of normalized stddevs pe.score = 0.0 @@ -576,8 +588,8 @@ class Module(MgrModule): pe.score /= 3 * len(roots) return pe - def evaluate(self, ms, verbose=False): - pe = self.calc_eval(ms) + def evaluate(self, ms, pools, verbose=False): + pe = self.calc_eval(ms, pools) return pe.show(verbose=verbose) def optimize(self, plan): @@ -661,7 +673,7 @@ class Module(MgrModule): ms = plan.initial osdmap = ms.osdmap crush = osdmap.get_crush() - pe = self.calc_eval(ms) + pe = self.calc_eval(ms, plan.pools) if pe.score == 0: self.log.info('Distribution is already perfect') return False @@ -768,7 +780,7 @@ class Module(MgrModule): # recalc plan.compat_ws = copy.deepcopy(next_ws) next_ms = plan.final_state() - next_pe = self.calc_eval(next_ms) + next_pe = self.calc_eval(next_ms, plan.pools) next_misplaced = next_ms.calc_misplaced_from(ms) self.log.debug('Step result score %f -> %f, misplacing %f', best_pe.score, next_pe.score, next_misplaced) -- 2.39.5