From 9238c01b2f6cf6014e3224213d3da574a87f40da Mon Sep 17 00:00:00 2001 From: John Spray Date: Wed, 20 Aug 2014 12:22:01 +0100 Subject: [PATCH] daemon: add DaemonGroup.resolve_role_list Used for tasks that want to take a flexible list of roles from their user config, including a null (everything) default and * wildcards. Signed-off-by: John Spray --- teuthology/orchestra/daemon.py | 55 ++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/teuthology/orchestra/daemon.py b/teuthology/orchestra/daemon.py index 3fa93b8d5a..74c68dfcb2 100644 --- a/teuthology/orchestra/daemon.py +++ b/teuthology/orchestra/daemon.py @@ -167,3 +167,58 @@ class DaemonGroup(object): :param role: Role (osd, mds, mon, rgw, for example) """ return self.daemons.get(role, {}).values() + + def resolve_role_list(self, roles, types): + """ + Resolve a configuration setting that may be None or contain wildcards + into a list of roles (where a role is e.g. 'mds.a' or 'osd.0'). This + is useful for tasks that take user input specifying a flexible subset + of the available roles. + + The task calling this must specify what kinds of roles it can can handle using the ``types`` argument, where + a role type is 'osd' or 'mds' for example. When selecting roles this is used as a filter, or when + an explicit list of roles is passed, the an exception is raised if any are not of a suitable type. + + Examples: + + :: + + # Passing None (i.e. user left config blank) defaults to all roles (filtered by ``types``) + None -> ['osd.0', 'osd.1', 'osd.2', 'mds.a', mds.b', 'mon.a'] + # Wildcards are expanded + ['mds.*', 'osd.0'] -> ['mds.a', 'mds.b', 'osd.0'] + # Boring lists are unaltered + ['osd.0', 'mds.a'] -> ['osd.0', 'mds.a'] + + :param roles: List (of roles or wildcards) or None (select all suitable roles) + :param types: List of acceptable role types, for example ['osd', 'mds']. + :return: List of strings like ["mds.0", "osd.2"] + """ + assert (isinstance(roles, list) or roles is None) + + resolved = [] + if roles is None: + # Handle default: all roles available + for type_ in types: + for daemon in self.iter_daemons_of_role(type_): + resolved.append(type_ + '.' + daemon.id_) + else: + # Handle explicit list of roles or wildcards + for raw_role in roles: + try: + role_type, role_id = raw_role.split(".") + except ValueError: + raise RuntimeError("Invalid role '{0}', roles must be of format .".format(raw_role)) + + if role_type not in types: + raise RuntimeError("Invalid role type '{0}' in role '{1}'".format(role_type, raw_role)) + + if role_id == "*": + # Handle wildcard, all roles of the type + for daemon in self.iter_daemons_of_role(role_type): + resolved.append(role_type + '.' + daemon.id_) + else: + # Handle explicit role + resolved.append(raw_role) + + return resolved -- 2.39.5