Add restart recovery logic.
Signed-off-by: Lantao Liu <lantaol@google.com>
This commit is contained in:
@@ -88,11 +88,6 @@ func (c *Container) Delete() error {
|
||||
return c.Status.Delete()
|
||||
}
|
||||
|
||||
// LoadContainer loads the internal used container type.
|
||||
func LoadContainer() (Container, error) {
|
||||
return Container{}, nil
|
||||
}
|
||||
|
||||
// Store stores all Containers.
|
||||
type Store struct {
|
||||
lock sync.RWMutex
|
||||
|
||||
@@ -41,6 +41,7 @@ func TestContainerStore(t *testing.T) {
|
||||
},
|
||||
},
|
||||
ImageRef: "TestImage-1",
|
||||
LogPath: "/test/log/path/1",
|
||||
},
|
||||
"2": {
|
||||
ID: "2",
|
||||
@@ -53,6 +54,7 @@ func TestContainerStore(t *testing.T) {
|
||||
},
|
||||
},
|
||||
ImageRef: "TestImage-2",
|
||||
LogPath: "/test/log/path/2",
|
||||
},
|
||||
"3": {
|
||||
ID: "3",
|
||||
@@ -65,6 +67,7 @@ func TestContainerStore(t *testing.T) {
|
||||
},
|
||||
},
|
||||
ImageRef: "TestImage-3",
|
||||
LogPath: "/test/log/path/3",
|
||||
},
|
||||
}
|
||||
statuses := map[string]Status{
|
||||
@@ -153,6 +156,7 @@ func TestWithContainerIO(t *testing.T) {
|
||||
},
|
||||
},
|
||||
ImageRef: "TestImage-1",
|
||||
LogPath: "/test/log/path",
|
||||
}
|
||||
status := Status{
|
||||
Pid: 1,
|
||||
|
||||
@@ -54,6 +54,8 @@ type Metadata struct {
|
||||
Config *runtime.ContainerConfig
|
||||
// ImageRef is the reference of image used by the container.
|
||||
ImageRef string
|
||||
// LogPath is the container log path.
|
||||
LogPath string
|
||||
}
|
||||
|
||||
// MarshalJSON encodes Metadata into bytes in json format.
|
||||
|
||||
@@ -36,6 +36,7 @@ func TestMetadataMarshalUnmarshal(t *testing.T) {
|
||||
},
|
||||
},
|
||||
ImageRef: "test-image-ref",
|
||||
LogPath: "/test/log/path",
|
||||
}
|
||||
|
||||
assert := assertlib.New(t)
|
||||
|
||||
@@ -58,8 +58,7 @@ type Status struct {
|
||||
Message string
|
||||
// Removing indicates that the container is in removing state.
|
||||
// This field doesn't need to be checkpointed.
|
||||
// TODO(random-liu): Reset this field to false during state recoverry.
|
||||
Removing bool
|
||||
Removing bool `json:"-"`
|
||||
}
|
||||
|
||||
// State returns current state of the container based on the container status.
|
||||
|
||||
@@ -81,6 +81,7 @@ func TestStatusEncodeDecode(t *testing.T) {
|
||||
assert.NoError(err)
|
||||
newS := &Status{}
|
||||
assert.NoError(newS.decode(data))
|
||||
s.Removing = false // Removing should not be encoded.
|
||||
assert.Equal(s, newS)
|
||||
|
||||
unsupported, err := json.Marshal(&versionedStatus{
|
||||
|
||||
@@ -17,17 +17,25 @@ limitations under the License.
|
||||
package sandbox
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
cnins "github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// ErrClosedNetNS is the error returned when network namespace is closed.
|
||||
var ErrClosedNetNS = errors.New("network namespace is closed")
|
||||
|
||||
// NetNS holds network namespace for sandbox
|
||||
type NetNS struct {
|
||||
sync.Mutex
|
||||
ns cnins.NetNS
|
||||
closed bool
|
||||
ns cnins.NetNS
|
||||
closed bool
|
||||
restored bool
|
||||
}
|
||||
|
||||
// NewNetNS creates a network namespace for the sandbox
|
||||
@@ -41,6 +49,22 @@ func NewNetNS() (*NetNS, error) {
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// LoadNetNS loads existing network namespace. It returns ErrClosedNetNS
|
||||
// if the network namespace has already been closed.
|
||||
func LoadNetNS(path string) (*NetNS, error) {
|
||||
if err := cnins.IsNSorErr(path); err != nil {
|
||||
if _, ok := err.(cnins.NSPathNotExistErr); ok {
|
||||
return nil, ErrClosedNetNS
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
ns, err := cnins.GetNS(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load network namespace %v", err)
|
||||
}
|
||||
return &NetNS{ns: ns, restored: true}, nil
|
||||
}
|
||||
|
||||
// Remove removes network namepace if it exists and not closed. Remove is idempotent,
|
||||
// meaning it might be invoked multiple times and provides consistent result.
|
||||
func (n *NetNS) Remove() error {
|
||||
@@ -49,10 +73,34 @@ func (n *NetNS) Remove() error {
|
||||
if !n.closed {
|
||||
err := n.ns.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("failed to close network namespace: %v", err)
|
||||
}
|
||||
n.closed = true
|
||||
}
|
||||
if n.restored {
|
||||
path := n.ns.Path()
|
||||
// TODO(random-liu): Add util function for unmount.
|
||||
// Check netns existence.
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("failed to stat netns: %v", err)
|
||||
}
|
||||
mounted, err := mount.Mounted(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check netns mounted: %v", err)
|
||||
}
|
||||
if mounted {
|
||||
err := unix.Unmount(path, unix.MNT_DETACH)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return fmt.Errorf("failed to umount netns: %v", err)
|
||||
}
|
||||
}
|
||||
if err := os.RemoveAll(path); err != nil {
|
||||
return fmt.Errorf("failed to remove netns: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user