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(a)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(a)redhat.com>