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:
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)
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)
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 = {
'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
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):
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
# 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)