Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix use of --module-only on existing installations without write permissions #3659

Merged
63 changes: 41 additions & 22 deletions easybuild/framework/easyblock.py
Original file line number Diff line number Diff line change
Expand Up @@ -2994,7 +2994,13 @@ def make_module_step(self, fake=False):
self.module_generator.create_symlinks(mod_symlink_paths, fake=fake)

if ActiveMNS().mns.det_make_devel_module() and not fake and build_option('generate_devel_module'):
self.make_devel_module()
try:
self.make_devel_module()
except EasyBuildError as error:
if build_option('module_only'):
self.log.info("Using --module-only so can recover from error: %s", error)
else:
raise error
else:
self.log.info("Skipping devel module...")

Expand Down Expand Up @@ -3449,14 +3455,20 @@ def build_and_install_one(ecdict, init_env):
buildstats = get_build_stats(app, start_time, build_option('command_line'))
_log.info("Build stats: %s" % buildstats)

# move the reproducability files to the final log directory
archive_reprod_dir = os.path.join(new_log_dir, REPROD)
if os.path.exists(archive_reprod_dir):
backup_dir = find_backup_name_candidate(archive_reprod_dir)
move_file(archive_reprod_dir, backup_dir)
_log.info("Existing reproducability directory %s backed up to %s", archive_reprod_dir, backup_dir)
move_file(reprod_dir, archive_reprod_dir)
_log.info("Wrote files for reproducability to %s", archive_reprod_dir)
try:
# move the reproducability files to the final log directory
archive_reprod_dir = os.path.join(new_log_dir, REPROD)
if os.path.exists(archive_reprod_dir):
backup_dir = find_backup_name_candidate(archive_reprod_dir)
move_file(archive_reprod_dir, backup_dir)
_log.info("Existing reproducability directory %s backed up to %s", archive_reprod_dir, backup_dir)
move_file(reprod_dir, archive_reprod_dir)
_log.info("Wrote files for reproducability to %s", archive_reprod_dir)
except EasyBuildError as error:
if build_option('module_only'):
_log.info("Using --module-only so can recover from error: %s", error)
else:
raise error

try:
# upload easyconfig (and patch files) to central repository
Expand All @@ -3476,22 +3488,29 @@ def build_and_install_one(ecdict, init_env):
# cleanup logs
app.close_log()
log_fn = os.path.basename(get_log_filename(app.name, app.version))
application_log = os.path.join(new_log_dir, log_fn)
move_logs(app.logfile, application_log)
try:
application_log = os.path.join(new_log_dir, log_fn)
move_logs(app.logfile, application_log)

newspec = os.path.join(new_log_dir, app.cfg.filename())
copy_file(spec, newspec)
_log.debug("Copied easyconfig file %s to %s", spec, newspec)
newspec = os.path.join(new_log_dir, app.cfg.filename())
copy_file(spec, newspec)
_log.debug("Copied easyconfig file %s to %s", spec, newspec)

# copy patches
for patch in app.patches:
target = os.path.join(new_log_dir, os.path.basename(patch['path']))
copy_file(patch['path'], target)
_log.debug("Copied patch %s to %s", patch['path'], target)
# copy patches
for patch in app.patches:
target = os.path.join(new_log_dir, os.path.basename(patch['path']))
copy_file(patch['path'], target)
_log.debug("Copied patch %s to %s", patch['path'], target)

if build_option('read_only_installdir'):
# take away user write permissions (again)
adjust_permissions(new_log_dir, stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH, add=False, recursive=True)
if build_option('read_only_installdir'):
# take away user write permissions (again)
adjust_permissions(new_log_dir, stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH, add=False, recursive=True)
except EasyBuildError as error:
if build_option('module_only'):
application_log = None
_log.debug("Using --module-only so can recover from error: %s", error)
else:
raise error

end_timestamp = datetime.now()

Expand Down
19 changes: 18 additions & 1 deletion test/framework/toy_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -1625,8 +1625,25 @@ def test_module_only(self):
modtxt = read_file(toy_core_mod)
self.assertTrue(re.search('load.*intel/2018a', modtxt), "load statement for intel/2018a found in module")

os.remove(toy_mod)
# Test we can create a module even for an installation where we don't have write permissions
os.remove(toy_core_mod)
# remove the write permissions on the installation
adjust_permissions(prefix, stat.S_IRUSR | stat.S_IXUSR, relative=False)
self.assertFalse(os.path.exists(toy_core_mod))
self.eb_main(args, do_build=True, raise_error=True)
self.assertTrue(os.path.exists(toy_core_mod))
# existing install is reused
modtxt2 = read_file(toy_core_mod)
self.assertTrue(re.search("set root %s" % prefix, modtxt2))
self.assertEqual(len(os.listdir(os.path.join(self.test_installpath, 'software'))), 3)
self.assertEqual(len(os.listdir(os.path.join(self.test_installpath, 'software', 'toy'))), 1)

# make sure load statements for dependencies are included
modtxt = read_file(toy_core_mod)
self.assertTrue(re.search('load.*intel/2018a', modtxt), "load statement for intel/2018a found in module")

os.remove(toy_core_mod)
os.remove(toy_mod)

# test installing (only) additional module in Lua syntax (if Lmod is available)
lmod_abspath = os.environ.get('LMOD_CMD') or which('lmod')
Expand Down