Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ barkeep_dep = declare_dependency(
lib_src = [
'src/site/site.cpp',
'src/uenv/env.cpp',
'src/uenv/modular_env.cpp',
'src/uenv/log.cpp',
'src/uenv/meta.cpp',
'src/uenv/oras.cpp',
Expand Down
5 changes: 5 additions & 0 deletions src/cli/run.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ You need to finish the current session by typing 'exit' or hitting '<ctrl-d>'.)"
for (auto e : env->uenvs) {
commands.push_back(fmt::format("{}:{}", e.second.sqfs_path.string(),
e.second.mount_path));
// sub-images
for (auto [sqfs, mnt] : e.second.sub_images) {
commands.push_back(
fmt::format("{}:{}", sqfs.string(), mnt.string()));
}
}

commands.push_back("--");
Expand Down
5 changes: 5 additions & 0 deletions src/cli/start.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ will not work, because it starts a new interactive shell.)",
for (auto e : env->uenvs) {
commands.push_back(fmt::format("{}:{}", e.second.sqfs_path.string(),
e.second.mount_path));
// sub-images
for (auto [sqfs, mnt] : e.second.sub_images) {
commands.push_back(
fmt::format("{}:{}", sqfs.string(), mnt.string()));
}
}

// find the current shell (zsh, bash, etc)
Expand Down
27 changes: 24 additions & 3 deletions src/uenv/env.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
#include <util/fs.h>
#include <util/subprocess.h>

#include "modular_env.hpp"
#include "util/expected.h"

namespace uenv {

using util::unexpected;
Expand Down Expand Up @@ -116,12 +119,15 @@ concretise_env(const std::string& uenv_args,
// and meta data (if they have meta data).

std::unordered_map<std::string, uenv::concrete_uenv> uenvs;
// std::vector<std::tuple<>>
std::set<fs::path> used_mounts;
std::set<fs::path> used_sqfs;
for (auto& desc : *uenv_descriptions) {
// determine the sqfs_path
fs::path sqfs_path;

// dependent images
std::vector<std::tuple<std::filesystem::path, std::filesystem::path>>
sub_images;
// if a label was used to describe the uenv (e.g. "prgenv-gnu/24.7"
// it has to be looked up in a repo.
if (auto label = desc.label()) {
Expand Down Expand Up @@ -169,7 +175,17 @@ concretise_env(const std::string& uenv_args,
// otherwise an explicit filename was provided, e.g.
// "/scratch/myimages/develp/store.squashfs"
else {
// check if desc.filename is a json
sqfs_path = fs::path(*desc.filename());
if (sqfs_path.extension() == ".json") {
// NOTE: we ignore mount_path and read it from the sqfs file
auto menv = read_modular_env(sqfs_path, *repo_arg);
if (!menv) {
return unexpected(menv.error());
}
sqfs_path = menv.value().sqfs_path;
sub_images = menv.value().sub_images;
}
}

sqfs_path = fs::absolute(sqfs_path);
Expand Down Expand Up @@ -264,8 +280,13 @@ concretise_env(const std::string& uenv_args,
used_sqfs.insert(sqfs_path);
}

uenvs[name] = concrete_uenv{name, mount, sqfs_path,
meta.path, description, std::move(views)};
uenvs[name] = concrete_uenv{.name = name,
.mount_path = mount,
.sqfs_path = sqfs_path,
.sub_images = sub_images,
.meta_path = meta.path,
.description = description,
.views = std::move(views)};
}

// A dictionary with view name as a key, and a list of uenv that provide
Expand Down
65 changes: 65 additions & 0 deletions src/uenv/modular_env.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include "modular_env.hpp"
#include <exception>
#include <fstream>
#include <nlohmann/json.hpp>
#include <tuple>
#include <uenv/repository.h>
#include <util/expected.h>

namespace uenv {

util::expected<modular_env_paths, std::string>
read_modular_env(const std::filesystem::path& modular_uenv_json_path,
std::optional<std::filesystem::path> repo_arg) {

using json = nlohmann::json;
std::ifstream f(modular_uenv_json_path.c_str());
json data;
try {
data = json::parse(f);
} catch (std::exception& e) {
return util::unexpected(
fmt::format("error modular uenv json file {}: {}",
modular_uenv_json_path.string(), e.what()));
}

if (!data.contains("root")) {
return util::unexpected(
fmt::format("error {} doesn't specify the root-image",
modular_uenv_json_path.string()));
}

auto store = uenv::open_repository(*repo_arg);
if (!store) {
return util::unexpected(
fmt::format("unable to open repo: {}", store.error()));
}

std::vector<std::tuple<std::filesystem::path, std::filesystem::path>>
sub_images;
std::filesystem::path sqfs_path =
data["root"]["image"]["file"].get<std::string>();
std::filesystem::path mount_path =
data["root"]["image"]["prefix_path"].get<std::string>();

// GPU image if present
if (data.contains("gpu")) {
std::filesystem::path image = data["gpu"]["image"]["file"];
std::filesystem::path mount = data["gpu"]["image"]["prefix_path"];
sub_images.push_back(std::make_tuple(image, mount));
}

if (data.contains("compilers")) {
for (auto entry : data["compilers"]) {
auto mount = entry["image"]["prefix_path"];
auto sqfs = entry["image"]["file"];
sub_images.push_back(std::make_tuple(sqfs, mount));
}
}

return modular_env_paths{.sqfs_path = sqfs_path,
.mount_path = mount_path,
.sub_images = sub_images};
}

} // namespace uenv
21 changes: 21 additions & 0 deletions src/uenv/modular_env.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#include "uenv/uenv.h"
#include <filesystem>
#include <optional>
#include <util/expected.h>

namespace uenv {

struct modular_env_paths {
std::filesystem::path sqfs_path;
std::filesystem::path mount_path;
std::vector<std::tuple<std::filesystem::path, std::filesystem::path>>
sub_images;
};

util::expected<modular_env_paths, std::string>
read_modular_env(const std::filesystem::path&,
std::optional<std::filesystem::path>);

} // namespace uenv
3 changes: 3 additions & 0 deletions src/uenv/uenv.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ struct concrete_uenv {
std::filesystem::path mount_path;
/// the path of the squashfs image to be mounted
std::filesystem::path sqfs_path;
/// subordinate images tuple(sqfs path, mount point)
std::vector<std::tuple<std::filesystem::path, std::filesystem::path>>
sub_images;
/// the path of the meta data - not set if no meta data path was found
std::optional<std::filesystem::path> meta_path;

Expand Down