diff options
| author | Joey Hess <joey@kitenet.net> | 2014-11-23 17:13:02 -0400 |
|---|---|---|
| committer | Joey Hess <joey@kitenet.net> | 2014-11-23 17:13:02 -0400 |
| commit | 95296a961c4ca967538e63e7d0b78f845493fcf8 (patch) | |
| tree | 693a9a96797c064c6a939d713a2125bfba9a43fb /src | |
| parent | f85720415d55d836691fe04f9b9192cdc1b427ba (diff) | |
| parent | baba668033f86b7c91f6b15c58002ea4bdbf3da2 (diff) | |
Merge branch 'joeyconfig'
Diffstat (limited to 'src')
| -rw-r--r-- | src/Propellor/Property/OS.hs | 107 | ||||
| -rw-r--r-- | src/Propellor/Property/User.hs | 25 |
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 |
