Saggi Mizrahi has uploaded a new change for review.
Change subject: [WIP] Implement a process to do dangerous IO in C
......................................................................
[WIP] Implement a process to do dangerous IO in C
This replaces the process pool with a process that can serve multiple
requests written in C.
This implementation is much more scalable and lightweight. Should solve
bugs related to running out of helpers, logging getting suck, python
forking deadlocking, running out of memory and other things as well.
The communication between VDSM and the IOProcess is done with json
objects.
The IOProcess starts with 3 thread:
1. requestReader - reads requests from the pipe, builds a DOM
representation of it and queues it up for handling
2. responseWriter - gets response DOMs from the queue converts them to a
JSON string and send it over the pipe
3. requestHandler - pops requests from the queue and provisions threads
for handling them. Currently we I just allocate a new thread per
request. If there is ever a need to have a thread pool this is where
the load balancing is going to sit.
Each request gets the are as a JsonNode and returns a response that is a
JsonNode as well. Most exported functions are pretty trivial and are a
good example on how to write new ones.
Unlink the ProcessPoolHelper, high level commands sit of the OopWrapper
and are run from the client side instead of being implemented in C on
the IOProcess side.
Change-Id: Ie4664d5330debbe38ba33b74ebb586ac42913b4a
Signed-off-by: Saggi Mizrahi <smizrahi(a)redhat.com>
---
M configure.ac
M tests/Makefile.am
A tests/ioprocessTests.py
A tests/outOfProcessTests.py
D tests/processPoolTests.py
M vdsm.spec.in
M vdsm/constants.py.in
M vdsm/storage/Makefile.am
M vdsm/storage/fileSD.py
M vdsm/storage/fileUtils.py
M vdsm/storage/fileVolume.py
A vdsm/storage/ioprocess.py
A vdsm/storage/ioprocess/.gitignore
A vdsm/storage/ioprocess/Makefile.am
A vdsm/storage/ioprocess/exported-functions.c
A vdsm/storage/ioprocess/exported-functions.h
A vdsm/storage/ioprocess/ioprocess.c
A vdsm/storage/ioprocess/json-dom-generator.c
A vdsm/storage/ioprocess/json-dom-generator.h
A vdsm/storage/ioprocess/json-dom-parser.c
A vdsm/storage/ioprocess/json-dom-parser.h
A vdsm/storage/ioprocess/json-dom.c
A vdsm/storage/ioprocess/json-dom.h
M vdsm/storage/misc.py
M vdsm/storage/nfsSD.py
M vdsm/storage/outOfProcess.py
D vdsm/storage/processPool.py
M vdsm/storage/sd.py
M vdsm/storage/sp.py
M vdsm/storage/task.py
30 files changed, 3,018 insertions(+), 666 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/46/3946/1
--
To view, visit http://gerrit.ovirt.org/3946
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie4664d5330debbe38ba33b74ebb586ac42913b4a
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Saggi Mizrahi <smizrahi(a)redhat.com>
Eduardo has uploaded a new change for review.
Change subject: Use more fine lock for hsm.deleteImage().
......................................................................
Use more fine lock for hsm.deleteImage().
When removing an image from a specific SD, lock the image in this
SD exclusively.
Related to: BZ#960952.
Change-Id: Iab04d548610cd86eb70e1fd13a29a3508778cc1d
Signed-off-by: Eduardo <ewarszaw(a)redhat.com>
---
M vdsm/storage/hsm.py
1 file changed, 2 insertions(+), 1 deletion(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/13/16413/1
diff --git a/vdsm/storage/hsm.py b/vdsm/storage/hsm.py
index 5639c13..09c5404 100644
--- a/vdsm/storage/hsm.py
+++ b/vdsm/storage/hsm.py
@@ -1437,7 +1437,8 @@
self.getPool(spUUID) # Validates that the pool is connected. WHY?
dom = self.validateSdUUID(sdUUID)
- vars.task.getExclusiveLock(STORAGE, imgUUID)
+ imageResourcesNamespace = sd.getNamespace(sdUUID, IMAGE_NAMESPACE)
+ vars.task.getExclusiveLock(imageResourcesNamespace, imgUUID)
vars.task.getSharedLock(STORAGE, sdUUID)
allVols = dom.getAllVolumes()
volsByImg = sd.getVolsOfImage(allVols, imgUUID)
--
To view, visit http://gerrit.ovirt.org/16413
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Iab04d548610cd86eb70e1fd13a29a3508778cc1d
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Eduardo <ewarszaw(a)redhat.com>
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>