1212c1933SFabiano Rosas# 2212c1933SFabiano Rosas# Migration test main engine 3212c1933SFabiano Rosas# 4212c1933SFabiano Rosas# Copyright (c) 2016 Red Hat, Inc. 5212c1933SFabiano Rosas# 6212c1933SFabiano Rosas# This library is free software; you can redistribute it and/or 7212c1933SFabiano Rosas# modify it under the terms of the GNU Lesser General Public 8212c1933SFabiano Rosas# License as published by the Free Software Foundation; either 9212c1933SFabiano Rosas# version 2.1 of the License, or (at your option) any later version. 10212c1933SFabiano Rosas# 11212c1933SFabiano Rosas# This library is distributed in the hope that it will be useful, 12212c1933SFabiano Rosas# but WITHOUT ANY WARRANTY; without even the implied warranty of 13212c1933SFabiano Rosas# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14212c1933SFabiano Rosas# Lesser General Public License for more details. 15212c1933SFabiano Rosas# 16212c1933SFabiano Rosas# You should have received a copy of the GNU Lesser General Public 17212c1933SFabiano Rosas# License along with this library; if not, see <http://www.gnu.org/licenses/>. 18212c1933SFabiano Rosas# 19212c1933SFabiano Rosas 20212c1933SFabiano Rosas 21212c1933SFabiano Rosasimport os 22212c1933SFabiano Rosasimport re 23212c1933SFabiano Rosasimport sys 24212c1933SFabiano Rosasimport time 25212c1933SFabiano Rosas 26212c1933SFabiano Rosasfrom guestperf.progress import Progress, ProgressStats 27*5984870eSHyman Huangfrom guestperf.report import Report, ReportResult 28212c1933SFabiano Rosasfrom guestperf.timings import TimingRecord, Timings 29212c1933SFabiano Rosas 30212c1933SFabiano Rosassys.path.append(os.path.join(os.path.dirname(__file__), 31212c1933SFabiano Rosas '..', '..', '..', 'python')) 32212c1933SFabiano Rosasfrom qemu.machine import QEMUMachine 33212c1933SFabiano Rosas 3445f34156SHyman Huang# multifd supported compression algorithms 3545f34156SHyman HuangMULTIFD_CMP_ALGS = ("zlib", "zstd", "qpl", "uadk") 36212c1933SFabiano Rosas 37212c1933SFabiano Rosasclass Engine(object): 38212c1933SFabiano Rosas 39212c1933SFabiano Rosas def __init__(self, binary, dst_host, kernel, initrd, transport="tcp", 40212c1933SFabiano Rosas sleep=15, verbose=False, debug=False): 41212c1933SFabiano Rosas 42212c1933SFabiano Rosas self._binary = binary # Path to QEMU binary 43212c1933SFabiano Rosas self._dst_host = dst_host # Hostname of target host 44212c1933SFabiano Rosas self._kernel = kernel # Path to kernel image 45212c1933SFabiano Rosas self._initrd = initrd # Path to stress initrd 46212c1933SFabiano Rosas self._transport = transport # 'unix' or 'tcp' or 'rdma' 47212c1933SFabiano Rosas self._sleep = sleep 48212c1933SFabiano Rosas self._verbose = verbose 49212c1933SFabiano Rosas self._debug = debug 50212c1933SFabiano Rosas 51212c1933SFabiano Rosas if debug: 52212c1933SFabiano Rosas self._verbose = debug 53212c1933SFabiano Rosas 54212c1933SFabiano Rosas def _vcpu_timing(self, pid, tid_list): 55212c1933SFabiano Rosas records = [] 56212c1933SFabiano Rosas now = time.time() 57212c1933SFabiano Rosas 58212c1933SFabiano Rosas jiffies_per_sec = os.sysconf(os.sysconf_names['SC_CLK_TCK']) 59212c1933SFabiano Rosas for tid in tid_list: 60212c1933SFabiano Rosas statfile = "/proc/%d/task/%d/stat" % (pid, tid) 61212c1933SFabiano Rosas with open(statfile, "r") as fh: 62212c1933SFabiano Rosas stat = fh.readline() 63212c1933SFabiano Rosas fields = stat.split(" ") 64212c1933SFabiano Rosas stime = int(fields[13]) 65212c1933SFabiano Rosas utime = int(fields[14]) 66212c1933SFabiano Rosas records.append(TimingRecord(tid, now, 1000 * (stime + utime) / jiffies_per_sec)) 67212c1933SFabiano Rosas return records 68212c1933SFabiano Rosas 69212c1933SFabiano Rosas def _cpu_timing(self, pid): 70212c1933SFabiano Rosas now = time.time() 71212c1933SFabiano Rosas 72212c1933SFabiano Rosas jiffies_per_sec = os.sysconf(os.sysconf_names['SC_CLK_TCK']) 73212c1933SFabiano Rosas statfile = "/proc/%d/stat" % pid 74212c1933SFabiano Rosas with open(statfile, "r") as fh: 75212c1933SFabiano Rosas stat = fh.readline() 76212c1933SFabiano Rosas fields = stat.split(" ") 77212c1933SFabiano Rosas stime = int(fields[13]) 78212c1933SFabiano Rosas utime = int(fields[14]) 79212c1933SFabiano Rosas return TimingRecord(pid, now, 1000 * (stime + utime) / jiffies_per_sec) 80212c1933SFabiano Rosas 81212c1933SFabiano Rosas def _migrate_progress(self, vm): 82212c1933SFabiano Rosas info = vm.cmd("query-migrate") 83212c1933SFabiano Rosas 84212c1933SFabiano Rosas if "ram" not in info: 85212c1933SFabiano Rosas info["ram"] = {} 86212c1933SFabiano Rosas 87212c1933SFabiano Rosas return Progress( 88212c1933SFabiano Rosas info.get("status", "active"), 89212c1933SFabiano Rosas ProgressStats( 90212c1933SFabiano Rosas info["ram"].get("transferred", 0), 91212c1933SFabiano Rosas info["ram"].get("remaining", 0), 92212c1933SFabiano Rosas info["ram"].get("total", 0), 93212c1933SFabiano Rosas info["ram"].get("duplicate", 0), 94212c1933SFabiano Rosas info["ram"].get("skipped", 0), 95212c1933SFabiano Rosas info["ram"].get("normal", 0), 96212c1933SFabiano Rosas info["ram"].get("normal-bytes", 0), 97212c1933SFabiano Rosas info["ram"].get("dirty-pages-rate", 0), 98212c1933SFabiano Rosas info["ram"].get("mbps", 0), 99212c1933SFabiano Rosas info["ram"].get("dirty-sync-count", 0) 100212c1933SFabiano Rosas ), 101212c1933SFabiano Rosas time.time(), 102212c1933SFabiano Rosas info.get("total-time", 0), 103212c1933SFabiano Rosas info.get("downtime", 0), 104212c1933SFabiano Rosas info.get("expected-downtime", 0), 105212c1933SFabiano Rosas info.get("setup-time", 0), 106212c1933SFabiano Rosas info.get("cpu-throttle-percentage", 0), 107212c1933SFabiano Rosas info.get("dirty-limit-throttle-time-per-round", 0), 108212c1933SFabiano Rosas info.get("dirty-limit-ring-full-time", 0), 109212c1933SFabiano Rosas ) 110212c1933SFabiano Rosas 11132a1bb21SHyman Huang def _migrate(self, hardware, scenario, src, 11232a1bb21SHyman Huang dst, connect_uri, defer_migrate): 113212c1933SFabiano Rosas src_qemu_time = [] 114212c1933SFabiano Rosas src_vcpu_time = [] 115212c1933SFabiano Rosas src_pid = src.get_pid() 116212c1933SFabiano Rosas 117212c1933SFabiano Rosas vcpus = src.cmd("query-cpus-fast") 118212c1933SFabiano Rosas src_threads = [] 119212c1933SFabiano Rosas for vcpu in vcpus: 120212c1933SFabiano Rosas src_threads.append(vcpu["thread-id"]) 121212c1933SFabiano Rosas 122212c1933SFabiano Rosas # XXX how to get dst timings on remote host ? 123212c1933SFabiano Rosas 124212c1933SFabiano Rosas if self._verbose: 125212c1933SFabiano Rosas print("Sleeping %d seconds for initial guest workload run" % self._sleep) 126212c1933SFabiano Rosas sleep_secs = self._sleep 127212c1933SFabiano Rosas while sleep_secs > 1: 128212c1933SFabiano Rosas src_qemu_time.append(self._cpu_timing(src_pid)) 129212c1933SFabiano Rosas src_vcpu_time.extend(self._vcpu_timing(src_pid, src_threads)) 130212c1933SFabiano Rosas time.sleep(1) 131212c1933SFabiano Rosas sleep_secs -= 1 132212c1933SFabiano Rosas 133212c1933SFabiano Rosas if self._verbose: 134212c1933SFabiano Rosas print("Starting migration") 135212c1933SFabiano Rosas if scenario._auto_converge: 136212c1933SFabiano Rosas resp = src.cmd("migrate-set-capabilities", 137212c1933SFabiano Rosas capabilities = [ 138212c1933SFabiano Rosas { "capability": "auto-converge", 139212c1933SFabiano Rosas "state": True } 140212c1933SFabiano Rosas ]) 141212c1933SFabiano Rosas resp = src.cmd("migrate-set-parameters", 142212c1933SFabiano Rosas cpu_throttle_increment=scenario._auto_converge_step) 143212c1933SFabiano Rosas 144212c1933SFabiano Rosas if scenario._post_copy: 145212c1933SFabiano Rosas resp = src.cmd("migrate-set-capabilities", 146212c1933SFabiano Rosas capabilities = [ 147212c1933SFabiano Rosas { "capability": "postcopy-ram", 148212c1933SFabiano Rosas "state": True } 149212c1933SFabiano Rosas ]) 150212c1933SFabiano Rosas resp = dst.cmd("migrate-set-capabilities", 151212c1933SFabiano Rosas capabilities = [ 152212c1933SFabiano Rosas { "capability": "postcopy-ram", 153212c1933SFabiano Rosas "state": True } 154212c1933SFabiano Rosas ]) 155212c1933SFabiano Rosas 156212c1933SFabiano Rosas resp = src.cmd("migrate-set-parameters", 157212c1933SFabiano Rosas max_bandwidth=scenario._bandwidth * 1024 * 1024) 158212c1933SFabiano Rosas 159212c1933SFabiano Rosas resp = src.cmd("migrate-set-parameters", 160212c1933SFabiano Rosas downtime_limit=scenario._downtime) 161212c1933SFabiano Rosas 162212c1933SFabiano Rosas if scenario._compression_mt: 163212c1933SFabiano Rosas resp = src.cmd("migrate-set-capabilities", 164212c1933SFabiano Rosas capabilities = [ 165212c1933SFabiano Rosas { "capability": "compress", 166212c1933SFabiano Rosas "state": True } 167212c1933SFabiano Rosas ]) 168212c1933SFabiano Rosas resp = src.cmd("migrate-set-parameters", 169212c1933SFabiano Rosas compress_threads=scenario._compression_mt_threads) 170212c1933SFabiano Rosas resp = dst.cmd("migrate-set-capabilities", 171212c1933SFabiano Rosas capabilities = [ 172212c1933SFabiano Rosas { "capability": "compress", 173212c1933SFabiano Rosas "state": True } 174212c1933SFabiano Rosas ]) 175212c1933SFabiano Rosas resp = dst.cmd("migrate-set-parameters", 176212c1933SFabiano Rosas decompress_threads=scenario._compression_mt_threads) 177212c1933SFabiano Rosas 178212c1933SFabiano Rosas if scenario._compression_xbzrle: 179212c1933SFabiano Rosas resp = src.cmd("migrate-set-capabilities", 180212c1933SFabiano Rosas capabilities = [ 181212c1933SFabiano Rosas { "capability": "xbzrle", 182212c1933SFabiano Rosas "state": True } 183212c1933SFabiano Rosas ]) 184212c1933SFabiano Rosas resp = dst.cmd("migrate-set-capabilities", 185212c1933SFabiano Rosas capabilities = [ 186212c1933SFabiano Rosas { "capability": "xbzrle", 187212c1933SFabiano Rosas "state": True } 188212c1933SFabiano Rosas ]) 189212c1933SFabiano Rosas resp = src.cmd("migrate-set-parameters", 190212c1933SFabiano Rosas xbzrle_cache_size=( 191212c1933SFabiano Rosas hardware._mem * 192212c1933SFabiano Rosas 1024 * 1024 * 1024 / 100 * 193212c1933SFabiano Rosas scenario._compression_xbzrle_cache)) 194212c1933SFabiano Rosas 195212c1933SFabiano Rosas if scenario._multifd: 19645f34156SHyman Huang if (scenario._multifd_compression and 19745f34156SHyman Huang (scenario._multifd_compression not in MULTIFD_CMP_ALGS)): 19845f34156SHyman Huang raise Exception("unsupported multifd compression " 19945f34156SHyman Huang "algorithm: %s" % 20045f34156SHyman Huang scenario._multifd_compression) 20145f34156SHyman Huang 202212c1933SFabiano Rosas resp = src.cmd("migrate-set-capabilities", 203212c1933SFabiano Rosas capabilities = [ 204212c1933SFabiano Rosas { "capability": "multifd", 205212c1933SFabiano Rosas "state": True } 206212c1933SFabiano Rosas ]) 207212c1933SFabiano Rosas resp = src.cmd("migrate-set-parameters", 208212c1933SFabiano Rosas multifd_channels=scenario._multifd_channels) 209212c1933SFabiano Rosas resp = dst.cmd("migrate-set-capabilities", 210212c1933SFabiano Rosas capabilities = [ 211212c1933SFabiano Rosas { "capability": "multifd", 212212c1933SFabiano Rosas "state": True } 213212c1933SFabiano Rosas ]) 214212c1933SFabiano Rosas resp = dst.cmd("migrate-set-parameters", 215212c1933SFabiano Rosas multifd_channels=scenario._multifd_channels) 216212c1933SFabiano Rosas 21745f34156SHyman Huang if scenario._multifd_compression: 21845f34156SHyman Huang resp = src.cmd("migrate-set-parameters", 21945f34156SHyman Huang multifd_compression=scenario._multifd_compression) 22045f34156SHyman Huang resp = dst.cmd("migrate-set-parameters", 22145f34156SHyman Huang multifd_compression=scenario._multifd_compression) 22245f34156SHyman Huang 223212c1933SFabiano Rosas if scenario._dirty_limit: 224212c1933SFabiano Rosas if not hardware._dirty_ring_size: 225212c1933SFabiano Rosas raise Exception("dirty ring size must be configured when " 226212c1933SFabiano Rosas "testing dirty limit migration") 227212c1933SFabiano Rosas 228212c1933SFabiano Rosas resp = src.cmd("migrate-set-capabilities", 229212c1933SFabiano Rosas capabilities = [ 230212c1933SFabiano Rosas { "capability": "dirty-limit", 231212c1933SFabiano Rosas "state": True } 232212c1933SFabiano Rosas ]) 233212c1933SFabiano Rosas resp = src.cmd("migrate-set-parameters", 234212c1933SFabiano Rosas x_vcpu_dirty_limit_period=scenario._x_vcpu_dirty_limit_period) 235212c1933SFabiano Rosas resp = src.cmd("migrate-set-parameters", 236212c1933SFabiano Rosas vcpu_dirty_limit=scenario._vcpu_dirty_limit) 237212c1933SFabiano Rosas 23832a1bb21SHyman Huang if defer_migrate: 23932a1bb21SHyman Huang resp = dst.cmd("migrate-incoming", uri=connect_uri) 240212c1933SFabiano Rosas resp = src.cmd("migrate", uri=connect_uri) 241212c1933SFabiano Rosas 242212c1933SFabiano Rosas post_copy = False 243212c1933SFabiano Rosas paused = False 244212c1933SFabiano Rosas 245212c1933SFabiano Rosas progress_history = [] 246212c1933SFabiano Rosas 247212c1933SFabiano Rosas start = time.time() 248212c1933SFabiano Rosas loop = 0 249212c1933SFabiano Rosas while True: 250212c1933SFabiano Rosas loop = loop + 1 251212c1933SFabiano Rosas time.sleep(0.05) 252212c1933SFabiano Rosas 253212c1933SFabiano Rosas progress = self._migrate_progress(src) 254212c1933SFabiano Rosas if (loop % 20) == 0: 255212c1933SFabiano Rosas src_qemu_time.append(self._cpu_timing(src_pid)) 256212c1933SFabiano Rosas src_vcpu_time.extend(self._vcpu_timing(src_pid, src_threads)) 257212c1933SFabiano Rosas 258212c1933SFabiano Rosas if (len(progress_history) == 0 or 259212c1933SFabiano Rosas (progress_history[-1]._ram._iterations < 260212c1933SFabiano Rosas progress._ram._iterations)): 261212c1933SFabiano Rosas progress_history.append(progress) 262212c1933SFabiano Rosas 263212c1933SFabiano Rosas if progress._status in ("completed", "failed", "cancelled"): 264212c1933SFabiano Rosas if progress._status == "completed" and paused: 265212c1933SFabiano Rosas dst.cmd("cont") 266212c1933SFabiano Rosas if progress_history[-1] != progress: 267212c1933SFabiano Rosas progress_history.append(progress) 268212c1933SFabiano Rosas 269212c1933SFabiano Rosas if progress._status == "completed": 270212c1933SFabiano Rosas if self._verbose: 271212c1933SFabiano Rosas print("Sleeping %d seconds for final guest workload run" % self._sleep) 272212c1933SFabiano Rosas sleep_secs = self._sleep 273212c1933SFabiano Rosas while sleep_secs > 1: 274212c1933SFabiano Rosas time.sleep(1) 275212c1933SFabiano Rosas src_qemu_time.append(self._cpu_timing(src_pid)) 276212c1933SFabiano Rosas src_vcpu_time.extend(self._vcpu_timing(src_pid, src_threads)) 277212c1933SFabiano Rosas sleep_secs -= 1 278212c1933SFabiano Rosas 279*5984870eSHyman Huang result = ReportResult() 280*5984870eSHyman Huang if progress._status == "completed" and not paused: 281*5984870eSHyman Huang result = ReportResult(True) 282*5984870eSHyman Huang 283*5984870eSHyman Huang return [progress_history, src_qemu_time, src_vcpu_time, result] 284212c1933SFabiano Rosas 285212c1933SFabiano Rosas if self._verbose and (loop % 20) == 0: 286212c1933SFabiano Rosas print("Iter %d: remain %5dMB of %5dMB (total %5dMB @ %5dMb/sec)" % ( 287212c1933SFabiano Rosas progress._ram._iterations, 288212c1933SFabiano Rosas progress._ram._remaining_bytes / (1024 * 1024), 289212c1933SFabiano Rosas progress._ram._total_bytes / (1024 * 1024), 290212c1933SFabiano Rosas progress._ram._transferred_bytes / (1024 * 1024), 291212c1933SFabiano Rosas progress._ram._transfer_rate_mbs, 292212c1933SFabiano Rosas )) 293212c1933SFabiano Rosas 294212c1933SFabiano Rosas if progress._ram._iterations > scenario._max_iters: 295212c1933SFabiano Rosas if self._verbose: 296212c1933SFabiano Rosas print("No completion after %d iterations over RAM" % scenario._max_iters) 297212c1933SFabiano Rosas src.cmd("migrate_cancel") 298212c1933SFabiano Rosas continue 299212c1933SFabiano Rosas 300212c1933SFabiano Rosas if time.time() > (start + scenario._max_time): 301212c1933SFabiano Rosas if self._verbose: 302212c1933SFabiano Rosas print("No completion after %d seconds" % scenario._max_time) 303212c1933SFabiano Rosas src.cmd("migrate_cancel") 304212c1933SFabiano Rosas continue 305212c1933SFabiano Rosas 306212c1933SFabiano Rosas if (scenario._post_copy and 307212c1933SFabiano Rosas progress._ram._iterations >= scenario._post_copy_iters and 308212c1933SFabiano Rosas not post_copy): 309212c1933SFabiano Rosas if self._verbose: 310212c1933SFabiano Rosas print("Switching to post-copy after %d iterations" % scenario._post_copy_iters) 311212c1933SFabiano Rosas resp = src.cmd("migrate-start-postcopy") 312212c1933SFabiano Rosas post_copy = True 313212c1933SFabiano Rosas 314212c1933SFabiano Rosas if (scenario._pause and 315212c1933SFabiano Rosas progress._ram._iterations >= scenario._pause_iters and 316212c1933SFabiano Rosas not paused): 317212c1933SFabiano Rosas if self._verbose: 318212c1933SFabiano Rosas print("Pausing VM after %d iterations" % scenario._pause_iters) 319212c1933SFabiano Rosas resp = src.cmd("stop") 320212c1933SFabiano Rosas paused = True 321212c1933SFabiano Rosas 322212c1933SFabiano Rosas def _is_ppc64le(self): 323212c1933SFabiano Rosas _, _, _, _, machine = os.uname() 324212c1933SFabiano Rosas if machine == "ppc64le": 325212c1933SFabiano Rosas return True 326212c1933SFabiano Rosas return False 327212c1933SFabiano Rosas 328212c1933SFabiano Rosas def _get_guest_console_args(self): 329212c1933SFabiano Rosas if self._is_ppc64le(): 330212c1933SFabiano Rosas return "console=hvc0" 331212c1933SFabiano Rosas else: 332212c1933SFabiano Rosas return "console=ttyS0" 333212c1933SFabiano Rosas 334212c1933SFabiano Rosas def _get_qemu_serial_args(self): 335212c1933SFabiano Rosas if self._is_ppc64le(): 336212c1933SFabiano Rosas return ["-chardev", "stdio,id=cdev0", 337212c1933SFabiano Rosas "-device", "spapr-vty,chardev=cdev0"] 338212c1933SFabiano Rosas else: 339212c1933SFabiano Rosas return ["-chardev", "stdio,id=cdev0", 340212c1933SFabiano Rosas "-device", "isa-serial,chardev=cdev0"] 341212c1933SFabiano Rosas 342212c1933SFabiano Rosas def _get_common_args(self, hardware, tunnelled=False): 343212c1933SFabiano Rosas args = [ 344212c1933SFabiano Rosas "noapic", 345212c1933SFabiano Rosas "edd=off", 346212c1933SFabiano Rosas "printk.time=1", 347212c1933SFabiano Rosas "noreplace-smp", 348212c1933SFabiano Rosas "cgroup_disable=memory", 349212c1933SFabiano Rosas "pci=noearly", 350212c1933SFabiano Rosas ] 351212c1933SFabiano Rosas 352212c1933SFabiano Rosas args.append(self._get_guest_console_args()) 353212c1933SFabiano Rosas 354212c1933SFabiano Rosas if self._debug: 355212c1933SFabiano Rosas args.append("debug") 356212c1933SFabiano Rosas else: 357212c1933SFabiano Rosas args.append("quiet") 358212c1933SFabiano Rosas 359212c1933SFabiano Rosas args.append("ramsize=%s" % hardware._mem) 360212c1933SFabiano Rosas 361212c1933SFabiano Rosas cmdline = " ".join(args) 362212c1933SFabiano Rosas if tunnelled: 363212c1933SFabiano Rosas cmdline = "'" + cmdline + "'" 364212c1933SFabiano Rosas 365212c1933SFabiano Rosas argv = [ 366212c1933SFabiano Rosas "-cpu", "host", 367212c1933SFabiano Rosas "-kernel", self._kernel, 368212c1933SFabiano Rosas "-initrd", self._initrd, 369212c1933SFabiano Rosas "-append", cmdline, 370212c1933SFabiano Rosas "-m", str((hardware._mem * 1024) + 512), 371212c1933SFabiano Rosas "-smp", str(hardware._cpus), 372212c1933SFabiano Rosas ] 373212c1933SFabiano Rosas if hardware._dirty_ring_size: 374212c1933SFabiano Rosas argv.extend(["-accel", "kvm,dirty-ring-size=%s" % 375212c1933SFabiano Rosas hardware._dirty_ring_size]) 376212c1933SFabiano Rosas else: 377212c1933SFabiano Rosas argv.extend(["-accel", "kvm"]) 378212c1933SFabiano Rosas 379212c1933SFabiano Rosas argv.extend(self._get_qemu_serial_args()) 380212c1933SFabiano Rosas 381212c1933SFabiano Rosas if self._debug: 382212c1933SFabiano Rosas argv.extend(["-machine", "graphics=off"]) 383212c1933SFabiano Rosas 384212c1933SFabiano Rosas if hardware._prealloc_pages: 385212c1933SFabiano Rosas argv_source += ["-mem-path", "/dev/shm", 386212c1933SFabiano Rosas "-mem-prealloc"] 387212c1933SFabiano Rosas if hardware._locked_pages: 388212c1933SFabiano Rosas argv_source += ["-overcommit", "mem-lock=on"] 389212c1933SFabiano Rosas if hardware._huge_pages: 390212c1933SFabiano Rosas pass 391212c1933SFabiano Rosas 392212c1933SFabiano Rosas return argv 393212c1933SFabiano Rosas 394212c1933SFabiano Rosas def _get_src_args(self, hardware): 395212c1933SFabiano Rosas return self._get_common_args(hardware) 396212c1933SFabiano Rosas 39732a1bb21SHyman Huang def _get_dst_args(self, hardware, uri, defer_migrate): 398212c1933SFabiano Rosas tunnelled = False 399212c1933SFabiano Rosas if self._dst_host != "localhost": 400212c1933SFabiano Rosas tunnelled = True 401212c1933SFabiano Rosas argv = self._get_common_args(hardware, tunnelled) 40232a1bb21SHyman Huang 40332a1bb21SHyman Huang if defer_migrate: 40432a1bb21SHyman Huang return argv + ["-incoming", "defer"] 405212c1933SFabiano Rosas return argv + ["-incoming", uri] 406212c1933SFabiano Rosas 407212c1933SFabiano Rosas @staticmethod 408212c1933SFabiano Rosas def _get_common_wrapper(cpu_bind, mem_bind): 409212c1933SFabiano Rosas wrapper = [] 410212c1933SFabiano Rosas if len(cpu_bind) > 0 or len(mem_bind) > 0: 411212c1933SFabiano Rosas wrapper.append("numactl") 412212c1933SFabiano Rosas if cpu_bind: 413212c1933SFabiano Rosas wrapper.append("--physcpubind=%s" % ",".join(cpu_bind)) 414212c1933SFabiano Rosas if mem_bind: 415212c1933SFabiano Rosas wrapper.append("--membind=%s" % ",".join(mem_bind)) 416212c1933SFabiano Rosas 417212c1933SFabiano Rosas return wrapper 418212c1933SFabiano Rosas 419212c1933SFabiano Rosas def _get_src_wrapper(self, hardware): 420212c1933SFabiano Rosas return self._get_common_wrapper(hardware._src_cpu_bind, hardware._src_mem_bind) 421212c1933SFabiano Rosas 422212c1933SFabiano Rosas def _get_dst_wrapper(self, hardware): 423212c1933SFabiano Rosas wrapper = self._get_common_wrapper(hardware._dst_cpu_bind, hardware._dst_mem_bind) 424212c1933SFabiano Rosas if self._dst_host != "localhost": 425212c1933SFabiano Rosas return ["ssh", 426212c1933SFabiano Rosas "-R", "9001:localhost:9001", 427212c1933SFabiano Rosas self._dst_host] + wrapper 428212c1933SFabiano Rosas else: 429212c1933SFabiano Rosas return wrapper 430212c1933SFabiano Rosas 431212c1933SFabiano Rosas def _get_timings(self, vm): 432212c1933SFabiano Rosas log = vm.get_log() 433212c1933SFabiano Rosas if not log: 434212c1933SFabiano Rosas return [] 435212c1933SFabiano Rosas if self._debug: 436212c1933SFabiano Rosas print(log) 437212c1933SFabiano Rosas 438212c1933SFabiano Rosas regex = r"[^\s]+\s\((\d+)\):\sINFO:\s(\d+)ms\scopied\s\d+\sGB\sin\s(\d+)ms" 439212c1933SFabiano Rosas matcher = re.compile(regex) 440212c1933SFabiano Rosas records = [] 441212c1933SFabiano Rosas for line in log.split("\n"): 442212c1933SFabiano Rosas match = matcher.match(line) 443212c1933SFabiano Rosas if match: 444212c1933SFabiano Rosas records.append(TimingRecord(int(match.group(1)), 445212c1933SFabiano Rosas int(match.group(2)) / 1000.0, 446212c1933SFabiano Rosas int(match.group(3)))) 447212c1933SFabiano Rosas return records 448212c1933SFabiano Rosas 449212c1933SFabiano Rosas def run(self, hardware, scenario, result_dir=os.getcwd()): 450212c1933SFabiano Rosas abs_result_dir = os.path.join(result_dir, scenario._name) 45132a1bb21SHyman Huang defer_migrate = False 452212c1933SFabiano Rosas 453212c1933SFabiano Rosas if self._transport == "tcp": 454212c1933SFabiano Rosas uri = "tcp:%s:9000" % self._dst_host 455212c1933SFabiano Rosas elif self._transport == "rdma": 456212c1933SFabiano Rosas uri = "rdma:%s:9000" % self._dst_host 457212c1933SFabiano Rosas elif self._transport == "unix": 458212c1933SFabiano Rosas if self._dst_host != "localhost": 459212c1933SFabiano Rosas raise Exception("Running use unix migration transport for non-local host") 460212c1933SFabiano Rosas uri = "unix:/var/tmp/qemu-migrate-%d.migrate" % os.getpid() 461212c1933SFabiano Rosas try: 462212c1933SFabiano Rosas os.remove(uri[5:]) 463212c1933SFabiano Rosas os.remove(monaddr) 464212c1933SFabiano Rosas except: 465212c1933SFabiano Rosas pass 466212c1933SFabiano Rosas 46732a1bb21SHyman Huang if scenario._multifd: 46832a1bb21SHyman Huang defer_migrate = True 46932a1bb21SHyman Huang 470212c1933SFabiano Rosas if self._dst_host != "localhost": 471212c1933SFabiano Rosas dstmonaddr = ("localhost", 9001) 472212c1933SFabiano Rosas else: 473212c1933SFabiano Rosas dstmonaddr = "/var/tmp/qemu-dst-%d-monitor.sock" % os.getpid() 474212c1933SFabiano Rosas srcmonaddr = "/var/tmp/qemu-src-%d-monitor.sock" % os.getpid() 475212c1933SFabiano Rosas 476212c1933SFabiano Rosas src = QEMUMachine(self._binary, 477212c1933SFabiano Rosas args=self._get_src_args(hardware), 478212c1933SFabiano Rosas wrapper=self._get_src_wrapper(hardware), 479212c1933SFabiano Rosas name="qemu-src-%d" % os.getpid(), 480212c1933SFabiano Rosas monitor_address=srcmonaddr) 481212c1933SFabiano Rosas 482212c1933SFabiano Rosas dst = QEMUMachine(self._binary, 48332a1bb21SHyman Huang args=self._get_dst_args(hardware, uri, defer_migrate), 484212c1933SFabiano Rosas wrapper=self._get_dst_wrapper(hardware), 485212c1933SFabiano Rosas name="qemu-dst-%d" % os.getpid(), 486212c1933SFabiano Rosas monitor_address=dstmonaddr) 487212c1933SFabiano Rosas 488212c1933SFabiano Rosas try: 489212c1933SFabiano Rosas src.launch() 490212c1933SFabiano Rosas dst.launch() 491212c1933SFabiano Rosas 49232a1bb21SHyman Huang ret = self._migrate(hardware, scenario, src, 49332a1bb21SHyman Huang dst, uri, defer_migrate) 494212c1933SFabiano Rosas progress_history = ret[0] 495212c1933SFabiano Rosas qemu_timings = ret[1] 496212c1933SFabiano Rosas vcpu_timings = ret[2] 497*5984870eSHyman Huang result = ret[3] 498212c1933SFabiano Rosas if uri[0:5] == "unix:" and os.path.exists(uri[5:]): 499212c1933SFabiano Rosas os.remove(uri[5:]) 500212c1933SFabiano Rosas 501212c1933SFabiano Rosas if os.path.exists(srcmonaddr): 502212c1933SFabiano Rosas os.remove(srcmonaddr) 503212c1933SFabiano Rosas 504212c1933SFabiano Rosas if self._dst_host == "localhost" and os.path.exists(dstmonaddr): 505212c1933SFabiano Rosas os.remove(dstmonaddr) 506212c1933SFabiano Rosas 507212c1933SFabiano Rosas if self._verbose: 508212c1933SFabiano Rosas print("Finished migration") 509212c1933SFabiano Rosas 510212c1933SFabiano Rosas src.shutdown() 511212c1933SFabiano Rosas dst.shutdown() 512212c1933SFabiano Rosas 513212c1933SFabiano Rosas return Report(hardware, scenario, progress_history, 514212c1933SFabiano Rosas Timings(self._get_timings(src) + self._get_timings(dst)), 515212c1933SFabiano Rosas Timings(qemu_timings), 516212c1933SFabiano Rosas Timings(vcpu_timings), 517*5984870eSHyman Huang result, 518212c1933SFabiano Rosas self._binary, self._dst_host, self._kernel, 519212c1933SFabiano Rosas self._initrd, self._transport, self._sleep) 520212c1933SFabiano Rosas except Exception as e: 521212c1933SFabiano Rosas if self._debug: 522212c1933SFabiano Rosas print("Failed: %s" % str(e)) 523212c1933SFabiano Rosas try: 524212c1933SFabiano Rosas src.shutdown() 525212c1933SFabiano Rosas except: 526212c1933SFabiano Rosas pass 527212c1933SFabiano Rosas try: 528212c1933SFabiano Rosas dst.shutdown() 529212c1933SFabiano Rosas except: 530212c1933SFabiano Rosas pass 531212c1933SFabiano Rosas 532212c1933SFabiano Rosas if self._debug: 533212c1933SFabiano Rosas print(src.get_log()) 534212c1933SFabiano Rosas print(dst.get_log()) 535212c1933SFabiano Rosas raise 536212c1933SFabiano Rosas 537