summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2018-01-02 11:05:50 +0000
committerSean Whitton <spwhitton@spwhitton.name>2018-01-02 11:05:50 +0000
commit98ccd5b865c66dff7f2a98cccacc3221808134a4 (patch)
treea689f6fabec6930bd33eafe8993bef20e98bbaf5
parent1e1a3dff95aa8d03c2b3710965cef86362da5d51 (diff)
parent17659793e835913e4c8631f09d856b3eef6d8ea4 (diff)
Merge tag '5.2.0' into debian
tagging package propellor version 5.2.0 # gpg: Signature made Sat 30 Dec 2017 17:34:48 GMT # gpg: using RSA key 28A500C35207EAB72F6C0F25DB12DB0FF05F8F38 # gpg: Good signature from "Joey Hess <joeyh@joeyh.name>" [full] # Primary key fingerprint: E85A 5F63 B31D 24C1 EBF0 D81C C910 D922 2512 E3C7 # Subkey fingerprint: 28A5 00C3 5207 EAB7 2F6C 0F25 DB12 DB0F F05F 8F38
-rw-r--r--debian/changelog28
-rw-r--r--doc/forum/How_to_add_a_privdata_for_Gitlab_cookies/comment_2_ab81471e6466944810906284f9a523cc._comment66
-rw-r--r--doc/forum/How_to_add_a_privdata_for_Gitlab_cookies/comment_3_32aaf0dd4d2a33d3ac7596bc47c15028._comment16
-rw-r--r--doc/forum/How_to_add_a_privdata_for_Gitlab_cookies/comment_4_ec1136accf484b572a1bcdfee40dcc92._comment14
-rw-r--r--doc/forum/Sbuild_and_jessie.mdwn23
-rw-r--r--doc/forum/Sbuild_and_jessie/comment_1_31dc85774c182a583aeb1935e9fef2d6._comment10
-rw-r--r--doc/forum/Sbuild_and_jessie/comment_2_41ed6253709b18ec799624a66b9b8078._comment8
-rw-r--r--doc/forum/Sbuild_and_jessie/comment_3_a4d6fdbed71270d7a4ffbfe98d1aa479._comment11
-rw-r--r--doc/forum/Sbuild_and_jessie/comment_4_9e409a59abc81786481207ffbbd7c3ac._comment10
-rw-r--r--doc/forum/Sbuild_and_jessie/comment_5_6303943e3425b29b1e4727d809574cda._comment8
-rw-r--r--doc/forum/Sbuild_and_jessie/comment_6_a88b331c80f57acdf55ac0c0ce3dce6f._comment8
-rw-r--r--doc/forum/Sbuild_and_jessie/comment_7_38650a2151201eaf6f40d8becbbe8861._comment10
-rw-r--r--doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__.mdwn131
-rw-r--r--doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_10_4cfd25f81e2ed3a0cc491558038e347b._comment7
-rw-r--r--doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_1_abbccfa3a607086ec96da122ae39fb57._comment20
-rw-r--r--doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_2_00b8165c200b515c98d4e66c66df8a56._comment27
-rw-r--r--doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_3_f0d4a3e7e41e2fe5ea981e8755ffede3._comment12
-rw-r--r--doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_4_e30b385d9b6a5e41809eb7b482d15e46._comment10
-rw-r--r--doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_5_2de24368d2891a5d44107ab7a858f3c1._comment8
-rw-r--r--doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_6_2dac20b315875c93e17e6733a42264ff._comment10
-rw-r--r--doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_7_cb0a1052e1ad421d4c1f2b15c30a7f06._comment10
-rw-r--r--doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_8_7f0b14866c6473f2218fc6ae97a9adee._comment15
-rw-r--r--doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_9_b0ebdfabdc973c7e4a24825d5ab327d2._comment9
-rw-r--r--doc/forum/imageBuiltFor_mount_points_not_automatically_created.mdwn52
-rw-r--r--doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_10_00b4f5d4fd445b8041a2744c2dd755f0._comment36
-rw-r--r--doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_11_6f691ea981679e92d7c0ae6cf1cfce6f._comment29
-rw-r--r--doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_12_8717ae3d2e60d07025a11c930cf26b84._comment8
-rw-r--r--doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_13_10b9bf6e92a80dff2c14f41c22347b3f._comment22
-rw-r--r--doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_14_d7948bf285cc4769ccd1802a1fa86eee._comment10
-rw-r--r--doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_15_05bdf475e1a8b5d8d36f88fef0210383._comment7
-rw-r--r--doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_16_53ec0ff959e60af5382f2b6fd54ced26._comment17
-rw-r--r--doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_1_af7d83cf29a578901fcf9aca0ea2426b._comment27
-rw-r--r--doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_2_f90109eb016065586225fc59674c431c._comment20
-rw-r--r--doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_3_f2ec6998ed728f42cdb23116dbce8ade._comment17
-rw-r--r--doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_4_021311b587601d76c64afe06638e1fef._comment11
-rw-r--r--doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_5_95af19d3f8e01525a616b48e376c3326._comment8
-rw-r--r--doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_6_8c454f014e0cf4e6b3af9b8f68f987fa._comment7
-rw-r--r--doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_7_ad9ea2799890df2dfce4f0cc99e397e9._comment8
-rw-r--r--doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_8_ad50abb937a9801a4db2293765137b75._comment8
-rw-r--r--doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_9_68b3d9ca04283c2400f5b23e486bb4b7._comment62
-rw-r--r--doc/forum/parted:_invalid_token:_fat.mdwn37
-rw-r--r--doc/forum/parted:_invalid_token:_fat/comment_1_0ad5e1df0db6dbdaba298f5f890d79a2._comment11
-rw-r--r--doc/forum/parted:_invalid_token:_fat/comment_2_88db9d05c7e4d028f35d98ba6b082d55._comment7
-rw-r--r--doc/forum/parted:_invalid_token:_fat/comment_3_76fd3da6d79f4a369d01ecfad8300025._comment8
-rw-r--r--doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__..mdwn25
-rw-r--r--doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_1_4dea8fc15186923aeffcd0272a8c14c0._comment38
-rw-r--r--doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_2_10e8132f96e66a4c215ed275e22d1bda._comment16
-rw-r--r--doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_3_e288978072a6f38539150be1ebf4b0f2._comment11
-rw-r--r--doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_4_074a7c14425635ddb25b7d3046337533._comment38
-rw-r--r--doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_5_4cda097e7650c4ba46e26c6e3dbbdc75._comment65
-rw-r--r--doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_6_249337c7f647cca8f4e23c99897458d9._comment22
-rw-r--r--doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_7_cf7efafc0ee96d5cecf452ebe49015d5._comment9
-rw-r--r--doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_8_66bab35f7eb78584e1adf93b4b8dccb4._comment12
-rw-r--r--doc/forum/secret-project_and_type_constructor_or_class___8216__PartSpec__8217__.mdwn43
-rw-r--r--doc/forum/secret-project_and_type_constructor_or_class___8216__PartSpec__8217__/comment_1_492a5c5297a80f18282361fb5c27ad8a._comment20
-rw-r--r--doc/forum/secret-project_and_type_constructor_or_class___8216__PartSpec__8217__/comment_2_4e2f36fc1de2644c22d69ab9a2d7e94a._comment8
-rw-r--r--doc/forum/secret-project_and_type_constructor_or_class___8216__PartSpec__8217__/comment_3_b436b5eb909dd4b228bb36546f593547._comment17
-rw-r--r--doc/forum/secret-project_and_type_constructor_or_class___8216__PartSpec__8217__/comment_4_568bda577a15f1ef405dd20eec24aa9b._comment19
-rw-r--r--doc/forum/secret-project_deliverable.mdwn27
-rw-r--r--doc/forum/secret-project_deliverable/comment_1_49f421da4a94d9267ca5e75679a4c92c._comment9
-rw-r--r--doc/forum/secret-project_deliverable/comment_2_a3faea076e7477d5ce4fcb03a38d74a7._comment11
-rw-r--r--doc/news/version_5.0.0.mdwn20
-rw-r--r--doc/news/version_5.1.0.mdwn18
-rw-r--r--doc/todo/etckeeper/comment_2_69484bfac40de156a4b877f27aa69eca._comment14
-rw-r--r--doc/todo/etckeeper/comment_3_5f62128bdb550de475d22abb35730949._comment7
-rw-r--r--doc/todo/privdata_propigation_into_diskimages.mdwn6
-rw-r--r--doc/todo/removable_drive_partitioning_and_install.mdwn40
-rw-r--r--doc/todo/spin_without_remote_compilation/comment_6_513dededf5872a51eb443a211cee13fa._comment11
-rw-r--r--doc/todo/spin_without_remote_compilation/comment_7_3fed94d212de0e4ad2d2364cc91e6c94._comment18
-rw-r--r--joeyconfig.hs22
-rw-r--r--propellor.cabal5
-rw-r--r--src/Propellor/Property/Bootstrap.hs14
-rw-r--r--src/Propellor/Property/DiskImage.hs52
-rw-r--r--src/Propellor/Property/DiskImage/PartSpec.hs6
-rw-r--r--src/Propellor/Property/Grub.hs62
-rw-r--r--src/Propellor/Property/Installer.hs20
-rw-r--r--src/Propellor/Property/Installer/Target.hs462
-rw-r--r--src/Propellor/Property/Installer/Types.hs16
-rw-r--r--src/Propellor/Property/Mount.hs4
-rw-r--r--src/Propellor/Property/Parted.hs93
-rw-r--r--src/Propellor/Property/Parted/Types.hs61
-rw-r--r--src/Propellor/Property/Sbuild.hs15
-rw-r--r--src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs2
-rw-r--r--src/Propellor/Property/SiteSpecific/JoeySites.hs51
-rw-r--r--src/Propellor/Types/Bootloader.hs7
85 files changed, 2169 insertions, 130 deletions
diff --git a/debian/changelog b/debian/changelog
index 173e0acc..a99661d8 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,31 @@
+propellor (5.2.0) unstable; urgency=medium
+
+ [ Joey Hess ]
+ * bootstrappedFrom: Set up local privdata file.
+ * Parted: Fix names used for FAT and VFAT partitions.
+ * Parted: Add an Alignment parameter. (API change)
+ A good default to use is safeAlignment, which is 4MiB,
+ well suited for inexpensive flash drives, and fine for other disks too.
+ Previously, a very non-optimial 1MB (not 1MiB) alignment had been used.
+ * DiskImage: Use safeAlignment. It didn't seem worth making the
+ alignment configurable here.
+ * Fixed rounding bug in Parted.calcPartTable.
+ * DiskImage: Fix rsync crash when a mount point does not exist in the
+ chroot.
+ * Fix bug in unmountBelow that caused unmounting of nested mounts to
+ fail.
+ * Grub.boots, Grub.bootsMounted: Pass --target to grub-install.
+ * Added Propellor.Property.Installer modules, which can be used to create
+ bootable installer disk images, which then run propellor to install
+ a system. This code was extracted from the demo I gave in my
+ talk at DebConf 2017.
+
+ [ Sean Whitton ]
+ * Sbuild: add notes about Debian jessie hosts and backports of sbuild and
+ autopkgtest.
+
+ -- Joey Hess <id@joeyh.name> Sat, 30 Dec 2017 13:34:29 -0400
+
propellor (5.1.0-1) unstable; urgency=medium
* Package new upstream release.
diff --git a/doc/forum/How_to_add_a_privdata_for_Gitlab_cookies/comment_2_ab81471e6466944810906284f9a523cc._comment b/doc/forum/How_to_add_a_privdata_for_Gitlab_cookies/comment_2_ab81471e6466944810906284f9a523cc._comment
new file mode 100644
index 00000000..a9b50d81
--- /dev/null
+++ b/doc/forum/How_to_add_a_privdata_for_Gitlab_cookies/comment_2_ab81471e6466944810906284f9a523cc._comment
@@ -0,0 +1,66 @@
+[[!comment format=mdwn
+ username="picca"
+ avatar="http://cdn.libravatar.org/avatar/7e61c80d28018b10d31f6db7dddb864c"
+ subject="comment 2"
+ date="2017-11-27T15:50:08Z"
+ content="""
+Hello, joey
+
+I try this but It ends up with an error during the compilation
+
+ blabla' :: Property (HasInfo + DebianLike)
+ blabla' = withPrivData (Password \"xxxxxxxxxxxxxx\") (Context \"yyyyyyyyyyyyy\") $ \getdata ->
+ property' \"blabla\" $ \w -> getdata $ \privdata -> ensureProperty w
+ (buildAndInstall (Git (\"https://toto:\" ++ (privDataVal privdata) ++ \"@xxxxxxxxxxxxxx\") Nothing \"blabla\"))
+
+ blabla :: Property (HasInfo + DebianLike)
+ blabla = withOS \"Install BlaBla Stack\" $ \w o -> case o of
+ (Just (System (Debian _ Unstable) _)) -> ensureProperty w $ unstable
+ (Just (System (Debian _ (Stable \"jessie\")) _)) -> ensureProperty w $ jessie
+ (Just (System (Debian _ (Stable \"stretch\")) _)) -> ensureProperty w $ stretch
+ _ -> error $ \"Blabla installation not yet implemented on \" ++ show o
+ where
+ unstable :: Property (HasInfo + DebianLike)
+ unstable = propertyList \"Stretch Blabla\" $ props
+ & Apt.installed [\"python3-gpyfft\"]
+ & blabla'
+
+ jessie :: Property (HasInfo + Debian)
+ jessie = propertyList \"Jessie Blabla\" $ props
+ & Apt.installedBackport [\"cython\", \"cython3\"]
+ & Apt.installedBackport [\"python-sphinx\", \"python3-sphinx\"]
+ & buildAndInstall (Backport \"appdirs\" Nothing Nothing)
+ & buildAndInstall (Backport \"pytools\" Nothing Nothing)
+ & buildAndInstall (Backport \"pyopencl\" Nothing (Just \"nodocs\"))
+ & buildAndInstall (Backport \"clfft\" Nothing Nothing)
+ & buildAndInstall (Backport \"gpyfft\" (Just \"nostrip\") Nothing)
+ & blabla'
+
+ stretch :: Property (HasInfo + DebianLike)
+ stretch = propertyList \"Stretch Blabla\" $ props
+ & buildAndInstall (Backport \"gpyfft\" (Just \"nostrip\") Nothing)
+ & blabla'
+
+
+
+here the error
+
+ src/propellor-config.hs:810:60-75: error:
+ • Couldn't match type ‘'False’ with ‘'True’
+ arising from a use of ‘ensureProperty’
+ • In the expression: ensureProperty w
+ In the expression: ensureProperty w $ unstable
+ In a case alternative:
+ (Just (System (Debian _ (Unstable)) _))
+ -> ensureProperty w $ stretch
+
+It seems to me that this is an error with the HasInfo, but I could not manage to solve this problem by myself.
+
+do you have a Idea in ordert o solve this ?
+
+thanks
+
+Frederic
+
+
+"""]]
diff --git a/doc/forum/How_to_add_a_privdata_for_Gitlab_cookies/comment_3_32aaf0dd4d2a33d3ac7596bc47c15028._comment b/doc/forum/How_to_add_a_privdata_for_Gitlab_cookies/comment_3_32aaf0dd4d2a33d3ac7596bc47c15028._comment
new file mode 100644
index 00000000..beaa631f
--- /dev/null
+++ b/doc/forum/How_to_add_a_privdata_for_Gitlab_cookies/comment_3_32aaf0dd4d2a33d3ac7596bc47c15028._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2017-11-27T20:41:40Z"
+ content="""
+Yes, ensureProperty cannot be used with a Property HasInfo as that would
+prevent propellor from collecting that Info.
+
+You could avoid that by factoring the `blabla'` out of the properties
+that install packages, to the top level of the property:
+
+ blabla = blabla' `requires` installpackages
+ where
+ installpackages = withOS "Install BlaBla Stack" $ \w o -> case o of
+ ...
+"""]]
diff --git a/doc/forum/How_to_add_a_privdata_for_Gitlab_cookies/comment_4_ec1136accf484b572a1bcdfee40dcc92._comment b/doc/forum/How_to_add_a_privdata_for_Gitlab_cookies/comment_4_ec1136accf484b572a1bcdfee40dcc92._comment
new file mode 100644
index 00000000..596e2141
--- /dev/null
+++ b/doc/forum/How_to_add_a_privdata_for_Gitlab_cookies/comment_4_ec1136accf484b572a1bcdfee40dcc92._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="picca"
+ avatar="http://cdn.libravatar.org/avatar/7e61c80d28018b10d31f6db7dddb864c"
+ subject="comment 4"
+ date="2017-11-28T06:37:34Z"
+ content="""
+Thanks a lot,
+
+if I understand correctly,it means that it is not possible to use withPrivData with ensureProperty if the property HasInfo.
+
+Cheers
+
+Fred
+"""]]
diff --git a/doc/forum/Sbuild_and_jessie.mdwn b/doc/forum/Sbuild_and_jessie.mdwn
new file mode 100644
index 00000000..3786a26f
--- /dev/null
+++ b/doc/forum/Sbuild_and_jessie.mdwn
@@ -0,0 +1,23 @@
+Hello, I am using the Sbuild property on a jessie computer.
+
+after installing this
+
+ & (Sbuild.built Sbuild.UseCcache $ props
+ & osDebian (Stable "jessie") X86_64
+ & Sbuild.update `period` Weekly (Just 1)
+ & Sbuild.useHostProxy irdrx1)
+ & Sbuild.userConfig (User "picca")
+ & Sbuild.usableBy (User "picca")
+
+I get this error message
+
+picca@irdrx1:~/Debian/python-qtconsole/python-qtconsole$ sbuild
+Error reading configuration: AUTOPKGTEST binary 'autopkgtest' does not exist or is not executable at /usr/share/perl5/Sbuild/Conf.pm line 75.
+
+once `autopkgtest` installed it works great.
+
+So to my opinion the autopkgtest dependency is missing.
+
+Cheers and thanks for this new Sbuild which is really nice :))
+
+Frederic
diff --git a/doc/forum/Sbuild_and_jessie/comment_1_31dc85774c182a583aeb1935e9fef2d6._comment b/doc/forum/Sbuild_and_jessie/comment_1_31dc85774c182a583aeb1935e9fef2d6._comment
new file mode 100644
index 00000000..87508843
--- /dev/null
+++ b/doc/forum/Sbuild_and_jessie/comment_1_31dc85774c182a583aeb1935e9fef2d6._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="diagnosis"
+ date="2017-12-08T17:47:24Z"
+ content="""
+I think that the issue is that under jessie the binary is named `adt-run` not `autopkgtest`. In which case, the problem is in `Sbuild.userConfig` which refers to `autopkgtest`. Maybe `Sbuild.useConfig`'s haddock should say that it is for stretch and newer.
+
+`Sbuild.built` already installs `autopkgtest` (by means of `Sbuild.preReqsInstalled`). So I don't see how installing that package could have fixed the problem. Possibly you installed from jessie-backports, and maybe that version provides `/usr/bin/autopkgtest`?
+"""]]
diff --git a/doc/forum/Sbuild_and_jessie/comment_2_41ed6253709b18ec799624a66b9b8078._comment b/doc/forum/Sbuild_and_jessie/comment_2_41ed6253709b18ec799624a66b9b8078._comment
new file mode 100644
index 00000000..fd8646a1
--- /dev/null
+++ b/doc/forum/Sbuild_and_jessie/comment_2_41ed6253709b18ec799624a66b9b8078._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="comment 2"
+ date="2017-12-08T17:48:05Z"
+ content="""
+Hmm, what I said in my previous comment would make sense only if the host system is also jessie. Is it?
+"""]]
diff --git a/doc/forum/Sbuild_and_jessie/comment_3_a4d6fdbed71270d7a4ffbfe98d1aa479._comment b/doc/forum/Sbuild_and_jessie/comment_3_a4d6fdbed71270d7a4ffbfe98d1aa479._comment
new file mode 100644
index 00000000..8acacf57
--- /dev/null
+++ b/doc/forum/Sbuild_and_jessie/comment_3_a4d6fdbed71270d7a4ffbfe98d1aa479._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="picca"
+ avatar="http://cdn.libravatar.org/avatar/7e61c80d28018b10d31f6db7dddb864c"
+ subject="comment 3"
+ date="2017-12-08T18:21:46Z"
+ content="""
+I will be able to check which version of autopkgtest is installed on the computer only monday.
+Yes the host is the computer that I am configuring, so it is a jessie computer.
+
+cheers
+"""]]
diff --git a/doc/forum/Sbuild_and_jessie/comment_4_9e409a59abc81786481207ffbbd7c3ac._comment b/doc/forum/Sbuild_and_jessie/comment_4_9e409a59abc81786481207ffbbd7c3ac._comment
new file mode 100644
index 00000000..0974f8cd
--- /dev/null
+++ b/doc/forum/Sbuild_and_jessie/comment_4_9e409a59abc81786481207ffbbd7c3ac._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="picca"
+ avatar="http://cdn.libravatar.org/avatar/7e61c80d28018b10d31f6db7dddb864c"
+ subject="comment 4"
+ date="2017-12-13T15:44:13Z"
+ content="""
+Here the version, I installed
+
+ii autopkgtest 4.4~bpo8+1 all automatic as-installed testing for Debian packages
+"""]]
diff --git a/doc/forum/Sbuild_and_jessie/comment_5_6303943e3425b29b1e4727d809574cda._comment b/doc/forum/Sbuild_and_jessie/comment_5_6303943e3425b29b1e4727d809574cda._comment
new file mode 100644
index 00000000..96fd7fbf
--- /dev/null
+++ b/doc/forum/Sbuild_and_jessie/comment_5_6303943e3425b29b1e4727d809574cda._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="comment 5"
+ date="2017-12-16T15:11:05Z"
+ content="""
+Thanks. So I think that Sbuild.userConfig should either install the backport when the host's info indicates that it runs Jessie, or simply say in its docstring that it works for stretch or newer. Joey, which do you prefer?
+"""]]
diff --git a/doc/forum/Sbuild_and_jessie/comment_6_a88b331c80f57acdf55ac0c0ce3dce6f._comment b/doc/forum/Sbuild_and_jessie/comment_6_a88b331c80f57acdf55ac0c0ce3dce6f._comment
new file mode 100644
index 00000000..b98163a7
--- /dev/null
+++ b/doc/forum/Sbuild_and_jessie/comment_6_a88b331c80f57acdf55ac0c0ce3dce6f._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 6"""
+ date="2017-12-16T15:46:09Z"
+ content="""
+Either is fine by me. The property could also be made to fail when run
+on an unsupported version of Debian.
+"""]]
diff --git a/doc/forum/Sbuild_and_jessie/comment_7_38650a2151201eaf6f40d8becbbe8861._comment b/doc/forum/Sbuild_and_jessie/comment_7_38650a2151201eaf6f40d8becbbe8861._comment
new file mode 100644
index 00000000..12dfbaac
--- /dev/null
+++ b/doc/forum/Sbuild_and_jessie/comment_7_38650a2151201eaf6f40d8becbbe8861._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ avatar="http://cdn.libravatar.org/avatar/9c3f08f80e67733fd506c353239569eb"
+ subject="Patch mailed to propellor@joeyh.name"
+ date="2017-12-22T18:11:07Z"
+ content="""
+I started preparing a patch so that `Sbuild.userConfig` would install the backport on Jessie, but realised that what is probably going on is that you have a backport of sbuild installed -- I assume that the sbuild that comes with jessie tries to invoke `adt-run` not `autopkgtest`. So `Sbuild.userConfig` would have to check the installed version of sbuild before it could determine whether to install the backport of autopkgtest.
+
+I think it would be unwise to incorporate that complexity into Sbuild.hs for the sake of an old release of Debian, so I've mailed a patch to Joey simply documenting the issue.
+"""]]
diff --git a/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__.mdwn b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__.mdwn
new file mode 100644
index 00000000..232dfe95
--- /dev/null
+++ b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__.mdwn
@@ -0,0 +1,131 @@
+I'm trying to create an image to boot a PC Engines' APU2, which uses coreboot. The debugging is particularly funny as I don't have a usb to serial converter to see what's going on -_-. I've used the following properties:
+
+ laptop :: Host
+ laptop = host "laptop" $ props
+ & osDebian Unstable X86_64
+ ...
+ & imageBuiltFor router
+ (RawDiskImage "/srv/router.img")
+ (Chroot.Debootstrapped mempty)
+
+ router :: Host
+ router = host "router" $ props
+ & hasPartitionTableType GPT
+ & hasPartition
+ ( partition EXT2
+ `mountedAt` "/boot"
+ `partLocation` Beginning
+ `setSize` MegaBytes 150
+ )
+ & hasPartition
+ ( partition EXT4
+ `mountedAt` "/"
+ `addFreeSpace` MegaBytes 500
+ )
+ & osDebian (Stable "stretch") X86_64
+ & Apt.installed ["linux-image-amd64"]
+ & serialGrub
+ ...
+ where
+ serialGrub :: Property (HasInfo + DebianLike)
+ serialGrub = "/etc/default/grub" `File.containsLines`
+ [ "GRUB_CMDLINE_LINUX=\"console=ttyS0,115200n8 biosdevname=0\""
+ , "GRUB_SERIAL_COMMAND=\"serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1\""
+ , "GRUB_TERMINAL=serial"
+ ]
+ -- `onChange` Grub.mkConfig
+ `requires` Grub.installed Grub.Coreboot
+ `describe` "GRUB configured for PC Engines' APU2 serial console"
+
+This returns:
+
+ $ propellor --spin laptop
+ ...
+ router no services started ... ok
+ router has partition table type GPT ... ok
+ router has has /boot partition ... ok
+ router has has / partition ... ok
+ router has Operating System (Debian Linux (Stable "stretch")) X86_64 ... ok
+ ...
+ router apt installed linux-image-amd64 ... ok
+ Reading package lists...
+ Building dependency tree...
+ Reading state information...
+ The following additional packages will be installed:
+ gettext-base grub-common grub-coreboot-bin grub2-common libfreetype6
+ libfuse2 libpng16-16 os-prober
+ Suggested packages:
+ multiboot-doc grub-emu xorriso desktop-base console-setup fuse
+ The following NEW packages will be installed:
+ gettext-base grub-common grub-coreboot grub-coreboot-bin grub2-common
+ libfreetype6 libfuse2 libpng16-16 os-prober
+ 0 upgraded, 9 newly installed, 0 to remove and 0 not upgraded.
+ Need to get 4354 kB of archives.
+ After this operation, 20.9 MB of additional disk space will be used.
+ Get:1 http://deb.debian.org/debian stretch/main amd64 libpng16-16 amd64 1.6.28-1 [280 kB]
+ Get:2 http://deb.debian.org/debian stretch/main amd64 libfreetype6 amd64 2.6.3-3.2 [438 kB]
+ Get:3 http://deb.debian.org/debian stretch/main amd64 libfuse2 amd64 2.9.7-1 [125 kB]
+ Get:4 http://deb.debian.org/debian stretch/main amd64 gettext-base amd64 0.19.8.1-2 [121 kB]
+ Get:5 http://deb.debian.org/debian stretch/main amd64 grub-common amd64 2.02~beta3-5 [2174 kB]
+ Get:6 http://deb.debian.org/debian stretch/main amd64 grub2-common amd64 2.02~beta3-5 [526 kB]
+ Get:7 http://deb.debian.org/debian stretch/main amd64 grub-coreboot-bin amd64 2.02~beta3-5 [587 kB]
+ Get:8 http://deb.debian.org/debian stretch/main amd64 grub-coreboot amd64 2.02~beta3-5 [73.0 kB]
+ Get:9 http://deb.debian.org/debian stretch/main amd64 os-prober amd64 1.76~deb9u1 [30.0 kB]
+ Preconfiguring packages ...
+ E: Can not write log (Is /dev/pts mounted?) - posix_openpt (19: No such device)
+ Fetched 4354 kB in 1s (2803 kB/s)
+ Selecting previously unselected package libpng16-16:amd64.
+ (Reading database ... 26264 files and directories currently installed.)
+ Preparing to unpack .../0-libpng16-16_1.6.28-1_amd64.deb ...
+ Unpacking libpng16-16:amd64 (1.6.28-1) ...
+ Selecting previously unselected package libfreetype6:amd64.
+ Preparing to unpack .../1-libfreetype6_2.6.3-3.2_amd64.deb ...
+ Unpacking libfreetype6:amd64 (2.6.3-3.2) ...
+ Selecting previously unselected package libfuse2:amd64.
+ Preparing to unpack .../2-libfuse2_2.9.7-1_amd64.deb ...
+ Unpacking libfuse2:amd64 (2.9.7-1) ...
+ Selecting previously unselected package gettext-base.
+ Preparing to unpack .../3-gettext-base_0.19.8.1-2_amd64.deb ...
+ Unpacking gettext-base (0.19.8.1-2) ...
+ Selecting previously unselected package grub-common.
+ Preparing to unpack .../4-grub-common_2.02~beta3-5_amd64.deb ...
+ Unpacking grub-common (2.02~beta3-5) ...
+ Selecting previously unselected package grub2-common.
+ Preparing to unpack .../5-grub2-common_2.02~beta3-5_amd64.deb ...
+ Unpacking grub2-common (2.02~beta3-5) ...
+ Selecting previously unselected package grub-coreboot-bin.
+ Preparing to unpack .../6-grub-coreboot-bin_2.02~beta3-5_amd64.deb ...
+ Unpacking grub-coreboot-bin (2.02~beta3-5) ...
+ Selecting previously unselected package grub-coreboot.
+ Preparing to unpack .../7-grub-coreboot_2.02~beta3-5_amd64.deb ...
+ Unpacking grub-coreboot (2.02~beta3-5) ...
+ Selecting previously unselected package os-prober.
+ Preparing to unpack .../8-os-prober_1.76~deb9u1_amd64.deb ...
+ Unpacking os-prober (1.76~deb9u1) ...
+ Setting up libpng16-16:amd64 (1.6.28-1) ...
+ Setting up libfuse2:amd64 (2.9.7-1) ...
+ Setting up gettext-base (0.19.8.1-2) ...
+ Setting up libfreetype6:amd64 (2.6.3-3.2) ...
+ Processing triggers for libc-bin (2.24-11+deb9u1) ...
+ Setting up grub-common (2.02~beta3-5) ...
+ Setting up grub2-common (2.02~beta3-5) ...
+ Setting up os-prober (1.76~deb9u1) ...
+ Setting up grub-coreboot-bin (2.02~beta3-5) ...
+
+ Creating config file /etc/default/grub with new version
+ Setting up grub-coreboot (2.02~beta3-5) ...
+ router GRUB configured for PC Engines' APU2 serial console ... ok
+ loop deleted : /dev/loop0
+ 25,091,167 100% 194.29MB/s 0:00:00 (xfr#4, to-chk=0/5)
+ 769,633,861 99% 26.74MB/s 0:00:27 (xfr#26204, to-chk=0/33524)
+ update-initramfs: Generating /boot/initrd.img-4.9.0-4-amd64
+ /usr/sbin/grub-mkconfig: 253: /usr/sbin/grub-mkconfig: cannot create /boot/grub/grub.cfg.new: Directory nonexistent
+ loop deleted : /dev/loop0
+ laptop built disk image /srv/router.img ... failed
+ laptop overall ... failed
+
+So, grub-mkconfig seems to be run without /boot/grub existing, which I can confirm by looking into /srv/router.img.chroot/boot/:
+
+ $ ls /srv/router.img.chroot/boot/
+ config-4.9.0-4-amd64 initrd.img-4.9.0-4-amd64 System.map-4.9.0-4-amd64 vmlinuz-4.9.0-4-amd64
+
diff --git a/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_10_4cfd25f81e2ed3a0cc491558038e347b._comment b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_10_4cfd25f81e2ed3a0cc491558038e347b._comment
new file mode 100644
index 00000000..a6eb510a
--- /dev/null
+++ b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_10_4cfd25f81e2ed3a0cc491558038e347b._comment
@@ -0,0 +1,7 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 10"""
+ date="2017-12-21T04:05:40Z"
+ content="""
+Implemented --target passing based on Grub.installed's Info.
+"""]]
diff --git a/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_1_abbccfa3a607086ec96da122ae39fb57._comment b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_1_abbccfa3a607086ec96da122ae39fb57._comment
new file mode 100644
index 00000000..205d783b
--- /dev/null
+++ b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_1_abbccfa3a607086ec96da122ae39fb57._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="gueux"
+ avatar="http://cdn.libravatar.org/avatar/2982bac2c2cd94ab3860efb189deafc8"
+ subject="comment 1"
+ date="2017-12-19T21:45:08Z"
+ content="""
+I tried to swap update-grub and grub-install in Grub.bootsMounted, I get:
+
+ ...
+ 17,512,735 69% 185.22MB/s 0:00:00 (xfr#1, to-chk=0/5)
+ 129 0% 0.15kB/s 0:00:00 (xfr#3, to-chk=0/33524)
+ update-initramfs: Generating /boot/initrd.img-4.9.0-4-amd64
+ grub-install: error: /usr/lib/grub/i386-pc/modinfo.sh doesn't exist. Please specify --target or --directory.
+ loop deleted : /dev/loop0
+ laptop built disk image /srv/router.img ... failed
+ laptop overall ... failed
+
+Which is weird, as grub-install should try to use /usr/lib/grub/i386-coreboot/...
+
+"""]]
diff --git a/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_2_00b8165c200b515c98d4e66c66df8a56._comment b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_2_00b8165c200b515c98d4e66c66df8a56._comment
new file mode 100644
index 00000000..099be8a2
--- /dev/null
+++ b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_2_00b8165c200b515c98d4e66c66df8a56._comment
@@ -0,0 +1,27 @@
+[[!comment format=mdwn
+ username="gueux"
+ avatar="http://cdn.libravatar.org/avatar/2982bac2c2cd94ab3860efb189deafc8"
+ subject="comment 2"
+ date="2017-12-19T22:01:17Z"
+ content="""
+manually adding \"--target\" and \"i386-coreboot\" to grub-install arguments seems to make the build successful:
+
+ 17,512,735 69% 155.80MB/s 0:00:00 (xfr#1, to-chk=0/5)
+ 129 0% 0.14kB/s 0:00:00 (xfr#3, to-chk=0/33524)
+ update-initramfs: Generating /boot/initrd.img-4.9.0-4-amd64
+ Installing for i386-coreboot platform.
+ grub-install: warning: WARNING: no platform-specific install was performed.
+ Installation finished. No error reported.
+ Generating grub configuration file ...
+ Found linux image: /boot/vmlinuz-4.9.0-4-amd64
+ Found initrd image: /boot/initrd.img-4.9.0-4-amd64
+ done
+ loop deleted : /dev/loop0
+ laptop built disk image /srv/router.img ... done
+ laptop overall ... done
+
+I've not tested the image yet, but I guess we need to a BIOS argument to bootsMounted, or put the BIOS property is Info.
+
+/srv/router.img.chroot/boot/ still contains only, config-4.9.0-4-amd64, System.map-4.9.0-4-amd64, initrd.img-4.9.0-4-amd64, vmlinuz-4.9.0-4-amd64. There is no /srv/router.img.chroot/boot/grub/
+
+"""]]
diff --git a/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_3_f0d4a3e7e41e2fe5ea981e8755ffede3._comment b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_3_f0d4a3e7e41e2fe5ea981e8755ffede3._comment
new file mode 100644
index 00000000..c3f3a84e
--- /dev/null
+++ b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_3_f0d4a3e7e41e2fe5ea981e8755ffede3._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2017-12-20T16:40:36Z"
+ content="""
+I think it makes sense to pass BIOS to Grub.bootsMounted (and also to
+Grub.boots). Of course the image building properties will also get an added
+parameter. This should be straightforward to do.
+
+(Using info for it could work, but I don't know if it would avoid any
+duplication of configuration.)
+"""]]
diff --git a/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_4_e30b385d9b6a5e41809eb7b482d15e46._comment b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_4_e30b385d9b6a5e41809eb7b482d15e46._comment
new file mode 100644
index 00000000..ab320e25
--- /dev/null
+++ b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_4_e30b385d9b6a5e41809eb7b482d15e46._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="gueux"
+ avatar="http://cdn.libravatar.org/avatar/2982bac2c2cd94ab3860efb189deafc8"
+ subject="comment 4"
+ date="2017-12-20T18:01:33Z"
+ content="""
+Should update-grub and grub-install be swapped (as I did) in Grub.bootsMounted?
+
+
+"""]]
diff --git a/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_5_2de24368d2891a5d44107ab7a858f3c1._comment b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_5_2de24368d2891a5d44107ab7a858f3c1._comment
new file mode 100644
index 00000000..08f78521
--- /dev/null
+++ b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_5_2de24368d2891a5d44107ab7a858f3c1._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="gueux"
+ avatar="http://cdn.libravatar.org/avatar/2982bac2c2cd94ab3860efb189deafc8"
+ subject="comment 5"
+ date="2017-12-20T18:19:49Z"
+ content="""
+Are you preparing a patch to pass BIOS to Grub.bootsMounted and Grub.boots or do you want me to do so?
+"""]]
diff --git a/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_6_2dac20b315875c93e17e6733a42264ff._comment b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_6_2dac20b315875c93e17e6733a42264ff._comment
new file mode 100644
index 00000000..37712317
--- /dev/null
+++ b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_6_2dac20b315875c93e17e6733a42264ff._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 6"""
+ date="2017-12-20T21:33:31Z"
+ content="""
+update-grub generates the grub config file, so AFAIK it needs to come
+before grub-install.
+
+If you can do the patches for BIOS please do.
+"""]]
diff --git a/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_7_cb0a1052e1ad421d4c1f2b15c30a7f06._comment b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_7_cb0a1052e1ad421d4c1f2b15c30a7f06._comment
new file mode 100644
index 00000000..f5fcf414
--- /dev/null
+++ b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_7_cb0a1052e1ad421d4c1f2b15c30a7f06._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="gueux"
+ avatar="http://cdn.libravatar.org/avatar/2982bac2c2cd94ab3860efb189deafc8"
+ subject="comment 7"
+ date="2017-12-20T21:54:30Z"
+ content="""
+But that seems to fail without switching the two (see my original problem and my first comment), or is there another problem?
+
+I can provide the patch for BIOS tomorrow.
+"""]]
diff --git a/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_8_7f0b14866c6473f2218fc6ae97a9adee._comment b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_8_7f0b14866c6473f2218fc6ae97a9adee._comment
new file mode 100644
index 00000000..bdf10e6f
--- /dev/null
+++ b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_8_7f0b14866c6473f2218fc6ae97a9adee._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 8"""
+ date="2017-12-20T22:21:35Z"
+ content="""
+The debian grub-pc package creates /boot/grub in its postinst.
+
+It seems that grub-coreboot does not. I don't know why.
+Seems like it could be considered a bug to me; installing the package
+and then running grub-mkconfig ought to just work. I'm going to file a bug
+report.
+
+Anyway, I suppose propellor ought to work around the bug by making sure
+/boot/grub exists.
+"""]]
diff --git a/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_9_b0ebdfabdc973c7e4a24825d5ab327d2._comment b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_9_b0ebdfabdc973c7e4a24825d5ab327d2._comment
new file mode 100644
index 00000000..683e7989
--- /dev/null
+++ b/doc/forum/grub-mkconfig_incorrectly_run_by_imageBuiltFor__63__/comment_9_b0ebdfabdc973c7e4a24825d5ab327d2._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 9"""
+ date="2017-12-21T03:32:59Z"
+ content="""
+I forgot -- Grub.installed already sets Info to say what BIOS
+it was installed for. So, bootsMounted can just get that Info and
+pass the appropriate --target.
+"""]]
diff --git a/doc/forum/imageBuiltFor_mount_points_not_automatically_created.mdwn b/doc/forum/imageBuiltFor_mount_points_not_automatically_created.mdwn
new file mode 100644
index 00000000..003bc716
--- /dev/null
+++ b/doc/forum/imageBuiltFor_mount_points_not_automatically_created.mdwn
@@ -0,0 +1,52 @@
+I'm trying to build an image for my router, which (after all) seems to need Grub.EFI64...
+
+Here is my config:
+
+ caillette = host hn $ props
+ & hasPartitionTableType GPT
+ & hasPartition
+ ( partition VFAT
+ `mountedAt` "/boot/efi"
+ `partLocation` Beginning
+ `setSize` MegaBytes 10
+ `setFlag` EspFlag
+ )
+ & hasPartition
+ ( partition EXT2
+ `mountedAt` "/boot"
+ `setSize` MegaBytes 150
+ )
+ & hasPartition
+ ( partition EXT4
+ `mountedAt` "/"
+ `partLocation` End
+ `addFreeSpace` MegaBytes 500
+ )
+ & standardSystem (Stable "stretch") X86_64
+ [ "home router" ]
+ & Apt.installed ["linux-image-amd64"]
+ & serialGrub
+ where
+ serialGrub :: Property (HasInfo + DebianLike)
+ serialGrub = "/etc/default/grub" `File.containsLines`
+ [ "GRUB_CMDLINE_LINUX=\"console=ttyS0,115200n8 biosdevname=0\""
+ , "GRUB_SERIAL_COMMAND=\"serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1\""
+ , "GRUB_TERMINAL=serial"
+ ]
+ -- `onChange` Grub.mkConfig
+ `requires` Grub.installed Grub.EFI64
+ `describe` "GRUB configured for PC Engines' APU2 serial console"
+
+When running propellor it fails with:
+
+ ...
+ mkfs.fat 4.1 (2017-01-24)
+ loop deleted : /dev/loop0
+ rsync: change_dir "/srv/router.img.chroot/boot/efi" failed: No such file or directory (2)
+ 0 100% 0.00kB/s 0:00:00 (xfr#0, to-chk=0/0)rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1196) [sender=3.1.2]
+
+ loop deleted : /dev/loop0
+ laptop built disk image /srv/router.img ... failed
+ laptop overall ... failed
+
+Shouldn't /boot/efi be automatically created?
diff --git a/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_10_00b4f5d4fd445b8041a2744c2dd755f0._comment b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_10_00b4f5d4fd445b8041a2744c2dd755f0._comment
new file mode 100644
index 00000000..e38825e1
--- /dev/null
+++ b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_10_00b4f5d4fd445b8041a2744c2dd755f0._comment
@@ -0,0 +1,36 @@
+[[!comment format=mdwn
+ username="gueux"
+ avatar="http://cdn.libravatar.org/avatar/2982bac2c2cd94ab3860efb189deafc8"
+ subject="comment 10"
+ date="2017-12-22T10:21:28Z"
+ content="""
+Ouch, that does not seem like it was easy to debug... Thanks for looking into this!
+
+ src/Propellor/Property/Parted.hs:114:27: warning: [-Wtype-defaults]
+ • Defaulting the following constraints to type ‘Double’
+ (Show a0)
+ arising from a use of ‘show’
+ at src/Propellor/Property/Parted.hs:114:27-57
+ (Fractional a0)
+ arising from a use of ‘/’
+ at src/Propellor/Property/Parted.hs:114:33-56
+ (Num a0)
+ arising from a use of ‘fromIntegral’
+ at src/Propellor/Property/Parted.hs:114:33-46
+ • In the first argument of ‘(++)’, namely
+ ‘show (fromIntegral n / 1000000)’
+ In the expression: show (fromIntegral n / 1000000) ++ \"MB\"
+ In an equation for ‘partposfuzzy’:
+ partposfuzzy n
+ | n > 0 = show (fromIntegral n / 1000000) ++ \"MB\"
+ | otherwise = \"1MB\"
+
+I now get:
+
+ mount: /tmp/mntzZ3vjF: wrong fs type, bad option, bad superblock on /dev/mapper/loop0p2, missing codepage or helper program, or other error.
+ umount: /tmp/mntzZ3vjF: not mounted.
+ ** fatal error: failed unmounting /tmp/mntzZ3vjF
+ propellor: StopPropellorException \"Cannot continue!\"
+
+:(. I'll try to reboot, I don't get how to remove/unmount this /dev/mapper/loop0p2 (I tried \"dmsetup remove\", \"losetup -d\" without success...)
+"""]]
diff --git a/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_11_6f691ea981679e92d7c0ae6cf1cfce6f._comment b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_11_6f691ea981679e92d7c0ae6cf1cfce6f._comment
new file mode 100644
index 00000000..8d39744b
--- /dev/null
+++ b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_11_6f691ea981679e92d7c0ae6cf1cfce6f._comment
@@ -0,0 +1,29 @@
+[[!comment format=mdwn
+ username="gueux"
+ avatar="http://cdn.libravatar.org/avatar/2982bac2c2cd94ab3860efb189deafc8"
+ subject="comment 11"
+ date="2017-12-22T12:10:37Z"
+ content="""
+So, I rebooted, but I still had the /dev/mapper/loop problem. I was able to \"dmsetup remove\" these, though...
+
+I deleted router.img and router.img.parttable...
+
+ creating /srv/router.img of size 1.66 gigabytes
+ loop deleted : /dev/loop0
+ mkfs.fat 4.1 (2017-01-24)
+ loop deleted : /dev/loop0
+ 26,456,191 100% 29.82MB/s 0:00:00 (xfr#5, to-chk=0/7)
+ 770,763,841 99% 2.16MB/s 0:05:40 (xfr#26256, to-chk=0/33583)
+ update-initramfs: Generating /boot/initrd.img-4.9.0-4-amd64
+ Generating grub configuration file ...
+ Found linux image: /boot/vmlinuz-4.9.0-4-amd64
+ Found initrd image: /boot/initrd.img-4.9.0-4-amd64
+ done
+ grub-install: error: /usr/lib/grub/i386-efi/modinfo.sh doesn't exist. Please specify --target or --directory.
+ loop deleted : /dev/loop0
+ laptop built disk image /srv/router.img ... failed
+ laptop overall ... failed
+
+
+...and I'm back to the grub-install/grub-update problem, which seems to apply to grub-efi-amd64. It's weird, because it's the version I have on my laptop, and I did not notice this issue (but I installed debian on it a long time ago, so, the bug may have appeared since then).
+"""]]
diff --git a/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_12_8717ae3d2e60d07025a11c930cf26b84._comment b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_12_8717ae3d2e60d07025a11c930cf26b84._comment
new file mode 100644
index 00000000..caaa5713
--- /dev/null
+++ b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_12_8717ae3d2e60d07025a11c930cf26b84._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="gueux"
+ avatar="http://cdn.libravatar.org/avatar/2982bac2c2cd94ab3860efb189deafc8"
+ subject="comment 12"
+ date="2017-12-22T12:16:50Z"
+ content="""
+Or not? I found this one: you inverted EFI64 and EFI32 in Grub.targetParam :)
+"""]]
diff --git a/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_13_10b9bf6e92a80dff2c14f41c22347b3f._comment b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_13_10b9bf6e92a80dff2c14f41c22347b3f._comment
new file mode 100644
index 00000000..6d8a33eb
--- /dev/null
+++ b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_13_10b9bf6e92a80dff2c14f41c22347b3f._comment
@@ -0,0 +1,22 @@
+[[!comment format=mdwn
+ username="gueux"
+ avatar="http://cdn.libravatar.org/avatar/2982bac2c2cd94ab3860efb189deafc8"
+ subject="comment 13"
+ date="2017-12-22T12:20:57Z"
+ content="""
+ 17,514,598 66% 53.61MB/s 0:00:00 (xfr#1, to-chk=0/7)
+ 129 0% 0.06kB/s 0:00:01 (xfr#3, to-chk=0/33583)
+ update-initramfs: Generating /boot/initrd.img-4.9.0-4-amd64
+ Generating grub configuration file ...
+ Found linux image: /boot/vmlinuz-4.9.0-4-amd64
+ Found initrd image: /boot/initrd.img-4.9.0-4-amd64
+ done
+ Installing for x86_64-efi platform.
+ Installation finished. No error reported.
+ loop deleted : /dev/loop0
+ laptop built disk image /srv/router.img ... done
+ laptop overall ... done
+
+
+\o/. Let's see if it boots... I just have one try, then I'll have to move for a few days...
+"""]]
diff --git a/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_14_d7948bf285cc4769ccd1802a1fa86eee._comment b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_14_d7948bf285cc4769ccd1802a1fa86eee._comment
new file mode 100644
index 00000000..88870d0d
--- /dev/null
+++ b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_14_d7948bf285cc4769ccd1802a1fa86eee._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="gueux"
+ avatar="http://cdn.libravatar.org/avatar/2982bac2c2cd94ab3860efb189deafc8"
+ subject="comment 14"
+ date="2017-12-22T12:44:18Z"
+ content="""
+Unfortunately it didn't... But I think it's probably a problem of choosing the right grub version. I did boot a grml64 sdcard, and I think they use hybrid bios/uefi boot. I have to investigate, let's see this in a few days :)
+
+Thanks a lot for your help!
+"""]]
diff --git a/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_15_05bdf475e1a8b5d8d36f88fef0210383._comment b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_15_05bdf475e1a8b5d8d36f88fef0210383._comment
new file mode 100644
index 00000000..5bf364ac
--- /dev/null
+++ b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_15_05bdf475e1a8b5d8d36f88fef0210383._comment
@@ -0,0 +1,7 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 15"""
+ date="2017-12-22T13:24:44Z"
+ content="""
+Oops, fixed the Grub.targetParam inversion.
+"""]]
diff --git a/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_16_53ec0ff959e60af5382f2b6fd54ced26._comment b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_16_53ec0ff959e60af5382f2b6fd54ced26._comment
new file mode 100644
index 00000000..e471dfc2
--- /dev/null
+++ b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_16_53ec0ff959e60af5382f2b6fd54ced26._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="stappers"
+ avatar="http://cdn.libravatar.org/avatar/bf33450acf6fc2a17a8b4e6fc7749c65"
+ subject="the working config"
+ date="2017-12-27T21:26:21Z"
+ content="""
+Is the working config somewhere available?
+
+If yes, where??
+
+
+Yes, I what to reproduce it.
+
+
+Cheers
+Geert Stappers
+"""]]
diff --git a/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_1_af7d83cf29a578901fcf9aca0ea2426b._comment b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_1_af7d83cf29a578901fcf9aca0ea2426b._comment
new file mode 100644
index 00000000..e32e0870
--- /dev/null
+++ b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_1_af7d83cf29a578901fcf9aca0ea2426b._comment
@@ -0,0 +1,27 @@
+[[!comment format=mdwn
+ username="gueux"
+ avatar="http://cdn.libravatar.org/avatar/2982bac2c2cd94ab3860efb189deafc8"
+ subject="comment 1"
+ date="2017-12-20T19:00:54Z"
+ content="""
+When I add a `File.dirExists \"/boot/efi\"` property, it goes further, but fails at the end:
+
+ 0 100% 0.00kB/s 0:00:00 (xfr#0, to-chk=0/1)
+ 26,454,269 100% 163.62MB/s 0:00:00 (xfr#5, to-chk=0/8)
+ 770,765,173 99% 53.06MB/s 0:00:13 (xfr#26256, to-chk=0/33584)
+ update-initramfs: Generating /boot/initrd.img-4.9.0-4-amd64
+ Installing for x86_64-efi platform.
+ Installation finished. No error reported.
+ Generating grub configuration file ...
+ Found linux image: /boot/vmlinuz-4.9.0-4-amd64
+ Found initrd image: /boot/initrd.img-4.9.0-4-amd64
+ done
+ umount: /tmp/mntAMcRoY/boot/efi: not mounted.
+ ** fatal error: failed unmounting /tmp/mntAMcRoY/boot/efi
+ ** warning: /tmp/mntAMcRoY: removeDirectoryRecursive:removeContentsRecursive:removeDirectory: resource busy (Device or resource busy)
+ device-mapper: remove ioctl on loop0p3 failed: Device or resource busy
+ loop deleted : /dev/loop0
+ laptop built disk image /srv/router.img ... failed
+ laptop overall ... failed
+
+"""]]
diff --git a/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_2_f90109eb016065586225fc59674c431c._comment b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_2_f90109eb016065586225fc59674c431c._comment
new file mode 100644
index 00000000..d8655a59
--- /dev/null
+++ b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_2_f90109eb016065586225fc59674c431c._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2017-12-20T21:36:36Z"
+ content="""
+AFAICS, DiskImage.imageFinalized creates any mount points that were not
+rsynced over from the chroot. But, I guess that partitionsPopulated is
+expecting the mount point to exist in order to rsync its content over,
+and if nothing created /boot/efi that would explain the rsync error.
+I've added a check to prevent that problem.
+
+As for the unmount problem, it's a problem with the order
+it traverses the mount points for unmounting. That is using
+"unmountBelow" with the directory where the disk image partitions
+are loop mounted. If that unmounts `boot` first, it will implicitly
+unmount `boot/efi` (due to --lazy) and then will fail when it
+tries to explicitly unmount it. Added sorting that should fix that.
+
+Let me know how that goes, I've not tested it with your config.
+"""]]
diff --git a/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_3_f2ec6998ed728f42cdb23116dbce8ade._comment b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_3_f2ec6998ed728f42cdb23116dbce8ade._comment
new file mode 100644
index 00000000..8bf91368
--- /dev/null
+++ b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_3_f2ec6998ed728f42cdb23116dbce8ade._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="gueux"
+ avatar="http://cdn.libravatar.org/avatar/2982bac2c2cd94ab3860efb189deafc8"
+ subject="comment 3"
+ date="2017-12-21T09:11:23Z"
+ content="""
+OK.
+I tried to run propellor again, I got a new error (probably related to the recent alignment changes):
+
+ ...
+ creating /srv/router.img of size 1.66 gigabytes
+ Error: You requested a partition from 168MB to 1661MB (sectors 327680..3244031).
+ The closest location we can manage is 168MB to 1661MB (sectors 327680..3243998).
+ laptop built disk image /srv/router.img ... failed
+ laptop overall ... failed
+
+"""]]
diff --git a/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_4_021311b587601d76c64afe06638e1fef._comment b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_4_021311b587601d76c64afe06638e1fef._comment
new file mode 100644
index 00000000..ae5f6463
--- /dev/null
+++ b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_4_021311b587601d76c64afe06638e1fef._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 4"""
+ date="2017-12-21T16:06:56Z"
+ content="""
+That's definitely due to the alignment changes, I knew those changes
+could run afoul of parted's checks, but in my tests they seemed to work.
+
+Could you paste /srv/router.img.parttable, that should have enough
+infromation for me to reproduce the problem.
+"""]]
diff --git a/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_5_95af19d3f8e01525a616b48e376c3326._comment b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_5_95af19d3f8e01525a616b48e376c3326._comment
new file mode 100644
index 00000000..6eaa60ab
--- /dev/null
+++ b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_5_95af19d3f8e01525a616b48e376c3326._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="gueux"
+ avatar="http://cdn.libravatar.org/avatar/2982bac2c2cd94ab3860efb189deafc8"
+ subject="comment 5"
+ date="2017-12-21T16:21:50Z"
+ content="""
+ PartTable GPT (Alignment 4194304) [Partition {partType = Primary, partSize = MegaBytes 10, partFs = VFAT, partMkFsOpts = [], partFlags = [(EspFlag,True)], partName = Nothing},Partition {partType = Primary, partSize = MegaBytes 150, partFs = EXT2, partMkFsOpts = [], partFlags = [], partName = Nothing},Partition {partType = Primary, partSize = MegaBytes 1489, partFs = EXT4, partMkFsOpts = [], partFlags = [], partName = Nothing}]
+"""]]
diff --git a/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_6_8c454f014e0cf4e6b3af9b8f68f987fa._comment b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_6_8c454f014e0cf4e6b3af9b8f68f987fa._comment
new file mode 100644
index 00000000..711fc21e
--- /dev/null
+++ b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_6_8c454f014e0cf4e6b3af9b8f68f987fa._comment
@@ -0,0 +1,7 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 6"""
+ date="2017-12-21T18:51:01Z"
+ content="""
+Oh also need the size of /srv/router.img in bytes.
+"""]]
diff --git a/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_7_ad9ea2799890df2dfce4f0cc99e397e9._comment b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_7_ad9ea2799890df2dfce4f0cc99e397e9._comment
new file mode 100644
index 00000000..f273d3b0
--- /dev/null
+++ b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_7_ad9ea2799890df2dfce4f0cc99e397e9._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="gueux"
+ avatar="http://cdn.libravatar.org/avatar/2982bac2c2cd94ab3860efb189deafc8"
+ subject="comment 7"
+ date="2017-12-21T18:54:32Z"
+ content="""
+1660944384
+"""]]
diff --git a/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_8_ad50abb937a9801a4db2293765137b75._comment b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_8_ad50abb937a9801a4db2293765137b75._comment
new file mode 100644
index 00000000..4e102a26
--- /dev/null
+++ b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_8_ad50abb937a9801a4db2293765137b75._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="gueux"
+ avatar="http://cdn.libravatar.org/avatar/2982bac2c2cd94ab3860efb189deafc8"
+ subject="comment 8"
+ date="2017-12-21T20:40:56Z"
+ content="""
+parted seems pretty hairy with partition alignment. In case it's too hard to integrate parted with propellor, maybe fdisk would be easier?
+"""]]
diff --git a/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_9_68b3d9ca04283c2400f5b23e486bb4b7._comment b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_9_68b3d9ca04283c2400f5b23e486bb4b7._comment
new file mode 100644
index 00000000..fd5b25e4
--- /dev/null
+++ b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_9_68b3d9ca04283c2400f5b23e486bb4b7._comment
@@ -0,0 +1,62 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2017-12-21T19:44:45Z"
+ content="""
+Reproduced it with that information.
+
+ ghci> calcPartedParamsSize guexPartTable
+ (["mklabel","gpt","mkpart","primary","fat32","4194304B","16777215B","set","1","esp","on","mkpart","primary","ext2","16777216B","167772159B","mkpart","primary","ext4","167772160B","1660944383B"],1660944384)
+ joey@darkstar:~>dd if=/dev/zero of=test bs=1M count=1584
+ joey@darkstar:~>parted test
+ (parted) p
+ Model: (file)
+ Disk /home/joey/test: 1661MB
+ Sector size (logical/physical): 512B/512B
+ (parted) mklabel gpt
+ (parted) mkpart primary fat32 4194304B 16777215B
+ (parted) mkpart primary ext2 16777216B 167772159B
+ (parted) mkpart primary ext4 167772160B 1660944383B
+ Warning: You requested a partition from 168MB to 1661MB (sectors 327680..3244031).
+ The closest location we can manage is 168MB to 1661MB (sectors 327680..3243998).
+
+The problem only occurs with the gpt partition table. With "mklabel msdos",
+the mkpart command succeeds.
+
+So, gpt must have an additional restriction
+of some kind. I don't know what. The highest end position that parted
+will accept for that partition is 1660927487B; slightly smaller partitions
+are accepted. It's not a requirement that the position or size be divisible
+by anything in particular. Perhaps gpt needs some amount of reserved space
+at the end of the disk or something.
+
+Before 4MiB alignment was added, here's what
+propellor did for the same PartTable, which worked.
+
+ mkpart primary ext4 160MB 1649MB
+
+It would be good for propellor to not need to know about all the minutia of
+partition tables. Seems that the way it used to call parted gave it enough
+wiggle room that it avoided this kind of problem.
+
+To make parititions well aligned, propellor needs to precisely control where
+they begin (since parted does not have a way to configure modern
+alignment requirments). Perhaps propellor could precisely specify where a
+partition begins, but use the "MB" to leave wiggle room in where it ends
+so parted can pick a suitable end point.
+
+Let's see.. this works with the gpt example:
+
+ (parted) mkpart primary fat32 4194304B 16.777215MB
+ (parted) mkpart primary ext2 16777216B 167.772159MB
+ (parted) mkpart primary ext4 167772160B 1660.944383MB
+
+That lets parted end the last partition right at the ideal 1660927487B.
+The previous two partitions end right where propellor expects.
+(Hopefully parted never rounds a MB value *up*!)
+
+Ok, I've convinced myself to make propellor use this wacky technique
+of B for the start position and fractional MB for the end position!
+I've implemented it, hopefully my analysis above is good to make
+this work with all the different kinds of partition tables.
+"""]]
diff --git a/doc/forum/parted:_invalid_token:_fat.mdwn b/doc/forum/parted:_invalid_token:_fat.mdwn
new file mode 100644
index 00000000..d5e5f532
--- /dev/null
+++ b/doc/forum/parted:_invalid_token:_fat.mdwn
@@ -0,0 +1,37 @@
+I'm trying to add a fat32 partition for /boot/efi to my router image. Here is the relevant config:
+
+ router = host hn $ props
+ & hasPartitionTableType GPT
+ & hasPartition
+ ( partition FAT
+ `mountedAt` "/boot/efi"
+ `partLocation` Beginning
+ `setSize` MegaBytes 10
+ `setFlag` BootFlag
+ )
+ & hasPartition
+ ( partition EXT2
+ `mountedAt` "/boot"
+ `partLocation` Beginning
+ `setSize` MegaBytes 150
+ )
+ & hasPartition
+ ( partition EXT4
+ `mountedAt` "/"
+ `addFreeSpace` MegaBytes 500
+ )
+ & standardSystem (Stable "stretch") X86_64
+ [ dom ++ " home router" ]
+
+
+But parted does not seem to support "fat" as a file system type.
+
+ parted: invalid token: fat
+ Error: Expecting a file system type.
+
+It should probably use "fat32" instead, but replacing "fat" by "fat32" in the PartedVal instance of Partition.Fs fails, too:
+
+ mount: /tmp/mnteepFPo: wrong fs type, bad option, bad superblock on /dev/mapper/loop0p1, missing codepage or helper program, or other error.
+ umount: /tmp/mnteepFPo: not mounted.
+ ** fatal error: failed unmounting /tmp/mnteepFPo
+ propellor: StopPropellorException "Cannot continue!"
diff --git a/doc/forum/parted:_invalid_token:_fat/comment_1_0ad5e1df0db6dbdaba298f5f890d79a2._comment b/doc/forum/parted:_invalid_token:_fat/comment_1_0ad5e1df0db6dbdaba298f5f890d79a2._comment
new file mode 100644
index 00000000..b859054d
--- /dev/null
+++ b/doc/forum/parted:_invalid_token:_fat/comment_1_0ad5e1df0db6dbdaba298f5f890d79a2._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2017-12-20T16:52:30Z"
+ content="""
+Your change seems right. I think the mount error is unrelated;
+it comes from DiskImage which mounts the loopback device with
+-t auto, so the parted name for fat shouldn't impact that.
+
+There might be something in dmesg about why the mount failed.
+"""]]
diff --git a/doc/forum/parted:_invalid_token:_fat/comment_2_88db9d05c7e4d028f35d98ba6b082d55._comment b/doc/forum/parted:_invalid_token:_fat/comment_2_88db9d05c7e4d028f35d98ba6b082d55._comment
new file mode 100644
index 00000000..292a4109
--- /dev/null
+++ b/doc/forum/parted:_invalid_token:_fat/comment_2_88db9d05c7e4d028f35d98ba6b082d55._comment
@@ -0,0 +1,7 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2017-12-20T17:25:11Z"
+ content="""
+I went ahead and made the change in parted.
+"""]]
diff --git a/doc/forum/parted:_invalid_token:_fat/comment_3_76fd3da6d79f4a369d01ecfad8300025._comment b/doc/forum/parted:_invalid_token:_fat/comment_3_76fd3da6d79f4a369d01ecfad8300025._comment
new file mode 100644
index 00000000..0d45590a
--- /dev/null
+++ b/doc/forum/parted:_invalid_token:_fat/comment_3_76fd3da6d79f4a369d01ecfad8300025._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="gueux"
+ avatar="http://cdn.libravatar.org/avatar/2982bac2c2cd94ab3860efb189deafc8"
+ subject="comment 3"
+ date="2017-12-20T17:59:02Z"
+ content="""
+OK, great!
+"""]]
diff --git a/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__..mdwn b/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__..mdwn
new file mode 100644
index 00000000..ca665c3c
--- /dev/null
+++ b/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__..mdwn
@@ -0,0 +1,25 @@
+Hi,
+
+While attempting to build "secret-project" I encountered this
+
+ [ 7 of 10] Compiling Installer.UI ( Installer/UI.hs, .stack-work/dist/x86_64-linux-nopie/Cabal-1.24.2.0/build/propellor-config/propellor-config-tmp/Installer/UI.o )
+
+ /home/stappers/src/secret-project/Installer/UI.hs:228:14: error:
+ Not in scope: ‘UI.loadFile’
+ Module ‘Graphics.UI.Threepenny’ does not export ‘loadFile’.
+
+ -- While building custom Setup.hs for package secret-project-0.0 using:
+ /root/.stack/setup-exe-cache/x86_64-linux-nopie/Cabal-simple_mPHDZzAJ_1.24.2.0_ghc-8.0.2 --builddir=.stack-work/dist/x86_64-linux-nopie/Cabal-1.24.2.0 build exe:propellor-config --ghc-options " -ddump-hi -ddump-to-file"
+ Process exited with code: ExitFailure 1
+
+
+From <http://propellor.branchable.com/forum/secret-project_and_type_constructor_or_class___8216__PartSpec__8217__/#comment-179662ace1bc9a24782d60e73f2a5a4e>
+I understand that a UI patch to threepenny-gui is needed.
+But I don't understand that request.
+
+How to patch the threepenny-gui??
+
+
+Cheers
+
+Geert Stappers
diff --git a/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_1_4dea8fc15186923aeffcd0272a8c14c0._comment b/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_1_4dea8fc15186923aeffcd0272a8c14c0._comment
new file mode 100644
index 00000000..58543ee5
--- /dev/null
+++ b/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_1_4dea8fc15186923aeffcd0272a8c14c0._comment
@@ -0,0 +1,38 @@
+[[!comment format=mdwn
+ username="stappers@eb96885816da287c29f6f699999434d532149234"
+ nickname="stappers"
+ avatar="http://cdn.libravatar.org/avatar/bf33450acf6fc2a17a8b4e6fc7749c65"
+ subject="additional information"
+ date="2017-12-28T12:44:23Z"
+ content="""
+There was another error before the error reported above. It was
+
+ Error: While constructing the build plan, the following exceptions were encountered:
+
+ In the dependencies for secret-project-0.0:
+ threepenny-gui-0.7.0.1 from stack configuration does not match (==0.8.0.0) (latest matching version
+ is 0.8.0.0)
+ needed since secret-project is a build target.
+
+My workaround was
+
+ --- a/secret-project.cabal
+ +++ b/secret-project.cabal
+ @@ -21,7 +21,7 @@ Executable propellor-config
+ Build-Depends:
+ base (>= 4.9 && < 5.0)
+ , propellor >= 4.7.6
+ - , threepenny-gui (== 0.8.0.0)
+ + , threepenny-gui (== 0.7.0.1)
+ , random (>= 1.1)
+ , random-shuffle (>= 0.0.4)
+ , filepath (>= 1.4)
+
+That because `stack.yaml` has a package line
+
+ - http://github.com/joeyh/threepenny-gui/archive/59242cf93bdb8eaa805f5c2b0241e9a1cba9a70f.zip
+
+where I think/assume the 0.7.0.1 comes from.
+
+
+"""]]
diff --git a/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_2_10e8132f96e66a4c215ed275e22d1bda._comment b/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_2_10e8132f96e66a4c215ed275e22d1bda._comment
new file mode 100644
index 00000000..f25b614b
--- /dev/null
+++ b/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_2_10e8132f96e66a4c215ed275e22d1bda._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2017-12-28T17:01:21Z"
+ content="""
+The zip file pointed to by the stack.yaml file contains a patched version
+of threepenny-gui 0.8.0.0, the same as the cabal file requires.
+
+Downgrading the dependency won't work, thus your build problems. All I can
+tell you is it's built successfully with stack every time I've tried to
+build it, and stack pins all package versions to ensure a reproducible
+build.
+
+It may be that you're using too old a version of stack or
+something like that; I've used stack 1.1.2.
+"""]]
diff --git a/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_3_e288978072a6f38539150be1ebf4b0f2._comment b/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_3_e288978072a6f38539150be1ebf4b0f2._comment
new file mode 100644
index 00000000..5dc314de
--- /dev/null
+++ b/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_3_e288978072a6f38539150be1ebf4b0f2._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="stappers@eb96885816da287c29f6f699999434d532149234"
+ nickname="stappers"
+ avatar="http://cdn.libravatar.org/avatar/bf33450acf6fc2a17a8b4e6fc7749c65"
+ subject="my stack version"
+ date="2017-12-28T22:13:21Z"
+ content="""
+ $ stack --version
+ Version 1.6.3, Git revision b27e629b8c4ce369e3b8273f04db193b060000db (5454 commits) x86_64 hpack-0.20.0
+
+"""]]
diff --git a/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_4_074a7c14425635ddb25b7d3046337533._comment b/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_4_074a7c14425635ddb25b7d3046337533._comment
new file mode 100644
index 00000000..4ea04076
--- /dev/null
+++ b/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_4_074a7c14425635ddb25b7d3046337533._comment
@@ -0,0 +1,38 @@
+[[!comment format=mdwn
+ username="stappers@eb96885816da287c29f6f699999434d532149234"
+ nickname="stappers"
+ avatar="http://cdn.libravatar.org/avatar/bf33450acf6fc2a17a8b4e6fc7749c65"
+ subject="threepenny-ui in cabal"
+ date="2017-12-29T08:46:19Z"
+ content="""
+Without a version for threepenny-ui in secret-project.cabal gets 0.7.0.1 installed by `stack build`.
+
+Where 0.7.0.1 comes from is unclear to me.
+Downloading and unzipping <https://github.com/joeyh/threepenny-gui/archive/59242cf93bdb8eaa805f5c2b0241e9a1cba9a70f.zip> didn't reveal any 0.7.0.1.
+
+Having `threepenny-gui (>= 0.8.0.0)` in secret-project.cabal gives this compile error:
+
+
+ Error: While constructing the build plan, the following exceptions were encountered:
+
+ In the dependencies for secret-project-0.0:
+ threepenny-gui-0.7.0.1 from stack configuration does not match (>=0.8.0.0) (latest matching version
+ is 0.8.2.0)
+ needed since secret-project is a build target.
+
+ Some potential ways to resolve this:
+
+ * Recommended action: try adding the following to your extra-deps
+ in /home/stappers/src/secret-project/stack.yaml:
+
+ - threepenny-gui-0.8.2.0
+
+ * Set 'allow-newer: true' to ignore all version constraints and build anyway.
+
+ * You may also want to try using the 'stack solver' command.
+
+ Plan construction failed.
+
+
+
+"""]]
diff --git a/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_5_4cda097e7650c4ba46e26c6e3dbbdc75._comment b/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_5_4cda097e7650c4ba46e26c6e3dbbdc75._comment
new file mode 100644
index 00000000..608e0bb1
--- /dev/null
+++ b/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_5_4cda097e7650c4ba46e26c6e3dbbdc75._comment
@@ -0,0 +1,65 @@
+[[!comment format=mdwn
+ username="stappers@eb96885816da287c29f6f699999434d532149234"
+ nickname="stappers"
+ avatar="http://cdn.libravatar.org/avatar/bf33450acf6fc2a17a8b4e6fc7749c65"
+ subject="stack extra dep threepenny-gui-0.8.2.0 compile error"
+ date="2017-12-29T09:22:34Z"
+ content="""
+With having
+
+ extra-deps:
+ - propellor-5.1.0
+ - threepenny-gui-0.8.2.0
+
+in `stack.yaml` gives me this compile error:
+
+ Preprocessing executable 'propellor-config' for secret-project-0.0...
+ [ 7 of 10] Compiling Installer.UI ( Installer/UI.hs, .stack-work/dist/x86_64-linux-nopie/Cabal-1.24.2.0/build/propellor-config/propellor-config-tmp/Installer/UI.o )
+
+ /home/stappers/src/secret-project/Installer/UI.hs:282:32: error:
+ • Couldn't match type ‘(t1, (Int, Int))’ with ‘[Char]’
+ Expected type: UI.DragData
+ Actual type: (t1, (Int, Int))
+ • In the pattern: (_d, (x, y))
+ In the second argument of ‘($)’, namely
+ ‘\ (_d, (x, y))
+ -> void
+ $ do { now <- getTime clock;
+ liftIO $ writeIORef draginfo (x, y, now);
+ .... }’
+ In a stmt of a 'do' block:
+ on UI.dragStart elt
+ $ \ (_d, (x, y))
+ -> void
+ $ do { now <- getTime clock;
+ liftIO $ writeIORef draginfo (x, y, now);
+ .... }
+
+ /home/stappers/src/secret-project/Installer/UI.hs:487:27: error:
+ • Couldn't match type ‘(t0 a0, (Int, Int))’ with ‘[Char]’
+ Expected type: UI.DragData
+ Actual type: (t0 a0, (Int, Int))
+ • In the pattern: (d, (x, y))
+ In the second argument of ‘($)’, namely
+ ‘\ (d, (x, y))
+ -> when (not (null d))
+ $ liftIO $ writeIORef dropSuccess (True, (x, y))’
+ In a stmt of a 'do' block:
+ on UI.drop elt
+ $ \ (d, (x, y))
+ -> when (not (null d))
+ $ liftIO $ writeIORef dropSuccess (True, (x, y))
+
+ -- While building custom Setup.hs for package secret-project-0.0 using:
+ /root/.stack/setup-exe-cache/x86_64-linux-nopie/Cabal-simple_mPHDZzAJ_1.24.2.0_ghc-8.0.2 --builddir=.stack-work/dist/x86_64-linux-nopie/Cabal-1.24.2.0 build exe:propellor-config --ghc-options \" -ddump-hi -ddump-to-file\"
+ Process exited with code: ExitFailure 1
+
+I hope it is reproduceable and that it can be fixed.
+
+Thank you
+
+Groeten
+
+Geert Stappers
+
+"""]]
diff --git a/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_6_249337c7f647cca8f4e23c99897458d9._comment b/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_6_249337c7f647cca8f4e23c99897458d9._comment
new file mode 100644
index 00000000..9d540993
--- /dev/null
+++ b/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_6_249337c7f647cca8f4e23c99897458d9._comment
@@ -0,0 +1,22 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 6"""
+ date="2017-12-29T15:56:21Z"
+ content="""
+You need this for it to build with the newer stack:
+
+ --- a/stack.yaml
+ +++ b/stack.yaml
+ @@ -4,4 +4,5 @@ packages:
+ resolver: lts-8.12
+ extra-deps:
+ - propellor-5.1.0
+ +- archive: http://github.com/joeyh/threepenny-gui/archive/59242cf93bdb8eaa805f5c2b0241e9a1cba9a70f.zip
+ explicit-setup-deps:
+
+However, that won't work with the
+[stack currently in debian](http://package.debian.org/haskell-stack)
+and since secret-project later installs that version of stack and runs
+it against the same stack.yaml file, I can't commit that change until
+Debian gets around to [upgrading haskell-stack](http://bugs.debian.org/877256)
+"""]]
diff --git a/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_7_cf7efafc0ee96d5cecf452ebe49015d5._comment b/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_7_cf7efafc0ee96d5cecf452ebe49015d5._comment
new file mode 100644
index 00000000..3f140c2e
--- /dev/null
+++ b/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_7_cf7efafc0ee96d5cecf452ebe49015d5._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 7"""
+ date="2017-12-29T16:26:41Z"
+ content="""
+Asked the stack developers and found a stack.yaml that
+I think worked with both versions of stack. At least both can build with
+it, have not tried running secret-project again.
+"""]]
diff --git a/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_8_66bab35f7eb78584e1adf93b4b8dccb4._comment b/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_8_66bab35f7eb78584e1adf93b4b8dccb4._comment
new file mode 100644
index 00000000..a5c37aac
--- /dev/null
+++ b/doc/forum/secret-project_and_Module___8216__Graphics.UI.Threepenny__8217___does_not_export___8216__loadFile__8217__./comment_8_66bab35f7eb78584e1adf93b4b8dccb4._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="stappers@eb96885816da287c29f6f699999434d532149234"
+ nickname="stappers"
+ avatar="http://cdn.libravatar.org/avatar/bf33450acf6fc2a17a8b4e6fc7749c65"
+ subject="Clean build"
+ date="2017-12-29T17:41:02Z"
+ content="""
+Yes, with the updated `stack.yaml` I do get a clean build upon `stack build`.
+
+Yeah
+
+"""]]
diff --git a/doc/forum/secret-project_and_type_constructor_or_class___8216__PartSpec__8217__.mdwn b/doc/forum/secret-project_and_type_constructor_or_class___8216__PartSpec__8217__.mdwn
new file mode 100644
index 00000000..94d58f2b
--- /dev/null
+++ b/doc/forum/secret-project_and_type_constructor_or_class___8216__PartSpec__8217__.mdwn
@@ -0,0 +1,43 @@
+Hi,
+
+After
+ git clone https://git.joeyh.name/git/secret-project.git
+
+plus
+ --- a/secret-project.cabal
+ +++ b/secret-project.cabal
+ @@ -21,7 +21,7 @@ Executable propellor-config
+ Build-Depends:
+ base (>= 4.9 && < 5.0)
+ , propellor >= 4.7.6
+ - , threepenny-gui (== 0.8.0.0)
+ + , threepenny-gui (>= 0.8.0.0)
+ , random (>= 1.1)
+ , random-shuffle (>= 0.0.4)
+ , filepath (>= 1.4)
+
+
+Gives `propellor spin` me this
+
+[ 5 of 10] Compiling Installer.Target ( Installer/Target.hs, dist/build/propellor-config/propellor-config-tmp/Installer/Target.o )
+
+Installer/Target.hs:28:51: error:
+ Not in scope: type constructor or class ‘PartSpec’
+
+Installer/Target.hs:97:30: error:
+ Not in scope: type constructor or class ‘PartSpec’
+
+Installer/Target.hs:178:51: error:
+ Not in scope: type constructor or class ‘PartSpec’
+propellor: cabal build failed
+CallStack (from HasCallStack):
+ error, called at src/Propellor/Bootstrap.hs:259:25 in main:Propellor.Bootstrap
+
+
+
+How to get beyond that compile error?
+
+
+Cheers
+Geert Stappers
+
diff --git a/doc/forum/secret-project_and_type_constructor_or_class___8216__PartSpec__8217__/comment_1_492a5c5297a80f18282361fb5c27ad8a._comment b/doc/forum/secret-project_and_type_constructor_or_class___8216__PartSpec__8217__/comment_1_492a5c5297a80f18282361fb5c27ad8a._comment
new file mode 100644
index 00000000..5fbd00ff
--- /dev/null
+++ b/doc/forum/secret-project_and_type_constructor_or_class___8216__PartSpec__8217__/comment_1_492a5c5297a80f18282361fb5c27ad8a._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="stappers@eb96885816da287c29f6f699999434d532149234"
+ nickname="stappers"
+ avatar="http://cdn.libravatar.org/avatar/bf33450acf6fc2a17a8b4e6fc7749c65"
+ subject="patch, sorry for the previous line wraps"
+ date="2017-12-27T23:14:22Z"
+ content="""
+ --- a/secret-project.cabal
+ +++ b/secret-project.cabal
+ @@ -21,7 +21,7 @@ Executable propellor-config
+ Build-Depends:
+ base (>= 4.9 && < 5.0)
+ , propellor >= 4.7.6
+ - , threepenny-gui (== 0.8.0.0)
+ + , threepenny-gui (>= 0.8.0.0)
+ , random (>= 1.1)
+ , random-shuffle (>= 0.0.4)
+ , filepath (>= 1.4)
+
+"""]]
diff --git a/doc/forum/secret-project_and_type_constructor_or_class___8216__PartSpec__8217__/comment_2_4e2f36fc1de2644c22d69ab9a2d7e94a._comment b/doc/forum/secret-project_and_type_constructor_or_class___8216__PartSpec__8217__/comment_2_4e2f36fc1de2644c22d69ab9a2d7e94a._comment
new file mode 100644
index 00000000..a5e48372
--- /dev/null
+++ b/doc/forum/secret-project_and_type_constructor_or_class___8216__PartSpec__8217__/comment_2_4e2f36fc1de2644c22d69ab9a2d7e94a._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2017-12-27T23:42:50Z"
+ content="""
+You need to build secret-project using stack, to get the right version
+of propellor and also a UI patch to threepenny-gui.
+"""]]
diff --git a/doc/forum/secret-project_and_type_constructor_or_class___8216__PartSpec__8217__/comment_3_b436b5eb909dd4b228bb36546f593547._comment b/doc/forum/secret-project_and_type_constructor_or_class___8216__PartSpec__8217__/comment_3_b436b5eb909dd4b228bb36546f593547._comment
new file mode 100644
index 00000000..3380be42
--- /dev/null
+++ b/doc/forum/secret-project_and_type_constructor_or_class___8216__PartSpec__8217__/comment_3_b436b5eb909dd4b228bb36546f593547._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="stappers@eb96885816da287c29f6f699999434d532149234"
+ nickname="stappers"
+ avatar="http://cdn.libravatar.org/avatar/bf33450acf6fc2a17a8b4e6fc7749c65"
+ subject="README.mdwn"
+ date="2017-12-28T12:02:17Z"
+ content="""
+
+Use `stack` for building.
+Find stack at <https://docs.haskellstack.org/en/stable/README/>
+
+After installing `stack` do
+
+ stack build
+
+in this directory.
+"""]]
diff --git a/doc/forum/secret-project_and_type_constructor_or_class___8216__PartSpec__8217__/comment_4_568bda577a15f1ef405dd20eec24aa9b._comment b/doc/forum/secret-project_and_type_constructor_or_class___8216__PartSpec__8217__/comment_4_568bda577a15f1ef405dd20eec24aa9b._comment
new file mode 100644
index 00000000..52726dc1
--- /dev/null
+++ b/doc/forum/secret-project_and_type_constructor_or_class___8216__PartSpec__8217__/comment_4_568bda577a15f1ef405dd20eec24aa9b._comment
@@ -0,0 +1,19 @@
+[[!comment format=mdwn
+ username="stappers@eb96885816da287c29f6f699999434d532149234"
+ nickname="stappers"
+ avatar="http://cdn.libravatar.org/avatar/bf33450acf6fc2a17a8b4e6fc7749c65"
+ subject="patch"
+ date="2017-12-28T13:08:12Z"
+ content="""
+patch against the now existing README file
+
+ --- a/README
+ +++ b/README
+ @@ -4,3 +4,5 @@ based GUI. I ran it live in my \"Life After Debian\" talk at DebConf 17.
+ http://meetings-archive.debian.net/pub/debian-meetings/2017/debconf17/life-after-debian.vp8.webm
+
+ If you would like to build this, use stack, eg \"stack build\"
+ +
+ +FYI stack homepage is https://docs.haskellstack.org/en/stable/README/
+
+"""]]
diff --git a/doc/forum/secret-project_deliverable.mdwn b/doc/forum/secret-project_deliverable.mdwn
new file mode 100644
index 00000000..b1fcab54
--- /dev/null
+++ b/doc/forum/secret-project_deliverable.mdwn
@@ -0,0 +1,27 @@
+Hi,
+
+The secret-project README says to do `stack build`.
+
+Doing that gives me a clean compile.
+
+
+But what deliverable should I have now?
+
+
+Snippet from `secret-project.cabal`:
+
+ Executable propellor-config
+ Main-Is: config.hs
+
+But I don't have a `propellor-config`.
+
+Running `propellor` gives compile errors.
+So that doesn't seem the next step for getting any deliverable.
+
+For what should I be looking??
+
+
+Cheers
+
+Geert Stappers
+
diff --git a/doc/forum/secret-project_deliverable/comment_1_49f421da4a94d9267ca5e75679a4c92c._comment b/doc/forum/secret-project_deliverable/comment_1_49f421da4a94d9267ca5e75679a4c92c._comment
new file mode 100644
index 00000000..9f8c8a90
--- /dev/null
+++ b/doc/forum/secret-project_deliverable/comment_1_49f421da4a94d9267ca5e75679a4c92c._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2017-12-29T19:49:02Z"
+ content="""
+I've added some hints to the README, of course it's been a while since I
+ran it and I only ran it a couple times. The content of the config.hs is
+really more important than the gory details of how to run it, in my opinion.
+"""]]
diff --git a/doc/forum/secret-project_deliverable/comment_2_a3faea076e7477d5ce4fcb03a38d74a7._comment b/doc/forum/secret-project_deliverable/comment_2_a3faea076e7477d5ce4fcb03a38d74a7._comment
new file mode 100644
index 00000000..24738e49
--- /dev/null
+++ b/doc/forum/secret-project_deliverable/comment_2_a3faea076e7477d5ce4fcb03a38d74a7._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="stappers@eb96885816da287c29f6f699999434d532149234"
+ nickname="stappers"
+ avatar="http://cdn.libravatar.org/avatar/bf33450acf6fc2a17a8b4e6fc7749c65"
+ subject="almost there"
+ date="2017-12-29T21:09:04Z"
+ content="""
+thanks
+
+got another error that I probaly can fix my self
+"""]]
diff --git a/doc/news/version_5.0.0.mdwn b/doc/news/version_5.0.0.mdwn
deleted file mode 100644
index dbf678cc..00000000
--- a/doc/news/version_5.0.0.mdwn
+++ /dev/null
@@ -1,20 +0,0 @@
-propellor 5.0.0 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
- * 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."""]] \ No newline at end of file
diff --git a/doc/news/version_5.1.0.mdwn b/doc/news/version_5.1.0.mdwn
new file mode 100644
index 00000000..dd007a24
--- /dev/null
+++ b/doc/news/version_5.1.0.mdwn
@@ -0,0 +1,18 @@
+propellor 5.1.0 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+ * [ Sean Whitton ]
+ * File.isSymlinkedTo now revertable. (minor API change)
+ * Sbuild module changes:
+ - Type of Sbuild.built changed to accept additional properties to be
+ ensured inside schroots. (API change)
+ See the suggested usage in module's documentation for new syntax.
+ - Drop Sbuild.installed, Sbuild.builtFor, Sbuild.updated,
+ Sbuild.updatedFor. (API change)
+ Use Sbuild.built instead. See suggested usage in module's documentation.
+ - Propellor no longer sets up apt proxies in sbuild chroots automatically.
+ Instead, pass the new Sbuild.useHostProxy to Sbuild.built to have
+ Propellor propagate the host's Apt proxy configuration into the chroot.
+ See suggested usage in module's documentation.
+ - Internally, Propellor no longer invokes sbuild-createchroot(1) to build
+ schroots.
+ - Update documentation."""]] \ No newline at end of file
diff --git a/doc/todo/etckeeper/comment_2_69484bfac40de156a4b877f27aa69eca._comment b/doc/todo/etckeeper/comment_2_69484bfac40de156a4b877f27aa69eca._comment
new file mode 100644
index 00000000..dfb9f9df
--- /dev/null
+++ b/doc/todo/etckeeper/comment_2_69484bfac40de156a4b877f27aa69eca._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="stappers@eb96885816da287c29f6f699999434d532149234"
+ nickname="stappers"
+ avatar="http://cdn.libravatar.org/avatar/bf33450acf6fc2a17a8b4e6fc7749c65"
+ subject="why still on todo list"
+ date="2017-12-27T23:00:58Z"
+ content="""
+the 'all needed apt.installed[\"etckeeper\"]' seems to me that the etckeeper is available.
+
+Why is this still on the todo list?
+
+What kind of patches are wanted??
+
+"""]]
diff --git a/doc/todo/etckeeper/comment_3_5f62128bdb550de475d22abb35730949._comment b/doc/todo/etckeeper/comment_3_5f62128bdb550de475d22abb35730949._comment
new file mode 100644
index 00000000..7d2f8d43
--- /dev/null
+++ b/doc/todo/etckeeper/comment_3_5f62128bdb550de475d22abb35730949._comment
@@ -0,0 +1,7 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2017-12-27T23:35:16Z"
+ content="""
+Yeah, just been waiting to hear back from the issue submitter.
+"""]]
diff --git a/doc/todo/privdata_propigation_into_diskimages.mdwn b/doc/todo/privdata_propigation_into_diskimages.mdwn
new file mode 100644
index 00000000..80a42d23
--- /dev/null
+++ b/doc/todo/privdata_propigation_into_diskimages.mdwn
@@ -0,0 +1,6 @@
+When building a disk image with propellor bootstrapped in it, the decrypted
+privdata file is not written, so propellor can't be run on the booted
+system without first doing a propellor --spin from the dev laptop. Not a
+big problem but worth fixing some time. --[[Joey]]
+
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/todo/removable_drive_partitioning_and_install.mdwn b/doc/todo/removable_drive_partitioning_and_install.mdwn
new file mode 100644
index 00000000..891c3b92
--- /dev/null
+++ b/doc/todo/removable_drive_partitioning_and_install.mdwn
@@ -0,0 +1,40 @@
+I want to be able to temporarily plug in the root drive of another host
+to my laptop and run propellor to re-image the drive with the properties of
+the host it belongs to. This is especially useful when the drive is too
+large to make a DiskImage on my laptop.
+
+Open design questions:
+
+* How to uniquely identify which removable drive belongs to which Host?
+ Could use partition uuids for updating an already imaged drive, but not
+ for the initial build.
+
+ /dev/disk/by-id/ seems a good way to go. Eg for a USB drive I have,
+ "/dev/disk/by-id/usb-LaCie_iamaKey_37637172f536ba-0:0" probably uniquely
+ identifies it, at least as long as the manufacturer is not reusing serial
+ numbers.
+
+ One problem with /dev/disk/by-id/ is, if a removable drive is attached
+ on a different bus (ie, a SATA drive might be connected via SATA or a USB
+ dock), it won't appear the same there.
+
+ Could instead use eg `udevadm info --query=all -n /dev/sdb`, which
+ breaks out `ID_SERIAL`. However, this would be harder for the user to
+ look up. Or, could parse the /dev/disk/by-id/ name, excluding the bus
+ part of it.
+
+ Question: When using microsd card adapter, does the serial number pass
+ through so different microsds can be distinguished?
+ > Checked this, and two microsd card adapters from different
+ > manufacturers with different microsd cards have the same by-id.
+ > Those must have no serial number..
+
+* Should an already imaged drive be updated incrementally or re-imaged?
+ Seems both cases would be useful, the former especially for incrementally
+ configuring it, the latter to bring it up from a clean state.
+ If it defaults to updating, the user could force a re-image by deleting
+ the partitions from the drive manually.
+
+secret-project has some code for /target which might be reusable here.
+
+--[[Joey]]
diff --git a/doc/todo/spin_without_remote_compilation/comment_6_513dededf5872a51eb443a211cee13fa._comment b/doc/todo/spin_without_remote_compilation/comment_6_513dededf5872a51eb443a211cee13fa._comment
new file mode 100644
index 00000000..5e9325da
--- /dev/null
+++ b/doc/todo/spin_without_remote_compilation/comment_6_513dededf5872a51eb443a211cee13fa._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="np"
+ avatar="http://cdn.libravatar.org/avatar/54743cddf009909589217983a7aac25f"
+ subject="Bounty"
+ date="2017-11-24T13:23:13Z"
+ content="""
+Hi!
+
+What's left to be done for this issue.
+If there is any work to sponsor to have this feature integrated I would gladly do so.
+"""]]
diff --git a/doc/todo/spin_without_remote_compilation/comment_7_3fed94d212de0e4ad2d2364cc91e6c94._comment b/doc/todo/spin_without_remote_compilation/comment_7_3fed94d212de0e4ad2d2364cc91e6c94._comment
new file mode 100644
index 00000000..b45941ab
--- /dev/null
+++ b/doc/todo/spin_without_remote_compilation/comment_7_3fed94d212de0e4ad2d2364cc91e6c94._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 7"""
+ date="2017-12-03T18:20:25Z"
+ content="""
+Felix did some more work on this last April, in his precompiled-rebased-2
+branch.
+
+In particular, that branch is supposed to handle case #3 above (by a git
+clone to temp dir and move of the files).
+
+Felix said he had not tested it, and I have not tested it either. If
+someone can try his branch and confirm that it works, including handling
+of cases #2 and #3 above, I'd be happy to merge it.
+
+(origin/precompiled has the above branch and has had current master
+cleanly merged into it, and builds successfully.)
+"""]]
diff --git a/joeyconfig.hs b/joeyconfig.hs
index d39b7ed8..96be56c5 100644
--- a/joeyconfig.hs
+++ b/joeyconfig.hs
@@ -32,7 +32,6 @@ import qualified Propellor.Property.Gpg as Gpg
import qualified Propellor.Property.Systemd as Systemd
import qualified Propellor.Property.Journald as Journald
import qualified Propellor.Property.Fail2Ban as Fail2Ban
-import qualified Propellor.Property.Aiccu as Aiccu
import qualified Propellor.Property.OS as OS
import qualified Propellor.Property.HostingProvider.CloudAtCost as CloudAtCost
import qualified Propellor.Property.HostingProvider.Linode as Linode
@@ -86,20 +85,20 @@ darkstar :: Host
darkstar = host "darkstar.kitenet.net" $ props
& osDebian Unstable X86_64
& ipv6 "2001:4830:1600:187::2"
- & Aiccu.hasConfig "T18376" "JHZ2-SIXXS"
-
- & User.nuked (User "nosuchuser") User.YesReallyDeleteHome
+ & Hostname.sane
+ & Apt.serviceInstalledRunning "swapspace"
& JoeySites.dkimMilter
& JoeySites.postfixSaslPasswordClient
-- & JoeySites.alarmClock "*-*-* 7:30" (User "joey")
-- "/usr/bin/timeout 45m /home/joey/bin/goodmorning"
+ & JoeySites.laptopSoftware
& Ssh.userKeys (User "joey") hostContext
[ (SshRsa, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC1YoyHxZwG5Eg0yiMTJLSWJ/+dMM6zZkZiR4JJ0iUfP+tT2bm/lxYompbSqBeiCq+PYcSC67mALxp1vfmdOV//LWlbXfotpxtyxbdTcQbHhdz4num9rJQz1tjsOsxTEheX5jKirFNC5OiKhqwIuNydKWDS9qHGqsKcZQ8p+n1g9Lr3nJVGY7eRRXzw/HopTpwmGmAmb9IXY6DC2k91KReRZAlOrk0287LaK3eCe1z0bu7LYzqqS+w99iXZ/Qs0m9OqAPnHZjWQQ0fN4xn5JQpZSJ7sqO38TBAimM+IHPmy2FTNVVn9zGM+vN1O2xr3l796QmaUG1+XLL0shfR/OZbb joey@darkstar")
]
- & imageBuiltFor honeybee
- (RawDiskImage "/srv/honeybee.img")
- (Debootstrapped mempty)
+ -- & imageBuiltFor honeybee
+ -- (RawDiskImage "/srv/honeybee.img")
+ -- (Debootstrapped mempty)
gnu :: Host
gnu = host "gnu.kitenet.net" $ props
@@ -183,15 +182,9 @@ honeybee = host "honeybee.kitenet.net" $ props
& cubietech_Cubietruck
& hasPartition
- ( partition EXT2
- `mountedAt` "/boot"
- `partLocation` Beginning
- `setSize` MegaBytes 200
- )
- & hasPartition
( partition EXT4
`mountedAt` "/"
- `addFreeSpace` MegaBytes 500
+ `setSize` MegaBytes 8000
)
& Apt.installed ["firmware-brcm80211"]
@@ -207,6 +200,7 @@ honeybee = host "honeybee.kitenet.net" $ props
& JoeySites.homePowerMonitor
(User "joey")
+ hosts
(Context "homepower.joeyh.name")
(SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMAmVYddg/RgCbIj+cLcEiddeFXaYFnbEJ3uGj9G/EyV joey@honeybee")
& JoeySites.homeRouter
diff --git a/propellor.cabal b/propellor.cabal
index 5f9d9ce5..a76d63f0 100644
--- a/propellor.cabal
+++ b/propellor.cabal
@@ -1,5 +1,5 @@
Name: propellor
-Version: 5.1.0
+Version: 5.2.0
Cabal-Version: >= 1.20
License: BSD2
Maintainer: Joey Hess <id@joeyh.name>
@@ -121,6 +121,9 @@ Library
Propellor.Property.Gpg
Propellor.Property.Group
Propellor.Property.Grub
+ Propellor.Property.Installer
+ Propellor.Property.Installer.Types
+ Propellor.Property.Installer.Target
Propellor.Property.Journald
Propellor.Property.Kerberos
Propellor.Property.LetsEncrypt
diff --git a/src/Propellor/Property/Bootstrap.hs b/src/Propellor/Property/Bootstrap.hs
index f0759dae..25a6af33 100644
--- a/src/Propellor/Property/Bootstrap.hs
+++ b/src/Propellor/Property/Bootstrap.hs
@@ -14,6 +14,8 @@ import Propellor.Base
import Propellor.Bootstrap
import Propellor.Types.Info
import Propellor.Property.Chroot
+import Propellor.PrivData.Paths
+import Utility.FileMode
import Data.List
import qualified Data.ByteString as B
@@ -63,8 +65,18 @@ bootstrappedFrom reposource = check inChroot $
go :: Property Linux
go = property "Propellor bootstrapped" $ do
system <- getOS
+ -- gets Host value representing the chroot this is run in
+ chroothost <- ask
+ -- load privdata from outside the chroot, and filter
+ -- to only the privdata needed inside the chroot.
+ privdata <- liftIO $ filterPrivData chroothost
+ <$> readPrivDataFile privDataLocal
bootstrapper <- getBootstrapper
- assumeChange $ exposeTrueLocaldir $ const $
+ assumeChange $ exposeTrueLocaldir $ const $ do
+ liftIO $ createDirectoryIfMissing True $
+ takeDirectory privDataLocal
+ liftIO $ writeFileProtected privDataLocal $
+ show privdata
runShellCommand $ buildShellCommand
[ "cd " ++ localdir
, checkDepsCommand bootstrapper system
diff --git a/src/Propellor/Property/DiskImage.hs b/src/Propellor/Property/DiskImage.hs
index 6564192f..24459476 100644
--- a/src/Propellor/Property/DiskImage.hs
+++ b/src/Propellor/Property/DiskImage.hs
@@ -17,7 +17,7 @@ module Propellor.Property.DiskImage (
imageRebuiltFor,
imageBuiltFrom,
imageExists,
- Grub.BIOS(..),
+ GrubTarget(..),
) where
import Propellor.Base
@@ -41,6 +41,7 @@ import Propellor.Types.Bootloader
import Propellor.Container
import Utility.Path
import Utility.FileMode
+import Utility.DataUnits
import Data.List (isPrefixOf, isInfixOf, sortBy, unzip4)
import Data.Function (on)
@@ -220,7 +221,7 @@ imageBuilt' rebuild img mkchroot tabletype partspec =
-- installed.
final = case fromInfo (containerInfo chroot) of
[] -> unbootable "no bootloader is installed"
- [GrubInstalled] -> grubFinalized
+ [GrubInstalled grubtarget] -> grubFinalized grubtarget
[UbootInstalled p] -> ubootFinalized p
[FlashKernelInstalled] -> flashKernelFinalized
[UbootInstalled p, FlashKernelInstalled] ->
@@ -265,7 +266,7 @@ imageBuiltFrom img chrootdir tabletype final partspec = mkimg <!> rmimg
imageFinalized final dest mnts mntopts devs parttable
rmimg = undoRevertableProperty (buildDiskImage img)
`before` undoRevertableProperty (imageExists' dest dummyparttable)
- dummyparttable = PartTable tabletype []
+ dummyparttable = PartTable tabletype safeAlignment []
partitionsPopulated :: FilePath -> [Maybe MountPoint] -> [MountOpts] -> [LoopDev] -> Property DebianLike
partitionsPopulated chrootdir mnts mntopts devs = property' desc $ \w ->
@@ -274,13 +275,18 @@ partitionsPopulated chrootdir mnts mntopts devs = property' desc $ \w ->
desc = "partitions populated from " ++ chrootdir
go _ Nothing _ _ = noChange
- go w (Just mnt) mntopt loopdev = withTmpDir "mnt" $ \tmpdir -> bracket
- (liftIO $ mount "auto" (partitionLoopDev loopdev) tmpdir mntopt)
- (const $ liftIO $ umountLazy tmpdir)
- $ \ismounted -> if ismounted
- then ensureProperty w $
- syncDirFiltered (filtersfor mnt) (chrootdir ++ mnt) tmpdir
- else return FailedChange
+ go w (Just mnt) mntopt loopdev = ifM (liftIO $ doesDirectoryExist srcdir) $
+ ( withTmpDir "mnt" $ \tmpdir -> bracket
+ (liftIO $ mount "auto" (partitionLoopDev loopdev) tmpdir mntopt)
+ (const $ liftIO $ umountLazy tmpdir)
+ $ \ismounted -> if ismounted
+ then ensureProperty w $
+ syncDirFiltered (filtersfor mnt) srcdir tmpdir
+ else return FailedChange
+ , return NoChange
+ )
+ where
+ srcdir = chrootdir ++ mnt
filtersfor mnt =
let childmnts = map (drop (length (dropTrailingPathSeparator mnt))) $
@@ -300,7 +306,7 @@ fitChrootSize :: TableType -> [PartSpec ()] -> [PartSize] -> ([Maybe MountPoint]
fitChrootSize tt l basesizes = (mounts, mountopts, parttable)
where
(mounts, mountopts, sizers, _) = unzip4 l
- parttable = PartTable tt (zipWith id sizers basesizes)
+ parttable = PartTable tt safeAlignment (zipWith id sizers basesizes)
-- | Generates a map of the sizes of the contents of
-- every directory in a filesystem tree.
@@ -339,17 +345,24 @@ getMountSz szm l (Just mntpt) =
imageExists :: RawDiskImage -> ByteSize -> Property Linux
imageExists (RawDiskImage img) isz = property ("disk image exists" ++ img) $ liftIO $ do
ms <- catchMaybeIO $ getFileStatus img
- case ms of
+ case fmap (toInteger . fileSize) ms of
Just s
- | toInteger (fileSize s) == toInteger sz -> return NoChange
- | toInteger (fileSize s) > toInteger sz -> do
+ | s == toInteger sz -> return NoChange
+ | s > toInteger sz -> do
+ infoMessage ["truncating " ++ img ++ " to " ++ humansz]
setFileSize img (fromInteger sz)
return MadeChange
- _ -> do
+ | otherwise -> do
+ infoMessage ["expanding " ++ img ++ " from " ++ roughSize storageUnits False s ++ " to " ++ humansz]
+ L.writeFile img (L.replicate (fromIntegral sz) 0)
+ return MadeChange
+ Nothing -> do
+ infoMessage ["creating " ++ img ++ " of size " ++ humansz]
L.writeFile img (L.replicate (fromIntegral sz) 0)
return MadeChange
where
sz = ceiling (fromInteger isz / sectorsize) * ceiling sectorsize
+ humansz = roughSize storageUnits False (toInteger sz)
-- Disks have a sector size, and making a disk image not
-- aligned to a sector size will confuse some programs.
-- Common sector sizes are 512 and 4096; use 4096 as it's larger.
@@ -388,7 +401,7 @@ imageExists' dest@(RawDiskImage img) parttable = (setup <!> cleanup) `describe`
type Finalization = (RawDiskImage -> FilePath -> [LoopDev] -> Property Linux)
imageFinalized :: Finalization -> RawDiskImage -> [Maybe MountPoint] -> [MountOpts] -> [LoopDev] -> PartTable -> Property Linux
-imageFinalized final img mnts mntopts devs (PartTable _ parts) =
+imageFinalized final img mnts mntopts devs (PartTable _ _ parts) =
property' "disk image finalized" $ \w ->
withTmpDir "mnt" $ \top ->
go w top `finally` liftIO (unmountall top)
@@ -441,9 +454,10 @@ unbootable msg = \_ _ _ -> property desc $ do
where
desc = "image is not bootable"
-grubFinalized :: Finalization
-grubFinalized _img mnt loopdevs = Grub.bootsMounted mnt wholediskloopdev
- `describe` "disk image boots using grub"
+grubFinalized :: GrubTarget -> Finalization
+grubFinalized grubtarget _img mnt loopdevs =
+ Grub.bootsMounted mnt wholediskloopdev grubtarget
+ `describe` "disk image boots using grub"
where
-- It doesn't matter which loopdev we use; all
-- come from the same disk image, and it's the loop dev
diff --git a/src/Propellor/Property/DiskImage/PartSpec.hs b/src/Propellor/Property/DiskImage/PartSpec.hs
index 6a03c857..942cfa3e 100644
--- a/src/Propellor/Property/DiskImage/PartSpec.hs
+++ b/src/Propellor/Property/DiskImage/PartSpec.hs
@@ -160,8 +160,8 @@ hasPartition p@(mmp, _, _, _) = pureInfoProperty desc
(PartInfo [PartSpecInfo p])
where
desc = case mmp of
- Just mp -> "has " ++ mp ++ " partition"
- Nothing -> "has unmounted partition"
+ Just mp -> mp ++ " partition"
+ Nothing -> "unmounted partition"
-- | Adjusts the PartSpec for the partition mounted at the specified location.
--
@@ -170,7 +170,7 @@ hasPartition p@(mmp, _, _, _) = pureInfoProperty desc
-- > & adjustPartition "/boot" (`addFreeSpace` MegaBytes 150)
adjustPartition :: MountPoint -> (PartSpec PartLocation -> PartSpec PartLocation) -> Property (HasInfo + UnixLike)
adjustPartition mp f = pureInfoProperty
- ("has " ++ mp ++ " adjusted")
+ (mp ++ " adjusted")
(PartInfo [AdjustPartSpecInfo mp f])
-- | Indicates partition layout in a disk. Default is somewhere in the
diff --git a/src/Propellor/Property/Grub.hs b/src/Propellor/Property/Grub.hs
index d0516dc8..5cb9077d 100644
--- a/src/Propellor/Property/Grub.hs
+++ b/src/Propellor/Property/Grub.hs
@@ -1,4 +1,15 @@
-module Propellor.Property.Grub where
+module Propellor.Property.Grub (
+ GrubDevice,
+ OSDevice,
+ GrubTarget(..),
+ installed,
+ mkConfig,
+ installed',
+ boots,
+ bootsMounted,
+ TimeoutSecs,
+ chainPVGrub
+) where
import Propellor.Base
import qualified Propellor.Property.File as File
@@ -14,40 +25,36 @@ type GrubDevice = String
-- | Eg, \"\/dev/sda\"
type OSDevice = String
-type TimeoutSecs = Int
-
--- | Types of machines that grub can boot.
-data BIOS = PC | EFI64 | EFI32 | Coreboot | Xen
-
-- | Installs the grub package. This does not make grub be used as the
-- bootloader.
--
-- This includes running update-grub, unless it's run in a chroot.
-installed :: BIOS -> Property (HasInfo + DebianLike)
-installed bios = installed' bios
+installed :: GrubTarget -> Property (HasInfo + DebianLike)
+installed grubtarget = installed' grubtarget
`onChange` (check (not <$> inChroot) mkConfig)
--- Run update-grub, to generate the grub boot menu. It will be
+-- | Run update-grub, to generate the grub boot menu. It will be
-- automatically updated when kernel packages are installed.
mkConfig :: Property DebianLike
mkConfig = tightenTargets $ cmdProperty "update-grub" []
`assume` MadeChange
-- | Installs grub; does not run update-grub.
-installed' :: BIOS -> Property (HasInfo + DebianLike)
-installed' bios = setInfoProperty aptinstall
- (toInfo [GrubInstalled])
+installed' :: GrubTarget -> Property (HasInfo + DebianLike)
+installed' grubtarget = setInfoProperty aptinstall
+ (toInfo [GrubInstalled grubtarget])
`describe` "grub package installed"
where
aptinstall = Apt.installed [debpkg]
- debpkg = case bios of
+ debpkg = case grubtarget of
PC -> "grub-pc"
EFI64 -> "grub-efi-amd64"
EFI32 -> "grub-efi-ia32"
Coreboot -> "grub-coreboot"
Xen -> "grub-xen"
--- | Installs grub onto a device, so the system can boot from that device.
+-- | Installs grub onto a device's boot loader,
+-- so the system can boot from that device.
--
-- You may want to install grub to multiple devices; eg for a system
-- that uses software RAID.
@@ -57,9 +64,24 @@ installed' bios = setInfoProperty aptinstall
-- to arrange for this property to only run once, by eg making it be run
-- onChange after OS.cleanInstallOnce.
boots :: OSDevice -> Property Linux
-boots dev = tightenTargets $ cmdProperty "grub-install" [dev]
- `assume` MadeChange
- `describe` ("grub boots " ++ dev)
+boots dev = property' ("grub boots " ++ dev) $ \w -> do
+ grubtarget <- askInfo
+ let ps = case grubtarget of
+ [GrubInstalled t] -> [targetParam t]
+ _ -> []
+ ensureProperty w $
+ cmdProperty "grub-install" (ps ++ [dev])
+ `assume` MadeChange
+
+targetParam :: GrubTarget -> String
+targetParam t = "--target=" ++ case t of
+ PC -> "i386-pc"
+ EFI32 -> "i386-efi"
+ EFI64 -> "x86_64-efi"
+ Coreboot -> "i386-coreboot"
+ Xen -> "x86_64-xen"
+
+type TimeoutSecs = Int
-- | Use PV-grub chaining to boot
--
@@ -95,8 +117,8 @@ chainPVGrub rootdev bootdev timeout = combineProperties desc $ props
-- at a particular directory. The OSDevice should be the underlying disk
-- device that grub will be installed to (generally a whole disk,
-- not a partition).
-bootsMounted :: FilePath -> OSDevice -> Property Linux
-bootsMounted mnt wholediskdev = combineProperties desc $ props
+bootsMounted :: FilePath -> OSDevice -> GrubTarget -> Property Linux
+bootsMounted mnt wholediskdev grubtarget = combineProperties desc $ props
-- remove mounts that are done below to make sure the right thing
-- gets mounted
& cleanupmounts
@@ -112,7 +134,7 @@ bootsMounted mnt wholediskdev = combineProperties desc $ props
& inchroot "update-grub" []
`assume` MadeChange
& check haveosprober (inchroot "chmod" ["+x", osprober])
- & inchroot "grub-install" [wholediskdev]
+ & inchroot "grub-install" [targetParam grubtarget, wholediskdev]
`assume` MadeChange
& cleanupmounts
-- sync all buffered changes out to the disk in case it's
diff --git a/src/Propellor/Property/Installer.hs b/src/Propellor/Property/Installer.hs
new file mode 100644
index 00000000..f03391f5
--- /dev/null
+++ b/src/Propellor/Property/Installer.hs
@@ -0,0 +1,20 @@
+-- | Installer disk image generation
+--
+-- These modules contain properties that can be used to create a disk
+-- image, suitable for booting from removable media, that can perform an
+-- interactive or non-interactive installation of a Host's internal disk.
+--
+-- The disk image is created using propellor. When booted, it runs
+-- propellor to install to the desired disk.
+--
+-- There is no user interface included here. For an example of using
+-- this to build a full, interactive installer, see
+-- <https://git.joeyh.name/index.cgi/secret-project.git/>
+
+module Propellor.Property.Installer (
+ module Propellor.Property.Installer.Types,
+ module Propellor.Property.Installer.Target
+) where
+
+import Propellor.Property.Installer.Types
+import Propellor.Property.Installer.Target
diff --git a/src/Propellor/Property/Installer/Target.hs b/src/Propellor/Property/Installer/Target.hs
new file mode 100644
index 00000000..986c75ea
--- /dev/null
+++ b/src/Propellor/Property/Installer/Target.hs
@@ -0,0 +1,462 @@
+{-# LANGUAGE TypeOperators #-}
+
+-- | Installation to a target disk.
+--
+-- Note that the RevertableProperties in this module are not really
+-- revertable; the target disk can't be put back how it was.
+-- The RevertableProperty type is used only to let them be used
+-- in a Versioned Host as shown below.
+--
+-- Here's an example of a noninteractive installer image using
+-- these properties.
+--
+-- There are two versions of Hosts, the installer and the target system.
+--
+-- > data Variety = Installer | Target
+-- > deriving (Eq)
+--
+-- The seed of both the installer and the target. They have some properties
+-- in common, and some different properties. The `targetInstalled`
+-- property knows how to convert the installer it's running on into a
+-- target system.
+--
+-- > seed :: Versioned Variety Host
+-- > seed ver = host "debian.local" $ props
+-- > & osDebian Unstable X86_64
+-- > & Hostname.sane
+-- > & Apt.stdSourcesList
+-- > & Apt.installed ["linux-image-amd64"]
+-- > & Grub.installed PC
+-- > & "en_US.UTF-8" `Locale.selectedFor` ["LANG"]
+-- > & ver ( (== Installer) --> targetInstalled seed Target (userInput ver) parts)
+-- > & ver ( (== Target) --> fstabLists (userInput ver) parts)
+-- > & ver ( (== Installer) --> targetBootable (userInput ver))
+-- > where
+-- > parts = TargetPartTable MSDOS
+-- > [ partition EXT4 `mountedAt` "/"
+-- > `useDiskSpace` RemainingSpace
+-- > , swapPartition (MegaBytes 1024)
+-- > ]
+--
+-- The installer disk image can then be built from the seed as follows:
+--
+-- > installerBuilt :: RevertableProperty (HasInfo + DebianLike) Linux
+-- > installerBuilt = imageBuilt (VirtualBoxPointer "/srv/installer.vmdk")
+-- > (hostChroot (seed `version` installer) (Debootstrapped mempty))
+-- > MSDOS
+-- > [ partition EXT4 `mountedAt` "/"
+-- > `setFlag` BootFlag
+-- > `reservedSpacePercentage` 0
+-- > `addFreeSpace` MegaBytes 256
+-- > ]
+--
+-- When the installer is booted up, and propellor is run, it installs
+-- to the target disk. Since this example is a noninteractive installer,
+-- the details of what it installs to are configured before it's built.
+--
+-- > data HardCodedUserInput = HardCodedUserInput (Maybe TargetDiskDevice) (Maybe DiskEraseConfirmed)
+-- >
+-- > instance UserInput HardCodedUserInput where
+-- > targetDiskDevice (HardCodedUserInput t _) = Just t
+-- > diskEraseConfirmed (HardCodedUserInput _ c) = Just c
+-- >
+-- > userInput :: Version -> HardCodedUserInput
+-- > userInput Installer = HardCodedUserInput Nothing Nothing
+-- > userInput Target = HardCodedUserInput (Just (TargetDiskDevice "/dev/sda")) (Just DiskEraseConfirmed)
+--
+-- For an example of how to use this to make an interactive installer,
+-- see <https://git.joeyh.name/index.cgi/secret-project.git/>
+
+module Propellor.Property.Installer.Target (
+ TargetPartTable(..),
+ targetInstalled,
+ mountTarget,
+ fstabLists,
+ targetBootable,
+ partitionTargetDisk,
+ targetDir,
+ probeDisk,
+ findDiskDevices,
+ TargetFilled,
+ TargetFilledHandle,
+ prepTargetFilled,
+ checkTargetFilled,
+ TargetFilledPercent(..),
+ targetFilledPercent,
+) where
+
+import Propellor
+import Propellor.Property.Installer.Types
+import Propellor.Message
+import Propellor.Types.Bootloader
+import Propellor.Types.PartSpec
+import Propellor.Property.Chroot
+import Propellor.Property.Versioned
+import Propellor.Property.Parted
+import Propellor.Property.Mount
+import qualified Propellor.Property.Fstab as Fstab
+import qualified Propellor.Property.Grub as Grub
+import qualified Propellor.Property.Rsync as Rsync
+
+import Text.Read
+import Control.Monad
+import Control.Monad.IO.Class (liftIO)
+import System.Directory
+import System.FilePath
+import Data.Maybe
+import Data.List
+import Data.Char
+import Data.Ord
+import Data.Ratio
+import System.Process (readProcess)
+
+data TargetPartTable = TargetPartTable TableType [PartSpec DiskPart]
+
+-- | Property that installs the target system to the TargetDiskDevice
+-- specified in the UserInput. That device will be re-partitioned and
+-- formatted and all files erased.
+--
+-- The installation is done efficiently by rsyncing the installer's files
+-- to the target, which forms the basis for a chroot that is provisioned with
+-- the specified version of the Host. Thanks to
+-- Propellor.Property.Versioned, any unwanted properties of the installer
+-- will be automatically reverted in the chroot.
+--
+-- When there is no TargetDiskDevice or the user has not confirmed the
+-- installation, nothing is done except for installing dependencies.
+-- So, this can also be used as a property of the installer
+-- image.
+targetInstalled
+ :: UserInput i
+ => Versioned v Host
+ -> v
+ -> i
+ -> TargetPartTable
+ -> RevertableProperty (HasInfo + DebianLike) (HasInfo + DebianLike)
+targetInstalled vtargethost v userinput (TargetPartTable tabletype partspec) =
+ case (targetDiskDevice userinput, diskEraseConfirmed userinput) of
+ (Just (TargetDiskDevice targetdev), Just _diskeraseconfirmed) ->
+ go `describe` ("target system installed to " ++ targetdev)
+ _ -> tightenTargets installdeps <!> doNothing
+ where
+ targethost = vtargethost `version` v
+ go = RevertableProperty
+ (setupRevertableProperty p)
+ -- Versioned needs both "sides" of the RevertableProperty
+ -- to have the same type, so add empty Info to make the
+ -- types line up.
+ (undoRevertableProperty p `setInfoProperty` mempty)
+ where
+ p = partitionTargetDisk userinput tabletype partspec
+ `before` mountTarget userinput partspec
+ `before` provisioned chroot
+
+ chroot = hostChroot targethost RsyncBootstrapper targetDir
+
+ -- Install dependencies that will be needed later when installing
+ -- the target.
+ installdeps = Rsync.installed
+
+data RsyncBootstrapper = RsyncBootstrapper
+
+instance ChrootBootstrapper RsyncBootstrapper where
+ buildchroot RsyncBootstrapper _ target = Right $
+ mountaside
+ `before` rsynced
+ `before` umountaside
+ where
+ -- bind mount the root filesystem to /mnt, which exposes
+ -- the contents of all directories that have things mounted
+ -- on top of them to rsync.
+ mountaside = bindMount "/" "/mnt"
+ rsynced = Rsync.rsync
+ [ "--one-file-system"
+ , "-aHAXS"
+ , "--delete"
+ , "/mnt/"
+ , target
+ ]
+ umountaside = cmdProperty "umount" ["-l", "/mnt"]
+ `assume` MadeChange
+
+mountTarget
+ :: UserInput i
+ => i
+ -> [PartSpec DiskPart]
+ -> RevertableProperty Linux Linux
+mountTarget userinput partspec = setup <!> cleanup
+ where
+ setup = property "target mounted" $
+ case targetDiskDevice userinput of
+ Just (TargetDiskDevice targetdev) -> do
+ liftIO unmountTarget
+ r <- liftIO $ forM tomount $
+ mountone targetdev
+ if and r
+ then return MadeChange
+ else return FailedChange
+ Nothing -> return NoChange
+ cleanup = property "target unmounted" $ do
+ liftIO unmountTarget
+ liftIO $ removeDirectoryRecursive targetDir
+ return NoChange
+
+ -- Sort so / comes before /home etc
+ tomount = sortOn (fst . fst) $
+ map (\((mp, mo, _, _), n) -> ((mp, mo), n)) $
+ zip partspec partNums
+
+ mountone targetdev ((mmountpoint, mountopts), num) =
+ case mmountpoint of
+ Nothing -> return True
+ Just mountpoint -> do
+ let targetmount = targetDir ++ mountpoint
+ createDirectoryIfMissing True targetmount
+ let dev = diskPartition targetdev num
+ mount "auto" dev targetmount mountopts
+
+-- | Property for use in the target Host to set up its fstab.
+-- Should be passed the same TargetPartTable as `targetInstalled`.
+fstabLists
+ :: UserInput i
+ => i
+ -> TargetPartTable
+ -> RevertableProperty Linux Linux
+fstabLists userinput (TargetPartTable _ partspecs) = setup <!> doNothing
+ where
+ setup = case targetDiskDevice userinput of
+ Just (TargetDiskDevice targetdev) ->
+ Fstab.fstabbed mnts (swaps targetdev)
+ `requires` devmounted
+ `before` devumounted
+ Nothing -> doNothing
+
+ -- needed for ftabbed UUID probing to work
+ devmounted :: Property Linux
+ devmounted = tightenTargets $ mounted "devtmpfs" "udev" "/dev" mempty
+ devumounted :: Property Linux
+ devumounted = tightenTargets $ cmdProperty "umount" ["-l", "/dev"]
+ `assume` MadeChange
+
+ partitions = map (\(mp, _, mkpart, _) -> (mp, mkpart mempty)) partspecs
+ mnts = mapMaybe fst $
+ filter (\(_, p) -> partFs p /= LinuxSwap) partitions
+ swaps targetdev =
+ map (Fstab.SwapPartition . diskPartition targetdev . snd) $
+ filter (\((_, p), _) -> partFs p == LinuxSwap)
+ (zip partitions partNums)
+
+-- | Make the target bootable using whatever bootloader is installed on it.
+targetBootable
+ :: UserInput i
+ => i
+ -> RevertableProperty Linux Linux
+targetBootable userinput =
+ case (targetDiskDevice userinput, diskEraseConfirmed userinput) of
+ (Just (TargetDiskDevice targetdev), Just _diskeraseconfirmed) ->
+ go targetdev <!> doNothing
+ _ -> doNothing <!> doNothing
+ where
+ desc = "bootloader installed on target disk"
+ go :: FilePath -> Property Linux
+ go targetdev = property' desc $ \w -> do
+ bootloaders <- askInfo
+ case bootloaders of
+ [GrubInstalled gt] -> ensureProperty w $
+ Grub.bootsMounted targetDir targetdev gt
+ [] -> do
+ warningMessage "no bootloader was installed"
+ return NoChange
+ l -> do
+ warningMessage $ "don't know how to enable bootloader(s) " ++ show l
+ return FailedChange
+
+partitionTargetDisk
+ :: UserInput i
+ => i
+ -> TableType
+ -> [PartSpec DiskPart]
+ -> RevertableProperty DebianLike DebianLike
+partitionTargetDisk userinput tabletype partspec = go <!> doNothing
+ where
+ go = check targetNotMounted $ property' "target disk partitioned" $ \w -> do
+ case (targetDiskDevice userinput, diskEraseConfirmed userinput) of
+ (Just (TargetDiskDevice targetdev), Just _diskeraseconfirmed) -> do
+ liftIO $ unmountTarget
+ disksize <- liftIO $ getDiskSize targetdev
+ let parttable = calcPartTable disksize tabletype safeAlignment partspec
+ ensureProperty w $
+ partitioned YesReallyDeleteDiskContents targetdev parttable
+ _ -> error "user input does not allow partitioning disk"
+
+unmountTarget :: IO ()
+unmountTarget = mapM_ umountLazy . reverse . sort =<< targetMountPoints
+
+targetMountPoints :: IO [MountPoint]
+targetMountPoints = filter isTargetMountPoint <$> mountPoints
+
+isTargetMountPoint :: MountPoint -> Bool
+isTargetMountPoint mp =
+ mp == targetDir
+ || addTrailingPathSeparator targetDir `isPrefixOf` mp
+
+targetNotMounted :: IO Bool
+targetNotMounted = not . any (== targetDir) <$> mountPoints
+
+-- | Where the target disk is mounted while it's being installed.
+targetDir :: FilePath
+targetDir = "/target"
+
+partNums :: [Integer]
+partNums = [1..]
+
+-- /dev/sda to /dev/sda1
+diskPartition :: FilePath -> Integer -> FilePath
+diskPartition dev num = dev ++ show num
+
+-- | This can be used to find a likely disk device to use as the target
+-- for an installation.
+--
+-- This is a bit of a hack; of course the user could be prompted but to
+-- avoid prompting, some heuristics...
+-- * It should not already be mounted.
+-- * Prefer disks big enough to comfortably hold a Linux installation,
+-- so at least 8 gb.
+-- (But, if the system only has a smaller disk, it should be used.)
+-- * A medium size internal disk is better than a large removable disk,
+-- because removable or added drives are often used for data storage
+-- on systems with smaller internal disk for the OS.
+-- (But, if the internal disk is too small, prefer removable disk;
+-- some systems have an unusably small internal disk.)
+-- * Prefer the first disk in BIOS order, all other things being equal,
+-- because the main OS disk typically comes first. This can be
+-- approximated by preferring /dev/sda to /dev/sdb.
+probeDisk :: IO TargetDiskDevice
+probeDisk = do
+ unmountTarget
+ mounteddevs <- getMountedDeviceIDs
+ let notmounted d = flip notElem (map Just mounteddevs)
+ <$> getMinorNumber d
+ candidates <- mapM probeCandidate
+ =<< filterM notmounted
+ =<< findDiskDevices
+ case reverse (sort candidates) of
+ (Candidate { candidateDevice = Down dev } : _) ->
+ return $ TargetDiskDevice dev
+ [] -> error "Unable to find any disk to install to!"
+
+-- | Find disk devices, such as /dev/sda (not partitions)
+findDiskDevices :: IO [FilePath]
+findDiskDevices = map ("/dev" </>) . filter isdisk
+ <$> getDirectoryContents "/dev"
+ where
+ isdisk ('s':'d':_:[]) = True
+ isdisk _ = False
+
+-- | When comparing two Candidates, the better of the two will be larger.
+data Candidate = Candidate
+ { candidateBigEnoughForOS :: Bool
+ , candidateIsFixedDisk :: Bool
+ -- use Down so that /dev/sda orders larger than /dev/sdb
+ , candidateDevice :: Down FilePath
+ } deriving (Eq, Ord)
+
+probeCandidate :: FilePath -> IO Candidate
+probeCandidate dev = do
+ DiskSize sz <- getDiskSize dev
+ isfixeddisk <- not <$> isRemovableDisk dev
+ return $ Candidate
+ { candidateBigEnoughForOS = sz >= 8 * onegb
+ , candidateIsFixedDisk = isfixeddisk
+ , candidateDevice = Down dev
+ }
+ where
+ onegb = 1024*1024*1000
+
+newtype MinorNumber = MinorNumber Integer
+ deriving (Eq, Show)
+
+getMountedDeviceIDs :: IO [MinorNumber]
+getMountedDeviceIDs = mapMaybe parse . lines <$> readProcess "findmnt"
+ [ "-rn"
+ , "--output"
+ , "MAJ:MIN"
+ ]
+ ""
+ where
+ parse = fmap MinorNumber . readMaybe
+ . dropWhile (not . isDigit) . dropWhile (/= ':')
+
+-- There is not currently a native haskell interface for getting the minor
+-- number of a device.
+getMinorNumber :: FilePath -> IO (Maybe MinorNumber)
+getMinorNumber dev = fmap MinorNumber . readMaybe
+ <$> readProcess "stat" [ "--printf", "%T", dev ] ""
+
+-- A removable disk may show up as removable or as hotplug.
+isRemovableDisk :: FilePath -> IO Bool
+isRemovableDisk dev = do
+ isremovable <- checkblk "RM"
+ ishotplug <- checkblk "HOTPLUG"
+ return (isremovable || ishotplug)
+ where
+ checkblk field = (== "1\n") <$> readProcess "lsblk"
+ [ "-rn"
+ , "--nodeps"
+ , "--output", field
+ , dev
+ ]
+ ""
+
+getDiskSize :: FilePath -> IO DiskSize
+getDiskSize dev = do
+ sectors <- fromMaybe 0 . readMaybe
+ <$> readProcess "blockdev" ["--getsz", dev] ""
+ return (DiskSize (sectors * 512))
+
+getMountsSizes :: IO [(MountPoint, Integer)]
+getMountsSizes = mapMaybe (parse . words) . lines <$> readProcess "findmnt" ps ""
+ where
+ ps = ["-rnb", "-o", "TARGET,USED"]
+ parse (mp:szs:[]) = do
+ sz <- readMaybe szs
+ return (mp, sz)
+ parse _ = Nothing
+
+-- | How much of the target disks are used, compared with the size of the
+-- installer's root device. Since the main part of an installation
+-- is rsyncing the latter to the former, this allows roughly estimating
+-- the percent done while an install is running, and can be used in some
+-- sort of progress display.
+data TargetFilled = TargetFilled (Ratio Integer)
+ deriving (Show, Eq)
+
+instance Monoid TargetFilled where
+ mempty = TargetFilled (0 % 1)
+ mappend (TargetFilled n) (TargetFilled m) = TargetFilled (n+m)
+
+newtype TargetFilledHandle = TargetFilledHandle Integer
+
+prepTargetFilled :: IO TargetFilledHandle
+prepTargetFilled = go =<< getMountSource "/"
+ where
+ go (Just dev) = do
+ -- Assumes that the installer uses a single partition.
+ DiskSize sz <- getDiskSize dev
+ return (TargetFilledHandle sz)
+ go Nothing = return (TargetFilledHandle 0)
+
+checkTargetFilled :: TargetFilledHandle -> IO TargetFilled
+checkTargetFilled (TargetFilledHandle installsz) = do
+ targetsz <- sum . map snd . filter (isTargetMountPoint . fst)
+ <$> getMountsSizes
+ return (TargetFilled (targetsz % max 1 installsz))
+
+newtype TargetFilledPercent = TargetFilledPercent Int
+ deriving (Show, Eq)
+
+targetFilledPercent :: TargetFilled -> TargetFilledPercent
+targetFilledPercent (TargetFilled r) = TargetFilledPercent $ floor percent
+ where
+ percent :: Double
+ percent = min 100 (fromRational r * 100)
diff --git a/src/Propellor/Property/Installer/Types.hs b/src/Propellor/Property/Installer/Types.hs
new file mode 100644
index 00000000..648cf3b3
--- /dev/null
+++ b/src/Propellor/Property/Installer/Types.hs
@@ -0,0 +1,16 @@
+module Propellor.Property.Installer.Types where
+
+-- | The disk device to install to.
+newtype TargetDiskDevice = TargetDiskDevice FilePath
+ deriving (Read, Show)
+
+data DiskEraseConfirmed = DiskEraseConfirmed
+ deriving (Read, Show)
+
+-- | Class of user input that an installer might prompt for.
+class UserInput i where
+ -- | Get the disk device the user selected to install to.
+ targetDiskDevice :: i -> Maybe TargetDiskDevice
+ -- | Check if the user has confirmed they want to erase the target
+ -- disk device.
+ diskEraseConfirmed :: i -> Maybe DiskEraseConfirmed
diff --git a/src/Propellor/Property/Mount.hs b/src/Propellor/Property/Mount.hs
index c047161d..71f1733e 100644
--- a/src/Propellor/Property/Mount.hs
+++ b/src/Propellor/Property/Mount.hs
@@ -149,4 +149,6 @@ umountLazy mnt =
unmountBelow :: FilePath -> IO ()
unmountBelow d = do
submnts <- mountPointsBelow d
- forM_ submnts umountLazy
+ -- sort so sub-mounts are unmounted before the mount point
+ -- containing them
+ forM_ (reverse (sort submnts)) umountLazy
diff --git a/src/Propellor/Property/Parted.hs b/src/Propellor/Property/Parted.hs
index d60d4a60..97cf815e 100644
--- a/src/Propellor/Property/Parted.hs
+++ b/src/Propellor/Property/Parted.hs
@@ -13,6 +13,8 @@ module Propellor.Property.Parted (
toPartSize,
fromPartSize,
reducePartSize,
+ Alignment(..),
+ safeAlignment,
Partition.MkfsOpts,
PartType(..),
PartFlag(..),
@@ -50,19 +52,28 @@ data Eep = YesReallyDeleteDiskContents
--
-- This deletes any existing partitions in the disk! Use with EXTREME caution!
partitioned :: Eep -> FilePath -> PartTable -> Property DebianLike
-partitioned eep disk (PartTable tabletype parts) = property' desc $ \w -> do
+partitioned eep disk parttable@(PartTable _ _ parts) = property' desc $ \w -> do
isdev <- liftIO $ isBlockDevice <$> getFileStatus disk
ensureProperty w $ combineProperties desc $ props
- & parted eep disk partedparams
+ & parted eep disk (fst (calcPartedParamsSize parttable))
& if isdev
then formatl (map (\n -> disk ++ show n) [1 :: Int ..])
else Partition.kpartx disk (formatl . map Partition.partitionLoopDev)
where
desc = disk ++ " partitioned"
formatl devs = combineProperties desc (toProps $ map format (zip parts devs))
- partedparams = concat $ mklabel : mkparts (1 :: Integer) mempty parts []
format (p, dev) = Partition.formatted' (partMkFsOpts p)
Partition.YesReallyFormatPartition (partFs p) dev
+
+-- | Gets the total size of the disk specified by the partition table.
+partTableSize :: PartTable -> ByteSize
+partTableSize = snd . calcPartedParamsSize
+
+calcPartedParamsSize :: PartTable -> ([String], ByteSize)
+calcPartedParamsSize (PartTable tabletype alignment parts) =
+ let (ps, sz) = calcparts (1 :: Integer) firstpos parts []
+ in (concat (mklabel : ps), sz)
+ where
mklabel = ["mklabel", pval tabletype]
mkflag partnum (f, b) =
[ "set"
@@ -70,39 +81,58 @@ partitioned eep disk (PartTable tabletype parts) = property' desc $ \w -> do
, pval f
, pval b
]
- mkpart partnum offset p =
+ mkpart partnum startpos endpos p =
[ "mkpart"
, pval (partType p)
, pval (partFs p)
- , pval offset
- , pval (offset <> partSize p)
+ , partposexact startpos
+ , partposfuzzy endpos
] ++ case partName p of
Just n -> ["name", show partnum, n]
Nothing -> []
- mkparts partnum offset (p:ps) c =
- mkparts (partnum+1) (offset <> partSize p) ps
- (c ++ mkpart partnum offset p : map (mkflag partnum) (partFlags p))
- mkparts _ _ [] c = c
+ calcparts partnum startpos (p:ps) c =
+ let endpos = startpos + align (partSize p)
+ in calcparts (partnum+1) endpos ps
+ (c ++ mkpart partnum startpos (endpos-1) p : map (mkflag partnum) (partFlags p))
+ calcparts _ endpos [] c = (c, endpos)
+
+ -- Exact partition position value for parted.
+ -- For alignment to work, the start of a partition must be
+ -- specified exactly.
+ partposexact n
+ | n > 0 = show n ++ "B"
+ -- parted can't make partitions smaller than 1MB;
+ -- avoid failure in edge cases
+ | otherwise = "1MB"
+
+ -- Fuzzy partition position valie for parted.
+ -- This is used to specify the end of the partition,
+ -- parted takes the "MB" as license to slightly reduce the
+ -- partition size when something about the partition table
+ -- does not allow the partition to end exactly at the position.
+ partposfuzzy n
+ | n > 0 = show (fromIntegral n / 1000000 :: Double) ++ "MB"
+ | otherwise = "1MB"
+
+ -- Location of the start of the first partition,
+ -- leaving space for the partition table, and aligning.
+ firstpos = align partitionTableOverhead
+
+ align = alignTo alignment
-- | Runs parted on a disk with the specified parameters.
--
-- Parted is run in script mode, so it will never prompt for input.
--- It is asked to use cylinder alignment for the disk.
parted :: Eep -> FilePath -> [String] -> Property (DebianLike + ArchLinux)
parted YesReallyDeleteDiskContents disk ps = p `requires` installed
where
- p = cmdProperty "parted" ("--script":"--align":"cylinder":disk:ps)
+ p = cmdProperty "parted" ("--script":"--align":"none":disk:ps)
`assume` MadeChange
-- | Gets parted installed.
installed :: Property (DebianLike + ArchLinux)
installed = Apt.installed ["parted"] `pickOS` Pacman.installed ["parted"]
--- | Gets the total size of the disk specified by the partition table.
-partTableSize :: PartTable -> ByteSize
-partTableSize (PartTable _ ps) = fromPartSize $
- mconcat (partitionTableOverhead : map partSize ps)
-
-- | Some disk is used to store the partition table itself. Assume less
-- than 1 mb.
partitionTableOverhead :: PartSize
@@ -112,27 +142,27 @@ partitionTableOverhead = MegaBytes 1
--
-- For example:
--
--- > calcPartTable (DiskSize (1024 * 1024 * 1024 * 100)) MSDOS
+-- > calcPartTable (DiskSize (1024 * 1024 * 1024 * 100)) MSDOS safeAlignment
-- > [ partition EXT2 `mountedAt` "/boot"
-- > `setSize` MegaBytes 256
-- > `setFlag` BootFlag
-- > , partition EXT4 `mountedAt` "/"
--- > `useDisk` RemainingSpace
+-- > `useDiskSpace` RemainingSpace
-- > ]
-calcPartTable :: DiskSize -> TableType -> [PartSpec DiskPart] -> PartTable
-calcPartTable (DiskSize disksize) tt l = PartTable tt (map go l)
+calcPartTable :: DiskSize -> TableType -> Alignment -> [PartSpec DiskPart] -> PartTable
+calcPartTable (DiskSize disksize) tt alignment l =
+ PartTable tt alignment (map go l)
where
go (_, _, mkpart, FixedDiskPart) = mkpart defSz
- go (_, _, mkpart, DynamicDiskPart (Percent p)) = mkpart $ toPartSize $
+ go (_, _, mkpart, DynamicDiskPart (Percent p)) = mkpart $ Bytes $
diskremainingafterfixed * fromIntegral p `div` 100
- go (_, _, mkpart, DynamicDiskPart RemainingSpace) = mkpart $ toPartSize $
+ go (_, _, mkpart, DynamicDiskPart RemainingSpace) = mkpart $ Bytes $
diskremaining `div` genericLength (filter isremainingspace l)
- diskremainingafterfixed =
+ diskremainingafterfixed =
disksize - sumsizes (filter isfixed l)
diskremaining =
disksize - sumsizes (filter (not . isremainingspace) l)
- sumsizes = sum . map fromPartSize . (partitionTableOverhead :) .
- map (partSize . go)
+ sumsizes = partTableSize . PartTable tt alignment . map go
isfixed (_, _, _, FixedDiskPart) = True
isfixed _ = False
isremainingspace (_, _, _, DynamicDiskPart RemainingSpace) = True
@@ -177,3 +207,14 @@ defSz = MegaBytes 128
-- Add an additional 200 mb for temp files, journals, etc.
fudgeSz :: PartSize -> PartSize
fudgeSz (MegaBytes n) = MegaBytes (n + n `div` 100 * 2 + 3 + 200)
+fudgeSz (Bytes n) = fudgeSz (toPartSize n)
+
+alignTo :: Alignment -> PartSize -> ByteSize
+alignTo _ (Bytes n) = n -- no alignment done for Bytes
+alignTo (Alignment alignment) partsize
+ | alignment < 1 = n
+ | otherwise = case rem n alignment of
+ 0 -> n
+ r -> n - r + alignment
+ where
+ n = fromPartSize partsize
diff --git a/src/Propellor/Property/Parted/Types.hs b/src/Propellor/Property/Parted/Types.hs
index 3350e008..e5c62739 100644
--- a/src/Propellor/Property/Parted/Types.hs
+++ b/src/Propellor/Property/Parted/Types.hs
@@ -1,6 +1,5 @@
module Propellor.Property.Parted.Types where
-import Propellor.Base
import qualified Propellor.Property.Partition as Partition
import Utility.DataUnits
@@ -17,14 +16,16 @@ instance PartedVal TableType where
pval = map toLower . show
-- | A disk's partition table.
-data PartTable = PartTable TableType [Partition]
+data PartTable = PartTable TableType Alignment [Partition]
deriving (Show)
instance Monoid PartTable where
- -- | default TableType is MSDOS
- mempty = PartTable MSDOS []
+ -- | default TableType is MSDOS, with a `safeAlignment`.
+ mempty = PartTable MSDOS safeAlignment []
-- | uses the TableType of the second parameter
- mappend (PartTable _l1 ps1) (PartTable l2 ps2) = PartTable l2 (ps1 ++ ps2)
+ -- and the larger alignment,
+ mappend (PartTable _l1 a1 ps1) (PartTable l2 a2 ps2) =
+ PartTable l2 (max a1 a2) (ps1 ++ ps2)
-- | A partition on the disk.
data Partition = Partition
@@ -57,33 +58,51 @@ instance PartedVal PartType where
pval Logical = "logical"
pval Extended = "extended"
--- | All partition sizing is done in megabytes, so that parted can
--- automatically lay out the partitions.
---
--- Note that these are SI megabytes, not mebibytes.
-newtype PartSize = MegaBytes Integer
+-- | Size of a partition.
+data PartSize
+ -- Since disk sizes are typically given in MB, not MiB, this
+ -- uses SI MegaBytes (powers of 10).
+ = MegaBytes Integer
+ -- For more control, the partition size can be given in bytes.
+ -- Note that this will prevent any automatic alignment from
+ -- being done.
+ | Bytes Integer
deriving (Show)
-instance PartedVal PartSize where
- pval (MegaBytes n)
- | n > 0 = val n ++ "MB"
- -- parted can't make partitions smaller than 1MB;
- -- avoid failure in edge cases
- | otherwise = "1MB"
-
-- | Rounds up to the nearest MegaByte.
toPartSize :: ByteSize -> PartSize
-toPartSize b = MegaBytes $ ceiling (fromInteger b / 1000000 :: Double)
+toPartSize = toPartSize' ceiling
+
+toPartSize' :: (Double -> Integer) -> ByteSize -> PartSize
+toPartSize' rounder b = MegaBytes $ rounder (fromInteger b / 1000000 :: Double)
fromPartSize :: PartSize -> ByteSize
fromPartSize (MegaBytes b) = b * 1000000
+fromPartSize (Bytes n) = n
instance Monoid PartSize where
mempty = MegaBytes 0
mappend (MegaBytes a) (MegaBytes b) = MegaBytes (a + b)
+ mappend (Bytes a) b = Bytes (a + fromPartSize b)
+ mappend a (Bytes b) = Bytes (b + fromPartSize a)
reducePartSize :: PartSize -> PartSize -> PartSize
reducePartSize (MegaBytes a) (MegaBytes b) = MegaBytes (a - b)
+reducePartSize (Bytes a) b = Bytes (a - fromPartSize b)
+reducePartSize a (Bytes b) = Bytes (fromPartSize a - b)
+
+-- | Partitions need to be aligned for optimal efficiency.
+-- The alignment is a number of bytes.
+newtype Alignment = Alignment ByteSize
+ deriving (Show, Eq, Ord)
+
+-- | 4MiB alignment is optimal for inexpensive flash drives and
+-- is a good safe default for all drives.
+safeAlignment :: Alignment
+safeAlignment = Alignment (4*1024*1024)
+
+fromAlignment :: Alignment -> ByteSize
+fromAlignment (Alignment n) = n
-- | Flags that can be set on a partition.
data PartFlag = BootFlag | RootFlag | SwapFlag | HiddenFlag | RaidFlag | LvmFlag | LbaFlag | LegacyBootFlag | IrstFlag | EspFlag | PaloFlag
@@ -106,6 +125,8 @@ instance PartedVal Bool where
pval True = "on"
pval False = "off"
+-- This is used for creating partitions, not formatting partitions,
+-- so it's ok to use eg, fat32 for both FAT and VFAT.
instance PartedVal Partition.Fs where
pval Partition.EXT2 = "ext2"
pval Partition.EXT3 = "ext3"
@@ -113,7 +134,7 @@ instance PartedVal Partition.Fs where
pval Partition.BTRFS = "btrfs"
pval Partition.REISERFS = "reiserfs"
pval Partition.XFS = "xfs"
- pval Partition.FAT = "fat"
- pval Partition.VFAT = "vfat"
+ pval Partition.FAT = "fat32"
+ pval Partition.VFAT = "fat32"
pval Partition.NTFS = "ntfs"
pval Partition.LinuxSwap = "linux-swap"
diff --git a/src/Propellor/Property/Sbuild.hs b/src/Propellor/Property/Sbuild.hs
index d323ee67..8cc2e3be 100644
--- a/src/Propellor/Property/Sbuild.hs
+++ b/src/Propellor/Property/Sbuild.hs
@@ -48,6 +48,14 @@ To take advantage of the piuparts and autopkgtest support, add to your
>
> $autopkgtest_root_args = "";
> $autopkgtest_opts = ["--", "schroot", "%r-%a-sbuild"];
+
+On Debian jessie hosts, you should ensure that sbuild and autopkgtest come from
+the same suite. This is because the autopkgtest binary changed its name between
+jessie and stretch. If you have not installed backports of sbuild or
+autopkgtest, you don't need to do anything. But if you have installed either
+package from jessie-backports (with Propellor or otherwise), you should install
+the other from jessie-backports, too.
+
-}
module Propellor.Property.Sbuild (
@@ -376,6 +384,13 @@ ccachePrepared = propertyList "sbuild group ccache configured" $ props
--
-- You probably want a custom ~/.sbuildrc on your workstation, but
-- this property is handy for quickly setting up build boxes.
+--
+-- On Debian jessie hosts, you should ensure that sbuild and autopkgtest come
+-- from the same suite. This is because the autopkgtest binary changed its name
+-- between jessie and stretch. If you have not installed backports of sbuild or
+-- autopkgtest, you don't need to do anything. But if you have installed either
+-- package from jessie-backports (with Propellor or otherwise), you should
+-- install the other from jessie-backports, too.
userConfig :: User -> Property DebianLike
userConfig user@(User u) = go
`requires` usableBy user
diff --git a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs
index 2d5a244f..e3d21ac1 100644
--- a/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs
+++ b/src/Propellor/Property/SiteSpecific/GitAnnexBuilder.hs
@@ -181,6 +181,8 @@ armAutoBuilder suite arch flavor =
-- Works around ghc crash with parallel builds on arm.
& (homedir </> ".cabal" </> "config")
`File.lacksLine` "jobs: $ncpus"
+ -- Work around https://github.com/systemd/systemd/issues/7135
+ & Systemd.containerCfg "--system-call-filter=set_tls"
androidAutoBuilderContainer :: Times -> TimeOut -> Systemd.Container
androidAutoBuilderContainer crontimes timeout =
diff --git a/src/Propellor/Property/SiteSpecific/JoeySites.hs b/src/Propellor/Property/SiteSpecific/JoeySites.hs
index 6965af76..9385493c 100644
--- a/src/Propellor/Property/SiteSpecific/JoeySites.hs
+++ b/src/Propellor/Property/SiteSpecific/JoeySites.hs
@@ -646,7 +646,7 @@ dkimInstalled = go `onChange` Service.restarted "opendkim"
& Apt.serviceInstalledRunning "opendkim"
& File.dirExists "/etc/mail"
& File.hasPrivContent "/etc/mail/dkim.key" (Context "kitenet.net")
- & File.ownerGroup "/etc/mail/dkim.key" (User "opendkim") (Group "opendkim")
+ & File.ownerGroup "/etc/mail/dkim.key" (User "root") (Group "root")
& "/etc/default/opendkim" `File.containsLine`
"SOCKET=\"inet:8891@localhost\""
`onChange`
@@ -906,8 +906,8 @@ alarmClock oncalendar (User user) command = combineProperties "goodmorning timer
("Login", "LidSwitchIgnoreInhibited", "no")
-- My home power monitor.
-homePowerMonitor :: IsContext c => User -> c -> (SshKeyType, Ssh.PubKeyText) -> Property (HasInfo + DebianLike)
-homePowerMonitor user ctx sshkey = propertyList "home power monitor" $ props
+homePowerMonitor :: IsContext c => User -> [Host] -> c -> (SshKeyType, Ssh.PubKeyText) -> Property (HasInfo + DebianLike)
+homePowerMonitor user hosts ctx sshkey = propertyList "home power monitor" $ props
& Apache.installed
& Apt.installed ["python", "python-pymodbus", "rrdtool", "rsync"]
& File.ownerGroup "/var/www/html" user (userGroup user)
@@ -923,6 +923,7 @@ homePowerMonitor user ctx sshkey = propertyList "home power monitor" $ props
`requires` File.ownerGroup (takeDirectory sshkeyfile)
user (userGroup user)
`requires` File.dirExists (takeDirectory sshkeyfile)
+ `requires` Ssh.knownHost hosts "kitenet.net" user
where
d = "/var/www/html/homepower"
sshkeyfile = d </> ".ssh/key"
@@ -1033,3 +1034,47 @@ ipmasq intif = File.hasContent ifupscript
ifupscript = "/etc/network/if-up.d/ipmasq"
pppupscript = "/etc/ppp/ip-up.d/ipmasq"
scriptmode f = f `File.mode` combineModes (readModes ++ executeModes)
+
+laptopSoftware :: Property DebianLike
+laptopSoftware = Apt.installed
+ [ "procmeter3", "xfce4", "procmeter3", "unclutter"
+ , "mplayer", "fbreader", "firefox", "chromium"
+ , "libdatetime-event-sunrise-perl", "libtime-duration-perl"
+ , "iftop", "network-manager", "gtk-redshift", "powertop"
+ , "gimp", "gthumb", "inkscape", "sozi", "xzgv", "hugin"
+ , "mpc", "mpd", "ncmpc", "sonata", "mpdtoys"
+ , "bsdgames", "nethack"
+ , "xmonad", "libghc-xmonad-dev", "libghc-xmonad-contrib-dev"
+ , "ttf-bitstream-vera"
+ , "mairix", "offlineimap", "mutt"
+ , "nmap"
+ , "udevil", "pmount"
+ , "arbtt", "hledger", "bc"
+ , "apache2", "ikiwiki", "libhighlight-perl"
+ , "pal"
+ , "yeahconsole", "xkbset", "xinput"
+ , "assword", "pumpa", "vorbis-tools"
+ , "xul-ext-ublock-origin", "xul-ext-pdf.js", "xul-ext-status4evar"
+ , "vim-syntastic", "vim-fugitive"
+ , "adb", "gthumb"
+ , "w3m", "sm", "weechat"
+ , "borgbackup", "wipe"
+ ]
+ `requires` baseSoftware
+ `requires` devSoftware
+
+baseSoftware :: Property DebianLike
+baseSoftware = Apt.installed
+ [ "bash", "bash-completion", "vim", "screen", "less", "moreutils"
+ , "git", "mr", "etckeeper", "git-annex", "ssh", "vim-vimoutliner"
+ ]
+
+devSoftware :: Property DebianLike
+devSoftware = Apt.installed
+ [ "build-essential", "debhelper", "devscripts"
+ , "ghc", "cabal-install", "haskell-stack"
+ , "hothasktags", "hdevtools", "hlint"
+ , "gdb", "dpkg-repack", "lintian"
+ , "pristine-tar", "github-backup"
+ , "kvm"
+ ]
diff --git a/src/Propellor/Types/Bootloader.hs b/src/Propellor/Types/Bootloader.hs
index fd929d7e..65117bd2 100644
--- a/src/Propellor/Types/Bootloader.hs
+++ b/src/Propellor/Types/Bootloader.hs
@@ -7,13 +7,16 @@ import Propellor.Types.Info
-- | Boot loader installed on a host.
data BootloaderInstalled
- = GrubInstalled
+ = GrubInstalled GrubTarget
| FlashKernelInstalled
| UbootInstalled (FilePath -> FilePath -> Property Linux)
deriving (Typeable)
+-- | Platforms that grub can boot.
+data GrubTarget = PC | EFI64 | EFI32 | Coreboot | Xen
+
instance Show BootloaderInstalled where
- show GrubInstalled = "GrubInstalled"
+ show (GrubInstalled _) = "GrubInstalled"
show FlashKernelInstalled = "FlashKernelInstalled"
show (UbootInstalled _) = "UbootInstalled"