Change in vdsm[master]: virt: stats: move last fields the static group
by fromani@redhat.com
Francesco Romani has uploaded a new change for review.
Change subject: virt: stats: move last fields the static group
......................................................................
virt: stats: move last fields the static group
WRITEME
Change-Id: I469759b86115d80bad62c3449fe9084d5f2e550b
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
M vdsm/virt/vm.py
1 file changed, 3 insertions(+), 3 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/57/26557/1
diff --git a/vdsm/virt/vm.py b/vdsm/virt/vm.py
index bbd47dd..84527b9 100644
--- a/vdsm/virt/vm.py
+++ b/vdsm/virt/vm.py
@@ -2413,9 +2413,6 @@
self._addBalloonInfoStats(stats)
self._addMigrationVmStats(stats)
- stats['hash'] = self._devXmlHash
- if self._watchdogEvent:
- stats["watchdogEvent"] = self._watchdogEvent
return stats
def _addExitedVmStats(self, stats):
@@ -2447,6 +2444,9 @@
stats['clientIp'] = self.conf.get('clientIp', '')
if 'pauseCode' in self.conf:
stats['pauseCode'] = self.conf['pauseCode']
+ stats['hash'] = self._devXmlHash
+ if self._watchdogEvent:
+ stats['watchdogEvent'] = self._watchdogEvent
def _addDynamicVmStats(self, stats):
decStats = {}
--
To view, visit http://gerrit.ovirt.org/26557
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I469759b86115d80bad62c3449fe9084d5f2e550b
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Francesco Romani <fromani(a)redhat.com>
10 years
Change in vdsm[master]: [WIP] VDSM <=> Engine data optimization
by Vinzenz Feenstra
Vinzenz Feenstra has uploaded a new change for review.
Change subject: [WIP] VDSM <=> Engine data optimization
......................................................................
[WIP] VDSM <=> Engine data optimization
Change-Id: Ifa0a7a86a351a8c2d891f22802a95d1fe1bc1df4
Signed-off-by: Vinzenz Feenstra <vfeenstr(a)redhat.com>
---
M vdsm/API.py
M vdsm/BindingXMLRPC.py
M vdsm/vm.py
M vdsm_api/vdsmapi-schema.json
4 files changed, 499 insertions(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/41/14541/1
diff --git a/vdsm/API.py b/vdsm/API.py
index ee72116..ebf331d 100644
--- a/vdsm/API.py
+++ b/vdsm/API.py
@@ -334,6 +334,66 @@
return errCode['noVM']
return v.migrateStatus()
+ def getRuntimeStats(self):
+ """
+ Retrieve runtime statistics for the specific VM
+ """
+ v = self._cif.vmContainer.get(self._UUID)
+ if not v:
+ return errCode['noVM']
+ return {
+ 'status': doneCode,
+ 'runtimeStats': {
+ self._UUID: v.getRuntimeStats().copy()}}
+
+ def getStatus(self):
+ """
+ Retrieve VM status information for the specific VM
+ """
+ v = self._cif.vmContainer.get(self._UUID)
+ if not v:
+ return errCode['noVM']
+ return {
+ 'status': doneCode,
+ 'vmStatus': {
+ self._UUID: v.getStatus().copy()}}
+
+ def getDeviceStats(self):
+ """
+ Retrieve device statistics for the specific VM
+ """
+ v = self._cif.vmcontainer.get(self._uuid)
+ if not v:
+ return errCode['noVM']
+ return {
+ 'status': doneCode,
+ 'deviceStats': {
+ self._UUID: v.getDeviceStats().copy()}}
+
+ def getConfInfo(self):
+ """
+ Retrieve configuration information for the specific VM
+ """
+ v = self._cif.vmcontainer.get(self._uuid)
+ if not v:
+ return errCode['noVM']
+ return {
+ 'status': doneCode,
+ 'info': {
+ self._UUID: v.getInfo().copy()}}
+
+ def getGuestDetails(self):
+ """
+ Retrieve guest information for the specific VM
+ """
+ v = self._cif.vmcontainer.get(self._uuid)
+ if not v:
+ return errCode['noVM']
+ return {
+ 'status': doneCode,
+ 'guestDetails': {
+ self._UUID: v.getGuestDetails().copy()}}
+
def getStats(self):
"""
Obtain statistics of the specified VM
diff --git a/vdsm/BindingXMLRPC.py b/vdsm/BindingXMLRPC.py
index 9a4db12..912018c 100644
--- a/vdsm/BindingXMLRPC.py
+++ b/vdsm/BindingXMLRPC.py
@@ -314,6 +314,52 @@
vm = API.VM(vmId)
return vm.getStats()
+ def vmGetRuntimeStats(self, vmIds):
+ result = {}
+ for vmId in vmIds:
+ vm = API.VM(vmId)
+ result.update(vm.getRuntimeStats()['runtimeStats'])
+ return {
+ 'status': doneCode,
+ 'runtimeStats': result}
+
+ def vmGetStatus(self, vmIds):
+ result = {}
+ for vmId in vmIds:
+ vm = API.VM(vmId)
+ result.update(vm.getStatus()['vmStatus'])
+ return {
+ 'status': doneCode,
+ 'vmStatus': result}
+
+ def vmGetAllDeviceStats(self):
+ vms = self.getVMList()
+ result = {}
+ for vm in vms['vmList']:
+ v = API.VM(vm['vmId'])
+ result.update(v.getDeviceStats()['deviceStats'])
+ return {
+ 'status': doneCode,
+ 'deviceStats': result}
+
+ def vmGetConfInfo(self, vmIds):
+ result = {}
+ for vmId in vmIds:
+ vm = API.VM(vmId)
+ result.update(vm.getConfInfo()['vmConfInfo'])
+ return {
+ 'status': doneCode,
+ 'vmConfInfo': result}
+
+ def vmGetGuestDetails(self, vmIds):
+ result = {}
+ for vmId in vmIds:
+ vm = API.VM(vmId)
+ result.update(vm.getGuestDetails()['guestDetails'])
+ return {
+ 'status': doneCode,
+ 'guestDetails': result}
+
def getAllVmStats(self):
"""
Get statistics of all running VMs.
diff --git a/vdsm/vm.py b/vdsm/vm.py
index ddb09c8..6d57649 100644
--- a/vdsm/vm.py
+++ b/vdsm/vm.py
@@ -26,6 +26,7 @@
import tempfile
import pickle
from copy import deepcopy
+import json
from vdsm import utils
from vdsm.define import NORMAL, ERROR, doneCode, errCode
@@ -1115,6 +1116,65 @@
self.conf['status'] = self.lastStatus
return self.conf
+ def _hashObject(self, o):
+ return str(hash(json.dumps(o)))
+
+ def _getHashes(self, stats):
+ return {
+ 'info': self._hashObject(self._getInfo(stats)),
+ 'status': self._hashObject(self._getStatus(stats)),
+ 'guestDetals': self._hashObject(self._getGuestDetails(stats))}
+
+ def _extractKeys(self, dictObject, keys):
+ extracted = {}
+ for k in keys:
+ v = dictObject.get(k)
+ if v:
+ extracted[k] = v
+ return extracted
+
+ def getRuntimeStats(self):
+ allStats = self.getStats()
+ USED_KEYS = ('cpuSys', 'cpuUser', 'memUsage', 'elapsedTime', 'status',
+ 'statsAge')
+ stats = self._extractKeys(allStats, USED_KEYS)
+ stats['hashes'] = self._getHashes(allStats)
+ if 'hash' in allStats:
+ stats['hashes']['config'] = allStats['hash']
+ return stats
+
+ def _getStatus(self, stats):
+ USED_KEYS = ('timeOffset', 'monitorResponse', 'clientIp', 'lastLogin',
+ 'username', 'session', 'guestIPs')
+ return self._extractKeys(stats, USED_KEYS)
+
+ def getStatus(self):
+ return self._getStatus(self.getStats())
+
+ def _getDeviceStats(self, stats):
+ USED_KEYS = ('network', 'disks', 'disksUsage', 'balloonInfo',
+ 'memoryStats')
+ return self._extractKeys(stats, USED_KEYS)
+
+ def getDeviceStats(self):
+ return self._getDeviceStats(self.getStats())
+
+ def _getInfo(self, stats):
+ USED_KEYS = ('acpiEnable', 'vmType', 'guestName', 'guestOS',
+ 'kvmEnable', 'pauseCode', 'displayIp', 'displayPort',
+ 'displaySecurePort', 'pid')
+ return self._extractKeys(stats, USED_KEYS)
+
+ def getInfo(self):
+ return self._getInfo(self.getStats())
+
+ def _getGuestDetails(self, stats):
+ USED_KEYS = ('appList', 'netIfaces')
+ return self._extractKeys(stats, USED_KEYS)
+
+ def getGuestDetails(self):
+ return self._getGuestDetails(self.getStats())
+
def getStats(self):
# used by API.Vm.getStats
diff --git a/vdsm_api/vdsmapi-schema.json b/vdsm_api/vdsmapi-schema.json
index 4ff8c7a..33be905 100644
--- a/vdsm_api/vdsmapi-schema.json
+++ b/vdsm_api/vdsmapi-schema.json
@@ -4850,6 +4850,339 @@
'data': {'vmID': 'UUID'},
'returns': 'VmDefinition'}
+##
+# @VmRuntimeStatsHashes:
+#
+# Hashes of several statistics and information around VMs
+#
+# @info: Hash for VmConfInfo data
+#
+# @config: Hash of the VM configuration XML
+#
+# @status: Hash of the VmStatusInfo data
+#
+# @guestDetails: Hash of the VmGuestDetails data
+#
+# Since: 4.10.3
+##
+{ 'type': 'VmRuntimeStatsHashes',
+ 'data': { 'info': 'str', 'config': 'str', 'status': 'str',
+ 'guestDetails': 'str'}}
+
+##
+# @VmRuntimeStats:
+#
+# Frequently changed and required data around VMs
+#
+# @cpuSys: Ratio of CPU time spent by qemu on other than guest time
+#
+# @cpuUser: Ratio of CPU time spent by the guest VM
+#
+# @memUsage: The percent of memory in use by the guest
+#
+# @elapsedTime: The number of seconds that the VM has been running
+#
+# @status: The current status of the given VM
+#
+# @statsAge: The age of these statistics in seconds
+#
+# @hashes: Hashes of several statistics and information around VMs
+#
+# Since: 4.10.3
+##
+{ 'type': 'VmRuntimeStats',
+ 'data': { 'cpuSys': 'float', 'cpuUser': 'float', 'memUsage': 'uint',
+ 'elapsedTime': 'uint', 'status': 'VmStatus', 'statsAge': 'float',
+ 'hashes': 'VmRuntimeStatsHashes'}}
+
+##
+# @VmRuntimeStatsResult:
+#
+# Union result of VmRuntimeStats or ExitedVmStats
+#
+# @exited: Indicates if the result is VmRuntimeStats or ExitedVmStats
+#
+# Since: 4.10.3
+##
+{'type': 'VmRuntimeStatsResult',
+ 'data': { 'exited': 'bool' },
+ 'union': ['VmRuntimeStats', 'ExitedVmStats']}
+
+##
+# @VmRuntimeStatsMap:
+#
+# A mapping of VM runtime statistics indexed by vm id (UUID).
+#
+# Since: 4.10.3
+##
+{'map': 'VmRuntimeStatsMap',
+ 'key': 'UUID', 'value': 'VmRuntimeStatsResult' }}
+
+
+##
+# @VM.getRuntimeStats:
+#
+# Get runtime information about a list of VMs
+#
+# @vmIDs: a list of UUIDs for VMs to query
+#
+# Returns:
+# VmRuntimeStatsMap
+#
+# Since: 4.10.3
+##
+{'command': {'class': 'VM', 'name': 'getRuntimeStats'},
+ 'data': {'vmIDs': ['UUID']},
+ 'returns': 'VmRuntimeStatsMap'}
+
+##
+# @VmStatusInfo:
+#
+# Information to the status of a VM and less frequently changed information
+#
+# @timeOffset: The time difference from host to the VM in seconds
+#
+# @monitorResponse: Indicates if the qemu monitor is responsive
+#
+# @clientIp: The IP address of the client connected to the display
+#
+# @username: the username associated with the current session
+#
+# @session: The current state of user interaction with the VM
+#
+# @guestIPs: A space separated string of assigned IPv4 addresses
+#
+# @pauseCode: Indicates the reason a VM has been paused
+#
+# Since: 4.10.3
+##
+{ 'type': 'VmStatusInfo',
+ 'data': { 'timeOffset': 'uint', 'monitorResponse': 'int', 'clientIp': 'str',
+ 'username': 'str', 'session': 'GuestSessionState',
+ 'guestIPs': 'str', 'pauseCode': 'str'}}
+
+##
+# @VmStatusInfoResult:
+#
+# Union result of VmStatusInfo or ExitedVmStats
+#
+# @exited: Indicates if the result is VmStatusInfo or ExitedVmStats
+#
+# Since: 4.10.3
+##
+{'type': 'VmStatusInfoResult',
+ 'data': { 'exited': 'bool' },
+ 'union': ['VmStatusInfo', 'ExitedVmStats']}
+
+##
+# @VmStatusInfoMap:
+#
+# A mapping of VM status information indexed by vm id (UUID).
+#
+# Since: 4.10.3
+##
+{'map': 'VmStatusInfoMap',
+ 'key': 'UUID', 'value': 'VmStatusInfoResult'}
+
+##
+# @VM.getStatus:
+#
+# Get status information about a list of VMs
+#
+# @vmIDs: a list of UUIDs for VMs to query
+#
+# Returns:
+# VmStatusMap
+#
+# Since: 4.10.3
+##
+{'command': {'class': 'VM', 'name': 'getStatus'},
+ 'data': {'vmIDs': ['UUID']},
+ 'returns': 'VmStatusInfoMap'}
+
+##
+# @VmConfInfo:
+#
+# VM configuration information
+#
+# @acpiEnable: Indicates if ACPI is enabled inside the VM
+#
+# @displayPort: The port in use for unencrypted display data
+#
+# @displaySecurePort: The port in use for encrypted display data
+#
+# @displayType: The type of display in use
+#
+# @displayIp: The IP address to use for accessing the VM display
+#
+# @pid: The process ID of the underlying qemu process
+#
+# @vmType: The type of VM
+#
+# @kvmEnable: Indicates if KVM hardware acceleration is enabled
+#
+# @cdrom: #optional The path to an ISO image used in the VM's CD-ROM device
+#
+# @boot: #optional An alias for the type of device used to boot the VM
+#
+# Since: 4.10.3
+##
+{ 'type': 'VmConfInfo',
+ 'data': { 'acpiEnable': 'bool', 'vmType': 'VmType',
+ 'kvmEnable': 'bool', 'displayIp': 'str', 'displayPort': 'uint',
+ 'displaySecurePort': 'uint', 'displayType': 'VmDisplayType',
+ 'pid': 'uint', '*boot': 'VmBootMode', '*cdrom': 'str'}}
+
+##
+# @VmConfInfoResult:
+#
+# Union result of VmConfInfo or ExitedVmStats
+#
+# @exited: Indicates if the result is VmConfInfo or ExitedVmStats
+#
+# Since: 4.10.3
+##
+{'type': 'VmConfInfoResult',
+ 'data': { 'exited': 'bool' },
+ 'union': ['VmConfInfo', 'ExitedVmStats']}
+
+##
+# @VmConfInfoMap:
+#
+# A mapping of VM config information indexed by vm id (UUID).
+#
+# Since: 4.10.3
+##
+{'map': 'VmConfInfoMap',
+ 'key': 'UUID', 'value': 'VmConfInfoResult' }}
+
+##
+# @VM.getConfInfo:
+#
+# Get configuration information about a list of VMs
+#
+# @vmIDs: a list of UUIDs for VMs to query
+#
+# Returns:
+# VmConfInfoMap
+#
+# Since: 4.10.3
+##
+{'command': {'class': 'VM', 'name': 'getConfInfo'},
+ 'data': {'vmIDs': ['UUID']},
+ 'returns': 'VmConfInfoMap'}
+
+##
+# @VmDeviceStats:
+#
+# VM device statistics containing information for getting statistics and SLA
+# information.
+#
+# @memoryStats: Memory statistics as reported by the guest agent
+#
+# @balloonInfo: Guest memory balloon information
+#
+# @disksUsage: Info about mounted filesystems as reported by the agent
+#
+# @network: Network bandwidth/utilization statistics
+#
+# @disks: Disk bandwidth/utilization statistics
+#
+# Since: 4.10.3
+##
+{ 'type': 'VmDeviceStats',
+ 'data': { 'network': 'NetworkInterfaceStatsMap', 'disks': 'VmDiskStatsMap',
+ 'disksUsage': ['GuestMountInfo'], 'balloonInfo': 'BalloonInfo',
+ 'memoryStats': 'GuestMemoryStats' }}
+
+##
+# @VmDeviceStatsResult:
+#
+# Union result of VmDeviceStats or ExitedVmStats
+#
+# @exited: Indicates if the result is VmDeviceStats or ExitedVmStats
+#
+# Since: 4.10.3
+##
+{'type': 'VmDeviceStatsResult',
+ 'data': { 'exited': 'bool' },
+ 'union': ['VmDeviceStats', 'ExitedVmStats']}
+
+##
+# @VmDeviceStatsMap:
+#
+# A mapping of VM device statistics indexed by vm id (UUID).
+#
+# Since: 4.10.3
+##
+{'map': 'VmDeviceStatsMap',
+ 'key': 'UUID', 'value': 'VmDeviceStatsResult' }}
+
+##
+# @VM.getAllDeviceStats:
+#
+# Get device statistics from all VMs
+#
+# Returns:
+# VmDeviceStatsMap
+#
+# Since: 4.10.3
+##
+{'command': {'class': 'VM', 'name': 'getAllDeviceStats'},
+ 'returns': 'VmDeviceStatsMap'}
+
+##
+# @VmGuestDetails:
+#
+# Non-frequent changed details from guest OSes
+#
+# @appsList: A list of installed applications with their versions
+#
+# @netIfaces: Network device address info as reported by the agent
+#
+# Since: 4.10.3
+##
+{ 'type': 'VmGuestDetails',
+ 'data': { 'appsList': ['str'], 'netIfaces': ['GuestNetworkDeviceInfo'] }}
+
+##
+# @VmGuestDetailsResult:
+#
+# Union result of VmDeviceStats or ExitedVmStats
+#
+# @exited: Indicates if the result is VmGuestDetails or ExitedVmStats
+#
+# Since: 4.10.3
+##
+{'type': 'VmGuestDetailsResult',
+ 'data': { 'exited': 'bool' },
+ 'union': ['VmGuestDetails', 'ExitedVmStats']}
+
+##
+# @VmGuestDetailsMap:
+#
+# A mapping of detailed information of guests indexed by vm id (UUID).
+#
+# Since: 4.10.3
+##
+{'map': 'VmGuestDetailsMap',
+ 'key': 'UUID', 'value': 'VmGuestDetailsResult' }}
+
+##
+# @VM.getGuestDetails:
+#
+# Get details from the guest OS from a list of VMs
+#
+# @vmIDs: a list of UUIDs for VMs to query
+#
+# Returns:
+# VmGuestDetailsMap
+#
+# Since: 4.10.3
+##
+{'command': {'class': 'VM', 'name': 'getGuestDetails'},
+ 'data': {'vmIDs': ['UUID']},
+ 'returns': 'VmGuestDetailsMap'}
##
# @VM.getMigrationStatus:
--
To view, visit http://gerrit.ovirt.org/14541
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ifa0a7a86a351a8c2d891f22802a95d1fe1bc1df4
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Vinzenz Feenstra <vfeenstr(a)redhat.com>
10 years
Change in vdsm[master]: vm: abort and report error if domain destroy fails
by fromani@redhat.com
Francesco Romani has uploaded a new change for review.
Change subject: vm: abort and report error if domain destroy fails
......................................................................
vm: abort and report error if domain destroy fails
The call of vm._dom.destroy() is not expected to fail.
However, if the failure is not impossible, and in
that case VDSM should detect that and report the
error instead of blindly go ahead.
This patch let releaseVm() bail out with an error
as soon as possible if destroy() fails.
Change-Id: Id6d5819321cd0cb28aa43678dc65ee83c215c2d7
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
M vdsm/virt/vm.py
1 file changed, 1 insertion(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/25/28025/1
diff --git a/vdsm/virt/vm.py b/vdsm/virt/vm.py
index b73d84d..e299654 100644
--- a/vdsm/virt/vm.py
+++ b/vdsm/virt/vm.py
@@ -4324,6 +4324,7 @@
except libvirt.libvirtError as e:
self.log.warning("Failed to destroy VM '%s'",
self.conf['vmId'])
+ return errCode['destroyErr']
if not self.cif.mom:
self.cif.ksmMonitor.adjust()
--
To view, visit http://gerrit.ovirt.org/28025
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Id6d5819321cd0cb28aa43678dc65ee83c215c2d7
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Francesco Romani <fromani(a)redhat.com>
10 years
Change in vdsm[master]: vm: narrow down try/except block in releaseVm
by fromani@redhat.com
Francesco Romani has uploaded a new change for review.
Change subject: vm: narrow down try/except block in releaseVm
......................................................................
vm: narrow down try/except block in releaseVm
In releaseVm, we have a too wide try/except block;
only self._dom.destroy() can actually raise libvirtError,
so this patch narrows down the block size.
Change-Id: I9c2b60d8f490f9559edad429baf3989e98d05cf6
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
M vdsm/virt/vm.py
1 file changed, 6 insertions(+), 6 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/24/28024/1
diff --git a/vdsm/virt/vm.py b/vdsm/virt/vm.py
index 112e548..b73d84d 100644
--- a/vdsm/virt/vm.py
+++ b/vdsm/virt/vm.py
@@ -4304,13 +4304,13 @@
self.log.info('Release VM resources')
self.lastStatus = vmstatus.POWERING_DOWN
+ # Terminate the VM's creation thread.
+ self._incomingMigrationFinished.set()
+ if self._vmStats:
+ self._vmStats.stop()
+ if self.guestAgent:
+ self.guestAgent.stop()
try:
- # Terminate the VM's creation thread.
- self._incomingMigrationFinished.set()
- if self._vmStats:
- self._vmStats.stop()
- if self.guestAgent:
- self.guestAgent.stop()
if self._dom:
try:
self._dom.destroyFlags(
--
To view, visit http://gerrit.ovirt.org/28024
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I9c2b60d8f490f9559edad429baf3989e98d05cf6
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Francesco Romani <fromani(a)redhat.com>
10 years
Change in vdsm[master]: vm: improve the logging when destroying domains
by fromani@redhat.com
Francesco Romani has uploaded a new change for review.
Change subject: vm: improve the logging when destroying domains
......................................................................
vm: improve the logging when destroying domains
The logging of the failures of the domain destruction
in releaseVm was messy and confusing.
This patch improve the logging and make sure that errors
aren't silently ignored.
Change-Id: Ib314ecd66bb7ccb95da96605d810041f767bc9e0
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
M vdsm/virt/vm.py
1 file changed, 5 insertions(+), 7 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/23/28023/1
diff --git a/vdsm/virt/vm.py b/vdsm/virt/vm.py
index 2f121d0..112e548 100644
--- a/vdsm/virt/vm.py
+++ b/vdsm/virt/vm.py
@@ -4316,16 +4316,14 @@
self._dom.destroyFlags(
libvirt.VIR_DOMAIN_DESTROY_GRACEFUL)
except libvirt.libvirtError as e:
+ self.log.warning("Failed to destroy VM '%s' "
+ "gracefully", self.conf['vmId'])
if (e.get_error_code() ==
- libvirt.VIR_ERR_OPERATION_FAILED):
- self.log.warn("Failed to destroy VM '%s' "
- "gracefully", self.conf['vmId'])
+ libvirt.VIR_ERR_OPERATION_FAILED):
self._dom.destroy()
except libvirt.libvirtError as e:
- if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
- self.log.warning("libvirt domain not found", exc_info=True)
- else:
- self.log.warn("VM %s is not running", self.conf['vmId'])
+ self.log.warning("Failed to destroy VM '%s'",
+ self.conf['vmId'])
if not self.cif.mom:
self.cif.ksmMonitor.adjust()
--
To view, visit http://gerrit.ovirt.org/28023
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ib314ecd66bb7ccb95da96605d810041f767bc9e0
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Francesco Romani <fromani(a)redhat.com>
10 years
Change in vdsm[master]: vm: extract the vm destroy in a method
by fromani@redhat.com
Francesco Romani has uploaded a new change for review.
Change subject: vm: extract the vm destroy in a method
......................................................................
vm: extract the vm destroy in a method
this patch extracts the sequence of calls to vm._dom.destroy()
in a separate method, with no functional changes, with the intent
of clean up and modularize the code.
Change-Id: I91de9dc310cd563396e0f646533ba986bcb7e35e
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
M vdsm/virt/vm.py
1 file changed, 21 insertions(+), 15 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/26/28026/1
diff --git a/vdsm/virt/vm.py b/vdsm/virt/vm.py
index e299654..43a2acd 100644
--- a/vdsm/virt/vm.py
+++ b/vdsm/virt/vm.py
@@ -4298,6 +4298,7 @@
'vmPayload' in drive.specParams):
supervdsm.getProxy().removeFs(drive.path)
+ response = {'status': doneCode}
with self._releaseLock:
if self._released:
return {'status': doneCode}
@@ -4310,21 +4311,10 @@
self._vmStats.stop()
if self.guestAgent:
self.guestAgent.stop()
- try:
- if self._dom:
- try:
- self._dom.destroyFlags(
- libvirt.VIR_DOMAIN_DESTROY_GRACEFUL)
- except libvirt.libvirtError as e:
- self.log.warning("Failed to destroy VM '%s' "
- "gracefully", self.conf['vmId'])
- if (e.get_error_code() ==
- libvirt.VIR_ERR_OPERATION_FAILED):
- self._dom.destroy()
- except libvirt.libvirtError as e:
- self.log.warning("Failed to destroy VM '%s'",
- self.conf['vmId'])
- return errCode['destroyErr']
+
+ response = self._destroyVm()
+ if response['status']['code']:
+ return response
if not self.cif.mom:
self.cif.ksmMonitor.adjust()
@@ -4339,6 +4329,22 @@
self._released = True
+ return response
+
+ def _destroyVm(self):
+ if self._dom:
+ try:
+ try:
+ self._dom.destroyFlags(libvirt.VIR_DOMAIN_DESTROY_GRACEFUL)
+ except libvirt.libvirtError as e:
+ self.log.warning("Failed to destroy VM '%s' gracefully",
+ self.conf['vmId'])
+ if e.get_error_code() == libvirt.VIR_ERR_OPERATION_FAILED:
+ self._dom.destroy()
+ except libvirt.libvirtError as e:
+ self.log.warning("Failed to destroy VM '%s'",
+ self.conf['vmId'])
+ return errCode['destroyErr']
return {'status': doneCode}
def deleteVm(self):
--
To view, visit http://gerrit.ovirt.org/28026
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I91de9dc310cd563396e0f646533ba986bcb7e35e
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Francesco Romani <fromani(a)redhat.com>
10 years
Change in vdsm[master]: sd: make preallocate optional in volume validation
by Federico Simoncelli
Federico Simoncelli has uploaded a new change for review.
Change subject: sd: make preallocate optional in volume validation
......................................................................
sd: make preallocate optional in volume validation
Change-Id: Ide89098b404e992678441d4b6f996ff203e055f0
Signed-off-by: Federico Simoncelli <fsimonce(a)redhat.com>
---
M vdsm/storage/blockSD.py
M vdsm/storage/hsm.py
M vdsm/storage/sd.py
3 files changed, 7 insertions(+), 5 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/29/28129/1
diff --git a/vdsm/storage/blockSD.py b/vdsm/storage/blockSD.py
index 921d343..5acbd0d 100644
--- a/vdsm/storage/blockSD.py
+++ b/vdsm/storage/blockSD.py
@@ -629,7 +629,8 @@
getVAllocSize = getVSize
- def validateCreateVolumeParams(self, volFormat, preallocate, srcVolUUID):
+ def validateCreateVolumeParams(self, volFormat, srcVolUUID,
+ preallocate=None):
super(BlockStorageDomain, self) \
.validateCreateVolumeParams(volFormat, preallocate, srcVolUUID)
# Sparse-Raw not supported for block volumes
diff --git a/vdsm/storage/hsm.py b/vdsm/storage/hsm.py
index 6279395..5c05bab 100644
--- a/vdsm/storage/hsm.py
+++ b/vdsm/storage/hsm.py
@@ -1423,7 +1423,7 @@
if srcVolUUID:
misc.validateUUID(srcVolUUID, 'srcVolUUID')
# Validate volume type and format
- dom.validateCreateVolumeParams(volFormat, preallocate, srcVolUUID)
+ dom.validateCreateVolumeParams(volFormat, srcVolUUID, preallocate)
vars.task.getSharedLock(STORAGE, sdUUID)
self._spmSchedule(spUUID, "createVolume", pool.createVolume, sdUUID,
@@ -1743,7 +1743,7 @@
else:
dom = sdUUID
sdCache.produce(dom).validateCreateVolumeParams(
- volFormat, preallocate, volume.BLANK_UUID)
+ volFormat, volume.BLANK_UUID, preallocate)
# If dstSdUUID defined, means we copy image to it
domains = [sdUUID]
diff --git a/vdsm/storage/sd.py b/vdsm/storage/sd.py
index f5be95c..0f3ecdb 100644
--- a/vdsm/storage/sd.py
+++ b/vdsm/storage/sd.py
@@ -404,14 +404,15 @@
"""
pass
- def validateCreateVolumeParams(self, volFormat, preallocate, srcVolUUID):
+ def validateCreateVolumeParams(self, volFormat, srcVolUUID,
+ preallocate=None):
"""
Validate create volume parameters
"""
if volFormat not in volume.VOL_FORMAT:
raise se.IncorrectFormat(type2name(volFormat))
- if preallocate not in volume.VOL_TYPE:
+ if preallocate is not None and preallocate not in volume.VOL_TYPE:
raise se.IncorrectType(type2name(preallocate))
# Volumes with a parent must be cow
--
To view, visit http://gerrit.ovirt.org/28129
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ide89098b404e992678441d4b6f996ff203e055f0
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Federico Simoncelli <fsimonce(a)redhat.com>
10 years
Change in vdsm[master]: sd: unify validateCreateVolumeParams
by Federico Simoncelli
Federico Simoncelli has uploaded a new change for review.
Change subject: sd: unify validateCreateVolumeParams
......................................................................
sd: unify validateCreateVolumeParams
Change-Id: I082dc8b382af4a163fd4d10c67e696b1072e6b71
Signed-off-by: Federico Simoncelli <fsimonce(a)redhat.com>
---
M vdsm/storage/blockSD.py
M vdsm/storage/blockVolume.py
M vdsm/storage/fileSD.py
M vdsm/storage/fileVolume.py
M vdsm/storage/sd.py
M vdsm/storage/volume.py
6 files changed, 18 insertions(+), 65 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/28/28128/1
diff --git a/vdsm/storage/blockSD.py b/vdsm/storage/blockSD.py
index 8b84255..921d343 100644
--- a/vdsm/storage/blockSD.py
+++ b/vdsm/storage/blockSD.py
@@ -50,6 +50,7 @@
import resourceManager as rm
import mount
import supervdsm as svdsm
+import volume
STORAGE_DOMAIN_TAG = "RHAT_storage_domain"
STORAGE_UNREADY_DOMAIN_TAG = STORAGE_DOMAIN_TAG + "_UNREADY"
@@ -628,16 +629,12 @@
getVAllocSize = getVSize
- @classmethod
- def validateCreateVolumeParams(cls, volFormat, preallocate, srcVolUUID):
- """
- Validate create volume parameters.
- 'srcVolUUID' - backing volume UUID
- 'volFormat' - volume format RAW/QCOW2
- 'preallocate' - sparse/preallocate
- """
- blockVolume.BlockVolume.validateCreateVolumeParams(
- volFormat, preallocate, srcVolUUID)
+ def validateCreateVolumeParams(self, volFormat, preallocate, srcVolUUID):
+ super(BlockStorageDomain, self) \
+ .validateCreateVolumeParams(volFormat, preallocate, srcVolUUID)
+ # Sparse-Raw not supported for block volumes
+ if preallocate == volume.SPARSE_VOL and volFormat == volume.RAW_FORMAT:
+ raise se.IncorrectFormat(srcVolUUID)
@classmethod
def getMetaDataMapping(cls, vgName, oldMapping={}):
diff --git a/vdsm/storage/blockVolume.py b/vdsm/storage/blockVolume.py
index 299766a..fbc8a6f 100644
--- a/vdsm/storage/blockVolume.py
+++ b/vdsm/storage/blockVolume.py
@@ -113,21 +113,6 @@
os.unlink(volPath)
@classmethod
- def validateCreateVolumeParams(cls, volFormat, preallocate, srcVolUUID):
- """
- Validate create volume parameters.
- 'srcVolUUID' - backing volume UUID
- 'volFormat' - volume format RAW/QCOW2
- 'preallocate' - sparse/preallocate
- """
- volume.Volume.validateCreateVolumeParams(volFormat, preallocate,
- srcVolUUID)
-
- # Sparse-Raw not supported for block volumes
- if preallocate == volume.SPARSE_VOL and volFormat == volume.RAW_FORMAT:
- raise se.IncorrectFormat(srcVolUUID)
-
- @classmethod
def createVolumeMetadataRollback(cls, taskObj, sdUUID, offs):
cls.log.info("Metadata rollback for sdUUID=%s offs=%s", sdUUID, offs)
cls.__putMetadata((sdUUID, int(offs)),
diff --git a/vdsm/storage/fileSD.py b/vdsm/storage/fileSD.py
index 087364e..dcf1272 100644
--- a/vdsm/storage/fileSD.py
+++ b/vdsm/storage/fileSD.py
@@ -321,17 +321,6 @@
return stat.st_blocks * ST_BYTES_PER_BLOCK
- @classmethod
- def validateCreateVolumeParams(cls, volFormat, preallocate, srcVolUUID):
- """
- Validate create volume parameters.
- 'srcVolUUID' - backing volume UUID
- 'volFormat' - volume format RAW/QCOW2
- 'preallocate' - sparse/preallocate
- """
- fileVolume.FileVolume.validateCreateVolumeParams(
- volFormat, preallocate, srcVolUUID)
-
def getVolumeLease(self, imgUUID, volUUID):
"""
Return the volume lease (leasePath, leaseOffset)
diff --git a/vdsm/storage/fileVolume.py b/vdsm/storage/fileVolume.py
index 62be9df..654818e 100644
--- a/vdsm/storage/fileVolume.py
+++ b/vdsm/storage/fileVolume.py
@@ -90,17 +90,6 @@
oop.getProcessPool(sdUUID).os.unlink(volPath)
@classmethod
- def validateCreateVolumeParams(cls, volFormat, preallocate, srcVolUUID):
- """
- Validate create volume parameters.
- 'srcVolUUID' - backing volume UUID
- 'volFormat' - volume format RAW/QCOW2
- 'preallocate' - sparse/preallocate
- """
- volume.Volume.validateCreateVolumeParams(volFormat, preallocate,
- srcVolUUID)
-
- @classmethod
def createVolumeMetadataRollback(cls, taskObj, volPath):
cls.log.info("createVolumeMetadataRollback: volPath=%s" % (volPath))
metaPath = cls.__metaVolumePath(volPath)
diff --git a/vdsm/storage/sd.py b/vdsm/storage/sd.py
index 56c84cc..f5be95c 100644
--- a/vdsm/storage/sd.py
+++ b/vdsm/storage/sd.py
@@ -34,6 +34,7 @@
import clusterlock
import outOfProcess as oop
from persistentDict import unicodeEncoder, unicodeDecoder
+import volume
from vdsm.config import config
@@ -403,12 +404,19 @@
"""
pass
- @classmethod
- def validateCreateVolumeParams(cls, volFormat, preallocate, srcVolUUID):
+ def validateCreateVolumeParams(self, volFormat, preallocate, srcVolUUID):
"""
Validate create volume parameters
"""
- pass
+ if volFormat not in volume.VOL_FORMAT:
+ raise se.IncorrectFormat(type2name(volFormat))
+
+ if preallocate not in volume.VOL_TYPE:
+ raise se.IncorrectType(type2name(preallocate))
+
+ # Volumes with a parent must be cow
+ if srcVolUUID != volume.BLANK_UUID and volFormat != volume.COW_FORMAT:
+ raise se.IncorrectFormat(srcVolUUID)
def createVolume(self, imgUUID, size, volFormat, preallocate, diskType,
volUUID, desc, srcImgUUID, srcVolUUID):
diff --git a/vdsm/storage/volume.py b/vdsm/storage/volume.py
index 45a46df..242c6c8 100644
--- a/vdsm/storage/volume.py
+++ b/vdsm/storage/volume.py
@@ -359,21 +359,6 @@
fileUtils.cleanupdir(imageDir)
@classmethod
- def validateCreateVolumeParams(cls, volFormat, preallocate, srcVolUUID):
- """
- Validate create volume parameters
- """
- if volFormat not in VOL_FORMAT:
- raise se.IncorrectFormat(type2name(volFormat))
-
- if preallocate not in VOL_TYPE:
- raise se.IncorrectType(type2name(preallocate))
-
- # Volumes with a parent must be cow
- if srcVolUUID != volume.BLANK_UUID and volFormat != volume.COW_FORMAT:
- raise se.IncorrectFormat(srcVolUUID)
-
- @classmethod
def create(cls, repoPath, sdUUID, imgUUID, size, volFormat, preallocate,
diskType, volUUID, desc, srcImgUUID, srcVolUUID):
"""
--
To view, visit http://gerrit.ovirt.org/28128
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I082dc8b382af4a163fd4d10c67e696b1072e6b71
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Federico Simoncelli <fsimonce(a)redhat.com>
10 years
Change in vdsm[master]: profile: Allow disabling threads when using the decorator
by Nir Soffer
Nir Soffer has uploaded a new change for review.
Change subject: profile: Allow disabling threads when using the decorator
......................................................................
profile: Allow disabling threads when using the decorator
yappi supports profiling all threads (default) or only the thread where
the profiler was started from. This patch add this option to the profile
decorator. This is is probably not going to be used very much, but
useful when you need it.
New threading tests verify that yappi indeed work correctly with other
threads, even those that started before yappi was started.
Change-Id: I6608a831e0ac2d347d9b2f00458e570da31fdafd
Signed-off-by: Nir Soffer <nsoffer(a)redhat.com>
---
M lib/vdsm/profile.py
M tests/profileTests.py
2 files changed, 83 insertions(+), 6 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/94/27894/1
diff --git a/lib/vdsm/profile.py b/lib/vdsm/profile.py
index d9069f5..8344e28 100644
--- a/lib/vdsm/profile.py
+++ b/lib/vdsm/profile.py
@@ -33,10 +33,13 @@
# Import yappi lazily when profile is started
yappi = None
+# Defaults
+
_FILENAME = os.path.join(constants.P_VDSM_RUN, 'vdsmd.prof')
_FORMAT = config.get('vars', 'profile_format')
_BUILTINS = config.getboolean('vars', 'profile_builtins')
_CLOCK = config.get('vars', 'profile_clock')
+_THREADS = True
_lock = threading.Lock()
@@ -48,7 +51,7 @@
def start():
""" Starts application wide profiling """
if is_enabled():
- _start_profiling(_BUILTINS, _CLOCK)
+ _start_profiling(_CLOCK, _BUILTINS, _THREADS)
def stop():
@@ -66,7 +69,7 @@
return yappi and yappi.is_running()
-def profile(filename, format=_FORMAT, builtins=_BUILTINS, clock=_CLOCK):
+def profile(filename, format=_FORMAT, clock=_CLOCK, builtins=_BUILTINS, threads=_THREADS):
"""
Profile decorated function, saving profile to filename using format.
@@ -76,7 +79,7 @@
def decorator(f):
@wraps(f)
def wrapper(*a, **kw):
- _start_profiling(builtins, clock)
+ _start_profiling(clock, builtins, threads)
try:
return f(*a, **kw)
finally:
@@ -85,7 +88,7 @@
return decorator
-def _start_profiling(builtins, clock):
+def _start_profiling(clock, builtins, threads):
global yappi
logging.debug("Starting profiling")
with _lock:
@@ -96,7 +99,7 @@
if yappi.is_running():
raise Error('Profiler is already running')
yappi.set_clock_type(clock)
- yappi.start(builtins=builtins)
+ yappi.start(builtins=builtins, profile_threads=threads)
def _stop_profiling(filename, format):
diff --git a/tests/profileTests.py b/tests/profileTests.py
index 2501620..2bdc691 100644
--- a/tests/profileTests.py
+++ b/tests/profileTests.py
@@ -23,6 +23,7 @@
import os
import pstats
import time
+import threading
from vdsm import profile
from vdsm import config
@@ -259,6 +260,75 @@
def wall_clock(self):
time.sleep(0.1)
+
+class ThreadsProfileTests(ProfileTests):
+
+ def setUp(self):
+ self.thread = None
+ self.ready = threading.Event()
+
+ @MonkeyPatch(profile, 'config', make_config(enable='false'))
+ def test_new_threads(self):
+ # The easy case - threads started after yappi was started
+ requires_yappi()
+ self.new_threads()
+ stats = open_ystats(FILENAME)
+ name = function_name(self.worker_function)
+ func = find_function(stats, __file__, name)
+ self.assertEquals(func.ncall, 1)
+
+ @MonkeyPatch(profile, 'config', make_config(enable='false'))
+ def test_running_threads(self):
+ # The harder case - threads started before yappi was started
+ requires_yappi()
+ self.start_thread()
+ self.running_threads()
+ stats = open_ystats(FILENAME)
+ name = function_name(self.worker_function)
+ func = find_function(stats, __file__, name)
+ self.assertEquals(func.ncall, 1)
+
+ @MonkeyPatch(profile, 'config', make_config(enable='false'))
+ def test_without_threads(self):
+ requires_yappi()
+ self.without_threads()
+ stats = open_ystats(FILENAME)
+ name = function_name(self.worker_function)
+ self.assertRaises(NotFound, find_function, stats, __file__, name)
+
+ @profile.profile(FILENAME, format="ystat", threads=True)
+ def new_threads(self):
+ self.start_thread()
+ self.ready.set()
+ self.join_thread()
+
+ @profile.profile(FILENAME, format="ystat", threads=True)
+ def running_threads(self):
+ self.ready.set()
+ self.join_thread()
+
+ @profile.profile(FILENAME, format="ystat", threads=False)
+ def without_threads(self):
+ self.start_thread()
+ self.ready.set()
+ self.join_thread()
+
+ def start_thread(self):
+ self.thread = threading.Thread(target=self.worker)
+ self.thread.daemon = True
+ self.thread.start()
+
+ def join_thread(self):
+ self.thread.join()
+
+ def worker(self):
+ self.ready.wait()
+ self.worker_function()
+
+ def worker_function(self):
+ pass
+
+
# Helpers
def open_ystats(filename):
@@ -274,11 +344,15 @@
return False
+class NotFound(Exception):
+ pass
+
+
def find_function(ystats, module, name):
for func in ystats:
if func.module == module and func.name == name:
return func
- raise Exception('No such function: %s(%s)' % (module, name))
+ raise NotFound('No such function: %s(%s)' % (module, name))
def function_name(meth):
--
To view, visit http://gerrit.ovirt.org/27894
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I6608a831e0ac2d347d9b2f00458e570da31fdafd
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Nir Soffer <nsoffer(a)redhat.com>
10 years
Change in vdsm[master]: profile: Support yappi clock types
by Nir Soffer
Nir Soffer has uploaded a new change for review.
Change subject: profile: Support yappi clock types
......................................................................
profile: Support yappi clock types
yappi supports both "cpu" clock and "wall" clcok. The default "cpu"
clock is handy when you want to see when time is spent running code. The
wall clock is handy when you want to understand when time is spent
running or sleeping.
See test_cpu_clock and test_wall_clock if the difference between the
clock is not clear.
Change-Id: I64069de315a0bad5cb19365b43edf79aceeedca1
Signed-off-by: Nir Soffer <nsoffer(a)redhat.com>
---
M lib/vdsm/config.py.in
M lib/vdsm/profile.py
M tests/profileTests.py
3 files changed, 78 insertions(+), 5 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/16/27816/1
diff --git a/lib/vdsm/config.py.in b/lib/vdsm/config.py.in
index 01d5580..e8546f8 100644
--- a/lib/vdsm/config.py.in
+++ b/lib/vdsm/config.py.in
@@ -36,9 +36,12 @@
'Profile file format (pstat, callgrind, ystat)'),
('profile_builtins', 'false',
- 'Profile builtin functions used by standart Python modules. '
+ 'Profile builtin functions used by standard Python modules. '
'false by default.'),
+ ('profile_clock', 'cpu',
+ 'Sets the underlying clock type (cpu, wall)'),
+
('host_mem_reserve', '256',
'Reserves memory for the host to prevent VMs from using all the '
'physical pages. The values are in Mbytes.'),
diff --git a/lib/vdsm/profile.py b/lib/vdsm/profile.py
index 3095737..d9069f5 100644
--- a/lib/vdsm/profile.py
+++ b/lib/vdsm/profile.py
@@ -36,6 +36,7 @@
_FILENAME = os.path.join(constants.P_VDSM_RUN, 'vdsmd.prof')
_FORMAT = config.get('vars', 'profile_format')
_BUILTINS = config.getboolean('vars', 'profile_builtins')
+_CLOCK = config.get('vars', 'profile_clock')
_lock = threading.Lock()
@@ -47,7 +48,7 @@
def start():
""" Starts application wide profiling """
if is_enabled():
- _start_profiling(_BUILTINS)
+ _start_profiling(_BUILTINS, _CLOCK)
def stop():
@@ -65,7 +66,7 @@
return yappi and yappi.is_running()
-def profile(filename, format=_FORMAT, builtins=_BUILTINS):
+def profile(filename, format=_FORMAT, builtins=_BUILTINS, clock=_CLOCK):
"""
Profile decorated function, saving profile to filename using format.
@@ -75,7 +76,7 @@
def decorator(f):
@wraps(f)
def wrapper(*a, **kw):
- _start_profiling(builtins)
+ _start_profiling(builtins, clock)
try:
return f(*a, **kw)
finally:
@@ -84,7 +85,7 @@
return decorator
-def _start_profiling(builtins):
+def _start_profiling(builtins, clock):
global yappi
logging.debug("Starting profiling")
with _lock:
@@ -94,6 +95,7 @@
# that thinks they own the single process profiler.
if yappi.is_running():
raise Error('Profiler is already running')
+ yappi.set_clock_type(clock)
yappi.start(builtins=builtins)
diff --git a/tests/profileTests.py b/tests/profileTests.py
index 6bf2673..ba7e128 100644
--- a/tests/profileTests.py
+++ b/tests/profileTests.py
@@ -22,6 +22,7 @@
import errno
import os
import pstats
+import time
from vdsm import profile
from vdsm import config
@@ -109,6 +110,34 @@
@MonkeyPatch(profile, 'config', make_config(enable='true'))
@MonkeyPatch(profile, '_FILENAME', FILENAME)
+ @MonkeyPatch(profile, '_FORMAT', 'ystat')
+ @MonkeyPatch(profile, '_CLOCK', 'cpu')
+ def test_cpu_clock(self):
+ requires_yappi()
+ profile.start()
+ self.sleep(0.1)
+ profile.stop()
+ stats = open_ystats(FILENAME)
+ name = function_name(self.sleep)
+ func = find_function(stats, __file__, name)
+ self.assertTrue(func.ttot < 0.1)
+
+ @MonkeyPatch(profile, 'config', make_config(enable='true'))
+ @MonkeyPatch(profile, '_FILENAME', FILENAME)
+ @MonkeyPatch(profile, '_FORMAT', 'ystat')
+ @MonkeyPatch(profile, '_CLOCK', 'wall')
+ def test_cpu_clock(self):
+ requires_yappi()
+ profile.start()
+ self.sleep(0.1)
+ profile.stop()
+ stats = open_ystats(FILENAME)
+ name = function_name(self.sleep)
+ func = find_function(stats, __file__, name)
+ self.assertTrue(func.ttot > 0.1)
+
+ @MonkeyPatch(profile, 'config', make_config(enable='true'))
+ @MonkeyPatch(profile, '_FILENAME', FILENAME)
def test_is_running(self):
requires_yappi()
self.assertFalse(profile.is_running())
@@ -132,6 +161,9 @@
self.assertFalse(profile.is_running())
finally:
profile.stop()
+
+ def sleep(self, seconds):
+ time.sleep(seconds)
class FunctionProfileTests(ProfileTests):
@@ -181,6 +213,24 @@
stats = open_ystats(FILENAME)
self.assertFalse(find_module(stats, '__builtin__'))
+ @MonkeyPatch(profile, 'config', make_config(enable='false'))
+ def test_cpu_clock(self):
+ requires_yappi()
+ self.cpu_clock()
+ stats = open_ystats(FILENAME)
+ name = function_name(self.cpu_clock)
+ func = find_function(stats, __file__, name)
+ self.assertTrue(func.ttot < 0.1)
+
+ @MonkeyPatch(profile, 'config', make_config(enable='false'))
+ def test_wall_clock(self):
+ requires_yappi()
+ self.wall_clock()
+ stats = open_ystats(FILENAME)
+ name = function_name(self.wall_clock)
+ func = find_function(stats, __file__, name)
+ self.assertTrue(func.ttot > 0.1)
+
@profile.profile(FILENAME)
def profiled_function(self):
self.assertTrue(profile.is_running())
@@ -201,6 +251,13 @@
def with_builtins(self):
pass
+ @profile.profile(FILENAME, format="ystat", clock="cpu")
+ def cpu_clock(self):
+ time.sleep(0.1)
+
+ @profile.profile(FILENAME, format="ystat", clock="wall")
+ def wall_clock(self):
+ time.sleep(0.1)
# Helpers
@@ -215,3 +272,14 @@
if func.module == name:
return True
return False
+
+
+def find_function(ystats, module, name):
+ for func in ystats:
+ if func.module == module and func.name == name:
+ return func
+ raise Exception('No such function: %s(%s)' % (module, name))
+
+
+def function_name(meth):
+ return meth.im_class.__name__ + '.' + meth.__name__
--
To view, visit http://gerrit.ovirt.org/27816
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I64069de315a0bad5cb19365b43edf79aceeedca1
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Nir Soffer <nsoffer(a)redhat.com>
10 years