Gentoo Archives: gentoo-dev

From: Richard Yao <ryao@g.o>
To: gentoo-dev@l.g.o
Subject: Re: [gentoo-dev] usr merge
Date: Wed, 06 Apr 2016 17:43:51
Message-Id: 57054AB4.1020902@gentoo.org
In Reply to: Re: [gentoo-dev] usr merge by Richard Yao
1 On 04/06/2016 12:33 PM, Richard Yao wrote:
2 > On 04/06/2016 12:20 PM, Alexis Ballier wrote:
3 >> On Wednesday, April 6, 2016 6:06:35 PM CEST, Richard Yao wrote:
4 >>
5 >>> That is unless you put per-system state in /usr/local, do symlinks to it
6 >>> in / and mount /usr/local as part of system boot, which is the other way
7 >>> of doing this. I have seen a variant of this done in asuswrt-merlin on
8 >>> routers.
9 >>
10 >> This doesnt seem to have anything to do with what I was describing.
11 >>
12 >> Another option I'm using a lot is nfsroot. This doesn't have the same
13 >> level of flexibility: running multiple hosts with nfsroot and thus
14 >> shared /etc/fstab tends to be annoying.
15 >>
16 >>>> See https://fedoraproject.org/wiki/Features/UsrMove for a more complete
17 >>>> discussion.
18 >>>
19 >>> That does not address the problems of supporting this configuration in a
20 >>> rolling release.
21 >>>
22 >>> Formats in /etc can fall out of sync with software in /usr. If boot
23 >>> options change, the stuff in /etc/init.d is not updated. If you add
24 >>> software, the update to /etc/init.d is omitted. If you have a baselayout
25 >>> change, it is not propagated.
26 >>
27 >> Ever heard of CONFIG_PROTECT ? :) What you describe is already what
28 >> happens and what most people want.
29 >
30 > Leveraging the /usr merge to enable easier updating of multiple systems
31 > means that you are updating a Gentoo system image on a build server,
32 > snapshotting /usr both before/after the update and then distributing the
33 > delta on /usr to other systems without any of the changes that occurred
34 > outside of /usr. A proper update requires finding all of those changes
35 > and then applying them manually. That really is not the same thing that
36 > RHEL and Solaris have, where the necessity of propagating changes
37 > outside of /usr is minimized by having none to propagate.
38
39 After thinking about it some more, maybe git can be (ab)used to do this
40 by having the image's root be a git repository with /usr in .gitingore.
41
42 When updates are done, you would run etc-update on the build host by
43 committing the changes to / into git with ./usr in .gitignore. Then you
44 would have the delta from /usr via whatever mechanism that the user
45 wishes to use with a patch on / from the build system that can be merged
46 into each target's / repository. The procedure would require more effort
47 than what Solaris and RHEL do, but if documented, it should fix the
48 partial update problem that occurs when you do a /usr merge in a rolling
49 release and then do what people on Solaris and RHEL do to update systems
50 configured for updates via deltas of /usr.
51
52 To give an example, lets assume:
53
54 1. /path/to/build/image has a git repository with ./usr in .gitignore on
55 the build host while the targets have the same (with paths being / and
56 /usr of course).
57
58 2. Things are on ZFS on the build host and the targets.
59
60 3. There is a snapshot of the build environment that the targets have.
61
62 4. tank/BUILD/gentoo is the / and tank/BUILD/gentoo/usr is the /usr on
63 the build host.
64
65 5. The targets have rpool/SYSTEM/USR/gentoo as their /usr and
66 rpool/SYSTEM/USR is set readonly (so /usr is not modified due to
67 inheritance of readonly).
68
69 The delta generation would be something like this:
70
71 # Setup build environment
72 sudo -i /path/to/enter-container.sh /path/to/build/image
73 https://gist.github.com/ryao/3c345f206b19c9795109)
74
75 # Update portage
76 emerge-webrsync / emerge-delta-webrsync / emerge --sync
77 # Preferably one of the first two with PORTAGE_GPG_* configured
78
79 # Install updates
80 emerge -avDuN @world
81
82 # Update config files
83 etc-update
84
85 # Exit build environment
86 exit
87
88 # Commit changes to /
89 git -C /path/to/build/image commit -a
90
91 # Snapshot the build environment
92 sudo -i zfs snapshot -r tank/BUILD/gentoo@"$(date +%Y%m%d)"
93
94 Then a child could be updated by something like:
95
96 # First /usr
97 zfs send -i tank/BUILD/gentoo@previous tank/BUILD/gentoo/usr@"$(date
98 +%Y%m%d)" | ssh root@$CHILD zfs recv rpool/SYSTEM/USR/gentoo
99
100 # Then /
101 git -C /path/to/build/image diff HEAD^ | ssh root@$CHILD git -C
102 /other/location apply
103
104 # If conflicts occurred, fix whatever was broken
105 ssh root@$CHILD
106
107 # Reboot / restart services
108 reboot
109
110 This is intended to only be an example, but there are a few problems
111 with this simple example that are worth mentioning:
112
113 1. You probably want to have a shell into the system in case the update
114 to / does not go well, which makes the update to / somewhat hackish.
115
116 2. The way Solaris does things is to have boot environments where the
117 change is in a different boot environment that only takes effect as part
118 of a reboot. If you are doing a boot environment type thing, you could
119 probably update / for the new reboot, although you would want to
120 implement easy rollback if anything goes wrong.
121
122 That step on / is somewhat hackish, but it is intended to be an example.
123
124 Doing something similar to what Solaris did to make management of
125 multiple systems easier is likely doable with some way of handling
126 changes outside of /usr.
127
128 > I do not understand how CONFIG_PROTECT is relevant here. Whatever
129 > CONFIG_PROTECT did was done on the build system. The systems receiving
130 > the updates via ZFS send/recv or some similar mechanism are not going to
131 > have CONFIG_PROTECT evaluated. Even if it were somehow evaluated, all of
132 > the paths in CONFIG_PROTECT should be outside of /usr anyway.