summaryrefslogtreecommitdiff
diff options
-rw-r--r--cmd/snap-update-ns/common.go5
-rw-r--r--cmd/snap-update-ns/common_test.go3
-rw-r--r--cmd/snap-update-ns/export_test.go31
-rw-r--r--sandbox/cgroup/export_test.go16
-rw-r--r--sandbox/cgroup/freezer.go (renamed from cmd/snap-update-ns/freezer.go)38
-rw-r--r--sandbox/cgroup/freezer_test.go (renamed from cmd/snap-update-ns/freezer_test.go)28
-rw-r--r--tests/main/lxd-no-fuse/task.yaml5
-rw-r--r--tests/main/lxd-snapfuse/task.yaml5
8 files changed, 75 insertions, 56 deletions
diff --git a/cmd/snap-update-ns/common.go b/cmd/snap-update-ns/common.go
index b669e8a217..805d843f41 100644
--- a/cmd/snap-update-ns/common.go
+++ b/cmd/snap-update-ns/common.go
@@ -25,6 +25,7 @@ import (
"github.com/snapcore/snapd/cmd/snaplock"
"github.com/snapcore/snapd/logger"
"github.com/snapcore/snapd/osutil"
+ "github.com/snapcore/snapd/sandbox/cgroup"
)
type CommonProfileUpdateContext struct {
@@ -78,7 +79,7 @@ func (upCtx *CommonProfileUpdateContext) Lock() (func(), error) {
// introduce a symlink that would cause us to mount something other
// than what we expected).
logger.Debugf("freezing processes of snap %q", instanceName)
- if err := freezeSnapProcesses(instanceName); err != nil {
+ if err := cgroup.FreezeSnapProcesses(instanceName); err != nil {
// If we cannot freeze the processes we should drop the lock.
lock.Close()
return nil, err
@@ -88,7 +89,7 @@ func (upCtx *CommonProfileUpdateContext) Lock() (func(), error) {
logger.Debugf("unlocking mount namespace of snap %q", instanceName)
lock.Close()
logger.Debugf("thawing processes of snap %q", instanceName)
- thawSnapProcesses(instanceName)
+ cgroup.ThawSnapProcesses(instanceName)
}
return unlock, nil
}
diff --git a/cmd/snap-update-ns/common_test.go b/cmd/snap-update-ns/common_test.go
index 400579bb1e..00e54c6426 100644
--- a/cmd/snap-update-ns/common_test.go
+++ b/cmd/snap-update-ns/common_test.go
@@ -31,6 +31,7 @@ import (
"github.com/snapcore/snapd/cmd/snaplock"
"github.com/snapcore/snapd/dirs"
"github.com/snapcore/snapd/osutil"
+ "github.com/snapcore/snapd/sandbox/cgroup"
"github.com/snapcore/snapd/testutil"
)
@@ -55,7 +56,7 @@ func (s *commonSuite) TestInstanceName(c *C) {
func (s *commonSuite) TestLock(c *C) {
// Mock away real freezer code, allowing test code to return an error when freezing.
var freezingError error
- restore := update.MockFreezing(func(string) error { return freezingError }, func(string) error { return nil })
+ restore := cgroup.MockFreezing(func(string) error { return freezingError }, func(string) error { return nil })
defer restore()
// Mock system directories, we use the lock directory.
dirs.SetRootDir(s.dir)
diff --git a/cmd/snap-update-ns/export_test.go b/cmd/snap-update-ns/export_test.go
index 7ef3d5bbe3..7c7a254d6a 100644
--- a/cmd/snap-update-ns/export_test.go
+++ b/cmd/snap-update-ns/export_test.go
@@ -23,8 +23,6 @@ import (
"os"
"syscall"
- . "gopkg.in/check.v1"
-
"github.com/snapcore/snapd/osutil"
"github.com/snapcore/snapd/osutil/sys"
)
@@ -34,10 +32,6 @@ var (
ValidateInstanceName = validateInstanceName
ProcessArguments = processArguments
- // freezer
- FreezeSnapProcesses = freezeSnapProcesses
- ThawSnapProcesses = thawSnapProcesses
-
// utils
PlanWritableMimic = planWritableMimic
ExecWritableMimic = execWritableMimic
@@ -149,31 +143,6 @@ func MockSystemCalls(sc SystemCalls) (restore func()) {
}
}
-func MockFreezerCgroupDir(c *C) (restore func()) {
- old := freezerCgroupDir
- freezerCgroupDir = c.MkDir()
- return func() {
- freezerCgroupDir = old
- }
-}
-
-func FreezerCgroupDir() string {
- return freezerCgroupDir
-}
-
-func MockFreezing(freeze, thaw func(snapName string) error) (restore func()) {
- oldFreeze := freezeSnapProcesses
- oldThaw := thawSnapProcesses
-
- freezeSnapProcesses = freeze
- thawSnapProcesses = thaw
-
- return func() {
- freezeSnapProcesses = oldFreeze
- thawSnapProcesses = oldThaw
- }
-}
-
func MockChangePerform(f func(chg *Change, as *Assumptions) ([]*Change, error)) func() {
origChangePerform := changePerform
changePerform = f
diff --git a/sandbox/cgroup/export_test.go b/sandbox/cgroup/export_test.go
index ab918ba2fa..35f8381391 100644
--- a/sandbox/cgroup/export_test.go
+++ b/sandbox/cgroup/export_test.go
@@ -18,6 +18,10 @@
*/
package cgroup
+import (
+ . "gopkg.in/check.v1"
+)
+
var (
Cgroup2SuperMagic = cgroup2SuperMagic
ProbeCgroupVersion = probeCgroupVersion
@@ -38,3 +42,15 @@ func MockFsRootPath(p string) (restore func()) {
rootPath = old
}
}
+
+func MockFreezerCgroupDir(c *C) (restore func()) {
+ old := freezerCgroupDir
+ freezerCgroupDir = c.MkDir()
+ return func() {
+ freezerCgroupDir = old
+ }
+}
+
+func FreezerCgroupDir() string {
+ return freezerCgroupDir
+}
diff --git a/cmd/snap-update-ns/freezer.go b/sandbox/cgroup/freezer.go
index 9cce4557c6..c7220ad0a2 100644
--- a/cmd/snap-update-ns/freezer.go
+++ b/sandbox/cgroup/freezer.go
@@ -17,7 +17,7 @@
*
*/
-package main
+package cgroup
import (
"bytes"
@@ -30,10 +30,22 @@ import (
var freezerCgroupDir = "/sys/fs/cgroup/freezer"
-var (
- freezeSnapProcesses = freezeSnapProcessesImpl
- thawSnapProcesses = thawSnapProcessesImpl
-)
+// FreezeSnapProcessesImpl suspends execution of all the processes belonging to
+// a given snap. Processes remain frozen until ThawSnapProcesses is called,
+// care must be taken not to freezer processes indefinitely.
+//
+// The freeze operation is not instant. Once commenced it proceeds
+// asynchronously. Internally the function waits for the freezing to complete
+// in at most 3000ms. If this time is insufficient then the processes are
+// thawed and an error is returned.
+//
+// This operation can be mocked with MockFreezing
+var FreezeSnapProcesses = freezeSnapProcessesImpl
+
+// ThawSnapProcesses resumes execution of all processes belonging to a given snap.
+//
+// This operation can be mocked with MockFreezing
+var ThawSnapProcesses = thawSnapProcessesImpl
// freezeSnapProcessesImpl freezes all the processes originating from the given snap.
// Processes are frozen regardless of which particular snap application they
@@ -61,7 +73,7 @@ func freezeSnapProcessesImpl(snapName string) error {
return nil
}
// If we got here then we timed out after seeing FREEZING for too long.
- thawSnapProcesses(snapName) // ignore the error, this is best-effort.
+ ThawSnapProcesses(snapName) // ignore the error, this is best-effort.
return fmt.Errorf("cannot finish freezing processes of snap %q", snapName)
}
@@ -77,3 +89,17 @@ func thawSnapProcessesImpl(snapName string) error {
}
return nil
}
+
+// MockFreezing replaces the real implementation of freeze and thaw.
+func MockFreezing(freeze, thaw func(snapName string) error) (restore func()) {
+ oldFreeze := FreezeSnapProcesses
+ oldThaw := ThawSnapProcesses
+
+ FreezeSnapProcesses = freeze
+ ThawSnapProcesses = thaw
+
+ return func() {
+ FreezeSnapProcesses = oldFreeze
+ ThawSnapProcesses = oldThaw
+ }
+}
diff --git a/cmd/snap-update-ns/freezer_test.go b/sandbox/cgroup/freezer_test.go
index 89813ffbed..668cb419e8 100644
--- a/cmd/snap-update-ns/freezer_test.go
+++ b/sandbox/cgroup/freezer_test.go
@@ -17,7 +17,7 @@
*
*/
-package main_test
+package cgroup_test
import (
"fmt"
@@ -26,7 +26,7 @@ import (
. "gopkg.in/check.v1"
- update "github.com/snapcore/snapd/cmd/snap-update-ns"
+ "github.com/snapcore/snapd/sandbox/cgroup"
"github.com/snapcore/snapd/testutil"
)
@@ -35,56 +35,56 @@ type freezerSuite struct{}
var _ = Suite(&freezerSuite{})
func (s *freezerSuite) TestFreezeSnapProcesses(c *C) {
- restore := update.MockFreezerCgroupDir(c)
+ restore := cgroup.MockFreezerCgroupDir(c)
defer restore()
n := "foo" // snap name
- p := filepath.Join(update.FreezerCgroupDir(), fmt.Sprintf("snap.%s", n)) // snap freezer cgroup
+ p := filepath.Join(cgroup.FreezerCgroupDir(), fmt.Sprintf("snap.%s", n)) // snap freezer cgroup
f := filepath.Join(p, "freezer.state") // freezer.state file of the cgroup
// When the freezer cgroup filesystem doesn't exist we do nothing at all.
- c.Assert(update.FreezeSnapProcesses(n), IsNil)
+ c.Assert(cgroup.FreezeSnapProcesses(n), IsNil)
_, err := os.Stat(f)
c.Assert(os.IsNotExist(err), Equals, true)
// When the freezer cgroup filesystem exists but the particular cgroup
// doesn't exist we don nothing at all.
- c.Assert(os.MkdirAll(update.FreezerCgroupDir(), 0755), IsNil)
- c.Assert(update.FreezeSnapProcesses(n), IsNil)
+ c.Assert(os.MkdirAll(cgroup.FreezerCgroupDir(), 0755), IsNil)
+ c.Assert(cgroup.FreezeSnapProcesses(n), IsNil)
_, err = os.Stat(f)
c.Assert(os.IsNotExist(err), Equals, true)
// When the cgroup exists we write FROZEN the freezer.state file.
c.Assert(os.MkdirAll(p, 0755), IsNil)
- c.Assert(update.FreezeSnapProcesses(n), IsNil)
+ c.Assert(cgroup.FreezeSnapProcesses(n), IsNil)
_, err = os.Stat(f)
c.Assert(err, IsNil)
c.Assert(f, testutil.FileEquals, `FROZEN`)
}
func (s *freezerSuite) TestThawSnapProcesses(c *C) {
- restore := update.MockFreezerCgroupDir(c)
+ restore := cgroup.MockFreezerCgroupDir(c)
defer restore()
n := "foo" // snap name
- p := filepath.Join(update.FreezerCgroupDir(), fmt.Sprintf("snap.%s", n)) // snap freezer cgroup
+ p := filepath.Join(cgroup.FreezerCgroupDir(), fmt.Sprintf("snap.%s", n)) // snap freezer cgroup
f := filepath.Join(p, "freezer.state") // freezer.state file of the cgroup
// When the freezer cgroup filesystem doesn't exist we do nothing at all.
- c.Assert(update.ThawSnapProcesses(n), IsNil)
+ c.Assert(cgroup.ThawSnapProcesses(n), IsNil)
_, err := os.Stat(f)
c.Assert(os.IsNotExist(err), Equals, true)
// When the freezer cgroup filesystem exists but the particular cgroup
// doesn't exist we don nothing at all.
- c.Assert(os.MkdirAll(update.FreezerCgroupDir(), 0755), IsNil)
- c.Assert(update.ThawSnapProcesses(n), IsNil)
+ c.Assert(os.MkdirAll(cgroup.FreezerCgroupDir(), 0755), IsNil)
+ c.Assert(cgroup.ThawSnapProcesses(n), IsNil)
_, err = os.Stat(f)
c.Assert(os.IsNotExist(err), Equals, true)
// When the cgroup exists we write THAWED the freezer.state file.
c.Assert(os.MkdirAll(p, 0755), IsNil)
- c.Assert(update.ThawSnapProcesses(n), IsNil)
+ c.Assert(cgroup.ThawSnapProcesses(n), IsNil)
_, err = os.Stat(f)
c.Assert(err, IsNil)
c.Assert(f, testutil.FileEquals, `THAWED`)
diff --git a/tests/main/lxd-no-fuse/task.yaml b/tests/main/lxd-no-fuse/task.yaml
index 516eacd6b3..f8149f2983 100644
--- a/tests/main/lxd-no-fuse/task.yaml
+++ b/tests/main/lxd-no-fuse/task.yaml
@@ -23,7 +23,10 @@ execute: |
lxd.lxc config set core.proxy_https "$http_proxy"
fi
- lxd.lxc launch "images:ubuntu/18.04" my-ubuntu
+ # The snapd package we build as part of the tests will only run on the
+ # distro we build on. So we need to launch the right ubuntu version.
+ . /etc/os-release
+ lxd.lxc launch "ubuntu:${VERSION_ID}" my-ubuntu
echo "Remove fuse to trigger the fuse sanity check"
lxd.lxc exec my-ubuntu -- apt autoremove -y fuse
diff --git a/tests/main/lxd-snapfuse/task.yaml b/tests/main/lxd-snapfuse/task.yaml
index da4c5d6e7f..d1a20d2c96 100644
--- a/tests/main/lxd-snapfuse/task.yaml
+++ b/tests/main/lxd-snapfuse/task.yaml
@@ -29,7 +29,10 @@ execute: |
lxd.lxc config set core.proxy_https "$http_proxy"
fi
- lxd.lxc launch "images:ubuntu/18.04" my-ubuntu
+ # The snapd package we build as part of the tests will only run on the
+ # distro we build on. So we need to launch the right ubuntu version.
+ . /etc/os-release
+ lxd.lxc launch "ubuntu:${VERSION_ID}" my-ubuntu
echo "Install snapd"
lxd.lxc exec my-ubuntu -- mkdir -p "$GOHOME"