docs(development): add HACKING.md

Merge HACKING, README.modules, README.testsuite into HACKING.md.

Provide a new paragraph about git commit messages.
master
Harald Hoyer 2020-12-14 16:21:30 +01:00 committed by Harald Hoyer
parent e473057ae1
commit 1ed4b9f100
6 changed files with 253 additions and 219 deletions

23
HACKING
View File

@ -1,23 +0,0 @@
Right now, most of the testing is done using a qemu/kvm guest and
generating the initramfs on another box but the support is all present
to build for the "running" machine. For the former, you can boot the guest
using qemu's -kernel and -initrd options.

dracut exists and will build an image. It is command-line equivalent
to most mkinitrd implementations and should be pretty straight-forward
to use.

To use, just run dracut with an output file name and, optionally, a
kernel version (it defaults to using the current). The appropriate
modules will be copied over and things should be good to go. If you'd
like to customize the list of modules copied in, edit /etc/dracut.conf
and set
dracutmodules="foo bar baz"

Note that dracut calls functional components in modules.d "modules"
while kernel modules are called "drivers".

Requirements:
* udev
* nfs module: nfs daemon and rpc helper
* iscsi: iscsi

248
HACKING.md Normal file
View File

@ -0,0 +1,248 @@
# Dracut Developer Guidelines

## git

Currently dracut lives on github.com and kernel.org.

* https://github.com/dracutdevs/dracut.git
* https://git.kernel.org/pub/scm/boot/dracut/dracut.git

Pull requests should be filed preferably on github nowadays.

### 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
fore 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
encrpted 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

For the testsuite to work, you will have to install at least the following software packages:
```
dash \
asciidoc \
mdadm \
lvm2 \
dmraid \
cryptsetup \
nfs-utils \
nbd \
dhcp-server \
scsi-target-utils \
iscsi-initiator-utils \
strace \
syslinux \
python-imgcreate \
genisoimage \
btrfs-progs \
kmod-devel \
gcc \
bzip2 \
xz \
tar \
wget \
rpm-build \
${NULL}
```

How to run the testsuite:

```
$ 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 ...
```
$ sudo make run
```
to run the test without doing the setup

View File

@ -29,32 +29,6 @@ specific functionality into the initramfs. They live in the modules.d
subdirectory, and use functionality provided by dracut-functions to do their
work.

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 in README.modules.
* 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.

Currently dracut lives on github.com and kernel.org.

The tarballs can be found here:
@ -62,15 +36,7 @@ The tarballs can be found here:
ftp://ftp.kernel.org/pub/linux/utils/boot/dracut/

Git:
git://git.kernel.org/pub/scm/boot/dracut/dracut.git
http://git.kernel.org/pub/scm/boot/dracut/dracut.git
https://git.kernel.org/pub/scm/boot/dracut/dracut.git

git@github.com:dracutdevs/dracut.git

Git Web:
https://github.com/dracutdevs/dracut.git

https://github.com/dracutdevs/dracut.git
http://git.kernel.org/?p=boot/dracut/dracut.git

Project Documentation:
@ -79,8 +45,8 @@ Project Documentation:
Project Wiki:
http://dracut.wiki.kernel.org

See the TODO file for things which still need to be done and HACKING for
some instructions on how to get started. There is also a mailing list
See the github issue tracker for things which still need to be done and HACKING.md
for some instructions on how to get started. There is also a mailing list
that is being used for the discussion -- initramfs@vger.kernel.org.
It is a typical vger list, send mail to majordomo@vger.kernel.org with body
of 'subscribe initramfs email@host.com'

View File

@ -1,112 +0,0 @@
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
fore 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
encrpted 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.

View File

@ -1,45 +0,0 @@
For the testsuite to work, you will have to install at least the following software packages:
dash \
asciidoc \
mdadm \
lvm2 \
dmraid \
cryptsetup \
nfs-utils \
nbd \
dhcp-server \
scsi-target-utils \
iscsi-initiator-utils \
strace \
syslinux \
python-imgcreate \
genisoimage \
btrfs-progs \
kmod-devel \
gcc \
bzip2 \
xz \
tar \
wget \
rpm-build \
${NULL}

TEST-04-FULL-SYSTEMD: systemd >= 187

How to run the testsuite:

$ 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 ...
$ sudo make run
to run the test without doing the setup

View File

@ -280,7 +280,7 @@ echo 'dracut_rescue_image="yes"' > $RPM_BUILD_ROOT%{dracutlibdir}/dracut.conf.d/

%files
%if %{with doc}
%doc README.md HACKING TODO AUTHORS NEWS dracut.html dracut.png dracut.svg
%doc README.md HACKING.md TODO AUTHORS NEWS dracut.html dracut.png dracut.svg
%endif
%{!?_licensedir:%global license %%doc}
%license COPYING lgpl-2.1.txt