Commit 2ed05593 authored by Jan Koester's avatar Jan Koester
Browse files

test

parent 7d52db60
Loading
Loading
Loading
Loading
+7 −8
Changes for src/containers.cpp: 7 added lines, 8 removed lines.
Original line number Diff line number Diff line
@@ -214,8 +214,8 @@ std::vector<std::string> hostNameservers() {
    return out;
}

// the container's /etc/resolv.conf (images expect that file)
std::string resolvConf(const Settings &s) {
// the container's name servers (its resolv.conf / resolv.yaml)
std::vector<std::string> nameservers(const Settings &s) {
    std::vector<std::string> servers = s.dns;
    if (servers.empty())
        for (auto &n : hostNameservers()) {
@@ -224,9 +224,7 @@ std::string resolvConf(const Settings &s) {
            servers.push_back(n);
        }
    if (servers.empty() && !s.gateway.empty()) servers.push_back(s.gateway);
    std::string out;
    for (auto &n : servers) out += "nameserver " + n + "\n";
    return out;
    return servers;
}

std::string prepare(const Settings &s) {
@@ -236,9 +234,10 @@ std::string prepare(const Settings &s) {
    std::string host = s.hostname.empty() ? s.name : s.hostname;
    // with DHCP the supervisor writes the leased address in later
    std::string ip = s.network == "bridge" && !s.address.empty() && !isDhcp(s) ? s.address.substr(0, s.address.find('/')) : "127.0.1.1";
    std::string hosts = "127.0.0.1\tlocalhost\n::1\tlocalhost ip6-localhost ip6-loopback\n" + ip + "\t" + host + "\n";
    if (!writeFile(dir + "/hosts", hosts) || !writeFile(dir + "/hostname", host + "\n") ||
        !writeFile(dir + "/resolv.conf", resolvConf(s)))
    std::vector<std::string> servers = nameservers(s);
    if (!writeFile(dir + "/hosts", hostsText(host, ip)) || !writeFile(dir + "/hostname", host + "\n") ||
        !writeFile(dir + "/resolv.conf", resolvConfText(servers)) || !writeFile(dir + "/host.yaml", hostYaml(host, ip)) ||
        !writeFile(dir + "/resolv.yaml", resolvYaml(servers)))
        return sysErr(dir, errno);
    return "";
}
+56 −4
Changes for src/runtime.cpp: 56 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -145,6 +145,21 @@ struct Pid1 {
            if (fd >= 0) close(fd);
        }
    }
    // a FenrirOS image (os-release ID or ID_LIKE fenriros): its systempp
    // reads /etc/host.yaml and /etc/resolv.yaml, not hosts and resolv.conf
    static bool fenrirOs() {
        std::string text;
        if (!readFile("/etc/os-release", text) && !readFile("/usr/lib/os-release", text)) return false;
        for (auto &line : split(text, '\n')) {
            std::string l = trim(line);
            if (!startsWith(l, "ID=") && !startsWith(l, "ID_LIKE=")) continue;
            std::string v = l.substr(l.find('=') + 1);
            if (v.size() >= 2 && (v[0] == '"' || v[0] == '\'')) v = v.substr(1, v.size() - 2);
            for (auto &w : split(v, ' '))
                if (w == "fenriros") return true;
        }
        return false;
    }
    void mountFs(const char *type, const std::string &where, unsigned long flags, const std::string &opts = "") {
        target(where, false);
        must(mount(type, where.c_str(), type, flags, opts.empty() ? nullptr : opts.c_str()) == 0, "mount " + where);
@@ -234,6 +249,12 @@ struct Pid1 {
            binds.push_back({openTree(host, ro), where, !S_ISDIR(st.st_mode), ro});
        };
        for (const char *f : {"hosts", "hostname", "resolv.conf"}) source(l.dir + "/" + f, std::string("/etc/") + f, false);
        // systempp's: only mounted in a FenrirOS image, which is known
        // after pivoting (its os-release resolved inside the container)
        size_t yamlBinds = binds.size();
        for (const char *f : {"host.yaml", "resolv.yaml"}) source(l.dir + "/" + f, std::string("/etc/") + f, false);
        std::vector<Bind> yaml(binds.begin() + yamlBinds, binds.end());
        binds.resize(yamlBinds);
        for (auto &b : s.binds) {
            std::vector<std::string> p = split(b, ':');
            bool ro = p.size() > 1 && p.back() == "ro";
@@ -274,6 +295,11 @@ struct Pid1 {
        symlink("/proc/self/fd/2", "/dev/stderr");
        symlink("/proc/kcore", "/dev/core");

        bool fenriros = fenrirOs();
        for (auto &b : yaml) {
            if (fenriros) attach(b.fd, b.where, b.file);
            close(b.fd);
        }
        for (auto &b : binds) {
            attach(b.fd, b.where, b.file);
            close(b.fd);
@@ -648,11 +674,11 @@ private:
        writeFile(statePath(s.name, ".lease"), "address=" + l.cidr() + "\ngateway=" + l.routerText() + "\ndns=" +
                                                    join(l.dnsText(), " ") + "\nexpires=" +
                                                    std::to_string((long long)(l.obtained + l.seconds)) + "\n");
        rewrite(_l.dir + "/hosts", "127.0.0.1\tlocalhost\n::1\tlocalhost ip6-localhost ip6-loopback\n" + ip + "\t" + host + "\n");
        rewrite(_l.dir + "/hosts", hostsText(host, ip));
        rewrite(_l.dir + "/host.yaml", hostYaml(host, ip));
        if (s.dns.empty() && !l.dns.empty()) {
            std::string r;
            for (auto &d : l.dnsText()) r += "nameserver " + d + "\n";
            rewrite(_l.dir + "/resolv.conf", r);
            rewrite(_l.dir + "/resolv.conf", resolvConfText(l.dnsText()));
            rewrite(_l.dir + "/resolv.yaml", resolvYaml(l.dnsText()));
        }
    }

@@ -776,6 +802,32 @@ int supervise(const Launch &l, int status) {

} // namespace

std::string hostsText(const std::string &host, const std::string &ip) {
    return "127.0.0.1\tlocalhost\n::1\tlocalhost ip6-localhost ip6-loopback\n" + ip + "\t" + host + "\n";
}

// systempp's /etc/host.yaml (format: systempp src/linux/netdb.cpp)
std::string hostYaml(const std::string &host, const std::string &ip) {
    auto entry = [](const std::string &addr, const std::string &name, const std::string &aliases) {
        return "  - ip: \"" + addr + "\"\n    name: " + name + "\n    aliases: [" + aliases + "]\n";
    };
    return "hostname: " + host + "\nhosts:\n" + entry("127.0.0.1", "localhost", "") +
           entry("::1", "localhost", "ip6-localhost, ip6-loopback") + entry(ip, host, "");
}

std::string resolvConfText(const std::vector<std::string> &servers) {
    std::string out;
    for (auto &n : servers) out += "nameserver " + n + "\n";
    return out;
}

// systempp's /etc/resolv.yaml ("- nameserver: <address>")
std::string resolvYaml(const std::vector<std::string> &servers) {
    std::string out;
    for (auto &n : servers) out += "- nameserver: \"" + n + "\"\n";
    return out;
}

std::string hostVeth(const std::string &name) {
    std::string n = "veth" + name;
    if (n.size() <= 15 && n.find('.') == std::string::npos) return n;
+12 −2
Changes for src/runtime.h: 12 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -42,8 +42,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * directory), pivots into it and then mounts, from inside -- so a symlink
 * in the image can't send a mount to the host -- /proc, /sys (read-only),
 * /dev (tmpfs with the usual nodes, devpts, /dev/shm, mqueue), the
 * container's /etc/hosts, /etc/hostname and /etc/resolv.conf, the bind
 * mounts and tmpfs of its settings. Kernel interfaces in /proc are made
 * container's /etc/hosts, /etc/hostname and /etc/resolv.conf (in a
 * FenrirOS image, os-release ID=fenriros, also systempp's /etc/host.yaml
 * and /etc/resolv.yaml, which it reads instead), the bind mounts and tmpfs
 * of its settings. Kernel interfaces in /proc are made
 * read-only or masked as Docker does. The capability bounding set is cut
 * to Docker's default (boot: nspawn's), plus/minus the settings.
 *
@@ -80,6 +82,14 @@ pid_t launch(const Launch &l, int *status, std::string &err);
std::string hostVeth(const std::string &name);
std::string cgroupOf(const std::string &name);

// the container's name files, written into its directory by prepare() and
// (Address=dhcp) by the supervisor: hosts and resolv.conf for every image,
// host.yaml and resolv.yaml (systempp's formats) for FenrirOS images
std::string hostsText(const std::string &host, const std::string &ip);
std::string hostYaml(const std::string &host, const std::string &ip);
std::string resolvConfText(const std::vector<std::string> &servers);
std::string resolvYaml(const std::vector<std::string> &servers);

// a signal by name (TERM, SIGTERM) or number; 0 if unknown
int signalNumber(const std::string &name);