Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/adopt.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ func runAdopt(cmd *cobra.Command, _ []string) error {
fmt.Printf(" gateway: %s\n", gateway)
fmt.Printf(" primary-nic: %s\n", primaryNIC)
fmt.Printf(" secondary-nics: %s\n", strings.Join(secondaryNICs, ","))
fmt.Printf(" enis: %s\n", cmp.Or(strings.Join(eniIDs, ","), "none"))
if len(ips) > 0 {
fmt.Printf(" pool-size: %d (first=%s, last=%s)\n", len(ips), ips[0], ips[len(ips)-1])
} else {
Expand Down
5 changes: 2 additions & 3 deletions cmd/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
)

const (
defaultLeaseFile = "/var/lib/cocoon/net/leases.json"
defaultControlSocket = "/run/cocoon-net/control.sock"
defaultMetricsAddr = ":9092"

Expand Down Expand Up @@ -52,7 +51,7 @@ they expire.`,
RunE: runDaemon,
}
cmd.Flags().StringVar(&flagStateDir, "state-dir", defaultStateDir, "directory containing pool.json")
cmd.Flags().StringVar(&flagLeaseFile, "lease-file", defaultLeaseFile, "path to lease persistence file")
cmd.Flags().StringVar(&flagLeaseFile, "lease-file", "", "lease persistence file (default <state-dir>/leases.json)")
cmd.Flags().StringVar(&flagControlSocket, "control-socket", cmp.Or(os.Getenv("COCOON_NET_CONTROL_SOCKET"), defaultControlSocket), "root-only Unix socket for local lease lifecycle operations (empty to disable)")
cmd.Flags().BoolVar(&flagSkipIPTables, "skip-iptables", false, "skip iptables setup (for pre-configured nodes)")
cmd.Flags().StringVar(&flagMetricsAddr, "metrics-addr", cmp.Or(os.Getenv("COCOON_NET_METRICS_ADDR"), defaultMetricsAddr), "prometheus metrics listen address (empty to disable)")
Expand Down Expand Up @@ -109,7 +108,7 @@ func runDaemon(cmd *cobra.Command, _ []string) error {
Gateway: gateway,
SubnetMask: ipNet.Mask,
DNSServers: dnsIPs,
LeaseFile: flagLeaseFile,
LeaseFile: resolveLeaseFile(),
ControlSocket: flagControlSocket,
}, poolIPs)

Expand Down
2 changes: 0 additions & 2 deletions cmd/teardown.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import (
"github.com/cocoonstack/cocoon-net/platform"
)

const leaseFileName = "leases.json"

func newTeardownCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "teardown",
Expand Down
13 changes: 11 additions & 2 deletions cmd/utils.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package cmd

import (
"cmp"
"context"
"fmt"
"net"
"path/filepath"
"slices"
"strings"

Expand All @@ -13,7 +15,10 @@ import (
"github.com/cocoonstack/cocoon-net/pool"
)

const defaultStateDir = "/var/lib/cocoon/net"
const (
defaultStateDir = "/var/lib/cocoon/net"
leaseFileName = "leases.json"
)

var (
flagPlatform string
Expand All @@ -38,7 +43,7 @@ func registerCommonFlags(cmd *cobra.Command, defaultPoolSize int) {
cmd.Flags().StringVar(&flagSubnet, "subnet", "", "VM subnet CIDR, e.g. 172.20.100.0/24 (required)")
cmd.Flags().IntVar(&flagPoolSize, "pool-size", defaultPoolSize, "number of IPs in the pool")
cmd.Flags().StringVar(&flagGateway, "gateway", "", "gateway IP on cni0 (default: first IP in subnet)")
cmd.Flags().StringVar(&flagPrimaryNIC, "primary-nic", "", "host primary NIC (auto-detect if empty)")
cmd.Flags().StringVar(&flagPrimaryNIC, "primary-nic", "", "host primary NIC (default: eth0 on volcengine, ens4 otherwise)")
cmd.Flags().StringVar(&flagDNS, "dns", "8.8.8.8,1.1.1.1", "comma-separated DNS servers for DHCP clients")
cmd.Flags().StringVar(&flagStateDir, "state-dir", defaultStateDir, "state directory")
cmd.Flags().BoolVar(&flagDryRun, "dry-run", false, "show what would be done without making changes")
Expand Down Expand Up @@ -91,6 +96,10 @@ func resolveSubnet() error {
return nil
}

func resolveLeaseFile() string {
return cmp.Or(flagLeaseFile, filepath.Join(flagStateDir, leaseFileName))
}

func splitTrim(s, sep string) []string {
parts := strings.Split(s, sep)
for i := range parts {
Expand Down
21 changes: 21 additions & 0 deletions cmd/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,24 @@ func TestResolveSubnet(t *testing.T) {
})
}
}

func TestResolveLeaseFile(t *testing.T) {
tests := []struct {
name string
stateDir string
leaseFile string
want string
}{
{"default state dir", defaultStateDir, "", "/var/lib/cocoon/net/leases.json"},
{"custom state dir", "/srv/cocoon/net", "", "/srv/cocoon/net/leases.json"},
{"explicit lease file wins", "/srv/cocoon/net", "/run/cocoon/leases.json", "/run/cocoon/leases.json"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
flagStateDir, flagLeaseFile = tt.stateDir, tt.leaseFile
if got := resolveLeaseFile(); got != tt.want {
t.Errorf("resolveLeaseFile() = %q, want %q", got, tt.want)
}
})
}
}
2 changes: 1 addition & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ variables below; runtime state (what was provisioned, and for whom) lives in
| `--primary-nic` | `eth0` (Volcengine) / `ens4` (other platforms) | Host primary NIC |
| `--dns` | `8.8.8.8,1.1.1.1` | DNS servers for DHCP clients |
| `--state-dir` | `/var/lib/cocoon/net` | State directory for `pool.json` |
| `--lease-file` | `/var/lib/cocoon/net/leases.json` (independent of `--state-dir`) | (daemon) DHCP lease persistence file |
| `--lease-file` | `<state-dir>/leases.json` | (daemon) DHCP lease persistence file |
| `--control-socket` | `/run/cocoon-net/control.sock` | (daemon) Root-only Unix socket used by local VM lifecycle managers to reclaim leases; empty to disable |
| `--drop-cidr` | none | (repeatable, `init`/`adopt`) Destination CIDR to DROP at `FORWARD` for VM traffic -- see [DHCP: traffic isolation](dhcp.md#traffic-isolation) |
| `--drop-internal-access` | `false` | (`init`/`adopt`) DROP `FORWARD` traffic within the node's own `--subnet` |
Expand Down
2 changes: 1 addition & 1 deletion docs/dhcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ VPC-routable IP directly from this server.
`204` after a successful or already-completed release, `400` for an invalid
MAC, and `500` when persistence fails; callers may safely retry a `500`.
- Leases are persisted to the `--lease-file` (default
`/var/lib/cocoon/net/leases.json`) on every allocation/release, and
`<state-dir>/leases.json`) on every allocation/release, and
reloaded at daemon startup so a restart doesn't strand or double-assign
leases.

Expand Down
1 change: 0 additions & 1 deletion platform/ip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ func TestSubnetIPs_Slash24SkipsBroadcast(t *testing.T) {
func TestSubnetIPs_Slash28(t *testing.T) {
t.Parallel()

// /28 has 16 addresses, 14 hosts, minus gateway = 13.
got, err := SubnetIPs("192.168.10.0/28", "192.168.10.1", 32)
if err != nil {
t.Fatalf("SubnetIPs: %v", err)
Expand Down
1 change: 1 addition & 0 deletions platform/volcengine/adopt.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ import (
"github.com/cocoonstack/cocoon-net/platform"
)

// Adopt is a no-op: the VPC routes the VM subnet to the secondary ENIs, so no host route hijacks it.
func (v *Volcengine) Adopt(context.Context, *platform.Config) error { return nil }