Esempio n. 1
1
// 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 == "" {
			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
}
Esempio n. 2
0
func removeCurrentSymlinks(info snap.PlaceInfo) error {
	var err1, err2 error

	// the snap "current" symlink
	currentActiveSymlink := filepath.Join(info.MountDir(), "..", "current")
	err1 = os.Remove(currentActiveSymlink)
	if err1 != nil && !os.IsNotExist(err1) {
		logger.Noticef("Cannot remove %q: %v", currentActiveSymlink, err1)
	} else {
		err1 = nil
	}

	// the data "current" symlink
	currentDataSymlink := filepath.Join(info.DataDir(), "..", "current")
	err2 = os.Remove(currentDataSymlink)
	if err2 != nil && !os.IsNotExist(err2) {
		logger.Noticef("Cannot remove %q: %v", currentDataSymlink, err2)
	} else {
		err2 = nil
	}

	if err1 != nil && err2 != nil {
		return fmt.Errorf("cannot remove snap current symlink: %v and %v", err1, err2)
	} else if err1 != nil {
		return fmt.Errorf("cannot remove snap current symlink: %v", err1)
	} else if err2 != nil {
		return fmt.Errorf("cannot remove snap current symlink: %v", err2)
	}

	return nil
}
Esempio n. 3
0
func autoImportFromAllMounts() (int, error) {
	cands, err := autoImportCandidates()
	if err != nil {
		return 0, err
	}

	added := 0
	for _, cand := range cands {
		err := ackFile(cand)
		// the server is not ready yet
		if _, ok := err.(client.ConnectionError); ok {
			logger.Noticef("queuing for later %s", cand)
			if err := queueFile(cand); err != nil {
				return 0, err
			}
			continue
		}
		if err != nil {
			logger.Noticef("error: cannot import %s: %s", cand, err)
			continue
		} else {
			logger.Noticef("imported %s", cand)
		}
		added++
	}

	return added, nil
}
Esempio n. 4
0
func autoImportFromSpool() (added int, err error) {
	files, err := ioutil.ReadDir(dirs.SnapAssertsSpoolDir)
	if os.IsNotExist(err) {
		return 0, nil
	}
	if err != nil {
		return 0, err
	}

	for _, fi := range files {
		cand := filepath.Join(dirs.SnapAssertsSpoolDir, fi.Name())
		if err := ackFile(cand); err != nil {
			logger.Noticef("error: cannot import %s: %s", cand, err)
			continue
		} else {
			logger.Noticef("imported %s", cand)
			added++
		}
		// FIXME: only remove stuff older than N days?
		if err := os.Remove(cand); err != nil {
			return 0, err
		}
	}

	return added, nil
}
Esempio n. 5
0
// patch1 adds the snap type and the current revision to the snap state.
func patch1(s *state.State) error {
	var stateMap map[string]*snapstate.SnapState

	err := s.Get("snaps", &stateMap)
	if err == state.ErrNoState {
		return nil
	}
	if err != nil {
		return err
	}

	for snapName, snapState := range stateMap {
		seq := snapState.Sequence
		if len(seq) == 0 {
			continue
		}
		typ := snap.TypeApp
		snapInfo, err := readInfo(snapName, seq[len(seq)-1])
		if err != nil {
			logger.Noticef("Recording type for snap %q: cannot retrieve info, assuming it's a app: %v", snapName, err)
		} else {
			logger.Noticef("Recording type for snap %q: setting to %q", snapName, snapInfo.Type)
			typ = snapInfo.Type
		}
		snapState.SetType(typ)
		snapState.Current = seq[len(seq)-1].Revision
	}

	s.Set("snaps", stateMap)
	return nil
}
Esempio n. 6
0
func (c *autoConnectChecker) check(plug *interfaces.Plug, slot *interfaces.Slot) bool {
	var plugDecl *asserts.SnapDeclaration
	if plug.Snap.SnapID != "" {
		var err error
		plugDecl, err = c.snapDeclaration(plug.Snap.SnapID)
		if err != nil {
			logger.Noticef("error: cannot find snap declaration for %q: %v", plug.Snap.Name(), err)
			return false
		}
	}

	var slotDecl *asserts.SnapDeclaration
	if slot.Snap.SnapID != "" {
		var err error
		slotDecl, err = c.snapDeclaration(slot.Snap.SnapID)
		if err != nil {
			logger.Noticef("error: cannot find snap declaration for %q: %v", slot.Snap.Name(), err)
			return false
		}
	}

	// check the connection against the declarations' rules
	ic := policy.ConnectCandidate{
		Plug:                plug.PlugInfo,
		PlugSnapDeclaration: plugDecl,
		Slot:                slot.SlotInfo,
		SlotSnapDeclaration: slotDecl,
		BaseDeclaration:     c.baseDecl,
	}

	return ic.CheckAutoConnect() == nil
}
Esempio n. 7
0
// Apply applies any necessary patches to update the provided state to
// conventions required by the current patch level of the system.
func Apply(s *state.State) error {
	var stateLevel int
	s.Lock()
	err := s.Get("patch-level", &stateLevel)
	s.Unlock()
	if err != nil && err != state.ErrNoState {
		return err
	}
	if stateLevel == Level {
		// already at right level, nothing to do
		return nil
	}
	if stateLevel > Level {
		return fmt.Errorf("cannot downgrade: snapd is too old for the current system state (patch level %d)", stateLevel)
	}

	level := stateLevel
	for level < Level {
		logger.Noticef("Patching system state from level %d to %d", level, level+1)
		patch := patches[level+1]
		if patch == nil {
			return fmt.Errorf("cannot upgrade: snapd is too new for the current system state (patch level %d)", level)
		}
		err := applyOne(patch, s, level)
		if err != nil {
			logger.Noticef("Cannnot patch: %v", err)
			return fmt.Errorf("cannot patch system state from level %d to %d: %v", level, level+1, err)
		}
		level++
	}

	return nil
}
Esempio n. 8
0
// UpdateMany updates everything from the given list of names that the
// store says is updateable. If the list is empty, update everything.
// Note that the state must be locked by the caller.
func UpdateMany(st *state.State, names []string, userID int) ([]string, []*state.TaskSet, error) {
	user, err := userFromUserID(st, userID)
	if err != nil {
		return nil, nil, err
	}

	updates, stateByID, err := refreshCandidates(st, names, user)
	if err != nil {
		return nil, nil, err
	}

	if ValidateRefreshes != nil && len(updates) != 0 {
		updates, err = ValidateRefreshes(st, updates, userID)
		if err != nil {
			// not doing "refresh all" report the error
			if len(names) != 0 {
				return nil, nil, err
			}
			// doing "refresh all", log the problems
			logger.Noticef("cannot refresh some snaps: %v", err)
		}
	}

	updated := make([]string, 0, len(updates))
	tasksets := make([]*state.TaskSet, 0, len(updates))
	for _, update := range updates {
		snapst := stateByID[update.SnapID]
		// XXX: this check goes away when update-to-local is done
		if err := checkRevisionIsNew(update.Name(), snapst, update.Revision); err != nil {
			continue
		}

		ss := &SnapSetup{
			Channel:      snapst.Channel,
			UserID:       userID,
			Flags:        snapst.Flags.ForSnapSetup(),
			DownloadInfo: &update.DownloadInfo,
			SideInfo:     &update.SideInfo,
		}

		ts, err := doInstall(st, snapst, ss)
		if err != nil {
			if len(names) == 0 {
				// doing "refresh all", just skip this snap
				logger.Noticef("cannot refresh snap %q: %v", update.Name(), err)
				continue
			}
			return nil, nil, err
		}
		updated = append(updated, update.Name())
		tasksets = append(tasksets, ts)
	}

	return updated, tasksets, nil
}
Esempio n. 9
0
// UpdateBootRevisions synchronizes the active kernel and OS snap versions
// with the versions that actually booted. This is needed because a
// system may install "os=v2" but that fails to boot. The bootloader
// fallback logic will revert to "os=v1" but on the filesystem snappy
// still has the "active" version set to "v2" which is
// misleading. This code will check what kernel/os booted and set
// those versions active.To do this it creates a Change and kicks
// start it directly.
func UpdateBootRevisions(st *state.State) error {
	const errorPrefix = "cannot update revisions after boot changes: "

	if release.OnClassic {
		return nil
	}

	bootloader, err := partition.FindBootloader()
	if err != nil {
		return fmt.Errorf(errorPrefix+"%s", err)
	}

	m, err := bootloader.GetBootVars("snap_kernel", "snap_core")
	if err != nil {
		return fmt.Errorf(errorPrefix+"%s", err)
	}

	var tsAll []*state.TaskSet
	for _, snapNameAndRevno := range []string{m["snap_kernel"], m["snap_core"]} {
		name, rev, err := nameAndRevnoFromSnap(snapNameAndRevno)
		if err != nil {
			logger.Noticef("cannot parse %q: %s", snapNameAndRevno, err)
			continue
		}
		info, err := CurrentInfo(st, name)
		if err != nil {
			logger.Noticef("cannot get info for %q: %s", name, err)
			continue
		}
		if rev != info.SideInfo.Revision {
			// FIXME: check that there is no task
			//        for this already in progress
			ts, err := RevertToRevision(st, name, rev, Flags{})
			if err != nil {
				return err
			}
			tsAll = append(tsAll, ts)
		}
	}

	if len(tsAll) == 0 {
		return nil
	}

	msg := fmt.Sprintf("Update kernel and core snap revisions")
	chg := st.NewChange("update-revisions", msg)
	for _, ts := range tsAll {
		chg.AddAll(ts)
	}
	st.EnsureBefore(0)

	return nil
}
Esempio n. 10
0
func (b *Backend) Setup(snapInfo *snap.Info, confinement interfaces.ConfinementOptions, repo *interfaces.Repository) error {
	snapName := snapInfo.Name()
	rawSnippets, err := repo.SecuritySnippetsForSnap(snapInfo.Name(), interfaces.SecuritySystemd)
	if err != nil {
		return fmt.Errorf("cannot obtain systemd security snippets for snap %q: %s", snapName, err)
	}
	snippets, err := unmarshalRawSnippetMap(rawSnippets)
	if err != nil {
		return fmt.Errorf("cannot unmarshal systemd snippets for snap %q: %s", snapName, err)
	}
	snippet, err := mergeSnippetMap(snippets)
	if err != nil {
		return fmt.Errorf("cannot merge systemd snippets for snap %q: %s", snapName, err)
	}
	content, err := renderSnippet(snippet)
	if err != nil {
		return fmt.Errorf("cannot render systemd snippets for snap %q: %s", snapName, err)
	}
	dir := dirs.SnapServicesDir
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("cannot create directory for systemd services %q: %s", dir, err)
	}
	glob := interfaces.InterfaceServiceName(snapName, "*")

	systemd := sysd.New(dirs.GlobalRootDir, &dummyReporter{})
	// We need to be carefully here and stop all removed service units before
	// we remove their files as otherwise systemd is not able to disable/stop
	// them anymore.
	if err := disableRemovedServices(systemd, dir, glob, content); err != nil {
		logger.Noticef("cannot stop removed services: %s", err)
	}
	changed, removed, errEnsure := osutil.EnsureDirState(dir, glob, content)
	// Reload systemd whenever something is added or removed
	if len(changed) > 0 || len(removed) > 0 {
		err := systemd.DaemonReload()
		if err != nil {
			logger.Noticef("cannot reload systemd state: %s", err)
		}
	}
	// Ensure the service is running right now and on reboots
	for _, service := range changed {
		if err := systemd.Enable(service); err != nil {
			logger.Noticef("cannot enable service %q: %s", service, err)
		}
		// If we have a new service here which isn't started yet the restart
		// operation will start it.
		if err := systemd.Restart(service, 10*time.Second); err != nil {
			logger.Noticef("cannot restart service %q: %s", service, err)
		}
	}
	return errEnsure
}
Esempio n. 11
0
// ClearTrashedData removes the trash. It returns no errors on the assumption that it is called very late in the game.
func (b Backend) ClearTrashedData(oldSnap *snap.Info) {
	dirs, err := snapDataDirs(oldSnap)
	if err != nil {
		logger.Noticef("Cannot remove previous data for %q: %v", oldSnap.Name(), err)
		return
	}

	for _, d := range dirs {
		if err := clearTrash(d); err != nil {
			logger.Noticef("Cannot remove %s: %v", d, err)
		}
	}
}
Esempio n. 12
0
func (b *Backend) Setup(snapInfo *snap.Info, devMode bool, repo *interfaces.Repository) error {
	snapName := snapInfo.Name()
	rawSnippets, err := repo.SecuritySnippetsForSnap(snapInfo.Name(), interfaces.SecuritySystemd)
	if err != nil {
		return fmt.Errorf("cannot obtain systemd security snippets for snap %q: %s", snapName, err)
	}
	snippets, err := unmarshalRawSnippetMap(rawSnippets)
	if err != nil {
		return fmt.Errorf("cannot unmarshal systemd snippets for snap %q: %s", snapName, err)
	}
	snippet, err := mergeSnippetMap(snippets)
	if err != nil {
		return fmt.Errorf("cannot merge systemd snippets for snap %q: %s", snapName, err)
	}
	content, err := renderSnippet(snippet)
	if err != nil {
		return fmt.Errorf("cannot render systemd snippets for snap %q: %s", snapName, err)
	}
	dir := dirs.SnapServicesDir
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("cannot create directory for systemd services %q: %s", dir, err)
	}
	glob := interfaces.InterfaceServiceName(snapName, "*")
	changed, removed, errEnsure := osutil.EnsureDirState(dir, glob, content)
	systemd := sysd.New(dirs.GlobalRootDir, &dummyReporter{})
	// Reload systemd whenever something is added or removed
	if len(changed) > 0 || len(removed) > 0 {
		err := systemd.DaemonReload()
		if err != nil {
			logger.Noticef("cannot reload systemd state: %s", err)
		}
	}
	// Start any new services
	for _, service := range changed {
		err := systemd.Start(service)
		if err != nil {
			logger.Noticef("cannot start service %q: %s", service, err)
		}
	}
	// Stop any removed services
	for _, service := range removed {
		err := systemd.Stop(service, 10*time.Second)
		if err != nil {
			logger.Noticef("cannot stop service %q: %s", service, err)
		}
	}
	return errEnsure
}
Esempio n. 13
0
// KernelOrOsRebootRequired returns whether a reboot is required to swith to the given OS or kernel snap.
func KernelOrOsRebootRequired(s *snap.Info) bool {
	if s.Type != snap.TypeKernel && s.Type != snap.TypeOS {
		return false
	}

	bootloader, err := partition.FindBootloader()
	if err != nil {
		logger.Noticef("cannot get boot settings: %s", err)
		return false
	}

	var nextBoot, goodBoot string
	switch s.Type {
	case snap.TypeKernel:
		nextBoot = "snap_try_kernel"
		goodBoot = "snap_kernel"
	case snap.TypeOS:
		nextBoot = "snap_try_core"
		goodBoot = "snap_core"
	}

	m, err := bootloader.GetBootVars(nextBoot, goodBoot)
	if err != nil {
		return false
	}

	squashfsName := filepath.Base(s.MountFile())
	if m[nextBoot] == squashfsName && m[goodBoot] != m[nextBoot] {
		return true
	}

	return false
}
Esempio n. 14
0
func run() error {
	store.SetUserAgentFromVersion(cmd.Version)

	d, err := daemon.New()
	if err != nil {
		return err
	}
	if err := d.Init(); err != nil {
		return err
	}
	d.Version = cmd.Version

	d.Start()

	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
	select {
	case sig := <-ch:
		logger.Noticef("Exiting on %s signal.\n", sig)
	case <-d.Dying():
		// something called Stop()
	}

	return d.Stop()
}
Esempio n. 15
0
// FirstBoot will do some initial boot setup and then sync the
// state
func FirstBoot() error {
	// Disable firstboot on classic for now. In the long run we want
	// classic to have a firstboot as well so that we can install
	// snaps in a classic environment (LP: #1609903). However right
	// now firstboot is under heavy development so until the dust
	// settles we disable it.
	if release.OnClassic {
		return nil
	}

	if firstboot.HasRun() {
		return ErrNotFirstBoot
	}

	// FIXME: the netplan config is static, we do not need to generate
	//        it from snapd, we can just set it in e.g. ubuntu-core-config
	if err := firstbootInitialNetworkConfig(); err != nil {
		logger.Noticef("Failed during inital network configuration: %s", err)
	}

	// snappy will be in a very unhappy state if this happens,
	// because populateStateFromSeed will error if there
	// is a state file already
	if err := populateStateFromSeed(); err != nil {
		return err
	}

	return firstboot.StampFirstBoot()
}
Esempio n. 16
0
func (o *Overlord) requestRestart(t state.RestartType) {
	if o.restartHandler == nil {
		logger.Noticef("restart requested but no handler set")
	} else {
		o.restartHandler(t)
	}
}
Esempio n. 17
0
func runSnapConfine(info *snap.Info, securityTag, snapApp, command, hook string, args []string) error {
	if err := createUserDataDirs(info); err != nil {
		logger.Noticef("WARNING: cannot create user data directory: %s", err)
	}

	cmd := []string{
		filepath.Join(dirs.LibExecDir, "snap-confine"),
		securityTag,
		filepath.Join(dirs.LibExecDir, "snap-exec"),
	}

	if command != "" {
		cmd = append(cmd, "--command="+command)
	}

	if hook != "" {
		cmd = append(cmd, "--hook="+hook)
	}

	// snap-exec is POSIXly-- options must come before positionals.
	cmd = append(cmd, snapApp)
	cmd = append(cmd, args...)

	return syscallExec(cmd[0], cmd, snapenv.ExecEnv(info))
}
Esempio n. 18
0
func queueFile(src string) error {
	// refuse huge files, this is for assertions
	fi, err := os.Stat(src)
	if err != nil {
		return err
	}
	// 640kb ought be to enough for anyone
	if fi.Size() > 640*1024 {
		msg := fmt.Errorf("cannot queue %s, file size too big: %v", src, fi.Size())
		logger.Noticef("error: %v", msg)
		return msg
	}

	// ensure name is predictable, weak hash is ok
	hash, _, err := osutil.FileDigest(src, crypto.SHA3_384)
	if err != nil {
		return err
	}

	dst := filepath.Join(dirs.SnapAssertsSpoolDir, fmt.Sprintf("%s.assert", base64.URLEncoding.EncodeToString(hash)))
	if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil {
		return err
	}

	return osutil.CopyFile(src, dst, osutil.CopyFlagOverwrite)
}
Esempio n. 19
0
func (m *InterfaceManager) doSetupProfiles(task *state.Task, _ *tomb.Tomb) error {
	task.State().Lock()
	defer task.State().Unlock()

	// Get snap.Info from bits handed by the snap manager.
	ss, err := snapstate.TaskSnapSetup(task)
	if err != nil {
		return err
	}

	snapInfo, err := snap.ReadInfo(ss.Name(), ss.SideInfo)
	if err != nil {
		return err
	}
	snap.AddImplicitSlots(snapInfo)
	snapName := snapInfo.Name()

	// The snap may have been updated so perform the following operation to
	// ensure that we are always working on the correct state:
	//
	// - disconnect all connections to/from the given snap
	//   - remembering the snaps that were affected by this operation
	// - remove the (old) snap from the interfaces repository
	// - add the (new) snap to the interfaces repository
	// - restore connections based on what is kept in the state
	//   - if a connection cannot be restored then remove it from the state
	// - setup the security of all the affected snaps
	affectedSnaps, err := m.repo.DisconnectSnap(snapName)
	if err != nil {
		return err
	}
	// XXX: what about snap renames? We should remove the old name (or switch
	// to IDs in the interfaces repository)
	if err := m.repo.RemoveSnap(snapName); err != nil {
		return err
	}
	if err := m.repo.AddSnap(snapInfo); err != nil {
		if _, ok := err.(*interfaces.BadInterfacesError); ok {
			logger.Noticef("%s", err)
		} else {
			return err
		}
	}
	if err := m.reloadConnections(snapName); err != nil {
		return err
	}
	// FIXME: here we should not reconnect auto-connect plug/slot
	// pairs that were explicitly disconnected by the user
	if err := m.autoConnect(task, snapName, nil); err != nil {
		return err
	}
	if err := setupSnapSecurity(task, snapInfo, ss.DevModeAllowed(), m.repo); err != nil {
		return err
	}

	return m.setupAffectedSnaps(task, snapName, affectedSnaps)
}
Esempio n. 20
0
func disableRemovedServices(systemd sysd.Systemd, dir, glob string, content map[string]*osutil.FileState) error {
	paths, err := filepath.Glob(filepath.Join(dir, glob))
	if err != nil {
		return err
	}
	for _, path := range paths {
		service := filepath.Base(path)
		if content[service] == nil {
			if err := systemd.Disable(service); err != nil {
				logger.Noticef("cannot disable service %q: %s", service, err)
			}
			if err := systemd.Stop(service, 5*time.Second); err != nil {
				logger.Noticef("cannot stop service %q: %s", service, err)
			}
		}
	}
	return nil
}
Esempio n. 21
0
func removeGeneratedWrappers(s *snap.Info, meter progress.Meter) error {
	err1 := wrappers.RemoveSnapBinaries(s)
	if err1 != nil {
		logger.Noticef("Cannot remove binaries for %q: %v", s.Name(), err1)
	}

	err2 := wrappers.RemoveSnapServices(s, meter)
	if err2 != nil {
		logger.Noticef("Cannot remove services for %q: %v", s.Name(), err2)
	}

	err3 := wrappers.RemoveSnapDesktopFiles(s)
	if err3 != nil {
		logger.Noticef("Cannot remove desktop files for %q: %v", s.Name(), err3)
	}

	return firstErr(err1, err2, err3)
}
Esempio n. 22
0
func parseInstallYamlData(yamlData []byte) (*InstallYaml, error) {
	var i InstallYaml
	err := yaml.Unmarshal(yamlData, &i)
	if err != nil {
		logger.Noticef("Cannot parse install.yaml %q", yamlData)
		return nil, err
	}

	return &i, nil
}
Esempio n. 23
0
func (b *Backend) Remove(snapName string) error {
	systemd := sysd.New(dirs.GlobalRootDir, &dummyReporter{})
	// Remove all the files matching snap glob
	glob := interfaces.InterfaceServiceName(snapName, "*")
	_, removed, errEnsure := osutil.EnsureDirState(dirs.SnapServicesDir, glob, nil)
	for _, service := range removed {
		if err := systemd.DisableNow(service); err != nil {
			logger.Noticef("cannot disable service %q: %s", service, err)
		}
	}
	// Reload systemd whenever something is removed
	if len(removed) > 0 {
		err := systemd.DaemonReload()
		if err != nil {
			logger.Noticef("cannot reload systemd state: %s", err)
		}
	}
	return errEnsure
}
Esempio n. 24
0
func getChanges(c *Command, r *http.Request, user *auth.UserState) Response {
	query := r.URL.Query()
	qselect := query.Get("select")
	if qselect == "" {
		qselect = "in-progress"
	}
	var filter func(*state.Change) bool
	switch qselect {
	case "all":
		filter = func(*state.Change) bool { return true }
	case "in-progress":
		filter = func(chg *state.Change) bool { return !chg.Status().Ready() }
	case "ready":
		filter = func(chg *state.Change) bool { return chg.Status().Ready() }
	default:
		return BadRequest("select should be one of: all,in-progress,ready")
	}

	if wantedName := query.Get("for"); wantedName != "" {
		outerFilter := filter
		filter = func(chg *state.Change) bool {
			if !outerFilter(chg) {
				return false
			}

			var snapNames []string
			if err := chg.Get("snap-names", &snapNames); err != nil {
				logger.Noticef("Cannot get snap-name for change %v", chg.ID())
				return false
			}

			for _, snapName := range snapNames {
				if snapName == wantedName {
					return true
				}
			}

			return false
		}
	}

	state := c.d.overlord.State()
	state.Lock()
	defer state.Unlock()
	chgs := state.Changes()
	chgInfos := make([]*changeInfo, 0, len(chgs))
	for _, chg := range chgs {
		if !filter(chg) {
			continue
		}
		chgInfos = append(chgInfos, change2changeInfo(chg))
	}
	return SyncResponse(chgInfos, nil)
}
Esempio n. 25
0
// UndoCopySnapData removes the copy that may have been done for newInfo snap of oldInfo snap data and also the data directories that may have been created for newInfo snap.
func (b Backend) UndoCopySnapData(newInfo *snap.Info, oldInfo *snap.Info, meter progress.Meter) error {
	err1 := b.RemoveSnapData(newInfo)
	if err1 != nil {
		logger.Noticef("Cannot remove data directories for %q: %v", newInfo.Name(), err1)
	}

	var err2 error
	if oldInfo == nil {
		// first install, remove created common data dir
		err2 = b.RemoveSnapCommonData(newInfo)
		if err2 != nil {
			logger.Noticef("Cannot remove common data directories for %q: %v", newInfo.Name(), err2)
		}
	} else {
		err2 = b.untrashData(newInfo)
		if err2 != nil {
			logger.Noticef("Cannot restore original data for %q while undoing: %v", newInfo.Name(), err2)
		}
	}

	return firstErr(err1, err2)
}
Esempio n. 26
0
func (m *InterfaceManager) addSnaps() error {
	snaps, err := snapstate.ActiveInfos(m.state)
	if err != nil {
		return err
	}
	for _, snapInfo := range snaps {
		snap.AddImplicitSlots(snapInfo)
		if err := m.repo.AddSnap(snapInfo); err != nil {
			logger.Noticef("%s", err)
		}
	}
	return nil
}
Esempio n. 27
0
// plural!
func getSnapsInfo(c *Command, r *http.Request, user *auth.UserState) Response {

	if shouldSearchStore(r) {
		logger.Noticef("Jumping to \"find\" to better support legacy request %q", r.URL)
		return searchStore(c, r, user)
	}

	route := c.d.router.Get(snapCmd.Path)
	if route == nil {
		return InternalError("cannot find route for snaps")
	}

	found, err := allLocalSnapInfos(c.d.overlord.State())
	if err != nil {
		return InternalError("cannot list local snaps! %v", err)
	}

	results := make([]*json.RawMessage, len(found))

	for i, x := range found {
		name := x.info.Name()
		rev := x.info.Revision

		url, err := route.URL("name", name)
		if err != nil {
			logger.Noticef("Cannot build URL for snap %q revision %s: %v", name, rev, err)
			continue
		}

		data, err := json.Marshal(webify(mapLocal(x.info, x.snapst), url.String()))
		if err != nil {
			return InternalError("cannot serialize snap %q revision %s: %v", name, rev, err)
		}
		raw := json.RawMessage(data)
		results[i] = &raw
	}

	return SyncResponse(results, &Meta{Sources: []string{"local"}})
}
Esempio n. 28
0
func tryMount(deviceName string) (string, error) {
	tmpMountTarget, err := ioutil.TempDir("", "snapd-auto-import-mount-")
	if err != nil {
		err = fmt.Errorf("cannot create temporary mount point: %v", err)
		logger.Noticef("error: %v", err)
		return "", err
	}
	// udev does not provide much environment ;)
	if os.Getenv("PATH") == "" {
		os.Setenv("PATH", "/usr/sbin:/usr/bin:/sbin:/bin")
	}
	// not using syscall.Mount() because we don't know the fs type in advance
	cmd := exec.Command("mount", "-o", "ro", "--make-private", deviceName, tmpMountTarget)
	if output, err := cmd.CombinedOutput(); err != nil {
		os.Remove(tmpMountTarget)
		err = fmt.Errorf("cannot mount %s: %s", deviceName, osutil.OutputErr(output, err))
		logger.Noticef("error: %v", err)
		return "", err
	}

	return tmpMountTarget, nil
}
Esempio n. 29
0
// InUse checks if the given name/revision is used in the
// boot environment
func InUse(name string, rev snap.Revision) bool {
	bootloader, err := partition.FindBootloader()
	if err != nil {
		logger.Noticef("cannot get boot settings: %s", err)
		return false
	}

	bootVars, err := bootloader.GetBootVars("snap_kernel", "snap_try_kernel", "snap_core", "snap_try_core")
	if err != nil {
		logger.Noticef("cannot get boot vars: %s", err)
		return false
	}

	snapFile := filepath.Base(snap.MountFile(name, rev))
	for _, bootVar := range bootVars {
		if bootVar == snapFile {
			return true
		}
	}

	return false
}
Esempio n. 30
0
// Start the Daemon
func (d *Daemon) Start() {
	// die when asked to restart (systemd should get us back up!)
	d.overlord.SetRestartHandler(func(t state.RestartType) {
		switch t {
		case state.RestartDaemon:
			d.tomb.Kill(nil)
		case state.RestartSystem:
			cmd := exec.Command("shutdown", "+10", "-r", shutdownMsg)
			if out, err := cmd.CombinedOutput(); err != nil {
				logger.Noticef("%s", osutil.OutputErr(out, err))
			}
		default:
			logger.Noticef("internal error: restart handler called with unknown restart type: %v", t)
			d.tomb.Kill(nil)
		}
	})

	// the loop runs in its own goroutine
	d.overlord.Loop()

	d.tomb.Go(func() error {
		if d.snapListener != nil {
			d.tomb.Go(func() error {
				if err := http.Serve(d.snapListener, logit(d.router)); err != nil && d.tomb.Err() == tomb.ErrStillAlive {
					return err
				}

				return nil
			})
		}

		if err := http.Serve(d.snapdListener, logit(d.router)); err != nil && d.tomb.Err() == tomb.ErrStillAlive {
			return err
		}

		return nil
	})
}