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