summaryrefslogtreecommitdiff
path: root/libpod/boltdb_state_internal.go
diff options
context:
space:
mode:
Diffstat (limited to 'libpod/boltdb_state_internal.go')
-rw-r--r--libpod/boltdb_state_internal.go220
1 files changed, 202 insertions, 18 deletions
diff --git a/libpod/boltdb_state_internal.go b/libpod/boltdb_state_internal.go
index 2f485318c..a48de3092 100644
--- a/libpod/boltdb_state_internal.go
+++ b/libpod/boltdb_state_internal.go
@@ -26,6 +26,7 @@ const (
volName = "vol"
allVolsName = "allVolumes"
execName = "exec"
+ aliasesName = "aliases"
runtimeConfigName = "runtime-config"
configName = "config"
@@ -36,6 +37,7 @@ const (
containersName = "containers"
podIDName = "pod-id"
namespaceName = "namespace"
+ networksName = "networks"
staticDirName = "static-dir"
tmpDirName = "tmp-dir"
@@ -47,26 +49,28 @@ const (
)
var (
- idRegistryBkt = []byte(idRegistryName)
- nameRegistryBkt = []byte(nameRegistryName)
- nsRegistryBkt = []byte(nsRegistryName)
- ctrBkt = []byte(ctrName)
- allCtrsBkt = []byte(allCtrsName)
- podBkt = []byte(podName)
- allPodsBkt = []byte(allPodsName)
- volBkt = []byte(volName)
- allVolsBkt = []byte(allVolsName)
- execBkt = []byte(execName)
- runtimeConfigBkt = []byte(runtimeConfigName)
-
- configKey = []byte(configName)
- stateKey = []byte(stateName)
+ idRegistryBkt = []byte(idRegistryName)
+ nameRegistryBkt = []byte(nameRegistryName)
+ nsRegistryBkt = []byte(nsRegistryName)
+ ctrBkt = []byte(ctrName)
+ allCtrsBkt = []byte(allCtrsName)
+ podBkt = []byte(podName)
+ allPodsBkt = []byte(allPodsName)
+ volBkt = []byte(volName)
+ allVolsBkt = []byte(allVolsName)
+ execBkt = []byte(execName)
+ aliasesBkt = []byte(aliasesName)
+ runtimeConfigBkt = []byte(runtimeConfigName)
dependenciesBkt = []byte(dependenciesName)
volDependenciesBkt = []byte(volCtrDependencies)
- netNSKey = []byte(netNSName)
- containersBkt = []byte(containersName)
- podIDKey = []byte(podIDName)
- namespaceKey = []byte(namespaceName)
+ networksBkt = []byte(networksName)
+
+ configKey = []byte(configName)
+ stateKey = []byte(stateName)
+ netNSKey = []byte(netNSName)
+ containersBkt = []byte(containersName)
+ podIDKey = []byte(podIDName)
+ namespaceKey = []byte(namespaceName)
staticDirKey = []byte(staticDirName)
tmpDirKey = []byte(tmpDirName)
@@ -350,6 +354,14 @@ func getExecBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
return bkt, nil
}
+func getAliasesBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
+ bkt := tx.Bucket(aliasesBkt)
+ if bkt == nil {
+ return nil, errors.Wrapf(define.ErrDBBadConfig, "aliases bucket not found in DB")
+ }
+ return bkt, nil
+}
+
func getRuntimeConfigBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
bkt := tx.Bucket(runtimeConfigBkt)
if bkt == nil {
@@ -572,6 +584,11 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error {
return err
}
+ allAliasesBkt, err := getAliasesBucket(tx)
+ if err != nil {
+ return err
+ }
+
// If a pod was given, check if it exists
var podDB *bolt.Bucket
var podCtrs *bolt.Bucket
@@ -618,6 +635,44 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error {
return errors.Wrapf(err, "name \"%s\" is in use", ctr.Name())
}
+ // Check that we don't have any empty network names
+ for _, net := range ctr.config.Networks {
+ if net == "" {
+ return errors.Wrapf(define.ErrInvalidArg, "network names cannot be an empty string")
+ }
+ }
+
+ // If we have network aliases, check if they are already in use.
+ for net, aliases := range ctr.config.NetworkAliases {
+ // Aliases cannot conflict with container names.
+ for _, alias := range aliases {
+ aliasExist := namesBucket.Get([]byte(alias))
+ if aliasExist != nil {
+ return errors.Wrapf(define.ErrCtrExists, "alias %q conflicts with existing container/pod name", alias)
+ }
+ }
+
+ netAliasesBkt := allAliasesBkt.Bucket([]byte(net))
+ if netAliasesBkt != nil {
+ for _, alias := range aliases {
+ aliasExist := netAliasesBkt.Get([]byte(alias))
+ if aliasExist != nil {
+ return errors.Wrapf(define.ErrAliasExists, "network alias %q already exists for network %q", net, alias)
+ }
+ }
+ }
+ hasNet := false
+ for _, testNet := range ctr.config.Networks {
+ if testNet == net {
+ hasNet = true
+ break
+ }
+ }
+ if !hasNet {
+ return errors.Wrapf(define.ErrInvalidArg, "container %s has network aliases for network %q but is not part of that network", ctr.ID(), net)
+ }
+ }
+
// No overlapping containers
// Add the new container to the DB
if err := idsBucket.Put(ctrID, ctrName); err != nil {
@@ -635,6 +690,63 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error {
return errors.Wrapf(err, "error adding container %s to all containers bucket in DB", ctr.ID())
}
+ // Check aliases for all networks, remove conflicts with the
+ // container name.
+ for _, net := range ctr.config.Networks {
+ netAliasesBkt := allAliasesBkt.Bucket([]byte(net))
+ if netAliasesBkt == nil {
+ continue
+ }
+
+ otherCtrID := netAliasesBkt.Get(ctrName)
+ if otherCtrID == nil {
+ continue
+ }
+
+ if err := netAliasesBkt.Delete(ctrName); err != nil {
+ return errors.Wrapf(err, "error removing container %s name from network aliases for network %s", ctr.ID(), net)
+ }
+
+ // We now need to remove from the other container.
+ // To do this, we work through the container bucket,
+ // then its aliases bucket, then its aliases for this
+ // specific network, then we remove the alias.
+ // Just slightly ridiculous. Just slightly.
+ otherCtr := ctrBucket.Bucket(otherCtrID)
+ if otherCtr == nil {
+ // The state is inconsistent, but we can't do
+ // much...
+ logrus.Errorf("Container %s referred to by network alias but not present in state", string(otherCtrID))
+ continue
+ }
+ otherCtrAliases := otherCtr.Bucket(aliasesBkt)
+ if otherCtrAliases == nil {
+ logrus.Errorf("Container %s is missing aliases but but has an alias", string(otherCtrID))
+ continue
+ }
+ otherCtrNetworkAliases := otherCtrAliases.Bucket([]byte(net))
+ if otherCtrNetworkAliases == nil {
+ logrus.Errorf("Container %s is missing network aliases bucket for network %s but has alias in that network", string(otherCtrID), net)
+ }
+ if otherCtrNetworkAliases.Get(ctrName) != nil {
+ if err := otherCtrNetworkAliases.Delete(ctrName); err != nil {
+ return errors.Wrapf(err, "error removing container %s name from network %s aliases of container %s", ctr.Name(), net, string(otherCtrID))
+ }
+ }
+ }
+
+ for net, aliases := range ctr.config.NetworkAliases {
+ netAliasesBkt, err := allAliasesBkt.CreateBucketIfNotExists([]byte(net))
+ if err != nil {
+ return errors.Wrapf(err, "error creating network aliases bucket for network %q", net)
+ }
+ for _, alias := range aliases {
+ if err := netAliasesBkt.Put([]byte(alias), ctrID); err != nil {
+ return errors.Wrapf(err, "error adding container %s network alias %q to network %q", ctr.ID(), alias, net)
+ }
+ }
+ }
+
newCtrBkt, err := ctrBucket.CreateBucket(ctrID)
if err != nil {
return errors.Wrapf(err, "error adding container %s bucket to DB", ctr.ID())
@@ -661,6 +773,35 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error {
return errors.Wrapf(err, "error adding container %s netns path to DB", ctr.ID())
}
}
+ if ctr.config.Networks != nil {
+ ctrNetworksBkt, err := newCtrBkt.CreateBucket(networksBkt)
+ if err != nil {
+ return errors.Wrapf(err, "error creating networks bucket for container %s", ctr.ID())
+ }
+ for _, network := range ctr.config.Networks {
+ if err := ctrNetworksBkt.Put([]byte(network), ctrID); err != nil {
+ return errors.Wrapf(err, "error adding network %q to networks bucket for container %s", network, ctr.ID())
+ }
+ }
+ }
+ if ctr.config.NetworkAliases != nil {
+ ctrAliasesBkt, err := newCtrBkt.CreateBucket(aliasesBkt)
+ if err != nil {
+ return errors.Wrapf(err, "error creating network aliases bucket for container %s", ctr.ID())
+ }
+ for net, aliases := range ctr.config.NetworkAliases {
+ netAliasesBkt, err := ctrAliasesBkt.CreateBucket([]byte(net))
+ if err != nil {
+ return errors.Wrapf(err, "error creating network aliases bucket for network %q in container %s", net, ctr.ID())
+ }
+ for _, alias := range aliases {
+ if err := netAliasesBkt.Put([]byte(alias), ctrID); err != nil {
+ return errors.Wrapf(err, "error creating network alias %q in network %q for container %s", alias, net, ctr.ID())
+ }
+ }
+ }
+ }
+
if _, err := newCtrBkt.CreateBucket(dependenciesBkt); err != nil {
return errors.Wrapf(err, "error creating dependencies bucket for container %s", ctr.ID())
}
@@ -857,6 +998,49 @@ func (s *BoltState) removeContainer(ctr *Container, pod *Pod, tx *bolt.Tx) error
return errors.Wrapf(define.ErrCtrExists, "container %s is a dependency of the following containers: %s", ctr.ID(), strings.Join(deps, ", "))
}
+ // Does the container have any network aliases?
+ ctrNetAliasesBkt := ctrExists.Bucket(aliasesBkt)
+ if ctrNetAliasesBkt != nil {
+ allAliasesBkt, err := getAliasesBucket(tx)
+ if err != nil {
+ return err
+ }
+ ctrNetworksBkt := ctrExists.Bucket(networksBkt)
+ // Internal state mismatch if this doesn't exist - we'll just
+ // assume there are no aliases in that case.
+ if ctrNetworksBkt != nil {
+ // This is a little gross. Iterate through all networks
+ // the container is joined to. Check if we have aliases
+ // for them. If we do have such aliases, remove all of
+ // then from the global aliases table for that network.
+ err = ctrNetworksBkt.ForEach(func(network, v []byte) error {
+ netAliasesBkt := ctrNetAliasesBkt.Bucket(network)
+ if netAliasesBkt == nil {
+ return nil
+ }
+ netAllAliasesBkt := allAliasesBkt.Bucket(network)
+ if netAllAliasesBkt == nil {
+ // Again the state is inconsistent here,
+ // but the best we can do is try and
+ // recover by ignoring it.
+ return nil
+ }
+ return netAliasesBkt.ForEach(func(alias, v []byte) error {
+ // We don't want to hard-fail on a
+ // missing alias, so continue if we hit
+ // errors.
+ if err := netAllAliasesBkt.Delete(alias); err != nil {
+ logrus.Errorf("Error removing alias %q from network %q when removing container %s", string(alias), string(network), ctr.ID())
+ }
+ return nil
+ })
+ })
+ if err != nil {
+ return err
+ }
+ }
+ }
+
if err := ctrBucket.DeleteBucket(ctrID); err != nil {
return errors.Wrapf(define.ErrInternal, "error deleting container %s from DB", ctr.ID())
}