Skip to content

Commit 322c05a

Browse files
committed
Script to interpret virsh configs
Signed-off-by: Krzysztof Filipek <[email protected]>
1 parent 92f3cd6 commit 322c05a

File tree

4 files changed

+171
-29
lines changed

4 files changed

+171
-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: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<!-- SPDX-License-Identifier: BSD-2-Clause
2+
# Copyright (C) 2024 Intel Corporation.
3+
-->
4+
<domain type='qemu'>
5+
<name>CascadeLake2Var1</name>
6+
<os>
7+
<type arch='x86_64' machine='pc'>hvm</type>
8+
</os>
9+
<vcpu placement='static'>4</vcpu>
10+
<cpu>
11+
<model>Cascadelake-Server</model>
12+
<topology sockets='2' dies='1' cores='2' threads='1'/>
13+
<numa>
14+
<cell id='0' cpus='0-1' memory='1100' unit='MiB'>
15+
<distances>
16+
<sibling id='0' value='10'/>
17+
<sibling id='1' value='20'/>
18+
<sibling id='2' value='17'/>
19+
</distances>
20+
</cell>
21+
<cell id='1' cpus='2-3' memory='1200' unit='MiB'>
22+
<distances>
23+
<sibling id='0' value='20'/>
24+
<sibling id='1' value='10'/>
25+
<sibling id='2' value='28'/>
26+
</distances>
27+
</cell>
28+
<cell id='2' memory='1200' unit='MiB'>
29+
<distances>
30+
<sibling id='0' value='17'/>
31+
<sibling id='1' value='28'/>
32+
<sibling id='2' value='10'/>
33+
</distances>
34+
</cell>
35+
<interconnects>
36+
<latency initiator='0' target='0' type='access' value='10'/>
37+
<bandwidth initiator='0' target='0' type='access' value='10485760' unit='B'/>
38+
39+
<latency initiator='0' target='1' type='access' value='20'/>
40+
<bandwidth initiator='0' target='1' type='access' value='5242880' unit='B'/>
41+
42+
<latency initiator='0' target='2' type='access' value='16'/>
43+
<bandwidth initiator='0' target='2' type='access' value='1048576' unit='B'/>
44+
45+
<latency initiator='1' target='1' type='access' value='10'/>
46+
<bandwidth initiator='1' target='1' type='access' value='10485760' unit='B'/>
47+
48+
<latency initiator='1' target='2' type='access' value='27'/>
49+
<bandwidth initiator='1' target='2' type='access' value='1048576' unit='B'/>
50+
</interconnects>
51+
</numa>
52+
</cpu>
53+
</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 # pip install psutil
7+
import shutil
8+
9+
# First of all: pip install -r requirements.txt
10+
# Enable verbose mode by using environment variable ENABLE_VERBOSE=1
11+
12+
TopologyCfg = collections.namedtuple(
13+
"TopologyCfg", ["name", "hmat", "cpu_model", "cpu_options", "mem_options"]
14+
)
15+
16+
verbose_mode = False
17+
18+
19+
def enable_verbose():
20+
"""
21+
Parse command line arguments
22+
"""
23+
# print(os.getenv('ENABLE_VERBOSE', 'False'))
24+
global verbose_mode
25+
verbose_mode = os.getenv("ENABLE_VERBOSE", False)
26+
27+
28+
def parse_topology_xml(tpg_file_name: str) -> TopologyCfg:
29+
"""
30+
Parse topology xml file
31+
"""
32+
try:
33+
virsh_path = shutil.which("virsh")
34+
if virsh_path is None:
35+
raise Exception("virsh not found in PATH")
36+
37+
result = subprocess.run( # nosec
38+
[virsh_path, "domxml-to-native", "qemu-argv", tpg_file_name],
39+
stdout=subprocess.PIPE,
40+
shell=False,
41+
)
42+
result.check_returncode()
43+
libvirt_args = result.stdout.decode("utf-8").strip()
44+
45+
tpg_cfg = {
46+
"name": re.search(r"guest=(\w+)", libvirt_args).group(1),
47+
"hmat": "hmat=on" in libvirt_args,
48+
"cpu_model": re.search(r"cpu (\S+)", libvirt_args).group(1),
49+
"cpu_options": re.search("(?=-smp)(.*)threads=[0-9]+", libvirt_args).group(
50+
0
51+
),
52+
"mem_options": re.search(
53+
r"-object '{\"qom-type\":\"memory-backend-ram\".*(?=-uuid)",
54+
libvirt_args,
55+
).group(0),
56+
}
57+
58+
if verbose_mode != False:
59+
print(f"Name: {tpg_cfg['cpu_model']}")
60+
print(f"HMAT: {tpg_cfg['hmat']}")
61+
print(f"CPU_MODEL: {tpg_cfg['cpu_model']}")
62+
print(f"CPU_OPTIONS: {tpg_cfg['cpu_options']}")
63+
print(f"MEM_OPTIONS: {tpg_cfg['mem_options']}")
64+
65+
tpg = TopologyCfg(**tpg_cfg)
66+
except FileNotFoundError:
67+
sys.exit(f"\n Provided file is missing or missing virsh.")
68+
except subprocess.CalledProcessError:
69+
sys.exit(f"\n XML file: {tpg_file_name} error in virsh parsing")
70+
return tpg
71+
72+
73+
def get_qemu_args(tpg_file_name: str) -> str:
74+
"""
75+
Get QEMU arguments from topology xml file
76+
"""
77+
tpg = parse_topology_xml(tpg_file_name)
78+
qemu_args = f"-name {tpg.name} {calculate_memory(tpg)} -cpu {tpg.cpu_model} {tpg.cpu_options} {tpg.mem_options}"
79+
return qemu_args
80+
81+
82+
def calculate_memory(tpg: TopologyCfg) -> str:
83+
"""
84+
Memory used by QEMU
85+
"""
86+
if tpg.mem_options:
87+
mem_needed = 0
88+
all_sizes = re.findall(r'size":(\d+)', tpg.mem_options)
89+
for single_size in all_sizes:
90+
mem_needed += int(single_size)
91+
92+
mem = psutil.virtual_memory()
93+
if mem_needed >= mem.total:
94+
raise MemoryHostException(mem.total, mem_needed, tpg.name)
95+
return f"-m {mem_needed/1024/1024}M"
96+
else:
97+
return "-m 2G"
98+
99+
100+
if __name__ == "__main__":
101+
enable_verbose()
102+
103+
# Parse arg named: tpg_file_name
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)