mirror of
https://github.com/kairos-io/kairos-agent.git
synced 2025-08-07 11:23:28 +00:00
Track active/passive boot for upgrade workflow (#133)
* Track active/passive boot for upgrade workflow Track what are we booting from during upgrade in order to not backup active into passive if we are booting from passive. If we are booting from active or recovery the workflow keeps as it was, backup active into passive, and then move the transition image into active. Signed-off-by: Itxaka <itxaka@kairos.io>
This commit is contained in:
parent
ca4cf5059d
commit
442973526e
2
go.mod
2
go.mod
@ -12,7 +12,7 @@ require (
|
|||||||
github.com/hashicorp/go-multierror v1.1.1
|
github.com/hashicorp/go-multierror v1.1.1
|
||||||
github.com/jaypipes/ghw v0.12.0
|
github.com/jaypipes/ghw v0.12.0
|
||||||
github.com/joho/godotenv v1.5.1
|
github.com/joho/godotenv v1.5.1
|
||||||
github.com/kairos-io/kairos-sdk v0.0.13
|
github.com/kairos-io/kairos-sdk v0.0.14
|
||||||
github.com/labstack/echo/v4 v4.11.1
|
github.com/labstack/echo/v4 v4.11.1
|
||||||
github.com/mitchellh/mapstructure v1.5.0
|
github.com/mitchellh/mapstructure v1.5.0
|
||||||
github.com/mudler/go-nodepair v0.0.0-20221223092639-ba399a66fdfb
|
github.com/mudler/go-nodepair v0.0.0-20221223092639-ba399a66fdfb
|
||||||
|
2
go.sum
2
go.sum
@ -358,6 +358,8 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
|
|||||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
github.com/kairos-io/kairos-sdk v0.0.13 h1:YI+ETmlk86+mHTQYBNPmVTiO2Ux63HmkRzxhAJRr9JI=
|
github.com/kairos-io/kairos-sdk v0.0.13 h1:YI+ETmlk86+mHTQYBNPmVTiO2Ux63HmkRzxhAJRr9JI=
|
||||||
github.com/kairos-io/kairos-sdk v0.0.13/go.mod h1:+fhVoCEA2hD7OFTmhDmy4pP3uC9q84OYhDa7irkEVWQ=
|
github.com/kairos-io/kairos-sdk v0.0.13/go.mod h1:+fhVoCEA2hD7OFTmhDmy4pP3uC9q84OYhDa7irkEVWQ=
|
||||||
|
github.com/kairos-io/kairos-sdk v0.0.14 h1:yVKaay70cjmAUY6m4uLoV9UguBv3Dx3JxAh2faRlUZo=
|
||||||
|
github.com/kairos-io/kairos-sdk v0.0.14/go.mod h1:+fhVoCEA2hD7OFTmhDmy4pP3uC9q84OYhDa7irkEVWQ=
|
||||||
github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329 h1:qq2nCpSrXrmvDGRxW0ruW9BVEV1CN2a9YDOExdt+U0o=
|
github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329 h1:qq2nCpSrXrmvDGRxW0ruW9BVEV1CN2a9YDOExdt+U0o=
|
||||||
github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329/go.mod h1:2VPVQDR4wO7KXHwP+DAypEy67rXf+okUx2zjgpCxZw4=
|
github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329/go.mod h1:2VPVQDR4wO7KXHwP+DAypEy67rXf+okUx2zjgpCxZw4=
|
||||||
github.com/kendru/darwin/go/depgraph v0.0.0-20221105232959-877d6a81060c h1:eKb4PqwAMhlqwXw0W3atpKaYaPGlXE/Fwh+xpCEYaPk=
|
github.com/kendru/darwin/go/depgraph v0.0.0-20221105232959-877d6a81060c h1:eKb4PqwAMhlqwXw0W3atpKaYaPGlXE/Fwh+xpCEYaPk=
|
||||||
|
@ -18,15 +18,16 @@ package action
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/elemental"
|
"github.com/kairos-io/kairos-agent/v2/pkg/elemental"
|
||||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||||
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||||
|
"github.com/kairos-io/kairos-sdk/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UpgradeAction represents the struct that will run the upgrade from start to finish
|
// UpgradeAction represents the struct that will run the upgrade from start to finish
|
||||||
@ -121,6 +122,16 @@ func (u *UpgradeAction) Run() (err error) {
|
|||||||
var upgradeImg v1.Image
|
var upgradeImg v1.Image
|
||||||
var finalImageFile string
|
var finalImageFile string
|
||||||
|
|
||||||
|
// Track where we booted from to have a different workflow
|
||||||
|
// Booted from active: backup active into passive, upgrade active
|
||||||
|
// Booted from passive: Upgrade active, leave passive as is
|
||||||
|
var bootedFrom state.Boot
|
||||||
|
|
||||||
|
bootedFrom, err = state.DetectBootWithVFS(u.config.Fs)
|
||||||
|
if err != nil {
|
||||||
|
u.config.Logger.Warnf("error detecting boot: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
cleanup := utils.NewCleanStack()
|
cleanup := utils.NewCleanStack()
|
||||||
defer func() { err = cleanup.Cleanup(err) }()
|
defer func() { err = cleanup.Cleanup(err) }()
|
||||||
|
|
||||||
@ -230,9 +241,10 @@ func (u *UpgradeAction) Run() (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not upgrading recovery, backup active into passive
|
// If not upgrading recovery and booting from non passive, backup active into passive
|
||||||
if !u.spec.RecoveryUpgrade {
|
// We dont want to overwrite passive if we are booting from passive as it could mean that active is broken and we would
|
||||||
//TODO this step could be part of elemental package
|
// be overriding a working passive with a broken/unknown active
|
||||||
|
if u.spec.RecoveryUpgrade == false && bootedFrom != state.Passive {
|
||||||
// backup current active.img to passive.img before overwriting the active.img
|
// backup current active.img to passive.img before overwriting the active.img
|
||||||
u.Info("Backing up current active image")
|
u.Info("Backing up current active image")
|
||||||
source := filepath.Join(u.spec.Partitions.State.MountPoint, "cOS", constants.ActiveImgFile)
|
source := filepath.Join(u.spec.Partitions.State.MountPoint, "cOS", constants.ActiveImgFile)
|
||||||
|
@ -149,6 +149,13 @@ var _ = Describe("Runtime Actions", func() {
|
|||||||
err = fsutils.MkdirAll(config.Fs, filepath.Join(spec.Active.MountPoint, "etc"), constants.DirPerm)
|
err = fsutils.MkdirAll(config.Fs, filepath.Join(spec.Active.MountPoint, "etc"), constants.DirPerm)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
|
err = fsutils.MkdirAll(config.Fs, "/proc", constants.DirPerm)
|
||||||
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Write proc/cmdline so we can detect what we booted from
|
||||||
|
err = fs.WriteFile("/proc/cmdline", []byte(constants.ActiveLabel), constants.FilePerm)
|
||||||
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
err = fs.WriteFile(
|
err = fs.WriteFile(
|
||||||
filepath.Join(spec.Active.MountPoint, "etc", "os-release"),
|
filepath.Join(spec.Active.MountPoint, "etc", "os-release"),
|
||||||
[]byte("GRUB_ENTRY_NAME=TESTOS"),
|
[]byte("GRUB_ENTRY_NAME=TESTOS"),
|
||||||
@ -161,9 +168,6 @@ var _ = Describe("Runtime Actions", func() {
|
|||||||
spec.Recovery.Size = 10
|
spec.Recovery.Size = 10
|
||||||
|
|
||||||
runner.SideEffect = func(command string, args ...string) ([]byte, error) {
|
runner.SideEffect = func(command string, args ...string) ([]byte, error) {
|
||||||
if command == "cat" && args[0] == "/proc/cmdline" {
|
|
||||||
return []byte(constants.ActiveLabel), nil
|
|
||||||
}
|
|
||||||
if command == "mv" && args[0] == "-f" && args[1] == activeImg && args[2] == passiveImg {
|
if command == "mv" && args[0] == "-f" && args[1] == activeImg && args[2] == passiveImg {
|
||||||
// we doing backup, do the "move"
|
// we doing backup, do the "move"
|
||||||
source, _ := fs.ReadFile(activeImg)
|
source, _ := fs.ReadFile(activeImg)
|
||||||
@ -359,6 +363,13 @@ var _ = Describe("Runtime Actions", func() {
|
|||||||
)
|
)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
|
err = fsutils.MkdirAll(config.Fs, "/proc", constants.DirPerm)
|
||||||
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Write proc/cmdline so we can detect what we booted from
|
||||||
|
err = fs.WriteFile("/proc/cmdline", []byte(constants.PassiveLabel), constants.FilePerm)
|
||||||
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
spec.Active.Size = 10
|
spec.Active.Size = 10
|
||||||
spec.Passive.Size = 10
|
spec.Passive.Size = 10
|
||||||
spec.Recovery.Size = 10
|
spec.Recovery.Size = 10
|
||||||
@ -373,6 +384,10 @@ var _ = Describe("Runtime Actions", func() {
|
|||||||
_ = fs.WriteFile(activeImg, source, constants.FilePerm)
|
_ = fs.WriteFile(activeImg, source, constants.FilePerm)
|
||||||
_ = fs.RemoveAll(spec.Active.File)
|
_ = fs.RemoveAll(spec.Active.File)
|
||||||
}
|
}
|
||||||
|
if command == "mv" && args[0] == "-f" && args[1] == activeImg && args[2] == passiveImg {
|
||||||
|
// If this command was called then its a complete failure as it tried to copy active into passive
|
||||||
|
StopTrying("Passive was overwritten").Now()
|
||||||
|
}
|
||||||
return []byte{}, nil
|
return []byte{}, nil
|
||||||
}
|
}
|
||||||
config.Runner = runner
|
config.Runner = runner
|
||||||
@ -436,6 +451,13 @@ var _ = Describe("Runtime Actions", func() {
|
|||||||
|
|
||||||
spec.RecoveryUpgrade = true
|
spec.RecoveryUpgrade = true
|
||||||
|
|
||||||
|
err = fsutils.MkdirAll(config.Fs, "/proc", constants.DirPerm)
|
||||||
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Write proc/cmdline so we can detect what we booted from
|
||||||
|
err = fs.WriteFile("/proc/cmdline", []byte(constants.RecoveryLabel), constants.FilePerm)
|
||||||
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
runner.SideEffect = func(command string, args ...string) ([]byte, error) {
|
runner.SideEffect = func(command string, args ...string) ([]byte, error) {
|
||||||
if command == "cat" && args[0] == "/proc/cmdline" {
|
if command == "cat" && args[0] == "/proc/cmdline" {
|
||||||
return []byte(constants.RecoveryLabel), nil
|
return []byte(constants.RecoveryLabel), nil
|
||||||
@ -522,6 +544,13 @@ var _ = Describe("Runtime Actions", func() {
|
|||||||
|
|
||||||
spec.RecoveryUpgrade = true
|
spec.RecoveryUpgrade = true
|
||||||
|
|
||||||
|
err = fsutils.MkdirAll(config.Fs, "/proc", constants.DirPerm)
|
||||||
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Write proc/cmdline so we can detect what we booted from
|
||||||
|
err = fs.WriteFile("/proc/cmdline", []byte(constants.RecoveryLabel), constants.FilePerm)
|
||||||
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
runner.SideEffect = func(command string, args ...string) ([]byte, error) {
|
runner.SideEffect = func(command string, args ...string) ([]byte, error) {
|
||||||
if command == "cat" && args[0] == "/proc/cmdline" {
|
if command == "cat" && args[0] == "/proc/cmdline" {
|
||||||
return []byte(constants.RecoveryLabel), nil
|
return []byte(constants.RecoveryLabel), nil
|
||||||
|
Loading…
Reference in New Issue
Block a user