packages feed

propellor 4.9.0 → 5.0.0

raw patch · 24 files changed

+881/−211 lines, 24 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Propellor.Property.Chroot: noServices :: RevertableProperty UnixLike UnixLike
- Propellor.Property.Debootstrap: programPath :: IO (Maybe FilePath)
- Propellor.Property.DiskImage.PartSpec: fudge :: PartSize -> PartSize
- Propellor.Types.PartSpec: adjustp :: PartSpec t -> (Partition -> Partition) -> PartSpec t
- Propellor.Types.PartSpec: adjustt :: PartSpec t -> (t -> t) -> PartSpec t
- Propellor.Types.PartSpec: defSz :: PartSize
- Propellor.Types.PartSpec: errorReadonly :: MountOpts
- Propellor.Types.PartSpec: extended :: PartSpec t -> PartSpec t
- Propellor.Types.PartSpec: mountOpt :: ToMountOpts o => PartSpec t -> o -> PartSpec t
- Propellor.Types.PartSpec: mountedAt :: PartSpec t -> FilePath -> PartSpec t
- Propellor.Types.PartSpec: partition :: Monoid t => Fs -> PartSpec t
- Propellor.Types.PartSpec: reservedSpacePercentage :: PartSpec t -> Int -> PartSpec t
- Propellor.Types.PartSpec: setFlag :: PartSpec t -> PartFlag -> PartSpec t
- Propellor.Types.PartSpec: setSize :: PartSpec t -> PartSize -> PartSpec t
- Propellor.Types.PartSpec: swapPartition :: Monoid t => PartSize -> PartSpec t
+ Propellor.Property: impossible :: SingI t => String -> Property (MetaTypes t)
+ Propellor.Property.Debootstrap: UseEmulation :: DebootstrapConfig
+ Propellor.Property.DiskImage: imageBuiltFor :: (DiskImage d, ChrootBootstrapper bootstrapper) => Host -> d -> bootstrapper -> RevertableProperty (HasInfo + DebianLike) Linux
+ Propellor.Property.DiskImage: imageRebuiltFor :: (DiskImage d, ChrootBootstrapper bootstrapper) => Host -> d -> bootstrapper -> RevertableProperty (HasInfo + DebianLike) Linux
+ Propellor.Property.DiskImage.PartSpec: AIX :: TableType
+ Propellor.Property.DiskImage.PartSpec: AMIGA :: TableType
+ Propellor.Property.DiskImage.PartSpec: BSD :: TableType
+ Propellor.Property.DiskImage.PartSpec: BTRFS :: Fs
+ Propellor.Property.DiskImage.PartSpec: Beginning :: PartLocation
+ Propellor.Property.DiskImage.PartSpec: DVH :: TableType
+ Propellor.Property.DiskImage.PartSpec: EXT2 :: Fs
+ Propellor.Property.DiskImage.PartSpec: EXT3 :: Fs
+ Propellor.Property.DiskImage.PartSpec: EXT4 :: Fs
+ Propellor.Property.DiskImage.PartSpec: End :: PartLocation
+ Propellor.Property.DiskImage.PartSpec: FAT :: Fs
+ Propellor.Property.DiskImage.PartSpec: GPT :: TableType
+ Propellor.Property.DiskImage.PartSpec: LOOP :: TableType
+ Propellor.Property.DiskImage.PartSpec: LinuxSwap :: Fs
+ Propellor.Property.DiskImage.PartSpec: MAC :: TableType
+ Propellor.Property.DiskImage.PartSpec: MSDOS :: TableType
+ Propellor.Property.DiskImage.PartSpec: MegaBytes :: Integer -> PartSize
+ Propellor.Property.DiskImage.PartSpec: Middle :: PartLocation
+ Propellor.Property.DiskImage.PartSpec: NTFS :: Fs
+ Propellor.Property.DiskImage.PartSpec: PC98 :: TableType
+ Propellor.Property.DiskImage.PartSpec: PartTableSpec :: TableType -> [PartSpec ()] -> PartTableSpec
+ Propellor.Property.DiskImage.PartSpec: REISERFS :: Fs
+ Propellor.Property.DiskImage.PartSpec: SUN :: TableType
+ Propellor.Property.DiskImage.PartSpec: VFAT :: Fs
+ Propellor.Property.DiskImage.PartSpec: XFS :: Fs
+ Propellor.Property.DiskImage.PartSpec: adjustPartition :: MountPoint -> (PartSpec PartLocation -> PartSpec PartLocation) -> Property (HasInfo + UnixLike)
+ Propellor.Property.DiskImage.PartSpec: data Fs
+ Propellor.Property.DiskImage.PartSpec: data PartInfo
+ Propellor.Property.DiskImage.PartSpec: data PartLocation
+ Propellor.Property.DiskImage.PartSpec: data PartTableSpec
+ Propellor.Property.DiskImage.PartSpec: data TableType
+ Propellor.Property.DiskImage.PartSpec: errorReadonly :: MountOpts
+ Propellor.Property.DiskImage.PartSpec: extended :: PartSpec t -> PartSpec t
+ Propellor.Property.DiskImage.PartSpec: hasPartition :: PartSpec PartLocation -> Property (HasInfo + UnixLike)
+ Propellor.Property.DiskImage.PartSpec: hasPartitionTableType :: TableType -> Property (HasInfo + UnixLike)
+ Propellor.Property.DiskImage.PartSpec: instance GHC.Base.Monoid Propellor.Property.DiskImage.PartSpec.PartInfo
+ Propellor.Property.DiskImage.PartSpec: instance GHC.Base.Monoid Propellor.Property.DiskImage.PartSpec.PartLocation
+ Propellor.Property.DiskImage.PartSpec: instance GHC.Classes.Eq Propellor.Property.DiskImage.PartSpec.PartLocation
+ Propellor.Property.DiskImage.PartSpec: instance GHC.Classes.Ord Propellor.Property.DiskImage.PartSpec.PartLocation
+ Propellor.Property.DiskImage.PartSpec: instance GHC.Show.Show Propellor.Property.DiskImage.PartSpec.PartInfo
+ Propellor.Property.DiskImage.PartSpec: instance Propellor.Types.Info.IsInfo Propellor.Property.DiskImage.PartSpec.PartInfo
+ Propellor.Property.DiskImage.PartSpec: mountOpt :: ToMountOpts o => PartSpec t -> o -> PartSpec t
+ Propellor.Property.DiskImage.PartSpec: mountedAt :: PartSpec t -> MountPoint -> PartSpec t
+ Propellor.Property.DiskImage.PartSpec: newtype PartSize
+ Propellor.Property.DiskImage.PartSpec: partLocation :: PartSpec PartLocation -> PartLocation -> PartSpec PartLocation
+ Propellor.Property.DiskImage.PartSpec: partition :: Monoid t => Fs -> PartSpec t
+ Propellor.Property.DiskImage.PartSpec: reservedSpacePercentage :: PartSpec t -> Int -> PartSpec t
+ Propellor.Property.DiskImage.PartSpec: setFlag :: PartSpec t -> PartFlag -> PartSpec t
+ Propellor.Property.DiskImage.PartSpec: setSize :: PartSpec t -> PartSize -> PartSpec t
+ Propellor.Property.DiskImage.PartSpec: swapPartition :: Monoid t => PartSize -> PartSpec t
+ Propellor.Property.DiskImage.PartSpec: toPartTableSpec :: PartInfo -> PartTableSpec
+ Propellor.Property.DiskImage.PartSpec: type PartSpec t = (Maybe MountPoint, MountOpts, PartSize -> Partition, t)
+ Propellor.Property.Fail2Ban: actionConfFile :: Action -> FilePath
+ Propellor.Property.Fail2Ban: filterConfFile :: Filter -> FilePath
+ Propellor.Property.Fail2Ban: jailConfigured' :: Jail -> [(IniKey, String)] -> Property UnixLike
+ Propellor.Property.Fail2Ban: jailEnabled' :: Jail -> [(IniKey, String)] -> Property DebianLike
+ Propellor.Property.Fail2Ban: oldJailConfFile :: Jail -> FilePath
+ Propellor.Property.Fail2Ban: type Action = String
+ Propellor.Property.Fail2Ban: type Filter = String
+ Propellor.Property.FlashKernel: flashKernelMounted :: FilePath -> Property Linux
+ Propellor.Property.FlashKernel: installed :: Machine -> Property (HasInfo + DebianLike)
+ Propellor.Property.FlashKernel: type Machine = String
+ Propellor.Property.Machine: Marvell_SheevaPlug_ESATA :: Marvell_SheevaPlug_BootDevice
+ Propellor.Property.Machine: Marvell_SheevaPlug_SDCard :: Marvell_SheevaPlug_BootDevice
+ Propellor.Property.Machine: cubietech_Cubieboard :: Property (HasInfo + DebianLike)
+ Propellor.Property.Machine: cubietech_Cubieboard2 :: Property (HasInfo + DebianLike)
+ Propellor.Property.Machine: cubietech_Cubietruck :: Property (HasInfo + DebianLike)
+ Propellor.Property.Machine: data Marvell_SheevaPlug_BootDevice
+ Propellor.Property.Machine: lemaker_Banana_Pi :: Property (HasInfo + DebianLike)
+ Propellor.Property.Machine: lemaker_Banana_Pro :: Property (HasInfo + DebianLike)
+ Propellor.Property.Machine: linkSprite_pcDuino3_Nano :: Property (HasInfo + DebianLike)
+ Propellor.Property.Machine: marvell_SheevaPlug :: Marvell_SheevaPlug_BootDevice -> Property (HasInfo + DebianLike)
+ Propellor.Property.Machine: olimex_A10_OLinuXino_LIME :: Property (HasInfo + DebianLike)
+ Propellor.Property.Machine: olimex_A10s_OLinuXino_Micro :: Property (HasInfo + DebianLike)
+ Propellor.Property.Machine: olimex_A20_OLinuXino_LIME :: Property (HasInfo + DebianLike)
+ Propellor.Property.Machine: olimex_A20_OLinuXino_LIME2 :: Property (HasInfo + DebianLike)
+ Propellor.Property.Machine: olimex_A20_OLinuXino_Micro :: Property (HasInfo + DebianLike)
+ Propellor.Property.Machine: olimex_A20_SOM_EVB :: Property (HasInfo + DebianLike)
+ Propellor.Property.Mount: getMountContaining :: FilePath -> IO (Maybe Source)
+ Propellor.Property.Parted: defSz :: PartSize
+ Propellor.Property.Parted: fudgeSz :: PartSize -> PartSize
+ Propellor.Property.Qemu: foreignBinariesEmulated :: RevertableProperty Linux Linux
+ Propellor.Property.Qemu: removeHostEmulationBinary :: FilePath -> Property Linux
+ Propellor.Property.Qemu: supportsArch :: System -> Architecture -> Bool
+ Propellor.Property.Service: NoServices :: NoServices
+ Propellor.Property.Service: data NoServices
+ Propellor.Property.Service: instance GHC.Classes.Eq Propellor.Property.Service.NoServices
+ Propellor.Property.Service: instance GHC.Show.Show Propellor.Property.Service.NoServices
+ Propellor.Property.Service: noServices :: RevertableProperty (HasInfo + UnixLike) UnixLike
+ Propellor.Property.Service: servicesDisabled :: Propellor Bool
+ Propellor.Property.Uboot: sunxi :: BoardName -> Property (HasInfo + DebianLike)
+ Propellor.Property.Uboot: type BoardName = String
+ Propellor.Types.Bootloader: FlashKernelInstalled :: BootloaderInstalled
+ Propellor.Types.Bootloader: UbootInstalled :: (FilePath -> FilePath -> Property Linux) -> BootloaderInstalled
+ Propellor.Types.PartSpec: PartTableSpec :: TableType -> [PartSpec ()] -> PartTableSpec
+ Propellor.Types.PartSpec: data PartTableSpec
+ Propellor.Types.PartSpec: instance GHC.Show.Show Propellor.Types.PartSpec.PartTableSpec
- Propellor.Property.Mount: findmntField :: String -> FilePath -> IO (Maybe String)
+ Propellor.Property.Mount: findmntField :: String -> [String] -> IO (Maybe String)

Files

CHANGELOG view
@@ -1,3 +1,26 @@+propellor (5.0.0) unstable; urgency=medium++  * Debootstrap.built now supports bootstrapping chroots for foreign+    OS's, using qemu-user-static.+  * Machine: New module collecting machine-specific properties for +    building bootable images for ARM boards.+    Tested working boards: Olimex Lime, CubieTruck, Banana Pi, SheevaPlug.+  * Diskimage.imageBuiltFor: New property to build a disk image for a Host,+    using partition table information configured via the new properties+    hasPartitionTableType, hasPartition and adjustPartition.+  * Chroot.noServices moved to Service.noServices and its type changed.+    (API change)+  * Service: Avoid starting services when noServices is used.+  * Add Typeable instance to OriginUrl, fixing build with old versions+    of ghc.+  * Added Propellor.Property.impossible+  * Fail2Ban: Added several additional properties.+    Thanks, Félix Sipma.+  * Fail2Ban: Renamed jail.d conf file to use .local.+    Thanks, Félix Sipma.++ -- Joey Hess <id@joeyh.name>  Sun, 19 Nov 2017 15:42:44 -0400+ propellor (4.9.0) unstable; urgency=medium    * When the ipv4 and ipv6 properties are used with a container, avoid
debian/changelog view
@@ -1,3 +1,26 @@+propellor (5.0.0) unstable; urgency=medium++  * Debootstrap.built now supports bootstrapping chroots for foreign+    OS's, using qemu-user-static.+  * Machine: New module collecting machine-specific properties for +    building bootable images for ARM boards.+    Tested working boards: Olimex Lime, CubieTruck, Banana Pi, SheevaPlug.+  * Diskimage.imageBuiltFor: New property to build a disk image for a Host,+    using partition table information configured via the new properties+    hasPartitionTableType, hasPartition and adjustPartition.+  * Chroot.noServices moved to Service.noServices and its type changed.+    (API change)+  * Service: Avoid starting services when noServices is used.+  * Add Typeable instance to OriginUrl, fixing build with old versions+    of ghc.+  * Added Propellor.Property.impossible+  * Fail2Ban: Added several additional properties.+    Thanks, Félix Sipma.+  * Fail2Ban: Renamed jail.d conf file to use .local.+    Thanks, Félix Sipma.++ -- Joey Hess <id@joeyh.name>  Sun, 19 Nov 2017 15:42:44 -0400+ propellor (4.9.0) unstable; urgency=medium    * When the ipv4 and ipv6 properties are used with a container, avoid
joeyconfig.hs view
@@ -6,6 +6,8 @@ import Propellor.Property.Scheduled import Propellor.Property.DiskImage import Propellor.Property.Chroot+import Propellor.Property.Machine+import Propellor.Property.Bootstrap import qualified Propellor.Property.File as File import qualified Propellor.Property.Apt as Apt import qualified Propellor.Property.Network as Network@@ -23,6 +25,7 @@ import qualified Propellor.Property.Postfix as Postfix import qualified Propellor.Property.Apache as Apache import qualified Propellor.Property.LetsEncrypt as LetsEncrypt+import qualified Propellor.Property.Locale as Locale import qualified Propellor.Property.Grub as Grub import qualified Propellor.Property.Borg as Borg import qualified Propellor.Property.Gpg as Gpg@@ -94,16 +97,9 @@ 	& Ssh.userKeys (User "joey") hostContext 		[ (SshRsa, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC1YoyHxZwG5Eg0yiMTJLSWJ/+dMM6zZkZiR4JJ0iUfP+tT2bm/lxYompbSqBeiCq+PYcSC67mALxp1vfmdOV//LWlbXfotpxtyxbdTcQbHhdz4num9rJQz1tjsOsxTEheX5jKirFNC5OiKhqwIuNydKWDS9qHGqsKcZQ8p+n1g9Lr3nJVGY7eRRXzw/HopTpwmGmAmb9IXY6DC2k91KReRZAlOrk0287LaK3eCe1z0bu7LYzqqS+w99iXZ/Qs0m9OqAPnHZjWQQ0fN4xn5JQpZSJ7sqO38TBAimM+IHPmy2FTNVVn9zGM+vN1O2xr3l796QmaUG1+XLL0shfR/OZbb joey@darkstar") 		]-	& imageBuilt (VirtualBoxPointer "/srv/test.vmdk") mychroot MSDOS-		[ partition EXT2 `mountedAt` "/boot"-		, partition EXT4 `mountedAt` "/"-		, swapPartition (MegaBytes 256)-		]-  where-	mychroot d = debootstrapped mempty d $ props-		& osDebian Unstable X86_64-		& Apt.installed ["linux-image-amd64"]-		& Grub.installed PC+	& imageBuiltFor honeybee+		(RawDiskImage "/srv/honeybee.img")+		(Debootstrapped mempty)  gnu :: Host gnu = host "gnu.kitenet.net" $ props@@ -184,22 +180,30 @@ honeybee = host "honeybee.kitenet.net" $ props 	& standardSystem Testing ARMHF 		[ "Home router and arm git-annex build box." ]--	-- Hard to get console access, so no automatic upgrades,-	-- and try to be robust.-	& "/etc/default/rcS" `File.containsLine` "FSCKFIX=yes"--	-- Cubietruck-	& Apt.installed ["flash-kernel"]-	& "/etc/flash-kernel/machine" `File.hasContent` ["Cubietech Cubietruck"]-	& Apt.installed ["linux-image-armmp"]+	+	& cubietech_Cubietruck+	& hasPartition+		( partition EXT2+			`mountedAt` "/boot"+			`partLocation` Beginning+			`setSize` MegaBytes 200+		)+	& hasPartition+		( partition EXT4+			`mountedAt` "/"+			`addFreeSpace` MegaBytes 500+		)+	 	& Apt.installed ["firmware-brcm80211"] 		-- Workaround for https://bugs.debian.org/844056 		`requires` File.hasPrivContent "/lib/firmware/brcm/brcmfmac43362-sdio.txt" anyContext 		`requires` File.dirExists "/lib/firmware/brcm"--	-- No hardware clock-	& Apt.serviceInstalledRunning "ntp"+	& "/etc/default/rcS" `File.containsLine` "FSCKFIX=yes"+	& Apt.serviceInstalledRunning "ntp" -- no hardware clock+	& bootstrappedFrom GitRepoOutsideChroot+	& Ssh.hostKeys hostContext+		[ (SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIS/hDYq1MAxfOBf49htym3BOYlx4Gk9SDpiHjv7u6IC")+		]  	& JoeySites.homePowerMonitor 		(User "joey")@@ -209,19 +213,13 @@ 	& Apt.installed ["mtr-tiny", "iftop", "screen"] 	& Postfix.satellite -	& Systemd.nspawned (GitAnnexBuilder.autoBuilderContainer-		GitAnnexBuilder.armAutoBuilder-		Unstable ARMEL Nothing (Cron.Times "15 10 * * *") "10h")-	-- Disabled because it does not work, and the old systemd-	-- in the container uses a ton of CPU-	! Systemd.nspawned (GitAnnexBuilder.autoBuilderContainer-		GitAnnexBuilder.stackAutoBuilder-		(Stable "jessie") ARMEL (Just "ancient") weekdays "10h")+	& check (not <$> inChroot) (setupRevertableProperty autobuilder) 	-- In case compiler needs more than available ram 	& Apt.serviceInstalledRunning "swapspace"   where-	weekdays = Cron.Times "15 10 * * 2-5"-	-- weekends = Cron.Times "15 10 * * 6-7"+	autobuilder = Systemd.nspawned $ GitAnnexBuilder.autoBuilderContainer+		GitAnnexBuilder.armAutoBuilder+		Unstable ARMEL Nothing (Cron.Times "15 10 * * *") "10h"  -- This is not a complete description of kite, since it's a -- multiuser system with eg, user passwords that are not deployed@@ -565,6 +563,7 @@ 	& osDebian suite arch 	& Hostname.sane 	& Hostname.searchDomain+	& Locale.available "en_US.UTF-8" 	& File.hasContent "/etc/motd" ("":motd++[""]) 	& Apt.stdSourcesList `onChange` Apt.upgrade 	& Apt.cacheCleaned
propellor.cabal view
@@ -1,5 +1,5 @@ Name: propellor-Version: 4.9.0+Version: 5.0.0 Cabal-Version: >= 1.20 License: BSD2 Maintainer: Joey Hess <id@joeyh.name>@@ -111,6 +111,7 @@     Propellor.Property.File     Propellor.Property.Firejail     Propellor.Property.Firewall+    Propellor.Property.FlashKernel     Propellor.Property.FreeBSD     Propellor.Property.FreeBSD.Pkg     Propellor.Property.FreeBSD.Poudriere@@ -128,6 +129,7 @@     Propellor.Property.Locale     Propellor.Property.Logcheck     Propellor.Property.Lvm+    Propellor.Property.Machine     Propellor.Property.Mount     Propellor.Property.Network     Propellor.Property.Nginx@@ -141,6 +143,7 @@     Propellor.Property.Postfix     Propellor.Property.PropellorRepo     Propellor.Property.Prosody+    Propellor.Property.Qemu     Propellor.Property.Reboot     Propellor.Property.Restic     Propellor.Property.Rsync@@ -154,6 +157,7 @@     Propellor.Property.Systemd.Core     Propellor.Property.Timezone     Propellor.Property.Tor+    Propellor.Property.Uboot     Propellor.Property.Unbound     Propellor.Property.User     Propellor.Property.Uwsgi
src/Propellor/Bootstrap.hs view
@@ -80,7 +80,7 @@   where 	go Cabal = 		[ "cabal configure"-		, "cabal build propellor-config"+		, "cabal build -j1 propellor-config" 		, "ln -sf dist/build/propellor-config/propellor-config propellor" 		] 	go Stack =@@ -280,7 +280,9 @@ 				boolSystem "sh" [Param "-c", Param (depsCommand (Robustly Cabal) (Just sys))] 					<&&> cabal ["configure"] 		)-	cabal_build = cabal ["build", "propellor-config"]+	-- The -j1 is to only run one job at a time -- in some situations,+	-- eg in qemu, ghc does not run reliably in parallel.+	cabal_build = cabal ["build", "-j1", "propellor-config"]  stackBuild :: Maybe System -> IO Bool stackBuild _msys = do
src/Propellor/Property.hs view
@@ -32,6 +32,7 @@ 	, makeChange 	, noChange 	, doNothing+	, impossible 	, endAction 	-- * Property result checking 	, UncheckedProperty@@ -62,6 +63,7 @@ import Propellor.Types.MetaTypes import Propellor.Types.Singletons import Propellor.Info+import Propellor.Message import Propellor.EnsureProperty import Utility.Exception import Utility.Monad@@ -363,6 +365,12 @@ -- This is the same as `mempty` from the `Monoid` instance. doNothing :: SingI t => Property (MetaTypes t) doNothing = mempty++-- | In situations where it's not possible to provide a property that+-- works, this can be used to make a property that always fails with an+-- error message you provide.+impossible :: SingI t => String -> Property (MetaTypes t)+impossible msg = property "impossible" $ errorMessage msg  -- | Registers an action that should be run at the very end, after -- propellor has checks all the properties of a host.
src/Propellor/Property/Chroot.hs view
@@ -9,7 +9,6 @@ 	ChrootBootstrapper(..), 	Debootstrapped(..), 	ChrootTarball(..),-	noServices, 	inChroot, 	exposeTrueLocaldir, 	-- * Internal use@@ -32,7 +31,6 @@ import qualified Propellor.Property.File as File import qualified Propellor.Shim as Shim import Propellor.Property.Mount-import Utility.FileMode import Utility.Split  import qualified Data.Map as M@@ -256,26 +254,6 @@  chrootDesc :: Chroot -> String -> String chrootDesc (Chroot loc _ _ _) desc = "chroot " ++ loc ++ " " ++ desc---- | Adding this property to a chroot prevents daemons and other services--- from being started, which is often something you want to prevent when--- building a chroot.------ On Debian, this is accomplished by installing a </usr/sbin/policy-rc.d>--- script that does not let any daemons be started by packages that use--- invoke-rc.d. Reverting the property removes the script.------ This property has no effect on non-Debian systems.-noServices :: RevertableProperty UnixLike UnixLike-noServices = setup <!> teardown-  where-	f = "/usr/sbin/policy-rc.d"-	script = [ "#!/bin/sh", "exit 101" ]-	setup = combineProperties "no services started" $ toProps-		[ File.hasContent f script-		, File.mode f (combineModes (readModes ++ executeModes))-		]-	teardown = File.notPresent f  -- | Check if propellor is currently running within a chroot. --
src/Propellor/Property/Debootstrap.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE TypeFamilies #-}+ module Propellor.Property.Debootstrap ( 	Url, 	DebootstrapConfig(..),@@ -6,12 +8,12 @@ 	extractSuite, 	installed, 	sourceInstall,-	programPath, ) where  import Propellor.Base import qualified Propellor.Property.Apt as Apt import Propellor.Property.Chroot.Util+import Propellor.Property.Qemu import Utility.Path import Utility.FileMode @@ -29,6 +31,7 @@ 	| MinBase 	| BuilddD 	| DebootstrapParam String+	| UseEmulation 	| DebootstrapConfig :+ DebootstrapConfig 	deriving (Show) @@ -41,15 +44,41 @@ toParams MinBase = [Param "--variant=minbase"] toParams BuilddD = [Param "--variant=buildd"] toParams (DebootstrapParam p) = [Param p]+toParams UseEmulation = [] toParams (c1 :+ c2) = toParams c1 <> toParams c2 +useEmulation :: DebootstrapConfig -> Bool+useEmulation UseEmulation = True+useEmulation (a :+ b) = useEmulation a || useEmulation b+useEmulation _ = False+ -- | Builds a chroot in the given directory using debootstrap. -- -- The System can be any OS and architecture that debootstrap -- and the kernel support.+--+-- When the System is architecture that the kernel does not support,+-- it can still be bootstrapped using emulation. This is determined+-- by checking `supportsArch`, or can be configured with `UseEmulation`.+--+-- When emulation is used, the chroot will have an additional binary +-- installed in it. To get a completelty clean chroot (eg for producing a+-- bootable disk image), use the `removeHostEmulationBinary` property. built :: FilePath -> System -> DebootstrapConfig -> Property Linux-built target system config = built' (setupRevertableProperty installed) target system config+built target system@(System _ targetarch) config =+	withOS ("debootstrapped " ++ target) go+  where+	go w (Just hostos)+		| supportsArch hostos targetarch && not (useEmulation config) =+			ensureProperty w $+				built' (setupRevertableProperty installed)+					target system config+	go w _ = ensureProperty w $ do+		let p = setupRevertableProperty foreignBinariesEmulated+			`before` setupRevertableProperty installed+		built' p target system (config :+ UseEmulation) +-- | Like `built`,  but uses the provided Property to install debootstrap. built' :: Property Linux -> FilePath -> System -> DebootstrapConfig -> Property Linux built' installprop target system@(System _ arch) config =  	go `before` oldpermfix@@ -68,7 +97,9 @@ 			, Param suite 			, Param target 			]-		cmd <- fromMaybe "debootstrap" <$> programPath+		cmd <- if useEmulation config+			then pure "qemu-debootstrap"+			else fromMaybe "debootstrap" <$> programPath 		de <- standardPathEnv 		ifM (boolSystemEnv cmd params (Just de)) 			( return MadeChange
src/Propellor/Property/DiskImage.hs view
@@ -13,6 +13,8 @@ 	VirtualBoxPointer(..), 	imageBuilt, 	imageRebuilt,+	imageBuiltFor,+	imageRebuiltFor, 	imageBuiltFrom, 	imageExists, 	Grub.BIOS(..),@@ -24,9 +26,12 @@ import Propellor.Property.Chroot.Util (removeChroot) import Propellor.Property.Mount import qualified Propellor.Property.Chroot as Chroot+import qualified Propellor.Property.Service as Service import qualified Propellor.Property.Grub as Grub import qualified Propellor.Property.File as File import qualified Propellor.Property.Apt as Apt+import qualified Propellor.Property.Qemu as Qemu+import qualified Propellor.Property.FlashKernel as FlashKernel import Propellor.Property.Parted import Propellor.Property.Fstab (SwapPartition(..), genFstab) import Propellor.Property.Partition@@ -101,7 +106,7 @@ -- to avoid expensive IO to generate a new one. And, it's updated in-place, -- so its contents are undefined during the build process. ----- Note that the `Chroot.noServices` property is automatically added to the+-- Note that the `Service.noServices` property is automatically added to the -- chroot while the disk image is being built, which should prevent any -- daemons that are included from being started on the system that is -- building the disk image.@@ -131,37 +136,60 @@ -- > 		& User.hasPassword (User "demo") -- >		& User.hasDesktopGroups (User "demo") -- > 		& ...+imageBuilt :: DiskImage d => d -> (FilePath -> Chroot) -> TableType -> [PartSpec ()] -> RevertableProperty (HasInfo + DebianLike) Linux+imageBuilt = imageBuilt' False++-- | Like 'imageBuilt', but the chroot is deleted and rebuilt from scratch+-- each time. This is more expensive, but useful to ensure reproducible+-- results when the properties of the chroot have been changed.+imageRebuilt :: DiskImage d => d -> (FilePath -> Chroot) -> TableType -> [PartSpec ()] -> RevertableProperty (HasInfo + DebianLike) Linux+imageRebuilt = imageBuilt' True++-- | Create a bootable disk image for a Host. ----- This can also be used with `Chroot.hostChroot` to build a disk image--- that has all the properties of a Host. For example:+-- This works just like 'imageBuilt', but partition table is+-- determined by looking at the Host's 'hasPartitionTableType',+-- `hasPartition', and 'adjustPartition' properties. --+-- For example:+-- -- > foo :: Host -- > foo = host "foo.example.com" $ props--- >	& imageBuilt (RawDiskImage "/srv/diskimages/bar-disk.img")--- >		(hostChroot bar (Debootstrapped mempty))--- >		MSDOS--- >		[ partition EXT2 `mountedAt` "/boot"--- >			`setFlag` BootFlag--- >		, partition EXT4 `mountedAt` "/"--- >			`addFreeSpace` MegaBytes 5000--- >		, swapPartition (MegaBytes 256)--- >		]+-- >	& imageBuiltFor bar+-- >		(RawDiskImage "/srv/diskimages/bar-disk.img")+-- >		(Debootstrapped mempty) -- > -- > bar :: Host -- > bar = host "bar.example.com" $ props+-- >	& hasPartiton+-- >		( partition EXT2+-- >		`mountedAt` "/boot"+-- >		`partLocation` Beginning+-- >		`addFreeSpace` MegaBytes 150+-- >		)+-- >	& hasPartiton+-- >		( partition EXT4+-- >		`mountedAt` "/"+-- >		`addFreeSpace` MegaBytes 500+-- >		) -- >	& osDebian Unstable X86_64 -- >	& Apt.installed ["linux-image-amd64"] -- >	& Grub.installed PC -- >	& hasPassword (User "root")-imageBuilt :: DiskImage d => d -> (FilePath -> Chroot) -> TableType -> [PartSpec ()] -> RevertableProperty (HasInfo + DebianLike) Linux-imageBuilt = imageBuilt' False+imageBuiltFor :: (DiskImage d, Chroot.ChrootBootstrapper bootstrapper) => Host -> d -> bootstrapper -> RevertableProperty (HasInfo + DebianLike) Linux+imageBuiltFor = imageBuiltFor' False --- | Like 'built', but the chroot is deleted and rebuilt from scratch each--- time. This is more expensive, but useful to ensure reproducible results--- when the properties of the chroot have been changed.-imageRebuilt :: DiskImage d => d -> (FilePath -> Chroot) -> TableType -> [PartSpec ()] -> RevertableProperty (HasInfo + DebianLike) Linux-imageRebuilt = imageBuilt' True+-- | Like 'imageBuiltFor', but the chroot is deleted and rebuilt from+-- scratch each time.+imageRebuiltFor :: (DiskImage d, Chroot.ChrootBootstrapper bootstrapper) => Host -> d -> bootstrapper -> RevertableProperty (HasInfo + DebianLike) Linux+imageRebuiltFor = imageBuiltFor' False +imageBuiltFor' :: (DiskImage d, Chroot.ChrootBootstrapper bootstrapper) => Bool -> Host -> d -> bootstrapper -> RevertableProperty (HasInfo + DebianLike) Linux+imageBuiltFor' rebuild h d bs =+	imageBuilt' rebuild d (Chroot.hostChroot h bs) tt pil+  where+	PartTableSpec tt pil = toPartTableSpec (fromInfo (hostInfo h))+ imageBuilt' :: DiskImage d => Bool -> d -> (FilePath -> Chroot) -> TableType -> [PartSpec ()] -> RevertableProperty (HasInfo + DebianLike) Linux imageBuilt' rebuild img mkchroot tabletype partspec = 	imageBuiltFrom img chrootdir tabletype final partspec@@ -183,7 +211,7 @@ 		in setContainerProps c $ containerProps c 			-- Before ensuring any other properties of the chroot, 			-- avoid starting services. Reverted by imageFinalized.-			&^ Chroot.noServices+			&^ Service.noServices 			& cachesCleaned 	-- Only propagate privdata Info from this chroot, nothing else. 	propprivdataonly (Chroot.Chroot d b ip h) =@@ -191,8 +219,14 @@ 	-- Pick boot loader finalization based on which bootloader is 	-- installed. 	final = case fromInfo (containerInfo chroot) of-		[GrubInstalled] -> grubBooted 		[] -> unbootable "no bootloader is installed"+		[GrubInstalled] -> grubFinalized+		[UbootInstalled p] -> ubootFinalized p+		[FlashKernelInstalled] -> flashKernelFinalized+		[UbootInstalled p, FlashKernelInstalled] -> +			ubootFlashKernelFinalized p+		[FlashKernelInstalled, UbootInstalled p] -> +			ubootFlashKernelFinalized p 		_ -> unbootable "multiple bootloaders are installed; don't know which to use"  -- | This property is automatically added to the chroot when building a@@ -215,7 +249,7 @@ 		liftIO $ unmountBelow chrootdir 		szm <- M.mapKeys (toSysDir chrootdir) . M.map toPartSize 			<$> liftIO (dirSizes chrootdir)-		let calcsz mnts = maybe defSz fudge . getMountSz szm mnts+		let calcsz mnts = maybe defSz fudgeSz . getMountSz szm mnts 		-- tie the knot! 		let (mnts, mntopts, parttable) = fitChrootSize tabletype partspec $ 			map (calcsz mnts) mnts@@ -228,7 +262,7 @@ 	mkimg' mnts mntopts parttable devs = 		partitionsPopulated chrootdir mnts mntopts devs 			`before`-		imageFinalized final mnts mntopts devs parttable+		imageFinalized final dest mnts mntopts devs parttable 	rmimg = undoRevertableProperty (buildDiskImage img) 		`before` undoRevertableProperty (imageExists' dest dummyparttable) 	dummyparttable = PartTable tabletype []@@ -351,10 +385,10 @@ -- -- It's ok if the property leaves additional things mounted -- in the partition tree.-type Finalization = (FilePath -> [LoopDev] -> Property Linux)+type Finalization = (RawDiskImage -> FilePath -> [LoopDev] -> Property Linux) -imageFinalized :: Finalization -> [Maybe MountPoint] -> [MountOpts] -> [LoopDev] -> PartTable -> Property Linux-imageFinalized final mnts mntopts devs (PartTable _ parts) =+imageFinalized :: Finalization -> RawDiskImage -> [Maybe MountPoint] -> [MountOpts] -> [LoopDev] -> PartTable -> Property Linux+imageFinalized final img mnts mntopts devs (PartTable _ parts) = 	property' "disk image finalized" $ \w -> 		withTmpDir "mnt" $ \top -> 			go w top `finally` liftIO (unmountall top)@@ -363,7 +397,9 @@ 		liftIO $ mountall top 		liftIO $ writefstab top 		liftIO $ allowservices top-		ensureProperty w $ final top devs+		ensureProperty w $ +			final img top devs+				`before` Qemu.removeHostEmulationBinary top  	-- Ordered lexographically by mount point, so / comes before /usr 	-- comes before /usr/local@@ -399,18 +435,14 @@ 	allowservices top = nukeFile (top ++ "/usr/sbin/policy-rc.d")  unbootable :: String -> Finalization-unbootable msg = \_ _ -> property desc $ do+unbootable msg = \_ _ _ -> property desc $ do 	warningMessage (desc ++ ": " ++ msg) 	return FailedChange   where 	desc = "image is not bootable" --- | Makes grub be the boot loader of the disk image.------ This does not install the grub package. You will need to add--- the `Grub.installed` property to the chroot.-grubBooted :: Finalization-grubBooted mnt loopdevs = Grub.bootsMounted mnt wholediskloopdev+grubFinalized :: Finalization+grubFinalized _img mnt loopdevs = Grub.bootsMounted mnt wholediskloopdev 	`describe` "disk image boots using grub"   where 	-- It doesn't matter which loopdev we use; all@@ -419,6 +451,17 @@ 	wholediskloopdev = case loopdevs of 		(l:_) -> wholeDiskLoopDev l 		[] -> error "No loop devs provided!"++ubootFinalized :: (FilePath -> FilePath -> Property Linux) -> Finalization+ubootFinalized p (RawDiskImage img) mnt _loopdevs = p img mnt++flashKernelFinalized :: Finalization+flashKernelFinalized _img mnt _loopdevs = FlashKernel.flashKernelMounted mnt++ubootFlashKernelFinalized :: (FilePath -> FilePath -> Property Linux) -> Finalization+ubootFlashKernelFinalized p img mnt loopdevs = +	ubootFinalized p img mnt loopdevs+		`before` flashKernelFinalized img mnt loopdevs  isChild :: FilePath -> Maybe MountPoint -> Bool isChild mntpt (Just d)
src/Propellor/Property/DiskImage/PartSpec.hs view
@@ -1,33 +1,186 @@--- | Disk image partition specification and combinators.+{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving #-} --- Partitions in disk images default to being sized large enough to hold--- the files that appear in the directory where the partition is to be--- mounted. Plus a fudge factor, since filesystems have some space--- overhead.+-- | Disk image partition specification.  module Propellor.Property.DiskImage.PartSpec (-	module Propellor.Types.PartSpec,-	module Propellor.Property.DiskImage.PartSpec,-	module Propellor.Property.Parted.Types,-	module Propellor.Property.Partition,+	PartSpec,+	Fs(..),+	PartSize(..),+	partition,+	-- * PartSpec combinators+	swapPartition,+	mountedAt,+	addFreeSpace,+	setSize,+	mountOpt,+	errorReadonly,+	reservedSpacePercentage,+	setFlag,+	extended,+	-- * Partition properties+	--+	-- | These properties do not do any disk partitioning on their own, but+	-- the Info they set can be used when building a disk image for a+	-- host.+	hasPartition,+	adjustPartition,+	PartLocation(..),+	partLocation,+	hasPartitionTableType,+	TableType(..),+	PartInfo,+	toPartTableSpec,+	PartTableSpec(..) ) where  import Propellor.Base import Propellor.Property.Parted import Propellor.Types.PartSpec-import Propellor.Property.Parted.Types+import Propellor.Types.Info import Propellor.Property.Partition (Fs(..))+import Propellor.Property.Mount --- | Adds additional free space to the partition.+import Data.List (sortBy)+import Data.Ord++-- | Specifies a partition with a given filesystem.+--+-- The partition is not mounted anywhere by default; use the combinators+-- below to configure it.+partition :: Monoid t => Fs -> PartSpec t+partition fs = (Nothing, mempty, mkPartition fs, mempty)++-- | Specifies a swap partition of a given size.+swapPartition :: Monoid t => PartSize -> PartSpec t+swapPartition sz = (Nothing, mempty, const (mkPartition LinuxSwap sz), mempty)++-- | Specifies where to mount a partition.+mountedAt :: PartSpec t -> MountPoint -> PartSpec t+mountedAt (_, o, p, t) mp = (Just mp, o, p, t)++-- | Partitions in disk images default to being sized large enough to hold+-- the files that live in that partition.+--+-- This adds additional free space to a partition. addFreeSpace :: PartSpec t -> PartSize -> PartSpec t addFreeSpace (mp, o, p, t) freesz = (mp, o, p', t)   where 	p' = \sz -> p (sz <> freesz) --- | Add 2% for filesystem overhead. Rationalle for picking 2%:--- A filesystem with 1% overhead might just sneak by as acceptable.--- Double that just in case. Add an additional 3 mb to deal with--- non-scaling overhead of filesystems (eg, superblocks). --- Add an additional 200 mb for temp files, journals, etc.-fudge :: PartSize -> PartSize-fudge (MegaBytes n) = MegaBytes (n + n `div` 100 * 2 + 3 + 200)+-- | Specify a fixed size for a partition.+setSize :: PartSpec t -> PartSize -> PartSpec t+setSize (mp, o, p, t) sz = (mp, o, const (p sz), t)++-- | Specifies a mount option, such as "noexec"+mountOpt :: ToMountOpts o => PartSpec t -> o -> PartSpec t+mountOpt (mp, o, p, t) o' = (mp, o <> toMountOpts o', p, t)++-- | Mount option to make a partition be remounted readonly when there's an+-- error accessing it.+errorReadonly :: MountOpts+errorReadonly = toMountOpts "errors=remount-ro"++-- | Sets the percent of the filesystem blocks reserved for the super-user.+--+-- The default is 5% for ext2 and ext4. Some filesystems may not support+-- this.+reservedSpacePercentage :: PartSpec t -> Int -> PartSpec t+reservedSpacePercentage s percent = adjustp s $ \p -> +	p { partMkFsOpts = ("-m"):show percent:partMkFsOpts p }++-- | Sets a flag on the partition.+setFlag :: PartSpec t -> PartFlag -> PartSpec t+setFlag s f = adjustp s $ \p -> p { partFlags = (f, True):partFlags p }++-- | Makes a MSDOS partition be Extended, rather than Primary.+extended :: PartSpec t -> PartSpec t+extended s = adjustp s $ \p -> p { partType = Extended }++adjustp :: PartSpec t -> (Partition -> Partition) -> PartSpec t+adjustp (mp, o, p, t) f = (mp, o, f . p, t)++data PartInfoVal+	= TableTypeInfo TableType+	| PartSpecInfo (PartSpec PartLocation)+	| AdjustPartSpecInfo MountPoint (PartSpec PartLocation -> PartSpec PartLocation)++newtype PartInfo = PartInfo [PartInfoVal]+	deriving (Monoid, Typeable)++instance IsInfo PartInfo where+	propagateInfo _ = PropagateInfo False++instance Show PartInfo where+	show = show . toPartTableSpec++toPartTableSpec :: PartInfo -> PartTableSpec+toPartTableSpec (PartInfo l) = PartTableSpec tt pil+  where+	tt = fromMaybe MSDOS $ headMaybe $ reverse $ mapMaybe gettt l++	pil = map convert $ sortBy (comparing location) $ adjust collect+	collect = mapMaybe getspartspec l+	adjust ps = adjust' ps (mapMaybe getadjust l)+	adjust' ps [] = ps+	adjust' ps ((mp, f):rest) = adjust' (map (adjustone mp f) ps) rest+	adjustone mp f p@(mp', _, _, _)+		| Just mp == mp' = f p+		| otherwise = p+	location (_, _, _, loc) = loc+	convert (mp, o, p, _) = (mp, o, p, ())+	+	gettt (TableTypeInfo t) = Just t+	gettt _ = Nothing+	getspartspec (PartSpecInfo ps) = Just ps+	getspartspec _ = Nothing+	getadjust (AdjustPartSpecInfo mp f) = Just (mp, f)+	getadjust _ = Nothing++-- | Indicates the partition table type of a host.+--+-- When not specified, the default is MSDOS.+--+-- For example:+--+-- >	& hasPartitionTableType GPT+hasPartitionTableType :: TableType -> Property (HasInfo + UnixLike)+hasPartitionTableType tt = pureInfoProperty+	("partition table type " ++ show tt)+	(PartInfo [TableTypeInfo tt])++-- | Indicates that a host has a partition.+--+-- For example:+--+-- >	& hasPartiton (partition EXT2 `mountedAt` "/boot" `partLocation` Beginning)+-- >	& hasPartiton (partition EXT4 `mountedAt` "/")+-- >	& hasPartiton (partition EXT4 `mountedAt` "/home" `partLocation` End `reservedSpacePercentage` 0)+hasPartition :: PartSpec PartLocation -> Property (HasInfo + UnixLike)+hasPartition p@(mmp, _, _, _) = pureInfoProperty desc+	(PartInfo [PartSpecInfo p])+  where+	desc = case mmp of+		Just mp -> "has " ++ mp ++ " partition"+		Nothing -> "has unmounted partition"++-- | Adjusts the PartSpec for the partition mounted at the specified location.+--+-- For example:+--+-- > 	& adjustPartition "/boot" (`addFreeSpace` MegaBytes 150)+adjustPartition :: MountPoint -> (PartSpec PartLocation -> PartSpec PartLocation) -> Property (HasInfo + UnixLike)+adjustPartition mp f = pureInfoProperty+	("has " ++ mp ++ " adjusted")+	(PartInfo [AdjustPartSpecInfo mp f])++-- | Indicates partition layout in a disk. Default is somewhere in the+-- middle.+data PartLocation = Beginning | Middle | End+	deriving (Eq, Ord)++instance Monoid PartLocation where+	mempty = Middle+	mappend _ b = b++partLocation :: PartSpec PartLocation -> PartLocation -> PartSpec PartLocation+partLocation (mp, o, p, _) l = (mp, o, p, l)
src/Propellor/Property/Fail2Ban.hs view
@@ -2,6 +2,7 @@  import Propellor.Base import qualified Propellor.Property.Apt as Apt+import qualified Propellor.Property.File as File import qualified Propellor.Property.Service as Service import Propellor.Property.ConfFile @@ -13,18 +14,47 @@  type Jail = String +type Filter = String++type Action = String+ -- | By default, fail2ban only enables the ssh jail, but many others -- are available to be enabled, for example "postfix-sasl" jailEnabled :: Jail -> Property DebianLike-jailEnabled name = jailConfigured name "enabled" "true"+jailEnabled name = jailEnabled' name [] 	`onChange` reloaded +jailEnabled' :: Jail -> [(IniKey, String)] -> Property DebianLike+jailEnabled' name settings =+	jailConfigured' name (("enabled", "true") : settings)+	`onChange` reloaded+ -- | Configures a jail. For example: ----- > jailConfigured "sshd" "port" "2222"+-- > jailConfigured' "sshd" [("port", "2222")]+jailConfigured' :: Jail -> [(IniKey, String)] -> Property UnixLike+jailConfigured' name settings = propertyList ("jail \"" ++ name ++ "\" configuration") $ props+	-- removes .conf files added by old versions of Fail2Ban properties+	& File.notPresent (oldJailConfFile name)+	& jailConfFile name `iniFileContains` [(name, settings)]++-- | Adds a setting to a given jail. For example:+--+-- > jailConfigured "sshd" "port"  "2222" jailConfigured :: Jail -> IniKey -> String -> Property UnixLike-jailConfigured name key value = -	jailConfFile name `containsIniSetting` (name, key, value)+jailConfigured name key value = propertyList ("jail \"" ++ name ++ "\" configuration") $ props+	-- removes .conf files added by old versions of Fail2Ban properties+	& File.notPresent (oldJailConfFile name)+	& jailConfFile name `containsIniSetting` (name, key, value) +oldJailConfFile :: Jail -> FilePath+oldJailConfFile name = "/etc/fail2ban/jail.d/" ++ name ++ ".conf"+ jailConfFile :: Jail -> FilePath-jailConfFile name = "/etc/fail2ban/jail.d/" ++ name ++ ".conf"+jailConfFile name = "/etc/fail2ban/jail.d/" ++ name ++ ".local"++filterConfFile :: Filter -> FilePath+filterConfFile name = "/etc/fail2ban/filter.d/" ++ name ++ ".local"++actionConfFile :: Action -> FilePath+actionConfFile name = "/etc/fail2ban/action.d/" ++ name ++ ".local"
+ src/Propellor/Property/FlashKernel.hs view
@@ -0,0 +1,63 @@+-- | Make ARM systems bootable using Debian's flash-kernel package.++module Propellor.Property.FlashKernel where++import Propellor.Base+import qualified Propellor.Property.File as File+import qualified Propellor.Property.Apt as Apt+import Propellor.Property.Mount+import Propellor.Types.Bootloader+import Propellor.Types.Info++-- | A machine name, such as "Cubietech Cubietruck" or "Olimex A10-OLinuXino-LIME"+--+-- flash-kernel supports many different machines,+-- see its file /usr/share/flash-kernel/db/all.db for a list.+type Machine = String++-- | Uses flash-kernel to make a machine bootable.+--+-- Before using this, an appropriate kernel needs to already be installed, +-- and on many machines, u-boot needs to be installed too.+installed :: Machine -> Property (HasInfo + DebianLike)+installed machine = setInfoProperty go (toInfo [FlashKernelInstalled])+  where+	go = "/etc/flash-kernel/machine" `File.hasContent` [machine]+		`onChange` (cmdProperty "flash-kernel" [] `assume` MadeChange)+		`requires` File.dirExists "/etc/flash-kernel"+		`requires` Apt.installed ["flash-kernel"]++-- | Runs flash-kernel in the system mounted at a particular directory.+flashKernelMounted :: FilePath -> Property Linux+flashKernelMounted mnt = combineProperties desc $ props+	-- remove mounts that are done below to make sure the right thing+	-- gets mounted+	& cleanupmounts+	& bindMount "/dev" (inmnt "/dev")+	& mounted "proc" "proc" (inmnt "/proc") mempty+	& mounted "sysfs" "sys" (inmnt "/sys") mempty+	-- update the initramfs so it gets the uuid of the root partition+	& inchroot "update-initramfs" ["-u"]+		`assume` MadeChange+	& inchroot "flash-kernel" []+		`assume` MadeChange+	& cleanupmounts+  where+	desc = "flash-kernel run"++	-- cannot use </> since the filepath is absolute+	inmnt f = mnt ++ f++	inchroot cmd ps = cmdProperty "chroot" ([mnt, cmd] ++ ps)++	cleanupmounts :: Property Linux+	cleanupmounts = property desc $ liftIO $ do+		cleanup "/sys"+		cleanup "/proc"+		cleanup "/dev"+		return NoChange+	  where+		cleanup m =+			let mp = inmnt m+			in whenM (isMounted mp) $+				umountLazy mp
+ src/Propellor/Property/Machine.hs view
@@ -0,0 +1,201 @@+-- | Machine-specific properties.+--+-- Many embedded computers have their own special configuration needed+-- to use them. Rather than needing to hunt down documentation about the+-- kernel, bootloader, etc for a given machine, if there's a property+-- in here for your machine, you can simply use it.+--+-- Not all machine properties have been tested yet. If one flagged as+-- untested and you find it works, please let us know.+--+-- You will need to configure the `Host` with the right `Architecture`+-- for the machine. These properties do test at runtime that a supported+-- Architecture was selected.+--+-- Sometimes non-free firmware is needed to use a board. If the board won't+-- be functional at all without it, its property will include the non-free+-- firmware, but if the non-free firmware is only needed for non-critical+-- functionality, it won't be included.+-- +-- Example: Building a disk image for a Marvell SheevaPlug +--+-- This defines a Host "sheeva" that is a Marvell SheevaPlug.+-- A bootable disk image for "sheeva" is built on another machine+-- "darkstar", which can be eg an Intel laptop running Debian.+--+-- > import Propellor.Property.Machine+-- > import Propellor.Property.DiskImage+-- > +-- > sheeva :: Host+-- > sheeva = host "sheeva.example.com" $ props+-- > 	& osDebian Unstable ARMEL+-- > 	& marvell_SheevaPlug Marvell_SheevaPlug_SDCard+-- >	& hasPartiton+-- >		( partition EXT4+-- > 		`mountedAt` "/"+-- >		`addFreeSpace` MegaBytes 2048+-- >		)+-- >+-- > darkstar :: Host+-- > darkstar = host "darkstar.example.com" $ props+-- >	& imageBuiltFor sheeva+-- >		(RawDiskImage "/srv/sheeva-disk.img")+-- >		(Debootstrapped mempty)++module Propellor.Property.Machine (+	-- * ARM boards+	Marvell_SheevaPlug_BootDevice(..),+	marvell_SheevaPlug,+	cubietech_Cubietruck,+	olimex_A10_OLinuXino_LIME,+	-- * ARM boards (untested)+	cubietech_Cubieboard,+	cubietech_Cubieboard2,+	lemaker_Banana_Pi,+	lemaker_Banana_Pro,+	olimex_A10s_OLinuXino_Micro,+	olimex_A20_OLinuXino_LIME,+	olimex_A20_OLinuXino_LIME2,+	olimex_A20_OLinuXino_Micro,+	olimex_A20_SOM_EVB,+	linkSprite_pcDuino3_Nano,+) where++import Propellor.Base+import Propellor.Types.Core+import qualified Propellor.Property.Apt as Apt+import qualified Propellor.Property.FlashKernel as FlashKernel+import qualified Propellor.Property.Uboot as Uboot+import Propellor.Property.DiskImage.PartSpec++data Marvell_SheevaPlug_BootDevice+	= Marvell_SheevaPlug_SDCard+	| Marvell_SheevaPlug_ESATA++-- | Marvell SheevaPlug+--+-- This includes a small EXT2 formatted /boot partition.+--+-- Note that u-boot may need to be upgraded manually, and will need to be+-- configured to boot from the SD card or eSATA. See+-- https://www.cyrius.com/debian/kirkwood/sheevaplug/install/+marvell_SheevaPlug :: Marvell_SheevaPlug_BootDevice -> Property (HasInfo + DebianLike)+marvell_SheevaPlug bd = fk+	`requires` marvell+	`requires` hasPartition bootpart+  where+	fk = case bd of+		Marvell_SheevaPlug_SDCard ->+			FlashKernel.installed "Marvell SheevaPlug Reference Board"+		Marvell_SheevaPlug_ESATA ->+			FlashKernel.installed "Marvell eSATA SheevaPlug Reference Board"+	-- The boot loader needs an EXT2 boot partition, which comes+	-- first. Add some free space to allow for additional kernel images+	-- and initrds.+	bootpart :: PartSpec PartLocation+	bootpart = partition EXT2+		`mountedAt` "/boot"+		`partLocation` Beginning+		`addFreeSpace` MegaBytes 150++-- | Cubietech Cubietruck+-- +-- Wifi needs non-free firmware-brcm80211, which is not installed by+-- this property. Also, see https://bugs.debian.org/844056+cubietech_Cubietruck :: Property (HasInfo + DebianLike)+cubietech_Cubietruck = FlashKernel.installed "Cubietech Cubietruck"+	`requires` sunixi "Cubietruck"+	`requires` lpae++-- | Cubietech Cubieboard (untested)+cubietech_Cubieboard :: Property (HasInfo + DebianLike)+cubietech_Cubieboard = FlashKernel.installed "Cubietech Cubieboard"+	`requires` sunixi "Cubieboard"+	`requires` armmp++-- | Cubietech Cubieboard2 (untested)+cubietech_Cubieboard2 :: Property (HasInfo + DebianLike)+cubietech_Cubieboard2 = FlashKernel.installed "Cubietech Cubieboard2"+	`requires` sunixi "Cubieboard2"+	`requires` lpae++-- | LeMaker Banana Pi+lemaker_Banana_Pi :: Property (HasInfo + DebianLike)+lemaker_Banana_Pi = FlashKernel.installed "LeMaker Banana Pi"+	`requires` sunixi "Bananapi"+	`requires` lpae++-- | LeMaker Banana Pro (untested)+lemaker_Banana_Pro :: Property (HasInfo + DebianLike)+lemaker_Banana_Pro = FlashKernel.installed "LeMaker Banana Pro"+	`requires` sunixi "Bananapro"+	`requires` lpae++-- | Olimex A10-OLinuXino-LIME+olimex_A10_OLinuXino_LIME :: Property (HasInfo + DebianLike)+olimex_A10_OLinuXino_LIME = FlashKernel.installed "Olimex A10-OLinuXino-LIME"+	`requires` sunixi "A10-OLinuXino-Lime"+	`requires` armmp++-- | Olimex A10s-Olinuxino Micro (untested)+olimex_A10s_OLinuXino_Micro :: Property (HasInfo + DebianLike)+olimex_A10s_OLinuXino_Micro = FlashKernel.installed "Olimex A10s-Olinuxino Micro"+	`requires` sunixi "A10s-OLinuXino-M"+	`requires` armmp++-- | Olimex A20-OlinuXino-LIME (untested)+olimex_A20_OLinuXino_LIME :: Property (HasInfo + DebianLike)+olimex_A20_OLinuXino_LIME = FlashKernel.installed "Olimex A20-OLinuXino-LIME"+	`requires` sunixi "A20-OLinuXino-Lime"+	`requires` lpae++-- | Olimex A20-OlinuXino-LIME2 (untested)+olimex_A20_OLinuXino_LIME2 :: Property (HasInfo + DebianLike)+olimex_A20_OLinuXino_LIME2 = FlashKernel.installed "Olimex A20-OLinuXino-LIME2"+	`requires` sunixi "A20-OLinuXino-Lime2"+	`requires` lpae++-- | Olimex A20-Olinuxino Micro (untested)+olimex_A20_OLinuXino_Micro :: Property (HasInfo + DebianLike)+olimex_A20_OLinuXino_Micro = FlashKernel.installed "Olimex A20-Olinuxino Micro"+	`requires` sunixi "A20-OLinuXino-MICRO"+	`requires` lpae++-- | Olimex A20-SOM-EVB (untested)+olimex_A20_SOM_EVB :: Property (HasInfo + DebianLike)+olimex_A20_SOM_EVB = FlashKernel.installed "Olimex A20-Olimex-SOM-EVB"+	`requires` sunixi "A20-Olimex-SOM-EVB"+	`requires` lpae++-- | LinkSprite pcDuino Nano (untested)+--+-- Needs non-free firmware, see+-- https://wiki.debian.org/InstallingDebianOn/Allwinner+linkSprite_pcDuino3_Nano :: Property (HasInfo + DebianLike)+linkSprite_pcDuino3_Nano = FlashKernel.installed "LinkSprite pcDuino3 Nano"+	`requires` sunixi "Linksprite_pcDuino3"+	`requires` lpae++sunixi :: Uboot.BoardName -> Property (HasInfo + DebianLike)+sunixi boardname = Uboot.sunxi boardname+	`requires` Apt.installed+		[ "firmware-linux-free"+		, "sunxi-tools"+		]++armmp :: Property DebianLike+armmp = checkArchitecture [ARMHF, ARMEL] $+	Apt.installed ["linux-image-armmp"]++lpae :: Property DebianLike+lpae = checkArchitecture [ARMHF, ARMEL] $ +	Apt.installed ["linux-image-armmp-lpae"]++marvell :: Property DebianLike+marvell = checkArchitecture [ARMEL] $+	Apt.installed ["linux-image-marvell"]++checkArchitecture :: [Architecture] -> Property DebianLike -> Property DebianLike+checkArchitecture as p = withOS (getDesc p) $ \w o -> case o of+	(Just (System _ arch)) | arch `elem` as -> ensureProperty w p+	_ -> error $ "Machine needs architecture to be one of: " ++ show as
src/Propellor/Property/Mount.hs view
@@ -90,18 +90,18 @@  -- | Filesystem type mounted at a given location. getFsType :: MountPoint -> IO (Maybe FsType)-getFsType = findmntField "fstype"+getFsType p = findmntField "fstype" [p]  -- | Mount options for the filesystem mounted at a given location. getFsMountOpts :: MountPoint -> IO MountOpts getFsMountOpts p = maybe mempty toMountOpts-	<$> findmntField "fs-options" p+	<$> findmntField "fs-options" [p]  type UUID = String  -- | UUID of filesystem mounted at a given location. getMountUUID :: MountPoint -> IO (Maybe UUID)-getMountUUID = findmntField "uuid"+getMountUUID p = findmntField "uuid" [p]  -- | UUID of a device getSourceUUID :: Source -> IO (Maybe UUID)@@ -111,7 +111,7 @@  -- | Label of filesystem mounted at a given location. getMountLabel :: MountPoint -> IO (Maybe Label)-getMountLabel = findmntField "label"+getMountLabel p = findmntField "label" [p]  -- | Label of a device getSourceLabel :: Source -> IO (Maybe UUID)@@ -119,12 +119,16 @@  -- | Device mounted at a given location. getMountSource :: MountPoint -> IO (Maybe Source)-getMountSource = findmntField "source"+getMountSource p = findmntField "source" [p] -findmntField :: String -> FilePath -> IO (Maybe String)-findmntField field mnt = catchDefaultIO Nothing $+-- | Device that a given path is located within.+getMountContaining :: FilePath -> IO (Maybe Source)+getMountContaining p = findmntField "source" ["-T", p]++findmntField :: String -> [String] -> IO (Maybe String)+findmntField field ps = catchDefaultIO Nothing $ 	headMaybe . filter (not . null) . lines-		<$> readProcess "findmnt" ["-n", mnt, "--output", field]+		<$> readProcess "findmnt" ("-n" : ps ++ ["--output", field])  blkidTag :: String -> Source -> IO (Maybe String) blkidTag tag dev = catchDefaultIO Nothing $
src/Propellor/Property/Parted.hs view
@@ -21,13 +21,14 @@ 	parted, 	Eep(..), 	installed,-	-- * PartSpec combinators+	-- * Partition table sizing 	calcPartTable, 	DiskSize(..), 	DiskPart,-	module Propellor.Types.PartSpec, 	DiskSpaceUse(..), 	useDiskSpace,+	defSz,+	fudgeSz, ) where  import Propellor.Base@@ -35,7 +36,7 @@ import qualified Propellor.Property.Apt as Apt import qualified Propellor.Property.Pacman as Pacman import qualified Propellor.Property.Partition as Partition-import Propellor.Types.PartSpec+import Propellor.Types.PartSpec (PartSpec) import Utility.DataUnits  import System.Posix.Files@@ -160,3 +161,19 @@ -- (less all fixed size partitions), or the remaining space in the disk. useDiskSpace :: PartSpec DiskPart -> DiskSpaceUse -> PartSpec DiskPart useDiskSpace (mp, o, p, _) diskuse = (mp, o, p, DynamicDiskPart diskuse)++-- | Default partition size when not otherwize specified is 128 MegaBytes.+defSz :: PartSize+defSz = MegaBytes 128++-- | When a partition is sized to fit the files that live in it,+-- this fudge factor is added to the size of the files. This is necessary+-- since filesystems have some space overhead.+-- +-- Add 2% for filesystem overhead. Rationalle for picking 2%:+-- A filesystem with 1% overhead might just sneak by as acceptable.+-- Double that just in case. Add an additional 3 mb to deal with+-- non-scaling overhead of filesystems (eg, superblocks). +-- Add an additional 200 mb for temp files, journals, etc.+fudgeSz :: PartSize -> PartSize+fudgeSz (MegaBytes n) = MegaBytes (n + n `div` 100 * 2 + 3 + 200)
src/Propellor/Property/PropellorRepo.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE DeriveDataTypeable #-}+ module Propellor.Property.PropellorRepo where  import Propellor.Base@@ -24,4 +26,4 @@ 			else makeChange $ setRepoUrl u  newtype OriginUrl = OriginUrl String-	deriving (Show)+	deriving (Show, Typeable)
+ src/Propellor/Property/Qemu.hs view
@@ -0,0 +1,49 @@+module Propellor.Property.Qemu where++import Propellor.Base+import qualified Propellor.Property.Apt as Apt++-- | Installs qemu user mode emulation binaries, built statically,+-- which allow foreign binaries to run directly.+foreignBinariesEmulated :: RevertableProperty Linux Linux+foreignBinariesEmulated = (setup <!> cleanup)+	`describe` "foreign binary emulation"+  where+	setup = Apt.installed p `pickOS` unsupportedOS+	cleanup = Apt.removed p `pickOS` unsupportedOS+	p = ["qemu-user-static"]++-- | Removes qemu user mode emulation binary for the host CPU.+-- This binary is copied into a chroot by qemu-debootstrap, and is not+-- part of any package.+--+-- Note that removing the binary will prevent using the chroot on the host+-- system.+--+-- The FilePath is the path to the top of the chroot.+removeHostEmulationBinary :: FilePath -> Property Linux+removeHostEmulationBinary top = tightenTargets $ +	scriptProperty ["rm -f " ++ top ++ "/usr/bin/qemu-*-static"]+		`assume` MadeChange++-- | Check if the given System supports an Architecture.+--+-- For example, on Debian, X86_64 supports X86_32, and vice-versa.+supportsArch :: System -> Architecture -> Bool+supportsArch (System os a) b+	| a == b = True+	| otherwise = case os of+		Debian _ _ -> debianlike+		Buntish _ -> debianlike+		-- don't know about other OS's+		_ -> False+  where+	debianlike =+		let l = +			[ (X86_64, X86_32)+			, (ARMHF, ARMEL)+			, (PPC, PPC64)+			, (SPARC, SPARC64)+			, (S390, S390X)+			]+		in elem (a, b) l || elem (b, a) l
src/Propellor/Property/Service.hs view
@@ -1,6 +1,11 @@+{-# LANGUAGE DeriveDataTypeable #-}+ module Propellor.Property.Service where  import Propellor.Base+import Propellor.Types.Info+import qualified Propellor.Property.File as File+import Utility.FileMode  type ServiceName = String @@ -21,7 +26,34 @@ reloaded = signaled "reload" "reloaded"  signaled :: String -> Desc -> ServiceName -> Property DebianLike-signaled cmd desc svc = tightenTargets $ p `describe` (desc ++ " " ++ svc)+signaled cmd desc svc = check (not <$> servicesDisabled) $+	tightenTargets $ p `describe` (desc ++ " " ++ svc)   where 	p = scriptProperty ["service " ++ shellEscape svc ++ " " ++ cmd ++ " >/dev/null 2>&1 || true"] 		`assume` NoChange++-- | This property prevents daemons and other services from being started,+-- which is often something you want to prevent when building a chroot.+--+-- When this is set, `running` and `restarted` will not start services.+--+-- On Debian this installs a </usr/sbin/policy-rc.d> script to further+-- prevent any packages that get installed from starting daemons.+-- Reverting the property removes the script.+noServices :: RevertableProperty (HasInfo + UnixLike) UnixLike+noServices = (setup `setInfoProperty` toInfo (InfoVal NoServices)) <!> teardown+  where+	f = "/usr/sbin/policy-rc.d"+	script = [ "#!/bin/sh", "exit 101" ]+	setup = combineProperties "no services started" $ toProps+		[ File.hasContent f script+		, File.mode f (combineModes (readModes ++ executeModes))+		]+	teardown = File.notPresent f++-- | Check if the noServices property is in effect.+servicesDisabled :: Propellor Bool+servicesDisabled = isJust . fromInfoVal+	<$> (askInfo :: Propellor (InfoVal NoServices))++data NoServices = NoServices deriving (Eq, Show, Typeable)
src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs view
@@ -119,10 +119,10 @@ standardAutoBuilder suite arch flavor = 	propertyList "standard git-annex autobuilder" $ props 		& osDebian suite arch-		& buildDepsApt 		& Apt.stdSourcesList 		& Apt.unattendedUpgrades 		& Apt.cacheCleaned+		& buildDepsApt 		& User.accountFor (User builduser) 		& tree (architectureToDebianArchString arch) flavor 
src/Propellor/Property/SiteSpecific/GitHome.hs view
@@ -20,7 +20,14 @@ 				moveout tmpdir home 			, property "rmdir" $ makeChange $ void $ 				catchMaybeIO $ removeDirectory tmpdir-			, userScriptProperty user ["rm -rf .aptitude/ .bashrc .profile; bin/mr checkout; bin/fixups"]+			, userScriptProperty user ["rm -rf .aptitude/ .bashrc .profile"]+				`assume` MadeChange+			-- Set HOSTNAME so that this sees the right+			-- hostname when run in a chroot with a different+			-- hostname than the current one.+			, userScriptProperty user ["HOSTNAME=$(cat /etc/hostname) bin/mr checkout"]+				`assume` MadeChange+			, userScriptProperty user ["bin/fixups"] 				`assume` MadeChange 			] 	moveout tmpdir home = do
src/Propellor/Property/SiteSpecific/JoeySites.hs view
@@ -912,16 +912,20 @@ homePowerMonitor :: IsContext c => User -> c -> (SshKeyType, Ssh.PubKeyText) -> Property (HasInfo + DebianLike) homePowerMonitor user ctx sshkey = propertyList "home power monitor" $ props 	& Apache.installed-	& Apt.installed ["python", "python-pymodbus"]+	& Apt.installed ["python", "python-pymodbus", "rrdtool"] 	& File.ownerGroup "/var/www/html" user (userGroup user) 	& Git.cloned user "git://git.kitenet.net/joey/homepower" d Nothing-		`onChange` buildpoller+	& buildpoller 	& Systemd.enabled servicename 		`requires` serviceinstalled 		`onChange` Systemd.started servicename+	& User.hasGroup user (Group "dialout") 	& Cron.niceJob "homepower upload" 		(Cron.Times "1 * * * *") user d rsynccommand 		`requires` Ssh.userKeyAt (Just sshkeyfile) user ctx sshkey+		`requires` File.ownerGroup (takeDirectory sshkeyfile)+			user (userGroup user)+		`requires` File.dirExists (takeDirectory sshkeyfile)   where 	d = "/var/www/html/homepower" 	sshkeyfile = d </> ".ssh/key"@@ -957,30 +961,34 @@ homeRouter = propertyList "home router" $ props 	& Network.static "wlan0" (IPv4 "10.1.1.1") Nothing 		`requires` Network.cleanInterfacesFile-	& Apt.serviceInstalledRunning "hostapd"-		`requires` File.hasContent "/etc/hostapd/hostapd.conf"+	& Apt.installed ["hostapd"]+	& File.hasContent "/etc/hostapd/hostapd.conf" 			[ "interface=wlan0" 			, "ssid=house" 			, "hw_mode=g" 			, "channel=8" 			]-		`requires` File.dirExists "/lib/hostapd"-	& Apt.serviceInstalledRunning "dnsmasq"-		`requires` File.hasContent "/etc/dnsmasq.conf"-			[ "domain-needed"-			, "bogus-priv"-			, "interface=wlan0"-			, "domain=kitenet.net"-			, "dhcp-range=10.1.1.100,10.1.1.150,24h"-			, "no-hosts"-			, "address=/honeybee.kitenet.net/10.1.1.1"-			]-		`requires` File.hasContent "/etc/resolv.conf"-			[ "domain kitenet.net"-			, "search kitenet.net"-			, "nameserver 8.8.8.8"-			, "nameserver 8.8.4.4"-			]+		`requires` File.dirExists "/etc/hostapd"+		`requires` File.hasContent "/etc/default/hostapd"+			[ "DAEMON_CONF=/etc/hostapd/hostapd.conf" ]+		`onChange` Service.running "hostapd"+	& File.hasContent "/etc/resolv.conf"+		[ "domain kitenet.net"+		, "search kitenet.net"+		, "nameserver 8.8.8.8"+		, "nameserver 8.8.4.4"+		]+	& Apt.installed ["dnsmasq"]+	& File.hasContent "/etc/dnsmasq.conf"+		[ "domain-needed"+		, "bogus-priv"+		, "interface=wlan0"+		, "domain=kitenet.net"+		, "dhcp-range=10.1.1.100,10.1.1.150,24h"+		, "no-hosts"+		, "address=/honeybee.kitenet.net/10.1.1.1"+		]+		`onChange` Service.restarted "dnsmasq" 	& ipmasq "wlan0" 	& Apt.serviceInstalledRunning "netplug" 	& Network.dhcp' "eth0"
+ src/Propellor/Property/Uboot.hs view
@@ -0,0 +1,36 @@+module Propellor.Property.Uboot where++import Propellor.Base+import Propellor.Types.Info+import Propellor.Types.Bootloader+import Propellor.Property.Chroot+import Propellor.Property.Mount+import qualified Propellor.Property.Apt as Apt++-- | Name of a board.+type BoardName = String++-- | Installs u-boot for Allwinner/sunxi platforms.+--+-- This includes writing it to the boot sector.+sunxi :: BoardName -> Property (HasInfo + DebianLike)+sunxi boardname = setInfoProperty (check (not <$> inChroot) go) info+	`requires` Apt.installed ["u-boot", "u-boot-sunxi"]+  where+	go :: Property Linux+	go = property' "u-boot installed" $ \w -> do+		v <- liftIO $ getMountContaining "/boot"+		case v of+			Nothing -> error "unable to determine boot device"+			Just dev -> ensureProperty w (dd dev "/")+	dd :: FilePath -> FilePath -> Property Linux+	dd dev prefix = tightenTargets $ cmdProperty "dd"+		[ "conv=fsync,notrunc"+		, "if=" ++ prefix ++ "/usr/lib/u-boot/"+			++ boardname ++ "/u-boot-sunxi-with-spl.bin"+		, "of=" ++ dev+		, "bs=1024"+		, "seek=8"+		]+		`assume` NoChange+	info = toInfo [UbootInstalled dd]
src/Propellor/Types/Bootloader.hs view
@@ -2,11 +2,20 @@  module Propellor.Types.Bootloader where +import Propellor.Types import Propellor.Types.Info  -- | Boot loader installed on a host.-data BootloaderInstalled = GrubInstalled-	deriving (Typeable, Show)+data BootloaderInstalled+	= GrubInstalled+	| FlashKernelInstalled+	| UbootInstalled (FilePath -> FilePath -> Property Linux)+	deriving (Typeable)++instance Show BootloaderInstalled where+	show GrubInstalled = "GrubInstalled"+	show FlashKernelInstalled = "FlashKernelInstalled"+	show (UbootInstalled _) = "UbootInstalled"  instance IsInfo [BootloaderInstalled] where 	propagateInfo _ = PropagateInfo False
src/Propellor/Types/PartSpec.hs view
@@ -1,66 +1,14 @@--- | Partition specification combinators.- module Propellor.Types.PartSpec where -import Propellor.Base import Propellor.Property.Parted.Types import Propellor.Property.Mount-import Propellor.Property.Partition  -- | Specifies a mount point, mount options, and a constructor for a -- Partition that determines its size. type PartSpec t = (Maybe MountPoint, MountOpts, PartSize -> Partition, t) --- | Specifies a partition with a given filesystem.------ The partition is not mounted anywhere by default; use the combinators--- below to configure it.-partition :: Monoid t => Fs -> PartSpec t-partition fs = (Nothing, mempty, mkPartition fs, mempty)---- | Specifies a swap partition of a given size.-swapPartition :: Monoid t => PartSize -> PartSpec t-swapPartition sz = (Nothing, mempty, const (mkPartition LinuxSwap sz), mempty)---- | Specifies where to mount a partition.-mountedAt :: PartSpec t -> FilePath -> PartSpec t-mountedAt (_, o, p, t) mp = (Just mp, o, p, t)---- | Specify a fixed size for a partition.-setSize :: PartSpec t -> PartSize -> PartSpec t-setSize (mp, o, p, t) sz = (mp, o, const (p sz), t)---- | Specifies a mount option, such as "noexec"-mountOpt :: ToMountOpts o => PartSpec t -> o -> PartSpec t-mountOpt (mp, o, p, t) o' = (mp, o <> toMountOpts o', p, t)---- | Mount option to make a partition be remounted readonly when there's an--- error accessing it.-errorReadonly :: MountOpts-errorReadonly = toMountOpts "errors=remount-ro"---- | Sets the percent of the filesystem blocks reserved for the super-user.------ The default is 5% for ext2 and ext4. Some filesystems may not support--- this.-reservedSpacePercentage :: PartSpec t -> Int -> PartSpec t-reservedSpacePercentage s percent = adjustp s $ \p -> -	p { partMkFsOpts = ("-m"):show percent:partMkFsOpts p }---- | Sets a flag on the partition.-setFlag :: PartSpec t -> PartFlag -> PartSpec t-setFlag s f = adjustp s $ \p -> p { partFlags = (f, True):partFlags p }---- | Makes a MSDOS partition be Extended, rather than Primary.-extended :: PartSpec t -> PartSpec t-extended s = adjustp s $ \p -> p { partType = Extended }--adjustp :: PartSpec t -> (Partition -> Partition) -> PartSpec t-adjustp (mp, o, p, t) f = (mp, o, f . p, t)--adjustt :: PartSpec t -> (t -> t) -> PartSpec t-adjustt (mp, o, p, t) f = (mp, o, p, f t)+-- | Specifies a partition table.+data PartTableSpec = PartTableSpec TableType [PartSpec ()] --- | Default partition size when not otherwize specified is 128 MegaBytes.-defSz :: PartSize-defSz = MegaBytes 128+instance Show PartTableSpec where+	show (PartTableSpec tt _) = "PartTableSpec " ++ show tt