Skip to content

Commit

Permalink
Support reopen tap FD if something wrong to VM
Browse files Browse the repository at this point in the history
  • Loading branch information
keyingliu authored and Yingke Liu committed Feb 13, 2019
1 parent e128049 commit 2be8bcc
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 0 deletions.
4 changes: 4 additions & 0 deletions pkg/nettools/nettools.go
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,10 @@ func RecoverContainerSideNetwork(csn *network.ContainerSideNetwork, nsPath strin
bindDeviceToVFIO(devIdentifier)
} else {
ifaceType = network.InterfaceTypeTap
// It's OK if OpenTAP failed as the device is busy and used by running VM
if fo, err := OpenTAP(link.Attrs().Name); err == nil {
desc.Fo = fo
}
}
if desc.Type != ifaceType {
return fmt.Errorf("bad interface type for %q", desc.Name)
Expand Down
15 changes: 15 additions & 0 deletions pkg/tapmanager/fdserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ type FDSource interface {
// specified key. It's intended to be called after
// Virtlet restart.
Recover(key string, data []byte) error
// RetrieveFDs retrieves FDs in case the FD is null
RetrieveFDs(key string) ([]int, error)
// Stop stops any goroutines associated with FDSource
// but doesn't release the namespaces
Stop() error
Expand Down Expand Up @@ -162,6 +164,19 @@ func (s *FDServer) getFDs(key string) ([]int, error) {
if !found {
return nil, fmt.Errorf("bad fd key: %q", key)
}

var err error
if fds == nil {
// Run here means:
// first: the virtlet gets restarted and recoverNetworkNamespaces is called
// but tap fd is missing
// then: VM gets restarted for some reasons
fds, err = s.source.RetrieveFDs(key)
if err != nil {
return nil, err
}
s.fds[key] = fds
}
return fds, nil
}

Expand Down
39 changes: 39 additions & 0 deletions pkg/tapmanager/tapfdsource.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,45 @@ func (s *TapFDSource) Recover(key string, data []byte) error {
})
}

// RetrieveFDs retrieve the FDs
// It is only the case if VM exited but recover didn't populate the FDs
func (s *TapFDSource) RetrieveFDs(key string) ([]int, error) {
var podNet *podNetwork
var fds []int
func() {
s.Lock()
defer s.Unlock()
podNet = s.fdMap[key]
}()
if podNet == nil {
return nil, fmt.Errorf("bad key (%s) to retrieve FDs", key)
}

netNSPath := cni.PodNetNSPath(podNet.pnd.PodID)
vmNS, err := ns.GetNS(netNSPath)
if err != nil {
return nil, fmt.Errorf("failed to open network namespace at %q: %v", netNSPath, err)
}

if err := utils.CallInNetNSWithSysfsRemounted(vmNS, func(hostNS ns.NetNS) error {
allLinks, err := netlink.LinkList()
if err != nil {
return fmt.Errorf("error listing the links: %v", err)
}

return nettools.RecoverContainerSideNetwork(podNet.csn, netNSPath, allLinks, hostNS)
}); err != nil {
return nil, err
}

for _, ifDesc := range podNet.csn.Interfaces {
if ifDesc.Fo != nil {
fds = append(fds, int(ifDesc.Fo.Fd()))
}
}
return fds, nil
}

func (s *TapFDSource) setupNetNS(key string, pnd *PodNetworkDesc, initNet func(netNSPath string, allLinks []netlink.Link, hostNS ns.NetNS) (*network.ContainerSideNetwork, error)) error {
netNSPath := cni.PodNetNSPath(pnd.PodID)
vmNS, err := ns.GetNS(netNSPath)
Expand Down

0 comments on commit 2be8bcc

Please sign in to comment.