kexec: restore static ips after kexec
This commit is contained in:
parent
65227bf951
commit
985547acc6
2 changed files with 103 additions and 0 deletions
|
@ -29,6 +29,11 @@
|
|||
for p in /etc/ssh/ssh_host_*; do
|
||||
cp -a "$p" ssh
|
||||
done
|
||||
|
||||
# save the networking config for later use
|
||||
ip --json addr > addrs.json
|
||||
ip --json route > routes.json
|
||||
|
||||
find | cpio -o -H newc | gzip -9 > ../extra.gz
|
||||
popd
|
||||
cat "''${SCRIPT_DIR}/initrd" extra.gz > final-initrd
|
||||
|
@ -76,14 +81,29 @@
|
|||
# for detection if we are on kexec
|
||||
environment.etc.is_kexec.text = "true";
|
||||
|
||||
systemd.services.restoreNetwork = {
|
||||
path = [
|
||||
pkgs.iproute2
|
||||
];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
serviceConfig.ExecStart = "/run/current-system/sw/bin/restore_network /root/network/addrs.json /root/network/routes.json";
|
||||
};
|
||||
|
||||
environment.systemPackages = [
|
||||
(pkgs.writers.writePython3Bin "restore_network" { flakeIgnore = ["E501"]; } ./restore_routes.py)
|
||||
];
|
||||
|
||||
# Restore ssh host and user keys if they are available.
|
||||
# This avoids warnings of unknown ssh keys.
|
||||
boot.initrd.postMountCommands = ''
|
||||
mkdir -m 700 -p /mnt-root/root/.ssh
|
||||
mkdir -m 755 -p /mnt-root/etc/ssh
|
||||
mkdir -m 755 -p /mnt-root/root/network
|
||||
if [[ -f ssh/authorized_keys ]]; then
|
||||
install -m 400 ssh/authorized_keys /mnt-root/root/.ssh
|
||||
fi
|
||||
install -m 400 ssh/ssh_host_* /mnt-root/etc/ssh
|
||||
cp *.json /mnt-root/root/network/
|
||||
'';
|
||||
}
|
||||
|
|
83
nix/restore_routes.py
Normal file
83
nix/restore_routes.py
Normal file
|
@ -0,0 +1,83 @@
|
|||
import json
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
|
||||
def filter_interfaces(network):
|
||||
output = []
|
||||
for net in network:
|
||||
if net["ifname"] == "lo":
|
||||
continue
|
||||
addr_info = []
|
||||
for addr in net["addr_info"]:
|
||||
if addr.get("dynamic", False):
|
||||
pass
|
||||
elif addr["local"].startswith("fe80"):
|
||||
pass
|
||||
else:
|
||||
addr_info.append(addr)
|
||||
if addr_info != []:
|
||||
net["addr_info"] = addr_info
|
||||
output.append(net)
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def main():
|
||||
with open(sys.argv[1]) as f:
|
||||
addresses = json.load(f)
|
||||
with open(sys.argv[2]) as f:
|
||||
routes = json.load(f)
|
||||
relevant_interfaces = filter_interfaces(addresses)
|
||||
current_interfaces = json.loads(
|
||||
subprocess.run(
|
||||
["ip", "--json", "addr"],
|
||||
capture_output=True,
|
||||
).stdout
|
||||
)
|
||||
|
||||
for interface in relevant_interfaces:
|
||||
for current_interface in current_interfaces:
|
||||
if "address" in interface and "address" in current_interface:
|
||||
if interface["address"] == current_interface["address"]:
|
||||
for addr in interface["addr_info"]:
|
||||
subprocess.run(
|
||||
[
|
||||
"ip",
|
||||
"addr",
|
||||
"add",
|
||||
"dev",
|
||||
current_interface["ifname"],
|
||||
f'{addr["local"]}/{addr["prefixlen"]}',
|
||||
]
|
||||
)
|
||||
for route in routes:
|
||||
if route["dev"] == interface["ifname"]:
|
||||
if route.get("gateway", False):
|
||||
subprocess.run(
|
||||
[
|
||||
"ip",
|
||||
"route",
|
||||
"add",
|
||||
route["dst"],
|
||||
"via",
|
||||
route["gateway"],
|
||||
"dev",
|
||||
current_interface["ifname"],
|
||||
]
|
||||
)
|
||||
else:
|
||||
subprocess.run(
|
||||
[
|
||||
"ip",
|
||||
"route",
|
||||
"add",
|
||||
route["dst"],
|
||||
"dev",
|
||||
current_interface["ifname"],
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in a new issue