systemd container may be mostly done (untested)
This commit is contained in:
parent
1af298dc10
commit
6a5a1bc761
|
@ -25,6 +25,7 @@ import qualified Propellor.Property.Grub as Grub
|
||||||
import qualified Propellor.Property.Obnam as Obnam
|
import qualified Propellor.Property.Obnam as Obnam
|
||||||
import qualified Propellor.Property.Gpg as Gpg
|
import qualified Propellor.Property.Gpg as Gpg
|
||||||
import qualified Propellor.Property.Chroot as Chroot
|
import qualified Propellor.Property.Chroot as Chroot
|
||||||
|
import qualified Propellor.Property.Systemd as Systemd
|
||||||
import qualified Propellor.Property.HostingProvider.DigitalOcean as DigitalOcean
|
import qualified Propellor.Property.HostingProvider.DigitalOcean as DigitalOcean
|
||||||
import qualified Propellor.Property.HostingProvider.CloudAtCost as CloudAtCost
|
import qualified Propellor.Property.HostingProvider.CloudAtCost as CloudAtCost
|
||||||
import qualified Propellor.Property.HostingProvider.Linode as Linode
|
import qualified Propellor.Property.HostingProvider.Linode as Linode
|
||||||
|
@ -80,7 +81,13 @@ clam = standardSystem "clam.kitenet.net" Unstable "amd64"
|
||||||
! Ssh.listenPort 80
|
! Ssh.listenPort 80
|
||||||
! Ssh.listenPort 443
|
! Ssh.listenPort 443
|
||||||
|
|
||||||
& Chroot.provisioned testChroot
|
! Chroot.provisioned testChroot
|
||||||
|
& Systemd.persistentJournal
|
||||||
|
& Systemd.nspawned meow
|
||||||
|
|
||||||
|
meow :: Systemd.Container
|
||||||
|
meow = Systemd.container "meow" (System (Debian Unstable) "amd64") []
|
||||||
|
& Apt.serviceInstalledRunning ["fingerd"]
|
||||||
|
|
||||||
testChroot :: Chroot.Chroot
|
testChroot :: Chroot.Chroot
|
||||||
testChroot = Chroot.chroot "/tmp/chroot" (System (Debian Unstable) "amd64")
|
testChroot = Chroot.chroot "/tmp/chroot" (System (Debian Unstable) "amd64")
|
||||||
|
|
|
@ -2,6 +2,8 @@ module Propellor.Property.Chroot (
|
||||||
Chroot(..),
|
Chroot(..),
|
||||||
chroot,
|
chroot,
|
||||||
provisioned,
|
provisioned,
|
||||||
|
-- * Internal use
|
||||||
|
propellChroot,
|
||||||
chain,
|
chain,
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
@ -42,7 +44,7 @@ provisioned c@(Chroot loc system _) = RevertableProperty
|
||||||
where
|
where
|
||||||
go desc a = property (chrootDesc c desc) $ ensureProperties [a]
|
go desc a = property (chrootDesc c desc) $ ensureProperties [a]
|
||||||
|
|
||||||
setup = provisionChroot c `requires` toProp built
|
setup = propellChroot c (inChrootProcess c) `requires` toProp built
|
||||||
|
|
||||||
built = case system of
|
built = case system of
|
||||||
(System (Debian _) _) -> debootstrap
|
(System (Debian _) _) -> debootstrap
|
||||||
|
@ -60,11 +62,8 @@ chrootInfo (Chroot loc _ h) =
|
||||||
mempty { _chrootinfo = mempty { _chroots = M.singleton loc h } }
|
mempty { _chrootinfo = mempty { _chroots = M.singleton loc h } }
|
||||||
|
|
||||||
-- | Propellor is run inside the chroot to provision it.
|
-- | Propellor is run inside the chroot to provision it.
|
||||||
--
|
propellChroot :: Chroot -> ([String] -> CreateProcess) -> Property
|
||||||
-- Strange and wonderful tricks let the host's /usr/local/propellor
|
propellChroot c@(Chroot loc _ _) mkproc = property (chrootDesc c "provisioned") $ do
|
||||||
-- be used inside the chroot, without needing to install anything.
|
|
||||||
provisionChroot :: Chroot -> Property
|
|
||||||
provisionChroot c@(Chroot loc _ _) = property (chrootDesc c "provisioned") $ do
|
|
||||||
let d = localdir </> shimdir c
|
let d = localdir </> shimdir c
|
||||||
let me = localdir </> "propellor"
|
let me = localdir </> "propellor"
|
||||||
shim <- liftIO $ ifM (doesDirectoryExist d)
|
shim <- liftIO $ ifM (doesDirectoryExist d)
|
||||||
|
@ -90,7 +89,7 @@ provisionChroot c@(Chroot loc _ _) = property (chrootDesc c "provisioned") $ do
|
||||||
chainprovision shim = do
|
chainprovision shim = do
|
||||||
parenthost <- asks hostName
|
parenthost <- asks hostName
|
||||||
cmd <- liftIO $ toChain parenthost c
|
cmd <- liftIO $ toChain parenthost c
|
||||||
let p = inChrootProcess c
|
let p = mkproc
|
||||||
[ shim
|
[ shim
|
||||||
, "--continue"
|
, "--continue"
|
||||||
, show cmd
|
, show cmd
|
||||||
|
|
|
@ -8,7 +8,9 @@ module Propellor.Property.Systemd (
|
||||||
import Propellor
|
import Propellor
|
||||||
import qualified Propellor.Property.Chroot as Chroot
|
import qualified Propellor.Property.Chroot as Chroot
|
||||||
import qualified Propellor.Property.Apt as Apt
|
import qualified Propellor.Property.Apt as Apt
|
||||||
|
import qualified Propellor.Property.File as File
|
||||||
import Utility.SafeCommand
|
import Utility.SafeCommand
|
||||||
|
import Utility.FileMode
|
||||||
|
|
||||||
import Data.List.Utils
|
import Data.List.Utils
|
||||||
|
|
||||||
|
@ -29,7 +31,7 @@ instance Hostlike Container where
|
||||||
installed :: Property
|
installed :: Property
|
||||||
installed = Apt.installed ["systemd", "dbus"]
|
installed = Apt.installed ["systemd", "dbus"]
|
||||||
|
|
||||||
-- | Sets up persistent storage of the journal.
|
-- | Enables persistent storage of the journal.
|
||||||
persistentJournal :: Property
|
persistentJournal :: Property
|
||||||
persistentJournal = check (not <$> doesDirectoryExist dir) $
|
persistentJournal = check (not <$> doesDirectoryExist dir) $
|
||||||
combineProperties "persistent systetemd journal"
|
combineProperties "persistent systetemd journal"
|
||||||
|
@ -64,21 +66,29 @@ container name system ps = Container name system ps (Host name [] mempty)
|
||||||
nspawned :: Container -> RevertableProperty
|
nspawned :: Container -> RevertableProperty
|
||||||
nspawned c@(Container name system _ h) = RevertableProperty setup teardown
|
nspawned c@(Container name system _ h) = RevertableProperty setup teardown
|
||||||
where
|
where
|
||||||
-- TODO after container is running, use nsenter to enter it
|
setup = containerprovisioned
|
||||||
-- and run propellor to finish provisioning.
|
`requires` toProp (nspawnService c)
|
||||||
setup = toProp (nspawnService c)
|
|
||||||
`requires` toProp chrootprovisioned
|
`requires` toProp chrootprovisioned
|
||||||
|
`requires` toProp (enterScript c)
|
||||||
|
|
||||||
teardown = toProp (revert (chrootprovisioned))
|
teardown = toProp (revert (chrootprovisioned))
|
||||||
`requires` toProp (revert (nspawnService c))
|
`requires` toProp (revert (nspawnService c))
|
||||||
|
`requires` toProp (revert (enterScript c))
|
||||||
|
|
||||||
-- When provisioning the chroot, pass a version of the Host
|
-- When provisioning the chroot, pass a version of the Host
|
||||||
-- that only has the Property of systemd being installed.
|
-- that only has the Property of systemd being installed.
|
||||||
-- This is to avoid starting any daemons in the chroot,
|
-- This is to avoid starting any daemons in the chroot,
|
||||||
-- which would not run in the container's namespace.
|
-- which would not run in the container's namespace.
|
||||||
chrootprovisioned = Chroot.provisioned $
|
chrootprovisioned = Chroot.provisioned $
|
||||||
Chroot.Chroot (containerDir name) system $
|
mkChroot $ h { hostProperties = [installed] }
|
||||||
h { hostProperties = [installed] }
|
|
||||||
|
-- Use nsenter to enter container and and run propellor to
|
||||||
|
-- finish provisioning.
|
||||||
|
containerprovisioned = Chroot.propellChroot
|
||||||
|
(mkChroot h)
|
||||||
|
(enterContainerProcess c)
|
||||||
|
|
||||||
|
mkChroot = Chroot.Chroot (containerDir name) system
|
||||||
|
|
||||||
nspawnService :: Container -> RevertableProperty
|
nspawnService :: Container -> RevertableProperty
|
||||||
nspawnService (Container name _ ps _) = RevertableProperty setup teardown
|
nspawnService (Container name _ ps _) = RevertableProperty setup teardown
|
||||||
|
@ -91,13 +101,45 @@ nspawnService (Container name _ ps _) = RevertableProperty setup teardown
|
||||||
[ cmdProperty "systemctl" ["enable", service]
|
[ cmdProperty "systemctl" ["enable", service]
|
||||||
, cmdProperty "systemctl" ["start", service]
|
, cmdProperty "systemctl" ["start", service]
|
||||||
]
|
]
|
||||||
|
-- TODO ^ adjust execStart line to reflect ps
|
||||||
-- TODO adjust execStart line to reflect ps
|
|
||||||
|
|
||||||
teardown = undefined
|
teardown = undefined
|
||||||
|
|
||||||
|
-- | Installs a "enter-machinename" script that root can use to run a
|
||||||
|
-- command inside the container.
|
||||||
|
--
|
||||||
|
-- This uses nsenter to enter the container, by looking up the pid of the
|
||||||
|
-- container's init process and using its namespace.
|
||||||
|
enterScript :: Container -> RevertableProperty
|
||||||
|
enterScript c@(Container name _ _ _) = RevertableProperty setup teardown
|
||||||
|
where
|
||||||
|
setup = combineProperties ("generated " ++ enterScriptFile c)
|
||||||
|
[ scriptfile `File.hasContent`
|
||||||
|
[ "#!/bin/sh"
|
||||||
|
, "# Generated by propellor"
|
||||||
|
, "pid=\"$(machinectl show " ++ shellEscape name ++ " -p Leader | cut -d= -f2)\" || true"
|
||||||
|
, "if [ -n \"$pid\" ]; then"
|
||||||
|
, "\tnsenter -p -u -n -i -m -t \"$pid\""
|
||||||
|
, "else"
|
||||||
|
, "\texit 1"
|
||||||
|
, "fi"
|
||||||
|
]
|
||||||
|
, scriptfile `File.mode` combineModes (readModes ++ executeModes)
|
||||||
|
]
|
||||||
|
teardown = File.notPresent scriptfile
|
||||||
|
scriptfile = enterScriptFile c
|
||||||
|
|
||||||
|
enterScriptFile :: Container -> FilePath
|
||||||
|
enterScriptFile (Container name _ _ _ ) = "enter-" ++ mungename name
|
||||||
|
|
||||||
|
enterContainerProcess :: Container -> [String] -> CreateProcess
|
||||||
|
enterContainerProcess = proc . enterScriptFile
|
||||||
|
|
||||||
nspawnServiceName :: MachineName -> String
|
nspawnServiceName :: MachineName -> String
|
||||||
nspawnServiceName name = "systemd-nspawn@" ++ name ++ ".service"
|
nspawnServiceName name = "systemd-nspawn@" ++ name ++ ".service"
|
||||||
|
|
||||||
containerDir :: MachineName -> FilePath
|
containerDir :: MachineName -> FilePath
|
||||||
containerDir name = "/var/lib/container" ++ replace "/" "_" name
|
containerDir name = "/var/lib/container" ++ mungename name
|
||||||
|
|
||||||
|
mungename :: MachineName -> String
|
||||||
|
mungename = replace "/" "_"
|
||||||
|
|
Loading…
Reference in New Issue