xref: /qemu/tests/qemu-iotests/testenv.py (revision 11b8920ed2093848f79f93d106afe8a69a61a523)
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