Skip to content

Commit b629954

Browse files
committed
reintegrate-wg-in-netlight
1 parent 5d13abe commit b629954

File tree

7 files changed

+391
-17
lines changed

7 files changed

+391
-17
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ require (
104104
github.com/gtank/ristretto255 v0.1.2 // indirect
105105
github.com/hanwen/go-fuse/v2 v2.3.0 // indirect
106106
github.com/hashicorp/errwrap v1.1.0 // indirect
107-
github.com/hashicorp/go-multierror v1.1.1 // indirect
107+
github.com/hashicorp/go-multierror v1.1.1
108108
github.com/hashicorp/go-retryablehttp v0.7.7
109109
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
110110
github.com/holiman/uint256 v1.2.3 // indirect

pkg/gridtypes/zos/network_light.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,28 @@ type NetworkLight struct {
2929
// if no mycelium configuration is provided, vms can't
3030
// get mycelium IPs.
3131
Mycelium Mycelium `json:"mycelium,omitempty"`
32+
33+
// wg config
34+
// IP range of the network, must be an IPv4 /16
35+
// for example a 10.1.0.0/16
36+
NetworkIPRange gridtypes.IPNet `json:"ip_range"`
37+
38+
// The private wg key of this node (this peer) which is installing this
39+
// network workload right now.
40+
// This has to be filled in by the user (and not generated for example)
41+
// because other peers need to be installed as well (with this peer public key)
42+
// hence it's easier to configure everything one time at the user side and then
43+
// apply everything on all nodes at once
44+
WGPrivateKey string `json:"wireguard_private_key"`
45+
46+
// WGListenPort is the wireguard listen port on this node. this has
47+
// to be filled in by the user for same reason as private key (other nodes need to know about it)
48+
// To find a free port you have to ask the node first by a call over RMB about which ports are possible
49+
// to use.
50+
WGListenPort uint16 `json:"wireguard_listen_port"`
51+
52+
// Peers is a list of other peers in this network
53+
Peers []Peer `json:"peers"`
3254
}
3355

3456
// Valid checks if the network resource is valid.

pkg/netlight/network.go

Lines changed: 144 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"os"
1010
"path/filepath"
1111
"slices"
12+
"strings"
1213
"time"
1314

1415
"github.com/blang/semver"
@@ -20,13 +21,15 @@ import (
2021
localPkg "github.com/threefoldtech/zosbase/pkg"
2122
"github.com/threefoldtech/zosbase/pkg/cache"
2223
"github.com/threefoldtech/zosbase/pkg/gridtypes/zos"
24+
"github.com/threefoldtech/zosbase/pkg/netbase/wireguard"
2325
"github.com/threefoldtech/zosbase/pkg/netlight/bridge"
2426
"github.com/threefoldtech/zosbase/pkg/netlight/ifaceutil"
2527
"github.com/threefoldtech/zosbase/pkg/netlight/ipam"
2628
"github.com/threefoldtech/zosbase/pkg/netlight/namespace"
2729
"github.com/threefoldtech/zosbase/pkg/netlight/options"
2830
"github.com/threefoldtech/zosbase/pkg/netlight/public"
2931
"github.com/threefoldtech/zosbase/pkg/netlight/resource"
32+
"github.com/threefoldtech/zosbase/pkg/set"
3033
"github.com/threefoldtech/zosbase/pkg/versioned"
3134
"github.com/vishvananda/netlink"
3235
)
@@ -50,6 +53,7 @@ var NetworkSchemaLatestVersion = semver.MustParse("0.1.0")
5053
type networker struct {
5154
ipamLease string
5255
networkDir string
56+
portSet *set.UIntSet
5357
}
5458

5559
var _ localPkg.NetworkerLight = (*networker)(nil)
@@ -63,13 +67,19 @@ func NewNetworker() (localPkg.NetworkerLight, error) {
6367
ipamLease := filepath.Join(vd, ipamLeaseDir)
6468
runtimeDir := filepath.Join(vd, networkDir)
6569

66-
return &networker{
70+
n := networker{
6771
ipamLease: ipamLease,
6872
networkDir: runtimeDir,
69-
}, nil
73+
portSet: set.NewInt(),
74+
}
75+
76+
if err := n.syncWGPorts(); err != nil {
77+
return nil, err
78+
}
79+
return &n, nil
7080
}
7181

72-
func (n *networker) Create(name string, privateNet net.IPNet, seed []byte) error {
82+
func (n *networker) Create(name string, net zos.NetworkLight, seed []byte) error {
7383
b, err := bridge.Get(NDMZBridge)
7484
if err != nil {
7585
return err
@@ -79,7 +89,68 @@ func (n *networker) Create(name string, privateNet net.IPNet, seed []byte) error
7989
return err
8090
}
8191

82-
_, err = resource.Create(name, b, ip, NDMZGwIP, &privateNet, seed)
92+
storedNR, err := n.networkOf(zos.NetID(name))
93+
if err != nil && !os.IsNotExist(err) {
94+
return errors.Wrap(err, "failed to load previous network setup")
95+
}
96+
97+
if err == nil {
98+
if err := n.releasePort(storedNR.WGListenPort); err != nil {
99+
return err
100+
}
101+
}
102+
103+
if err := n.reservePort(net.WGListenPort); err != nil {
104+
return err
105+
}
106+
107+
// _, err = resource.Create(name, b, ip, NDMZGwIP, &privateNet, seed)
108+
netr, err := resource.Create(name, b, ip, NDMZGwIP, &net.Subnet.IPNet, seed, net)
109+
// netr, err := resource.Create(name, b, ip, NDMZGwIP, &net.Subnet.IPNet, net.Mycelium.Key, net.NetworkIPRange.IPNet, net)
110+
if err != nil {
111+
return err
112+
}
113+
114+
cleanup := func() {
115+
log.Error().Msg("clean up network resource")
116+
if err := resource.Delete(name); err != nil {
117+
log.Error().Err(err).Msg("error during deletion of network resource after failed deployment")
118+
}
119+
if err := n.releasePort(net.WGListenPort); err != nil {
120+
log.Error().Err(err).Msg("release wireguard port failed")
121+
}
122+
}
123+
124+
defer func() {
125+
if err != nil {
126+
cleanup()
127+
}
128+
}()
129+
130+
wgName, err := netr.WGName()
131+
if err != nil {
132+
return errors.Wrap(err, "failed to get wg interface name for network resource")
133+
}
134+
135+
exists, err := netr.HasWireguard()
136+
if err != nil {
137+
return errors.Wrap(err, "failed to check if network resource has wireguard setup")
138+
}
139+
140+
if !exists {
141+
var wg *wireguard.Wireguard
142+
wg, err = wireguard.New(wgName)
143+
if err != nil {
144+
return errors.Wrapf(err, "failed to create wg interface for network resource '%s'", name)
145+
}
146+
if err = netr.SetWireguard(wg); err != nil {
147+
return errors.Wrap(err, "failed to setup wireguard interface for network resource")
148+
}
149+
}
150+
151+
if err = netr.ConfigureWG(net.WGPrivateKey); err != nil {
152+
return errors.Wrap(err, "failed to configure network resource")
153+
}
83154
return err
84155
}
85156

@@ -462,3 +533,72 @@ func createNDMZBridge(name string, gw string) (*netlink.Bridge, error) {
462533

463534
return link.(*netlink.Bridge), nil
464535
}
536+
537+
func (n *networker) WireguardPorts() ([]uint, error) {
538+
return n.portSet.List()
539+
}
540+
541+
func (n *networker) syncWGPorts() error {
542+
names, err := namespace.List("n-")
543+
if err != nil {
544+
return err
545+
}
546+
547+
readPort := func(name string) (int, error) {
548+
netNS, err := namespace.GetByName(name)
549+
if err != nil {
550+
return 0, err
551+
}
552+
defer netNS.Close()
553+
554+
ifaceName := strings.Replace(name, "n-", "w-", 1)
555+
556+
var port int
557+
err = netNS.Do(func(_ ns.NetNS) error {
558+
link, err := wireguard.GetByName(ifaceName)
559+
if err != nil {
560+
return err
561+
}
562+
d, err := link.Device()
563+
if err != nil {
564+
return err
565+
}
566+
567+
port = d.ListenPort
568+
return nil
569+
})
570+
if err != nil {
571+
return 0, err
572+
}
573+
574+
return port, nil
575+
}
576+
577+
for _, name := range names {
578+
port, err := readPort(name)
579+
if err != nil {
580+
log.Error().Err(err).Str("namespace", name).Msgf("failed to read port for network namespace")
581+
continue
582+
}
583+
// skip error cause we don't care if there are some duplicate at this point
584+
_ = n.portSet.Add(uint(port))
585+
}
586+
587+
return nil
588+
}
589+
590+
func (n *networker) reservePort(port uint16) error {
591+
log.Debug().Uint16("port", port).Msg("reserve wireguard port")
592+
err := n.portSet.Add(uint(port))
593+
if err != nil {
594+
return errors.Wrap(err, "wireguard listen port already in use, pick another one")
595+
}
596+
597+
return nil
598+
}
599+
600+
func (n *networker) releasePort(port uint16) error {
601+
log.Debug().Uint16("port", port).Msg("release wireguard port")
602+
n.portSet.Remove(uint(port))
603+
return nil
604+
}

0 commit comments

Comments
 (0)