Skip to content
Merged
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
29 changes: 13 additions & 16 deletions pkg/staticnetworkconfig/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"context"
"fmt"
"path/filepath"
"regexp"
"sort"
"strings"

Expand Down Expand Up @@ -167,7 +168,8 @@ func (s *StaticNetworkConfigGenerator) formatNMConnection(nmConnection string) (

func (s *StaticNetworkConfigGenerator) validateInterfaceNamesExistence(macInterfaceMap models.MacInterfaceMap, networksConfig []StaticNetworkConfigData) error {
interfaceNames := lo.Map(macInterfaceMap, func(m *models.MacInterfaceMapItems0, _ int) string { return m.LogicalNicName })
var matched bool
// See 'man systemd.net-naming-scheme' for interface naming protocol
predicatableIfaceNamePattern := regexp.MustCompile("^en[PsvxXbucaipod]")
for _, nc := range networksConfig {
cfg, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: true}, []byte(nc.FileContents))
if err != nil {
Expand All @@ -177,7 +179,8 @@ func (s *StaticNetworkConfigGenerator) validateInterfaceNamesExistence(macInterf
connectionSection := cfg.Section("connection")
interfaceName, err := connectionSection.GetKey("interface-name")
if err != nil {
return errors.Wrapf(err, "failed to get interface-name for file %s", nc.FilePath)
// When the id field is provided the interface-name will not be present
continue
}
interfaceType, err := connectionSection.GetKey("type")
if err != nil {
Expand All @@ -186,23 +189,14 @@ func (s *StaticNetworkConfigGenerator) validateInterfaceNamesExistence(macInterf
switch interfaceType.String() {
case "802-3-ethernet", "ethernet":
if !lo.Contains(interfaceNames, interfaceName.String()) {
return errors.Errorf("mac-interface mapping for interface %s is missing", interfaceName.String())
}
matched = true
case "vlan":
vlanSection := cfg.Section("vlan")
parent, err := vlanSection.GetKey("parent")
if err != nil {
return errors.Wrapf(err, "failed to get parent of vlan %s", interfaceName.Name())
}
if lo.Contains(interfaceNames, parent.String()) {
matched = true
if !predicatableIfaceNamePattern.MatchString(interfaceName.String()) {
return errors.Errorf("mac-interface mapping for interface %s is missing and not a physical interface", interfaceName.String())
} else {
s.log.Infof("Interface %s has no mac-interface mapping but matches a physical interface", interfaceName.String())
}
}
}
}
if !matched {
return errors.Errorf("no mac address mapping can be associated with the available network interfaces %v", interfaceNames)
}
return nil
}

Expand All @@ -220,6 +214,9 @@ func (s *StaticNetworkConfigGenerator) ValidateStaticConfigParams(staticNetworkC
}

func (s *StaticNetworkConfigGenerator) validateMacInterfaceName(hostIdx int, macInterfaceMap models.MacInterfaceMap) error {
if len(macInterfaceMap) == 0 {
return fmt.Errorf("at least one interface for host %d must be provided", hostIdx)
}
interfaceCheck := make(map[string]struct{}, len(macInterfaceMap))
macCheck := make(map[string]struct{}, len(macInterfaceMap))
for _, macInterface := range macInterfaceMap {
Expand Down
90 changes: 79 additions & 11 deletions pkg/staticnetworkconfig/generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,17 +238,6 @@ var _ = Describe("validate mac interface mapping", func() {
vlan:
base-iface: eth1
id: 101`
It("vlan without underlying interface - no mapping", func() {
err := staticNetworkGenerator.ValidateStaticConfigParams([]*models.HostStaticNetworkConfig{
{
MacInterfaceMap: nil,
NetworkYaml: withoutUnderlyingInterface,
},
})
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("no mac address mapping can be associated with the available network interfaces"))
})

It("vlan with underlying interface - no mapping", func() {
err := staticNetworkGenerator.ValidateStaticConfigParams([]*models.HostStaticNetworkConfig{
{
Expand Down Expand Up @@ -288,6 +277,85 @@ var _ = Describe("validate mac interface mapping", func() {
Expect(err).ToNot(HaveOccurred())
})
})

Context("no mapping for physical interfaces", func() {
withPhysicalInterface := `interfaces:
- name: eth0
type: ethernet
state: up
ipv4:
enabled: true
dhcp: false
address:
- ip: 192.0.2.1
prefix-length: 24
- name: eno12399np0
type: ethernet
state: up
ipv4:
enabled: false
dhcp: false`
withNoMappedInterfaces := `interfaces:
- name: eno12345
type: ethernet
state: up
ipv4:
enabled: false
dhcp: false
- name: eno12399np0
type: ethernet
state: up
ipv4:
enabled: false
dhcp: false`
withMacIdentifier := `interfaces:
- name: eth0
type: ethernet
state: up
identifier: mac-address
mac-address: f8:75:a4:a4:00:fe
ipv4:
enabled: false
dhcp: false`
It("no mapping needed for physical interface", func() {
err := staticNetworkGenerator.ValidateStaticConfigParams([]*models.HostStaticNetworkConfig{
{
MacInterfaceMap: []*models.MacInterfaceMapItems0{
{
LogicalNicName: "eth0",
MacAddress: "f8:75:a4:a4:00:fe",
},
},
NetworkYaml: withPhysicalInterface,
},
})
Expect(err).ToNot(HaveOccurred())
})
It("at least one mapped interface is required", func() {
err := staticNetworkGenerator.ValidateStaticConfigParams([]*models.HostStaticNetworkConfig{
{
MacInterfaceMap: []*models.MacInterfaceMapItems0{},
NetworkYaml: withNoMappedInterfaces,
},
})
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("at least one interface for host"))
})
It("mac-identifier field is allowed", func() {
err := staticNetworkGenerator.ValidateStaticConfigParams([]*models.HostStaticNetworkConfig{
{
MacInterfaceMap: []*models.MacInterfaceMapItems0{
{
LogicalNicName: "eth0",
MacAddress: "f8:75:a4:a4:00:fe",
},
},
NetworkYaml: withMacIdentifier,
},
})
Expect(err).ToNot(HaveOccurred())
})
})
})

var _ = Describe("StaticNetworkConfig", func() {
Expand Down