diff --git a/sm-client b/sm-client index 4ecedc88..51747e8e 100755 --- a/sm-client +++ b/sm-client @@ -53,28 +53,53 @@ This site: args: argparse.Namespace - def print_service_order(sm_dict: SMClusterState, cmd, site): """ Show service list ordered by dependency in debug mode""" + if cmd == "status" or cmd == "list": + # status and list are collected in parallel for all services, there is no order + return + stage = 0 logging.debug("Service order by dependency:") - for mod_i in [ i for i in settings.sm_conf.get_modules() if i not in settings.default_module]: #@todo to rework module support - logging.debug("--------------------") - for service_name in sm_dict.get_module_services(sm_dict.get_available_sites()[0],mod_i): #@todo if not - logging.debug(f"{service_name}") - - ts = copy.deepcopy(sm_dict.globals[settings.default_module]['ts']) - while ts and ts.is_active(): # process all services one by one in sorted by dependency - stage += 1 - logging.debug(f"------ Stage {stage} -------") - for serv in ts.get_ready(): - serv_sequence_info = "" if cmd not in settings.dr_processing_cmd else \ - "( " + " ".join(map(lambda site_mode: f"-> {site_mode[1]} on {site_mode[0]}", - sm_dict.get_dr_operation_sequence(serv, cmd, site))) + " )" - logging.debug(f"{serv} {serv_sequence_info}") - ts.done(serv) - logging.debug("Done. ----------------") - + for elem in settings.module_flow: + flow, flow_cmds = list(elem.items())[0] + # if particular flow performs only particular cmds, + # which are not relevant for current cmd, then we skip this flow + if cmd in ['standby', 'disable', 'return'] and (flow_cmds and flow_cmds == ['active']): + continue + if cmd == 'active' and (flow_cmds and set(flow_cmds) == {'standby', 'disable'}): + continue + + # we process all services in this flow in the services order. + # services order is controlled by ts (TopologicalSorter) + ts = copy.deepcopy(sm_dict.globals[flow]['ts']) + while ts and ts.is_active(): + stage += 1 + logging.debug(f"------ Stage {stage} -------") + + # for each svc, print operations which are going to be performed for this svc + stage_services = ts.get_ready() + for svc in stage_services: + # svc operation looks like: "$svc: $cmd on $site", with optional " -> $opposite_cmd on $opposite_site" + # the actual look depends on current cmd (if it is DR cmd or per-site cmd), provided site and current flow_cmds + if cmd in settings.dr_processing_cmd: + if flow_cmds: + actual_site = site + is_standby_during_move = flow_cmds[0] == "standby" and cmd == "move" + is_active_during_stop = flow_cmds[0] == "active" and cmd == "stop" + if is_standby_during_move or is_active_during_stop: + actual_site = settings.sm_conf.get_opposite_site(site) + logging.debug(f"{svc}: {flow_cmds[0]} on {actual_site}") + else: + site_cmd_seq = sm_dict.get_dr_operation_sequence(svc, cmd, site) + operation = " -> ".join(map(lambda site_cmd: f"{site_cmd[1]} on {site_cmd[0]}", site_cmd_seq)) + logging.debug(f"{svc}: {operation}") + else: + logging.debug(f"{svc}: {cmd} on {site}") + + # mark svc as done, so next time TopologicalSorter will give us next stage, if any left for this flow + ts.done(svc) + logging.debug("------ Done ------") def run(services: list = None, cmd="", site=""): """ Business Logic - implements main flow """