propellor/src/Propellor/Property/Chroot.hs

161 lines
5.0 KiB
Haskell
Raw Normal View History

module Propellor.Property.Chroot (
2014-11-20 21:18:26 +00:00
Chroot(..),
2014-11-21 19:55:27 +00:00
debootstrapped,
provisioned,
-- * Internal use
provisioned',
propigateChrootInfo,
propellChroot,
2014-11-20 19:15:28 +00:00
chain,
) where
import Propellor
2014-11-21 22:55:33 +00:00
import Propellor.Types.Chroot
2014-11-23 02:37:25 +00:00
import Propellor.Property.Chroot.Util
import qualified Propellor.Property.Debootstrap as Debootstrap
2014-11-21 21:11:26 +00:00
import qualified Propellor.Property.Systemd.Core as Systemd
2014-11-20 19:15:28 +00:00
import qualified Propellor.Shim as Shim
import Utility.SafeCommand
import qualified Data.Map as M
2014-11-20 19:15:28 +00:00
import Data.List.Utils
import System.Posix.Directory
2014-11-21 19:55:27 +00:00
data Chroot = Chroot FilePath System BuilderConf Host
deriving (Show)
data BuilderConf
= UsingDeboostrap Debootstrap.DebootstrapConfig
deriving (Show)
instance Hostlike Chroot where
2014-11-21 19:55:27 +00:00
(Chroot l s c h) & p = Chroot l s c (h & p)
(Chroot l s c h) &^ p = Chroot l s c (h &^ p)
getHost (Chroot _ _ _ h) = h
2014-11-21 19:55:27 +00:00
-- | Defines a Chroot at the given location, built with debootstrap.
--
2014-11-21 19:55:27 +00:00
-- Properties can be added to configure the Chroot.
--
-- > debootstrapped (System (Debian Unstable) "amd64") Debootstrap.BuildD "/srv/chroot/ghc-dev"
-- > & Apt.installed ["ghc", "haskell-platform"]
-- > & ...
2014-11-21 19:55:27 +00:00
debootstrapped :: System -> Debootstrap.DebootstrapConfig -> FilePath -> Chroot
debootstrapped system conf location = case system of
(System (Debian _) _) -> mk
(System (Ubuntu _) _) -> mk
where
h = Host location [] mempty
mk = Chroot location system (UsingDeboostrap conf) h
& os system
-- | Ensures that the chroot exists and is provisioned according to its
-- properties.
--
-- Reverting this property removes the chroot. Note that it does not ensure
-- that any processes that might be running inside the chroot are stopped.
provisioned :: Chroot -> RevertableProperty
2014-11-21 21:11:26 +00:00
provisioned c = provisioned' (propigateChrootInfo c) c False
2014-11-21 21:11:26 +00:00
provisioned' :: (Property -> Property) -> Chroot -> Bool -> RevertableProperty
provisioned' propigator c@(Chroot loc system builderconf _) systemdonly = RevertableProperty
(propigator $ go "exists" setup)
(go "removed" teardown)
where
2014-11-20 19:15:28 +00:00
go desc a = property (chrootDesc c desc) $ ensureProperties [a]
2014-11-21 21:11:26 +00:00
setup = propellChroot c (inChrootProcess c) systemdonly
`requires` toProp built
2014-11-21 19:55:27 +00:00
built = case (system, builderconf) of
((System (Debian _) _), UsingDeboostrap cf) -> debootstrap cf
((System (Ubuntu _) _), UsingDeboostrap cf) -> debootstrap cf
2014-11-21 19:55:27 +00:00
debootstrap = Debootstrap.built loc system
teardown = toProp (revert built)
propigateChrootInfo :: Chroot -> Property -> Property
2014-11-20 20:04:48 +00:00
propigateChrootInfo c p = propigateInfo c p (<> chrootInfo c)
chrootInfo :: Chroot -> Info
2014-11-21 19:55:27 +00:00
chrootInfo (Chroot loc _ _ h) =
2014-11-20 20:04:48 +00:00
mempty { _chrootinfo = mempty { _chroots = M.singleton loc h } }
2014-11-20 19:15:28 +00:00
-- | Propellor is run inside the chroot to provision it.
2014-11-21 21:11:26 +00:00
propellChroot :: Chroot -> ([String] -> CreateProcess) -> Bool -> Property
propellChroot c@(Chroot loc _ _ _) mkproc systemdonly = property (chrootDesc c "provisioned") $ do
2014-11-20 19:15:28 +00:00
let d = localdir </> shimdir c
let me = localdir </> "propellor"
shim <- liftIO $ ifM (doesDirectoryExist d)
( pure (Shim.file me d)
, Shim.setup me Nothing d
2014-11-20 19:15:28 +00:00
)
ifM (liftIO $ bindmount shim)
( chainprovision shim
, return FailedChange
)
where
bindmount shim = ifM (doesFileExist (loc ++ shim))
( return True
, do
let mntpnt = loc ++ localdir
createDirectoryIfMissing True mntpnt
boolSystem "mount"
[ Param "--bind"
, File localdir, File mntpnt
]
)
chainprovision shim = do
parenthost <- asks hostName
2014-11-21 21:11:26 +00:00
cmd <- liftIO $ toChain parenthost c systemdonly
2014-11-23 02:37:25 +00:00
pe <- liftIO standardPathEnv
let p = mkproc
2014-11-20 19:15:28 +00:00
[ shim
, "--continue"
, show cmd
2014-11-20 19:15:28 +00:00
]
2014-11-23 02:37:25 +00:00
let p' = p { env = Just pe }
liftIO $ withHandle StdoutHandle createProcessSuccess p'
2014-11-20 19:15:28 +00:00
processChainOutput
2014-11-21 21:11:26 +00:00
toChain :: HostName -> Chroot -> Bool -> IO CmdLine
toChain parenthost (Chroot loc _ _ _) systemdonly = do
onconsole <- isConsole <$> mkMessageHandle
2014-11-21 21:11:26 +00:00
return $ ChrootChain parenthost loc systemdonly onconsole
chain :: [Host] -> CmdLine -> IO ()
chain hostlist (ChrootChain hn loc systemdonly onconsole) =
case findHostNoAlias hostlist hn of
Nothing -> errorMessage ("cannot find host " ++ hn)
Just parenthost -> case M.lookup loc (_chroots $ _chrootinfo $ hostInfo parenthost) of
Nothing -> errorMessage ("cannot find chroot " ++ loc ++ " on host " ++ hn)
Just h -> go h
2014-11-20 19:15:28 +00:00
where
go h = do
changeWorkingDirectory localdir
when onconsole forceConsole
2014-11-20 19:15:28 +00:00
onlyProcess (provisioningLock loc) $ do
2014-11-21 21:11:26 +00:00
r <- runPropellor h $ ensureProperties $
if systemdonly
then [Systemd.installed]
else hostProperties h
2014-11-20 19:15:28 +00:00
putStrLn $ "\n" ++ show r
2014-11-21 21:11:26 +00:00
chain _ _ = errorMessage "bad chain command"
2014-11-20 19:15:28 +00:00
inChrootProcess :: Chroot -> [String] -> CreateProcess
2014-11-21 19:55:27 +00:00
inChrootProcess (Chroot loc _ _ _) cmd = proc "chroot" (loc:cmd)
2014-11-20 19:15:28 +00:00
provisioningLock :: FilePath -> FilePath
provisioningLock containerloc = "chroot" </> mungeloc containerloc ++ ".lock"
shimdir :: Chroot -> FilePath
2014-11-21 19:55:27 +00:00
shimdir (Chroot loc _ _ _) = "chroot" </> mungeloc loc ++ ".shim"
2014-11-20 19:15:28 +00:00
mungeloc :: FilePath -> String
mungeloc = replace "/" "_"
chrootDesc :: Chroot -> String -> String
2014-11-21 19:55:27 +00:00
chrootDesc (Chroot loc _ _ _) desc = "chroot " ++ loc ++ " " ++ desc