diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Propellor/Property/HostingProvider/DigitalOcean.hs | 39 |
1 files changed, 34 insertions, 5 deletions
diff --git a/src/Propellor/Property/HostingProvider/DigitalOcean.hs b/src/Propellor/Property/HostingProvider/DigitalOcean.hs index 4565935f..32165d48 100644 --- a/src/Propellor/Property/HostingProvider/DigitalOcean.hs +++ b/src/Propellor/Property/HostingProvider/DigitalOcean.hs @@ -1,21 +1,50 @@ -module Propellor.Property.HostingProvider.DigitalOcean where +module Propellor.Property.HostingProvider.DigitalOcean ( + distroKernel +) where import Propellor import qualified Propellor.Property.Apt as Apt import qualified Propellor.Property.File as File +import Data.List + -- Digital Ocean does not provide any way to boot -- the kernel provided by the distribution, except using kexec. -- Without this, some old, and perhaps insecure kernel will be used. -- --- Note that this only causes the new kernel to be loaded on reboot. --- If the power is cycled, the old kernel still boots up. --- TODO: detect this and reboot immediately? +-- This property causes the distro kernel to be loaded on reboot, using kexec. +-- +-- 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 = propertyList "digital ocean distro kernel hack" - [ Apt.installed ["grub-pc", "kexec-tools"] + [ Apt.installed ["grub-pc", "kexec-tools", "file"] , "/etc/default/kexec" `File.containsLines` [ "LOAD_KEXEC=true" , "USE_GRUB_CONFIG=true" ] `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 |
