Commit 6e63698a authored by jan.koester's avatar jan.koester
Browse files

test

parent 7f7c0e26
Loading
Loading
Loading
Loading
+43 −3
Changes for src/network.cpp: 43 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
#include <cctype>
#include <cstdlib>
#include <functional>
#include <map>

#include <unistd.h>
#include <fcntl.h>
@@ -754,6 +755,42 @@ static bool validIfname(const std::string &n) {
// of configuration only loses its Bond=/Bridge=.
static std::string memberConfigName(const std::string &ifname) { return "10-" + ifname; }

// The .network/.netdev files in ConfigDir before a multi-file change, to put
// back when a later write fails: a half-saved bond (its .netdev written, its
// members not) would otherwise stay and be created on the next reload.
namespace {
struct ConfigSnapshot {
    std::map<std::string, std::string> files;  // path -> contents
    ConfigSnapshot() {
        std::error_code ec;
        for (auto &e : std::filesystem::directory_iterator(NetworkManager::ConfigDir, ec)) {
            const std::string ext = e.path().extension().string();
            if (ext != ".network" && ext != ".netdev") continue;
            std::ifstream in(e.path());
            std::ostringstream text;
            text << in.rdbuf();
            files[e.path().string()] = text.str();
        }
    }
    void restore() const {
        std::error_code ec;
        for (auto &e : std::filesystem::directory_iterator(NetworkManager::ConfigDir, ec)) {
            const std::string ext = e.path().extension().string();
            if ((ext == ".network" || ext == ".netdev") && !files.count(e.path().string()))
                std::filesystem::remove(e.path(), ec);
        }
        for (auto &[path, text] : files) {
            std::ifstream in(path);
            std::ostringstream now;
            now << in.rdbuf();
            if (in.is_open() && now.str() == text) continue;
            std::ofstream out(path, std::ios::trunc);
            out << text;
        }
    }
};
}

bool NetworkManager::saveNetDev(const NetDevConfig &in, const std::vector<std::string> &members, std::string *err) {
    NetDevConfig nd = in;
    auto fail = [&](const std::string &e) { if (err) *err = e; return false; };
@@ -786,6 +823,9 @@ bool NetworkManager::saveNetDev(const NetDevConfig &in, const std::vector<std::s
        nd.name = old->name;
    }

    const ConfigSnapshot before;
    auto rollback = [&]() { before.restore(); return false; };

    std::ostringstream f;
    f << "# Managed by syslite (sysbus)\n[NetDev]\nName=" << nd.ifname << "\nKind=" << nd.kind << "\n";
    if (nd.kind == "bond") {
@@ -795,7 +835,7 @@ bool NetworkManager::saveNetDev(const NetDevConfig &in, const std::vector<std::s
    } else {
        f << "\n[Bridge]\nSTP=" << (nd.stp ? "yes" : "no") << "\n";
    }
    if (!writeAtomically(base + nd.name + ".netdev", f.str(), err)) return false;
    if (!writeAtomically(base + nd.name + ".netdev", f.str(), err)) return rollback();

    // members: the new ones get member configurations, the others lose theirs
    std::vector<NetworkConfig> configs = _configs;  // writes don't touch _configs
@@ -809,7 +849,7 @@ bool NetworkManager::saveNetDev(const NetDevConfig &in, const std::vector<std::s
        } else {
            cfg.bond.clear();
            cfg.bridge.clear();
            if (!writeNetworkFile(cfg, err)) return false;
            if (!writeNetworkFile(cfg, err)) return rollback();
        }
    }
    for (auto &m : members) {
@@ -824,7 +864,7 @@ bool NetworkManager::saveNetDev(const NetDevConfig &in, const std::vector<std::s
        cfg.dns.clear();
        cfg.bond = nd.kind == "bond" ? nd.ifname : "";
        cfg.bridge = nd.kind == "bridge" ? nd.ifname : "";
        if (!writeNetworkFile(cfg, err)) return false;
        if (!writeNetworkFile(cfg, err)) return rollback();
    }
    reloadConfigs();
    return true;