File backport_complex_xmlrpc_objects_and_logger_spam.patch of Package cobbler
Index: cobbler/items/item.py
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/cobbler/items/item.py b/cobbler/items/item.py
--- a/cobbler/items/item.py (revision 5c498dbf2af6e3782b37605a477759e1aacc16b2)
+++ b/cobbler/items/item.py (revision 7371e1eeb7b735edd22897c5aba35987f295391f)
@@ -974,7 +974,7 @@
parent = parent.parent
# FIXME: Now get the object and check its existence
results.append(self.api.settings())
- self.logger.info(
+ self.logger.debug(
"grab_tree found %s children (including settings) of this object",
len(results),
)
Index: config/cobbler/logging_config.conf
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/cobbler/logging_config.conf b/config/cobbler/logging_config.conf
--- a/config/cobbler/logging_config.conf (revision 5c498dbf2af6e3782b37605a477759e1aacc16b2)
+++ b/config/cobbler/logging_config.conf (revision 7371e1eeb7b735edd22897c5aba35987f295391f)
@@ -19,7 +19,7 @@
[handler_stdout]
class=StreamHandler
-level=WARNING
+level=INFO
formatter=stdout
args=(sys.stdout,)
@@ -34,7 +34,7 @@
[handler_FileLogger]
class=FileHandler
-level=DEBUG
+level=INFO
formatter=Logfile
args=('/var/log/cobbler/cobbler.log', 'a')
Index: cobbler/items/distro.py
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/cobbler/items/distro.py b/cobbler/items/distro.py
--- a/cobbler/items/distro.py (revision 7371e1eeb7b735edd22897c5aba35987f295391f)
+++ b/cobbler/items/distro.py (revision e72a03db09397a5dde1b16d0d831a549e0a86bd2)
@@ -34,6 +34,8 @@
A Cobbler distribution object
"""
+ # Constants
+ TYPE_NAME = "distro"
COLLECTION_TYPE = "distro"
def __init__(self, api, *args, **kwargs):
Index: cobbler/items/system.py
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/cobbler/items/system.py b/cobbler/items/system.py
--- a/cobbler/items/system.py (revision 7371e1eeb7b735edd22897c5aba35987f295391f)
+++ b/cobbler/items/system.py (revision e72a03db09397a5dde1b16d0d831a549e0a86bd2)
@@ -730,6 +730,8 @@
A Cobbler system object.
"""
+ # Constants
+ TYPE_NAME = "system"
COLLECTION_TYPE = "system"
def __init__(self, api, *args, **kwargs):
Index: cobbler/remote.py
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/cobbler/remote.py b/cobbler/remote.py
--- a/cobbler/remote.py (revision 7371e1eeb7b735edd22897c5aba35987f295391f)
+++ b/cobbler/remote.py (revision e72a03db09397a5dde1b16d0d831a549e0a86bd2)
@@ -34,6 +34,7 @@
from typing import Dict, List, Optional, Union
from xmlrpc.server import SimpleXMLRPCRequestHandler
+from cobbler import enums
from cobbler import autoinstall_manager
from cobbler import configgen
from cobbler.items import item, package, system, image, profile, repo, mgmtclass, distro, file, menu
@@ -712,7 +713,38 @@
.. seealso:: Logically identical to :func:`~cobbler.api.CobblerAPI.get_item_resolved_value`
"""
self._log("get_item_resolved_value(%s)" % item_uuid, attribute=attribute)
- return self.api.get_item_resolved_value(item_uuid, attribute)
+ return_value = self.api.get_item_resolved_value(item_uuid, attribute)
+ if return_value is None:
+ self._log(
+ "get_item_resolved_value(%s): returned None" % item_uuid,
+ attribute=attribute,
+ )
+ raise ValueError(
+ 'None is not a valid value for the resolved attribute "%s". Please fix the item(s) '
+ 'starting at uuid "%s"' % (attribute, item_uuid)
+ )
+ elif isinstance(return_value, enums.ConvertableEnum):
+ return return_value.value
+ elif isinstance(
+ return_value,
+ (utils.DHCP, enums.NetworkInterfaceType, enums.BaudRates, item.Item),
+ ):
+ return return_value.name
+ elif isinstance(return_value, dict):
+ return self.xmlrpc_hacks(return_value)
+
+ if not isinstance(
+ return_value, (str, int, float, bool, tuple, bytes, bytearray, dict, list)
+ ):
+ self._log(
+ "get_item_resolved_value(%s): Cannot return XML-RPC compliant type. Please add a case to convert"
+ ' type "%s" to an XML-RPC compliant type!'
+ % (item_uuid, type(return_value))
+ )
+ raise ValueError(
+ "Cannot return XML-RPC compliant type. See logs for more information!"
+ )
+ return return_value
def get_item(self, what: str, name: str, flatten=False, resolved: bool = False):
"""
Index: tests/xmlrpcapi/non_object_calls_test.py
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/tests/xmlrpcapi/non_object_calls_test.py b/tests/xmlrpcapi/non_object_calls_test.py
--- a/tests/xmlrpcapi/non_object_calls_test.py (revision 7371e1eeb7b735edd22897c5aba35987f295391f)
+++ b/tests/xmlrpcapi/non_object_calls_test.py (revision e72a03db09397a5dde1b16d0d831a549e0a86bd2)
@@ -4,6 +4,8 @@
import time
import re
+from tests.conftest import does_not_raise
+
TEST_POWER_MANAGEMENT = True
TEST_SYSTEM = ""
@@ -186,8 +188,26 @@
assert match_obj
+@pytest.mark.parametrize(
+ "input_attribute,checked_object,expected_result,expected_exception",
+ [
+ ("kernel_options", "system", {"a": "1", "b": "2", "d": "~"}, does_not_raise()),
+ ("arch", "distro", "x86_64", does_not_raise()),
+ ("distro", "profile", "testdistro_item_resolved_value", does_not_raise()),
+ ("profile", "system", "testprofile_item_resolved_value", does_not_raise()),
+ ],
+)
def test_get_item_resolved_value(
- remote, token, create_distro, create_profile, create_system, create_kernel_initrd
+ remote,
+ token,
+ create_distro,
+ create_profile,
+ create_system,
+ create_kernel_initrd,
+ input_attribute,
+ checked_object,
+ expected_result,
+ expected_exception,
):
# Arrange
fk_kernel = "vmlinuz1"
@@ -203,11 +223,18 @@
create_profile(name_profile, name_distro, "a=1 b=2 c=3 c=4 c=5 d e")
test_system_handle = create_system(name_system, name_profile)
remote.modify_system(test_system_handle, "kernel_options", "!c !e", token=token)
- test_system = remote.get_system(name_system, token=token)
- expected_result = {"a": "1", "b": "2", "d": None}
+ if checked_object == "distro":
+ test_item = remote.get_distro(name_distro, token=token)
+ elif checked_object == "profile":
+ test_item = remote.get_profile(name_profile, token=token)
+ elif checked_object == "system":
+ test_item = remote.get_system(name_system, token=token)
+ else:
+ raise ValueError("checked_object has wrong value")
# Act
- result = remote.get_item_resolved_value(test_system.get("uid"), "kernel_options")
+ with expected_exception:
+ result = remote.get_item_resolved_value(test_item.get("uid"), input_attribute)
- # Assert
- assert expected_result == result
+ # Assert
+ assert expected_result == result
Index: cobbler/remote.py
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/cobbler/remote.py b/cobbler/remote.py
--- a/cobbler/remote.py (revision cb840ce25e78aa26349e3b23065b0fdf78fbadbc)
+++ b/cobbler/remote.py (revision 8398a921c898744929afa1620efa70859d5463bb)
@@ -731,6 +731,20 @@
):
return return_value.name
elif isinstance(return_value, dict):
+ if (
+ attribute == "interfaces"
+ and len(return_value) > 0
+ and all(
+ isinstance(value, system.NetworkInterface)
+ for value in return_value.values()
+ )
+ ):
+ interface_return_value = {}
+ for interface_name in return_value:
+ interface_return_value[interface_name] = return_value[
+ interface_name
+ ].to_dict(resolved=True)
+ return interface_return_value
return self.xmlrpc_hacks(return_value)
if not isinstance(
Index: tests/xmlrpcapi/non_object_calls_test.py
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/tests/xmlrpcapi/non_object_calls_test.py b/tests/xmlrpcapi/non_object_calls_test.py
--- a/tests/xmlrpcapi/non_object_calls_test.py (revision cb840ce25e78aa26349e3b23065b0fdf78fbadbc)
+++ b/tests/xmlrpcapi/non_object_calls_test.py (revision 8398a921c898744929afa1620efa70859d5463bb)
@@ -195,6 +195,40 @@
("arch", "distro", "x86_64", does_not_raise()),
("distro", "profile", "testdistro_item_resolved_value", does_not_raise()),
("profile", "system", "testprofile_item_resolved_value", does_not_raise()),
+ (
+ "interfaces",
+ "system",
+ {
+ "eth0": {
+ "bonding_opts": "",
+ "bridge_opts": "",
+ "cnames": [],
+ "connected_mode": False,
+ "dhcp_tag": "",
+ "dns_name": "",
+ "if_gateway": "",
+ "interface_master": "",
+ "interface_type": "NA",
+ "ip_address": "",
+ "ipv6_address": "",
+ "ipv6_default_gateway": "",
+ "ipv6_mtu": "",
+ "ipv6_prefix": "",
+ "ipv6_secondaries": [],
+ "ipv6_static_routes": [],
+ "mac_address": "aa:bb:cc:dd:ee:ff",
+ "management": False,
+ "mtu": "",
+ "netmask": "",
+ "static": False,
+ "static_routes": [],
+ "virt_bridge": "",
+ }
+ },
+ does_not_raise(),
+ ),
+ ("modify_interface", "system", {}, pytest.raises(ValueError)),
+ ("doesnt_exist", "system", {}, pytest.raises(AttributeError)),
],
)
def test_get_item_resolved_value(
@@ -223,6 +257,12 @@
create_profile(name_profile, name_distro, "a=1 b=2 c=3 c=4 c=5 d e")
test_system_handle = create_system(name_system, name_profile)
remote.modify_system(test_system_handle, "kernel_options", "!c !e", token=token)
+ remote.modify_system(
+ test_system_handle,
+ "modify_interface",
+ {"macaddress-eth0": "aa:bb:cc:dd:ee:ff"},
+ token=token,
+ )
if checked_object == "distro":
test_item = remote.get_distro(name_distro, token=token)
elif checked_object == "profile":