Change in vdsm[master]: stats: report detailed VM down status

fromani at redhat.com fromani at redhat.com
Sun Dec 22 21:45:33 UTC 2013


Francesco Romani has uploaded a new change for review.

Change subject: stats: report detailed VM down status
......................................................................

stats: report detailed VM down status

When a VM goes down it reports exitCode == 1 (ERROR), and the
exitMessage is passed verbarim to the VM log.

In order to have translatable messages, a more detailed
error code is needed.
This patch introduces a new explicit errorCode value, to be
filled with the detailed status code.

The new detailed value is added separately for backward
compatibility with the existing interface.

Change-Id: I8d7064fe79d1cd34499fbb32ed0644757cbe05dd
Bug-Url: https://bugzilla.redhat.com/557125
Signed-off-by: Francesco Romani <fromani at redhat.com>
---
M lib/vdsm/define.py
M vdsm/vm.py
M vdsm_api/vdsmapi-schema.json
3 files changed, 50 insertions(+), 10 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/31/22631/1

diff --git a/lib/vdsm/define.py b/lib/vdsm/define.py
index df8bbf4..50b65c3 100644
--- a/lib/vdsm/define.py
+++ b/lib/vdsm/define.py
@@ -145,3 +145,10 @@
 #exitCodes
 ERROR = 1
 NORMAL = 0
+
+
+class VMDownErrorCode:
+    Success = 0
+    GenericError = 1
+    LostQEMUConnection = 2
+    LibvirtStartFailed = 3
diff --git a/vdsm/vm.py b/vdsm/vm.py
index 534705d..c34c47c 100644
--- a/vdsm/vm.py
+++ b/vdsm/vm.py
@@ -43,7 +43,7 @@
 from vdsm import utils
 from vdsm import vdscli
 from vdsm.config import config
-from vdsm.define import ERROR, NORMAL, doneCode, errCode
+from vdsm.define import ERROR, NORMAL, doneCode, errCode, VMDownErrorCode
 from vdsm.netinfo import DUMMY_BRIDGE
 from storage import outOfProcess as oop
 from storage import sd
@@ -2116,7 +2116,7 @@
     def _startUnderlyingVm(self):
         self.log.debug("Start")
         try:
-            self.memCommit()
+            self.memCommit()  # can raise: ValueError, ConfigParser.Error
             self._ongoingCreations.acquire()
             self.log.debug("_ongoingCreations acquired")
             self._vmCreationEvent.set()
@@ -2162,7 +2162,7 @@
                 self.log.info("Skipping errors on recovery", exc_info=True)
             else:
                 self.log.error("The vm start process failed", exc_info=True)
-                self.setDownStatus(ERROR, str(e))
+                self.setDownStatus(ERROR, str(e), VMDownErrorCode.GenericError)
 
     def _incomingMigrationPending(self):
         return 'migrationDest' in self.conf or 'restoreState' in self.conf
@@ -2184,6 +2184,7 @@
                     # A destroy request has been issued, exit early
                     break
                 drive['path'] = self.cif.prepareVolumePath(drive, self.id)
+                # can raise: VolumeError
             if drive['device'] == 'disk' and isVdsmImage(drive):
                 domains.append(drive['domainID'])
         else:
@@ -2206,7 +2207,8 @@
             elif self.user_destroy:
                 self.setDownStatus(NORMAL, 'User shut down')
             else:
-                self.setDownStatus(ERROR, "Lost connection with qemu process")
+                self.setDownStatus(ERROR, "Lost connection with qemu process",
+                                   VMDownErrorCode.LostQEMUConnection)
 
     def _loadCorrectedTimeout(self, base, doubler=20, load=None):
         """
@@ -2604,7 +2606,8 @@
 
         utils.rmFile(self._guestSocketFile)
 
-    def setDownStatus(self, code, reason):
+    def setDownStatus(self, code, reason,
+                      errorCode=VMDownErrorCode.GenericError):
         try:
             self.lastStatus = 'Down'
             with self._confLock:
@@ -2614,6 +2617,8 @@
                         "Wake up from hibernation failed")
                 else:
                     self.conf['exitMessage'] = reason
+                    if code == ERROR:
+                        self.conf['errorCode'] = errorCode
             self.log.debug("Changed state to Down: " + reason)
         except DoubleDownError:
             pass
@@ -2662,6 +2667,8 @@
             stats['exitMessage'] = self.conf['exitMessage']
             if 'timeOffset' in self.conf:
                 stats['timeOffset'] = self.conf['timeOffset']
+            if 'errorCode' in self.conf:
+                stats['errorCode'] = self.conf['errorCode']
             return stats
 
         stats = {
@@ -2970,9 +2977,10 @@
         self.log.info("VM wrapper has started")
         self.conf['smp'] = self.conf.get('smp', '1')
         devices = self.buildConfDevices()
+        # can raise: ValueError, RuntimeError, ConfigParser.Error
 
         if not 'recover' in self.conf:
-            self.preparePaths(devices[DISK_DEVICES])
+            self.preparePaths(devices[DISK_DEVICES])  # can raise: VolumeError
             self._prepareTransientDisks(devices[DISK_DEVICES])
             # Update self.conf with updated devices
             # For old type vmParams, new 'devices' key will be
@@ -2988,7 +2996,7 @@
             # saving we will fail in inconsistent state during recovery.
             # So, to get proper device objects during VM recovery flow
             # we must to have updated conf before VM run
-            self.saveState()
+            self.saveState()  # can raise: OSError, IOError
         else:
             for drive in devices[DISK_DEVICES]:
                 if drive['device'] == 'disk' and isVdsmImage(drive):
@@ -3006,13 +3014,14 @@
             return
         if not 'recover' in self.conf:
             domxml = hooks.before_vm_start(self._buildCmdLine(), self.conf)
+            # can raise: HookError
             self.log.debug(domxml)
         if 'recover' in self.conf:
             self._dom = NotifyingVirDomain(
                 self._connection.lookupByUUIDString(self.id),
                 self._timeoutExperienced)
             # Reinitialize the merge statuses
-            self._checkMerge()
+            self._checkMerge()  # can raise: OSError, IOError
         elif 'restoreState' in self.conf:
             fromSnapshot = self.conf.get('restoreFromSnapshot', False)
             srcDomXML = self.conf.pop('_srcDomXML')
@@ -3020,6 +3029,7 @@
                 srcDomXML = self._correctDiskVolumes(srcDomXML)
             hooks.before_vm_dehibernate(srcDomXML, self.conf,
                                         {'FROM_SNAPSHOT': str(fromSnapshot)})
+            # can raise: HookError
 
             fname = self.cif.prepareVolumePath(self.conf['restoreState'])
             try:
@@ -3050,7 +3060,8 @@
                                           dev.custom)
 
         if not self._dom:
-            self.setDownStatus(ERROR, 'failed to start libvirt vm')
+            self.setDownStatus(ERROR, 'failed to start libvirt vm',
+                               VMDownErrorCode.LibvirtStartFailed)
             return
         self._domDependentInit()
 
diff --git a/vdsm_api/vdsmapi-schema.json b/vdsm_api/vdsmapi-schema.json
index 77ca409..8a1ee8a 100644
--- a/vdsm_api/vdsmapi-schema.json
+++ b/vdsm_api/vdsmapi-schema.json
@@ -5220,6 +5220,25 @@
 {'enum': 'VmExitCode', 'data': ['NORMAL', 'ERROR']}
 
 ##
+# @VmErrorCode:
+#
+# An enumeration of VM error codes if VM exit status code is ERROR.
+#
+# @success:                 The VM has exited gracefully
+#
+# @generic error:           Unspecified error code.
+#
+# @lost qemu connection:    The VM has lost the connection with QEMU
+#
+# @libvirt start failed:    The VM failed to start thorugh libvirt
+#
+# Since: 4.13.0
+##
+{'enum': 'VmErrorCode',
+ 'data': ['success', 'generic error',
+          'lost qemu connection', 'libvirt start failed']}
+
+##
 # @ExitedVmStats:
 #
 # Statistics about a VM that no longer running.
@@ -5232,11 +5251,14 @@
 #
 # @timeOffset:   #optional The time difference from host to the VM in seconds
 #
+# @errorCode:    #optional The specific error code if the VM is exited
+#                with error (new in version 4.13.0)
+#
 # Since: 4.10.0
 ##
 {'type': 'ExitedVmStats',
  'data': {'exitCode': 'VmExitCode', 'status': 'VmStatus', 'exitMessage': 'str',
-          '*timeOffset': 'int'}}
+          '*timeOffset': 'int', '*errorCode': 'VmErrorCode'}}
 
 ##
 # @VmDiskStats:


-- 
To view, visit http://gerrit.ovirt.org/22631
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I8d7064fe79d1cd34499fbb32ed0644757cbe05dd
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Francesco Romani <fromani at redhat.com>


More information about the vdsm-patches mailing list