feat(dns-server): check system prerequisites when init/add machine: DNS port is not in use by another DNS server

This commit is contained in:
Pavel Sviderski
2025-04-30 20:46:10 +10:00
parent 6e1165ec57
commit 769f5e47c3
6 changed files with 366 additions and 180 deletions
+34
View File
@@ -359,6 +359,8 @@ func (m *Machine) Run(ctx context.Context) error {
var err error
m.cluster.UpdateMachineID(m.state.ID)
// TODO: set DNS server to m.IP() on the docker server so it knows which addr to pass as --dns
// for service containers.
// Ensure the corrosion config is up to date, including a new gossip address if the machine
// has just joined a cluster.
@@ -540,6 +542,38 @@ func (m *Machine) configureCorrosion() error {
return nil
}
// CheckPrerequisites verifies if the machine meets all necessary system requirements to participate in the cluster.
func (m *Machine) CheckPrerequisites(ctx context.Context, _ *emptypb.Empty) (*pb.CheckPrerequisitesResponse, error) {
// Check DNS port (UDP) availability.
if err := checkDNSPortAvailable(); err != nil {
return &pb.CheckPrerequisitesResponse{
Satisfied: false,
Error: err.Error(),
}, nil
}
return &pb.CheckPrerequisitesResponse{
Satisfied: true,
}, nil
}
// checkDNSPortAvailable verifies that DNS port 53/udp is available for Uncloud's embedded DNS service.
func checkDNSPortAvailable() error {
addr := &net.UDPAddr{
IP: net.IPv4(127, 0, 0, 210), // Use a unique loopback address to avoid conflicts.
Port: dns.Port,
}
conn, err := net.ListenUDP("udp", addr)
if err != nil {
return fmt.Errorf("DNS port %d/udp is already in use by another service: %w. Uncloud needs this port "+
"to run the embedded internal DNS service on WireGuard interface 'uncloud'. Please reconfigure "+
"any DNS servers (like dnsmasq, systemd-resolved, or named) that might be listening on all network "+
"interfaces (0.0.0.0) on the machine and try again", dns.Port, err)
}
conn.Close()
return nil
}
// InitCluster initialises a new cluster on the local machine with the provided network configuration.
func (m *Machine) InitCluster(ctx context.Context, req *pb.InitClusterRequest) (*pb.InitClusterResponse, error) {
if m.Initialised() {