Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

luminous: mgr/restful: fix py got exception when get osd info #26199

Merged
merged 2 commits into from Mar 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/pybind/mgr/restful/api/crush.py
Expand Up @@ -14,11 +14,11 @@ def get(self, **kwargs):
"""
Show crush rules
"""
rules = module.instance.get('osd_map_crush')['rules']
nodes = module.instance.get('osd_map_tree')['nodes']
crush = module.instance.get('osd_map_crush')
rules = crush['rules']

for rule in rules:
rule['osd_count'] = len(common.crush_rule_osds(nodes, rule))
rule['osd_count'] = len(common.crush_rule_osds(crush['buckets'], rule))

return rules

Expand Down
54 changes: 33 additions & 21 deletions src/pybind/mgr/restful/common.py
Expand Up @@ -88,31 +88,34 @@ def pool_update_commands(pool_name, args):

return commands


def crush_rule_osds(nodes, rule):
nodes_by_id = dict((n['id'], n) for n in nodes)
def crush_rule_osds(node_buckets, rule):
nodes_by_id = dict((b['id'], b) for b in node_buckets)

def _gather_leaf_ids(node):
if node['id'] >= 0:
return set([node['id']])

result = set()
for child_id in node['children']:
if child_id >= 0:
result.add(child_id)
for item in node['items']:
if item['id'] >= 0:
result.add(item['id'])
else:
result |= _gather_leaf_ids(nodes_by_id[child_id])
result |= _gather_leaf_ids(nodes_by_id[item['id']])

return result

def _gather_descendent_ids(node, typ):
result = set()
for child_id in node['children']:
child_node = nodes_by_id[child_id]
if child_node['type'] == typ:
result.add(child_node['id'])
elif 'children' in child_node:
result |= _gather_descendent_ids(child_node, typ)
for item in node['items']:
if item['id'] >= 0:
if typ == "osd":
result.add(item['id'])
else:
child_node = nodes_by_id[item['id']]
if child_node['type_name'] == typ:
result.add(child_node['id'])
elif 'items' in child_node:
result |= _gather_descendent_ids(child_node, typ)

return result

Expand All @@ -124,17 +127,26 @@ def _gather_osds(root, steps):
step = steps[0]
if step['op'] == 'choose_firstn':
# Choose all descendents of the current node of type 'type'
d = _gather_descendent_ids(root, step['type'])
for desc_node in [nodes_by_id[i] for i in d]:
osds |= _gather_osds(desc_node, steps[1:])
descendent_ids = _gather_descendent_ids(root, step['type'])
for node_id in descendent_ids:
if node_id >= 0:
osds.add(node_id)
else:
for desc_node in nodes_by_id[node_id]:
osds |= _gather_osds(desc_node, steps[1:])
elif step['op'] == 'chooseleaf_firstn':
# Choose all descendents of the current node of type 'type',
# and select all leaves beneath those
for desc_node in [nodes_by_id[i] for i in _gather_descendent_ids(root, step['type'])]:
# Short circuit another iteration to find the emit
# and assume anything we've done a chooseleaf on
# is going to be part of the selected set of osds
osds |= _gather_leaf_ids(desc_node)
descendent_ids = _gather_descendent_ids(root, step['type'])
for node_id in descendent_ids:
if node_id >= 0:
osds.add(node_id)
else:
for desc_node in nodes_by_id[node_id]['items']:
# Short circuit another iteration to find the emit
# and assume anything we've done a chooseleaf on
# is going to be part of the selected set of osds
osds |= _gather_leaf_ids(desc_node)
elif step['op'] == 'emit':
if root['id'] >= 0:
osds |= root['id']
Expand Down
5 changes: 3 additions & 2 deletions src/pybind/mgr/restful/module.py
Expand Up @@ -503,14 +503,15 @@ def get_mons(self):
def get_osd_pools(self):
osds = dict(map(lambda x: (x['osd'], []), self.get('osd_map')['osds']))
pools = dict(map(lambda x: (x['pool'], x), self.get('osd_map')['pools']))
crush_rules = self.get('osd_map_crush')['rules']
crush = self.get('osd_map_crush')
crush_rules = crush['rules']

osds_by_pool = {}
for pool_id, pool in pools.items():
pool_osds = None
for rule in [r for r in crush_rules if r['rule_id'] == pool['crush_rule']]:
if rule['min_size'] <= pool['size'] <= rule['max_size']:
pool_osds = common.crush_rule_osds(self.get('osd_map_tree')['nodes'], rule)
pool_osds = common.crush_rule_osds(crush['buckets'], rule)

osds_by_pool[pool_id] = pool_osds

Expand Down