diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/networking.go | 75 | ||||
-rw-r--r-- | libpod/runtime.go | 25 |
2 files changed, 87 insertions, 13 deletions
diff --git a/libpod/networking.go b/libpod/networking.go index 24e6339d7..082aae20d 100644 --- a/libpod/networking.go +++ b/libpod/networking.go @@ -1,10 +1,15 @@ package libpod import ( + "net" + "strings" + "github.com/containernetworking/plugins/pkg/ns" "github.com/cri-o/ocicni/pkg/ocicni" "github.com/pkg/errors" "github.com/sirupsen/logrus" + "k8s.io/kubernetes/pkg/api/v1" + "k8s.io/kubernetes/pkg/kubelet/network/hostport" ) // Get an OCICNI network config @@ -18,6 +23,32 @@ func getPodNetwork(id, name, nsPath string, ports []ocicni.PortMapping) ocicni.P } } +// Convert port mapping struct from OCICNI version to one Kubernetes understands +func portMappingToHostport(mappings []ocicni.PortMapping) ([]*hostport.PortMapping, error) { + newMappings := make([]*hostport.PortMapping, len(mappings)) + for _, port := range mappings { + var protocol v1.Protocol + switch strings.ToLower(port.Protocol) { + case "udp": + protocol = v1.ProtocolUDP + case "tcp": + protocol = v1.ProtocolTCP + default: + return nil, errors.Wrapf(ErrInvalidArg, "protocol must be TCP or UDP, instead got %s", port.Protocol) + } + + newPort := new(hostport.PortMapping) + newPort.Name = "" + newPort.HostPort = port.HostPort + newPort.ContainerPort = port.ContainerPort + newPort.Protocol = protocol + newPort.HostIP = port.HostIP + + newMappings = append(newMappings, newPort) + } + return newMappings, nil +} + // Create and configure a new network namespace for a container func (r *Runtime) createNetNS(ctr *Container) (err error) { ctrNS, err := ns.NewNS() @@ -38,7 +69,32 @@ func (r *Runtime) createNetNS(ctr *Container) (err error) { return errors.Wrapf(err, "error configuring network namespace for container %s", ctr.ID()) } - // TODO hostport mappings for forwarded ports + if len(ctr.config.PortMappings) != 0 { + ip, err := r.netPlugin.GetPodNetworkStatus(podNetwork) + if err != nil { + return errors.Wrapf(err, "failed to get status of network for container %s", ctr.ID()) + } + + ip4 := net.ParseIP(ip).To4() + if ip4 == nil { + return errors.Wrapf(err, "failed to parse IPv4 address for container %s", ctr.ID()) + } + + portMappings, err := portMappingToHostport(ctr.config.PortMappings) + if err != nil { + return errors.Wrapf(err, "failed to generate port ammpings for container %s", ctr.ID()) + } + + err = r.hostportManager.Add(ctr.ID(), &hostport.PodPortMapping{ + Name: ctr.Name(), + PortMappings: portMappings, + IP: ip4, + HostNetwork: false, + }, "lo") + if err != nil { + return errors.Wrapf(err, "failed to add port mappings for container %s", ctr.ID()) + } + } ctr.state.NetNS = ctrNS @@ -62,7 +118,22 @@ func (r *Runtime) teardownNetNS(ctr *Container) error { return nil } - // TODO hostport mappings for forwarded ports should be undone + portMappings, err := portMappingToHostport(ctr.config.PortMappings) + if err != nil { + logrus.Errorf("Failed to generate port mappings for container %s: %v", ctr.ID(), err) + } else { + // Only attempt to remove hostport mappings if we successfully + // converted to hostport-style mappings + err := r.hostportManager.Remove(ctr.ID(), &hostport.PodPortMapping{ + Name: ctr.Name(), + PortMappings: portMappings, + HostNetwork: false, + }) + if err != nil { + logrus.Errorf("Failed to tear down port mappings for container %s: %v", ctr.ID(), err) + } + } + podNetwork := getPodNetwork(ctr.ID(), ctr.Name(), ctr.state.NetNS.Path(), ctr.config.PortMappings) // The network may have already been torn down, so don't fail here, just log diff --git a/libpod/runtime.go b/libpod/runtime.go index 9712b6dd3..480da6677 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -12,6 +12,7 @@ import ( "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/ulule/deepcopier" + "k8s.io/kubernetes/pkg/kubelet/network/hostport" ) // A RuntimeOption is a functional option which alters the Runtime created by @@ -20,16 +21,17 @@ type RuntimeOption func(*Runtime) error // Runtime is the core libpod runtime type Runtime struct { - config *RuntimeConfig - state State - store storage.Store - storageService *storageService - imageContext *types.SystemContext - ociRuntime *OCIRuntime - lockDir string - netPlugin ocicni.CNIPlugin - valid bool - lock sync.RWMutex + config *RuntimeConfig + state State + store storage.Store + storageService *storageService + imageContext *types.SystemContext + ociRuntime *OCIRuntime + lockDir string + netPlugin ocicni.CNIPlugin + hostportManager hostport.HostPortManager + valid bool + lock sync.RWMutex } // RuntimeConfig contains configuration options used to set up the runtime @@ -170,7 +172,8 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) { } runtime.netPlugin = netPlugin - // TODO: iptables/firewalld integration to ensure rules are in place for forwarding + // Set up the hostport manager + runtime.hostportManager = hostport.NewHostportManager() // Set up the state if runtime.config.InMemoryState { |