From d8624e2e5df9baf6883eb91b4be8282fb4b62304 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sun, 23 Nov 2014 15:42:22 -0400 Subject: WIP --- src/Propellor/Property/OS.hs | 108 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 src/Propellor/Property/OS.hs (limited to 'src') diff --git a/src/Propellor/Property/OS.hs b/src/Propellor/Property/OS.hs new file mode 100644 index 00000000..914fb9f3 --- /dev/null +++ b/src/Propellor/Property/OS.hs @@ -0,0 +1,108 @@ +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. +-- +-- 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 (confirm "com.example.foo") (BackupOldOS <> UseOldKernel) +-- > `onChange` propertyList "fixing up after clean install" +-- > [ fixupNetworkInterfaces +-- > , fixupRootSsh +-- > -- , installDistroKernel +-- > -- , installGrub +-- > ] +-- > & Apt.installed ["ssh"] +-- > -- rest of system properties here +cleanInstallOnce :: Confirmation -> Exceptions -> Property +cleanInstallOnce c = check (not <$> doesFileExist flagfile) $ + Property "OS cleanly installed" $ do + confirm c + error "TODO" + -- debootstrap /new-os chroot; avoid running + -- propellor inside the chroot yet + -- unmount all mounts + -- move all directories to /old-os, + -- except for /boot and /lib/modules + -- move /new-os to / + -- touch /etc/propellor-cleaninstall + -- 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) + -- return MadeChange + where + flagfile = "/etc/propellor-cleaninstall" + +-- | To confirm you really intend to apply a dangerous Property to a +-- system, and have not copied and pasted it in by accident, you must +-- provide as confirmation, the hostname of the system you intend +-- to apply the Property to, written in the form form "com.example.somehost" +newtype Confirmation = Confirmation String + +confirm :: String -> Confirmation +confirm (Confirmation c) h + | h ==(intercalate "." $ reverse $ split "." c) = return () + | otherwise = error "Bad confirmation of dangerous Property; see the documentation to fix this." + +-- | 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" -- cgit v1.2.3