From b7b5b6f8e3072530f4c3fc07e5960e54c90729b5 Mon Sep 17 00:00:00 2001 From: baude Date: Thu, 29 Oct 2020 15:54:33 -0500 Subject: network aliases for container creation podman can now support adding network aliases when running containers (--network-alias). It requires an updated dnsname plugin as well as an updated ocicni to work properly. Signed-off-by: baude --- .../github.com/cri-o/ocicni/pkg/ocicni/ocicni.go | 93 ++++++++++------------ vendor/github.com/cri-o/ocicni/pkg/ocicni/types.go | 18 ++++- .../cri-o/ocicni/pkg/ocicni/util_linux.go | 79 ++++++++++++++++++ .../cri-o/ocicni/pkg/ocicni/util_unsupported.go | 19 ++++- 4 files changed, 154 insertions(+), 55 deletions(-) (limited to 'vendor/github.com/cri-o') diff --git a/vendor/github.com/cri-o/ocicni/pkg/ocicni/ocicni.go b/vendor/github.com/cri-o/ocicni/pkg/ocicni/ocicni.go index a8e2fbfa8..ee09adc8d 100644 --- a/vendor/github.com/cri-o/ocicni/pkg/ocicni/ocicni.go +++ b/vendor/github.com/cri-o/ocicni/pkg/ocicni/ocicni.go @@ -24,7 +24,6 @@ import ( type cniNetworkPlugin struct { cniConfig *libcni.CNIConfig - loNetwork *cniNetwork sync.RWMutex defaultNetName netName @@ -217,7 +216,6 @@ func initCNI(exec cniinvoke.Exec, cacheDir, defaultNetName string, confDir strin changeable: defaultNetName == "", }, networks: make(map[string]*cniNetwork), - loNetwork: getLoNetwork(), confDir: confDir, binDirs: binDirs, shutdownChan: make(chan struct{}), @@ -335,31 +333,9 @@ func loadNetworks(confDir string, cni *libcni.CNIConfig) (map[string]*cniNetwork } const ( - loIfname string = "lo" - loNetname string = "cni-loopback" + loIfname string = "lo" ) -func getLoNetwork() *cniNetwork { - loConfig, err := libcni.ConfListFromBytes([]byte(fmt.Sprintf(`{ - "cniVersion": "0.3.1", - "name": "%s", - "plugins": [{ - "type": "loopback" - }] -}`, loNetname))) - if err != nil { - // The hardcoded config above should always be valid and unit tests will - // catch this - panic(err) - } - loNetwork := &cniNetwork{ - name: loIfname, - config: loConfig, - } - - return loNetwork -} - func (plugin *cniNetworkPlugin) syncNetworkConfig() error { networks, defaultNetName, err := loadNetworks(plugin.confDir, plugin.cniConfig) if err != nil { @@ -525,16 +501,11 @@ func (plugin *cniNetworkPlugin) forEachNetwork(podNetwork *PodNetwork, fromCache return nil } -func buildLoopbackRuntimeConf(cacheDir string, podNetwork *PodNetwork) *libcni.RuntimeConf { - return &libcni.RuntimeConf{ - ContainerID: podNetwork.ID, - NetNS: podNetwork.NetNS, - CacheDir: cacheDir, - IfName: loIfname, - } +func (plugin *cniNetworkPlugin) SetUpPod(podNetwork PodNetwork) ([]NetResult, error) { + return plugin.SetUpPodWithContext(context.Background(), podNetwork) } -func (plugin *cniNetworkPlugin) SetUpPod(podNetwork PodNetwork) ([]NetResult, error) { +func (plugin *cniNetworkPlugin) SetUpPodWithContext(ctx context.Context, podNetwork PodNetwork) ([]NetResult, error) { if err := plugin.networksAvailable(&podNetwork); err != nil { return nil, err } @@ -542,15 +513,15 @@ func (plugin *cniNetworkPlugin) SetUpPod(podNetwork PodNetwork) ([]NetResult, er plugin.podLock(podNetwork).Lock() defer plugin.podUnlock(podNetwork) - loRt := buildLoopbackRuntimeConf(plugin.cacheDir, &podNetwork) - if _, err := plugin.loNetwork.addToNetwork(loRt, plugin.cniConfig); err != nil { - logrus.Errorf("Error while adding to cni lo network: %s", err) + // Set up loopback interface + if err := bringUpLoopback(podNetwork.NetNS); err != nil { + logrus.Errorf(err.Error()) return nil, err } results := make([]NetResult, 0) if err := plugin.forEachNetwork(&podNetwork, false, func(network *cniNetwork, podNetwork *PodNetwork, rt *libcni.RuntimeConf) error { - result, err := network.addToNetwork(rt, plugin.cniConfig) + result, err := network.addToNetwork(ctx, rt, plugin.cniConfig) if err != nil { logrus.Errorf("Error while adding pod to CNI network %q: %s", network.name, err) return err @@ -622,7 +593,7 @@ func (plugin *cniNetworkPlugin) getCachedNetworkInfo(containerID string) ([]NetA continue } // Ignore the loopback interface; it's handled separately - if cachedInfo.IfName == loIfname && cachedInfo.NetName == loNetname { + if cachedInfo.IfName == loIfname && cachedInfo.NetName == "cni-loopback" { continue } if cachedInfo.IfName == "" || cachedInfo.NetName == "" { @@ -641,6 +612,10 @@ func (plugin *cniNetworkPlugin) getCachedNetworkInfo(containerID string) ([]NetA // TearDownPod tears down pod networks. Prefers cached pod attachment information // but falls back to given network attachment information. func (plugin *cniNetworkPlugin) TearDownPod(podNetwork PodNetwork) error { + return plugin.TearDownPodWithContext(context.Background(), podNetwork) +} + +func (plugin *cniNetworkPlugin) TearDownPodWithContext(ctx context.Context, podNetwork PodNetwork) error { if len(podNetwork.Networks) == 0 { attachments, err := plugin.getCachedNetworkInfo(podNetwork.ID) if err == nil && len(attachments) > 0 { @@ -652,17 +627,16 @@ func (plugin *cniNetworkPlugin) TearDownPod(podNetwork PodNetwork) error { return err } - loRt := buildLoopbackRuntimeConf(plugin.cacheDir, &podNetwork) - if err := plugin.loNetwork.deleteFromNetwork(loRt, plugin.cniConfig); err != nil { - logrus.Errorf("Error while removing pod from CNI lo network: %v", err) - // Loopback teardown errors are not fatal - } - plugin.podLock(podNetwork).Lock() defer plugin.podUnlock(podNetwork) + if err := tearDownLoopback(podNetwork.NetNS); err != nil { + // ignore error + logrus.Errorf("Ignoring error tearing down loopback interface: %v", err) + } + return plugin.forEachNetwork(&podNetwork, true, func(network *cniNetwork, podNetwork *PodNetwork, rt *libcni.RuntimeConf) error { - if err := network.deleteFromNetwork(rt, plugin.cniConfig); err != nil { + if err := network.deleteFromNetwork(ctx, rt, plugin.cniConfig); err != nil { logrus.Errorf("Error while removing pod from CNI network %q: %s", network.name, err) return err } @@ -673,12 +647,23 @@ func (plugin *cniNetworkPlugin) TearDownPod(podNetwork PodNetwork) error { // GetPodNetworkStatus returns IP addressing and interface details for all // networks attached to the pod. func (plugin *cniNetworkPlugin) GetPodNetworkStatus(podNetwork PodNetwork) ([]NetResult, error) { + return plugin.GetPodNetworkStatusWithContext(context.Background(), podNetwork) +} + +// GetPodNetworkStatusWithContext returns IP addressing and interface details for all +// networks attached to the pod. +func (plugin *cniNetworkPlugin) GetPodNetworkStatusWithContext(ctx context.Context, podNetwork PodNetwork) ([]NetResult, error) { plugin.podLock(podNetwork).Lock() defer plugin.podUnlock(podNetwork) + if err := checkLoopback(podNetwork.NetNS); err != nil { + logrus.Errorf(err.Error()) + return nil, err + } + results := make([]NetResult, 0) if err := plugin.forEachNetwork(&podNetwork, true, func(network *cniNetwork, podNetwork *PodNetwork, rt *libcni.RuntimeConf) error { - result, err := network.checkNetwork(rt, plugin.cniConfig, plugin.nsManager, podNetwork.NetNS) + result, err := network.checkNetwork(ctx, rt, plugin.cniConfig, plugin.nsManager, podNetwork.NetNS) if err != nil { logrus.Errorf("Error while checking pod to CNI network %q: %s", network.name, err) return err @@ -700,9 +685,9 @@ func (plugin *cniNetworkPlugin) GetPodNetworkStatus(podNetwork PodNetwork) ([]Ne return results, nil } -func (network *cniNetwork) addToNetwork(rt *libcni.RuntimeConf, cni *libcni.CNIConfig) (cnitypes.Result, error) { +func (network *cniNetwork) addToNetwork(ctx context.Context, rt *libcni.RuntimeConf, cni *libcni.CNIConfig) (cnitypes.Result, error) { logrus.Infof("About to add CNI network %s (type=%v)", network.name, network.config.Plugins[0].Network.Type) - res, err := cni.AddNetworkList(context.Background(), network.config, rt) + res, err := cni.AddNetworkList(ctx, network.config, rt) if err != nil { logrus.Errorf("Error adding network: %v", err) return nil, err @@ -711,7 +696,7 @@ func (network *cniNetwork) addToNetwork(rt *libcni.RuntimeConf, cni *libcni.CNIC return res, nil } -func (network *cniNetwork) checkNetwork(rt *libcni.RuntimeConf, cni *libcni.CNIConfig, nsManager *nsManager, netns string) (cnitypes.Result, error) { +func (network *cniNetwork) checkNetwork(ctx context.Context, rt *libcni.RuntimeConf, cni *libcni.CNIConfig, nsManager *nsManager, netns string) (cnitypes.Result, error) { logrus.Infof("About to check CNI network %s (type=%v)", network.name, network.config.Plugins[0].Network.Type) gtet, err := cniversion.GreaterThanOrEqualTo(network.config.CNIVersion, "0.4.0") @@ -723,7 +708,7 @@ func (network *cniNetwork) checkNetwork(rt *libcni.RuntimeConf, cni *libcni.CNIC // When CNIVersion supports Check, use it. Otherwise fall back on what was done initially. if gtet { - err = cni.CheckNetworkList(context.Background(), network.config, rt) + err = cni.CheckNetworkList(ctx, network.config, rt) logrus.Infof("Checking CNI network %s (config version=%v)", network.name, network.config.CNIVersion) if err != nil { logrus.Errorf("Error checking network: %v", err) @@ -783,9 +768,9 @@ func (network *cniNetwork) checkNetwork(rt *libcni.RuntimeConf, cni *libcni.CNIC return converted, nil } -func (network *cniNetwork) deleteFromNetwork(rt *libcni.RuntimeConf, cni *libcni.CNIConfig) error { +func (network *cniNetwork) deleteFromNetwork(ctx context.Context, rt *libcni.RuntimeConf, cni *libcni.CNIConfig) error { logrus.Infof("About to del CNI network %s (type=%v)", network.name, network.config.Plugins[0].Network.Type) - if err := cni.DelNetworkList(context.Background(), network.config, rt); err != nil { + if err := cni.DelNetworkList(ctx, network.config, rt); err != nil { logrus.Errorf("Error deleting network: %v", err) return err } @@ -848,6 +833,10 @@ func buildCNIRuntimeConf(cacheDir string, podNetwork *PodNetwork, ifName string, rt.CapabilityArgs["ipRanges"] = runtimeConfig.IpRanges } + // Set Aliases in Capabilities + if len(podNetwork.Aliases) > 0 { + rt.CapabilityArgs["aliases"] = podNetwork.Aliases + } return rt, nil } diff --git a/vendor/github.com/cri-o/ocicni/pkg/ocicni/types.go b/vendor/github.com/cri-o/ocicni/pkg/ocicni/types.go index 717ecda33..7326b4b40 100644 --- a/vendor/github.com/cri-o/ocicni/pkg/ocicni/types.go +++ b/vendor/github.com/cri-o/ocicni/pkg/ocicni/types.go @@ -1,6 +1,8 @@ package ocicni import ( + "context" + "github.com/containernetworking/cni/pkg/types" ) @@ -87,6 +89,11 @@ type PodNetwork struct { // It is optional, and can be omitted for some or all specified networks // without issue. RuntimeConfig map[string]RuntimeConfig + + // Aliases are network-scoped names for resolving a container + // by name. The key value is the network name and the value is + // is a string slice of aliases + Aliases map[string][]string } // NetAttachment describes a container network attachment @@ -122,12 +129,21 @@ type CNIPlugin interface { // pod are launched. SetUpPod(network PodNetwork) ([]NetResult, error) + // SetUpPodWithContext is the same as SetUpPod but takes a context + SetUpPodWithContext(ctx context.Context, network PodNetwork) ([]NetResult, error) + // TearDownPod is the method called before a pod's sandbox container will be deleted TearDownPod(network PodNetwork) error - // Status is the method called to obtain the ipv4 or ipv6 addresses of the pod sandbox + // TearDownPodWithContext is the same as TearDownPod but takes a context + TearDownPodWithContext(ctx context.Context, network PodNetwork) error + + // GetPodNetworkStatus is the method called to obtain the ipv4 or ipv6 addresses of the pod sandbox GetPodNetworkStatus(network PodNetwork) ([]NetResult, error) + // GetPodNetworkStatusWithContext is the same as GetPodNetworkStatus but takes a context + GetPodNetworkStatusWithContext(ctx context.Context, network PodNetwork) ([]NetResult, error) + // NetworkStatus returns error if the network plugin is in error state Status() error diff --git a/vendor/github.com/cri-o/ocicni/pkg/ocicni/util_linux.go b/vendor/github.com/cri-o/ocicni/pkg/ocicni/util_linux.go index d263ae4df..53c22f83f 100644 --- a/vendor/github.com/cri-o/ocicni/pkg/ocicni/util_linux.go +++ b/vendor/github.com/cri-o/ocicni/pkg/ocicni/util_linux.go @@ -7,6 +7,9 @@ import ( "net" "os/exec" "strings" + + "github.com/containernetworking/plugins/pkg/ns" + "github.com/vishvananda/netlink" ) var defaultNamespaceEnterCommandName = "nsenter" @@ -69,3 +72,79 @@ func getContainerDetails(nsm *nsManager, netnsPath, interfaceName, addrType stri return ipNet, &mac, nil } + +func tearDownLoopback(netns string) error { + return ns.WithNetNSPath(netns, func(_ ns.NetNS) error { + link, err := netlink.LinkByName(loIfname) + if err != nil { + return err // not tested + } + err = netlink.LinkSetDown(link) + if err != nil { + return err // not tested + } + return nil + }) +} + +func bringUpLoopback(netns string) error { + if err := ns.WithNetNSPath(netns, func(_ ns.NetNS) error { + link, err := netlink.LinkByName(loIfname) + if err == nil { + err = netlink.LinkSetUp(link) + } + if err != nil { + return err + } + + v4Addrs, err := netlink.AddrList(link, netlink.FAMILY_V4) + if err != nil { + return err + } + if len(v4Addrs) != 0 { + // sanity check that this is a loopback address + for _, addr := range v4Addrs { + if !addr.IP.IsLoopback() { + return fmt.Errorf("loopback interface found with non-loopback address %q", addr.IP) + } + } + } + + v6Addrs, err := netlink.AddrList(link, netlink.FAMILY_V6) + if err != nil { + return err + } + if len(v6Addrs) != 0 { + // sanity check that this is a loopback address + for _, addr := range v6Addrs { + if !addr.IP.IsLoopback() { + return fmt.Errorf("loopback interface found with non-loopback address %q", addr.IP) + } + } + } + + return nil + }); err != nil { + return fmt.Errorf("error adding loopback interface: %s", err) + } + return nil +} + +func checkLoopback(netns string) error { + // Make sure loopback interface is up + if err := ns.WithNetNSPath(netns, func(_ ns.NetNS) error { + link, err := netlink.LinkByName(loIfname) + if err != nil { + return err + } + + if link.Attrs().Flags&net.FlagUp != net.FlagUp { + return fmt.Errorf("loopback interface is down") + } + + return nil + }); err != nil { + return fmt.Errorf("error checking loopback interface: %v", err) + } + return nil +} diff --git a/vendor/github.com/cri-o/ocicni/pkg/ocicni/util_unsupported.go b/vendor/github.com/cri-o/ocicni/pkg/ocicni/util_unsupported.go index 0b1c72208..b87f0d373 100644 --- a/vendor/github.com/cri-o/ocicni/pkg/ocicni/util_unsupported.go +++ b/vendor/github.com/cri-o/ocicni/pkg/ocicni/util_unsupported.go @@ -3,17 +3,32 @@ package ocicni import ( - "fmt" + "errors" "net" ) type nsManager struct { } +var errUnsupportedPlatform = errors.New("unsupported platform") + func (nsm *nsManager) init() error { return nil } func getContainerDetails(nsm *nsManager, netnsPath, interfaceName, addrType string) (*net.IPNet, *net.HardwareAddr, error) { - return nil, nil, fmt.Errorf("not supported yet") + return nil, nil, errUnsupportedPlatform +} + +func tearDownLoopback(netns string) error { + return errUnsupportedPlatform +} + +func bringUpLoopback(netns string) error { + return errUnsupportedPlatform +} + +func checkLoopback(netns string) error { + return errUnsupportedPlatform + } -- cgit v1.2.3-54-g00ecf