Exemple #1
0
def main(_, options, *args):
    # suite name or file path
    suite, flow_file = parse_suite_arg(options, args[0])

    # extract task host platforms from the suite
    config = SuiteConfig(
        suite, flow_file, options,
        load_template_vars(options.templatevars, options.templatevars_file))

    platforms = {
        config.get_config(['runtime', name, 'platform'])
        for name in config.get_namespace_list('all tasks')
    } - {None, 'localhost'}

    # When "suite run hosts" are formalised as "flow platforms"
    # we can substitute `localhost` for this, in the mean time
    # we will have to assume that flow hosts are configured correctly.

    if not platforms:
        sys.exit(0)

    verbose = cylc.flow.flags.verbose

    # get the cylc version on each platform
    versions = {}
    for platform_name in sorted(platforms):
        platform = get_platform(platform_name)
        cmd = construct_platform_ssh_cmd(['version'], platform)
        if verbose:
            print(cmd)
        proc = procopen(cmd, stdin=DEVNULL, stdout=PIPE, stderr=PIPE)
        out, err = proc.communicate()
        out = out.decode()
        err = err.decode()
        if proc.wait() == 0:
            if verbose:
                print("   %s" % out)
            versions[platform_name] = out.strip()
        else:
            versions[platform_name] = f'ERROR: {err.strip()}'

    # report results
    max_len = max((len(platform_name) for platform_name in platforms))
    print(f'{"platform".rjust(max_len)}: cylc version')
    print('-' * (max_len + 14))
    for platform_name, result in versions.items():
        print(f'{platform_name.rjust(max_len)}: {result}')
    if all((version == CYLC_VERSION for version in versions.values())):
        exit = 0
    elif options.error:
        exit = 1
    else:
        exit = 0
    sys.exit(exit)
Exemple #2
0
def main(parser, options, reg):
    suite, suiterc = parse_suite_arg(options, reg)

    if options.all_tasks and options.all_namespaces:
        parser.error("Choose either -a or -n")
    if options.all_tasks:
        which = "all tasks"
    elif options.all_namespaces:
        which = "all namespaces"
    elif options.crange:
        which = "crange"
        try:
            tr_start, tr_stop = options.crange.split(',')
        except ValueError:
            tr_start = tr_stop = options.crange
    else:
        which = "graphed tasks"

    if options.tree:
        if os.environ['LANG'] == 'C' and options.box:
            print("WARNING, ignoring -t/--tree: $LANG=C", file=sys.stderr)
            options.tree = False

    if options.titles and options.mro:
        parser.error("Please choose --mro or --title, not both")

    if options.tree and any(
        [options.all_tasks, options.all_namespaces, options.mro]):
        print("WARNING: -t chosen, ignoring non-tree options.",
              file=sys.stderr)
    config = SuiteConfig(
        suite, suiterc, options,
        load_template_vars(options.templatevars, options.templatevars_file))
    if options.tree:
        config.print_first_parent_tree(pretty=options.box,
                                       titles=options.titles)
    elif options.crange:
        for node in sorted(config.get_node_labels(tr_start, tr_stop)):
            print(node)
    else:
        result = config.get_namespace_list(which)
        namespaces = list(result)
        namespaces.sort()

        if (options.mro or options.titles):
            # compute padding
            maxlen = 0
            for ns in namespaces:
                if len(ns) > maxlen:
                    maxlen = len(ns)
            padding = maxlen * ' '

        for ns in namespaces:
            if options.mro:
                print(ns, padding[0:len(padding) - len(ns)], end=' ')
                print(' '.join(config.get_mro(ns)))
            elif options.titles:
                print(ns, padding[0:len(padding) - len(ns)], end=' ')
                print(result[ns])
            else:
                print(ns)
Exemple #3
0
def main(_, options, *args):
    # suite name or file path
    suite, suiterc = parse_suite_arg(options, args[0])

    # extract task host accounts from the suite
    config = SuiteConfig(
        suite, suiterc, options,
        load_template_vars(options.templatevars, options.templatevars_file))
    account_set = set()
    for name in config.get_namespace_list('all tasks'):
        account_set.add(
            (config.get_config(['runtime', name, 'remote', 'owner']),
             config.get_config(['runtime', name, 'remote', 'host'])))
    task_remote_mgr = TaskRemoteMgr(suite, SubProcPool())
    for _, host_str in account_set:
        task_remote_mgr.remote_host_select(host_str)
    accounts = []
    while account_set:
        for user, host_str in account_set.copy():
            res = task_remote_mgr.remote_host_select(host_str)
            if res:
                account_set.remove((user, host_str))
                accounts.append((user, res))
        if account_set:
            task_remote_mgr.proc_pool.process()
            sleep(1.0)

    # Interrogate the each remote account with CYLC_VERSION set to our version.
    # Post backward compatibility concerns to do this we can just run:
    #   cylc version --host=HOST --user=USER
    # but this command only exists for version > 6.3.0.
    # So for the moment generate an actual remote invocation command string for
    # "cylc --version".

    # (save verbose flag as gets reset in remrun)
    verbose = cylc.flow.flags.verbose

    warn = {}
    contacted = 0
    for user, host in sorted(accounts):
        argv = ["cylc", "version"]
        if user and host:
            argv += ["--user=%s" % user, "--host=%s" % host]
            user_at_host = "%s@%s" % (user, host)
        elif user:
            argv += ["--user=%s" % user]
            user_at_host = "%s@localhost" % user
        elif host:
            argv += ["--host=%s" % host]
            user_at_host = host
        if verbose:
            print("%s: %s" % (user_at_host, ' '.join(argv)))
        proc = procopen(argv,
                        stdin=open(os.devnull),
                        stdoutpipe=True,
                        stderrpipe=True)
        out, err = proc.communicate()
        out = out.decode()
        err = err.decode()
        if proc.wait() == 0:
            if verbose:
                print("   %s" % out)
            contacted += 1
            out = out.strip()
            if out != CYLC_VERSION:
                warn[user_at_host] = out
        else:
            print('ERROR ' + user_at_host + ':', file=sys.stderr)
            print(err, file=sys.stderr)

    # report results
    if not warn:
        if contacted:
            print("All", contacted, "accounts have cylc-" + CYLC_VERSION)
    else:
        print("WARNING: failed to invoke cylc-%s on %d accounts:" %
              (CYLC_VERSION, len(warn)))
        m = max(len(ac) for ac in warn)
        for ac, warning in warn.items():
            print(' ', ac.ljust(m), warning)
        if options.error:
            sys.exit(1)