12e5a2f57SVladimir Sementsov-Ogievskiy# TestEnv class to manage test environment variables. 22e5a2f57SVladimir Sementsov-Ogievskiy# 32e5a2f57SVladimir Sementsov-Ogievskiy# Copyright (c) 2020-2021 Virtuozzo International GmbH 42e5a2f57SVladimir Sementsov-Ogievskiy# 52e5a2f57SVladimir Sementsov-Ogievskiy# This program is free software; you can redistribute it and/or modify 62e5a2f57SVladimir Sementsov-Ogievskiy# it under the terms of the GNU General Public License as published by 72e5a2f57SVladimir Sementsov-Ogievskiy# the Free Software Foundation; either version 2 of the License, or 82e5a2f57SVladimir Sementsov-Ogievskiy# (at your option) any later version. 92e5a2f57SVladimir Sementsov-Ogievskiy# 102e5a2f57SVladimir Sementsov-Ogievskiy# This program is distributed in the hope that it will be useful, 112e5a2f57SVladimir Sementsov-Ogievskiy# but WITHOUT ANY WARRANTY; without even the implied warranty of 122e5a2f57SVladimir Sementsov-Ogievskiy# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 132e5a2f57SVladimir Sementsov-Ogievskiy# GNU General Public License for more details. 142e5a2f57SVladimir Sementsov-Ogievskiy# 152e5a2f57SVladimir Sementsov-Ogievskiy# You should have received a copy of the GNU General Public License 162e5a2f57SVladimir Sementsov-Ogievskiy# along with this program. If not, see <http://www.gnu.org/licenses/>. 172e5a2f57SVladimir Sementsov-Ogievskiy# 182e5a2f57SVladimir Sementsov-Ogievskiy 192e5a2f57SVladimir Sementsov-Ogievskiyimport os 202e5a2f57SVladimir Sementsov-Ogievskiyimport sys 212e5a2f57SVladimir Sementsov-Ogievskiyimport tempfile 222e5a2f57SVladimir Sementsov-Ogievskiyfrom pathlib import Path 232e5a2f57SVladimir Sementsov-Ogievskiyimport shutil 242e5a2f57SVladimir Sementsov-Ogievskiyimport collections 252e5a2f57SVladimir Sementsov-Ogievskiyimport random 262e5a2f57SVladimir Sementsov-Ogievskiyimport subprocess 272e5a2f57SVladimir Sementsov-Ogievskiyimport glob 28e3890045SJohn Snowfrom typing import List, Dict, Any, Optional 29e3890045SJohn Snow 30e3890045SJohn Snowif sys.version_info >= (3, 9): 31e3890045SJohn Snow from contextlib import AbstractContextManager as ContextManager 32e3890045SJohn Snowelse: 33e3890045SJohn Snow from typing import ContextManager 342e5a2f57SVladimir Sementsov-Ogievskiy 35cfb9b0b7SEmanuele Giuseppe EspositoDEF_GDB_OPTIONS = 'localhost:12345' 362e5a2f57SVladimir Sementsov-Ogievskiy 372e5a2f57SVladimir Sementsov-Ogievskiydef isxfile(path: str) -> bool: 382e5a2f57SVladimir Sementsov-Ogievskiy return os.path.isfile(path) and os.access(path, os.X_OK) 392e5a2f57SVladimir Sementsov-Ogievskiy 402e5a2f57SVladimir Sementsov-Ogievskiy 412e5a2f57SVladimir Sementsov-Ogievskiydef get_default_machine(qemu_prog: str) -> str: 422e5a2f57SVladimir Sementsov-Ogievskiy outp = subprocess.run([qemu_prog, '-machine', 'help'], check=True, 432e5a2f57SVladimir Sementsov-Ogievskiy universal_newlines=True, 442e5a2f57SVladimir Sementsov-Ogievskiy stdout=subprocess.PIPE).stdout 452e5a2f57SVladimir Sementsov-Ogievskiy 462e5a2f57SVladimir Sementsov-Ogievskiy machines = outp.split('\n') 472e5a2f57SVladimir Sementsov-Ogievskiy try: 483b7094feSAndrey Drobyshev default_machine = next(m for m in machines if ' (default)' in m) 492e5a2f57SVladimir Sementsov-Ogievskiy except StopIteration: 502e5a2f57SVladimir Sementsov-Ogievskiy return '' 512e5a2f57SVladimir Sementsov-Ogievskiy default_machine = default_machine.split(' ', 1)[0] 522e5a2f57SVladimir Sementsov-Ogievskiy 532e5a2f57SVladimir Sementsov-Ogievskiy alias_suf = ' (alias of {})'.format(default_machine) 542e5a2f57SVladimir Sementsov-Ogievskiy alias = next((m for m in machines if m.endswith(alias_suf)), None) 552e5a2f57SVladimir Sementsov-Ogievskiy if alias is not None: 562e5a2f57SVladimir Sementsov-Ogievskiy default_machine = alias.split(' ', 1)[0] 572e5a2f57SVladimir Sementsov-Ogievskiy 582e5a2f57SVladimir Sementsov-Ogievskiy return default_machine 592e5a2f57SVladimir Sementsov-Ogievskiy 602e5a2f57SVladimir Sementsov-Ogievskiy 612e5a2f57SVladimir Sementsov-Ogievskiyclass TestEnv(ContextManager['TestEnv']): 622e5a2f57SVladimir Sementsov-Ogievskiy """ 632e5a2f57SVladimir Sementsov-Ogievskiy Manage system environment for running tests 642e5a2f57SVladimir Sementsov-Ogievskiy 652e5a2f57SVladimir Sementsov-Ogievskiy The following variables are supported/provided. They are represented by 662e5a2f57SVladimir Sementsov-Ogievskiy lower-cased TestEnv attributes. 672e5a2f57SVladimir Sementsov-Ogievskiy """ 682e5a2f57SVladimir Sementsov-Ogievskiy 692e5a2f57SVladimir Sementsov-Ogievskiy # We store environment variables as instance attributes, and there are a 702e5a2f57SVladimir Sementsov-Ogievskiy # lot of them. Silence pylint: 712e5a2f57SVladimir Sementsov-Ogievskiy # pylint: disable=too-many-instance-attributes 722e5a2f57SVladimir Sementsov-Ogievskiy 732e5a2f57SVladimir Sementsov-Ogievskiy env_variables = ['PYTHONPATH', 'TEST_DIR', 'SOCK_DIR', 'SAMPLE_IMG_DIR', 741a8fcca0SHanna Reitz 'PYTHON', 'QEMU_PROG', 'QEMU_IMG_PROG', 752e5a2f57SVladimir Sementsov-Ogievskiy 'QEMU_IO_PROG', 'QEMU_NBD_PROG', 'QSD_PROG', 76c163c723SJohn Snow 'QEMU_OPTIONS', 'QEMU_IMG_OPTIONS', 772e5a2f57SVladimir Sementsov-Ogievskiy 'QEMU_IO_OPTIONS', 'QEMU_IO_OPTIONS_NO_FMT', 782e5a2f57SVladimir Sementsov-Ogievskiy 'QEMU_NBD_OPTIONS', 'IMGOPTS', 'IMGFMT', 'IMGPROTO', 792e5a2f57SVladimir Sementsov-Ogievskiy 'AIOMODE', 'CACHEMODE', 'VALGRIND_QEMU', 802e5a2f57SVladimir Sementsov-Ogievskiy 'CACHEMODE_IS_DEFAULT', 'IMGFMT_GENERIC', 'IMGOPTSSYNTAX', 81cfb9b0b7SEmanuele Giuseppe Esposito 'IMGKEYSECRET', 'QEMU_DEFAULT_MACHINE', 'MALLOC_PERTURB_', 82eb7a91d0SEmanuele Giuseppe Esposito 'GDB_OPTIONS', 'PRINT_QEMU'] 832e5a2f57SVladimir Sementsov-Ogievskiy 84c64430d2SPaolo Bonzini def prepare_subprocess(self, args: List[str]) -> Dict[str, str]: 85c64430d2SPaolo Bonzini if self.debug: 86c64430d2SPaolo Bonzini args.append('-d') 87c64430d2SPaolo Bonzini 88c64430d2SPaolo Bonzini with open(args[0], encoding="utf-8") as f: 89c64430d2SPaolo Bonzini try: 90c64430d2SPaolo Bonzini if f.readline().rstrip() == '#!/usr/bin/env python3': 91c64430d2SPaolo Bonzini args.insert(0, self.python) 92c64430d2SPaolo Bonzini except UnicodeDecodeError: # binary test? for future. 93c64430d2SPaolo Bonzini pass 94c64430d2SPaolo Bonzini 95c64430d2SPaolo Bonzini os_env = os.environ.copy() 96c64430d2SPaolo Bonzini os_env.update(self.get_env()) 97c64430d2SPaolo Bonzini return os_env 98c64430d2SPaolo Bonzini 992e5a2f57SVladimir Sementsov-Ogievskiy def get_env(self) -> Dict[str, str]: 1002e5a2f57SVladimir Sementsov-Ogievskiy env = {} 1012e5a2f57SVladimir Sementsov-Ogievskiy for v in self.env_variables: 1022e5a2f57SVladimir Sementsov-Ogievskiy val = getattr(self, v.lower(), None) 1032e5a2f57SVladimir Sementsov-Ogievskiy if val is not None: 1042e5a2f57SVladimir Sementsov-Ogievskiy env[v] = val 1052e5a2f57SVladimir Sementsov-Ogievskiy 1062e5a2f57SVladimir Sementsov-Ogievskiy return env 1072e5a2f57SVladimir Sementsov-Ogievskiy 1082e5a2f57SVladimir Sementsov-Ogievskiy def init_directories(self) -> None: 1092e5a2f57SVladimir Sementsov-Ogievskiy """Init directory variables: 1102e5a2f57SVladimir Sementsov-Ogievskiy PYTHONPATH 1112e5a2f57SVladimir Sementsov-Ogievskiy TEST_DIR 1122e5a2f57SVladimir Sementsov-Ogievskiy SOCK_DIR 1132e5a2f57SVladimir Sementsov-Ogievskiy SAMPLE_IMG_DIR 1142e5a2f57SVladimir Sementsov-Ogievskiy """ 115af6d4c56SJohn Snow 116af6d4c56SJohn Snow # Path where qemu goodies live in this source tree. 117af6d4c56SJohn Snow qemu_srctree_path = Path(__file__, '../../../python').resolve() 118af6d4c56SJohn Snow 119af6d4c56SJohn Snow self.pythonpath = os.pathsep.join(filter(None, ( 120af6d4c56SJohn Snow self.source_iotests, 121af6d4c56SJohn Snow str(qemu_srctree_path), 122af6d4c56SJohn Snow os.getenv('PYTHONPATH'), 123af6d4c56SJohn Snow ))) 1242e5a2f57SVladimir Sementsov-Ogievskiy 1252e5a2f57SVladimir Sementsov-Ogievskiy self.test_dir = os.getenv('TEST_DIR', 1262e5a2f57SVladimir Sementsov-Ogievskiy os.path.join(os.getcwd(), 'scratch')) 1272e5a2f57SVladimir Sementsov-Ogievskiy Path(self.test_dir).mkdir(parents=True, exist_ok=True) 1282e5a2f57SVladimir Sementsov-Ogievskiy 1292e5a2f57SVladimir Sementsov-Ogievskiy try: 1302e5a2f57SVladimir Sementsov-Ogievskiy self.sock_dir = os.environ['SOCK_DIR'] 1312e5a2f57SVladimir Sementsov-Ogievskiy self.tmp_sock_dir = False 132c3d479aaSPaolo Bonzini Path(self.sock_dir).mkdir(parents=True, exist_ok=True) 1332e5a2f57SVladimir Sementsov-Ogievskiy except KeyError: 1347d2faf0cSDaniel P. Berrangé self.sock_dir = tempfile.mkdtemp(prefix="qemu-iotests-") 1352e5a2f57SVladimir Sementsov-Ogievskiy self.tmp_sock_dir = True 1362e5a2f57SVladimir Sementsov-Ogievskiy 1372e5a2f57SVladimir Sementsov-Ogievskiy self.sample_img_dir = os.getenv('SAMPLE_IMG_DIR', 1382e5a2f57SVladimir Sementsov-Ogievskiy os.path.join(self.source_iotests, 1392e5a2f57SVladimir Sementsov-Ogievskiy 'sample_images')) 1402e5a2f57SVladimir Sementsov-Ogievskiy 1412e5a2f57SVladimir Sementsov-Ogievskiy def init_binaries(self) -> None: 1422e5a2f57SVladimir Sementsov-Ogievskiy """Init binary path variables: 1432e5a2f57SVladimir Sementsov-Ogievskiy PYTHON (for bash tests) 1442e5a2f57SVladimir Sementsov-Ogievskiy QEMU_PROG, QEMU_IMG_PROG, QEMU_IO_PROG, QEMU_NBD_PROG, QSD_PROG 1452e5a2f57SVladimir Sementsov-Ogievskiy """ 1462e5a2f57SVladimir Sementsov-Ogievskiy self.python = sys.executable 1472e5a2f57SVladimir Sementsov-Ogievskiy 1482e5a2f57SVladimir Sementsov-Ogievskiy def root(*names: str) -> str: 1492e5a2f57SVladimir Sementsov-Ogievskiy return os.path.join(self.build_root, *names) 1502e5a2f57SVladimir Sementsov-Ogievskiy 1512e5a2f57SVladimir Sementsov-Ogievskiy arch = os.uname().machine 1522e5a2f57SVladimir Sementsov-Ogievskiy if 'ppc64' in arch: 1532e5a2f57SVladimir Sementsov-Ogievskiy arch = 'ppc64' 1542e5a2f57SVladimir Sementsov-Ogievskiy 1552e5a2f57SVladimir Sementsov-Ogievskiy self.qemu_prog = os.getenv('QEMU_PROG', root(f'qemu-system-{arch}')) 1562e5a2f57SVladimir Sementsov-Ogievskiy if not os.path.exists(self.qemu_prog): 1572e5a2f57SVladimir Sementsov-Ogievskiy pattern = root('qemu-system-*') 1582e5a2f57SVladimir Sementsov-Ogievskiy try: 159ca502ca6SKevin Wolf progs = sorted(glob.iglob(pattern)) 1602e5a2f57SVladimir Sementsov-Ogievskiy self.qemu_prog = next(p for p in progs if isxfile(p)) 1612e5a2f57SVladimir Sementsov-Ogievskiy except StopIteration: 1622e5a2f57SVladimir Sementsov-Ogievskiy sys.exit("Not found any Qemu executable binary by pattern " 1632e5a2f57SVladimir Sementsov-Ogievskiy f"'{pattern}'") 1642e5a2f57SVladimir Sementsov-Ogievskiy 1652e5a2f57SVladimir Sementsov-Ogievskiy self.qemu_img_prog = os.getenv('QEMU_IMG_PROG', root('qemu-img')) 1662e5a2f57SVladimir Sementsov-Ogievskiy self.qemu_io_prog = os.getenv('QEMU_IO_PROG', root('qemu-io')) 1672e5a2f57SVladimir Sementsov-Ogievskiy self.qemu_nbd_prog = os.getenv('QEMU_NBD_PROG', root('qemu-nbd')) 1682e5a2f57SVladimir Sementsov-Ogievskiy self.qsd_prog = os.getenv('QSD_PROG', root('storage-daemon', 1692e5a2f57SVladimir Sementsov-Ogievskiy 'qemu-storage-daemon')) 1702e5a2f57SVladimir Sementsov-Ogievskiy 1712e5a2f57SVladimir Sementsov-Ogievskiy for b in [self.qemu_img_prog, self.qemu_io_prog, self.qemu_nbd_prog, 1722e5a2f57SVladimir Sementsov-Ogievskiy self.qemu_prog, self.qsd_prog]: 1732e5a2f57SVladimir Sementsov-Ogievskiy if not os.path.exists(b): 1742e5a2f57SVladimir Sementsov-Ogievskiy sys.exit('No such file: ' + b) 1752e5a2f57SVladimir Sementsov-Ogievskiy if not isxfile(b): 1762e5a2f57SVladimir Sementsov-Ogievskiy sys.exit('Not executable: ' + b) 1772e5a2f57SVladimir Sementsov-Ogievskiy 1780c8076b0SDaniel P. Berrangé def __init__(self, source_dir: str, build_dir: str, 1790c8076b0SDaniel P. Berrangé imgfmt: str, imgproto: str, aiomode: str, 1802e5a2f57SVladimir Sementsov-Ogievskiy cachemode: Optional[str] = None, 1812e5a2f57SVladimir Sementsov-Ogievskiy imgopts: Optional[str] = None, 1822e5a2f57SVladimir Sementsov-Ogievskiy misalign: bool = False, 1832e5a2f57SVladimir Sementsov-Ogievskiy debug: bool = False, 184cfb9b0b7SEmanuele Giuseppe Esposito valgrind: bool = False, 185eb7a91d0SEmanuele Giuseppe Esposito gdb: bool = False, 186a9e21786SDaniel P. Berrangé qprint: bool = False, 187a9e21786SDaniel P. Berrangé dry_run: bool = False) -> None: 1882e5a2f57SVladimir Sementsov-Ogievskiy self.imgfmt = imgfmt 1892e5a2f57SVladimir Sementsov-Ogievskiy self.imgproto = imgproto 1902e5a2f57SVladimir Sementsov-Ogievskiy self.aiomode = aiomode 1912e5a2f57SVladimir Sementsov-Ogievskiy self.imgopts = imgopts 1922e5a2f57SVladimir Sementsov-Ogievskiy self.misalign = misalign 1932e5a2f57SVladimir Sementsov-Ogievskiy self.debug = debug 1942e5a2f57SVladimir Sementsov-Ogievskiy 195eb7a91d0SEmanuele Giuseppe Esposito if qprint: 196eb7a91d0SEmanuele Giuseppe Esposito self.print_qemu = 'y' 197eb7a91d0SEmanuele Giuseppe Esposito 198cfb9b0b7SEmanuele Giuseppe Esposito if gdb: 199cfb9b0b7SEmanuele Giuseppe Esposito self.gdb_options = os.getenv('GDB_OPTIONS', DEF_GDB_OPTIONS) 200cfb9b0b7SEmanuele Giuseppe Esposito if not self.gdb_options: 201cfb9b0b7SEmanuele Giuseppe Esposito # cover the case 'export GDB_OPTIONS=' 202cfb9b0b7SEmanuele Giuseppe Esposito self.gdb_options = DEF_GDB_OPTIONS 203cfb9b0b7SEmanuele Giuseppe Esposito elif 'GDB_OPTIONS' in os.environ: 204cfb9b0b7SEmanuele Giuseppe Esposito # to not propagate it in prepare_subprocess() 205cfb9b0b7SEmanuele Giuseppe Esposito del os.environ['GDB_OPTIONS'] 206cfb9b0b7SEmanuele Giuseppe Esposito 2072e5a2f57SVladimir Sementsov-Ogievskiy if valgrind: 2082e5a2f57SVladimir Sementsov-Ogievskiy self.valgrind_qemu = 'y' 2092e5a2f57SVladimir Sementsov-Ogievskiy 2102e5a2f57SVladimir Sementsov-Ogievskiy if cachemode is None: 2112e5a2f57SVladimir Sementsov-Ogievskiy self.cachemode_is_default = 'true' 2122e5a2f57SVladimir Sementsov-Ogievskiy self.cachemode = 'writeback' 2132e5a2f57SVladimir Sementsov-Ogievskiy else: 2142e5a2f57SVladimir Sementsov-Ogievskiy self.cachemode_is_default = 'false' 2152e5a2f57SVladimir Sementsov-Ogievskiy self.cachemode = cachemode 2162e5a2f57SVladimir Sementsov-Ogievskiy 2172e5a2f57SVladimir Sementsov-Ogievskiy # Initialize generic paths: build_root, build_iotests, source_iotests, 2182e5a2f57SVladimir Sementsov-Ogievskiy # which are needed to initialize some environment variables. They are 2192e5a2f57SVladimir Sementsov-Ogievskiy # used by init_*() functions as well. 2202e5a2f57SVladimir Sementsov-Ogievskiy 2210c8076b0SDaniel P. Berrangé self.source_iotests = source_dir 2220c8076b0SDaniel P. Berrangé self.build_iotests = build_dir 2232e5a2f57SVladimir Sementsov-Ogievskiy 2249444e5f5SJohn Snow self.build_root = Path(self.build_iotests).parent.parent 2252e5a2f57SVladimir Sementsov-Ogievskiy 2262e5a2f57SVladimir Sementsov-Ogievskiy self.init_directories() 227a9e21786SDaniel P. Berrangé 228a9e21786SDaniel P. Berrangé if dry_run: 229a9e21786SDaniel P. Berrangé return 230a9e21786SDaniel P. Berrangé 2312e5a2f57SVladimir Sementsov-Ogievskiy self.init_binaries() 2322e5a2f57SVladimir Sementsov-Ogievskiy 2332e5a2f57SVladimir Sementsov-Ogievskiy self.malloc_perturb_ = os.getenv('MALLOC_PERTURB_', 2342e5a2f57SVladimir Sementsov-Ogievskiy str(random.randrange(1, 255))) 2352e5a2f57SVladimir Sementsov-Ogievskiy 2362e5a2f57SVladimir Sementsov-Ogievskiy # QEMU_OPTIONS 2372e5a2f57SVladimir Sementsov-Ogievskiy self.qemu_options = '-nodefaults -display none -accel qtest' 2382e5a2f57SVladimir Sementsov-Ogievskiy machine_map = ( 2392e5a2f57SVladimir Sementsov-Ogievskiy ('arm', 'virt'), 2402e5a2f57SVladimir Sementsov-Ogievskiy ('aarch64', 'virt'), 2412e5a2f57SVladimir Sementsov-Ogievskiy ('avr', 'mega2560'), 2427033f1fdSLaurent Vivier ('m68k', 'virt'), 243798f35fcSThomas Huth ('or1k', 'virt'), 2443213bbafSlaokz ('riscv32', 'virt'), 2453213bbafSlaokz ('riscv64', 'virt'), 2462e5a2f57SVladimir Sementsov-Ogievskiy ('rx', 'gdbsim-r5f562n8'), 247fd729433SThomas Huth ('sh4', 'r2d'), 248*51cdb680SThomas Huth ('sh4eb', 'r2d'), 2492e5a2f57SVladimir Sementsov-Ogievskiy ('tricore', 'tricore_testboard') 2502e5a2f57SVladimir Sementsov-Ogievskiy ) 2512e5a2f57SVladimir Sementsov-Ogievskiy for suffix, machine in machine_map: 2522e5a2f57SVladimir Sementsov-Ogievskiy if self.qemu_prog.endswith(f'qemu-system-{suffix}'): 2532e5a2f57SVladimir Sementsov-Ogievskiy self.qemu_options += f' -machine {machine}' 2542e5a2f57SVladimir Sementsov-Ogievskiy 2552e5a2f57SVladimir Sementsov-Ogievskiy # QEMU_DEFAULT_MACHINE 2562e5a2f57SVladimir Sementsov-Ogievskiy self.qemu_default_machine = get_default_machine(self.qemu_prog) 2572e5a2f57SVladimir Sementsov-Ogievskiy 2582e5a2f57SVladimir Sementsov-Ogievskiy self.qemu_img_options = os.getenv('QEMU_IMG_OPTIONS') 2592e5a2f57SVladimir Sementsov-Ogievskiy self.qemu_nbd_options = os.getenv('QEMU_NBD_OPTIONS') 2602e5a2f57SVladimir Sementsov-Ogievskiy 261c8f60bfbSAmjad Alsharafi is_generic = self.imgfmt not in ['bochs', 'cloop', 'dmg', 'vvfat'] 2622e5a2f57SVladimir Sementsov-Ogievskiy self.imgfmt_generic = 'true' if is_generic else 'false' 2632e5a2f57SVladimir Sementsov-Ogievskiy 2642e5a2f57SVladimir Sementsov-Ogievskiy self.qemu_io_options = f'--cache {self.cachemode} --aio {self.aiomode}' 2652e5a2f57SVladimir Sementsov-Ogievskiy if self.misalign: 2662e5a2f57SVladimir Sementsov-Ogievskiy self.qemu_io_options += ' --misalign' 2672e5a2f57SVladimir Sementsov-Ogievskiy 2682e5a2f57SVladimir Sementsov-Ogievskiy self.qemu_io_options_no_fmt = self.qemu_io_options 2692e5a2f57SVladimir Sementsov-Ogievskiy 2702e5a2f57SVladimir Sementsov-Ogievskiy if self.imgfmt == 'luks': 2712e5a2f57SVladimir Sementsov-Ogievskiy self.imgoptssyntax = 'true' 2722e5a2f57SVladimir Sementsov-Ogievskiy self.imgkeysecret = '123456' 2732e5a2f57SVladimir Sementsov-Ogievskiy if not self.imgopts: 2742e5a2f57SVladimir Sementsov-Ogievskiy self.imgopts = 'iter-time=10' 2752e5a2f57SVladimir Sementsov-Ogievskiy elif 'iter-time=' not in self.imgopts: 2762e5a2f57SVladimir Sementsov-Ogievskiy self.imgopts += ',iter-time=10' 2772e5a2f57SVladimir Sementsov-Ogievskiy else: 2782e5a2f57SVladimir Sementsov-Ogievskiy self.imgoptssyntax = 'false' 2792e5a2f57SVladimir Sementsov-Ogievskiy self.qemu_io_options += ' -f ' + self.imgfmt 2802e5a2f57SVladimir Sementsov-Ogievskiy 2812e5a2f57SVladimir Sementsov-Ogievskiy if self.imgfmt == 'vmdk': 2822e5a2f57SVladimir Sementsov-Ogievskiy if not self.imgopts: 2832e5a2f57SVladimir Sementsov-Ogievskiy self.imgopts = 'zeroed_grain=on' 2842e5a2f57SVladimir Sementsov-Ogievskiy elif 'zeroed_grain=' not in self.imgopts: 2852e5a2f57SVladimir Sementsov-Ogievskiy self.imgopts += ',zeroed_grain=on' 2862e5a2f57SVladimir Sementsov-Ogievskiy 2872e5a2f57SVladimir Sementsov-Ogievskiy def close(self) -> None: 2882e5a2f57SVladimir Sementsov-Ogievskiy if self.tmp_sock_dir: 2892e5a2f57SVladimir Sementsov-Ogievskiy shutil.rmtree(self.sock_dir) 2902e5a2f57SVladimir Sementsov-Ogievskiy 2912e5a2f57SVladimir Sementsov-Ogievskiy def __enter__(self) -> 'TestEnv': 2922e5a2f57SVladimir Sementsov-Ogievskiy return self 2932e5a2f57SVladimir Sementsov-Ogievskiy 2942e5a2f57SVladimir Sementsov-Ogievskiy def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None: 2952e5a2f57SVladimir Sementsov-Ogievskiy self.close() 2962e5a2f57SVladimir Sementsov-Ogievskiy 297d316859fSPaolo Bonzini def print_env(self, prefix: str = '') -> None: 2982e5a2f57SVladimir Sementsov-Ogievskiy template = """\ 299d316859fSPaolo Bonzini{prefix}QEMU -- "{QEMU_PROG}" {QEMU_OPTIONS} 300d316859fSPaolo Bonzini{prefix}QEMU_IMG -- "{QEMU_IMG_PROG}" {QEMU_IMG_OPTIONS} 301d316859fSPaolo Bonzini{prefix}QEMU_IO -- "{QEMU_IO_PROG}" {QEMU_IO_OPTIONS} 302d316859fSPaolo Bonzini{prefix}QEMU_NBD -- "{QEMU_NBD_PROG}" {QEMU_NBD_OPTIONS} 303d316859fSPaolo Bonzini{prefix}IMGFMT -- {IMGFMT}{imgopts} 304d316859fSPaolo Bonzini{prefix}IMGPROTO -- {IMGPROTO} 305d316859fSPaolo Bonzini{prefix}PLATFORM -- {platform} 306d316859fSPaolo Bonzini{prefix}TEST_DIR -- {TEST_DIR} 307d316859fSPaolo Bonzini{prefix}SOCK_DIR -- {SOCK_DIR} 308d316859fSPaolo Bonzini{prefix}GDB_OPTIONS -- {GDB_OPTIONS} 309d316859fSPaolo Bonzini{prefix}VALGRIND_QEMU -- {VALGRIND_QEMU} 310d316859fSPaolo Bonzini{prefix}PRINT_QEMU_OUTPUT -- {PRINT_QEMU} 311d316859fSPaolo Bonzini{prefix}""" 3122e5a2f57SVladimir Sementsov-Ogievskiy 3132e5a2f57SVladimir Sementsov-Ogievskiy args = collections.defaultdict(str, self.get_env()) 3142e5a2f57SVladimir Sementsov-Ogievskiy 3152e5a2f57SVladimir Sementsov-Ogievskiy if 'IMGOPTS' in args: 3162e5a2f57SVladimir Sementsov-Ogievskiy args['imgopts'] = f" ({args['IMGOPTS']})" 3172e5a2f57SVladimir Sementsov-Ogievskiy 3182e5a2f57SVladimir Sementsov-Ogievskiy u = os.uname() 3192e5a2f57SVladimir Sementsov-Ogievskiy args['platform'] = f'{u.sysname}/{u.machine} {u.nodename} {u.release}' 320d316859fSPaolo Bonzini args['prefix'] = prefix 3212e5a2f57SVladimir Sementsov-Ogievskiy print(template.format_map(args)) 322