예제 #1
0
파일: case_clone.py 프로젝트: bertinia/cime
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
예제 #2
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
예제 #3
0
 def set_casename(self):
     text = self.CaseNameInput.text()
     if check_name(text):
         self.CreateNewcaseArgs["case"] = text
         self.ApplyCreateNewcase.setEnabled(True)
     self.check_ready_to_apply()