summaryrefslogtreecommitdiff
path: root/libpod/boltdb_state.go
diff options
context:
space:
mode:
Diffstat (limited to 'libpod/boltdb_state.go')
-rw-r--r--libpod/boltdb_state.go172
1 files changed, 137 insertions, 35 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
})
}