Example #1
0
func doInstall(s *state.State, curActive bool, snapName, snapPath, channel string, userID int, flags snappy.InstallFlags) (*state.TaskSet, error) {
	if err := checkChangeConflict(s, snapName); err != nil {
		return nil, err
	}

	if snapPath == "" && channel == "" {
		channel = "stable"
	}

	var prepare *state.Task
	ss := SnapSetup{
		Channel: channel,
		UserID:  userID,
		Flags:   int(flags),
	}
	ss.Name = snapName
	ss.SnapPath = snapPath
	if snapPath != "" {
		prepare = s.NewTask("prepare-snap", fmt.Sprintf(i18n.G("Prepare snap %q"), snapPath))
	} else {
		prepare = s.NewTask("download-snap", fmt.Sprintf(i18n.G("Download snap %q from channel %q"), snapName, channel))
	}
	prepare.Set("snap-setup", ss)

	tasks := []*state.Task{prepare}
	addTask := func(t *state.Task) {
		t.Set("snap-setup-task", prepare.ID())
		tasks = append(tasks, t)
	}

	// mount
	mount := s.NewTask("mount-snap", fmt.Sprintf(i18n.G("Mount snap %q"), snapName))
	addTask(mount)
	mount.WaitFor(prepare)
	precopy := mount

	if curActive {
		// unlink-current-snap (will stop services for copy-data)
		unlink := s.NewTask("unlink-current-snap", fmt.Sprintf(i18n.G("Make current revision for snap %q unavailable"), snapName))
		addTask(unlink)
		unlink.WaitFor(mount)
		precopy = unlink
	}

	// copy-data (needs stopped services by unlink)
	copyData := s.NewTask("copy-snap-data", fmt.Sprintf(i18n.G("Copy snap %q data"), snapName))
	addTask(copyData)
	copyData.WaitFor(precopy)

	// security
	setupSecurity := s.NewTask("setup-profiles", fmt.Sprintf(i18n.G("Setup snap %q security profiles"), snapName))
	addTask(setupSecurity)
	setupSecurity.WaitFor(copyData)

	// finalize (wrappers+current symlink)
	linkSnap := s.NewTask("link-snap", fmt.Sprintf(i18n.G("Make snap %q available to the system"), snapName))
	addTask(linkSnap)
	linkSnap.WaitFor(setupSecurity)

	return state.NewTaskSet(tasks...), nil
}