virt: support cpu tunning and Iothread allocation

This commit is contained in:
gqlo 2020-08-16 02:08:46 +09:00 committed by Daniel Wozniak
parent 4fb4d12fdb
commit 50701b3573
4 changed files with 1262 additions and 15 deletions

View file

@ -965,6 +965,7 @@ def _gen_xml(
context["mem"] = nesthash(mem)
context["cpu"] = nesthash()
context["cputune"] = nesthash()
if isinstance(cpu, int):
context["cpu"]["maximum"] = str(cpu)
elif isinstance(cpu, dict):
@ -1898,7 +1899,8 @@ def init(
:param name: name of the virtual machine to create
:param cpu:
Number of virtual CPUs to assign to the virtual machine or a dictionary with detailed information to configure
cpu model and topology. The structure of the dictionary is documented in :ref:`init-cpu-def`.
cpu model and topology, numa node tuning, cpu tuning and iothreads allocation. The structure of the dictionary is
documented in :ref:`init-cpu-def`.
.. code-block:: yaml
@ -1939,7 +1941,7 @@ def init(
memory: 1g
discard: True
distances:
0: 10
0: 10 # sibling id : value
1: 21
2: 31
3: 41
@ -1952,6 +1954,60 @@ def init(
1: 10
2: 21
3: 31
tuning:
vcpupin:
0: 1-4,^2 # vcpuid : cpuset
1: 0,1
2: 2,3
3: 0,4
emulatorpin: 1-3
iothreadpin:
1: 5,6 # iothread id: cpuset
2: 7,8
shares: 2048
period: 1000000
quota: -1
global_period: 1000000
global_quota: -1
emulator_period: 1000000
emulator_quota: -1
iothread_period: 1000000
iothread_quota: -1
vcpusched:
- scheduler: fifo
priority: 1
vcpus: 0,3-5
- scheduler: rr
priority: 3
iothreadsched:
- scheduler: idle
- scheduler: batch
iothreads: 2,3
emulatorsched:
- scheduler: batch
cachetune:
0-3: # vcpus set
0: # cache id
level: 3
type: both
size: 4
1:
level: 3
type: both
size: 6
monitor:
1: 3
0-3: 3
4-5:
monitor:
4: 3 # vcpus: level
5: 3
memorytune:
0-3: # vcpus set
0: 60 # node id: bandwidth
4-5:
0: 60
iothreads: 4
.. versionadded:: Aluminium
@ -2147,6 +2203,76 @@ def init(
element define the distance between NUMA cells and ``sibling`` sub-element is used to specify the distance value
between sibling NUMA cells.
vcpupin
The optional vcpupin element specifies which of host's physical CPUs the domain vCPU will be pinned to.
emulatorpin
The optional emulatorpin element specifies which of host physical CPUs the "emulator", a subset of a domain not
including vCPU or iothreads will be pinned to.
iothreadpin
The optional iothreadpin element specifies which of host physical CPUs the IOThreads will be pinned to.
shares
The optional shares element specifies the proportional weighted share for the domain.
period
The optional period element specifies the enforcement interval (unit: microseconds).
quota
The optional quota element specifies the maximum allowed bandwidth (unit: microseconds).
global_period
The optional global_period element specifies the enforcement CFS scheduler interval (unit: microseconds) for the
whole domain in contrast with period which enforces the interval per vCPU.
global_quota
The optional global_quota element specifies the maximum allowed bandwidth (unit: microseconds) within a period
for the whole domain.
emulator_period
The optional emulator_period element specifies the enforcement interval (unit: microseconds).
emulator_quota
The optional emulator_quota element specifies the maximum allowed bandwidth (unit: microseconds) for domain's
emulator threads (those excluding vCPUs).
iothread_period
The optional iothread_period element specifies the enforcement interval (unit: microseconds) for IOThreads.
iothread_quota
The optional iothread_quota element specifies the maximum allowed bandwidth (unit: microseconds) for IOThreads.
vcpusched
specify the scheduler type for vCPUs.
The value is a list of dictionaries with the ``scheduler`` key (values ``batch``, ``idle``, ``fifo``, ``rr``)
and the optional ``priority`` and ``vcpus`` keys. The ``priority`` value usually is a positive integer and the
``vcpus`` value is a cpu set like ``1-4,^3,6`` or simply the vcpu id.
iothreadsched
specify the scheduler type for IO threads.
The value is a list of dictionaries with the ``scheduler`` key (values ``batch``, ``idle``, ``fifo``, ``rr``)
and the optional ``priority`` and ``vcpus`` keys. The ``priority`` value usually is a positive integer and the
``vcpus`` value is a cpu set like ``1-4,^3,6`` or simply the vcpu id.
emulatorsched
specify the scheduler type (values batch, idle, fifo, rr) for particular the emulator.
The value is a dictionary with the ``scheduler`` key (values ``batch``, ``idle``, ``fifo``, ``rr``)
and the optional ``priority`` and ``vcpus`` keys. The ``priority`` value usually is a positive integer.
cachetune
Optional cachetune element can control allocations for CPU caches using the resctrl on the host.
monitor
The optional element monitor creates the cache monitor(s) for current cache allocation.
memorytune
Optional memorytune element can control allocations for memory bandwidth using the resctrl on the host.
iothreads
Number of threads for supported disk devices to perform I/O requests. iothread id will be numbered from 1 to
the provided number (Default: None).
.. _init-boot-def:
.. rubric:: Boot parameters definition
@ -2765,11 +2891,14 @@ def update(
Update the definition of an existing domain.
:param name: Name of the domain to update
:param cpu: Number of virtual CPUs to assign to the virtual machine or a dictionary with detailed information to
configure cpu model and topology. The structure of the dictionary is documented in :ref:`init-cpu-def`.
To update any cpu/vcpu element specify the new values to the corresponding tag. To remove any element or
attribute, specify ``None`` object. Please note that ``None`` object is mapped to ``null`` in yaml, use
``null`` in sls file instead.
:param cpu:
Number of virtual CPUs to assign to the virtual machine or a dictionary with detailed information to configure
cpu model and topology, numa node tuning, cpu tuning and iothreads allocation. The structure of the dictionary is
documented in :ref:`init-cpu-def`.
To update any cpu parameters specify the new values to the corresponding tag. To remove any element or attribute,
specify ``None`` object. Please note that ``None`` object is mapped to ``null`` in yaml, use ``null`` in sls file
instead.
:param mem: Amount of memory to allocate to the virtual machine in MiB. Since 3002, a dictionary can be used to
contain detailed configuration which support memory allocation or tuning. Supported parameters are ``boot``,
``current``, ``max``, ``slots``, ``hard_limit``, ``soft_limit``, ``swap_hard_limit``, ``min_guarantee``,
@ -3251,6 +3380,130 @@ def update(
"set": lambda n, v: n.set("value", str(v)),
"del": salt.utils.xmlutil.del_attribute("value", ["id"]),
},
{"path": "cpu:iothreads", "xpath": "iothreads"},
{"path": "cpu:tuning:shares", "xpath": "cputune/shares"},
{"path": "cpu:tuning:period", "xpath": "cputune/period"},
{"path": "cpu:tuning:quota", "xpath": "cputune/quota"},
{"path": "cpu:tuning:global_period", "xpath": "cputune/global_period"},
{"path": "cpu:tuning:global_quota", "xpath": "cputune/global_quota"},
{"path": "cpu:tuning:emulator_period", "xpath": "cputune/emulator_period"},
{"path": "cpu:tuning:emulator_quota", "xpath": "cputune/emulator_quota"},
{"path": "cpu:tuning:iothread_period", "xpath": "cputune/iothread_period"},
{"path": "cpu:tuning:iothread_quota", "xpath": "cputune/iothread_quota"},
{
"path": "cpu:tuning:vcpupin:{id}",
"xpath": "cputune/vcpupin[@vcpu='$id']",
"get": lambda n: str(n.get("cpuset")) if n.get("cpuset") else None,
"set": lambda n, v: n.set("cpuset", str(v)),
"del": salt.utils.xmlutil.del_attribute("cpuset", ["vcpu"]),
},
{
"path": "cpu:tuning:emulatorpin",
"xpath": "cputune/emulatorpin",
"get": lambda n: str(n.get("cpuset")) if n.get("cpuset") else None,
"set": lambda n, v: n.set("cpuset", str(v)),
"del": salt.utils.xmlutil.del_attribute("cpuset", []),
},
{
"path": "cpu:tuning:iothreadpin:{id}",
"xpath": "cputune/iothreadpin[@iothread='$id']",
"get": lambda n: str(n.get("cpuset")) if n.get("cpuset") else None,
"set": lambda n, v: n.set("cpuset", str(v)),
"del": salt.utils.xmlutil.del_attribute("cpuset", ["iothread"]),
},
{
"path": "cpu:tuning:vcpusched:{id}:scheduler",
"xpath": "cputune/vcpusched[$id]",
"get": lambda n: str(n.get("scheduler")),
"set": lambda n, v: n.set("scheduler", str(v)),
"del": salt.utils.xmlutil.del_attribute("scheduler", ["priority", "vcpus"]),
},
{
"path": "cpu:tuning:vcpusched:{id}:priority",
"xpath": "cputune/vcpusched[$id]",
"get": lambda n: str(n.get("priority")) if n.get("priority") else None,
"set": lambda n, v: n.set("priority", str(v)),
"del": salt.utils.xmlutil.del_attribute("priority"),
},
{
"path": "cpu:tuning:vcpusched:{id}:vcpus",
"xpath": "cputune/vcpusched[$id]",
"get": lambda n: str(n.get("vcpus")) if n.get("vcpus") else None,
"set": lambda n, v: n.set("vcpus", str(v)),
"del": salt.utils.xmlutil.del_attribute("vcpus"),
},
{
"path": "cpu:tuning:iothreadsched:{id}:scheduler",
"xpath": "cputune/iothreadsched[$id]",
"get": lambda n: str(n.get("scheduler")),
"set": lambda n, v: n.set("scheduler", str(v)),
"del": salt.utils.xmlutil.del_attribute(
"scheduler", ["priority", "iothreads"]
),
},
{
"path": "cpu:tuning:iothreadsched:{id}:priority",
"xpath": "cputune/iothreadsched[$id]",
"get": lambda n: str(n.get("priority")) if n.get("priority") else None,
"set": lambda n, v: n.set("priority", str(v)),
"del": salt.utils.xmlutil.del_attribute("priority"),
},
{
"path": "cpu:tuning:iothreadsched:{id}:iothreads",
"xpath": "cputune/iothreadsched[$id]",
"get": lambda n: str(n.get("iothreads")) if n.get("iothreads") else None,
"set": lambda n, v: n.set("iothreads", str(v)),
"del": salt.utils.xmlutil.del_attribute("iothreads"),
},
{
"path": "cpu:tuning:emulatorsched:scheduler",
"xpath": "cputune/emulatorsched",
"get": lambda n: str(n.get("scheduler")),
"set": lambda n, v: n.set("scheduler", str(v)),
"del": salt.utils.xmlutil.del_attribute("scheduler", ["priority"]),
},
{
"path": "cpu:tuning:emulatorsched:priority",
"xpath": "cputune/emulatorsched",
"get": lambda n: str(n.get("priority")) if n.get("priority") else None,
"set": lambda n, v: n.set("priority", str(v)),
"del": salt.utils.xmlutil.del_attribute("priority"),
},
{
"path": "cpu:tuning:cachetune:{id}:{sid}:level",
"xpath": "cputune/cachetune[@vcpus='$id']/cache[@id='$sid']",
"get": lambda n: str(n.get("level")) if n.get("level") else None,
"set": lambda n, v: n.set("level", str(v)),
"del": salt.utils.xmlutil.del_attribute("level", ["id", "unit", "vcpus"]),
},
{
"path": "cpu:tuning:cachetune:{id}:{sid}:type",
"xpath": "cputune/cachetune[@vcpus='$id']/cache[@id='$sid']",
"get": lambda n: str(n.get("type")) if n.get("type") else None,
"set": lambda n, v: n.set("type", str(v)),
"del": salt.utils.xmlutil.del_attribute("type", ["id", "unit", "vcpus"]),
},
{
"path": "cpu:tuning:cachetune:{id}:{sid}:size",
"xpath": "cputune/cachetune[@vcpus='$id']/cache[@id='$sid']",
"get": lambda n: str(n.get("size")) if n.get("size") else None,
"set": lambda n, v: n.set("size", str(v)),
"del": salt.utils.xmlutil.del_attribute("size", ["id", "unit", "vcpus"]),
},
{
"path": "cpu:tuning:cachetune:{id}:monitor:{sid}",
"xpath": "cputune/cachetune[@vcpus='$id']/monitor[@vcpus='$sid']",
"get": lambda n: str(n.get("level")) if n.get("level") else None,
"set": lambda n, v: n.set("level", str(v)),
"del": salt.utils.xmlutil.del_attribute("level", ["vcpus"]),
},
{
"path": "cpu:tuning:memorytune:{id}:{sid}",
"xpath": "cputune/memorytune[@vcpus='$id']/node[@id='$sid']",
"get": lambda n: str(n.get("bandwidth")) if n.get("bandwidth") else None,
"set": lambda n, v: n.set("bandwidth", str(v)),
"del": salt.utils.xmlutil.del_attribute("bandwidth", ["id", "vcpus"]),
},
]
# update NUMA host policy

View file

@ -294,8 +294,122 @@ def defined(
.. versionadded:: 3001
:param name: name of the virtual machine to run
:param cpu: Number of virtual CPUs to assign to the virtual machine or a dictionary with detailed information to configure
cpu model and topology. The structure of the dictionary is documented in :ref:`init-cpu-def`.
:param cpu:
Number of virtual CPUs to assign to the virtual machine or a dictionary with detailed information to configure
cpu model and topology, numa node tuning, cpu tuning and iothreads allocation. The structure of the dictionary is
documented in :ref:`init-cpu-def`.
.. code-block:: yaml
cpu:
placement: static
cpuset: 0-11
current: 5
maximum: 12
vcpus:
0:
enabled: 'yes'
hotpluggable: 'no'
order: 1
1:
enabled: 'no'
hotpluggable: 'yes'
match: minimum
mode: custom
check: full
vendor: Intel
model:
name: core2duo
fallback: allow
vendor_id: GenuineIntel
topology:
sockets: 1
cores: 12
threads: 1
cache:
level: 3
mode: emulate
feature:
policy: optional
name: lahf_lm
numa:
0:
cpus: 0-3
memory: 1g
discard: 'yes'
distances:
0: 10 # sibling id : value
1: 21
2: 31
3: 41
1:
cpus: 4-6
memory: 1g
memAccess: shared
distances:
0: 21
1: 10
2: 21
3: 31
tuning:
vcpupin:
0: 1-4,^2 # vcpuid : cpuset
1: 0,1
2: 2,3
3: 0,4
emulatorpin: 1-3
iothreadpin:
1: 5,6 # iothread id: cpuset
2: 7,8
shares: 2048
period: 1000000
quota: -1
global_period: 1000000
global_quota: -1
emulator_period: 1000000
emulator_quota: -1
iothread_period: 1000000
iothread_quota: -1
vcpusched:
- scheduler: fifo
priority: 1
- scheduler: fifo
priority: 2
vcpus: 1-3
- scheduler: rr
priority: 3
vcpus: 4
iothreadsched:
- scheduler: batch
iothreads: 2
emulatorsched:
scheduler: idle
cachetune:
0-3: # vcpus set
0: # cache id
level: 3
type: both
size: 4
1:
level: 3
type: both
size: 6
monitor:
1: 3
0-3: 3
4-5:
monitor:
4: 3 # vcpus: level
5: 3
memorytune:
0-3: # vcpus set
0: 60 # node id: bandwidth
4-5:
0: 60
iothreads: 4
.. versionadded:: Aluminium
:param mem: Amount of memory to allocate to the virtual machine in MiB. Since 3002, a dictionary can be used to
contain detailed configuration which support memory allocation or tuning. Supported parameters are ``boot``,
``current``, ``max``, ``slots``, ``hard_limit``, ``soft_limit``, ``swap_hard_limit``, ``min_guarantee``,
@ -544,12 +658,14 @@ def running(
.. versionadded:: 2016.3.0
:param name: name of the virtual machine to run
:param cpu: Number of virtual CPUs to assign to the virtual machine or a dictionary with detailed information to
configure cpu model and topology. The structure of the dictionary is documented in :ref:`init-cpu-def`.
:param cpu:
Number of virtual CPUs to assign to the virtual machine or a dictionary with detailed information to configure
cpu model and topology, numa node tuning, cpu tuning and iothreads allocation. The structure of the dictionary is
documented in :ref:`init-cpu-def`.
To update any cpu/vcpu element specify the new values to the corresponding tag. To remove any element or
attribute,specify ``None`` object. Please note that ``None`` object is mapped to ``null`` in yaml, use ``null``
in sls file instead.
To update any cpu parameters specify the new values to the corresponding tag. To remove any element or attribute,
specify ``None`` object. Please note that ``None`` object is mapped to ``null`` in yaml, use ``null`` in sls file
instead.
:param mem: Amount of memory to allocate to the virtual machine in MiB. Since 3002, a dictionary can be used to
contain detailed configuration which support memory allocation or tuning. Supported parameters are ``boot``,
``current``, ``max``, ``slots``, ``hard_limit``, ``soft_limit``, ``swap_hard_limit``, ``min_guarantee``,
@ -672,6 +788,18 @@ def running(
.. versionadded:: Aluminium
:param numatune:
The optional numatune element provides details of how to tune the performance of a NUMA host via controlling NUMA
policy for domain process. The optional ``memory`` element specifies how to allocate memory for the domain process
on a NUMA host. ``memnode`` elements can specify memory allocation policies per each guest NUMA node. The definition
used in the dictionary can be found at :ref:`init-cpu-def`.
To update any numatune parameters, specify the new value. To remove any ``numatune`` parameters, pass a None object,
for instance: 'numatune': ``None``. Please note that ``None`` is mapped to ``null`` in sls file, pass ``null`` in
sls file instead.
.. versionadded:: Aluminium
.. rubric:: Example States
Make sure an already-defined virtual machine called ``domain_name`` is running:

View file

@ -51,6 +51,98 @@
</numa>
{%- endif %}
</cpu>
{%- if cpu.iothreads %}
<iothreads>{{ cpu.iothreads }}</iothreads>
{%- endif %}
{%- endif %}
{%- if cpu.tuning %}
<cputune>
{%- if cpu.tuning.vcpupin %}
{%- for vcpu_id, cpuset in cpu.tuning.vcpupin.items() %}
<vcpupin vcpu='{{ vcpu_id }}' cpuset='{{ cpuset }}'/>
{%- endfor %}
{%- endif %}
{%- if cpu.tuning.emulatorpin %}
<emulatorpin cpuset="{{ cpu.tuning.emulatorpin }}"/>
{%- endif %}
{%- if cpu.tuning.iothreadpin %}
{%- for thread_id, cpuset in cpu.tuning.iothreadpin.items() %}
<iothreadpin iothread='{{ thread_id }}' cpuset='{{ cpuset }}'/>
{%- endfor %}
{%- endif %}
{%- if cpu.tuning.shares %}
<shares>{{ cpu.tuning.shares }}</shares>
{%- endif %}
{%- if cpu.tuning.period %}
<period>{{ cpu.tuning.period }}</period>
{%- endif %}
{%- if cpu.tuning.quota %}
<quota>{{ cpu.tuning.quota }}</quota>
{%- endif %}
{%- if cpu.tuning.global_period %}
<global_period>{{ cpu.tuning.global_period }}</global_period>
{%- endif %}
{%- if cpu.tuning.global_quota %}
<global_quota>{{ cpu.tuning.global_quota }}</global_quota>
{%- endif %}
{%- if cpu.tuning.emulator_period %}
<emulator_period>{{ cpu.tuning.emulator_period }}</emulator_period>
{%- endif %}
{%- if cpu.tuning.emulator_quota %}
<emulator_quota>{{ cpu.tuning.emulator_quota }}</emulator_quota>
{%- endif %}
{%- if cpu.tuning.iothread_period %}
<iothread_period>{{ cpu.tuning.iothread_period }}</iothread_period>
{%- endif %}
{%- if cpu.tuning.iothread_quota %}
<iothread_quota>{{ cpu.tuning.iothread_quota }}</iothread_quota>
{%- endif %}
{%- if cpu.tuning.vcpusched %}
{%- for sched in cpu.tuning.vcpusched %}
<vcpusched scheduler='{{ sched.scheduler }}'
{%- if sched.get("vcpus") %} vcpus='{{ sched.get("vcpus") }}'{% endif -%}
{%- if sched.get("priority") is not none %} priority='{{ sched.get("priority") }}'{% endif -%}
/>
{%- endfor %}
{%- endif %}
{%- if cpu.tuning.iothreadsched %}
{%- for sched in cpu.tuning.iothreadsched %}
<iothreadsched scheduler='{{ sched.scheduler }}'
{%- if sched.get("iothreads") %} iothreads='{{ sched.get("iothreads") }}'{% endif -%}
{%- if sched.get("priority") is not none %} priority='{{ sched.get("priority") }}'{% endif -%}
/>
{%- endfor %}
{%- endif %}
{%- if cpu.tuning.emulatorsched %}
<emulatorsched scheduler='{{ cpu.tuning.emulatorsched.scheduler }}'
{%- if cpu.tuning.emulatorsched.get("priority") is not none %} priority='{{ cpu.tuning.emulatorsched.get("priority") }}'{% endif -%}
/>
{%- endif %}
{%- if cpu.tuning.cachetune %}
{%- for k, v in cpu.tuning.cachetune.items() %}
<cachetune vcpus='{{ k }}'>
{%- for e, atrs in v.items() %}
{%- if e is number and atrs %}
<cache id='{{ e }}' {%- for atr, val in atrs.items() %} {{ atr }}='{{ val }}' {%- endfor %} />
{%- elif e is not number %}
{%- for atr, val in atrs.items() %}
<monitor level='{{ val }}' vcpus='{{ atr }}'/>
{%- endfor %}
{%- endif %}
{%- endfor %}
</cachetune>
{%- endfor %}
{%- endif %}
{%- if cpu.tuning.memorytune %}
{%- for vcpus, nodes in cpu.tuning.memorytune.items() %}
<memorytune vcpus='{{ vcpus}}'>
{%- for id, bandwidth in nodes.items() %}
<node id='{{ id }}' bandwidth='{{ bandwidth }}'/>
{%- endfor %}
</memorytune>
{%- endfor %}
{%- endif %}
</cputune>
{%- endif %}
{%- if mem.max %}
<maxMemory {{ opt_attribute(mem, 'slots') }} unit='KiB'>{{ to_kib(mem.max) }}</maxMemory>
@ -81,7 +173,7 @@
<numatune>
{%- if 'memory' in numatune and numatune.memory %}
<memory mode='{{ numatune.memory.mode }}'
{%- if numatune.memory.nodeset %}nodeset='{{ numatune.memory.nodeset }}'{%- endif %}
{%- if numatune.memory.nodeset %} nodeset='{{ numatune.memory.nodeset }}'{%- endif %}
/>
{%- endif %}
{%- if 'memnodes' in numatune and numatune.memnodes %}

View file

@ -666,6 +666,187 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
{"0": "20", "1": "10"},
)
def test_gen_xml_cputune(self):
"""
Test virt._gen_xml() with CPU tuning
"""
diskp = virt._disk_profile(self.mock_conn, "default", "kvm", [], "hello")
nicp = virt._nic_profile("default", "kvm")
cputune = {
"shares": 2048,
"period": 122000,
"quota": -1,
"global_period": 1000000,
"global_quota": -3,
"emulator_period": 1200000,
"emulator_quota": -10,
"iothread_period": 133000,
"iothread_quota": -1,
"vcpupin": {0: "1-4,^2", 1: "0,1", 2: "2,3", 3: "0,4"},
"emulatorpin": "1-3",
"iothreadpin": {1: "5-6", 2: "7-8"},
"vcpusched": [
{"scheduler": "fifo", "priority": 1, "vcpus": "0"},
{"scheduler": "fifo", "priority": 2, "vcpus": "1"},
{"scheduler": "idle", "priority": 3, "vcpus": "2"},
],
"iothreadsched": [
{"scheduler": "idle"},
{"scheduler": "batch", "iothreads": "5-7", "priority": 1},
],
"emulatorsched": {"scheduler": "rr", "priority": 2},
"cachetune": {
"0-3": {
0: {"level": 3, "type": "both", "size": 3},
1: {"level": 3, "type": "both", "size": 3},
"monitor": {1: 3, "0-3": 3},
},
"4-5": {"monitor": {4: 3, 5: 2}},
},
"memorytune": {"0-2": {0: 60}, "3-4": {0: 50, 1: 70}},
}
xml_data = virt._gen_xml(
self.mock_conn,
"hello",
{"maximum": 1, "tuning": cputune, "iothreads": 2},
512,
diskp,
nicp,
"kvm",
"hvm",
"x86_64",
)
root = ET.fromstring(xml_data)
self.assertEqual(root.find("cputune").find("shares").text, "2048")
self.assertEqual(root.find("cputune").find("period").text, "122000")
self.assertEqual(root.find("cputune").find("quota").text, "-1")
self.assertEqual(root.find("cputune").find("global_period").text, "1000000")
self.assertEqual(root.find("cputune").find("global_quota").text, "-3")
self.assertEqual(root.find("cputune").find("emulator_period").text, "1200000")
self.assertEqual(root.find("cputune").find("emulator_quota").text, "-10")
self.assertEqual(root.find("cputune").find("iothread_period").text, "133000")
self.assertEqual(root.find("cputune").find("iothread_quota").text, "-1")
self.assertEqual(
root.find("cputune").find("vcpupin[@vcpu='0']").attrib.get("cpuset"),
"1-4,^2",
)
self.assertEqual(
root.find("cputune").find("vcpupin[@vcpu='1']").attrib.get("cpuset"), "0,1",
)
self.assertEqual(
root.find("cputune").find("vcpupin[@vcpu='2']").attrib.get("cpuset"), "2,3",
)
self.assertEqual(
root.find("cputune").find("vcpupin[@vcpu='3']").attrib.get("cpuset"), "0,4",
)
self.assertEqual(
root.find("cputune").find("emulatorpin").attrib.get("cpuset"), "1-3"
)
self.assertEqual(
root.find("cputune")
.find("iothreadpin[@iothread='1']")
.attrib.get("cpuset"),
"5-6",
)
self.assertEqual(
root.find("cputune")
.find("iothreadpin[@iothread='2']")
.attrib.get("cpuset"),
"7-8",
)
self.assertDictEqual(
{
s.get("vcpus"): {
"scheduler": s.get("scheduler"),
"priority": s.get("priority"),
}
for s in root.findall("cputune/vcpusched")
},
{
"0": {"scheduler": "fifo", "priority": "1"},
"1": {"scheduler": "fifo", "priority": "2"},
"2": {"scheduler": "idle", "priority": "3"},
},
)
self.assertDictEqual(
{
s.get("iothreads"): {
"scheduler": s.get("scheduler"),
"priority": s.get("priority"),
}
for s in root.findall("cputune/iothreadsched")
},
{
None: {"scheduler": "idle", "priority": None},
"5-7": {"scheduler": "batch", "priority": "1"},
},
)
self.assertEqual(root.find("cputune/emulatorsched").get("scheduler"), "rr")
self.assertEqual(root.find("cputune/emulatorsched").get("priority"), "2")
self.assertEqual(
root.find("./cputune/cachetune[@vcpus='0-3']").attrib.get("vcpus"), "0-3"
)
self.assertEqual(
root.find("./cputune/cachetune[@vcpus='0-3']/cache[@id='0']").attrib.get(
"level"
),
"3",
)
self.assertEqual(
root.find("./cputune/cachetune[@vcpus='0-3']/cache[@id='0']").attrib.get(
"type"
),
"both",
)
self.assertEqual(
root.find(
"./cputune/cachetune[@vcpus='0-3']/monitor[@vcpus='1']"
).attrib.get("level"),
"3",
)
self.assertNotEqual(
root.find("./cputune/cachetune[@vcpus='0-3']/monitor[@vcpus='1']"), None
)
self.assertNotEqual(
root.find("./cputune/cachetune[@vcpus='4-5']").attrib.get("vcpus"), None
)
self.assertEqual(
root.find("./cputune/cachetune[@vcpus='4-5']/cache[@id='0']"), None
)
self.assertEqual(
root.find(
"./cputune/cachetune[@vcpus='4-5']/monitor[@vcpus='4']"
).attrib.get("level"),
"3",
)
self.assertEqual(
root.find(
"./cputune/cachetune[@vcpus='4-5']/monitor[@vcpus='5']"
).attrib.get("level"),
"2",
)
self.assertNotEqual(root.find("./cputune/memorytune[@vcpus='0-2']"), None)
self.assertEqual(
root.find("./cputune/memorytune[@vcpus='0-2']/node[@id='0']").attrib.get(
"bandwidth"
),
"60",
)
self.assertNotEqual(root.find("./cputune/memorytune[@vcpus='3-4']"), None)
self.assertEqual(
root.find("./cputune/memorytune[@vcpus='3-4']/node[@id='0']").attrib.get(
"bandwidth"
),
"50",
)
self.assertEqual(
root.find("./cputune/memorytune[@vcpus='3-4']/node[@id='1']").attrib.get(
"bandwidth"
),
"70",
)
self.assertEqual(root.find("iothreads").text, "2")
def test_default_disk_profile_hypervisor_esxi(self):
"""
Test virt._disk_profile() default ESXi profile
@ -2665,6 +2846,179 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
self.assertEqual(setxml.find("./memoryBacking/access").attrib["mode"], "shared")
self.assertNotEqual(setxml.find("./memoryBacking/discard"), None)
# test adding iothreads
self.assertEqual(
{
"definition": True,
"disk": {"attached": [], "detached": [], "updated": []},
"interface": {"attached": [], "detached": []},
"cpu": True,
},
virt.update("my_vm", cpu={"iothreads": 5}),
)
setxml = ET.fromstring(define_mock.call_args[0][0])
self.assertEqual(setxml.find("iothreads").text, "5")
# test adding cpu tune parameters
cputune = {
"shares": 2048,
"period": 122000,
"quota": -1,
"global_period": 1000000,
"global_quota": -3,
"emulator_period": 1200000,
"emulator_quota": -10,
"iothread_period": 133000,
"iothread_quota": -1,
"vcpupin": {0: "1-4,^2", 1: "0,1", 2: "2,3", 3: "0,4"},
"emulatorpin": "1-3",
"iothreadpin": {1: "5-6", 2: "7-8"},
"vcpusched": [
{"scheduler": "fifo", "priority": 1, "vcpus": "0"},
{"scheduler": "fifo", "priotity": 2, "vcpus": "1"},
{"scheduler": "idle", "priotity": 3, "vcpus": "2"},
],
"iothreadsched": [{"scheduler": "batch", "iothreads": "7"}],
"cachetune": {
"0-3": {
0: {"level": 3, "type": "both", "size": 3},
1: {"level": 3, "type": "both", "size": 3},
"monitor": {1: 3, "0-3": 3},
},
"4-5": {"monitor": {4: 3, 5: 2}},
},
"memorytune": {"0-2": {0: 60}, "3-4": {0: 50, 1: 70}},
}
self.assertEqual(
{
"definition": True,
"disk": {"attached": [], "detached": [], "updated": []},
"interface": {"attached": [], "detached": []},
"cpu": True,
},
virt.update("my_vm", cpu={"tuning": cputune}),
)
setxml = ET.fromstring(define_mock.call_args[0][0])
self.assertEqual(setxml.find("cputune").find("shares").text, "2048")
self.assertEqual(setxml.find("cputune").find("period").text, "122000")
self.assertEqual(setxml.find("cputune").find("quota").text, "-1")
self.assertEqual(setxml.find("cputune").find("global_period").text, "1000000")
self.assertEqual(setxml.find("cputune").find("global_quota").text, "-3")
self.assertEqual(setxml.find("cputune").find("emulator_period").text, "1200000")
self.assertEqual(setxml.find("cputune").find("emulator_quota").text, "-10")
self.assertEqual(setxml.find("cputune").find("iothread_period").text, "133000")
self.assertEqual(setxml.find("cputune").find("iothread_quota").text, "-1")
self.assertEqual(
setxml.find("cputune").find("vcpupin[@vcpu='0']").attrib.get("cpuset"),
"1-4,^2",
)
self.assertEqual(
setxml.find("cputune").find("vcpupin[@vcpu='1']").attrib.get("cpuset"),
"0,1",
)
self.assertEqual(
setxml.find("cputune").find("vcpupin[@vcpu='2']").attrib.get("cpuset"),
"2,3",
)
self.assertEqual(
setxml.find("cputune").find("vcpupin[@vcpu='3']").attrib.get("cpuset"),
"0,4",
)
self.assertEqual(
setxml.find("cputune").find("emulatorpin").attrib.get("cpuset"), "1-3"
)
self.assertEqual(
setxml.find("cputune")
.find("iothreadpin[@iothread='1']")
.attrib.get("cpuset"),
"5-6",
)
self.assertEqual(
setxml.find("cputune")
.find("iothreadpin[@iothread='2']")
.attrib.get("cpuset"),
"7-8",
)
self.assertEqual(
setxml.find("cputune").find("vcpusched[@vcpus='0']").attrib.get("priority"),
"1",
)
self.assertEqual(
setxml.find("cputune")
.find("vcpusched[@vcpus='0']")
.attrib.get("scheduler"),
"fifo",
)
self.assertEqual(
setxml.find("cputune").find("iothreadsched").attrib.get("iothreads"), "7"
)
self.assertEqual(
setxml.find("cputune").find("iothreadsched").attrib.get("scheduler"),
"batch",
)
self.assertEqual(
setxml.find("./cputune/cachetune[@vcpus='0-3']").attrib.get("vcpus"), "0-3"
)
self.assertEqual(
setxml.find("./cputune/cachetune[@vcpus='0-3']/cache[@id='0']").attrib.get(
"level"
),
"3",
)
self.assertEqual(
setxml.find("./cputune/cachetune[@vcpus='0-3']/cache[@id='0']").attrib.get(
"type"
),
"both",
)
self.assertEqual(
setxml.find(
"./cputune/cachetune[@vcpus='0-3']/monitor[@vcpus='1']"
).attrib.get("level"),
"3",
)
self.assertNotEqual(
setxml.find("./cputune/cachetune[@vcpus='0-3']/monitor[@vcpus='1']"), None
)
self.assertNotEqual(
setxml.find("./cputune/cachetune[@vcpus='4-5']").attrib.get("vcpus"), None
)
self.assertEqual(
setxml.find("./cputune/cachetune[@vcpus='4-5']/cache[@id='0']"), None
)
self.assertEqual(
setxml.find(
"./cputune/cachetune[@vcpus='4-5']/monitor[@vcpus='4']"
).attrib.get("level"),
"3",
)
self.assertEqual(
setxml.find(
"./cputune/cachetune[@vcpus='4-5']/monitor[@vcpus='5']"
).attrib.get("level"),
"2",
)
self.assertNotEqual(setxml.find("./cputune/memorytune[@vcpus='0-2']"), None)
self.assertEqual(
setxml.find("./cputune/memorytune[@vcpus='0-2']/node[@id='0']").attrib.get(
"bandwidth"
),
"60",
)
self.assertNotEqual(setxml.find("./cputune/memorytune[@vcpus='3-4']"), None)
self.assertEqual(
setxml.find("./cputune/memorytune[@vcpus='3-4']/node[@id='0']").attrib.get(
"bandwidth"
),
"50",
)
self.assertEqual(
setxml.find("./cputune/memorytune[@vcpus='3-4']/node[@id='1']").attrib.get(
"bandwidth"
),
"70",
)
# Update disks case
devattach_mock = MagicMock(return_value=0)
devdetach_mock = MagicMock(return_value=0)
@ -4454,6 +4808,426 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
virt.update("vm_with_memback_param", mem=unchanged_page),
)
def test_update_iothreads_params(self):
"""
Test virt.update() with iothreads parameters.
"""
xml_with_iothreads_params = """
<domain type='kvm' id='8'>
<name>xml_with_iothreads_params</name>
<memory unit='KiB'>1048576</memory>
<currentMemory unit='KiB'>1048576</currentMemory>
<maxMemory slots="12" unit="KiB">1048576</maxMemory>
<vcpu placement='auto'>1</vcpu>
<iothreads>6</iothreads>
<os>
<type arch='x86_64' machine='pc-i440fx-2.6'>hvm</type>
</os>
</domain>
"""
domain_mock = self.set_mock_vm(
"xml_with_iothreads_params", xml_with_iothreads_params
)
domain_mock.OSType = MagicMock(return_value="hvm")
define_mock = MagicMock(return_value=True)
self.mock_conn.defineXML = define_mock
# test updating existing iothreads
self.assertEqual(
{
"definition": True,
"disk": {"attached": [], "detached": [], "updated": []},
"interface": {"attached": [], "detached": []},
"cpu": False,
},
virt.update("xml_with_iothreads_params", cpu={"iothreads": 7}),
)
setxml = ET.fromstring(define_mock.call_args[0][0])
self.assertEqual(setxml.find("iothreads").text, "7")
def test_update_cputune_paramters(self):
"""
Test virt.update() with cputune parameters.
"""
xml_with_cputune_params = """
<domain type='kvm' id='8'>
<name>xml_with_cputune_params</name>
<memory unit='KiB'>1048576</memory>
<currentMemory unit='KiB'>1048576</currentMemory>
<maxMemory slots="12" unit="KiB">1048576</maxMemory>
<vcpu placement='auto'>1</vcpu>
<iothreads>4</iothreads>
<cputune>
<shares>2048</shares>
<period>1000000</period>
<quota>-1</quota>
<global_period>1000000</global_period>
<global_quota>-1</global_quota>
<emulator_period>1000000</emulator_period>
<emulator_quota>-1</emulator_quota>
<iothread_period>1000000</iothread_period>
<iothread_quota>-1</iothread_quota>
<vcpupin vcpu="0" cpuset="0-2"/>
<vcpupin vcpu="1" cpuset="3"/>
<vcpupin vcpu="2" cpuset="4"/>
<vcpupin vcpu="3" cpuset="5-7"/>
<emulatorpin cpuset="1-2"/>
<iothreadpin iothread="1" cpuset="1-5"/>
<iothreadpin iothread="2" cpuset="6-7"/>
<vcpusched vcpus="0" scheduler="idle" priority="3"/>
<vcpusched vcpus="1" scheduler="rr" priority="1"/>
<vcpusched vcpus="2" scheduler="fifo" priority="2"/>
<iothreadsched iothreads="4" scheduler="fifo"/>
<emulatorsched scheduler="idle"/>
<cachetune vcpus="0-4">
<cache id="0" level="2" type="both" size="4" unit="KiB"/>
<cache id="1" level="2" type="both" size="4" unit="KiB"/>
<monitor level="5" vcpus="0-2"/>
<monitor level="6" vcpus="1-3"/>
</cachetune>
<cachetune vcpus="5-8">
<monitor level="5" vcpus="5-6"/>
<monitor level="3" vcpus="7-8"/>
</cachetune>
<memorytune vcpus="0-6">
<node id="0" bandwidth="45"/>
</memorytune>
<memorytune vcpus="7-8">
<node id="0" bandwidth="120"/>
</memorytune>
</cputune>
<os>
<type arch='x86_64' machine='pc-i440fx-2.6'>hvm</type>
</os>
</domain>
"""
domain_mock = self.set_mock_vm(
"xml_with_cputune_params", xml_with_cputune_params
)
domain_mock.OSType = MagicMock(return_value="hvm")
define_mock = MagicMock(return_value=True)
self.mock_conn.defineXML = define_mock
# test updating existing cputune parameters
cputune = {
"shares": 1024,
"period": 5000,
"quota": -20,
"global_period": 4000,
"global_quota": -30,
"emulator_period": 3000,
"emulator_quota": -4,
"iothread_period": 7000,
"iothread_quota": -5,
"vcpupin": {0: "1-4,^2", 1: "0,1", 2: "2,3", 3: "0,4"},
"emulatorpin": "1-3",
"iothreadpin": {1: "5-6", 2: "7-8"},
"vcpusched": [
{"scheduler": "fifo", "priority": 1, "vcpus": "0"},
{"scheduler": "fifo", "priority": 2, "vcpus": "1"},
{"scheduler": "idle", "priority": 3, "vcpus": "2"},
],
"iothreadsched": [
{"scheduler": "batch", "iothreads": "5-7", "priority": 1}
],
"emulatorsched": {"scheduler": "rr", "priority": 2},
"cachetune": {
"0-3": {
0: {"level": 3, "type": "both", "size": 3},
1: {"level": 3, "type": "both", "size": 3},
"monitor": {1: 3, "0-3": 3},
},
"4-5": {"monitor": {4: 3, 5: 2}},
},
"memorytune": {"0-2": {0: 60}, "3-4": {0: 50, 1: 70}},
}
self.assertEqual(
{
"definition": True,
"disk": {"attached": [], "detached": [], "updated": []},
"interface": {"attached": [], "detached": []},
"cpu": False,
},
virt.update("xml_with_cputune_params", cpu={"tuning": cputune}),
)
setxml = ET.fromstring(define_mock.call_args[0][0])
self.assertEqual(setxml.find("cputune").find("shares").text, "1024")
self.assertEqual(setxml.find("cputune").find("period").text, "5000")
self.assertEqual(setxml.find("cputune").find("quota").text, "-20")
self.assertEqual(setxml.find("cputune").find("global_period").text, "4000")
self.assertEqual(setxml.find("cputune").find("global_quota").text, "-30")
self.assertEqual(setxml.find("cputune").find("emulator_period").text, "3000")
self.assertEqual(setxml.find("cputune").find("emulator_quota").text, "-4")
self.assertEqual(setxml.find("cputune").find("iothread_period").text, "7000")
self.assertEqual(setxml.find("cputune").find("iothread_quota").text, "-5")
self.assertEqual(
setxml.find("cputune").find("vcpupin[@vcpu='0']").attrib.get("cpuset"),
"1-4,^2",
)
self.assertEqual(
setxml.find("cputune").find("vcpupin[@vcpu='1']").attrib.get("cpuset"),
"0,1",
)
self.assertEqual(
setxml.find("cputune").find("vcpupin[@vcpu='2']").attrib.get("cpuset"),
"2,3",
)
self.assertEqual(
setxml.find("cputune").find("vcpupin[@vcpu='3']").attrib.get("cpuset"),
"0,4",
)
self.assertEqual(
setxml.find("cputune").find("emulatorpin").attrib.get("cpuset"), "1-3"
)
self.assertEqual(
setxml.find("cputune")
.find("iothreadpin[@iothread='1']")
.attrib.get("cpuset"),
"5-6",
)
self.assertEqual(
setxml.find("cputune")
.find("iothreadpin[@iothread='2']")
.attrib.get("cpuset"),
"7-8",
)
self.assertDictEqual(
{
s.get("vcpus"): {
"scheduler": s.get("scheduler"),
"priority": s.get("priority"),
}
for s in setxml.findall("cputune/vcpusched")
},
{
"0": {"scheduler": "fifo", "priority": "1"},
"1": {"scheduler": "fifo", "priority": "2"},
"2": {"scheduler": "idle", "priority": "3"},
},
)
self.assertDictEqual(
{
s.get("iothreads"): {
"scheduler": s.get("scheduler"),
"priority": s.get("priority"),
}
for s in setxml.findall("cputune/iothreadsched")
},
{"5-7": {"scheduler": "batch", "priority": "1"}},
)
self.assertEqual(setxml.find("cputune/emulatorsched").get("scheduler"), "rr")
self.assertEqual(setxml.find("cputune/emulatorsched").get("priority"), "2")
self.assertEqual(
setxml.find("./cputune/cachetune[@vcpus='0-3']").attrib.get("vcpus"), "0-3"
)
self.assertEqual(
setxml.find("./cputune/cachetune[@vcpus='0-3']/cache[@id='0']").attrib.get(
"level"
),
"3",
)
self.assertEqual(
setxml.find("./cputune/cachetune[@vcpus='0-3']/cache[@id='0']").attrib.get(
"type"
),
"both",
)
self.assertEqual(
setxml.find(
"./cputune/cachetune[@vcpus='0-3']/monitor[@vcpus='1']"
).attrib.get("level"),
"3",
)
self.assertNotEqual(
setxml.find("./cputune/cachetune[@vcpus='0-3']/monitor[@vcpus='1']"), None
)
self.assertNotEqual(
setxml.find("./cputune/cachetune[@vcpus='4-5']").attrib.get("vcpus"), None
)
self.assertEqual(
setxml.find("./cputune/cachetune[@vcpus='4-5']/cache[@id='0']"), None
)
self.assertEqual(
setxml.find(
"./cputune/cachetune[@vcpus='4-5']/monitor[@vcpus='4']"
).attrib.get("level"),
"3",
)
self.assertEqual(
setxml.find(
"./cputune/cachetune[@vcpus='4-5']/monitor[@vcpus='5']"
).attrib.get("level"),
"2",
)
self.assertNotEqual(setxml.find("./cputune/memorytune[@vcpus='0-2']"), None)
self.assertEqual(
setxml.find("./cputune/memorytune[@vcpus='0-2']/node[@id='0']").attrib.get(
"bandwidth"
),
"60",
)
self.assertNotEqual(setxml.find("./cputune/memorytune[@vcpus='3-4']"), None)
self.assertEqual(
setxml.find("./cputune/memorytune[@vcpus='3-4']/node[@id='0']").attrib.get(
"bandwidth"
),
"50",
)
self.assertEqual(
setxml.find("./cputune/memorytune[@vcpus='3-4']/node[@id='1']").attrib.get(
"bandwidth"
),
"70",
)
# test removing cputune attributes and sub elements
cputune = {
"shares": None,
"period": 20000,
"quota": None,
"global_period": 5000,
"global_quota": None,
"emulator_period": 2000,
"emulator_quota": -4,
"iothread_period": None,
"iothread_quota": -5,
"vcpupin": {0: "1-4,^2", 2: "2,4"},
"emulatorpin": None,
"iothreadpin": {1: "5-6"},
"vcpusched": [{"scheduler": "idle", "priority": 5, "vcpus": "1"}],
"iothreadsched": None,
"cachetune": {
"0-3": {
0: {"level": 4, "type": "data", "size": 7},
"monitor": {"1-2": 11},
},
},
"memorytune": {"3-4": {0: 37, 1: 73}},
}
self.assertEqual(
{
"definition": True,
"disk": {"attached": [], "detached": [], "updated": []},
"interface": {"attached": [], "detached": []},
"cpu": False,
},
virt.update("xml_with_cputune_params", cpu={"tuning": cputune}),
)
setxml = ET.fromstring(define_mock.call_args[0][0])
self.assertEqual(setxml.find("cputune").find("shares"), None)
self.assertEqual(setxml.find("cputune").find("period").text, "20000")
self.assertEqual(setxml.find("cputune").find("quota"), None)
self.assertEqual(setxml.find("cputune").find("global_period").text, "5000")
self.assertEqual(setxml.find("cputune").find("global_quota"), None)
self.assertEqual(setxml.find("cputune").find("emulator_period").text, "2000")
self.assertEqual(setxml.find("cputune").find("emulator_quota").text, "-4")
self.assertEqual(setxml.find("cputune").find("iothread_period"), None)
self.assertEqual(setxml.find("cputune").find("iothread_quota").text, "-5")
self.assertEqual(
setxml.find("cputune").find("vcpupin[@vcpu='0']").attrib.get("cpuset"),
"1-4,^2",
)
self.assertEqual(setxml.find("cputune").find("vcpupin[@vcpu='1']"), None)
self.assertEqual(
setxml.find("cputune").find("vcpupin[@vcpu='2']").attrib.get("cpuset"),
"2,4",
)
self.assertEqual(setxml.find("cputune").find("vcpupin[@vcpu='3']"), None)
self.assertEqual(setxml.find("cputune").find("emulatorpin"), None)
self.assertEqual(
setxml.find("cputune")
.find("iothreadpin[@iothread='1']")
.attrib.get("cpuset"),
"5-6",
)
self.assertEqual(
setxml.find("cputune").find("iothreadpin[@iothread='2']"), None
)
self.assertDictEqual(
{
s.get("vcpus"): {
"scheduler": s.get("scheduler"),
"priority": s.get("priority"),
}
for s in setxml.findall("cputune/vcpusched")
},
{"1": {"scheduler": "idle", "priority": "5"}},
)
self.assertEqual(setxml.find("cputune").find("iothreadsched"), None)
self.assertEqual(
setxml.find("./cputune/cachetune[@vcpus='0-3']").attrib.get("vcpus"), "0-3"
)
self.assertEqual(
setxml.find("./cputune/cachetune[@vcpus='0-3']/cache[@id='0']").attrib.get(
"size"
),
"7",
)
self.assertEqual(
setxml.find("./cputune/cachetune[@vcpus='0-3']/cache[@id='0']").attrib.get(
"level"
),
"4",
)
self.assertEqual(
setxml.find("./cputune/cachetune[@vcpus='0-3']/cache[@id='0']").attrib.get(
"type"
),
"data",
)
self.assertEqual(
setxml.find(
"./cputune/cachetune[@vcpus='0-3']/monitor[@vcpus='1-2']"
).attrib.get("level"),
"11",
)
self.assertEqual(
setxml.find("./cputune/cachetune[@vcpus='0-3']/monitor[@vcpus='3-4']"), None
)
self.assertEqual(
setxml.find("./cputune/cachetune[@vcpus='0-3']/cache[@id='1']"), None
)
self.assertEqual(setxml.find("./cputune/cachetune[@vcpus='4-5']"), None)
self.assertEqual(setxml.find("./cputune/memorytune[@vcpus='0-2']"), None)
self.assertEqual(
setxml.find("./cputune/memorytune[@vcpus='3-4']/node[@id='0']").attrib.get(
"bandwidth"
),
"37",
)
self.assertEqual(
setxml.find("./cputune/memorytune[@vcpus='3-4']/node[@id='1']").attrib.get(
"bandwidth"
),
"73",
)
cputune_subelement = {
"vcpupin": None,
"iothreadpin": None,
"vcpusched": None,
"iothreadsched": None,
"cachetune": None,
"memorytune": None,
}
self.assertEqual(
{
"definition": True,
"disk": {"attached": [], "detached": [], "updated": []},
"interface": {"attached": [], "detached": []},
"cpu": False,
},
virt.update("xml_with_cputune_params", cpu={"tuning": cputune_subelement}),
)
setxml = ET.fromstring(define_mock.call_args[0][0])
self.assertEqual(setxml.find("cputune").find("vcpupin"), None)
self.assertEqual(setxml.find("cputune").find("iothreadpin"), None)
self.assertEqual(setxml.find("cputune").find("vcpusched"), None)
self.assertEqual(setxml.find("cputune").find("iothreadsched"), None)
self.assertEqual(setxml.find("cputune").find("cachetune"), None)
self.assertEqual(setxml.find("cputune").find("memorytune"), None)
def test_handle_unit(self):
"""
Test regex function for handling units