From 52efdf5db569c25b508ec4b25211b6f9a7ea9e64 Mon Sep 17 00:00:00 2001 From: Pawel Stolowski Date: Thu, 20 Feb 2020 10:34:18 +0100 Subject: [PATCH 1/8] Support preseeding of classic with snapd and core18 snaps. --- cmd/snap-preseed/main_test.go | 20 ++- cmd/snap-preseed/preseed_linux.go | 19 +-- .../devicestate/firstboot_preseed_test.go | 114 ++++++++++++++++++ overlord/devicestate/firstboot_test.go | 2 +- 4 files changed, 142 insertions(+), 13 deletions(-) diff --git a/cmd/snap-preseed/main_test.go b/cmd/snap-preseed/main_test.go index 66894b1b865..93f53e070c6 100644 --- a/cmd/snap-preseed/main_test.go +++ b/cmd/snap-preseed/main_test.go @@ -214,6 +214,22 @@ func (s *startPreseedSuite) TestSystemSnapFromSeed(c *C) { c.Check(path, Equals, "/some/path/core") } +func (s *startPreseedSuite) TestSystemSnapFromSnapdSeed(c *C) { + tmpDir := c.MkDir() + + restore := main.MockSeedOpen(func(rootDir, label string) (seed.Seed, error) { + return &Fake16Seed{ + Essential: []*seed.Snap{{Path: "/some/path/snapd.snap", SideInfo: &snap.SideInfo{RealName: "snapd"}}}, + UsesSnapd: true, + }, nil + }) + defer restore() + + path, err := main.SystemSnapFromSeed(tmpDir) + c.Assert(err, IsNil) + c.Check(path, Equals, "/some/path/snapd.snap") +} + func (s *startPreseedSuite) TestSystemSnapFromSeedOpenError(c *C) { tmpDir := c.MkDir() @@ -240,10 +256,6 @@ func (s *startPreseedSuite) TestSystemSnapFromSeedErrors(c *C) { _, err = main.SystemSnapFromSeed(tmpDir) c.Assert(err, ErrorMatches, "core snap not found") - fakeSeed.UsesSnapd = true - _, err = main.SystemSnapFromSeed(tmpDir) - c.Assert(err, ErrorMatches, "preseeding with snapd snap is not supported yet") - fakeSeed.LoadMetaErr = fmt.Errorf("load meta failed") _, err = main.SystemSnapFromSeed(tmpDir) c.Assert(err, ErrorMatches, "load meta failed") diff --git a/cmd/snap-preseed/preseed_linux.go b/cmd/snap-preseed/preseed_linux.go index 296b15d60f1..f387ce1f5e5 100644 --- a/cmd/snap-preseed/preseed_linux.go +++ b/cmd/snap-preseed/preseed_linux.go @@ -83,24 +83,27 @@ var systemSnapFromSeed = func(rootDir string) (string, error) { return "", err } - // TODO: handle core18, snapd snap. + var required string if seed.UsesSnapdSnap() { - return "", fmt.Errorf("preseeding with snapd snap is not supported yet") + required = "snapd" + } else { + required = "core" } - var coreSnapPath string + var snapPath string ess := seed.EssentialSnaps() if len(ess) > 0 { - if ess[0].SnapName() == "core" { - coreSnapPath = ess[0].Path + // core / snapd snap is the first essential snap. + if ess[0].SnapName() == required { + snapPath = ess[0].Path } } - if coreSnapPath == "" { - return "", fmt.Errorf("core snap not found") + if snapPath == "" { + return "", fmt.Errorf("%s snap not found", required) } - return coreSnapPath, nil + return snapPath, nil } func prepareChroot(preseedChroot string) (func(), error) { diff --git a/overlord/devicestate/firstboot_preseed_test.go b/overlord/devicestate/firstboot_preseed_test.go index 7e54bb88391..e38f9e49816 100644 --- a/overlord/devicestate/firstboot_preseed_test.go +++ b/overlord/devicestate/firstboot_preseed_test.go @@ -102,6 +102,7 @@ func checkPreseedTaskStates(c *C, st *state.State) { c.Fatalf("unhandled task kind %s", t.Kind()) } } + // sanity: check that doneTasks is not declaring more tasks than // actually expected. c.Check(doneTasks, DeepEquals, seenDone) @@ -183,6 +184,7 @@ func checkPreseedOrder(c *C, tsAll []*state.TaskSet, snaps ...string) { c.Check(waitTasks, HasLen, 0) } else { c.Assert(waitTasks, HasLen, 1) + c.Assert(waitTasks[0].Kind(), Equals, prevTask.Kind()) c.Check(waitTasks[0], Equals, prevTask) } @@ -306,4 +308,116 @@ snaps: c.Assert(chg.Err(), IsNil) checkPreseedTaskStates(c, st) + + // verify + r, err := os.Open(dirs.SnapStateFile) + c.Assert(err, IsNil) + diskState, err := state.ReadState(nil, r) + c.Assert(err, IsNil) + + diskState.Lock() + defer diskState.Unlock() + + // seeded snaps are installed + _, err = snapstate.CurrentInfo(diskState, "core") + c.Check(err, IsNil) + _, err = snapstate.CurrentInfo(diskState, "foo") + c.Check(err, IsNil) + + // but we're not considered seeded + var seeded bool + err = diskState.Get("seeded", &seeded) + c.Assert(err, Equals, state.ErrNoState) +} + +func (s *firstbootPreseed16Suite) TestPreseedClassicWithSnapdOnlyHappy(c *C) { + restorePreseedMode := release.MockPreseedMode(func() bool { return true }) + defer restorePreseedMode() + + restore := release.MockOnClassic(true) + defer restore() + + mockMountCmd := testutil.MockCommand(c, "mount", "") + defer mockMountCmd.Restore() + + mockUmountCmd := testutil.MockCommand(c, "umount", "") + defer mockUmountCmd.Restore() + + core18Fname, snapdFname, _, _ := s.makeCore18Snaps(c, &core18SnapsOpts{ + classic: true, + }) + + // put a firstboot snap into the SnapBlobDir + snapYaml := `name: foo +version: 1.0 +base: core18 +` + fooFname, fooDecl, fooRev := s.MakeAssertedSnap(c, snapYaml, nil, snap.R(128), "developerid") + s.WriteAssertions("foo.asserts", s.devAcct, fooRev, fooDecl) + + // add a model assertion and its chain + assertsChain := s.makeModelAssertionChain(c, "my-model-classic", nil) + s.WriteAssertions("model.asserts", assertsChain...) + + // create a seed.yaml + content := []byte(fmt.Sprintf(` +snaps: + - name: snapd + file: %s + - name: foo + file: %s + - name: core18 + file: %s +`, snapdFname, fooFname, core18Fname)) + err := ioutil.WriteFile(filepath.Join(dirs.SnapSeedDir, "seed.yaml"), content, 0644) + c.Assert(err, IsNil) + + // run the firstboot stuff + s.startOverlord(c) + st := s.overlord.State() + st.Lock() + defer st.Unlock() + + opts := &devicestate.PopulateStateFromSeedOptions{Preseed: true} + tsAll, err := devicestate.PopulateStateFromSeedImpl(st, opts, s.perfTimings) + c.Assert(err, IsNil) + + checkPreseedOrder(c, tsAll, "snapd", "core18", "foo") + + // now run the change and check the result + chg := st.NewChange("seed", "run the populate from seed changes") + for _, ts := range tsAll { + chg.AddAll(ts) + } + c.Assert(st.Changes(), HasLen, 1) + c.Assert(chg.Err(), IsNil) + + st.Unlock() + err = s.overlord.Settle(settleTimeout) + st.Lock() + c.Assert(err, IsNil) + + checkPreseedTaskStates(c, st) + + // verify + r, err := os.Open(dirs.SnapStateFile) + c.Assert(err, IsNil) + diskState, err := state.ReadState(nil, r) + c.Assert(err, IsNil) + + diskState.Lock() + defer diskState.Unlock() + + // seeded snaps are installed + _, err = snapstate.CurrentInfo(diskState, "snapd") + c.Check(err, IsNil) + _, err = snapstate.CurrentInfo(diskState, "core18") + c.Check(err, IsNil) + _, err = snapstate.CurrentInfo(diskState, "foo") + c.Check(err, IsNil) + + // but we're not considered seeded + var seeded bool + err = diskState.Get("seeded", &seeded) + c.Assert(err, Equals, state.ErrNoState) } diff --git a/overlord/devicestate/firstboot_test.go b/overlord/devicestate/firstboot_test.go index 961a603bb58..a76d622b18f 100644 --- a/overlord/devicestate/firstboot_test.go +++ b/overlord/devicestate/firstboot_test.go @@ -1160,7 +1160,7 @@ type core18SnapsOpts struct { gadget bool } -func (s *firstBoot16Suite) makeCore18Snaps(c *C, opts *core18SnapsOpts) (core18Fn, snapdFn, kernelFn, gadgetFn string) { +func (s *firstBoot16BaseTest) makeCore18Snaps(c *C, opts *core18SnapsOpts) (core18Fn, snapdFn, kernelFn, gadgetFn string) { if opts == nil { opts = &core18SnapsOpts{} } From 55d6b49dd35f573980e2ead4e3aa8d7bc916c25d Mon Sep 17 00:00:00 2001 From: Pawel Stolowski Date: Thu, 20 Feb 2020 17:27:54 +0100 Subject: [PATCH 2/8] Add spread test. --- tests/main/preseed-snapd-snap/seed.yaml.in | 7 ++ tests/main/preseed-snapd-snap/task.yaml | 110 +++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 tests/main/preseed-snapd-snap/seed.yaml.in create mode 100644 tests/main/preseed-snapd-snap/task.yaml diff --git a/tests/main/preseed-snapd-snap/seed.yaml.in b/tests/main/preseed-snapd-snap/seed.yaml.in new file mode 100644 index 00000000000..353e8a05395 --- /dev/null +++ b/tests/main/preseed-snapd-snap/seed.yaml.in @@ -0,0 +1,7 @@ +snaps: + - name: snapd + file: @SNAPD@ + unasserted: true + - name: core18 + file: @CORE@ + unasserted: true diff --git a/tests/main/preseed-snapd-snap/task.yaml b/tests/main/preseed-snapd-snap/task.yaml new file mode 100644 index 00000000000..ea68065ecc5 --- /dev/null +++ b/tests/main/preseed-snapd-snap/task.yaml @@ -0,0 +1,110 @@ +summary: Check that preseeding of current ubuntu cloud image works with snapd + and core18 works. +description: | + This test checks that preseeding of Ubuntu cloud images with snap-preseed + command works, up to the point where the image is ready to be booted. + The test assumes cloud image with a core and lxd snaps in its seeds/. + +systems: [ubuntu-20.04-*] + +environment: + IMAGE_MOUNTPOINT: /mnt/cloudimg + +prepare: | + # the get_image_url_for_nested_vm is a convenient helper that returns + # a cloud image url matching current $SPREAD_SYSTEM. + #shellcheck source=tests/lib/nested.sh + . "$TESTSLIB/nested.sh" + wget "$(get_image_url_for_nested_vm)" -O cloudimg.img + mkdir -p "$IMAGE_MOUNTPOINT" + +restore: | + # any of the restore commands can fail depending on where execute part stopped, + # account for that with ||true. + umount_ubuntu_image "$IMAGE_MOUNTPOINT" || true + +execute: | + setup_preseeding_core18() { + local IMAGE_MOUNTPOINT=$1 + local SEEDS_DIR + SEEDS_DIR="$IMAGE_MOUNTPOINT/var/lib/snapd/seed/" + rm -f "$SEEDS_DIR"/snaps/*.snap + rm -f "$SEEDS_DIR"/seed.yaml + + snap download --edge snapd + snap download --edge core18 + + CORE=$(ls core18*.snap) + SNAPD=$(ls snapd*.snap) + sed seed.yaml.in -E -e 's/@CORE@/'"$CORE"'/' -e 's/@SNAPD@/'"$SNAPD"'/' > "$SEEDS_DIR"/seed.yaml + + cp "$CORE" "$SNAPD" "$SEEDS_DIR"/snaps/ + } + + #shellcheck source=tests/lib/preseed.sh + . "$TESTSLIB/preseed.sh" + mount_ubuntu_image cloudimg.img "$IMAGE_MOUNTPOINT" + setup_preseeding_core18 "$IMAGE_MOUNTPOINT" + + echo "Running pre-seeeding" + /usr/lib/snapd/snap-preseed "$IMAGE_MOUNTPOINT" + + # sanity, core snap mounted by snap-preseed got unmounted + mount | not MATCH "snap-preseed" + + snap debug state "$IMAGE_MOUNTPOINT"/var/lib/snapd/state.json --change=1 > tasks.log + + echo "Check that the tasks of preseeded snapd have expected statuses" + # Note, these checks match statuses, but not the order + MATCH "Done .+ prerequisites +Ensure prerequisites for \"snapd\" are available" < tasks.log + MATCH "Done .+ prepare-snap +Prepare snap \"/var/lib/snapd/seed/snaps/snapd_[0-9]+.snap" < tasks.log + MATCH "Done .+ mount-snap +Mount snap \"snapd\"" < tasks.log + MATCH "Done .+ copy-snap-data +Copy snap \"snapd\" data" < tasks.log + MATCH "Done .+ setup-profiles +Setup snap \"snapd\" \(unset\) security profiles" < tasks.log + MATCH "Done .+ link-snap +Make snap \"snapd\" \(unset\) available to the system" < tasks.log + MATCH "Done .+ auto-connect +Automatically connect eligible plugs and slots of snap \"snapd\"" < tasks.log + MATCH "Done .+ set-auto-aliases +Set automatic aliases for snap \"snapd\"" < tasks.log + MATCH "Done .+ setup-aliases +Setup snap \"snapd\" aliases" < tasks.log + MATCH "Done .+ prerequisites +Ensure prerequisites for \"core18\" are available" < tasks.log + MATCH "Done .+ prepare-snap +Prepare snap \"/var/lib/snapd/seed/snaps/core18_[0-9]+.snap\"" < tasks.log + MATCH "Done .+ mount-snap +Mount snap \"core18\" \(unset\)" < tasks.log + MATCH "Done .+ copy-snap-data +Copy snap \"core18\" data" < tasks.log + MATCH "Done .+ setup-profiles +Setup snap \"core18\" \(unset\) security profiles" < tasks.log + MATCH "Done .+ link-snap +Make snap \"core18\" \(unset\) available to the system" < tasks.log + MATCH "Done .+ auto-connect +Automatically connect eligible plugs and slots of snap \"core18\"" < tasks.log + MATCH "Done .+ setup-profiles +Setup snap \"core18\" \(unset\) security profiles for auto-connections" < tasks.log + MATCH "Done .+ set-auto-aliases +Set automatic aliases for snap \"core18\"" < tasks.log + MATCH "Done .+ setup-aliases +Setup snap \"core18\" aliases" < tasks.log + + echo "Checking that there were no other 'Done' tasks when preseeding" + [ "$(grep -c ' Done ' tasks.log)" = "18" ] + + # mark-preseeded task is where snap-preseed stopped, therefore it's in Doing. + MATCH "Doing .+ mark-preseeded +Mark system pre-seeded" < tasks.log + + # everything below is pending execution on first boot + MATCH "Do .+ run-hook +Run install hook of \"snapd\" snap if present" < tasks.log + MATCH "Do .+ start-snap-services +Start snap \"snapd\" \(unset\) services" < tasks.log + MATCH "Do .+ run-hook +Run configure hook of \"core\" snap if present" < tasks.log + MATCH "Do .+ run-hook +Run install hook of \"core18\" snap if present" < tasks.log + MATCH "Do .+ start-snap-services +Start snap \"core18\" \(unset\) services" < tasks.log + MATCH "Do .+ run-hook +Run health check of \"core18\" snap" < tasks.log + MATCH "Do .+ mark-seeded +Mark system seeded" < tasks.log + + echo "Checking that mount units have been created on the target image" + SYSTEMD_UNITS="$IMAGE_MOUNTPOINT"/etc/systemd + test -f "$SYSTEMD_UNITS"/system/snap-snapd-*.mount + test -f "$SYSTEMD_UNITS"/system/snap-core18-*.mount + for unit in snap.lxd.daemon.service snap.lxd.daemon.unix.socket snap.lxd.activate.service; do + test -f "$SYSTEMD_UNITS/system/$unit" + done + + echo "Checking enabled systemd mount units" + test -L "$SYSTEMD_UNITS"/system/multi-user.target.wants/snap-snapd-*.mount + test -L "$SYSTEMD_UNITS"/system/multi-user.target.wants/snap-core18-*.mount + echo "LXD service shouldn't be enabled at this point" + test ! -e "$SYSTEMD_UNITS"/system/multi-user.target.wants/snap.lxd.activate.service + + #shellcheck source=tests/lib/preseed.sh + . "$TESTSLIB/preseed.sh" + umount_ubuntu_image "$IMAGE_MOUNTPOINT" From f08151e75eeea97e06c8ca77a4315487fe0fb031 Mon Sep 17 00:00:00 2001 From: Pawel Stolowski Date: Thu, 20 Feb 2020 18:37:19 +0100 Subject: [PATCH 3/8] Fix wrong match. --- tests/main/preseed-snapd-snap/task.yaml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/main/preseed-snapd-snap/task.yaml b/tests/main/preseed-snapd-snap/task.yaml index ea68065ecc5..0272d61d2ec 100644 --- a/tests/main/preseed-snapd-snap/task.yaml +++ b/tests/main/preseed-snapd-snap/task.yaml @@ -72,7 +72,7 @@ execute: | MATCH "Done .+ setup-profiles +Setup snap \"core18\" \(unset\) security profiles" < tasks.log MATCH "Done .+ link-snap +Make snap \"core18\" \(unset\) available to the system" < tasks.log MATCH "Done .+ auto-connect +Automatically connect eligible plugs and slots of snap \"core18\"" < tasks.log - MATCH "Done .+ setup-profiles +Setup snap \"core18\" \(unset\) security profiles for auto-connections" < tasks.log + MATCH "Done .+ setup-profiles +Setup snap \"core18\" \(unset\) security profiles" < tasks.log MATCH "Done .+ set-auto-aliases +Set automatic aliases for snap \"core18\"" < tasks.log MATCH "Done .+ setup-aliases +Setup snap \"core18\" aliases" < tasks.log @@ -95,15 +95,10 @@ execute: | SYSTEMD_UNITS="$IMAGE_MOUNTPOINT"/etc/systemd test -f "$SYSTEMD_UNITS"/system/snap-snapd-*.mount test -f "$SYSTEMD_UNITS"/system/snap-core18-*.mount - for unit in snap.lxd.daemon.service snap.lxd.daemon.unix.socket snap.lxd.activate.service; do - test -f "$SYSTEMD_UNITS/system/$unit" - done echo "Checking enabled systemd mount units" test -L "$SYSTEMD_UNITS"/system/multi-user.target.wants/snap-snapd-*.mount test -L "$SYSTEMD_UNITS"/system/multi-user.target.wants/snap-core18-*.mount - echo "LXD service shouldn't be enabled at this point" - test ! -e "$SYSTEMD_UNITS"/system/multi-user.target.wants/snap.lxd.activate.service #shellcheck source=tests/lib/preseed.sh . "$TESTSLIB/preseed.sh" From 6ce59ae9264fbae543410627ecdc4ba6c454ae2d Mon Sep 17 00:00:00 2001 From: Pawel Stolowski Date: Fri, 21 Feb 2020 10:45:19 +0100 Subject: [PATCH 4/8] Explicit check for status of the preseeding change. Simplify sed quoting in the spread test (thanks Ian). --- overlord/devicestate/firstboot_preseed_test.go | 2 ++ tests/main/preseed-snapd-snap/task.yaml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/overlord/devicestate/firstboot_preseed_test.go b/overlord/devicestate/firstboot_preseed_test.go index e38f9e49816..578addf6367 100644 --- a/overlord/devicestate/firstboot_preseed_test.go +++ b/overlord/devicestate/firstboot_preseed_test.go @@ -308,6 +308,7 @@ snaps: c.Assert(chg.Err(), IsNil) checkPreseedTaskStates(c, st) + c.Check(chg.Status(), Equals, state.DoingStatus) // verify r, err := os.Open(dirs.SnapStateFile) @@ -398,6 +399,7 @@ snaps: c.Assert(err, IsNil) checkPreseedTaskStates(c, st) + c.Check(chg.Status(), Equals, state.DoingStatus) // verify r, err := os.Open(dirs.SnapStateFile) diff --git a/tests/main/preseed-snapd-snap/task.yaml b/tests/main/preseed-snapd-snap/task.yaml index 0272d61d2ec..784b2e52899 100644 --- a/tests/main/preseed-snapd-snap/task.yaml +++ b/tests/main/preseed-snapd-snap/task.yaml @@ -36,7 +36,7 @@ execute: | CORE=$(ls core18*.snap) SNAPD=$(ls snapd*.snap) - sed seed.yaml.in -E -e 's/@CORE@/'"$CORE"'/' -e 's/@SNAPD@/'"$SNAPD"'/' > "$SEEDS_DIR"/seed.yaml + sed seed.yaml.in -E -e "s/@CORE@/$CORE/" -e "s/@SNAPD@/$SNAPD/" > "$SEEDS_DIR"/seed.yaml cp "$CORE" "$SNAPD" "$SEEDS_DIR"/snaps/ } From cafdaa5bf0ac36a6537487bc68d61a2d7d5a24a8 Mon Sep 17 00:00:00 2001 From: Pawel Stolowski Date: Fri, 21 Feb 2020 11:00:07 +0100 Subject: [PATCH 5/8] Include preseed.sh in restore. --- tests/main/preseed-snapd-snap/task.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/main/preseed-snapd-snap/task.yaml b/tests/main/preseed-snapd-snap/task.yaml index 784b2e52899..4d898d61d7c 100644 --- a/tests/main/preseed-snapd-snap/task.yaml +++ b/tests/main/preseed-snapd-snap/task.yaml @@ -19,6 +19,9 @@ prepare: | mkdir -p "$IMAGE_MOUNTPOINT" restore: | + #shellcheck source=tests/lib/preseed.sh + . "$TESTSLIB/preseed.sh" + # any of the restore commands can fail depending on where execute part stopped, # account for that with ||true. umount_ubuntu_image "$IMAGE_MOUNTPOINT" || true From 140ca449306a618cfc6229a92b3ab9be8d033609 Mon Sep 17 00:00:00 2001 From: Pawel Stolowski Date: Mon, 24 Feb 2020 14:09:10 +0100 Subject: [PATCH 6/8] Fail with an error if model is not classic in snapo-preseed. --- cmd/snap-preseed/main_test.go | 51 +++++++++++++++++++++++-- cmd/snap-preseed/preseed_linux.go | 8 ++++ tests/main/preseed-snapd-snap/task.yaml | 2 +- 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/cmd/snap-preseed/main_test.go b/cmd/snap-preseed/main_test.go index c19371e7bb1..f5172062c9e 100644 --- a/cmd/snap-preseed/main_test.go +++ b/cmd/snap-preseed/main_test.go @@ -31,6 +31,7 @@ import ( . "gopkg.in/check.v1" "github.com/snapcore/snapd/asserts" + "github.com/snapcore/snapd/asserts/assertstest" "github.com/snapcore/snapd/cmd/snap-preseed" "github.com/snapcore/snapd/dirs" "github.com/snapcore/snapd/seed" @@ -171,6 +172,7 @@ func (s *startPreseedSuite) TestRunPreseedHappy(c *C) { } type Fake16Seed struct { + AssertsModel *asserts.Model Essential []*seed.Snap LoadMetaErr error LoadAssertionsErr error @@ -179,12 +181,25 @@ type Fake16Seed struct { // Fake implementation of seed.Seed interface +func mockClassicModel() *asserts.Model { + headers := map[string]interface{}{ + "type": "model", + "authority-id": "brand", + "series": "16", + "brand-id": "brand", + "model": "classicbaz-3000", + "classic": "true", + "timestamp": "2018-01-01T08:00:00+00:00", + } + return assertstest.FakeAssertion(headers, nil).(*asserts.Model) +} + func (fs *Fake16Seed) LoadAssertions(db asserts.RODatabase, commitTo func(*asserts.Batch) error) error { return fs.LoadAssertionsErr } func (fs *Fake16Seed) Model() (*asserts.Model, error) { - panic("not implemented") + return fs.AssertsModel, nil } func (fs *Fake16Seed) LoadMeta(tm timings.Measurer) error { @@ -208,7 +223,8 @@ func (s *startPreseedSuite) TestSystemSnapFromSeed(c *C) { restore := main.MockSeedOpen(func(rootDir, label string) (seed.Seed, error) { return &Fake16Seed{ - Essential: []*seed.Snap{{Path: "/some/path/core", SideInfo: &snap.SideInfo{RealName: "core"}}}, + AssertsModel: mockClassicModel(), + Essential: []*seed.Snap{{Path: "/some/path/core", SideInfo: &snap.SideInfo{RealName: "core"}}}, }, nil }) defer restore() @@ -223,8 +239,9 @@ func (s *startPreseedSuite) TestSystemSnapFromSnapdSeed(c *C) { restore := main.MockSeedOpen(func(rootDir, label string) (seed.Seed, error) { return &Fake16Seed{ - Essential: []*seed.Snap{{Path: "/some/path/snapd.snap", SideInfo: &snap.SideInfo{RealName: "snapd"}}}, - UsesSnapd: true, + AssertsModel: mockClassicModel(), + Essential: []*seed.Snap{{Path: "/some/path/snapd.snap", SideInfo: &snap.SideInfo{RealName: "snapd"}}}, + UsesSnapd: true, }, nil }) defer restore() @@ -248,6 +265,7 @@ func (s *startPreseedSuite) TestSystemSnapFromSeedErrors(c *C) { tmpDir := c.MkDir() fakeSeed := &Fake16Seed{} + fakeSeed.AssertsModel = mockClassicModel() restore := main.MockSeedOpen(func(rootDir, label string) (seed.Seed, error) { return fakeSeed, nil }) defer restore() @@ -270,6 +288,31 @@ func (s *startPreseedSuite) TestSystemSnapFromSeedErrors(c *C) { c.Assert(err, ErrorMatches, "load assertions failed") } +func (s *startPreseedSuite) TestClassicRequired(c *C) { + tmpDir := c.MkDir() + + headers := map[string]interface{}{ + "type": "model", + "authority-id": "brand", + "series": "16", + "brand-id": "brand", + "model": "baz-3000", + "architecture": "armhf", + "gadget": "brand-gadget", + "kernel": "kernel", + "timestamp": "2018-01-01T08:00:00+00:00", + } + + fakeSeed := &Fake16Seed{} + fakeSeed.AssertsModel = assertstest.FakeAssertion(headers, nil).(*asserts.Model) + + restore := main.MockSeedOpen(func(rootDir, label string) (seed.Seed, error) { return fakeSeed, nil }) + defer restore() + + _, err := main.SystemSnapFromSeed(tmpDir) + c.Assert(err, ErrorMatches, "preseeding is only supported on classic systems") +} + func (s *startPreseedSuite) TestRunPreseedUnsupportedVersion(c *C) { tmpDir := c.MkDir() dirs.SetRootDir(tmpDir) diff --git a/cmd/snap-preseed/preseed_linux.go b/cmd/snap-preseed/preseed_linux.go index 605acff5f1e..272bf82564a 100644 --- a/cmd/snap-preseed/preseed_linux.go +++ b/cmd/snap-preseed/preseed_linux.go @@ -85,6 +85,14 @@ var systemSnapFromSeed = func(rootDir string) (string, error) { return "", err } + model, err := seed.Model() + if err != nil { + return "", err + } + if !model.Classic() { + return "", fmt.Errorf("preseeding is only supported on classic systems") + } + var required string if seed.UsesSnapdSnap() { required = "snapd" diff --git a/tests/main/preseed-snapd-snap/task.yaml b/tests/main/preseed-snapd-snap/task.yaml index 4d898d61d7c..b8d274b83e7 100644 --- a/tests/main/preseed-snapd-snap/task.yaml +++ b/tests/main/preseed-snapd-snap/task.yaml @@ -5,7 +5,7 @@ description: | command works, up to the point where the image is ready to be booted. The test assumes cloud image with a core and lxd snaps in its seeds/. -systems: [ubuntu-20.04-*] +systems: [ubuntu-19.10-*, ubuntu-20.04-*] environment: IMAGE_MOUNTPOINT: /mnt/cloudimg From 9be5e6246350f96c2812b75b01f2f01865f0c9db Mon Sep 17 00:00:00 2001 From: Pawel Stolowski Date: Wed, 26 Feb 2020 15:27:21 +0100 Subject: [PATCH 7/8] Tweak the summary. Co-Authored-By: Zygmunt Krynicki --- tests/main/preseed-snapd-snap/task.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/main/preseed-snapd-snap/task.yaml b/tests/main/preseed-snapd-snap/task.yaml index b8d274b83e7..93ee2263e60 100644 --- a/tests/main/preseed-snapd-snap/task.yaml +++ b/tests/main/preseed-snapd-snap/task.yaml @@ -1,5 +1,5 @@ summary: Check that preseeding of current ubuntu cloud image works with snapd - and core18 works. + and core18. description: | This test checks that preseeding of Ubuntu cloud images with snap-preseed command works, up to the point where the image is ready to be booted. From 9402af6ae21deb4515d23259ae22a6e0398999b2 Mon Sep 17 00:00:00 2001 From: Pawel Stolowski Date: Wed, 26 Feb 2020 16:16:55 +0100 Subject: [PATCH 8/8] Tweak test summary, add TODO re core. --- cmd/snap-preseed/preseed_linux.go | 2 ++ tests/main/preseed-snapd-snap/task.yaml | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/snap-preseed/preseed_linux.go b/cmd/snap-preseed/preseed_linux.go index 272bf82564a..2749e077820 100644 --- a/cmd/snap-preseed/preseed_linux.go +++ b/cmd/snap-preseed/preseed_linux.go @@ -89,6 +89,8 @@ var systemSnapFromSeed = func(rootDir string) (string, error) { if err != nil { return "", err } + + // TODO: implement preseeding for core. if !model.Classic() { return "", fmt.Errorf("preseeding is only supported on classic systems") } diff --git a/tests/main/preseed-snapd-snap/task.yaml b/tests/main/preseed-snapd-snap/task.yaml index 93ee2263e60..52d74195e3f 100644 --- a/tests/main/preseed-snapd-snap/task.yaml +++ b/tests/main/preseed-snapd-snap/task.yaml @@ -1,5 +1,7 @@ -summary: Check that preseeding of current ubuntu cloud image works with snapd +summary: | + Check that preseeding of current ubuntu cloud image works with snapd and core18. + description: | This test checks that preseeding of Ubuntu cloud images with snap-preseed command works, up to the point where the image is ready to be booted.