Repository: cobbler/cobbler

Issue:
XML-RPC: Boolean values cannot be set with `modify_setting`
### Describe the bug

```
[root@localhost cobbler]# cobbler sync --dhcp
task started: 2023-02-02_051336_Sync_f09f71089bbe47bc8299204141feebf2
task started (id=Sync, time=Thu Feb  2 05:13:36 2023)
start_task(sync); event_id(2023-02-02_051336_Sync_f09f71089bbe47bc8299204141feebf2)
"manage_dhcp" not set. Skipping DHCP sync.
*** TASK COMPLETE ***

[root@localhost cobbler]# cobbler setting edit --name=manage_dhcp --value=true
Changing the setting failed
```

The configuration file was not changed.

`settings.yaml`:

```yaml
manage_dhcp: false
manage_dhcp_v4: false
```

### Expected behavior

The configuration file can be written normally

### Cobbler version

_v3.4.0_

### Operating system

```
[root@localhost dhcp]# cat /etc/os-release 
NAME="Fedora Linux"
VERSION="37 (Server Edition)"
ID=fedora
VERSION_ID=37
```
### Cobbler log

```
INFO | REMOTE create_task(Sync); event_id(2023-02-02_051425_Sync_cc59548baaf74238851c757a040bd3a7); user(?)
INFO | start_task(sync); event_id(2023-02-02_051425_Sync_cc59548baaf74238851c757a040bd3a7)
INFO | "manage_dhcp" not set. Skipping DHCP sync.
INFO | ### TASK COMPLETE ###
```

### Screenshots

None


Discussion:
@xuezhixin So I looked into your bug again.

The error message you are seeing is from the CLI directly. The error message appears if the return code from the XML-RPC is not `0`. Thus the reason for this must be in the log file. The log entries in the issue report only show the `cobbler sync`. The relevant lines can be found probably directly during the time you execute the command. However the reasons for this can range from a disabled `allow_dynamic_settings` setting to a real bug.

Please extend your bug report with the required information or it will be hard for me to help you. The PR you opened has no real change and is in fact IMHO not providing the changes that you need to fix this bug - if it is one.
```
[root@localhost cobbler]# grep allow_dynamic_settings /etc/cobbler/settings.yaml 
allow_dynamic_settings: true
[root@localhost cobbler]# cobbler setting edit --name=manage_dhcp --value=true
Changing the setting failed
```

```
print("_______",getattr(self.api.settings(), setting_name))
print("_______",isinstance(getattr(self.api.settings(), setting_name), int))
_______ False
_______ True
```
Thank you for your attention. This was recorded during my self-test, **allow_dynamic_settings=true**. If you need, I will provide the corresponding error log later.In addition, I submitted pytest and set **allow_dynamic_settings=true**.
@xuezhixin So seeing the debugging you did tells me the following things:

1. The setting that is present inside `setting_name` is `False`.
2. Due to the implementation details of booleans in Python it is of course also a valid integer.

I looked at the code again and found the bug myself now I believe. Hopefully, with the output of the following prompt, you understand too what needs to be done:

```
(venv) enno@dell-workhorse:~/Sources/git/cobbler> python3
Python 3.10.9 (main, Dec 08 2022, 14:49:06) [GCC] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> isinstance(False, int)
True
>>> isinstance(0, int)
True
>>> isinstance(False, int)
True
>>> isinstance(False, bool)
True
>>> isinstance(0, bool)
False
```

If I am not mistaken we actually want to do the following:

```patch
diff --git a/cobbler/remote.py b/cobbler/remote.py
index ffc0fad41..85e705c12 100644
--- a/cobbler/remote.py
+++ b/cobbler/remote.py
@@ -2038,10 +2038,10 @@ class CobblerXMLRPCInterface:
         try:
             if isinstance(getattr(self.api.settings(), setting_name), str):
                 value = str(value)
-            elif isinstance(getattr(self.api.settings(), setting_name), int):
-                value = int(value)
             elif isinstance(getattr(self.api.settings(), setting_name), bool):
                 value = self.api.input_boolean(value)
+            elif isinstance(getattr(self.api.settings(), setting_name), int):
+                value = int(value)
             elif isinstance(getattr(self.api.settings(), setting_name), float):
                 value = float(value)
             elif isinstance(getattr(self.api.settings(), setting_name), list):
```

Feel free to use this inside your patch but remember to submit also a test that shows that my guesswork (because I haven't verified if I am right) is actually correct.
Yes, I will modify and resubmit.

Resolving patch:
diff --git a/cobbler/api.py b/cobbler/api.py
--- a/cobbler/api.py
+++ b/cobbler/api.py
@@ -14,7 +14,7 @@
 import threading
 from configparser import ConfigParser
 from pathlib import Path
-from typing import Dict, List, Optional, Union
+from typing import TYPE_CHECKING, Dict, List, Optional, Union
 
 from schema import SchemaError
 
@@ -58,6 +58,9 @@
 )
 from cobbler.decorator import InheritableDictProperty
 
+if TYPE_CHECKING:
+    from cobbler.settings import Settings
+
 
 # notes on locking:
 # - CobblerAPI is a singleton object
@@ -383,7 +386,7 @@ def images(self):
         """
         return self.get_items("image")
 
-    def settings(self):
+    def settings(self) -> "Settings":
         """
         Return the application configuration
         """
diff --git a/cobbler/remote.py b/cobbler/remote.py
--- a/cobbler/remote.py
+++ b/cobbler/remote.py
@@ -18,7 +18,7 @@
 import re
 import xmlrpc.server
 from socketserver import ThreadingMixIn
-from typing import Any, Dict, List, Optional, Union
+from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
 from xmlrpc.server import SimpleXMLRPCRequestHandler
 
 from cobbler import enums
@@ -40,6 +40,9 @@
     validate_uuid,
 )
 
+if TYPE_CHECKING:
+    from cobbler.api import CobblerAPI
+
 EVENT_TIMEOUT = 7 * 24 * 60 * 60  # 1 week
 CACHE_TIMEOUT = 10 * 60  # 10 minutes
 
@@ -51,7 +54,7 @@ class CobblerXMLRPCInterface:
     Most read-write operations require a token returned from "login". Read operations do not.
     """
 
-    def __init__(self, api):
+    def __init__(self, api: "CobblerAPI"):
         """
         Constructor. Requires a Cobbler API handle.
 
@@ -1303,7 +1306,7 @@ def has_item(self, what: str, name: str, token: Optional[str] = None):
             return False
         return True
 
-    def get_item_handle(self, what: str, name: str):
+    def get_item_handle(self, what: str, name: str) -> str:
         """
         Given the name of an object (or other search parameters), return a reference (object id) that can be used with
         ``modify_*`` functions or ``save_*`` functions to manipulate that object.
@@ -2014,7 +2017,12 @@ def modify_menu(self, object_id, attribute, arg, token: str):
         """
         return self.modify_item("menu", object_id, attribute, arg, token)
 
-    def modify_setting(self, setting_name: str, value, token: str) -> int:
+    def modify_setting(
+        self,
+        setting_name: str,
+        value: Union[str, bool, float, int, Dict[Any, Any], List[Any]],
+        token: str,
+    ) -> int:
         """
         Modify a single attribute of a setting.
 
@@ -2038,16 +2046,16 @@ def modify_setting(self, setting_name: str, value, token: str) -> int:
         try:
             if isinstance(getattr(self.api.settings(), setting_name), str):
                 value = str(value)
-            elif isinstance(getattr(self.api.settings(), setting_name), int):
-                value = int(value)
             elif isinstance(getattr(self.api.settings(), setting_name), bool):
                 value = self.api.input_boolean(value)
+            elif isinstance(getattr(self.api.settings(), setting_name), int):
+                value = int(value)
             elif isinstance(getattr(self.api.settings(), setting_name), float):
                 value = float(value)
             elif isinstance(getattr(self.api.settings(), setting_name), list):
-                value = self.api.input_string_or_list(value)
+                value = self.api.input_string_or_list_no_inherit(value)
             elif isinstance(getattr(self.api.settings(), setting_name), dict):
-                value = self.api.input_string_or_dict(value)
+                value = self.api.input_string_or_dict_no_inherit(value)
             else:
                 self.logger.error(
                     "modify_setting(%s) - Wrong type for value", setting_name


Test patch:
diff --git a/tests/conftest.py b/tests/conftest.py
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -2,6 +2,7 @@
 import shutil
 from contextlib import contextmanager
 from pathlib import Path
+from typing import Callable
 
 import pytest
 
@@ -19,13 +20,13 @@ def does_not_raise():
 
 @pytest.fixture(scope="function")
 def cobbler_api() -> CobblerAPI:
-    CobblerAPI.__shared_state = {}
-    CobblerAPI.__has_loaded = False
+    CobblerAPI.__shared_state = {}  # type: ignore
+    CobblerAPI.__has_loaded = False  # type: ignore
     return CobblerAPI()
 
 
 @pytest.fixture(scope="function", autouse=True)
-def reset_settings_yaml(tmp_path):
+def reset_settings_yaml(tmp_path: Path):
     filename = "settings.yaml"
     filepath = "/etc/cobbler/%s" % filename
     shutil.copy(filepath, tmp_path.joinpath(filename))
@@ -34,7 +35,7 @@ def reset_settings_yaml(tmp_path):
 
 
 @pytest.fixture(scope="function", autouse=True)
-def reset_items(cobbler_api):
+def reset_items(cobbler_api: CobblerAPI):
     for system in cobbler_api.systems():
         cobbler_api.remove_system(system.name)
     for image in cobbler_api.images():
@@ -56,8 +57,8 @@ def reset_items(cobbler_api):
 
 
 @pytest.fixture(scope="function")
-def create_testfile(tmp_path):
-    def _create_testfile(filename):
+def create_testfile(tmp_path: Path):
+    def _create_testfile(filename: str):
         path = os.path.join(tmp_path, filename)
         if not os.path.exists(path):
             Path(path).touch()
@@ -67,8 +68,8 @@ def _create_testfile(filename):
 
 
 @pytest.fixture(scope="function")
-def create_kernel_initrd(create_testfile):
-    def _create_kernel_initrd(name_kernel, name_initrd):
+def create_kernel_initrd(create_testfile: Callable[[str], str]):
+    def _create_kernel_initrd(name_kernel: str, name_initrd: str) -> str:
         create_testfile(name_kernel)
         return os.path.dirname(create_testfile(name_initrd))
 
@@ -76,7 +77,13 @@ def _create_kernel_initrd(name_kernel, name_initrd):
 
 
 @pytest.fixture(scope="function")
-def create_distro(request, cobbler_api, create_kernel_initrd, fk_kernel, fk_initrd):
+def create_distro(
+    request: "pytest.FixtureRequest",
+    cobbler_api: CobblerAPI,
+    create_kernel_initrd: Callable[[str, str], str],
+    fk_kernel: str,
+    fk_initrd: str,
+):
     """
     Returns a function which has no arguments. The function returns a distro object. The distro is already added to
     the CobblerAPI.
@@ -99,13 +106,13 @@ def _create_distro():
 
 
 @pytest.fixture(scope="function")
-def create_profile(request, cobbler_api):
+def create_profile(request: "pytest.FixtureRequest", cobbler_api: CobblerAPI):
     """
     Returns a function which has the distro name as an argument. The function returns a profile object. The profile is
     already added to the CobblerAPI.
     """
 
-    def _create_profile(distro_name):
+    def _create_profile(distro_name: str) -> Profile:
         test_profile = Profile(cobbler_api)
         test_profile.name = (
             request.node.originalname
@@ -120,13 +127,13 @@ def _create_profile(distro_name):
 
 
 @pytest.fixture(scope="function")
-def create_image(request, cobbler_api):
+def create_image(request: "pytest.FixtureRequest", cobbler_api: CobblerAPI):
     """
     Returns a function which has no arguments. The function returns an image object. The image is already added to the
     CobblerAPI.
     """
 
-    def _create_image():
+    def _create_image() -> Image:
         test_image = Image(cobbler_api)
         test_image.name = (
             request.node.originalname
@@ -140,13 +147,13 @@ def _create_image():
 
 
 @pytest.fixture(scope="function")
-def create_system(request, cobbler_api):
+def create_system(request: "pytest.FixtureRequest", cobbler_api: CobblerAPI):
     """
     Returns a function which has the profile name as an argument. The function returns a system object. The system is
     already added to the CobblerAPI.
     """
 
-    def _create_system(profile_name="", image_name="", name=""):
+    def _create_system(profile_name: str = "", image_name: str = "", name: str = ""):
         test_system = System(cobbler_api)
         if name == "":
             test_system.name = (
@@ -191,7 +198,7 @@ def cleanup_leftover_items():
 
 
 @pytest.fixture(scope="function")
-def fk_initrd(request):
+def fk_initrd(request: "pytest.FixtureRequest") -> str:
     """
     The path to the first fake initrd.
 
@@ -203,7 +210,7 @@ def fk_initrd(request):
 
 
 @pytest.fixture(scope="function")
-def fk_kernel(request):
+def fk_kernel(request: "pytest.FixtureRequest") -> str:
     """
     The path to the first fake kernel.
 
@@ -215,7 +222,7 @@ def fk_kernel(request):
 
 
 @pytest.fixture(scope="function")
-def redhat_autoinstall():
+def redhat_autoinstall() -> str:
     """
     The path to the test.ks file for redhat autoinstall.
 
@@ -225,7 +232,7 @@ def redhat_autoinstall():
 
 
 @pytest.fixture(scope="function")
-def suse_autoyast():
+def suse_autoyast() -> str:
     """
     The path to the suse autoyast xml-file.
     :return: A path as a string.
@@ -234,7 +241,7 @@ def suse_autoyast():
 
 
 @pytest.fixture(scope="function")
-def ubuntu_preseed():
+def ubuntu_preseed() -> str:
     """
     The path to the ubuntu preseed file.
     :return: A path as a string.
diff --git a/tests/xmlrpcapi/conftest.py b/tests/xmlrpcapi/conftest.py
--- a/tests/xmlrpcapi/conftest.py
+++ b/tests/xmlrpcapi/conftest.py
@@ -1,15 +1,19 @@
 import os
 import sys
 from pathlib import Path
+from typing import Any, Callable, Dict, Tuple, Union
 
 import pytest
 
+from cobbler.api import CobblerAPI
 from cobbler.utils import get_shared_secret
 from cobbler.remote import CobblerXMLRPCInterface
 
 
 @pytest.fixture(scope="function")
-def remote(cobbler_xmlrpc_base) -> CobblerXMLRPCInterface:
+def remote(
+    cobbler_xmlrpc_base: Tuple[CobblerXMLRPCInterface, str]
+) -> CobblerXMLRPCInterface:
     """
 
     :param cobbler_xmlrpc_base:
@@ -19,7 +23,7 @@ def remote(cobbler_xmlrpc_base) -> CobblerXMLRPCInterface:
 
 
 @pytest.fixture(scope="function")
-def token(cobbler_xmlrpc_base) -> str:
+def token(cobbler_xmlrpc_base: Tuple[CobblerXMLRPCInterface, str]) -> str:
     """
 
     :param cobbler_xmlrpc_base:
@@ -29,7 +33,7 @@ def token(cobbler_xmlrpc_base) -> str:
 
 
 @pytest.fixture(scope="function")
-def cobbler_xmlrpc_base(cobbler_api):
+def cobbler_xmlrpc_base(cobbler_api: CobblerAPI):
     """
     Initialises the api object and makes it available to the test.
     """
@@ -48,15 +52,17 @@ def testsnippet() -> str:
 
 
 @pytest.fixture(scope="function")
-def snippet_add(remote, token):
-    def _snippet_add(name: str, data):
+def snippet_add(
+    remote: CobblerXMLRPCInterface, token: str
+) -> Callable[[str, str], None]:
+    def _snippet_add(name: str, data: str) -> None:
         remote.write_autoinstall_snippet(name, data, token)
 
     return _snippet_add
 
 
 @pytest.fixture(scope="function")
-def snippet_remove(remote, token):
+def snippet_remove(remote: CobblerXMLRPCInterface, token: str):
     def _snippet_remove(name: str):
         remote.remove_autoinstall_snippet(name, token)
 
@@ -64,10 +70,10 @@ def _snippet_remove(name: str):
 
 
 @pytest.fixture(scope="function")
-def create_distro(remote, token):
+def create_distro(remote: CobblerXMLRPCInterface, token: str):
     def _create_distro(
         name: str, arch: str, breed: str, path_kernel: str, path_initrd: str
-    ):
+    ) -> str:
         distro = remote.new_distro(token)
         remote.modify_distro(distro, "name", name, token)
         remote.modify_distro(distro, "arch", arch, token)
@@ -81,7 +87,7 @@ def _create_distro(
 
 
 @pytest.fixture(scope="function")
-def remove_distro(remote, token):
+def remove_distro(remote: CobblerXMLRPCInterface, token: str):
     def _remove_distro(name: str):
         remote.remove_distro(name, token)
 
@@ -89,8 +95,10 @@ def _remove_distro(name: str):
 
 
 @pytest.fixture(scope="function")
-def create_profile(remote, token):
-    def _create_profile(name, distro, kernel_options):
+def create_profile(remote: CobblerXMLRPCInterface, token: str):
+    def _create_profile(
+        name: str, distro: str, kernel_options: Union[Dict[str, Any], str]
+    ) -> str:
         profile = remote.new_profile(token)
         remote.modify_profile(profile, "name", name, token)
         remote.modify_profile(profile, "distro", distro, token)
@@ -102,16 +110,16 @@ def _create_profile(name, distro, kernel_options):
 
 
 @pytest.fixture(scope="function")
-def remove_profile(remote, token):
-    def _remove_profile(name):
+def remove_profile(remote: CobblerXMLRPCInterface, token: str):
+    def _remove_profile(name: str):
         remote.remove_profile(name, token)
 
     return _remove_profile
 
 
 @pytest.fixture(scope="function")
-def create_system(remote, token):
-    def _create_system(name, profile):
+def create_system(remote: CobblerXMLRPCInterface, token: str):
+    def _create_system(name: str, profile: str) -> str:
         system = remote.new_system(token)
         remote.modify_system(system, "name", name, token)
         remote.modify_system(system, "profile", profile, token)
@@ -122,16 +130,18 @@ def _create_system(name, profile):
 
 
 @pytest.fixture(scope="function")
-def remove_system(remote, token):
-    def _remove_system(name):
+def remove_system(remote: CobblerXMLRPCInterface, token: str):
+    def _remove_system(name: str):
         remote.remove_system(name, token)
 
     return _remove_system
 
 
 @pytest.fixture(scope="function")
-def create_file(remote, token):
-    def _create_file(name, is_directory, action, group, mode, owner, path, template):
+def create_file(remote: CobblerXMLRPCInterface, token: str):
+    def _create_file(
+        name: str, is_directory, action, group, mode, owner, path, template
+    ):
         file_id = remote.new_file(token)
 
         remote.modify_file(file_id, "name", name, token)
@@ -150,16 +160,16 @@ def _create_file(name, is_directory, action, group, mode, owner, path, template)
 
 
 @pytest.fixture(scope="function")
-def remove_file(remote, token):
-    def _remove_file(name):
+def remove_file(remote: CobblerXMLRPCInterface, token: str):
+    def _remove_file(name: str):
         remote.remove_file(name, token)
 
     return _remove_file
 
 
 @pytest.fixture()
-def create_mgmt_class(remote, token):
-    def _create_mgmt_class(name):
+def create_mgmt_class(remote: CobblerXMLRPCInterface, token: str):
+    def _create_mgmt_class(name: str):
         mgmtclass = remote.new_mgmtclass(token)
         remote.modify_mgmtclass(mgmtclass, "name", name, token)
         remote.save_mgmtclass(mgmtclass, token)
@@ -169,15 +179,15 @@ def _create_mgmt_class(name):
 
 
 @pytest.fixture(scope="function")
-def remove_mgmt_class(remote, token):
-    def _remove_mgmt_class(name):
+def remove_mgmt_class(remote: CobblerXMLRPCInterface, token: str):
+    def _remove_mgmt_class(name: str):
         remote.remove_mgmtclass(name, token)
 
     return _remove_mgmt_class
 
 
 @pytest.fixture(scope="function")
-def create_autoinstall_template(remote, token):
+def create_autoinstall_template(remote: CobblerXMLRPCInterface, token: str):
     def _create_autoinstall_template(filename, content):
         remote.write_autoinstall_template(filename, content, token)
 
@@ -185,16 +195,16 @@ def _create_autoinstall_template(filename, content):
 
 
 @pytest.fixture(scope="function")
-def remove_autoinstall_template(remote, token):
-    def _remove_autoinstall_template(name):
+def remove_autoinstall_template(remote: CobblerXMLRPCInterface, token: str):
+    def _remove_autoinstall_template(name: str):
         remote.remove_autoinstall_template(name, token)
 
     return _remove_autoinstall_template
 
 
 @pytest.fixture(scope="function")
-def create_repo(remote, token):
-    def _create_repo(name, mirror, mirror_locally):
+def create_repo(remote: CobblerXMLRPCInterface, token: str):
+    def _create_repo(name: str, mirror, mirror_locally):
         repo = remote.new_repo(token)
         remote.modify_repo(repo, "name", name, token)
         remote.modify_repo(repo, "mirror", mirror, token)
@@ -206,15 +216,15 @@ def _create_repo(name, mirror, mirror_locally):
 
 
 @pytest.fixture(scope="function")
-def remove_repo(remote, token):
-    def _remove_repo(name):
+def remove_repo(remote: CobblerXMLRPCInterface, token: str):
+    def _remove_repo(name: str):
         remote.remove_repo(name, token)
 
     return _remove_repo
 
 
 @pytest.fixture(scope="function")
-def create_menu(remote, token):
+def create_menu(remote: CobblerXMLRPCInterface, token: str):
     def _create_menu(name, display_name):
         menu_id = remote.new_menu(token)
 
@@ -228,7 +238,7 @@ def _create_menu(name, display_name):
 
 
 @pytest.fixture(scope="function")
-def remove_menu(remote, token):
+def remove_menu(remote: CobblerXMLRPCInterface, token: str):
     def _remove_menu(name):
         remote.remove_menu(name, token)
 
@@ -236,7 +246,7 @@ def _remove_menu(name):
 
 
 @pytest.fixture(scope="function")
-def create_testprofile(remote, token):
+def create_testprofile(remote: CobblerXMLRPCInterface, token):
     """
     Create a profile with the name "testprofile0"
     :param remote: See the corresponding fixture.
@@ -251,7 +261,7 @@ def create_testprofile(remote, token):
 
 
 @pytest.fixture(scope="function")
-def remove_testprofile(remote, token):
+def remove_testprofile(remote: CobblerXMLRPCInterface, token: str):
     """
     Removes the profile with the name "testprofile0".
     :param remote: See the corresponding fixture.
@@ -262,7 +272,7 @@ def remove_testprofile(remote, token):
 
 
 @pytest.fixture(scope="function")
-def remove_testdistro(remote, token):
+def remove_testdistro(remote: CobblerXMLRPCInterface, token: str):
     """
     Removes the distro "testdistro0" from the running cobbler after the test.
     :param remote: See the corresponding fixture.
@@ -273,7 +283,13 @@ def remove_testdistro(remote, token):
 
 
 @pytest.fixture(scope="function")
-def create_testdistro(remote, token, fk_kernel, fk_initrd, create_kernel_initrd):
+def create_testdistro(
+    remote: CobblerXMLRPCInterface,
+    token: str,
+    fk_kernel,
+    fk_initrd,
+    create_kernel_initrd: Callable[[str, str], str],
+):
     """
     Creates a distro "testdistro0" with the architecture "x86_64", breed "suse" and the fixtures which are setting the
     fake kernel and initrd.
@@ -293,7 +309,7 @@ def create_testdistro(remote, token, fk_kernel, fk_initrd, create_kernel_initrd)
 
 
 @pytest.fixture(scope="function")
-def create_testsystem(remote, token):
+def create_testsystem(remote: CobblerXMLRPCInterface, token: str):
     """
     Add a system with the name "testsystem0", the system is assigend to the profile "testprofile0".
     :param remote: See the corresponding fixture.
@@ -306,7 +322,7 @@ def create_testsystem(remote, token):
 
 
 @pytest.fixture()
-def remove_testsystem(remote, token):
+def remove_testsystem(remote: CobblerXMLRPCInterface, token: str):
     """
     Remove a system "testsystem0".
     :param remote: See the corresponding fixture.
@@ -317,7 +333,7 @@ def remove_testsystem(remote, token):
 
 
 @pytest.fixture(scope="function")
-def create_testrepo(remote, token):
+def create_testrepo(remote: CobblerXMLRPCInterface, token: str):
     """
     Create a testrepository with the name "testrepo0"
     :param remote: See the corresponding fixture.
@@ -331,7 +347,7 @@ def create_testrepo(remote, token):
 
 
 @pytest.fixture(scope="function")
-def remove_testrepo(remote, token):
+def remove_testrepo(remote: CobblerXMLRPCInterface, token: str):
     """
     Remove a repo "testrepo0".
     :param remote: See the corresponding fixture.
@@ -342,7 +358,7 @@ def remove_testrepo(remote, token):
 
 
 @pytest.fixture(scope="function")
-def create_testimage(remote, token):
+def create_testimage(remote: CobblerXMLRPCInterface, token: str):
     """
     Create a testrepository with the name "testimage0"
     :param remote: See the corresponding fixture.
@@ -354,7 +370,7 @@ def create_testimage(remote, token):
 
 
 @pytest.fixture(scope="function")
-def remove_testimage(remote, token):
+def remove_testimage(remote: CobblerXMLRPCInterface, token: str):
     """
     Remove the image "testimage0".
     :param remote: See the corresponding fixture.
@@ -365,7 +381,7 @@ def remove_testimage(remote, token):
 
 
 @pytest.fixture(scope="function")
-def create_testpackage(remote, token):
+def create_testpackage(remote: CobblerXMLRPCInterface, token: str):
     """
     Create a testpackage with the name "testpackage0"
     :param remote: See the corresponding fixture.
@@ -377,7 +393,7 @@ def create_testpackage(remote, token):
 
 
 @pytest.fixture(scope="function")
-def remove_testpackage(remote, token):
+def remove_testpackage(remote: CobblerXMLRPCInterface, token: str):
     """
     Remove a package "testpackage0".
     :param remote: See the corresponding fixture.
@@ -389,7 +405,7 @@ def remove_testpackage(remote, token):
 
 
 @pytest.fixture(scope="function")
-def create_testfile_item(remote, token):
+def create_testfile_item(remote: CobblerXMLRPCInterface, token: str):
     """
     Create a testfile with the name "testfile0"
     :param remote: See the corresponding fixture.
@@ -407,7 +423,7 @@ def create_testfile_item(remote, token):
 
 
 @pytest.fixture(scope="function")
-def remove_testfile(remote, token):
+def remove_testfile(remote: CobblerXMLRPCInterface, token: str):
     """
     Remove a file "testfile0".
     :param remote: See the corresponding fixture.
@@ -418,7 +434,7 @@ def remove_testfile(remote, token):
 
 
 @pytest.fixture(scope="function")
-def create_mgmtclass(remote, token):
+def create_mgmtclass(remote: CobblerXMLRPCInterface, token: str):
     """
     Create a mgmtclass with the name "mgmtclass0"
     :param remote: See the corresponding fixture.
@@ -431,7 +447,7 @@ def create_mgmtclass(remote, token):
 
 
 @pytest.fixture(scope="function")
-def remove_mgmtclass(remote, token):
+def remove_mgmtclass(remote: CobblerXMLRPCInterface, token: str):
     """
     Remove a mgmtclass "mgmtclass0".
     :param remote: See the corresponding fixture.
@@ -442,7 +458,7 @@ def remove_mgmtclass(remote, token):
 
 
 @pytest.fixture(scope="function")
-def create_testmenu(remote, token):
+def create_testmenu(remote: CobblerXMLRPCInterface, token: str):
     """
     Create a menu with the name "testmenu0"
     :param remote: See the corresponding fixture.
@@ -455,7 +471,7 @@ def create_testmenu(remote, token):
 
 
 @pytest.fixture(scope="function")
-def remove_testmenu(remote, token):
+def remove_testmenu(remote: CobblerXMLRPCInterface, token: str):
     """
     Remove a menu "testmenu0".
     :param remote: See the corresponding fixture.
@@ -466,7 +482,7 @@ def remove_testmenu(remote, token):
 
 
 @pytest.fixture(scope="function")
-def template_files(redhat_autoinstall, suse_autoyast, ubuntu_preseed):
+def template_files(redhat_autoinstall: str, suse_autoyast: str, ubuntu_preseed: str):
     """
     Create the template files and remove them afterwards.
 
diff --git a/tests/xmlrpcapi/miscellaneous_test.py b/tests/xmlrpcapi/miscellaneous_test.py
--- a/tests/xmlrpcapi/miscellaneous_test.py
+++ b/tests/xmlrpcapi/miscellaneous_test.py
@@ -2,743 +2,675 @@
 import os
 import pathlib
 import time
+from typing import Any, Callable, Dict, List, Union
 
 import pytest
+from cobbler.remote import CobblerXMLRPCInterface
 
 from cobbler.utils import get_shared_secret
 
 
-@pytest.fixture(autouse=True)
-def cleanup_clear_system_logs(remove_distro, remove_profile, remove_system):
-    yield
-    remove_system("testsystem_clearsystemlog")
-    remove_profile("testprofile_clearsystemlog")
-    remove_distro("testdistro_clearsystemlog")
+def test_clear_system_logs(
+    remote: CobblerXMLRPCInterface,
+    token: str,
+    create_kernel_initrd: Callable[[str, str], str],
+    create_distro: Callable[[str, str, str, str, str], str],
+    create_profile: Callable[[str, str, Union[Dict[str, Any], str]], str],
+    create_system: Callable[[str, str], str],
+):
+    # Arrange
+    fk_kernel = "vmlinuz1"
+    fk_initrd = "initrd1.img"
+    name_distro = "testdistro_clearsystemlog"
+    name_profile = "testprofile_clearsystemlog"
+    name_system = "testsystem_clearsystemlog"
+    basepath = create_kernel_initrd(fk_kernel, fk_initrd)
+    path_kernel = os.path.join(basepath, fk_kernel)
+    path_initrd = os.path.join(basepath, fk_initrd)
+
+    create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
+    create_profile(name_profile, name_distro, "a=1 b=2 c=3 c=4 c=5 d e")
+    system = create_system(name_system, name_profile)
+
+    # Act
+    result = remote.clear_system_logs(system, token)
+
+    # Assert
+    assert result
+
+
+def test_disable_netboot(
+    remote: CobblerXMLRPCInterface,
+    token: str,
+    create_distro: Callable[[str, str, str, str, str], str],
+    create_profile,
+    create_system,
+    create_kernel_initrd: Callable[[str, str], str],
+):
+    # Arrange
+    fk_kernel = "vmlinuz1"
+    fk_initrd = "initrd1.img"
+    name_distro = "test_distro_template_for_system"
+    name_profile = "test_profile_template_for_system"
+    name_system = "test_system_template_for_system"
+    folder = create_kernel_initrd(fk_kernel, fk_initrd)
+    path_kernel = os.path.join(folder, fk_kernel)
+    path_initrd = os.path.join(folder, fk_initrd)
+
+    create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
+    create_profile(name_profile, name_distro, "text")
+    create_system(name_system, name_profile)
+
+    # Act
+    result = remote.disable_netboot(name_system, token)
+
+    # Assert
+    assert result
+
+
+def test_extended_version(remote: CobblerXMLRPCInterface):
+    # Arrange
+
+    # Act
+    result = remote.extended_version()
+
+    # Assert Example Dict: {'builddate': 'Mon Feb 10 15:38:48 2020', 'gitdate': '?', 'gitstamp': '?', 'version':
+    #                       '3.4.0', 'version_tuple': [3, 4, 0]}
+    assert type(result) == dict
+    assert type(result.get("version_tuple")) == list
+    assert [3, 4, 0] == result.get("version_tuple")
+
+
+def test_find_items_paged(
+    remote: CobblerXMLRPCInterface,
+    token: str,
+    create_distro: Callable[[str, str, str, str, str], str],
+    create_kernel_initrd: Callable[[str, str], str],
+):
+    # Arrange
+    fk_kernel = "vmlinuz1"
+    fk_initrd = "initrd1.img"
+    folder = create_kernel_initrd(fk_kernel, fk_initrd)
+    path_kernel = os.path.join(folder, fk_kernel)
+    path_initrd = os.path.join(folder, fk_initrd)
+    name_distro_1 = "distro_items_paged_1"
+    name_distro_2 = "distro_items_paged_2"
+    create_distro(name_distro_1, "x86_64", "suse", path_kernel, path_initrd)
+    create_distro(name_distro_2, "x86_64", "suse", path_kernel, path_initrd)
+
+    # Act
+    result = remote.find_items_paged("distro", None, "name", 1, 1)
+
+    # Assert
+    # Example output
+    # {'items': [{'ctime': 1589386486.9040322, 'depth': 0, 'mtime': 1589386486.9040322, 'source_repos': [],
+    # 'tree_build_time': 0, 'uid': 'cbf288465c724c439cf2ede6c94de4e8', 'arch': 'x86_64', 'autoinstall_meta': {},
+    # 'boot_files': {}, 'boot_loaders': '<<inherit>>', 'breed': 'suse', 'comment': '', 'fetchable_files': {},
+    # 'initrd': '/var/log/cobbler/cobbler.log', 'kernel': '/var/log/cobbler/cobbler.log', 'remote_boot_initrd': '~',
+    # 'remote_boot_kernel': '~', 'kernel_options': {}, 'kernel_options_post': {}, 'mgmt_classes': [],
+    # 'name': 'distro_items_paged_1', 'os_version': 'virtio26', 'owners': ['admin'], 'redhat_management_key': '',
+    # 'template_files': {}}], 'pageinfo': {'page': 1, 'prev_page': '~', 'next_page': 2, 'pages': [1, 2],
+    # 'num_pages': 2, 'num_items': 2, 'start_item': 0, 'end_item': 1, 'items_per_page': 1,
+    # 'items_per_page_list': [10, 20, 50, 100, 200, 500]}}
+    assert type(result) == dict
+    assert type(result.get("items")) == list
+    assert "pageinfo" in result
+    assert "pages" in result["pageinfo"]
+    assert result["pageinfo"]["pages"] == [1, 2]
+
+
+@pytest.mark.skip(
+    "This functionality was implemented very quickly. The test for this needs to be fixed at a "
+    "later point!"
+)
+def test_find_system_by_dns_name(
+    remote: CobblerXMLRPCInterface,
+    token: str,
+    create_distro: Callable[[str, str, str, str, str], str],
+    create_profile,
+    create_system,
+    create_kernel_initrd: Callable[[str, str], str],
+):
+    # Arrange
+    fk_kernel = "vmlinuz1"
+    fk_initrd = "initrd1.img"
+    basepath = create_kernel_initrd(fk_kernel, fk_initrd)
+    path_kernel = os.path.join(basepath, fk_kernel)
+    path_initrd = os.path.join(basepath, fk_initrd)
+    name_distro = "test_distro_template_for_system"
+    name_profile = "test_profile_template_for_system"
+    name_system = "test_system_template_for_system"
+    dns_name = "test.cobbler-test.local"
+    create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
+    create_profile(name_profile, name_distro, "text")
+    system = create_system(name_system, name_profile)
+    remote.modify_system(system, "dns_name", dns_name, token)
+    remote.save_system(system, token)
+
+    # Act
+    result = remote.find_system_by_dns_name(dns_name)
+
+    # Assert
+    assert result
+
+
+def test_generate_script(
+    remote: CobblerXMLRPCInterface,
+    create_distro: Callable[[str, str, str, str, str], str],
+    create_profile,
+    create_kernel_initrd,
+):
+    # Arrange
+    fk_kernel = "vmlinuz1"
+    fk_initrd = "initrd1.img"
+    basepath = create_kernel_initrd(fk_kernel, fk_initrd)
+    path_kernel = os.path.join(basepath, fk_kernel)
+    path_initrd = os.path.join(basepath, fk_initrd)
+    name_distro = "test_distro_template_for_system"
+    name_profile = "test_profile_template_for_system"
+    name_autoinstall_script = "test_generate_script"
+    create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
+    create_profile(name_profile, name_distro, "text")
+    # TODO: Create Autoinstall Script
+
+    # Act
+    result = remote.generate_script(name_profile, None, name_autoinstall_script)
+
+    # Assert
+    assert result
+
+
+def test_get_item_as_rendered(
+    remote: CobblerXMLRPCInterface,
+    token: str,
+    create_distro: Callable[[str, str, str, str, str], str],
+    create_kernel_initrd,
+):
+    # Arrange
+    fk_kernel = "vmlinuz1"
+    fk_initrd = "initrd1.img"
+    basepath = create_kernel_initrd(fk_kernel, fk_initrd)
+    path_kernel = os.path.join(basepath, fk_kernel)
+    path_initrd = os.path.join(basepath, fk_initrd)
+    name = "test_item_as_rendered"
+    create_distro(name, "x86_64", "suse", path_kernel, path_initrd)
+
+    # Act
+    result = remote.get_distro_as_rendered(name, token)
+
+    # Assert
+    assert result
+
+
+def test_get_s_since(
+    remote: CobblerXMLRPCInterface,
+    create_distro: Callable[[str, str, str, str, str], str],
+    create_kernel_initrd,
+):
+    # Arrange
+    fk_kernel = "vmlinuz1"
+    fk_initrd = "initrd1.img"
+    basepath = create_kernel_initrd(fk_kernel, fk_initrd)
+    path_kernel = os.path.join(basepath, fk_kernel)
+    path_initrd = os.path.join(basepath, fk_initrd)
+    name_distro_before = "test_distro_since_before"
+    name_distro_after = "test_distro_since_after"
+    create_distro(name_distro_before, "x86_64", "suse", path_kernel, path_initrd)
+    mtime = float(time.time())
+    create_distro(name_distro_after, "x86_64", "suse", path_kernel, path_initrd)
+
+    # Act
+    result = remote.get_distros_since(mtime)
+
+    # Assert
+    assert isinstance(result, list)
+    assert len(result) == 1
+
+
+def test_get_authn_module_name(remote, token):
+    # Arrange
+
+    # Act
+    result = remote.get_authn_module_name(token)
+
+    # Assert
+    assert result
+
+
+def test_get_blended_data(
+    remote: CobblerXMLRPCInterface,
+    create_distro: Callable[[str, str, str, str, str], str],
+    create_profile,
+    create_system,
+    create_kernel_initrd,
+):
+    # Arrange
+    fk_kernel = "vmlinuz1"
+    fk_initrd = "initrd1.img"
+    basepath = create_kernel_initrd(fk_kernel, fk_initrd)
+    path_kernel = os.path.join(basepath, fk_kernel)
+    path_initrd = os.path.join(basepath, fk_initrd)
+    name_distro = "test_distro_blended"
+    name_profile = "test_profile_blended"
+    name_system = "test_system_blended"
+    create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
+    create_profile(name_profile, name_distro, "text")
+    create_system(name_system, name_profile)
+
+    # Act
+    result = remote.get_blended_data(name_profile, name_system)
+
+    # Assert
+    assert result
+
+
+def test_get_config_data(
+    remote: CobblerXMLRPCInterface,
+    token: str,
+    create_distro: Callable[[str, str, str, str, str], str],
+    create_profile,
+    create_system,
+    create_kernel_initrd,
+):
+    # Arrange
+    fk_kernel = "vmlinuz1"
+    fk_initrd = "initrd1.img"
+    basepath = create_kernel_initrd(fk_kernel, fk_initrd)
+    path_kernel = os.path.join(basepath, fk_kernel)
+    path_initrd = os.path.join(basepath, fk_initrd)
+    name_distro = "test_distro_template_for_system"
+    name_profile = "test_profile_template_for_system"
+    name_system = "test_system_template_for_system"
+    system_hostname = "testhostname"
+    create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
+    create_profile(name_profile, name_distro, "text")
+    system = create_system(name_system, name_profile)
+    remote.modify_system(system, "hostname", system_hostname, token)
+    remote.save_system(system, token)
+
+    # Act
+    result = remote.get_config_data(system_hostname)
+
+    # Assert
+    assert json.loads(result)
+
+
+def test_get_repos_compatible_with_profile(
+    remote: CobblerXMLRPCInterface,
+    token: str,
+    create_distro: Callable[[str, str, str, str, str], str],
+    create_profile,
+    create_repo,
+    create_kernel_initrd,
+):
+    # Arrange
+    fk_kernel = "vmlinuz1"
+    fk_initrd = "initrd1.img"
+    basepath = create_kernel_initrd(fk_kernel, fk_initrd)
+    path_kernel = os.path.join(basepath, fk_kernel)
+    path_initrd = os.path.join(basepath, fk_initrd)
+    name_distro = "test_distro_get_repo_for_profile"
+    name_profile = "test_profile_get_repo_for_profile"
+    name_repo_compatible = "test_repo_compatible_profile_1"
+    name_repo_incompatible = "test_repo_compatible_profile_2"
+    create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
+    create_profile(name_profile, name_distro, "text")
+    repo_compatible = create_repo(name_repo_compatible, "http://localhost", False)
+    repo_incompatible = create_repo(name_repo_incompatible, "http://localhost", False)
+    remote.modify_repo(repo_compatible, "arch", "x86_64", token)
+    remote.save_repo(repo_compatible, token)
+    remote.modify_repo(repo_incompatible, "arch", "ppc64le", token)
+    remote.save_repo(repo_incompatible, token)
+
+    # Act
+    result = remote.get_repos_compatible_with_profile(name_profile, token)
+
+    # Assert
+    assert result != []
+
+
+def test_get_status(remote: CobblerXMLRPCInterface, token: str):
+    # Arrange
+    logfile = pathlib.Path("/var/log/cobbler/install.log")
+    if logfile.exists():
+        logfile.unlink()
+
+    # Act
+    result = remote.get_status("normal", token)
+
+    # Assert
+    assert result == {}
+
+
+@pytest.mark.skip(
+    "The function under test appears to have a bug. For now we skip the test."
+)
+def test_get_template_file_for_profile(
+    remote: CobblerXMLRPCInterface,
+    create_distro: Callable[[str, str, str, str, str], str],
+    create_profile,
+    create_autoinstall_template,
+    remove_autoinstall_template,
+    create_kernel_initrd,
+):
+    # Arrange
+    fk_kernel = "vmlinuz1"
+    fk_initrd = "initrd1.img"
+    basepath = create_kernel_initrd(fk_kernel, fk_initrd)
+    path_kernel = os.path.join(basepath, fk_kernel)
+    path_initrd = os.path.join(basepath, fk_initrd)
+    name_distro = "test_distro_template_for_profile"
+    name_profile = "test_profile_template_for_profile"
+    name_template = "test_template_for_profile"
+    content_template = "# Testtemplate"
+    create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
+    create_profile(name_profile, name_distro, "text")
+    create_autoinstall_template(name_template, content_template)
+
+    # Act
+    # TODO: Fix test & functionality!
+    result = remote.get_template_file_for_profile(name_profile, name_template)
+
+    # Cleanup
+    remove_autoinstall_template(name_template)
+
+    # Assert
+    assert result == content_template
+
+
+def test_get_template_file_for_system(
+    remote: CobblerXMLRPCInterface,
+    create_distro: Callable[[str, str, str, str, str], str],
+    create_profile,
+    create_system,
+    create_autoinstall_template,
+    remove_autoinstall_template,
+    create_kernel_initrd,
+):
+    # Arrange
+    fk_kernel = "vmlinuz1"
+    fk_initrd = "initrd1.img"
+    basepath = create_kernel_initrd(fk_kernel, fk_initrd)
+    path_kernel = os.path.join(basepath, fk_kernel)
+    path_initrd = os.path.join(basepath, fk_initrd)
+    name_distro = "test_distro_template_for_system"
+    name_profile = "test_profile_template_for_system"
+    name_system = "test_system_template_for_system"
+    name_template = "test_template_for_system"
+    content_template = "# Testtemplate"
+    create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
+    create_profile(name_profile, name_distro, "text")
+    create_system(name_system, name_profile)
+    create_autoinstall_template(name_template, content_template)
+
+    # Act
+    result = remote.get_template_file_for_system(name_system, name_template)
+
+    # Cleanup
+    remove_autoinstall_template(name_template)
+
+    # Assert
+    assert result
+
+
+def test_is_autoinstall_in_use(
+    remote: CobblerXMLRPCInterface,
+    token: str,
+    create_distro: Callable[[str, str, str, str, str], str],
+    create_profile,
+    create_kernel_initrd,
+):
+    # Arrange
+    fk_kernel = "vmlinuz1"
+    fk_initrd = "initrd1.img"
+    basepath = create_kernel_initrd(fk_kernel, fk_initrd)
+    path_kernel = os.path.join(basepath, fk_kernel)
+    path_initrd = os.path.join(basepath, fk_initrd)
+    name_distro = "test_distro_is_autoinstall_in_use"
+    name_profile = "test_profile_is_autoinstall_in_use"
+    create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
+    create_profile(name_profile, name_distro, "text")
+
+    # Act
+    result = remote.is_autoinstall_in_use(name_profile, token)
+
+    # Assert
+    assert not result
+
+
+def test_logout(remote: CobblerXMLRPCInterface):
+    # Arrange
+    shared_secret = get_shared_secret()
+    newtoken = remote.login("", shared_secret)
+
+    # Act
+    resultlogout = remote.logout(newtoken)
+    resulttokencheck = remote.token_check(newtoken)
+
+    # Assert
+    assert resultlogout
+    assert not resulttokencheck
+
+
+@pytest.mark.parametrize(
+    "setting_name,input_allow_dynamic_settings,input_value,expected_result",
+    [
+        ("auth_token_expiration", True, 7200, 0),
+        ("manage_dhcp", True, True, 0),
+        ("manage_dhcp", False, True, 1),
+        ("bootloaders_ipxe_folder", True, "/my/test/folder", 0),
+        ("bootloaders_modules", True, ["fake", "bootloaders"], 0),
+        ("mongodb", True, {"host": "test", "port": 1234}, 0),
+    ],
+)
+def test_modify_setting(
+    remote: CobblerXMLRPCInterface,
+    token: str,
+    setting_name: str,
+    input_allow_dynamic_settings: bool,
+    input_value: Union[str, bool, float, int, Dict[Any, Any], List[Any]],
+    expected_result: int,
+):
+    """
+    Test that all types of settings can be successfully set or not.
+    """
+    # Arrange
+    remote.api.settings().allow_dynamic_settings = input_allow_dynamic_settings
 
+    # Act
+    result = remote.modify_setting(setting_name, input_value, token)
 
-@pytest.fixture(autouse=True)
-def cleanup_disable_netboot(remove_distro, remove_profile, remove_system):
-    yield
-    remove_system("test_distro_template_for_system")
-    remove_profile("test_profile_template_for_system")
-    remove_distro("test_system_template_for_system")
+    # Assert
+    assert result == expected_result
+    assert remote.get_settings().get(setting_name) == input_value
 
 
-@pytest.fixture(autouse=True)
-def cleanup_find_system_by_dns_name(remove_distro, remove_profile, remove_system):
-    yield
-    remove_system("test_system_template_for_system")
-    remove_profile("test_profile_template_for_system")
-    remove_distro("test_distro_template_for_system")
+def test_read_autoinstall_template(
+    remote: CobblerXMLRPCInterface,
+    token: str,
+    create_autoinstall_template,
+    remove_autoinstall_template,
+):
+    # Arrange
+    name = "test_template_name"
+    create_autoinstall_template(name, "# Testtemplate")
 
+    # Act
+    result = remote.read_autoinstall_template(name, token)
 
-@pytest.fixture(autouse=True)
-def cleanup_find_items_paged(remove_distro):
-    yield
-    remove_distro("test_distro_template_for_system")
-    remove_distro("test_system_template_for_system")
+    # Cleanup
+    remove_autoinstall_template(name)
 
+    # Assert
+    assert result
 
-@pytest.fixture(autouse=True)
-def cleanup_get_blended_data(remove_distro, remove_profile, remove_system):
-    remove_system("test_system_blended")
-    remove_profile("test_profile_blended")
-    remove_distro("test_distro_blended")
 
+def test_write_autoinstall_template(
+    remote: CobblerXMLRPCInterface, token: str, remove_autoinstall_template
+):
+    # Arrange
+    name = "testtemplate"
 
-@pytest.fixture(autouse=True)
-def cleanup_run_install_triggers(remove_distro, remove_profile, remove_system):
-    remove_system("testsystem_run_install_triggers")
-    remove_profile("testprofile_run_install_triggers")
-    remove_distro("testdistro_run_install_triggers")
+    # Act
+    result = remote.write_autoinstall_template(name, "# Testtemplate", token)
 
+    # Cleanup
+    remove_autoinstall_template(name)
 
-class TestMiscellaneous:
-    """
-    Class to test remote calls to cobbler which do not belong into a specific category.
-    """
+    # Assert
+    assert result
 
-    def test_clear_system_logs(
-        self,
-        remote,
-        token,
-        create_kernel_initrd,
-        create_distro,
-        create_profile,
-        create_system,
-        remove_distro,
-        remove_profile,
-        remove_system,
-        cleanup_clear_system_logs,
-    ):
-        # Arrange
-        fk_kernel = "vmlinuz1"
-        fk_initrd = "initrd1.img"
-        name_distro = "testdistro_clearsystemlog"
-        name_profile = "testprofile_clearsystemlog"
-        name_system = "testsystem_clearsystemlog"
-        basepath = create_kernel_initrd(fk_kernel, fk_initrd)
-        path_kernel = os.path.join(basepath, fk_kernel)
-        path_initrd = os.path.join(basepath, fk_initrd)
-
-        create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
-        create_profile(name_profile, name_distro, "a=1 b=2 c=3 c=4 c=5 d e")
-        system = create_system(name_system, name_profile)
-
-        # Act
-        result = remote.clear_system_logs(system, token)
-
-        # Assert
-        assert result
-
-    def test_disable_netboot(
-        self,
-        remote,
-        token,
-        create_distro,
-        remove_distro,
-        create_profile,
-        remove_profile,
-        create_system,
-        remove_system,
-        create_kernel_initrd,
-        cleanup_disable_netboot,
-    ):
-        # Arrange
-        fk_kernel = "vmlinuz1"
-        fk_initrd = "initrd1.img"
-        name_distro = "test_distro_template_for_system"
-        name_profile = "test_profile_template_for_system"
-        name_system = "test_system_template_for_system"
-        folder = create_kernel_initrd(fk_kernel, fk_initrd)
-        path_kernel = os.path.join(folder, fk_kernel)
-        path_initrd = os.path.join(folder, fk_initrd)
-
-        create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
-        create_profile(name_profile, name_distro, "text")
-        create_system(name_system, name_profile)
-
-        # Act
-        result = remote.disable_netboot(name_system, token)
-
-        # Assert
-        assert result
-
-    def test_extended_version(self, remote):
-        # Arrange
-
-        # Act
-        result = remote.extended_version()
-
-        # Assert Example Dict: {'builddate': 'Mon Feb 10 15:38:48 2020', 'gitdate': '?', 'gitstamp': '?', 'version':
-        #                       '3.4.0', 'version_tuple': [3, 4, 0]}
-        assert type(result) == dict
-        assert type(result.get("version_tuple")) == list
-        assert [3, 4, 0] == result.get("version_tuple")
-
-    def test_find_items_paged(
-        self,
-        remote,
-        token,
-        create_distro,
-        remove_distro,
-        create_kernel_initrd,
-        cleanup_find_items_paged,
-    ):
-        # Arrange
-        fk_kernel = "vmlinuz1"
-        fk_initrd = "initrd1.img"
-        folder = create_kernel_initrd(fk_kernel, fk_initrd)
-        path_kernel = os.path.join(folder, fk_kernel)
-        path_initrd = os.path.join(folder, fk_initrd)
-        name_distro_1 = "distro_items_paged_1"
-        name_distro_2 = "distro_items_paged_2"
-        create_distro(name_distro_1, "x86_64", "suse", path_kernel, path_initrd)
-        create_distro(name_distro_2, "x86_64", "suse", path_kernel, path_initrd)
-
-        # Act
-        result = remote.find_items_paged("distro", None, "name", 1, 1)
-
-        # Assert
-        # Example output
-        # {'items': [{'ctime': 1589386486.9040322, 'depth': 0, 'mtime': 1589386486.9040322, 'source_repos': [],
-        # 'tree_build_time': 0, 'uid': 'cbf288465c724c439cf2ede6c94de4e8', 'arch': 'x86_64', 'autoinstall_meta': {},
-        # 'boot_files': {}, 'boot_loaders': '<<inherit>>', 'breed': 'suse', 'comment': '', 'fetchable_files': {},
-        # 'initrd': '/var/log/cobbler/cobbler.log', 'kernel': '/var/log/cobbler/cobbler.log', 'remote_boot_initrd': '~',
-        # 'remote_boot_kernel': '~', 'kernel_options': {}, 'kernel_options_post': {}, 'mgmt_classes': [],
-        # 'name': 'distro_items_paged_1', 'os_version': 'virtio26', 'owners': ['admin'], 'redhat_management_key': '',
-        # 'template_files': {}}], 'pageinfo': {'page': 1, 'prev_page': '~', 'next_page': 2, 'pages': [1, 2],
-        # 'num_pages': 2, 'num_items': 2, 'start_item': 0, 'end_item': 1, 'items_per_page': 1,
-        # 'items_per_page_list': [10, 20, 50, 100, 200, 500]}}
-        assert type(result) == dict
-        assert type(result.get("items")) == list
-        assert "pageinfo" in result
-        assert "pages" in result["pageinfo"]
-        assert result["pageinfo"]["pages"] == [1, 2]
-
-    @pytest.mark.skip(
-        "This functionality was implemented very quickly. The test for this needs to be fixed at a "
-        "later point!"
-    )
-    def test_find_system_by_dns_name(
-        self,
-        remote,
-        token,
-        create_distro,
-        remove_distro,
-        create_profile,
-        remove_profile,
-        create_system,
-        remove_system,
-        create_kernel_initrd,
-        cleanup_find_system_by_dns_name,
-    ):
-        # Arrange
-        fk_kernel = "vmlinuz1"
-        fk_initrd = "initrd1.img"
-        basepath = create_kernel_initrd(fk_kernel, fk_initrd)
-        path_kernel = os.path.join(basepath, fk_kernel)
-        path_initrd = os.path.join(basepath, fk_initrd)
-        name_distro = "test_distro_template_for_system"
-        name_profile = "test_profile_template_for_system"
-        name_system = "test_system_template_for_system"
-        dns_name = "test.cobbler-test.local"
-        create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
-        create_profile(name_profile, name_distro, "text")
-        system = create_system(name_system, name_profile)
-        remote.modify_system(system, "dns_name", dns_name, token)
-        remote.save_system(system, token)
-
-        # Act
-        result = remote.find_system_by_dns_name(dns_name)
-
-        # Assert
-        assert result
-
-    def test_generate_script(
-        self,
-        remote,
-        create_distro,
-        remove_distro,
-        create_profile,
-        remove_profile,
-        create_system,
-        remove_system,
-        create_kernel_initrd,
-    ):
-        # Arrange
-        fk_kernel = "vmlinuz1"
-        fk_initrd = "initrd1.img"
-        basepath = create_kernel_initrd(fk_kernel, fk_initrd)
-        path_kernel = os.path.join(basepath, fk_kernel)
-        path_initrd = os.path.join(basepath, fk_initrd)
-        name_distro = "test_distro_template_for_system"
-        name_profile = "test_profile_template_for_system"
-        name_autoinstall_script = "test_generate_script"
-        create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
-        create_profile(name_profile, name_distro, "text")
-        # TODO: Create Autoinstall Script
-
-        # Act
-        result = remote.generate_script(name_profile, None, name_autoinstall_script)
-
-        # Cleanup
-        remove_profile(name_profile)
-        remove_distro(name_distro)
-
-        # Assert
-        assert result
-
-    def test_get_item_as_rendered(
-        self, remote, token, create_distro, remove_distro, create_kernel_initrd
-    ):
-        # Arrange
-        fk_kernel = "vmlinuz1"
-        fk_initrd = "initrd1.img"
-        basepath = create_kernel_initrd(fk_kernel, fk_initrd)
-        path_kernel = os.path.join(basepath, fk_kernel)
-        path_initrd = os.path.join(basepath, fk_initrd)
-        name = "test_item_as_rendered"
-        create_distro(name, "x86_64", "suse", path_kernel, path_initrd)
-
-        # Act
-        result = remote.get_distro_as_rendered(name, token)
-
-        # Cleanup
-        remove_distro(name)
-
-        # Assert
-        assert result
-
-    def test_get_s_since(
-        self, remote, create_distro, remove_distro, create_kernel_initrd
-    ):
-        # Arrange
-        fk_kernel = "vmlinuz1"
-        fk_initrd = "initrd1.img"
-        basepath = create_kernel_initrd(fk_kernel, fk_initrd)
-        path_kernel = os.path.join(basepath, fk_kernel)
-        path_initrd = os.path.join(basepath, fk_initrd)
-        name_distro_before = "test_distro_since_before"
-        name_distro_after = "test_distro_since_after"
-        create_distro(name_distro_before, "x86_64", "suse", path_kernel, path_initrd)
-        mtime = float(time.time())
-        create_distro(name_distro_after, "x86_64", "suse", path_kernel, path_initrd)
-
-        # Act
-        result = remote.get_distros_since(mtime)
-
-        # Cleanup
-        remove_distro(name_distro_before)
-        remove_distro(name_distro_after)
-
-        # Assert
-        assert isinstance(result, list)
-        assert len(result) == 1
-
-    def test_get_authn_module_name(self, remote, token):
-        # Arrange
-
-        # Act
-        result = remote.get_authn_module_name(token)
-
-        # Assert
-        assert result
-
-    def test_get_blended_data(
-        self,
-        remote,
-        create_distro,
-        create_profile,
-        create_system,
-        create_kernel_initrd,
-        cleanup_get_blended_data,
-    ):
-        # Arrange
-        fk_kernel = "vmlinuz1"
-        fk_initrd = "initrd1.img"
-        basepath = create_kernel_initrd(fk_kernel, fk_initrd)
-        path_kernel = os.path.join(basepath, fk_kernel)
-        path_initrd = os.path.join(basepath, fk_initrd)
-        name_distro = "test_distro_blended"
-        name_profile = "test_profile_blended"
-        name_system = "test_system_blended"
-        create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
-        create_profile(name_profile, name_distro, "text")
-        create_system(name_system, name_profile)
-
-        # Act
-        result = remote.get_blended_data(name_profile, name_system)
-
-        # Assert
-        assert result
-
-    def test_get_config_data(
-        self,
-        remote,
-        token,
-        create_distro,
-        remove_distro,
-        create_profile,
-        remove_profile,
-        create_system,
-        remove_system,
-        create_kernel_initrd,
-    ):
-        # Arrange
-        fk_kernel = "vmlinuz1"
-        fk_initrd = "initrd1.img"
-        basepath = create_kernel_initrd(fk_kernel, fk_initrd)
-        path_kernel = os.path.join(basepath, fk_kernel)
-        path_initrd = os.path.join(basepath, fk_initrd)
-        name_distro = "test_distro_template_for_system"
-        name_profile = "test_profile_template_for_system"
-        name_system = "test_system_template_for_system"
-        system_hostname = "testhostname"
-        create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
-        create_profile(name_profile, name_distro, "text")
-        system = create_system(name_system, name_profile)
-        remote.modify_system(system, "hostname", system_hostname, token)
-        remote.save_system(system, token)
-
-        # Act
-        result = remote.get_config_data(system_hostname)
-
-        # Cleanup
-        remove_system(name_system)
-        remove_profile(name_profile)
-        remove_distro(name_distro)
-
-        # Assert
-        assert json.loads(result)
-
-    def test_get_repos_compatible_with_profile(
-        self,
-        remote,
-        token,
-        create_distro,
-        remove_distro,
-        create_profile,
-        remove_profile,
-        create_repo,
-        remove_repo,
-        create_kernel_initrd,
-    ):
-        # Arrange
-        fk_kernel = "vmlinuz1"
-        fk_initrd = "initrd1.img"
-        basepath = create_kernel_initrd(fk_kernel, fk_initrd)
-        path_kernel = os.path.join(basepath, fk_kernel)
-        path_initrd = os.path.join(basepath, fk_initrd)
-        name_distro = "test_distro_get_repo_for_profile"
-        name_profile = "test_profile_get_repo_for_profile"
-        name_repo_compatible = "test_repo_compatible_profile_1"
-        name_repo_incompatible = "test_repo_compatible_profile_2"
-        create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
-        create_profile(name_profile, name_distro, "text")
-        repo_compatible = create_repo(name_repo_compatible, "http://localhost", False)
-        repo_incompatible = create_repo(
-            name_repo_incompatible, "http://localhost", False
-        )
-        remote.modify_repo(repo_compatible, "arch", "x86_64", token)
-        remote.save_repo(repo_compatible, token)
-        remote.modify_repo(repo_incompatible, "arch", "ppc64le", token)
-        remote.save_repo(repo_incompatible, token)
-
-        # Act
-        result = remote.get_repos_compatible_with_profile(name_profile, token)
-
-        # Cleanup
-        remove_profile(name_profile)
-        remove_distro(name_distro)
-        remove_repo(name_repo_compatible)
-        remove_repo(name_repo_incompatible)
-
-        # Assert
-        assert result != []
-
-    def test_get_status(self, remote, token):
-        # Arrange
-        logfile = pathlib.Path("/var/log/cobbler/install.log")
-        if logfile.exists():
-            logfile.unlink()
-
-        # Act
-        result = remote.get_status("normal", token)
-
-        # Assert
-        assert result == {}
-
-    @pytest.mark.skip(
-        "The function under test appears to have a bug. For now we skip the test."
-    )
-    def test_get_template_file_for_profile(
-        self,
-        remote,
-        create_distro,
-        remove_distro,
-        create_profile,
-        remove_profile,
-        create_autoinstall_template,
-        remove_autoinstall_template,
-        create_kernel_initrd,
-    ):
-        # Arrange
-        fk_kernel = "vmlinuz1"
-        fk_initrd = "initrd1.img"
-        basepath = create_kernel_initrd(fk_kernel, fk_initrd)
-        path_kernel = os.path.join(basepath, fk_kernel)
-        path_initrd = os.path.join(basepath, fk_initrd)
-        name_distro = "test_distro_template_for_profile"
-        name_profile = "test_profile_template_for_profile"
-        name_template = "test_template_for_profile"
-        content_template = "# Testtemplate"
-        create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
-        create_profile(name_profile, name_distro, "text")
-        create_autoinstall_template(name_template, content_template)
-
-        # Act
-        # TODO: Fix test & functionality!
-        result = remote.get_template_file_for_profile(name_profile, name_template)
-
-        # Cleanup
-        remove_profile(name_profile)
-        remove_distro(name_distro)
-        remove_autoinstall_template(name_template)
-
-        # Assert
-        assert result == content_template
-
-    def test_get_template_file_for_system(
-        self,
-        remote,
-        create_distro,
-        remove_distro,
-        create_profile,
-        remove_profile,
-        create_system,
-        remove_system,
-        create_autoinstall_template,
-        remove_autoinstall_template,
-        create_kernel_initrd,
-    ):
-        # Arrange
-        fk_kernel = "vmlinuz1"
-        fk_initrd = "initrd1.img"
-        basepath = create_kernel_initrd(fk_kernel, fk_initrd)
-        path_kernel = os.path.join(basepath, fk_kernel)
-        path_initrd = os.path.join(basepath, fk_initrd)
-        name_distro = "test_distro_template_for_system"
-        name_profile = "test_profile_template_for_system"
-        name_system = "test_system_template_for_system"
-        name_template = "test_template_for_system"
-        content_template = "# Testtemplate"
-        create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
-        create_profile(name_profile, name_distro, "text")
-        create_system(name_system, name_profile)
-        create_autoinstall_template(name_template, content_template)
-
-        # Act
-        result = remote.get_template_file_for_system(name_system, name_template)
-
-        # Cleanup
-        remove_system(name_system)
-        remove_profile(name_profile)
-        remove_distro(name_distro)
-        remove_autoinstall_template(name_template)
-
-        # Assert
-        assert result
-
-    def test_is_autoinstall_in_use(
-        self,
-        remote,
-        token,
-        create_distro,
-        remove_distro,
-        create_profile,
-        remove_profile,
-        create_kernel_initrd,
-    ):
-        # Arrange
-        fk_kernel = "vmlinuz1"
-        fk_initrd = "initrd1.img"
-        basepath = create_kernel_initrd(fk_kernel, fk_initrd)
-        path_kernel = os.path.join(basepath, fk_kernel)
-        path_initrd = os.path.join(basepath, fk_initrd)
-        name_distro = "test_distro_is_autoinstall_in_use"
-        name_profile = "test_profile_is_autoinstall_in_use"
-        create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
-        create_profile(name_profile, name_distro, "text")
-
-        # Act
-        result = remote.is_autoinstall_in_use(name_profile, token)
-
-        # Cleanup
-        remove_profile(name_profile)
-        remove_distro(name_distro)
-
-        # Assert
-        assert not result
-
-    def test_logout(self, remote):
-        # Arrange
-        shared_secret = get_shared_secret()
-        newtoken = remote.login("", shared_secret)
-
-        # Act
-        resultlogout = remote.logout(newtoken)
-        resulttokencheck = remote.token_check(newtoken)
-
-        # Assert
-        assert resultlogout
-        assert not resulttokencheck
-
-    def test_modify_setting(self, remote, token):
-        # Arrange
-
-        # Act
-        result = remote.modify_setting("auth_token_expiration", 7200, token)
-
-        # Assert
-        assert result == 1
-
-    def test_read_autoinstall_template(
-        self, remote, token, create_autoinstall_template, remove_autoinstall_template
-    ):
-        # Arrange
-        name = "test_template_name"
-        create_autoinstall_template(name, "# Testtemplate")
-
-        # Act
-        result = remote.read_autoinstall_template(name, token)
-
-        # Cleanup
-        remove_autoinstall_template(name)
-
-        # Assert
-        assert result
-
-    def test_write_autoinstall_template(
-        self, remote, token, remove_autoinstall_template
-    ):
-        # Arrange
-        name = "testtemplate"
-
-        # Act
-        result = remote.write_autoinstall_template(name, "# Testtemplate", token)
-
-        # Cleanup
-        remove_autoinstall_template(name)
-
-        # Assert
-        assert result
-
-    def test_remove_autoinstall_template(
-        self, remote, token, create_autoinstall_template
-    ):
-        # Arrange
-        name = "test_template_remove"
-        create_autoinstall_template(name, "# Testtemplate")
-
-        # Act
-        result = remote.remove_autoinstall_template(name, token)
-
-        # Assert
-        assert result
-
-    def test_read_autoinstall_snippet(
-        self, remote, token, testsnippet, snippet_add, snippet_remove
-    ):
-        # Arrange
-        snippet_name = "testsnippet_read"
-        snippet_add(snippet_name, testsnippet)
-
-        # Act
-        result = remote.read_autoinstall_snippet(snippet_name, token)
-
-        # Assert
-        assert result == testsnippet
-
-        # Cleanup
-        snippet_remove(snippet_name)
-
-    def test_write_autoinstall_snippet(
-        self, remote, token, testsnippet, snippet_remove
-    ):
-        # Arrange
-        # See fixture: testsnippet
-        name = "testsnippet_write"
-
-        # Act
-        result = remote.write_autoinstall_snippet(name, testsnippet, token)
-
-        # Assert
-        assert result
-
-        # Cleanup
-        snippet_remove(name)
-
-    def test_remove_autoinstall_snippet(self, remote, token, snippet_add, testsnippet):
-        # Arrange
-        name = "testsnippet_remove"
-        snippet_add(name, testsnippet)
-
-        # Act
-        result = remote.remove_autoinstall_snippet(name, token)
-
-        # Assert
-        assert result
-
-    def test_run_install_triggers(
-        self,
-        remote,
-        token,
-        create_kernel_initrd,
-        create_distro,
-        create_profile,
-        create_system,
-        cleanup_run_install_triggers,
-    ):
-        # Arrange
-        fk_kernel = "vmlinuz1"
-        fk_initrd = "initrd1.img"
-        name_distro = "testdistro_run_install_triggers"
-        name_profile = "testprofile_run_install_triggers"
-        name_system = "testsystem_run_install_triggers"
-        basepath = create_kernel_initrd(fk_kernel, fk_initrd)
-        path_kernel = os.path.join(basepath, fk_kernel)
-        path_initrd = os.path.join(basepath, fk_initrd)
-
-        create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
-        create_profile(name_profile, name_distro, "a=1 b=2 c=3 c=4 c=5 d e")
-        create_system(name_system, name_profile)
-
-        # Act
-        result_pre = remote.run_install_triggers(
-            "pre", "system", name_system, "10.0.0.2", token
-        )
-        result_post = remote.run_install_triggers(
-            "post", "system", name_system, "10.0.0.2", token
-        )
-
-        # Assert
-        assert result_pre
-        assert result_post
-
-    def test_version(self, remote):
-        # Arrange
-
-        # Act
-        result = remote.version()
-
-        # Assert
-        # Will fail if the version is adjusted in the setup.py
-        assert result == 3.4
-
-    @pytest.mark.usefixtures(
-        "create_testdistro",
-        "create_testmenu",
-        "create_profile",
-        "remove_testdistro",
-        "remove_testmenu",
-        "remove_testprofile",
+
+def test_remove_autoinstall_template(
+    remote: CobblerXMLRPCInterface, token: str, create_autoinstall_template
+):
+    # Arrange
+    name = "test_template_remove"
+    create_autoinstall_template(name, "# Testtemplate")
+
+    # Act
+    result = remote.remove_autoinstall_template(name, token)
+
+    # Assert
+    assert result
+
+
+def test_read_autoinstall_snippet(
+    remote: CobblerXMLRPCInterface, token: str, testsnippet, snippet_add, snippet_remove
+):
+    # Arrange
+    snippet_name = "testsnippet_read"
+    snippet_add(snippet_name, testsnippet)
+
+    # Act
+    result = remote.read_autoinstall_snippet(snippet_name, token)
+
+    # Assert
+    assert result == testsnippet
+
+    # Cleanup
+    snippet_remove(snippet_name)
+
+
+def test_write_autoinstall_snippet(
+    remote: CobblerXMLRPCInterface, token: str, testsnippet, snippet_remove
+):
+    # Arrange
+    # See fixture: testsnippet
+    name = "testsnippet_write"
+
+    # Act
+    result = remote.write_autoinstall_snippet(name, testsnippet, token)
+
+    # Assert
+    assert result
+
+    # Cleanup
+    snippet_remove(name)
+
+
+def test_remove_autoinstall_snippet(
+    remote: CobblerXMLRPCInterface, token: str, snippet_add, testsnippet
+):
+    # Arrange
+    name = "testsnippet_remove"
+    snippet_add(name, testsnippet)
+
+    # Act
+    result = remote.remove_autoinstall_snippet(name, token)
+
+    # Assert
+    assert result
+
+
+def test_run_install_triggers(
+    remote: CobblerXMLRPCInterface,
+    token: str,
+    create_kernel_initrd,
+    create_distro: Callable[[str, str, str, str, str], str],
+    create_profile,
+    create_system,
+):
+    # Arrange
+    fk_kernel = "vmlinuz1"
+    fk_initrd = "initrd1.img"
+    name_distro = "testdistro_run_install_triggers"
+    name_profile = "testprofile_run_install_triggers"
+    name_system = "testsystem_run_install_triggers"
+    basepath = create_kernel_initrd(fk_kernel, fk_initrd)
+    path_kernel = os.path.join(basepath, fk_kernel)
+    path_initrd = os.path.join(basepath, fk_initrd)
+
+    create_distro(name_distro, "x86_64", "suse", path_kernel, path_initrd)
+    create_profile(name_profile, name_distro, "a=1 b=2 c=3 c=4 c=5 d e")
+    create_system(name_system, name_profile)
+
+    # Act
+    result_pre = remote.run_install_triggers(
+        "pre", "system", name_system, "10.0.0.2", token
     )
-    def test_render_vars(self, remote, token):
-        """
-        Test: string replacements for @@xyz@@
-        """
-
-        # Arrange --> There is nothing to be arranged
-        kernel_options = "tree=http://@@http_server@@/cblr/links/@@distro_name@@"
-
-        # Act
-        distro = remote.get_item_handle("distro", "testdistro0")
-        remote.modify_distro(distro, "kernel_options", kernel_options, token)
-        remote.save_distro(distro, token)
-
-        # Assert --> Let the test pass if the call is okay.
-        assert True
-
-    @pytest.mark.skip("Functionality is broken!")
-    @pytest.mark.usefixtures(
-        "create_testdistro",
-        "create_testmenu",
-        "create_testprofile",
-        "create_testsystem",
-        "remove_testdistro",
-        "remove_testmenu",
-        "remove_testprofile",
-        "remove_testsystem",
+    result_post = remote.run_install_triggers(
+        "post", "system", name_system, "10.0.0.2", token
     )
-    def test_upload_log_data(self, remote):
-        # Arrange
 
-        # Act
-        result = remote.upload_log_data(
-            "testsystem0", "testinstall.log", 0, 0, b"asdas"
-        )
+    # Assert
+    assert result_pre
+    assert result_post
+
+
+def test_version(remote: CobblerXMLRPCInterface):
+    # Arrange
+
+    # Act
+    result = remote.version()
+
+    # Assert
+    # Will fail if the version is adjusted in the setup.py
+    assert result == 3.4
+
+
+@pytest.mark.usefixtures(
+    "create_testdistro",
+    "create_testmenu",
+    "create_profile",
+    "remove_testdistro",
+    "remove_testmenu",
+    "remove_testprofile",
+)
+def test_render_vars(remote: CobblerXMLRPCInterface, token: str):
+    """
+    Test: string replacements for @@xyz@@
+    """
 
-        # Assert
-        assert isinstance(result, bool)
-        assert result
+    # Arrange --> There is nothing to be arranged
+    kernel_options = "tree=http://@@http_server@@/cblr/links/@@distro_name@@"
+
+    # Act
+    distro = remote.get_item_handle("distro", "testdistro0")
+    remote.modify_distro(distro, "kernel_options", kernel_options, token)
+    remote.save_distro(distro, token)
+
+    # Assert --> Let the test pass if the call is okay.
+    assert True
+
+
+@pytest.mark.skip("Functionality is broken!")
+@pytest.mark.usefixtures(
+    "create_testdistro",
+    "create_testmenu",
+    "create_testprofile",
+    "create_testsystem",
+    "remove_testdistro",
+    "remove_testmenu",
+    "remove_testprofile",
+    "remove_testsystem",
+)
+def test_upload_log_data(remote: CobblerXMLRPCInterface):
+    # Arrange
+
+    # Act
+    result = remote.upload_log_data("testsystem0", "testinstall.log", 0, 0, b"asdas")
+
+    # Assert
+    assert isinstance(result, bool)
+    assert result