On 04/06/2016 12:33 PM, Richard Yao wrote:
> On 04/06/2016 12:20 PM, Alexis Ballier wrote:
>> On Wednesday, April 6, 2016 6:06:35 PM CEST, Richard Yao wrote:
>>
>>> That is unless you put per-system state in /usr/local, do symlinks to it
>>> in / and mount /usr/local as part of system boot, which is the other way
>>> of doing this. I have seen a variant of this done in asuswrt-merlin on
>>> routers.
>>
>> This doesnt seem to have anything to do with what I was describing.
>>
>> Another option I'm using a lot is nfsroot. This doesn't have the same
>> level of flexibility: running multiple hosts with nfsroot and thus
>> shared /etc/fstab tends to be annoying.
>>
>>>> See https://fedoraproject.org/wiki/Features/UsrMove for a more complete
>>>> discussion.
>>>
>>> That does not address the problems of supporting this configuration in a
>>> rolling release.
>>>
>>> Formats in /etc can fall out of sync with software in /usr. If boot
>>> options change, the stuff in /etc/init.d is not updated. If you add
>>> software, the update to /etc/init.d is omitted. If you have a baselayout
>>> change, it is not propagated.
>>
>> Ever heard of CONFIG_PROTECT ? :) What you describe is already what
>> happens and what most people want.
> 
> Leveraging the /usr merge to enable easier updating of multiple systems
> means that you are updating a Gentoo system image on a build server,
> snapshotting /usr both before/after the update and then distributing the
> delta on /usr to other systems without any of the changes that occurred
> outside of /usr. A proper update requires finding all of those changes
> and then applying them manually. That really is not the same thing that
> RHEL and Solaris have, where the necessity of propagating changes
> outside of /usr is minimized by having none to propagate.

After thinking about it some more, maybe git can be (ab)used to do this
by having the image's root be a git repository with /usr in .gitingore.

When updates are done, you would run etc-update on the build host by
committing the changes to / into git with ./usr in .gitignore. Then you
would have the delta from /usr via whatever mechanism that the user
wishes to use with a patch on / from the build system that can be merged
into each target's / repository. The procedure would require more effort
than what Solaris and RHEL do, but if documented, it should fix the
partial update problem that occurs when you do a /usr merge in a rolling
release and then do what people on Solaris and RHEL do to update systems
configured for updates via deltas of /usr.

To give an example, lets assume:

1. /path/to/build/image has a git repository with ./usr in .gitignore on
the build host while the targets have the same (with paths being / and
/usr of course).

2. Things are on ZFS on the build host and the targets.

3. There is a snapshot of the build environment that the targets have.

4. tank/BUILD/gentoo is the / and tank/BUILD/gentoo/usr is the /usr on
the build host.

5. The targets have rpool/SYSTEM/USR/gentoo as their /usr and
rpool/SYSTEM/USR is set readonly (so /usr is not modified due to
inheritance of readonly).

The delta generation would be something like this:

# Setup build environment
sudo -i /path/to/enter-container.sh /path/to/build/image
https://gist.github.com/ryao/3c345f206b19c9795109)

# Update portage
emerge-webrsync / emerge-delta-webrsync / emerge --sync
# Preferably one of the first two with PORTAGE_GPG_* configured

# Install updates
emerge -avDuN @world

# Update config files
etc-update

# Exit build environment
exit

# Commit changes to /
git -C /path/to/build/image commit -a

# Snapshot the build environment
sudo -i zfs snapshot -r tank/BUILD/gentoo@"$(date +%Y%m%d)"

Then a child could be updated by something like:

# First /usr
zfs send -i tank/BUILD/gentoo@previous tank/BUILD/gentoo/usr@"$(date
+%Y%m%d)" | ssh root@$CHILD zfs recv rpool/SYSTEM/USR/gentoo

# Then /
git -C /path/to/build/image diff HEAD^ | ssh root@$CHILD git -C
/other/location apply

# If conflicts occurred, fix whatever was broken
ssh root@$CHILD

# Reboot / restart services
reboot

This is intended to only be an example, but there are a few problems
with this simple example that are worth mentioning:

1. You probably want to have a shell into the system in case the update
to / does not go well, which makes the update to / somewhat hackish.

2. The way Solaris does things is to have boot environments where the
change is in a different boot environment that only takes effect as part
of a reboot. If you are doing a boot environment type thing, you could
probably update / for the new reboot, although you would want to
implement easy rollback if anything goes wrong.

That step on / is somewhat hackish, but it is intended to be an example.

Doing something similar to what Solaris did to make management of
multiple systems easier is likely doable with some way of handling
changes outside of /usr.

> I do not understand how CONFIG_PROTECT is relevant here. Whatever
> CONFIG_PROTECT did was done on the build system. The systems receiving
> the updates via ZFS send/recv or some similar mechanism are not going to
> have CONFIG_PROTECT evaluated. Even if it were somehow evaluated, all of
> the paths in CONFIG_PROTECT should be outside of /usr anyway.

Reply via email to