Exemplo n.º 1
0
    def set_batch_system(self, batchobj, batch_system_type=None):
        if batch_system_type is not None:
            self.set_batch_system_type(batch_system_type)

        if batchobj.batch_system_node is not None and batchobj.machine_node is not None:
            for node in batchobj.get_children("", root=batchobj.machine_node):
                name = self.name(node)
                if name != 'directives':
                    oldnode = batchobj.get_optional_child(
                        name, root=batchobj.batch_system_node)
                    if oldnode is not None:
                        logger.debug("Replacing {}".format(self.name(oldnode)))
                        batchobj.remove_child(oldnode,
                                              root=batchobj.batch_system_node)

        if batchobj.batch_system_node is not None:
            self.add_child(self.copy(batchobj.batch_system_node))
        if batchobj.machine_node is not None:
            self.add_child(self.copy(batchobj.machine_node))
        if os.path.exists(
                os.path.join(self._caseroot, "LockedFiles", "env_batch.xml")):
            unlock_file(os.path.basename(batchobj.filename),
                        caseroot=self._caseroot)
        self.set_value("BATCH_SYSTEM", batch_system_type)
        if os.path.exists(os.path.join(self._caseroot, "LockedFiles")):
            lock_file(os.path.basename(batchobj.filename),
                      caseroot=self._caseroot)
Exemplo n.º 2
0
def post_build(case, logs, build_complete=False):
###############################################################################

    logdir = case.get_value("LOGDIR")

    #zip build logs to CASEROOT/logs
    if logdir:
        bldlogdir = os.path.join(logdir, "bld")
        if not os.path.exists(bldlogdir):
            os.makedirs(bldlogdir)

    for log in logs:
        logger.info("Copying build log {} to {}".format(log, bldlogdir))
        with open(log, 'rb') as f_in:
            with gzip.open("{}.gz".format(log), 'wb') as f_out:
                shutil.copyfileobj(f_in, f_out)
        if "sharedlibroot" not in log:
            shutil.copy("{}.gz".format(log), os.path.join(bldlogdir, "{}.gz".format(os.path.basename(log))))
        os.remove(log)

    if build_complete:

        # Set XML to indicate build complete
        case.set_value("BUILD_COMPLETE", True)
        case.set_value("BUILD_STATUS", 0)
        if "SMP_VALUE" in os.environ:
            case.set_value("SMP_BUILD", os.environ["SMP_VALUE"])
            case.flush()

        lock_file("env_build.xml")

        # must ensure there's an lid
        lid = os.environ["LID"] if "LID" in os.environ else get_timestamp("%y%m%d-%H%M%S")
        save_build_provenance(case, lid=lid)
Exemplo n.º 3
0
 def _init_locked_files(self, caseroot, expected):
     """
     If the locked env_run.orig.xml does not exist, copy the current
     env_run.xml file. If it does exist, restore values changed in a previous
     run of the test.
     """
     if is_locked("env_run.orig.xml"):
         self.compare_env_run(expected=expected)
     elif os.path.isfile(os.path.join(caseroot, "env_run.xml")):
         lock_file("env_run.xml", caseroot=caseroot, newname="env_run.orig.xml")
Exemplo n.º 4
0
def post_build(case, logs, build_complete=False, save_build_provenance=True):
###############################################################################
    for log in logs:
        gzip_existing_file(log)

    if build_complete:
        # must ensure there's an lid
        lid = os.environ["LID"] if "LID" in os.environ else get_timestamp("%y%m%d-%H%M%S")
        if save_build_provenance:
            save_build_provenance_sub(case, lid=lid)
        # Set XML to indicate build complete
        case.set_value("BUILD_COMPLETE", True)
        case.set_value("BUILD_STATUS", 0)
        if "SMP_VALUE" in os.environ:
            case.set_value("SMP_BUILD", os.environ["SMP_VALUE"])
            case.flush()

        lock_file("env_build.xml")
Exemplo n.º 5
0
    def _xml_phase(self, test):
    ###########################################################################
        test_case = CIME.utils.parse_test_name(test)[0]

        # Create, fill and write an envtest object
        test_dir = self._get_test_dir(test)
        envtest = EnvTest(test_dir)

        # Determine list of component classes that this coupler/driver knows how
        # to deal with. This list follows the same order as compset longnames follow.
        files = Files()
        drv_config_file = files.get_value("CONFIG_CPL_FILE")
        drv_comp = Component(drv_config_file, "CPL")
        envtest.add_elements_by_group(files, {}, "env_test.xml")
        envtest.add_elements_by_group(drv_comp, {}, "env_test.xml")
        envtest.set_value("TESTCASE", test_case)
        envtest.set_value("TEST_TESTID", self._test_id)
        envtest.set_value("CASEBASEID", test)
        if test in self._test_data and "options" in self._test_data[test] and \
                "memleak_tolerance" in self._test_data[test]['options']:
            envtest.set_value("TEST_MEMLEAK_TOLERANCE", self._test_data[test]['options']['memleak_tolerance'])

        test_argv = "-testname {} -testroot {}".format(test, self._test_root)
        if self._baseline_gen_name:
            test_argv += " -generate {}".format(self._baseline_gen_name)
            basegen_case_fullpath = os.path.join(self._baseline_root,self._baseline_gen_name, test)
            logger.debug("basegen_case is {}".format(basegen_case_fullpath))
            envtest.set_value("BASELINE_NAME_GEN", self._baseline_gen_name)
            envtest.set_value("BASEGEN_CASE", os.path.join(self._baseline_gen_name, test))
        if self._baseline_cmp_name:
            test_argv += " -compare {}".format(self._baseline_cmp_name)
            envtest.set_value("BASELINE_NAME_CMP", self._baseline_cmp_name)
            envtest.set_value("BASECMP_CASE", os.path.join(self._baseline_cmp_name, test))

        envtest.set_value("TEST_ARGV", test_argv)
        envtest.set_value("CLEANUP", self._clean)

        envtest.set_value("BASELINE_ROOT", self._baseline_root)
        envtest.set_value("GENERATE_BASELINE", self._baseline_gen_name is not None)
        envtest.set_value("COMPARE_BASELINE", self._baseline_cmp_name is not None)
        envtest.set_value("CCSM_CPRNC", self._machobj.get_value("CCSM_CPRNC", resolved=False))
        tput_tolerance = self._machobj.get_value("TEST_TPUT_TOLERANCE", resolved=False)
        envtest.set_value("TEST_TPUT_TOLERANCE", 0.25 if tput_tolerance is None else tput_tolerance)

        # Add the test instructions from config_test to env_test in the case
        config_test = Tests()
        testnode = config_test.get_test_node(test_case)
        envtest.add_test(testnode)
        # Determine the test_case from the test name
        test_case, case_opts = CIME.utils.parse_test_name(test)[:2]

        # Determine case_opts from the test_case
        if case_opts is not None:
            logger.debug("case_opts are {} ".format(case_opts))
            for opt in case_opts: # pylint: disable=not-an-iterable

                logger.debug("case_opt is {}".format(opt))
                if opt == 'D':
                    envtest.set_test_parameter("DEBUG", "TRUE")
                    logger.debug (" DEBUG set to TRUE")

                elif opt == 'E':
                    envtest.set_test_parameter("USE_ESMF_LIB", "TRUE")
                    logger.debug (" USE_ESMF_LIB set to TRUE")

                elif opt == 'CG':
                    envtest.set_test_parameter("CALENDAR", "GREGORIAN")
                    logger.debug (" CALENDAR set to {}".format(opt))

                elif opt.startswith('L'):
                    match =  re.match('L([A-Za-z])([0-9]*)', opt)
                    stop_option = {"y":"nyears", "m":"nmonths", "d":"ndays", "h":"nhours",
                                   "s":"nseconds", "n":"nsteps"}
                    opt = match.group(1)
                    envtest.set_test_parameter("STOP_OPTION",stop_option[opt])
                    opti = match.group(2)
                    envtest.set_test_parameter("STOP_N", opti)

                    logger.debug (" STOP_OPTION set to {}".format(stop_option[opt]))
                    logger.debug (" STOP_N      set to {}".format(opti))

                elif opt.startswith('R'):
                    # R option is for testing in PTS_MODE or Single Column Model
                    #  (SCM) mode
                    envtest.set_test_parameter("PTS_MODE", "TRUE")

                    # For PTS_MODE, compile with mpi-serial
                    envtest.set_test_parameter("MPILIB", "mpi-serial")

                elif (opt.startswith('I') or # Marker to distinguish tests with same name - ignored
                      opt.startswith('M') or # handled in create_newcase
                      opt.startswith('P') or # handled in create_newcase
                      opt.startswith('N') or # handled in create_newcase
                      opt.startswith('C') or # handled in create_newcase
                      opt.startswith('V')):  # handled in create_newcase
                    pass

                elif opt.startswith('IOP'):
                    logger.warning("IOP test option not yet implemented")
                else:
                    expect(False, "Could not parse option '{}' ".format(opt))

        envtest.write()
        lock_file("env_run.xml", caseroot=test_dir, newname="env_run.orig.xml")

        with Case(test_dir, read_only=False) as case:
            if self._output_root is None:
                self._output_root = case.get_value("CIME_OUTPUT_ROOT")
            # if we are running a single test we don't need sharedlibroot
            if len(self._tests) > 1 and self._cime_model != "e3sm":
                case.set_value("SHAREDLIBROOT",
                               os.path.join(self._output_root,
                                            "sharedlibroot.{}".format(self._test_id)))
            envtest.set_initial_values(case)
            case.set_value("TEST", True)
            case.set_value("SAVE_TIMING", self._save_timing)

            # Scale back build parallelism on systems with few cores
            if self._model_build_cost > self._proc_pool:
                case.set_value("GMAKE_J", self._proc_pool)
                self._model_build_cost = self._proc_pool

        return True, ""
Exemplo n.º 6
0
    def _xml_phase(self, test):
    ###########################################################################
        test_case = CIME.utils.parse_test_name(test)[0]

        # Create, fill and write an envtest object
        test_dir = self._get_test_dir(test)
        envtest = EnvTest(test_dir)

        # Determine list of component classes that this coupler/driver knows how
        # to deal with. This list follows the same order as compset longnames follow.
        files = Files()
        drv_config_file = files.get_value("CONFIG_CPL_FILE")
        drv_comp = Component(drv_config_file, "CPL")
        envtest.add_elements_by_group(files, {}, "env_test.xml")
        envtest.add_elements_by_group(drv_comp, {}, "env_test.xml")
        envtest.set_value("TESTCASE", test_case)
        envtest.set_value("TEST_TESTID", self._test_id)
        envtest.set_value("CASEBASEID", test)
        if test in self._test_data and "options" in self._test_data[test] and \
                "memleak_tolerance" in self._test_data[test]['options']:
            envtest.set_value("TEST_MEMLEAK_TOLERANCE", self._test_data[test]['options']['memleak_tolerance'])

        test_argv = "-testname {} -testroot {}".format(test, self._test_root)
        if self._baseline_gen_name:
            test_argv += " -generate {}".format(self._baseline_gen_name)
            basegen_case_fullpath = os.path.join(self._baseline_root,self._baseline_gen_name, test)
            logger.debug("basegen_case is {}".format(basegen_case_fullpath))
            envtest.set_value("BASELINE_NAME_GEN", self._baseline_gen_name)
            envtest.set_value("BASEGEN_CASE", os.path.join(self._baseline_gen_name, test))
        if self._baseline_cmp_name:
            test_argv += " -compare {}".format(self._baseline_cmp_name)
            envtest.set_value("BASELINE_NAME_CMP", self._baseline_cmp_name)
            envtest.set_value("BASECMP_CASE", os.path.join(self._baseline_cmp_name, test))

        envtest.set_value("TEST_ARGV", test_argv)
        envtest.set_value("CLEANUP", self._clean)

        envtest.set_value("BASELINE_ROOT", self._baseline_root)
        envtest.set_value("GENERATE_BASELINE", self._baseline_gen_name is not None)
        envtest.set_value("COMPARE_BASELINE", self._baseline_cmp_name is not None)
        envtest.set_value("CCSM_CPRNC", self._machobj.get_value("CCSM_CPRNC", resolved=False))
        tput_tolerance = self._machobj.get_value("TEST_TPUT_TOLERANCE", resolved=False)
        envtest.set_value("TEST_TPUT_TOLERANCE", 0.25 if tput_tolerance is None else tput_tolerance)

        # Add the test instructions from config_test to env_test in the case
        config_test = Tests()
        testnode = config_test.get_test_node(test_case)
        envtest.add_test(testnode)
        # Determine the test_case from the test name
        test_case, case_opts = CIME.utils.parse_test_name(test)[:2]

        # Determine case_opts from the test_case
        if case_opts is not None:
            logger.debug("case_opts are {} ".format(case_opts))
            for opt in case_opts: # pylint: disable=not-an-iterable

                logger.debug("case_opt is {}".format(opt))
                if opt == 'D':
                    envtest.set_test_parameter("DEBUG", "TRUE")
                    logger.debug (" DEBUG set to TRUE")

                elif opt == 'E':
                    envtest.set_test_parameter("USE_ESMF_LIB", "TRUE")
                    logger.debug (" USE_ESMF_LIB set to TRUE")

                elif opt == 'CG':
                    envtest.set_test_parameter("CALENDAR", "GREGORIAN")
                    logger.debug (" CALENDAR set to {}".format(opt))

                elif opt.startswith('L'):
                    match =  re.match('L([A-Za-z])([0-9]*)', opt)
                    stop_option = {"y":"nyears", "m":"nmonths", "d":"ndays", "h":"nhours",
                                   "s":"nseconds", "n":"nsteps"}
                    opt = match.group(1)
                    envtest.set_test_parameter("STOP_OPTION",stop_option[opt])
                    opti = match.group(2)
                    envtest.set_test_parameter("STOP_N", opti)

                    logger.debug (" STOP_OPTION set to {}".format(stop_option[opt]))
                    logger.debug (" STOP_N      set to {}".format(opti))

                elif opt.startswith('R'):
                    # R option is for testing in PTS_MODE or Single Column Model
                    #  (SCM) mode
                    envtest.set_test_parameter("PTS_MODE", "TRUE")

                    # For PTS_MODE, compile with mpi-serial
                    envtest.set_test_parameter("MPILIB", "mpi-serial")

                elif (opt.startswith('I') or # Marker to distinguish tests with same name - ignored
                      opt.startswith('M') or # handled in create_newcase
                      opt.startswith('P') or # handled in create_newcase
                      opt.startswith('N') or # handled in create_newcase
                      opt.startswith('C') or # handled in create_newcase
                      opt.startswith('V')):  # handled in create_newcase
                    pass

                elif opt.startswith('IOP'):
                    logger.warning("IOP test option not yet implemented")
                else:
                    expect(False, "Could not parse option '{}' ".format(opt))

        envtest.write()
        lock_file("env_run.xml", caseroot=test_dir, newname="env_run.orig.xml")

        with Case(test_dir, read_only=False) as case:
            if self._output_root is None:
                self._output_root = case.get_value("CIME_OUTPUT_ROOT")
            # if we are running a single test we don't need sharedlibroot
            if len(self._tests) > 1 and self._cime_model != "e3sm":
                case.set_value("SHAREDLIBROOT",
                               os.path.join(self._output_root,
                                            "sharedlibroot.{}".format(self._test_id)))
            envtest.set_initial_values(case)
            case.set_value("TEST", True)
            case.set_value("SAVE_TIMING", self._save_timing)

            # Scale back build parallelism on systems with few cores
            if self._model_build_cost > self._proc_pool:
                case.set_value("GMAKE_J", self._proc_pool)
                self._model_build_cost = self._proc_pool
Exemplo n.º 7
0
    if build_complete:
        # must ensure there's an lid
        lid = os.environ["LID"] if "LID" in os.environ else get_timestamp(
            "%y%m%d-%H%M%S")
        if save_build_provenance:
            save_build_provenance_sub(case, lid=lid)
        # Set XML to indicate build complete
        case.set_value("BUILD_COMPLETE", True)
        case.set_value("BUILD_STATUS", 0)
        if "SMP_VALUE" in os.environ:
            case.set_value("SMP_BUILD", os.environ["SMP_VALUE"])

        case.flush()

        lock_file("env_build.xml", caseroot=case.get_value("CASEROOT"))


###############################################################################
def case_build(caseroot,
               case,
               sharedlib_only=False,
               model_only=False,
               buildlist=None,
               save_build_provenance=True):
    ###############################################################################
    functor = lambda: _case_build_impl(caseroot, case, sharedlib_only,
                                       model_only, buildlist,
                                       save_build_provenance)
    cb = "case.build"
    if (sharedlib_only == True):
Exemplo n.º 8
0
def create_clone(self,
                 newcase,
                 keepexe=False,
                 mach_dir=None,
                 project=None,
                 cime_output_root=None,
                 exeroot=None,
                 rundir=None,
                 user_mods_dir=None):
    """
    Create a case clone

    If exeroot or rundir are provided (not None), sets these directories
    to the given paths; if not provided, uses default values for these
    directories. It is an error to provide exeroot if keepexe is True.
    """
    if cime_output_root is None:
        cime_output_root = self.get_value("CIME_OUTPUT_ROOT")

    newcaseroot = os.path.abspath(newcase)
    expect(not os.path.isdir(newcaseroot),
           "New caseroot directory {} already exists".format(newcaseroot))
    newcasename = os.path.basename(newcaseroot)
    expect(check_name(newcasename),
           "New case name invalid {} ".format(newcasename))
    newcase_cimeroot = os.path.abspath(get_cime_root())

    # create clone from case to case
    clone_cimeroot = self.get_value("CIMEROOT")
    if newcase_cimeroot != clone_cimeroot:
        logger.warning(" case  CIMEROOT is {} ".format(newcase_cimeroot))
        logger.warning(" clone CIMEROOT is {} ".format(clone_cimeroot))
        logger.warning(
            " It is NOT recommended to clone cases from different versions of CIME."
        )

    # *** create case object as deepcopy of clone object ***
    srcroot = os.path.join(newcase_cimeroot, "..")
    newcase = self.copy(newcasename, newcaseroot, newsrcroot=srcroot)
    newcase.set_value("CIMEROOT", newcase_cimeroot)

    # if we are cloning to a different user modify the output directory
    olduser = self.get_value("USER")
    newuser = os.environ.get("USER")
    if olduser != newuser:
        cime_output_root = cime_output_root.replace(olduser, newuser)
        newcase.set_value("USER", newuser)
    newcase.set_value("CIME_OUTPUT_ROOT", cime_output_root)

    # try to make the new output directory and raise an exception
    # on any error other than directory already exists.
    if os.path.isdir(cime_output_root):
        expect(
            os.access(cime_output_root, os.W_OK),
            "Directory {} is not writable "
            "by this user.  Use the --cime-output-root flag to provide a writable "
            "scratch directory".format(cime_output_root))
    else:
        try:
            os.makedirs(cime_output_root)
        except:
            if not os.path.isdir(cime_output_root):
                raise

    # determine if will use clone executable or not
    if keepexe:
        orig_exeroot = self.get_value("EXEROOT")
        newcase.set_value("EXEROOT", orig_exeroot)
        newcase.set_value("BUILD_COMPLETE", "TRUE")
        orig_bld_complete = self.get_value("BUILD_COMPLETE")
        if not orig_bld_complete:
            logger.warning(
                "\nWARNING: Creating a clone with --keepexe before building the original case may cause PIO_TYPENAME to be invalid in the clone"
            )
            logger.warning(
                "Avoid this message by building case one before you clone.\n")
    else:
        newcase.set_value("BUILD_COMPLETE", "FALSE")

    # set machdir
    if mach_dir is not None:
        newcase.set_value("MACHDIR", mach_dir)

    # set exeroot and rundir if requested
    if exeroot is not None:
        expect(
            not keepexe, "create_case_clone: if keepexe is True, "
            "then exeroot cannot be set")
        newcase.set_value("EXEROOT", exeroot)
    if rundir is not None:
        newcase.set_value("RUNDIR", rundir)

    # Set project id
    # Note: we do not just copy this from the clone because it seems likely that
    # users will want to change this sometimes, especially when cloning another
    # user's case. However, note that, if a project is not given, the fallback will
    # be to copy it from the clone, just like other xml variables are copied.
    if project is None:
        project = self.get_value("PROJECT", subgroup=self.get_primary_job())
    if project is not None:
        newcase.set_value("PROJECT", project)

    # create caseroot
    newcase.create_caseroot(clone=True)
    newcase.flush(flushall=True)

    # copy user_ files
    cloneroot = self.get_case_root()
    files = glob.glob(cloneroot + '/user_*')

    for item in files:
        safe_copy(item, newcaseroot)

    # copy SourceMod and Buildconf files
    # if symlinks exist, copy rather than follow links
    for casesub in ("SourceMods", "Buildconf"):
        shutil.copytree(os.path.join(cloneroot, casesub),
                        os.path.join(newcaseroot, casesub),
                        symlinks=True)

    # lock env_case.xml in new case
    lock_file("env_case.xml", newcaseroot)

    # apply user_mods if appropriate
    newcase_root = newcase.get_value("CASEROOT")
    if user_mods_dir is not None:
        if keepexe:
            # If keepexe CANNOT change any env_build.xml variables - so make a temporary copy of
            # env_build.xml and verify that it has not been modified
            safe_copy(
                os.path.join(newcaseroot, "env_build.xml"),
                os.path.join(newcaseroot, "LockedFiles", "env_build.xml"))

        # Now apply contents of user_mods directory
        apply_user_mods(newcase_root, user_mods_dir, keepexe=keepexe)

        # Determine if env_build.xml has changed
        if keepexe:
            success, comment = compare_files(
                os.path.join(newcaseroot, "env_build.xml"),
                os.path.join(newcaseroot, "LockedFiles", "env_build.xml"))
            if not success:
                logger.warning(comment)
                shutil.rmtree(newcase_root)
                expect(
                    False,
                    "env_build.xml cannot be changed via usermods if keepexe is an option: \n "
                    "Failed to clone case, removed {}\n".format(newcase_root))

    # if keep executable, then remove the new case SourceMods directory and link SourceMods to
    # the clone directory
    if keepexe:
        shutil.rmtree(os.path.join(newcase_root, "SourceMods"))
        os.symlink(os.path.join(cloneroot, "SourceMods"),
                   os.path.join(newcase_root, "SourceMods"))

    # Update README.case
    fclone = open(cloneroot + "/README.case", "r")
    fnewcase = open(newcaseroot + "/README.case", "a")
    fnewcase.write("\n    *** original clone README follows ****")
    fnewcase.write("\n " + fclone.read())

    clonename = self.get_value("CASE")
    logger.info(" Successfully created new case {} from clone case {} ".format(
        newcasename, clonename))

    newcase.case_setup()

    return newcase
Exemplo n.º 9
0
def _submit(case, job=None, no_batch=False, prereq=None, allow_fail=False, resubmit=False,
            resubmit_immediate=False, skip_pnl=False, mail_user=None, mail_type=None,
            batch_args=None):
    if job is None:
        job = case.get_primary_job()

    # Check if CONTINUE_RUN value makes sense
    if job != "case.test" and case.get_value("CONTINUE_RUN"):
        rundir = case.get_value("RUNDIR")
        caseroot = case.get_value("CASEROOT")
        expect(os.path.isdir(rundir),
               "CONTINUE_RUN is true but RUNDIR {} does not exist".format(rundir))
        expect(len(glob.glob(os.path.join(rundir, "*.nc"))) > 0,
               "CONTINUE_RUN is true but this case does not appear to have been run before (no .nc files in RUNDIR)")
        expect(does_file_have_string(os.path.join(caseroot, "CaseStatus"), "case.run {}".format(CASE_SUCCESS)),
               "CONTINUE_RUN is true but this case does not appear to have ever run successfully")

    # if case.submit is called with the no_batch flag then we assume that this
    # flag will stay in effect for the duration of the RESUBMITs
    env_batch = case.get_env("batch")
    if resubmit:
        if env_batch.get_batch_system_type() == "none":
            no_batch = True

        # This is a resubmission, do not reinitialize test values
        if job == "case.test":
            case.set_value("IS_FIRST_RUN", False)

        resub = case.get_value("RESUBMIT")
        logger.info("Submitting job '{}', resubmit={:d}".format(job, resub))
        case.set_value("RESUBMIT", resub-1)
        if case.get_value("RESUBMIT_SETS_CONTINUE_RUN"):
            case.set_value("CONTINUE_RUN", True)

    else:
        if job == "case.test":
            case.set_value("IS_FIRST_RUN", True)

        if no_batch:
            batch_system = "none"
        else:
            batch_system = env_batch.get_batch_system_type()

        case.set_value("BATCH_SYSTEM", batch_system)

        env_batch_has_changed = False
        try:
            case.check_lockedfile(os.path.basename(env_batch.filename))
        except SystemExit:
            env_batch_has_changed = True

        if env_batch.get_batch_system_type() != "none" and env_batch_has_changed:
            # May need to regen batch files if user made batch setting changes (e.g. walltime, queue, etc)
            logger.warning(\
"""
env_batch.xml appears to have changed, regenerating batch scripts
manual edits to these file will be lost!
""")
            env_batch.make_all_batch_files(case)

        unlock_file(os.path.basename(env_batch.filename))
        lock_file(os.path.basename(env_batch.filename))

        if job == case.get_primary_job():
            case.check_case()
            case.check_DA_settings()
            if case.get_value("MACH") == "mira":
                with open(".original_host", "w") as fd:
                    fd.write( socket.gethostname())

    #Load Modules
    case.load_env()

    case.flush()

    logger.warning("submit_jobs {}".format(job))
    job_ids = case.submit_jobs(no_batch=no_batch, job=job, prereq=prereq,
                               skip_pnl=skip_pnl, resubmit_immediate=resubmit_immediate,
                               allow_fail=allow_fail, mail_user=mail_user,
                               mail_type=mail_type, batch_args=batch_args)

    xml_jobids = []
    for jobname, jobid in job_ids.items():
        logger.info("Submitted job {} with id {}".format(jobname, jobid))
        if jobid:
            xml_jobids.append("{}:{}".format(jobname, jobid))

    xml_jobid_text = ", ".join(xml_jobids)
    if xml_jobid_text:
        case.set_value("JOB_IDS", xml_jobid_text)

    return xml_jobid_text
Exemplo n.º 10
0
    for log in logs:
        gzip_existing_file(log)

    if build_complete:
        # must ensure there's an lid
        lid = os.environ["LID"] if "LID" in os.environ else get_timestamp("%y%m%d-%H%M%S")
        if save_build_provenance:
            save_build_provenance_sub(case, lid=lid)
        # Set XML to indicate build complete
        case.set_value("BUILD_COMPLETE", True)
        case.set_value("BUILD_STATUS", 0)
        if "SMP_VALUE" in os.environ:
            case.set_value("SMP_BUILD", os.environ["SMP_VALUE"])
            case.flush()

        lock_file("env_build.xml")


###############################################################################
def case_build(caseroot, case, sharedlib_only=False, model_only=False, buildlist=None, save_build_provenance=True):
###############################################################################
    functor = lambda: _case_build_impl(caseroot, case, sharedlib_only, model_only, buildlist,
                                       save_build_provenance)
    return run_and_log_case_status(functor, "case.build", caseroot=caseroot)

###############################################################################
def clean(case, cleanlist=None, clean_all=False, clean_depends=None):
###############################################################################
    functor = lambda: _clean_impl(case, cleanlist, clean_all, clean_depends)
    return run_and_log_case_status(functor, "build.clean", caseroot=case.get_value("CASEROOT"))
Exemplo n.º 11
0
def _case_setup_impl(case, caseroot, clean=False, test_mode=False, reset=False):
###############################################################################
    os.chdir(caseroot)

    # Check that $DIN_LOC_ROOT exists - and abort if not a namelist compare tests
    din_loc_root = case.get_value("DIN_LOC_ROOT")
    testcase     = case.get_value("TESTCASE")
    expect(not (not os.path.isdir(din_loc_root) and testcase != "SBN"),
           "inputdata root is not a directory: {}".format(din_loc_root))

    # Remove batch scripts
    if reset or clean:
        # clean batch script
        batch_script = get_batch_script_for_job(case.get_primary_job())
        if os.path.exists(batch_script):
            os.remove(batch_script)
            logger.info("Successfully cleaned batch script {}".format(batch_script))

        if not test_mode:
            # rebuild the models (even on restart)
            case.set_value("BUILD_COMPLETE", False)

    if not clean:
        case.load_env()

        models = case.get_values("COMP_CLASSES")
        mach = case.get_value("MACH")
        compiler = case.get_value("COMPILER")
        debug = case.get_value("DEBUG")
        mpilib = case.get_value("MPILIB")
        sysos = case.get_value("OS")
        expect(mach is not None, "xml variable MACH is not set")

        # creates the Macros.make, Depends.compiler, Depends.machine, Depends.machine.compiler
        # and env_mach_specific.xml if they don't already exist.
        if not os.path.isfile("Macros.make") or not os.path.isfile("env_mach_specific.xml"):
            configure(Machines(machine=mach), caseroot, ["Makefile"], compiler, mpilib, debug, sysos)

        # Set tasks to 1 if mpi-serial library
        if mpilib == "mpi-serial":
            for vid, value in case:
                if vid.startswith("NTASKS") and value != 1:
                    case.set_value(vid, 1)

        # Check ninst.
        # In CIME there can be multiple instances of each component model (an ensemble) NINST is the instance of that component.
        multi_driver = case.get_value("MULTI_DRIVER")
        nthrds = 1
        for comp in models:
            ntasks = case.get_value("NTASKS_{}".format(comp))
            nthrds = max(nthrds,case.get_value("NTHRDS_{}".format(comp)))
            if comp == "CPL":
                continue
            ninst  = case.get_value("NINST_{}".format(comp))
            if multi_driver:
                expect(case.get_value("NINST_LAYOUT_{}".format(comp)) == "concurrent",
                       "If multi_driver is TRUE, NINST_LAYOUT_{} must be concurrent".format(comp))
                case.set_value("NTASKS_PER_INST_{}".format(comp), ntasks)
            else:
                if ninst > ntasks:
                    if ntasks == 1:
                        case.set_value("NTASKS_{}".format(comp), ninst)
                        ntasks = ninst
                    else:
                        expect(False, "NINST_{} value {:d} greater than NTASKS_{} {:d}".format(comp, ninst, comp, ntasks))
                case.set_value("NTASKS_PER_INST_{}".format(comp), int(ntasks / ninst))
        if nthrds > 1:
            case.set_value("BUILD_THREADED",True)

        if os.path.exists(get_batch_script_for_job(case.get_primary_job())):
            logger.info("Machine/Decomp/Pes configuration has already been done ...skipping")

            case.initialize_derived_attributes()

            case.set_value("SMP_PRESENT", case.get_build_threaded())

        else:
            case.check_pelayouts_require_rebuild(models)

            unlock_file("env_build.xml")
            unlock_file("env_batch.xml")

            case.flush()
            case.check_lockedfiles()

            case.initialize_derived_attributes()

            cost_per_node = 16 if case.get_value("MACH") == "yellowstone" else case.get_value("MAX_MPITASKS_PER_NODE")
            case.set_value("COST_PES", case.num_nodes * cost_per_node)
            case.set_value("TOTALPES", case.total_tasks)
            case.set_value("SMP_PRESENT", case.get_build_threaded())

            # create batch files
            env_batch = case.get_env("batch")
            env_batch.make_all_batch_files(case)
            if get_model() == "e3sm" and not case.get_value("TEST"):
                input_batch_script = os.path.join(case.get_value("MACHDIR"), "template.case.run.sh")
                env_batch.make_batch_script(input_batch_script, "case.run", case, outfile=get_batch_script_for_job("case.run.sh"))

            # May need to select new batch settings if pelayout changed (e.g. problem is now too big for prev-selected queue)
            env_batch.set_job_defaults([(case.get_primary_job(), {})], case)
            case.schedule_rewrite(env_batch)

            # Make a copy of env_mach_pes.xml in order to be able
            # to check that it does not change once case.setup is invoked
            case.flush()
            logger.debug("at copy TOTALPES = {}".format(case.get_value("TOTALPES")))
            lock_file("env_mach_pes.xml")
            lock_file("env_batch.xml")

        # Create user_nl files for the required number of instances
        if not os.path.exists("user_nl_cpl"):
            logger.info("Creating user_nl_xxx files for components and cpl")

        # loop over models
        for model in models:
            comp = case.get_value("COMP_{}".format(model))
            logger.debug("Building {} usernl files".format(model))
            _build_usernl_files(case, model, comp)
            if comp == "cism":
                glcroot = case.get_value("COMP_ROOT_DIR_GLC")
                run_cmd_no_fail("{}/cime_config/cism.template {}".format(glcroot, caseroot))

        _build_usernl_files(case, "drv", "cpl")

        # Create needed directories for case
        case.create_dirs()

        logger.info("If an old case build already exists, might want to run \'case.build --clean\' before building")

        # Some tests need namelists created here (ERP) - so do this if we are in test mode
        if test_mode or get_model() == "e3sm":
            logger.info("Generating component namelists as part of setup")
            case.create_namelists()

        # Record env information
        env_module = case.get_env("mach_specific")
        env_module.make_env_mach_specific_file("sh", case)
        env_module.make_env_mach_specific_file("csh", case)
        env_module.save_all_env_info("software_environment.txt")
Exemplo n.º 12
0
def create_clone(self, newcase, keepexe=False, mach_dir=None, project=None,
                      cime_output_root=None, exeroot=None, rundir=None,
                      user_mods_dir=None):
    """
    Create a case clone

    If exeroot or rundir are provided (not None), sets these directories
    to the given paths; if not provided, uses default values for these
    directories. It is an error to provide exeroot if keepexe is True.
    """
    if cime_output_root is None:
        cime_output_root = self.get_value("CIME_OUTPUT_ROOT")

    newcaseroot = os.path.abspath(newcase)
    expect(not os.path.isdir(newcaseroot),
           "New caseroot directory {} already exists".format(newcaseroot))
    newcasename = os.path.basename(newcaseroot)
    expect(check_name(newcasename),
           "New case name invalid {} ".format(newcasename))
    newcase_cimeroot = os.path.abspath(get_cime_root())

    # create clone from case to case
    clone_cimeroot = self.get_value("CIMEROOT")
    if newcase_cimeroot != clone_cimeroot:
        logger.warning(" case  CIMEROOT is {} ".format(newcase_cimeroot))
        logger.warning(" clone CIMEROOT is {} ".format(clone_cimeroot))
        logger.warning(" It is NOT recommended to clone cases from different versions of CIME.")

    # *** create case object as deepcopy of clone object ***
    srcroot = os.path.join(newcase_cimeroot,"..")
    newcase = self.copy(newcasename, newcaseroot, newsrcroot=srcroot)
    newcase.set_value("CIMEROOT", newcase_cimeroot)

    # if we are cloning to a different user modify the output directory
    olduser = self.get_value("USER")
    newuser = os.environ.get("USER")
    if olduser != newuser:
        cime_output_root = cime_output_root.replace(olduser, newuser)
        newcase.set_value("USER", newuser)
    newcase.set_value("CIME_OUTPUT_ROOT", cime_output_root)

    # try to make the new output directory and raise an exception
    # on any error other than directory already exists.
    if os.path.isdir(cime_output_root):
        expect(os.access(cime_output_root, os.W_OK), "Directory {} is not writable "
               "by this user.  Use the --cime-output-root flag to provide a writable "
               "scratch directory".format(cime_output_root))
    else:
        try:
            os.makedirs(cime_output_root)
        except:
            if not os.path.isdir(cime_output_root):
                raise

    # determine if will use clone executable or not
    if keepexe:
        orig_exeroot = self.get_value("EXEROOT")
        newcase.set_value("EXEROOT", orig_exeroot)
        newcase.set_value("BUILD_COMPLETE","TRUE")
        orig_bld_complete = self.get_value("BUILD_COMPLETE")
        if not orig_bld_complete:
            logger.warning("\nWARNING: Creating a clone with --keepexe before building the original case may cause PIO_TYPENAME to be invalid in the clone")
            logger.warning("Avoid this message by building case one before you clone.\n")
    else:
        newcase.set_value("BUILD_COMPLETE","FALSE")

    # set machdir
    if mach_dir is not None:
        newcase.set_value("MACHDIR", mach_dir)

    # set exeroot and rundir if requested
    if exeroot is not None:
        expect(not keepexe, "create_case_clone: if keepexe is True, "
               "then exeroot cannot be set")
        newcase.set_value("EXEROOT", exeroot)
    if rundir is not None:
        newcase.set_value("RUNDIR", rundir)

    # Set project id
    # Note: we do not just copy this from the clone because it seems likely that
    # users will want to change this sometimes, especially when cloning another
    # user's case. However, note that, if a project is not given, the fallback will
    # be to copy it from the clone, just like other xml variables are copied.
    if project is None:
        project = self.get_value("PROJECT", subgroup=self.get_primary_job())
    if project is not None:
        newcase.set_value("PROJECT", project)

    # create caseroot
    newcase.create_caseroot(clone=True)
    newcase.flush(flushall=True)

    # copy user_ files
    cloneroot = self.get_case_root()
    files = glob.glob(cloneroot + '/user_*')

    for item in files:
        safe_copy(item, newcaseroot)

    # copy SourceMod and Buildconf files
    # if symlinks exist, copy rather than follow links
    for casesub in ("SourceMods", "Buildconf"):
        shutil.copytree(os.path.join(cloneroot, casesub),
                        os.path.join(newcaseroot, casesub),
                        symlinks=True)

    # lock env_case.xml in new case
    lock_file("env_case.xml", newcaseroot)

    # apply user_mods if appropriate
    newcase_root = newcase.get_value("CASEROOT")
    if user_mods_dir is not None:
        if keepexe:
            # If keepexe CANNOT change any env_build.xml variables - so make a temporary copy of
            # env_build.xml and verify that it has not been modified
            safe_copy(os.path.join(newcaseroot, "env_build.xml"),
                      os.path.join(newcaseroot, "LockedFiles", "env_build.xml"))

        # Now apply contents of user_mods directory
        apply_user_mods(newcase_root, user_mods_dir, keepexe=keepexe)

        # Determine if env_build.xml has changed
        if keepexe:
            success, comment = compare_files(os.path.join(newcaseroot, "env_build.xml"),
                                             os.path.join(newcaseroot, "LockedFiles", "env_build.xml"))
            if not success:
                logger.warning(comment)
                shutil.rmtree(newcase_root)
                expect(False, "env_build.xml cannot be changed via usermods if keepexe is an option: \n "
                           "Failed to clone case, removed {}\n".format(newcase_root))

    # if keep executable, then remove the new case SourceMods directory and link SourceMods to
    # the clone directory
    if keepexe:
        shutil.rmtree(os.path.join(newcase_root, "SourceMods"))
        os.symlink(os.path.join(cloneroot, "SourceMods"),
                   os.path.join(newcase_root, "SourceMods"))

    # Update README.case
    fclone   = open(cloneroot + "/README.case", "r")
    fnewcase = open(newcaseroot  + "/README.case", "a")
    fnewcase.write("\n    *** original clone README follows ****")
    fnewcase.write("\n " +  fclone.read())

    clonename = self.get_value("CASE")
    logger.info(" Successfully created new case {} from clone case {} ".format(newcasename, clonename))

    newcase.case_setup()

    return newcase
Exemplo n.º 13
0
            if not "cam.i" in newfile:
                if os.path.lexists(newfile):
                    os.unlink(newfile)
                os.symlink(reffile, newfile)


def per_run_case_updates(case, date, sdrestdir, user_mods_dir, rundir):
    caseroot = case.get_value("CASEROOT")
    basecasename = os.path.basename(caseroot)[:-6]
    member = os.path.basename(caseroot)[-2:]

    unlock_file("env_case.xml", caseroot=caseroot)
    casename = basecasename + "." + date + "." + member
    case.set_value("CASE", casename)
    case.flush()
    lock_file("env_case.xml", caseroot=caseroot)

    case.set_value("CONTINUE_RUN", False)
    case.set_value("RUN_REFDATE", date)
    case.set_value("RUN_STARTDATE", date)
    case.set_value("RUN_REFDIR", sdrestdir)
    case.set_value("REST_OPTION", 'none')
    case.set_value("PROJECT", "P93300007")
    #    dout_s_root = case.get_value("DOUT_S_ROOT")
    #    dout_s_root = os.path.join(os.path.dirname(dout_s_root),casename)
    #    if dout_s_root.startswith("/glade/scratch"):
    #        dout_s_root = dout_s_root.replace("/glade/scratch/","/glade/p/nsc/ncgd0042/")
    #    case.set_value("DOUT_S_ROOT",dout_s_root)
    # restage user_nl files for each run
    for usermod in glob.iglob(user_mods_dir + "/user*"):
        safe_copy(usermod, caseroot)
Exemplo n.º 14
0
    if not external_workflow:
        try:
            case.check_lockedfile(os.path.basename(env_batch.filename),
                                  caseroot=caseroot)
        except:
            env_batch_has_changed = True

    if batch_system != "none" and env_batch_has_changed and not external_workflow:
        # May need to regen batch files if user made batch setting changes (e.g. walltime, queue, etc)
        logger.warning("""
env_batch.xml appears to have changed, regenerating batch scripts
manual edits to these file will be lost!
""")
        env_batch.make_all_batch_files(case)
    case.flush()
    lock_file(os.path.basename(env_batch.filename), caseroot=caseroot)

    if resubmit:
        # This is a resubmission, do not reinitialize test values
        if job == "case.test":
            case.set_value("IS_FIRST_RUN", False)

        resub = case.get_value("RESUBMIT")
        logger.info("Submitting job '{}', resubmit={:d}".format(job, resub))
        case.set_value("RESUBMIT", resub - 1)
        if case.get_value("RESUBMIT_SETS_CONTINUE_RUN"):
            case.set_value("CONTINUE_RUN", True)

    else:
        if job == "case.test":
            case.set_value("IS_FIRST_RUN", True)
Exemplo n.º 15
0
            env_batch.make_all_batch_files(case)
            if get_model() == "e3sm" and not case.get_value("TEST"):
                input_batch_script = os.path.join(case.get_value("MACHDIR"),
                                                  "template.case.run.sh")
                env_batch.make_batch_script(
                    input_batch_script,
                    "case.run",
                    case,
                    outfile=get_batch_script_for_job("case.run.sh"))

            # Make a copy of env_mach_pes.xml in order to be able
            # to check that it does not change once case.setup is invoked
            case.flush()
            logger.debug("at copy TOTALPES = {}".format(
                case.get_value("TOTALPES")))
            lock_file("env_mach_pes.xml")
            lock_file("env_batch.xml")

        # Create user_nl files for the required number of instances
        if not os.path.exists("user_nl_cpl"):
            logger.info("Creating user_nl_xxx files for components and cpl")

        # loop over models
        for model in models:
            comp = case.get_value("COMP_{}".format(model))
            logger.debug("Building {} usernl files".format(model))
            _build_usernl_files(case, model, comp)
            if comp == "cism":
                glcroot = case.get_value("COMP_ROOT_DIR_GLC")
                run_cmd_no_fail("{}/cime_config/cism.template {}".format(
                    glcroot, caseroot))
Exemplo n.º 16
0
        try:
            case.check_lockedfile(os.path.basename(env_batch.filename))
        except:
            env_batch_has_changed = True

    if batch_system != "none" and env_batch_has_changed and not external_workflow:
        # May need to regen batch files if user made batch setting changes (e.g. walltime, queue, etc)
        logger.warning(\
"""
env_batch.xml appears to have changed, regenerating batch scripts
manual edits to these file will be lost!
""")
        env_batch.make_all_batch_files(case)

    unlock_file(os.path.basename(env_batch.filename))
    lock_file(os.path.basename(env_batch.filename))

    if resubmit:
        # This is a resubmission, do not reinitialize test values
        if job == "case.test":
            case.set_value("IS_FIRST_RUN", False)

        resub = case.get_value("RESUBMIT")
        logger.info("Submitting job '{}', resubmit={:d}".format(job, resub))
        case.set_value("RESUBMIT", resub-1)
        if case.get_value("RESUBMIT_SETS_CONTINUE_RUN"):
            case.set_value("CONTINUE_RUN", True)

    else:
        if job == "case.test":
            case.set_value("IS_FIRST_RUN", True)
Exemplo n.º 17
0
def _submit(case, job=None, no_batch=False, prereq=None, allow_fail=False, resubmit=False,
            resubmit_immediate=False, skip_pnl=False, mail_user=None, mail_type=None,
            batch_args=None):
    if job is None:
        job = case.get_primary_job()

    # Check if CONTINUE_RUN value makes sense
    if job != "case.test" and case.get_value("CONTINUE_RUN"):
        rundir = case.get_value("RUNDIR")
        expect(os.path.isdir(rundir),
               "CONTINUE_RUN is true but RUNDIR {} does not exist".format(rundir))
        # only checks for the first instance in a multidriver case
        if case.get_value("MULTI_DRIVER"):
            rpointer = "rpointer.drv_0001"
        else:
            rpointer = "rpointer.drv"
        expect(os.path.exists(os.path.join(rundir,rpointer)),
               "CONTINUE_RUN is true but this case does not appear to have restart files staged in {}".format(rundir))
        # Finally we open the rpointer file and check that it's correct
        casename = case.get_value("CASE")
        with open(os.path.join(rundir,rpointer), "r") as fd:
            ncfile = fd.readline().strip()
            expect(ncfile.startswith(casename) and
                   os.path.exists(os.path.join(rundir,ncfile)),
                   "File {ncfile} not present or does not match case {casename}".
                   format(ncfile=os.path.join(rundir,ncfile),casename=casename))

    # if case.submit is called with the no_batch flag then we assume that this
    # flag will stay in effect for the duration of the RESUBMITs
    env_batch = case.get_env("batch")

    if resubmit and env_batch.get_batch_system_type() == "none":
        no_batch = True
    if no_batch:
        batch_system = "none"
    else:
        batch_system = env_batch.get_batch_system_type()

    case.set_value("BATCH_SYSTEM", batch_system)

    env_batch_has_changed = False
    try:
        case.check_lockedfile(os.path.basename(env_batch.filename))
    except:
        env_batch_has_changed = True

    if batch_system != "none" and env_batch_has_changed:
        # May need to regen batch files if user made batch setting changes (e.g. walltime, queue, etc)
        logger.warning(\
"""
env_batch.xml appears to have changed, regenerating batch scripts
manual edits to these file will be lost!
""")
        env_batch.make_all_batch_files(case)

    unlock_file(os.path.basename(env_batch.filename))
    lock_file(os.path.basename(env_batch.filename))

    if resubmit:
        # This is a resubmission, do not reinitialize test values
        if job == "case.test":
            case.set_value("IS_FIRST_RUN", False)

        resub = case.get_value("RESUBMIT")
        logger.info("Submitting job '{}', resubmit={:d}".format(job, resub))
        case.set_value("RESUBMIT", resub-1)
        if case.get_value("RESUBMIT_SETS_CONTINUE_RUN"):
            case.set_value("CONTINUE_RUN", True)

    else:
        if job == "case.test":
            case.set_value("IS_FIRST_RUN", True)

        if no_batch:
            batch_system = "none"
        else:
            batch_system = env_batch.get_batch_system_type()

        case.set_value("BATCH_SYSTEM", batch_system)

        env_batch_has_changed = False
        try:
            case.check_lockedfile(os.path.basename(env_batch.filename))
        except CIMEError:
            env_batch_has_changed = True

        if env_batch.get_batch_system_type() != "none" and env_batch_has_changed:
            # May need to regen batch files if user made batch setting changes (e.g. walltime, queue, etc)
            logger.warning(\
"""
env_batch.xml appears to have changed, regenerating batch scripts
manual edits to these file will be lost!
""")
            env_batch.make_all_batch_files(case)

        unlock_file(os.path.basename(env_batch.filename))
        lock_file(os.path.basename(env_batch.filename))

        if job == case.get_primary_job():
            case.check_case()
            case.check_DA_settings()
            if case.get_value("MACH") == "mira":
                with open(".original_host", "w") as fd:
                    fd.write( socket.gethostname())

    #Load Modules
    case.load_env()

    case.flush()

    logger.warning("submit_jobs {}".format(job))
    job_ids = case.submit_jobs(no_batch=no_batch, job=job, prereq=prereq,
                               skip_pnl=skip_pnl, resubmit_immediate=resubmit_immediate,
                               allow_fail=allow_fail, mail_user=mail_user,
                               mail_type=mail_type, batch_args=batch_args)

    xml_jobids = []
    for jobname, jobid in job_ids.items():
        logger.info("Submitted job {} with id {}".format(jobname, jobid))
        if jobid:
            xml_jobids.append("{}:{}".format(jobname, jobid))

    xml_jobid_text = ", ".join(xml_jobids)
    if xml_jobid_text:
        case.set_value("JOB_IDS", xml_jobid_text)

    return xml_jobid_text