Skip to content

Commit 72cb4ec

Browse files
committed
Script to interpret virsh configs
Signed-off-by: Krzysztof Filipek <krzysztof.filipek@intel.com>
1 parent f31f7b0 commit 72cb4ec

File tree

4 files changed

+170
-29
lines changed

4 files changed

+170
-29
lines changed

.github/workflows/qemu.yml

Lines changed: 9 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ jobs:
2525
- name: Install qemu
2626
run: |
2727
sudo apt update && sudo apt install -y qemu-system genisoimage qemu-utils
28+
- name: Install libvirt and script dependencies
29+
run: |
30+
sudo apt-get install -y libvirt-clients libvirt-daemon-system libvirt-daemon virtinst bridge-utils
31+
pip install -r scripts/qemu/requirements.txt
32+
sudo usermod -a -G kvm,libvirt $USER
2833
- name: Run ssh-keygen
2934
run: ssh-keygen -b 4096 -N '' -f ~/.ssh/id_rsa
3035
- name: Generate iso with user info
@@ -65,6 +70,9 @@ jobs:
6570
run: wget https://cloud-images.ubuntu.com/releases/lunar/release/ubuntu-23.04-server-cloudimg-amd64.img
6671
- name: Resize image
6772
run: qemu-img resize ./ubuntu-23.04-server-cloudimg-amd64.img +4G
73+
- name: Print qemu args
74+
run: |
75+
echo `python3 scripts/qemu/qemu_config.py scripts/qemu/configs/default.xml | sed s/''\''/'/g`
6876
- name: Run qemu
6977
run: |
7078
sudo qemu-system-x86_64 \
@@ -73,35 +81,7 @@ jobs:
7381
-machine q35,usb=off,hmat=on \
7482
-enable-kvm \
7583
-net nic -net user,hostfwd=tcp::2222-:22 \
76-
-m 3500M \
77-
-smp 4 \
78-
-object memory-backend-ram,size=1100M,id=ram0 \
79-
-object memory-backend-ram,size=1200M,id=ram1 \
80-
-object memory-backend-ram,size=1200M,id=ram2 \
81-
-numa node,nodeid=0,memdev=ram0,cpus=0-1 \
82-
-numa node,nodeid=1,memdev=ram1,cpus=2-3 \
83-
-numa node,nodeid=2,memdev=ram2,initiator=0 \
84-
-numa dist,src=0,dst=0,val=10 \
85-
-numa dist,src=0,dst=1,val=20 \
86-
-numa dist,src=0,dst=2,val=17 \
87-
-numa dist,src=1,dst=0,val=20 \
88-
-numa dist,src=1,dst=1,val=10 \
89-
-numa dist,src=1,dst=2,val=28 \
90-
-numa dist,src=2,dst=0,val=17 \
91-
-numa dist,src=2,dst=1,val=28 \
92-
-numa dist,src=2,dst=2,val=10 \
93-
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-latency,latency=10 \
94-
-numa hmat-lb,initiator=0,target=0,hierarchy=memory,data-type=access-bandwidth,bandwidth=10485760 \
95-
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-latency,latency=20 \
96-
-numa hmat-lb,initiator=0,target=1,hierarchy=memory,data-type=access-bandwidth,bandwidth=5242880 \
97-
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-latency,latency=16 \
98-
-numa hmat-lb,initiator=0,target=2,hierarchy=memory,data-type=access-bandwidth,bandwidth=1048576 \
99-
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-latency,latency=20 \
100-
-numa hmat-lb,initiator=1,target=0,hierarchy=memory,data-type=access-bandwidth,bandwidth=5242880 \
101-
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-latency,latency=10 \
102-
-numa hmat-lb,initiator=1,target=1,hierarchy=memory,data-type=access-bandwidth,bandwidth=10485760 \
103-
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-latency,latency=27 \
104-
-numa hmat-lb,initiator=1,target=2,hierarchy=memory,data-type=access-bandwidth,bandwidth=1048576 \
84+
$(echo `python3 scripts/qemu/qemu_config.py scripts/qemu/configs/default.xml | sed s/''\''/'/g`) \
10585
-daemonize -display none
10686
- name: Run ssh keyscan
10787
run: |

scripts/qemu/configs/default.xml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<!-- SPDX-License-Identifier: BSD-2-Clause
2+
# Copyright (C) 2024 Intel Corporation.
3+
-->
4+
<domain type='qemu'>
5+
<name>CascadeLake</name>
6+
<os>
7+
<type arch='x86_64' machine='pc'>hvm</type>
8+
</os>
9+
<vcpu placement='static'>4</vcpu>
10+
<cpu>
11+
<topology sockets='2' dies='1' cores='2' threads='1'/>
12+
<numa>
13+
<cell id='0' cpus='0-1' memory='1100' unit='MiB'>
14+
<distances>
15+
<sibling id='0' value='10'/>
16+
<sibling id='1' value='20'/>
17+
<sibling id='2' value='17'/>
18+
</distances>
19+
</cell>
20+
<cell id='1' cpus='2-3' memory='1200' unit='MiB'>
21+
<distances>
22+
<sibling id='0' value='20'/>
23+
<sibling id='1' value='10'/>
24+
<sibling id='2' value='28'/>
25+
</distances>
26+
</cell>
27+
<cell id='2' memory='1200' unit='MiB'>
28+
<distances>
29+
<sibling id='0' value='17'/>
30+
<sibling id='1' value='28'/>
31+
<sibling id='2' value='10'/>
32+
</distances>
33+
</cell>
34+
<interconnects>
35+
<latency initiator='0' target='0' type='access' value='10'/>
36+
<bandwidth initiator='0' target='0' type='access' value='10485760' unit='B'/>
37+
38+
<latency initiator='0' target='1' type='access' value='20'/>
39+
<bandwidth initiator='0' target='1' type='access' value='5242880' unit='B'/>
40+
41+
<latency initiator='0' target='2' type='access' value='16'/>
42+
<bandwidth initiator='0' target='2' type='access' value='1048576' unit='B'/>
43+
44+
<latency initiator='1' target='1' type='access' value='10'/>
45+
<bandwidth initiator='1' target='1' type='access' value='10485760' unit='B'/>
46+
47+
<latency initiator='1' target='2' type='access' value='27'/>
48+
<bandwidth initiator='1' target='2' type='access' value='1048576' unit='B'/>
49+
</interconnects>
50+
</numa>
51+
</cpu>
52+
</domain>

scripts/qemu/qemu_config.py

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import re
2+
import subprocess # nosec
3+
import sys
4+
import collections
5+
import os
6+
import psutil
7+
import shutil
8+
9+
# If you want to manually run this script please install deps by: pip install -r requirements.txt
10+
# To get virsh please install libvirt-clients
11+
#
12+
# Enable verbose mode by using environment variable ENABLE_VERBOSE=1
13+
14+
TopologyCfg = collections.namedtuple(
15+
"TopologyCfg", ["name", "hmat", "cpu_model", "cpu_options", "mem_options"]
16+
)
17+
18+
verbose_mode = False
19+
20+
21+
def enable_verbose():
22+
"""
23+
Parse command line arguments
24+
"""
25+
global verbose_mode
26+
verbose_mode = os.getenv("ENABLE_VERBOSE", False)
27+
28+
29+
def parse_topology_xml(tpg_file_name: str) -> TopologyCfg:
30+
"""
31+
Parse topology xml file
32+
"""
33+
try:
34+
virsh_path = shutil.which("virsh")
35+
if virsh_path is None:
36+
raise Exception("virsh not found in PATH")
37+
38+
result = subprocess.run( # nosec
39+
[virsh_path, "domxml-to-native", "qemu-argv", tpg_file_name],
40+
stdout=subprocess.PIPE,
41+
shell=False,
42+
)
43+
result.check_returncode()
44+
libvirt_args = result.stdout.decode("utf-8").strip()
45+
46+
tpg_cfg = {
47+
"name": re.search(r"guest=(\w+)", libvirt_args).group(1),
48+
"hmat": "hmat=on" in libvirt_args,
49+
"cpu_model": re.search(r"cpu (\S+)", libvirt_args).group(1),
50+
"cpu_options": re.search("(?=-smp)(.*)threads=[0-9]+", libvirt_args).group(
51+
0
52+
),
53+
"mem_options": re.search(
54+
r"-object '{\"qom-type\":\"memory-backend-ram\".*(?=-uuid)",
55+
libvirt_args,
56+
).group(0),
57+
}
58+
59+
if verbose_mode != False:
60+
print(f"Name: {tpg_cfg['cpu_model']}")
61+
print(f"HMAT: {tpg_cfg['hmat']}")
62+
print(f"CPU_MODEL: {tpg_cfg['cpu_model']}")
63+
print(f"CPU_OPTIONS: {tpg_cfg['cpu_options']}")
64+
print(f"MEM_OPTIONS: {tpg_cfg['mem_options']}")
65+
66+
tpg = TopologyCfg(**tpg_cfg)
67+
except subprocess.CalledProcessError:
68+
sys.exit(f"\n XML file: {tpg_file_name} error in virsh parsing")
69+
except Exception:
70+
sys.exit(f"\n Provided file is missing or missing virsh.")
71+
return tpg
72+
73+
74+
def get_qemu_args(tpg_file_name: str) -> str:
75+
"""
76+
Get QEMU arguments from topology xml file
77+
"""
78+
tpg = parse_topology_xml(tpg_file_name)
79+
qemu_args = f"-name {tpg.name} {calculate_memory(tpg)} -cpu {tpg.cpu_model} {tpg.cpu_options} {tpg.mem_options}"
80+
return qemu_args
81+
82+
83+
def calculate_memory(tpg: TopologyCfg) -> str:
84+
"""
85+
Memory used by QEMU
86+
"""
87+
if tpg.mem_options:
88+
mem_needed = 0
89+
all_sizes = re.findall(r'size":(\d+)', tpg.mem_options)
90+
for single_size in all_sizes:
91+
mem_needed += int(single_size)
92+
93+
mem = psutil.virtual_memory()
94+
if mem_needed >= mem.total:
95+
raise MemoryHostException(mem.total, mem_needed, tpg.name)
96+
return f"-m {mem_needed/1024/1024}M"
97+
else:
98+
return "-m 2G"
99+
100+
101+
if __name__ == "__main__":
102+
enable_verbose()
103+
104+
if len(sys.argv) > 1:
105+
tpg_file_name = sys.argv[1]
106+
else:
107+
sys.exit(f"\n Usage: {sys.argv[0]} <tpg_file_name>")
108+
print(get_qemu_args(tpg_file_name))

scripts/qemu/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
psutil

0 commit comments

Comments
 (0)