summaryrefslogtreecommitdiff
path: root/libpod/network/network.go
diff options
context:
space:
mode:
authorPaul Holzinger <pholzing@redhat.com>2021-08-16 16:11:26 +0200
committerPaul Holzinger <pholzing@redhat.com>2021-09-15 20:00:20 +0200
commit85e8fbf7f33717ef6a0d6cf9e2143b52c874c2de (patch)
tree82b0c29102d2779c18ea8a6f10df5dc1139e3817 /libpod/network/network.go
parent218f132fdf4939d9e0374ef860d534f19e71df54 (diff)
downloadpodman-85e8fbf7f33717ef6a0d6cf9e2143b52c874c2de.tar.gz
podman-85e8fbf7f33717ef6a0d6cf9e2143b52c874c2de.tar.bz2
podman-85e8fbf7f33717ef6a0d6cf9e2143b52c874c2de.zip
Wire network interface into libpod
Make use of the new network interface in libpod. This commit contains several breaking changes: - podman network create only outputs the new network name and not file path. - podman network ls shows the network driver instead of the cni version and plugins. - podman network inspect outputs the new network struct and not the cni conflist. - The bindings and libpod api endpoints have been changed to use the new network structure. The container network status is stored in a new field in the state. The status should be received with the new `c.getNetworkStatus`. This will migrate the old status to the new format. Therefore old containers should contine to work correctly in all cases even when network connect/ disconnect is used. New features: - podman network reload keeps the ip and mac for more than one network. - podman container restore keeps the ip and mac for more than one network. - The network create compat endpoint can now use more than one ipam config. The man pages and the swagger doc are updated to reflect the latest changes. Signed-off-by: Paul Holzinger <pholzing@redhat.com>
Diffstat (limited to 'libpod/network/network.go')
-rw-r--r--libpod/network/network.go288
1 files changed, 0 insertions, 288 deletions
diff --git a/libpod/network/network.go b/libpod/network/network.go
deleted file mode 100644
index 3b81ce776..000000000
--- a/libpod/network/network.go
+++ /dev/null
@@ -1,288 +0,0 @@
-package network
-
-import (
- "encoding/json"
- "net"
- "os"
-
- "github.com/containernetworking/cni/libcni"
- "github.com/containernetworking/cni/pkg/types"
- "github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator"
- "github.com/containers/common/pkg/config"
- "github.com/containers/podman/v3/libpod/define"
- "github.com/containers/podman/v3/pkg/domain/entities"
- "github.com/containers/podman/v3/pkg/rootless"
- "github.com/containers/podman/v3/pkg/util"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
-)
-
-var (
- // BridgeNetworkDriver defines the bridge cni driver
- BridgeNetworkDriver = "bridge"
- // DefaultNetworkDriver is the default network type used
- DefaultNetworkDriver = BridgeNetworkDriver
- // MacVLANNetworkDriver defines the macvlan cni driver
- MacVLANNetworkDriver = "macvlan"
-)
-
-// SupportedNetworkDrivers describes the list of supported drivers
-var SupportedNetworkDrivers = []string{BridgeNetworkDriver, MacVLANNetworkDriver}
-
-// isSupportedDriver checks if the user provided driver is supported
-func isSupportedDriver(driver string) error {
- if util.StringInSlice(driver, SupportedNetworkDrivers) {
- return nil
- }
- return errors.Errorf("driver '%s' is not supported", driver)
-}
-
-// GetLiveNetworks returns a slice of networks representing what the system
-// has defined as network interfaces
-func GetLiveNetworks() ([]*net.IPNet, error) {
- addrs, err := net.InterfaceAddrs()
- if err != nil {
- return nil, err
- }
- nets := make([]*net.IPNet, 0, len(addrs))
- for _, address := range addrs {
- _, n, err := net.ParseCIDR(address.String())
- if err != nil {
- return nil, err
- }
- nets = append(nets, n)
- }
- return nets, nil
-}
-
-// GetLiveNetworkNames returns a list of network interfaces on the system
-func GetLiveNetworkNames() ([]string, error) {
- liveInterfaces, err := net.Interfaces()
- if err != nil {
- return nil, err
- }
- interfaceNames := make([]string, 0, len(liveInterfaces))
- for _, i := range liveInterfaces {
- interfaceNames = append(interfaceNames, i.Name)
- }
- return interfaceNames, nil
-}
-
-// GetFreeNetwork looks for a free network according to existing cni configuration
-// files and network interfaces.
-func GetFreeNetwork(config *config.Config) (*net.IPNet, error) {
- networks, err := GetNetworksFromFilesystem(config)
- if err != nil {
- return nil, err
- }
- liveNetworks, err := GetLiveNetworks()
- if err != nil {
- return nil, err
- }
- nextNetwork, err := GetDefaultPodmanNetwork()
- if err != nil {
- return nil, err
- }
- logrus.Debugf("default network is %s", nextNetwork.String())
- for {
- newNetwork, err := NextSubnet(nextNetwork)
- if err != nil {
- return nil, err
- }
- logrus.Debugf("checking if network %s intersects with other cni networks", nextNetwork.String())
- if intersectsConfig, _ := networkIntersectsWithNetworks(newNetwork, allocatorToIPNets(networks)); intersectsConfig {
- logrus.Debugf("network %s is already being used by a cni configuration", nextNetwork.String())
- nextNetwork = newNetwork
- continue
- }
- logrus.Debugf("checking if network %s intersects with any network interfaces", nextNetwork.String())
- if intersectsLive, _ := networkIntersectsWithNetworks(newNetwork, liveNetworks); !intersectsLive {
- break
- }
- logrus.Debugf("network %s is being used by a network interface", nextNetwork.String())
- nextNetwork = newNetwork
- }
- return nextNetwork, nil
-}
-
-func allocatorToIPNets(networks []*allocator.Net) []*net.IPNet {
- var nets []*net.IPNet
- for _, network := range networks {
- if len(network.IPAM.Ranges) > 0 {
- // this is the new IPAM range style
- // append each subnet from ipam the rangeset
- for _, allocatorRange := range network.IPAM.Ranges {
- for _, r := range allocatorRange {
- nets = append(nets, newIPNetFromSubnet(r.Subnet))
- }
- }
- } else {
- // looks like the old, deprecated style
- nets = append(nets, newIPNetFromSubnet(network.IPAM.Subnet))
- }
- }
- return nets
-}
-
-func newIPNetFromSubnet(subnet types.IPNet) *net.IPNet {
- n := net.IPNet{
- IP: subnet.IP,
- Mask: subnet.Mask,
- }
- return &n
-}
-
-func networkIntersectsWithNetworks(n *net.IPNet, networklist []*net.IPNet) (bool, *net.IPNet) {
- for _, nw := range networklist {
- if networkIntersect(n, nw) {
- return true, nw
- }
- }
- return false, nil
-}
-
-func networkIntersect(n1, n2 *net.IPNet) bool {
- return n2.Contains(n1.IP) || n1.Contains(n2.IP)
-}
-
-// ValidateUserNetworkIsAvailable returns via an error if a network is available
-// to be used
-func ValidateUserNetworkIsAvailable(config *config.Config, userNet *net.IPNet) error {
- if len(userNet.IP) == 0 || len(userNet.Mask) == 0 {
- return errors.Errorf("network %s's ip or mask cannot be empty", userNet.String())
- }
-
- ones, bit := userNet.Mask.Size()
- if ones == 0 || bit == 0 {
- return errors.Errorf("network %s's mask is invalid", userNet.String())
- }
-
- networks, err := GetNetworksFromFilesystem(config)
- if err != nil {
- return err
- }
- liveNetworks, err := GetLiveNetworks()
- if err != nil {
- return err
- }
- logrus.Debugf("checking if network %s exists in cni networks", userNet.String())
- if intersectsConfig, _ := networkIntersectsWithNetworks(userNet, allocatorToIPNets(networks)); intersectsConfig {
- return errors.Errorf("network %s is already being used by a cni configuration", userNet.String())
- }
- logrus.Debugf("checking if network %s exists in any network interfaces", userNet.String())
- if intersectsLive, _ := networkIntersectsWithNetworks(userNet, liveNetworks); intersectsLive {
- return errors.Errorf("network %s is being used by a network interface", userNet.String())
- }
- return nil
-}
-
-// removeNetwork is removes a cni network without a lock and should only be called
-// when a lock was otherwise acquired.
-func removeNetwork(config *config.Config, name string) error {
- cniPath, err := GetCNIConfigPathByNameOrID(config, name)
- if err != nil {
- return err
- }
- // Before we delete the configuration file, we need to make sure we can read and parse
- // it to get the network interface name so we can remove that too
- interfaceName, err := GetInterfaceNameFromConfig(cniPath)
- if err == nil {
- // Don't try to remove the network interface if we are not root
- if !rootless.IsRootless() {
- liveNetworkNames, err := GetLiveNetworkNames()
- if err != nil {
- return errors.Wrapf(err, "failed to get live network names")
- }
- if util.StringInSlice(interfaceName, liveNetworkNames) {
- if err = RemoveInterface(interfaceName); err != nil {
- // only log the error, it is not fatal
- logrus.Infof("failed to remove network interface %s: %v", interfaceName, err)
- }
- }
- }
- } else if err != ErrNoSuchNetworkInterface {
- // Don't error if we couldn't find the network interface name
- return err
- }
- // Remove the configuration file
- if err := os.Remove(cniPath); err != nil {
- return errors.Wrap(err, "failed to remove network configuration")
- }
- return nil
-}
-
-// RemoveNetwork removes a given network by name. If the network has container associated with it, that
-// must be handled outside the context of this.
-func RemoveNetwork(config *config.Config, name string) error {
- l, err := acquireCNILock(config)
- if err != nil {
- return err
- }
- defer l.releaseCNILock()
- return removeNetwork(config, name)
-}
-
-// InspectNetwork reads a CNI config and returns its configuration
-func InspectNetwork(config *config.Config, name string) (map[string]interface{}, error) {
- b, err := ReadRawCNIConfByNameOrID(config, name)
- if err != nil {
- return nil, err
- }
- rawList := make(map[string]interface{})
- err = json.Unmarshal(b, &rawList)
- return rawList, err
-}
-
-// Exists says whether a given network exists or not; it meant
-// specifically for restful responses so 404s can be used
-func Exists(config *config.Config, name string) (bool, error) {
- _, err := ReadRawCNIConfByNameOrID(config, name)
- if err != nil {
- if errors.Cause(err) == define.ErrNoSuchNetwork {
- return false, nil
- }
- return false, err
- }
- return true, nil
-}
-
-// PruneNetworks removes networks that are not being used and that is not the default
-// network. To keep proper fencing for imports, you must provide the used networks
-// to this function as a map. the key is meaningful in the map, the book is a no-op
-func PruneNetworks(rtc *config.Config, usedNetworks map[string]bool) ([]*entities.NetworkPruneReport, error) {
- var reports []*entities.NetworkPruneReport
- lock, err := acquireCNILock(rtc)
- if err != nil {
- return nil, err
- }
- defer lock.releaseCNILock()
- nets, err := GetNetworkNamesFromFileSystem(rtc)
- if err != nil {
- return nil, err
- }
- for _, n := range nets {
- _, found := usedNetworks[n]
- // Remove is not default network and not found in the used list
- if n != rtc.Network.DefaultNetwork && !found {
- reports = append(reports, &entities.NetworkPruneReport{
- Name: n,
- Error: removeNetwork(rtc, n),
- })
- }
- }
- return reports, nil
-}
-
-// NormalizeName translates a network ID into a name.
-// If the input is a name the name is returned.
-func NormalizeName(config *config.Config, nameOrID string) (string, error) {
- path, err := GetCNIConfigPathByNameOrID(config, nameOrID)
- if err != nil {
- return "", err
- }
- conf, err := libcni.ConfListFromFile(path)
- if err != nil {
- return "", err
- }
- return conf.Name, nil
-}