···4647By default, some units are filtered from the outputs to make it less spammy.
48This can be disabled for development or testing by setting the environment variable
49-`STC_DISPLAY_ALL_UNITS=1`
005051Most of these actions are either self-explaining but some of them have to do
52with our units or the activation script. For this reason, these topics are
···4647By default, some units are filtered from the outputs to make it less spammy.
48This can be disabled for development or testing by setting the environment variable
49+`STC_DISPLAY_ALL_UNITS=1`.
50+51+More detailed output can be displayed by setting `STC_DEBUG=1`.
5253Most of these actions are either self-explaining but some of them have to do
54with our units or the activation script. For this reason, these topics are
···123// Allow for this switch-to-configuration to remain consistent with the perl implementation.
124// Perl's "die" uses errno to set the exit code: https://perldoc.perl.org/perlvar#%24%21
125fn die() -> ! {
126- std::process::exit(std::io::Error::last_os_error().raw_os_error().unwrap_or(1));
0000000127}
128129fn parse_os_release() -> Result<HashMap<String, String>> {
···259 &unit_file_content,
260 ParseOption {
261 enabled_quote: true,
00262 // Allow for escaped characters that won't get interpreted by the INI parser. These
263 // often show up in systemd unit files device/mount/swap unit names (e.g. dev-disk-by\x2dlabel-root.device).
264 enabled_escape: false,
···907 submitted_jobs: &Rc<RefCell<HashMap<dbus::Path<'static>, Job>>>,
908) {
909 while !submitted_jobs.borrow().is_empty() {
0000910 _ = conn.process(Duration::from_millis(500));
911 }
912}
···959 .restart_unit("nixos-activation.service", "replace")
960 .context("Failed to restart nixos-activation.service")?;
9610962 while !*nixos_activation_done.borrow() {
963 _ = dbus_conn
964 .process(Duration::from_secs(500))
···987988/// Performs switch-to-configuration functionality for the entire system
989fn do_system_switch(action: Action) -> anyhow::Result<()> {
00990 let out = PathBuf::from(required_env("OUT")?);
991 let toplevel = PathBuf::from(required_env("TOPLEVEL")?);
992 let distro_id = required_env("DISTRO_ID")?;
···994 let install_bootloader = required_env("INSTALL_BOOTLOADER")?;
995 let locale_archive = required_env("LOCALE_ARCHIVE")?;
996 let new_systemd = PathBuf::from(required_env("SYSTEMD")?);
00000997998 let action = ACTION.get_or_init(|| action);
09991000 // The action that is to be performed (like switch, boot, test, dry-activate) Also exposed via
1001 // environment variable from now on
···1027 std::fs::set_permissions("/run/nixos", perms)
1028 .context("Failed to set permissions on /run/nixos directory")?;
102901030 let Ok(lock) = std::fs::OpenOptions::new()
1031 .append(true)
1032 .create(true)
···1036 die();
1037 };
103801039 let Ok(_lock) = Flock::lock(lock, FlockArg::LockExclusiveNonblock) else {
1040 eprintln!("Could not acquire lock");
1041 die();
1042 };
10431044- if syslog::init(Facility::LOG_USER, LevelFilter::Debug, Some("nixos")).is_err() {
1045 bail!("Failed to initialize logger");
1046 }
1047···1051 != "1"
1052 {
1053 do_pre_switch_check(&pre_switch_check, &toplevel, action)?;
01054 }
10551056 if *action == Action::Check {
···1060 // Install or update the bootloader.
1061 if matches!(action, Action::Switch | Action::Boot) {
1062 do_install_bootloader(&install_bootloader, &toplevel)?;
01063 }
10641065 // Just in case the new configuration hangs the system, do a sync now.
···1640 eprintln!("restarting systemd...");
1641 _ = systemd.reexecute(); // we don't get a dbus reply here
164201643 while !*systemd_reload_status.borrow() {
1644 _ = dbus_conn
1645 .process(Duration::from_millis(500))
···16541655 // Make systemd reload its units.
1656 _ = systemd.reload(); // we don't get a dbus reply here
01657 while !*systemd_reload_status.borrow() {
1658 _ = dbus_conn
1659 .process(Duration::from_millis(500))
···1690 .canonicalize()
1691 .context("Failed to get full path to /proc/self/exe")?;
169201693 std::process::Command::new(&myself)
1694 .uid(uid)
1695 .gid(gid)
···1865 //
1866 // Wait for events from systemd to settle. process() will return true if we have received any
1867 // messages on the bus.
1868- while dbus_conn
1869- .process(Duration::from_millis(250))
1870- .unwrap_or_default()
1871- {}
000000018721873 let new_active_units = get_active_units(&systemd)?;
1874
···123// Allow for this switch-to-configuration to remain consistent with the perl implementation.
124// Perl's "die" uses errno to set the exit code: https://perldoc.perl.org/perlvar#%24%21
125fn die() -> ! {
126+ let code = match std::io::Error::last_os_error().raw_os_error().unwrap_or(1) {
127+ // Ensure that even if errno did not point to a helpful error code, we still have a
128+ // non-zero exit code
129+ 0 => 1,
130+ other => other,
131+ };
132+133+ std::process::exit(code);
134}
135136fn parse_os_release() -> Result<HashMap<String, String>> {
···266 &unit_file_content,
267 ParseOption {
268 enabled_quote: true,
269+ enabled_indented_mutiline_value: false,
270+ enabled_preserve_key_leading_whitespace: false,
271 // Allow for escaped characters that won't get interpreted by the INI parser. These
272 // often show up in systemd unit files device/mount/swap unit names (e.g. dev-disk-by\x2dlabel-root.device).
273 enabled_escape: false,
···916 submitted_jobs: &Rc<RefCell<HashMap<dbus::Path<'static>, Job>>>,
917) {
918 while !submitted_jobs.borrow().is_empty() {
919+ log::debug!(
920+ "waiting for submitted jobs to finish, still have {} job(s)",
921+ submitted_jobs.borrow().len()
922+ );
923 _ = conn.process(Duration::from_millis(500));
924 }
925}
···972 .restart_unit("nixos-activation.service", "replace")
973 .context("Failed to restart nixos-activation.service")?;
974975+ log::debug!("waiting for nixos activation to finish");
976 while !*nixos_activation_done.borrow() {
977 _ = dbus_conn
978 .process(Duration::from_secs(500))
···10011002/// Performs switch-to-configuration functionality for the entire system
1003fn do_system_switch(action: Action) -> anyhow::Result<()> {
1004+ log::debug!("Performing system switch");
1005+1006 let out = PathBuf::from(required_env("OUT")?);
1007 let toplevel = PathBuf::from(required_env("TOPLEVEL")?);
1008 let distro_id = required_env("DISTRO_ID")?;
···1010 let install_bootloader = required_env("INSTALL_BOOTLOADER")?;
1011 let locale_archive = required_env("LOCALE_ARCHIVE")?;
1012 let new_systemd = PathBuf::from(required_env("SYSTEMD")?);
1013+ let log_level = if std::env::var("STC_DEBUG").is_ok() {
1014+ LevelFilter::Debug
1015+ } else {
1016+ LevelFilter::Info
1017+ };
10181019 let action = ACTION.get_or_init(|| action);
1020+ log::debug!("Using action {:?}", action);
10211022 // The action that is to be performed (like switch, boot, test, dry-activate) Also exposed via
1023 // environment variable from now on
···1049 std::fs::set_permissions("/run/nixos", perms)
1050 .context("Failed to set permissions on /run/nixos directory")?;
10511052+ log::debug!("Creating lock file /run/nixos/switch-to-configuration.lock");
1053 let Ok(lock) = std::fs::OpenOptions::new()
1054 .append(true)
1055 .create(true)
···1059 die();
1060 };
10611062+ log::debug!("Acquiring lock on file /run/nixos/switch-to-configuration.lock");
1063 let Ok(_lock) = Flock::lock(lock, FlockArg::LockExclusiveNonblock) else {
1064 eprintln!("Could not acquire lock");
1065 die();
1066 };
10671068+ if syslog::init(Facility::LOG_USER, log_level, Some("nixos")).is_err() {
1069 bail!("Failed to initialize logger");
1070 }
1071···1075 != "1"
1076 {
1077 do_pre_switch_check(&pre_switch_check, &toplevel, action)?;
1078+ log::debug!("Done performing pre-switch checks");
1079 }
10801081 if *action == Action::Check {
···1085 // Install or update the bootloader.
1086 if matches!(action, Action::Switch | Action::Boot) {
1087 do_install_bootloader(&install_bootloader, &toplevel)?;
1088+ log::debug!("Done performing bootloader installation");
1089 }
10901091 // Just in case the new configuration hangs the system, do a sync now.
···1666 eprintln!("restarting systemd...");
1667 _ = systemd.reexecute(); // we don't get a dbus reply here
16681669+ log::debug!("waiting for systemd restart to finish");
1670 while !*systemd_reload_status.borrow() {
1671 _ = dbus_conn
1672 .process(Duration::from_millis(500))
···16811682 // Make systemd reload its units.
1683 _ = systemd.reload(); // we don't get a dbus reply here
1684+ log::debug!("waiting for systemd reload to finish");
1685 while !*systemd_reload_status.borrow() {
1686 _ = dbus_conn
1687 .process(Duration::from_millis(500))
···1718 .canonicalize()
1719 .context("Failed to get full path to /proc/self/exe")?;
17201721+ log::debug!("Performing user switch for {name}");
1722 std::process::Command::new(&myself)
1723 .uid(uid)
1724 .gid(gid)
···1894 //
1895 // Wait for events from systemd to settle. process() will return true if we have received any
1896 // messages on the bus.
1897+ let mut waited = Duration::from_millis(0);
1898+ let wait_interval = Duration::from_millis(250);
1899+ let max_wait = Duration::from_secs(90);
1900+ log::debug!("waiting for systemd events to settle");
1901+ while dbus_conn.process(wait_interval).unwrap_or_default() {
1902+ waited += wait_interval;
1903+ if waited >= max_wait {
1904+ log::debug!("timed out waiting systemd events to settle");
1905+ break;
1906+ }
1907+ }
19081909 let new_active_units = get_active_units(&systemd)?;
1910