示例#1
0
    def help_topics(self, topic, browse, prefix="topics", title="help topics"):

        # build list of help topics from xtlib/help_topics directory
        topics_dir = os.path.join(file_utils.get_xtlib_dir(), "help_topics",
                                  prefix)
        if not os.path.isdir(topics_dir):
            errors.env_error("Missing help topics dir: {}".format(topics_dir))
        topic_files, _ = file_utils.get_local_filenames(topics_dir)

        # build a map from topic names to the files
        topic_map = {file_utils.root_name(fn): fn for fn in topic_files}

        if not topic:
            console.print("available {}:".format(title))
            keys = list(topic_map.keys())
            keys.sort()

            for topic_name in keys:
                console.print("  {}".format(topic_name))

            console.print()
            console.print(
                "To display a help topic, use 'xt help topic <topic name>'")
        else:
            # print a specific topic
            topic_low = topic.lower()
            if not topic_low in topic_map:
                errors.general_error(
                    "help topic not found: {}".format(topic_low))

            text = file_utils.read_text_file(topic_map[topic_low])
            print(text)
    def create_demo(self, destination, response, overwrite):
        '''
        This command will removed the specified destination directory if it exists (prompting the user for approval).
        Specifying the current directory as the destination will produce an error.
        '''

        # set up from_dir
        from_dir = file_utils.get_xtlib_dir() + "/demo_files"

        # set up dest_dir
        dest_dir = destination
        if not dest_dir:
            errors.syntax_error("An output directory must be specified")

        create = True
        console.print("creating demo files at: {}".format(
            os.path.abspath(dest_dir)))

        if os.path.exists(dest_dir):
            answer = pc_utils.input_response(
                "'{}' already exists; OK to delete? (y/n): ".format(dest_dir),
                response)
            if answer != "y":
                create = False

        if create:
            file_utils.ensure_dir_deleted(dest_dir)

            shutil.copytree(from_dir, dest_dir)
            #file_utils.copy_tree(from_dir, dest_dir)

            if not self.store.does_workspace_exist("xt-demo"):
                # import xt-demo workspace from archive file
                console.print(
                    "importing xt-demo workspace (usually takes about 30 seconds)"
                )
                impl_storage_api = ImplStorageApi(self.config, self.store)

                fn_archive = os.path.join(file_utils.get_xtlib_dir(),
                                          "demo_files", "xt-demo-archive.zip")
                impl_storage_api.import_workspace(fn_archive,
                                                  "xt-demo",
                                                  "xtd",
                                                  overwrite=overwrite,
                                                  show_output=False)
示例#3
0
def overwrite_default_config():
    default_config_path = os.path.join(get_resource_dir(),
                                       constants.FN_DEFAULT_CONFIG)
    if is_default_config_present():
        file_utils.zap_file(default_config_path)

    res_dir = get_resource_dir()
    file_utils.ensure_dir_exists(res_dir)
    fn_source = os.path.join(file_utils.get_xtlib_dir(), "helpers",
                             constants.FN_DEFAULT_CONFIG)
    shutil.copyfile(fn_source, default_config_path)
示例#4
0
def load_and_validate_config(fn, validate_as_default):

    # load the config file
    config = XTConfig(fn=fn, create_if_needed=False)

    # load the validation schema
    fn_schema = os.path.join(file_utils.get_xtlib_dir(), "helpers",
                             "xt_config_schema.yaml")
    schema = load_yaml(fn_schema)

    # validate the config file
    validator = Validator()
    validator.validate(schema, fn_schema, config.data, config.fn,
                       validate_as_default)

    return config
示例#5
0
def get_default_config_path():
    '''
    always call this function to find the "default_config.yaml" file.
    calling this ensures that the file has been copied from its package location.
    '''
    res_dir = get_resource_dir()
    fn = os.path.join(res_dir, constants.FN_DEFAULT_CONFIG)

    if not os.path.exists(fn):
        # copy it from its helpers dir in the installed package (or dev directory)
        file_utils.ensure_dir_exists(res_dir)
        fn_source = os.path.join(file_utils.get_xtlib_dir(), "helpers",
                                 constants.FN_DEFAULT_CONFIG)
        shutil.copyfile(fn_source, fn)

        # make file readonly
        file_utils.make_readonly(fn)

    return fn
示例#6
0
    def snapshot_all_code(self, snapshot_dir, cmd_parts, args):
        '''
        make local snapshot of each code_dir (and xtlib, if needed)
        '''
        code_dirs = args["code_dirs"]
        xtlib_capture = args["xtlib_upload"]
        code_omit = args["code_omit"]
        script_dir = None

        code_upload = args["code_upload"]
        
        # this step should always be done so that script_dir is removed from cmd_parts
        script_dir = self.remove_script_dir_from_parts(cmd_parts)

        if code_upload:
            for i, code_dir in enumerate(code_dirs):
                # fixup "$scriptdir" relative paths
                if "$scriptdir" in code_dir:
                    code_dir = code_dir.replace("$scriptdir", script_dir)

                if "::" in code_dir:
                    code_dir, dest_dir = code_dir.split("::")
                else:
                    dest_dir = "."
                self.make_local_snapshot(snapshot_dir, code_dir, dest_dir, code_omit)
        else:
            script_dir = snapshot_dir

        if xtlib_capture:
            # copy XTLIB directory to "xtlib" subdir of temp
            xtlib_dir = file_utils.get_xtlib_dir()
            dest_dir = snapshot_dir + "/xtlib"
            file_utils.ensure_dir_deleted(dest_dir)

            # don't copy the "demo_files" directory
            shutil.copytree(xtlib_dir, dest_dir, ignore=shutil.ignore_patterns("demo_files"))

        console.diag("after create local snapshot")
        return script_dir
示例#7
0
def test():
    fn_schema = os.path.join(file_utils.get_xtlib_dir(), "helpers",
                             "xt_config_schema.yaml")
    schema = file_utils.load_yaml(fn_schema)

    # a good first test: the default config file!
    fn_to_validate = get_default_config_path()

    default_config = file_utils.load_yaml(fn_to_validate)

    local_config = file_utils.load_yaml("xt_config.yaml")
    qt_config = file_utils.load_yaml("../quick-test/xt_config.yaml")

    validator = Validator()
    started = time.time()

    validator.validate(schema, default_config, True, "default config")
    validator.validate(schema, local_config, False, "local_config")
    validator.validate(schema, qt_config, False, "qt_config")

    elapsed = time.time() - started
    print("elapsed time: {:.4f} secs".format(elapsed))
示例#8
0
    def adjust_run_commands(self, job_id, job_runs, using_hp, experiment,
                            service_type, snapshot_dir, args):
        '''
        This method is called to allow the backend to inject needed shell commands before the user cmd.  At the
        time this is called, files can still be added to snapshot_dir.
        '''
        store_data_dir, data_action, data_writable, store_model_dir, model_action, model_writable,  \
            storage_name, storage_key = self.get_action_args(args)

        # local or POOL of vm's
        fn_wrapped = None  # we use same script for each box (but with different ARGS)
        username = args["username"]

        for i, box_runs in enumerate(job_runs):
            # wrap the user commands in FIRST RUN of each box (apply data/model actions)
            br = box_runs[0]
            box_info = br["box_info"]
            actions = ["data", "model"]
            run_name = br["run_name"]
            is_windows = False
            node_id = utils.node_id(i)

            run_specs = br["run_specs"]
            cmd_parts = run_specs["cmd_parts"]

            if not fn_wrapped:
                # just wrap the user cmd once (shared by all boxes/nodes)
                assert cmd_parts[0] == "python"
                assert cmd_parts[1] == "-u"
                assert len(cmd_parts[2]) > 0

                # update the target_fn (might have been switched to the xt controller)
                target_fn = cmd_parts[2]
                arg_parts = cmd_parts[3:]

                setup = self.config.get_setup_from_target_def(self.compute_def)

                # we only do this once (for the first box/job)
                fn_wrapped = super().wrap_user_command(cmd_parts,
                                                       snapshot_dir,
                                                       store_data_dir,
                                                       data_action,
                                                       data_writable,
                                                       store_model_dir,
                                                       model_action,
                                                       model_writable,
                                                       storage_name,
                                                       storage_key,
                                                       actions,
                                                       is_windows=is_windows,
                                                       sudo_available=False,
                                                       username=username,
                                                       use_username=False,
                                                       install_blobfuse=True,
                                                       setup=setup,
                                                       change_dir=False,
                                                       args=args)

                # AML wants a python script, so use our tiny python shim to run wrapped.sh
                fn_shim = "aml_shim.py"
                fn_from = file_utils.get_xtlib_dir() + "/backends/" + fn_shim
                fn_to = snapshot_dir + "/" + fn_shim
                shutil.copyfile(fn_from, fn_to)

                # copy to submit-logs
                utils.copy_to_submit_logs(args, fn_from)

            # we update each box's command (passing RUN_NAME as arg to wrapped.sh)
            script_part = "{} {} {}".format(os.path.basename(fn_wrapped),
                                            node_id, run_name)
            sh_parts = ['/bin/bash', '--login', script_part]

            # pass sh_parts as a single argument to avoid wierd "arg": 1 problems with AML estimators
            wrapped_parts = ["python", "-u", fn_shim, " ".join(sh_parts)]
            run_specs["cmd_parts"] = wrapped_parts
示例#9
0
def get_default_config_template_path():
    return os.path.join(file_utils.get_xtlib_dir(), "helpers",
                        constants.FN_DEFAULT_TEMPLATE)