On Mon, Apr 7, 2014 at 3:37 PM, Apollon Oikonomopoulos <[email protected]>wrote:

> According to the QEMU Machine Protocol Specification, the messages sent
> by QMP as a response to a command can be of two types: either an error
> message (identified by the "error" key), or a success message
> (identified by the "return" key).
>
> Since we explicitly handle errors by raising a HypervisorError, there is
> no reason to return the whole response message; instead we return only
> the response part, which is the dual behavior of accepting commands from
> the callers without the surrounding {"execute": ...} object.
>
> We also unexport the RETURN_KEY constant, which is now only used
> internally.
>
> Signed-off-by: Apollon Oikonomopoulos <[email protected]>
> ---
>  lib/hypervisor/hv_kvm/__init__.py            |  4 ++--
>  lib/hypervisor/hv_kvm/monitor.py             | 18 ++++++++++++------
>  test/py/ganeti.hypervisor.hv_kvm_unittest.py | 15 ++++++++-------
>  3 files changed, 22 insertions(+), 15 deletions(-)
>
> diff --git a/lib/hypervisor/hv_kvm/__init__.py
> b/lib/hypervisor/hv_kvm/__init__.py
> index 227dafd..496bc6b 100644
> --- a/lib/hypervisor/hv_kvm/__init__.py
> +++ b/lib/hypervisor/hv_kvm/__init__.py
> @@ -856,10 +856,10 @@ class KVMHypervisor(hv_base.BaseHypervisor):
>      try:
>        qmp = QmpConnection(self._InstanceQmpMonitor(instance_name))
>        qmp.connect()
> -      vcpus = len(qmp.Execute("query-cpus")[qmp.RETURN_KEY])
> +      vcpus = len(qmp.Execute("query-cpus"))
>        # Will fail if ballooning is not enabled, but we can then just
> resort to
>        # the value above.
> -      mem_bytes =
> qmp.Execute("query-balloon")[qmp.RETURN_KEY][qmp.ACTUAL_KEY]
> +      mem_bytes = qmp.Execute("query-balloon")[qmp.ACTUAL_KEY]
>        memory = mem_bytes / 1048576
>      except errors.HypervisorError:
>        pass
> diff --git a/lib/hypervisor/hv_kvm/monitor.py
> b/lib/hypervisor/hv_kvm/monitor.py
> index 8176a41..b93cacd 100644
> --- a/lib/hypervisor/hv_kvm/monitor.py
> +++ b/lib/hypervisor/hv_kvm/monitor.py
> @@ -189,7 +189,7 @@ class QmpConnection(MonitorSocket):
>    _FIRST_MESSAGE_KEY = "QMP"
>    _EVENT_KEY = "event"
>    _ERROR_KEY = "error"
> -  _RETURN_KEY = RETURN_KEY = "return"
> +  _RETURN_KEY = "return"
>    _ACTUAL_KEY = ACTUAL_KEY = "actual"
>    _ERROR_CLASS_KEY = "class"
>    _ERROR_DESC_KEY = "desc"
> @@ -339,7 +339,7 @@ class QmpConnection(MonitorSocket):
>
>      """
>      result = self.Execute(self._QUERY_COMMANDS)
> -    return frozenset(com["name"] for com in result[self._RETURN_KEY])
> +    return frozenset(com["name"] for com in result)
>
>    def Execute(self, command, arguments=None):
>      """Executes a QMP command and returns the response of the server.
> @@ -368,8 +368,11 @@ class QmpConnection(MonitorSocket):
>        message[self._ARGUMENTS_KEY] = arguments
>      self._Send(message)
>
> -    # Events can occur between the sending of the command and the
> reception
> -    # of the response, so we need to filter out messages with the event
> key.
> +    # According the the QMP specification, there are only two reply types
> to a
> +    # command: either error (containing the "error" key) or success
> (containing
> +    # the "return" key). There is also a third possibility, that of an
> +    # (unrelated to the command) asynchronous event notification,
> identified by
> +    # the "event" key.
>      while True:
>        response = self._Recv()
>        err = response[self._ERROR_KEY]
> @@ -380,5 +383,8 @@ class QmpConnection(MonitorSocket):
>                                        err[self._ERROR_DESC_KEY],
>                                        err[self._ERROR_CLASS_KEY]))
>
> -      elif not response[self._EVENT_KEY]:
> -        return response
> +      elif response[self._EVENT_KEY]:
> +        # Filter-out any asynchronous events
> +        continue
> +
> +      return response[self._RETURN_KEY]
> diff --git a/test/py/ganeti.hypervisor.hv_kvm_unittest.py b/test/py/
> ganeti.hypervisor.hv_kvm_unittest.py
> index bc153ba..aebf1f6 100755
> --- a/test/py/ganeti.hypervisor.hv_kvm_unittest.py
> +++ b/test/py/ganeti.hypervisor.hv_kvm_unittest.py
> @@ -189,10 +189,10 @@ class TestQmp(testutils.GanetiTestCase):
>        ]
>
>      expected_responses = [
> -      {"return": {"enabled": True, "present": True}},
> -      {"return": {}},
> -      {"return": [{"name": "quit"}, {"name": "eject"}]},
> -      {"return": {"running": True, "singlestep": False}},
> +      {"enabled": True, "present": True},
> +      {},
> +      [{"name": "quit"}, {"name": "eject"}],
> +      {"running": True, "singlestep": False},
>        ]
>
>      # Set up the stub
> @@ -207,11 +207,12 @@ class TestQmp(testutils.GanetiTestCase):
>
>      # Format the script
>      for request, expected_response in zip(requests, expected_responses):
> -      response = qmp_connection.Execute(request)
> -      msg = hv_kvm.QmpMessage(expected_response)
> +      response = qmp_connection.Execute(request["execute"],
> +                                        request["arguments"])
> +      self.assertEqual(response, expected_response)
> +      msg = hv_kvm.QmpMessage({"return": expected_response})
>        self.assertEqual(len(str(msg).splitlines()), 1,
>                         msg="Got multi-line message")
> -      self.assertEqual(response, msg)
>
>      self.assertRaises(monitor.QmpCommandNotSupported,
>                        qmp_connection.Execute,
> --
> 1.9.1
>
>
LGTM, thanks.



-- 
Thomas Thrainer | Software Engineer | [email protected] |

Google Germany GmbH
Dienerstr. 12
80331 München

Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg
Geschäftsführer: Graham Law, Christine Elizabeth Flores

Reply via email to