Repository: cobbler/cobbler

Issue:
boot.cfg file generation on tftproot for esxi systems fail 
### Describe the bug

Cobbler fails for esxi systems on sync, `/var/lib/tftpboot/esxi/system` directory does not exist.
I think previous `mkdir` from `filesystem_helpers` would create any parent directory if it didn't exist.
Also looks to me that distro `boot_files` are not being copied to tftproot (just kernel and initrd).

### Steps to reproduce

1. run cobbler sync with esxi distro and system

### Expected behavior

`boot.cfg` files for each esxi system are created.

### Cobbler version

````
Cobbler 3.4.0
  source: b71c2031, Wed Aug 24 16:49:38 2022 +0200
  build time: Wed Aug 24 21:44:01 2022
````

### Operating system

Centos 8 Stream

### Cobbler log

<!--- Paste (partial) output from `/var/log/cobbler/cobbler.log` -->
````
Aug 25 07:29:38 centos8-build cobblerd[2238]: INFO | generating PXE configuration files
Aug 25 07:29:38 centos8-build cobblerd[2238]: INFO | generating: /var/lib/tftpboot/esxi/system/01-52-54-00-54-de-11/boot.cfg
Aug 25 07:29:38 centos8-build cobblerd[2238]: INFO | Exception occurred: <class 'FileNotFoundError'>
Aug 25 07:29:38 centos8-build cobblerd[2238]: INFO | Exception value: [Errno 2] No such file or directory: '/var/lib/tftpboot/esxi/system/01-52-54-00-54-de-11'
Aug 25 07:29:38 centos8-build cobblerd[2238]: INFO | Exception Info:
Aug 25 07:29:38 centos8-build cobblerd[2238]:  File "/usr/local/lib/python3.6/site-packages/cobbler/utils/filesystem_helpers.py", line 326, in mkdir
Aug 25 07:29:38 centos8-build cobblerd[2238]:    pathlib.Path(path).mkdir(mode=mode)
Aug 25 07:29:38 centos8-build cobblerd[2238]:  File "/usr/lib64/python3.6/pathlib.py", line 1248, in mkdir
Aug 25 07:29:38 centos8-build cobblerd[2238]:    self._accessor.mkdir(self, mode)
Aug 25 07:29:38 centos8-build cobblerd[2238]:  File "/usr/lib64/python3.6/pathlib.py", line 387, in wrapped
Aug 25 07:29:38 centos8-build cobblerd[2238]:    return strfunc(str(pathobj), *args)
Aug 25 07:29:38 centos8-build cobblerd[2238]: INFO | Exception occurred: <class 'cobbler.cexceptions.CX'>
Aug 25 07:29:38 centos8-build cobblerd[2238]: INFO | Exception value: 'Error creating /var/lib/tftpboot/esxi/system/01-52-54-00-54-de-11'
Aug 25 07:29:38 centos8-build cobblerd[2238]: INFO | Exception Info:
Aug 25 07:29:38 centos8-build cobblerd[2238]:  File "/usr/local/lib/python3.6/site-packages/cobbler/remote.py", line 100, in run
Aug 25 07:29:38 centos8-build cobblerd[2238]:    rc = self._run(self)
Aug 25 07:29:38 centos8-build cobblerd[2238]:  File "/usr/local/lib/python3.6/site-packages/cobbler/remote.py", line 227, in runner
Aug 25 07:29:38 centos8-build cobblerd[2238]:    self.remote.api.sync(self.options.get("verbose", False), what=what)
Aug 25 07:29:38 centos8-build cobblerd[2238]:  File "/usr/local/lib/python3.6/site-packages/cobbler/api.py", line 1832, in sync
Aug 25 07:29:38 centos8-build cobblerd[2238]:    sync_obj.run()
Aug 25 07:29:38 centos8-build cobblerd[2238]:  File "/usr/local/lib/python3.6/site-packages/cobbler/actions/sync.py", line 126, in run
Aug 25 07:29:38 centos8-build cobblerd[2238]:    self.tftpd.sync(self.verbose)
Aug 25 07:29:38 centos8-build cobblerd[2238]:  File "/usr/local/lib/python3.6/site-packages/cobbler/modules/managers/in_tftpd.py", line 184, in sync
Aug 25 07:29:38 centos8-build cobblerd[2238]:    self.tftpgen.write_all_system_files(system, menu_items)
Aug 25 07:29:38 centos8-build cobblerd[2238]:  File "/usr/local/lib/python3.6/site-packages/cobbler/tftpgen.py", line 313, in write_all_system_files
Aug 25 07:29:38 centos8-build cobblerd[2238]:    metadata=pxe_metadata,
Aug 25 07:29:38 centos8-build cobblerd[2238]:  File "/usr/local/lib/python3.6/site-packages/cobbler/tftpgen.py", line 822, in write_pxe_file
Aug 25 07:29:38 centos8-build cobblerd[2238]:    self._write_bootcfg_file("system", system.name, bootcfg_path)
Aug 25 07:29:38 centos8-build cobblerd[2238]:  File "/usr/local/lib/python3.6/site-packages/cobbler/tftpgen.py", line 1559, in _write_bootcfg_file
Aug 25 07:29:38 centos8-build cobblerd[2238]:    filesystem_helpers.mkdir(os.path.dirname(bootcfg_path))
Aug 25 07:29:38 centos8-build cobblerd[2238]:  File "/usr/local/lib/python3.6/site-packages/cobbler/utils/filesystem_helpers.py", line 331, in mkdir
Aug 25 07:29:38 centos8-build cobblerd[2238]:    raise CX("Error creating %s" % path) from os_error
Aug 25 07:29:38 centos8-build cobblerd[2238]: ERROR | ### TASK FAILED ###
````

### Screenshots

### Additional information

@SchoolGuy I will try to have a look at this later on the day


Discussion:
Well... I refactored it and messed it up. So I shall fix it before the stable release...
P.S.: If you can of course fix it, then that would be even better! :)

Resolving patch:
diff --git a/cobbler/actions/sync.py b/cobbler/actions/sync.py
--- a/cobbler/actions/sync.py
+++ b/cobbler/actions/sync.py
@@ -193,13 +193,16 @@ def clean_trees(self):
                 ]:
                     # clean out directory contents
                     filesystem_helpers.rmtree_contents(path)
+        for directory in [
+            self.pxelinux_dir,
+            self.grub_dir,
+            self.images_dir,
+            self.ipxe_dir,
+            self.esxi_dir,
+            self.rendered_dir,
+        ]:
+            filesystem_helpers.rmtree(directory)
         filesystem_helpers.create_tftpboot_dirs(self.api)
-        filesystem_helpers.rmtree_contents(self.pxelinux_dir)
-        filesystem_helpers.rmtree_contents(self.grub_dir)
-        filesystem_helpers.rmtree_contents(self.images_dir)
-        filesystem_helpers.rmtree_contents(self.ipxe_dir)
-        filesystem_helpers.rmtree_contents(self.esxi_dir)
-        filesystem_helpers.rmtree_contents(self.rendered_dir)
 
     def write_dhcp(self):
         """
diff --git a/cobbler/utils/filesystem_helpers.py b/cobbler/utils/filesystem_helpers.py
--- a/cobbler/utils/filesystem_helpers.py
+++ b/cobbler/utils/filesystem_helpers.py
@@ -437,6 +437,7 @@ def create_tftpboot_dirs(api):
         bootloc / "images",
         bootloc / "ipxe",
         esxi_dir,
+        esxi_dir / "system",
     ]
     for directory_path in tftpboot_directory_paths:
         __create_if_not_exists(directory_path)


Test patch:
diff --git a/tests/utils/filesystem_helpers_test.py b/tests/utils/filesystem_helpers_test.py
--- a/tests/utils/filesystem_helpers_test.py
+++ b/tests/utils/filesystem_helpers_test.py
@@ -244,7 +244,7 @@ def test_create_tftpboot_dirs(mocker, cobbler_api):
     filesystem_helpers.create_tftpboot_dirs(cobbler_api)
 
     # Assert
-    assert mock_mkdir.call_count == 12
+    assert mock_mkdir.call_count == 13
     assert mock_path_symlink_to.call_count == 3