mirror of
https://github.com/kairos-io/kairos-agent.git
synced 2025-08-15 23:13:01 +00:00
After upgrade or recovery, set bootentry to "cos" (#251)
This commit is contained in:
parent
0c06b1b183
commit
3328a2987f
@ -2,8 +2,6 @@ package action
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
cnst "github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/elemental"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -11,6 +9,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
cnst "github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||||
|
"github.com/kairos-io/kairos-agent/v2/pkg/elemental"
|
||||||
|
|
||||||
"github.com/erikgeiser/promptkit/confirmation"
|
"github.com/erikgeiser/promptkit/confirmation"
|
||||||
"github.com/erikgeiser/promptkit/selection"
|
"github.com/erikgeiser/promptkit/selection"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/config"
|
"github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||||
@ -82,15 +83,15 @@ func selectBootEntrySystemd(cfg *config.Config, entry string) error {
|
|||||||
|
|
||||||
}
|
}
|
||||||
originalEntries := entries
|
originalEntries := entries
|
||||||
// when there are only 3 entries, we can assume they are active, passive and recovery
|
// when there are only 3 entries, we can assume they are either cos (which will be replaced eventually), fallback or recovery
|
||||||
if len(entries) == 3 {
|
if len(entries) == 3 {
|
||||||
entries = []string{"cos", "fallback", "recovery"}
|
entries = []string{"cos", "fallback", "recovery"}
|
||||||
}
|
}
|
||||||
// when there are more than 3 entries, then we need to also extract the part between the first _ and the .conf in order to distinguish the entries
|
|
||||||
|
|
||||||
// Check that entry exists in the entries list
|
// Check that entry exists in the entries list
|
||||||
err = entryInList(cfg, entry, entries)
|
err = entryInList(cfg, entry, entries)
|
||||||
if err != nil {
|
// we also accept "active" as a selection so we can migrate eventually from cos
|
||||||
|
if err != nil && !strings.HasPrefix(entry, "active") {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +114,12 @@ func selectBootEntrySystemd(cfg *config.Config, entry string) error {
|
|||||||
cfg.Logger.Errorf("could not read loader.conf: %s", err)
|
cfg.Logger.Errorf("could not read loader.conf: %s", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
originalEntry := entry
|
||||||
if !reflect.DeepEqual(originalEntries, entries) {
|
if !reflect.DeepEqual(originalEntries, entries) {
|
||||||
|
// since we temporarily allow also active, here we need to first set entry to "cos" so it will match with the originalEntries
|
||||||
|
if strings.HasPrefix(entry, "active") {
|
||||||
|
entry = "cos"
|
||||||
|
}
|
||||||
for _, e := range originalEntries {
|
for _, e := range originalEntries {
|
||||||
if strings.HasPrefix(e, entry) {
|
if strings.HasPrefix(e, entry) {
|
||||||
entry = e
|
entry = e
|
||||||
@ -131,7 +137,7 @@ func selectBootEntrySystemd(cfg *config.Config, entry string) error {
|
|||||||
cfg.Logger.Errorf("could not write loader.conf: %s", err)
|
cfg.Logger.Errorf("could not write loader.conf: %s", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cfg.Logger.Infof("Default boot entry set to %s", entry)
|
cfg.Logger.Infof("Default boot entry set to %s", originalEntry)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,6 +216,13 @@ func bootNameToSystemdConf(name string) (string, error) {
|
|||||||
return "active" + differenciator + ".conf", nil
|
return "active" + differenciator + ".conf", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(name, "active") {
|
||||||
|
if name != "active" {
|
||||||
|
differenciator = "_" + strings.TrimPrefix(name, "active ")
|
||||||
|
}
|
||||||
|
return "active" + differenciator + ".conf", nil
|
||||||
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(name, "fallback") {
|
if strings.HasPrefix(name, "fallback") {
|
||||||
if name != "fallback" {
|
if name != "fallback" {
|
||||||
differenciator = "_" + strings.TrimPrefix(name, "fallback ")
|
differenciator = "_" + strings.TrimPrefix(name, "fallback ")
|
||||||
|
@ -108,17 +108,19 @@ var _ = Describe("Bootentries tests", Label("bootentry"), func() {
|
|||||||
It("lists the boot entries if there is any", func() {
|
It("lists the boot entries if there is any", func() {
|
||||||
err := fs.WriteFile("/efi/loader/loader.conf", []byte("timeout 5\ndefault kairos\nrecovery kairos2\n"), os.ModePerm)
|
err := fs.WriteFile("/efi/loader/loader.conf", []byte("timeout 5\ndefault kairos\nrecovery kairos2\n"), os.ModePerm)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
err = fs.WriteFile("/efi/loader/entries/active.conf", []byte("title kairos\nlinux /vmlinuz\ninitrd /initrd\noptions root=LABEL=COS_GRUB\n"), os.ModePerm)
|
err = fs.WriteFile("/efi/loader/entries/active.conf", []byte("title kairos\nefi /EFI/kairos/active.efi\n"), os.ModePerm)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
err = fs.WriteFile("/efi/loader/entries/passive.conf", []byte("title kairos (fallback)\nefi /EFI/kairos/passive.efi\n"), os.ModePerm)
|
||||||
err = fs.WriteFile("/efi/loader/entries/passive.conf", []byte("title kairos2\nlinux /vmlinuz2\ninitrd /initrd2\noptions root=LABEL=COS_GRUB2\n"), os.ModePerm)
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
err = fs.WriteFile("/efi/loader/entries/recovery.conf", []byte("title kairos recovery\nefi /EFI/kairos/recovery.efi\n"), os.ModePerm)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
entries, err := listSystemdEntries(config, &v1.Partition{MountPoint: "/efi"})
|
entries, err := listSystemdEntries(config, &v1.Partition{MountPoint: "/efi"})
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(entries).To(HaveLen(2))
|
Expect(entries).To(HaveLen(3))
|
||||||
Expect(entries).To(ContainElement("cos"))
|
Expect(entries).To(ContainElement("cos"))
|
||||||
Expect(entries).To(ContainElement("fallback"))
|
Expect(entries).To(ContainElement("fallback"))
|
||||||
|
Expect(entries).To(ContainElement("recovery"))
|
||||||
|
|
||||||
})
|
})
|
||||||
It("list empty boot entries if there is none", func() {
|
It("list empty boot entries if there is none", func() {
|
||||||
@ -185,7 +187,51 @@ var _ = Describe("Bootentries tests", Label("bootentry"), func() {
|
|||||||
"",
|
"",
|
||||||
syscall.MS_REMOUNT|syscall.MS_RDONLY,
|
syscall.MS_REMOUNT|syscall.MS_RDONLY,
|
||||||
"")).To(BeTrue())
|
"")).To(BeTrue())
|
||||||
|
|
||||||
|
err = SelectBootEntry(config, "cos")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(memLog.String()).To(ContainSubstring("Default boot entry set to cos"))
|
||||||
|
reader, err = utils.SystemdBootConfReader(fs, "/efi/loader/loader.conf")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(reader["default"]).To(Equal("active.conf"))
|
||||||
|
// Should have called a remount to make it RW
|
||||||
|
Expect(syscallMock.WasMountCalledWith(
|
||||||
|
"",
|
||||||
|
"/efi",
|
||||||
|
"",
|
||||||
|
syscall.MS_REMOUNT,
|
||||||
|
"")).To(BeTrue())
|
||||||
|
// Should have called a remount to make it RO
|
||||||
|
Expect(syscallMock.WasMountCalledWith(
|
||||||
|
"",
|
||||||
|
"/efi",
|
||||||
|
"",
|
||||||
|
syscall.MS_REMOUNT|syscall.MS_RDONLY,
|
||||||
|
"")).To(BeTrue())
|
||||||
|
|
||||||
|
// also works using active (we want to get rid of the word cos later but this also needs to be applied in GRUB)
|
||||||
|
err = SelectBootEntry(config, "active")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(memLog.String()).To(ContainSubstring("Default boot entry set to active"))
|
||||||
|
reader, err = utils.SystemdBootConfReader(fs, "/efi/loader/loader.conf")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(reader["default"]).To(Equal("active.conf"))
|
||||||
|
// Should have called a remount to make it RW
|
||||||
|
Expect(syscallMock.WasMountCalledWith(
|
||||||
|
"",
|
||||||
|
"/efi",
|
||||||
|
"",
|
||||||
|
syscall.MS_REMOUNT,
|
||||||
|
"")).To(BeTrue())
|
||||||
|
// Should have called a remount to make it RO
|
||||||
|
Expect(syscallMock.WasMountCalledWith(
|
||||||
|
"",
|
||||||
|
"/efi",
|
||||||
|
"",
|
||||||
|
syscall.MS_REMOUNT|syscall.MS_RDONLY,
|
||||||
|
"")).To(BeTrue())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("selects the boot entry in a extend-cmdline installation with boot branding", func() {
|
It("selects the boot entry in a extend-cmdline installation with boot branding", func() {
|
||||||
err := fs.WriteFile("/efi/loader/entries/active_install-mode_awesomeos.conf", []byte("title awesomeos\nefi /EFI/kairos/active_install-mode_awesomeos.efi\n"), os.ModePerm)
|
err := fs.WriteFile("/efi/loader/entries/active_install-mode_awesomeos.conf", []byte("title awesomeos\nefi /EFI/kairos/active_install-mode_awesomeos.efi\n"), os.ModePerm)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
@ -258,6 +304,28 @@ var _ = Describe("Bootentries tests", Label("bootentry"), func() {
|
|||||||
"",
|
"",
|
||||||
syscall.MS_REMOUNT|syscall.MS_RDONLY,
|
syscall.MS_REMOUNT|syscall.MS_RDONLY,
|
||||||
"")).To(BeTrue())
|
"")).To(BeTrue())
|
||||||
|
|
||||||
|
// also works using active (we want to get rid of the word cos later but this also needs to be applied in GRUB)
|
||||||
|
err = SelectBootEntry(config, "active")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(memLog.String()).To(ContainSubstring("Default boot entry set to active"))
|
||||||
|
reader, err = utils.SystemdBootConfReader(fs, "/efi/loader/loader.conf")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(reader["default"]).To(Equal("active_install-mode_awesomeos.conf"))
|
||||||
|
// Should have called a remount to make it RW
|
||||||
|
Expect(syscallMock.WasMountCalledWith(
|
||||||
|
"",
|
||||||
|
"/efi",
|
||||||
|
"",
|
||||||
|
syscall.MS_REMOUNT,
|
||||||
|
"")).To(BeTrue())
|
||||||
|
// Should have called a remount to make it RO
|
||||||
|
Expect(syscallMock.WasMountCalledWith(
|
||||||
|
"",
|
||||||
|
"/efi",
|
||||||
|
"",
|
||||||
|
syscall.MS_REMOUNT|syscall.MS_RDONLY,
|
||||||
|
"")).To(BeTrue())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("selects the boot entry in a extra-cmdline installation", func() {
|
It("selects the boot entry in a extra-cmdline installation", func() {
|
||||||
@ -401,9 +469,52 @@ var _ = Describe("Bootentries tests", Label("bootentry"), func() {
|
|||||||
"",
|
"",
|
||||||
syscall.MS_REMOUNT|syscall.MS_RDONLY,
|
syscall.MS_REMOUNT|syscall.MS_RDONLY,
|
||||||
"")).To(BeTrue())
|
"")).To(BeTrue())
|
||||||
|
|
||||||
|
// also works using active (we want to get rid of the word cos later but this also needs to be applied in GRUB)
|
||||||
|
err = SelectBootEntry(config, "active")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(memLog.String()).To(ContainSubstring("Default boot entry set to active"))
|
||||||
|
reader, err = utils.SystemdBootConfReader(fs, "/efi/loader/loader.conf")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(reader["default"]).To(Equal("active.conf"))
|
||||||
|
// Should have called a remount to make it RW
|
||||||
|
Expect(syscallMock.WasMountCalledWith(
|
||||||
|
"",
|
||||||
|
"/efi",
|
||||||
|
"",
|
||||||
|
syscall.MS_REMOUNT,
|
||||||
|
"")).To(BeTrue())
|
||||||
|
// Should have called a remount to make it RO
|
||||||
|
Expect(syscallMock.WasMountCalledWith(
|
||||||
|
"",
|
||||||
|
"/efi",
|
||||||
|
"",
|
||||||
|
syscall.MS_REMOUNT|syscall.MS_RDONLY,
|
||||||
|
"")).To(BeTrue())
|
||||||
|
err = SelectBootEntry(config, "active foobar")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(memLog.String()).To(ContainSubstring("Default boot entry set to active foobar"))
|
||||||
|
reader, err = utils.SystemdBootConfReader(fs, "/efi/loader/loader.conf")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(reader["default"]).To(Equal("active_foobar.conf"))
|
||||||
|
// Should have called a remount to make it RW
|
||||||
|
Expect(syscallMock.WasMountCalledWith(
|
||||||
|
"",
|
||||||
|
"/efi",
|
||||||
|
"",
|
||||||
|
syscall.MS_REMOUNT,
|
||||||
|
"")).To(BeTrue())
|
||||||
|
// Should have called a remount to make it RO
|
||||||
|
Expect(syscallMock.WasMountCalledWith(
|
||||||
|
"",
|
||||||
|
"/efi",
|
||||||
|
"",
|
||||||
|
syscall.MS_REMOUNT|syscall.MS_RDONLY,
|
||||||
|
"")).To(BeTrue())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Context("Under grub", func() {
|
Context("Under grub", func() {
|
||||||
Context("ListBootEntries", func() {
|
Context("ListBootEntries", func() {
|
||||||
It("fails to list the boot entries when there is no grub files", func() {
|
It("fails to list the boot entries when there is no grub files", func() {
|
||||||
|
@ -161,7 +161,7 @@ func (i *InstallAction) Run() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SelectBootEntry sets the default boot entry to the selected entry
|
// SelectBootEntry sets the default boot entry to the selected entry
|
||||||
err = action.SelectBootEntry(i.cfg, "active")
|
err = action.SelectBootEntry(i.cfg, "cos")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
i.cfg.Logger.Warnf("selecting active boot entry: %s", err.Error())
|
i.cfg.Logger.Warnf("selecting active boot entry: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ func (r *ResetAction) Run() (err error) {
|
|||||||
return fmt.Errorf("copying recovery to active: %w", err)
|
return fmt.Errorf("copying recovery to active: %w", err)
|
||||||
}
|
}
|
||||||
// SelectBootEntry sets the default boot entry to the selected entry
|
// SelectBootEntry sets the default boot entry to the selected entry
|
||||||
err = action.SelectBootEntry(r.cfg, "active")
|
err = action.SelectBootEntry(r.cfg, "cos")
|
||||||
// Should we fail? Or warn?
|
// Should we fail? Or warn?
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.cfg.Logger.Errorf("selecting boot entry : %s", err.Error())
|
r.cfg.Logger.Errorf("selecting boot entry : %s", err.Error())
|
||||||
|
@ -90,7 +90,7 @@ func (i *UpgradeAction) Run() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SelectBootEntry sets the default boot entry to the selected entry
|
// SelectBootEntry sets the default boot entry to the selected entry
|
||||||
err = action.SelectBootEntry(i.cfg, "active")
|
err = action.SelectBootEntry(i.cfg, "cos")
|
||||||
// Should we fail? Or warn?
|
// Should we fail? Or warn?
|
||||||
if err != nil {
|
if err != nil {
|
||||||
i.cfg.Logger.Errorf("selecting boot entry: %s", err.Error())
|
i.cfg.Logger.Errorf("selecting boot entry: %s", err.Error())
|
||||||
|
Loading…
Reference in New Issue
Block a user