Skip to content

Commit

Permalink
Support NIC identifiers as alternative to MAC addresses (#351)
Browse files Browse the repository at this point in the history
  • Loading branch information
GrigoriyMikhalkin authored Mar 2, 2023
1 parent 73651ec commit 2156944
Show file tree
Hide file tree
Showing 13 changed files with 389 additions and 232 deletions.
5 changes: 3 additions & 2 deletions cmd/metal-api/internal/datastore/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import (
"fmt"
"math/big"

"github.com/metal-stack/metal-api/cmd/metal-api/internal/metal"
r "gopkg.in/rethinkdb/rethinkdb-go.v6"

"github.com/metal-stack/metal-api/cmd/metal-api/internal/metal"
)

// MachineSearchQuery can be used to search machines.
Expand Down Expand Up @@ -403,7 +404,7 @@ func (rs *RethinkStore) ListMachines() (metal.Machines, error) {
// CreateMachine creates a new machine in the database as "unallocated new machines".
// If the given machine has an allocation, the function returns an error because
// allocated machines cannot be created. If there is already a machine with the
// given ID in the database it will be replaced the the given machine.
// given ID in the database it will be replaced the given machine.
// CreateNetwork creates a new network.
func (rs *RethinkStore) CreateMachine(m *metal.Machine) error {
if m.Allocation != nil {
Expand Down
6 changes: 5 additions & 1 deletion cmd/metal-api/internal/grpc/boot-service.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import (
"time"

"github.com/avast/retry-go/v4"
"go.uber.org/zap"

"github.com/metal-stack/metal-api/cmd/metal-api/internal/datastore"
"github.com/metal-stack/metal-api/cmd/metal-api/internal/metal"
v1 "github.com/metal-stack/metal-api/pkg/api/v1"
"github.com/metal-stack/metal-lib/bus"
"go.uber.org/zap"
)

type BootService struct {
Expand Down Expand Up @@ -122,11 +123,14 @@ func (b *BootService) Register(ctx context.Context, req *v1.BootServiceRegisterR
neighs = append(neighs, metal.Nic{
Name: neigh.Name,
MacAddress: metal.MacAddress(neigh.Mac),
Hostname: neigh.Hostname,
Identifier: neigh.Identifier,
})
}
nics = append(nics, metal.Nic{
Name: nic.Name,
MacAddress: metal.MacAddress(nic.Mac),
Identifier: nic.Identifier,
Neighbors: neighs,
})
}
Expand Down
40 changes: 34 additions & 6 deletions cmd/metal-api/internal/metal/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,20 @@ type MacAddress string
type Nic struct {
MacAddress MacAddress `rethinkdb:"macAddress" json:"macAddress"`
Name string `rethinkdb:"name" json:"name"`
Identifier string `rethinkdb:"identifier" json:"identifier"`
Vrf string `rethinkdb:"vrf" json:"vrf"`
Neighbors Nics `rethinkdb:"neighbors" json:"neighbors"`
Hostname string `rethinkdb:"hostname" json:"hostname"`
}

// GetIdentifier returns the identifier of a nic.
// It returns the mac address as a fallback if no identifier was found.
// (this is for backwards compatibility with old metal-core and metal-hammer versions)
func (n *Nic) GetIdentifier() string {
if n.Identifier != "" {
return n.Identifier
}
return string(n.MacAddress)
}

// Nics is a list of nics.
Expand Down Expand Up @@ -147,22 +159,38 @@ func (n *Network) SubstractPrefixes(prefixes ...Prefix) []Prefix {
return result
}

type NicMap map[MacAddress]*Nic
func (nics Nics) FilterByHostname(hostname string) (res Nics) {
if hostname == "" {
return nics
}

// ByMac creates a indexed map from a nic list.
func (nics Nics) ByMac() NicMap {
res := make(map[MacAddress]*Nic)
for i, n := range nics {
res[n.MacAddress] = &nics[i]
if n.Hostname == hostname {
res = append(res, nics[i])
}
}

return res
}

// ByName creates a indexed map from a nic list.
// ByName creates a map (nic names --> nic) from a nic list.
func (nics Nics) ByName() map[string]*Nic {
res := make(map[string]*Nic)

for i, n := range nics {
res[n.Name] = &nics[i]
}

return res
}

// ByIdentifier creates a map (nic identifier --> nic) from a nic list.
func (nics Nics) ByIdentifier() map[string]*Nic {
res := make(map[string]*Nic)

for i, n := range nics {
res[n.GetIdentifier()] = &nics[i]
}

return res
}
15 changes: 7 additions & 8 deletions cmd/metal-api/internal/metal/network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"testing"
)

func TestNics_ByMac(t *testing.T) {
func TestNics_ByIdentifier(t *testing.T) {
// Create Nics
countOfNics := 3
nicArray := make([]Nic, countOfNics)
Expand All @@ -23,28 +23,27 @@ func TestNics_ByMac(t *testing.T) {
nicArray[i].Neighbors = append(nicArray[0:i], nicArray[i+1:countOfNics]...)
}

map1 := NicMap{}
map1 := map[string]*Nic{}
for i, n := range nicArray {
map1[n.MacAddress] = &nicArray[i]
map1[string(n.MacAddress)] = &nicArray[i]
}

tests := []struct {
name string
nics Nics
want NicMap
want map[string]*Nic
}{
// Test Data Array (only 1 data):
{
name: "TestNics_ByMac Test 1",
name: "TestNics_ByIdentifier Test 1",
nics: nicArray,
want: map1,
},
}
for i := range tests {
tt := tests[i]
t.Run(tt.name, func(t *testing.T) {
if got := tt.nics.ByMac(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Nics.ByMac() = %v, want %v", got, tt.want)
if got := tt.nics.ByIdentifier(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Nics.ByIdentifier() = %v, want %v", got, tt.want)
}
})
}
Expand Down
19 changes: 11 additions & 8 deletions cmd/metal-api/internal/metal/switch.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,12 @@ func (s *Switch) ConnectMachine(machine *Machine) int {
// calculate the connections for this machine
for _, switchNic := range s.Nics {
for _, machineNic := range machine.Hardware.Nics {
devNeighbors := machineNic.Neighbors.ByMac()
if _, has := devNeighbors[switchNic.MacAddress]; has {
var has bool

neighMap := machineNic.Neighbors.FilterByHostname(s.Name).ByIdentifier()

_, has = neighMap[switchNic.GetIdentifier()]
if has {
conn := Connection{
Nic: switchNic,
MachineID: machine.ID,
Expand All @@ -115,20 +119,19 @@ func (s *Switch) ConnectMachine(machine *Machine) int {

// SetVrfOfMachine set port on switch where machine is connected to given vrf
func (s *Switch) SetVrfOfMachine(m *Machine, vrf string) {
affectedMacs := map[MacAddress]bool{}
affected := map[string]bool{}
for _, c := range s.MachineConnections[m.ID] {
mac := c.Nic.MacAddress
affectedMacs[mac] = true
affected[c.Nic.GetIdentifier()] = true
}

if len(affectedMacs) == 0 {
if len(affected) == 0 {
return
}

nics := Nics{}
for mac, old := range s.Nics.ByMac() {
for k, old := range s.Nics.ByIdentifier() {
e := old
if _, ok := affectedMacs[mac]; ok {
if _, ok := affected[k]; ok {
e.Vrf = vrf
}
nics = append(nics, *e)
Expand Down
81 changes: 78 additions & 3 deletions cmd/metal-api/internal/metal/switch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,16 +99,18 @@ func TestSwitch_ConnectMachine2(t *testing.T) {
PartitionID string
RackID string
}

switchName1 := "switch-1"
switchName2 := "switch-2"
tests := []struct {
name string
fields fields
machine *Machine
}{
// Test Data Array (Only 1 Value):
{
name: "simple connection",
fields: fields{
ID: "switch-1",
ID: switchName1,
Nics: []Nic{
{
Name: "eth0",
Expand Down Expand Up @@ -155,9 +157,79 @@ func TestSwitch_ConnectMachine2(t *testing.T) {
Neighbors: []Nic{
{
MacAddress: "11:11:11",
Hostname: switchName1,
},
{
MacAddress: "11:11:12",
Hostname: switchName1,
},
},
},
{
Name: "eth1",
Neighbors: []Nic{
{
MacAddress: "22:11:11",
Hostname: switchName1,
},
{
MacAddress: "11:11:13",
Hostname: switchName1,
},
},
},
},
},
},
},
{
name: "multiple switch connection",
fields: fields{
ID: switchName1,
Nics: []Nic{
{
Name: "eth0",
MacAddress: "00:11:11",
},
{
Name: "swp1",
MacAddress: "11:11:11",
},
{
Name: "swp2",
MacAddress: "22:11:11",
},
},
PartitionID: "nbg1",
RackID: "rack1",
MachineConnections: ConnectionMap{
"machine-1": []Connection{
{
Nic: Nic{
Name: "swp1",
MacAddress: "11:11:11",
},
MachineID: "machine-1",
},
},
},
},
machine: &Machine{
Base: Base{
ID: "machine-1",
},
Hardware: MachineHardware{
Nics: []Nic{
{
Name: "eth0",
Neighbors: []Nic{
{
MacAddress: "11:11:11",
Hostname: switchName1,
},
{
MacAddress: "11:11:12",
Hostname: switchName1,
},
},
},
Expand All @@ -166,9 +238,11 @@ func TestSwitch_ConnectMachine2(t *testing.T) {
Neighbors: []Nic{
{
MacAddress: "22:11:11",
Hostname: switchName2,
},
{
MacAddress: "11:11:13",
Hostname: switchName2,
},
},
},
Expand All @@ -182,7 +256,8 @@ func TestSwitch_ConnectMachine2(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
s := Switch{
Base: Base{
ID: tt.fields.ID,
ID: tt.fields.ID,
Name: tt.fields.ID,
},
RackID: tt.fields.RackID,
Nics: tt.fields.Nics,
Expand Down
Loading

0 comments on commit 2156944

Please sign in to comment.