]> git.ipfire.org Git - thirdparty/dracut.git/blob - docs/HACKING.md
docs: create CONTRIBUTING.md
[thirdparty/dracut.git] / docs / HACKING.md
1 # Dracut Developer Guidelines
2
3 Please make sure to follow our [Contribution Guidelines](CONTRIBUTING.md).
4
5 ## git
6
7 Currently dracut lives on github.com.
8
9 * https://github.com/dracutdevs/dracut.git
10
11 Pull requests should be filed preferably on github nowadays.
12
13 ### Code Format
14
15 It is recommended, that you install a plugin for your editor, which reads in `.editorconfig`.
16 Additionally `emacs` and `vim` config files are provided for convenience.
17
18 To reformat C files use `astyle`:
19 ```console
20 $ astyle --options=.astylerc <FILE>
21 ```
22
23 For convenience there is also a Makefile `indent-c` target `make indent-c`.
24
25 To reformat shell files use `shfmt`:
26
27 ```console
28 $ shfmt_version=3.2.4
29 $ wget "https://github.com/mvdan/sh/releases/download/v${shfmt_version}/shfmt_v${shfmt_version}_linux_amd64" -O shfmt
30 $ chmod u+x shfmt
31 $ ./shfmt -w -s .
32 ```
33
34 or
35
36 ```console
37 $ GO111MODULE=on go get mvdan.cc/sh/v3/cmd/shfmt
38 $ $GOPATH/bin/shfmt -w -s .
39 ```
40
41 or if `shfmt` is already in your `PATH`, use `make indent`.
42
43 Some IDEs already have support for shfmt.
44
45 For convenience the `make indent` Makefile target also calls shfmt, if it is in `$PATH`.
46
47 ### Commit Messages
48
49 Commit messages should answer these questions:
50
51 * What?: a short summary of what you changed in the subject line.
52 * Why?: what the intended outcome of the change is (arguably the most important piece of information that should go into a message).
53 * How?: if multiple approaches for achieving your goal were available, you also want to explain why you chose the used implementation strategy.
54 Note that you should not explain how your change achieves your goal in your commit message.
55 That should be obvious from the code itself.
56 If you cannot achieve that clarity with the used programming language, use comments within the code instead.
57
58 The commit message is primarily the place for documenting the why.
59
60 Commit message titles should follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
61
62 Format is `<type>[optional scope]: <description>`, where `type` is one of:
63
64 * fix: A bug fix
65 * feat: A new feature
66 * perf: A code change that improves performance
67 * refactor: A code change that neither fixes a bug nor adds a feature
68 * style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
69 * test: Adding missing tests or correcting existing tests
70 * docs: Documentation only changes
71 * revert: Reverts a previous commit
72 * chore: Other changes that don't modify src or test files
73 * build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
74 * ci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
75
76 `scope` should be the module name (without numbers) or:
77
78 * cli: for the dracut command line interface
79 * rt: for the dracut initramfs runtime logic
80 * functions: for general purpose dracut functions
81
82 Commit messages are checked with [Commisery](https://github.com/tomtom-international/commisery).
83
84 ## Writing modules
85
86 Some general rules for writing modules:
87
88 * Use one of the inst family of functions to actually install files
89 on to the initramfs. They handle mangling the pathnames and (for binaries,
90 scripts, and kernel modules) installing dependencies as appropriate so
91 you do not have to.
92 * Scripts that end up on the initramfs should be POSIX compliant. dracut
93 will try to use /bin/dash as /bin/sh for the initramfs if it is available,
94 so you should install it on your system -- dash aims for strict POSIX
95 compliance to the extent possible.
96 * Hooks MUST be POSIX compliant -- they are sourced by the init script,
97 and having a bashism break your user's ability to boot really sucks.
98 * Generator modules should have a two digit numeric prefix -- they run in
99 ascending sort order. Anything in the 90-99 range is stuff that dracut
100 relies on, so try not to break those hooks.
101 * Hooks must have a .sh extension.
102 * Generator modules are described in more detail later on.
103 * We have some breakpoints for debugging your hooks. If you pass 'rdbreak'
104 as a kernel parameter, the initramfs will drop to a shell just before
105 switching to a new root. You can pass 'rdbreak=hookpoint', and the initramfs
106 will break just before hooks in that hookpoint run.
107
108 Also, there is an attempt to keep things as distribution-agnostic as
109 possible. Every distribution has their own tool here and it's not
110 something which is really interesting to have separate across them.
111 So contributions to help decrease the distro-dependencies are welcome.
112
113 Most of the functionality that dracut implements are actually implemented
114 by dracut modules. dracut modules live in modules.d, and have the following
115 structure:
116
117 ```
118 dracut_install_dir/modules.d/
119 00modname/
120 module-setup.sh
121 check
122 <other files as needed by the hook>
123 ```
124
125 `00modname`: The name of the module prefixed by a two-digit numeric sort code.
126 The numeric code must be present and in the range of 00 - 99.
127 Modules with lower numbers are installed first. This is important
128 because the dracut install functions (which install files onto
129 the initrd) refuse to overwrite already installed files. This makes
130 it easy for an earlier module to override the functionality of a
131 later module, so that you can have a distro or system specific
132 module override or modify the functionality of a generic module
133 without having to patch the more generic module.
134
135 `module-setup.sh`:
136 dracut sources this script to install the functionality that a
137 module implements onto the initrd. For the most part, this amounts
138 to copying files from the host system onto the initrd in a controlled
139 manner.
140
141 `install()`:
142 This function of module-setup.sh is called to install all
143 non-kernel files. dracut supplies several install functions that are
144 specialized for different file types. Browse through dracut-functions
145 fore more details. dracut also provides a $moddir variable if you
146 need to install a file from the module directory, such as an initrd
147 hook, a udev rule, or a specialized executable.
148
149 `installkernel()`:
150 This function of module-setup.sh is called to install all
151 kernel related files.
152
153
154 `check()`:
155 dracut calls this function to check and see if a module can be installed
156 on the initrd.
157
158 When called without options, check should check to make sure that
159 any files it needs to install into the initrd from the host system
160 are present. It should exit with a 0 if they are, and a 1 if they are
161 not.
162
163 When called with $hostonly set, it should perform the same check
164 that it would without it set, and it should also check to see if the
165 functionality the module implements is being used on the host system.
166 For example, if this module handles installing support for LUKS
167 encrypted volumes, it should return 0 if all the tools to handle
168 encrpted volumes are available and the host system has the root
169 partition on an encrypted volume, 1 otherwise.
170
171 `depends()`:
172 This function should output a list of dracut modules
173 that it relies upon. An example would be the nfs and iscsi modules,
174 which rely on the network module to detect and configure network
175 interfaces.
176
177 Any other files in the module will not be touched by dracut directly.
178
179 You are encouraged to provide a README that describes what the module is for.
180
181
182 ### Hooks
183
184 init has the following hook points to inject scripts:
185
186 `/lib/dracut/hooks/cmdline/*.sh`
187 scripts for command line parsing
188
189 `/lib/dracut/hooks/pre-udev/*.sh`
190 scripts to run before udev is started
191
192 `/lib/dracut/hooks/pre-trigger/*.sh`
193 scripts to run before the main udev trigger is pulled
194
195 `/lib/dracut/hooks/initqueue/*.sh`
196 runs in parallel to the udev trigger
197 Udev events can add scripts here with /sbin/initqueue.
198 If /sbin/initqueue is called with the "--onetime" option, the script
199 will be removed after it was run.
200 If /lib/dracut/hooks/initqueue/work is created and udev >= 143 then
201 this loop can process the jobs in parallel to the udevtrigger.
202 If the udev queue is empty and no root device is found or no root
203 filesystem was mounted, the user will be dropped to a shell after
204 a timeout.
205 Scripts can remove themselves from the initqueue by "rm $job".
206
207 `/lib/dracut/hooks/pre-mount/*.sh`
208 scripts to run before the root filesystem is mounted
209 Network filesystems like NFS that do not use device files are an
210 exception. Root can be mounted already at this point.
211
212 `/lib/dracut/hooks/mount/*.sh`
213 scripts to mount the root filesystem
214 If the udev queue is empty and no root device is found or no root
215 filesystem was mounted, the user will be dropped to a shell after
216 a timeout.
217
218 `/lib/dracut/hooks/pre-pivot/*.sh`
219 scripts to run before latter initramfs cleanups
220
221 `/lib/dracut/hooks/cleanup/*.sh`
222 scripts to run before the real init is executed and the initramfs
223 disappears
224 All processes started before should be killed here.
225
226
227 ## Testsuite
228
229 ### Rootless in a container with podman
230
231 ```console
232 $ cd <DRACUT_SOURCE>
233 $ podman pull [CONTAINER]
234 $ podman run --rm -it \
235 --cap-add=SYS_PTRACE --user 0 \
236 -v /dev:/dev -v ./:/dracut:z \
237 [CONTAINER] \
238 bash -l
239 # cd /dracut
240 # ./configure
241 # make -j $(getconf _NPROCESSORS_ONLN)
242 # cd test
243 # make V=1 SKIP="16 60 61" clean check
244 ```
245
246 with `[CONTAINER]` being one of the
247 [github `dracutdevs` containers](https://github.com/orgs/dracutdevs/packages),
248 e.g. `ghcr.io/dracutdevs/fedora:latest`.
249
250 ### On bare metal
251
252 For the testsuite to pass, you will have to install at least the software packages
253 mentioned in the `test/container` Dockerfiles.
254
255 ```
256 $ sudo make clean check
257 ```
258
259 in verbose mode:
260 ```
261 $ sudo make V=1 clean check
262 ```
263
264 only specific test:
265 ```
266 $ sudo make TESTS="01 20 40" clean check
267 ```
268 only runs the 01, 20 and 40 tests.
269
270 debug a specific test case:
271 ```
272 $ cd TEST-01-BASIC
273 $ sudo make clean setup run
274 ```
275 ... change some kernel parameters in `test.sh` ...
276 ```
277 $ sudo make run
278 ```
279 to run the test without doing the setup.