aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@gmail.com>2017-12-06 15:54:59 -0500
committerAtomic Bot <atomic-devel@projectatomic.io>2017-12-14 23:59:21 +0000
commit0ff92f8e20edb46eb8a9d82b929e153bcdaa3044 (patch)
tree14289c5dea9b738004837144ec6c5045d2f4789d
parent824a648fcb87c112fb498db94b8e39a84ba649bd (diff)
downloadpodman-0ff92f8e20edb46eb8a9d82b929e153bcdaa3044.tar.gz
podman-0ff92f8e20edb46eb8a9d82b929e153bcdaa3044.tar.bz2
podman-0ff92f8e20edb46eb8a9d82b929e153bcdaa3044.zip
Add network namespaces to SQL state
Signed-off-by: Matthew Heon <matthew.heon@gmail.com> Closes: #109 Approved by: mheon
-rw-r--r--libpod/container.go5
-rw-r--r--libpod/networking.go37
-rw-r--r--libpod/sql_state.go63
-rw-r--r--libpod/sql_state_internal.go14
4 files changed, 98 insertions, 21 deletions
diff --git a/libpod/container.go b/libpod/container.go
index 12fd13f51..ada037531 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -12,6 +12,7 @@ import (
"time"
"github.com/containerd/cgroups"
+ "github.com/containernetworking/plugins/pkg/ns"
"github.com/containers/storage"
"github.com/containers/storage/pkg/archive"
"github.com/cri-o/ocicni/pkg/ocicni"
@@ -100,6 +101,10 @@ type containerRuntimeInfo struct {
OOMKilled bool `json:"oomKilled,omitempty"`
// PID is the PID of a running container
PID int `json:"pid,omitempty"`
+ // NetNSPath is the path of the container's network namespace
+ // Will only be set if config.CreateNetNS is true, or the container was
+ // told to join another container's network namespace
+ NetNS ns.NetNS
// TODO: Save information about image used in container if one is used
}
diff --git a/libpod/networking.go b/libpod/networking.go
index 893d6863a..f613ad5f8 100644
--- a/libpod/networking.go
+++ b/libpod/networking.go
@@ -3,11 +3,12 @@ package libpod
import (
"github.com/containernetworking/plugins/pkg/ns"
"github.com/cri-o/ocicni/pkg/ocicni"
+ "github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
// Get an OCICNI network config
-func getPodNetwork(id, name, nsPath string, ports []ocicni.PortMappings) ocicni.PodNetwork {
+func getPodNetwork(id, name, nsPath string, ports []ocicni.PortMapping) ocicni.PodNetwork {
return ocicni.PodNetwork{
Name: name,
Namespace: name, // TODO is there something else we should put here? We don't know about Kube namespaces
@@ -17,29 +18,31 @@ func getPodNetwork(id, name, nsPath string, ports []ocicni.PortMappings) ocicni.
}
}
-// Create and configure a new network namespace
-func (r *Runtime) createNetNS(id, name string, ports []ocicni.PortMapping) (n ns.NetNS, err error) {
+// Create and configure a new network namespace for a container
+func (r *Runtime) createNetNS(ctr *Container) (err error) {
ns, err := ns.NewNS()
if err != nil {
- return nil, errors.Wrapf(err, "error creating network namespace %s", id)
+ return errors.Wrapf(err, "error creating network namespace for container %s", ctr.ID())
}
defer func() {
if err != nil {
if err2 := ns.Close(); err2 != nil {
- logrus.Errorf("Error closing partially created network namespace %s: %v", id, err2)
+ logrus.Errorf("Error closing partially created network namespace for container %s: %v", ctr.ID(), err2)
}
}
}()
- podNetwork := getPodNetwork(id, name, ns.Path(), ports)
+ podNetwork := getPodNetwork(ctr.ID(), ctr.Name(), ns.Path(), ctr.config.PortMappings)
if err := r.netPlugin.SetUpPod(podNetwork); err != nil {
- return nil, errors.Wrapf(err, "error configuring network namespace %s", id)
+ return errors.Wrapf(err, "error configuring network namespace for container %s", ctr.ID())
}
// TODO hostport mappings for forwarded ports
- return ns, nil
+ ctr.state.NetNS = ns
+
+ return nil
}
// Join an existing network namespace
@@ -53,13 +56,25 @@ func joinNetNS(path string) (ns.NetNS, error) {
}
// Tear down a network namespace
-func (r *Runtime) teardownNetNS(id, name string, ports []ocicni.PortMapping, ns ns.NetNS) error {
+func (r *Runtime) teardownNetNS(ctr *Container) error {
+ if ctr.state.NetNS == nil {
+ // The container has no network namespace, we're set
+ return nil
+ }
+
// TODO hostport mappings for forwarded ports should be undone
- podNetwork := getPodNetwork(id, name, ns.Path(), ports)
+ 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
if err := r.netPlugin.TearDownPod(podNetwork); err != nil {
- return errors.Wrapf(err, "failed to remove network namespace %s", id)
+ logrus.Errorf("Failed to tear down network namespace for container %s: %v", ctr.ID(), err)
+ }
+
+ if err := ctr.state.NetNS.Close(); err != nil {
+ return errors.Wrapf(err, "error closing network namespace for container %s", ctr.ID())
}
+ ctr.state.NetNS = nil
+
return nil
}
diff --git a/libpod/sql_state.go b/libpod/sql_state.go
index d0969a783..97df749e9 100644
--- a/libpod/sql_state.go
+++ b/libpod/sql_state.go
@@ -15,7 +15,7 @@ import (
// DBSchema is the current DB schema version
// Increments every time a change is made to the database's tables
-const DBSchema = 3
+const DBSchema = 4
// SQLState is a state implementation backed by a persistent SQLite3 database
type SQLState struct {
@@ -151,7 +151,8 @@ func (s *SQLState) Container(id string) (*Container, error) {
containerState.FinishedTime,
containerState.ExitCode,
containerState.OomKilled,
- containerState.Pid
+ containerState.Pid,
+ containerState.NetNSPath
FROM containers
INNER JOIN
containerState ON containers.Id = containerState.Id
@@ -186,7 +187,8 @@ func (s *SQLState) LookupContainer(idOrName string) (*Container, error) {
containerState.FinishedTime,
containerState.ExitCode,
containerState.OomKilled,
- containerState.Pid
+ containerState.Pid,
+ containerState.NetNSPath
FROM containers
INNER JOIN
containerState ON containers.Id = containerState.Id
@@ -270,7 +272,7 @@ func (s *SQLState) AddContainer(ctr *Container) (err error) {
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
);`
addCtrState = `INSERT INTO containerState VALUES (
- ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
+ ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
);`
)
@@ -297,6 +299,11 @@ func (s *SQLState) AddContainer(ctr *Container) (err error) {
return errors.Wrapf(err, "error marshaling container %s port mappings to JSON", ctr.ID())
}
+ netNSPath := ""
+ if ctr.state.NetNS != nil {
+ netNSPath = ctr.state.NetNS.Path()
+ }
+
tx, err := s.db.Begin()
if err != nil {
return errors.Wrapf(err, "error beginning database transaction")
@@ -342,7 +349,8 @@ func (s *SQLState) AddContainer(ctr *Container) (err error) {
timeToSQL(ctr.state.FinishedTime),
ctr.state.ExitCode,
boolToSQL(ctr.state.OOMKilled),
- ctr.state.PID)
+ ctr.state.PID,
+ netNSPath)
if err != nil {
return errors.Wrapf(err, "error adding container %s state to database", ctr.ID())
}
@@ -381,7 +389,8 @@ func (s *SQLState) UpdateContainer(ctr *Container) error {
FinishedTime,
ExitCode,
OomKilled,
- Pid
+ Pid,
+ NetNSPath
FROM containerState WHERE ID=?;`
var (
@@ -394,6 +403,7 @@ func (s *SQLState) UpdateContainer(ctr *Container) error {
exitCode int32
oomKilled int
pid int
+ netNSPath string
)
if !s.valid {
@@ -414,7 +424,8 @@ func (s *SQLState) UpdateContainer(ctr *Container) error {
&finishedTimeString,
&exitCode,
&oomKilled,
- &pid)
+ &pid,
+ &netNSPath)
if err != nil {
// The container may not exist in the database
if err == sql.ErrNoRows {
@@ -453,6 +464,32 @@ func (s *SQLState) UpdateContainer(ctr *Container) error {
}
newState.FinishedTime = finishedTime
+ // Do we need to replace the container's netns?
+ if netNSPath != "" {
+ // Check if the container's old state has a good netns
+ if ctr.state.NetNS != nil && netNSPath == ctr.state.NetNS.Path() {
+ newState.NetNS = ctr.state.NetNS
+ } else {
+ // Tear down the existing namespace
+ if err := s.runtime.teardownNetNS(ctr); err != nil {
+ return err
+ }
+
+ // Open the new network namespace
+ ns, err := joinNetNS(netNSPath)
+ if err != nil {
+ return errors.Wrapf(err, "error joining network namespace for container %s", ctr.ID())
+ }
+ newState.NetNS = ns
+ }
+ } else {
+ // The container no longer has a network namespace
+ // Tear down the old one
+ if err := s.runtime.teardownNetNS(ctr); err != nil {
+ return err
+ }
+ }
+
// New state compiled successfully, swap it into the current state
ctr.state = newState
@@ -470,9 +507,15 @@ func (s *SQLState) SaveContainer(ctr *Container) error {
FinishedTime=?,
ExitCode=?,
OomKilled=?,
- Pid=?
+ Pid=?,
+ NetNSPath=?
WHERE Id=?;`
+ netNSPath := ""
+ if ctr.state.NetNS != nil {
+ netNSPath = ctr.state.NetNS.Path()
+ }
+
if !s.valid {
return ErrDBClosed
}
@@ -504,6 +547,7 @@ func (s *SQLState) SaveContainer(ctr *Container) error {
ctr.state.ExitCode,
boolToSQL(ctr.state.OOMKilled),
ctr.state.PID,
+ netNSPath,
ctr.ID())
if err != nil {
return errors.Wrapf(err, "error updating container %s state in database", ctr.ID())
@@ -593,7 +637,8 @@ func (s *SQLState) AllContainers() ([]*Container, error) {
containerState.FinishedTime,
containerState.ExitCode,
containerState.OomKilled,
- containerState.Pid
+ containerState.Pid,
+ containerState.NetNSPath
FROM containers
INNER JOIN
containerState ON containers.Id = containerState.Id
diff --git a/libpod/sql_state_internal.go b/libpod/sql_state_internal.go
index 1d1878b9d..e1ecc8ea6 100644
--- a/libpod/sql_state_internal.go
+++ b/libpod/sql_state_internal.go
@@ -200,6 +200,7 @@ func prepareDB(db *sql.DB) (err error) {
ExitCode INTEGER NOT NULL,
OomKilled INTEGER NOT NULL,
Pid INTEGER NOT NULL,
+ NetNSPath TEXT NOT NULL,
CHECK (State>0),
CHECK (OomKilled IN (0, 1)),
FOREIGN KEY (Id) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED
@@ -296,6 +297,7 @@ func ctrFromScannable(row scannable, runtime *Runtime, specsDir string, lockDir
exitCode int32
oomKilled int
pid int
+ netNSPath string
)
err := row.Scan(
@@ -323,7 +325,8 @@ func ctrFromScannable(row scannable, runtime *Runtime, specsDir string, lockDir
&finishedTimeString,
&exitCode,
&oomKilled,
- &pid)
+ &pid,
+ &netNSPath)
if err != nil {
if err == sql.ErrNoRows {
return nil, ErrNoSuchCtr
@@ -394,6 +397,15 @@ func ctrFromScannable(row scannable, runtime *Runtime, specsDir string, lockDir
}
ctr.state.FinishedTime = finishedTime
+ // Join the network namespace, if there is one
+ if netNSPath != "" {
+ netNS, err := joinNetNS(netNSPath)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error joining network namespace for container %s", id)
+ }
+ ctr.state.NetNS = netNS
+ }
+
ctr.valid = true
ctr.runtime = runtime