Example #1
0
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`)
}
Example #2
0
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,
	})
}
Example #3
0
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,
	})
}
Example #4
0
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)
}
Example #5
0
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")
}
Example #6
0
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
}
Example #7
0
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()
}