summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libpod/boltdb_state.go172
-rw-r--r--libpod/container.go57
-rw-r--r--libpod/container_internal_linux.go42
-rw-r--r--libpod/networking_linux.go215
-rw-r--r--libpod/state.go6
5 files changed, 226 insertions, 266 deletions
diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go
index 1242a8d6b..d322ccc53 100644
--- a/libpod/boltdb_state.go
+++ b/libpod/boltdb_state.go
@@ -2,11 +2,14 @@ package libpod
import (
"bytes"
+ "fmt"
+ "net"
"os"
"strings"
"sync"
"github.com/containers/podman/v3/libpod/define"
+ "github.com/containers/podman/v3/libpod/network/types"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -971,7 +974,7 @@ func (s *BoltState) AllContainers() ([]*Container, error) {
}
// GetNetworks returns the CNI networks this container is a part of.
-func (s *BoltState) GetNetworks(ctr *Container) ([]string, error) {
+func (s *BoltState) GetNetworks(ctr *Container) (map[string]types.PerNetworkOptions, error) {
if !s.valid {
return nil, define.ErrDBClosed
}
@@ -984,6 +987,11 @@ func (s *BoltState) GetNetworks(ctr *Container) ([]string, error) {
return nil, errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace)
}
+ // if the network mode is not bridge return no networks
+ if !ctr.config.NetMode.IsBridge() {
+ return nil, nil
+ }
+
ctrID := []byte(ctr.ID())
db, err := s.getDBCon()
@@ -992,7 +1000,9 @@ func (s *BoltState) GetNetworks(ctr *Container) ([]string, error) {
}
defer s.deferredCloseDBCon(db)
- networks := []string{}
+ networks := make(map[string]types.PerNetworkOptions)
+
+ var convertDB bool
err = db.View(func(tx *bolt.Tx) error {
ctrBucket, err := getCtrBucket(tx)
@@ -1008,17 +1018,131 @@ func (s *BoltState) GetNetworks(ctr *Container) ([]string, error) {
ctrNetworkBkt := dbCtr.Bucket(networksBkt)
if ctrNetworkBkt == nil {
- return errors.Wrapf(define.ErrNoSuchNetwork, "container %s is not joined to any CNI networks", ctr.ID())
+ // convert if needed
+ convertDB = true
+ return nil
}
return ctrNetworkBkt.ForEach(func(network, v []byte) error {
- networks = append(networks, string(network))
+ opts := types.PerNetworkOptions{}
+ if err := json.Unmarshal(v, &opts); err != nil {
+ // special case for backwards compat
+ // earlier version used the container id as value so we set a
+ // special error to indicate the we have to migrate the db
+ if !bytes.Equal(v, ctrID) {
+ return err
+ }
+ convertDB = true
+ }
+ networks[string(network)] = opts
return nil
})
})
if err != nil {
return nil, err
}
+ if convertDB {
+ err = db.Update(func(tx *bolt.Tx) error {
+ ctrBucket, err := getCtrBucket(tx)
+ if err != nil {
+ return err
+ }
+
+ dbCtr := ctrBucket.Bucket(ctrID)
+ if dbCtr == nil {
+ ctr.valid = false
+ return errors.Wrapf(define.ErrNoSuchCtr, "container %s does not exist in database", ctr.ID())
+ }
+
+ var networkList []string
+
+ ctrNetworkBkt := dbCtr.Bucket(networksBkt)
+ if ctrNetworkBkt == nil {
+ ctrNetworkBkt, err = dbCtr.CreateBucket(networksBkt)
+ if err != nil {
+ return errors.Wrapf(err, "error creating networks bucket for container %s", ctr.ID())
+ }
+ // the container has no networks in the db lookup config and write to the db
+ networkList = ctr.config.Networks
+ // if there are no networks we have to add the default
+ if len(networkList) == 0 {
+ networkList = []string{ctr.runtime.config.Network.DefaultNetwork}
+ }
+ } else {
+ err = ctrNetworkBkt.ForEach(func(network, v []byte) error {
+ networkList = append(networkList, string(network))
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ }
+
+ // the container has no networks in the db lookup config and write to the db
+ for i, network := range networkList {
+ var intName string
+ if ctr.state.NetInterfaceDescriptions != nil {
+ eth, exists := ctr.state.NetInterfaceDescriptions.getInterfaceByName(network)
+ if !exists {
+ return errors.Errorf("no network interface name for container %s on network %s", ctr.config.ID, network)
+ }
+ intName = eth
+ } else {
+ intName = fmt.Sprintf("eth%d", i)
+ }
+ getAliases := func(network string) []string {
+ var aliases []string
+ ctrAliasesBkt := dbCtr.Bucket(aliasesBkt)
+ if ctrAliasesBkt == nil {
+ return nil
+ }
+ netAliasesBkt := ctrAliasesBkt.Bucket([]byte(network))
+ if netAliasesBkt == nil {
+ // No aliases for this specific network.
+ return nil
+ }
+
+ // lets ignore the error here there is nothing we can do
+ _ = netAliasesBkt.ForEach(func(alias, v []byte) error {
+ aliases = append(aliases, string(alias))
+ return nil
+ })
+ // also add the short container id as alias
+ return aliases
+ }
+
+ netOpts := &types.PerNetworkOptions{
+ InterfaceName: intName,
+ // we have to add the short id as alias for docker compat
+ Aliases: append(getAliases(network), ctr.config.ID[:12]),
+ }
+ // only set the static ip/mac on the first network
+ if i == 0 {
+ if ctr.config.StaticIP != nil {
+ netOpts.StaticIPs = []net.IP{ctr.config.StaticIP}
+ }
+ netOpts.StaticMAC = ctr.config.StaticMAC
+ }
+
+ optsBytes, err := json.Marshal(netOpts)
+ if err != nil {
+ return err
+ }
+ // insert into network map because we need to return this
+ networks[network] = *netOpts
+
+ err = ctrNetworkBkt.Put([]byte(network), optsBytes)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+ })
+ if err != nil {
+ return nil, err
+ }
+ }
+
return networks, nil
}
@@ -1173,7 +1297,7 @@ func (s *BoltState) GetAllNetworkAliases(ctr *Container) (map[string][]string, e
// NetworkConnect adds the given container to the given network. If aliases are
// specified, those will be added to the given network.
-func (s *BoltState) NetworkConnect(ctr *Container, network string, aliases []string) error {
+func (s *BoltState) NetworkConnect(ctr *Container, network string, opts types.PerNetworkOptions) error {
if !s.valid {
return define.ErrDBClosed
}
@@ -1190,6 +1314,11 @@ func (s *BoltState) NetworkConnect(ctr *Container, network string, aliases []str
return errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace)
}
+ optBytes, err := json.Marshal(opts)
+ if err != nil {
+ return errors.Wrapf(err, "error marshalling network options JSON for container %s", ctr.ID())
+ }
+
ctrID := []byte(ctr.ID())
db, err := s.getDBCon()
@@ -1210,47 +1339,20 @@ func (s *BoltState) NetworkConnect(ctr *Container, network string, aliases []str
return errors.Wrapf(define.ErrNoSuchCtr, "container %s does not exist in database", ctr.ID())
}
- ctrAliasesBkt, err := dbCtr.CreateBucketIfNotExists(aliasesBkt)
- if err != nil {
- return errors.Wrapf(err, "error creating aliases bucket for container %s", ctr.ID())
- }
-
ctrNetworksBkt := dbCtr.Bucket(networksBkt)
if ctrNetworksBkt == nil {
- ctrNetworksBkt, err = dbCtr.CreateBucket(networksBkt)
- if err != nil {
- return errors.Wrapf(err, "error creating networks bucket for container %s", ctr.ID())
- }
- ctrNetworks := ctr.config.Networks
- if len(ctrNetworks) == 0 {
- ctrNetworks = []string{ctr.runtime.config.Network.DefaultNetwork}
- }
- // Copy in all the container's CNI networks
- for _, net := range ctrNetworks {
- if err := ctrNetworksBkt.Put([]byte(net), ctrID); err != nil {
- return errors.Wrapf(err, "error adding container %s network %s to DB", ctr.ID(), net)
- }
- }
+ return errors.Wrapf(define.ErrNoSuchNetwork, "container %s does not have a network bucket", ctr.ID())
}
netConnected := ctrNetworksBkt.Get([]byte(network))
if netConnected != nil {
- return errors.Wrapf(define.ErrNetworkExists, "container %s is already connected to CNI network %q", ctr.ID(), network)
+ return errors.Wrapf(define.ErrNetworkExists, "container %s is already connected to network %q", ctr.ID(), network)
}
// Add the network
- if err := ctrNetworksBkt.Put([]byte(network), ctrID); err != nil {
+ if err := ctrNetworksBkt.Put([]byte(network), optBytes); err != nil {
return errors.Wrapf(err, "error adding container %s to network %s in DB", ctr.ID(), network)
}
- ctrNetAliasesBkt, err := ctrAliasesBkt.CreateBucketIfNotExists([]byte(network))
- if err != nil {
- return errors.Wrapf(err, "error adding container %s network aliases bucket for network %s", ctr.ID(), network)
- }
- for _, alias := range aliases {
- if err := ctrNetAliasesBkt.Put([]byte(alias), ctrID); err != nil {
- return errors.Wrapf(err, "error adding container %s network alias %s for network %s", ctr.ID(), alias, network)
- }
- }
return nil
})
}
diff --git a/libpod/container.go b/libpod/container.go
index 2b74a1943..006661d5b 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -1176,7 +1176,18 @@ func (c *Container) Networks() ([]string, bool, error) {
}
}
- return c.networks()
+ networks, err := c.networks()
+ if err != nil {
+ return nil, false, err
+ }
+
+ names := make([]string, 0, len(networks))
+
+ for name := range networks {
+ names = append(names, name)
+ }
+
+ return names, false, nil
}
// NetworkMode gets the configured network mode for the container.
@@ -1220,36 +1231,8 @@ func (c *Container) NetworkMode() string {
}
// Unlocked accessor for networks
-func (c *Container) networks() ([]string, bool, error) {
- networks, err := c.runtime.state.GetNetworks(c)
- if err != nil && errors.Cause(err) == define.ErrNoSuchNetwork {
- if len(c.config.Networks) == 0 && c.config.NetMode.IsBridge() {
- return []string{c.runtime.config.Network.DefaultNetwork}, true, nil
- }
- return c.config.Networks, false, nil
- }
-
- return networks, false, err
-}
-
-// networksByNameIndex provides us with a map of container networks where key
-// is network name and value is the index position
-func (c *Container) networksByNameIndex() (map[string]int, error) {
- networks, _, err := c.networks()
- if err != nil {
- return nil, err
- }
- networkNamesByIndex := make(map[string]int, len(networks))
- for index, name := range networks {
- networkNamesByIndex[name] = index
- }
- return networkNamesByIndex, nil
-}
-
-// add puts the new given CNI network name into the tracking map
-// and assigns it a new integer based on the map length
-func (d ContainerNetworkDescriptions) add(networkName string) {
- d[networkName] = len(d)
+func (c *Container) networks() (map[string]types.PerNetworkOptions, error) {
+ return c.runtime.state.GetNetworks(c)
}
// getInterfaceByName returns a formatted interface name for a given
@@ -1270,9 +1253,7 @@ func (c *Container) getNetworkStatus() map[string]types.StatusBlock {
return c.state.NetworkStatus
}
if c.state.NetworkStatusOld != nil {
- // Note: NetworkStatusOld does not contain the network names so we get them extra
- // Generally the order should be the same
- networks, _, err := c.networks()
+ networks, err := c.networks()
if err != nil {
return nil
}
@@ -1280,12 +1261,16 @@ func (c *Container) getNetworkStatus() map[string]types.StatusBlock {
return nil
}
result := make(map[string]types.StatusBlock, len(c.state.NetworkStatusOld))
- for i := range c.state.NetworkStatusOld {
+ i := 0
+ // Note: NetworkStatusOld does not contain the network names so we get them extra
+ // We cannot guarantee the same order but after a state refresh it should work
+ for netName := range networks {
status, err := cni.CNIResultToStatus(c.state.NetworkStatusOld[i])
if err != nil {
return nil
}
- result[networks[i]] = status
+ result[netName] = status
+ i++
}
c.state.NetworkStatus = result
_ = c.save()
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index ef9f13f44..f4b629a83 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -1293,23 +1293,6 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
return nil, 0, err
}
- // If a container is restored multiple times from an exported checkpoint with
- // the help of '--import --name', the restore will fail if during 'podman run'
- // a static container IP was set with '--ip'. The user can tell the restore
- // process to ignore the static IP with '--ignore-static-ip'
- if options.IgnoreStaticIP {
- c.config.StaticIP = nil
- }
-
- // If a container is restored multiple times from an exported checkpoint with
- // the help of '--import --name', the restore will fail if during 'podman run'
- // a static container MAC address was set with '--mac-address'. The user
- // can tell the restore process to ignore the static MAC with
- // '--ignore-static-mac'
- if options.IgnoreStaticMAC {
- c.config.StaticMAC = nil
- }
-
// Read network configuration from checkpoint
var netStatus map[string]types.StatusBlock
_, err := metadata.ReadJSONFile(&netStatus, c.bundlePath(), metadata.NetworkStatusFile)
@@ -1325,19 +1308,19 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
if err == nil && options.Name == "" && (!options.IgnoreStaticIP || !options.IgnoreStaticMAC) {
// The file with the network.status does exist. Let's restore the
// container with the same networks settings as during checkpointing.
- aliases, err := c.GetAllNetworkAliases()
+ networkOpts, err := c.networks()
if err != nil {
return nil, 0, err
}
+
netOpts := make(map[string]types.PerNetworkOptions, len(netStatus))
- for network, status := range netStatus {
- perNetOpts := types.PerNetworkOptions{}
- for name, netInt := range status.Interfaces {
- perNetOpts = types.PerNetworkOptions{
- InterfaceName: name,
- Aliases: aliases[network],
- }
- if !options.IgnoreStaticMAC {
+ for network, perNetOpts := range networkOpts {
+ // unset mac and ips before we start adding the ones from the status
+ perNetOpts.StaticMAC = nil
+ perNetOpts.StaticIPs = nil
+ for name, netInt := range netStatus[network].Interfaces {
+ perNetOpts.InterfaceName = name
+ if !options.IgnoreStaticIP {
perNetOpts.StaticMAC = netInt.MacAddress
}
if !options.IgnoreStaticIP {
@@ -1349,13 +1332,6 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
// For now just use the first interface to get the ips this should be good enough for most cases.
break
}
- if perNetOpts.InterfaceName == "" {
- eth, exists := c.state.NetInterfaceDescriptions.getInterfaceByName(network)
- if !exists {
- return nil, 0, errors.Errorf("no network interface name for container %s on network %s", c.config.ID, network)
- }
- perNetOpts.InterfaceName = eth
- }
netOpts[network] = perNetOpts
}
c.perNetworkOpts = netOpts
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index 5fb97dd73..3f56be855 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -53,41 +53,6 @@ const (
persistentCNIDir = "/var/lib/cni"
)
-// GetAllNetworkAliases returns all configured aliases for this container.
-// It also adds the container short ID as alias to match docker.
-func (c *Container) GetAllNetworkAliases() (map[string][]string, error) {
- allAliases, err := c.runtime.state.GetAllNetworkAliases(c)
- if err != nil {
- return nil, err
- }
-
- // get the all attached networks, we cannot use GetAllNetworkAliases()
- // since it returns nil if there are no aliases
- nets, _, err := c.networks()
- if err != nil {
- return nil, err
- }
-
- // add container short ID as alias to match docker
- for _, net := range nets {
- allAliases[net] = append(allAliases[net], c.config.ID[:12])
- }
- return allAliases, nil
-}
-
-// GetNetworkAliases returns configured aliases for this network.
-// It also adds the container short ID as alias to match docker.
-func (c *Container) GetNetworkAliases(netName string) ([]string, error) {
- aliases, err := c.runtime.state.GetNetworkAliases(c, netName)
- if err != nil {
- return nil, err
- }
-
- // add container short ID as alias to match docker
- aliases = append(aliases, c.config.ID[:12])
- return aliases, nil
-}
-
// convertPortMappings will remove the HostIP part from the ports when running inside podman machine.
// This is need because a HostIP of 127.0.0.1 would now allow the gvproxy forwarder to reach to open ports.
// For machine the HostIP must only be used by gvproxy and never in the VM.
@@ -104,53 +69,20 @@ func (c *Container) convertPortMappings() []types.PortMapping {
return newPorts
}
-func (c *Container) getNetworkOptions() (types.NetworkOptions, error) {
+func (c *Container) getNetworkOptions(networkOpts map[string]types.PerNetworkOptions) (types.NetworkOptions, error) {
opts := types.NetworkOptions{
ContainerID: c.config.ID,
ContainerName: getCNIPodName(c),
}
opts.PortMappings = c.convertPortMappings()
- networks, _, err := c.networks()
- if err != nil {
- return opts, err
- }
- aliases, err := c.GetAllNetworkAliases()
- if err != nil {
- return opts, err
- }
// If the container requested special network options use this instead of the config.
// This is the case for container restore or network reload.
if c.perNetworkOpts != nil {
opts.Networks = c.perNetworkOpts
- return opts, nil
- }
-
- // Update container map of interface descriptions
- if err := c.setupNetworkDescriptions(networks); err != nil {
- return opts, err
- }
-
- nets := make(map[string]types.PerNetworkOptions, len(networks))
- for i, network := range networks {
- eth, exists := c.state.NetInterfaceDescriptions.getInterfaceByName(network)
- if !exists {
- return opts, errors.Errorf("no network interface name for container %s on network %s", c.config.ID, network)
- }
- netOpts := types.PerNetworkOptions{
- InterfaceName: eth,
- Aliases: aliases[network],
- }
- // only set the static ip/mac on the first network
- if i == 0 {
- if c.config.StaticIP != nil {
- netOpts.StaticIPs = []net.IP{c.config.StaticIP}
- }
- netOpts.StaticMAC = c.config.StaticMAC
- }
- nets[network] = netOpts
+ } else {
+ opts.Networks = networkOpts
}
- opts.Networks = nets
return opts, nil
}
@@ -697,7 +629,7 @@ func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) (status map[str
if ctr.config.NetMode.IsSlirp4netns() {
return nil, r.setupSlirp4netns(ctr, ctrNS)
}
- networks, _, err := ctr.networks()
+ networks, err := ctr.networks()
if err != nil {
return nil, err
}
@@ -707,7 +639,7 @@ func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) (status map[str
return nil, nil
}
- netOpts, err := ctr.getNetworkOptions()
+ netOpts, err := ctr.getNetworkOptions(networks)
if err != nil {
return nil, err
}
@@ -862,13 +794,13 @@ func (r *Runtime) teardownCNI(ctr *Container) error {
logrus.Debugf("Tearing down network namespace at %s for container %s", ctr.state.NetNS.Path(), ctr.ID())
- networks, _, err := ctr.networks()
+ networks, err := ctr.networks()
if err != nil {
return err
}
if !ctr.config.NetMode.IsSlirp4netns() && len(networks) > 0 {
- netOpts, err := ctr.getNetworkOptions()
+ netOpts, err := ctr.getNetworkOptions(networks)
if err != nil {
return err
}
@@ -960,22 +892,17 @@ func (r *Runtime) reloadContainerNetwork(ctr *Container) (map[string]types.Statu
}
}
- aliases, err := ctr.GetAllNetworkAliases()
+ networkOpts, err := ctr.networks()
if err != nil {
return nil, err
}
// Set the same network settings as before..
netStatus := ctr.getNetworkStatus()
- netOpts := make(map[string]types.PerNetworkOptions, len(netStatus))
- for network, status := range netStatus {
- perNetOpts := types.PerNetworkOptions{}
- for name, netInt := range status.Interfaces {
- perNetOpts = types.PerNetworkOptions{
- InterfaceName: name,
- Aliases: aliases[network],
- StaticMAC: netInt.MacAddress,
- }
+ for network, perNetOpts := range networkOpts {
+ for name, netInt := range netStatus[network].Interfaces {
+ perNetOpts.InterfaceName = name
+ perNetOpts.StaticMAC = netInt.MacAddress
for _, netAddress := range netInt.Subnets {
perNetOpts.StaticIPs = append(perNetOpts.StaticIPs, netAddress.IPNet.IP)
}
@@ -983,16 +910,9 @@ func (r *Runtime) reloadContainerNetwork(ctr *Container) (map[string]types.Statu
// For now just use the first interface to get the ips this should be good enough for most cases.
break
}
- if perNetOpts.InterfaceName == "" {
- eth, exists := ctr.state.NetInterfaceDescriptions.getInterfaceByName(network)
- if !exists {
- return nil, errors.Errorf("no network interface name for container %s on network %s", ctr.config.ID, network)
- }
- perNetOpts.InterfaceName = eth
- }
- netOpts[network] = perNetOpts
+ networkOpts[network] = perNetOpts
}
- ctr.perNetworkOpts = netOpts
+ ctr.perNetworkOpts = networkOpts
return r.configureNetNS(ctr, ctr.state.NetNS)
}
@@ -1049,7 +969,7 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e
settings := new(define.InspectNetworkSettings)
settings.Ports = makeInspectPortBindings(c.config.PortMappings, c.config.ExposedPorts)
- networks, isDefault, err := c.networks()
+ networks, err := c.networks()
if err != nil {
return nil, err
}
@@ -1060,14 +980,10 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e
// the container joined.
if len(networks) > 0 {
settings.Networks = make(map[string]*define.InspectAdditionalNetwork, len(networks))
- for _, net := range networks {
+ for net, opts := range networks {
cniNet := new(define.InspectAdditionalNetwork)
cniNet.NetworkID = net
- aliases, err := c.GetNetworkAliases(net)
- if err != nil {
- return nil, err
- }
- cniNet.Aliases = aliases
+ cniNet.Aliases = opts.Aliases
settings.Networks[net] = cniNet
}
}
@@ -1092,7 +1008,7 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e
settings.Networks = make(map[string]*define.InspectAdditionalNetwork)
- for _, name := range networks {
+ for name, opts := range networks {
result := netStatus[name]
addedNet := new(define.InspectAdditionalNetwork)
addedNet.NetworkID = name
@@ -1101,19 +1017,17 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e
if err != nil {
return nil, err
}
-
- aliases, err := c.GetNetworkAliases(name)
- if err != nil {
- return nil, err
- }
- addedNet.Aliases = aliases
+ addedNet.Aliases = opts.Aliases
addedNet.InspectBasicNetworkConfig = basicConfig
settings.Networks[name] = addedNet
}
- if !isDefault {
+ // if not only the default network is connected we can return here
+ // otherwise we have to populate the InspectBasicNetworkConfig settings
+ _, isDefaultNet := networks[c.runtime.config.Network.DefaultNetwork]
+ if !(len(networks) == 1 && isDefaultNet) {
return settings, nil
}
}
@@ -1135,29 +1049,6 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e
return settings, nil
}
-// setupNetworkDescriptions adds networks and eth values to the container's
-// network descriptions
-func (c *Container) setupNetworkDescriptions(networks []string) error {
- // if the map is nil and we have networks
- if c.state.NetInterfaceDescriptions == nil && len(networks) > 0 {
- c.state.NetInterfaceDescriptions = make(ContainerNetworkDescriptions)
- }
- origLen := len(c.state.NetInterfaceDescriptions)
- for _, n := range networks {
- // if the network is not in the map, add it
- if _, exists := c.state.NetInterfaceDescriptions[n]; !exists {
- c.state.NetInterfaceDescriptions.add(n)
- }
- }
- // if the map changed, we need to save the container state
- if origLen != len(c.state.NetInterfaceDescriptions) {
- if err := c.save(); err != nil {
- return err
- }
- }
- return nil
-}
-
// resultToBasicNetworkConfig produces an InspectBasicNetworkConfig from a CNI
// result
func resultToBasicNetworkConfig(result types.StatusBlock) (define.InspectBasicNetworkConfig, error) {
@@ -1213,7 +1104,7 @@ func (c *Container) NetworkDisconnect(nameOrID, netName string, force bool) erro
c.lock.Lock()
defer c.lock.Unlock()
- networks, err := c.networksByNameIndex()
+ networks, err := c.networks()
if err != nil {
return err
}
@@ -1254,14 +1145,8 @@ func (c *Container) NetworkDisconnect(nameOrID, netName string, force bool) erro
ContainerName: getCNIPodName(c),
}
opts.PortMappings = c.convertPortMappings()
- eth, exists := c.state.NetInterfaceDescriptions.getInterfaceByName(netName)
- if !exists {
- return errors.Errorf("no network interface name for container %s on network %s", c.config.ID, netName)
- }
opts.Networks = map[string]types.PerNetworkOptions{
- netName: {
- InterfaceName: eth,
- },
+ netName: networks[netName],
}
if err := c.runtime.teardownNetwork(c.state.NetNS.Path(), opts); err != nil {
@@ -1294,7 +1179,7 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e
c.lock.Lock()
defer c.lock.Unlock()
- networks, err := c.networksByNameIndex()
+ networks, err := c.networks()
if err != nil {
return err
}
@@ -1321,7 +1206,18 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e
return errors.Wrapf(define.ErrInvalidArg, "cannot set network aliases for network %q because dns is disabled", netName)
}
- if err := c.runtime.state.NetworkConnect(c, netName, aliases); err != nil {
+ eth := getFreeInterfaceName(networks)
+ if eth == "" {
+ return errors.New("could not find free network interface name")
+ }
+
+ perNetOpt := types.PerNetworkOptions{
+ // always add the short id as alias to match docker
+ Aliases: append(aliases, c.config.ID[:12]),
+ InterfaceName: eth,
+ }
+
+ if err := c.runtime.state.NetworkConnect(c, netName, perNetOpt); err != nil {
return err
}
c.newNetworkEvent(events.NetworkConnect, netName)
@@ -1332,30 +1228,13 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e
return errors.Wrapf(define.ErrNoNetwork, "unable to connect %s to %s", nameOrID, netName)
}
- ctrNetworks, _, err := c.networks()
- if err != nil {
- return err
- }
- // Update network descriptions
- if err := c.setupNetworkDescriptions(ctrNetworks); err != nil {
- return err
- }
-
opts := types.NetworkOptions{
ContainerID: c.config.ID,
ContainerName: getCNIPodName(c),
}
opts.PortMappings = c.convertPortMappings()
- eth, exists := c.state.NetInterfaceDescriptions.getInterfaceByName(netName)
- if !exists {
- return errors.Errorf("no network interface name for container %s on network %s", c.config.ID, netName)
- }
- aliases = append(aliases, c.config.ID[:12])
opts.Networks = map[string]types.PerNetworkOptions{
- netName: {
- Aliases: aliases,
- InterfaceName: eth,
- },
+ netName: perNetOpt,
}
results, err := c.runtime.setUpNetwork(c.state.NetNS.Path(), opts)
@@ -1385,6 +1264,22 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e
return nil
}
+// get a free interface name for a new network
+// return an empty string if no free name was found
+func getFreeInterfaceName(networks map[string]types.PerNetworkOptions) string {
+ ifNames := make([]string, 0, len(networks))
+ for _, opts := range networks {
+ ifNames = append(ifNames, opts.InterfaceName)
+ }
+ for i := 0; i < 100000; i++ {
+ ifName := fmt.Sprintf("eth%d", i)
+ if !util.StringInSlice(ifName, ifNames) {
+ return ifName
+ }
+ }
+ return ""
+}
+
// DisconnectContainerFromNetwork removes a container from its CNI network
func (r *Runtime) DisconnectContainerFromNetwork(nameOrID, netName string, force bool) error {
ctr, err := r.LookupContainer(nameOrID)
diff --git a/libpod/state.go b/libpod/state.go
index 4b711bae9..fe7b86fdb 100644
--- a/libpod/state.go
+++ b/libpod/state.go
@@ -1,5 +1,7 @@
package libpod
+import "github.com/containers/podman/v3/libpod/network/types"
+
// State is a storage backend for libpod's current state.
// A State is only initialized once per instance of libpod.
// As such, initialization methods for State implementations may safely assume
@@ -99,14 +101,14 @@ type State interface {
AllContainers() ([]*Container, error)
// Get networks the container is currently connected to.
- GetNetworks(ctr *Container) ([]string, error)
+ GetNetworks(ctr *Container) (map[string]types.PerNetworkOptions, error)
// Get network aliases for the given container in the given network.
GetNetworkAliases(ctr *Container, network string) ([]string, error)
// Get all network aliases for the given container.
GetAllNetworkAliases(ctr *Container) (map[string][]string, error)
// Add the container to the given network, adding the given aliases
// (if present).
- NetworkConnect(ctr *Container, network string, aliases []string) error
+ NetworkConnect(ctr *Container, network string, opts types.PerNetworkOptions) error
// Remove the container from the given network, removing all aliases for
// the container in that network in the process.
NetworkDisconnect(ctr *Container, network string) error