26ba25
From 99213f4ec15e0f5d1c5cae562e1010091da4a66e Mon Sep 17 00:00:00 2001
26ba25
From: Yash Mankad <ymankad@redhat.com>
26ba25
Date: Wed, 12 Dec 2018 00:14:38 +0000
26ba25
Subject: [PATCH 10/13] scripts/qemu.py: introduce set_console() method
26ba25
MIME-Version: 1.0
26ba25
Content-Type: text/plain; charset=UTF-8
26ba25
Content-Transfer-Encoding: 8bit
26ba25
26ba25
RH-Author: Yash Mankad <ymankad@redhat.com>
26ba25
Message-id: <76ce1001806fed23760f7c02b8e8472d793ef8b1.1544573601.git.ymankad@redhat.com>
26ba25
Patchwork-id: 83435
26ba25
O-Subject: [RHEL-8.0 qemu-kvm PATCH v2 4/7] scripts/qemu.py: introduce set_console() method
26ba25
Bugzilla: 1655807
26ba25
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
26ba25
RH-Acked-by: John Snow <jsnow@redhat.com>
26ba25
RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
26ba25
26ba25
From: Cleber Rosa <crosa@redhat.com>
26ba25
26ba25
The set_console() method is intended to ease higher level use cases
26ba25
that require a console device.
26ba25
26ba25
The amount of intelligence is limited on purpose, requiring either the
26ba25
device type explicitly, or the existence of a machine (pattern)
26ba25
definition.
26ba25
26ba25
Because of the console device type selection criteria (by machine
26ba25
type), users should also be able to define that.  It'll then be used
26ba25
for both '-machine' and for the console device type selection.
26ba25
26ba25
Users of the set_console() method will certainly be interested in
26ba25
accessing the console device, and for that a console_socket property
26ba25
has been added.
26ba25
26ba25
Signed-off-by: Cleber Rosa <crosa@redhat.com>
26ba25
Message-Id: <20180530184156.15634-5-crosa@redhat.com>
26ba25
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
26ba25
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
26ba25
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
26ba25
(cherry picked from commit 22dea9db2baf72a79782c748c57e2d87b06234d5)
26ba25
Signed-off-by: Yash Mankad <ymankad@redhat.com>
26ba25
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
26ba25
---
26ba25
 scripts/qemu.py | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
26ba25
 1 file changed, 96 insertions(+), 1 deletion(-)
26ba25
26ba25
diff --git a/scripts/qemu.py b/scripts/qemu.py
26ba25
index 7cd8193..f099ce7 100644
26ba25
--- a/scripts/qemu.py
26ba25
+++ b/scripts/qemu.py
26ba25
@@ -17,19 +17,41 @@ import logging
26ba25
 import os
26ba25
 import subprocess
26ba25
 import qmp.qmp
26ba25
+import re
26ba25
 import shutil
26ba25
+import socket
26ba25
 import tempfile
26ba25
 
26ba25
 
26ba25
 LOG = logging.getLogger(__name__)
26ba25
 
26ba25
 
26ba25
+#: Maps machine types to the preferred console device types
26ba25
+CONSOLE_DEV_TYPES = {
26ba25
+    r'^clipper$': 'isa-serial',
26ba25
+    r'^malta': 'isa-serial',
26ba25
+    r'^(pc.*|q35.*|isapc)$': 'isa-serial',
26ba25
+    r'^(40p|powernv|prep)$': 'isa-serial',
26ba25
+    r'^pseries.*': 'spapr-vty',
26ba25
+    r'^s390-ccw-virtio.*': 'sclpconsole',
26ba25
+    }
26ba25
+
26ba25
+
26ba25
 class QEMUMachineError(Exception):
26ba25
     """
26ba25
     Exception called when an error in QEMUMachine happens.
26ba25
     """
26ba25
 
26ba25
 
26ba25
+class QEMUMachineAddDeviceError(QEMUMachineError):
26ba25
+    """
26ba25
+    Exception raised when a request to add a device can not be fulfilled
26ba25
+
26ba25
+    The failures are caused by limitations, lack of information or conflicting
26ba25
+    requests on the QEMUMachine methods.  This exception does not represent
26ba25
+    failures reported by the QEMU binary itself.
26ba25
+    """
26ba25
+
26ba25
 class MonitorResponseError(qmp.qmp.QMPError):
26ba25
     '''
26ba25
     Represents erroneous QMP monitor reply
26ba25
@@ -91,6 +113,10 @@ class QEMUMachine(object):
26ba25
         self._test_dir = test_dir
26ba25
         self._temp_dir = None
26ba25
         self._launched = False
26ba25
+        self._machine = None
26ba25
+        self._console_device_type = None
26ba25
+        self._console_address = None
26ba25
+        self._console_socket = None
26ba25
 
26ba25
         # just in case logging wasn't configured by the main script:
26ba25
         logging.basicConfig()
26ba25
@@ -175,9 +201,19 @@ class QEMUMachine(object):
26ba25
                 self._monitor_address[1])
26ba25
         else:
26ba25
             moncdev = 'socket,id=mon,path=%s' % self._vm_monitor
26ba25
-        return ['-chardev', moncdev,
26ba25
+        args = ['-chardev', moncdev,
26ba25
                 '-mon', 'chardev=mon,mode=control',
26ba25
                 '-display', 'none', '-vga', 'none']
26ba25
+        if self._machine is not None:
26ba25
+            args.extend(['-machine', self._machine])
26ba25
+        if self._console_device_type is not None:
26ba25
+            self._console_address = os.path.join(self._temp_dir,
26ba25
+                                                 self._name + "-console.sock")
26ba25
+            chardev = ('socket,id=console,path=%s,server,nowait' %
26ba25
+                       self._console_address)
26ba25
+            device = '%s,chardev=console' % self._console_device_type
26ba25
+            args.extend(['-chardev', chardev, '-device', device])
26ba25
+        return args
26ba25
 
26ba25
     def _pre_launch(self):
26ba25
         self._temp_dir = tempfile.mkdtemp(dir=self._test_dir)
26ba25
@@ -202,6 +238,10 @@ class QEMUMachine(object):
26ba25
 
26ba25
         self._qemu_log_path = None
26ba25
 
26ba25
+        if self._console_socket is not None:
26ba25
+            self._console_socket.close()
26ba25
+            self._console_socket = None
26ba25
+
26ba25
         if self._temp_dir is not None:
26ba25
             shutil.rmtree(self._temp_dir)
26ba25
             self._temp_dir = None
26ba25
@@ -365,3 +405,58 @@ class QEMUMachine(object):
26ba25
         Adds to the list of extra arguments to be given to the QEMU binary
26ba25
         '''
26ba25
         self._args.extend(args)
26ba25
+
26ba25
+    def set_machine(self, machine_type):
26ba25
+        '''
26ba25
+        Sets the machine type
26ba25
+
26ba25
+        If set, the machine type will be added to the base arguments
26ba25
+        of the resulting QEMU command line.
26ba25
+        '''
26ba25
+        self._machine = machine_type
26ba25
+
26ba25
+    def set_console(self, device_type=None):
26ba25
+        '''
26ba25
+        Sets the device type for a console device
26ba25
+
26ba25
+        If set, the console device and a backing character device will
26ba25
+        be added to the base arguments of the resulting QEMU command
26ba25
+        line.
26ba25
+
26ba25
+        This is a convenience method that will either use the provided
26ba25
+        device type, of if not given, it will used the device type set
26ba25
+        on CONSOLE_DEV_TYPES.
26ba25
+
26ba25
+        The actual setting of command line arguments will be be done at
26ba25
+        machine launch time, as it depends on the temporary directory
26ba25
+        to be created.
26ba25
+
26ba25
+        @param device_type: the device type, such as "isa-serial"
26ba25
+        @raises: QEMUMachineAddDeviceError if the device type is not given
26ba25
+                 and can not be determined.
26ba25
+        '''
26ba25
+        if device_type is None:
26ba25
+            if self._machine is None:
26ba25
+                raise QEMUMachineAddDeviceError("Can not add a console device:"
26ba25
+                                                " QEMU instance without a "
26ba25
+                                                "defined machine type")
26ba25
+            for regex, device in CONSOLE_DEV_TYPES.items():
26ba25
+                if re.match(regex, self._machine):
26ba25
+                    device_type = device
26ba25
+                    break
26ba25
+            if device_type is None:
26ba25
+                raise QEMUMachineAddDeviceError("Can not add a console device:"
26ba25
+                                                " no matching console device "
26ba25
+                                                "type definition")
26ba25
+        self._console_device_type = device_type
26ba25
+
26ba25
+    @property
26ba25
+    def console_socket(self):
26ba25
+        """
26ba25
+        Returns a socket connected to the console
26ba25
+        """
26ba25
+        if self._console_socket is None:
26ba25
+            self._console_socket = socket.socket(socket.AF_UNIX,
26ba25
+                                                 socket.SOCK_STREAM)
26ba25
+            self._console_socket.connect(self._console_address)
26ba25
+        return self._console_socket
26ba25
-- 
26ba25
1.8.3.1
26ba25