diff --git a/pkg/virt-launcher/virtwrap/network/dhcp/dhcp.go b/pkg/virt-launcher/virtwrap/network/dhcp/dhcp.go index 87068cafb432..22de3b877758 100644 --- a/pkg/virt-launcher/virtwrap/network/dhcp/dhcp.go +++ b/pkg/virt-launcher/virtwrap/network/dhcp/dhcp.go @@ -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") @@ -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 { diff --git a/pkg/virt-launcher/virtwrap/network/generated_mock_network.go b/pkg/virt-launcher/virtwrap/network/generated_mock_network.go index 208b8e4bcd64..d4416e2f35af 100644 --- a/pkg/virt-launcher/virtwrap/network/generated_mock_network.go +++ b/pkg/virt-launcher/virtwrap/network/generated_mock_network.go @@ -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 @@ -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) } diff --git a/pkg/virt-launcher/virtwrap/network/network.go b/pkg/virt-launcher/virtwrap/network/network.go index a977af18d095..1963efeba1e8 100644 --- a/pkg/virt-launcher/virtwrap/network/network.go +++ b/pkg/virt-launcher/virtwrap/network/network.go @@ -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{} @@ -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, @@ -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 { @@ -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 diff --git a/pkg/virt-launcher/virtwrap/network/network_test.go b/pkg/virt-launcher/virtwrap/network/network_test.go index f3b3abc760ce..9e16a7161e17 100644 --- a/pkg/virt-launcher/virtwrap/network/network_test.go +++ b/pkg/virt-launcher/virtwrap/network/network_test.go @@ -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(``) }) Context("on successful Network setup", func() { @@ -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(``) mockNetwork.EXPECT().LinkByName(podInterface).Return(dummy, nil) mockNetwork.EXPECT().AddrList(dummy, netlink.FAMILY_V4).Return(addrList, nil) @@ -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()) @@ -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()) + }) }) })