Skip to content

Commit 33b733b

Browse files
committed
Inc_backup: Automate incremental backup lifecycle test cases
Automate cases: RHEL-187642 pull mode backup and managed save vm together RHEL-187641 pull mode backup and save vm together RHEL-199045 Start an existing backup job after libvirtd restarted RHEL-199046 kill qemu process between libvirtd stop/start when there is an existing pull-mode backup job Signed-off-by: meinaLi <[email protected]>
1 parent 00ed85c commit 33b733b

File tree

2 files changed

+243
-0
lines changed

2 files changed

+243
-0
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
- incremental_backup.lifecycle:
2+
type = incremental_backup_lifecycle
3+
start_vm = "no"
4+
disk_type = "file"
5+
target_disk = "vda"
6+
disk_dict = {"type_name": ${disk_type}, "target":{"dev": "%s", "bus": "virtio"}, "driver": {"name": "qemu", "type": "qcow2"}}
7+
full_checkpoint = "check_full"
8+
inc_checkpoint = "check_inc1"
9+
nbd_hostname = "localhost"
10+
nbd_tcp_port = "10809"
11+
backup_dict = {'mode': 'pull', 'server': {'name': '${nbd_hostname}', 'port': '${nbd_tcp_port}'}, 'disks': [{'name': 'vda', 'backup': 'yes', 'type': 'file', 'scratch': {'attrs': {'file': '%s'}}}]}
12+
checkpoint_dict = {'name': '%s', 'disks': [{'name': 'vda', 'checkpoint': 'bitmap'}]}
13+
inc_backup_dict = {'mode': 'pull', 'incremental': '${full_checkpoint}', 'server': {'name': '${nbd_hostname}', 'port': '${nbd_tcp_port}'}, 'disks': [{'name': 'vda', 'backup': 'yes', 'type': 'file', 'scratch': {'attrs': {'file': '%s'}}}]}
14+
variants test_case:
15+
- save_vm:
16+
expected_error = "Timed out during operation: cannot acquire state change lock.*remoteDispatchDomainBackupBegin"
17+
- managedsave:
18+
expected_error = "Timed out during operation: cannot acquire state change lock.*remoteDispatchDomainBackupBegin"
19+
- restart_service:
20+
expected_error = "Timed out during operation: cannot acquire state change lock.*monitor"
21+
- kill_qemu_process:
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
import os
2+
3+
from avocado.utils import process
4+
from virttest import data_dir
5+
from virttest import virsh
6+
from virttest import utils_backup
7+
from virttest.utils_libvirtd import Libvirtd
8+
9+
from virttest.libvirt_xml import vm_xml
10+
from virttest.libvirt_xml import backup_xml
11+
from virttest.libvirt_xml import checkpoint_xml
12+
from virttest.utils_test import libvirt
13+
14+
15+
def prepare_backup_xml(test, params, backup_type):
16+
"""
17+
Prepare the backup xml.
18+
19+
:return: return the backup options and the scratch file.
20+
"""
21+
scratch_file = data_dir.get_data_dir() + '/scratch_file_%s' % backup_type
22+
backup_dict = eval(params.get("backup_dict", "{}") % scratch_file)
23+
full_checkpoint = params.get("full_checkpoint")
24+
inc_checkpoint = params.get("inc_checkpoint")
25+
if backup_type == "inc":
26+
backup_dict.update({'incremental': full_checkpoint})
27+
checkpoint_dict = eval(params.get("checkpoint_dict") % inc_checkpoint)
28+
else:
29+
checkpoint_dict = eval(params.get("checkpoint_dict") % full_checkpoint)
30+
backup_dev = backup_xml.BackupXML()
31+
backup_dev.setup_attrs(**backup_dict)
32+
test.log.debug("The backup xml is %s." % backup_dev)
33+
checkpoint_dev = checkpoint_xml.CheckpointXML()
34+
checkpoint_dev.setup_attrs(**checkpoint_dict)
35+
backup_options = backup_dev.xml + " " + checkpoint_dev.xml
36+
return backup_options
37+
38+
39+
def start_full_backup(test, params):
40+
"""
41+
Start a full backup.
42+
43+
:return: return the backup file path.
44+
"""
45+
vm_name = params.get("main_vm")
46+
backup_file_path = data_dir.get_data_dir() + '/full.backup'
47+
target_disk = params.get("target_disk")
48+
nbd_hostname = params.get("nbd_hostname")
49+
nbd_tcp_port = params.get("nbd_tcp_port")
50+
nbd_params = {
51+
'nbd_protocol': "tcp",
52+
'nbd_hostname': nbd_hostname,
53+
'nbd_tcp_port': nbd_tcp_port,
54+
'nbd_export': target_disk
55+
}
56+
backup_options = prepare_backup_xml(test, params, backup_type="full")
57+
virsh.backup_begin(vm_name, backup_options, debug=True)
58+
try:
59+
utils_backup.pull_full_backup_to_file(nbd_params, backup_file_path)
60+
except Exception as details:
61+
test.fail("Fail to get full backup data: %s" % details)
62+
test.log.debug("Full backup to %s" % backup_file_path)
63+
return backup_file_path
64+
65+
66+
def start_incremental_backup(test, params):
67+
"""
68+
Start an incremental backup.
69+
70+
:return: return the backup file path.
71+
"""
72+
vm_name = params.get("main_vm")
73+
backup_file_path = data_dir.get_data_dir() + '/inc.backup'
74+
nbd_hostname = params.get("nbd_hostname")
75+
nbd_tcp_port = params.get("nbd_tcp_port")
76+
target_disk = params.get("target_disk")
77+
nbd_bitmap_name = "backup-" + target_disk
78+
original_disk_size = params.get("original_disk_size", "10G")
79+
nbd_params = {
80+
'nbd_hostname': nbd_hostname,
81+
'nbd_tcp_port': nbd_tcp_port,
82+
'nbd_export': target_disk
83+
}
84+
backup_options = prepare_backup_xml(test, params, backup_type="inc")
85+
virsh.backup_begin(vm_name, backup_options, debug=True, ignore_status=False)
86+
try:
87+
utils_backup.pull_incremental_backup_to_file(
88+
nbd_params, backup_file_path, nbd_bitmap_name,
89+
original_disk_size)
90+
except Exception as details:
91+
test.fail("Fail to get incremental backup data: %s" % details)
92+
return backup_file_path
93+
94+
95+
def test_save_vm(test, params):
96+
"""
97+
Test save vm with incremental backup.
98+
99+
:return: return the list of backup files.
100+
"""
101+
vm_name = params.get("main_vm")
102+
expected_error = params.get("expected_error")
103+
test.log.info("Start full backup.")
104+
backup_file_path = start_full_backup(test, params)
105+
backup_file_list.append(backup_file_path)
106+
107+
test.log.info("Do save before abort the backup job.")
108+
save_file = data_dir.get_data_dir() + '/%s.save' % vm_name
109+
save_result = virsh.save(vm_name, save_file, debug=True)
110+
libvirt.check_result(save_result, expected_error)
111+
abort_result = virsh.domjobabort(vm_name)
112+
libvirt.check_exit_status(abort_result)
113+
114+
test.log.info("Do save after abort the backup job.")
115+
virsh.save(vm_name, save_file, debug=True, ignore_status=False)
116+
virsh.restore(save_file, debug=True, ignore_status=False)
117+
if os.path.exists(save_file):
118+
os.remove(save_file)
119+
120+
test.log.info("Start incremental backup.")
121+
backup_file_path = start_incremental_backup(test, params)
122+
backup_file_list.append(backup_file_path)
123+
return backup_file_list
124+
125+
126+
def test_managedsave(test, params):
127+
"""
128+
Test managedsave vm with incremental backup.
129+
130+
:return: return the list of backup files
131+
"""
132+
vm_name = params.get("main_vm")
133+
expected_error = params.get("expected_error")
134+
test.log.info("Start full backup.")
135+
backup_file_path = start_full_backup(test, params)
136+
backup_file_list.append(backup_file_path)
137+
138+
test.log.info("Do managedsave before abort the backup job.")
139+
save_result = virsh.managedsave(vm_name, debug=True)
140+
libvirt.check_result(save_result, expected_error)
141+
virsh.domjobabort(vm_name)
142+
143+
test.log.info("Do managedsave after abort the backup job.")
144+
virsh.managedsave(vm_name, debug=True, ignore_status=False)
145+
virsh.start(vm_name)
146+
test.log.info("Start incremental backup.")
147+
backup_file_path = start_incremental_backup(test, params)
148+
backup_file_list.append(backup_file_path)
149+
return backup_file_list
150+
151+
152+
def test_restart_service(test, params):
153+
"""
154+
Test restart libvirtd/virtqemud service after backup.
155+
156+
:return: return the list of backup files.
157+
"""
158+
vm_name = params.get("main_vm")
159+
expected_error = params.get("expected_error")
160+
test.log.info("Start full backup.")
161+
backup_file_path = start_full_backup(test, params)
162+
backup_file_list.append(backup_file_path)
163+
164+
test.log.info("Restart libvirtd/virtqemud service.")
165+
Libvirtd().restart()
166+
167+
test.log.info("Start incremental backup")
168+
backup_options = prepare_backup_xml(test, params, backup_type="inc")
169+
result = virsh.backup_begin(vm_name, backup_options, debug=True)
170+
libvirt.check_result(result, expected_error)
171+
return backup_file_list
172+
173+
174+
def test_kill_qemu_process(test, params):
175+
"""
176+
Kill qemu process between libvirtd stop/start when there is an existing pull-mode backup job.
177+
178+
:return: return the list of backup files.
179+
"""
180+
vm_name = params.get("main_vm")
181+
test.log.info("Start full backup.")
182+
backup_file_path = start_full_backup(test, params)
183+
backup_file_list.append(backup_file_path)
184+
185+
test.log.info("Stop libvirt daemon and kill qemu process.")
186+
Libvirtd().stop()
187+
process.run("kill -9 `pidof qemu-kvm`", shell=True, ignore_status=False)
188+
189+
test.log.info("Start libvirt daemon and start the guest again.")
190+
Libvirtd().start()
191+
dom_state = virsh.domstate(vm_name).stdout.strip()
192+
if "shut off" not in dom_state:
193+
test.fail("The guest doesn't shutoff as expected!")
194+
start_result = virsh.start(vm_name, debug=True)
195+
libvirt.check_exit_status(start_result)
196+
return backup_file_list
197+
198+
199+
def run(test, params, env):
200+
"""
201+
Test vm lifecycle with incremental backup
202+
"""
203+
vm_name = params.get("main_vm")
204+
vm = env.get_vm(vm_name)
205+
case = params.get('test_case', '')
206+
207+
vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name)
208+
vmxml_backup = vmxml.copy()
209+
run_test = eval('test_%s' % case)
210+
global backup_file_list
211+
backup_file_list = []
212+
213+
try:
214+
if not vm.is_alive():
215+
vm.start()
216+
backup_file_list = run_test(test, params)
217+
finally:
218+
utils_backup.clean_checkpoints(vm_name)
219+
vmxml_backup.sync()
220+
for file in backup_file_list:
221+
if os.path.exists(file):
222+
os.remove(file)

0 commit comments

Comments
 (0)