From 71a729feb9242fa5f809c6ec4e7a3db572ec8822 Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Sat, 26 Oct 2019 06:13:58 -0500 Subject: hscript: Implement NetAddress::execute --- hscript/CMakeLists.txt | 4 ++- hscript/network.cc | 36 ++++++++++++++++++- hscript/script.cc | 97 +++++++++++++++++++++++++++++++++++--------------- 3 files changed, 106 insertions(+), 31 deletions(-) diff --git a/hscript/CMakeLists.txt b/hscript/CMakeLists.txt index 9043e2b..d0c5473 100644 --- a/hscript/CMakeLists.txt +++ b/hscript/CMakeLists.txt @@ -11,10 +11,12 @@ set(HSCRIPT_INCLUDE script.hh ) +find_package(Boost REQUIRED COMPONENTS filesystem) + add_library(hscript ${HSCRIPT_SOURCE}) target_compile_features(hscript PRIVATE cxx_nullptr) target_compile_features(hscript PUBLIC cxx_unicode_literals) -target_link_libraries(hscript ${BLKID_LIBRARIES} ${LIBUDEV_LIBRARIES} ${PARTED_LIBRARIES}) +target_link_libraries(hscript ${BLKID_LIBRARIES} ${Boost_FILESYSTEM_LIBRARY} ${LIBUDEV_LIBRARIES} ${PARTED_LIBRARIES}) install(TARGETS hscript DESTINATION lib) install(FILES ${HSCRIPT_INCLUDE} DESTINATION include/hscript) diff --git a/hscript/network.cc b/hscript/network.cc index e375385..a47e69e 100644 --- a/hscript/network.cc +++ b/hscript/network.cc @@ -265,7 +265,41 @@ bool NetAddress::validate(ScriptOptions opts) const { } bool NetAddress::execute(ScriptOptions) const { - return false; + std::ofstream config("/tmp/horizon/netifrc/config_" + this->iface(), + std::ios_base::app); + if(!config) { + output_error("installfile:" + std::to_string(this->lineno()), + "netaddress: couldn't write network configuration for " + + this->iface()); + return false; + } + + switch(this->type()) { + case DHCP: + config << "dhcp"; + break; + case SLAAC: + /* automatically handled by netifrc */ + break; + case Static: + config << this->address() << "/" << std::to_string(this->prefix()) + << std::endl; + break; + } + + if(!this->gateway().empty()) { + std::ofstream route("/tmp/horizon/netifrc/routes_" + this->iface(), + std::ios_base::app); + if(!route) { + output_error("installfile:" + std::to_string(this->lineno()), + "netaddress: couldn't write route configuration for " + + this->iface()); + return false; + } + route << "default via " << this->gateway() << std::endl; + } + + return true; } diff --git a/hscript/script.cc b/hscript/script.cc index d58efb7..0e7e00d 100644 --- a/hscript/script.cc +++ b/hscript/script.cc @@ -12,13 +12,12 @@ #include #include -#include /* strerror */ +#include #include #include #include #include #include -#include /* mkdir */ #include "script.hh" #include "disk.hh" @@ -35,6 +34,8 @@ typedef Horizon::Keys::Key *(*key_parse_fn)(const std::string &, int, int*, int* using namespace Horizon::Keys; +namespace fs = boost::filesystem; + const std::map valid_keys = { {"network", &Network::parseFromData}, {"hostname", &Hostname::parseFromData}, @@ -880,13 +881,13 @@ bool Script::validate() const { bool Script::execute() const { bool success; + boost::system::error_code ec; - if(mkdir("/tmp/horizon", S_IRUSR | S_IWUSR | S_IXUSR) != 0) { - if(errno != EEXIST) { - output_error("internal", "could not create temporary directory", - ::strerror(errno)); - return false; - } + if(!fs::exists("/tmp/horizon", ec) && + !fs::create_directory("/tmp/horizon", ec)) { + output_error("internal", "could not create temporary directory", + ec.message()); + return false; } /* REQ: Runner.Execute.Verify */ @@ -980,6 +981,7 @@ bool Script::execute() const { << "ctrl_interface=/var/run/wpa_supplicant" << std::endl << "ctrl_interface_group=wheel" << std::endl << "update_config=1" << std::endl; + wpao.close(); } else { output_error("internal", "cannot write wireless networking configuration"); @@ -992,36 +994,73 @@ bool Script::execute() const { } } - std::ifstream wpai("/tmp/horizon/wpa_supplicant.conf"); - if(wpai) { - if(opts.test(Simulate)) { + if(opts.test(Simulate)) { + std::ifstream wpai("/tmp/horizon/wpa_supplicant.conf"); + if(wpai) { std::cout << "cat >/target/etc/wpa_supplicant/wpa_supplicant.conf " - << "<<- WPA_EOF" << std::endl; - std::cout << wpai.rdbuf(); - std::cout << std::endl << "WPA_EOF" << std::endl; + << "<<- WPA_EOF" << std::endl + << wpai.rdbuf() << std::endl + << "WPA_EOF" << std::endl; } else { - std::ofstream target_wpa("/target/etc/wpa_supplicant/" - "wpa_supplicant.conf", - std::ios_base::trunc); - if(!target_wpa) { - output_error("internal", "cannot save wireless networking " - "configuration to target"); - } else { - target_wpa << wpai.rdbuf(); - } + output_error("internal", + "cannot read wireless networking configuration"); } } else { - output_error("internal", - "cannot read wireless networking configuration"); + fs::copy_file("/tmp/horizon/wpa_supplicant.conf", + "/target/etc/wpa_supplicant/wpa_supplicant.conf", + fs::copy_option::overwrite_if_exists, + ec); + if(ec.failed()) { + output_error("internal", "cannot save wireless networking " + "configuration to target", ec.message()); + } } } - for(auto &addr : this->internal->addresses) { - if(!addr->execute(opts)) { - EXECUTE_FAILURE("net"); - /* "Soft" error. Not fatal. */ + if(!this->internal->addresses.empty()) { + fs::path netifrc_dir("/tmp/horizon/netifrc"); + if(!fs::exists(netifrc_dir) && + !fs::create_directory(netifrc_dir, ec)) { + output_error("internal", "cannot create temporary directory", + ec.message()); + } + + for(auto &addr : this->internal->addresses) { + if(!addr->execute(opts)) { + EXECUTE_FAILURE("net"); + /* "Soft" error. Not fatal. */ + } + } + + std::ostringstream conf; + for(auto &&var_dent : fs::directory_iterator(netifrc_dir)) { + const std::string variable(var_dent.path().filename().string()); + std::ifstream contents(var_dent.path().string()); + if(!contents) { + output_error("internal", "cannot read network configuration"); + continue; + } + conf << variable << "=\""; + if(contents.rdbuf()->in_avail()) conf << contents.rdbuf(); + conf << "\"" << std::endl; + } + + if(opts.test(Simulate)) { + std::cout << "cat >/target/etc/conf.d/net <<- NETCONF_EOF" + << std::endl << conf.str() << std::endl + << "NETCONF_EOF" << std::endl; + } else { + std::ofstream conf_file("/target/etc/conf.d/net", + std::ios_base::trunc); + if(!conf_file) { + output_error("internal", "cannot save network configuration " + "to target"); + } else { + conf_file << conf.str(); + } } } + if(!this->internal->network->execute(opts)) { EXECUTE_FAILURE("net"); return false; -- cgit v1.2.3-70-g09d2