qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
To: John Snow <jsnow@redhat.com>
Cc: Jonathan Cameron <Jonathan.Cameron@huawei.com>,
	Shiju Jose <shiju.jose@huawei.com>,
	Cleber Rosa <crosa@redhat.com>,
	linux-kernel@vger.kernel.org, qemu-devel@nongnu.org
Subject: Re: [PATCH v5 7/7] scripts/ghes_inject: add a script to generate GHES error inject
Date: Fri, 9 Aug 2024 09:37:18 +0200	[thread overview]
Message-ID: <20240809093718.095d0a34@foz.lan> (raw)
In-Reply-To: <20240809082609.1864eabe@foz.lan>

Em Fri, 9 Aug 2024 08:26:09 +0200
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> escreveu:

> Em Fri, 9 Aug 2024 00:41:37 +0200
> Mauro Carvalho Chehab <mchehab+huawei@kernel.org> escreveu:
> 
> > > You should be able to use e.g.
> > > 
> > > legacy.py's QEMUMonitorProtocol class for synchronous connections, e.g.
> > > 
> > > from qemu.qmp.legacy import QEMUMonitorProtocol
> > > 
> > > qmp = QEMUMonitorProtocol((host, port))
> > > qmp.connect(negotiate=True)  
> > 
> > That sounds interesting! I give it a try.
> 
> I applied the enclosed patch at the end of my patch series, but
> somehow it is not working. For whatever reason, connect() is
> raising a StateError apparently due to Runstate.CONNECTING.
> 
> I tried both as declaring (see enclosed patch):
> 
> 	class qmp(QEMUMonitorProtocol)
> 
> and using:
> 
> -        super().__init__(self.host, self.port)
> +        self.qmp_monitor = QEMUMonitorProtocol(self.host, self.port)
> 
> On both cases, it keeps waiting forever for a connection.

Nevermind, placing host/post on a tuple made it work.

The enclosed patch converts the script to use QEMUMonitorProtocol.

I'll fold it with the script for the next spin of this series.

Regards,
Mauro

---

[PATCH] scripts/qmp_helper.py: use QEMUMonitorProtocol class

Instead of reinventing the wheel, let's use QEMUMonitorProtocol.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

diff --git a/scripts/arm_processor_error.py b/scripts/arm_processor_error.py
index 756935a2263c..f869f07860b8 100644
--- a/scripts/arm_processor_error.py
+++ b/scripts/arm_processor_error.py
@@ -169,14 +169,11 @@ def send_cper(self, args):
         if args.mpidr:
             cper["mpidr-el1"] = arg["mpidr"]
         elif cpus:
-            get_mpidr = {
-                "execute": "qom-get",
-                "arguments": {
-                    'path': cpus[0],
-                    'property': "x-mpidr"
-                }
+            cmd_arg = {
+                'path': cpus[0],
+                'property': "x-mpidr"
             }
-            ret = qmp_cmd.send_cmd(get_mpidr, may_open=True)
+            ret = qmp_cmd.send_cmd("qom-get", cmd_arg, may_open=True)
             if isinstance(ret, int):
                 cper["mpidr-el1"] = ret
             else:
@@ -291,8 +288,7 @@ def send_cper(self, args):
         context_info_num = 0
 
         if ctx:
-            ret = qmp_cmd.send_cmd('{ "execute": "query-target" }',
-                                   may_open=True)
+            ret = qmp_cmd.send_cmd("query-target", may_open=True)
 
             default_ctx = self.CONTEXT_MISC_REG
 
@@ -363,14 +359,11 @@ def send_cper(self, args):
 
         if "midr-el1" not in arg:
             if cpus:
-                get_mpidr = {
-                    "execute": "qom-get",
-                    "arguments": {
-                        'path': cpus[0],
-                        'property': "midr"
-                    }
+                cmd_arg = {
+                    'path': cpus[0],
+                    'property': "midr"
                 }
-                ret = qmp_cmd.send_cmd(get_mpidr, may_open=True)
+                ret = qmp_cmd.send_cmd("qom-get", cmd_arg, may_open=True)
                 if isinstance(ret, int):
                     arg["midr-el1"] = ret
 
diff --git a/scripts/qmp_helper.py b/scripts/qmp_helper.py
index 7214c15c6718..e2e0a881f6c1 100644
--- a/scripts/qmp_helper.py
+++ b/scripts/qmp_helper.py
@@ -9,6 +9,19 @@
 import socket
 import sys
 
+from os import path
+
+try:
+    qemu_dir = path.abspath(path.dirname(path.dirname(__file__)))
+    sys.path.append(path.join(qemu_dir, 'python'))
+
+    from qemu.qmp.legacy import QEMUMonitorProtocol
+
+except ModuleNotFoundError as exc:
+    print(f"Module '{exc.name}' not found.")
+    print("Try export PYTHONPATH=top-qemu-dir/python or run from top-qemu-dir")
+    sys.exit(1)
+
 from base64 import b64encode
 
 class qmp:
@@ -16,26 +29,23 @@ class qmp:
     Opens a connection and send/receive QMP commands.
     """
 
-    def send_cmd(self, command, may_open=False, return_error=True):
+    def send_cmd(self, command, args=None, may_open=False, return_error=True):
         """Send a command to QMP, optinally opening a connection"""
 
         if may_open:
             self._connect()
-        elif not self.socket:
-            return None
+        elif not self.connected:
+            return False
 
-        if isinstance(command, dict):
-            data = json.dumps(command).encode("utf-8")
-        else:
-            data = command.encode("utf-8")
+        msg = { 'execute': command }
+        if args:
+            msg['arguments'] = args
 
-        self.socket.sendall(data)
-        data = self.socket.recv(1024)
         try:
-            obj = json.loads(data.decode("utf-8"))
-        except json.JSONDecodeError as e:
-            print(f"Invalid QMP answer: {e}")
-            self._close()
+            obj = self.qmp_monitor.cmd_obj(msg)
+        except Exception as e:
+            print(f"Command: {command}")
+            print(f"Failed to inject error: {e}.")
             return None
 
         if "return" in obj:
@@ -49,6 +59,7 @@ def send_cmd(self, command, may_open=False, return_error=True):
         elif isinstance(obj.get("error"), dict):
             error = obj["error"]
             if return_error:
+                print(f"Command: {msg}")
                 print(f'{error["class"]}: {error["desc"]}')
         else:
             print(json.dumps(obj))
@@ -57,75 +68,37 @@ def send_cmd(self, command, may_open=False, return_error=True):
 
     def _close(self):
         """Shutdown and close the socket, if opened"""
-        if not self.socket:
+        if not self.connected:
             return
 
-        self.socket.shutdown(socket.SHUT_WR)
-        while 1:
-            data = self.socket.recv(1024)
-            if data == b"":
-                break
-            try:
-                obj = json.loads(data.decode("utf-8"))
-            except json.JSONDecodeError as e:
-                print(f"Invalid QMP answer: {e}")
-                self.socket.close()
-                self.socket = None
-                return
-
-            if isinstance(obj.get("return"), dict):
-                print(json.dumps(obj["return"]))
-            if isinstance(obj.get("error"), dict):
-                error = obj["error"]
-                print(f'{error["class"]}: {error["desc"]}')
-            else:
-                print(json.dumps(obj))
-
-        self.socket.close()
-        self.socket = None
+        self.qmp_monitor.close()
+        self.connected = False
 
     def _connect(self):
         """Connect to a QMP TCP/IP port, if not connected yet"""
 
-        if self.socket:
+        if self.connected:
             return True
 
-        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
         try:
-            self.socket.connect((self.host, self.port))
-        except ConnectionRefusedError:
+            ret = self.qmp_monitor.connect(negotiate=True)
+        except ConnectionError:
             sys.exit(f"Can't connect to QMP host {self.host}:{self.port}")
-
-        data = self.socket.recv(1024)
-        try:
-            obj = json.loads(data.decode("utf-8"))
-        except json.JSONDecodeError as e:
-            print(f"Invalid QMP answer: {e}")
-            self._close()
             return False
 
-        if "QMP" not in obj:
-            print(f"Invalid QMP answer: {data.decode('utf-8')}")
-            self._close()
-            return False
-
-        result = self.send_cmd('{ "execute": "qmp_capabilities" }')
-        if not result:
-            self._close()
-            return False
+        self.connected = True
 
         return True
 
     def __init__(self, host, port, debug=False):
         """Initialize variables used by the QMP send logic"""
 
-        self.socket = None
+        self.connected = False
         self.host = host
         self.port = port
         self.debug = debug
 
-    def __del__(self):
-        self._close()
+        self.qmp_monitor = QEMUMonitorProtocol(address=(self.host, self.port))
 
     #
     # Socket QMP send command
@@ -142,9 +115,6 @@ def send_cper(self, guid, data):
             }
         }
 
-        command = '{ "execute": "ghes-cper", '
-        command += '"arguments": ' + json.dumps(cmd_arg) + " }"
-
         if self.debug:
             print(f"GUID: {guid}")
             print("CPER:")
@@ -168,7 +138,7 @@ def send_cper(self, guid, data):
 
         self._connect()
 
-        if self.send_cmd(command):
+        if self.send_cmd("ghes-cper", cmd_arg):
             print("Error injected.")
 
     def search_qom(self, path, prop, regex):
@@ -185,14 +155,11 @@ def search_qom(self, path, prop, regex):
         i = 0
         while 1:
             dev = f"{path}[{i}]"
-            cmd =  {
-                "execute": "qom-get",
-                "arguments": {
-                    'path': dev,
-                    'property': prop
-                }
+            args = {
+                'path': dev,
+                'property': prop
             }
-            ret = self.send_cmd(cmd, may_open=True, return_error=False)
+            ret = self.send_cmd("qom-get", args, may_open=True, return_error=False)
             if not ret:
                 break
 



      reply	other threads:[~2024-08-09  7:38 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-02 21:43 [PATCH v5 0/7] Add ACPI CPER firmware first error injection on ARM emulation Mauro Carvalho Chehab
2024-08-02 21:43 ` [PATCH v5 1/7] arm/virt: place power button pin number on a define Mauro Carvalho Chehab
2024-08-06  8:57   ` Igor Mammedov
2024-08-02 21:43 ` [PATCH v5 2/7] acpi/generic_event_device: add an APEI error device Mauro Carvalho Chehab
2024-08-05 16:39   ` Jonathan Cameron via
2024-08-06  5:50     ` Mauro Carvalho Chehab
2024-08-06  8:54   ` Igor Mammedov
2024-08-02 21:43 ` [PATCH v5 3/7] arm/virt: Wire up GPIO error source for ACPI / GHES Mauro Carvalho Chehab
2024-08-05 16:54   ` Jonathan Cameron via
2024-08-06  5:56     ` Mauro Carvalho Chehab
2024-08-06  9:15   ` Igor Mammedov
2024-08-02 21:43 ` [PATCH v5 4/7] acpi/ghes: Support GPIO error source Mauro Carvalho Chehab
2024-08-05 16:56   ` Jonathan Cameron via
2024-08-06  6:09     ` Mauro Carvalho Chehab
2024-08-06  9:18       ` Igor Mammedov
2024-08-06  9:32   ` Igor Mammedov
2024-08-07  7:15     ` Mauro Carvalho Chehab
2024-08-02 21:44 ` [PATCH v5 5/7] qapi/ghes-cper: add an interface to do generic CPER error injection Mauro Carvalho Chehab
2024-08-05 17:00   ` Jonathan Cameron via
2024-08-06  9:15   ` Shiju Jose via
2024-08-06 12:51   ` Igor Mammedov
2024-08-06 12:58     ` Mauro Carvalho Chehab
2024-08-08  8:50   ` Markus Armbruster
2024-08-08 14:11     ` Mauro Carvalho Chehab
2024-08-08 14:22       ` Igor Mammedov
2024-08-08 14:45         ` Markus Armbruster
2024-08-09  8:42           ` Mauro Carvalho Chehab
2024-08-02 21:44 ` [PATCH v5 6/7] acpi/ghes: add support for generic error injection via QAPI Mauro Carvalho Chehab
2024-08-05 17:03   ` Jonathan Cameron via
2024-08-06 11:13   ` Shiju Jose via
2024-08-06 14:31   ` Igor Mammedov
2024-08-07  7:47     ` Mauro Carvalho Chehab
2024-08-07  9:34       ` Jonathan Cameron via
2024-08-07 13:23         ` Mauro Carvalho Chehab
2024-08-07 13:43           ` Igor Mammedov
2024-08-07 13:28         ` Igor Mammedov
2024-08-07 14:25     ` Jonathan Cameron via
2024-08-08  8:11       ` Igor Mammedov
2024-08-08 18:19         ` Mauro Carvalho Chehab
2024-08-12  9:39           ` Igor Mammedov
2024-08-13 18:59             ` Mauro Carvalho Chehab
2024-08-08 12:11     ` Mauro Carvalho Chehab
2024-08-08 12:45       ` Igor Mammedov
2024-08-02 21:44 ` [PATCH v5 7/7] scripts/ghes_inject: add a script to generate GHES error inject Mauro Carvalho Chehab
2024-08-06 14:56   ` Igor Mammedov
2024-08-08 20:58   ` John Snow
2024-08-08 21:51     ` Mauro Carvalho Chehab
2024-08-08 21:21   ` John Snow
2024-08-08 22:41     ` Mauro Carvalho Chehab
2024-08-08 23:33       ` John Snow
2024-08-09  8:24         ` Mauro Carvalho Chehab
2024-08-09 19:26           ` John Snow
2024-08-09  6:26       ` Mauro Carvalho Chehab
2024-08-09  7:37         ` Mauro Carvalho Chehab [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240809093718.095d0a34@foz.lan \
    --to=mchehab+huawei@kernel.org \
    --cc=Jonathan.Cameron@huawei.com \
    --cc=crosa@redhat.com \
    --cc=jsnow@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=qemu-devel@nongnu.org \
    --cc=shiju.jose@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).