diff options
Diffstat (limited to 'src/pybind/mgr/restful/common.py')
-rw-r--r-- | src/pybind/mgr/restful/common.py | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/src/pybind/mgr/restful/common.py b/src/pybind/mgr/restful/common.py new file mode 100644 index 00000000..1b957d6b --- /dev/null +++ b/src/pybind/mgr/restful/common.py @@ -0,0 +1,156 @@ +# List of valid osd flags +OSD_FLAGS = [ + 'pause', 'noup', 'nodown', 'noout', 'noin', 'nobackfill', + 'norecover', 'noscrub', 'nodeep-scrub', +] + +# Implemented osd commands +OSD_IMPLEMENTED_COMMANDS = [ + 'scrub', 'deep-scrub', 'repair' +] + +# Valid values for the 'var' argument to 'ceph osd pool set' +POOL_PROPERTIES_1 = [ + 'size', 'min_size', 'pg_num', + 'crush_rule', 'hashpspool', +] + +POOL_PROPERTIES_2 = [ + 'pgp_num' +] + +POOL_PROPERTIES = POOL_PROPERTIES_1 + POOL_PROPERTIES_2 + +# Valid values for the 'ceph osd pool set-quota' command +POOL_QUOTA_PROPERTIES = [ + ('quota_max_bytes', 'max_bytes'), + ('quota_max_objects', 'max_objects'), +] + +POOL_ARGS = POOL_PROPERTIES + [x for x,_ in POOL_QUOTA_PROPERTIES] + + +# Transform command to a human readable form +def humanify_command(command): + out = [command['prefix']] + + for arg, val in command.items(): + if arg != 'prefix': + out.append("%s=%s" % (str(arg), str(val))) + + return " ".join(out) + + +def invalid_pool_args(args): + invalid = [] + for arg in args: + if arg not in POOL_ARGS: + invalid.append(arg) + + return invalid + + +def pool_update_commands(pool_name, args): + commands = [[], []] + + # We should increase pgp_num when we are re-setting pg_num + if 'pg_num' in args and 'pgp_num' not in args: + args['pgp_num'] = args['pg_num'] + + # Run the first pool set and quota properties in parallel + for var in POOL_PROPERTIES_1: + if var in args: + commands[0].append({ + 'prefix': 'osd pool set', + 'pool': pool_name, + 'var': var, + 'val': args[var], + }) + + for (var, field) in POOL_QUOTA_PROPERTIES: + if var in args: + commands[0].append({ + 'prefix': 'osd pool set-quota', + 'pool': pool_name, + 'field': field, + 'val': str(args[var]), + }) + + # The second pool set properties need to be run after the first wave + for var in POOL_PROPERTIES_2: + if var in args: + commands[1].append({ + 'prefix': 'osd pool set', + 'pool': pool_name, + 'var': var, + 'val': args[var], + }) + + return commands + +def crush_rule_osds(node_buckets, rule): + nodes_by_id = dict((b['id'], b) for b in node_buckets) + + def _gather_leaf_ids(node_id): + if node_id >= 0: + return set([node_id]) + + result = set() + for item in nodes_by_id[node_id]['items']: + result |= _gather_leaf_ids(item['id']) + + return result + + def _gather_descendent_ids(node, typ): + result = set() + 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 + + def _gather_osds(root, steps): + if root['id'] >= 0: + return set([root['id']]) + + osds = set() + step = steps[0] + if step['op'] == 'choose_firstn': + # Choose all descendents of the current node of type 'type' + descendent_ids = _gather_descendent_ids(root, step['type']) + for node_id in descendent_ids: + if node_id >= 0: + osds.add(node_id) + else: + osds |= _gather_osds(nodes_by_id[node_id], steps[1:]) + elif step['op'] == 'chooseleaf_firstn': + # Choose all descendents of the current node of type 'type', + # and select all leaves beneath those + 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['id']) + elif step['op'] == 'emit': + if root['id'] >= 0: + osds |= root['id'] + + return osds + + osds = set() + for i, step in enumerate(rule['steps']): + if step['op'] == 'take': + osds |= _gather_osds(nodes_by_id[step['item']], rule['steps'][i + 1:]) + return osds |