diff --git a/internal/config/cell.go b/internal/config/cell.go index a4c86246..2b2a75a8 100644 --- a/internal/config/cell.go +++ b/internal/config/cell.go @@ -114,10 +114,14 @@ type GalacticCellConfig struct { // exec agent. Galactic drops traffic to them unless it is addressed to the // guest's link-local address. // - // Set it only once every node in the cell runs a Galactic that supports - // host-only ports. An older tap plugin ignores the list and leaves the - // ports open, and a newer one whose datapath is not loaded refuses the - // attachment. + // Set it only once every node in the cell runs a Galactic that installs + // galactic-tap-host-only. The conflist names that plugin, so a node + // without it fails the attachment rather than leaving the ports open, as + // does a node whose datapath is not loaded. + // + // Rolling a node back to a Galactic without that plugin also fails DEL + // for sandboxes whose conflist names it, so their teardown retries until + // the plugin is installed again. HypervisorHostOnlyPorts []uint16 `json:"hypervisorHostOnlyPorts,omitempty"` } diff --git a/internal/galactic/galactic/galactic.go b/internal/galactic/galactic/galactic.go index b08c80a2..365da3fa 100644 --- a/internal/galactic/galactic/galactic.go +++ b/internal/galactic/galactic/galactic.go @@ -40,6 +40,11 @@ const ( // PluginTap is the master plugin for virtual machine guests. PluginTap = "galactic-tap" + // PluginTapHostOnly is the tap plugin under the name only a node that + // enforces hostOnlyPorts installs, so an older node fails ADD instead of + // starting the guest with those ports open. + PluginTapHostOnly = "galactic-tap-host-only" + // PluginBGP publishes the attachment into BGP and SRv6. PluginBGP = "galactic-bgp" @@ -138,6 +143,9 @@ func Conflist( DAN: dan, HostOnlyPorts: hostOnlyPorts, } + if plugin == PluginTap && len(hostOnlyPorts) > 0 { + master.Type = PluginTapHostOnly + } if len(addresses) > 0 { master.IPAM = &IPAM{Type: PluginIPAM, Addresses: addresses} } diff --git a/internal/galactic/galactic/galactic_test.go b/internal/galactic/galactic/galactic_test.go index 54e161ab..8c2fcb6e 100644 --- a/internal/galactic/galactic/galactic_test.go +++ b/internal/galactic/galactic/galactic_test.go @@ -179,6 +179,13 @@ func TestConflistCarriesHostOnlyPorts(t *testing.T) { if _, present := masterStanza(t, open)["hostOnlyPorts"]; present { t.Errorf("attachment without host-only ports carries the field: %s", open) } + if got := masterStanza(t, fenced)["type"]; got != PluginTapHostOnly { + t.Errorf("fenced attachment: plugin %v, want %q so a node that cannot enforce the ports fails ADD", + got, PluginTapHostOnly) + } + if got := masterStanza(t, open)["type"]; got != PluginTap { + t.Errorf("attachment without host-only ports: plugin %v, want %q", got, PluginTap) + } } func masterStanza(t *testing.T, raw string) map[string]any {