Skip to content

Commit

Permalink
Merge branch 'master' into add-mutter-idlemonitor-getidletime-to-desk…
Browse files Browse the repository at this point in the history
…top-interface
  • Loading branch information
MiguelPires committed Oct 27, 2023
2 parents 3e09767 + 6aa9e0e commit 9228ace
Show file tree
Hide file tree
Showing 9 changed files with 189 additions and 24 deletions.
3 changes: 3 additions & 0 deletions boot/boot.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,9 @@ func fixedInUse(inUse bool) InUseFunc {
// InUse returns a checker for whether a given name/revision is used in the
// boot environment for snaps of the relevant snap type.
func InUse(typ snap.Type, dev snap.Device) (InUseFunc, error) {
modeenvLock()
defer modeenvUnlock()

if !dev.RunMode() {
// ephemeral mode, block manipulations for now
return fixedInUse(true), nil
Expand Down
41 changes: 41 additions & 0 deletions boot/boot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,47 @@ func (s *bootenvSuite) TestInUse(c *C) {
}
}

func (s *bootenv20Suite) TestInUseCore20(c *C) {
coreDev := boottest.MockUC20Device("", nil)
c.Assert(coreDev.HasModeenv(), Equals, true)
c.Assert(coreDev.IsCoreBoot(), Equals, true)

r := setupUC20Bootenv(
c,
s.bootloader,
&bootenv20Setup{
modeenv: &boot.Modeenv{
// base is base1
Base: s.base1.Filename(),
// no try base
TryBase: "",
// gadget is gadget1
Gadget: s.gadget1.Filename(),
// current kernels is just kern1
CurrentKernels: []string{s.kern1.Filename()},
// operating mode is run
Mode: "run",
// RecoverySystem is unset, as it should be during run mode
RecoverySystem: "",
},
// enabled kernel is kern1
kern: s.kern1,
// no try kernel enabled
tryKern: nil,
// kernel status is default
kernStatus: boot.DefaultStatus,
})
defer r()

inUse, err := boot.InUse(snap.TypeKernel, coreDev)
c.Check(err, IsNil)
c.Check(inUse(s.kern1.SnapName(), s.kern1.SnapRevision()), Equals, true)
c.Check(inUse(s.kern2.SnapName(), s.kern2.SnapRevision()), Equals, false)

_, err = boot.InUse(snap.TypeBase, coreDev)
c.Check(err, IsNil)
}

func (s *bootenvSuite) TestInUseEphemeral(c *C) {
coreDev := boottest.MockDevice("some-snap@install")

Expand Down
4 changes: 4 additions & 0 deletions gadget/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -938,6 +938,10 @@ func buildNewVolumeToDeviceMapping(mod Model, old GadgetData, vols map[string]*V

traits, err := DiskTraitsFromDeviceAndValidate(vol, dev, validateOpts)
if err != nil {
if isPreUC20 {
logger.Noticef("WARNING: not applying gadget asset updates on main system-boot volume due to error while finding disk traits: %v", err)
return nil, errSkipUpdateProceedRefresh
}
return nil, err
}

Expand Down
56 changes: 56 additions & 0 deletions gadget/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5215,6 +5215,62 @@ func (u *updateTestSuite) TestBuildNewVolumeToDeviceMappingPreUC20NonFatalError(
c.Assert(err, Not(Equals), gadget.ErrSkipUpdateProceedRefresh)
}

func (u *updateTestSuite) TestBuildNewVolumeToDeviceMappingPreUC20CannotMap(c *C) {
fmt.Println("TestBuildNewVolumeToDeviceMappingPreUC20CannotMap")
defer fmt.Println("TestBuildNewVolumeToDeviceMappingPreUC20CannotMap")
mockLogBuf, restore := logger.MockLogger()
defer restore()

allLaidOutVolumes, err := gadgettest.LayoutMultiVolumeFromYaml(c.MkDir(), "", gadgettest.UC16YAMLImplicitSystemData, uc16Model)
c.Assert(err, IsNil)

old := gadget.GadgetData{
Info: &gadget.Info{
Volumes: make(map[string]*gadget.Volume),
},
}

for volName, laidOutVol := range allLaidOutVolumes {
old.Info.Volumes[volName] = laidOutVol.Volume
}

// setup symlink for the system-boot partition
err = os.MkdirAll(filepath.Join(dirs.GlobalRootDir, "/dev/disk/by-partlabel"), 0755)
c.Assert(err, IsNil)
fakedevicepart := filepath.Join(dirs.GlobalRootDir, "/dev/vda1")
err = os.Symlink(fakedevicepart, filepath.Join(dirs.GlobalRootDir, "/dev/disk/by-partlabel", disks.BlkIDEncodeLabel("EFI System")))
c.Assert(err, IsNil)
err = os.WriteFile(fakedevicepart, nil, 0644)
c.Assert(err, IsNil)

// mock the partition device node to mock disk
restore = disks.MockPartitionDeviceNodeToDiskMapping(map[string]*disks.MockDiskMapping{
filepath.Join(dirs.GlobalRootDir, "/dev/vda1"): gadgettest.VMSystemVolumeDiskMapping,
})
defer restore()

// and the device name to the disk itself
restore = disks.MockDeviceNameToDiskMapping(map[string]*disks.MockDiskMapping{
"/dev/vda": gadgettest.VMSystemVolumeDiskMapping,
})
defer restore()

vols := map[string]*gadget.Volume{}
for name, lov := range allLaidOutVolumes {
vols[name] = lov.Volume
}

// The call will fail as it won't find a match between /dev/vda2 and
// any partition defined in the gadget. But it is ok for UC16/18.
_, err = gadget.BuildNewVolumeToDeviceMapping(uc16Model, old, vols)
c.Assert(err, Equals, gadget.ErrSkipUpdateProceedRefresh)
c.Assert(mockLogBuf.String(), testutil.Contains, "WARNING: not applying gadget asset updates on main system-boot volume due to error while finding disk traits")

// it's a fatal error on UC20 though
_, err = gadget.BuildNewVolumeToDeviceMapping(uc20Model, old, vols)
c.Assert(err, Not(Equals), gadget.ErrSkipUpdateProceedRefresh)
}

func (u *updateTestSuite) TestBuildNewVolumeToDeviceMappingUC20MultiVolume(c *C) {
allLaidOutVolumes, err := gadgettest.LayoutMultiVolumeFromYaml(c.MkDir(), "", gadgettest.MultiVolumeUC20GadgetYaml, uc20Model)
c.Assert(err, IsNil)
Expand Down
2 changes: 1 addition & 1 deletion overlord/snapstate/snapstate.go
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ func doInstall(st *state.State, snapst *SnapState, snapsup *SnapSetup, flags int
}
// If snapsup.Version was smaller, 1 is returned.
if res == 1 {
if err := CheckChangeConflictRunExclusively(st, "snapd downgrade"); err != nil {
if err := checkChangeConflictExclusiveKinds(st, "snapd downgrade", fromChange); err != nil {
return nil, err
}
}
Expand Down
56 changes: 56 additions & 0 deletions overlord/snapstate/snapstate_update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10482,3 +10482,59 @@ func (s *snapmgrTestSuite) TestUpdateManyRevOptsOrder(c *C) {
testOrder([]string{"snap-c", "some-snap", "some-other-snap"})
testOrder([]string{"snap-c", "some-other-snap", "some-snap"})
}

func (s *snapmgrTestSuite) TestSnapdRefreshForRemodel(c *C) {
s.state.Lock()
defer s.state.Unlock()

// Set snapd state in the system: currently rev 44 installed, but also
// 22 is in the system (simply to avoid trying to reach the store for
// that rev when we want to refresh to it).
snapstate.Set(s.state, "snapd", &snapstate.SnapState{
Active: true,
TrackingChannel: "latest/edge",
Sequence: []*snap.SideInfo{
{RealName: "snapd", SnapID: "snapd-snap-id", Revision: snap.R(44)},
{RealName: "snapd", SnapID: "snapd-snap-id", Revision: snap.R(22)}},
Current: snap.R(44),
SnapType: "app",
})

restore := snapstate.MockSnapReadInfo(func(name string, si *snap.SideInfo) (*snap.Info, error) {
var version string
switch name {
case "snapd":
switch si.Revision.N {
case 22:
version = "1.0"
default:
version = "2.0"
}
default:
version = "1.0"
}
return &snap.Info{
SuggestedName: name,
Version: version,
Architectures: []string{"all"},
SideInfo: *si,
}, nil
})
defer restore()

// This is part of a remodeling change
chg := s.state.NewChange("remodel", "...")
chg.SetStatus(state.DoStatus)

// Update to snapd rev 22, which is an older revision. This checks that
// things are fine in that case and that there is no conflict detected
// as we are doing this from the remodel change.
opts := &snapstate.RevisionOptions{Channel: "stable", Revision: snap.R(22)}
_, err := snapstate.UpdateWithDeviceContext(s.state, "snapd", opts, s.user.ID, snapstate.Flags{}, nil, nil, chg.ID())
c.Check(err, IsNil)

// But there is a conflict if this update is not part of the remodel change.
_, err = snapstate.UpdateWithDeviceContext(s.state, "snapd", opts, s.user.ID, snapstate.Flags{}, nil, nil, "")
c.Check(err, FitsTypeOf, &snapstate.ChangeConflictError{})
c.Check(err, ErrorMatches, "remodeling in progress, no other changes allowed until this is done")
}
35 changes: 12 additions & 23 deletions tests/core/system-snap-refresh/task.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,37 +17,26 @@ prepare: |
echo "SNAPD_SHUTDOWN_DELAY=1" >> /etc/environment
systemctl restart snapd
restore: |
TARGET_SNAP_NAME=core
if os.query is-core18; then
TARGET_SNAP_NAME=core18
elif os.query is-core20; then
TARGET_SNAP_NAME=core20
fi
TARGET_SNAP_NAME="$(snaps.name core)"
# Save initial revision
"$TESTSTOOLS"/snaps-state show-revision "$TARGET_SNAP_NAME" > initi_rev.log
if not snap remove "$TARGET_SNAP_NAME" --revision=x2; then
snap changes
exit 1
fi
restore: |
TARGET_SNAP_NAME="$(snaps.name core)"
# We need to make sure the base snap has the initial rev
test "$("$TESTSTOOLS"/snaps-state show-revision "$TARGET_SNAP_NAME")" == "$(cat initi_rev.log)"
# remove SNAPD_SHUTDOWN_DELAY from /etc/environment again
#shellcheck disable=SC2005
echo "$(grep -v 'SNAPD_SHUTDOWN_DELAY=1' /etc/environment)" > /etc/environment
systemctl restart snapd
execute: |
TARGET_SNAP_NAME=core
if os.query is-core18; then
TARGET_SNAP_NAME=core18
elif os.query is-core20; then
TARGET_SNAP_NAME=core20
elif os.query is-core22; then
TARGET_SNAP_NAME=core22
fi
TARGET_SNAP_NAME="$(snaps.name core)"
# After installing a new version of the core/core18 snap the system is rebooted
if [ "$SPREAD_REBOOT" = 0 ]; then
currRev="$(readlink /snap/${TARGET_SNAP_NAME}/current)"
currRev="$(readlink /snap/"${TARGET_SNAP_NAME}"/current)"
echo "$currRev" > initialRev
# use journalctl wrapper to grep only the logs collected while the test is running
Expand All @@ -57,7 +46,7 @@ execute: |
fi
# install new target snap
snap install --dangerous --no-wait "/var/lib/snapd/snaps/${TARGET_SNAP_NAME}_${currRev}.snap"
snap install --dangerous --no-wait /var/lib/snapd/snaps/"${TARGET_SNAP_NAME}"_"${currRev}".snap
# Detect in the logs when the reboot can been triggered
"$TESTSTOOLS"/journal-state match-log -n 50 --wait 2 "Waiting for system reboot"
Expand All @@ -68,7 +57,7 @@ execute: |
snap watch --last=install
# Check the current revision has changed
currRev="$(readlink /snap/${TARGET_SNAP_NAME}/current)"
currRev="$(readlink /snap/"${TARGET_SNAP_NAME}"/current)"
[ "$(cat initialRev)" != "$currRev" ]
# revert the target snap
Expand All @@ -82,6 +71,6 @@ execute: |
# Wait for the revert to complete.
snap watch --last=revert-snap
# Check the current revision is the same than the original
currRev="$(readlink /snap/${TARGET_SNAP_NAME}/current)"
currRev="$(readlink /snap/"${TARGET_SNAP_NAME}"/current)"
[ "$(cat initialRev)" == "$currRev" ]
fi
10 changes: 10 additions & 0 deletions tests/lib/tools/snaps-state
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ show_help() {
echo " install-local <snap-name> [OPTIONS]"
echo " install-local-as <snap-name> <dest-name> [OPTIONS]"
echo " show-name <snap>"
echo " show-revision <snap>"
echo " is-confinement-supported <classic|devmode|strict>"
echo " repack-snapd-deb-into-snap <snapd|core>"
echo " repack-core-snap-into-snapd-snap"
Expand Down Expand Up @@ -99,6 +100,15 @@ show_name() {
esac
}

show_revision() {
local snap="$1"
if not snap list "$snap" &>/dev/null; then
echo "snaps-state: the snap $snap is not installed" >&2
exit 1
fi
snap info "$snap" | awk "/installed: / {print(\$3)}" | sed -e 's/(\(.*\))/\1/'
}

is_confinement_supported() {
local confinement="$1"
if [ -z "$confinement" ]; then
Expand Down
6 changes: 6 additions & 0 deletions tests/main/snaps-state/task.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ execute: |
kernel_name=$("$TESTSTOOLS"/snaps-state show-name kernel)
gadget_name=$("$TESTSTOOLS"/snaps-state show-name gadget)
# Check the core revision
core_rev=$("$TESTSTOOLS"/snaps-state show-revision "$core_name")
snap info "$core_name" | grep "installed:" | MATCH "\($core_rev\)"
# Check the snap revision when it is not installed
"$TESTSTOOLS"/snaps-state show-revision not_installed 2>&1 | MATCH "snaps-state: the snap not_installed is not installed"
# Check the core, kernel and gadget snaps
snap list "$core_name"
if os.query is-core; then
Expand Down

0 comments on commit 9228ace

Please sign in to comment.