func (s *gadgetYamlTestSuite) TestReadGadgetYamlMissingBootloader(c *C) { info := snaptest.MockSnap(c, mockGadgetSnapYaml, &snap.SideInfo{Revision: snap.R(42)}) err := ioutil.WriteFile(filepath.Join(info.MountDir(), "meta", "gadget.yaml"), nil, 0644) c.Assert(err, IsNil) _, err = snap.ReadGadgetInfo(info) c.Assert(err, ErrorMatches, "cannot read gadget snap details: bootloader not declared in any volume") }
func (s *gadgetYamlTestSuite) TestReadGadgetYamlInvalidBootloader(c *C) { info := snaptest.MockSnap(c, mockGadgetSnapYaml, &snap.SideInfo{Revision: snap.R(42)}) mockGadgetYamlBroken := []byte(` volumes: name: bootloader: silo `) err := ioutil.WriteFile(filepath.Join(info.MountDir(), "meta", "gadget.yaml"), mockGadgetYamlBroken, 0644) c.Assert(err, IsNil) _, err = snap.ReadGadgetInfo(info) c.Assert(err, ErrorMatches, "cannot read gadget snap details: bootloader must be either grub or u-boot") }
func (s *gadgetYamlTestSuite) TestReadGadgetYamlValid(c *C) { info := snaptest.MockSnap(c, mockGadgetSnapYaml, &snap.SideInfo{Revision: snap.R(42)}) err := ioutil.WriteFile(filepath.Join(info.MountDir(), "meta", "gadget.yaml"), mockGadgetYaml, 0644) c.Assert(err, IsNil) ginfo, err := snap.ReadGadgetInfo(info) c.Assert(err, IsNil) c.Assert(ginfo, DeepEquals, &snap.GadgetInfo{ Defaults: map[string]map[string]interface{}{ "core": {"something": true}, }, Volumes: map[string]snap.GadgetVolume{ "volumename": { Schema: "mbr", Bootloader: "u-boot", ID: "id,guid", Structure: []snap.VolumeStructure{ { Label: "system-boot", Offset: "12345", OffsetWrite: "777", Size: "88888", Type: "id,guid", ID: "id,guid", Filesystem: "vfat", Content: []snap.VolumeContent{ { Source: "subdir/", Target: "/", Unpack: false, }, { Image: "foo.img", Offset: "4321", OffsetWrite: "8888", Size: "88888", Unpack: false, }, }, }, }, }, }, }) }
func (s *gadgetYamlTestSuite) TestReadGadgetYamlMissing(c *C) { info := snaptest.MockSnap(c, mockGadgetSnapYaml, &snap.SideInfo{Revision: snap.R(42)}) _, err := snap.ReadGadgetInfo(info) c.Assert(err, ErrorMatches, ".*meta/gadget.yaml: no such file or directory") }
func doInstall(s *state.State, snapst *SnapState, ss *SnapSetup) (*state.TaskSet, error) { if err := checkChangeConflict(s, ss.Name(), snapst); err != nil { return nil, err } targetRevision := ss.Revision() revisionStr := "" if ss.SideInfo != nil { revisionStr = fmt.Sprintf(" (%s)", targetRevision) } // check if we already have the revision locally (alters tasks) revisionIsLocal := snapst.LastIndex(targetRevision) >= 0 var prepare, prev *state.Task fromStore := false // if we have a local revision here we go back to that if ss.SnapPath != "" || revisionIsLocal { prepare = s.NewTask("prepare-snap", fmt.Sprintf(i18n.G("Prepare snap %q%s"), ss.SnapPath, revisionStr)) } else { fromStore = true prepare = s.NewTask("download-snap", fmt.Sprintf(i18n.G("Download snap %q%s from channel %q"), ss.Name(), revisionStr, ss.Channel)) } prepare.Set("snap-setup", ss) tasks := []*state.Task{prepare} addTask := func(t *state.Task) { t.Set("snap-setup-task", prepare.ID()) t.WaitFor(prev) tasks = append(tasks, t) } prev = prepare if fromStore { // fetch and check assertions checkAsserts := s.NewTask("validate-snap", fmt.Sprintf(i18n.G("Fetch and check assertions for snap %q%s"), ss.Name(), revisionStr)) addTask(checkAsserts) prev = checkAsserts } // mount if !revisionIsLocal { mount := s.NewTask("mount-snap", fmt.Sprintf(i18n.G("Mount snap %q%s"), ss.Name(), revisionStr)) addTask(mount) prev = mount } if snapst.Active { // unlink-current-snap (will stop services for copy-data) stop := s.NewTask("stop-snap-services", fmt.Sprintf(i18n.G("Stop snap %q services"), ss.Name())) addTask(stop) prev = stop unlink := s.NewTask("unlink-current-snap", fmt.Sprintf(i18n.G("Make current revision for snap %q unavailable"), ss.Name())) addTask(unlink) prev = unlink } // copy-data (needs stopped services by unlink) if !ss.Flags.Revert { copyData := s.NewTask("copy-snap-data", fmt.Sprintf(i18n.G("Copy snap %q data"), ss.Name())) addTask(copyData) prev = copyData } // security setupSecurity := s.NewTask("setup-profiles", fmt.Sprintf(i18n.G("Setup snap %q%s security profiles"), ss.Name(), revisionStr)) addTask(setupSecurity) prev = setupSecurity // finalize (wrappers+current symlink) linkSnap := s.NewTask("link-snap", fmt.Sprintf(i18n.G("Make snap %q%s available to the system"), ss.Name(), revisionStr)) addTask(linkSnap) prev = linkSnap // run new serices startSnapServices := s.NewTask("start-snap-services", fmt.Sprintf(i18n.G("Start snap %q%s services"), ss.Name(), revisionStr)) addTask(startSnapServices) prev = startSnapServices // Do not do that if we are reverting to a local revision if snapst.HasCurrent() && !ss.Flags.Revert { seq := snapst.Sequence currentIndex := snapst.LastIndex(snapst.Current) // discard everything after "current" (we may have reverted to // a previous versions earlier) for i := currentIndex + 1; i < len(seq); i++ { si := seq[i] if si.Revision == targetRevision { // but don't discard this one; its' the thing we're switching to! continue } ts := removeInactiveRevision(s, ss.Name(), si.Revision) ts.WaitFor(prev) tasks = append(tasks, ts.Tasks()...) prev = tasks[len(tasks)-1] } // make sure we're not scheduling the removal of the target // revision in the case where the target revision is already in // the sequence. for i := 0; i < currentIndex; i++ { si := seq[i] if si.Revision == targetRevision { // we do *not* want to removeInactiveRevision of this one copy(seq[i:], seq[i+1:]) seq = seq[:len(seq)-1] currentIndex-- } } // normal garbage collect for i := 0; i <= currentIndex-2; i++ { si := seq[i] ts := removeInactiveRevision(s, ss.Name(), si.Revision) ts.WaitFor(prev) tasks = append(tasks, ts.Tasks()...) prev = tasks[len(tasks)-1] } addTask(s.NewTask("cleanup", fmt.Sprintf("Clean up %q%s install", ss.Name(), revisionStr))) } var defaults map[string]interface{} if !snapst.HasCurrent() && ss.SideInfo != nil && ss.SideInfo.SnapID != "" { gadget, err := GadgetInfo(s) if err != nil && err != state.ErrNoState { return nil, err } if err == nil { gadgetInfo, err := snap.ReadGadgetInfo(gadget) if err != nil { return nil, err } defaults = gadgetInfo.Defaults[ss.SideInfo.SnapID] } } installSet := state.NewTaskSet(tasks...) configSet := Configure(s, ss.Name(), defaults) configSet.WaitAll(installSet) installSet.AddAll(configSet) return installSet, nil }