Skip to content

Commit

Permalink
Merge pull request #9737 from AlonaKaplan/phase1_cleanup
Browse files Browse the repository at this point in the history
hotunplug - reverse phase1
  • Loading branch information
kubevirt-bot committed Jun 16, 2023
2 parents aa40ad0 + b574ebd commit d250711
Show file tree
Hide file tree
Showing 23 changed files with 982 additions and 203 deletions.
12 changes: 12 additions & 0 deletions pkg/network/cache/dhcpconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ func WriteDHCPInterfaceCache(c cacheCreator, pid, ifaceName string, dhcpConfig *
return dhcpCache.Write(dhcpConfig)
}

func DeleteDHCPInterfaceCache(c cacheCreator, pid, ifaceName string) error {
dhcpCache, err := NewDHCPInterfaceCache(c, pid).IfaceEntry(ifaceName)
if err != nil {
return err
}
return dhcpCache.Delete()
}

func NewDHCPInterfaceCache(creator cacheCreator, pid string) DHCPInterfaceCache {
podRootFilesystemPath := fmt.Sprintf("/proc/%s/root", pid)
return DHCPInterfaceCache{creator.New(filepath.Join(podRootFilesystemPath, util.VirtPrivateDir))}
Expand All @@ -75,6 +83,10 @@ func (d DHCPInterfaceCache) Write(dhcpConfig *DHCPConfig) error {
return d.cache.Write(dhcpConfig)
}

func (d DHCPInterfaceCache) Delete() error {
return d.cache.Delete()
}

type DHCPConfig struct {
Name string
IP netlink.Addr
Expand Down
12 changes: 12 additions & 0 deletions pkg/network/cache/domaininterface.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ func NewDomainInterfaceCache(creator cacheCreator, pid string) DomainInterfaceCa
return DomainInterfaceCache{creator.New(filepath.Join(podRootFilesystemPath, util.VirtPrivateDir))}
}

func DeleteDomainInterfaceCache(c cacheCreator, pid, ifaceName string) error {
domainCache, err := NewDomainInterfaceCache(c, pid).IfaceEntry(ifaceName)
if err != nil {
return err
}
return domainCache.Delete()
}

func (d DomainInterfaceCache) IfaceEntry(ifaceName string) (DomainInterfaceCache, error) {
const domainIfaceCacheFileFormat = "interface-cache-%s.json"
cacheFileName := fmt.Sprintf(domainIfaceCacheFileFormat, ifaceName)
Expand All @@ -72,3 +80,7 @@ func (d DomainInterfaceCache) Read() (*api.Interface, error) {
func (d DomainInterfaceCache) Write(domainInterface *api.Interface) error {
return d.cache.Write(domainInterface)
}

func (d DomainInterfaceCache) Delete() error {
return d.cache.Delete()
}
13 changes: 13 additions & 0 deletions pkg/network/cache/domaininterface_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,17 @@ var _ = Describe("DomainInterfaceCache", func() {
Expect(err).NotTo(HaveOccurred())
Expect(newObj).To(Equal(obj))
})

It("should delete pod interface from the cache", func() {
domainIfaceCache, err := cache.NewDomainInterfaceCache(&cacheCreator, "123").IfaceEntry("abc")
Expect(err).NotTo(HaveOccurred())
Expect(domainIfaceCache.Write(obj)).To(Succeed())
newObj, err := domainIfaceCache.Read()
Expect(err).NotTo(HaveOccurred())
Expect(newObj).To(Equal(obj))

Expect(domainIfaceCache.Delete()).To(Succeed())
_, err = domainIfaceCache.Read()
Expect(err).To(MatchError(os.ErrNotExist))
})
})
4 changes: 4 additions & 0 deletions pkg/network/driver/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ type NetworkHandler interface {
LinkSetUp(link netlink.Link) error
LinkSetName(link netlink.Link, name string) error
LinkAdd(link netlink.Link) error
LinkDel(link netlink.Link) error
LinkSetLearningOff(link netlink.Link) error
ParseAddr(s string) (*netlink.Addr, error)
LinkSetHardwareAddr(link netlink.Link, hwaddr net.HardwareAddr) error
Expand Down Expand Up @@ -127,6 +128,9 @@ func (h *NetworkUtilsHandler) LinkSetName(link netlink.Link, name string) error
func (h *NetworkUtilsHandler) LinkAdd(link netlink.Link) error {
return netlink.LinkAdd(link)
}
func (h *NetworkUtilsHandler) LinkDel(link netlink.Link) error {
return netlink.LinkDel(link)
}
func (h *NetworkUtilsHandler) LinkSetLearningOff(link netlink.Link) error {
return netlink.LinkSetLearning(link, false)
}
Expand Down
10 changes: 10 additions & 0 deletions pkg/network/driver/generated_mock_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,16 @@ func (_mr *_MockNetworkHandlerRecorder) LinkAdd(arg0 interface{}) *gomock.Call {
return _mr.mock.ctrl.RecordCall(_mr.mock, "LinkAdd", arg0)
}

func (_m *MockNetworkHandler) LinkDel(link netlink.Link) error {
ret := _m.ctrl.Call(_m, "LinkDel", link)
ret0, _ := ret[0].(error)
return ret0
}

func (_mr *_MockNetworkHandlerRecorder) LinkDel(arg0 interface{}) *gomock.Call {
return _mr.mock.ctrl.RecordCall(_mr.mock, "LinkDel", arg0)
}

func (_m *MockNetworkHandler) LinkSetLearningOff(link netlink.Link) error {
ret := _m.ctrl.Call(_m, "LinkSetLearningOff", link)
ret0, _ := ret[0].(error)
Expand Down
10 changes: 9 additions & 1 deletion pkg/network/link/discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package link

import (
"errors"
"fmt"
"strings"

Expand All @@ -34,6 +35,7 @@ import (
// DiscoverByNetwork return the pod interface link of the given network name.
// If link not found, it will try to get the link using the pod interface's ordinal name (net1, net2,...)
// based on the subject network position in the given networks slice.
// If no link is found, a nil link will be returned.
func DiscoverByNetwork(handler driver.NetworkHandler, networks []v1.Network, subjectNetwork v1.Network) (netlink.Link, error) {
ifaceNames, err := networkInterfaceNames(networks, subjectNetwork)
if err != nil {
Expand All @@ -60,7 +62,13 @@ func linkByNames(handler driver.NetworkHandler, names []string) (netlink.Link, e
if err == nil {
return link, nil
}
errs = append(errs, fmt.Sprintf("could not get link with name %q: %v", name, err))
var linkNotFoundErr netlink.LinkNotFoundError
if !errors.As(err, &linkNotFoundErr) {
errs = append(errs, fmt.Sprintf("could not get link with name %q: %v", name, err))
}
}
if len(errs) == 0 {
return nil, nil
}
return nil, fmt.Errorf(strings.Join(errs, ", "))
}
5 changes: 4 additions & 1 deletion pkg/network/setup/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ go_library(
"netstat.go",
"network.go",
"podnic.go",
"unpluggedpodnic.go",
],
importpath = "kubevirt.io/kubevirt/pkg/network/setup",
visibility = ["//visibility:public"],
Expand All @@ -29,7 +30,9 @@ go_library(
"//staging/src/kubevirt.io/client-go/log:go_default_library",
"//staging/src/kubevirt.io/client-go/precond:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/vishvananda/netlink:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
],
)

Expand All @@ -43,6 +46,7 @@ go_test(
"network_suite_test.go",
"network_test.go",
"podnic_test.go",
"unpluggedpodnic_test.go",
],
embed = [":go_default_library"],
deps = [
Expand All @@ -56,7 +60,6 @@ go_test(
"//pkg/network/sriov:go_default_library",
"//pkg/network/vmispec:go_default_library",
"//pkg/os/fs:go_default_library",
"//pkg/pointer:go_default_library",
"//pkg/virt-launcher/virtwrap/api:go_default_library",
"//staging/src/kubevirt.io/api/core/v1:go_default_library",
"//staging/src/kubevirt.io/client-go/api:go_default_library",
Expand Down
62 changes: 56 additions & 6 deletions pkg/network/setup/configstate.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,29 @@ package network
import (
"fmt"

v1 "kubevirt.io/api/core/v1"

"k8s.io/apimachinery/pkg/util/errors"

"kubevirt.io/client-go/log"

"kubevirt.io/kubevirt/pkg/network/cache"
neterrors "kubevirt.io/kubevirt/pkg/network/errors"
)

type configStateCacheReaderWriter interface {
type configStateCacheRUD interface {
Read(networkName string) (cache.PodIfaceState, error)
Write(networkName string, state cache.PodIfaceState) error
Delete(networkName string) error
}

type ConfigState struct {
cache configStateCacheReaderWriter
cache configStateCacheRUD
ns NSExecutor
}

func NewConfigState(configStateCache configStateCacheReaderWriter, ns NSExecutor) ConfigState {
return ConfigState{configStateCache, ns}
func NewConfigState(configStateCache configStateCacheRUD, ns NSExecutor) ConfigState {
return ConfigState{cache: configStateCache, ns: ns}
}

// Run passes through the state machine flow, executing the following steps:
Expand All @@ -49,7 +54,7 @@ func NewConfigState(configStateCache configStateCacheReaderWriter, ns NSExecutor
//
// The discovery step can be executed repeatedly with no limitation.
// The configuration step is allowed to run only once. Any attempt to run it again will cause a critical error.
func (c ConfigState) Run(nics []podNIC, preRunFunc func([]podNIC) ([]podNIC, error), discoverFunc func(*podNIC) error, configFunc func(*podNIC) error) error {
func (c *ConfigState) Run(nics []podNIC, preRunFunc func([]podNIC) ([]podNIC, error), discoverFunc func(*podNIC) error, configFunc func(*podNIC) error) error {
var pendingNICs []podNIC
for _, nic := range nics {
state, err := c.cache.Read(nic.vmiSpecNetwork.Name)
Expand Down Expand Up @@ -83,7 +88,7 @@ func (c ConfigState) Run(nics []podNIC, preRunFunc func([]podNIC) ([]podNIC, err
return err
}

func (c ConfigState) plug(nics []podNIC, discoverFunc func(*podNIC) error, configFunc func(*podNIC) error) error {
func (c *ConfigState) plug(nics []podNIC, discoverFunc func(*podNIC) error, configFunc func(*podNIC) error) error {
for i := range nics {
if ferr := discoverFunc(&nics[i]); ferr != nil {
return ferr
Expand Down Expand Up @@ -114,3 +119,48 @@ func (c ConfigState) plug(nics []podNIC, discoverFunc func(*podNIC) error, confi
}
return nil
}

func (c *ConfigState) Unplug(networks []v1.Network, filterFunc func([]v1.Network) ([]string, error), cleanupFunc func(string) error) error {
var nonPendingNetworks []v1.Network
var err error
if nonPendingNetworks, err = c.nonPendingNetworks(networks); err != nil {
return err
}

if len(nonPendingNetworks) == 0 {
return nil
}
err = c.ns.Do(func() error {
networksToUnplug, doErr := filterFunc(nonPendingNetworks)
if doErr != nil {
return doErr
}

var cleanupErrors []error
for _, net := range networksToUnplug {
if cleanupErr := cleanupFunc(net); cleanupErr != nil {
cleanupErrors = append(cleanupErrors, cleanupErr)
} else if cleanupErr := c.cache.Delete(net); cleanupErr != nil {
cleanupErrors = append(cleanupErrors, cleanupErr)
}
}
return errors.NewAggregate(cleanupErrors)
})
return err
}

func (c *ConfigState) nonPendingNetworks(networks []v1.Network) ([]v1.Network, error) {
var nonPendingNetworks []v1.Network

for _, net := range networks {

state, err := c.cache.Read(net.Name)
if err != nil {
return nil, err
}
if state != cache.PodIfaceNetworkPreparationPending {
nonPendingNetworks = append(nonPendingNetworks, net)
}
}
return nonPendingNetworks, nil
}

0 comments on commit d250711

Please sign in to comment.