From a904476333bcacfbed5d0ca95e8f8b3cca9fb327 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 01:05:51 -0400 Subject: [PATCH 01/26] avoid console output when chaining into chroot and not at console --- src/Propellor/CmdLine.hs | 2 +- src/Propellor/Property/Chroot.hs | 15 +++++++++------ src/Propellor/Types.hs | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Propellor/CmdLine.hs b/src/Propellor/CmdLine.hs index 466b60f..a26e255 100644 --- a/src/Propellor/CmdLine.hs +++ b/src/Propellor/CmdLine.hs @@ -85,8 +85,8 @@ defaultMain hostlist = do go _ (Edit field context) = editPrivData field context go _ ListFields = listPrivDataFields hostlist go _ (AddKey keyid) = addKey keyid + go _ (ChrootChain hn loc onconsole) = Chroot.chain hostlist hn loc onconsole go _ (DockerChain hn cid) = Docker.chain hostlist hn cid - go _ (ChrootChain hn loc) = Chroot.chain hostlist hn loc go _ (DockerInit hn) = Docker.init hn go _ (GitPush fin fout) = gitPushHelper fin fout go _ (Update _) = forceConsole >> fetchFirst (onlyprocess update) diff --git a/src/Propellor/Property/Chroot.hs b/src/Propellor/Property/Chroot.hs index 798330b..e6c2c84 100644 --- a/src/Propellor/Property/Chroot.hs +++ b/src/Propellor/Property/Chroot.hs @@ -89,19 +89,22 @@ provisionChroot c@(Chroot loc _ _) = property (chrootDesc c "provisioned") $ do chainprovision shim = do parenthost <- asks hostName + cmd <- liftIO $ toChain parenthost c let p = inChrootProcess c [ shim , "--continue" - , show $ toChain parenthost c + , show cmd ] liftIO $ withHandle StdoutHandle createProcessSuccess p processChainOutput -toChain :: HostName -> Chroot -> CmdLine -toChain parenthost (Chroot loc _ _) = ChrootChain parenthost loc +toChain :: HostName -> Chroot -> IO CmdLine +toChain parenthost (Chroot loc _ _) = do + onconsole <- isConsole <$> mkMessageHandle + return $ ChrootChain parenthost loc onconsole -chain :: [Host] -> HostName -> FilePath -> IO () -chain hostlist hn loc = case findHostNoAlias hostlist hn of +chain :: [Host] -> HostName -> FilePath -> Bool -> IO () +chain hostlist hn loc 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) @@ -109,7 +112,7 @@ chain hostlist hn loc = case findHostNoAlias hostlist hn of where go h = do changeWorkingDirectory localdir - forceConsole + when onconsole forceConsole onlyProcess (provisioningLock loc) $ do r <- runPropellor h $ ensureProperties $ hostProperties h putStrLn $ "\n" ++ show r diff --git a/src/Propellor/Types.hs b/src/Propellor/Types.hs index 56eafc6..65dbd3c 100644 --- a/src/Propellor/Types.hs +++ b/src/Propellor/Types.hs @@ -155,7 +155,7 @@ data CmdLine | Update HostName | DockerInit HostName | DockerChain HostName String - | ChrootChain HostName FilePath + | ChrootChain HostName FilePath Bool | GitPush Fd Fd deriving (Read, Show, Eq) From 45349c210d0822e6041015d7681887ff02f87ce0 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 01:09:15 -0400 Subject: [PATCH 02/26] add missing support for reverting chroot wow, that was suprisingly trivial! --- src/Propellor/Property/Chroot.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Propellor/Property/Chroot.hs b/src/Propellor/Property/Chroot.hs index e6c2c84..874d775 100644 --- a/src/Propellor/Property/Chroot.hs +++ b/src/Propellor/Property/Chroot.hs @@ -42,15 +42,15 @@ provisioned c@(Chroot loc system _) = RevertableProperty where go desc a = property (chrootDesc c desc) $ ensureProperties [a] - setup = provisionChroot c `requires` built + setup = provisionChroot c `requires` toProp built built = case system of (System (Debian _) _) -> debootstrap (System (Ubuntu _) _) -> debootstrap - debootstrap = toProp (Debootstrap.built loc system []) + debootstrap = Debootstrap.built loc system [] - teardown = undefined + teardown = toProp (revert built) propigateChrootInfo :: Chroot -> Property -> Property propigateChrootInfo c p = propigateInfo c p (<> chrootInfo c) From 1af298dc10fddc3deb32fa8af2638d00dfbc2665 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 01:14:19 -0400 Subject: [PATCH 03/26] trim --- debian/changelog | 1 - 1 file changed, 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index d6dc615..74a34b7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -13,7 +13,6 @@ propellor (1.0.0) UNRELEASED; urgency=medium * DigitalOcean.distroKernel property now reboots into the distribution kernel when necessary. * Avoid outputting color setting sequences when not run on a terminal. - * Run remote propellor --spin with a controlling terminal. * Docker code simplified by using `docker exec`; needs docker 1.3.1. * Docker containers are now a separate data type, cannot be included in the main host list, and are instead passed to From 6a5a1bc76132128e4bd2312dfadc98e83b0baf40 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 12:17:03 -0400 Subject: [PATCH 04/26] systemd container may be mostly done (untested) --- config-joey.hs | 9 ++++- src/Propellor/Property/Chroot.hs | 13 ++++--- src/Propellor/Property/Systemd.hs | 60 ++++++++++++++++++++++++++----- 3 files changed, 65 insertions(+), 17 deletions(-) diff --git a/config-joey.hs b/config-joey.hs index a11e1d8..62c5af9 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -25,6 +25,7 @@ import qualified Propellor.Property.Grub as Grub import qualified Propellor.Property.Obnam as Obnam import qualified Propellor.Property.Gpg as Gpg 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.CloudAtCost as CloudAtCost import qualified Propellor.Property.HostingProvider.Linode as Linode @@ -80,7 +81,13 @@ clam = standardSystem "clam.kitenet.net" Unstable "amd64" ! Ssh.listenPort 80 ! 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 "/tmp/chroot" (System (Debian Unstable) "amd64") diff --git a/src/Propellor/Property/Chroot.hs b/src/Propellor/Property/Chroot.hs index 874d775..e7bac84 100644 --- a/src/Propellor/Property/Chroot.hs +++ b/src/Propellor/Property/Chroot.hs @@ -2,6 +2,8 @@ module Propellor.Property.Chroot ( Chroot(..), chroot, provisioned, + -- * Internal use + propellChroot, chain, ) where @@ -42,7 +44,7 @@ provisioned c@(Chroot loc system _) = RevertableProperty where 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 (System (Debian _) _) -> debootstrap @@ -60,11 +62,8 @@ chrootInfo (Chroot loc _ h) = mempty { _chrootinfo = mempty { _chroots = M.singleton loc h } } -- | Propellor is run inside the chroot to provision it. --- --- Strange and wonderful tricks let the host's /usr/local/propellor --- be used inside the chroot, without needing to install anything. -provisionChroot :: Chroot -> Property -provisionChroot c@(Chroot loc _ _) = property (chrootDesc c "provisioned") $ do +propellChroot :: Chroot -> ([String] -> CreateProcess) -> Property +propellChroot c@(Chroot loc _ _) mkproc = property (chrootDesc c "provisioned") $ do let d = localdir shimdir c let me = localdir "propellor" shim <- liftIO $ ifM (doesDirectoryExist d) @@ -90,7 +89,7 @@ provisionChroot c@(Chroot loc _ _) = property (chrootDesc c "provisioned") $ do chainprovision shim = do parenthost <- asks hostName cmd <- liftIO $ toChain parenthost c - let p = inChrootProcess c + let p = mkproc [ shim , "--continue" , show cmd diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index be08a84..63a150f 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -8,7 +8,9 @@ module Propellor.Property.Systemd ( import Propellor import qualified Propellor.Property.Chroot as Chroot import qualified Propellor.Property.Apt as Apt +import qualified Propellor.Property.File as File import Utility.SafeCommand +import Utility.FileMode import Data.List.Utils @@ -29,7 +31,7 @@ instance Hostlike Container where installed :: Property installed = Apt.installed ["systemd", "dbus"] --- | Sets up persistent storage of the journal. +-- | Enables persistent storage of the journal. persistentJournal :: Property persistentJournal = check (not <$> doesDirectoryExist dir) $ combineProperties "persistent systetemd journal" @@ -64,21 +66,29 @@ container name system ps = Container name system ps (Host name [] mempty) 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) + setup = containerprovisioned + `requires` toProp (nspawnService c) `requires` toProp chrootprovisioned + `requires` toProp (enterScript c) teardown = toProp (revert (chrootprovisioned)) `requires` toProp (revert (nspawnService c)) + `requires` toProp (revert (enterScript 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] } + mkChroot $ 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 name _ ps _) = RevertableProperty setup teardown @@ -91,13 +101,45 @@ nspawnService (Container name _ ps _) = RevertableProperty setup teardown [ cmdProperty "systemctl" ["enable", service] , cmdProperty "systemctl" ["start", service] ] - - -- TODO adjust execStart line to reflect ps + -- TODO ^ adjust execStart line to reflect ps 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 name = "systemd-nspawn@" ++ name ++ ".service" containerDir :: MachineName -> FilePath -containerDir name = "/var/lib/container" ++ replace "/" "_" name +containerDir name = "/var/lib/container" ++ mungename name + +mungename :: MachineName -> String +mungename = replace "/" "_" From 976afedea3fabc98ac64d72bbad3aacd7602f84d Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 12:18:03 -0400 Subject: [PATCH 05/26] propellor spin --- config-joey.hs | 2 +- src/Propellor/Property/Systemd.hs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/config-joey.hs b/config-joey.hs index 62c5af9..b2b324f 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -87,7 +87,7 @@ clam = standardSystem "clam.kitenet.net" Unstable "amd64" meow :: Systemd.Container meow = Systemd.container "meow" (System (Debian Unstable) "amd64") [] - & Apt.serviceInstalledRunning ["fingerd"] + & Apt.serviceInstalledRunning "fingerd" testChroot :: Chroot.Chroot testChroot = Chroot.chroot "/tmp/chroot" (System (Debian Unstable) "amd64") diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index 63a150f..88c0374 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -1,6 +1,7 @@ module Propellor.Property.Systemd ( installed, persistentJournal, + Container, container, nspawned, ) where From ae6a5e815c7f1cde269090f45470a23231e0124c Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 12:35:07 -0400 Subject: [PATCH 06/26] propellor spin --- src/Propellor/Property/Systemd.hs | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index 88c0374..3f2dccc 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -1,5 +1,8 @@ module Propellor.Property.Systemd ( installed, + started, + stopped, + enabled, persistentJournal, Container, container, @@ -15,6 +18,8 @@ import Utility.FileMode import Data.List.Utils +type ServiceName = String + type MachineName = String type NspawnParam = CommandParam @@ -32,12 +37,28 @@ instance Hostlike Container where installed :: Property installed = Apt.installed ["systemd", "dbus"] +-- | Starts a systemd service. +started :: ServiceName -> Property +started n = trivial $ cmdProperty "systemctl" ["start", n] + `describe` ("service " ++ n ++ " started") + +-- | Stops a systemd service. +stopped :: ServiceName -> Property +stopped n = trivial $ cmdProperty "systemctl" ["stop", n] + `describe` ("service " ++ n ++ " stopped") + +-- | Enables a systemd service. +enabled :: ServiceName -> Property +enabled n = trivial $ cmdProperty "systemctl" ["enable", n] + `describe` ("service " ++ n ++ " enabled") + -- | Enables persistent storage of the journal. persistentJournal :: Property persistentJournal = check (not <$> doesDirectoryExist dir) $ - combineProperties "persistent systetemd journal" + combineProperties "persistent systemd journal" [ cmdProperty "install" ["-d", "-g", "systemd-journal", dir] , cmdProperty "setfacl" ["-R", "-nm", "g:adm:rx,d:g:adm:rx", dir] + , started "systemd-journal-flush" ] `requires` Apt.installed ["acl"] where @@ -99,8 +120,8 @@ nspawnService (Container name _ ps _) = RevertableProperty setup teardown setup = check (not <$> doesFileExist servicefile) $ combineProperties ("container running " ++ service) - [ cmdProperty "systemctl" ["enable", service] - , cmdProperty "systemctl" ["start", service] + [ enabled service + , started service ] -- TODO ^ adjust execStart line to reflect ps @@ -136,11 +157,11 @@ enterScriptFile (Container name _ _ _ ) = "enter-" ++ mungename name enterContainerProcess :: Container -> [String] -> CreateProcess enterContainerProcess = proc . enterScriptFile -nspawnServiceName :: MachineName -> String +nspawnServiceName :: MachineName -> ServiceName nspawnServiceName name = "systemd-nspawn@" ++ name ++ ".service" containerDir :: MachineName -> FilePath -containerDir name = "/var/lib/container" ++ mungename name +containerDir name = "/var/lib/container" mungename name mungename :: MachineName -> String mungename = replace "/" "_" From b076b1b3d3f0f60ad9ab42bce12c1b3a8baef4b6 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 13:25:48 -0400 Subject: [PATCH 07/26] propellor spin From 3ba82a1c9c27f1e79eeecfcfad7bbb9dce653488 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 13:49:17 -0400 Subject: [PATCH 08/26] propellor spin --- src/Propellor/Property/Systemd.hs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index 3f2dccc..3547f60 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -88,14 +88,14 @@ container name system ps = Container name system ps (Host name [] mempty) nspawned :: Container -> RevertableProperty nspawned c@(Container name system _ h) = RevertableProperty setup teardown where - setup = containerprovisioned - `requires` toProp (nspawnService c) - `requires` toProp chrootprovisioned - `requires` toProp (enterScript c) - - teardown = toProp (revert (chrootprovisioned)) - `requires` toProp (revert (nspawnService c)) - `requires` toProp (revert (enterScript c)) + setup = propertyList ("nspawned " ++ name) (map toProp steps) + teardown = propertyList ("not nspawned " ++ name) + (map (toProp . revert) (reverse steps)) + steps = + [ enterScript c + , chrootprovisioned + , nspawnService c + ] -- When provisioning the chroot, pass a version of the Host -- that only has the Property of systemd being installed. @@ -119,10 +119,8 @@ nspawnService (Container name _ ps _) = RevertableProperty setup teardown servicefile = "/etc/systemd/system/multi-user.target.wants" service setup = check (not <$> doesFileExist servicefile) $ - combineProperties ("container running " ++ service) - [ enabled service - , started service - ] + started service + `requires` enabled service -- TODO ^ adjust execStart line to reflect ps teardown = undefined From 09e79e6263db1f7309b9787585d797e46c6905b9 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 13:55:42 -0400 Subject: [PATCH 09/26] propellor spin --- src/Propellor/Property/Systemd.hs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index 3547f60..428d11b 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -88,9 +88,10 @@ container name system ps = Container name system ps (Host name [] mempty) nspawned :: Container -> RevertableProperty nspawned c@(Container name system _ h) = RevertableProperty setup teardown where - setup = propertyList ("nspawned " ++ name) (map toProp steps) - teardown = propertyList ("not nspawned " ++ name) - (map (toProp . revert) (reverse steps)) + setup = propertyList ("nspawned " ++ name) $ + map toProp steps ++ [containerprovisioned] + teardown = propertyList ("not nspawned " ++ name) $ + map (toProp . revert) (reverse steps) steps = [ enterScript c , chrootprovisioned @@ -141,6 +142,7 @@ enterScript c@(Container name _ _ _) = RevertableProperty setup teardown , "if [ -n \"$pid\" ]; then" , "\tnsenter -p -u -n -i -m -t \"$pid\"" , "else" + , "\techo container not running >&2" , "\texit 1" , "fi" ] @@ -150,7 +152,7 @@ enterScript c@(Container name _ _ _) = RevertableProperty setup teardown scriptfile = enterScriptFile c enterScriptFile :: Container -> FilePath -enterScriptFile (Container name _ _ _ ) = "enter-" ++ mungename name +enterScriptFile (Container name _ _ _ ) = "/usr/local/bin/enter-" ++ mungename name enterContainerProcess :: Container -> [String] -> CreateProcess enterContainerProcess = proc . enterScriptFile From 5e1a47552a07b596b0b264ca752025335b29e45b Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 13:57:58 -0400 Subject: [PATCH 10/26] propellor spin --- src/Propellor/Property/Systemd.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index 428d11b..862b674 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -140,7 +140,7 @@ enterScript c@(Container name _ _ _) = RevertableProperty setup teardown , "# 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\"" + , "\tnsenter -p -u -n -i -m -t \"$pid\" \"$@\"" , "else" , "\techo container not running >&2" , "\texit 1" From 7d4d3e44518aef38e7c036e76dfaf8e6f1c21bdb Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 14:11:02 -0400 Subject: [PATCH 11/26] fix info propigation Need to propigate the full container info, not the subset used in chroot deployment. --- src/Propellor/Property/Chroot.hs | 9 +++++++-- src/Propellor/Property/Systemd.hs | 10 +++++----- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/Propellor/Property/Chroot.hs b/src/Propellor/Property/Chroot.hs index e7bac84..7fee3a5 100644 --- a/src/Propellor/Property/Chroot.hs +++ b/src/Propellor/Property/Chroot.hs @@ -3,6 +3,8 @@ module Propellor.Property.Chroot ( chroot, provisioned, -- * Internal use + provisioned', + propigateChrootInfo, propellChroot, chain, ) where @@ -38,8 +40,11 @@ chroot location system = Chroot location system (Host location [] mempty) -- 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 -provisioned c@(Chroot loc system _) = RevertableProperty - (propigateChrootInfo c (go "exists" setup)) +provisioned c = provisioned' (propigateChrootInfo c) c + +provisioned' :: (Property -> Property) -> Chroot -> RevertableProperty +provisioned' propigator c@(Chroot loc system _) = RevertableProperty + (propigator $ go "exists" setup) (go "removed" teardown) where go desc a = property (chrootDesc c desc) $ ensureProperties [a] diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index 862b674..9b0a445 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -88,9 +88,9 @@ container name system ps = Container name system ps (Host name [] mempty) nspawned :: Container -> RevertableProperty nspawned c@(Container name system _ h) = RevertableProperty setup teardown where - setup = propertyList ("nspawned " ++ name) $ + setup = combineProperties ("nspawned " ++ name) $ map toProp steps ++ [containerprovisioned] - teardown = propertyList ("not nspawned " ++ name) $ + teardown = combineProperties ("not nspawned " ++ name) $ map (toProp . revert) (reverse steps) steps = [ enterScript c @@ -102,16 +102,16 @@ nspawned c@(Container name system _ h) = RevertableProperty setup teardown -- 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 $ + chrootprovisioned = Chroot.provisioned' (Chroot.propigateChrootInfo chroot) $ mkChroot $ h { hostProperties = [installed] } -- Use nsenter to enter container and and run propellor to -- finish provisioning. - containerprovisioned = Chroot.propellChroot - (mkChroot h) + containerprovisioned = Chroot.propellChroot chroot (enterContainerProcess c) mkChroot = Chroot.Chroot (containerDir name) system + chroot = mkChroot h nspawnService :: Container -> RevertableProperty nspawnService (Container name _ ps _) = RevertableProperty setup teardown From 7c03f5eea4107ca53b72ed80701c5ca55100e548 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 14:11:43 -0400 Subject: [PATCH 12/26] propellor spin From cf3a8883ecec79ad8b44be956ae98db3bfa3f42f Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 14:17:19 -0400 Subject: [PATCH 13/26] propellor spin --- config-joey.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-joey.hs b/config-joey.hs index b2b324f..da7d8ea 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -87,7 +87,7 @@ clam = standardSystem "clam.kitenet.net" Unstable "amd64" meow :: Systemd.Container meow = Systemd.container "meow" (System (Debian Unstable) "amd64") [] - & Apt.serviceInstalledRunning "fingerd" + & Apt.serviceInstalledRunning "uptimed" testChroot :: Chroot.Chroot testChroot = Chroot.chroot "/tmp/chroot" (System (Debian Unstable) "amd64") From 36e89cd148cd266254f4c50c5396d05433ed9bb3 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 14:31:13 -0400 Subject: [PATCH 14/26] os info propigation Also, lost the systemd-nspawn parameters; I'll do that some other way. --- config-joey.hs | 3 ++- src/Propellor/Property/Chroot.hs | 2 ++ src/Propellor/Property/Systemd.hs | 28 ++++++++++++++-------------- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/config-joey.hs b/config-joey.hs index da7d8ea..a12544d 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -86,8 +86,9 @@ clam = standardSystem "clam.kitenet.net" Unstable "amd64" & Systemd.nspawned meow meow :: Systemd.Container -meow = Systemd.container "meow" (System (Debian Unstable) "amd64") [] +meow = Systemd.container "meow" (System (Debian Unstable) "amd64") & Apt.serviceInstalledRunning "uptimed" + & alias "meow.kitenet.net" testChroot :: Chroot.Chroot testChroot = Chroot.chroot "/tmp/chroot" (System (Debian Unstable) "amd64") diff --git a/src/Propellor/Property/Chroot.hs b/src/Propellor/Property/Chroot.hs index 7fee3a5..2aad26f 100644 --- a/src/Propellor/Property/Chroot.hs +++ b/src/Propellor/Property/Chroot.hs @@ -19,6 +19,7 @@ import Data.List.Utils import System.Posix.Directory data Chroot = Chroot FilePath System Host + deriving (Show) instance Hostlike Chroot where (Chroot l s h) & p = Chroot l s (h & p) @@ -33,6 +34,7 @@ instance Hostlike Chroot where -- > & ... chroot :: FilePath -> System -> Chroot chroot location system = Chroot location system (Host location [] mempty) + & os system -- | Ensures that the chroot exists and is provisioned according to its -- properties. diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index 9b0a445..c6f57e2 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -22,14 +22,12 @@ type ServiceName = String type MachineName = String -type NspawnParam = CommandParam - -data Container = Container MachineName System [CommandParam] Host +data Container = Container MachineName System 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 + (Container n s h) & p = Container n s (h & p) + (Container n s h) &^ p = Container n s (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 @@ -67,9 +65,12 @@ persistentJournal = check (not <$> doesDirectoryExist dir) $ -- | 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) +-- > container "webserver" (System (Debian Unstable) "amd64") +-- > & Apt.installedRunning "apache2" +-- > & ... +container :: MachineName -> System -> Container +container name system = Container name system (Host name [] mempty) + & os system -- | Runs a container using systemd-nspawn. -- @@ -86,7 +87,7 @@ container name system ps = Container name system ps (Host name [] mempty) -- 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 +nspawned c@(Container name system h) = RevertableProperty setup teardown where setup = combineProperties ("nspawned " ++ name) $ map toProp steps ++ [containerprovisioned] @@ -114,7 +115,7 @@ nspawned c@(Container name system _ h) = RevertableProperty setup teardown chroot = mkChroot h nspawnService :: Container -> RevertableProperty -nspawnService (Container name _ ps _) = RevertableProperty setup teardown +nspawnService (Container name _ _) = RevertableProperty setup teardown where service = nspawnServiceName name servicefile = "/etc/systemd/system/multi-user.target.wants" service @@ -122,7 +123,6 @@ nspawnService (Container name _ ps _) = RevertableProperty setup teardown setup = check (not <$> doesFileExist servicefile) $ started service `requires` enabled service - -- TODO ^ adjust execStart line to reflect ps teardown = undefined @@ -132,7 +132,7 @@ nspawnService (Container name _ ps _) = RevertableProperty setup teardown -- 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 +enterScript c@(Container name _ _) = RevertableProperty setup teardown where setup = combineProperties ("generated " ++ enterScriptFile c) [ scriptfile `File.hasContent` @@ -152,7 +152,7 @@ enterScript c@(Container name _ _ _) = RevertableProperty setup teardown scriptfile = enterScriptFile c enterScriptFile :: Container -> FilePath -enterScriptFile (Container name _ _ _ ) = "/usr/local/bin/enter-" ++ mungename name +enterScriptFile (Container name _ _ ) = "/usr/local/bin/enter-" ++ mungename name enterContainerProcess :: Container -> [String] -> CreateProcess enterContainerProcess = proc . enterScriptFile From fbce215f3381b36df64c0e268bb816b1b0a4fd0d Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 14:37:19 -0400 Subject: [PATCH 15/26] implement teardown --- src/Propellor/Property/Systemd.hs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index c6f57e2..ce7d63c 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -3,6 +3,7 @@ module Propellor.Property.Systemd ( started, stopped, enabled, + disabled, persistentJournal, Container, container, @@ -50,6 +51,11 @@ enabled :: ServiceName -> Property enabled n = trivial $ cmdProperty "systemctl" ["enable", n] `describe` ("service " ++ n ++ " enabled") +-- | Disables a systemd service. +disabled :: ServiceName -> Property +disabled n = trivial $ cmdProperty "systemctl" ["distable", n] + `describe` ("service " ++ n ++ " disabled") + -- | Enables persistent storage of the journal. persistentJournal :: Property persistentJournal = check (not <$> doesDirectoryExist dir) $ @@ -121,10 +127,12 @@ nspawnService (Container name _ _) = RevertableProperty setup teardown servicefile = "/etc/systemd/system/multi-user.target.wants" service setup = check (not <$> doesFileExist servicefile) $ - started service - `requires` enabled service + started service + `requires` enabled service - teardown = undefined + teardown = check (doesFileExist servicefile) $ + disabled service + `requires` stopped service -- | Installs a "enter-machinename" script that root can use to run a -- command inside the container. From 9e611d87cd95999eb6b3e5e7f6c855f7c092f57c Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 15:55:27 -0400 Subject: [PATCH 16/26] add debootstrap parameters --- config-joey.hs | 4 +- src/Propellor/Property/Chroot.hs | 56 ++++++++++++++++----------- src/Propellor/Property/Debootstrap.hs | 28 ++++++++++++-- src/Propellor/Property/Systemd.hs | 25 +++++++----- 4 files changed, 75 insertions(+), 38 deletions(-) diff --git a/config-joey.hs b/config-joey.hs index a12544d..2971c1a 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -86,12 +86,12 @@ clam = standardSystem "clam.kitenet.net" Unstable "amd64" & Systemd.nspawned meow meow :: Systemd.Container -meow = Systemd.container "meow" (System (Debian Unstable) "amd64") +meow = Systemd.container "meow" (Chroot.debootstrapped (System (Debian Unstable) "amd64") mempty) & Apt.serviceInstalledRunning "uptimed" & alias "meow.kitenet.net" testChroot :: Chroot.Chroot -testChroot = Chroot.chroot "/tmp/chroot" (System (Debian Unstable) "amd64") +testChroot = Chroot.debootstrapped (System (Debian Unstable) "amd64") mempty "/tmp/chroot" & File.hasContent "/foo" ["hello"] orca :: Host diff --git a/src/Propellor/Property/Chroot.hs b/src/Propellor/Property/Chroot.hs index 2aad26f..8d4a036 100644 --- a/src/Propellor/Property/Chroot.hs +++ b/src/Propellor/Property/Chroot.hs @@ -1,6 +1,6 @@ module Propellor.Property.Chroot ( Chroot(..), - chroot, + debootstrapped, provisioned, -- * Internal use provisioned', @@ -18,23 +18,33 @@ import qualified Data.Map as M import Data.List.Utils import System.Posix.Directory -data Chroot = Chroot FilePath System Host +data Chroot = Chroot FilePath System BuilderConf Host + deriving (Show) + +data BuilderConf + = UsingDeboostrap Debootstrap.DebootstrapConfig deriving (Show) instance Hostlike Chroot where - (Chroot l s h) & p = Chroot l s (h & p) - (Chroot l s h) &^ p = Chroot l s (h &^ p) - getHost (Chroot _ _ h) = h + (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 --- | Defines a Chroot at the given location, containing the specified --- System. Properties can be added to configure the Chroot. +-- | Defines a Chroot at the given location, built with debootstrap. -- --- > chroot "/srv/chroot/ghc-dev" (System (Debian Unstable) "amd64") --- > & Apt.installed ["build-essential", "ghc", "haskell-platform"] +-- Properties can be added to configure the Chroot. +-- +-- > debootstrapped (System (Debian Unstable) "amd64") Debootstrap.BuildD "/srv/chroot/ghc-dev" +-- > & Apt.installed ["ghc", "haskell-platform"] -- > & ... -chroot :: FilePath -> System -> Chroot -chroot location system = Chroot location system (Host location [] mempty) - & os system +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. @@ -45,7 +55,7 @@ provisioned :: Chroot -> RevertableProperty provisioned c = provisioned' (propigateChrootInfo c) c provisioned' :: (Property -> Property) -> Chroot -> RevertableProperty -provisioned' propigator c@(Chroot loc system _) = RevertableProperty +provisioned' propigator c@(Chroot loc system builderconf _) = RevertableProperty (propigator $ go "exists" setup) (go "removed" teardown) where @@ -53,11 +63,11 @@ provisioned' propigator c@(Chroot loc system _) = RevertableProperty setup = propellChroot c (inChrootProcess c) `requires` toProp built - built = case system of - (System (Debian _) _) -> debootstrap - (System (Ubuntu _) _) -> debootstrap + built = case (system, builderconf) of + ((System (Debian _) _), UsingDeboostrap cf) -> debootstrap cf + ((System (Ubuntu _) _), UsingDeboostrap cf) -> debootstrap cf - debootstrap = Debootstrap.built loc system [] + debootstrap = Debootstrap.built loc system teardown = toProp (revert built) @@ -65,12 +75,12 @@ propigateChrootInfo :: Chroot -> Property -> Property propigateChrootInfo c p = propigateInfo c p (<> chrootInfo c) chrootInfo :: Chroot -> Info -chrootInfo (Chroot loc _ h) = +chrootInfo (Chroot loc _ _ h) = mempty { _chrootinfo = mempty { _chroots = M.singleton loc h } } -- | Propellor is run inside the chroot to provision it. propellChroot :: Chroot -> ([String] -> CreateProcess) -> Property -propellChroot c@(Chroot loc _ _) mkproc = property (chrootDesc c "provisioned") $ do +propellChroot c@(Chroot loc _ _ _) mkproc = property (chrootDesc c "provisioned") $ do let d = localdir shimdir c let me = localdir "propellor" shim <- liftIO $ ifM (doesDirectoryExist d) @@ -105,7 +115,7 @@ propellChroot c@(Chroot loc _ _) mkproc = property (chrootDesc c "provisioned") processChainOutput toChain :: HostName -> Chroot -> IO CmdLine -toChain parenthost (Chroot loc _ _) = do +toChain parenthost (Chroot loc _ _ _) = do onconsole <- isConsole <$> mkMessageHandle return $ ChrootChain parenthost loc onconsole @@ -124,16 +134,16 @@ chain hostlist hn loc onconsole = case findHostNoAlias hostlist hn of putStrLn $ "\n" ++ show r inChrootProcess :: Chroot -> [String] -> CreateProcess -inChrootProcess (Chroot loc _ _) cmd = proc "chroot" (loc:cmd) +inChrootProcess (Chroot loc _ _ _) cmd = proc "chroot" (loc:cmd) provisioningLock :: FilePath -> FilePath provisioningLock containerloc = "chroot" mungeloc containerloc ++ ".lock" shimdir :: Chroot -> FilePath -shimdir (Chroot loc _ _) = "chroot" mungeloc loc ++ ".shim" +shimdir (Chroot loc _ _ _) = "chroot" mungeloc loc ++ ".shim" mungeloc :: FilePath -> String mungeloc = replace "/" "_" chrootDesc :: Chroot -> String -> String -chrootDesc (Chroot loc _ _) desc = "chroot " ++ loc ++ " " ++ desc +chrootDesc (Chroot loc _ _ _) desc = "chroot " ++ loc ++ " " ++ desc diff --git a/src/Propellor/Property/Debootstrap.hs b/src/Propellor/Property/Debootstrap.hs index 5f521c3..747662c 100644 --- a/src/Propellor/Property/Debootstrap.hs +++ b/src/Propellor/Property/Debootstrap.hs @@ -1,5 +1,6 @@ module Propellor.Property.Debootstrap ( Url, + DebootstrapConfig(..), built, installed, programPath, @@ -18,6 +19,27 @@ import System.Posix.Directory type Url = String +-- | A monoid for debootstrap configuration. +-- mempty is a default debootstrapped system. +data DebootstrapConfig + = DefaultConfig + | MinBase + | BuilddD + | DebootstrapParam String + | DebootstrapConfig :+ DebootstrapConfig + deriving (Show) + +instance Monoid DebootstrapConfig where + mempty = DefaultConfig + mappend = (:+) + +toParams :: DebootstrapConfig -> [CommandParam] +toParams DefaultConfig = [] +toParams MinBase = [Param "--variant=minbase"] +toParams BuilddD = [Param "--variant=buildd"] +toParams (DebootstrapParam p) = [Param p] +toParams (c1 :+ c2) = toParams c1 <> toParams c2 + -- | Builds a chroot in the given directory using debootstrap. -- -- The System can be any OS and architecture that debootstrap @@ -28,8 +50,8 @@ type Url = String -- -- Note that reverting this property does not stop any processes -- currently running in the chroot. -built :: FilePath -> System -> [CommandParam] -> RevertableProperty -built target system@(System _ arch) extraparams = +built :: FilePath -> System -> DebootstrapConfig -> RevertableProperty +built target system@(System _ arch) config = RevertableProperty setup teardown where setup = check (unpopulated target <||> ispartial) setupprop @@ -44,7 +66,7 @@ built target system@(System _ arch) extraparams = suite <- case extractSuite system of Nothing -> errorMessage $ "don't know how to debootstrap " ++ show system Just s -> pure s - let params = extraparams ++ + let params = toParams config ++ [ Param $ "--arch=" ++ arch , Param suite , Param target diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index ce7d63c..d91b441 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -23,11 +23,11 @@ type ServiceName = String type MachineName = String -data Container = Container MachineName System Host +data Container = Container MachineName Chroot.Chroot Host instance Hostlike Container where - (Container n s h) & p = Container n s (h & p) - (Container n s h) &^ p = Container n s (h &^ p) + (Container n c h) & p = Container n c (h & p) + (Container n c h) &^ p = Container n c (h &^ p) getHost (Container _ _ h) = h -- dbus is only a Recommends of systemd, but is needed for communication @@ -68,15 +68,19 @@ persistentJournal = check (not <$> doesDirectoryExist dir) $ 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. +-- | Defines a container with a given machine name. -- --- > container "webserver" (System (Debian Unstable) "amd64") +-- Properties can be added to configure the Container. +-- +-- > container "webserver" (Chroot.debootstrapped (System (Debian Unstable) "amd64") mempty) -- > & Apt.installedRunning "apache2" -- > & ... -container :: MachineName -> System -> Container -container name system = Container name system (Host name [] mempty) +container :: MachineName -> (FilePath -> Chroot.Chroot) -> Container +container name mkchroot = Container name c h & os system + where + c@(Chroot.Chroot _ system _ _) = mkchroot (containerDir name) + h = Host name [] mempty -- | Runs a container using systemd-nspawn. -- @@ -93,7 +97,8 @@ container name system = Container name system (Host name [] mempty) -- 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 +nspawned c@(Container name (Chroot.Chroot loc system builderconf _) h) = + RevertableProperty setup teardown where setup = combineProperties ("nspawned " ++ name) $ map toProp steps ++ [containerprovisioned] @@ -117,7 +122,7 @@ nspawned c@(Container name system h) = RevertableProperty setup teardown containerprovisioned = Chroot.propellChroot chroot (enterContainerProcess c) - mkChroot = Chroot.Chroot (containerDir name) system + mkChroot = Chroot.Chroot loc system builderconf chroot = mkChroot h nspawnService :: Container -> RevertableProperty From c4accb72e20bc0906c1089c60574b844234d6401 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 15:56:50 -0400 Subject: [PATCH 17/26] propellor spin --- config-joey.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-joey.hs b/config-joey.hs index 2971c1a..a2a501a 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -83,7 +83,7 @@ clam = standardSystem "clam.kitenet.net" Unstable "amd64" ! Chroot.provisioned testChroot & Systemd.persistentJournal - & Systemd.nspawned meow + ! Systemd.nspawned meow meow :: Systemd.Container meow = Systemd.container "meow" (Chroot.debootstrapped (System (Debian Unstable) "amd64") mempty) From f6afeb889f4b11418daac7825c1adb1df4ff145c Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 16:01:51 -0400 Subject: [PATCH 18/26] lock down chroot perm --- src/Propellor/Property/Debootstrap.hs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Propellor/Property/Debootstrap.hs b/src/Propellor/Property/Debootstrap.hs index 747662c..0611e73 100644 --- a/src/Propellor/Property/Debootstrap.hs +++ b/src/Propellor/Property/Debootstrap.hs @@ -16,6 +16,7 @@ import Data.List import Data.Char import Control.Exception import System.Posix.Directory +import System.Posix.Files type Url = String @@ -63,6 +64,11 @@ built target system@(System _ arch) config = setupprop = property ("debootstrapped " ++ target) $ liftIO $ do createDirectoryIfMissing True target + -- Don't allow non-root users to see inside the chroot, + -- since doing so can allow them to do various attacks + -- including hard link farming suid programs for later + -- exploitation. + modifyFileMode target (removeModes [otherReadMode, otherExecuteMode, otherWriteMode]) suite <- case extractSuite system of Nothing -> errorMessage $ "don't know how to debootstrap " ++ show system Just s -> pure s From 33e9b10c19320cdeb82dedd21cfc8bc7a10ed649 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 16:02:10 -0400 Subject: [PATCH 19/26] typo --- src/Propellor/Property/Systemd.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index d91b441..d1b6bde 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -53,7 +53,7 @@ enabled n = trivial $ cmdProperty "systemctl" ["enable", n] -- | Disables a systemd service. disabled :: ServiceName -> Property -disabled n = trivial $ cmdProperty "systemctl" ["distable", n] +disabled n = trivial $ cmdProperty "systemctl" ["disable", n] `describe` ("service " ++ n ++ " disabled") -- | Enables persistent storage of the journal. From 79246e03c6bc5d97e7253f49c5e0389a6dc83daa Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 16:02:16 -0400 Subject: [PATCH 20/26] propellor spin From 7a6f277ccb99bf33d0f6a3f90cd809bb39031c9c Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 16:04:02 -0400 Subject: [PATCH 21/26] propellor spin --- config-joey.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-joey.hs b/config-joey.hs index a2a501a..2971c1a 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -83,7 +83,7 @@ clam = standardSystem "clam.kitenet.net" Unstable "amd64" ! Chroot.provisioned testChroot & Systemd.persistentJournal - ! Systemd.nspawned meow + & Systemd.nspawned meow meow :: Systemd.Container meow = Systemd.container "meow" (Chroot.debootstrapped (System (Debian Unstable) "amd64") mempty) From 435244353c998c55e1342e375eaec33619ecfe8f Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 16:19:04 -0400 Subject: [PATCH 22/26] propellor spin From 6e8b28cd3ce4264927cb9e9475b77954663c2ffa Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 17:11:26 -0400 Subject: [PATCH 23/26] propellor spin --- propellor.cabal | 1 + src/Propellor/CmdLine.hs | 2 +- src/Propellor/Property/Chroot.hs | 41 +++++++++++++++----------- src/Propellor/Property/Systemd.hs | 25 ++++++---------- src/Propellor/Property/Systemd/Core.hs | 10 +++++++ src/Propellor/Types.hs | 2 +- 6 files changed, 46 insertions(+), 35 deletions(-) create mode 100644 src/Propellor/Property/Systemd/Core.hs diff --git a/propellor.cabal b/propellor.cabal index f45900c..e40b6e6 100644 --- a/propellor.cabal +++ b/propellor.cabal @@ -96,6 +96,7 @@ Library Propellor.Property.Ssh Propellor.Property.Sudo Propellor.Property.Systemd + Propellor.Property.Systemd.Core Propellor.Property.Tor Propellor.Property.User Propellor.Property.HostingProvider.CloudAtCost diff --git a/src/Propellor/CmdLine.hs b/src/Propellor/CmdLine.hs index a26e255..142efa1 100644 --- a/src/Propellor/CmdLine.hs +++ b/src/Propellor/CmdLine.hs @@ -85,7 +85,7 @@ defaultMain hostlist = do go _ (Edit field context) = editPrivData field context go _ ListFields = listPrivDataFields hostlist go _ (AddKey keyid) = addKey keyid - go _ (ChrootChain hn loc onconsole) = Chroot.chain hostlist hn loc onconsole + go _ c@(ChrootChain _ _ _ _) = Chroot.chain hostlist c go _ (DockerChain hn cid) = Docker.chain hostlist hn cid go _ (DockerInit hn) = Docker.init hn go _ (GitPush fin fout) = gitPushHelper fin fout diff --git a/src/Propellor/Property/Chroot.hs b/src/Propellor/Property/Chroot.hs index 8d4a036..7246e7e 100644 --- a/src/Propellor/Property/Chroot.hs +++ b/src/Propellor/Property/Chroot.hs @@ -11,6 +11,7 @@ module Propellor.Property.Chroot ( import Propellor import qualified Propellor.Property.Debootstrap as Debootstrap +import qualified Propellor.Property.Systemd.Core as Systemd import qualified Propellor.Shim as Shim import Utility.SafeCommand @@ -52,16 +53,17 @@ debootstrapped system conf location = case system of -- 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 -provisioned c = provisioned' (propigateChrootInfo c) c +provisioned c = provisioned' (propigateChrootInfo c) c False -provisioned' :: (Property -> Property) -> Chroot -> RevertableProperty -provisioned' propigator c@(Chroot loc system builderconf _) = RevertableProperty +provisioned' :: (Property -> Property) -> Chroot -> Bool -> RevertableProperty +provisioned' propigator c@(Chroot loc system builderconf _) systemdonly = RevertableProperty (propigator $ go "exists" setup) (go "removed" teardown) where go desc a = property (chrootDesc c desc) $ ensureProperties [a] - setup = propellChroot c (inChrootProcess c) `requires` toProp built + setup = propellChroot c (inChrootProcess c) systemdonly + `requires` toProp built built = case (system, builderconf) of ((System (Debian _) _), UsingDeboostrap cf) -> debootstrap cf @@ -79,8 +81,8 @@ chrootInfo (Chroot loc _ _ h) = mempty { _chrootinfo = mempty { _chroots = M.singleton loc h } } -- | Propellor is run inside the chroot to provision it. -propellChroot :: Chroot -> ([String] -> CreateProcess) -> Property -propellChroot c@(Chroot loc _ _ _) mkproc = property (chrootDesc c "provisioned") $ do +propellChroot :: Chroot -> ([String] -> CreateProcess) -> Bool -> Property +propellChroot c@(Chroot loc _ _ _) mkproc systemdonly = property (chrootDesc c "provisioned") $ do let d = localdir shimdir c let me = localdir "propellor" shim <- liftIO $ ifM (doesDirectoryExist d) @@ -105,7 +107,7 @@ propellChroot c@(Chroot loc _ _ _) mkproc = property (chrootDesc c "provisioned" chainprovision shim = do parenthost <- asks hostName - cmd <- liftIO $ toChain parenthost c + cmd <- liftIO $ toChain parenthost c systemdonly let p = mkproc [ shim , "--continue" @@ -114,24 +116,29 @@ propellChroot c@(Chroot loc _ _ _) mkproc = property (chrootDesc c "provisioned" liftIO $ withHandle StdoutHandle createProcessSuccess p processChainOutput -toChain :: HostName -> Chroot -> IO CmdLine -toChain parenthost (Chroot loc _ _ _) = do +toChain :: HostName -> Chroot -> Bool -> IO CmdLine +toChain parenthost (Chroot loc _ _ _) systemdonly = do onconsole <- isConsole <$> mkMessageHandle - return $ ChrootChain parenthost loc onconsole + return $ ChrootChain parenthost loc systemdonly onconsole -chain :: [Host] -> HostName -> FilePath -> Bool -> IO () -chain hostlist hn loc 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 +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 where go h = do changeWorkingDirectory localdir when onconsole forceConsole onlyProcess (provisioningLock loc) $ do - r <- runPropellor h $ ensureProperties $ hostProperties h + r <- runPropellor h $ ensureProperties $ + if systemdonly + then [Systemd.installed] + else hostProperties h putStrLn $ "\n" ++ show r +chain _ _ = errorMessage "bad chain command" inChrootProcess :: Chroot -> [String] -> CreateProcess inChrootProcess (Chroot loc _ _ _) cmd = proc "chroot" (loc:cmd) diff --git a/src/Propellor/Property/Systemd.hs b/src/Propellor/Property/Systemd.hs index d1b6bde..b50194f 100644 --- a/src/Propellor/Property/Systemd.hs +++ b/src/Propellor/Property/Systemd.hs @@ -1,5 +1,5 @@ module Propellor.Property.Systemd ( - installed, + module Propellor.Property.Systemd.Core, started, stopped, enabled, @@ -14,6 +14,7 @@ import Propellor import qualified Propellor.Property.Chroot as Chroot import qualified Propellor.Property.Apt as Apt import qualified Propellor.Property.File as File +import Propellor.Property.Systemd.Core import Utility.SafeCommand import Utility.FileMode @@ -30,12 +31,6 @@ instance Hostlike Container where (Container n c h) &^ p = Container n c (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"] - -- | Starts a systemd service. started :: ServiceName -> Property started n = trivial $ cmdProperty "systemctl" ["start", n] @@ -110,20 +105,18 @@ nspawned c@(Container name (Chroot.Chroot loc system builderconf _) h) = , 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.propigateChrootInfo chroot) $ - mkChroot $ h { hostProperties = [installed] } + -- Chroot provisioning is run in systemd-only mode, + -- which sets up the chroot and ensures systemd and dbus are + -- installed, but does not handle the other provisions. + chrootprovisioned = Chroot.provisioned' + (Chroot.propigateChrootInfo chroot) chroot True -- Use nsenter to enter container and and run propellor to -- finish provisioning. containerprovisioned = Chroot.propellChroot chroot - (enterContainerProcess c) + (enterContainerProcess c) False - mkChroot = Chroot.Chroot loc system builderconf - chroot = mkChroot h + chroot = Chroot.Chroot loc system builderconf h nspawnService :: Container -> RevertableProperty nspawnService (Container name _ _) = RevertableProperty setup teardown diff --git a/src/Propellor/Property/Systemd/Core.hs b/src/Propellor/Property/Systemd/Core.hs new file mode 100644 index 0000000..441717e --- /dev/null +++ b/src/Propellor/Property/Systemd/Core.hs @@ -0,0 +1,10 @@ +module Propellor.Property.Systemd.Core where + +import Propellor +import qualified Propellor.Property.Apt as Apt + +-- 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"] diff --git a/src/Propellor/Types.hs b/src/Propellor/Types.hs index 65dbd3c..a6c5aaf 100644 --- a/src/Propellor/Types.hs +++ b/src/Propellor/Types.hs @@ -155,7 +155,7 @@ data CmdLine | Update HostName | DockerInit HostName | DockerChain HostName String - | ChrootChain HostName FilePath Bool + | ChrootChain HostName FilePath Bool Bool | GitPush Fd Fd deriving (Read, Show, Eq) From 62d5b7cdc2a6f28e8eaa1b20d5194d91271f0490 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 17:13:12 -0400 Subject: [PATCH 24/26] propellor spin From a6c7e228625456cb267b6fa4b9f75e2cbc067f0d Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 17:16:30 -0400 Subject: [PATCH 25/26] propellor spin --- config-joey.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-joey.hs b/config-joey.hs index 2971c1a..a2a501a 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -83,7 +83,7 @@ clam = standardSystem "clam.kitenet.net" Unstable "amd64" ! Chroot.provisioned testChroot & Systemd.persistentJournal - & Systemd.nspawned meow + ! Systemd.nspawned meow meow :: Systemd.Container meow = Systemd.container "meow" (Chroot.debootstrapped (System (Debian Unstable) "amd64") mempty) From 04ea987075b869ea70cf55a193af7f5604ff0561 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 21 Nov 2014 17:19:00 -0400 Subject: [PATCH 26/26] propellor spin --- config-joey.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-joey.hs b/config-joey.hs index a2a501a..2971c1a 100644 --- a/config-joey.hs +++ b/config-joey.hs @@ -83,7 +83,7 @@ clam = standardSystem "clam.kitenet.net" Unstable "amd64" ! Chroot.provisioned testChroot & Systemd.persistentJournal - ! Systemd.nspawned meow + & Systemd.nspawned meow meow :: Systemd.Container meow = Systemd.container "meow" (Chroot.debootstrapped (System (Debian Unstable) "amd64") mempty)