func (s *seedYamlTestSuite) TestNoPathAllowed(c *C) { fn := filepath.Join(c.MkDir(), "seed.yaml") err := ioutil.WriteFile(fn, badMockSeedYaml, 0644) c.Assert(err, IsNil) _, err = snap.ReadSeedYaml(fn) c.Assert(err, ErrorMatches, `"foo/bar.snap" must be a filename, not a path`) }
func (s *seedYamlTestSuite) TestSimple(c *C) { fn := filepath.Join(c.MkDir(), "seed.yaml") err := ioutil.WriteFile(fn, mockSeedYaml, 0644) c.Assert(err, IsNil) seed, err := snap.ReadSeedYaml(fn) c.Assert(err, IsNil) c.Assert(seed.Snaps, HasLen, 2) c.Assert(seed.Snaps[0], DeepEquals, &snap.SeedSnap{ File: "foo_1.0_all.snap", Name: "foo", SnapID: "snapidsnapidsnapid", Channel: "stable", DevMode: true, }) c.Assert(seed.Snaps[1], DeepEquals, &snap.SeedSnap{ File: "local.snap", Name: "local", Unasserted: true, }) }
func (s *imageSuite) TestBootstrapToRootDirDevmodeSnap(c *C) { restore := sysdb.InjectTrusted(s.storeSigning.Trusted) defer restore() rootdir := filepath.Join(c.MkDir(), "imageroot") // FIXME: bootstrapToRootDir needs an unpacked gadget yaml gadgetUnpackDir := filepath.Join(c.MkDir(), "gadget") err := os.MkdirAll(gadgetUnpackDir, 0755) c.Assert(err, IsNil) err = ioutil.WriteFile(filepath.Join(gadgetUnpackDir, "grub.conf"), nil, 0644) c.Assert(err, IsNil) s.setupSnaps(c, gadgetUnpackDir) s.downloadedSnaps["devmode-snap"] = snaptest.MakeTestSnapWithFiles(c, devmodeSnap, nil) s.storeSnapInfo["devmode-snap"] = infoFromSnapYaml(c, devmodeSnap, snap.R(0)) // mock the mount cmds (for the extract kernel assets stuff) c1 := testutil.MockCommand(c, "mount", "") defer c1.Restore() c2 := testutil.MockCommand(c, "umount", "") defer c2.Restore() opts := &image.Options{ Snaps: []string{s.downloadedSnaps["devmode-snap"]}, RootDir: rootdir, GadgetUnpackDir: gadgetUnpackDir, } local, err := image.LocalSnaps(opts) c.Assert(err, IsNil) err = image.BootstrapToRootDir(s, s.model, opts, local) c.Assert(err, IsNil) // check seed yaml seed, err := snap.ReadSeedYaml(filepath.Join(rootdir, "var/lib/snapd/seed/seed.yaml")) c.Assert(err, IsNil) c.Check(seed.Snaps, HasLen, 5) // check devmode-snap info := &snap.Info{ SideInfo: snap.SideInfo{ RealName: "devmode-snap", Revision: snap.R("x1"), }, } fn := filepath.Base(info.MountFile()) p := filepath.Join(rootdir, "var/lib/snapd/seed/snaps", fn) c.Check(osutil.FileExists(p), Equals, true) // ensure local snaps are put last in seed.yaml last := len(seed.Snaps) - 1 c.Check(seed.Snaps[last], DeepEquals, &snap.SeedSnap{ Name: "devmode-snap", File: fn, DevMode: true, Unasserted: true, }) }
func (s *imageSuite) TestBootstrapToRootDirLocalCore(c *C) { restore := sysdb.InjectTrusted(s.storeSigning.Trusted) defer restore() rootdir := filepath.Join(c.MkDir(), "imageroot") // FIXME: bootstrapToRootDir needs an unpacked gadget yaml gadgetUnpackDir := filepath.Join(c.MkDir(), "gadget") s.setupSnaps(c, gadgetUnpackDir) // mock the mount cmds (for the extract kernel assets stuff) c1 := testutil.MockCommand(c, "mount", "") defer c1.Restore() c2 := testutil.MockCommand(c, "umount", "") defer c2.Restore() opts := &image.Options{ Snaps: []string{ s.downloadedSnaps["core"], s.downloadedSnaps["required-snap1"], }, RootDir: rootdir, GadgetUnpackDir: gadgetUnpackDir, } local, err := image.LocalSnaps(opts) c.Assert(err, IsNil) err = image.BootstrapToRootDir(s, s.model, opts, local) c.Assert(err, IsNil) // check seed yaml seed, err := snap.ReadSeedYaml(filepath.Join(rootdir, "var/lib/snapd/seed/seed.yaml")) c.Assert(err, IsNil) c.Check(seed.Snaps, HasLen, 4) // check the files are in place for i, name := range []string{"core_x1.snap", "pc-kernel", "pc", "required-snap1_x1.snap"} { unasserted := false info := s.storeSnapInfo[name] if info == nil { switch name { case "core_x1.snap": info = &snap.Info{ SideInfo: snap.SideInfo{ RealName: "core", Revision: snap.R("x1"), }, } unasserted = true case "required-snap1_x1.snap": info = &snap.Info{ SideInfo: snap.SideInfo{ RealName: "required-snap1", Revision: snap.R("x1"), }, } unasserted = true } } fn := filepath.Base(info.MountFile()) p := filepath.Join(rootdir, "var/lib/snapd/seed/snaps", fn) c.Check(osutil.FileExists(p), Equals, true) c.Check(seed.Snaps[i], DeepEquals, &snap.SeedSnap{ Name: info.Name(), SnapID: info.SnapID, File: fn, Unasserted: unasserted, }) } l, err := ioutil.ReadDir(filepath.Join(rootdir, "var/lib/snapd/seed/snaps")) c.Assert(err, IsNil) c.Check(l, HasLen, 4) storeAccountKey := s.storeSigning.StoreAccountKey("") brandPubKey, err := s.brandSigning.PublicKey("") c.Assert(err, IsNil) // check the assertions are in place for _, fn := range []string{"model", brandPubKey.ID() + ".account-key", "my-brand.account", storeAccountKey.PublicKeyID() + ".account-key"} { p := filepath.Join(rootdir, "var/lib/snapd/seed/assertions", fn) c.Check(osutil.FileExists(p), Equals, true) } b, err := ioutil.ReadFile(filepath.Join(rootdir, "var/lib/snapd/seed/assertions", "model")) c.Assert(err, IsNil) c.Check(b, DeepEquals, asserts.Encode(s.model)) b, err = ioutil.ReadFile(filepath.Join(rootdir, "var/lib/snapd/seed/assertions", "my-brand.account")) c.Assert(err, IsNil) a, err := asserts.Decode(b) c.Assert(err, IsNil) c.Check(a.Type(), Equals, asserts.AccountType) c.Check(a.HeaderString("account-id"), Equals, "my-brand") decls, err := filepath.Glob(filepath.Join(rootdir, "var/lib/snapd/seed/assertions", "*.snap-declaration")) c.Assert(err, IsNil) // nothing for core c.Check(decls, HasLen, 2) // check the bootloader config m, err := s.bootloader.GetBootVars("snap_kernel", "snap_core") c.Assert(err, IsNil) c.Check(m["snap_kernel"], Equals, "pc-kernel_2.snap") c.Assert(err, IsNil) c.Check(m["snap_core"], Equals, "core_x1.snap") // check that cloud-init is setup correctly c.Check(osutil.FileExists(filepath.Join(rootdir, "etc/cloud/cloud-init.disabled")), Equals, true) }
func (s *imageSuite) TestBootstrapToRootDir(c *C) { restore := sysdb.InjectTrusted(s.storeSigning.Trusted) defer restore() rootdir := filepath.Join(c.MkDir(), "imageroot") // FIXME: bootstrapToRootDir needs an unpacked gadget yaml gadgetUnpackDir := filepath.Join(c.MkDir(), "gadget") s.setupSnaps(c, gadgetUnpackDir) // mock the mount cmds (for the extract kernel assets stuff) c1 := testutil.MockCommand(c, "mount", "") defer c1.Restore() c2 := testutil.MockCommand(c, "umount", "") defer c2.Restore() opts := &image.Options{ RootDir: rootdir, GadgetUnpackDir: gadgetUnpackDir, } local, err := image.LocalSnaps(opts) c.Assert(err, IsNil) err = image.BootstrapToRootDir(s, s.model, opts, local) c.Assert(err, IsNil) // check seed yaml seed, err := snap.ReadSeedYaml(filepath.Join(rootdir, "var/lib/snapd/seed/seed.yaml")) c.Assert(err, IsNil) c.Check(seed.Snaps, HasLen, 4) // check the files are in place for i, name := range []string{"core", "pc-kernel", "pc"} { info := s.storeSnapInfo[name] fn := filepath.Base(info.MountFile()) p := filepath.Join(rootdir, "var/lib/snapd/seed/snaps", fn) c.Check(osutil.FileExists(p), Equals, true) c.Check(seed.Snaps[i], DeepEquals, &snap.SeedSnap{ Name: name, SnapID: name + "-Id", File: fn, }) } storeAccountKey := s.storeSigning.StoreAccountKey("") brandPubKey, err := s.brandSigning.PublicKey("") c.Assert(err, IsNil) // check the assertions are in place for _, fn := range []string{"model", brandPubKey.ID() + ".account-key", "my-brand.account", storeAccountKey.PublicKeyID() + ".account-key"} { p := filepath.Join(rootdir, "var/lib/snapd/seed/assertions", fn) c.Check(osutil.FileExists(p), Equals, true) } b, err := ioutil.ReadFile(filepath.Join(rootdir, "var/lib/snapd/seed/assertions", "model")) c.Assert(err, IsNil) c.Check(b, DeepEquals, asserts.Encode(s.model)) b, err = ioutil.ReadFile(filepath.Join(rootdir, "var/lib/snapd/seed/assertions", "my-brand.account")) c.Assert(err, IsNil) a, err := asserts.Decode(b) c.Assert(err, IsNil) c.Check(a.Type(), Equals, asserts.AccountType) c.Check(a.HeaderString("account-id"), Equals, "my-brand") // check the snap assertions are also in place for _, snapId := range []string{"pc-Id", "pc-kernel-Id", "core-Id"} { p := filepath.Join(rootdir, "var/lib/snapd/seed/assertions", fmt.Sprintf("16,%s.snap-declaration", snapId)) c.Check(osutil.FileExists(p), Equals, true) } // check the bootloader config m, err := s.bootloader.GetBootVars("snap_kernel", "snap_core") c.Assert(err, IsNil) c.Check(m["snap_kernel"], Equals, "pc-kernel_2.snap") c.Check(m["snap_core"], Equals, "core_3.snap") }
func populateStateFromSeedImpl(st *state.State) ([]*state.TaskSet, error) { // check that the state is empty var seeded bool err := st.Get("seeded", &seeded) if err != nil && err != state.ErrNoState { return nil, err } if seeded { return nil, fmt.Errorf("cannot populate state: already seeded") } // ack all initial assertions if err := importAssertionsFromSeed(st); err != nil { return nil, err } seed, err := snap.ReadSeedYaml(filepath.Join(dirs.SnapSeedDir, "seed.yaml")) if err != nil { return nil, err } tsAll := []*state.TaskSet{} for i, sn := range seed.Snaps { var flags snapstate.Flags if sn.DevMode { flags.DevMode = true } path := filepath.Join(dirs.SnapSeedDir, "snaps", sn.File) var sideInfo snap.SideInfo if sn.Unasserted { sideInfo.RealName = sn.Name } else { si, err := snapasserts.DeriveSideInfo(path, assertstate.DB(st)) if err == asserts.ErrNotFound { return nil, fmt.Errorf("cannot find signatures with metadata for snap %q (%q)", sn.Name, path) } if err != nil { return nil, err } sideInfo = *si sideInfo.Private = sn.Private } ts, err := snapstate.InstallPath(st, &sideInfo, path, sn.Channel, flags) if i > 0 { ts.WaitAll(tsAll[i-1]) } if err != nil { return nil, err } tsAll = append(tsAll, ts) } if len(tsAll) == 0 { return nil, nil } ts := tsAll[len(tsAll)-1] markSeeded := st.NewTask("mark-seeded", i18n.G("Mark system seeded")) markSeeded.WaitAll(ts) tsAll = append(tsAll, state.NewTaskSet(markSeeded)) return tsAll, nil }
func populateStateFromSeed() error { if osutil.FileExists(dirs.SnapStateFile) { return fmt.Errorf("cannot create state: state %q already exists", dirs.SnapStateFile) } ovld, err := overlord.New() if err != nil { return err } st := ovld.State() // ack all initial assertions if err := importAssertionsFromSeed(st); err != nil { return err } seed, err := snap.ReadSeedYaml(filepath.Join(dirs.SnapSeedDir, "seed.yaml")) if err != nil { return err } tsAll := []*state.TaskSet{} for i, sn := range seed.Snaps { st.Lock() flags := snapstate.Flags(0) if sn.DevMode { flags |= snapstate.DevMode } path := filepath.Join(dirs.SnapSeedDir, "snaps", sn.File) var sideInfo snap.SideInfo if sn.Unasserted { sideInfo.RealName = sn.Name } else { si, err := snapasserts.DeriveSideInfo(path, assertstate.DB(st)) if err == asserts.ErrNotFound { st.Unlock() return fmt.Errorf("cannot find signatures with metadata for snap %q (%q)", sn.Name, path) } if err != nil { st.Unlock() return err } sideInfo = *si sideInfo.Private = sn.Private } ts, err := snapstate.InstallPath(st, &sideInfo, path, sn.Channel, flags) if i > 0 { ts.WaitAll(tsAll[i-1]) } st.Unlock() if err != nil { return err } tsAll = append(tsAll, ts) } if len(tsAll) == 0 { return nil } st.Lock() msg := fmt.Sprintf("First boot seeding") chg := st.NewChange("seed", msg) for _, ts := range tsAll { chg.AddAll(ts) } st.Unlock() // do it and wait for ready ovld.Loop() st.EnsureBefore(0) <-chg.Ready() st.Lock() status := chg.Status() err = chg.Err() st.Unlock() if status != state.DoneStatus { ovld.Stop() return fmt.Errorf("cannot run seed change: %s", err) } return ovld.Stop() }