mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-07-27 20:33:54 -06:00
scripts/qemu.py: introduce set_console() method
The set_console() method is intended to ease higher level use cases that require a console device. The amount of intelligence is limited on purpose, requiring either the device type explicitly, or the existence of a machine (pattern) definition. Because of the console device type selection criteria (by machine type), users should also be able to define that. It'll then be used for both '-machine' and for the console device type selection. Users of the set_console() method will certainly be interested in accessing the console device, and for that a console_socket property has been added. Signed-off-by: Cleber Rosa <crosa@redhat.com> Message-Id: <20180530184156.15634-5-crosa@redhat.com> Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
This commit is contained in:
parent
7b1bd11cff
commit
22dea9db2b
1 changed files with 96 additions and 1 deletions
|
@ -17,19 +17,41 @@ import logging
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import qmp.qmp
|
import qmp.qmp
|
||||||
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
|
import socket
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
#: Maps machine types to the preferred console device types
|
||||||
|
CONSOLE_DEV_TYPES = {
|
||||||
|
r'^clipper$': 'isa-serial',
|
||||||
|
r'^malta': 'isa-serial',
|
||||||
|
r'^(pc.*|q35.*|isapc)$': 'isa-serial',
|
||||||
|
r'^(40p|powernv|prep)$': 'isa-serial',
|
||||||
|
r'^pseries.*': 'spapr-vty',
|
||||||
|
r'^s390-ccw-virtio.*': 'sclpconsole',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class QEMUMachineError(Exception):
|
class QEMUMachineError(Exception):
|
||||||
"""
|
"""
|
||||||
Exception called when an error in QEMUMachine happens.
|
Exception called when an error in QEMUMachine happens.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class QEMUMachineAddDeviceError(QEMUMachineError):
|
||||||
|
"""
|
||||||
|
Exception raised when a request to add a device can not be fulfilled
|
||||||
|
|
||||||
|
The failures are caused by limitations, lack of information or conflicting
|
||||||
|
requests on the QEMUMachine methods. This exception does not represent
|
||||||
|
failures reported by the QEMU binary itself.
|
||||||
|
"""
|
||||||
|
|
||||||
class MonitorResponseError(qmp.qmp.QMPError):
|
class MonitorResponseError(qmp.qmp.QMPError):
|
||||||
'''
|
'''
|
||||||
Represents erroneous QMP monitor reply
|
Represents erroneous QMP monitor reply
|
||||||
|
@ -91,6 +113,10 @@ class QEMUMachine(object):
|
||||||
self._test_dir = test_dir
|
self._test_dir = test_dir
|
||||||
self._temp_dir = None
|
self._temp_dir = None
|
||||||
self._launched = False
|
self._launched = False
|
||||||
|
self._machine = None
|
||||||
|
self._console_device_type = None
|
||||||
|
self._console_address = None
|
||||||
|
self._console_socket = None
|
||||||
|
|
||||||
# just in case logging wasn't configured by the main script:
|
# just in case logging wasn't configured by the main script:
|
||||||
logging.basicConfig()
|
logging.basicConfig()
|
||||||
|
@ -175,9 +201,19 @@ class QEMUMachine(object):
|
||||||
self._monitor_address[1])
|
self._monitor_address[1])
|
||||||
else:
|
else:
|
||||||
moncdev = 'socket,id=mon,path=%s' % self._vm_monitor
|
moncdev = 'socket,id=mon,path=%s' % self._vm_monitor
|
||||||
return ['-chardev', moncdev,
|
args = ['-chardev', moncdev,
|
||||||
'-mon', 'chardev=mon,mode=control',
|
'-mon', 'chardev=mon,mode=control',
|
||||||
'-display', 'none', '-vga', 'none']
|
'-display', 'none', '-vga', 'none']
|
||||||
|
if self._machine is not None:
|
||||||
|
args.extend(['-machine', self._machine])
|
||||||
|
if self._console_device_type is not None:
|
||||||
|
self._console_address = os.path.join(self._temp_dir,
|
||||||
|
self._name + "-console.sock")
|
||||||
|
chardev = ('socket,id=console,path=%s,server,nowait' %
|
||||||
|
self._console_address)
|
||||||
|
device = '%s,chardev=console' % self._console_device_type
|
||||||
|
args.extend(['-chardev', chardev, '-device', device])
|
||||||
|
return args
|
||||||
|
|
||||||
def _pre_launch(self):
|
def _pre_launch(self):
|
||||||
self._temp_dir = tempfile.mkdtemp(dir=self._test_dir)
|
self._temp_dir = tempfile.mkdtemp(dir=self._test_dir)
|
||||||
|
@ -202,6 +238,10 @@ class QEMUMachine(object):
|
||||||
|
|
||||||
self._qemu_log_path = None
|
self._qemu_log_path = None
|
||||||
|
|
||||||
|
if self._console_socket is not None:
|
||||||
|
self._console_socket.close()
|
||||||
|
self._console_socket = None
|
||||||
|
|
||||||
if self._temp_dir is not None:
|
if self._temp_dir is not None:
|
||||||
shutil.rmtree(self._temp_dir)
|
shutil.rmtree(self._temp_dir)
|
||||||
self._temp_dir = None
|
self._temp_dir = None
|
||||||
|
@ -365,3 +405,58 @@ class QEMUMachine(object):
|
||||||
Adds to the list of extra arguments to be given to the QEMU binary
|
Adds to the list of extra arguments to be given to the QEMU binary
|
||||||
'''
|
'''
|
||||||
self._args.extend(args)
|
self._args.extend(args)
|
||||||
|
|
||||||
|
def set_machine(self, machine_type):
|
||||||
|
'''
|
||||||
|
Sets the machine type
|
||||||
|
|
||||||
|
If set, the machine type will be added to the base arguments
|
||||||
|
of the resulting QEMU command line.
|
||||||
|
'''
|
||||||
|
self._machine = machine_type
|
||||||
|
|
||||||
|
def set_console(self, device_type=None):
|
||||||
|
'''
|
||||||
|
Sets the device type for a console device
|
||||||
|
|
||||||
|
If set, the console device and a backing character device will
|
||||||
|
be added to the base arguments of the resulting QEMU command
|
||||||
|
line.
|
||||||
|
|
||||||
|
This is a convenience method that will either use the provided
|
||||||
|
device type, of if not given, it will used the device type set
|
||||||
|
on CONSOLE_DEV_TYPES.
|
||||||
|
|
||||||
|
The actual setting of command line arguments will be be done at
|
||||||
|
machine launch time, as it depends on the temporary directory
|
||||||
|
to be created.
|
||||||
|
|
||||||
|
@param device_type: the device type, such as "isa-serial"
|
||||||
|
@raises: QEMUMachineAddDeviceError if the device type is not given
|
||||||
|
and can not be determined.
|
||||||
|
'''
|
||||||
|
if device_type is None:
|
||||||
|
if self._machine is None:
|
||||||
|
raise QEMUMachineAddDeviceError("Can not add a console device:"
|
||||||
|
" QEMU instance without a "
|
||||||
|
"defined machine type")
|
||||||
|
for regex, device in CONSOLE_DEV_TYPES.items():
|
||||||
|
if re.match(regex, self._machine):
|
||||||
|
device_type = device
|
||||||
|
break
|
||||||
|
if device_type is None:
|
||||||
|
raise QEMUMachineAddDeviceError("Can not add a console device:"
|
||||||
|
" no matching console device "
|
||||||
|
"type definition")
|
||||||
|
self._console_device_type = device_type
|
||||||
|
|
||||||
|
@property
|
||||||
|
def console_socket(self):
|
||||||
|
"""
|
||||||
|
Returns a socket connected to the console
|
||||||
|
"""
|
||||||
|
if self._console_socket is None:
|
||||||
|
self._console_socket = socket.socket(socket.AF_UNIX,
|
||||||
|
socket.SOCK_STREAM)
|
||||||
|
self._console_socket.connect(self._console_address)
|
||||||
|
return self._console_socket
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue