Repository: cobbler/cobbler

Issue:
regression after enum changes
A regression between c8e4af8affed82781212937c7655fd01f8488fec..e507f402f5a6dd8d9c7b6bbb8ce14bcb2cae3003, maybe caused by #2901 

````
Jan 24 12:46:23 cobbler-prv cobblerd[7220]: Traceback (most recent call last):
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:   File "/usr/lib/python3.8/site-packages/cobbler/enums.py", line 30, in to_enum
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:     return cls[value.upper()]
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:   File "/usr/lib64/python3.8/enum.py", line 387, in __getitem__
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:     return cls._member_map_[name]
Jan 24 12:46:23 cobbler-prv cobblerd[7220]: KeyError: '<<INHERIT>>'
Jan 24 12:46:23 cobbler-prv cobblerd[7220]: During handling of the above exception, another exception occurred:
Jan 24 12:46:23 cobbler-prv cobblerd[7220]: Traceback (most recent call last):
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:   File "/usr/lib/python3.8/site-packages/cobbler/cobbler_collections/manager.py", line 212, in deserialize
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:     serializer.deserialize(collection)
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:   File "/usr/lib/python3.8/site-packages/cobbler/serializer.py", line 128, in deserialize
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:     storage_module.deserialize(collection, topological)
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:   File "/usr/lib/python3.8/site-packages/cobbler/modules/serializers/file.py", line 160, in deserialize
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:     collection.from_list(datastruct)
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:   File "/usr/lib/python3.8/site-packages/cobbler/cobbler_collections/collection.py", line 201, in from_list
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:     item = self.factory_produce(self.api, item_dict)
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:   File "/usr/lib/python3.8/site-packages/cobbler/cobbler_collections/systems.py", line 50, in factory_produce
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:     new_system.from_dict(item_dict)
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:   File "/usr/lib/python3.8/site-packages/cobbler/items/system.py", line 844, in from_dict
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:     super().from_dict(dictionary)
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:   File "/usr/lib/python3.8/site-packages/cobbler/items/item.py", line 793, in from_dict
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:     setattr(self, lowered_key, dictionary[key])
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:   File "/usr/lib/python3.8/site-packages/cobbler/items/system.py", line 1584, in virt_disk_driver
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:     self._virt_disk_driver = enums.VirtDiskDrivers.to_enum(driver)
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:   File "/usr/lib/python3.8/site-packages/cobbler/enums.py", line 36, in to_enum
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:     raise ValueError(f"{value} must be one of {list(cls)}")
Jan 24 12:46:23 cobbler-prv cobblerd[7220]: ValueError: <<inherit>> must be one of [<VirtDiskDrivers.INHERTIED: '<<inherit>>'>, <VirtDiskDrivers.RAW: 'raw'>, <VirtDiskDrivers.QCOW2: 'qcow2'>, <VirtDiskDrivers.QED: 'qed'>, <VirtDiskDrivers.VDI: 'vdi'>, <VirtDiskDrivers.VDMK: 'vdmk'>]
Jan 24 12:46:23 cobbler-prv cobblerd[7220]: The above exception was the direct cause of the following exception:
Jan 24 12:46:23 cobbler-prv cobblerd[7220]: Traceback (most recent call last):
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:   File "/usr/bin/cobblerd", line 91, in main
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:     api = cobbler_api.CobblerAPI(is_cobblerd=True, settingsfile_location=options.config,
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:   File "/usr/lib/python3.8/site-packages/cobbler/api.py", line 106, in __init__
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:     self.deserialize()
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:   File "/usr/lib/python3.8/site-packages/cobbler/api.py", line 1647, in deserialize
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:     return self._collection_mgr.deserialize()
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:   File "/usr/lib/python3.8/site-packages/cobbler/cobbler_collections/manager.py", line 214, in deserialize
Jan 24 12:46:23 cobbler-prv cobblerd[7220]:     raise CX("serializer: error loading collection %s: %s. Check /etc/cobbler/modules.conf"
Jan 24 12:46:23 cobbler-prv cobblerd[7220]: cobbler.cexceptions.CX: "serializer: error loading collection system: <<inherit>> must be one of [<VirtDiskDrivers.INHERTIED: '<<inherit>>'>, <VirtDiskDrivers.RAW: 'raw'>, <VirtDiskDrivers.QCOW2: 'qcow2'>, <VirtDiskDrivers.QED: 'qed'>, <VirtDiskDrivers.VDI: 'vdi'>, <VirtDiskDrivers.VDMK: 'vdmk'>]. Check /etc/cobbler/modules.conf"
````


Discussion:
Argh. We have a test. Why wasn't it triggerd... But thanks for the quick find!

Resolving patch:
diff --git a/cobbler/enums.py b/cobbler/enums.py
--- a/cobbler/enums.py
+++ b/cobbler/enums.py
@@ -27,6 +27,11 @@ def to_enum(cls, value: Union[str, "ConvertableEnum"]) -> "ConvertableEnum":
         """
         try:
             if isinstance(value, str):
+                if value == VALUE_INHERITED:
+                    try:
+                        return cls["INHERITED"]
+                    except KeyError as key_error:
+                        raise ValueError("The enum given does not support inheritance!") from key_error
                 return cls[value.upper()]
             elif isinstance(value, cls):
                 return value
@@ -133,7 +138,7 @@ class VirtDiskDrivers(ConvertableEnum):
     This enum represents all virtual disk driver Cobbler can handle.
     """
 
-    INHERTIED = VALUE_INHERITED
+    INHERITED = VALUE_INHERITED
     RAW = "raw"
     QCOW2 = "qcow2"
     QED = "qed"
diff --git a/cobbler/items/system.py b/cobbler/items/system.py
--- a/cobbler/items/system.py
+++ b/cobbler/items/system.py
@@ -789,7 +789,7 @@ def __init__(self, api, *args, **kwargs):
         # FIXME: The virt_* attributes don't support inheritance yet
         self._virt_auto_boot: Union[bool, str] = enums.VALUE_INHERITED
         self._virt_cpus: Union[int, str] = enums.VALUE_INHERITED
-        self._virt_disk_driver = enums.VirtDiskDrivers.INHERTIED
+        self._virt_disk_driver = enums.VirtDiskDrivers.INHERITED
         self._virt_file_size: Union[float, str] = enums.VALUE_INHERITED
         self._virt_path = enums.VALUE_INHERITED
         self._virt_pxe_boot = False


Test patch:
diff --git a/tests/enums_test.py b/tests/enums_test.py
--- a/tests/enums_test.py
+++ b/tests/enums_test.py
@@ -33,6 +33,7 @@ def test_validate_arch(test_architecture, test_raise):
     ("qemu", does_not_raise()),
     ("<<inherit>>", does_not_raise()),
     (enums.VirtType.QEMU, does_not_raise()),
+    (enums.VirtType.INHERITED, does_not_raise()),
     (0, pytest.raises(TypeError))
 ])
 def test_set_virt_type(value, expected_exception):
@@ -40,7 +41,7 @@ def test_set_virt_type(value, expected_exception):
 
     # Act
     with expected_exception:
-        result = enums.VirtType.to_enum("qemu")
+        result = enums.VirtType.to_enum(value)
 
         # Assert
         if isinstance(value, str):
@@ -54,6 +55,7 @@ def test_set_virt_type(value, expected_exception):
 @pytest.mark.parametrize("value,expected_exception", [
     ("allow", does_not_raise()),
     (enums.TlsRequireCert.ALLOW, does_not_raise()),
+    (enums.VALUE_INHERITED, pytest.raises(ValueError)),
     (0, pytest.raises(TypeError))
 ])
 def test_validate_ldap_tls_reqcert(value, expected_exception):
@@ -75,7 +77,7 @@ def test_validate_ldap_tls_reqcert(value, expected_exception):
 @pytest.mark.parametrize("test_driver,test_raise", [
     (enums.VirtDiskDrivers.RAW, does_not_raise()),
     (enums.VALUE_INHERITED, does_not_raise()),
-    (enums.VirtDiskDrivers.INHERTIED, does_not_raise()),
+    (enums.VirtDiskDrivers.INHERITED, does_not_raise()),
     ("qcow2", does_not_raise()),
     ("<<inherit>>", does_not_raise()),
     ("bad_driver", pytest.raises(ValueError)),