summaryrefslogtreecommitdiff
path: root/src/Propellor/Property
diff options
context:
space:
mode:
authorJoey Hess2014-11-20 17:18:26 -0400
committerJoey Hess2014-11-20 17:18:26 -0400
commitf9cc7c149ead60d1178fa3b480282f6089cf79bd (patch)
tree1f9d62d03e0c4a307383bb2420a9ae98ba431947 /src/Propellor/Property
parent3669bd61d0e15682ce25b9a82788b8d69f87d123 (diff)
incomplete systemd container support
Diffstat (limited to 'src/Propellor/Property')
-rw-r--r--src/Propellor/Property/Chroot.hs6
-rw-r--r--src/Propellor/Property/Debootstrap.hs2
-rw-r--r--src/Propellor/Property/Systemd.hs103
3 files changed, 107 insertions, 4 deletions
diff --git a/src/Propellor/Property/Chroot.hs b/src/Propellor/Property/Chroot.hs
index ba7bf96c..798330b0 100644
--- a/src/Propellor/Property/Chroot.hs
+++ b/src/Propellor/Property/Chroot.hs
@@ -1,5 +1,5 @@
module Propellor.Property.Chroot (
- Chroot,
+ Chroot(..),
chroot,
provisioned,
chain,
@@ -24,7 +24,7 @@ instance Hostlike Chroot where
-- | Defines a Chroot at the given location, containing the specified
-- System. Properties can be added to configure the Chroot.
--
--- > chroot "/srv/chroot/ghc-dev" (System (Debian Unstable) "amd64"
+-- > chroot "/srv/chroot/ghc-dev" (System (Debian Unstable) "amd64")
-- > & Apt.installed ["build-essential", "ghc", "haskell-platform"]
-- > & ...
chroot :: FilePath -> System -> Chroot
@@ -48,7 +48,7 @@ provisioned c@(Chroot loc system _) = RevertableProperty
(System (Debian _) _) -> debootstrap
(System (Ubuntu _) _) -> debootstrap
- debootstrap = unrevertable (Debootstrap.built loc system [])
+ debootstrap = toProp (Debootstrap.built loc system [])
teardown = undefined
diff --git a/src/Propellor/Property/Debootstrap.hs b/src/Propellor/Property/Debootstrap.hs
index 4e7bc740..5f521c32 100644
--- a/src/Propellor/Property/Debootstrap.hs
+++ b/src/Propellor/Property/Debootstrap.hs
@@ -33,7 +33,7 @@ built target system@(System _ arch) extraparams =
RevertableProperty setup teardown
where
setup = check (unpopulated target <||> ispartial) setupprop
- `requires` unrevertable installed
+ `requires` toProp installed
teardown = check (not <$> unpopulated target) teardownprop
diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs
new file mode 100644
index 00000000..be08a847
--- /dev/null
+++ b/src/Propellor/Property/Systemd.hs
@@ -0,0 +1,103 @@
+module Propellor.Property.Systemd (
+ installed,
+ persistentJournal,
+ container,
+ nspawned,
+) where
+
+import Propellor
+import qualified Propellor.Property.Chroot as Chroot
+import qualified Propellor.Property.Apt as Apt
+import Utility.SafeCommand
+
+import Data.List.Utils
+
+type MachineName = String
+
+type NspawnParam = CommandParam
+
+data Container = Container MachineName System [CommandParam] Host
+
+instance Hostlike Container where
+ (Container n s ps h) & p = Container n s ps (h & p)
+ (Container n s ps h) &^ p = Container n s ps (h &^ p)
+ getHost (Container _ _ _ h) = h
+
+-- dbus is only a Recommends of systemd, but is needed for communication
+-- from the systemd inside a container to the one outside, so make sure it
+-- gets installed.
+installed :: Property
+installed = Apt.installed ["systemd", "dbus"]
+
+-- | Sets up persistent storage of the journal.
+persistentJournal :: Property
+persistentJournal = check (not <$> doesDirectoryExist dir) $
+ combineProperties "persistent systetemd journal"
+ [ cmdProperty "install" ["-d", "-g", "systemd-journal", dir]
+ , cmdProperty "setfacl" ["-R", "-nm", "g:adm:rx,d:g:adm:rx", dir]
+ ]
+ `requires` Apt.installed ["acl"]
+ where
+ dir = "/var/log/journal"
+
+-- | Defines a container with a given machine name, containing the specified
+-- System. Properties can be added to configure the Container.
+--
+-- > container "webserver" (System (Debian Unstable) "amd64") []
+container :: MachineName -> System -> [NspawnParam] -> Container
+container name system ps = Container name system ps (Host name [] mempty)
+
+-- | Runs a container using systemd-nspawn.
+--
+-- A systemd unit is set up for the container, so it will automatically
+-- be started on boot.
+--
+-- Systemd is automatically installed inside the container, and will
+-- communicate with the host's systemd. This allows systemctl to be used to
+-- examine the status of services running inside the container.
+--
+-- When the host system has persistentJournal enabled, journactl can be
+-- used to examine logs forwarded from the container.
+--
+-- Reverting this property stops the container, removes the systemd unit,
+-- and deletes the chroot and all its contents.
+nspawned :: Container -> RevertableProperty
+nspawned c@(Container name system _ h) = RevertableProperty setup teardown
+ where
+ -- TODO after container is running, use nsenter to enter it
+ -- and run propellor to finish provisioning.
+ setup = toProp (nspawnService c)
+ `requires` toProp chrootprovisioned
+
+ teardown = toProp (revert (chrootprovisioned))
+ `requires` toProp (revert (nspawnService c))
+
+ -- When provisioning the chroot, pass a version of the Host
+ -- that only has the Property of systemd being installed.
+ -- This is to avoid starting any daemons in the chroot,
+ -- which would not run in the container's namespace.
+ chrootprovisioned = Chroot.provisioned $
+ Chroot.Chroot (containerDir name) system $
+ h { hostProperties = [installed] }
+
+nspawnService :: Container -> RevertableProperty
+nspawnService (Container name _ ps _) = RevertableProperty setup teardown
+ where
+ service = nspawnServiceName name
+ servicefile = "/etc/systemd/system/multi-user.target.wants" </> service
+
+ setup = check (not <$> doesFileExist servicefile) $
+ combineProperties ("container running " ++ service)
+ [ cmdProperty "systemctl" ["enable", service]
+ , cmdProperty "systemctl" ["start", service]
+ ]
+
+ -- TODO adjust execStart line to reflect ps
+
+ teardown = undefined
+
+nspawnServiceName :: MachineName -> String
+nspawnServiceName name = "systemd-nspawn@" ++ name ++ ".service"
+
+containerDir :: MachineName -> FilePath
+containerDir name = "/var/lib/container" ++ replace "/" "_" name