From fc84cd5d479f164cf34ec33b70e75f917489ac30 Mon Sep 17 00:00:00 2001 From: Guido Trotter <ultrotter@google.com> Date: Thu, 8 Dec 2011 13:28:32 +0000 Subject: [PATCH] kvm: make qmp connections more robust Currently qmp fails at connect() time if there are socket errors. (eg. if the instance was started without qmp). Add some better checking. Also in the only place where we use it avoid hiding the error connecting to the socket as a failure to read the password file. In addition one variable is renamed because its name now conflicts with the newly imported stat module. Signed-off-by: Guido Trotter <ultrotter@google.com> Reviewed-by: Iustin Pop <iustin@google.com> --- lib/hypervisor/hv_kvm.py | 45 +++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/lib/hypervisor/hv_kvm.py b/lib/hypervisor/hv_kvm.py index b0f6724e4..1e51c3547 100644 --- a/lib/hypervisor/hv_kvm.py +++ b/lib/hypervisor/hv_kvm.py @@ -35,6 +35,7 @@ import struct import fcntl import shutil import socket +import stat import StringIO try: import affinity # pylint: disable=F0401 @@ -226,6 +227,19 @@ class QmpConnection: self._connected = False self._buf = "" + def _check_socket(self): + sock_stat = None + try: + sock_stat = os.stat(self.monitor_filename) + except EnvironmentError, err: + if err.errno == errno.ENOENT: + raise errors.HypervisorError("No qmp socket found") + else: + raise errors.HypervisorError("Error checking qmp socket: %s", + utils.ErrnoOrStr(err)) + if not stat.S_ISSOCK(sock_stat.st_mode): + raise errors.HypervisorError("Qmp socket is not a socket") + def _check_connection(self): """Make sure that the connection is established. @@ -244,7 +258,16 @@ class QmpConnection: @raise errors.ProgrammerError: when there are data serialization errors """ - self.sock.connect(self.monitor_filename) + if self._connected: + raise errors.ProgrammerError("Cannot connect twice") + + self._check_socket() + + # Check file existance/stuff + try: + self.sock.connect(self.monitor_filename) + except EnvironmentError: + raise errors.HypervisorError("Can't connect to qmp socket") self._connected = True # Check if we receive a correct greeting message from the server @@ -890,10 +913,10 @@ class KVMHypervisor(hv_base.BaseHypervisor): return None _, memory, vcpus = self._InstancePidInfo(pid) - stat = "---b-" + istat = "---b-" times = "0" - return (instance_name, pid, memory, vcpus, stat, times) + return (instance_name, pid, memory, vcpus, istat, times) def GetAllInstancesInfo(self): """Get properties of all instances. @@ -1433,19 +1456,21 @@ class KVMHypervisor(hv_base.BaseHypervisor): # for connection. spice_password_file = conf_hvp[constants.HV_KVM_SPICE_PASSWORD_FILE] if spice_password_file: + spice_pwd = "" try: spice_pwd = utils.ReadOneLineFile(spice_password_file, strict=True) - qmp = QmpConnection(self._InstanceQmpMonitor(instance.name)) - qmp.connect() - arguments = { - "protocol": "spice", - "password": spice_pwd, - } - qmp.Execute("set_password", arguments) except EnvironmentError, err: raise errors.HypervisorError("Failed to open SPICE password file %s: %s" % (spice_password_file, err)) + qmp = QmpConnection(self._InstanceQmpMonitor(instance.name)) + qmp.connect() + arguments = { + "protocol": "spice", + "password": spice_pwd, + } + qmp.Execute("set_password", arguments) + for filename in temp_files: utils.RemoveFile(filename) -- GitLab