Exemple #1
0
func (s *backendSuite) TestInstallingSnapCreatesModulesConf(c *C) {
	// NOTE: Hand out a permanent snippet so that .conf file is generated.
	s.Iface.PermanentSlotSnippetCallback = func(slot *interfaces.Slot, securitySystem interfaces.SecuritySystem) ([]byte, error) {
		if securitySystem == interfaces.SecurityKMod {
			return []byte("module1    \n    module2\nmodule1\n#\n"), nil
		}
		return nil, nil
	}

	path := filepath.Join(dirs.SnapKModModulesDir, "snap.samba.conf")
	c.Assert(osutil.FileExists(path), Equals, false)

	for _, devMode := range []bool{true, false} {
		s.modprobeCmd.ForgetCalls()
		snapInfo := s.InstallSnap(c, devMode, backendtest.SambaYamlV1, 0)

		c.Assert(osutil.FileExists(path), Equals, true)
		modfile, err := ioutil.ReadFile(path)
		c.Assert(err, IsNil)
		c.Assert(string(modfile), Equals, "# This file is automatically generated.\nmodule1\nmodule2\n")

		c.Assert(s.modprobeCmd.Calls(), DeepEquals, [][]string{
			{"modprobe", "--syslog", "module1"},
			{"modprobe", "--syslog", "module2"},
		})
		s.RemoveSnap(c, snapInfo)
	}
}
Exemple #2
0
func (s *linkSuite) TestLinkDoUndoCurrentSymlink(c *C) {
	const yaml = `name: hello
version: 1.0
`

	info := snaptest.MockSnap(c, yaml, &snap.SideInfo{Revision: snap.R(11)})

	err := s.be.LinkSnap(info)
	c.Assert(err, IsNil)

	mountDir := info.MountDir()
	dataDir := info.DataDir()
	currentActiveSymlink := filepath.Join(mountDir, "..", "current")
	currentActiveDir, err := filepath.EvalSymlinks(currentActiveSymlink)
	c.Assert(err, IsNil)
	c.Assert(currentActiveDir, Equals, mountDir)

	currentDataSymlink := filepath.Join(dataDir, "..", "current")
	currentDataDir, err := filepath.EvalSymlinks(currentDataSymlink)
	c.Assert(err, IsNil)
	c.Assert(currentDataDir, Equals, dataDir)

	// undo will remove the symlinks
	err = s.be.UnlinkSnap(info, &s.nullProgress)
	c.Assert(err, IsNil)

	c.Check(osutil.FileExists(currentActiveSymlink), Equals, false)
	c.Check(osutil.FileExists(currentDataSymlink), Equals, false)

}
Exemple #3
0
// ExecInCoreSnap makes sure you're executing the binary that ships in
// the core snap.
func ExecInCoreSnap() {
	if !release.OnClassic {
		// you're already the real deal, natch
		return
	}

	if os.Getenv(key) != "1" {
		return
	}

	exe, err := os.Readlink("/proc/self/exe")
	if err != nil {
		return
	}

	full := filepath.Join(newCore, exe)
	if !osutil.FileExists(full) {
		if rev, err := os.Readlink(oldCore); err != nil {
			return
		} else if revno, err := strconv.Atoi(rev); err != nil || revno < minOldRevno {
			return
		}

		full = filepath.Join(oldCore, exe)
		if !osutil.FileExists(full) {
			return
		}
	}

	logger.Debugf("restarting into %q", full)

	env := append(os.Environ(), key+"=0")
	panic(syscall.Exec(full, os.Args, env))
}
Exemple #4
0
func (s *setupSuite) TestSetupUndoIdempotent(c *C) {
	// make sure that a retry wouldn't stumble on partial work
	// use a kernel because that does and need to do strictly more

	// this cannot check systemd own behavior though around mounts!

	bootloader := boottest.NewMockBootloader("mock", c.MkDir())
	partition.ForceBootloader(bootloader)
	// we don't get real mounting
	os.Setenv("SNAPPY_SQUASHFS_UNPACK_FOR_TESTS", "1")
	defer os.Unsetenv("SNAPPY_SQUASHFS_UNPACK_FOR_TESTS")

	testFiles := [][]string{
		{"kernel.img", "kernel"},
		{"initrd.img", "initrd"},
		{"modules/4.4.0-14-generic/foo.ko", "a module"},
		{"firmware/bar.bin", "some firmware"},
		{"meta/kernel.yaml", "version: 4.2"},
	}
	snapPath := snaptest.MakeTestSnapWithFiles(c, `name: kernel
version: 1.0
type: kernel
`, testFiles)

	si := snap.SideInfo{
		RealName: "kernel",
		Revision: snap.R(140),
	}

	err := s.be.SetupSnap(snapPath, &si, &s.nullProgress)
	c.Assert(err, IsNil)

	minInfo := snap.MinimalPlaceInfo("kernel", snap.R(140))

	err = s.be.UndoSetupSnap(minInfo, "kernel", &s.nullProgress)
	c.Assert(err, IsNil)

	// retry run
	err = s.be.UndoSetupSnap(minInfo, "kernel", &s.nullProgress)
	c.Assert(err, IsNil)

	// sanity checks
	l, _ := filepath.Glob(filepath.Join(dirs.SnapServicesDir, "*.mount"))
	c.Assert(l, HasLen, 0)
	c.Assert(osutil.FileExists(minInfo.MountDir()), Equals, false)

	c.Assert(osutil.FileExists(minInfo.MountFile()), Equals, false)

	l, _ = filepath.Glob(filepath.Join(bootloader.Dir(), "*"))
	c.Assert(l, HasLen, 0)
}
Exemple #5
0
func loadState(backend state.Backend) (*state.State, error) {
	if !osutil.FileExists(dirs.SnapStateFile) {
		// fail fast, mostly interesting for tests, this dir is setup
		// by the snapd package
		stateDir := filepath.Dir(dirs.SnapStateFile)
		if !osutil.IsDirectory(stateDir) {
			return nil, fmt.Errorf("fatal: directory %q must be present", stateDir)
		}
		s := state.New(backend)
		patch.Init(s)
		return s, nil
	}

	r, err := os.Open(dirs.SnapStateFile)
	if err != nil {
		return nil, fmt.Errorf("cannot read the state file: %s", err)
	}
	defer r.Close()

	s, err := state.ReadState(backend, r)
	if err != nil {
		return nil, err
	}

	// one-shot migrations
	err = patch.Apply(s)
	if err != nil {
		return nil, err
	}
	return s, nil
}
Exemple #6
0
func (s *SnapSuite) TestSnapRunCreateDataDirs(c *check.C) {
	info, err := snap.InfoFromSnapYaml(mockYaml)
	c.Assert(err, check.IsNil)
	info.SideInfo.Revision = snap.R(42)

	fakeHome := c.MkDir()
	restorer := snaprun.MockUserCurrent(func() (*user.User, error) {
		return &user.User{HomeDir: fakeHome}, nil
	})
	defer restorer()

	err = snaprun.CreateUserDataDirs(info)
	c.Assert(err, check.IsNil)
	c.Check(osutil.FileExists(filepath.Join(fakeHome, "/snap/snapname/42")), check.Equals, true)
	c.Check(osutil.FileExists(filepath.Join(fakeHome, "/snap/snapname/common")), check.Equals, true)
}
Exemple #7
0
func (cs *clientSuite) TestClientLogin(c *check.C) {
	cs.rsp = `{"type": "sync", "result":
                     {"username": "******",
                      "macaroon": "the-root-macaroon",
                      "discharges": ["discharge-macaroon"]}}`

	outfile := filepath.Join(c.MkDir(), "json")
	os.Setenv(client.TestAuthFileEnvKey, outfile)
	defer os.Unsetenv(client.TestAuthFileEnvKey)

	c.Assert(cs.cli.LoggedIn(), check.Equals, false)

	user, err := cs.cli.Login("username", "pass", "")
	c.Check(err, check.IsNil)
	c.Check(user, check.DeepEquals, &client.User{
		Macaroon:   "the-root-macaroon",
		Discharges: []string{"discharge-macaroon"}})

	c.Assert(cs.cli.LoggedIn(), check.Equals, true)

	c.Check(osutil.FileExists(outfile), check.Equals, true)
	content, err := ioutil.ReadFile(outfile)
	c.Check(err, check.IsNil)
	c.Check(string(content), check.Equals, `{"macaroon":"the-root-macaroon","discharges":["discharge-macaroon"]}`)
}
Exemple #8
0
func removeMountUnit(baseDir string, meter progress.Meter) error {
	sysd := systemd.New(dirs.GlobalRootDir, meter)
	unit := systemd.MountUnitPath(dirs.StripRootDir(baseDir), "mount")
	if osutil.FileExists(unit) {
		// use umount -l (lazy) to ensure that even busy mount points
		// can be unmounted.
		// note that the long option --lazy is not supported on trusty.
		if output, err := exec.Command("umount", "-l", baseDir).CombinedOutput(); err != nil {
			return osutil.OutputErr(output, err)
		}

		if err := sysd.Stop(filepath.Base(unit), time.Duration(1*time.Second)); err != nil {
			return err
		}
		if err := sysd.Disable(filepath.Base(unit)); err != nil {
			return err
		}
		if err := os.Remove(unit); err != nil {
			return err
		}
		// daemon-reload to ensure that systemd actually really
		// forgets about this mount unit
		if err := sysd.DaemonReload(); err != nil {
			return err
		}
	}

	return nil
}
Exemple #9
0
// Open opens a given snap file with the right backend
func Open(path string) (Container, error) {

	// see if it's a snapdir first
	if osutil.FileExists(filepath.Join(path, "meta", "snap.yaml")) {
		return snapdir.New(path), nil
	}

	// open the file and check magic
	f, err := os.Open(path)
	if err != nil {
		return nil, fmt.Errorf("cannot open snap: %v", err)
	}
	defer f.Close()

	header := make([]byte, 20)
	if _, err := f.ReadAt(header, 0); err != nil {
		return nil, fmt.Errorf("cannot read snap: %v", err)
	}

	for _, h := range formatHandlers {
		if bytes.HasPrefix(header, h.magic) {
			return h.open(path)
		}
	}

	return nil, fmt.Errorf("cannot open snap: unknown header: %q", header)
}
Exemple #10
0
func (s *kernelOSSuite) TestExtractKernelAssetsNoUnpacksKernelForGrub(c *C) {
	// pretend to be a grub system
	mockGrub := boottest.NewMockBootloader("grub", c.MkDir())
	partition.ForceBootloader(mockGrub)

	files := [][]string{
		{"kernel.img", "I'm a kernel"},
		{"initrd.img", "...and I'm an initrd"},
		{"meta/kernel.yaml", "version: 4.2"},
	}
	si := &snap.SideInfo{
		RealName: "ubuntu-kernel",
		Revision: snap.R(42),
	}
	fn := snaptest.MakeTestSnapWithFiles(c, packageKernel, files)
	snapf, err := snap.Open(fn)
	c.Assert(err, IsNil)

	info, err := snap.ReadInfoFromSnapFile(snapf, si)
	c.Assert(err, IsNil)

	err = boot.ExtractKernelAssets(info, snapf)
	c.Assert(err, IsNil)

	// kernel is *not* here
	kernimg := filepath.Join(mockGrub.Dir(), "ubuntu-kernel_42.snap", "kernel.img")
	c.Assert(osutil.FileExists(kernimg), Equals, false)
}
Exemple #11
0
func (x *cmdShell) Execute(args []string) error {
	if len(args) > 0 {
		return ErrExtraArgs
	}

	shellType := x.Positional.ShellType

	// FIXME: make this generic so that all snaps can provide a
	//        shell
	if shellType == "classic" {
		if !osutil.FileExists("/snap/classic/current") {
			return fmt.Errorf(i18n.G(`Classic dimension disabled on this system.
Use "sudo snap install --devmode classic && sudo classic.create" to enable it.`))
		}

		// we need to re-exec if we do not run as root
		if os.Getuid() != 0 {
			if err := reexecWithSudo(); err != nil {
				return err
			}
		}

		fmt.Fprintln(Stdout, i18n.G(`Entering classic dimension`))
		fmt.Fprintln(Stdout, i18n.G(`

The home directory is shared between snappy and the classic dimension.
Run "exit" to leave the classic shell.
`))
		args := []string{"/snap/bin/classic.shell"}
		return syscall.Exec(args[0], args, os.Environ())
	}

	return fmt.Errorf(i18n.G("unsupported shell %v"), shellType)
}
Exemple #12
0
// RemoveSnapServices disables and removes service units for the applications from the snap which are services.
func RemoveSnapServices(s *snap.Info, inter interacter) error {
	sysd := systemd.New(dirs.GlobalRootDir, inter)

	nservices := 0

	for _, app := range s.Apps {
		if app.Daemon == "" || !osutil.FileExists(app.ServiceFile()) {
			continue
		}
		nservices++

		serviceName := filepath.Base(app.ServiceFile())
		if err := sysd.Disable(serviceName); err != nil {
			return err
		}

		if err := os.Remove(app.ServiceFile()); err != nil && !os.IsNotExist(err) {
			logger.Noticef("Failed to remove service file for %q: %v", serviceName, err)
		}

		if err := os.Remove(app.ServiceSocketFile()); err != nil && !os.IsNotExist(err) {
			logger.Noticef("Failed to remove socket file for %q: %v", serviceName, err)
		}
	}

	// only reload if we actually had services
	if nservices > 0 {
		if err := sysd.DaemonReload(); err != nil {
			return err
		}
	}

	return nil
}
Exemple #13
0
// StopSnapServices stops service units for the applications from the snap which are services.
func StopSnapServices(s *snap.Info, inter interacter) error {
	sysd := systemd.New(dirs.GlobalRootDir, inter)

	for _, app := range s.Apps {
		// Handle the case where service file doesn't exist and don't try to stop it as it will fail.
		// This can happen with snap try when snap.yaml is modified on the fly and a daemon line is added.
		if app.Daemon == "" || !osutil.FileExists(app.ServiceFile()) {
			continue
		}
		serviceName := filepath.Base(app.ServiceFile())
		tout := serviceStopTimeout(app)
		if err := sysd.Stop(serviceName, tout); err != nil {
			if !systemd.IsTimeout(err) {
				return err
			}
			inter.Notify(fmt.Sprintf("%s refused to stop, killing.", serviceName))
			// ignore errors for kill; nothing we'd do differently at this point
			sysd.Kill(serviceName, "TERM")
			time.Sleep(killWait)
			sysd.Kill(serviceName, "KILL")
		}
	}

	return nil

}
Exemple #14
0
// InDeveloperMode returns true if the image was build with --developer-mode
func InDeveloperMode() bool {
	// FIXME: this is a bit terrible, we really need a single
	//        bootloader dir like /boot or /boot/loader
	//        instead of having to query the partition code
	bootloader, err := findBootloader()
	if err != nil {
		// can only happy on systems like ubuntu classic
		// that are not full snappy systems
		return false
	}

	file := filepath.Join(bootloader.Dir(), InstallYamlFile)
	if !osutil.FileExists(file) {
		// no idea
		return false
	}

	InstallYaml, err := parseInstallYaml(file)
	if err != nil {
		// no idea
		return false
	}

	return InstallYaml.InstallOptions.DeveloperMode
}
Exemple #15
0
// newGrub create a new Grub bootloader object
func newGrub() Bootloader {
	g := &grub{}
	if !osutil.FileExists(g.ConfigFile()) {
		return nil
	}

	return g
}
Exemple #16
0
// newUboot create a new Uboot bootloader object
func newUboot() Bootloader {
	u := &uboot{}
	if !osutil.FileExists(u.envFile()) {
		return nil
	}

	return u
}
func (s *SnapSuite) TestAutoImportFromSpoolHappy(c *C) {
	restore := release.MockOnClassic(false)
	defer restore()

	fakeAssertData := []byte("my-assertion")

	n := 0
	total := 2
	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
		switch n {
		case 0:
			c.Check(r.Method, Equals, "POST")
			c.Check(r.URL.Path, Equals, "/v2/assertions")
			postData, err := ioutil.ReadAll(r.Body)
			c.Assert(err, IsNil)
			c.Check(postData, DeepEquals, fakeAssertData)
			fmt.Fprintln(w, `{"type": "sync", "result": {"ready": true, "status": "Done"}}`)
			n++
		case 1:
			c.Check(r.Method, Equals, "POST")
			c.Check(r.URL.Path, Equals, "/v2/create-user")
			postData, err := ioutil.ReadAll(r.Body)
			c.Assert(err, IsNil)
			c.Check(string(postData), Equals, `{"sudoer":true,"known":true}`)

			fmt.Fprintln(w, `{"type": "sync", "result": [{"username": "******"}]}`)
			n++
		default:
			c.Fatalf("unexpected request: %v (expected %d got %d)", r, total, n)
		}

	})

	dirs.SetRootDir(c.MkDir())
	defer dirs.SetRootDir("")

	fakeAssertsFn := filepath.Join(dirs.SnapAssertsSpoolDir, "1234343")
	err := os.MkdirAll(filepath.Dir(fakeAssertsFn), 0755)
	c.Assert(err, IsNil)
	err = ioutil.WriteFile(fakeAssertsFn, fakeAssertData, 0644)
	c.Assert(err, IsNil)

	l, err := logger.NewConsoleLog(s.stderr, 0)
	c.Assert(err, IsNil)
	logger.SetLogger(l)

	rest, err := snap.Parser().ParseArgs([]string{"auto-import"})
	c.Assert(err, IsNil)
	c.Assert(rest, DeepEquals, []string{})
	c.Check(s.Stdout(), Equals, `created user "foo"`+"\n")
	// matches because we may get a:
	//   "WARNING: cannot create syslog logger\n"
	// in the output
	c.Check(s.Stderr(), Matches, fmt.Sprintf("(?ms).*imported %s\n", fakeAssertsFn))
	c.Check(n, Equals, total)

	c.Check(osutil.FileExists(fakeAssertsFn), Equals, false)
}
Exemple #18
0
func (s *imageSuite) TestInstallCloudConfigNoConfig(c *C) {
	targetDir := c.MkDir()
	emptyGadgetDir := c.MkDir()

	dirs.SetRootDir(targetDir)
	err := image.InstallCloudConfig(emptyGadgetDir)
	c.Assert(err, IsNil)
	c.Check(osutil.FileExists(filepath.Join(targetDir, "etc/cloud/cloud-init.disabled")), Equals, true)
}
Exemple #19
0
func (ms *mgrsSuite) TestHappyRevert(c *C) {
	st := ms.o.State()
	st.Lock()
	defer st.Unlock()

	x1Yaml := `name: foo
version: 1.0
apps:
 x1:
  command: bin/bar
`
	x1binary := filepath.Join(dirs.SnapBinariesDir, "foo.x1")

	x2Yaml := `name: foo
version: 2.0
apps:
 x2:
  command: bin/bar
`
	x2binary := filepath.Join(dirs.SnapBinariesDir, "foo.x2")

	ms.installLocalTestSnap(c, x1Yaml)
	ms.installLocalTestSnap(c, x2Yaml)

	// ensure we are on x2
	_, err := os.Lstat(x2binary)
	c.Assert(err, IsNil)
	_, err = os.Lstat(x1binary)
	c.Assert(err, ErrorMatches, ".*no such file.*")

	// now do the revert
	ts, err := snapstate.Revert(st, "foo", snapstate.Flags{})
	c.Assert(err, IsNil)
	chg := st.NewChange("revert-snap", "...")
	chg.AddAll(ts)

	st.Unlock()
	err = ms.o.Settle()
	st.Lock()
	c.Assert(err, IsNil)

	c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("revert-snap change failed with: %v", chg.Err()))

	// ensure that we use x1 now
	_, err = os.Lstat(x1binary)
	c.Assert(err, IsNil)
	_, err = os.Lstat(x2binary)
	c.Assert(err, ErrorMatches, ".*no such file.*")

	// ensure that x1,x2 is still there, revert just moves the "current"
	// pointer
	for _, fn := range []string{"foo_x2.snap", "foo_x1.snap"} {
		p := filepath.Join(dirs.SnapBlobDir, fn)
		c.Assert(osutil.FileExists(p), Equals, true)
	}
}
Exemple #20
0
func (s *backendSuite) TestRemovingSnapRemovesModulesConf(c *C) {
	// NOTE: Hand out a permanent snippet so that .conf file is generated.
	s.Iface.PermanentSlotSnippetCallback = func(slot *interfaces.Slot, securitySystem interfaces.SecuritySystem) ([]byte, error) {
		if securitySystem == interfaces.SecurityKMod {
			return []byte("module1\nmodule2"), nil
		}
		return nil, nil
	}

	path := filepath.Join(dirs.SnapKModModulesDir, "snap.samba.conf")
	c.Assert(osutil.FileExists(path), Equals, false)

	for _, devMode := range []bool{true, false} {
		snapInfo := s.InstallSnap(c, devMode, backendtest.SambaYamlV1, 0)
		c.Assert(osutil.FileExists(path), Equals, true)
		s.RemoveSnap(c, snapInfo)
		c.Assert(osutil.FileExists(path), Equals, false)
	}
}
Exemple #21
0
func init() {
	ReleaseInfo = readOSRelease()
	// Assume that we are running on Classic
	OnClassic = true
	// On Ubuntu, dpkg is not present in an all-snap image so the presence of
	// dpkg status file can be used as an indicator for a classic vs all-snap
	// system.
	if ReleaseInfo.ID == "ubuntu" {
		OnClassic = osutil.FileExists("/var/lib/dpkg/status")
	}
}
Exemple #22
0
func (s *desktopSuite) TestAddPackageDesktopFiles(c *C) {
	expectedDesktopFilePath := filepath.Join(dirs.SnapDesktopFilesDir, "foo_foobar.desktop")
	c.Assert(osutil.FileExists(expectedDesktopFilePath), Equals, false)

	info := snaptest.MockSnap(c, desktopAppYaml, &snap.SideInfo{Revision: snap.R(11)})

	// generate .desktop file in the package baseDir
	baseDir := info.MountDir()
	err := os.MkdirAll(filepath.Join(baseDir, "meta", "gui"), 0755)
	c.Assert(err, IsNil)

	err = ioutil.WriteFile(filepath.Join(baseDir, "meta", "gui", "foobar.desktop"), mockDesktopFile, 0644)
	c.Assert(err, IsNil)

	err = wrappers.AddSnapDesktopFiles(info)
	c.Assert(err, IsNil)
	c.Assert(osutil.FileExists(expectedDesktopFilePath), Equals, true)
	c.Assert(s.mockUpdateDesktopDatabase.Calls(), DeepEquals, [][]string{
		{"update-desktop-database", dirs.SnapDesktopFilesDir},
	})
}
Exemple #23
0
func (s *backendSuite) TestRemove(c *C) {
	appCanaryToGo := filepath.Join(dirs.SnapMountPolicyDir, "snap.hello-world.hello-world.fstab")
	err := ioutil.WriteFile(appCanaryToGo, []byte("ni! ni! ni!"), 0644)
	c.Assert(err, IsNil)

	hookCanaryToGo := filepath.Join(dirs.SnapMountPolicyDir, "snap.hello-world.hook.apply-config.fstab")
	err = ioutil.WriteFile(hookCanaryToGo, []byte("ni! ni! ni!"), 0644)
	c.Assert(err, IsNil)

	canaryToStay := filepath.Join(dirs.SnapMountPolicyDir, "snap.i-stay.really.fstab")
	err = ioutil.WriteFile(canaryToStay, []byte("stay!"), 0644)
	c.Assert(err, IsNil)

	err = s.Backend.Remove("hello-world")
	c.Assert(err, IsNil)

	c.Assert(osutil.FileExists(appCanaryToGo), Equals, false)
	c.Assert(osutil.FileExists(hookCanaryToGo), Equals, false)
	content, err := ioutil.ReadFile(canaryToStay)
	c.Assert(err, IsNil)
	c.Assert(string(content), Equals, "stay!")
}
Exemple #24
0
func (s *PartitionTestSuite) TestInstallBootloaderConfig(c *C) {
	for _, t := range []struct{ gadgetFile, systemFile string }{
		{"grub.conf", "/boot/grub/grub.cfg"},
		{"uboot.conf", "/boot/uboot/uboot.env"},
	} {
		mockGadgetDir := c.MkDir()
		err := ioutil.WriteFile(filepath.Join(mockGadgetDir, t.gadgetFile), nil, 0644)
		err = InstallBootConfig(mockGadgetDir)
		c.Assert(err, IsNil)
		fn := filepath.Join(dirs.GlobalRootDir, t.systemFile)
		c.Assert(osutil.FileExists(fn), Equals, true)
	}
}
Exemple #25
0
func (s *linkSuite) TestLinkUndoIdempotent(c *C) {
	// make sure that a retry wouldn't stumble on partial work

	const yaml = `name: hello
version: 1.0
apps:
 bin:
   command: bin
 svc:
   command: svc
   daemon: simple
`

	info := snaptest.MockSnap(c, yaml, &snap.SideInfo{Revision: snap.R(11)})

	err := s.be.LinkSnap(info)
	c.Assert(err, IsNil)

	err = s.be.UnlinkSnap(info, &s.nullProgress)
	c.Assert(err, IsNil)

	err = s.be.UnlinkSnap(info, &s.nullProgress)
	c.Assert(err, IsNil)

	// no wrappers
	l, err := filepath.Glob(filepath.Join(dirs.SnapBinariesDir, "*"))
	c.Assert(err, IsNil)
	c.Assert(l, HasLen, 0)
	l, err = filepath.Glob(filepath.Join(dirs.SnapServicesDir, "*.service"))
	c.Assert(err, IsNil)
	c.Assert(l, HasLen, 0)

	// no symlinks
	currentActiveSymlink := filepath.Join(info.MountDir(), "..", "current")
	currentDataSymlink := filepath.Join(info.DataDir(), "..", "current")
	c.Check(osutil.FileExists(currentActiveSymlink), Equals, false)
	c.Check(osutil.FileExists(currentDataSymlink), Equals, false)
}
Exemple #26
0
func (b Backend) DiscardSnapNamespace(snapName string) error {
	mntFile := mountNsPath(snapName)
	// If there's a .mnt file that was created by snap-confine we should ask
	// snap-confine to discard it appropriately.
	if osutil.FileExists(mntFile) {
		snapDiscardNs := filepath.Join(dirs.LibExecDir, "snap-discard-ns")
		cmd := exec.Command(snapDiscardNs, snapName)
		output, err := cmd.CombinedOutput()
		if err != nil {
			return fmt.Errorf("cannot discard preserved namespaces of snap %q: %s", snapName, osutil.OutputErr(output, err))
		}
	}
	return nil
}
Exemple #27
0
func autoImportCandidates() ([]string, error) {
	var cands []string

	// see https://www.kernel.org/doc/Documentation/filesystems/proc.txt,
	// sec. 3.5
	f, err := os.Open(mountInfoPath)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		l := strings.Fields(scanner.Text())

		// Per proc.txt:3.5, /proc/<pid>/mountinfo looks like
		//
		//  36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
		//  (1)(2)(3)   (4)   (5)      (6)      (7)   (8) (9)   (10)         (11)
		//
		// and (7) has zero or more elements, find the "-" separator.
		i := 6
		for i < len(l) && l[i] != "-" {
			i++
		}
		if i+2 >= len(l) {
			continue
		}

		mountSrc := l[i+2]

		// skip everything that is not a device (cgroups, debugfs etc)
		if !strings.HasPrefix(mountSrc, "/dev/") {
			continue
		}
		// skip all loop devices (snaps)
		if strings.HasPrefix(mountSrc, "/dev/loop") {
			continue
		}

		mountPoint := l[4]
		cand := filepath.Join(mountPoint, autoImportsName)
		if osutil.FileExists(cand) {
			cands = append(cands, cand)
		}
	}

	return cands, scanner.Err()

}
Exemple #28
0
func (s *mountunitSuite) TestRemoveMountUnit(c *C) {
	info := &snap.Info{
		SideInfo: snap.SideInfo{
			RealName: "foo",
			Revision: snap.R(13),
		},
		Version:       "1.1",
		Architectures: []string{"all"},
	}

	err := backend.AddMountUnit(info, &s.nullProgress)
	c.Assert(err, IsNil)

	// ensure we have the files
	p := filepath.Join(dirs.SnapServicesDir, "snap-foo-13.mount")
	c.Assert(osutil.FileExists(p), Equals, true)

	// now call remove and ensure they are gone
	err = backend.RemoveMountUnit(info.MountDir(), &s.nullProgress)
	c.Assert(err, IsNil)
	p = filepath.Join(dirs.SnapServicesDir, "snaps-foo-13.mount")
	c.Assert(osutil.FileExists(p), Equals, false)
}
Exemple #29
0
func (ms *mgrsSuite) TestHappyRemove(c *C) {
	st := ms.o.State()
	st.Lock()
	defer st.Unlock()

	snapYamlContent := `name: foo
apps:
 bar:
  command: bin/bar
`
	snapInfo := ms.installLocalTestSnap(c, snapYamlContent+"version: 1.0")

	ts, err := snapstate.Remove(st, "foo", snap.R(0))
	c.Assert(err, IsNil)
	chg := st.NewChange("remove-snap", "...")
	chg.AddAll(ts)

	st.Unlock()
	err = ms.o.Settle()
	st.Lock()
	c.Assert(err, IsNil)

	c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("remove-snap change failed with: %v", chg.Err()))

	// ensure that the binary wrapper file got removed
	binaryWrapper := filepath.Join(dirs.SnapBinariesDir, "foo.bar")
	c.Assert(osutil.FileExists(binaryWrapper), Equals, false)

	// data dirs
	c.Assert(osutil.FileExists(snapInfo.DataDir()), Equals, false)
	c.Assert(osutil.FileExists(snapInfo.CommonDataDir()), Equals, false)

	// snap file and its mount
	c.Assert(osutil.FileExists(filepath.Join(dirs.SnapBlobDir, "foo_x1.snap")), Equals, false)
	mup := systemd.MountUnitPath("/snap/foo/x1")
	c.Assert(osutil.FileExists(mup), Equals, false)
}
Exemple #30
0
func (ms *mgrsSuite) TestHappyLocalInstall(c *C) {
	snapYamlContent := `name: foo
apps:
 bar:
  command: bin/bar
`
	snapPath := makeTestSnap(c, snapYamlContent+"version: 1.0")

	st := ms.o.State()
	st.Lock()
	defer st.Unlock()

	ts, err := snapstate.InstallPath(st, &snap.SideInfo{RealName: "foo"}, snapPath, "", snapstate.Flags{DevMode: true})
	c.Assert(err, IsNil)
	chg := st.NewChange("install-snap", "...")
	chg.AddAll(ts)

	st.Unlock()
	err = ms.o.Settle()
	st.Lock()
	c.Assert(err, IsNil)

	c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("install-snap change failed with: %v", chg.Err()))

	snap, err := snapstate.CurrentInfo(st, "foo")
	c.Assert(err, IsNil)

	// ensure that the binary wrapper file got generated with the right
	// name
	binaryWrapper := filepath.Join(dirs.SnapBinariesDir, "foo.bar")
	c.Assert(osutil.IsSymlink(binaryWrapper), Equals, true)

	// data dirs
	c.Assert(osutil.IsDirectory(snap.DataDir()), Equals, true)
	c.Assert(osutil.IsDirectory(snap.CommonDataDir()), Equals, true)

	// snap file and its mounting

	// after install the snap file is in the right dir
	c.Assert(osutil.FileExists(filepath.Join(dirs.SnapBlobDir, "foo_x1.snap")), Equals, true)

	// ensure the right unit is created
	mup := systemd.MountUnitPath("/snap/foo/x1")
	content, err := ioutil.ReadFile(mup)
	c.Assert(err, IsNil)
	c.Assert(string(content), Matches, "(?ms).*^Where=/snap/foo/x1")
	c.Assert(string(content), Matches, "(?ms).*^What=/var/lib/snapd/snaps/foo_x1.snap")

}