Skip to content

Commit 0514b43

Browse files
authored
Add check to prevent migrating existing machine from one rack to another (#615)
1 parent c5b2272 commit 0514b43

File tree

3 files changed

+279
-142
lines changed

3 files changed

+279
-142
lines changed

cmd/metal-api/internal/datastore/switch.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,11 @@ func (rs *RethinkStore) ConnectMachineWithSwitches(m *metal.Machine) error {
151151
newSwitches := metal.Switches{}
152152
for _, sw := range switches {
153153
oldSwitch := sw
154-
if cons := sw.ConnectMachine(m); cons > 0 {
154+
cons, err := sw.ConnectMachine(m)
155+
if err != nil {
156+
return err
157+
}
158+
if cons > 0 {
155159
oldSwitches = append(oldSwitches, oldSwitch)
156160
newSwitches = append(newSwitches, sw)
157161
}

cmd/metal-api/internal/metal/switch.go

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -115,32 +115,21 @@ func (c ConnectionMap) ByNicName() (map[string]Connection, error) {
115115
return res, nil
116116
}
117117

118-
// ConnectMachine iterates over all switch nics and machine nic neighbor
119-
// to find existing wire connections.
120-
// Implementation is very inefficient, will also find all connections,
121-
// which should not happen in a real environment.
122-
func (s *Switch) ConnectMachine(machine *Machine) int {
123-
// first remove all existing connections to this machine.
124-
delete(s.MachineConnections, machine.ID)
125-
126-
// calculate the connections for this machine
127-
for _, switchNic := range s.Nics {
128-
for _, machineNic := range machine.Hardware.Nics {
129-
var has bool
130-
131-
neighMap := machineNic.Neighbors.FilterByHostname(s.Name).ByIdentifier()
132-
133-
_, has = neighMap[switchNic.GetIdentifier()]
134-
if has {
135-
conn := Connection{
136-
Nic: switchNic,
137-
MachineID: machine.ID,
138-
}
139-
s.MachineConnections[machine.ID] = append(s.MachineConnections[machine.ID], conn)
140-
}
118+
// ConnectMachine checks if a machine is physically connected to the switch and updates the switch's connections if necessary
119+
func (s *Switch) ConnectMachine(machine *Machine) (int, error) {
120+
_, connectionExists := s.MachineConnections[machine.ID]
121+
physicalConnections := s.getPhysicalMachineConnections(machine)
122+
123+
if len(physicalConnections) < 1 {
124+
if connectionExists {
125+
return 0, fmt.Errorf("machine connection between machine %s and switch %s exists in the database but not physically; if you are attempting migrate the machine from one rack to another delete it first", machine.ID, s.ID)
141126
}
127+
return 0, nil
142128
}
143-
return len(s.MachineConnections[machine.ID])
129+
130+
delete(s.MachineConnections, machine.ID)
131+
s.MachineConnections[machine.ID] = append(s.MachineConnections[machine.ID], physicalConnections...)
132+
return len(physicalConnections), nil
144133
}
145134

146135
// SetVrfOfMachine set port on switch where machine is connected to given vrf
@@ -235,6 +224,23 @@ func (s *Switch) MapPortNames(targetOS SwitchOSVendor) (map[string]string, error
235224
return portNamesMap, nil
236225
}
237226

227+
func (s *Switch) getPhysicalMachineConnections(machine *Machine) Connections {
228+
connections := make(Connections, 0)
229+
for _, machineNic := range machine.Hardware.Nics {
230+
neighMap := machineNic.Neighbors.FilterByHostname(s.Name).ByIdentifier()
231+
232+
for _, switchNic := range s.Nics {
233+
if _, has := neighMap[switchNic.GetIdentifier()]; has {
234+
connections = append(connections, Connection{
235+
Nic: switchNic,
236+
MachineID: machine.ID,
237+
})
238+
}
239+
}
240+
}
241+
return connections
242+
}
243+
238244
func mapPortName(port string, sourceOS, targetOS SwitchOSVendor, allLines []int) (string, error) {
239245
line, err := portNameToLine(port, sourceOS)
240246
if err != nil {

0 commit comments

Comments
 (0)