wip: save current ks debugging state before bisect revert

All accumulated changes to kickstart template, test infrastructure,
and dnsmasq config. None of these produce a clean boot yet — saving
state before reverting to baseline for bisection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Michal
2026-03-28 20:24:14 +00:00
parent cc289c0f94
commit a664074fa3
7 changed files with 258 additions and 166 deletions

View File

@@ -40,50 +40,50 @@ export function ensurePxeNetwork(): void {
if (result.status === 0 && result.stdout.includes("Active: yes")) {
log(`Network ${PXE_NETWORK_NAME} already active`);
return;
} else {
// Destroy existing if present but inactive
if (result.status === 0) {
virsh("net-destroy", PXE_NETWORK_NAME);
virsh("net-undefine", PXE_NETWORK_NAME);
}
const xmlPath = "/tmp/lab-pxe-test-network.xml";
writeFileSync(xmlPath, NETWORK_XML);
log(`Creating PXE libvirt network: ${PXE_NETWORK_NAME} (${PXE_SUBNET}.0/24, no DHCP)`);
run(`virsh net-define "${xmlPath}"`);
run(`virsh net-start "${PXE_NETWORK_NAME}"`);
try { unlinkSync(xmlPath); } catch { /* ignore */ }
log(`Network ${PXE_NETWORK_NAME} created and active`);
}
// Destroy existing if present but inactive
if (result.status === 0) {
virsh("net-destroy", PXE_NETWORK_NAME);
virsh("net-undefine", PXE_NETWORK_NAME);
}
// Libvirt adds nftables reject rules for NAT networks that block host→VM SSH.
// Delete them now and after every VM reboot (libvirt recreates them).
deleteNftablesRejectRules();
}
const xmlPath = "/tmp/lab-pxe-test-network.xml";
writeFileSync(xmlPath, NETWORK_XML);
log(`Creating PXE libvirt network: ${PXE_NETWORK_NAME} (${PXE_SUBNET}.0/24, no DHCP)`);
run(`virsh net-define "${xmlPath}"`);
run(`virsh net-start "${PXE_NETWORK_NAME}"`);
try { unlinkSync(xmlPath); } catch { /* ignore */ }
// Libvirt creates nftables rules that reject traffic on the bridge.
// DHCP works (dnsmasq uses raw sockets) but TFTP/HTTP from VM->host gets blocked.
// Delete the reject rules so VM traffic can reach the bastion.
try {
// Delete the reject rules that libvirt added for our bridge.
// We find and delete each rule by its handle number.
const deleteRejectRules = (chain: string): void => {
const output = run(`nft -a list chain inet libvirt ${chain} 2>/dev/null || true`);
const lines = output.split("\n");
for (const line of lines) {
if (line.includes(PXE_BRIDGE) && line.includes("reject")) {
const handleMatch = line.match(/# handle (\d+)/);
if (handleMatch) {
run(`nft delete rule inet libvirt ${chain} handle ${handleMatch[1]}`);
/** Delete libvirt's nftables reject rules for our bridge so host→VM traffic works.
* Must be called after every VM start/restart — libvirt recreates them. */
export function deleteNftablesRejectRules(): void {
// libvirt uses "ip libvirt_network" table (not "inet libvirt")
const tables = ["ip libvirt_network", "ip6 libvirt_network", "inet libvirt"];
for (const table of tables) {
try {
for (const chain of ["guest_input", "guest_output"]) {
const output = run(`nft -a list chain ${table} ${chain} 2>/dev/null || true`);
for (const line of output.split("\n")) {
if (line.includes(PXE_BRIDGE) && line.includes("reject")) {
const handleMatch = line.match(/# handle (\d+)/);
if (handleMatch) {
run(`nft delete rule ${table} ${chain} handle ${handleMatch[1]}`);
}
}
}
}
};
deleteRejectRules("guest_input");
deleteRejectRules("guest_output");
log(`Removed nftables reject rules for ${PXE_BRIDGE}`);
} catch {
log(`Could not update nftables rules (may need manual firewall config)`);
} catch { /* table may not exist */ }
}
log(`Network ${PXE_NETWORK_NAME} created and active`);
}
/** Destroy the PXE test network. */