summaryrefslogtreecommitdiff
path: root/libpod/network/cni/cni_conversion.go
diff options
context:
space:
mode:
Diffstat (limited to 'libpod/network/cni/cni_conversion.go')
-rw-r--r--libpod/network/cni/cni_conversion.go378
1 files changed, 0 insertions, 378 deletions
diff --git a/libpod/network/cni/cni_conversion.go b/libpod/network/cni/cni_conversion.go
deleted file mode 100644
index 788165b5e..000000000
--- a/libpod/network/cni/cni_conversion.go
+++ /dev/null
@@ -1,378 +0,0 @@
-// +build linux
-
-package cni
-
-import (
- "encoding/json"
- "io/ioutil"
- "net"
- "os"
- "path/filepath"
- "strconv"
- "strings"
- "syscall"
- "time"
-
- "github.com/containernetworking/cni/libcni"
- internalutil "github.com/containers/podman/v3/libpod/network/internal/util"
- "github.com/containers/podman/v3/libpod/network/types"
- "github.com/containers/podman/v3/libpod/network/util"
- pkgutil "github.com/containers/podman/v3/pkg/util"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
-)
-
-func createNetworkFromCNIConfigList(conf *libcni.NetworkConfigList, confPath string) (*types.Network, error) {
- network := types.Network{
- Name: conf.Name,
- ID: getNetworkIDFromName(conf.Name),
- Labels: map[string]string{},
- Options: map[string]string{},
- IPAMOptions: map[string]string{},
- }
-
- cniJSON := make(map[string]interface{})
- err := json.Unmarshal(conf.Bytes, &cniJSON)
- if err != nil {
- return nil, errors.Wrapf(err, "failed to unmarshal network config %s", conf.Name)
- }
- if args, ok := cniJSON["args"]; ok {
- if key, ok := args.(map[string]interface{}); ok {
- // read network labels and options from the conf file
- network.Labels = getNetworkArgsFromConfList(key, podmanLabelKey)
- network.Options = getNetworkArgsFromConfList(key, podmanOptionsKey)
- }
- }
-
- f, err := os.Stat(confPath)
- if err != nil {
- return nil, err
- }
- stat := f.Sys().(*syscall.Stat_t)
- network.Created = time.Unix(int64(stat.Ctim.Sec), int64(stat.Ctim.Nsec))
-
- firstPlugin := conf.Plugins[0]
- network.Driver = firstPlugin.Network.Type
-
- switch firstPlugin.Network.Type {
- case types.BridgeNetworkDriver:
- var bridge hostLocalBridge
- err := json.Unmarshal(firstPlugin.Bytes, &bridge)
- if err != nil {
- return nil, errors.Wrapf(err, "failed to unmarshal the bridge plugin config in %s", confPath)
- }
- network.NetworkInterface = bridge.BrName
-
- // if isGateway is false we have an internal network
- if !bridge.IsGW {
- network.Internal = true
- }
-
- // set network options
- if bridge.MTU != 0 {
- network.Options["mtu"] = strconv.Itoa(bridge.MTU)
- }
- if bridge.Vlan != 0 {
- network.Options["vlan"] = strconv.Itoa(bridge.Vlan)
- }
-
- err = convertIPAMConfToNetwork(&network, bridge.IPAM, confPath)
- if err != nil {
- return nil, err
- }
-
- case types.MacVLANNetworkDriver, types.IPVLANNetworkDriver:
- var vlan VLANConfig
- err := json.Unmarshal(firstPlugin.Bytes, &vlan)
- if err != nil {
- return nil, errors.Wrapf(err, "failed to unmarshal the macvlan plugin config in %s", confPath)
- }
- network.NetworkInterface = vlan.Master
-
- // set network options
- if vlan.MTU != 0 {
- network.Options["mtu"] = strconv.Itoa(vlan.MTU)
- }
-
- if vlan.Mode != "" {
- network.Options["mode"] = vlan.Mode
- }
-
- err = convertIPAMConfToNetwork(&network, vlan.IPAM, confPath)
- if err != nil {
- return nil, err
- }
-
- default:
- // A warning would be good but users would get this warning every time so keep this at info level.
- logrus.Infof("Unsupported CNI config type %s in %s, this network can still be used but inspect or list cannot show all information",
- firstPlugin.Network.Type, confPath)
- }
-
- // check if the dnsname plugin is configured
- network.DNSEnabled = findPluginByName(conf.Plugins, "dnsname")
-
- return &network, nil
-}
-
-func findPluginByName(plugins []*libcni.NetworkConfig, name string) bool {
- for _, plugin := range plugins {
- if plugin.Network.Type == name {
- return true
- }
- }
- return false
-}
-
-// convertIPAMConfToNetwork converts A cni IPAMConfig to libpod network subnets.
-// It returns an array of subnets and an extra bool if dhcp is configured.
-func convertIPAMConfToNetwork(network *types.Network, ipam ipamConfig, confPath string) error {
- if ipam.PluginType == types.DHCPIPAMDriver {
- network.IPAMOptions["driver"] = types.DHCPIPAMDriver
- return nil
- }
-
- if ipam.PluginType != types.HostLocalIPAMDriver {
- return errors.Errorf("unsupported ipam plugin %s in %s", ipam.PluginType, confPath)
- }
-
- network.IPAMOptions["driver"] = types.HostLocalIPAMDriver
- for _, r := range ipam.Ranges {
- for _, ipam := range r {
- s := types.Subnet{}
-
- // Do not use types.ParseCIDR() because we want the ip to be
- // the network address and not a random ip in the sub.
- _, sub, err := net.ParseCIDR(ipam.Subnet)
- if err != nil {
- return err
- }
- s.Subnet = types.IPNet{IPNet: *sub}
-
- // gateway
- var gateway net.IP
- if ipam.Gateway != "" {
- gateway = net.ParseIP(ipam.Gateway)
- if gateway == nil {
- return errors.Errorf("failed to parse gateway ip %s", ipam.Gateway)
- }
- // convert to 4 byte if ipv4
- util.NormalizeIP(&gateway)
- } else if !network.Internal {
- // only add a gateway address if the network is not internal
- gateway, err = util.FirstIPInSubnet(sub)
- if err != nil {
- return errors.Errorf("failed to get first ip in subnet %s", sub.String())
- }
- }
- s.Gateway = gateway
-
- var rangeStart net.IP
- var rangeEnd net.IP
- if ipam.RangeStart != "" {
- rangeStart = net.ParseIP(ipam.RangeStart)
- if rangeStart == nil {
- return errors.Errorf("failed to parse range start ip %s", ipam.RangeStart)
- }
- }
- if ipam.RangeEnd != "" {
- rangeEnd = net.ParseIP(ipam.RangeEnd)
- if rangeEnd == nil {
- return errors.Errorf("failed to parse range end ip %s", ipam.RangeEnd)
- }
- }
- if rangeStart != nil || rangeEnd != nil {
- s.LeaseRange = &types.LeaseRange{}
- s.LeaseRange.StartIP = rangeStart
- s.LeaseRange.EndIP = rangeEnd
- }
- if util.IsIPv6(s.Subnet.IP) {
- network.IPv6Enabled = true
- }
- network.Subnets = append(network.Subnets, s)
- }
- }
- return nil
-}
-
-// getNetworkArgsFromConfList returns the map of args in a conflist, argType should be labels or options
-func getNetworkArgsFromConfList(args map[string]interface{}, argType string) map[string]string {
- if args, ok := args[argType]; ok {
- if labels, ok := args.(map[string]interface{}); ok {
- result := make(map[string]string, len(labels))
- for k, v := range labels {
- if v, ok := v.(string); ok {
- result[k] = v
- }
- }
- return result
- }
- }
- return map[string]string{}
-}
-
-// createCNIConfigListFromNetwork will create a cni config file from the given network.
-// It returns the cni config and the path to the file where the config was written.
-// Set writeToDisk to false to only add this network into memory.
-func (n *cniNetwork) createCNIConfigListFromNetwork(network *types.Network, writeToDisk bool) (*libcni.NetworkConfigList, string, error) {
- var (
- routes []ipamRoute
- ipamRanges [][]ipamLocalHostRangeConf
- ipamConf ipamConfig
- err error
- )
- if len(network.Subnets) > 0 {
- for _, subnet := range network.Subnets {
- route, err := newIPAMDefaultRoute(util.IsIPv6(subnet.Subnet.IP))
- if err != nil {
- return nil, "", err
- }
- routes = append(routes, route)
- ipam := newIPAMLocalHostRange(subnet.Subnet, subnet.LeaseRange, subnet.Gateway)
- ipamRanges = append(ipamRanges, []ipamLocalHostRangeConf{*ipam})
- }
- ipamConf = newIPAMHostLocalConf(routes, ipamRanges)
- } else {
- ipamConf = ipamConfig{PluginType: "dhcp"}
- }
-
- vlan := 0
- mtu := 0
- vlanPluginMode := ""
- for k, v := range network.Options {
- switch k {
- case "mtu":
- mtu, err = internalutil.ParseMTU(v)
- if err != nil {
- return nil, "", err
- }
-
- case "vlan":
- vlan, err = internalutil.ParseVlan(v)
- if err != nil {
- return nil, "", err
- }
-
- case "mode":
- switch network.Driver {
- case types.MacVLANNetworkDriver:
- if !pkgutil.StringInSlice(v, []string{"", "bridge", "private", "vepa", "passthru"}) {
- return nil, "", errors.Errorf("unknown macvlan mode %q", v)
- }
- case types.IPVLANNetworkDriver:
- if !pkgutil.StringInSlice(v, []string{"", "l2", "l3", "l3s"}) {
- return nil, "", errors.Errorf("unknown ipvlan mode %q", v)
- }
- default:
- return nil, "", errors.Errorf("cannot set option \"mode\" with driver %q", network.Driver)
- }
- vlanPluginMode = v
-
- default:
- return nil, "", errors.Errorf("unsupported network option %s", k)
- }
- }
-
- isGateway := true
- ipMasq := true
- if network.Internal {
- isGateway = false
- ipMasq = false
- }
- // create CNI plugin configuration
- // explicitly use CNI version 0.4.0 here, to use v1.0.0 at least containernetwork-plugins-1.0.1 has to be installed
- // the dnsname plugin also needs to be updated for 1.0.0
- // TODO change to 1.0.0 when most distros support it
- ncList := newNcList(network.Name, "0.4.0", network.Labels, network.Options)
- var plugins []interface{}
-
- switch network.Driver {
- case types.BridgeNetworkDriver:
- bridge := newHostLocalBridge(network.NetworkInterface, isGateway, ipMasq, mtu, vlan, ipamConf)
- plugins = append(plugins, bridge, newPortMapPlugin(), newFirewallPlugin(), newTuningPlugin())
- // if we find the dnsname plugin we add configuration for it
- if hasDNSNamePlugin(n.cniPluginDirs) && network.DNSEnabled {
- // Note: in the future we might like to allow for dynamic domain names
- plugins = append(plugins, newDNSNamePlugin(defaultPodmanDomainName))
- }
-
- case types.MacVLANNetworkDriver:
- plugins = append(plugins, newVLANPlugin(types.MacVLANNetworkDriver, network.NetworkInterface, vlanPluginMode, mtu, ipamConf))
-
- case types.IPVLANNetworkDriver:
- plugins = append(plugins, newVLANPlugin(types.IPVLANNetworkDriver, network.NetworkInterface, vlanPluginMode, mtu, ipamConf))
-
- default:
- return nil, "", errors.Errorf("driver %q is not supported by cni", network.Driver)
- }
- ncList["plugins"] = plugins
- b, err := json.MarshalIndent(ncList, "", " ")
- if err != nil {
- return nil, "", err
- }
- cniPathName := ""
- if writeToDisk {
- cniPathName = filepath.Join(n.cniConfigDir, network.Name+".conflist")
- err = ioutil.WriteFile(cniPathName, b, 0644)
- if err != nil {
- return nil, "", err
- }
- f, err := os.Stat(cniPathName)
- if err != nil {
- return nil, "", err
- }
- stat := f.Sys().(*syscall.Stat_t)
- network.Created = time.Unix(int64(stat.Ctim.Sec), int64(stat.Ctim.Nsec))
- } else {
- network.Created = time.Now()
- }
- config, err := libcni.ConfListFromBytes(b)
- if err != nil {
- return nil, "", err
- }
- return config, cniPathName, nil
-}
-
-func convertSpecgenPortsToCNIPorts(ports []types.PortMapping) ([]cniPortMapEntry, error) {
- cniPorts := make([]cniPortMapEntry, 0, len(ports))
- for _, port := range ports {
- if port.Protocol == "" {
- return nil, errors.New("port protocol should not be empty")
- }
- protocols := strings.Split(port.Protocol, ",")
-
- for _, protocol := range protocols {
- if !pkgutil.StringInSlice(protocol, []string{"tcp", "udp", "sctp"}) {
- return nil, errors.Errorf("unknown port protocol %s", protocol)
- }
- cniPort := cniPortMapEntry{
- HostPort: int(port.HostPort),
- ContainerPort: int(port.ContainerPort),
- HostIP: port.HostIP,
- Protocol: protocol,
- }
- cniPorts = append(cniPorts, cniPort)
- for i := 1; i < int(port.Range); i++ {
- cniPort := cniPortMapEntry{
- HostPort: int(port.HostPort) + i,
- ContainerPort: int(port.ContainerPort) + i,
- HostIP: port.HostIP,
- Protocol: protocol,
- }
- cniPorts = append(cniPorts, cniPort)
- }
- }
- }
- return cniPorts, nil
-}
-
-func removeMachinePlugin(conf *libcni.NetworkConfigList) *libcni.NetworkConfigList {
- plugins := make([]*libcni.NetworkConfig, 0, len(conf.Plugins))
- for _, net := range conf.Plugins {
- if net.Network.Type != "podman-machine" {
- plugins = append(plugins, net)
- }
- }
- conf.Plugins = plugins
- return conf
-}