DigitalOcean.distroKernel property now reboots into the distribution kernel when necessary.
It might be better to do this check on boot to limit the time running the DO kernel (which is not well security supported), but that has the possibility of entering a bad reboot loop. Limiting this check to when propellor runs avoids that, while still fixing the problem pretty fast.
This commit is contained in:
parent
8d91b5de6b
commit
46cd2ad0e0
|
@ -5,6 +5,8 @@ propellor (0.9.3) UNRELEASED; urgency=medium
|
||||||
* When multiple gpg keys are added, ensure that the privdata file
|
* When multiple gpg keys are added, ensure that the privdata file
|
||||||
can be decrypted by all of them.
|
can be decrypted by all of them.
|
||||||
* Convert GpgKeyId to newtype.
|
* Convert GpgKeyId to newtype.
|
||||||
|
* DigitalOcean.distroKernel property now reboots into the distribution
|
||||||
|
kernel when necessary.
|
||||||
|
|
||||||
-- Joey Hess <joeyh@debian.org> Mon, 10 Nov 2014 11:15:27 -0400
|
-- Joey Hess <joeyh@debian.org> Mon, 10 Nov 2014 11:15:27 -0400
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,50 @@
|
||||||
module Propellor.Property.HostingProvider.DigitalOcean where
|
module Propellor.Property.HostingProvider.DigitalOcean (
|
||||||
|
distroKernel
|
||||||
|
) where
|
||||||
|
|
||||||
import Propellor
|
import Propellor
|
||||||
import qualified Propellor.Property.Apt as Apt
|
import qualified Propellor.Property.Apt as Apt
|
||||||
import qualified Propellor.Property.File as File
|
import qualified Propellor.Property.File as File
|
||||||
|
|
||||||
|
import Data.List
|
||||||
|
|
||||||
-- Digital Ocean does not provide any way to boot
|
-- Digital Ocean does not provide any way to boot
|
||||||
-- the kernel provided by the distribution, except using kexec.
|
-- the kernel provided by the distribution, except using kexec.
|
||||||
-- Without this, some old, and perhaps insecure kernel will be used.
|
-- Without this, some old, and perhaps insecure kernel will be used.
|
||||||
--
|
--
|
||||||
-- Note that this only causes the new kernel to be loaded on reboot.
|
-- This property causes the distro kernel to be loaded on reboot, using kexec.
|
||||||
-- If the power is cycled, the old kernel still boots up.
|
--
|
||||||
-- TODO: detect this and reboot immediately?
|
-- If the power is cycled, the non-distro kernel still boots up.
|
||||||
|
-- So, this property also checks if the running kernel is present in /boot,
|
||||||
|
-- and if not, reboots immediately into a distro kernel.
|
||||||
distroKernel :: Property
|
distroKernel :: Property
|
||||||
distroKernel = propertyList "digital ocean distro kernel hack"
|
distroKernel = propertyList "digital ocean distro kernel hack"
|
||||||
[ Apt.installed ["grub-pc", "kexec-tools"]
|
[ Apt.installed ["grub-pc", "kexec-tools", "file"]
|
||||||
, "/etc/default/kexec" `File.containsLines`
|
, "/etc/default/kexec" `File.containsLines`
|
||||||
[ "LOAD_KEXEC=true"
|
[ "LOAD_KEXEC=true"
|
||||||
, "USE_GRUB_CONFIG=true"
|
, "USE_GRUB_CONFIG=true"
|
||||||
] `describe` "kexec configured"
|
] `describe` "kexec configured"
|
||||||
|
, check (not <$> runningInstalledKernel)
|
||||||
|
(cmdProperty "reboot" [])
|
||||||
|
`describe` "running installed kernel"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
runningInstalledKernel :: IO Bool
|
||||||
|
runningInstalledKernel = do
|
||||||
|
kernelver <- takeWhile (/= '\n') <$> readProcess "uname" ["-r"]
|
||||||
|
when (null kernelver) $
|
||||||
|
error "failed to read uname -r"
|
||||||
|
kernelimages <- concat <$> mapM kernelsIn ["/", "/boot/"]
|
||||||
|
when (null kernelimages) $
|
||||||
|
error "failed to find any installed kernel images"
|
||||||
|
findVersion kernelver <$>
|
||||||
|
readProcess "file" ("-L" : kernelimages)
|
||||||
|
|
||||||
|
-- File output looks something like this, we want to unambiguously
|
||||||
|
-- match the running kernel version:
|
||||||
|
-- Linux kernel x86 boot executable bzImage, version 3.16-3-amd64 (debian-kernel@lists.debian.org) #1 SMP Debian 3.1, RO-rootFS, swap_dev 0x2, Normal VGA
|
||||||
|
findVersion :: String -> String -> Bool
|
||||||
|
findVersion ver s = (" version " ++ ver ++ " ") `isInfixOf` s
|
||||||
|
|
||||||
|
kernelsIn :: FilePath -> IO [FilePath]
|
||||||
|
kernelsIn d = filter ("vmlinu" `isInfixOf`) <$> dirContents d
|
||||||
|
|
Loading…
Reference in New Issue