diff --git a/pkg/action/install.go b/pkg/action/install.go index f0f960a..1839ac0 100644 --- a/pkg/action/install.go +++ b/pkg/action/install.go @@ -189,6 +189,11 @@ func (i InstallAction) Run() (err error) { return err } + // Check if we should fail the installation by checking the sentinel file FailInstallationFileSentinel + if toFail, err := utils.CheckFailedInstallation(cnst.FailInstallationFileSentinel); toFail { + return err + } + // Deploy active image systemMeta, err := e.DeployImage(&i.spec.Active, true) if err != nil { diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index 3bf611c..fd57ca1 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -23,70 +23,71 @@ import ( ) const ( - GrubConf = "/etc/cos/grub.cfg" - GrubOEMEnv = "grub_oem_env" - GrubDefEntry = "Kairos" - DefaultTty = "tty1" - BiosPartName = "bios" - EfiLabel = "COS_GRUB" - EfiPartName = "efi" - ActiveLabel = "COS_ACTIVE" - PassiveLabel = "COS_PASSIVE" - SystemLabel = "COS_SYSTEM" - RecoveryLabel = "COS_RECOVERY" - RecoveryPartName = "recovery" - StateLabel = "COS_STATE" - StatePartName = "state" - InstallStateFile = "state.yaml" - PersistentLabel = "COS_PERSISTENT" - PersistentPartName = "persistent" - OEMLabel = "COS_OEM" - OEMPartName = "oem" - MountBinary = "/usr/bin/mount" - EfiDevice = "/sys/firmware/efi" - LinuxFs = "ext4" - LinuxImgFs = "ext2" - SquashFs = "squashfs" - EfiFs = "vfat" - EfiSize = uint(64) - OEMSize = uint(64) - PersistentSize = uint(0) - BiosSize = uint(1) - ImgSize = uint(3072) - HTTPTimeout = 60 - LiveDir = "/run/initramfs/live" - RecoveryDir = "/run/cos/recovery" - StateDir = "/run/cos/state" - OEMDir = "/run/cos/oem" - PersistentDir = "/run/cos/persistent" - ActiveDir = "/run/cos/active" - TransitionDir = "/run/cos/transition" - EfiDir = "/run/cos/efi" - RecoverySquashFile = "recovery.squashfs" - IsoRootFile = "rootfs.squashfs" - ActiveImgFile = "active.img" - PassiveImgFile = "passive.img" - RecoveryImgFile = "recovery.img" - IsoBaseTree = "/run/rootfsbase" - AfterInstallChrootHook = "after-install-chroot" - AfterInstallHook = "after-install" - BeforeInstallHook = "before-install" - AfterResetChrootHook = "after-reset-chroot" - AfterResetHook = "after-reset" - BeforeResetHook = "before-reset" - AfterUpgradeChrootHook = "after-upgrade-chroot" - AfterUpgradeHook = "after-upgrade" - BeforeUpgradeHook = "before-upgrade" - TransitionImgFile = "transition.img" - RunningStateDir = "/run/initramfs/cos-state" // TODO: converge this constant with StateDir/RecoveryDir in dracut module from cos-toolkit - RunningRecoveryStateDir = "/run/initramfs/isoscan" // TODO: converge this constant with StateDir/RecoveryDir in dracut module from cos-toolkit - ActiveImgName = "active" - PassiveImgName = "passive" - RecoveryImgName = "recovery" - StateResetImgName = "statereset" - GPT = "gpt" - UsrLocalPath = "/usr/local" - OEMPath = "/oem" + GrubConf = "/etc/cos/grub.cfg" + GrubOEMEnv = "grub_oem_env" + GrubDefEntry = "Kairos" + DefaultTty = "tty1" + BiosPartName = "bios" + EfiLabel = "COS_GRUB" + EfiPartName = "efi" + ActiveLabel = "COS_ACTIVE" + PassiveLabel = "COS_PASSIVE" + SystemLabel = "COS_SYSTEM" + RecoveryLabel = "COS_RECOVERY" + RecoveryPartName = "recovery" + StateLabel = "COS_STATE" + StatePartName = "state" + InstallStateFile = "state.yaml" + PersistentLabel = "COS_PERSISTENT" + PersistentPartName = "persistent" + OEMLabel = "COS_OEM" + OEMPartName = "oem" + MountBinary = "/usr/bin/mount" + EfiDevice = "/sys/firmware/efi" + LinuxFs = "ext4" + LinuxImgFs = "ext2" + SquashFs = "squashfs" + EfiFs = "vfat" + EfiSize = uint(64) + OEMSize = uint(64) + PersistentSize = uint(0) + BiosSize = uint(1) + ImgSize = uint(3072) + HTTPTimeout = 60 + LiveDir = "/run/initramfs/live" + RecoveryDir = "/run/cos/recovery" + StateDir = "/run/cos/state" + OEMDir = "/run/cos/oem" + PersistentDir = "/run/cos/persistent" + ActiveDir = "/run/cos/active" + TransitionDir = "/run/cos/transition" + EfiDir = "/run/cos/efi" + RecoverySquashFile = "recovery.squashfs" + IsoRootFile = "rootfs.squashfs" + ActiveImgFile = "active.img" + PassiveImgFile = "passive.img" + RecoveryImgFile = "recovery.img" + IsoBaseTree = "/run/rootfsbase" + AfterInstallChrootHook = "after-install-chroot" + AfterInstallHook = "after-install" + BeforeInstallHook = "before-install" + AfterResetChrootHook = "after-reset-chroot" + AfterResetHook = "after-reset" + BeforeResetHook = "before-reset" + AfterUpgradeChrootHook = "after-upgrade-chroot" + AfterUpgradeHook = "after-upgrade" + BeforeUpgradeHook = "before-upgrade" + TransitionImgFile = "transition.img" + RunningStateDir = "/run/initramfs/cos-state" // TODO: converge this constant with StateDir/RecoveryDir in dracut module from cos-toolkit + RunningRecoveryStateDir = "/run/initramfs/isoscan" // TODO: converge this constant with StateDir/RecoveryDir in dracut module from cos-toolkit + FailInstallationFileSentinel = "/run/cos/fail_installation" + ActiveImgName = "active" + PassiveImgName = "passive" + RecoveryImgName = "recovery" + StateResetImgName = "statereset" + GPT = "gpt" + UsrLocalPath = "/usr/local" + OEMPath = "/oem" // SELinux targeted policy paths SELinuxTargetedPath = "/etc/selinux/targeted" diff --git a/pkg/uki/install.go b/pkg/uki/install.go index c245da0..2198a3c 100644 --- a/pkg/uki/install.go +++ b/pkg/uki/install.go @@ -84,6 +84,11 @@ func (i *InstallAction) Run() (err error) { return err } + // Check if we should fail the installation by checking the sentinel file FailInstallationFileSentinel + if toFail, err := utils.CheckFailedInstallation(constants.FailInstallationFileSentinel); toFail { + return err + } + // Store cloud-config in TPM or copy it to COS_OEM? // Copy cloud-init if any err = e.CopyCloudConfig(i.spec.CloudInit) diff --git a/pkg/utils/common.go b/pkg/utils/common.go index dbf8932..9ccb95d 100644 --- a/pkg/utils/common.go +++ b/pkg/utils/common.go @@ -609,3 +609,15 @@ func SystemdBootConfWriter(fs v1.FS, filePath string, conf map[string]string) er return writer.Flush() } + +// CheckFailedInstallation checks if the state file if present, and if it is, it will return true and the error with the file content indicating why we should abort the installation +func CheckFailedInstallation(stateFile string) (bool, error) { + if _, err := os.Stat(stateFile); err == nil { + content, err := os.ReadFile(stateFile) + if err != nil { + return true, err + } + return true, fmt.Errorf("Installation failed: %s", string(content)) + } + return false, nil +}