From 8d56eb5342ad8afa35750f7f14791c44e37a8c30 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Tue, 10 Nov 2020 14:54:09 -0500 Subject: Add support for network connect / disconnect to DB Convert the existing network aliases set/remove code to network connect and disconnect. We can no longer modify aliases for an existing network, but we can add and remove entire networks. As part of this, we need to add a new function to retrieve current aliases the container is connected to (we had a table for this as of the first aliases PR, but it was not externally exposed). At the same time, remove all deconflicting logic for aliases. Docker does absolutely no checks of this nature, and allows two containers to have the same aliases, aliases that conflict with container names, etc - it's just left to DNS to return all the IP addresses, and presumably we round-robin from there? Most tests for the existing code had to be removed because of this. Convert all uses of the old container config.Networks field, which previously included all networks in the container, to use the new DB table. This ensures we actually get an up-to-date list of in-use networks. Also, add network aliases to the output of `podman inspect`. Signed-off-by: Matthew Heon --- libpod/boltdb_state_internal.go | 148 ++-------------------------------------- 1 file changed, 7 insertions(+), 141 deletions(-) (limited to 'libpod/boltdb_state_internal.go') diff --git a/libpod/boltdb_state_internal.go b/libpod/boltdb_state_internal.go index a48de3092..c06fedd3e 100644 --- a/libpod/boltdb_state_internal.go +++ b/libpod/boltdb_state_internal.go @@ -354,14 +354,6 @@ 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 { @@ -584,11 +576,6 @@ 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 @@ -635,41 +622,20 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error { return errors.Wrapf(err, "name \"%s\" is in use", ctr.Name()) } + allNets := make(map[string]bool) + // 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") } + allNets[net] = true } - // 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) + // Each network we have aliases for, must exist in networks + for net := range ctr.config.NetworkAliases { + if !allNets[net] { + return errors.Wrapf(define.ErrNoSuchNetwork, "container %s has network aliases for network %q but is not part of that network", ctr.ID(), net) } } @@ -690,63 +656,6 @@ 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()) @@ -998,49 +907,6 @@ 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()) } -- cgit v1.2.3-54-g00ecf