Example #1
0
 def __init__(self, vm, port=None):
     self.vm = vm
     self.port = port or free_port.find()
     self.vm.log.debug(f'monitor port {self.port}')
     self._sock = None
     self._queue = queue.Queue()
     self._ram_actual_changed = threading.Event()
     self._ram_target_changed = threading.Event()
     self._command_execution_lock = threading.RLock()
Example #2
0
 def __init__(self, m, key, host='127.0.0.1', port=None):
     self.host, self.key = host, key
     self.port = port or free_port.find()
     self.m = m
     self.m.log.debug(f'ssh port {self.port}')
     self._transport = None
Example #3
0
    def run(self, load=SNAPSHOT_BASE_NAME, guest_forwards=[], extra_args=[]):
        if load:
            self.vm.time_desync.report(self.vm.time_desync.LARGE)
        run_args = ['-loadvm', load] if load else []

        self.monitor = Monitor(self.vm)
        run_args += [
            '-qmp',
            (f'tcp:127.0.0.1:{self.monitor.port},'
             'server,nowait,nodelay')
        ]

        self.vm.ssh.port = free_port.find()
        self.vm.shared_directory = SharedDirectory(self.vm)
        self.vm.exec = self.vm.ssh.exec
        host_forwards = [(self.vm.ssh.port, 22)] + self.vm._host_forwards
        host_forwards = [
            f'hostfwd=tcp:127.0.0.1:{h}-:{g}' for h, g in host_forwards
        ]
        cache_guest_forward = (CACHE_INTERNAL_IP, CACHE_INTERNAL_PORT,
                               f'nc 127.0.0.1 {self.vm.http_cache.port}')
        guest_forwards = guest_forwards + [cache_guest_forward]
        run_args += [
            '-device', 'virtio-net,netdev=net0', '-netdev',
            ','.join(['user', 'id=net0'] + host_forwards +
                     (['restrict=yes'] if self.vm.sealed else []) + [
                         f'guestfwd=tcp:{ip}:{port}-cmd:{cmd}'
                         for ip, port, cmd in guest_forwards
                     ])
        ]

        self.image = os.path.join(self.vm.path, 'image.qcow2')
        if self._image_to_clone:
            # let's try to use /tmp (which is, hopefully, tmpfs) for transients
            # if it looks empty enough
            cloned_to_tmp = False
            required_space = os.path.getsize(self._image_to_clone) + 2 * 2**30
            if self.vm._transient:
                # Would be ideal to have it global (and multiuser-ok)
                tmp_free_lock = path.cache('.tmp-free-space-check-lock')
                with fasteners.process_lock.InterProcessLock(tmp_free_lock):
                    if temp.has_space(required_space, where='/tmp'):
                        self.image = temp.disappearing_file(
                            '/tmp', hint='fingertip-qemu')
                        self.vm.log.info('preloading image to /tmp...')
                        reflink.auto(self._image_to_clone, self.image)
                        self.vm.log.info('preloading image to /tmp completed')
                        cloned_to_tmp = True
            if not cloned_to_tmp:
                reflink.auto(self._image_to_clone, self.image)
            self._image_to_clone = None
        if self.virtio_scsi:
            run_args += [
                '-device', 'virtio-scsi-pci', '-device', 'scsi-hd,drive=hd',
                '-drive', f'file={self.image},cache=unsafe,'
                'if=none,id=hd,discard=unmap'
            ]
        else:
            run_args += [
                '-drive', f'file={self.image},cache=unsafe,'
                'if=virtio,discard=unmap'
            ]

        run_args += ['-m', str(self.vm.ram.max // 2**20)]

        os.makedirs(path.SHARED, exist_ok=True)

        args = QEMU_COMMON_ARGS + self.custom_args + run_args + extra_args
        self.vm.log.debug(' '.join(args))
        if self.vm._backend_mode == 'pexpect':
            # start connecting/negotiating QMP, later starts auto-ballooning
            threading.Thread(target=self.monitor.connect, daemon=True).start()
            pexp = self.vm.log.pseudofile_powered(pexpect.spawn,
                                                  logfile=logging.INFO)
            self.vm.console = pexp(self._qemu,
                                   args,
                                   echo=False,
                                   timeout=None,
                                   encoding='utf-8',
                                   codec_errors='ignore')
            self.live = True
        elif self.vm._backend_mode == 'direct':
            subprocess.run([self._qemu, '-serial', 'mon:stdio'] + args,
                           check=True)
            # FIXME: autoballooning won't start w/o the monitor connection!
            self.live = False
            self._go_down()
Example #4
0
 def __init__(self, vm, port=None):
     self.vm = vm
     self.port = port or free_port.find()
     self.vm.log.debug(f'monitor port {self.port}')
     self._sock = None