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 }
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") }
func genSocketFile(appInfo *snap.AppInfo) string { socketTemplate := `[Unit] # Auto-generated, DO NO EDIT Description=Socket for snap application {{.App.Snap.Name}}.{{.App.Name}} Requires={{.MountUnit}} Wants={{.PrerequisiteTarget}} After={{.MountUnit}} {{.PrerequisiteTarget}} X-Snappy=yes [Socket] ListenStream={{.App.ListenStream}} {{if .App.SocketMode}}SocketMode={{.App.SocketMode}}{{end}} [Install] WantedBy={{.SocketsTarget}} ` var templateOut bytes.Buffer t := template.Must(template.New("socket-wrapper").Parse(socketTemplate)) wrapperData := struct { App *snap.AppInfo ServiceFileName string PrerequisiteTarget string SocketsTarget string MountUnit string }{ App: appInfo, ServiceFileName: filepath.Base(appInfo.ServiceFile()), SocketsTarget: systemd.SocketsTarget, PrerequisiteTarget: systemd.PrerequisiteTarget, MountUnit: filepath.Base(systemd.MountUnitPath(appInfo.Snap.MountDir())), } if err := t.Execute(&templateOut, wrapperData); err != nil { // this can never happen, except we forget a variable logger.Panicf("Unable to execute template: %v", err) } return templateOut.String() }
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) }
func (s *setupSuite) TestSetupDoUndoSimple(c *C) { snapPath := makeTestSnap(c, helloYaml1) si := snap.SideInfo{ RealName: "hello", Revision: snap.R(14), } err := s.be.SetupSnap(snapPath, &si, &s.nullProgress) c.Assert(err, IsNil) // after setup the snap file is in the right dir c.Assert(osutil.FileExists(filepath.Join(dirs.SnapBlobDir, "hello_14.snap")), Equals, true) // ensure the right unit is created mup := systemd.MountUnitPath("/snap/hello/14", "mount") content, err := ioutil.ReadFile(mup) c.Assert(err, IsNil) c.Assert(string(content), Matches, "(?ms).*^Where=/snap/hello/14") c.Assert(string(content), Matches, "(?ms).*^What=/var/lib/snapd/snaps/hello_14.snap") minInfo := snap.MinimalPlaceInfo("hello", snap.R(14)) // mount dir was created c.Assert(osutil.FileExists(minInfo.MountDir()), Equals, true) // undo undoes the mount unit and the instdir creation err = s.be.UndoSetupSnap(minInfo, "app", &s.nullProgress) c.Assert(err, IsNil) 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) }
func (ms *mgrsSuite) TestHappyLocalInstallWithStoreMetadata(c *C) { snapDecl := ms.prereqSnapAssertions(c) snapYamlContent := `name: foo apps: bar: command: bin/bar ` snapPath := makeTestSnap(c, snapYamlContent+"version: 1.5") si := &snap.SideInfo{ RealName: "foo", SnapID: fooSnapID, Revision: snap.R(55), DeveloperID: "devdevdevID", Developer: "devdevdev", } st := ms.o.State() st.Lock() defer st.Unlock() // have the snap-declaration in the system db err := assertstate.Add(st, ms.storeSigning.StoreAccountKey("")) c.Assert(err, IsNil) err = assertstate.Add(st, ms.devAcct) c.Assert(err, IsNil) err = assertstate.Add(st, snapDecl) c.Assert(err, IsNil) ts, err := snapstate.InstallPath(st, si, 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())) info, err := snapstate.CurrentInfo(st, "foo") c.Assert(err, IsNil) c.Check(info.Revision, Equals, snap.R(55)) c.Check(info.SnapID, Equals, fooSnapID) c.Check(info.DeveloperID, Equals, "devdevdevID") c.Check(info.Developer, Equals, "devdevdev") c.Check(info.Version, Equals, "1.5") // 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(info.DataDir()), Equals, true) c.Assert(osutil.IsDirectory(info.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_55.snap")), Equals, true) // ensure the right unit is created mup := systemd.MountUnitPath("/snap/foo/55") content, err := ioutil.ReadFile(mup) c.Assert(err, IsNil) c.Assert(string(content), Matches, "(?ms).*^Where=/snap/foo/55") c.Assert(string(content), Matches, "(?ms).*^What=/var/lib/snapd/snaps/foo_55.snap") }
func genServiceFile(appInfo *snap.AppInfo) string { serviceTemplate := `[Unit] # Auto-generated, DO NO EDIT Description=Service for snap application {{.App.Snap.Name}}.{{.App.Name}} Requires={{.MountUnit}} Wants={{.PrerequisiteTarget}} After={{.MountUnit}} {{.PrerequisiteTarget}} X-Snappy=yes [Service] ExecStart={{.App.LauncherCommand}} Restart={{.Restart}} WorkingDirectory={{.App.Snap.DataDir}} {{if .App.StopCommand}}ExecStop={{.App.LauncherStopCommand}}{{end}} {{if .App.PostStopCommand}}ExecStopPost={{.App.LauncherPostStopCommand}}{{end}} {{if .StopTimeout}}TimeoutStopSec={{.StopTimeout.Seconds}}{{end}} Type={{.App.Daemon}} {{if .App.BusName}}BusName={{.App.BusName}}{{end}} {{if not .App.Socket}} [Install] WantedBy={{.ServicesTarget}} {{end}}` var templateOut bytes.Buffer t := template.Must(template.New("service-wrapper").Parse(serviceTemplate)) var restartCond string if appInfo.RestartCond == systemd.RestartNever { restartCond = "no" } else { restartCond = appInfo.RestartCond.String() } if restartCond == "" { restartCond = systemd.RestartOnFailure.String() } wrapperData := struct { App *snap.AppInfo Restart string StopTimeout time.Duration ServicesTarget string PrerequisiteTarget string MountUnit string Home string EnvVars string }{ App: appInfo, Restart: restartCond, StopTimeout: serviceStopTimeout(appInfo), ServicesTarget: systemd.ServicesTarget, PrerequisiteTarget: systemd.PrerequisiteTarget, MountUnit: filepath.Base(systemd.MountUnitPath(appInfo.Snap.MountDir())), // systemd runs as PID 1 so %h will not work. Home: "/root", } if err := t.Execute(&templateOut, wrapperData); err != nil { // this can never happen, except we forget a variable logger.Panicf("Unable to execute template: %v", err) } return templateOut.String() }