Skip to content

Commit

Permalink
Merge pull request #4 from pirat89/doc-tutorial-templates
Browse files Browse the repository at this point in the history
Doc tutorial templates
  • Loading branch information
matejmatuska authored Jan 10, 2025
2 parents 8379a4d + f778523 commit 1bb4148
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 0 deletions.
2 changes: 2 additions & 0 deletions docs/source/tutorials/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Tutorials
:caption: Contents:
:glob:

templates/index

.. Indices and tables
.. ==================
..
Expand Down
63 changes: 63 additions & 0 deletions docs/source/tutorials/templates/add-kernel-driver.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Install a kernel driver during the upgrade

Note that usually when someone wants to install particular kernel driver,
it's expected that the driver is needed to be used also during the in-place
upgrade as well as on the upgraded system.

```python
from leapp.actors import Actor
from leapp.models import (
KernelModule,
RpmTransactionTasks,
TargetInitramfsTasks,
TargetUserSpaceUpgradeTasks,
UpgradeInitramfsTasks
)
from leapp.tags import ChecksPhaseTag, IPUWorkflowTag


# AI: do not forget to change the class name when applied!
class AddKernelDriverMYDRIVER(Actor):
"""
Install the <mydriver> driver during the upgrade
Install the <mydriver> kernel module in the upgrade & target initramfs.
In this scenario it requires the package with the module is installed
on the target system and inside the target userspace container.
In case of the scenario when the module should be copied from a directory
existing on the host system, specify the path from where it should
be copied/installed instead, e.g.:
KernelModule(name='<mydriver>', module_path='/path/to/the/module')
and in such a case, most likely you will want to drop some parts of the
code as well when you do not need to install any additional rpms explicitly.
"""

# AI: do not forget to change the name when applied!
name = 'add_kernel_driver_<mydriver>'
consumes = ()
produces = (RpmTransactionTasks, TargetInitramfsTasks, TargetUserSpaceUpgradeTasks, UpgradeInitramfsTasks)
tags = (IPUWorkflowTag, ChecksPhaseTag)

def process(self):
# IMPORTANT: For the installation of these packages the (custom) repository
# must be enabled (used) for the IPU process! For the third party
# packages, ideal solution is to define such dnf repos inside the
# /etc/leapp/files/leapp_upgrade_repositories.repo file or using the
# --enablerepo option when running leapp (check documentation for the
# difference).
# This will create task to install the package with desired driver
# into the target userspace container
# <pkg-with-driver> - could be e.g. kmod-<mydriver>
self.produce(TargetUserSpaceUpgradeTasks(install_rpms=['<pkg-with-driver>']))

# and we want the package to be installed also during the upgrade,
# so the driver can be used also on the upgraded system
self.produce(RpmTransactionTasks(to_install=['<pkg-with-driver>']))

# this will require installation of the module in the upgrade and the
# target initramfs
k_module = KernelModule(name='<mydriver>')
self.produce(UpgradeInitramfsTasks(include_kernel_modules=[k_module]))
self.produce(TargetInitramfsTasks(include_kernel_modules=[k_module]))
```
86 changes: 86 additions & 0 deletions docs/source/tutorials/templates/execute-custom-script.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Execute custom script during the upgrade

For some people it could be tricky to write a code in Python and in some cases
they prefer to perform e.g. their shell script during the upgrade. And in some
cases you the code in bash could be just much more simple, when using tools
available on the system. Well, you will always need to do some Python code,
but in case you do not need anything else, just execute the code in the right
phase of the upgrade, here is the minimal actor to do so.

For more tips, check our actors how they work with the `run` function. There
are many useful examples:
[sytem\_upgrade\_common repo](https://github.com/oamg/leapp-repository/tree/main/repos/system\_upgrade/common/actors)

Check failure on line 12 in docs/source/tutorials/templates/execute-custom-script.md

View workflow job for this annotation

GitHub Actions / Check for spelling errors

sytem ==> system

The full list of existing phases in the IPUWorkflow and their tags see [IPUWorkflow](https://github.com/oamg/leapp-repository/blob/main/repos/system_upgrade/common/workflows/inplace_upgrade.py)

[//]: # (TODO: replace the URL by the link to upstream documentation.)

```python
from leapp.actors import Actor
from leapp.libraries.stdlib import api, CalledProcessError, run

# AI: replace <Phase>PhaseTag by a valid phase tag.
from leapp.tags import <Phase>PhaseTag, IPUWorkflowTag

# AI: change the name of the class when applied!!
class ExecuteMyCustomScript(Actor):
"""
This actor executes a script (or whatever executable command).
The actor is executed during the execution of the specified phase.
You can specify your script as path to the executable file, just
the name of the executable file if covered by PATH. If it's a custom script,
we suggest to store it under this actor directory in path:
tools/<myscript>
so the directory with actor contains at least:
actor.py
tools/<myscript>
ensure the file has set executable permission! In such a case, during
the actor execution you can call just <myscript> to execute it
"""

# AI: change the name when applied!!
name = 'execute\_my\_custom\_script'
consumes = ()
produces = ()
tags = (IPUWorkflowTag, <Phase>PhaseTag)

def process(self):
# Specify the command that should be executed.
# Pipelines are not allowed. It should be simple command. Each option
# need to be a different item in the array. The first item is the
# executable. Example:
# command = ['/usr/bin/echo', '-E', 'I have been executed...']
command = ['<myscript>']
try:
#
run(command)
except CalledProcessError as e:
# This happens if the command ends with non-zero exit code
self.current_logger().error('<Your error msg>')
details = {
'details': str(err),
'stderr': err.stderr,
'stdout': err.stdout
}
# Here you can decide what to do next. E.g. If you want to end with
# error and stop the upgrade process, uncomment the raise of exception
# below.
# # Note that usually you do not want to raise this error after the
# # upgrade DNF transaction has been performed as the system usually
# # ends just in emergency mode and more broken state.
# # In short, it is safe in phases prior the first reboot.
# raise StopActorExecutionError('Your error msg', details=details)

except OSError as e:
# This can happen just if the command is not possible to execute.
# E.g. the executable does not exist, it has not set executable
# mode, etc.
self.current_logger().error(
'Cannot execute cmd "{}": {}'
.format(command, str(e))
)
# Similarly, in case you want to stop the upgrade execution with error:
#
# raise StopActorExecutionError('Your err msg')
```
38 changes: 38 additions & 0 deletions docs/source/tutorials/templates/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
Templates
=========

Here you can find out various templates (examples) of actors that are covering
some common situations that people want to deal with during in-place upgrades.
Templates contains usually comments with additional explanations providing clues
what people want to do most likely in particular actors. Sometimes you will
want to possibly look at several templates and mix them to get you solution.

Our goal is to provide hints to people how they could create some actors
to cover some typical scenarios. Note that templates can be updated over time
as overall in-place upgrade solution is changed. So it's good to check
documentation for the particular leapp-repository version you have installed
on the system (do not exchange the version of leapp-repository with leapp!). E.g.:

Note these templates do not meet best practices for the actor development in
the official **leapp-repository** repository - to keep them short and simple.

```bash
rpm -qa "leapp-upgrade*"
```

TODO: make a link to best practices documentation.

.. toctree::
:maxdepth: 4
:caption: Contents:
:glob:

add-kernel-driver
execute-custom-script

.. Indices and tables
.. ==================
..
.. * :ref:`genindex`
.. * :ref:`modindex`
.. * :ref:`search`

0 comments on commit 1bb4148

Please sign in to comment.