Francesco Romani has uploaded a new change for review. Change subject: hypervisor interface: introduce CachingInterface ......................................................................
hypervisor interface: introduce CachingInterface CachingInterface is an interface which minimizes the call to the hypervisor leveraging bluk APIs and ExpiringCache. Change-Id: I54cd218d40cb501f5164a2a60093ebc8f8695878 Signed-off-by: Francesco Romani <[email protected]> --- A mom/HypervisorInterfaces/CachingInterface.py M mom/HypervisorInterfaces/vdsmInterface.py M mom/HypervisorInterfaces/vdsmrpcInterface.py 3 files changed, 109 insertions(+), 77 deletions(-) git pull ssh://gerrit.ovirt.org:29418/mom refs/changes/45/41145/1 diff --git a/mom/HypervisorInterfaces/CachingInterface.py b/mom/HypervisorInterfaces/CachingInterface.py new file mode 100644 index 0000000..29f9483 --- /dev/null +++ b/mom/HypervisorInterfaces/CachingInterface.py @@ -0,0 +1,64 @@ +# Memory Overcommitment Manager +# Copyright (C) 2015 Francesco Romani, Red Hat Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import contextlib +import json +import logging +import os +import threading +import time +import traceback +import uuid + +from mom.ExpiringCache import ExpiringCache +from mom.HypervisorInterfaces.HypervisorInterface import HypervisorInterface, \ + HypervisorInterfaceError + + +class CachingInterface(HypervisorInterface): + + def __init__(self, config): + self._config = config + self._cache = ExpiringCache( + self._config.getint('vdsm', 'cache-lifetime')) + + def getVmInfo(self, vmId): + stats = self._getVmStats(vmId) + return { + 'uuid': vmId, + 'pid': stats['pid'], + 'name': stats.get('vmName', 'VM-%s' % vmId) + } + + def _getVmStats(self, vmId): + stats = self._cache.get(vmId) + if stats is None: + self._refresh() + + stats = self._cache.get(vmId) + if stats is None: + raise vdsmException('unavailable stats for %s' % vmId, + self.logger) + return stats + + def _refresh(self): + all_stats = self._refreshVmStats() + for stats in all_stats: + try: + self._cache[stats['vmId']] = stats + except KeyError: + pass + return all_stats diff --git a/mom/HypervisorInterfaces/vdsmInterface.py b/mom/HypervisorInterfaces/vdsmInterface.py index 4dd8655..c38bfc3 100644 --- a/mom/HypervisorInterfaces/vdsmInterface.py +++ b/mom/HypervisorInterfaces/vdsmInterface.py @@ -20,11 +20,13 @@ import supervdsm import logging import traceback + +from mom.HypervisorInterfaces.CachingInterface import CachingInterface from mom.HypervisorInterfaces.HypervisorInterface import HypervisorInterface, \ HypervisorInterfaceError -class vdsmInterface(HypervisorInterface): +class vdsmInterface(CachingInterface): """ vdsmInterface provides a wrapper for the VDSM API so that VDSM- related error handling can be consolidated in one place. An instance of @@ -33,6 +35,7 @@ """ def __init__(self): + super(vdsmInterface, self).__init__(config) self.logger = logging.getLogger('mom.vdsmInterface') try: self.vdsm_api = API.Global() @@ -85,29 +88,14 @@ return None def getAllVmStats(self): - try: - response = self.vdsm_api.getAllVmStats() - self._check_status(response) - stats_list = response['statsList'] - vm_stats = dict( - (stat['vmId'], translate_stats(stat)) - for stat in stats_list) - self.logger.debug('VM Stats: %s', vm_stats.keys()) - return vm_stats - except vdsmException, e: - e.handle_exception() - return None + return self._refresh() def getVmMemoryStats(self, uuid): try: - vm = API.VM(uuid) - response = vm.getStats() - self._check_status(response) - stats = response['statsList'][0] - err_msg = _check_vm_memory_stats(stats) - if err_msg: - raise HypervisorInterfaceError(err_msg) - ret = _memory_info_from_vm_stats(stats) + ret = {} + stats = self._getVmStats(uuid) + for field in self.getStatsFields(): + ret[field] = stats[field] self.logger.debug('Memory stats: %s', ret) return ret except vdsmException, e: @@ -121,15 +109,6 @@ except vdsmException, e: e.handle_exception() - def getVmInfo(self, id): - data = {} - data['uuid'] = id - data['pid'] = self.getVmPid(id) - data['name'] = self.getVmName(id) - if None in data.values(): - return None - return data - def getStatsFields(self=None): return set(['mem_available', 'mem_unused', 'mem_free', 'major_fault', 'minor_fault', 'swap_in', 'swap_out', @@ -137,27 +116,22 @@ def getVmBalloonInfo(self, uuid): try: - vm = API.VM(uuid) - response = vm.getStats() - self._check_status(response) - ret = _balloon_info_from_vm_stats(response['statsList'][0]) - if ret: - return ret - return None + ret = {} + stats = self._getVmStats(uuid) + for field in ("balloon_max", "balloon_min", "balloon_cur"): + ret[field] = stats[field] + return ret except vdsmException, e: e.handle_exception() def getVmCpuTuneInfo(self, uuid): try: - vm = API.VM(uuid) - response = vm.getStats() - self._check_status(response) - ret = _cpu_tune_info_from_vm_stats(response['statsList'][0]) - if ret: - return ret - return None - except vdsmException, e: - e.handle_exception() + ret = {} + stats = self._getVmStats(uuid) + for field in ('vcpu_user_limit', 'vcpu_quota', + 'vcpu_period', 'vcpu_count'): + ret[field] = stats[field] + return ret def setVmCpuTune(self, uuid, quota, period): vm = API.VM(uuid) @@ -178,6 +152,23 @@ superVdsm = supervdsm.getProxy() superVdsm.ksmTune(tuningParams) + def _refreshVmStats(self): + return self._getAllVmStats() + + def _getAllVmStats(self): + try: + response = self.vdsm_api.getAllVmStats() + self._check_status(response) + stats_list = response['statsList'] + vm_stats = dict( + (stat['vmId'], translate_stats(stat)) + for stat in stats_list) + self.logger.debug('VM Stats: %s', vm_stats.keys()) + return vm_stats + except vdsmException, e: + e.handle_exception() + return None + def _check_vm_memory_stats(vm_stats): usage = int(vm_stats['memUsage']) diff --git a/mom/HypervisorInterfaces/vdsmrpcInterface.py b/mom/HypervisorInterfaces/vdsmrpcInterface.py index b80bf44..81ddeec 100644 --- a/mom/HypervisorInterfaces/vdsmrpcInterface.py +++ b/mom/HypervisorInterfaces/vdsmrpcInterface.py @@ -27,20 +27,19 @@ import stomp.exception from mom.ExpiringCache import ExpiringCache +from mom.HypervisorInterfaces.CachingInterface import CachingInterface from mom.HypervisorInterfaces.HypervisorInterface import HypervisorInterface, \ HypervisorInterfaceError from mom.HypervisorInterfaces.vdsmInterface import translate_stats -class vdsmrpcInterface(HypervisorInterface): +class vdsmrpcInterface(CachingInterface): def __init__(self, config): - self._config = config + super(vdsmrpcInterface, self).__init__(config) self.logger = logging.getLogger('mom.vdsmRpcInterface') self._intf = _json_rpc_interface_from_config( self.logger, self.config) - self._cache = ExpiringCache( - self._config.getint('vdsm', 'cache-lifetime')) self._intf.connect() def getVmList(self): @@ -99,14 +98,6 @@ self._call('VM.setBalloonTarget', vmID=uuid, target=target) except vdsmException, e: e.handle_exception() - - def getVmInfo(self, vmId): - stats = self._getVmStats(vmId) - return { - 'uuid': vmId, - 'pid': stats['pid'], - 'name': stats.get('vmName', 'VM-%s' % vmId) - } def getStatsFields(self=None): return set([ @@ -178,26 +169,12 @@ for (key, val) in tuningParams.items(): write_value('/sys/kernel/mm/ksm/%s' % key, val) - def _getVmStats(self, vmId): - stats = self._cache.get(vmId) - if stats is None: - self._refresh() - - stats = self._cache.get(vmId) - if stats is None: - raise vdsmException('unavailable stats for %s' % vmId, - self.logger) - return stats - - def _refresh(self): + def _refreshVmStats(self): self._logger.debug('refreshing all stats') - res = self._intf.call('Host.getAllVmStats') - if res['status']['code'] == 0: - for stats in res['statsList']: - try: - self._cache[stats['vmId']] = stats - except KeyError: - pass + try: + return self._getAllVmStats() + except vdsmException, e: + return [] def _translate_memory_stats(ret, stats): -- To view, visit https://gerrit.ovirt.org/41145 To unsubscribe, visit https://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I54cd218d40cb501f5164a2a60093ebc8f8695878 Gerrit-PatchSet: 1 Gerrit-Project: mom Gerrit-Branch: master Gerrit-Owner: Francesco Romani <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
