···11+# Activation script {#sec-activation-script}
22+33+The activation script is a bash script called to activate the new
44+configuration which resides in a NixOS system in `$out/activate`. Since its
55+contents depend on your system configuration, the contents may differ.
66+This chapter explains how the script works in general and some common NixOS
77+snippets. Please be aware that the script is executed on every boot and system
88+switch, so tasks that can be performed in other places should be performed
99+there (for example letting a directory of a service be created by systemd using
1010+mechanisms like `StateDirectory`, `CacheDirectory`, ... or if that's not
1111+possible using `preStart` of the service).
1212+1313+Activation scripts are defined as snippets using
1414+[](#opt-system.activationScripts). They can either be a simple multiline string
1515+or an attribute set that can depend on other snippets. The builder for the
1616+activation script will take these dependencies into account and order the
1717+snippets accordingly. As a simple example:
1818+1919+```nix
2020+system.activationScripts.my-activation-script = {
2121+ deps = [ "etc" ];
2222+ # supportsDryActivation = true;
2323+ text = ''
2424+ echo "Hallo i bims"
2525+ '';
2626+};
2727+```
2828+2929+This example creates an activation script snippet that is run after the `etc`
3030+snippet. The special variable `supportsDryActivation` can be set so the snippet
3131+is also run when `nixos-rebuild dry-activate` is run. To differentiate between
3232+real and dry activation, the `$NIXOS_ACTION` environment variable can be
3333+read which is set to `dry-activate` when a dry activation is done.
3434+3535+An activation script can write to special files instructing
3636+`switch-to-configuration` to restart/reload units. The script will take these
3737+requests into account and will incorperate the unit configuration as described
3838+above. This means that the activation script will "fake" a modified unit file
3939+and `switch-to-configuration` will act accordingly. By doing so, configuration
4040+like [systemd.services.\<name\>.restartIfChanged](#opt-systemd.services) is
4141+respected. Since the activation script is run **after** services are already
4242+stopped, [systemd.services.\<name\>.stopIfChanged](#opt-systemd.services)
4343+cannot be taken into account anymore and the unit is always restarted instead
4444+of being stopped and started afterwards.
4545+4646+The files that can be written to are `/run/nixos/activation-restart-list` and
4747+`/run/nixos/activation-reload-list` with their respective counterparts for
4848+dry activation being `/run/nixos/dry-activation-restart-list` and
4949+`/run/nixos/dry-activation-reload-list`. Those files can contain
5050+newline-separated lists of unit names where duplicates are being ignored. These
5151+files are not create automatically and activation scripts must take the
5252+possiblility into account that they have to create them first.
5353+5454+## NixOS snippets {#sec-activation-script-nixos-snippets}
5555+5656+There are some snippets NixOS enables by default because disabling them would
5757+most likely break you system. This section lists a few of them and what they
5858+do:
5959+6060+- `binsh` creates `/bin/sh` which points to the runtime shell
6161+- `etc` sets up the contents of `/etc`, this includes systemd units and
6262+ excludes `/etc/passwd`, `/etc/group`, and `/etc/shadow` (which are managed by
6363+ the `users` snippet)
6464+- `hostname` sets the system's hostname in the kernel (not in `/etc`)
6565+- `modprobe` sets the path to the `modprobe` binary for module auto-loading
6666+- `nix` prepares the nix store and adds a default initial channel
6767+- `specialfs` is responsible for mounting filesystems like `/proc` and `sys`
6868+- `users` creates and removes users and groups by managing `/etc/passwd`,
6969+ `/etc/group` and `/etc/shadow`. This also creates home directories
7070+- `usrbinenv` creates `/usr/bin/env`
7171+- `var` creates some directories in `/var` that are not service-specific
7272+- `wrappers` creates setuid wrappers like `ping` and `sudo`
···11+# Unit handling {#sec-unit-handling}
22+33+To figure out what units need to be started/stopped/restarted/reloaded, the
44+script first checks the current state of the system, similar to what `systemctl
55+list-units` shows. For each of the units, the script goes through the following
66+checks:
77+88+- Is the unit file still in the new system? If not, **stop** the service unless
99+ it sets `X-StopOnRemoval` in the `[Unit]` section to `false`.
1010+1111+- Is it a `.target` unit? If so, **start** it unless it sets
1212+ `RefuseManualStart` in the `[Unit]` section to `true` or `X-OnlyManualStart`
1313+ in the `[Unit]` section to `true`. Also **stop** the unit again unless it
1414+ sets `X-StopOnReconfiguration` to `false`.
1515+1616+- Are the contents of the unit files different? They are compared by parsing
1717+ them and comparing their contents. If they are different but only
1818+ `X-Reload-Triggers` in the `[Unit]` section is changed, **reload** the unit.
1919+ The NixOS module system allows setting these triggers with the option
2020+ [systemd.services.\<name\>.reloadTriggers](#opt-systemd.services). If the
2121+ unit files differ in any way, the following actions are performed:
2222+2323+ - `.path` and `.slice` units are ignored. There is no need to restart them
2424+ since changes in their values are applied by systemd when systemd is
2525+ reloaded.
2626+2727+ - `.mount` units are **reload**ed. These mostly come from the `/etc/fstab`
2828+ parser.
2929+3030+ - `.socket` units are currently ignored. This is to be fixed at a later
3131+ point.
3232+3333+ - The rest of the units (mostly `.service` units) are then **reload**ed if
3434+ `X-ReloadIfChanged` in the `[Service]` section is set to `true` (exposed
3535+ via [systemd.services.\<name\>.reloadIfChanged](#opt-systemd.services)).
3636+3737+ - If the reload flag is not set, some more flags decide if the unit is
3838+ skipped. These flags are `X-RestartIfChanged` in the `[Service]` section
3939+ (exposed via
4040+ [systemd.services.\<name\>.restartIfChanged](#opt-systemd.services)),
4141+ `RefuseManualStop` in the `[Unit]` section, and `X-OnlyManualStart` in the
4242+ `[Unit]` section.
4343+4444+ - The rest of the behavior is decided whether the unit has `X-StopIfChanged`
4545+ in the `[Service]` section set (exposed via
4646+ [systemd.services.\<name\>.stopIfChanged](#opt-systemd.services)). This is
4747+ set to `true` by default and must be explicitly turned off if not wanted.
4848+ If the flag is enabled, the unit is **stop**ped and then **start**ed. If
4949+ not, the unit is **restart**ed. The goal of the flag is to make sure that
5050+ the new unit never runs in the old environment which is still in place
5151+ before the activation script is run.
5252+5353+ - The last thing that is taken into account is whether the unit is a service
5454+ and socket-activated. Due to a bug, this is currently only done when
5555+ `X-StopIfChanged` is set. If the unit is socket-activated, the socket is
5656+ stopped and started, and the service is stopped and to be started by socket
5757+ activation.
···11+# What happens during a system switch? {#sec-switching-systems}
22+33+Running `nixos-rebuild switch` is one of the more common tasks under NixOS.
44+This chapter explains some of the internals of this command to make it simpler
55+for new module developers to configure their units correctly and to make it
66+easier to understand what is happening and why for curious administrators.
77+88+`nixos-rebuild`, like many deployment solutions, calls `switch-to-configuration`
99+which resides in a NixOS system at `$out/bin/switch-to-configuration`. The
1010+script is called with the action that is to be performed like `switch`, `test`,
1111+`boot`. There is also the `dry-activate` action which does not really perform
1212+the actions but rather prints what it would do if you called it with `test`.
1313+This feature can be used to check what service states would be changed if the
1414+configuration was switched to.
1515+1616+If the action is `switch` or `boot`, the bootloader is updated first so the
1717+configuration will be the next one to boot. Unless `NIXOS_NO_SYNC` is set to
1818+`1`, `/nix/store` is synced to disk.
1919+2020+If the action is `switch` or `test`, the currently running system is inspected
2121+and the actions to switch to the new system are calculated. This process takes
2222+two data sources into account: `/etc/fstab` and the current systemd status.
2323+Mounts and swaps are read from `/etc/fstab` and the corresponding actions are
2424+generated. If a new mount is added, for example, the proper `.mount` unit is
2525+marked to be started. The current systemd state is inspected, the difference
2626+between the current system and the desired configuration is calculated and
2727+actions are generated to get to this state. There are a lot of nuances that can
2828+be controlled by the units which are explained here.
2929+3030+After calculating what should be done, the actions are carried out. The order
3131+of actions is always the same:
3232+- Stop units (`systemctl stop`)
3333+- Run activation script (`$out/activate`)
3434+- See if the activation script requested more units to restart
3535+- Restart systemd if needed (`systemd daemon-reexec`)
3636+- Forget about the failed state of units (`systemctl reset-failed`)
3737+- Reload systemd (`systemctl daemon-reload`)
3838+- Reload systemd user instances (`systemctl --user daemon-reload`)
3939+- Set up tmpfiles (`systemd-tmpfiles --create`)
4040+- Reload units (`systemctl reload`)
4141+- Restart units (`systemctl restart`)
4242+- Start units (`systemctl start`)
4343+- Inspect what changed during these actions and print units that failed and
4444+ that were newly started
4545+4646+Most of these actions are either self-explaining but some of them have to do
4747+with our units or the activation script. For this reason, these topics are
4848+explained in the next sections.
4949+5050+```{=docbook}
5151+<xi:include href="unit-handling.section.xml" />
5252+<xi:include href="activation-script.section.xml" />
5353+```
···11+<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-activation-script">
22+ <title>Activation script</title>
33+ <para>
44+ The activation script is a bash script called to activate the new
55+ configuration which resides in a NixOS system in
66+ <literal>$out/activate</literal>. Since its contents depend on your
77+ system configuration, the contents may differ. This chapter explains
88+ how the script works in general and some common NixOS snippets.
99+ Please be aware that the script is executed on every boot and system
1010+ switch, so tasks that can be performed in other places should be
1111+ performed there (for example letting a directory of a service be
1212+ created by systemd using mechanisms like
1313+ <literal>StateDirectory</literal>,
1414+ <literal>CacheDirectory</literal>, … or if that’s not possible using
1515+ <literal>preStart</literal> of the service).
1616+ </para>
1717+ <para>
1818+ Activation scripts are defined as snippets using
1919+ <xref linkend="opt-system.activationScripts" />. They can either be
2020+ a simple multiline string or an attribute set that can depend on
2121+ other snippets. The builder for the activation script will take
2222+ these dependencies into account and order the snippets accordingly.
2323+ As a simple example:
2424+ </para>
2525+ <programlisting language="bash">
2626+system.activationScripts.my-activation-script = {
2727+ deps = [ "etc" ];
2828+ # supportsDryActivation = true;
2929+ text = ''
3030+ echo "Hallo i bims"
3131+ '';
3232+};
3333+</programlisting>
3434+ <para>
3535+ This example creates an activation script snippet that is run after
3636+ the <literal>etc</literal> snippet. The special variable
3737+ <literal>supportsDryActivation</literal> can be set so the snippet
3838+ is also run when <literal>nixos-rebuild dry-activate</literal> is
3939+ run. To differentiate between real and dry activation, the
4040+ <literal>$NIXOS_ACTION</literal> environment variable can be read
4141+ which is set to <literal>dry-activate</literal> when a dry
4242+ activation is done.
4343+ </para>
4444+ <para>
4545+ An activation script can write to special files instructing
4646+ <literal>switch-to-configuration</literal> to restart/reload units.
4747+ The script will take these requests into account and will
4848+ incorperate the unit configuration as described above. This means
4949+ that the activation script will <quote>fake</quote> a modified unit
5050+ file and <literal>switch-to-configuration</literal> will act
5151+ accordingly. By doing so, configuration like
5252+ <link linkend="opt-systemd.services">systemd.services.<name>.restartIfChanged</link>
5353+ is respected. Since the activation script is run
5454+ <emphasis role="strong">after</emphasis> services are already
5555+ stopped,
5656+ <link linkend="opt-systemd.services">systemd.services.<name>.stopIfChanged</link>
5757+ cannot be taken into account anymore and the unit is always
5858+ restarted instead of being stopped and started afterwards.
5959+ </para>
6060+ <para>
6161+ The files that can be written to are
6262+ <literal>/run/nixos/activation-restart-list</literal> and
6363+ <literal>/run/nixos/activation-reload-list</literal> with their
6464+ respective counterparts for dry activation being
6565+ <literal>/run/nixos/dry-activation-restart-list</literal> and
6666+ <literal>/run/nixos/dry-activation-reload-list</literal>. Those
6767+ files can contain newline-separated lists of unit names where
6868+ duplicates are being ignored. These files are not create
6969+ automatically and activation scripts must take the possiblility into
7070+ account that they have to create them first.
7171+ </para>
7272+ <section xml:id="sec-activation-script-nixos-snippets">
7373+ <title>NixOS snippets</title>
7474+ <para>
7575+ There are some snippets NixOS enables by default because disabling
7676+ them would most likely break you system. This section lists a few
7777+ of them and what they do:
7878+ </para>
7979+ <itemizedlist spacing="compact">
8080+ <listitem>
8181+ <para>
8282+ <literal>binsh</literal> creates <literal>/bin/sh</literal>
8383+ which points to the runtime shell
8484+ </para>
8585+ </listitem>
8686+ <listitem>
8787+ <para>
8888+ <literal>etc</literal> sets up the contents of
8989+ <literal>/etc</literal>, this includes systemd units and
9090+ excludes <literal>/etc/passwd</literal>,
9191+ <literal>/etc/group</literal>, and
9292+ <literal>/etc/shadow</literal> (which are managed by the
9393+ <literal>users</literal> snippet)
9494+ </para>
9595+ </listitem>
9696+ <listitem>
9797+ <para>
9898+ <literal>hostname</literal> sets the system’s hostname in the
9999+ kernel (not in <literal>/etc</literal>)
100100+ </para>
101101+ </listitem>
102102+ <listitem>
103103+ <para>
104104+ <literal>modprobe</literal> sets the path to the
105105+ <literal>modprobe</literal> binary for module auto-loading
106106+ </para>
107107+ </listitem>
108108+ <listitem>
109109+ <para>
110110+ <literal>nix</literal> prepares the nix store and adds a
111111+ default initial channel
112112+ </para>
113113+ </listitem>
114114+ <listitem>
115115+ <para>
116116+ <literal>specialfs</literal> is responsible for mounting
117117+ filesystems like <literal>/proc</literal> and
118118+ <literal>sys</literal>
119119+ </para>
120120+ </listitem>
121121+ <listitem>
122122+ <para>
123123+ <literal>users</literal> creates and removes users and groups
124124+ by managing <literal>/etc/passwd</literal>,
125125+ <literal>/etc/group</literal> and
126126+ <literal>/etc/shadow</literal>. This also creates home
127127+ directories
128128+ </para>
129129+ </listitem>
130130+ <listitem>
131131+ <para>
132132+ <literal>usrbinenv</literal> creates
133133+ <literal>/usr/bin/env</literal>
134134+ </para>
135135+ </listitem>
136136+ <listitem>
137137+ <para>
138138+ <literal>var</literal> creates some directories in
139139+ <literal>/var</literal> that are not service-specific
140140+ </para>
141141+ </listitem>
142142+ <listitem>
143143+ <para>
144144+ <literal>wrappers</literal> creates setuid wrappers like
145145+ <literal>ping</literal> and <literal>sudo</literal>
146146+ </para>
147147+ </listitem>
148148+ </itemizedlist>
149149+ </section>
150150+</section>
···11+<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-unit-handling">
22+ <title>Unit handling</title>
33+ <para>
44+ To figure out what units need to be
55+ started/stopped/restarted/reloaded, the script first checks the
66+ current state of the system, similar to what
77+ <literal>systemctl list-units</literal> shows. For each of the
88+ units, the script goes through the following checks:
99+ </para>
1010+ <itemizedlist>
1111+ <listitem>
1212+ <para>
1313+ Is the unit file still in the new system? If not,
1414+ <emphasis role="strong">stop</emphasis> the service unless it
1515+ sets <literal>X-StopOnRemoval</literal> in the
1616+ <literal>[Unit]</literal> section to <literal>false</literal>.
1717+ </para>
1818+ </listitem>
1919+ <listitem>
2020+ <para>
2121+ Is it a <literal>.target</literal> unit? If so,
2222+ <emphasis role="strong">start</emphasis> it unless it sets
2323+ <literal>RefuseManualStart</literal> in the
2424+ <literal>[Unit]</literal> section to <literal>true</literal> or
2525+ <literal>X-OnlyManualStart</literal> in the
2626+ <literal>[Unit]</literal> section to <literal>true</literal>.
2727+ Also <emphasis role="strong">stop</emphasis> the unit again
2828+ unless it sets <literal>X-StopOnReconfiguration</literal> to
2929+ <literal>false</literal>.
3030+ </para>
3131+ </listitem>
3232+ <listitem>
3333+ <para>
3434+ Are the contents of the unit files different? They are compared
3535+ by parsing them and comparing their contents. If they are
3636+ different but only <literal>X-Reload-Triggers</literal> in the
3737+ <literal>[Unit]</literal> section is changed,
3838+ <emphasis role="strong">reload</emphasis> the unit. The NixOS
3939+ module system allows setting these triggers with the option
4040+ <link linkend="opt-systemd.services">systemd.services.<name>.reloadTriggers</link>.
4141+ If the unit files differ in any way, the following actions are
4242+ performed:
4343+ </para>
4444+ <itemizedlist>
4545+ <listitem>
4646+ <para>
4747+ <literal>.path</literal> and <literal>.slice</literal> units
4848+ are ignored. There is no need to restart them since changes
4949+ in their values are applied by systemd when systemd is
5050+ reloaded.
5151+ </para>
5252+ </listitem>
5353+ <listitem>
5454+ <para>
5555+ <literal>.mount</literal> units are
5656+ <emphasis role="strong">reload</emphasis>ed. These mostly
5757+ come from the <literal>/etc/fstab</literal> parser.
5858+ </para>
5959+ </listitem>
6060+ <listitem>
6161+ <para>
6262+ <literal>.socket</literal> units are currently ignored. This
6363+ is to be fixed at a later point.
6464+ </para>
6565+ </listitem>
6666+ <listitem>
6767+ <para>
6868+ The rest of the units (mostly <literal>.service</literal>
6969+ units) are then <emphasis role="strong">reload</emphasis>ed
7070+ if <literal>X-ReloadIfChanged</literal> in the
7171+ <literal>[Service]</literal> section is set to
7272+ <literal>true</literal> (exposed via
7373+ <link linkend="opt-systemd.services">systemd.services.<name>.reloadIfChanged</link>).
7474+ </para>
7575+ </listitem>
7676+ <listitem>
7777+ <para>
7878+ If the reload flag is not set, some more flags decide if the
7979+ unit is skipped. These flags are
8080+ <literal>X-RestartIfChanged</literal> in the
8181+ <literal>[Service]</literal> section (exposed via
8282+ <link linkend="opt-systemd.services">systemd.services.<name>.restartIfChanged</link>),
8383+ <literal>RefuseManualStop</literal> in the
8484+ <literal>[Unit]</literal> section, and
8585+ <literal>X-OnlyManualStart</literal> in the
8686+ <literal>[Unit]</literal> section.
8787+ </para>
8888+ </listitem>
8989+ <listitem>
9090+ <para>
9191+ The rest of the behavior is decided whether the unit has
9292+ <literal>X-StopIfChanged</literal> in the
9393+ <literal>[Service]</literal> section set (exposed via
9494+ <link linkend="opt-systemd.services">systemd.services.<name>.stopIfChanged</link>).
9595+ This is set to <literal>true</literal> by default and must
9696+ be explicitly turned off if not wanted. If the flag is
9797+ enabled, the unit is
9898+ <emphasis role="strong">stop</emphasis>ped and then
9999+ <emphasis role="strong">start</emphasis>ed. If not, the unit
100100+ is <emphasis role="strong">restart</emphasis>ed. The goal of
101101+ the flag is to make sure that the new unit never runs in the
102102+ old environment which is still in place before the
103103+ activation script is run.
104104+ </para>
105105+ </listitem>
106106+ <listitem>
107107+ <para>
108108+ The last thing that is taken into account is whether the
109109+ unit is a service and socket-activated. Due to a bug, this
110110+ is currently only done when
111111+ <literal>X-StopIfChanged</literal> is set. If the unit is
112112+ socket-activated, the socket is stopped and started, and the
113113+ service is stopped and to be started by socket activation.
114114+ </para>
115115+ </listitem>
116116+ </itemizedlist>
117117+ </listitem>
118118+ </itemizedlist>
119119+</section>
···11+<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xi="http://www.w3.org/2001/XInclude" xml:id="sec-switching-systems">
22+ <title>What happens during a system switch?</title>
33+ <para>
44+ Running <literal>nixos-rebuild switch</literal> is one of the more
55+ common tasks under NixOS. This chapter explains some of the
66+ internals of this command to make it simpler for new module
77+ developers to configure their units correctly and to make it easier
88+ to understand what is happening and why for curious administrators.
99+ </para>
1010+ <para>
1111+ <literal>nixos-rebuild</literal>, like many deployment solutions,
1212+ calls <literal>switch-to-configuration</literal> which resides in a
1313+ NixOS system at <literal>$out/bin/switch-to-configuration</literal>.
1414+ The script is called with the action that is to be performed like
1515+ <literal>switch</literal>, <literal>test</literal>,
1616+ <literal>boot</literal>. There is also the
1717+ <literal>dry-activate</literal> action which does not really perform
1818+ the actions but rather prints what it would do if you called it with
1919+ <literal>test</literal>. This feature can be used to check what
2020+ service states would be changed if the configuration was switched
2121+ to.
2222+ </para>
2323+ <para>
2424+ If the action is <literal>switch</literal> or
2525+ <literal>boot</literal>, the bootloader is updated first so the
2626+ configuration will be the next one to boot. Unless
2727+ <literal>NIXOS_NO_SYNC</literal> is set to <literal>1</literal>,
2828+ <literal>/nix/store</literal> is synced to disk.
2929+ </para>
3030+ <para>
3131+ If the action is <literal>switch</literal> or
3232+ <literal>test</literal>, the currently running system is inspected
3333+ and the actions to switch to the new system are calculated. This
3434+ process takes two data sources into account:
3535+ <literal>/etc/fstab</literal> and the current systemd status. Mounts
3636+ and swaps are read from <literal>/etc/fstab</literal> and the
3737+ corresponding actions are generated. If a new mount is added, for
3838+ example, the proper <literal>.mount</literal> unit is marked to be
3939+ started. The current systemd state is inspected, the difference
4040+ between the current system and the desired configuration is
4141+ calculated and actions are generated to get to this state. There are
4242+ a lot of nuances that can be controlled by the units which are
4343+ explained here.
4444+ </para>
4545+ <para>
4646+ After calculating what should be done, the actions are carried out.
4747+ The order of actions is always the same:
4848+ </para>
4949+ <itemizedlist spacing="compact">
5050+ <listitem>
5151+ <para>
5252+ Stop units (<literal>systemctl stop</literal>)
5353+ </para>
5454+ </listitem>
5555+ <listitem>
5656+ <para>
5757+ Run activation script (<literal>$out/activate</literal>)
5858+ </para>
5959+ </listitem>
6060+ <listitem>
6161+ <para>
6262+ See if the activation script requested more units to restart
6363+ </para>
6464+ </listitem>
6565+ <listitem>
6666+ <para>
6767+ Restart systemd if needed
6868+ (<literal>systemd daemon-reexec</literal>)
6969+ </para>
7070+ </listitem>
7171+ <listitem>
7272+ <para>
7373+ Forget about the failed state of units
7474+ (<literal>systemctl reset-failed</literal>)
7575+ </para>
7676+ </listitem>
7777+ <listitem>
7878+ <para>
7979+ Reload systemd (<literal>systemctl daemon-reload</literal>)
8080+ </para>
8181+ </listitem>
8282+ <listitem>
8383+ <para>
8484+ Reload systemd user instances
8585+ (<literal>systemctl --user daemon-reload</literal>)
8686+ </para>
8787+ </listitem>
8888+ <listitem>
8989+ <para>
9090+ Set up tmpfiles (<literal>systemd-tmpfiles --create</literal>)
9191+ </para>
9292+ </listitem>
9393+ <listitem>
9494+ <para>
9595+ Reload units (<literal>systemctl reload</literal>)
9696+ </para>
9797+ </listitem>
9898+ <listitem>
9999+ <para>
100100+ Restart units (<literal>systemctl restart</literal>)
101101+ </para>
102102+ </listitem>
103103+ <listitem>
104104+ <para>
105105+ Start units (<literal>systemctl start</literal>)
106106+ </para>
107107+ </listitem>
108108+ <listitem>
109109+ <para>
110110+ Inspect what changed during these actions and print units that
111111+ failed and that were newly started
112112+ </para>
113113+ </listitem>
114114+ </itemizedlist>
115115+ <para>
116116+ Most of these actions are either self-explaining but some of them
117117+ have to do with our units or the activation script. For this reason,
118118+ these topics are explained in the next sections.
119119+ </para>
120120+ <xi:include href="unit-handling.section.xml" />
121121+ <xi:include href="activation-script.section.xml" />
122122+</chapter>
···4242 upgrade notes</link>.
4343 </para>
4444 </listitem>
4545+ <listitem>
4646+ <para>
4747+ systemd services can now set
4848+ <link linkend="opt-systemd.services">systemd.services.<name>.reloadTriggers</link>
4949+ instead of <literal>reloadIfChanged</literal> for a more
5050+ granular distinction between reloads and restarts.
5151+ </para>
5252+ </listitem>
4553 </itemizedlist>
4654 </section>
4755 <section xml:id="sec-release-22.05-new-services">
···550558 honors <literal>restartIfChanged</literal> and
551559 <literal>reloadIfChanged</literal> of the units.
552560 </para>
561561+ <itemizedlist spacing="compact">
562562+ <listitem>
563563+ <para>
564564+ Preferring to reload instead of restarting can still
565565+ be achieved using
566566+ <literal>/run/nixos/activation-reload-list</literal>.
567567+ </para>
568568+ </listitem>
569569+ </itemizedlist>
553570 </listitem>
554571 <listitem>
555572 <para>
+3
nixos/doc/manual/release-notes/rl-2205.section.md
···1717 Migrations may take a while, see the [changelog](https://docs.mattermost.com/install/self-managed-changelog.html#release-v6-3-extended-support-release)
1818 and [important upgrade notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html).
19192020+- systemd services can now set [systemd.services.\<name\>.reloadTriggers](#opt-systemd.services) instead of `reloadIfChanged` for a more granular distinction between reloads and restarts.
2121+2022## New Services {#sec-release-22.05-new-services}
21232224- [aesmd](https://github.com/intel/linux-sgx#install-the-intelr-sgx-psw), the Intel SGX Architectural Enclave Service Manager. Available as [services.aesmd](#opt-services.aesmd.enable).
···179181180182- `switch-to-configuration` (the script that is run when running `nixos-rebuild switch` for example) has been reworked
181183 * The interface that allows activation scripts to restart units has been streamlined. Restarting and reloading is now done by a single file `/run/nixos/activation-restart-list` that honors `restartIfChanged` and `reloadIfChanged` of the units.
184184+ * Preferring to reload instead of restarting can still be achieved using `/run/nixos/activation-reload-list`.
182185 * The script now uses a proper ini-file parser to parse systemd units. Some values are now only searched in one section instead of in the entire unit. This is only relevant for units that don't use the NixOS systemd moule.
183186 * `RefuseManualStop`, `X-OnlyManualStart`, `X-StopOnRemoval`, `X-StopOnReconfiguration` are only searched in the `[Unit]` section
184187 * `X-ReloadIfChanged`, `X-RestartIfChanged`, `X-StopIfChanged` are only searched in the `[Service]` section
+16
nixos/lib/systemd-unit-options.nix
···201201 '';
202202 };
203203204204+ reloadTriggers = mkOption {
205205+ default = [];
206206+ type = types.listOf unitOption;
207207+ description = ''
208208+ An arbitrary list of items such as derivations. If any item
209209+ in the list changes between reconfigurations, the service will
210210+ be reloaded. If anything but a reload trigger changes in the
211211+ unit file, the unit will be restarted instead.
212212+ '';
213213+ };
214214+204215 onFailure = mkOption {
205216 default = [];
206217 type = types.listOf unitNameType;
···338349 configuration switch if its definition has changed. If
339350 enabled, the value of <option>restartIfChanged</option> is
340351 ignored.
352352+353353+ This option should not be used anymore in favor of
354354+ <option>reloadTriggers</option> which allows more granular
355355+ control of when a service is reloaded and when a service
356356+ is restarted.
341357 '';
342358 };
343359
···2233use strict;
44use warnings;
55+use Array::Compare;
56use Config::IniFiles;
67use File::Path qw(make_path);
78use File::Basename;
88-use File::Slurp;
99+use File::Slurp qw(read_file write_file edit_file);
910use Net::DBus;
1011use Sys::Syslog qw(:standard :macros);
1112use Cwd 'abs_path';
···2021my $reloadListFile = "/run/nixos/reload-list";
21222223# Parse restart/reload requests by the activation script.
2323-# Activation scripts may write newline-separated units to this
2424+# Activation scripts may write newline-separated units to the restart
2425# file and switch-to-configuration will handle them. While
2526# `stopIfChanged = true` is ignored, switch-to-configuration will
2627# handle `restartIfChanged = false` and `reloadIfChanged = true`.
2828+# This is the same as specifying a restart trigger in the NixOS module.
2929+#
3030+# The reload file asks the script to reload a unit. This is the same as
3131+# specifying a reload trigger in the NixOS module and can be ignored if
3232+# the unit is restarted in this activation.
2733my $restartByActivationFile = "/run/nixos/activation-restart-list";
3434+my $reloadByActivationFile = "/run/nixos/activation-reload-list";
2835my $dryRestartByActivationFile = "/run/nixos/dry-activation-restart-list";
3636+my $dryReloadByActivationFile = "/run/nixos/dry-activation-reload-list";
29373038make_path("/run/nixos", { mode => oct(755) });
3139···131139132140 # Copy over all sections
133141 foreach my $sectionName (keys %fileContents) {
142142+ if ($sectionName eq "Install") {
143143+ # Skip the [Install] section because it has no relevant keys for us
144144+ next;
145145+ }
134146 # Copy over all keys
135147 foreach my $iniKey (keys %{$fileContents{$sectionName}}) {
136148 # Ensure the value is an array so it's easier to work with
···192204 write_file($fn, { append => 1 }, "$unit\n") if $action ne "dry-activate";
193205}
194206195195-# As a fingerprint for determining whether a unit has changed, we use
196196-# its absolute path. If it has an override file, we append *its*
197197-# absolute path as well.
198198-sub fingerprintUnit {
199199- my ($s) = @_;
200200- return abs_path($s) . (-f "${s}.d/overrides.conf" ? " " . abs_path "${s}.d/overrides.conf" : "");
207207+# The opposite of recordUnit, removes a unit name from a file
208208+sub unrecord_unit {
209209+ my ($fn, $unit) = @_;
210210+ edit_file { s/^$unit\n//msx } $fn if $action ne "dry-activate";
211211+}
212212+213213+# Compare the contents of two unit files and return whether the unit
214214+# needs to be restarted or reloaded. If the units differ, the service
215215+# is restarted unless the only difference is `X-Reload-Triggers` in the
216216+# `Unit` section. If this is the only modification, the unit is reloaded
217217+# instead of restarted.
218218+# Returns:
219219+# - 0 if the units are equal
220220+# - 1 if the units are different and a restart action is required
221221+# - 2 if the units are different and a reload action is required
222222+sub compare_units {
223223+ my ($old_unit, $new_unit) = @_;
224224+ my $comp = Array::Compare->new;
225225+ my $ret = 0;
226226+227227+ # Comparison hash for the sections
228228+ my %section_cmp = map { $_ => 1 } keys %{$new_unit};
229229+ # Iterate over the sections
230230+ foreach my $section_name (keys %{$old_unit}) {
231231+ # Missing section in the new unit?
232232+ if (not exists $section_cmp{$section_name}) {
233233+ if ($section_name eq 'Unit' and %{$old_unit->{'Unit'}} == 1 and defined(%{$old_unit->{'Unit'}}{'X-Reload-Triggers'})) {
234234+ # If a new [Unit] section was removed that only contained X-Reload-Triggers,
235235+ # do nothing.
236236+ next;
237237+ } else {
238238+ return 1;
239239+ }
240240+ }
241241+ delete $section_cmp{$section_name};
242242+ # Comparison hash for the section contents
243243+ my %ini_cmp = map { $_ => 1 } keys %{$new_unit->{$section_name}};
244244+ # Iterate over the keys of the section
245245+ foreach my $ini_key (keys %{$old_unit->{$section_name}}) {
246246+ delete $ini_cmp{$ini_key};
247247+ my @old_value = @{$old_unit->{$section_name}{$ini_key}};
248248+ # If the key is missing in the new unit, they are different...
249249+ if (not $new_unit->{$section_name}{$ini_key}) {
250250+ # ... unless the key that is now missing was the reload trigger
251251+ if ($section_name eq 'Unit' and $ini_key eq 'X-Reload-Triggers') {
252252+ next;
253253+ }
254254+ return 1;
255255+ }
256256+ my @new_value = @{$new_unit->{$section_name}{$ini_key}};
257257+ # If the contents are different, the units are different
258258+ if (not $comp->compare(\@old_value, \@new_value)) {
259259+ # Check if only the reload triggers changed
260260+ if ($section_name eq 'Unit' and $ini_key eq 'X-Reload-Triggers') {
261261+ $ret = 2;
262262+ } else {
263263+ return 1;
264264+ }
265265+ }
266266+ }
267267+ # A key was introduced that was missing in the old unit
268268+ if (%ini_cmp) {
269269+ if ($section_name eq 'Unit' and %ini_cmp == 1 and defined($ini_cmp{'X-Reload-Triggers'})) {
270270+ # If the newly introduced key was the reload triggers, reload the unit
271271+ $ret = 2;
272272+ } else {
273273+ return 1;
274274+ }
275275+ };
276276+ }
277277+ # A section was introduced that was missing in the old unit
278278+ if (%section_cmp) {
279279+ if (%section_cmp == 1 and defined($section_cmp{'Unit'}) and %{$new_unit->{'Unit'}} == 1 and defined(%{$new_unit->{'Unit'}}{'X-Reload-Triggers'})) {
280280+ # If a new [Unit] section was introduced that only contains X-Reload-Triggers,
281281+ # reload instead of restarting
282282+ $ret = 2;
283283+ } else {
284284+ return 1;
285285+ }
286286+ }
287287+288288+ return $ret;
201289}
202290203291sub handleModifiedUnit {
204204- my ($unit, $baseName, $newUnitFile, $activePrev, $unitsToStop, $unitsToStart, $unitsToReload, $unitsToRestart, $unitsToSkip) = @_;
292292+ my ($unit, $baseName, $newUnitFile, $newUnitInfo, $activePrev, $unitsToStop, $unitsToStart, $unitsToReload, $unitsToRestart, $unitsToSkip) = @_;
205293206294 if ($unit eq "sysinit.target" || $unit eq "basic.target" || $unit eq "multi-user.target" || $unit eq "graphical.target" || $unit =~ /\.path$/ || $unit =~ /\.slice$/) {
207295 # Do nothing. These cannot be restarted directly.
···219307 # Revert of the attempt: https://github.com/NixOS/nixpkgs/pull/147609
220308 # More details: https://github.com/NixOS/nixpkgs/issues/74899#issuecomment-981142430
221309 } else {
222222- my %unitInfo = parseUnit($newUnitFile);
223223- if (parseSystemdBool(\%unitInfo, "Service", "X-ReloadIfChanged", 0)) {
310310+ my %unitInfo = $newUnitInfo ? %{$newUnitInfo} : parseUnit($newUnitFile);
311311+ if (parseSystemdBool(\%unitInfo, "Service", "X-ReloadIfChanged", 0) and not $unitsToRestart->{$unit} and not $unitsToStop->{$unit}) {
224312 $unitsToReload->{$unit} = 1;
225313 recordUnit($reloadListFile, $unit);
226314 }
···234322 # stopped and started.
235323 $unitsToRestart->{$unit} = 1;
236324 recordUnit($restartListFile, $unit);
325325+ # Remove from units to reload so we don't restart and reload
326326+ if ($unitsToReload->{$unit}) {
327327+ delete $unitsToReload->{$unit};
328328+ unrecord_unit($reloadListFile, $unit);
329329+ }
237330 } else {
238331 # If this unit is socket-activated, then stop the
239332 # socket unit(s) as well, and restart the
···253346 $unitsToStart->{$socket} = 1;
254347 recordUnit($startListFile, $socket);
255348 $socketActivated = 1;
349349+ }
350350+ # Remove from units to reload so we don't restart and reload
351351+ if ($unitsToReload->{$unit}) {
352352+ delete $unitsToReload->{$unit};
353353+ unrecord_unit($reloadListFile, $unit);
256354 }
257355 }
258356 }
···268366 }
269367270368 $unitsToStop->{$unit} = 1;
369369+ # Remove from units to reload so we don't restart and reload
370370+ if ($unitsToReload->{$unit}) {
371371+ delete $unitsToReload->{$unit};
372372+ unrecord_unit($reloadListFile, $unit);
373373+ }
271374 }
272375 }
273376 }
···344447 }
345448 }
346449347347- elsif (fingerprintUnit($prevUnitFile) ne fingerprintUnit($newUnitFile)) {
348348- handleModifiedUnit($unit, $baseName, $newUnitFile, $activePrev, \%unitsToStop, \%unitsToStart, \%unitsToReload, \%unitsToRestart, \%unitsToSkip);
450450+ else {
451451+ my %old_unit_info = parseUnit($prevUnitFile);
452452+ my %new_unit_info = parseUnit($newUnitFile);
453453+ my $diff = compare_units(\%old_unit_info, \%new_unit_info);
454454+ if ($diff eq 1) {
455455+ handleModifiedUnit($unit, $baseName, $newUnitFile, \%new_unit_info, $activePrev, \%unitsToStop, \%unitsToStart, \%unitsToReload, \%unitsToRestart, \%unitsToSkip);
456456+ } elsif ($diff eq 2 and not $unitsToRestart{$unit}) {
457457+ $unitsToReload{$unit} = 1;
458458+ recordUnit($reloadListFile, $unit);
459459+ }
349460 }
350461 }
351462}
···359470 chomp $escaped;
360471 close $cmd or die;
361472 return $escaped;
362362-}
363363-364364-sub unique {
365365- my %seen;
366366- my @res;
367367- foreach my $name (@_) {
368368- next if $seen{$name};
369369- $seen{$name} = 1;
370370- push @res, $name;
371371- }
372372- return @res;
373473}
374474375475# Compare the previous and new fstab to figure out which filesystems
···407507 # "systemctl stop" here because systemd has lots of alias
408508 # units that prevent a stop from actually calling
409509 # "swapoff".
410410- print STDERR "stopping swap device: $device\n";
411411- system("@utillinux@/sbin/swapoff", $device);
510510+ if ($action ne "dry-activate") {
511511+ print STDERR "would stop swap device: $device\n";
512512+ } else {
513513+ print STDERR "stopping swap device: $device\n";
514514+ system("@utillinux@/sbin/swapoff", $device);
515515+ }
412516 }
413517 # FIXME: update swap options (i.e. its priority).
414518}
···469573 next;
470574 }
471575472472- handleModifiedUnit($unit, $baseName, $newUnitFile, $activePrev, \%unitsToRestart, \%unitsToRestart, \%unitsToReload, \%unitsToRestart, \%unitsToSkip);
576576+ handleModifiedUnit($unit, $baseName, $newUnitFile, undef, $activePrev, \%unitsToRestart, \%unitsToRestart, \%unitsToReload, \%unitsToRestart, \%unitsToSkip);
473577 }
474578 unlink($dryRestartByActivationFile);
475579580580+ foreach (split('\n', read_file($dryReloadByActivationFile, err_mode => 'quiet') // "")) {
581581+ my $unit = $_;
582582+583583+ if (defined($activePrev->{$unit}) and not $unitsToRestart{$unit} and not $unitsToStop{$unit}) {
584584+ $unitsToReload{$unit} = 1;
585585+ recordUnit($reloadListFile, $unit);
586586+ }
587587+ }
588588+ unlink($dryReloadByActivationFile);
589589+476590 print STDERR "would restart systemd\n" if $restartSystemd;
477591 print STDERR "would reload the following units: ", join(", ", sort(keys %unitsToReload)), "\n"
478592 if scalar(keys %unitsToReload) > 0;
···525639 next;
526640 }
527641528528- handleModifiedUnit($unit, $baseName, $newUnitFile, $activePrev, \%unitsToRestart, \%unitsToRestart, \%unitsToReload, \%unitsToRestart, \%unitsToSkip);
642642+ handleModifiedUnit($unit, $baseName, $newUnitFile, undef, $activePrev, \%unitsToRestart, \%unitsToRestart, \%unitsToReload, \%unitsToRestart, \%unitsToSkip);
529643}
530644# We can remove the file now because it has been propagated to the other restart/reload files
531645unlink($restartByActivationFile);
646646+647647+foreach (split('\n', read_file($reloadByActivationFile, err_mode => 'quiet') // "")) {
648648+ my $unit = $_;
649649+650650+ if (defined($activePrev->{$unit}) and not $unitsToRestart{$unit} and not $unitsToStop{$unit}) {
651651+ $unitsToReload{$unit} = 1;
652652+ recordUnit($reloadListFile, $unit);
653653+ }
654654+}
655655+# We can remove the file now because it has been propagated to the other reload file
656656+unlink($reloadByActivationFile);
532657533658# Restart systemd if necessary. Note that this is done using the
534659# current version of systemd, just in case the new one has trouble
···243243 { Requisite = toString config.requisite; }
244244 // optionalAttrs (config.restartTriggers != [])
245245 { X-Restart-Triggers = toString config.restartTriggers; }
246246+ // optionalAttrs (config.reloadTriggers != [])
247247+ { X-Reload-Triggers = toString config.reloadTriggers; }
246248 // optionalAttrs (config.description != "") {
247249 Description = config.description; }
248250 // optionalAttrs (config.documentation != []) {
···916918 )
917919 (optional hasDeprecated
918920 "Service '${name}.service' uses the attribute 'StartLimitInterval' in the Service section, which is deprecated. See https://github.com/NixOS/nixpkgs/issues/45786."
921921+ )
922922+ (optional (service.reloadIfChanged && service.reloadTriggers != [])
923923+ "Service '${name}.service' has both 'reloadIfChanged' and 'reloadTriggers' set. This is probably not what you want, because 'reloadTriggers' behave the same whay as 'restartTriggers' if 'reloadIfChanged' is set."
919924 )
920925 ]
921926 )
+241-6
nixos/tests/switch-test.nix
···1818 Type = "oneshot";
1919 RemainAfterExit = true;
2020 ExecStart = "${pkgs.coreutils}/bin/true";
2121+ ExecReload = "${pkgs.coreutils}/bin/true";
2122 };
2223 };
2324 };
···7071 };
7172 };
72737474+ simpleServiceWithExtraSection.configuration = {
7575+ imports = [ simpleServiceNostop.configuration ];
7676+ systemd.packages = [ (pkgs.writeTextFile {
7777+ name = "systemd-extra-section";
7878+ destination = "/etc/systemd/system/test.service";
7979+ text = ''
8080+ [X-Test]
8181+ X-Test-Value=a
8282+ '';
8383+ }) ];
8484+ };
8585+8686+ simpleServiceWithExtraSectionOtherName.configuration = {
8787+ imports = [ simpleServiceNostop.configuration ];
8888+ systemd.packages = [ (pkgs.writeTextFile {
8989+ name = "systemd-extra-section";
9090+ destination = "/etc/systemd/system/test.service";
9191+ text = ''
9292+ [X-Test2]
9393+ X-Test-Value=a
9494+ '';
9595+ }) ];
9696+ };
9797+9898+ simpleServiceWithInstallSection.configuration = {
9999+ imports = [ simpleServiceNostop.configuration ];
100100+ systemd.packages = [ (pkgs.writeTextFile {
101101+ name = "systemd-extra-section";
102102+ destination = "/etc/systemd/system/test.service";
103103+ text = ''
104104+ [Install]
105105+ WantedBy=multi-user.target
106106+ '';
107107+ }) ];
108108+ };
109109+110110+ simpleServiceWithExtraKey.configuration = {
111111+ imports = [ simpleServiceNostop.configuration ];
112112+ systemd.services.test.serviceConfig."X-Test" = "test";
113113+ };
114114+115115+ simpleServiceWithExtraKeyOtherValue.configuration = {
116116+ imports = [ simpleServiceNostop.configuration ];
117117+ systemd.services.test.serviceConfig."X-Test" = "test2";
118118+ };
119119+120120+ simpleServiceWithExtraKeyOtherName.configuration = {
121121+ imports = [ simpleServiceNostop.configuration ];
122122+ systemd.services.test.serviceConfig."X-Test2" = "test";
123123+ };
124124+125125+ simpleServiceReloadTrigger.configuration = {
126126+ imports = [ simpleServiceNostop.configuration ];
127127+ systemd.services.test.reloadTriggers = [ "/dev/null" ];
128128+ };
129129+130130+ simpleServiceReloadTriggerModified.configuration = {
131131+ imports = [ simpleServiceNostop.configuration ];
132132+ systemd.services.test.reloadTriggers = [ "/dev/zero" ];
133133+ };
134134+135135+ simpleServiceReloadTriggerModifiedAndSomethingElse.configuration = {
136136+ imports = [ simpleServiceNostop.configuration ];
137137+ systemd.services.test = {
138138+ reloadTriggers = [ "/dev/zero" ];
139139+ serviceConfig."X-Test" = "test";
140140+ };
141141+ };
142142+143143+ simpleServiceReloadTriggerModifiedSomethingElse.configuration = {
144144+ imports = [ simpleServiceNostop.configuration ];
145145+ systemd.services.test.serviceConfig."X-Test" = "test";
146146+ };
147147+73148 restart-and-reload-by-activation-script.configuration = {
74149 systemd.services = rec {
75150 simple-service = {
···93168 no-restart-service = simple-service // {
94169 restartIfChanged = false;
95170 };
171171+172172+ reload-triggers = simple-service // {
173173+ wantedBy = [ "multi-user.target" ];
174174+ };
175175+176176+ reload-triggers-and-restart-by-as = simple-service;
177177+178178+ reload-triggers-and-restart = simple-service // {
179179+ stopIfChanged = false; # easier to check for this
180180+ wantedBy = [ "multi-user.target" ];
181181+ };
96182 };
9718398184 system.activationScripts.restart-and-reload-test = {
···101187 text = ''
102188 if [ "$NIXOS_ACTION" = dry-activate ]; then
103189 f=/run/nixos/dry-activation-restart-list
190190+ g=/run/nixos/dry-activation-reload-list
104191 else
105192 f=/run/nixos/activation-restart-list
193193+ g=/run/nixos/activation-reload-list
106194 fi
107195 cat <<EOF >> "$f"
108196 simple-service.service
109197 simple-restart-service.service
110198 simple-reload-service.service
111199 no-restart-service.service
200200+ reload-triggers-and-restart-by-as.service
201201+ EOF
202202+203203+ cat <<EOF >> "$g"
204204+ reload-triggers.service
205205+ reload-triggers-and-restart-by-as.service
206206+ reload-triggers-and-restart.service
112207 EOF
113208 '';
114209 };
210210+ };
211211+212212+ restart-and-reload-by-activation-script-modified.configuration = {
213213+ imports = [ restart-and-reload-by-activation-script.configuration ];
214214+ systemd.services.reload-triggers-and-restart.serviceConfig.X-Modified = "test";
115215 };
116216117217 mount.configuration = {
···241341 raise Exception(f"Unexpected string '{needle}' was found")
242342243343344344+ machine.wait_for_unit("multi-user.target")
345345+244346 machine.succeed(
245347 "${stderrRunner} ${originalSystem}/bin/switch-to-configuration test"
246348 )
···379481 assert_contains(out, "Main PID:") # output of systemctl
380482 assert_lacks(out, "as well:")
381483484484+ with subtest("unit file parser"):
485485+ # Switch to a well-known state
486486+ switch_to_specialisation("${machine}", "simpleServiceNostop")
487487+488488+ # Add a section
489489+ out = switch_to_specialisation("${machine}", "simpleServiceWithExtraSection")
490490+ assert_lacks(out, "stopping the following units:")
491491+ assert_lacks(out, "NOT restarting the following changed units:")
492492+ assert_lacks(out, "reloading the following units:")
493493+ assert_contains(out, "\nrestarting the following units: test.service\n")
494494+ assert_lacks(out, "\nstarting the following units:")
495495+ assert_lacks(out, "the following new units were started:")
496496+ assert_lacks(out, "as well:")
497497+498498+ # Rename it
499499+ out = switch_to_specialisation("${machine}", "simpleServiceWithExtraSectionOtherName")
500500+ assert_lacks(out, "stopping the following units:")
501501+ assert_lacks(out, "NOT restarting the following changed units:")
502502+ assert_lacks(out, "reloading the following units:")
503503+ assert_contains(out, "\nrestarting the following units: test.service\n")
504504+ assert_lacks(out, "\nstarting the following units:")
505505+ assert_lacks(out, "the following new units were started:")
506506+ assert_lacks(out, "as well:")
507507+508508+ # Remove it
509509+ out = switch_to_specialisation("${machine}", "simpleServiceNostop")
510510+ assert_lacks(out, "stopping the following units:")
511511+ assert_lacks(out, "NOT restarting the following changed units:")
512512+ assert_lacks(out, "reloading the following units:")
513513+ assert_contains(out, "\nrestarting the following units: test.service\n")
514514+ assert_lacks(out, "\nstarting the following units:")
515515+ assert_lacks(out, "the following new units were started:")
516516+ assert_lacks(out, "as well:")
517517+518518+ # [Install] section is ignored
519519+ out = switch_to_specialisation("${machine}", "simpleServiceWithInstallSection")
520520+ assert_lacks(out, "stopping the following units:")
521521+ assert_lacks(out, "NOT restarting the following changed units:")
522522+ assert_lacks(out, "reloading the following units:")
523523+ assert_lacks(out, "\nrestarting the following units:")
524524+ assert_lacks(out, "\nstarting the following units:")
525525+ assert_lacks(out, "the following new units were started:")
526526+ assert_lacks(out, "as well:")
527527+528528+ # Add a key
529529+ out = switch_to_specialisation("${machine}", "simpleServiceWithExtraKey")
530530+ assert_lacks(out, "stopping the following units:")
531531+ assert_lacks(out, "NOT restarting the following changed units:")
532532+ assert_lacks(out, "reloading the following units:")
533533+ assert_contains(out, "\nrestarting the following units: test.service\n")
534534+ assert_lacks(out, "\nstarting the following units:")
535535+ assert_lacks(out, "the following new units were started:")
536536+ assert_lacks(out, "as well:")
537537+538538+ # Change its value
539539+ out = switch_to_specialisation("${machine}", "simpleServiceWithExtraKeyOtherValue")
540540+ assert_lacks(out, "stopping the following units:")
541541+ assert_lacks(out, "NOT restarting the following changed units:")
542542+ assert_lacks(out, "reloading the following units:")
543543+ assert_contains(out, "\nrestarting the following units: test.service\n")
544544+ assert_lacks(out, "\nstarting the following units:")
545545+ assert_lacks(out, "the following new units were started:")
546546+ assert_lacks(out, "as well:")
547547+548548+ # Rename it
549549+ out = switch_to_specialisation("${machine}", "simpleServiceWithExtraKeyOtherName")
550550+ assert_lacks(out, "stopping the following units:")
551551+ assert_lacks(out, "NOT restarting the following changed units:")
552552+ assert_lacks(out, "reloading the following units:")
553553+ assert_contains(out, "\nrestarting the following units: test.service\n")
554554+ assert_lacks(out, "\nstarting the following units:")
555555+ assert_lacks(out, "the following new units were started:")
556556+ assert_lacks(out, "as well:")
557557+558558+ # Remove it
559559+ out = switch_to_specialisation("${machine}", "simpleServiceNostop")
560560+ assert_lacks(out, "stopping the following units:")
561561+ assert_lacks(out, "NOT restarting the following changed units:")
562562+ assert_lacks(out, "reloading the following units:")
563563+ assert_contains(out, "\nrestarting the following units: test.service\n")
564564+ assert_lacks(out, "\nstarting the following units:")
565565+ assert_lacks(out, "the following new units were started:")
566566+ assert_lacks(out, "as well:")
567567+568568+ # Add a reload trigger
569569+ out = switch_to_specialisation("${machine}", "simpleServiceReloadTrigger")
570570+ assert_lacks(out, "stopping the following units:")
571571+ assert_lacks(out, "NOT restarting the following changed units:")
572572+ assert_contains(out, "reloading the following units: test.service\n")
573573+ assert_lacks(out, "\nrestarting the following units:")
574574+ assert_lacks(out, "\nstarting the following units:")
575575+ assert_lacks(out, "the following new units were started:")
576576+ assert_lacks(out, "as well:")
577577+578578+ # Modify the reload trigger
579579+ out = switch_to_specialisation("${machine}", "simpleServiceReloadTriggerModified")
580580+ assert_lacks(out, "stopping the following units:")
581581+ assert_lacks(out, "NOT restarting the following changed units:")
582582+ assert_contains(out, "reloading the following units: test.service\n")
583583+ assert_lacks(out, "\nrestarting the following units:")
584584+ assert_lacks(out, "\nstarting the following units:")
585585+ assert_lacks(out, "the following new units were started:")
586586+ assert_lacks(out, "as well:")
587587+588588+ # Modify the reload trigger and something else
589589+ out = switch_to_specialisation("${machine}", "simpleServiceReloadTriggerModifiedAndSomethingElse")
590590+ assert_lacks(out, "stopping the following units:")
591591+ assert_lacks(out, "NOT restarting the following changed units:")
592592+ assert_lacks(out, "reloading the following units:")
593593+ assert_contains(out, "\nrestarting the following units: test.service\n")
594594+ assert_lacks(out, "\nstarting the following units:")
595595+ assert_lacks(out, "the following new units were started:")
596596+ assert_lacks(out, "as well:")
597597+598598+ # Remove the reload trigger
599599+ out = switch_to_specialisation("${machine}", "simpleServiceReloadTriggerModifiedSomethingElse")
600600+ assert_lacks(out, "stopping the following units:")
601601+ assert_lacks(out, "NOT restarting the following changed units:")
602602+ assert_lacks(out, "reloading the following units:")
603603+ assert_lacks(out, "\nrestarting the following units:")
604604+ assert_lacks(out, "\nstarting the following units:")
605605+ assert_lacks(out, "the following new units were started:")
606606+ assert_lacks(out, "as well:")
607607+382608 with subtest("restart and reload by activation script"):
383609 switch_to_specialisation("${machine}", "simpleServiceNorestart")
384610 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script")
···386612 assert_lacks(out, "NOT restarting the following changed units:")
387613 assert_lacks(out, "reloading the following units:")
388614 assert_lacks(out, "restarting the following units:")
389389- assert_contains(out, "\nstarting the following units: no-restart-service.service, simple-reload-service.service, simple-restart-service.service, simple-service.service\n")
615615+ assert_contains(out, "\nstarting the following units: no-restart-service.service, reload-triggers-and-restart-by-as.service, simple-reload-service.service, simple-restart-service.service, simple-service.service\n")
390616 assert_lacks(out, "as well:")
391617 # Switch to the same system where the example services get restarted
392392- # by the activation script
618618+ # and reloaded by the activation script
393619 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script")
394620 assert_lacks(out, "stopping the following units:")
395621 assert_lacks(out, "NOT restarting the following changed units:")
396396- assert_contains(out, "reloading the following units: simple-reload-service.service\n")
397397- assert_contains(out, "restarting the following units: simple-restart-service.service, simple-service.service\n")
622622+ assert_contains(out, "reloading the following units: reload-triggers-and-restart.service, reload-triggers.service, simple-reload-service.service\n")
623623+ assert_contains(out, "restarting the following units: reload-triggers-and-restart-by-as.service, simple-restart-service.service, simple-service.service\n")
624624+ assert_lacks(out, "\nstarting the following units:")
625625+ assert_lacks(out, "as well:")
626626+ # Switch to the same system and see if the service gets restarted when it's modified
627627+ # while the fact that it's supposed to be reloaded by the activation script is ignored.
628628+ out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script-modified")
629629+ assert_lacks(out, "stopping the following units:")
630630+ assert_lacks(out, "NOT restarting the following changed units:")
631631+ assert_contains(out, "reloading the following units: reload-triggers.service, simple-reload-service.service\n")
632632+ assert_contains(out, "restarting the following units: reload-triggers-and-restart-by-as.service, reload-triggers-and-restart.service, simple-restart-service.service, simple-service.service\n")
398633 assert_lacks(out, "\nstarting the following units:")
399634 assert_lacks(out, "as well:")
400635 # The same, but in dry mode
401636 out = switch_to_specialisation("${machine}", "restart-and-reload-by-activation-script", action="dry-activate")
402637 assert_lacks(out, "would stop the following units:")
403638 assert_lacks(out, "would NOT stop the following changed units:")
404404- assert_contains(out, "would reload the following units: simple-reload-service.service\n")
405405- assert_contains(out, "would restart the following units: simple-restart-service.service, simple-service.service\n")
639639+ assert_contains(out, "would reload the following units: reload-triggers.service, simple-reload-service.service\n")
640640+ assert_contains(out, "would restart the following units: reload-triggers-and-restart-by-as.service, reload-triggers-and-restart.service, simple-restart-service.service, simple-service.service\n")
406641 assert_lacks(out, "\nwould start the following units:")
407642 assert_lacks(out, "as well:")
408643
···8888 ];
8989 # Slow tests
9090 disabledTests = [
9191- "test_clifford" # fails on cvxpy >= 1.1.15. https://github.com/Qiskit/qiskit-aer/pull/1318. Remove in future.
9291 "test_snapshot" # TODO: these ~30 tests fail on setup due to pytest fixture issues?
9392 "test_initialize_2" # TODO: simulations appear incorrect, off by >10%.
9393+ # These tests fail on cvxpy >= 1.1.15
9494+ "test_clifford"
9595+ "test_approx_random"
94969597 # these fail for some builds. Haven't been able to reproduce error locally.
9698 "test_kraus_gate_noise"
···9797 pytest_xdist = pytest-xdist; # added 2021-01-04
9898 python_simple_hipchat = python-simple-hipchat; # added 2021-07-21
9999 qasm2image = throw "qasm2image is no longer maintained (since November 2018), and is not compatible with the latest pythonPackages.qiskit versions."; # added 2020-12-09
100100+ qiskit-aqua = throw "qiskit-aqua has been removed due to deprecation, with its functionality moved to different qiskit packages";
100101 rdflib-jsonld = throw "rdflib-jsonld is not compatible with rdflib 6"; # added 2021-11-05
101102 repeated_test = throw "repeated_test is no longer maintained"; # added 2022-01-11
102103 requests_toolbelt = requests-toolbelt; # added 2017-09-26