Skip to content

Commit

Permalink
Handle dhcp server exceptions in virt-launcher
Browse files Browse the repository at this point in the history
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
  • Loading branch information
vladikr committed Feb 6, 2018
1 parent b7af089 commit b6e3cd3
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 42 deletions.
7 changes: 3 additions & 4 deletions pkg/virt-launcher/virtwrap/network/dhcp/dhcp.go
Expand Up @@ -39,7 +39,7 @@ func SingleClientDHCPServer(
serverIface string,
serverIP net.IP,
routerIP net.IP,
dnsIP net.IP) error {
dnsIP net.IP) {

log.Log.Info("Starting SingleClientDHCPServer")

Expand All @@ -57,14 +57,13 @@ func SingleClientDHCPServer(

l, err := dhcpConn.NewUDP4BoundListener(serverIface, ":67")
if err != nil {
return err
panic(err)
}
defer l.Close()
err = dhcp.Serve(l, handler)
if err != nil {
return err
panic(err)
}
return nil
}

type DHCPHandler struct {
Expand Down
10 changes: 6 additions & 4 deletions pkg/virt-launcher/virtwrap/network/generated_mock_network.go
Expand Up @@ -8,6 +8,8 @@ import (

gomock "github.com/golang/mock/gomock"
netlink "github.com/vishvananda/netlink"

v1 "kubevirt.io/kubevirt/pkg/api/v1"
)

// Mock of NetworkHandler interface
Expand Down Expand Up @@ -147,10 +149,10 @@ func (_mr *_MockNetworkHandlerRecorder) GetMacDetails(arg0 interface{}) *gomock.
return _mr.mock.ctrl.RecordCall(_mr.mock, "GetMacDetails", arg0)
}

func (_m *MockNetworkHandler) StartDHCP(nic *VIF, serverAddr *netlink.Addr) {
_m.ctrl.Call(_m, "StartDHCP", nic, serverAddr)
func (_m *MockNetworkHandler) StartDHCP(vm *v1.VirtualMachine, nic *VIF, serverAddr *netlink.Addr) {
_m.ctrl.Call(_m, "StartDHCP", vm, nic, serverAddr)
}

func (_mr *_MockNetworkHandlerRecorder) StartDHCP(arg0, arg1 interface{}) *gomock.Call {
return _mr.mock.ctrl.RecordCall(_mr.mock, "StartDHCP", arg0, arg1)
func (_mr *_MockNetworkHandlerRecorder) StartDHCP(arg0, arg1, arg2 interface{}) *gomock.Call {
return _mr.mock.ctrl.RecordCall(_mr.mock, "StartDHCP", arg0, arg1, arg2)
}
19 changes: 13 additions & 6 deletions pkg/virt-launcher/virtwrap/network/network.go
Expand Up @@ -66,7 +66,7 @@ type NetworkHandler interface {
ParseAddr(s string) (*netlink.Addr, error)
ChangeMacAddr(iface string) (net.HardwareAddr, error)
GetMacDetails(iface string) (net.HardwareAddr, error)
StartDHCP(nic *VIF, serverAddr *netlink.Addr)
StartDHCP(vm *v1.VirtualMachine, nic *VIF, serverAddr *netlink.Addr)
}

type NetworkUtilsHandler struct{}
Expand Down Expand Up @@ -136,10 +136,16 @@ func (h *NetworkUtilsHandler) ChangeMacAddr(iface string) (net.HardwareAddr, err
return currentMac, nil
}

func (h *NetworkUtilsHandler) StartDHCP(nic *VIF, serverAddr *netlink.Addr) {
// Start DHCP
go func() {
dhcp.SingleClientDHCPServer(
func (h *NetworkUtilsHandler) StartDHCP(vm *v1.VirtualMachine, nic *VIF, serverAddr *netlink.Addr) {
func() {
defer func() {
if err := recover(); err != nil && !vm.IsFinal() {
log.Log.Errorf("failed to run DHCP: %v", err)
panic("err")
}
}()

DHCPServer(
nic.MAC,
nic.IP.IP,
nic.IP.Mask,
Expand All @@ -153,6 +159,7 @@ func (h *NetworkUtilsHandler) StartDHCP(nic *VIF, serverAddr *netlink.Addr) {

// Allow mocking for tests
var SetupPodNetwork = SetupDefaultPodNetwork
var DHCPServer = dhcp.SingleClientDHCPServer

func initHandler() {
if Handler == nil {
Expand Down Expand Up @@ -273,7 +280,7 @@ func SetupDefaultPodNetwork(vm *v1.VirtualMachine, domain *api.Domain) error {
}

// Start DHCP Server
Handler.StartDHCP(nic, fakeaddr)
go Handler.StartDHCP(vm, nic, fakeaddr)

if err := plugNetworkDevice(vm, domain, nic); err != nil {
return err
Expand Down
103 changes: 75 additions & 28 deletions pkg/virt-launcher/virtwrap/network/network_test.go
Expand Up @@ -36,12 +36,46 @@ import (
var _ = Describe("Network", func() {
var mockNetwork *MockNetworkHandler
var ctrl *gomock.Controller

var dummy *netlink.Dummy
var addrList []netlink.Addr
var routeList []netlink.Route
var routeAddr netlink.Route
var fakeMac net.HardwareAddr
var fakeAddr netlink.Addr
var updateFakeMac net.HardwareAddr
var macvlanTest *netlink.Macvlan
var macvlanAddr *netlink.Addr
var testNic *VIF
var interfaceXml []byte
log.Log.SetIOWriter(GinkgoWriter)

BeforeEach(func() {
ctrl = gomock.NewController(GinkgoT())
mockNetwork = NewMockNetworkHandler(ctrl)
testMac := "12:34:56:78:9A:BC"
updateTestMac := "AF:B3:1F:78:2A:CA"
dummy = &netlink.Dummy{LinkAttrs: netlink.LinkAttrs{Index: 1}}
address := &net.IPNet{IP: net.IPv4(10, 35, 0, 6), Mask: net.CIDRMask(24, 32)}
gw := net.IPv4(10, 35, 0, 1)
fakeMac, _ = net.ParseMAC(testMac)
updateFakeMac, _ = net.ParseMAC(updateTestMac)
fakeAddr = netlink.Addr{IPNet: address}
addrList = []netlink.Addr{fakeAddr}
routeAddr = netlink.Route{Gw: gw}
routeList = []netlink.Route{routeAddr}
macvlanTest = &netlink.Macvlan{
LinkAttrs: netlink.LinkAttrs{
Name: macVlanIfaceName,
ParentIndex: 1,
},
Mode: netlink.MACVLAN_MODE_BRIDGE,
}
macvlanAddr, _ = netlink.ParseAddr(macVlanFakeIP)
testNic = &VIF{Name: podInterface,
IP: fakeAddr,
MAC: fakeMac,
Gateway: gw}
interfaceXml = []byte(`<Interface type="direct" trustGuestRxFilters="yes"><source dev="eth0" mode="bridge"></source><model type="virtio"></model><mac address="12:34:56:78:9a:bc"></mac></Interface>`)
})

Context("on successful Network setup", func() {
Expand All @@ -54,30 +88,6 @@ var _ = Describe("Network", func() {
}

api.SetObjectDefaults_Domain(domain)
testMac := "12:34:56:78:9A:BC"
updateTestMac := "AF:B3:1F:78:2A:CA"
dummy := &netlink.Dummy{LinkAttrs: netlink.LinkAttrs{Index: 1}}
address := &net.IPNet{IP: net.IPv4(10, 35, 0, 6), Mask: net.CIDRMask(24, 32)}
gw := net.IPv4(10, 35, 0, 1)
fakeMac, _ := net.ParseMAC(testMac)
updateFakeMac, _ := net.ParseMAC(updateTestMac)
fakeAddr := netlink.Addr{IPNet: address}
addrList := []netlink.Addr{fakeAddr}
routeAddr := netlink.Route{Gw: gw}
routeList := []netlink.Route{routeAddr}
macvlanTest := &netlink.Macvlan{
LinkAttrs: netlink.LinkAttrs{
Name: macVlanIfaceName,
ParentIndex: 1,
},
Mode: netlink.MACVLAN_MODE_BRIDGE,
}
macvlanAddr, _ := netlink.ParseAddr(macVlanFakeIP)
testNic := &VIF{Name: podInterface,
IP: fakeAddr,
MAC: fakeMac,
Gateway: gw}
var interfaceXml = []byte(`<Interface type="direct" trustGuestRxFilters="yes"><source dev="eth0" mode="bridge"></source><model type="virtio"></model><mac address="12:34:56:78:9a:bc"></mac></Interface>`)

mockNetwork.EXPECT().LinkByName(podInterface).Return(dummy, nil)
mockNetwork.EXPECT().AddrList(dummy, netlink.FAMILY_V4).Return(addrList, nil)
Expand All @@ -92,7 +102,7 @@ var _ = Describe("Network", func() {
mockNetwork.EXPECT().LinkSetUp(macvlanTest).Return(nil)
mockNetwork.EXPECT().ParseAddr(macVlanFakeIP).Return(macvlanAddr, nil)
mockNetwork.EXPECT().AddrAdd(macvlanTest, macvlanAddr).Return(nil)
mockNetwork.EXPECT().StartDHCP(testNic, macvlanAddr)
mockNetwork.EXPECT().StartDHCP(vm, testNic, macvlanAddr)

err := SetupPodNetwork(vm, domain)
Expect(err).To(BeNil())
Expand All @@ -108,8 +118,45 @@ var _ = Describe("Network", func() {
Expect(ifaceStaus.MAC).To(Equal(testNic.MAC.String()))
})
})
Context("on DHCP execution", func() {
It("should panic if vm is running", func() {
netInterface := &NetworkUtilsHandler{}
dhcpTestFunc := func() {
vm := &v1.VirtualMachine{
Status: v1.VirtualMachineStatus{Phase: v1.Running},
}

AfterEach(func() {
ctrl.Finish()
DHCPServer = func(clientMAC net.HardwareAddr,
clientIP net.IP,
clientMask net.IPMask,
serverIface string,
serverIP net.IP,
routerIP net.IP,
dnsIP net.IP) {
panic("DHCP exception: Running")
}
netInterface.StartDHCP(vm, testNic, &fakeAddr)
}
Expect(dhcpTestFunc).To(Panic())
})
It("should not panic if vm is shutting down", func() {
netInterface := &NetworkUtilsHandler{}
dhcpTestFunc := func() {
vm := &v1.VirtualMachine{
Status: v1.VirtualMachineStatus{Phase: v1.Succeeded},
}
DHCPServer = func(clientMAC net.HardwareAddr,
clientIP net.IP,
clientMask net.IPMask,
serverIface string,
serverIP net.IP,
routerIP net.IP,
dnsIP net.IP) {
panic("DHCP exception: Succeeded")
}
netInterface.StartDHCP(vm, testNic, &fakeAddr)
}
Expect(dhcpTestFunc).ShouldNot(Panic())
})
})
})

0 comments on commit b6e3cd3

Please sign in to comment.