summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoey Hess2014-11-23 17:13:02 -0400
committerJoey Hess2014-11-23 17:13:02 -0400
commit95296a961c4ca967538e63e7d0b78f845493fcf8 (patch)
tree693a9a96797c064c6a939d713a2125bfba9a43fb /src
parentf85720415d55d836691fe04f9b9192cdc1b427ba (diff)
parentbaba668033f86b7c91f6b15c58002ea4bdbf3da2 (diff)
Merge branch 'joeyconfig'
Diffstat (limited to 'src')
-rw-r--r--src/Propellor/Property/OS.hs107
-rw-r--r--src/Propellor/Property/User.hs25
2 files changed, 127 insertions, 5 deletions
diff --git a/src/Propellor/Property/OS.hs b/src/Propellor/Property/OS.hs
new file mode 100644
index 00000000..c96e20b3
--- /dev/null
+++ b/src/Propellor/Property/OS.hs
@@ -0,0 +1,107 @@
+module Propellor.Property.OS (
+ cleanInstallOnce,
+ Confirmation
+ confirm,
+ fixupNetworkAddresses,
+ fixupRootSsh,
+ oldOSRemoved,
+) where
+
+import Propellor
+import qualified Propellor.Property.Chroot as Chroot
+import qualified Propellor.Property.Debootstrap as Debootstrap
+
+-- | Replaces whatever OS was installed before with a clean installation
+-- of the OS that the Host is configured to have.
+--
+-- This can replace one Linux distribution with different one.
+-- But, it can also fail and leave the system in an unbootable state.
+--
+-- To avoid this property being accidentially used, you have to provide
+-- a Context containing the name of the host that you intend to apply the
+-- property to.
+--
+-- This property only runs once. The cleanly installed system will have
+-- a file /etc/propellor-cleaninstall, which indicates it was cleanly
+-- installed.
+--
+-- You will typically want to run some more properties after the clean
+-- install, to bootstrap from the cleanly installed system to a fully
+-- working system. For example:
+--
+-- > & os (System (Debian Unstable) "amd64")
+-- > & cleanInstall (Context "foo.example.com") (BackupOldOS <> UseOldKernel)
+-- > `onChange` propertyList "fixing up after clean install"
+-- > [ fixupNetworkInterfaces
+-- > , fixupRootSsh
+-- > -- , installDistroKernel
+-- > -- , installGrub
+-- > ]
+-- > & Apt.installed ["ssh"]
+-- > & User.hasSomePassword "root"
+-- > & User.accountFor "joey"
+-- > & User.hasSomePassword "joey"
+-- > -- rest of system properties here
+cleanInstallOnce :: Context -> Exceptions -> Property
+cleanInstallOnce (Context c) = check (not <$> doesFileExist flagfile) $
+ Property "OS cleanly installed" $ do
+ hostname <- asks hostName
+ when (hostname /= c) $
+ error "Run with bad context, not matching hostname. Not running cleanInstalOnce!"
+ error "TODO"
+ -- debootstrap /new-os chroot, but don't run propellor
+ -- inside the chroot.
+ -- unmount all mounts
+ -- move all directories to /old-os,
+ -- except for /boot and /lib/modules
+ -- move /new-os to /
+ -- touch flagfile
+ -- re-bootstrap propellor in /usr/local/propellor,
+ -- (using git repo bundle, privdata file, and possibly
+ -- git repo url, which all need to be arranged to
+ -- be present in /old-os's /usr/local/propellor)
+ -- enable shadow passwords (to avoid foot-shooting)
+ -- return MadeChange
+ where
+ flagfile = "/etc/propellor-cleaninstall"
+
+-- | Sometimes you want an almost clean install, but with some exceptions.
+data Exceptions
+ = UseOldKernel -- ^ Leave /boot and /lib/modules from old OS, so the system can boot using them as before
+ | BackupOldOS -- ^ Back up old OS to /old-os, to avoid losing any important files
+ | NoExceptions
+ | CombinedExceptions Exceptions Exceptions
+
+instance Monoid Exceptions where
+ mempty = NoExceptions
+ mappend = CombinedExceptions
+
+-- /etc/network/interfaces is configured to bring up all interfaces that
+-- are currently up, using the same IP addresses.
+--
+-- This property only does anything if it comes after cleanInstall,
+-- in the same propellor run where cleanInstall has made a change.
+fixupNetworkInterfaces :: Property
+fixupNetworkInterfaces = undefined
+
+-- /root/.ssh/authorized_keys is copied from the old os
+fixupRootSsh :: Property
+fixupRootSsh = undefined
+
+-- Installs an appropriate kernel from the distribution.
+installDistroKernel :: Property
+installDistroKernel = undefined
+
+-- Installs grub to boot the system.
+installGrub :: Property
+installGrub = undefined
+
+-- Removes the old OS's backup from /old-os
+oldOSRemoved :: Property
+oldOSRemoved = check (doesDirectoryExist oldOsDir) $
+ Property "old OS backup removed" $ liftIO $ do
+ removeDirectoryRecursive oldOsDir
+ return MadeChange
+
+oldOsDir :: FilePath
+oldOsDir = "/old-os"
diff --git a/src/Propellor/Property/User.hs b/src/Propellor/Property/User.hs
index 6a51703a..434a92a3 100644
--- a/src/Propellor/Property/User.hs
+++ b/src/Propellor/Property/User.hs
@@ -24,12 +24,27 @@ nuked user _ = check (isJust <$> catchMaybeIO (homedir user)) $ cmdProperty "use
-- | Only ensures that the user has some password set. It may or may
-- not be the password from the PrivData.
-hasSomePassword :: UserName -> Context -> Property
-hasSomePassword user context = check ((/= HasPassword) <$> getPasswordStatus user) $
- hasPassword user context
+hasSomePassword :: UserName -> Property
+hasSomePassword user = property (user ++ "has password") $ do
+ hostname <- asks hostName
+ ensureProperty $ hasSomePassword' user (Context hostname)
-hasPassword :: UserName -> Context -> Property
-hasPassword user context = withPrivData (Password user) context $ \getpassword ->
+-- | While hasSomePassword uses the name of the host as context,
+-- this allows specifying a different context. This is useful when
+-- you want to use the same password on multiple hosts, for example.
+hasSomePassword' :: UserName -> Context -> Property
+hasSomePassword' user context = check ((/= HasPassword) <$> getPasswordStatus user) $
+ hasPassword' user context
+
+-- | Ensures that a user's password is set to the password from the PrivData.
+-- (Will change any existing password.)
+hasPassword :: UserName -> Property
+hasPassword user = property (user ++ "has password") $ do
+ hostname <- asks hostName
+ ensureProperty $ hasPassword' user (Context hostname)
+
+hasPassword' :: UserName -> Context -> Property
+hasPassword' user context = withPrivData (Password user) context $ \getpassword ->
property (user ++ " has password") $
getpassword $ \password -> makeChange $
withHandle StdinHandle createProcessSuccess