]>
Commit | Line | Data |
---|---|---|
1ed4b9f1 HH |
1 | # Dracut Developer Guidelines |
2 | ||
d87572ed | 3 | Please make sure to follow our [Contribution Guidelines](../CONTRIBUTING.md). |
025906de | 4 | |
1ed4b9f1 HH |
5 | ## git |
6 | ||
025906de | 7 | Currently dracut lives on github.com. |
1ed4b9f1 HH |
8 | |
9 | * https://github.com/dracutdevs/dracut.git | |
1ed4b9f1 HH |
10 | |
11 | Pull requests should be filed preferably on github nowadays. | |
12 | ||
0561f953 HH |
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 | ||
b7b8eeda | 18 | To reformat C files use `astyle`: |
0561f953 | 19 | ```console |
b7b8eeda | 20 | $ astyle --options=.astylerc <FILE> |
0561f953 HH |
21 | ``` |
22 | ||
b7b8eeda | 23 | For convenience there is also a Makefile `indent-c` target `make indent-c`. |
0561f953 HH |
24 | |
25 | To reformat shell files use `shfmt`: | |
26 | ||
27 | ```console | |
cc914eaa | 28 | $ shfmt_version=3.2.4 |
0561f953 HH |
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 | ||
cc914eaa HH |
34 | or |
35 | ||
36 | ```console | |
37 | $ GO111MODULE=on go get mvdan.cc/sh/v3/cmd/shfmt | |
38 | $ $GOPATH/bin/shfmt -w -s . | |
39 | ``` | |
40 | ||
b7b8eeda HH |
41 | or if `shfmt` is already in your `PATH`, use `make indent`. |
42 | ||
0561f953 HH |
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 | ||
1ed4b9f1 HH |
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 | |
61ae423b | 145 | for more details. dracut also provides a $moddir variable if you |
1ed4b9f1 HH |
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 | |
ddf63231 | 168 | encrypted volumes are available and the host system has the root |
1ed4b9f1 HH |
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 | ||
5a04bd2d | 229 | ### Rootless in a container with podman |
4a76c187 | 230 | |
5a04bd2d HH |
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 | |
23389f6d | 243 | # make KVERSION="$(cd /lib/modules && ls -1 | tail -1)" V=1 SKIP="16 60 61" clean check |
1ed4b9f1 HH |
244 | ``` |
245 | ||
5a04bd2d HH |
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`. | |
4a76c187 | 249 | |
5a04bd2d | 250 | ### On bare metal |
4a76c187 | 251 | |
5a04bd2d HH |
252 | For the testsuite to pass, you will have to install at least the software packages |
253 | mentioned in the `test/container` Dockerfiles. | |
1ed4b9f1 HH |
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 | ``` | |
5a04bd2d | 275 | ... change some kernel parameters in `test.sh` ... |
1ed4b9f1 HH |
276 | ``` |
277 | $ sudo make run | |
278 | ``` | |
5a04bd2d | 279 | to run the test without doing the setup. |