mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Prepare to make root overlay the default.
We plan on making --overlay2=root:self the default for runsc. That will be a risky change which might need rollbacks. This change is in preparation for that. We manually set --overlay2=none in places where we don't want the overlay configuration to impact. This change should be a noop. The intention for this change is to make the risky change very small and limited to just flipping a flag. PiperOrigin-RevId: 513930702
This commit is contained in:
@@ -266,17 +266,17 @@ simple-tests: unit-tests # Compatibility target.
|
||||
INTEGRATION_TARGETS := //test/image:image_test //test/e2e:integration_test
|
||||
|
||||
docker-tests: load-basic $(RUNTIME_BIN)
|
||||
@$(call install_runtime,$(RUNTIME),) # Clear flags.
|
||||
@$(call install_runtime,$(RUNTIME),--overlay2=none)
|
||||
@$(call install_runtime,$(RUNTIME)-fdlimit,--fdlimit=2000) # Used by TestRlimitNoFile.
|
||||
@$(call install_runtime,$(RUNTIME)-dcache,--fdlimit=2000 --dcache=100) # Used by TestDentryCacheLimit.
|
||||
@$(call install_runtime,$(RUNTIME)-host-uds,--host-uds=all) # Used by TestHostSocketConnect.
|
||||
@$(call install_runtime,$(RUNTIME)-overlay,--overlay2=all:self) # Used by TestOverlay*.
|
||||
@$(call install_runtime,$(RUNTIME)-no-overlay,--overlay2=none) # Used by TestCheckpointRestore.
|
||||
@$(call test_runtime,$(RUNTIME),$(INTEGRATION_TARGETS) //test/e2e:integration_runtime_test)
|
||||
.PHONY: docker-tests
|
||||
|
||||
# TODO(b/241832602): Run overlay tests with host filestore option after S/R support is added.
|
||||
overlay-tests: load-basic $(RUNTIME_BIN)
|
||||
@$(call install_runtime,$(RUNTIME),--overlay2=all:memory)
|
||||
@$(call install_runtime,$(RUNTIME),--overlay2=all:dir=/tmp)
|
||||
@$(call test_runtime,$(RUNTIME),--test_env=TEST_OVERLAY=true $(INTEGRATION_TARGETS))
|
||||
.PHONY: overlay-tests
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ package tmpfs
|
||||
// afterLoad is called by stateify.
|
||||
func (fs *filesystem) afterLoad() {
|
||||
if fs.privateMF {
|
||||
// TODO(b/241832602): Add S/R support.
|
||||
// TODO(b/271612187): Add S/R support.
|
||||
panic("S/R not supported for private memory files")
|
||||
}
|
||||
fs.mf = fs.mfp.MemoryFile()
|
||||
|
||||
@@ -467,6 +467,20 @@ func WaitForHTTP(ip string, port int, timeout time.Duration) error {
|
||||
return Poll(cb, timeout)
|
||||
}
|
||||
|
||||
// HTTPRequestSucceeds sends a request to a given url and checks that the status is OK.
|
||||
func HTTPRequestSucceeds(client http.Client, server string, port int) error {
|
||||
url := fmt.Sprintf("http://%s:%d", server, port)
|
||||
// Ensure that content is being served.
|
||||
resp, err := client.Get(url)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reaching http server: %v", err)
|
||||
}
|
||||
if want := http.StatusOK; resp.StatusCode != want {
|
||||
return fmt.Errorf("wrong response code, got: %d, want: %d", resp.StatusCode, want)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reaper reaps child processes.
|
||||
type Reaper struct {
|
||||
// mu protects ch, which will be nil if the reaper is not running.
|
||||
|
||||
+6
-3
@@ -146,9 +146,12 @@ func (c *Do) Execute(_ context.Context, f *flag.FlagSet, args ...any) subcommand
|
||||
return util.Errorf("Error to retrieve hostname: %v", err)
|
||||
}
|
||||
|
||||
// If c.overlay is set, then forcefully enable overlay.
|
||||
if overlay2 := conf.GetOverlay2(); c.overlay && !overlay2.Enabled() {
|
||||
conf.Overlay = true
|
||||
// If c.overlay is set, then enable overlay.
|
||||
conf.Overlay = false // conf.Overlay is deprecated.
|
||||
if c.overlay {
|
||||
conf.Overlay2 = config.Overlay2{RootMount: true, SubMounts: true, Medium: "memory"}
|
||||
} else {
|
||||
conf.Overlay2 = config.Overlay2{RootMount: false, SubMounts: false, Medium: ""}
|
||||
}
|
||||
absRoot, err := resolvePath(c.root)
|
||||
if err != nil {
|
||||
|
||||
@@ -322,7 +322,7 @@ func (c *Config) validate() error {
|
||||
return fmt.Errorf("overlay flag has been replaced with overlay2 flag")
|
||||
}
|
||||
if overlay2 := c.GetOverlay2(); c.FileAccess == FileAccessShared && overlay2.Enabled() {
|
||||
return fmt.Errorf("overlay flag is incompatible with shared file access")
|
||||
return fmt.Errorf("overlay flag is incompatible with shared file access for rootfs")
|
||||
}
|
||||
if c.NumNetworkChannels <= 0 {
|
||||
return fmt.Errorf("num_network_channels must be > 0, got: %d", c.NumNetworkChannels)
|
||||
@@ -705,7 +705,9 @@ func defaultOverlay2() *Overlay2 {
|
||||
// Set implements flag.Value.
|
||||
func (o *Overlay2) Set(v string) error {
|
||||
if v == "none" {
|
||||
// Defaults are correct.
|
||||
o.RootMount = false
|
||||
o.SubMounts = false
|
||||
o.Medium = ""
|
||||
return nil
|
||||
}
|
||||
vs := strings.Split(v, ":")
|
||||
|
||||
@@ -252,7 +252,7 @@ func TestValidationFail(t *testing.T) {
|
||||
name: "shared+overlay",
|
||||
flags: map[string]string{
|
||||
"file-access": "shared",
|
||||
"overlay": "true",
|
||||
"overlay2": "root:self",
|
||||
},
|
||||
error: "overlay flag is incompatible",
|
||||
},
|
||||
|
||||
@@ -408,6 +408,7 @@ func configs(t *testing.T, noOverlay bool) map[string]*config.Config {
|
||||
cs := make(map[string]*config.Config)
|
||||
for _, p := range ps {
|
||||
c := testutil.TestConfig(t)
|
||||
c.Overlay2 = config.Overlay2{RootMount: false, SubMounts: false, Medium: ""}
|
||||
c.Platform = p
|
||||
cs[p] = c
|
||||
}
|
||||
@@ -417,7 +418,7 @@ func configs(t *testing.T, noOverlay bool) map[string]*config.Config {
|
||||
for _, p := range ps {
|
||||
c := testutil.TestConfig(t)
|
||||
c.Platform = p
|
||||
c.Overlay = true
|
||||
c.Overlay2 = config.Overlay2{RootMount: true, SubMounts: true, Medium: "memory"}
|
||||
cs[p+"-overlay"] = c
|
||||
}
|
||||
}
|
||||
@@ -616,7 +617,8 @@ func TestExePath(t *testing.T) {
|
||||
"default": testutil.TestConfig(t),
|
||||
"overlay": testutil.TestConfig(t),
|
||||
}
|
||||
configs["overlay"].Overlay = true
|
||||
configs["default"].Overlay2 = config.Overlay2{RootMount: false, SubMounts: false, Medium: ""}
|
||||
configs["overlay"].Overlay2 = config.Overlay2{RootMount: true, SubMounts: true, Medium: "memory"}
|
||||
|
||||
for name, conf := range configs {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
|
||||
@@ -1086,7 +1086,7 @@ func TestMultiContainerDifferentFilesystems(t *testing.T) {
|
||||
|
||||
// Make sure overlay is enabled, and none of the root filesystems are
|
||||
// read-only, otherwise we won't be able to create the file.
|
||||
conf.Overlay = true
|
||||
conf.Overlay2 = config.Overlay2{RootMount: true, SubMounts: true, Medium: "memory"}
|
||||
specs, ids := createSpecs(cmdRoot, cmd, cmd)
|
||||
for _, s := range specs {
|
||||
s.Root.Readonly = false
|
||||
|
||||
@@ -33,6 +33,7 @@ import (
|
||||
// into and out of the sandbox.
|
||||
func TestSharedVolume(t *testing.T) {
|
||||
conf := testutil.TestConfig(t)
|
||||
conf.Overlay2 = config.Overlay2{RootMount: false, SubMounts: false, Medium: ""}
|
||||
conf.FileAccess = config.FileAccessShared
|
||||
|
||||
// Main process just sleeps. We will use "exec" to probe the state of
|
||||
@@ -145,11 +146,6 @@ func TestSharedVolume(t *testing.T) {
|
||||
t.Errorf("stat %q got error %v, wanted nil", filename, err)
|
||||
}
|
||||
|
||||
// File should exist outside the sandbox.
|
||||
if _, err := os.Stat(filename); err != nil {
|
||||
t.Errorf("stat %q got error %v, wanted nil", filename, err)
|
||||
}
|
||||
|
||||
// Delete the file from within the sandbox.
|
||||
argsRemove := &control.ExecArgs{
|
||||
Filename: "/bin/rm",
|
||||
@@ -186,6 +182,7 @@ func checkFile(conf *config.Config, c *Container, filename string, want []byte)
|
||||
// is reflected inside.
|
||||
func TestSharedVolumeFile(t *testing.T) {
|
||||
conf := testutil.TestConfig(t)
|
||||
conf.Overlay2 = config.Overlay2{RootMount: false, SubMounts: false, Medium: ""}
|
||||
conf.FileAccess = config.FileAccessShared
|
||||
|
||||
// Main process just sleeps. We will use "exec" to probe the state of
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
@@ -213,3 +214,56 @@ func TestOverlayRootfsWhiteout(t *testing.T) {
|
||||
t.Errorf("root directory contains a file/directory whose name contains %q: output = %q", boot.SelfOverlayFilestorePrefix, got)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(b/271612187): Once S/R support is added for file-backed overlays, move
|
||||
// this test to integration_test.go so it can run with the default runsc
|
||||
// configuration which uses file-backed overlay.
|
||||
func TestCheckpointRestore(t *testing.T) {
|
||||
if !testutil.IsCheckpointSupported() {
|
||||
t.Skip("Pause/resume is not supported.")
|
||||
}
|
||||
dockerutil.EnsureDockerExperimentalEnabled()
|
||||
|
||||
ctx := context.Background()
|
||||
d := dockerutil.MakeContainerWithRuntime(ctx, t, "-no-overlay")
|
||||
defer d.CleanUp(ctx)
|
||||
|
||||
// Start the container.
|
||||
port := 8080
|
||||
if err := d.Spawn(ctx, dockerutil.RunOpts{
|
||||
Image: "basic/python",
|
||||
Ports: []int{port}, // See Dockerfile.
|
||||
}); err != nil {
|
||||
t.Fatalf("docker run failed: %v", err)
|
||||
}
|
||||
|
||||
// Create a snapshot.
|
||||
if err := d.Checkpoint(ctx, "test"); err != nil {
|
||||
t.Fatalf("docker checkpoint failed: %v", err)
|
||||
}
|
||||
if err := d.WaitTimeout(ctx, defaultWait); err != nil {
|
||||
t.Fatalf("wait failed: %v", err)
|
||||
}
|
||||
|
||||
// TODO(b/143498576): Remove Poll after github.com/moby/moby/issues/38963 is fixed.
|
||||
if err := testutil.Poll(func() error { return d.Restore(ctx, "test") }, defaultWait); err != nil {
|
||||
t.Fatalf("docker restore failed: %v", err)
|
||||
}
|
||||
|
||||
// Find container IP address.
|
||||
ip, err := d.FindIP(ctx, false)
|
||||
if err != nil {
|
||||
t.Fatalf("docker.FindIP failed: %v", err)
|
||||
}
|
||||
|
||||
// Wait until it's up and running.
|
||||
if err := testutil.WaitForHTTP(ip.String(), port, defaultWait); err != nil {
|
||||
t.Fatalf("WaitForHTTP() timeout: %v", err)
|
||||
}
|
||||
|
||||
// Check if container is working again.
|
||||
client := http.Client{Timeout: defaultWait}
|
||||
if err := testutil.HTTPRequestSucceeds(client, ip.String(), port); err != nil {
|
||||
t.Error("http request failed:", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,20 +56,6 @@ func TestMain(m *testing.M) {
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
// httpRequestSucceeds sends a request to a given url and checks that the status is OK.
|
||||
func httpRequestSucceeds(client http.Client, server string, port int) error {
|
||||
url := fmt.Sprintf("http://%s:%d", server, port)
|
||||
// Ensure that content is being served.
|
||||
resp, err := client.Get(url)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reaching http server: %v", err)
|
||||
}
|
||||
if want := http.StatusOK; resp.StatusCode != want {
|
||||
return fmt.Errorf("wrong response code, got: %d, want: %d", resp.StatusCode, want)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TestLifeCycle tests a basic Create/Start/Stop docker container life cycle.
|
||||
func TestLifeCycle(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
@@ -96,7 +82,7 @@ func TestLifeCycle(t *testing.T) {
|
||||
t.Fatalf("WaitForHTTP() timeout: %v", err)
|
||||
}
|
||||
client := http.Client{Timeout: defaultWait}
|
||||
if err := httpRequestSucceeds(client, ip.String(), port); err != nil {
|
||||
if err := testutil.HTTPRequestSucceeds(client, ip.String(), port); err != nil {
|
||||
t.Errorf("http request failed: %v", err)
|
||||
}
|
||||
|
||||
@@ -139,7 +125,7 @@ func TestPauseResume(t *testing.T) {
|
||||
|
||||
// Check that container is working.
|
||||
client := http.Client{Timeout: defaultWait}
|
||||
if err := httpRequestSucceeds(client, ip.String(), port); err != nil {
|
||||
if err := testutil.HTTPRequestSucceeds(client, ip.String(), port); err != nil {
|
||||
t.Error("http request failed:", err)
|
||||
}
|
||||
|
||||
@@ -171,57 +157,7 @@ func TestPauseResume(t *testing.T) {
|
||||
|
||||
// Check if container is working again.
|
||||
client = http.Client{Timeout: defaultWait}
|
||||
if err := httpRequestSucceeds(client, ip.String(), port); err != nil {
|
||||
t.Error("http request failed:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckpointRestore(t *testing.T) {
|
||||
if !testutil.IsCheckpointSupported() {
|
||||
t.Skip("Pause/resume is not supported.")
|
||||
}
|
||||
dockerutil.EnsureDockerExperimentalEnabled()
|
||||
|
||||
ctx := context.Background()
|
||||
d := dockerutil.MakeContainer(ctx, t)
|
||||
defer d.CleanUp(ctx)
|
||||
|
||||
// Start the container.
|
||||
port := 8080
|
||||
if err := d.Spawn(ctx, dockerutil.RunOpts{
|
||||
Image: "basic/python",
|
||||
Ports: []int{port}, // See Dockerfile.
|
||||
}); err != nil {
|
||||
t.Fatalf("docker run failed: %v", err)
|
||||
}
|
||||
|
||||
// Create a snapshot.
|
||||
if err := d.Checkpoint(ctx, "test"); err != nil {
|
||||
t.Fatalf("docker checkpoint failed: %v", err)
|
||||
}
|
||||
if err := d.WaitTimeout(ctx, defaultWait); err != nil {
|
||||
t.Fatalf("wait failed: %v", err)
|
||||
}
|
||||
|
||||
// TODO(b/143498576): Remove Poll after github.com/moby/moby/issues/38963 is fixed.
|
||||
if err := testutil.Poll(func() error { return d.Restore(ctx, "test") }, defaultWait); err != nil {
|
||||
t.Fatalf("docker restore failed: %v", err)
|
||||
}
|
||||
|
||||
// Find container IP address.
|
||||
ip, err := d.FindIP(ctx, false)
|
||||
if err != nil {
|
||||
t.Fatalf("docker.FindIP failed: %v", err)
|
||||
}
|
||||
|
||||
// Wait until it's up and running.
|
||||
if err := testutil.WaitForHTTP(ip.String(), port, defaultWait); err != nil {
|
||||
t.Fatalf("WaitForHTTP() timeout: %v", err)
|
||||
}
|
||||
|
||||
// Check if container is working again.
|
||||
client := http.Client{Timeout: defaultWait}
|
||||
if err := httpRequestSucceeds(client, ip.String(), port); err != nil {
|
||||
if err := testutil.HTTPRequestSucceeds(client, ip.String(), port); err != nil {
|
||||
t.Error("http request failed:", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,6 +238,8 @@ func runRunsc(tc *gtest.TestCase, spec *specs.Spec) error {
|
||||
}
|
||||
if *overlay {
|
||||
args = append(args, "-overlay2=all:dir=/tmp")
|
||||
} else {
|
||||
args = append(args, "-overlay2=none")
|
||||
}
|
||||
if *debug {
|
||||
args = append(args, "-debug", "-log-packets=true")
|
||||
|
||||
@@ -8,3 +8,4 @@ test_readline,b/162980389,TestReadline hangs forever
|
||||
test_resource,b/76174079,
|
||||
test_signal,,Flaky - signal: alarm clock
|
||||
test_socket,,Broken test
|
||||
test_os,b/271473320,TestScandir.test_attributes fails with overlay
|
||||
|
||||
|
Reference in New Issue
Block a user