waylyrics: 0.3.16 -> 0.3.20 (#364626)
[NixPkgs.git] / nixos / modules / services / networking / iscsi / root-initiator.nix
blob86396ae1e24fae6fd38aaa8bd4f042d0fb610e57
2   config,
3   lib,
4   pkgs,
5   ...
6 }:
7 with lib;
8 let
9   cfg = config.boot.iscsi-initiator;
12   # If you're booting entirely off another machine you may want to add
13   # this snippet to always boot the latest "system" version. It is not
14   # enabled by default in case you have an initrd on a local disk:
15   #
16   #     boot.initrd.postMountCommands = ''
17   #       ln -sfn /nix/var/nix/profiles/system/init /mnt-root/init
18   #       stage2Init=/init
19   #     '';
20   #
21   # Note: Theoretically you might want to connect to multiple portals and
22   # log in to multiple targets, however the authors of this module so far
23   # don't have the need or expertise to reasonably implement it. Also,
24   # consider carefully before making your boot chain depend on multiple
25   # machines to be up.
26   options.boot.iscsi-initiator = with types; {
27     name = mkOption {
28       description = ''
29         Name of the iSCSI initiator to boot from. Note, booting from iscsi
30         requires networkd based networking.
31       '';
32       default = null;
33       example = "iqn.2020-08.org.linux-iscsi.initiatorhost:example";
34       type = nullOr str;
35     };
37     discoverPortal = mkOption {
38       description = ''
39         iSCSI portal to boot from.
40       '';
41       default = null;
42       example = "192.168.1.1:3260";
43       type = nullOr str;
44     };
46     target = mkOption {
47       description = ''
48         Name of the iSCSI target to boot from.
49       '';
50       default = null;
51       example = "iqn.2020-08.org.linux-iscsi.targethost:example";
52       type = nullOr str;
53     };
55     logLevel = mkOption {
56       description = ''
57         Higher numbers elicits more logs.
58       '';
59       default = 1;
60       example = 8;
61       type = int;
62     };
64     loginAll = mkOption {
65       description = ''
66         Do not log into a specific target on the portal, but to all that we discover.
67         This overrides setting target.
68       '';
69       type = bool;
70       default = false;
71     };
73     extraIscsiCommands = mkOption {
74       description = "Extra iscsi commands to run in the initrd.";
75       default = "";
76       type = lines;
77     };
79     extraConfig = mkOption {
80       description = "Extra lines to append to /etc/iscsid.conf";
81       default = null;
82       type = nullOr lines;
83     };
85     extraConfigFile = mkOption {
86       description = ''
87         Append an additional file's contents to `/etc/iscsid.conf`. Use a non-store path
88         and store passwords in this file. Note: the file specified here must be available
89         in the initrd, see: `boot.initrd.secrets`.
90       '';
91       default = null;
92       type = nullOr str;
93     };
94   };
96   config = mkIf (cfg.name != null) {
97     # The "scripted" networking configuration (ie: non-networkd)
98     # doesn't properly order the start and stop of the interfaces, and the
99     # network interfaces are torn down before unmounting disks. Since this
100     # module is specifically for very-early-boot network mounts, we need
101     # the network to stay on.
102     #
103     # We could probably fix the scripted options to properly order, but I'm
104     # not inclined to invest that time today. Hopefully this gets users far
105     # enough along and they can just use networkd.
106     networking.useNetworkd = true;
107     networking.useDHCP = false; # Required to set useNetworkd = true
109     boot.initrd = {
110       network.enable = true;
112       # By default, the stage-1 disables the network and resets the interfaces
113       # on startup. Since our startup disks are on the network, we can't let
114       # the network not work.
115       network.flushBeforeStage2 = false;
117       kernelModules = [ "iscsi_tcp" ];
119       extraUtilsCommands = ''
120         copy_bin_and_libs ${pkgs.openiscsi}/bin/iscsid
121         copy_bin_and_libs ${pkgs.openiscsi}/bin/iscsiadm
122         ${optionalString (
123           !config.boot.initrd.network.ssh.enable
124         ) "cp -pv ${pkgs.glibc.out}/lib/libnss_files.so.* $out/lib"}
126         mkdir -p $out/etc/iscsi
127         cp ${config.environment.etc.hosts.source} $out/etc/hosts
128         cp ${pkgs.openiscsi}/etc/iscsi/iscsid.conf $out/etc/iscsi/iscsid.fragment.conf
129         chmod +w $out/etc/iscsi/iscsid.fragment.conf
130         cat << 'EOF' >> $out/etc/iscsi/iscsid.fragment.conf
131         ${optionalString (cfg.extraConfig != null) cfg.extraConfig}
132         EOF
133       '';
135       extraUtilsCommandsTest = ''
136         $out/bin/iscsiadm --version
137       '';
139       preLVMCommands =
140         let
141           extraCfgDumper = optionalString (cfg.extraConfigFile != null) ''
142             if [ -f "${cfg.extraConfigFile}" ]; then
143               printf "\n# The following is from ${cfg.extraConfigFile}:\n"
144               cat "${cfg.extraConfigFile}"
145             else
146               echo "Warning: boot.iscsi-initiator.extraConfigFile ${cfg.extraConfigFile} does not exist!" >&2
147             fi
148           '';
149         in
150         ''
151           ${optionalString (!config.boot.initrd.network.ssh.enable) ''
152             # stolen from initrd-ssh.nix
153             echo 'root:x:0:0:root:/root:/bin/ash' > /etc/passwd
154             echo 'passwd: files' > /etc/nsswitch.conf
155           ''}
157           cp -f $extraUtils/etc/hosts /etc/hosts
159           mkdir -p /etc/iscsi /run/lock/iscsi
160           echo "InitiatorName=${cfg.name}" > /etc/iscsi/initiatorname.iscsi
162           (
163             cat "$extraUtils/etc/iscsi/iscsid.fragment.conf"
164             printf "\n"
165             ${optionalString cfg.loginAll ''echo "node.startup = automatic"''}
166             ${extraCfgDumper}
167           ) > /etc/iscsi/iscsid.conf
169           iscsid --foreground --no-pid-file --debug ${toString cfg.logLevel} &
170           iscsiadm --mode discoverydb \
171             --type sendtargets \
172             --discover \
173             --portal ${escapeShellArg cfg.discoverPortal} \
174             --debug ${toString cfg.logLevel}
176           ${
177             if cfg.loginAll then
178               ''
179                 iscsiadm --mode node --loginall all
180               ''
181             else
182               ''
183                 iscsiadm --mode node --targetname ${escapeShellArg cfg.target} --login
184               ''
185           }
187           ${cfg.extraIscsiCommands}
189           pkill -9 iscsid
190         '';
191     };
193     services.openiscsi = {
194       enable = true;
195       inherit (cfg) name;
196     };
198     assertions = [
199       {
200         assertion = cfg.loginAll -> cfg.target == null;
201         message = "iSCSI target name is set while login on all portals is enabled.";
202       }
203       {
204         assertion = !config.boot.initrd.systemd.enable;
205         message = "systemd stage 1 does not support iscsi yet.";
206       }
207     ];
208   };