Add nanoswitch and cluster testing
Adds nanoswitch and the `switched-multi2` launch target to launch two Smalltown instances on a switched
network and enroll them into a single cluster. Nanoswitch contains a Linux bridge and a minimal DHCP server
and connects to the two Smalltown instances over virtual Ethernet cables. Also moves out the DHCP client into
a package since nanoswitch needs it.
Test Plan:
Manually tested using `bazel run //:launch -- switched-multi2` and observing that the second VM
(whose serial port is mapped to stdout) prints that it is enrolled. Also validated by `bazel run //core/cmd/dbg -- kubectl get node -o wide` returning two ready nodes.
X-Origin-Diff: phab/D572
GitOrigin-RevId: 9f6e2b3d8268749dd81588205646ae3976ad14b3
diff --git a/core/internal/network/main.go b/core/internal/network/main.go
index 00d7fb2..2466e05 100644
--- a/core/internal/network/main.go
+++ b/core/internal/network/main.go
@@ -22,11 +22,12 @@
"net"
"os"
- "git.monogon.dev/source/nexantic.git/core/internal/common/supervisor"
-
"github.com/vishvananda/netlink"
"go.uber.org/zap"
"golang.org/x/sys/unix"
+
+ "git.monogon.dev/source/nexantic.git/core/internal/common/supervisor"
+ "git.monogon.dev/source/nexantic.git/core/internal/network/dhcp"
)
const (
@@ -36,7 +37,7 @@
type Service struct {
config Config
- dhcp *dhcpClient
+ dhcp *dhcp.Client
logger *zap.Logger
}
@@ -47,7 +48,7 @@
func New(config Config) *Service {
return &Service{
config: config,
- dhcp: newDHCPClient(),
+ dhcp: dhcp.New(),
}
}
@@ -76,7 +77,7 @@
func (s *Service) addNetworkRoutes(link netlink.Link, addr net.IPNet, gw net.IP) error {
if err := netlink.AddrReplace(link, &netlink.Addr{IPNet: &addr}); err != nil {
- return err
+ return fmt.Errorf("failed to add DHCP address to network interface \"%v\": %w", link.Attrs().Name, err)
}
if gw.IsUnspecified() {
@@ -96,20 +97,20 @@
}
func (s *Service) useInterface(ctx context.Context, iface netlink.Link) error {
- err := supervisor.Run(ctx, "dhcp", s.dhcp.run(iface))
+ err := supervisor.Run(ctx, "dhcp", s.dhcp.Run(iface))
if err != nil {
return err
}
- status, err := s.dhcp.status(ctx, true)
+ status, err := s.dhcp.Status(ctx, true)
if err != nil {
- return fmt.Errorf("could not get DHCP status: %w", err)
+ return fmt.Errorf("could not get DHCP Status: %w", err)
}
- if err := setResolvconf(status.dns, []string{}); err != nil {
+ if err := setResolvconf(status.DNS, []string{}); err != nil {
s.logger.Warn("failed to set resolvconf", zap.Error(err))
}
- if err := s.addNetworkRoutes(iface, net.IPNet{IP: status.address.IP, Mask: status.address.Mask}, status.gateway); err != nil {
+ if err := s.addNetworkRoutes(iface, status.Address, status.Gateway); err != nil {
s.logger.Warn("failed to add routes", zap.Error(err))
}
@@ -118,11 +119,11 @@
// GetIP returns the current IP (and optionally waits for one to be assigned)
func (s *Service) GetIP(ctx context.Context, wait bool) (*net.IP, error) {
- status, err := s.dhcp.status(ctx, wait)
+ status, err := s.dhcp.Status(ctx, wait)
if err != nil {
return nil, err
}
- return &status.address.IP, nil
+ return &status.Address.IP, nil
}
func (s *Service) Run(ctx context.Context) error {