mirror of
https://github.com/siderolabs/talos.git
synced 2025-11-02 09:21:13 +01:00
feat: bring unconfigured links with link carrier up by default
This matches previous networkd implementation to make sure we can run DHCP on the interfaces which are not explicitly brought up. Signed-off-by: Andrey Smirnov <smirnov.andrey@gmail.com>
This commit is contained in:
parent
02bd657b25
commit
f93c9c8fa6
@ -42,6 +42,11 @@ func (ctrl *LinkConfigController) Inputs() []controller.Input {
|
||||
ID: pointer.ToString(config.V1Alpha1ID),
|
||||
Kind: controller.InputWeak,
|
||||
},
|
||||
{
|
||||
Namespace: network.NamespaceName,
|
||||
Type: network.LinkStatusType,
|
||||
Kind: controller.InputWeak,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,7 +116,7 @@ func (ctrl *LinkConfigController) Run(ctx context.Context, r controller.Runtime,
|
||||
}
|
||||
|
||||
// parse kernel cmdline for the interface name
|
||||
cmdlineLink := ctrl.parseCmdline(logger)
|
||||
cmdlineLink, cmdlineIgnored := ctrl.parseCmdline(logger)
|
||||
if cmdlineLink.Name != "" {
|
||||
if _, ignored := ignoredInterfaces[cmdlineLink.Name]; !ignored {
|
||||
var ids []string
|
||||
@ -127,7 +132,7 @@ func (ctrl *LinkConfigController) Run(ctx context.Context, r controller.Runtime,
|
||||
}
|
||||
}
|
||||
|
||||
// parse machine configuration for static routes
|
||||
// parse machine configuration for link specs
|
||||
if cfgProvider != nil {
|
||||
links := ctrl.parseMachineConfiguration(logger, cfgProvider)
|
||||
|
||||
@ -143,8 +148,56 @@ func (ctrl *LinkConfigController) Run(ctx context.Context, r controller.Runtime,
|
||||
}
|
||||
}
|
||||
|
||||
// list link for cleanup
|
||||
list, err := r.List(ctx, resource.NewMetadata(network.ConfigNamespaceName, network.LinkSpecType, "", resource.VersionUndefined))
|
||||
// bring up any physical link not mentioned explicitly in the machine configuration
|
||||
configuredLinks := map[string]struct{}{}
|
||||
|
||||
for _, linkName := range cmdlineIgnored {
|
||||
configuredLinks[linkName] = struct{}{}
|
||||
}
|
||||
|
||||
if cmdlineLink.Name != "" {
|
||||
configuredLinks[cmdlineLink.Name] = struct{}{}
|
||||
}
|
||||
|
||||
if cfgProvider != nil {
|
||||
for _, device := range cfgProvider.Machine().Network().Devices() {
|
||||
configuredLinks[device.Interface()] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
list, err := r.List(ctx, resource.NewMetadata(network.NamespaceName, network.LinkStatusType, "", resource.VersionUndefined))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error listing link statuses: %w", err)
|
||||
}
|
||||
|
||||
for _, item := range list.Items {
|
||||
linkStatus := item.(*network.LinkStatus) //nolint:errcheck,forcetypeassert
|
||||
|
||||
if _, configured := configuredLinks[linkStatus.Metadata().ID()]; !configured {
|
||||
if linkStatus.Physical() {
|
||||
var ids []string
|
||||
|
||||
ids, err = ctrl.apply(ctx, r, []network.LinkSpecSpec{
|
||||
{
|
||||
Name: linkStatus.Metadata().ID(),
|
||||
Up: true,
|
||||
ConfigLayer: network.ConfigDefault,
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("error applying default link up: %w", err)
|
||||
}
|
||||
|
||||
for _, id := range ids {
|
||||
touchedIDs[id] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// list links for cleanup
|
||||
list, err = r.List(ctx, resource.NewMetadata(network.ConfigNamespaceName, network.LinkSpecType, "", resource.VersionUndefined))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error listing resources: %w", err)
|
||||
}
|
||||
@ -189,23 +242,23 @@ func (ctrl *LinkConfigController) apply(ctx context.Context, r controller.Runtim
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
func (ctrl *LinkConfigController) parseCmdline(logger *zap.Logger) network.LinkSpecSpec {
|
||||
func (ctrl *LinkConfigController) parseCmdline(logger *zap.Logger) (network.LinkSpecSpec, []string) {
|
||||
if ctrl.Cmdline == nil {
|
||||
return network.LinkSpecSpec{}
|
||||
return network.LinkSpecSpec{}, nil
|
||||
}
|
||||
|
||||
settings, err := ParseCmdlineNetwork(ctrl.Cmdline)
|
||||
if err != nil {
|
||||
logger.Info("ignoring error", zap.Error(err))
|
||||
|
||||
return network.LinkSpecSpec{}
|
||||
return network.LinkSpecSpec{}, nil
|
||||
}
|
||||
|
||||
return network.LinkSpecSpec{
|
||||
Name: settings.LinkName,
|
||||
Up: true,
|
||||
ConfigLayer: network.ConfigCmdline,
|
||||
}
|
||||
}, settings.IgnoreInterfaces
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
|
||||
@ -97,6 +97,28 @@ func (suite *LinkConfigSuite) assertLinks(requiredIDs []string, check func(*netw
|
||||
return nil
|
||||
}
|
||||
|
||||
func (suite *LinkConfigSuite) assertNoLinks(unexpectedIDs []string) error {
|
||||
unexpIDs := make(map[string]struct{}, len(unexpectedIDs))
|
||||
|
||||
for _, id := range unexpectedIDs {
|
||||
unexpIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.ConfigNamespaceName, network.LinkSpecType, "", resource.VersionUndefined))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, res := range resources.Items {
|
||||
_, unexpected := unexpIDs[res.Metadata().ID()]
|
||||
if unexpected {
|
||||
return retry.ExpectedErrorf("unexpected ID %q", res.Metadata().ID())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (suite *LinkConfigSuite) TestLoopback() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.LinkConfigController{}))
|
||||
|
||||
@ -289,6 +311,77 @@ func (suite *LinkConfigSuite) TestMachineConfiguration() {
|
||||
}))
|
||||
}
|
||||
|
||||
func (suite *LinkConfigSuite) TestDefaultUp() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.LinkConfigController{
|
||||
Cmdline: procfs.NewCmdline("talos.network.interface.ignore=eth2"),
|
||||
}))
|
||||
|
||||
for _, link := range []string{"eth0", "eth1", "eth2"} {
|
||||
linkStatus := network.NewLinkStatus(network.NamespaceName, link)
|
||||
linkStatus.TypedSpec().Type = nethelpers.LinkEther
|
||||
linkStatus.TypedSpec().LinkState = true
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, linkStatus))
|
||||
}
|
||||
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkInterfaces: []*v1alpha1.Device{
|
||||
{
|
||||
DeviceInterface: "eth0",
|
||||
DeviceVlans: []*v1alpha1.Vlan{
|
||||
{
|
||||
VlanID: 24,
|
||||
VlanCIDR: "10.0.0.1/8",
|
||||
},
|
||||
{
|
||||
VlanID: 48,
|
||||
VlanCIDR: "10.0.0.2/8",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinks([]string{
|
||||
"default/eth1",
|
||||
}, func(r *network.LinkSpec) error {
|
||||
suite.Assert().Equal(network.ConfigDefault, r.TypedSpec().ConfigLayer)
|
||||
suite.Assert().True(r.TypedSpec().Up)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoLinks([]string{
|
||||
"default/eth0",
|
||||
"default/eth2",
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
func TestLinkConfigSuite(t *testing.T) {
|
||||
suite.Run(t, new(LinkConfigSuite))
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user