summaryrefslogtreecommitdiff
path: root/libpod/networking_linux.go
diff options
context:
space:
mode:
authorbaude <bbaude@redhat.com>2020-11-11 09:45:07 -0600
committerbaude <bbaude@redhat.com>2020-11-17 14:22:39 -0600
commitd3e794bda39167b15c5dc14d83333d1306316b11 (patch)
tree734cda964a2d46316f6aeb279be28fea541b32f5 /libpod/networking_linux.go
parent3a172c5999706e4493824c436bd7e2e8ea7b3d59 (diff)
downloadpodman-d3e794bda39167b15c5dc14d83333d1306316b11.tar.gz
podman-d3e794bda39167b15c5dc14d83333d1306316b11.tar.bz2
podman-d3e794bda39167b15c5dc14d83333d1306316b11.zip
add network connect|disconnect compat endpoints
this enables the ability to connect and disconnect a container from a given network. it is only for the compatibility layer. some code had to be refactored to avoid circular imports. additionally, tests are being deferred temporarily due to some incompatibility/bug in either docker-py or our stack. Signed-off-by: baude <bbaude@redhat.com>
Diffstat (limited to 'libpod/networking_linux.go')
-rw-r--r--libpod/networking_linux.go138
1 files changed, 138 insertions, 0 deletions
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index fed90cfc3..3882e095a 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -13,6 +13,7 @@ import (
"os"
"os/exec"
"path/filepath"
+ "sort"
"strings"
"syscall"
"time"
@@ -20,6 +21,7 @@ import (
cnitypes "github.com/containernetworking/cni/pkg/types/current"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containers/podman/v2/libpod/define"
+ "github.com/containers/podman/v2/libpod/network"
"github.com/containers/podman/v2/pkg/errorhandling"
"github.com/containers/podman/v2/pkg/netns"
"github.com/containers/podman/v2/pkg/rootless"
@@ -981,3 +983,139 @@ func (w *logrusDebugWriter) Write(p []byte) (int, error) {
logrus.Debugf("%s%s", w.prefix, string(p))
return len(p), nil
}
+
+// DisconnectContainerFromNetwork removes a container from its CNI network
+func (r *Runtime) DisconnectContainerFromNetwork(nameOrID, netName string, force bool) error {
+ ctr, err := r.LookupContainer(nameOrID)
+ if err != nil {
+ return err
+ }
+
+ networks, err := ctr.networksByNameIndex()
+ if err != nil {
+ return err
+ }
+
+ exists, err := network.Exists(r.config, netName)
+ if err != nil {
+ return err
+ }
+ if !exists {
+ return errors.Wrap(define.ErrNoSuchNetwork, netName)
+ }
+
+ index, nameExists := networks[netName]
+ if !nameExists && len(networks) > 0 {
+ return errors.Errorf("container %s is not connected to network %s", nameOrID, netName)
+ }
+
+ ctr.lock.Lock()
+ defer ctr.lock.Unlock()
+ if err := ctr.syncContainer(); err != nil {
+ return err
+ }
+
+ podConfig := r.getPodNetwork(ctr.ID(), ctr.Name(), ctr.state.NetNS.Path(), []string{netName}, ctr.config.PortMappings, nil, nil)
+ if err := r.netPlugin.TearDownPod(podConfig); err != nil {
+ return err
+ }
+ if err := r.state.NetworkDisconnect(ctr, netName); err != nil {
+ return err
+ }
+
+ // update network status
+ networkStatus := ctr.state.NetworkStatus
+ // if len is one and we confirmed earlier that the container is in
+ // fact connected to the network, then just return an empty slice
+ if len(networkStatus) == 1 {
+ ctr.state.NetworkStatus = make([]*cnitypes.Result, 0)
+ } else {
+ // clip out the index of the network
+ networkStatus[len(networkStatus)-1], networkStatus[index] = networkStatus[index], networkStatus[len(networkStatus)-1]
+ // shorten the slice by one
+ ctr.state.NetworkStatus = networkStatus[:len(networkStatus)-1]
+ }
+ return nil
+}
+
+// ConnectContainerToNetwork connects a container to a CNI network
+func (r *Runtime) ConnectContainerToNetwork(nameOrID, netName string, aliases []string) error {
+ ctr, err := r.LookupContainer(nameOrID)
+ if err != nil {
+ return err
+ }
+
+ networks, err := ctr.networksByNameIndex()
+ if err != nil {
+ return err
+ }
+
+ exists, err := network.Exists(r.config, netName)
+ if err != nil {
+ return err
+ }
+ if !exists {
+ return errors.Wrap(define.ErrNoSuchNetwork, netName)
+ }
+
+ _, nameExists := networks[netName]
+ if !nameExists && len(networks) > 0 {
+ return errors.Errorf("container %s is not connected to network %s", nameOrID, netName)
+ }
+
+ ctr.lock.Lock()
+ defer ctr.lock.Unlock()
+ if err := ctr.syncContainer(); err != nil {
+ return err
+ }
+
+ if err := r.state.NetworkConnect(ctr, netName, aliases); err != nil {
+ return err
+ }
+
+ podConfig := r.getPodNetwork(ctr.ID(), ctr.Name(), ctr.state.NetNS.Path(), []string{netName}, ctr.config.PortMappings, nil, nil)
+ podConfig.Aliases = make(map[string][]string, 1)
+ podConfig.Aliases[netName] = aliases
+ results, err := r.netPlugin.SetUpPod(podConfig)
+ if err != nil {
+ return err
+ }
+ if len(results) != 1 {
+ return errors.New("when adding aliases, results must be of length 1")
+ }
+
+ networkResults := make([]*cnitypes.Result, 0)
+ for _, r := range results {
+ resultCurrent, err := cnitypes.GetResult(r.Result)
+ if err != nil {
+ return errors.Wrapf(err, "error parsing CNI plugin result %q: %v", r.Result, err)
+ }
+ networkResults = append(networkResults, resultCurrent)
+ }
+
+ // update network status
+ networkStatus := ctr.state.NetworkStatus
+ // if len is one and we confirmed earlier that the container is in
+ // fact connected to the network, then just return an empty slice
+ if len(networkStatus) == 0 {
+ ctr.state.NetworkStatus = append(ctr.state.NetworkStatus, networkResults...)
+ } else {
+ // build a list of network names so we can sort and
+ // get the new name's index
+ var networkNames []string
+ for netName := range networks {
+ networkNames = append(networkNames, netName)
+ }
+ networkNames = append(networkNames, netName)
+ // sort
+ sort.Strings(networkNames)
+ // get index of new network name
+ index := sort.SearchStrings(networkNames, netName)
+ // Append a zero value to to the slice
+ networkStatus = append(networkStatus, &cnitypes.Result{})
+ // populate network status
+ copy(networkStatus[index+1:], networkStatus[index:])
+ networkStatus[index] = networkResults[0]
+ }
+ return nil
+}