From 4f699db8dad05b770b4e02d3de67137517c3463b Mon Sep 17 00:00:00 2001 From: baude Date: Thu, 12 Jul 2018 09:51:31 -0500 Subject: Support multiple networks This is a refresh of Dan William's PR #974 with a rebase and proper vendoring of ocicni and containernetworking/cni. It adds the ability to define multiple networks as so: podman run --network=net1,net2,foobar ... Signed-off-by: baude Closes: #1082 Approved by: baude --- .../github.com/cri-o/ocicni/pkg/ocicni/ocicni.go | 410 ++++++++++++++------- vendor/github.com/cri-o/ocicni/pkg/ocicni/types.go | 11 +- .../cri-o/ocicni/pkg/ocicni/types_unix.go | 10 +- .../cri-o/ocicni/pkg/ocicni/types_windows.go | 10 +- vendor/github.com/cri-o/ocicni/pkg/ocicni/util.go | 34 +- .../cri-o/ocicni/pkg/ocicni/util_linux.go | 71 ++++ .../cri-o/ocicni/pkg/ocicni/util_unsupported.go | 19 + 7 files changed, 383 insertions(+), 182 deletions(-) create mode 100644 vendor/github.com/cri-o/ocicni/pkg/ocicni/util_linux.go create mode 100644 vendor/github.com/cri-o/ocicni/pkg/ocicni/util_unsupported.go (limited to 'vendor/github.com/cri-o/ocicni/pkg') 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 e49c1dc84..33a3ae063 100644 --- a/vendor/github.com/cri-o/ocicni/pkg/ocicni/ocicni.go +++ b/vendor/github.com/cri-o/ocicni/pkg/ocicni/ocicni.go @@ -4,13 +4,16 @@ import ( "errors" "fmt" "os" - "os/exec" + "path" "sort" "strings" "sync" "github.com/containernetworking/cni/libcni" + cniinvoke "github.com/containernetworking/cni/pkg/invoke" cnitypes "github.com/containernetworking/cni/pkg/types" + cnicurrent "github.com/containernetworking/cni/pkg/types/current" + cniversion "github.com/containernetworking/cni/pkg/version" "github.com/fsnotify/fsnotify" "github.com/sirupsen/logrus" ) @@ -19,14 +22,16 @@ type cniNetworkPlugin struct { loNetwork *cniNetwork sync.RWMutex - defaultNetwork *cniNetwork + defaultNetName string + networks map[string]*cniNetwork - nsenterPath string - pluginDir string - cniDirs []string - vendorCNIDirPrefix string + nsManager *nsManager + confDir string + binDirs []string - monitorNetDirChan chan struct{} + shutdownChan chan struct{} + watcher *fsnotify.Watcher + done *sync.WaitGroup // The pod map provides synchronization for a given pod's network // operations. Each pod's setup/teardown/status operations @@ -34,12 +39,17 @@ type cniNetworkPlugin struct { // pods can proceed in parallel. podsLock sync.Mutex pods map[string]*podLock + + // For testcases + exec cniinvoke.Exec + cacheDir string } type cniNetwork struct { name string + filePath string NetworkConfig *libcni.NetworkConfigList - CNIConfig libcni.CNI + CNIConfig *libcni.CNIConfig } var errMissingDefaultNetwork = errors.New("Missing CNI default network") @@ -99,110 +109,150 @@ func (plugin *cniNetworkPlugin) podUnlock(podNetwork PodNetwork) { } } -func (plugin *cniNetworkPlugin) monitorNetDir() { +func newWatcher(confDir string) (*fsnotify.Watcher, error) { + // Ensure plugin directory exists, because the following monitoring logic + // relies on that. + if err := os.MkdirAll(confDir, 0755); err != nil { + return nil, fmt.Errorf("failed to create %q: %v", confDir, err) + } + watcher, err := fsnotify.NewWatcher() if err != nil { - logrus.Errorf("could not create new watcher %v", err) - return + return nil, fmt.Errorf("could not create new watcher %v", err) } - defer watcher.Close() + defer func() { + // Close watcher on error + if err != nil { + watcher.Close() + } + }() - if err = watcher.Add(plugin.pluginDir); err != nil { - logrus.Errorf("Failed to add watch on %q: %v", plugin.pluginDir, err) - return + if err = watcher.Add(confDir); err != nil { + return nil, fmt.Errorf("failed to add watch on %q: %v", confDir, err) } - // Now that `watcher` is running and watching the `pluginDir` - // gather the initial configuration, before starting the - // goroutine which will actually process events. It has to be - // done in this order to avoid missing any updates which might - // otherwise occur between gathering the initial configuration - // and starting the watcher. - if err := plugin.syncNetworkConfig(); err != nil { - logrus.Infof("Initial CNI setting failed, continue monitoring: %v", err) - } else { - logrus.Infof("Initial CNI setting succeeded") - } - - go func() { - for { - select { - case event := <-watcher.Events: - logrus.Debugf("CNI monitoring event %v", event) - if event.Op&fsnotify.Create != fsnotify.Create && - event.Op&fsnotify.Write != fsnotify.Write { - continue - } + return watcher, nil +} - if err = plugin.syncNetworkConfig(); err == nil { - logrus.Infof("CNI asynchronous setting succeeded") - continue +func (plugin *cniNetworkPlugin) monitorConfDir(start *sync.WaitGroup) { + start.Done() + plugin.done.Add(1) + defer plugin.done.Done() + for { + select { + case event := <-plugin.watcher.Events: + logrus.Warningf("CNI monitoring event %v", event) + + var defaultDeleted bool + createWrite := (event.Op&fsnotify.Create == fsnotify.Create || + event.Op&fsnotify.Write == fsnotify.Write) + if event.Op&fsnotify.Remove == fsnotify.Remove { + // Care about the event if the default network + // was just deleted + defNet := plugin.getDefaultNetwork() + if defNet != nil && event.Name == defNet.filePath { + defaultDeleted = true } - logrus.Errorf("CNI setting failed, continue monitoring: %v", err) + } + if !createWrite && !defaultDeleted { + continue + } - case err := <-watcher.Errors: - if err == nil { - continue - } - logrus.Errorf("CNI monitoring error %v", err) - close(plugin.monitorNetDirChan) - return + if err := plugin.syncNetworkConfig(); err != nil { + logrus.Errorf("CNI config loading failed, continue monitoring: %v", err) + continue } + + case err := <-plugin.watcher.Errors: + if err == nil { + continue + } + logrus.Errorf("CNI monitoring error %v", err) + return + + case <-plugin.shutdownChan: + return } - }() + } +} - <-plugin.monitorNetDirChan +// InitCNI takes a binary directory in which to search for CNI plugins, and +// a configuration directory in which to search for CNI JSON config files. +// If no valid CNI configs exist, network requests will fail until valid CNI +// config files are present in the config directory. +// If defaultNetName is not empty, a CNI config with that network name will +// be used as the default CNI network, and container network operations will +// fail until that network config is present and valid. +func InitCNI(defaultNetName string, confDir string, binDirs ...string) (CNIPlugin, error) { + return initCNI(nil, "", defaultNetName, confDir, binDirs...) } -// InitCNI takes the plugin directory and CNI directories where the CNI config -// files should be searched for. If no valid CNI configs exist, network requests -// will fail until valid CNI config files are present in the config directory. -func InitCNI(pluginDir string, cniDirs ...string) (CNIPlugin, error) { - vendorCNIDirPrefix := "" +// Internal function to allow faking out exec functions for testing +func initCNI(exec cniinvoke.Exec, cacheDir, defaultNetName string, confDir string, binDirs ...string) (CNIPlugin, error) { + if confDir == "" { + confDir = DefaultConfDir + } + if len(binDirs) == 0 { + binDirs = []string{DefaultBinDir} + } plugin := &cniNetworkPlugin{ - defaultNetwork: nil, - loNetwork: getLoNetwork(cniDirs, vendorCNIDirPrefix), - pluginDir: pluginDir, - cniDirs: cniDirs, - vendorCNIDirPrefix: vendorCNIDirPrefix, - monitorNetDirChan: make(chan struct{}), - pods: make(map[string]*podLock), + defaultNetName: defaultNetName, + networks: make(map[string]*cniNetwork), + loNetwork: getLoNetwork(exec, binDirs), + confDir: confDir, + binDirs: binDirs, + shutdownChan: make(chan struct{}), + done: &sync.WaitGroup{}, + pods: make(map[string]*podLock), + exec: exec, + cacheDir: cacheDir, + } + + if exec == nil { + exec = &cniinvoke.DefaultExec{ + RawExec: &cniinvoke.RawExec{Stderr: os.Stderr}, + PluginDecoder: cniversion.PluginDecoder{}, + } } - var err error - plugin.nsenterPath, err = exec.LookPath("nsenter") + nsm, err := newNSManager() if err != nil { return nil, err } + plugin.nsManager = nsm - // Ensure plugin directory exists, because the following monitoring logic - // relies on that. - if err := os.MkdirAll(pluginDir, 0755); err != nil { + plugin.syncNetworkConfig() + + plugin.watcher, err = newWatcher(plugin.confDir) + if err != nil { return nil, err } - go plugin.monitorNetDir() + startWg := sync.WaitGroup{} + startWg.Add(1) + go plugin.monitorConfDir(&startWg) + startWg.Wait() return plugin, nil } -func getDefaultCNINetwork(pluginDir string, cniDirs []string, vendorCNIDirPrefix string) (*cniNetwork, error) { - if pluginDir == "" { - pluginDir = DefaultNetDir - } - if len(cniDirs) == 0 { - cniDirs = []string{DefaultCNIDir} - } +func (plugin *cniNetworkPlugin) Shutdown() error { + close(plugin.shutdownChan) + plugin.watcher.Close() + plugin.done.Wait() + return nil +} - files, err := libcni.ConfFiles(pluginDir, []string{".conf", ".conflist", ".json"}) - switch { - case err != nil: - return nil, err - case len(files) == 0: - return nil, errMissingDefaultNetwork +func loadNetworks(exec cniinvoke.Exec, confDir string, binDirs []string) (map[string]*cniNetwork, string, error) { + files, err := libcni.ConfFiles(confDir, []string{".conf", ".conflist", ".json"}) + if err != nil { + return nil, "", err } + networks := make(map[string]*cniNetwork) + defaultNetName := "" + sort.Strings(files) for _, confFile := range files { var confList *libcni.NetworkConfigList @@ -232,27 +282,28 @@ func getDefaultCNINetwork(pluginDir string, cniDirs []string, vendorCNIDirPrefix logrus.Warningf("CNI config list %s has no networks, skipping", confFile) continue } - logrus.Infof("CNI network %s (type=%v) is used from %s", confList.Name, confList.Plugins[0].Network.Type, confFile) - // Search for vendor-specific plugins as well as default plugins in the CNI codebase. - vendorDir := vendorCNIDir(vendorCNIDirPrefix, confList.Plugins[0].Network.Type) - cninet := &libcni.CNIConfig{ - Path: append(cniDirs, vendorDir), + if confList.Name == "" { + confList.Name = path.Base(confFile) } - network := &cniNetwork{name: confList.Name, NetworkConfig: confList, CNIConfig: cninet} - return network, nil - } - return nil, fmt.Errorf("No valid networks found in %s", pluginDir) -} -func vendorCNIDir(prefix, pluginType string) string { - return fmt.Sprintf(VendorCNIDirTemplate, prefix, pluginType) -} + logrus.Infof("Found CNI network %s (type=%v) at %s", confList.Name, confList.Plugins[0].Network.Type, confFile) + + networks[confList.Name] = &cniNetwork{ + name: confList.Name, + filePath: confFile, + NetworkConfig: confList, + CNIConfig: libcni.NewCNIConfig(binDirs, exec), + } -func getLoNetwork(cniDirs []string, vendorDirPrefix string) *cniNetwork { - if len(cniDirs) == 0 { - cniDirs = []string{DefaultCNIDir} + if defaultNetName == "" { + defaultNetName = confList.Name + } } + return networks, defaultNetName, nil +} + +func getLoNetwork(exec cniinvoke.Exec, binDirs []string) *cniNetwork { loConfig, err := libcni.ConfListFromBytes([]byte(`{ "cniVersion": "0.2.0", "name": "cni-loopback", @@ -265,45 +316,62 @@ func getLoNetwork(cniDirs []string, vendorDirPrefix string) *cniNetwork { // catch this panic(err) } - vendorDir := vendorCNIDir(vendorDirPrefix, loConfig.Plugins[0].Network.Type) - cninet := &libcni.CNIConfig{ - Path: append(cniDirs, vendorDir), - } loNetwork := &cniNetwork{ name: "lo", NetworkConfig: loConfig, - CNIConfig: cninet, + CNIConfig: libcni.NewCNIConfig(binDirs, exec), } return loNetwork } func (plugin *cniNetworkPlugin) syncNetworkConfig() error { - network, err := getDefaultCNINetwork(plugin.pluginDir, plugin.cniDirs, plugin.vendorCNIDirPrefix) + networks, defaultNetName, err := loadNetworks(plugin.exec, plugin.confDir, plugin.binDirs) if err != nil { - logrus.Errorf("error updating cni config: %s", err) return err } - plugin.setDefaultNetwork(network) + + plugin.Lock() + defer plugin.Unlock() + if plugin.defaultNetName == "" { + plugin.defaultNetName = defaultNetName + } + plugin.networks = networks return nil } -func (plugin *cniNetworkPlugin) getDefaultNetwork() *cniNetwork { +func (plugin *cniNetworkPlugin) getNetwork(name string) (*cniNetwork, error) { plugin.RLock() defer plugin.RUnlock() - return plugin.defaultNetwork + net, ok := plugin.networks[name] + if !ok { + return nil, fmt.Errorf("CNI network %q not found", name) + } + return net, nil } -func (plugin *cniNetworkPlugin) setDefaultNetwork(n *cniNetwork) { - plugin.Lock() - defer plugin.Unlock() - plugin.defaultNetwork = n +func (plugin *cniNetworkPlugin) getDefaultNetworkName() string { + plugin.RLock() + defer plugin.RUnlock() + return plugin.defaultNetName } -func (plugin *cniNetworkPlugin) checkInitialized() error { - if plugin.getDefaultNetwork() == nil { - return errors.New("cni config uninitialized") +func (plugin *cniNetworkPlugin) getDefaultNetwork() *cniNetwork { + defaultNetName := plugin.getDefaultNetworkName() + if defaultNetName == "" { + return nil + } + network, _ := plugin.getNetwork(defaultNetName) + return network +} + +// networksAvailable returns an error if the pod requests no networks and the +// plugin has no default network, and thus the plugin has no idea what network +// to attach the pod to. +func (plugin *cniNetworkPlugin) networksAvailable(podNetwork *PodNetwork) error { + if len(podNetwork.Networks) == 0 && plugin.getDefaultNetwork() == nil { + return errMissingDefaultNetwork } return nil } @@ -312,59 +380,119 @@ func (plugin *cniNetworkPlugin) Name() string { return CNIPluginName } -func (plugin *cniNetworkPlugin) SetUpPod(podNetwork PodNetwork) (cnitypes.Result, error) { - if err := plugin.checkInitialized(); err != nil { +func (plugin *cniNetworkPlugin) forEachNetwork(podNetwork *PodNetwork, forEachFunc func(*cniNetwork, string, *PodNetwork) error) error { + networks := podNetwork.Networks + if len(networks) == 0 { + networks = append(networks, plugin.getDefaultNetworkName()) + } + for i, netName := range networks { + // Interface names start at "eth0" and count up for each network + ifName := fmt.Sprintf("eth%d", i) + network, err := plugin.getNetwork(netName) + if err != nil { + logrus.Errorf(err.Error()) + return err + } + if err := forEachFunc(network, ifName, podNetwork); err != nil { + return err + } + } + return nil +} + +func (plugin *cniNetworkPlugin) SetUpPod(podNetwork PodNetwork) ([]cnitypes.Result, error) { + if err := plugin.networksAvailable(&podNetwork); err != nil { return nil, err } plugin.podLock(podNetwork).Lock() defer plugin.podUnlock(podNetwork) - _, err := plugin.loNetwork.addToNetwork(podNetwork) + _, err := plugin.loNetwork.addToNetwork(plugin.cacheDir, &podNetwork, "lo") if err != nil { logrus.Errorf("Error while adding to cni lo network: %s", err) return nil, err } - result, err := plugin.getDefaultNetwork().addToNetwork(podNetwork) - if err != nil { - logrus.Errorf("Error while adding to cni network: %s", err) + results := make([]cnitypes.Result, 0) + if err := plugin.forEachNetwork(&podNetwork, func(network *cniNetwork, ifName string, podNetwork *PodNetwork) error { + result, err := network.addToNetwork(plugin.cacheDir, podNetwork, ifName) + if err != nil { + logrus.Errorf("Error while adding pod to CNI network %q: %s", network.name, err) + return err + } + results = append(results, result) + return nil + }); err != nil { return nil, err } - return result, err + return results, nil } func (plugin *cniNetworkPlugin) TearDownPod(podNetwork PodNetwork) error { - if err := plugin.checkInitialized(); err != nil { + if err := plugin.networksAvailable(&podNetwork); err != nil { return err } plugin.podLock(podNetwork).Lock() defer plugin.podUnlock(podNetwork) - return plugin.getDefaultNetwork().deleteFromNetwork(podNetwork) + return plugin.forEachNetwork(&podNetwork, func(network *cniNetwork, ifName string, podNetwork *PodNetwork) error { + if err := network.deleteFromNetwork(plugin.cacheDir, podNetwork, ifName); err != nil { + logrus.Errorf("Error while removing pod from CNI network %q: %s", network.name, err) + return err + } + return nil + }) } -// TODO: Use the addToNetwork function to obtain the IP of the Pod. That will assume idempotent ADD call to the plugin. -// Also fix the runtime's call to Status function to be done only in the case that the IP is lost, no need to do periodic calls -func (plugin *cniNetworkPlugin) GetPodNetworkStatus(podNetwork PodNetwork) (string, error) { +// GetPodNetworkStatus returns IP addressing and interface details for all +// networks attached to the pod. +func (plugin *cniNetworkPlugin) GetPodNetworkStatus(podNetwork PodNetwork) ([]cnitypes.Result, error) { plugin.podLock(podNetwork).Lock() defer plugin.podUnlock(podNetwork) - ip, err := getContainerIP(plugin.nsenterPath, podNetwork.NetNS, DefaultInterfaceName, "-4") - if err != nil { - ip, err = getContainerIP(plugin.nsenterPath, podNetwork.NetNS, DefaultInterfaceName, "-6") - } - if err != nil { - return "", err + results := make([]cnitypes.Result, 0) + if err := plugin.forEachNetwork(&podNetwork, func(network *cniNetwork, ifName string, podNetwork *PodNetwork) error { + version := "4" + ip, mac, err := getContainerDetails(plugin.nsManager, podNetwork.NetNS, ifName, "-4") + if err != nil { + ip, mac, err = getContainerDetails(plugin.nsManager, podNetwork.NetNS, ifName, "-6") + if err != nil { + return err + } + version = "6" + } + + // Until CNI's GET request lands, construct the Result manually + results = append(results, &cnicurrent.Result{ + CNIVersion: "0.3.1", + Interfaces: []*cnicurrent.Interface{ + { + Name: ifName, + Mac: mac.String(), + Sandbox: podNetwork.NetNS, + }, + }, + IPs: []*cnicurrent.IPConfig{ + { + Version: version, + Interface: cnicurrent.Int(0), + Address: *ip, + }, + }, + }) + return nil + }); err != nil { + return nil, err } - return ip.String(), nil + return results, nil } -func (network *cniNetwork) addToNetwork(podNetwork PodNetwork) (cnitypes.Result, error) { - rt, err := buildCNIRuntimeConf(podNetwork) +func (network *cniNetwork) addToNetwork(cacheDir string, podNetwork *PodNetwork, ifName string) (cnitypes.Result, error) { + rt, err := buildCNIRuntimeConf(cacheDir, podNetwork, ifName) if err != nil { logrus.Errorf("Error adding network: %v", err) return nil, err @@ -381,8 +509,8 @@ func (network *cniNetwork) addToNetwork(podNetwork PodNetwork) (cnitypes.Result, return res, nil } -func (network *cniNetwork) deleteFromNetwork(podNetwork PodNetwork) error { - rt, err := buildCNIRuntimeConf(podNetwork) +func (network *cniNetwork) deleteFromNetwork(cacheDir string, podNetwork *PodNetwork, ifName string) error { + rt, err := buildCNIRuntimeConf(cacheDir, podNetwork, ifName) if err != nil { logrus.Errorf("Error deleting network: %v", err) return err @@ -398,13 +526,14 @@ func (network *cniNetwork) deleteFromNetwork(podNetwork PodNetwork) error { return nil } -func buildCNIRuntimeConf(podNetwork PodNetwork) (*libcni.RuntimeConf, error) { +func buildCNIRuntimeConf(cacheDir string, podNetwork *PodNetwork, ifName string) (*libcni.RuntimeConf, error) { logrus.Infof("Got pod network %+v", podNetwork) rt := &libcni.RuntimeConf{ ContainerID: podNetwork.ID, NetNS: podNetwork.NetNS, - IfName: DefaultInterfaceName, + CacheDir: cacheDir, + IfName: ifName, Args: [][2]string{ {"IgnoreUnknown", "1"}, {"K8S_POD_NAMESPACE", podNetwork.Namespace}, @@ -424,5 +553,8 @@ func buildCNIRuntimeConf(podNetwork PodNetwork) (*libcni.RuntimeConf, error) { } func (plugin *cniNetworkPlugin) Status() error { - return plugin.checkInitialized() + if plugin.getDefaultNetwork() == nil { + return errMissingDefaultNetwork + } + return 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 39e9b591c..8ca61657a 100644 --- a/vendor/github.com/cri-o/ocicni/pkg/ocicni/types.go +++ b/vendor/github.com/cri-o/ocicni/pkg/ocicni/types.go @@ -36,6 +36,10 @@ type PodNetwork struct { NetNS string // PortMappings is the port mapping of the sandbox. PortMappings []PortMapping + + // Networks is a list of CNI network names to attach to the sandbox + // Leave this list empty to attach the default network to the sandbox + Networks []string } // CNIPlugin is the interface that needs to be implemented by a plugin @@ -47,14 +51,17 @@ type CNIPlugin interface { // SetUpPod is the method called after the sandbox container of // the pod has been created but before the other containers of the // pod are launched. - SetUpPod(network PodNetwork) (types.Result, error) + SetUpPod(network PodNetwork) ([]types.Result, 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 - GetPodNetworkStatus(network PodNetwork) (string, error) + GetPodNetworkStatus(network PodNetwork) ([]types.Result, error) // NetworkStatus returns error if the network plugin is in error state Status() error + + // Shutdown terminates all driver operations + Shutdown() error } diff --git a/vendor/github.com/cri-o/ocicni/pkg/ocicni/types_unix.go b/vendor/github.com/cri-o/ocicni/pkg/ocicni/types_unix.go index 21e713ffc..88010f737 100644 --- a/vendor/github.com/cri-o/ocicni/pkg/ocicni/types_unix.go +++ b/vendor/github.com/cri-o/ocicni/pkg/ocicni/types_unix.go @@ -3,10 +3,8 @@ package ocicni const ( - // DefaultNetDir is the place to look for CNI Network - DefaultNetDir = "/etc/cni/net.d" - // DefaultCNIDir is the place to look for cni config files - DefaultCNIDir = "/opt/cni/bin" - // VendorCNIDirTemplate is the template for looking up vendor specific cni config/executable files - VendorCNIDirTemplate = "%s/opt/%s/bin" + // DefaultConfDir is the default place to look for CNI Network + DefaultConfDir = "/etc/cni/net.d" + // DefaultBinDir is the default place to look for CNI config files + DefaultBinDir = "/opt/cni/bin" ) diff --git a/vendor/github.com/cri-o/ocicni/pkg/ocicni/types_windows.go b/vendor/github.com/cri-o/ocicni/pkg/ocicni/types_windows.go index f8b434c12..061ecae5c 100644 --- a/vendor/github.com/cri-o/ocicni/pkg/ocicni/types_windows.go +++ b/vendor/github.com/cri-o/ocicni/pkg/ocicni/types_windows.go @@ -3,10 +3,8 @@ package ocicni const ( - // DefaultNetDir is the place to look for CNI Network - DefaultNetDir = "C:\\cni\\etc\\net.d" - // DefaultCNIDir is the place to look for cni config files - DefaultCNIDir = "C:\\cni\\bin" - // VendorCNIDirTemplate is the template for looking up vendor specific cni config/executable files - VendorCNIDirTemplate = "C:\\cni\\%s\\opt\\%s\\bin" // XXX(vbatts) Not sure what to do here ... + // DefaultConfDir is the default place to look for CNI Network + DefaultConfDir = "C:\\cni\\etc\\net.d" + // DefaultBinDir is the default place to look for cni config files + DefaultBinDir = "C:\\cni\\bin" ) diff --git a/vendor/github.com/cri-o/ocicni/pkg/ocicni/util.go b/vendor/github.com/cri-o/ocicni/pkg/ocicni/util.go index 547e95972..2af786593 100644 --- a/vendor/github.com/cri-o/ocicni/pkg/ocicni/util.go +++ b/vendor/github.com/cri-o/ocicni/pkg/ocicni/util.go @@ -1,32 +1,8 @@ package ocicni -import ( - "fmt" - "net" - "os/exec" - "strings" -) - -func getContainerIP(nsenterPath, netnsPath, interfaceName, addrType string) (net.IP, error) { - // Try to retrieve ip inside container network namespace - output, err := exec.Command(nsenterPath, fmt.Sprintf("--net=%s", netnsPath), "-F", "--", - "ip", "-o", addrType, "addr", "show", "dev", interfaceName, "scope", "global").CombinedOutput() - if err != nil { - return nil, fmt.Errorf("Unexpected command output %s with error: %v", output, err) - } - - lines := strings.Split(string(output), "\n") - if len(lines) < 1 { - return nil, fmt.Errorf("Unexpected command output %s", output) - } - fields := strings.Fields(lines[0]) - if len(fields) < 4 { - return nil, fmt.Errorf("Unexpected address output %s ", lines[0]) - } - ip, _, err := net.ParseCIDR(fields[3]) - if err != nil { - return nil, fmt.Errorf("CNI failed to parse ip from output %s due to %v", output, err) - } - - return ip, nil +// newNSManager initializes a new namespace manager, which is a platform dependent struct. +func newNSManager() (*nsManager, error) { + nsm := &nsManager{} + err := nsm.init() + return nsm, err } 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 new file mode 100644 index 000000000..d263ae4df --- /dev/null +++ b/vendor/github.com/cri-o/ocicni/pkg/ocicni/util_linux.go @@ -0,0 +1,71 @@ +// +build linux + +package ocicni + +import ( + "fmt" + "net" + "os/exec" + "strings" +) + +var defaultNamespaceEnterCommandName = "nsenter" + +type nsManager struct { + nsenterPath string +} + +func (nsm *nsManager) init() error { + var err error + nsm.nsenterPath, err = exec.LookPath(defaultNamespaceEnterCommandName) + return err +} + +func getContainerDetails(nsm *nsManager, netnsPath, interfaceName, addrType string) (*net.IPNet, *net.HardwareAddr, error) { + // Try to retrieve ip inside container network namespace + output, err := exec.Command(nsm.nsenterPath, fmt.Sprintf("--net=%s", netnsPath), "-F", "--", + "ip", "-o", addrType, "addr", "show", "dev", interfaceName, "scope", "global").CombinedOutput() + if err != nil { + return nil, nil, fmt.Errorf("Unexpected command output %s with error: %v", output, err) + } + + lines := strings.Split(string(output), "\n") + if len(lines) < 1 { + return nil, nil, fmt.Errorf("Unexpected command output %s", output) + } + fields := strings.Fields(lines[0]) + if len(fields) < 4 { + return nil, nil, fmt.Errorf("Unexpected address output %s ", lines[0]) + } + ip, ipNet, err := net.ParseCIDR(fields[3]) + if err != nil { + return nil, nil, fmt.Errorf("CNI failed to parse ip from output %s due to %v", output, err) + } + if ip.To4() == nil { + ipNet.IP = ip + } else { + ipNet.IP = ip.To4() + } + + // Try to retrieve MAC inside container network namespace + output, err = exec.Command(nsm.nsenterPath, fmt.Sprintf("--net=%s", netnsPath), "-F", "--", + "ip", "link", "show", "dev", interfaceName).CombinedOutput() + if err != nil { + return nil, nil, fmt.Errorf("unexpected 'ip link' command output %s with error: %v", output, err) + } + + lines = strings.Split(string(output), "\n") + if len(lines) < 2 { + return nil, nil, fmt.Errorf("unexpected 'ip link' command output %s", output) + } + fields = strings.Fields(lines[1]) + if len(fields) < 4 { + return nil, nil, fmt.Errorf("unexpected link output %s ", lines[0]) + } + mac, err := net.ParseMAC(fields[1]) + if err != nil { + return nil, nil, fmt.Errorf("failed to parse MAC from output %s due to %v", output, err) + } + + return ipNet, &mac, 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 new file mode 100644 index 000000000..0b1c72208 --- /dev/null +++ b/vendor/github.com/cri-o/ocicni/pkg/ocicni/util_unsupported.go @@ -0,0 +1,19 @@ +// +build !linux + +package ocicni + +import ( + "fmt" + "net" +) + +type nsManager struct { +} + +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") +} -- cgit v1.2.3-54-g00ecf