summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorA. Wilcox <AWilcox@Wilcox-Tech.com>2020-03-18 21:34:25 -0500
committerA. Wilcox <AWilcox@Wilcox-Tech.com>2020-03-18 21:34:25 -0500
commitf04b3f589d7800653b9fb3ad08131f4edd2e2828 (patch)
tree1b18c37b79fa0c7a1d67dee441bcef51ece0cb0c
parentbbe669b761db4cb03fca2dbf9a7890d5a7e120af (diff)
downloadhorizon-f04b3f589d7800653b9fb3ad08131f4edd2e2828.tar.gz
horizon-f04b3f589d7800653b9fb3ad08131f4edd2e2828.tar.bz2
horizon-f04b3f589d7800653b9fb3ad08131f4edd2e2828.tar.xz
horizon-f04b3f589d7800653b9fb3ad08131f4edd2e2828.zip
hscript: Support creation of /etc/network/interfaces
-rw-r--r--hscript/network.cc94
-rw-r--r--hscript/script.cc2
-rw-r--r--hscript/script_e.cc108
-rw-r--r--tests/fixtures/0227-netconfigtype-eni.installfile4
-rw-r--r--tests/spec/simulator_spec.rb10
5 files changed, 169 insertions, 49 deletions
diff --git a/hscript/network.cc b/hscript/network.cc
index a7b2bee..445ccbb 100644
--- a/hscript/network.cc
+++ b/hscript/network.cc
@@ -294,47 +294,107 @@ bool NetAddress::validate() const {
return true; /* LCOV_EXCL_LINE */
}
-bool NetAddress::execute() const {
- output_info("installfile:" + std::to_string(this->lineno()),
- "netaddress: adding configuration for " + _iface);
-
- std::ofstream config("/tmp/horizon/netifrc/config_" + this->iface(),
+bool execute_address_netifrc(const NetAddress *addr) {
+ std::ofstream config("/tmp/horizon/netifrc/config_" + addr->iface(),
std::ios_base::app);
if(!config) {
- output_error("installfile:" + std::to_string(this->lineno()),
+ output_error("installfile:" + std::to_string(addr->lineno()),
"netaddress: couldn't write network configuration for "
- + this->iface());
+ + addr->iface());
return false;
}
- switch(this->type()) {
- case DHCP:
+ switch(addr->type()) {
+ case NetAddress::DHCP:
config << "dhcp";
break;
- case SLAAC:
+ case NetAddress::SLAAC:
/* automatically handled by netifrc */
break;
- case Static:
- config << this->address() << "/" << std::to_string(this->prefix())
+ case NetAddress::Static:
+ config << addr->address() << "/" << std::to_string(addr->prefix())
<< std::endl;
break;
}
- if(!this->gateway().empty()) {
- std::ofstream route("/tmp/horizon/netifrc/routes_" + this->iface(),
+ if(!addr->gateway().empty()) {
+ std::ofstream route("/tmp/horizon/netifrc/routes_" + addr->iface(),
std::ios_base::app);
if(!route) {
- output_error("installfile:" + std::to_string(this->lineno()),
+ output_error("installfile:" + std::to_string(addr->lineno()),
"netaddress: couldn't write route configuration for "
- + this->iface());
+ + addr->iface());
return false;
}
- route << "default via " << this->gateway() << std::endl;
+ route << "default via " << addr->gateway() << std::endl;
}
return true;
}
+bool execute_address_eni(const NetAddress *addr) {
+ std::ofstream config("/tmp/horizon/eni/" + addr->iface(),
+ std::ios_base::app);
+ if(!config) {
+ output_error("installfile:" + std::to_string(addr->lineno()),
+ "netaddress: couldn't write network configuration for "
+ + addr->iface());
+ return false;
+ }
+
+ switch(addr->type()) {
+ case NetAddress::DHCP:
+ config << "iface " << addr->iface() << " inet dhcp" << std::endl;
+ break;
+ case NetAddress::SLAAC:
+ config << "iface " << addr->iface() << " inet6 manual" << std::endl
+ << "\tpre-up echo 1 > /proc/sys/net/ipv6/conf/" << addr->iface()
+ << "/accept_ra" << std::endl;
+ break;
+ case NetAddress::Static:
+ config << "iface " << addr->iface() << " ";
+
+ if(addr->address().find(':') != std::string::npos) {
+ /* Disable SLAAC when using static IPv6 addressing. */
+ config << "inet6 static" << std::endl
+ << "\tpre-up echo 0 > /proc/sys/net/ipv6/conf/"
+ << addr->iface() << "/accept_ra" << std::endl;;
+ } else {
+ config << "inet static" << std::endl;
+ }
+
+ config << "\taddress " << addr->address() << std::endl
+ << "\tnetmask " << std::to_string(addr->prefix()) << std::endl;
+
+ if(!addr->gateway().empty()) {
+ config << "\tgateway " << addr->gateway() << std::endl;
+ }
+ }
+
+ return true;
+}
+
+bool NetAddress::execute() const {
+ output_info("installfile:" + std::to_string(this->lineno()),
+ "netaddress: adding configuration for " + _iface);
+
+ NetConfigType::ConfigSystem system = NetConfigType::Netifrc;
+
+ const Key *key = script->getOneValue("netconfigtype");
+ if(key != nullptr) {
+ const NetConfigType *nct = static_cast<const NetConfigType *>(key);
+ system = nct->type();
+ }
+
+ switch(system) {
+ case NetConfigType::Netifrc:
+ default:
+ return execute_address_netifrc(this);
+ case NetConfigType::ENI:
+ return execute_address_eni(this);
+ }
+}
+
Key *Nameserver::parseFromData(const std::string &data, int lineno,
int *errors, int *, const Script *script) {
diff --git a/hscript/script.cc b/hscript/script.cc
index fd9fc5a..7d1d4e2 100644
--- a/hscript/script.cc
+++ b/hscript/script.cc
@@ -334,6 +334,8 @@ void Script::setTargetDirectory(const std::string &dir) {
const Keys::Key *Script::getOneValue(std::string name) const {
if(name == "network") {
return this->internal->network.get();
+ } else if(name == "netconfigtype") {
+ return this->internal->netconfig.get();
} else if(name == "hostname") {
return this->internal->hostname.get();
} else if(name == "arch") {
diff --git a/hscript/script_e.cc b/hscript/script_e.cc
index 2b9f8f4..14d997d 100644
--- a/hscript/script_e.cc
+++ b/hscript/script_e.cc
@@ -58,6 +58,8 @@ void maybe_create_icon_dir(ScriptOptions opts, const std::string &target) {
bool Script::execute() const {
bool success;
error_code ec;
+ std::string netconf_file;
+ NetConfigType::ConfigSystem netconfsys = NetConfigType::Netifrc;
std::set<std::string> ifaces;
const std::string targ_etc(targetDirectory() + "/etc");
@@ -220,6 +222,10 @@ bool Script::execute() const {
/**************** NETWORK ****************/
output_step_start("net");
+ if(internal->netconfig) {
+ netconfsys = internal->netconfig->type();
+ }
+
if(!this->internal->ssids.empty()) {
std::ofstream wpao("/tmp/horizon/wpa_supplicant.conf",
std::ios_base::trunc);
@@ -274,9 +280,23 @@ bool Script::execute() const {
bool dhcp = false;
if(!internal->addresses.empty()) {
- fs::path netifrc_dir("/tmp/horizon/netifrc");
- if(!fs::exists(netifrc_dir) &&
- !fs::create_directory(netifrc_dir, ec)) {
+ fs::path conf_dir, targ_netconf_dir, targ_netconf_file;
+ switch(netconfsys) {
+ case NetConfigType::Netifrc:
+ conf_dir = fs::path("/tmp/horizon/netifrc");
+ netconf_file = "/etc/conf.d/net";
+ targ_netconf_dir = fs::path(targ_etc + "/conf.d");
+ break;
+ case NetConfigType::ENI:
+ conf_dir = fs::path("/tmp/horizon/eni");
+ netconf_file = "/etc/network/interfaces";
+ targ_netconf_dir = fs::path(targ_etc + "/network");
+ break;
+ }
+ targ_netconf_file = fs::path(targetDirectory() + netconf_file);
+
+ if(!fs::exists(conf_dir) &&
+ !fs::create_directory(conf_dir, ec)) {
output_error("internal", "cannot create temporary directory",
ec.message());
}
@@ -292,36 +312,55 @@ bool Script::execute() const {
}
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(netconfsys == NetConfigType::ENI) {
+ conf << "auto lo" << std::endl
+ << "iface lo inet loopback" << std::endl << std::endl;
+ }
+
+ for(auto &&varfile : fs::directory_iterator(conf_dir)) {
+ std::ifstream contents(varfile.path().string());
if(!contents) {
- output_error("internal", "cannot read network configuration");
+ output_error("internal", "cannot read network "
+ "configuration");
EXECUTE_FAILURE("net-internal");
continue;
}
- conf << variable << "=\"";
- if(contents.rdbuf()->in_avail()) conf << contents.rdbuf();
- conf << "\"" << std::endl;
+
+ switch(netconfsys) {
+ case NetConfigType::Netifrc: {
+ const std::string variable(varfile.path().filename().string());
+ conf << variable << "=\"";
+ if(contents.rdbuf()->in_avail()) conf << contents.rdbuf();
+ conf << "\"" << std::endl;
+ break;
+ }
+ case NetConfigType::ENI: {
+ const std::string iface(varfile.path().filename().string());
+ conf << "auto " << iface << std::endl;
+ if(contents.rdbuf()->in_avail()) conf << contents.rdbuf();
+ conf << std::endl;
+ break;
+ }
+ }
}
if(opts.test(Simulate)) {
- std::cout << "mkdir -p " << targ_etc << "/conf.d" << std::endl;
- std::cout << "cat >>/" << targ_etc << "/conf.d/net <<- NETCONF_EOF"
+ std::cout << "mkdir -p " << targ_netconf_dir << std::endl;
+ std::cout << "cat >>" << targ_netconf_file << " <<- NETCONF_EOF"
<< std::endl << conf.str() << std::endl
<< "NETCONF_EOF" << std::endl;
}
#ifdef HAS_INSTALL_ENV
else {
- if(!fs::exists(targ_etc + "/conf.d")) {
- fs::create_directory(targ_etc + "/conf.d", ec);
+ if(!fs::exists(targ_netconf_dir)) {
+ fs::create_directory(targ_netconf_dir, ec);
if(ec) {
- output_error("internal", "could not create /etc/conf.d "
- "directory", ec.message());
+ output_error("internal", "could not create network "
+ "configuration directory", ec.message());
}
}
- std::ofstream conf_file(targ_etc + "/conf.d/net",
- std::ios_base::app);
+ std::ofstream conf_file(targ_netconf_file, std::ios_base::app);
if(!conf_file) {
output_error("internal", "cannot save network configuration "
"to target");
@@ -397,8 +436,8 @@ bool Script::execute() const {
<< "/etc/wpa_supplicant/wpa_supplicant.conf"
<< std::endl;
}
- std::cout << "cp " << targ_etc << "/conf.d/net /etc/conf.d/net"
- << std::endl;
+ std::cout << "cp " << targetDirectory() << netconf_file << " "
+ << netconf_file << std::endl;
if(!internal->nses.empty()) {
std::cout << "cp " << targ_etc << "/resolv.conf* /etc/"
<< std::endl;
@@ -416,7 +455,7 @@ bool Script::execute() const {
EXECUTE_FAILURE("network");
}
}
- fs::copy_file(targ_etc + "/conf.d/net", "/etc/conf.d/net",
+ fs::copy_file(targetDirectory() + netconf_file, netconf_file,
fs_overwrite, ec);
if(ec) {
output_error("internal", "cannot use networking configuration "
@@ -424,17 +463,26 @@ bool Script::execute() const {
EXECUTE_FAILURE("network");
return false;
}
- for(auto &iface : ifaces) {
- fs::create_symlink("/etc/init.d/net.lo",
- "/etc/init.d/net." + iface, ec);
- if(ec && ec.value() != EEXIST) {
- output_error("internal", "could not use networking on "
- + iface, ec.message());
- EXECUTE_FAILURE("network");
- } else {
- run_command("service", {"net." + iface, "start"});
+
+ switch(netconfsys) {
+ case NetConfigType::Netifrc:
+ for(auto &iface : ifaces) {
+ fs::create_symlink("/etc/init.d/net.lo",
+ "/etc/init.d/net." + iface, ec);
+ if(ec && ec.value() != EEXIST) {
+ output_error("internal", "could not use networking on "
+ + iface, ec.message());
+ EXECUTE_FAILURE("network");
+ } else {
+ run_command("service", {"net." + iface, "start"});
+ }
}
+ break;
+ case NetConfigType::ENI:
+ run_command("/etc/init.d/networking", {"restart"});
+ break;
}
+
if(!internal->nses.empty()) {
if(dhcp) {
fs::copy_file(targ_etc + "/resolv.conf.head",
diff --git a/tests/fixtures/0227-netconfigtype-eni.installfile b/tests/fixtures/0227-netconfigtype-eni.installfile
index 2eb6712..e5beb22 100644
--- a/tests/fixtures/0227-netconfigtype-eni.installfile
+++ b/tests/fixtures/0227-netconfigtype-eni.installfile
@@ -1,8 +1,8 @@
-hostname horizon-netifrc-test
+hostname horizon-eni-test
rootpw $6$gumtLGmHwOVIRpQR$2M9PUO24hy5mofzWWf9a.YLbzOgOlUby1g0hDj.wG67E2wrrvys59fq02PPdxBdbgkLZFtjfEx6MHZwMBamwu/
network true
netconfigtype eni
-netaddress eth0 dhcp
+netaddress eth0 static 192.168.1.2 24 192.168.1.1
netaddress eth0 slaac
nameserver 9.9.9.10
diskid /dev/sda QEMU_HARDDISK
diff --git a/tests/spec/simulator_spec.rb b/tests/spec/simulator_spec.rb
index 66f1d8f..9d41356 100644
--- a/tests/spec/simulator_spec.rb
+++ b/tests/spec/simulator_spec.rb
@@ -213,6 +213,16 @@ printf '%s\\t%s\\t%s\\t%s\\t0\\t0\\n' /dev/gwyn/source /usr/src auto noatime >>
run_simulate
expect(last_command_started.stdout).to include("ln -s /etc/init.d/net.lo /target/etc/init.d/net.eth0")
end
+ it "configures IPv4 addressing correctly with eni" do
+ use_fixture '0227-netconfigtype-eni.installfile'
+ run_simulate
+ expect(last_command_started.stdout).to include("auto eth0\niface eth0 inet static")
+ end
+ it "configures IPv6 SLAAC addressing correctly with eni" do
+ use_fixture '0227-netconfigtype-eni.installfile'
+ run_simulate
+ expect(last_command_started.stdout).to include("iface eth0 inet6 manual")
+ end
end
context "simulating 'nameserver' execution" do
it "configures nameservers correctly" do