Repository: cobbler/cobbler

Issue:
Buildiso: `isolinux.cfg` not correctly formatted
### Describe the bug

The content of the `isolinux.cfg` file is not formatted correctly when using `cobbler buildiso`. There are whitespaces and newlines missing.

```bash
cob-srv:/var/cache/cobbler # cobbler distro list
   testdistro
cob-srv:/var/cache/cobbler # cobbler profile list
   testprofile
   testprofile1
   testprofile2
cob-srv:/var/cache/cobbler # cat /var/cache/cobbler/buildiso/isolinux/isolinux.cfg 
DEFAULT menu
PROMPT 0
MENU TITLE Cobbler | https://cobbler.github.io
TIMEOUT 200
TOTALTIMEOUT 6000
ONTIMEOUT local

LABEL local
        MENU LABEL (local)
        MENU DEFAULT
        KERNEL chain.c32
        APPEND hd0 0
LABEL testprofile  MENU LABEL testprofile  kernel 1.krn append initrd=1.img install=http://cob-srv.tf.local:80/cblr/links/1 autoyast=http://cob-srv.tf.local:80/cblr/svc/op/autoinstall/profile/testprofileLABEL testprofile1  MENU LABEL testprofile1  kernel 1.krn append initrd=1.img install=http://cob-srv.tf.local:80/cblr/links/1 autoyast=http://cob-srv.tf.local:80/cblr/svc/op/autoinstall/profile/testprofile1LABEL testprofile2  MENU LABEL testprofile2  kernel 1.krn append initrd=1.img install=http://cob-srv.tf.local:80/cblr/links/1 autoyast=http://cob-srv.tf.local:80/cblr/svc/op/autoinstall/profile/testprofile2MENU SEPARATORMENU END
cob-srv:/var/cache/cobbler #
```

### Steps to reproduce

1. Run cobbler `buildiso --tempdir=/var/cache/cobbler/buildiso --distro=testdistro`
2. Have a look at the `isolinux.cfg` file inside `/var/cache/cobbler/buildiso/isolinux`



### Expected behavior

The `isolinux.cfg` file should be formatted correctly.

### Cobbler version


````bash
cobbler version
 Cobbler 3.3.2
  source: ?, ?
  build time: Tue Mar 15 12:00:00 2022
````

### Operating system

```bash
cat /etc/os-release 
NAME="SLES"
VERSION="15-SP4"
VERSION_ID="15.4"
PRETTY_NAME="SUSE Linux Enterprise Server 15 SP4"
ID="sles"
ID_LIKE="suse"
ANSI_COLOR="0;32"
CPE_NAME="cpe:/o:suse:sles:15:sp4"
DOCUMENTATION_URL="https://documentation.suse.com/"
```

### Cobbler log

<!--- Paste (partial) output from `/var/log/cobbler/cobbler.log` -->
````bash
[Thread-76] 2022-03-15T16:31:41 - INFO | REMOTE start_task(Build Iso); event_id(2022-03-15_163141_buildiso); user(?)
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - DEBUG | running python triggers from /var/lib/cobbler/triggers/task/buildiso/pre/*
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - DEBUG | running shell triggers from /var/lib/cobbler/triggers/task/buildiso/pre/*
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - DEBUG | shell triggers finished successfully
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - INFO | Deleting and recreating the buildisodir at "/var/cache/cobbler/buildiso"
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - INFO | building tree for isolinux
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - INFO | building tree for GRUB 2
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - INFO | copying syslinux files
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - INFO | copying: /usr/share/syslinux/isolinux.bin -> /var/cache/cobbler/buildiso/isolinux/isolinux.bin
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - INFO | copying: /usr/share/syslinux/menu.c32 -> /var/cache/cobbler/buildiso/isolinux/menu.c32
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - INFO | copying: /usr/share/syslinux/chain.c32 -> /var/cache/cobbler/buildiso/isolinux/chain.c32
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - INFO | copying GRUB2 files
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - INFO | copying: /var/lib/cobbler/loaders/grub/grubx86.efi -> /var/cache/cobbler/buildiso/grub/grub.efi
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - INFO | Processing profile: "testprofile"
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - INFO | copying kernels and initrds for standalone distro
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - INFO | Processing profile: "testprofile1"
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - INFO | copying kernels and initrds for standalone distro
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - INFO | Processing profile: "testprofile2"
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - INFO | copying kernels and initrds for standalone distro
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - INFO | running: xorriso -as mkisofs  -isohybrid-mbr /usr/share/syslinux/isohdpfx.bin -c isolinux/boot.cat -b isolinux/isolinux.bin -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot -e grub/grub.efi -no-emul-boot -isohybrid-gpt-basdat -V "COBBLER_INSTALL" -o /var/cache/cobbler/profile_all.iso /var/cache/cobbler/buildiso
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - INFO | received on stdout:
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - DEBUG | received on stderr: xorriso 1.4.6 : RockRidge filesystem manipulator, libburnia project.

Drive current: -outdev 'stdio:/var/cache/cobbler/profile_all.iso'
Media current: stdio file, overwriteable
Media status : is blank
Media summary: 0 sessions, 0 data blocks, 0 data,  195g free
Added to ISO image: directory '/'='/var/cache/cobbler/buildiso'
xorriso : UPDATE : 9 files added in 1 seconds
xorriso : UPDATE : 9 files added in 1 seconds
xorriso : NOTE : Copying to System Area: 432 bytes from file '/usr/share/syslinux/isohdpfx.bin'
libisofs: NOTE : Aligned image size to cylinder size by 136 blocks
ISO image produced: 1024 sectors
Written to medium : 1024 sectors at LBA 0
Writing to 'stdio:/var/cache/cobbler/profile_all.iso' completed successfully.


[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - INFO | ISO build complete
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - INFO | You may wish to delete: /var/cache/cobbler/buildiso
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - INFO | The output file is: /var/cache/cobbler/profile_all.iso
[2022-03-15_163141_buildiso] 2022-03-15T16:31:42 - INFO | ### TASK COMPLETE ###
````


Discussion:

Resolving patch:
diff --git a/cobbler/actions/buildiso/netboot.py b/cobbler/actions/buildiso/netboot.py
--- a/cobbler/actions/buildiso/netboot.py
+++ b/cobbler/actions/buildiso/netboot.py
@@ -348,7 +348,7 @@ def generate_system(self, dist, system, exclude_dns: bool) -> str:
         """
         self.dist = dist
 
-        self.append_line = " append initrd=%s.img" % self.distro_name
+        self.append_line = "  APPEND initrd=%s.img" % self.distro_name
         if self.dist.breed == "suse":
             self._generate_append_suse()
         elif self.dist.breed == "redhat":
@@ -463,7 +463,7 @@ def _generate_netboot_system(self, system, cfglines: List[str], exclude_dns: boo
         cfglines.append("")
         cfglines.append("LABEL %s" % system.name)
         cfglines.append("  MENU LABEL %s" % system.name)
-        cfglines.append("  kernel %s.krn" % distname)
+        cfglines.append("  KERNEL %s.krn" % distname)
 
         data = utils.blender(self.api, False, system)
         if not re.match(r"[a-z]+://.*", data["autoinstall"]):
@@ -536,7 +536,7 @@ def generate_netboot_iso(
         cfglines.append("MENU END")
 
         with open(isolinuxcfg, "w+") as cfg:
-            cfg.writelines(cfglines)
+            cfg.writelines("%s\n" % l for l in cfglines)
 
     def run(
         self,
diff --git a/cobbler/actions/buildiso/standalone.py b/cobbler/actions/buildiso/standalone.py
--- a/cobbler/actions/buildiso/standalone.py
+++ b/cobbler/actions/buildiso/standalone.py
@@ -23,7 +23,7 @@ def _generate_append_line_standalone(data: dict, distro, descendant) -> str:
     :param descendant: The profile or system which is underneath the distro.
     :return: The base append_line which we need for booting the built ISO. Contains initrd and autoinstall parameter.
     """
-    append_line = "  append initrd=%s" % os.path.basename(distro.initrd)
+    append_line = "  APPEND initrd=%s" % os.path.basename(distro.initrd)
     if distro.breed == "redhat":
         append_line += " inst.ks=cdrom:/isolinux/%s.cfg" % descendant.name
     elif distro.breed == "suse":
@@ -236,7 +236,7 @@ def _generate_descendant(
         if menu_indent:
             cfglines.append("  MENU INDENT %d" % menu_indent)
         cfglines.append("  MENU LABEL %s" % descendant.name)
-        cfglines.append("  kernel %s" % os.path.basename(distro.kernel))
+        cfglines.append("  KERNEL %s" % os.path.basename(distro.kernel))
 
         cfglines.append(_generate_append_line_standalone(data, distro, descendant))
 
@@ -291,11 +291,11 @@ def generate_standalone_iso(
                 descendant, cfglines, distro, airgapped, repo_names_to_copy
             )
 
-        self.logger.info("done writing config")
         cfglines.append("")
         cfglines.append("MENU END")
         with open(os.path.join(self.isolinuxdir, "isolinux.cfg"), "w+") as cfg:
-            cfg.writelines(cfglines)
+            cfg.writelines("%s\n" % l for l in cfglines)
+        self.logger.info("done writing config")
 
         self._sync_airgapped_repos(airgapped, repo_names_to_copy)
 


Test patch: