diff options
author | Matthew Heon <matthew.heon@gmail.com> | 2017-12-08 15:11:14 -0500 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2017-12-14 23:59:21 +0000 |
commit | 840eb04e03e9292c54621c7ff75cbf95e690d86f (patch) | |
tree | 60216367054d06720a38ba96b1e1b1827e7e23a2 | |
parent | 316341a81dec52c5fd84c6e8c194639240c57273 (diff) | |
download | podman-840eb04e03e9292c54621c7ff75cbf95e690d86f.tar.gz podman-840eb04e03e9292c54621c7ff75cbf95e690d86f.tar.bz2 podman-840eb04e03e9292c54621c7ff75cbf95e690d86f.zip |
Add iptables integration to network code
Signed-off-by: Matthew Heon <matthew.heon@gmail.com>
Closes: #109
Approved by: mheon
-rw-r--r-- | libpod/networking.go | 75 | ||||
-rw-r--r-- | libpod/runtime.go | 25 | ||||
-rw-r--r-- | vendor/k8s.io/utils/LICENSE | 202 | ||||
-rw-r--r-- | vendor/k8s.io/utils/README.md | 51 | ||||
-rw-r--r-- | vendor/k8s.io/utils/exec/doc.go | 18 | ||||
-rw-r--r-- | vendor/k8s.io/utils/exec/exec.go | 202 |
6 files changed, 560 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 { diff --git a/vendor/k8s.io/utils/LICENSE b/vendor/k8s.io/utils/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/vendor/k8s.io/utils/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/k8s.io/utils/README.md b/vendor/k8s.io/utils/README.md new file mode 100644 index 000000000..2504649ef --- /dev/null +++ b/vendor/k8s.io/utils/README.md @@ -0,0 +1,51 @@ +# Utils + +[![Build Status]](https://travis-ci.org/kubernetes/utils) + +A set of Go libraries that provide low-level, +kubernetes-independent packages supplementing the [Go +standard libs]. + +## Purpose + +As Kubernetes grows and spins functionality out of its +[core] and into cooperating repositories like +[apiserver], [kubectl], [kubeadm], etc., the need +arises for leaf repositories to house shared code and +avoid cycles in repository relationships. + +This repository is intended to hold shared utilities +with no Kubernetes dependence that may be of interest +to any Go project. See these [instructions for moving] +an existing package to this repository. + + +## Criteria for adding code here + +- Used by multiple Kubernetes repositories. + +- Full unit test coverage. + +- Go tools compliant (`go get`, `go test`, etc.). + +- Complex enough to be worth vendoring, rather than copying. + +- Stable, or backward compatible, API. + +- _No dependence on any Kubernetes repository_. + +## Libraries + +- [Exec](/exec) provides an interface for `os/exec`. It makes it easier + to mock and replace in tests, especially with + the [FakeExec](exec/testing/fake_exec.go) struct. + +[Build Status]: https://travis-ci.org/kubernetes/utils.svg?branch=master +[Go standard libs]: https://golang.org/pkg/#stdlib +[api]: https://github.com/kubernetes/api +[apiserver]: https://github.com/kubernetes/apiserver +[core]: https://github.com/kubernetes/kubernetes +[ingress]: https://github.com/kubernetes/ingress +[kubeadm]: https://github.com/kubernetes/kubeadm +[kubectl]: https://github.com/kubernetes/kubectl +[instructions for moving]: ./HOWTOMOVE.md diff --git a/vendor/k8s.io/utils/exec/doc.go b/vendor/k8s.io/utils/exec/doc.go new file mode 100644 index 000000000..cbb44bdb5 --- /dev/null +++ b/vendor/k8s.io/utils/exec/doc.go @@ -0,0 +1,18 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package exec provides an injectable interface and implementations for running commands. +package exec // import "k8s.io/utils/exec" diff --git a/vendor/k8s.io/utils/exec/exec.go b/vendor/k8s.io/utils/exec/exec.go new file mode 100644 index 000000000..3b23eceb1 --- /dev/null +++ b/vendor/k8s.io/utils/exec/exec.go @@ -0,0 +1,202 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package exec + +import ( + "io" + osexec "os/exec" + "syscall" + "time" +) + +// ErrExecutableNotFound is returned if the executable is not found. +var ErrExecutableNotFound = osexec.ErrNotFound + +// Interface is an interface that presents a subset of the os/exec API. Use this +// when you want to inject fakeable/mockable exec behavior. +type Interface interface { + // Command returns a Cmd instance which can be used to run a single command. + // This follows the pattern of package os/exec. + Command(cmd string, args ...string) Cmd + + // LookPath wraps os/exec.LookPath + LookPath(file string) (string, error) +} + +// Cmd is an interface that presents an API that is very similar to Cmd from os/exec. +// As more functionality is needed, this can grow. Since Cmd is a struct, we will have +// to replace fields with get/set method pairs. +type Cmd interface { + // Run runs the command to the completion. + Run() error + // CombinedOutput runs the command and returns its combined standard output + // and standard error. This follows the pattern of package os/exec. + CombinedOutput() ([]byte, error) + // Output runs the command and returns standard output, but not standard err + Output() ([]byte, error) + SetDir(dir string) + SetStdin(in io.Reader) + SetStdout(out io.Writer) + SetStderr(out io.Writer) + // Stops the command by sending SIGTERM. It is not guaranteed the + // process will stop before this function returns. If the process is not + // responding, an internal timer function will send a SIGKILL to force + // terminate after 10 seconds. + Stop() +} + +// ExitError is an interface that presents an API similar to os.ProcessState, which is +// what ExitError from os/exec is. This is designed to make testing a bit easier and +// probably loses some of the cross-platform properties of the underlying library. +type ExitError interface { + String() string + Error() string + Exited() bool + ExitStatus() int +} + +// Implements Interface in terms of really exec()ing. +type executor struct{} + +// New returns a new Interface which will os/exec to run commands. +func New() Interface { + return &executor{} +} + +// Command is part of the Interface interface. +func (executor *executor) Command(cmd string, args ...string) Cmd { + return (*cmdWrapper)(osexec.Command(cmd, args...)) +} + +// LookPath is part of the Interface interface +func (executor *executor) LookPath(file string) (string, error) { + return osexec.LookPath(file) +} + +// Wraps exec.Cmd so we can capture errors. +type cmdWrapper osexec.Cmd + +var _ Cmd = &cmdWrapper{} + +func (cmd *cmdWrapper) SetDir(dir string) { + cmd.Dir = dir +} + +func (cmd *cmdWrapper) SetStdin(in io.Reader) { + cmd.Stdin = in +} + +func (cmd *cmdWrapper) SetStdout(out io.Writer) { + cmd.Stdout = out +} + +func (cmd *cmdWrapper) SetStderr(out io.Writer) { + cmd.Stderr = out +} + +// Run is part of the Cmd interface. +func (cmd *cmdWrapper) Run() error { + return (*osexec.Cmd)(cmd).Run() +} + +// CombinedOutput is part of the Cmd interface. +func (cmd *cmdWrapper) CombinedOutput() ([]byte, error) { + out, err := (*osexec.Cmd)(cmd).CombinedOutput() + if err != nil { + return out, handleError(err) + } + return out, nil +} + +func (cmd *cmdWrapper) Output() ([]byte, error) { + out, err := (*osexec.Cmd)(cmd).Output() + if err != nil { + return out, handleError(err) + } + return out, nil +} + +// Stop is part of the Cmd interface. +func (cmd *cmdWrapper) Stop() { + c := (*osexec.Cmd)(cmd) + if c.ProcessState.Exited() { + return + } + c.Process.Signal(syscall.SIGTERM) + time.AfterFunc(10*time.Second, func() { + if c.ProcessState.Exited() { + return + } + c.Process.Signal(syscall.SIGKILL) + }) +} + +func handleError(err error) error { + if ee, ok := err.(*osexec.ExitError); ok { + // Force a compile fail if exitErrorWrapper can't convert to ExitError. + var x ExitError = &ExitErrorWrapper{ee} + return x + } + if ee, ok := err.(*osexec.Error); ok { + if ee.Err == osexec.ErrNotFound { + return ErrExecutableNotFound + } + } + return err +} + +// ExitErrorWrapper is an implementation of ExitError in terms of os/exec ExitError. +// Note: standard exec.ExitError is type *os.ProcessState, which already implements Exited(). +type ExitErrorWrapper struct { + *osexec.ExitError +} + +var _ ExitError = ExitErrorWrapper{} + +// ExitStatus is part of the ExitError interface. +func (eew ExitErrorWrapper) ExitStatus() int { + ws, ok := eew.Sys().(syscall.WaitStatus) + if !ok { + panic("can't call ExitStatus() on a non-WaitStatus exitErrorWrapper") + } + return ws.ExitStatus() +} + +// CodeExitError is an implementation of ExitError consisting of an error object +// and an exit code (the upper bits of os.exec.ExitStatus). +type CodeExitError struct { + Err error + Code int +} + +var _ ExitError = CodeExitError{} + +func (e CodeExitError) Error() string { + return e.Err.Error() +} + +func (e CodeExitError) String() string { + return e.Err.Error() +} + +func (e CodeExitError) Exited() bool { + return true +} + +func (e CodeExitError) ExitStatus() int { + return e.Code +} |