Skip to content

Commit 3fc0482

Browse files
authored
Merge pull request avocado-framework#4285 from dzhengfy/return_qemu_log_migration
migration: Retrieve QEMU logs after migration failure
2 parents ab5b524 + 20eb824 commit 3fc0482

File tree

3 files changed

+65
-5
lines changed

3 files changed

+65
-5
lines changed

virttest/migration.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
utils_iptables,
1919
utils_misc,
2020
utils_net,
21+
utils_sys,
2122
utils_test,
2223
)
2324

@@ -372,6 +373,7 @@ def do_migration(
372373
{"func": <function domjobabort at 0x7f5835cd08c8>,
373374
"before_pause": "no"}
374375
]
376+
:param virsh_opt: str, virsh options
375377
:param args: dictionary used by func,
376378
'func_param' is mandatory for func parameter.
377379
If no real func_param, none is requested.
@@ -709,7 +711,7 @@ def _do_orderly_migration(
709711
raise exceptions.TestFail()
710712

711713
LOG.info("Checking migration result...")
712-
self.check_result(self.ret, args)
714+
self.check_result(self.ret, args, vms)
713715

714716
def cleanup_dest_vm(self, vm, srcuri, desturi):
715717
"""
@@ -830,17 +832,19 @@ def update_virsh_migrate_extra_args(self, params):
830832
extra_args.update({"err_msg": params.get("err_msg")})
831833
return extra_args
832834

833-
def check_result(self, result, params):
835+
def check_result(self, result, params, vms):
834836
"""
835837
Check if the migration result is as expected
836838
837839
:param result: the output of migration
838840
:param params: the parameters dict
839-
:raise: test.fail if test is failed
841+
:param vms: vm instances
842+
:raise: exceptions.TestFail if test is failed
840843
"""
841844
status_error = "yes" == params.get("status_error", "no")
842845
err_msg = params.get("err_msg")
843846
if not result:
847+
utils_sys.get_qemu_log(vms, type="both", params=params)
844848
raise exceptions.TestError("No migration result is returned.")
845849

846850
LOG.info("Migration out: %s", result.stdout_text.strip())
@@ -849,6 +853,7 @@ def check_result(self, result, params):
849853
if status_error: # Migration should fail
850854
if err_msg: # Special error messages are expected
851855
if not re.search(err_msg, result.stderr_text.strip()):
856+
utils_sys.get_qemu_log(vms, type="both", params=params)
852857
raise exceptions.TestFail(
853858
"Can not find the expected "
854859
"patterns '%s' in output '%s'"
@@ -863,6 +868,7 @@ def check_result(self, result, params):
863868
raise exceptions.TestFail("Migration success is unexpected result")
864869
else:
865870
if int(result.exit_status) != 0:
871+
utils_sys.get_qemu_log(vms, type="both", params=params)
866872
raise exceptions.TestFail(result.stderr_text.strip())
867873

868874
def do_cancel(self, sig=signal.SIGKILL):

virttest/migration_template.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ def _migrate(self):
510510
)
511511

512512
LOG.info("Check migration result: succeed or fail with expected error")
513-
self.obj_migration.check_result(self.obj_migration.ret, self.params)
513+
self.obj_migration.check_result(self.obj_migration.ret, self.params, self.vms)
514514

515515
# Check "suspended post-copy" event after postcopy migration
516516
if self.migrate_flags & VIR_MIGRATE_POSTCOPY:
@@ -563,7 +563,7 @@ def _migrate_back(self):
563563
)
564564

565565
LOG.info("Check migration result: succeed or fail with expected error")
566-
self.obj_migration.check_result(self.obj_migration.ret, self.params)
566+
self.obj_migration.check_result(self.obj_migration.ret, self.params, self.vms)
567567

568568
# Set vm connect_uri to self.src_uri if migration back succeeds
569569
if self.obj_migration.ret.exit_status == 0:

virttest/utils_sys.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from avocado.utils import process
1111

12+
from virttest import remote
1213
from virttest.utils_misc import cmd_status_output
1314
from virttest.utils_test import libvirt
1415

@@ -133,3 +134,56 @@ def get_pids_for(process_names, sort_pids=True, session=None):
133134
relevant_pids.sort()
134135

135136
return relevant_pids
137+
138+
139+
def get_qemu_log(vms, type="local", params=None, log_lines=10):
140+
"""
141+
Get last N lines of QEMU log from local host and remote host.
142+
143+
:param vms: VM objects
144+
:param type: str, valid values: "local", "remote" or "both"
145+
:param params: dict, test parameters
146+
:param log_lines: int, number of last lines to retrieve from log, default 10
147+
:return: list, like [{"vm_name": "vm1", "local": xxx, "remote": xxx}, {"vm_name": "vm2", "local": xxx}]
148+
"""
149+
logs = []
150+
if params is not None and type != "local":
151+
server_ip = params.get("migrate_dest_host", params.get("remote_ip"))
152+
server_user = params.get("server_user", params.get("remote_user"))
153+
server_pwd = params.get("server_pwd", params.get("remote_pwd"))
154+
if server_ip:
155+
server_session = remote.wait_for_login(
156+
"ssh", server_ip, "22", server_user, server_pwd, r"[\#\$]\s*$"
157+
)
158+
else:
159+
LOG.warning("Remote host IP not found in params")
160+
try:
161+
for vm in vms:
162+
log_contents = {"vm_name": vm.name}
163+
log_file = "/var/log/libvirt/qemu/%s.log" % vm.name
164+
cmd = "tail -n %d %s 2>/dev/null || echo 'Log file not found'" % (
165+
log_lines,
166+
log_file,
167+
)
168+
if type in ["local", "both"]:
169+
result = process.run(cmd, shell=True, ignore_status=True, verbose=False)
170+
log_content = result.stdout_text.strip()
171+
LOG.debug(
172+
"QEMU log from source host for vm %s:\n%s", vm.name, log_content
173+
)
174+
log_contents.update({"local": log_content})
175+
176+
if type in ["remote", "both"] and server_session is not None:
177+
log_content = server_session.cmd_output(cmd, timeout=10).strip()
178+
LOG.debug(
179+
"QEMU log from remote host for vm %s:\n%s", vm.name, log_content
180+
)
181+
log_contents.update({"remote": log_content})
182+
logs.append(log_contents)
183+
184+
except Exception as detail:
185+
LOG.warning("Failed to get QEMU log: %s", detail)
186+
finally:
187+
if server_session:
188+
server_session.close()
189+
return logs

0 commit comments

Comments
 (0)