diff --git a/cmd/natc/ippool/consensusippool.go b/cmd/natc/ippool/consensusippool.go index adf2090d1..3bc21bd03 100644 --- a/cmd/natc/ippool/consensusippool.go +++ b/cmd/natc/ippool/consensusippool.go @@ -10,8 +10,6 @@ import ( "fmt" "log" "net/netip" - "os" - "path/filepath" "time" "github.com/hashicorp/raft" @@ -155,11 +153,7 @@ func (ipp *ConsensusIPPool) domainLookup(from tailcfg.NodeID, addr netip.Addr) ( func (ipp *ConsensusIPPool) StartConsensus(ctx context.Context, ts *tsnet.Server, clusterTag string, clusterStateDir string) error { cfg := tsconsensus.DefaultConfig() cfg.ServeDebugMonitor = true - var err error - cfg.StateDirPath, err = getStatePath(clusterStateDir) - if err != nil { - return err - } + cfg.StateDirPath = clusterStateDir cns, err := tsconsensus.Start(ctx, ts, ipp, clusterTag, cfg) if err != nil { return err @@ -211,30 +205,6 @@ func (ps *consensusPerPeerState) unusedIPV4(ipset *netipx.IPSet, reuseDeadline t return netip.Addr{}, false, "", errors.New("ip pool exhausted") } -func getStatePath(pathFromFlag string) (string, error) { - var dirPath string - if pathFromFlag != "" { - dirPath = pathFromFlag - } else { - confDir, err := os.UserConfigDir() - if err != nil { - return "", err - } - dirPath = filepath.Join(confDir, "nat-connector-cluster-state") - } - - if err := os.MkdirAll(dirPath, 0700); err != nil { - return "", err - } - if fi, err := os.Stat(dirPath); err != nil { - return "", err - } else if !fi.IsDir() { - return "", fmt.Errorf("%v is not a directory", dirPath) - } - - return dirPath, nil -} - // isCloseToExpiry returns true if the lastUsed and now times are more than // half the lifetime apart func isCloseToExpiry(lastUsed, now time.Time, lifetime time.Duration) bool { diff --git a/cmd/natc/natc.go b/cmd/natc/natc.go index 719d5d20d..247bb2101 100644 --- a/cmd/natc/natc.go +++ b/cmd/natc/natc.go @@ -18,6 +18,7 @@ import ( "net/http" "net/netip" "os" + "path/filepath" "strings" "time" @@ -59,7 +60,7 @@ func main() { wgPort = fs.Uint("wg-port", 0, "udp port for wireguard and peer to peer traffic") clusterTag = fs.String("cluster-tag", "", "optionally run in a consensus cluster with other nodes with this tag") server = fs.String("login-server", ipn.DefaultControlURL, "the base URL of control server") - clusterStateDir = fs.String("cluster-state-dir", "", "path to directory in which to store raft state") + stateDir = fs.String("state-dir", "", "path to directory in which to store app state") ) ff.Parse(fs, os.Args[1:], ff.WithEnvVarPrefix("TS_NATC")) @@ -96,6 +97,7 @@ func main() { } ts := &tsnet.Server{ Hostname: *hostname, + Dir: *stateDir, } ts.ControlURL = *server if *wgPort != 0 { @@ -156,7 +158,11 @@ func main() { var ipp ippool.IPPool if *clusterTag != "" { cipp := ippool.NewConsensusIPPool(addrPool) - err = cipp.StartConsensus(ctx, ts, *clusterTag, *clusterStateDir) + clusterStateDir, err := getClusterStatePath(*stateDir) + if err != nil { + log.Fatalf("Creating cluster state dir failed: %v", err) + } + err = cipp.StartConsensus(ctx, ts, *clusterTag, clusterStateDir) if err != nil { log.Fatalf("StartConsensus: %v", err) } @@ -570,3 +576,28 @@ func proxyTCPConn(c net.Conn, dest string, ctor *connector) { p.Start() } + +func getClusterStatePath(stateDirFlag string) (string, error) { + var dirPath string + if stateDirFlag != "" { + dirPath = stateDirFlag + } else { + confDir, err := os.UserConfigDir() + if err != nil { + return "", err + } + dirPath = filepath.Join(confDir, "nat-connector-state") + } + dirPath = filepath.Join(dirPath, "cluster") + + if err := os.MkdirAll(dirPath, 0700); err != nil { + return "", err + } + if fi, err := os.Stat(dirPath); err != nil { + return "", err + } else if !fi.IsDir() { + return "", fmt.Errorf("%v is not a directory", dirPath) + } + + return dirPath, nil +}