test_xmlutil.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. import pytest
  2. import salt.utils.xmlutil as xml
  3. from salt._compat import ElementTree as ET
  4. @pytest.fixture
  5. def xml_doc():
  6. return ET.fromstring(
  7. """
  8. <domain>
  9. <name>test01</name>
  10. <memory unit="MiB">1024</memory>
  11. <cpu>
  12. <topology sockets="1"/>
  13. </cpu>
  14. <vcpus>
  15. <vcpu enabled="yes" id="1"/>
  16. </vcpus>
  17. <memtune>
  18. <hugepages>
  19. <page size="128"/>
  20. </hugepages>
  21. </memtune>
  22. </domain>
  23. """
  24. )
  25. def test_change_xml_text(xml_doc):
  26. ret = xml.change_xml(
  27. xml_doc, {"name": "test02"}, [{"path": "name", "xpath": "name"}]
  28. )
  29. assert ret
  30. assert "test02" == xml_doc.find("name").text
  31. def test_change_xml_text_nochange(xml_doc):
  32. ret = xml.change_xml(
  33. xml_doc, {"name": "test01"}, [{"path": "name", "xpath": "name"}]
  34. )
  35. assert not ret
  36. def test_change_xml_equals_nochange(xml_doc):
  37. ret = xml.change_xml(
  38. xml_doc,
  39. {"mem": 1023},
  40. [
  41. {
  42. "path": "mem",
  43. "xpath": "memory",
  44. "get": lambda n: int(n.text),
  45. "equals": lambda o, n: abs(o - n) <= 1,
  46. }
  47. ],
  48. )
  49. assert not ret
  50. def test_change_xml_text_notdefined(xml_doc):
  51. ret = xml.change_xml(xml_doc, {}, [{"path": "name", "xpath": "name"}])
  52. assert not ret
  53. def test_change_xml_text_removed(xml_doc):
  54. ret = xml.change_xml(xml_doc, {"name": None}, [{"path": "name", "xpath": "name"}])
  55. assert ret
  56. assert xml_doc.find("name") is None
  57. def test_change_xml_text_add(xml_doc):
  58. ret = xml.change_xml(
  59. xml_doc,
  60. {"cpu": {"vendor": "ACME"}},
  61. [{"path": "cpu:vendor", "xpath": "cpu/vendor"}],
  62. )
  63. assert ret
  64. assert "ACME" == xml_doc.find("cpu/vendor").text
  65. def test_change_xml_convert(xml_doc):
  66. ret = xml.change_xml(
  67. xml_doc,
  68. {"mem": 2},
  69. [{"path": "mem", "xpath": "memory", "convert": lambda v: v * 1024}],
  70. )
  71. assert ret
  72. assert "2048" == xml_doc.find("memory").text
  73. def test_change_xml_attr(xml_doc):
  74. ret = xml.change_xml(
  75. xml_doc,
  76. {"cpu": {"topology": {"cores": 4}}},
  77. [
  78. {
  79. "path": "cpu:topology:cores",
  80. "xpath": "cpu/topology",
  81. "get": lambda n: int(n.get("cores")) if n.get("cores") else None,
  82. "set": lambda n, v: n.set("cores", str(v)),
  83. "del": xml.del_attribute("cores"),
  84. }
  85. ],
  86. )
  87. assert ret
  88. assert "4" == xml_doc.find("cpu/topology").get("cores")
  89. def test_change_xml_attr_unchanged(xml_doc):
  90. ret = xml.change_xml(
  91. xml_doc,
  92. {"cpu": {"topology": {"sockets": 1}}},
  93. [
  94. {
  95. "path": "cpu:topology:sockets",
  96. "xpath": "cpu/topology",
  97. "get": lambda n: int(n.get("sockets")) if n.get("sockets") else None,
  98. "set": lambda n, v: n.set("sockets", str(v)),
  99. "del": xml.del_attribute("sockets"),
  100. }
  101. ],
  102. )
  103. assert not ret
  104. def test_change_xml_attr_remove(xml_doc):
  105. ret = xml.change_xml(
  106. xml_doc,
  107. {"cpu": {"topology": {"sockets": None}}},
  108. [
  109. {
  110. "path": "cpu:topology:sockets",
  111. "xpath": "./cpu/topology",
  112. "get": lambda n: int(n.get("sockets")) if n.get("sockets") else None,
  113. "set": lambda n, v: n.set("sockets", str(v)),
  114. "del": xml.del_attribute("sockets"),
  115. }
  116. ],
  117. )
  118. assert ret
  119. assert xml_doc.find("cpu") is None
  120. def test_change_xml_not_simple_value(xml_doc):
  121. ret = xml.change_xml(
  122. xml_doc,
  123. {"cpu": {"topology": {"sockets": None}}},
  124. [{"path": "cpu", "xpath": "vcpu", "get": lambda n: int(n.text)}],
  125. )
  126. assert not ret
  127. def test_change_xml_template(xml_doc):
  128. ret = xml.change_xml(
  129. xml_doc,
  130. {"cpu": {"vcpus": {2: {"enabled": True}, 4: {"enabled": False}}}},
  131. [
  132. {
  133. "path": "cpu:vcpus:{id}:enabled",
  134. "xpath": "vcpus/vcpu[@id='$id']",
  135. "convert": lambda v: "yes" if v else "no",
  136. "get": lambda n: n.get("enabled"),
  137. "set": lambda n, v: n.set("enabled", v),
  138. "del": xml.del_attribute("enabled", ["id"]),
  139. },
  140. ],
  141. )
  142. assert ret
  143. assert xml_doc.find("vcpus/vcpu[@id='1']") is None
  144. assert "yes" == xml_doc.find("vcpus/vcpu[@id='2']").get("enabled")
  145. assert "no" == xml_doc.find("vcpus/vcpu[@id='4']").get("enabled")
  146. def test_change_xml_template_remove(xml_doc):
  147. ret = xml.change_xml(
  148. xml_doc,
  149. {"cpu": {"vcpus": None}},
  150. [
  151. {
  152. "path": "cpu:vcpus:{id}:enabled",
  153. "xpath": "vcpus/vcpu[@id='$id']",
  154. "convert": lambda v: "yes" if v else "no",
  155. "get": lambda n: n.get("enabled"),
  156. "set": lambda n, v: n.set("enabled", v),
  157. "del": xml.del_attribute("enabled", ["id"]),
  158. },
  159. ],
  160. )
  161. assert ret
  162. assert xml_doc.find("vcpus") is None
  163. def test_change_xml_template_list(xml_doc):
  164. ret = xml.change_xml(
  165. xml_doc,
  166. {"memtune": {"hugepages": [{"size": "1024"}, {"size": "512"}]}},
  167. [
  168. {
  169. "path": "memtune:hugepages:{id}:size",
  170. "xpath": "memtune/hugepages/page[$id]",
  171. "get": lambda n: n.get("size"),
  172. "set": lambda n, v: n.set("size", v),
  173. "del": xml.del_attribute("size"),
  174. },
  175. ],
  176. )
  177. assert ret
  178. assert ["1024", "512"] == [
  179. n.get("size") for n in xml_doc.findall("memtune/hugepages/page")
  180. ]