Skip to content

Commit 3ac27a2

Browse files
authored
discovery: use interface CIDR for auto-generated subnet, tests (#1452)
* fix subnet for different nodes overwriting each other * set automatic subnet cidr based on interface * add option to wait for subnet discovery * use local api * use ip as identifier * use correct cidr * migrate discovery simple * convert dhcp * convert dns forward and backwards
1 parent 760b3e0 commit 3ac27a2

15 files changed

+285
-41
lines changed

api/api/openapi.yaml

+7
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,13 @@ paths:
857857
schema:
858858
type: string
859859
style: form
860+
- explode: true
861+
in: query
862+
name: wait
863+
required: true
864+
schema:
865+
type: boolean
866+
style: form
860867
responses:
861868
"204":
862869
description: No Content

api/api_roles_discovery.go

+10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/docs/RolesDiscoveryApi.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ No authorization required
519519

520520
## DiscoverySubnetStart
521521

522-
> DiscoverySubnetStart(ctx).Identifier(identifier).Execute()
522+
> DiscoverySubnetStart(ctx).Identifier(identifier).Wait(wait).Execute()
523523
524524
Discovery Subnets
525525

@@ -537,10 +537,11 @@ import (
537537

538538
func main() {
539539
identifier := "identifier_example" // string |
540+
wait := true // bool |
540541

541542
configuration := openapiclient.NewConfiguration()
542543
apiClient := openapiclient.NewAPIClient(configuration)
543-
r, err := apiClient.RolesDiscoveryApi.DiscoverySubnetStart(context.Background()).Identifier(identifier).Execute()
544+
r, err := apiClient.RolesDiscoveryApi.DiscoverySubnetStart(context.Background()).Identifier(identifier).Wait(wait).Execute()
544545
if err != nil {
545546
fmt.Fprintf(os.Stderr, "Error when calling `RolesDiscoveryApi.DiscoverySubnetStart``: %v\n", err)
546547
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
@@ -560,6 +561,7 @@ Other parameters are passed through a pointer to a apiDiscoverySubnetStartReques
560561
Name | Type | Description | Notes
561562
------------- | ------------- | ------------- | -------------
562563
**identifier** | **string** | |
564+
**wait** | **bool** | |
563565

564566
### Return type
565567

pkg/extconfig/ip.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ func (e *ExtConfig) GetInterfaceForIP(forIp net.IP) (*net.Interface, error) {
6363
}
6464
}
6565
}
66-
return nil, fmt.Errorf("faild to find interface for %s", forIp.String())
66+
return nil, fmt.Errorf("failed to find interface for %s", forIp.String())
6767
}
6868

6969
func (e *ExtConfig) GetIP() (net.IP, error) {

pkg/roles/dhcp/role_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
func generateHW() net.HardwareAddr {
1515
return net.HardwareAddr(securecookie.GenerateRandomKey(6))
1616
}
17+
1718
func RoleConfig() []byte {
1819
return []byte(tests.MustJSON(dhcp.RoleConfig{
1920
Port: 0,

pkg/roles/discovery/api_subnets.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ func (r *Role) APISubnetsPut() usecase.Interactor {
8787

8888
type APISubnetsStartInput struct {
8989
Name string `query:"identifier" required:"true"`
90+
Wait bool `query:"wait" required:"true"`
9091
}
9192

9293
func (r *Role) APISubnetsStart() usecase.Interactor {
@@ -107,7 +108,11 @@ func (r *Role) APISubnetsStart() usecase.Interactor {
107108
r.log.Warn("failed to parse subnet from KV", zap.Error(err))
108109
return status.Wrap(err, status.Internal)
109110
}
110-
go s.RunDiscovery(context.Background())
111+
if input.Wait {
112+
s.RunDiscovery(context.Background())
113+
} else {
114+
go s.RunDiscovery(context.Background())
115+
}
111116
return nil
112117
})
113118
u.SetName("discovery.subnet_start")

pkg/roles/discovery/device.go

+1-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
dhcptypes "beryju.io/gravity/pkg/roles/dhcp/types"
1111
"beryju.io/gravity/pkg/roles/discovery/types"
1212
dnstypes "beryju.io/gravity/pkg/roles/dns/types"
13-
"github.com/google/uuid"
1413
"go.etcd.io/etcd/api/v3/mvccpb"
1514
clientv3 "go.etcd.io/etcd/client/v3"
1615
"go.uber.org/zap"
@@ -27,8 +26,7 @@ type Device struct {
2726

2827
func (r *Role) newDevice() *Device {
2928
return &Device{
30-
Identifier: uuid.New().String(),
31-
inst: r.i,
29+
inst: r.i,
3230
}
3331
}
3432

pkg/roles/discovery/role.go

+29-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package discovery
22

33
import (
44
"context"
5-
"net/netip"
5+
"errors"
6+
"fmt"
7+
"net"
68

79
"beryju.io/gravity/pkg/extconfig"
810
instanceTypes "beryju.io/gravity/pkg/instance/types"
@@ -63,14 +65,14 @@ func New(instance roles.Instance) *Role {
6365
})
6466
r.i.AddEventListener(instanceTypes.EventTopicInstanceFirstStart, func(ev *roles.Event) {
6567
// On first start create a subnet based on the instance IP
66-
subnet := r.NewSubnet("default-instance-subnet")
67-
ip := netip.MustParseAddr(extconfig.Get().Instance.IP)
68-
prefix, err := ip.Prefix(24)
68+
subnet := r.NewSubnet(fmt.Sprintf("instance-subnet-%s", extconfig.Get().Instance.Identifier))
69+
70+
cidr, err := GetCIDRFromIP()
6971
if err != nil {
7072
r.log.Warn("failed to get prefix", zap.Error(err))
7173
return
7274
}
73-
subnet.CIDR = prefix.String()
75+
subnet.CIDR = cidr
7476
subnet.DNSResolver = extconfig.Get().FallbackDNS
7577
subnet.DiscoveryTTL = 86400
7678
err = subnet.put(ev.Context)
@@ -83,6 +85,28 @@ func New(instance roles.Instance) *Role {
8385
return r
8486
}
8587

88+
func GetCIDRFromIP() (string, error) {
89+
ip := net.ParseIP(extconfig.Get().Instance.IP)
90+
intf, err := extconfig.Get().GetInterfaceForIP(ip)
91+
if err != nil {
92+
return "", err
93+
}
94+
addrs, err := intf.Addrs()
95+
if err != nil {
96+
return "", err
97+
}
98+
for _, addr := range addrs {
99+
iip, net, err := net.ParseCIDR(addr.String())
100+
if err != nil {
101+
continue
102+
}
103+
if ip.Equal(iip) {
104+
return net.String(), nil
105+
}
106+
}
107+
return "", errors.New("no CIDR found")
108+
}
109+
86110
func (r *Role) Start(ctx context.Context, config []byte) error {
87111
r.cfg = r.decodeRoleConfig(config)
88112
if !r.cfg.Enabled || extconfig.Get().ListenOnlyMode {

pkg/roles/discovery/subnet.go

+4
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,12 @@ func (s *Subnet) RunDiscovery(ctx context.Context) []Device {
125125
dev.MAC = addr.Addr
126126
} else {
127127
dev.IP = addr.Addr
128+
dev.Identifier = addr.Addr
128129
}
129130
}
131+
if dev.Identifier == "" {
132+
continue
133+
}
130134
devices = append(devices, *dev)
131135
err := dev.put(tr.Context(), int64(s.DiscoveryTTL))
132136
if err != nil {

0 commit comments

Comments
 (0)