From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from PA4PR04CU001.outbound.protection.outlook.com (mail-francecentralazon11023072.outbound.protection.outlook.com [40.107.162.72]) by lore.virtuozzo.com (Postfix) with ESMTPS id 1FE4F802A7 for ; Fri, 2 Oct 2026 16:49:10 +0000 (UTC) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=q2RAtxtAz7u28dd2yNnnZxmB3dEvwEslorEzCKB3m/K/A6s6QhkLfQvVSa2EOJSauKqBPF1k4OJMDh5De4tYT7zFVHR62VLLOycehV3w2frHLjJ3e6in2eMyzmr/Z1c+mmS5GOcWK5p7tG2+QXHJcJy1xxAPc8lQTmwvQQO86GhnxNyJvUzTL470WF8BvIZCchajSAJHeD4eyjHwVzJQzNROxoyGRNZwMymnJGUbjgAmXEPuPcFIBAtXRUNA2gBpT5ofF20B/rMqUGKu8VWTHAcN+8BT3N33Wff3a8zIrB6r0R01xIzJn2E9pTOWS27qN8L7tidtDoYQ/3fC8QAFFA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=nAjsWsUtygWsZcNhW0BRcRqzfzDUPvQ6hnp4YR3cS0I=; b=aHvMCqglo/88z7OoSAY4MaYZyog1Fdb3DDCGkgZhD8E+PAoQttvdDxAcpyW2I3GA4tB6t1TJINqs4pspPCASQjbiNJr4JAo5yQ5ut3m3sm/GzgumI+pZinc7Y3omBXc9wXqeTNZRYoI05pOuYj0al410pwn717ze7yhb18tzFm0FMbfzZ/N0QHGM6lUBRyBNiTsUOMddQ+ZLsHH4r88UcfZarf++ha6LmMehFWpN2eFye5Hl4mB6CXZKkQkV9rhwWGDLTwMMIvGm8oHg8z+jFPCLuLBJDWsAzloyBD0hkWkhXktxmxyVop6sDizlev5Ts9oIpHsJ3MBtj1D1WK0ceA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 2a00:1450:4864:30::15) smtp.rcpttodomain=virtuozzo.com smtp.mailfrom=openvz.org; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=openvz.org; dkim=pass (signature was verified) header.d=openvz.org; arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=virtuozzo.onmicrosoft.com; s=selector2-virtuozzo-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=nAjsWsUtygWsZcNhW0BRcRqzfzDUPvQ6hnp4YR3cS0I=; b=g+l2fOsx+JAhuWpSmvm1PIh/roUs0sbHAWRiSwqdEUysEAPneMZwuLshtbpIGKQKaFXLMQhOUQcP1fWHcd5ksc3jOFm4oXMKmp+Lp9FP9FEgc9t6MgE0BZQdwVS5A2MauBfV+TdJ7/oVxgxdxQ//Elg63NYao0fbzustBTPRG4E= Received: from DU2PR04CA0016.eurprd04.prod.outlook.com (2603:10a6:10:3b::21) by PAVPR08MB8894.eurprd08.prod.outlook.com (2603:10a6:102:329::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.496.13; Fri, 2 Oct 2026 16:49:02 +0000 Received: from DU6PEPF0000A7DE.eurprd02.prod.outlook.com (2603:10a6:10:3b:cafe::6d) by DU2PR04CA0016.outlook.office365.com (2603:10a6:10:3b::21) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.472.18 via Frontend Transport; Fri, 2 Oct 2026 16:49:02 +0000 Authentication-Results: spf=pass (sender IP is 2a00:1450:4864:30::15) smtp.mailfrom=openvz.org; dkim=pass (signature was verified) header.d=openvz.org;dmarc=pass action=none header.from=openvz.org; Received-SPF: Pass (protection.outlook.com: domain of openvz.org designates 2a00:1450:4864:30::15 as permitted sender) receiver=protection.outlook.com; client-ip=2a00:1450:4864:30::15; helo=mail-wr2-x15.google.com; pr=C Received: from mail-wr2-x15.google.com (2a00:1450:4864:30::15) by DU6PEPF0000A7DE.mail.protection.outlook.com (2603:10a6:18:3::86) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.472.14 via Frontend Transport; Fri, 2 Oct 2026 16:49:00 +0000 Received: by mail-wr2-x15.google.com with SMTP id ffacd0b85a97d-48b017a3be3so2723791f8f.2 for ; Fri, 02 Oct 2026 09:49:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=openvz.org; s=google; t=1790959740; x=1791564540; darn=virtuozzo.com; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=nAjsWsUtygWsZcNhW0BRcRqzfzDUPvQ6hnp4YR3cS0I=; b=exbpH4N6pMW4z73pHTkiawAWf/aXRBQHqkNveA20hes/6t5/S4YwIUPYDXHfy2rfMR QuYW0MrjTo6fXBow+ypQsOp+RBUW8hPTM03viHXm6KydhpViM1MsBIIZeTLNGxtA7sAV E5/AKla83yY6kEguzK7xAU/XUMvQz7htTgpEAGE7u/PXZZEauXEVxwg13L3vgojUeDMv wI1glAGv0xqNoTOUJWV5cG0PrtFWktesSeUwei7crNZCFiXma7cXQSShEoBziwr5ldQC t2HcjFf8iAQOX8oFxJsqBpN+3W0K/RW0kMLFqsJ58XW26TyIHy1AS5ZkqlDKMGKkzS7k mrlA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790959740; x=1791564540; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=nAjsWsUtygWsZcNhW0BRcRqzfzDUPvQ6hnp4YR3cS0I=; b=zUq9FwLEYHNi11fj8ccEbrDArZkbSWS0wKR635ikHboulLI21PNjQ4OkMEBcZ4pk69 NCy7mWuDgGuJZyDT2n8Y/alCCPNis1t4B4RWLmh+nzzVXZT7UBsdSXza+G7Mj4pRWpFN xicF63Xe5BJsLsl79HZwbnZecRBY+PdQcD+2Qe6nfpV2tJsn/V+n3wKMjTGiBOO9WfCT IBbkoSHiCtt3NW0sMwp+y9MA23Avy0W7mSEJp1iEvHn6a2V2hFTuuyrMCi/ESsQ6eUGw yuF7+30XG6/7tch8d4DEXITvxtc/6wVt+sUVvARbx3QyNsvWPkg3A1rkf+GZGV54mrDA H7Zw== X-Gm-Message-State: AFq9FYJdizdz1H1kC9FOmum3Nh0wIpHMZFIOoX5mE/Jx6K9N3QDgXVpe CIs8I0b6UCkc3UbRnlGPD0G1D1ODhYVicYbKwLhxu0srDphQfLG+81+/1jWUG8ogYuZ70zdje+4 vWC3TGOg= X-Gm-Gg: AYBFou11b0p6+krNfk1SE48qND+03WlHAmlR3VjAi3UrsKXHv5tmMSpnTk6kNddFKHb 4wn92hEz65pblRLTtgyQFe++NogLlRypbdA3I/KYGj9HBFuXG7N1BLdstWeWsMjUE5BSXFJw2Dw jaLMbx5d1vYu1kdbKNEtdw8lbfKec02Zo1PzdGZIFg4tOYvZfxWiDg74leA6+W1SBCE3lJ+DH1W iXiFgxe9KlgYi+/xhg2R1Lpvq8arrXOl13+y75Ji8QVJiKBsRRrBZzXIu684s6AUHZIfZwcGPJo itn6e+ps3Ya5MHxpiQ388jdkPUL3pvUmgELNUdDL/3ba3Z9OzIsZgGaIPdOEC61pxvSpQTXAvBh 85D9ttUPfIMNKkUABAtmUi4wFDHlabE084sHtnMTh8Hr0E6K9f70lxHLRL2LRxPxLeOTFWAhy+V RtMqM9CmkgGmy4Vb3uGAOs8LEt2DftwOxDcss2+bN9JdAboHwVlPrkLC3LWrDLdz9GuQ== X-Received: by 2002:adf:edc2:0:b0:488:7d08:edbc with SMTP id ffacd0b85a97d-48b127431dcmr4337826f8f.24.1790959740273; Fri, 02 Oct 2026 09:49:00 -0700 (PDT) Received: from athena.sw.ru ([2a06:5b06:b600:300:e2e:474b:392b:33f7]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-48b380fada5sm6442174f8f.24.2026.10.02.09.48.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Oct 2026 09:48:59 -0700 (PDT) From: "Denis V. Lunev" To: svt-core@virtuozzo.com Cc: andrey.drobyshev@virtuozzo.com, den@virtuozzo.com Subject: [PATCH 3/3] iotests/migrate-cpr-exec: cover chardevs with logfile= #VSTOR-148304 Date: Fri, 2 Oct 2026 18:48:53 +0200 Message-ID: <20261002164853.2130337-4-den@openvz.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20261002164853.2130337-1-den@openvz.org> References: <20261002164853.2130337-1-den@openvz.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-EOPAttributedMessage: 0 X-EOPTenantAttributedMessage: 0bc7f26d-0264-416e-a6fc-8352af79c58f:0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DU6PEPF0000A7DE:EE_|PAVPR08MB8894:EE_ X-MS-Office365-Filtering-Correlation-Id: 7e0a9ac7-c83d-4d36-c783-08df20a50f68 X-LD-Processed: 0bc7f26d-0264-416e-a6fc-8352af79c58f,ExtAddr X-MS-Exchange-AtpMessageProperties: SA X-MS-Exchange-SenderADCheck: 0 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|704161211799003|48200799018|61400799027|376014|9140799003|82310400026|43022699015|6059299003|10067099003|56012099006|5063699009|16102099003|18002099003|55112099003|22082099003; X-Microsoft-Antispam-Message-Info: 7wpbGRqmmyaEoTVOVrv4H/3KN4aYfmHRy8/23vgfBNddE4AO90jst8hJjMqLxtg1oVZ/J9ABr5HMtgm9o2Su7Iv63Pbp149W+XbGQj/PXsqKg4YYc9V07z/72T4ISiE7YzmaGxOrnCjS0V8LA17xPH6mfznIKQJw5ziLcn6P9Q36NwsLsOAkFqvFImoyutV8KmFDI9zMTP6f7PTO50wq/ZO4E/n6ojgE4o2mEinhS0ATAB+FZOJG55svGvKI1wPW6rCRAJHSWWhhgVl8n2DCpIGnD2IyAccXOpYgF9s+aYbb6dM7bzUTWwH9LaqxbhOumcB4hwNfcKbDpUFq1vlmgmhS7FZmV+pZov2DDU3QuFWCvVl+lOfxVhUBiXKGzcIn9TZwWvc1MnbFH32oUyMIBq8J1St8FQumbGtgBbrWbLtIyJRbcVuo9r1kQ1Iew4TeaZYprCtpC3jyuylc9RcMz2GOA4tk8bo6s+qhnuINkiVXenyDoaQDEPllx+2nKL881KJ5sy1E3IuA+Dg8tZ8PWnl9BgdJ9v8pe8elLG8HkLNS2Ywaftoxt9SGvQvTZe+gWL/JSut8RMSYIxVvx7Cw2BdYWJPZyOOW7nTi5XLRRO/cu2oWSOHofSQbFRq0sqB9CyxD38l7u/ga2GemxsNz/12Sta0RdOUy2WVWvsbXdselBDF/AGyHsKmJMjt3QvpQjEPrPEdD09MWPye2NXdofqrlXk1YR4coqLo/fAGYyIZYy9koQY9X08jd+imHYEDRZ8dsCl8GbuY3IKUBUM4dp2FAIWUYEAd/MtjT/Z5S3u4POEN4l1meZ2Jz6HiE4+0CAjhXxq7dw8QtzIu2c91FZaY1BnObxoy7v63rX1HzTRP9eu/rgGNSv1e649mZpBHX X-Forefront-Antispam-Report: CIP:2a00:1450:4864:30::15;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail-wr2-x15.google.com;PTR:mail-wr2-x15.google.com;CAT:NONE;SFS:(13230040)(704161211799003)(48200799018)(61400799027)(376014)(9140799003)(82310400026)(43022699015)(6059299003)(10067099003)(56012099006)(5063699009)(16102099003)(18002099003)(55112099003)(22082099003);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: orSaXlVx5/OBUd3fB4sp+xcVy+kTD3jXbtnvG7+scmmBf1VM3q+0u9EX6uIZrIwAd+RhXioqimQZSBtY77lIHZeIecKLY+wXgxR/48ZHzDJAQ8u2zcX0OQ53UirmqtR9i8cGYB4eGEZCGZ7mfT8ivc4B75nkg/JrKv4S/GE4IlxaRAXPm3+Pl1pgNpwkmqBAzEzZ6LXvhHTF70SAmw7CdcQNmeAhc165EFWD0aqIs5AQU0U0U6z8olck4gYKHzb9nwyPiYV1MPornw0vLJLiuyj197wLkimIgeDT0YRp1vWj3aRwl6rwePn3uebzmpfB2ZXipqq1rLoaHBVewb+bmWO7hAZgaunq4T/Hb4wK/rSYkH+GRiajUnkLXBaYCFDRcG6JdLltHPNxcl2YbeyWVAxCx1BmIuIEznjRFXDlN3J+gGHdXcEJEnQECSmlvwip X-ExternalRecipientOutboundConnectors: 0bc7f26d-0264-416e-a6fc-8352af79c58f X-Auto-Response-Suppress: DR, OOF, AutoReply X-OriginatorOrg: virtuozzo.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 02 Oct 2026 16:49:00.9758 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 7e0a9ac7-c83d-4d36-c783-08df20a50f68 X-MS-Exchange-CrossTenant-Id: 0bc7f26d-0264-416e-a6fc-8352af79c58f X-MS-Exchange-CrossTenant-AuthSource: DU6PEPF0000A7DE.eurprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: Internet X-MS-Exchange-Transport-CrossTenantHeadersStamped: PAVPR08MB8894 List-Id: From: Denis V. Lunev Run a console pty with its log in an fdset, a guest agent socket and a second QMP monitor, each with a log, through cpr-exec with a command line whose logfile paths cannot be created, as libvirt's is. Cover chardev-change to a new log for pty and socket, and a failed chardev-change, whose rollback must keep the old log preserved. Signed-off-by: Denis V. Lunev --- tests/qemu-iotests/tests/migrate-cpr-exec | 132 ++++++++++++++++++ tests/qemu-iotests/tests/migrate-cpr-exec.out | 4 +- 2 files changed, 134 insertions(+), 2 deletions(-) diff --git a/tests/qemu-iotests/tests/migrate-cpr-exec b/tests/qemu-iotests/tests/migrate-cpr-exec index 51e6cbcd659..e8a6c502c84 100755 --- a/tests/qemu-iotests/tests/migrate-cpr-exec +++ b/tests/qemu-iotests/tests/migrate-cpr-exec @@ -288,6 +288,138 @@ class TestCprExec(iotests.QMPTestCase): '-device', 'isa-serial,chardev=char0') self._test_cpr(pre_cpr_hook=change_socket) + BAD_LOG = os.path.join(iotests.test_dir, 'nonexistent', 'chr.log') + + def _serial_write(self, data: str) -> None: + for c in data: + self.vm.qtest(f'outb 0x3f8 {ord(c)}') + + def _open_files(self) -> set: + fd_dir = f'/proc/{self.vm.get_pid()}/fd' + return {os.readlink(os.path.join(fd_dir, fd)) + for fd in os.listdir(fd_dir)} + + def _replace_arg(self, old: str, new: str) -> None: + args = list(self.vm._qemu_full_args) + args[args.index(old)] = new + self.vm._qemu_full_args = tuple(args) + + def _read(self, path: str) -> str: + with open(path, encoding='utf-8') as f: + return f.read() + + def _log_path(self, name: str) -> str: + path = os.path.join(iotests.test_dir, name) + self.addCleanup(lambda: os.path.exists(path) and os.remove(path)) + return path + + def test_chardev_logfile(self) -> None: + """Log fds survive cpr-exec; the new logfile= paths are never opened""" + console_log = self._log_path('console.log') + agent_log = self._log_path('agent.log') + mon_log = self._log_path('mon.log') + agent_sock = iotests.file_path('agent.sock') + mon_sock = iotests.file_path('mon.sock') + + console = 'pty,id=charserial0,logfile=/dev/fdset/1,logappend=on' + agent = (f'socket,id=charchannel0,path={agent_sock},server=on,' + f'wait=off,logfile={agent_log}') + mon = (f'socket,id=charmonitor1,path={mon_sock},server=on,' + f'wait=off,logfile={mon_log}') + + def pre_cpr(): + self._serial_write('before\n') + for c in (console, agent, mon): + self._replace_arg(c, c.replace(c[c.index('logfile='):], + f'logfile={self.BAD_LOG}')) + args = list(self.vm._qemu_full_args) + i = args.index('-add-fd') + self.vm._qemu_full_args = tuple(args[:i] + args[i + 2:]) + + def post_cpr(): + self._serial_write('after\n') + self.assertEqual(self._read(console_log), 'before\nafter\n') + self.assertLessEqual({agent_log, mon_log}, self._open_files()) + self.assertFalse(os.path.exists(os.path.dirname(self.BAD_LOG))) + + fd = os.open(console_log, os.O_WRONLY | os.O_CREAT | os.O_APPEND) + try: + self.vm.add_fd(fd, 1, 'console') + self.vm.add_args( + '-chardev', console, + '-device', 'isa-serial,chardev=charserial0', + '-chardev', agent, '-device', 'virtio-serial', + '-device', 'virtserialport,chardev=charchannel0,' + 'name=org.qemu.guest_agent.0', + '-chardev', mon, '-mon', 'chardev=charmonitor1,mode=control') + self._test_cpr(pre_cpr_hook=pre_cpr, post_cpr_hook=post_cpr) + finally: + os.close(fd) + + def _test_chardev_change_logfile(self, backend: str, data_new: dict, + opts_old: str) -> None: + """cpr-exec after chardev-change preserves the new log, not the old""" + log_old = self._log_path('chr-old.log') + log_new = self._log_path('chr-new.log') + arg = f'{backend},id=char0,{opts_old}logfile={log_old}' + + def change(): + self._serial_write('before\n') + res = self.vm.qmp('chardev-change', id='char0', + backend={'type': backend, + 'data': {**data_new, + 'logfile': log_new}}) + assert 'return' in res, res + self._replace_arg(arg, f'{backend},id=char0,{opts_old}' + f'logfile={self.BAD_LOG}') + + def post_cpr(): + self._serial_write('after\n') + self.assertEqual(self._read(log_old), 'before\n') + self.assertEqual(self._read(log_new), 'after\n') + self.assertNotIn(log_old, self._open_files()) + + self.vm.add_args('-chardev', arg, + '-device', 'isa-serial,chardev=char0') + self._test_cpr(pre_cpr_hook=change, post_cpr_hook=post_cpr) + + def test_chardev_change_logfile_pty(self) -> None: + self._test_chardev_change_logfile('pty', {}, '') + + def test_chardev_change_logfile_socket(self) -> None: + sock1 = iotests.file_path('chr-log-sock1') + sock2 = iotests.file_path('chr-log-sock2') + self._test_chardev_change_logfile( + 'socket', + {'addr': {'type': 'unix', 'data': {'path': sock2}}, + 'server': True, 'wait': False}, + f'path={sock1},server=on,wait=off,') + + def test_chardev_change_logfile_rollback(self) -> None: + """A rolled back chardev-change keeps the old log preserved""" + log = self._log_path('chr.log') + log_new = self._log_path('chr-new.log') + link = self._log_path('pty-rollback.link') + open(link, 'w').close() + arg = f'pty,id=char0,logfile={log}' + + def failed_change(): + self._serial_write('before\n') + res = self.vm.qmp('chardev-change', id='char0', + backend={'type': 'pty', + 'data': {'path': link, + 'logfile': log_new}}) + assert 'error' in res, res + self._replace_arg(arg, f'pty,id=char0,logfile={self.BAD_LOG}') + + def post_cpr(): + self._serial_write('after\n') + self.assertEqual(self._read(log), 'before\nafter\n') + + self.vm.add_args('-chardev', arg, + '-device', 'isa-serial,chardev=char0') + self._test_cpr(pre_cpr_hook=failed_change, post_cpr_hook=post_cpr) + def test_nbd_attached_hd(self) -> None: nbd_img = os.path.join(iotests.test_dir, 'nbd_disk') iotests.qemu_img_create('-f', 'qcow2', nbd_img, '64M') diff --git a/tests/qemu-iotests/tests/migrate-cpr-exec.out b/tests/qemu-iotests/tests/migrate-cpr-exec.out index 5ce2f9a2ed9..88bf7fa73a5 100644 --- a/tests/qemu-iotests/tests/migrate-cpr-exec.out +++ b/tests/qemu-iotests/tests/migrate-cpr-exec.out @@ -1,5 +1,5 @@ -.............................. +.................................. ---------------------------------------------------------------------- -Ran 30 tests +Ran 34 tests OK -- 2.53.0