2014-11-17 20:42:15 +00:00
module Propellor.Property.HostingProvider.DigitalOcean (
distroKernel
) where
2014-05-23 16:30:25 +00:00
import Propellor
import qualified Propellor.Property.Apt as Apt
import qualified Propellor.Property.File as File
2014-12-06 17:32:53 +00:00
import qualified Propellor.Property.Reboot as Reboot
2014-05-23 16:30:25 +00:00
2014-11-17 20:42:15 +00:00
import Data.List
2014-05-23 16:30:25 +00:00
-- 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.
--
2014-11-17 20:42:15 +00:00
-- 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.
2015-01-25 02:38:10 +00:00
distroKernel :: Property NoInfo
2014-05-23 16:30:25 +00:00
distroKernel = propertyList " digital ocean distro kernel hack "
2014-11-17 20:42:15 +00:00
[ Apt . installed [ " grub-pc " , " kexec-tools " , " file " ]
2014-05-23 16:30:25 +00:00
, " /etc/default/kexec " ` File . containsLines `
[ " LOAD_KEXEC=true "
, " USE_GRUB_CONFIG=true "
2014-05-23 16:31:42 +00:00
] ` describe ` " kexec configured "
2014-12-06 17:32:53 +00:00
, check ( not <$> runningInstalledKernel ) Reboot . now
` describe ` " running installed kernel "
2014-05-23 16:30:25 +00:00
]
2014-11-17 20:42:15 +00:00
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