Skip to content

Commit

Permalink
feat: Add interface mac field (#35)
Browse files Browse the repository at this point in the history
  • Loading branch information
scuzhanglei authored Aug 25, 2022
1 parent bcce9ba commit 6284294
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 5 deletions.
14 changes: 9 additions & 5 deletions cmd/virt-prerunner/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ func buildVMConfig(ctx context.Context, vm *virtv1alpha1.VirtualMachine) (*cloud
vmConfig.Net = append(vmConfig.Net, &netConfig)
case iface.Masquerade != nil:
netConfig := cloudhypervisor.NetConfig{
Id: iface.Name,
Id: iface.Name,
Mac: iface.MAC,
}
if err := setupMasqueradeNetwork(linkName, iface.Masquerade.CIDR, &netConfig); err != nil {
return nil, fmt.Errorf("setup masquerade network: %s", err)
Expand Down Expand Up @@ -377,14 +378,17 @@ func setupMasqueradeNetwork(linkName string, cidr string, netConfig *cloudhyperv
}

tapName := fmt.Sprintf("tap-%s", linkName)
tap, err := createTap(bridge, tapName)
if err != nil {
if _, err := createTap(bridge, tapName); err != nil {
return fmt.Errorf("create tap: %s", err)
}
netConfig.Tap = tapName
netConfig.Mac = tap.Attrs().HardwareAddr.String()

if err := startDHCPServer(bridgeName, tap.Attrs().HardwareAddr, vmIPNet, bridgeIP); err != nil {
vmMAC, err := net.ParseMAC(netConfig.Mac)
if err != nil {
return fmt.Errorf("parse VM MAC: %s", err)
}

if err := startDHCPServer(bridgeName, vmMAC, vmIPNet, bridgeIP); err != nil {
return fmt.Errorf("start DHCP server: %s", err)
}
return nil
Expand Down
2 changes: 2 additions & 0 deletions deploy/crd/virt.virtink.smartx.com_virtualmachines.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,8 @@ spec:
properties:
bridge:
type: object
mac:
type: string
masquerade:
properties:
cidr:
Expand Down
1 change: 1 addition & 0 deletions pkg/apis/virt/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ type Disk struct {

type Interface struct {
Name string `json:"name"`
MAC string `json:"mac,omitempty"`
InterfaceBindingMethod `json:",inline"`
}

Expand Down
12 changes: 12 additions & 0 deletions pkg/controller/vm_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,11 +433,23 @@ func (r *VMReconciler) buildVMPod(ctx context.Context, vm *virtv1alpha1.VirtualM

var networks []netv1.NetworkSelectionElement
for i, network := range vm.Spec.Networks {
var iface *virtv1alpha1.Interface
for j := range vm.Spec.Instance.Interfaces {
if vm.Spec.Instance.Interfaces[j].Name == network.Name {
iface = &vm.Spec.Instance.Interfaces[j]
break
}
}
if iface == nil {
return nil, fmt.Errorf("interface not found for network: %s", network.Name)
}

switch {
case network.Multus != nil:
networks = append(networks, netv1.NetworkSelectionElement{
Name: network.Multus.NetworkName,
InterfaceRequest: fmt.Sprintf("net%d", i),
MacRequest: iface.MAC,
})

var nad netv1.NetworkAttachmentDefinition
Expand Down
30 changes: 30 additions & 0 deletions pkg/controller/vm_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package controller

import (
"context"
"crypto/rand"
"encoding/json"
"fmt"
"net"
Expand Down Expand Up @@ -79,6 +80,14 @@ func MutateVM(ctx context.Context, vm *virtv1alpha1.VirtualMachine, oldVM *virtv
}

for i := range vm.Spec.Instance.Interfaces {
if vm.Spec.Instance.Interfaces[i].MAC == "" {
mac, err := generateMAC()
if err != nil {
return fmt.Errorf("generate MAC: %s", err)
}
vm.Spec.Instance.Interfaces[i].MAC = mac.String()
}

if vm.Spec.Instance.Interfaces[i].Bridge == nil && vm.Spec.Instance.Interfaces[i].Masquerade == nil && vm.Spec.Instance.Interfaces[i].SRIOV == nil {
vm.Spec.Instance.Interfaces[i].InterfaceBindingMethod = virtv1alpha1.InterfaceBindingMethod{
Bridge: &virtv1alpha1.InterfaceBridge{},
Expand Down Expand Up @@ -323,10 +332,22 @@ func ValidateInterface(ctx context.Context, iface *virtv1alpha1.Interface, field
if iface.Name == "" {
errs = append(errs, field.Required(fieldPath.Child("name"), ""))
}
errs = append(errs, ValidateMAC(iface.MAC, fieldPath.Child("mac"))...)
errs = append(errs, ValidateInterfaceBindingMethod(ctx, &iface.InterfaceBindingMethod, fieldPath)...)
return errs
}

func ValidateMAC(mac string, fieldPath *field.Path) field.ErrorList {
var errs field.ErrorList
if mac == "" {
errs = append(errs, field.Required(fieldPath, ""))
}
if _, err := net.ParseMAC(mac); err != nil {
errs = append(errs, field.Invalid(fieldPath, mac, err.Error()))
}
return errs
}

func ValidateInterfaceBindingMethod(ctx context.Context, bindingMethod *virtv1alpha1.InterfaceBindingMethod, fieldPath *field.Path) field.ErrorList {
var errs field.ErrorList
if bindingMethod == nil {
Expand Down Expand Up @@ -619,3 +640,12 @@ func ValidateMultusNetworkSource(ctx context.Context, source *virtv1alpha1.Multu
}
return errs
}

func generateMAC() (net.HardwareAddr, error) {
prefix := []byte{0x52, 0x54, 0x00}
suffix := make([]byte, 3)
if _, err := rand.Read(suffix); err != nil {
return nil, fmt.Errorf("rand: %s", err)
}
return net.HardwareAddr(append(prefix, suffix...)), nil
}
22 changes: 22 additions & 0 deletions pkg/controller/vm_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func TestValidateVM(t *testing.T) {
InterfaceBindingMethod: virtv1alpha1.InterfaceBindingMethod{
Bridge: &virtv1alpha1.InterfaceBridge{},
},
MAC: "c6:1c:ba:0a:45:88",
}},
},
Volumes: []virtv1alpha1.Volume{{
Expand Down Expand Up @@ -205,6 +206,20 @@ func TestValidateVM(t *testing.T) {
return vm
}(),
invalidFields: []string{"spec.instance.interfaces[0].name"},
}, {
vm: func() *virtv1alpha1.VirtualMachine {
vm := validVM.DeepCopy()
vm.Spec.Instance.Interfaces[0].MAC = ""
return vm
}(),
invalidFields: []string{"spec.instance.interfaces[0].mac"},
}, {
vm: func() *virtv1alpha1.VirtualMachine {
vm := validVM.DeepCopy()
vm.Spec.Instance.Interfaces[0].MAC = "01:1c:ba:0a:45:8"
return vm
}(),
invalidFields: []string{"spec.instance.interfaces[0].mac"},
}, {
vm: func() *virtv1alpha1.VirtualMachine {
vm := validVM.DeepCopy()
Expand Down Expand Up @@ -339,6 +354,13 @@ func TestMutateVM(t *testing.T) {
assert: func(vm *virtv1alpha1.VirtualMachine) {
assert.Equal(t, "1Gi", vm.Spec.Instance.Memory.Size.String())
},
}, {
vm: func() *virtv1alpha1.VirtualMachine {
return oldVM.DeepCopy()
}(),
assert: func(vm *virtv1alpha1.VirtualMachine) {
assert.NotEmpty(t, vm.Spec.Instance.Interfaces[0].MAC)
},
}, {
vm: func() *virtv1alpha1.VirtualMachine {
return oldVM.DeepCopy()
Expand Down

0 comments on commit 6284294

Please sign in to comment.