summaryrefslogtreecommitdiffstats
path: root/docs/HACKING.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/HACKING.md')
-rw-r--r--docs/HACKING.md279
1 files changed, 279 insertions, 0 deletions
diff --git a/docs/HACKING.md b/docs/HACKING.md
new file mode 100644
index 0000000..6a19434
--- /dev/null
+++ b/docs/HACKING.md
@@ -0,0 +1,279 @@
+# Dracut Developer Guidelines
+
+Please make sure to follow our [Contribution Guidelines](../CONTRIBUTING.md).
+
+## git
+
+Currently dracut lives on github.com.
+
+* https://github.com/dracutdevs/dracut.git
+
+Pull requests should be filed preferably on github nowadays.
+
+### Code Format
+
+It is recommended, that you install a plugin for your editor, which reads in `.editorconfig`.
+Additionally `emacs` and `vim` config files are provided for convenience.
+
+To reformat C files use `astyle`:
+```console
+$ astyle --options=.astylerc <FILE>
+```
+
+For convenience there is also a Makefile `indent-c` target `make indent-c`.
+
+To reformat shell files use `shfmt`:
+
+```console
+$ shfmt_version=3.2.4
+$ wget "https://github.com/mvdan/sh/releases/download/v${shfmt_version}/shfmt_v${shfmt_version}_linux_amd64" -O shfmt
+$ chmod u+x shfmt
+$ ./shfmt -w -s .
+```
+
+or
+
+```console
+$ GO111MODULE=on go get mvdan.cc/sh/v3/cmd/shfmt
+$ $GOPATH/bin/shfmt -w -s .
+```
+
+or if `shfmt` is already in your `PATH`, use `make indent`.
+
+Some IDEs already have support for shfmt.
+
+For convenience the `make indent` Makefile target also calls shfmt, if it is in `$PATH`.
+
+### Commit Messages
+
+Commit messages should answer these questions:
+
+* What?: a short summary of what you changed in the subject line.
+* Why?: what the intended outcome of the change is (arguably the most important piece of information that should go into a message).
+* How?: if multiple approaches for achieving your goal were available, you also want to explain why you chose the used implementation strategy.
+ Note that you should not explain how your change achieves your goal in your commit message.
+ That should be obvious from the code itself.
+ If you cannot achieve that clarity with the used programming language, use comments within the code instead.
+
+The commit message is primarily the place for documenting the why.
+
+Commit message titles should follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
+
+Format is `<type>[optional scope]: <description>`, where `type` is one of:
+
+* fix: A bug fix
+* feat: A new feature
+* perf: A code change that improves performance
+* refactor: A code change that neither fixes a bug nor adds a feature
+* style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
+* test: Adding missing tests or correcting existing tests
+* docs: Documentation only changes
+* revert: Reverts a previous commit
+* chore: Other changes that don't modify src or test files
+* build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
+* ci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
+
+`scope` should be the module name (without numbers) or:
+
+* cli: for the dracut command line interface
+* rt: for the dracut initramfs runtime logic
+* functions: for general purpose dracut functions
+
+Commit messages are checked with [Commisery](https://github.com/tomtom-international/commisery).
+
+## Writing modules
+
+Some general rules for writing modules:
+
+* Use one of the inst family of functions to actually install files
+ on to the initramfs. They handle mangling the pathnames and (for binaries,
+ scripts, and kernel modules) installing dependencies as appropriate so
+ you do not have to.
+* Scripts that end up on the initramfs should be POSIX compliant. dracut
+ will try to use /bin/dash as /bin/sh for the initramfs if it is available,
+ so you should install it on your system -- dash aims for strict POSIX
+ compliance to the extent possible.
+* Hooks MUST be POSIX compliant -- they are sourced by the init script,
+ and having a bashism break your user's ability to boot really sucks.
+* Generator modules should have a two digit numeric prefix -- they run in
+ ascending sort order. Anything in the 90-99 range is stuff that dracut
+ relies on, so try not to break those hooks.
+* Hooks must have a .sh extension.
+* Generator modules are described in more detail later on.
+* We have some breakpoints for debugging your hooks. If you pass 'rdbreak'
+ as a kernel parameter, the initramfs will drop to a shell just before
+ switching to a new root. You can pass 'rdbreak=hookpoint', and the initramfs
+ will break just before hooks in that hookpoint run.
+
+Also, there is an attempt to keep things as distribution-agnostic as
+possible. Every distribution has their own tool here and it's not
+something which is really interesting to have separate across them.
+So contributions to help decrease the distro-dependencies are welcome.
+
+Most of the functionality that dracut implements are actually implemented
+by dracut modules. dracut modules live in modules.d, and have the following
+structure:
+
+```
+dracut_install_dir/modules.d/
+ 00modname/
+ module-setup.sh
+ check
+ <other files as needed by the hook>
+```
+
+`00modname`: The name of the module prefixed by a two-digit numeric sort code.
+ The numeric code must be present and in the range of 00 - 99.
+ Modules with lower numbers are installed first. This is important
+ because the dracut install functions (which install files onto
+ the initrd) refuse to overwrite already installed files. This makes
+ it easy for an earlier module to override the functionality of a
+ later module, so that you can have a distro or system specific
+ module override or modify the functionality of a generic module
+ without having to patch the more generic module.
+
+`module-setup.sh`:
+ dracut sources this script to install the functionality that a
+ module implements onto the initrd. For the most part, this amounts
+ to copying files from the host system onto the initrd in a controlled
+ manner.
+
+`install()`:
+ This function of module-setup.sh is called to install all
+ non-kernel files. dracut supplies several install functions that are
+ specialized for different file types. Browse through dracut-functions
+ for more details. dracut also provides a $moddir variable if you
+ need to install a file from the module directory, such as an initrd
+ hook, a udev rule, or a specialized executable.
+
+`installkernel()`:
+ This function of module-setup.sh is called to install all
+ kernel related files.
+
+
+`check()`:
+ dracut calls this function to check and see if a module can be installed
+ on the initrd.
+
+ When called without options, check should check to make sure that
+ any files it needs to install into the initrd from the host system
+ are present. It should exit with a 0 if they are, and a 1 if they are
+ not.
+
+ When called with $hostonly set, it should perform the same check
+ that it would without it set, and it should also check to see if the
+ functionality the module implements is being used on the host system.
+ For example, if this module handles installing support for LUKS
+ encrypted volumes, it should return 0 if all the tools to handle
+ encrypted volumes are available and the host system has the root
+ partition on an encrypted volume, 1 otherwise.
+
+`depends()`:
+ This function should output a list of dracut modules
+ that it relies upon. An example would be the nfs and iscsi modules,
+ which rely on the network module to detect and configure network
+ interfaces.
+
+Any other files in the module will not be touched by dracut directly.
+
+You are encouraged to provide a README that describes what the module is for.
+
+
+### Hooks
+
+init has the following hook points to inject scripts:
+
+`/lib/dracut/hooks/cmdline/*.sh`
+ scripts for command line parsing
+
+`/lib/dracut/hooks/pre-udev/*.sh`
+ scripts to run before udev is started
+
+`/lib/dracut/hooks/pre-trigger/*.sh`
+ scripts to run before the main udev trigger is pulled
+
+`/lib/dracut/hooks/initqueue/*.sh`
+ runs in parallel to the udev trigger
+ Udev events can add scripts here with /sbin/initqueue.
+ If /sbin/initqueue is called with the "--onetime" option, the script
+ will be removed after it was run.
+ If /lib/dracut/hooks/initqueue/work is created and udev >= 143 then
+ this loop can process the jobs in parallel to the udevtrigger.
+ If the udev queue is empty and no root device is found or no root
+ filesystem was mounted, the user will be dropped to a shell after
+ a timeout.
+ Scripts can remove themselves from the initqueue by "rm $job".
+
+`/lib/dracut/hooks/pre-mount/*.sh`
+ scripts to run before the root filesystem is mounted
+ Network filesystems like NFS that do not use device files are an
+ exception. Root can be mounted already at this point.
+
+`/lib/dracut/hooks/mount/*.sh`
+ scripts to mount the root filesystem
+ If the udev queue is empty and no root device is found or no root
+ filesystem was mounted, the user will be dropped to a shell after
+ a timeout.
+
+`/lib/dracut/hooks/pre-pivot/*.sh`
+ scripts to run before latter initramfs cleanups
+
+`/lib/dracut/hooks/cleanup/*.sh`
+ scripts to run before the real init is executed and the initramfs
+ disappears
+ All processes started before should be killed here.
+
+
+## Testsuite
+
+### Rootless in a container with podman
+
+```console
+$ cd <DRACUT_SOURCE>
+$ podman pull [CONTAINER]
+$ podman run --rm -it \
+ --cap-add=SYS_PTRACE --user 0 \
+ -v /dev:/dev -v ./:/dracut:z \
+ [CONTAINER] \
+ bash -l
+# cd /dracut
+# ./configure
+# make -j $(getconf _NPROCESSORS_ONLN)
+# cd test
+# make KVERSION="$(cd /lib/modules && ls -1 | tail -1)" V=1 SKIP="16 60 61" clean check
+```
+
+with `[CONTAINER]` being one of the
+[github `dracutdevs` containers](https://github.com/orgs/dracutdevs/packages),
+e.g. `ghcr.io/dracutdevs/fedora:latest`.
+
+### On bare metal
+
+For the testsuite to pass, you will have to install at least the software packages
+mentioned in the `test/container` Dockerfiles.
+
+```
+$ sudo make clean check
+```
+
+in verbose mode:
+```
+$ sudo make V=1 clean check
+```
+
+only specific test:
+```
+$ sudo make TESTS="01 20 40" clean check
+```
+only runs the 01, 20 and 40 tests.
+
+debug a specific test case:
+```
+$ cd TEST-01-BASIC
+$ sudo make clean setup run
+```
+... change some kernel parameters in `test.sh` ...
+```
+$ sudo make run
+```
+to run the test without doing the setup.