Files
doos/src/container.hpp
T

115 lines
4.3 KiB
C++

#pragma once
#include <sys/types.h>
#include <cstdint>
#include <filesystem>
#include <functional>
#include <optional>
#include <string>
#include <vector>
#include "idmap.hpp"
#include "image.hpp"
#include "network.hpp"
#include "util.hpp"
namespace doos {
// What the user asked for. Unset fields mean "default on create, no constraint on existing".
struct Options {
std::optional<NetMode> net;
std::optional<std::string> image;
std::optional<IdMode> ids;
std::optional<std::uint64_t> size;
std::optional<std::uint64_t> memory;
std::optional<std::uint32_t> pids;
std::optional<std::uint32_t> milliCpus; // 0 = all cores
std::optional<bool> relaxed; // --hardening relaxed
};
class Container {
public:
Container(std::filesystem::path dir, std::string name) : dir_(std::move(dir)), name_(std::move(name)) {}
static void validateName(const std::string& name);
const std::string& name() const { return name_; }
const std::filesystem::path& dir() const { return dir_; }
std::filesystem::path rootfs() const { return dir_ / "rootfs"; }
std::filesystem::path layer(const std::string& hostDir) const; // layers/<name>/{upper,work}
std::filesystem::path privateDir(const std::string& hostDir) const;
std::filesystem::path lockFile() const { return dir_ / "lock"; }
std::filesystem::path pidFile() const { return dir_ / "pid"; }
std::filesystem::path metaFile() const { return dir_ / "meta"; }
// Where /etc lives on disk for this container (resolv.conf and tool config are written there).
std::filesystem::path etcDir() const;
NetMode net() const { return net_; }
long created() const { return created_; }
const std::string& image() const { return image_; }
bool imageMode() const { return !image_.empty(); }
IdMode ids() const { return ids_; }
std::uint64_t sizeCap() const { return size_; }
void setSizeCap(std::uint64_t bytes);
std::uint64_t memoryCap() const { return memory_; }
std::uint32_t pidsCap() const { return pids_; }
std::uint32_t milliCpus() const { return milliCpus_; }
bool relaxed() const { return relaxed_; }
// Limits take effect the next time the container starts.
void setLimits(std::optional<std::uint64_t> memory, std::optional<std::uint32_t> pids, std::optional<std::uint32_t> milliCpus);
void create(const NetMode& net, const std::string& image, IdMode ids, const Options& resolved);
void readMeta(); // meta only, no side effects
void load(); // readMeta + heal the layout
// Process id (outside view) of the container's init, if it is alive.
std::optional<pid_t> runningPid() const;
void recordPid(pid_t pid) const;
void clearPid() const;
// Mountpoints, layer dirs, and one-time seeding (skeleton, /etc copy). Idempotent.
void prepareLayout() const;
// Bytes the container wrote (writable layers and private dirs), as the host user can see them.
// Measured from inside the id map, so directories of other container ids are counted too.
std::uint64_t usedBytes(std::size_t& skipped) const;
private:
void writeMeta() const;
void seed(const std::string& marker, const std::string& label, const std::function<fsutil::SeedStats()>& work) const;
std::filesystem::path dir_;
std::string name_;
NetMode net_ = NetMode::Slirp;
long created_ = 0;
std::string image_;
IdMode ids_ = IdMode::Single;
std::uint64_t size_ = 0;
std::uint64_t memory_ = 0;
std::uint32_t pids_ = 0;
std::uint32_t milliCpus_ = 0;
bool relaxed_ = false;
};
class Store {
public:
explicit Store(std::filesystem::path root);
static Store fromEnvironment();
std::vector<Container> list() const;
// Returns the container and whether it was created by this call. Pulls a catalog image on demand.
std::pair<Container, bool> getOrCreate(const std::string& name, const Options& opts);
// Dry-run unless confirmed. Returns a human-readable report line.
std::string remove(const std::string& name, bool confirmed);
ImageStore images() const { return ImageStore(root_ / "images"); }
std::vector<std::string> containersUsing(const std::string& image) const;
const std::filesystem::path& root() const { return root_; }
private:
std::filesystem::path containersDir() const { return root_ / "containers"; }
std::filesystem::path root_;
};
} // namespace doos