From mboxrd@z Thu Jan 1 00:00:00 1970 From: ludo@gnu.org (Ludovic =?utf-8?Q?Court=C3=A8s?=) Subject: Re: Implementing guix system rollback / switch-generation Date: Mon, 06 Jun 2016 10:10:29 +0200 Message-ID: <87a8iy68lm.fsf@gnu.org> References: <87wpm3qngd.fsf@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:47097) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b9pcM-0002k7-CO for guix-devel@gnu.org; Mon, 06 Jun 2016 04:10:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1b9pcH-0003Um-TF for guix-devel@gnu.org; Mon, 06 Jun 2016 04:10:37 -0400 In-Reply-To: <87wpm3qngd.fsf@gmail.com> (Chris Marusich's message of "Sun, 05 Jun 2016 15:29:22 -0700") List-Id: "Development of GNU Guix and the GNU System distribution." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-devel-bounces+gcggd-guix-devel=m.gmane.org@gnu.org Sender: "Guix-devel" To: Chris Marusich Cc: guix-devel@gnu.org Hi Chris, Chris Marusich skribis: > Basically, I think there should be a command like "guix system > roll-back" which does the opposite of "guix system reconfigure > config.scm". The rollback command should not require an operating > system configuration file. I think this would be better than the > current rollback methods. What do you think? It would definitely be a welcome addition! The refactoring that was done to add =E2=80=98guix system list-generations=E2=80=99 was in the same = spirit. > As I understand it, when I invoke "guix system reconfigure config.scm", > the following things happen (in guix/scripts/system.scm): > > * A new system is built in the store (e.g., > /gnu/store/1qkdd4glvqjqf7azqniis7abkf7v1lng-system). > > * A new symlink is created in /var/guix/profiles (e.g., > /var/guix/profiles/system-7-link), which points to the system in the > store. > > * The /var/guix/profiles/system symlink is updated to point to the new > symlink. > > * The new system's activation script is run, and the Shepherd services > are upgraded. > > * A new grub.cfg is copied to /boot/grub/grub.cfg. This new grub.cfg > updates the default menu entry to point to the new system, and it adds > the previous system to the list of previous generations. > > At this point, you are running a new system. I am not sure if you need > to reboot to truly upgrade, but judging by the implementation of the > upgrade-shepherd-services procedure, it seems like you might sometimes > need to reboot to "really" complete the upgrade process. Indeed. Service upgrade is conservative, so it will not stop running services, because it cannot know if this is something the user wants and if it is safe; only services that are not currently running are loaded and started upon reconfigure. http://bugs.gnu.org/22039 To improve on this, I think it should be possible for Shepherd services to provide an =E2=80=98upgrade=E2=80=99 method in addition to start/stop, f= or those services that can be upgraded with no downtime (there aren=E2=80=99t so man= y of them, though.) > * Manually update the /var/guix/profiles/system symlink to point to a > previous generation, e.g., /var/guix/profiles/system-5-link. > > If you do this, it seems the running system will not actually be rolled > back. The system pointed to by /run/current-system will not change, > since it points to a store path rather than to the > /var/guix/profiles/system symlink. =E2=80=98guix system reconfigure=E2=80=99 could explicitly update /run/curr= ent-system to point to the old system. > In addition, because /boot/grub/grub.cfg has not been modified, when > you reboot, GRUB will still automatically select and boot the system > from which you wanted to roll back. Also, the previous system's > activation script will not be run, and the shepherd services will not > be downgraded. With that in mind, I'm not really sure what manually > flipping this symlink actually accomplishes. Not much, indeed. The problem with system rollback, as you=E2=80=99ve seen, is that we lack information about the old system, such as what its activation script is and what its Shepherd services are. We could add the activation script=E2=80=99s file name to the =E2=80=98para= meters=E2=80=99 file that you see in the result of =E2=80=98guix system build foo.scm=E2=80=99. = But it would be hard to add a forward-compatible yet complete description of the Shepherd services there. > * Use the emacs interface to update that symlink. > > This is the same as above, except that emacs does the symlink flip for > you. It does not seem to actually roll back the system. The elisp code > seems to assume that flipping the symlink is sufficient. Maybe that > works for changing user profile generations, but it seems to be > insufficient for system generation changes. > > * While booting, at the GRUB menu, manually select a previous > generation. > > This is the only method that seems to actually put the system back into > a previous state, and it appears to do so correctly. I've used this > method to save my systems a few times from bad upgrades, which is great. > The only downside to this method is that it doesn't modify the grub.cfg > file: until you reconfigure your system again, every time you restart, > GRUB will continue to automatically select and boot the newer, > problematic system from which you wanted to roll back. ISTR that GRUB has a mechanism to record the last selected menu entry and to use that as the next default entry. Now, it=E2=80=99s not always what one would want to do. However, =E2=80=98guix system roll-back/switch-generation=E2=80=99 could ge= nerate a grub.cfg where the default menu entry points to whatever old generation has been selected. > I'd like to implement a rollback mechanism that lets you run a single > command which actually does the opposite of "guix system reconfigure". > I've looked at the code in guix/scripts/system.scm, and at first blush > this seems like a straightforward task. However, I've noticed that the > switch-to-system procedure requires an operating system configuration > file to do things like get the system's activation script and generate > the new grub.cfg file. Surely a user should not have to specify the > previous system's operating system configuration file on the command > line in order to roll back the system. Is it possible to obtain these > things (e.g., the service activation script, the previous system's > grub.cfg) without requiring the user to supply the previous system's > operating system configuration file on the command line? Currently it=E2=80=99s not possible to obtain the activation script of past generations, but as I wrote above, it=E2=80=99d be doable. It=E2=80=99s not possible to obtain past grub.cfg files, but that=E2=80=99s= not a problem: we can always regenerate a new grub.cfg. What seems more difficult to me is Shepherd services. Maybe we could store in the system output (result of =E2=80=98guix system build=E2=80=99) = an sexp representation of (part of) our records: (shepherd-service (provisions (x y z)) (requirements (a b c)) (start-script "/gnu/store/=E2=80=A6-start-foo.scm") (stop-script "/gnu/store/=E2=80=A6-stop-foo.scm") =E2=80=A6) Then =E2=80=98upgrade-shepherd-services=E2=80=99 could start from this simp= lified representation instead of using the full-blown objects, and thus could work both when instantiating a new generation and when rolling back. > More generally, are people satisfied with the way system rollback is > currently implemented in GuixSD? Personally I=E2=80=99m not fully satisfied, but it=E2=80=99s true that it c= overs my main use case, which is to recover from a broken update. I had never thought about live =E2=80=9Cdowngrade=E2=80=9D of services when= rolling back, because the only times where I=E2=80=99ve wanted to roll back is right after booting (or trying to boot ;-)) into a new system generation. > Do you think that the mechanism I'm proposing is a bad idea? I'd hate > to try to implement something that nobody else thinks is needed. I think having basic delete-generations, switch-generations, and roll-back sub-commands would be definitely welcome. As a first step, switch-generations/roll-back commands could simply update the symlinks and regenerate grub.cfg. Milestone #2 would be running the previous system=E2=80=99s activation scri= pt, which installs /run/current-system and adjust the set of users and groups. Milestone #3 would be live service downgrade, as you describe. Thoughts? Ludo=E2=80=99.