Skip to content

Commit 38ce3c8

Browse files
sergelogvinovsmira
authored andcommitted
feat: nocloud prefer mac address
Use MAC address over network interface name. Signed-off-by: Serge Logvinov <serge.logvinov@sinextra.dev> Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
1 parent 401e894 commit 38ce3c8

File tree

6 files changed

+134
-11
lines changed

6 files changed

+134
-11
lines changed

internal/app/machined/pkg/runtime/v1alpha1/platform/internal/netutils/netutils.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@ package netutils
77

88
import (
99
"context"
10+
"fmt"
1011
"log"
1112
"time"
1213

14+
"github.com/cenkalti/backoff/v4"
15+
"github.com/cosi-project/runtime/pkg/safe"
1316
"github.com/cosi-project/runtime/pkg/state"
1417
"github.com/siderolabs/go-retry/retry"
1518

@@ -24,6 +27,36 @@ func Wait(ctx context.Context, r state.State) error {
2427
return network.NewReadyCondition(r, network.AddressReady).Wait(ctx)
2528
}
2629

30+
// WaitInterfaces for the interfaces to be up to interact with platform metadata services.
31+
func WaitInterfaces(ctx context.Context, r state.State) error {
32+
backoff := backoff.NewExponentialBackOff()
33+
backoff.MaxInterval = 2 * time.Second
34+
backoff.MaxElapsedTime = 30 * time.Second
35+
36+
for ctx.Err() == nil {
37+
hostInterfaces, err := safe.StateListAll[*network.LinkStatus](ctx, r)
38+
if err != nil {
39+
return fmt.Errorf("error listing host interfaces: %w", err)
40+
}
41+
42+
if hostInterfaces.Len() != 0 {
43+
return nil
44+
}
45+
46+
log.Printf("waiting for network interface appearse...")
47+
48+
interval := backoff.NextBackOff()
49+
50+
select {
51+
case <-ctx.Done():
52+
return nil
53+
case <-time.After(interval):
54+
}
55+
}
56+
57+
return nil
58+
}
59+
2760
// RetryFetch retries fetching from metadata service.
2861
func RetryFetch(ctx context.Context, f func(ctx context.Context) (string, error)) (string, error) {
2962
var (

internal/app/machined/pkg/runtime/v1alpha1/platform/nocloud/metadata.go

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,19 @@ func (n *Nocloud) acquireConfig(ctx context.Context, r state.State) (metadataCon
270270
return metadataConfigDl, metadataNetworkConfigDl, machineConfigDl, metadata, err
271271
}
272272

273-
//nolint:gocyclo
274-
func (n *Nocloud) applyNetworkConfigV1(config *NetworkConfig, networkConfig *runtime.PlatformNetworkConfig) error {
273+
//nolint:gocyclo,cyclop
274+
func (n *Nocloud) applyNetworkConfigV1(config *NetworkConfig, st state.State, networkConfig *runtime.PlatformNetworkConfig) error {
275+
ctx := context.TODO()
276+
277+
if err := netutils.WaitInterfaces(ctx, st); err != nil {
278+
return err
279+
}
280+
281+
hostInterfaces, err := safe.StateListAll[*network.LinkStatus](ctx, st)
282+
if err != nil {
283+
return fmt.Errorf("error listing host interfaces: %w", err)
284+
}
285+
275286
for _, ntwrk := range config.Config {
276287
switch ntwrk.Type {
277288
case "nameserver":
@@ -290,8 +301,29 @@ func (n *Nocloud) applyNetworkConfigV1(config *NetworkConfig, networkConfig *run
290301
ConfigLayer: network.ConfigPlatform,
291302
})
292303
case "physical":
304+
name := ntwrk.Interfaces
305+
306+
if ntwrk.Mac != "" {
307+
macAddressMatched := false
308+
hostInterfaceIter := hostInterfaces.Iterator()
309+
310+
for hostInterfaceIter.Next() {
311+
macAddress := hostInterfaceIter.Value().TypedSpec().PermanentAddr.String()
312+
if macAddress == ntwrk.Mac {
313+
name = hostInterfaceIter.Value().Metadata().ID()
314+
macAddressMatched = true
315+
316+
break
317+
}
318+
}
319+
320+
if !macAddressMatched {
321+
log.Printf("nocloud: no link with matching MAC address %q, defaulted to use name %s instead", ntwrk.Mac, name)
322+
}
323+
}
324+
293325
networkConfig.Links = append(networkConfig.Links, network.LinkSpecSpec{
294-
Name: ntwrk.Interfaces,
326+
Name: name,
295327
Up: true,
296328
ConfigLayer: network.ConfigPlatform,
297329
})
@@ -301,7 +333,7 @@ func (n *Nocloud) applyNetworkConfigV1(config *NetworkConfig, networkConfig *run
301333
case "dhcp", "dhcp4":
302334
networkConfig.Operators = append(networkConfig.Operators, network.OperatorSpecSpec{
303335
Operator: network.OperatorDHCP4,
304-
LinkName: ntwrk.Interfaces,
336+
LinkName: name,
305337
RequireUp: true,
306338
DHCP4: network.DHCP4OperatorSpec{
307339
RouteMetric: 1024,
@@ -335,7 +367,7 @@ func (n *Nocloud) applyNetworkConfigV1(config *NetworkConfig, networkConfig *run
335367
networkConfig.Addresses = append(networkConfig.Addresses,
336368
network.AddressSpecSpec{
337369
ConfigLayer: network.ConfigPlatform,
338-
LinkName: ntwrk.Interfaces,
370+
LinkName: name,
339371
Address: ipPrefix,
340372
Scope: nethelpers.ScopeGlobal,
341373
Flags: nethelpers.AddressFlags(nethelpers.AddressPermanent),
@@ -352,7 +384,7 @@ func (n *Nocloud) applyNetworkConfigV1(config *NetworkConfig, networkConfig *run
352384
route := network.RouteSpecSpec{
353385
ConfigLayer: network.ConfigPlatform,
354386
Gateway: gw,
355-
OutLinkName: ntwrk.Interfaces,
387+
OutLinkName: name,
356388
Table: nethelpers.TableMain,
357389
Protocol: nethelpers.ProtocolStatic,
358390
Type: nethelpers.TypeUnicast,
@@ -371,7 +403,7 @@ func (n *Nocloud) applyNetworkConfigV1(config *NetworkConfig, networkConfig *run
371403
case "ipv6_dhcpv6-stateful":
372404
networkConfig.Operators = append(networkConfig.Operators, network.OperatorSpecSpec{
373405
Operator: network.OperatorDHCP6,
374-
LinkName: ntwrk.Interfaces,
406+
LinkName: name,
375407
RequireUp: true,
376408
DHCP6: network.DHCP6OperatorSpec{
377409
RouteMetric: 1024,

internal/app/machined/pkg/runtime/v1alpha1/platform/nocloud/nocloud.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func (n *Nocloud) ParseMetadata(unmarshalledNetworkConfig *NetworkConfig, st sta
5252

5353
switch unmarshalledNetworkConfig.Version {
5454
case 1:
55-
if err := n.applyNetworkConfigV1(unmarshalledNetworkConfig, networkConfig); err != nil {
55+
if err := n.applyNetworkConfigV1(unmarshalledNetworkConfig, st, networkConfig); err != nil {
5656
return nil, err
5757
}
5858
case 2:

internal/app/machined/pkg/runtime/v1alpha1/platform/nocloud/nocloud_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ func TestParseMetadata(t *testing.T) {
5858

5959
st := state.WrapCore(namespaced.NewState(inmem.Build))
6060

61+
eth0 := network.NewLinkStatus(network.NamespaceName, "eth0")
62+
eth0.TypedSpec().PermanentAddr = nethelpers.HardwareAddr{0x68, 0x05, 0xca, 0xb8, 0xf1, 0xf7}
63+
require.NoError(t, st.Create(context.TODO(), eth0))
64+
6165
eth1 := network.NewLinkStatus(network.NamespaceName, "eth1")
6266
eth1.TypedSpec().PermanentAddr = nethelpers.HardwareAddr{0x68, 0x05, 0xca, 0xb8, 0xf1, 0xf8}
6367
require.NoError(t, st.Create(context.TODO(), eth1))

internal/app/machined/pkg/runtime/v1alpha1/platform/nocloud/testdata/expected-v1.yaml

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,24 @@ addresses:
55
scope: global
66
flags: permanent
77
layer: platform
8-
- address: 2001:2:3:4:5:6:7:8/64
8+
- address: 2001:2:3:4:5:6:7:f7/64
99
linkName: eth0
1010
family: inet6
1111
scope: global
1212
flags: permanent
1313
layer: platform
14+
- address: 192.168.2.11/24
15+
linkName: eth2
16+
family: inet4
17+
scope: global
18+
flags: permanent
19+
layer: platform
20+
- address: 2001:2:3:4:5:6:7:f9/64
21+
linkName: eth2
22+
family: inet6
23+
scope: global
24+
flags: permanent
25+
layer: platform
1426
links:
1527
- name: eth0
1628
logical: false
@@ -19,6 +31,13 @@ links:
1931
kind: ""
2032
type: netrom
2133
layer: platform
34+
- name: eth2
35+
logical: false
36+
up: true
37+
mtu: 0
38+
kind: ""
39+
type: netrom
40+
layer: platform
2241
routes:
2342
- family: inet4
2443
dst: ""
@@ -44,6 +63,30 @@ routes:
4463
flags: ""
4564
protocol: static
4665
layer: platform
66+
- family: inet4
67+
dst: ""
68+
src: ""
69+
gateway: 192.168.2.1
70+
outLinkName: eth2
71+
table: main
72+
priority: 1024
73+
scope: global
74+
type: unicast
75+
flags: ""
76+
protocol: static
77+
layer: platform
78+
- family: inet6
79+
dst: ""
80+
src: ""
81+
gateway: fe80::2
82+
outLinkName: eth2
83+
table: main
84+
priority: 2048
85+
scope: global
86+
type: unicast
87+
flags: ""
88+
protocol: static
89+
layer: platform
4790
hostnames:
4891
- hostname: talos
4992
domainname: fqdn

internal/app/machined/pkg/runtime/v1alpha1/platform/nocloud/testdata/metadata-v1.yaml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,26 @@ version: 1
22
config:
33
- type: physical
44
name: eth0
5-
mac_address: 'ae:71:9e:61:d0:ad'
5+
mac_address: '68:05:ca:b8:f1:f7'
66
subnets:
77
- type: static
88
address: '192.168.1.11'
99
netmask: '255.255.255.0'
1010
gateway: '192.168.1.1'
1111
- type: static6
12-
address: '2001:2:3:4:5:6:7:8/64'
12+
address: '2001:2:3:4:5:6:7:f7/64'
1313
gateway: 'fe80::1'
14+
- type: physical
15+
name: eth1
16+
mac_address: '68:05:ca:b8:f1:f9'
17+
subnets:
18+
- type: static
19+
address: '192.168.2.11'
20+
netmask: '255.255.255.0'
21+
gateway: '192.168.2.1'
22+
- type: static6
23+
address: '2001:2:3:4:5:6:7:f9/64'
24+
gateway: 'fe80::2'
1425
- type: nameserver
1526
address:
1627
- '192.168.1.1'

0 commit comments

Comments
 (0)