address openstack network duplication when interface may have both ipv6 and ipv4 addresses and add preflight check to identify duplicate source network definitions

This commit is contained in:
Gaurav Mehta 2024-09-13 11:21:45 +10:00 committed by Zespre Chang
parent ccc02a4edf
commit 03a8ef08e9
3 changed files with 61 additions and 16 deletions

View File

@ -226,6 +226,17 @@ func (h *virtualMachineHandler) preFlightChecks(vm *migration.VirtualMachineImpo
}
}
// dedup source network names as the same source network name cannot appear twice
sourceNetworkMap := make(map[string]bool)
for _, network := range vm.Spec.Mapping {
_, ok := sourceNetworkMap[network.SourceNetwork]
if !ok {
sourceNetworkMap[network.SourceNetwork] = true
continue
}
return fmt.Errorf("source network %s appears multiple times in vm spec", network.SourceNetwork)
}
return nil
}

View File

@ -337,23 +337,11 @@ func (c *Client) GenerateVirtualMachine(vm *migration.VirtualMachineImport) (*ku
return nil, fmt.Errorf("error getting firware settings: %v", err)
}
var networks []networkInfo
for network, values := range vmObj.Addresses {
valArr, ok := values.([]interface{})
if !ok {
return nil, fmt.Errorf("error asserting interface []interface")
}
for _, v := range valArr {
valMap, ok := v.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("error asserting network array element into map[string]string")
}
networks = append(networks, networkInfo{
NetworkName: network,
MAC: valMap["OS-EXT-IPS-MAC:mac_addr"].(string),
})
}
networks, err := generateNetworkInfo(vmObj.Addresses)
if err != nil {
return nil, err
}
newVM := &kubevirt.VirtualMachine{
ObjectMeta: metav1.ObjectMeta{
Name: vm.Spec.VirtualMachineName,
@ -640,3 +628,35 @@ func (c *Client) ImageFirmwareSettings(instance *servers.Server) (bool, bool, bo
}
return uefiType, tpmEnabled, secureBoot, nil
}
func generateNetworkInfo(info map[string]interface{}) ([]networkInfo, error) {
networks := make([]networkInfo, 0)
uniqueNetworks := make([]networkInfo, 0)
for network, values := range info {
valArr, ok := values.([]interface{})
if !ok {
return nil, fmt.Errorf("error asserting interface []interface")
}
for _, v := range valArr {
valMap, ok := v.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("error asserting network array element into map[string]string")
}
networks = append(networks, networkInfo{
NetworkName: network,
MAC: valMap["OS-EXT-IPS-MAC:mac_addr"].(string),
})
}
}
// in case of interfaces with ipv6 and ipv4 addresses they are reported twice, so we need to dedup them
// based on a mac address
networksMap := make(map[string]networkInfo)
for _, v := range networks {
networksMap[v.MAC] = v
}
for _, v := range networksMap {
uniqueNetworks = append(uniqueNetworks, v)
}
return uniqueNetworks, nil
}

View File

@ -2,6 +2,7 @@ package openstack
import (
"context"
"encoding/json"
"os"
"testing"
@ -124,3 +125,16 @@ func Test_GenerateVirtualMachine(t *testing.T) {
assert.NotEmpty(newVM.Spec.Template.Spec.Networks, "expected to find atleast 1 network as pod network should have been applied")
assert.NotEmpty(newVM.Spec.Template.Spec.Domain.Devices.Interfaces, "expected to find atleast 1 interface for pod-network")
}
func Test_generateNetworkInfo(t *testing.T) {
networkInfoByte := []byte(`{"private":[{"OS-EXT-IPS-MAC:mac_addr":"fa:16:3e:92:5f:45","OS-EXT-IPS:type":"fixed","addr":"fd5b:731d:94e1:0:f816:3eff:fe92:5f45","version":6},{"OS-EXT-IPS-MAC:mac_addr":"fa:16:3e:92:5f:45","OS-EXT-IPS:type":"fixed","addr":"10.0.0.38","version":4}],"shared":[{"OS-EXT-IPS-MAC:mac_addr":"fa:16:3e:ec:49:11","OS-EXT-IPS:type":"fixed","addr":"192.168.233.233","version":4}]}`)
var networkInfoMap map[string]interface{}
assert := require.New(t)
err := json.Unmarshal(networkInfoByte, &networkInfoMap)
assert.NoError(err, "expected no error while unmarshalling network info")
vmInterfaceDetails, err := generateNetworkInfo(networkInfoMap)
assert.NoError(err, "expected no error while generating network info")
assert.Len(vmInterfaceDetails, 2, "expected to find 2 interfaces only")
}