Change in vdsm[master]: GuestIF Refactoring
by Vinzenz Feenstra
Vinzenz Feenstra has uploaded a new change for review.
Change subject: GuestIF Refactoring
......................................................................
GuestIF Refactoring
Change-Id: Ib357d770a26ef1dc80b89a32bf6808551a7d622d
Signed-off-by: Vinzenz Feenstra <vfeenstr(a)redhat.com>
---
M vdsm/guestIF.py
1 file changed, 114 insertions(+), 76 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/18/24618/1
diff --git a/vdsm/guestIF.py b/vdsm/guestIF.py
index 229a55d..96ad68c 100644
--- a/vdsm/guestIF.py
+++ b/vdsm/guestIF.py
@@ -39,6 +39,115 @@
union(set(range(0x86, 0x9F + 1)))
+class UnknownMessageError(Exception):
+ def __init__(self, message, args):
+ Exception.__init__(self, 'Unknown or unsupported guest agent message '
+ '"%s" received with args "%s"' % (message,
+ str(args)))
+
+
+class MessageHandler(object):
+ def __init__(self, agent):
+ self.log = agent.log
+ self._agent = agent
+
+ def __call__(self, message, args):
+ handler = self.getattr(self, message.replace('-', '_'), None)
+ if handler:
+ handler(args)
+ else:
+ raise UnknownMessageError(message, args)
+
+ def applications(self, args):
+ self._agent.guestInfo['appsList'] = args['applications']
+
+ def fqdn(self, args):
+ self._agent.guestInfo['guestFQDN'] = args['fqdn']
+
+ def host_name(self, args):
+ self._agent.guestInfo['guestName'] = args['name']
+
+ def os_version(self, args):
+ self._agent.guestInfo['guestOs'] = args['version']
+
+ def session_lock(self, args):
+ self.agent.guestInfo['session'] = 'Locked'
+
+ def session_logoff(self, args):
+ self.agent.guestInfo['session'] = 'LoggedOff'
+
+ def session_logon(self, args):
+ self.agent.guestInfo['session'] = 'UserLoggedOn'
+
+ def session_unlock(self, args):
+ self.agent.guestInfo['session'] = 'Active'
+
+ def session_shutdown(self, args):
+ self.log.debug('Guest system shuts down')
+
+ def session_startup(self, args):
+ self.log.debug('Guest system started or restarted')
+
+ def uninstalled(self, args):
+ self.log.debug('Guest agent was uninstalled')
+ self._agent.guestInfo['appsList'] = []
+
+ def heartbeat(self, args):
+ self._agent.guestStatus = 'Up'
+ self._agent.guestInfo['memUsage'] = int(args['free-ram'])
+ # ovirt-guest-agent reports the following fields in 'memory-stat':
+ # 'mem_total', 'mem_free', 'mem_unused', 'swap_in', 'swap_out',
+ # 'pageflt' and 'majflt'
+ if 'memory-stat' in args:
+ for (k, v) in args['memory-stat'].iteritems():
+ # Convert the value to string since 64-bit integer is not
+ # supported in XMLRPC
+ self._agent.guestInfo['memoryStats'][k] = str(v)
+
+ if 'apiVersion' in args:
+ # The guest agent supports API Versioning
+ self._agent._handleAPIVersion(args['apiVersion'])
+ elif self._agent.effectiveApiVersion != _IMPLICIT_API_VERSION_ZERO:
+ # Older versions of the guest agent (before the introduction
+ # of API versioning) do not report this field
+ # Disable the API if not already disabled (e.g. after
+ # downgrade of the guest agent)
+ self.log.debug("API versioning no longer reported by guest.")
+ self._agent.effectiveApiVersion = _IMPLICIT_API_VERSION_ZERO
+
+ def network_interfaces(self, args):
+ interfaces = []
+ old_ips = ''
+ for iface in args['interfaces']:
+ iface['inet'] = iface.get('inet', [])
+ iface['inet6'] = iface.get('inet6', [])
+ interfaces.append(iface)
+ # Provide the old information which includes
+ # only the IP addresses.
+ old_ips += ' '.join(iface['inet']) + ' '
+ self._agent.guestInfo['netIfaces'] = interfaces
+ self._agent.guestInfo['guestIPs'] = old_ips.strip()
+
+ def active_user(self, args):
+ currentUser = args['name']
+ if ((currentUser != self._agent.guestInfo['username']) and
+ not (currentUser == 'Unknown' and
+ self._agent.guestInfo['username'] == 'None')):
+ self._agent.guestInfo['username'] = currentUser
+ self._agent.guestInfo['lastLogin'] = time.time()
+ self.log.debug("username: %s", repr(self.guestInfo['username']))
+
+ def disks_usage(self, args):
+ disks = []
+ for disk in args['disks']:
+ # Converting to string because XML-RPC doesn't support 64-bit
+ # integers.
+ disk['total'] = str(disk['total'])
+ disk['used'] = str(disk['used'])
+ disks.append(disk)
+ self._agent.guestInfo['disksUsage'] = disks
+
+
def _filterXmlChars(u):
"""
The set of characters allowed in XML documents is described in
@@ -109,6 +218,7 @@
def __init__(self, socketName, channelListener, log, user='Unknown',
ips='', connect=True):
+ self.handler = MessageHandler(self)
self.effectiveApiVersion = _IMPLICIT_API_VERSION_ZERO
self.log = log
self._socketName = socketName
@@ -223,82 +333,10 @@
self.log.log(logging.TRACE, "Guest's message %s: %s", message, args)
if self.guestStatus is None:
self.guestStatus = 'Up'
- if message == 'heartbeat':
- self.guestStatus = 'Up'
- self.guestInfo['memUsage'] = int(args['free-ram'])
- # ovirt-guest-agent reports the following fields in 'memory-stat':
- # 'mem_total', 'mem_free', 'mem_unused', 'swap_in', 'swap_out',
- # 'pageflt' and 'majflt'
- if 'memory-stat' in args:
- for (k, v) in args['memory-stat'].iteritems():
- # Convert the value to string since 64-bit integer is not
- # supported in XMLRPC
- self.guestInfo['memoryStats'][k] = str(v)
-
- if 'apiVersion' in args:
- # The guest agent supports API Versioning
- self._handleAPIVersion(args['apiVersion'])
- elif self.effectiveApiVersion != _IMPLICIT_API_VERSION_ZERO:
- # Older versions of the guest agent (before the introduction
- # of API versioning) do not report this field
- # Disable the API if not already disabled (e.g. after
- # downgrade of the guest agent)
- self.log.debug("API versioning no longer reported by guest.")
- self.effectiveApiVersion = _IMPLICIT_API_VERSION_ZERO
- elif message == 'host-name':
- self.guestInfo['guestName'] = args['name']
- elif message == 'os-version':
- self.guestInfo['guestOs'] = args['version']
- elif message == 'network-interfaces':
- interfaces = []
- old_ips = ''
- for iface in args['interfaces']:
- iface['inet'] = iface.get('inet', [])
- iface['inet6'] = iface.get('inet6', [])
- interfaces.append(iface)
- # Provide the old information which includes
- # only the IP addresses.
- old_ips += ' '.join(iface['inet']) + ' '
- self.guestInfo['netIfaces'] = interfaces
- self.guestInfo['guestIPs'] = old_ips.strip()
- elif message == 'applications':
- self.guestInfo['appsList'] = args['applications']
- elif message == 'active-user':
- currentUser = args['name']
- if ((currentUser != self.guestInfo['username']) and
- not (currentUser == 'Unknown' and
- self.guestInfo['username'] == 'None')):
- self.guestInfo['username'] = currentUser
- self.guestInfo['lastLogin'] = time.time()
- self.log.debug("username: %s", repr(self.guestInfo['username']))
- elif message == 'session-logon':
- self.guestInfo['session'] = "UserLoggedOn"
- elif message == 'session-lock':
- self.guestInfo['session'] = "Locked"
- elif message == 'session-unlock':
- self.guestInfo['session'] = "Active"
- elif message == 'session-logoff':
- self.guestInfo['session'] = "LoggedOff"
- elif message == 'uninstalled':
- self.log.debug("RHEV agent was uninstalled.")
- self.guestInfo['appsList'] = []
- elif message == 'session-startup':
- self.log.debug("Guest system is started or restarted.")
- elif message == 'fqdn':
- self.guestInfo['guestFQDN'] = args['fqdn']
- elif message == 'session-shutdown':
- self.log.debug("Guest system shuts down.")
- elif message == 'disks-usage':
- disks = []
- for disk in args['disks']:
- # Converting to string because XML-RPC doesn't support 64-bit
- # integers.
- disk['total'] = str(disk['total'])
- disk['used'] = str(disk['used'])
- disks.append(disk)
- self.guestInfo['disksUsage'] = disks
- else:
- self.log.error('Unknown message type %s', message)
+ try:
+ self.handler(message, args)
+ except UnknownMessageError as e:
+ self.log.error(e)
def stop(self):
self._stopped = True
--
To view, visit http://gerrit.ovirt.org/24618
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ib357d770a26ef1dc80b89a32bf6808551a7d622d
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Vinzenz Feenstra <vfeenstr(a)redhat.com>
7 years, 8 months
Change in vdsm[master]: tests: Fail if abort was not called
by Nir Soffer
Nir Soffer has uploaded a new change for review.
Change subject: tests: Fail if abort was not called
......................................................................
tests: Fail if abort was not called
The StuckJob was waiting one second and terminating silently even if the
test never called abort. Now we raise RuntimeError in this case.
Change-Id: If71d2aeeb4a4242678253845071f68f3a9b12f5d
Signed-off-by: Nir Soffer <nsoffer(a)redhat.com>
---
M tests/jobsTests.py
1 file changed, 2 insertions(+), 1 deletion(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/07/65207/1
diff --git a/tests/jobsTests.py b/tests/jobsTests.py
index 3b39277..520c98d 100644
--- a/tests/jobsTests.py
+++ b/tests/jobsTests.py
@@ -85,7 +85,8 @@
def _run(self):
self.event_running.set()
- self.event_aborted.wait(1)
+ if not self.event_aborted.wait(1):
+ raise RuntimeError("Timeout waiting for abort")
def _abort(self):
self.event_aborted.set()
--
To view, visit https://gerrit.ovirt.org/65207
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: If71d2aeeb4a4242678253845071f68f3a9b12f5d
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Nir Soffer <nsoffer(a)redhat.com>
7 years, 8 months
Change in vdsm[master]: profiling: Add devel:cpu_profile_filename option
by Nir Soffer
Nir Soffer has uploaded a new change for review.
Change subject: profiling: Add devel:cpu_profile_filename option
......................................................................
profiling: Add devel:cpu_profile_filename option
This is mainly for simplifying the tests. Now we can control the test
environment by mocking the config. Additionally, we use now a proper
temporary file for the saved profile, so the tests run now on a read
only file system.
This may also be useful for developers that want to change the location
of the application wide profile.
Change-Id: Id0a0800d08850fb236803813532210729ef16814
Signed-off-by: Nir Soffer <nsoffer(a)redhat.com>
---
M lib/vdsm/config.py.in
M lib/vdsm/profiling/cpu.py
M tests/cpu_profile_test.py
3 files changed, 125 insertions(+), 128 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/55/65255/1
diff --git a/lib/vdsm/config.py.in b/lib/vdsm/config.py.in
index 1a8367d..4cb2b85 100644
--- a/lib/vdsm/config.py.in
+++ b/lib/vdsm/config.py.in
@@ -478,6 +478,9 @@
('cpu_profile_enable', 'false',
'Enable whole process profiling (requires yappi profiler).'),
+ ('cpu_profile_filename', '/run/vdsm/vdsmd.prof',
+ 'Profile file name (/run/vdsm/vdsmd.prof)'),
+
('cpu_profile_format', 'pstat',
'Profile file format (pstat, callgrind, ystat)'),
diff --git a/lib/vdsm/profiling/cpu.py b/lib/vdsm/profiling/cpu.py
index 427f1db..6d7526a 100644
--- a/lib/vdsm/profiling/cpu.py
+++ b/lib/vdsm/profiling/cpu.py
@@ -25,10 +25,8 @@
from functools import wraps
import logging
-import os
import threading
-from vdsm import constants
from vdsm.config import config
from .errors import UsageError
@@ -37,8 +35,6 @@
yappi = None
# Defaults
-
-_FILENAME = os.path.join(constants.P_VDSM_RUN, 'vdsmd.prof')
_lock = threading.Lock()
_profiler = None
@@ -102,7 +98,7 @@
if _profiler:
raise UsageError('CPU profiler is already running')
_profiler = Profiler(
- _FILENAME,
+ config.get('devel', 'cpu_profile_filename'),
format=config.get('devel', 'cpu_profile_format'),
clock=config.get('devel', 'cpu_profile_clock'),
builtins=config.getboolean('devel', 'cpu_profile_builtins'),
diff --git a/tests/cpu_profile_test.py b/tests/cpu_profile_test.py
index 457dcda..c2cf307 100644
--- a/tests/cpu_profile_test.py
+++ b/tests/cpu_profile_test.py
@@ -18,8 +18,6 @@
# Refer to the README and COPYING files for full details of the license
#
-import errno
-import os
import pstats
import time
import threading
@@ -29,9 +27,10 @@
from vdsm.profiling import cpu
from vdsm.profiling.errors import UsageError
-from monkeypatch import MonkeyPatch, MonkeyPatchScope
+from monkeypatch import MonkeyPatchScope
from nose.plugins.skip import SkipTest
from testlib import VdsmTestCase, make_config
+from testlib import temporaryPath
yappi = None
try:
@@ -39,101 +38,84 @@
except ImportError:
pass
-FILENAME = __file__ + '.prof'
-
def requires_yappi():
if yappi is None:
raise SkipTest('yappi is not installed')
-class ProfileTests(VdsmTestCase):
-
- def tearDown(self):
- try:
- os.unlink(FILENAME)
- except OSError as e:
- if e.errno != errno.ENOENT:
- raise
-
-
@contextmanager
def env(enable='true', format='pstat', clock='cpu', builtins='false'):
- config = make_config([
- ('devel', 'cpu_profile_enable', enable),
- ('devel', 'cpu_profile_format', format),
- ('devel', 'cpu_profile_clock', clock),
- ('devel', 'cpu_profile_builtins', builtins),
- ])
- with MonkeyPatchScope([(cpu, 'config', config)]):
- yield
+ with temporaryPath() as filename:
+ config = make_config([
+ ('devel', 'cpu_profile_enable', enable),
+ ('devel', 'cpu_profile_filename', filename),
+ ('devel', 'cpu_profile_format', format),
+ ('devel', 'cpu_profile_clock', clock),
+ ('devel', 'cpu_profile_builtins', builtins),
+ ])
+ with MonkeyPatchScope([(cpu, 'config', config)]):
+ yield filename
-class ApplicationProfileTests(ProfileTests):
+class ApplicationProfileTests(VdsmTestCase):
- @MonkeyPatch(cpu, '_FILENAME', FILENAME)
def test_pstats_format(self):
requires_yappi()
- with env():
+ with env() as filename:
cpu.start()
cpu.is_running() # Let if profile something
cpu.stop()
- self.assertNotRaises(pstats.Stats, FILENAME)
+ self.assertNotRaises(pstats.Stats, filename)
- @MonkeyPatch(cpu, '_FILENAME', FILENAME)
def test_ystats_format(self):
requires_yappi()
- with env(format='ystat'):
+ with env(format='ystat') as filename:
cpu.start()
cpu.is_running() # Let if profile something
cpu.stop()
- self.assertNotRaises(open_ystats, FILENAME)
+ self.assertNotRaises(open_ystats, filename)
- @MonkeyPatch(cpu, '_FILENAME', FILENAME)
def test_with_builtins(self):
requires_yappi()
- with env(format='ystat', builtins='true'):
+ with env(format='ystat', builtins='true') as filename:
cpu.start()
dict()
cpu.stop()
- stats = open_ystats(FILENAME)
+ stats = open_ystats(filename)
self.assertTrue(find_module(stats, '__builtin__'))
- @MonkeyPatch(cpu, '_FILENAME', FILENAME)
def test_without_builtins(self):
requires_yappi()
- with env(format='ystat', builtins='false'):
+ with env(format='ystat', builtins='false') as filename:
cpu.start()
dict()
cpu.stop()
- stats = open_ystats(FILENAME)
+ stats = open_ystats(filename)
self.assertFalse(find_module(stats, '__builtin__'))
- @MonkeyPatch(cpu, '_FILENAME', FILENAME)
def test_cpu_clock(self):
requires_yappi()
- with env(format='ystat', clock='cpu', builtins='false'):
+ with env(format='ystat', clock='cpu', builtins='false') as filename:
cpu.start()
self.sleep(0.1)
cpu.stop()
- stats = open_ystats(FILENAME)
+ stats = open_ystats(filename)
name = function_name(self.sleep)
func = find_function(stats, __file__, name)
self.assertTrue(func.ttot < 0.1)
- @MonkeyPatch(cpu, '_FILENAME', FILENAME)
def test_wall_clock(self):
requires_yappi()
- with env(format='ystat', clock='wall', builtins='false'):
+ with env(format='ystat', clock='wall', builtins='false') as filename:
cpu.start()
self.sleep(0.1)
cpu.stop()
- stats = open_ystats(FILENAME)
+ stats = open_ystats(filename)
name = function_name(self.sleep)
func = find_function(stats, __file__, name)
self.assertTrue(func.ttot > 0.1)
- @MonkeyPatch(cpu, '_FILENAME', FILENAME)
def test_is_running(self):
requires_yappi()
with env():
@@ -163,101 +145,114 @@
time.sleep(seconds)
-class FunctionProfileTests(ProfileTests):
+class FunctionProfileTests(VdsmTestCase):
# Function profile must succeed if profile is disabled in config.
def test_profile_disabled(self):
requires_yappi()
- with env(enable='false'):
- self.profiled_function()
- self.assertNotRaises(pstats.Stats, FILENAME)
+ with env(enable='false') as filename:
+
+ @cpu.profile(filename)
+ def profiled_function():
+ self.assertTrue(cpu.is_running())
+
+ profiled_function()
+ self.assertNotRaises(pstats.Stats, filename)
# Function profile must fail if profile is enabled in config - we cannot
# use application wide profile and function profile in the same time.
- @MonkeyPatch(cpu, '_FILENAME', FILENAME)
def test_fail_if_Profile_is_running(self):
requires_yappi()
- with env(enable='true'):
+ with env(enable='true') as filename:
+
+ @cpu.profile(filename)
+ def profiled_function():
+ self.assertTrue(cpu.is_running())
+
cpu.start()
try:
- self.assertRaises(UsageError, self.profiled_function)
+ self.assertRaises(UsageError, profiled_function)
finally:
cpu.stop()
# It is not possible to call a profiled function from a profiled function.
def test_fail_recursive_profile(self):
requires_yappi()
- with env(enable='false'):
- self.assertRaises(UsageError, self.recursive_profile)
+ with env(enable='false') as filename:
+
+ @cpu.profile(filename)
+ def recursive_profile():
+ profiled_function()
+
+ @cpu.profile(filename)
+ def profiled_function():
+ self.assertTrue(cpu.is_running())
+
+ self.assertRaises(UsageError, recursive_profile)
def test_ystat_format(self):
requires_yappi()
- with env(enable='false'):
- self.ystat_format()
- self.assertNotRaises(open_ystats, FILENAME)
+ with env(enable='false') as filename:
+
+ @cpu.profile(filename, format="ystat")
+ def ystat_format():
+ pass
+
+ ystat_format()
+ self.assertNotRaises(open_ystats, filename)
def test_with_builtins(self):
requires_yappi()
- with env(enable='false'):
- self.with_builtins()
- stats = open_ystats(FILENAME)
+ with env(enable='false') as filename:
+
+ @cpu.profile(filename, format="ystat", builtins=True)
+ def with_builtins():
+ pass
+
+ with_builtins()
+ stats = open_ystats(filename)
self.assertTrue(find_module(stats, '__builtin__'))
def test_without_builtins(self):
requires_yappi()
- with env(enable='false'):
- self.without_builtins()
- stats = open_ystats(FILENAME)
+ with env(enable='false') as filename:
+
+ @cpu.profile(filename, format="ystat", builtins=False)
+ def without_builtins():
+ pass
+
+ without_builtins()
+ stats = open_ystats(filename)
self.assertFalse(find_module(stats, '__builtin__'))
def test_cpu_clock(self):
requires_yappi()
- with env(enable='false'):
- self.cpu_clock()
- stats = open_ystats(FILENAME)
- name = function_name(self.cpu_clock)
- func = find_function(stats, __file__, name)
+ with env(enable='false') as filename:
+
+ @cpu.profile(filename, format="ystat", clock="cpu")
+ def cpu_clock():
+ time.sleep(0.1)
+
+ cpu_clock()
+ stats = open_ystats(filename)
+ func = find_function(stats, __file__, "cpu_clock")
self.assertTrue(func.ttot < 0.1)
def test_wall_clock(self):
requires_yappi()
- with env(enable='false'):
- self.wall_clock()
- stats = open_ystats(FILENAME)
- name = function_name(self.wall_clock)
- func = find_function(stats, __file__, name)
+ with env(enable='false') as filename:
+
+ @cpu.profile(filename, format="ystat", clock="wall")
+ def wall_clock():
+ time.sleep(0.1)
+
+ wall_clock()
+ stats = open_ystats(filename)
+ func = find_function(stats, __file__, "wall_clock")
self.assertTrue(func.ttot > 0.1)
- @cpu.profile(FILENAME)
- def profiled_function(self):
- self.assertTrue(cpu.is_running())
- @cpu.profile(FILENAME)
- def recursive_profile(self):
- self.profiled_function()
-
- @cpu.profile(FILENAME, format="ystat")
- def ystat_format(self):
- pass
-
- @cpu.profile(FILENAME, format="ystat", builtins=False)
- def without_builtins(self):
- pass
-
- @cpu.profile(FILENAME, format="ystat", builtins=True)
- def with_builtins(self):
- pass
-
- @cpu.profile(FILENAME, format="ystat", clock="cpu")
- def cpu_clock(self):
- time.sleep(0.1)
-
- @cpu.profile(FILENAME, format="ystat", clock="wall")
- def wall_clock(self):
- time.sleep(0.1)
-
-
-class ThreadsProfileTests(ProfileTests):
+class ThreadsProfileTests(VdsmTestCase):
def setUp(self):
self.thread = None
@@ -267,9 +262,15 @@
def test_new_threads(self):
# The easy case - threads started after yappi was started
requires_yappi()
- with env(enable='false'):
- self.new_threads()
- stats = open_ystats(FILENAME)
+ with env(enable='false') as filename:
+
+ @cpu.profile(filename, format="ystat", threads=True)
+ def new_threads():
+ self.start_thread()
+ self.join_thread()
+
+ new_threads()
+ stats = open_ystats(filename)
name = function_name(self.worker_function)
func = find_function(stats, __file__, name)
self.assertEquals(func.ncall, 1)
@@ -277,35 +278,32 @@
def test_running_threads(self):
# The harder case - threads started before yappi was started
requires_yappi()
- with env(enable='false'):
+ with env(enable='false') as filename:
+
+ @cpu.profile(filename, format="ystat", threads=True)
+ def running_threads():
+ self.join_thread()
+
self.start_thread()
- self.running_threads()
- stats = open_ystats(FILENAME)
+ running_threads()
+ stats = open_ystats(filename)
name = function_name(self.worker_function)
func = find_function(stats, __file__, name)
self.assertEquals(func.ncall, 1)
def test_without_threads(self):
requires_yappi()
- with env(enable='false'):
- self.without_threads()
- stats = open_ystats(FILENAME)
+ with env(enable='false') as filename:
+
+ @cpu.profile(filename, format="ystat", threads=False)
+ def without_threads():
+ self.start_thread()
+ self.join_thread()
+
+ without_threads()
+ stats = open_ystats(filename)
name = function_name(self.worker_function)
self.assertRaises(NotFound, find_function, stats, __file__, name)
-
- @cpu.profile(FILENAME, format="ystat", threads=True)
- def new_threads(self):
- self.start_thread()
- self.join_thread()
-
- @cpu.profile(FILENAME, format="ystat", threads=True)
- def running_threads(self):
- self.join_thread()
-
- @cpu.profile(FILENAME, format="ystat", threads=False)
- def without_threads(self):
- self.start_thread()
- self.join_thread()
def start_thread(self):
self.thread = threading.Thread(target=self.worker)
--
To view, visit https://gerrit.ovirt.org/65255
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Id0a0800d08850fb236803813532210729ef16814
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Nir Soffer <nsoffer(a)redhat.com>
7 years, 8 months
Change in vdsm[master]: profiling: Add env context manager
by Nir Soffer
Nir Soffer has uploaded a new change for review.
Change subject: profiling: Add env context manager
......................................................................
profiling: Add env context manager
Instead of having multiple @MonkeyPatch() lines for each test, use a
context manager that creates the environment needed for the tests.
Change-Id: I936957c1fe96a69886dae63f45ffb463bb18279f
Signed-off-by: Nir Soffer <nsoffer(a)redhat.com>
---
M tests/cpu_profile_test.py
1 file changed, 114 insertions(+), 113 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/54/65254/1
diff --git a/tests/cpu_profile_test.py b/tests/cpu_profile_test.py
index 850d5e8..457dcda 100644
--- a/tests/cpu_profile_test.py
+++ b/tests/cpu_profile_test.py
@@ -24,10 +24,12 @@
import time
import threading
+from contextlib import contextmanager
+
from vdsm.profiling import cpu
from vdsm.profiling.errors import UsageError
-from monkeypatch import MonkeyPatch
+from monkeypatch import MonkeyPatch, MonkeyPatchScope
from nose.plugins.skip import SkipTest
from testlib import VdsmTestCase, make_config
@@ -55,106 +57,107 @@
raise
-def config(enable='true', format='pstat', clock='cpu', builtins='false'):
- return make_config([
+@contextmanager
+def env(enable='true', format='pstat', clock='cpu', builtins='false'):
+ config = make_config([
('devel', 'cpu_profile_enable', enable),
('devel', 'cpu_profile_format', format),
('devel', 'cpu_profile_clock', clock),
('devel', 'cpu_profile_builtins', builtins),
])
+ with MonkeyPatchScope([(cpu, 'config', config)]):
+ yield
class ApplicationProfileTests(ProfileTests):
- @MonkeyPatch(cpu, 'config', config())
@MonkeyPatch(cpu, '_FILENAME', FILENAME)
def test_pstats_format(self):
requires_yappi()
- cpu.start()
- cpu.is_running() # Let if profile something
- cpu.stop()
- self.assertNotRaises(pstats.Stats, FILENAME)
+ with env():
+ cpu.start()
+ cpu.is_running() # Let if profile something
+ cpu.stop()
+ self.assertNotRaises(pstats.Stats, FILENAME)
- @MonkeyPatch(cpu, 'config', config(format='ystat'))
@MonkeyPatch(cpu, '_FILENAME', FILENAME)
def test_ystats_format(self):
requires_yappi()
- cpu.start()
- cpu.is_running() # Let if profile something
- cpu.stop()
- self.assertNotRaises(open_ystats, FILENAME)
+ with env(format='ystat'):
+ cpu.start()
+ cpu.is_running() # Let if profile something
+ cpu.stop()
+ self.assertNotRaises(open_ystats, FILENAME)
- @MonkeyPatch(cpu, 'config', config(format='ystat', builtins='true'))
@MonkeyPatch(cpu, '_FILENAME', FILENAME)
def test_with_builtins(self):
requires_yappi()
- cpu.start()
- dict()
- cpu.stop()
- stats = open_ystats(FILENAME)
- self.assertTrue(find_module(stats, '__builtin__'))
+ with env(format='ystat', builtins='true'):
+ cpu.start()
+ dict()
+ cpu.stop()
+ stats = open_ystats(FILENAME)
+ self.assertTrue(find_module(stats, '__builtin__'))
- @MonkeyPatch(cpu, 'config', config(format='ystat', builtins='false'))
@MonkeyPatch(cpu, '_FILENAME', FILENAME)
def test_without_builtins(self):
requires_yappi()
- cpu.start()
- dict()
- cpu.stop()
- stats = open_ystats(FILENAME)
- self.assertFalse(find_module(stats, '__builtin__'))
+ with env(format='ystat', builtins='false'):
+ cpu.start()
+ dict()
+ cpu.stop()
+ stats = open_ystats(FILENAME)
+ self.assertFalse(find_module(stats, '__builtin__'))
- @MonkeyPatch(cpu, 'config',
- config(format='ystat', clock='cpu', builtins='false'))
@MonkeyPatch(cpu, '_FILENAME', FILENAME)
def test_cpu_clock(self):
requires_yappi()
- cpu.start()
- self.sleep(0.1)
- cpu.stop()
- stats = open_ystats(FILENAME)
- name = function_name(self.sleep)
- func = find_function(stats, __file__, name)
- self.assertTrue(func.ttot < 0.1)
+ with env(format='ystat', clock='cpu', builtins='false'):
+ cpu.start()
+ self.sleep(0.1)
+ cpu.stop()
+ stats = open_ystats(FILENAME)
+ name = function_name(self.sleep)
+ func = find_function(stats, __file__, name)
+ self.assertTrue(func.ttot < 0.1)
- @MonkeyPatch(cpu, 'config',
- config(format='ystat', clock='wall', builtins='false'))
@MonkeyPatch(cpu, '_FILENAME', FILENAME)
def test_wall_clock(self):
requires_yappi()
- cpu.start()
- self.sleep(0.1)
- cpu.stop()
- stats = open_ystats(FILENAME)
- name = function_name(self.sleep)
- func = find_function(stats, __file__, name)
- self.assertTrue(func.ttot > 0.1)
+ with env(format='ystat', clock='wall', builtins='false'):
+ cpu.start()
+ self.sleep(0.1)
+ cpu.stop()
+ stats = open_ystats(FILENAME)
+ name = function_name(self.sleep)
+ func = find_function(stats, __file__, name)
+ self.assertTrue(func.ttot > 0.1)
- @MonkeyPatch(cpu, 'config', config())
@MonkeyPatch(cpu, '_FILENAME', FILENAME)
def test_is_running(self):
requires_yappi()
- self.assertFalse(cpu.is_running())
- cpu.start()
- try:
- self.assertTrue(cpu.is_running())
- finally:
- cpu.stop()
- self.assertFalse(cpu.is_running())
+ with env():
+ self.assertFalse(cpu.is_running())
+ cpu.start()
+ try:
+ self.assertTrue(cpu.is_running())
+ finally:
+ cpu.stop()
+ self.assertFalse(cpu.is_running())
- @MonkeyPatch(cpu, 'config', config(enable='true'))
def test_is_enabled(self):
requires_yappi()
- self.assertTrue(cpu.is_enabled())
+ with env(enable='true'):
+ self.assertTrue(cpu.is_enabled())
# This must succeed even if yappi is not installed
- @MonkeyPatch(cpu, 'config', config(enable='false'))
def test_disabled(self):
- cpu.start()
- try:
- self.assertFalse(cpu.is_running())
- finally:
- cpu.stop()
+ with env(enable='false'):
+ cpu.start()
+ try:
+ self.assertFalse(cpu.is_running())
+ finally:
+ cpu.stop()
def sleep(self, seconds):
time.sleep(seconds)
@@ -163,69 +166,67 @@
class FunctionProfileTests(ProfileTests):
# Function profile must succeed if profile is disabled in config.
- @MonkeyPatch(cpu, 'config', config(enable='false'))
def test_profile_disabled(self):
requires_yappi()
- self.profiled_function()
- self.assertNotRaises(pstats.Stats, FILENAME)
+ with env(enable='false'):
+ self.profiled_function()
+ self.assertNotRaises(pstats.Stats, FILENAME)
# Function profile must fail if profile is enabled in config - we cannot
# use application wide profile and function profile in the same time.
- @MonkeyPatch(cpu, 'config', config(enable='true'))
@MonkeyPatch(cpu, '_FILENAME', FILENAME)
def test_fail_if_Profile_is_running(self):
requires_yappi()
- cpu.start()
- try:
- self.assertRaises(UsageError,
- self.profiled_function)
- finally:
- cpu.stop()
+ with env(enable='true'):
+ cpu.start()
+ try:
+ self.assertRaises(UsageError, self.profiled_function)
+ finally:
+ cpu.stop()
# It is not possible to call a profiled function from a profiled function.
- @MonkeyPatch(cpu, 'config', config(enable='false'))
def test_fail_recursive_profile(self):
requires_yappi()
- self.assertRaises(UsageError,
- self.recursive_profile)
+ with env(enable='false'):
+ self.assertRaises(UsageError, self.recursive_profile)
- @MonkeyPatch(cpu, 'config', config(enable='false'))
def test_ystat_format(self):
requires_yappi()
- self.ystat_format()
- self.assertNotRaises(open_ystats, FILENAME)
+ with env(enable='false'):
+ self.ystat_format()
+ self.assertNotRaises(open_ystats, FILENAME)
- @MonkeyPatch(cpu, 'config', config(enable='false'))
def test_with_builtins(self):
requires_yappi()
- self.with_builtins()
- stats = open_ystats(FILENAME)
- self.assertTrue(find_module(stats, '__builtin__'))
+ with env(enable='false'):
+ self.with_builtins()
+ stats = open_ystats(FILENAME)
+ self.assertTrue(find_module(stats, '__builtin__'))
- @MonkeyPatch(cpu, 'config', config(enable='false'))
def test_without_builtins(self):
requires_yappi()
- self.without_builtins()
- stats = open_ystats(FILENAME)
- self.assertFalse(find_module(stats, '__builtin__'))
+ with env(enable='false'):
+ self.without_builtins()
+ stats = open_ystats(FILENAME)
+ self.assertFalse(find_module(stats, '__builtin__'))
- @MonkeyPatch(cpu, 'config', 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)
+ with env(enable='false'):
+ 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(cpu, 'config', 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)
+ with env(enable='false'):
+ 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)
@cpu.profile(FILENAME)
def profiled_function(self):
@@ -263,34 +264,34 @@
self.ready = threading.Event()
self.resume = threading.Event()
- @MonkeyPatch(cpu, 'config', 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)
+ with env(enable='false'):
+ 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(cpu, 'config', 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)
+ with env(enable='false'):
+ 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(cpu, 'config', 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)
+ with env(enable='false'):
+ self.without_threads()
+ stats = open_ystats(FILENAME)
+ name = function_name(self.worker_function)
+ self.assertRaises(NotFound, find_function, stats, __file__, name)
@cpu.profile(FILENAME, format="ystat", threads=True)
def new_threads(self):
--
To view, visit https://gerrit.ovirt.org/65254
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I936957c1fe96a69886dae63f45ffb463bb18279f
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Nir Soffer <nsoffer(a)redhat.com>
7 years, 8 months
Change in vdsm[master]: profiling: Decouple cpu profiling from vdsm config
by Nir Soffer
Nir Soffer has uploaded a new change for review.
Change subject: profiling: Decouple cpu profiling from vdsm config
......................................................................
profiling: Decouple cpu profiling from vdsm config
Previously we accessed vdsm configuration to set module defaults during
import. This make it impossible to use the module from another
application like supervdsm or ovirt-ha-agent.
The configuration is accessed now when starting an application wide
profile using the start() and stop() interface.
This change also simplify the tests, we can mock (almost) everything via
the module config.
vdsm configuration is still loaded when importing the profiler module,
more work is needed to avoid this.
Change-Id: I711c7947534841f77b88c6067c992ca1a3a42fdb
Signed-off-by: Nir Soffer <nsoffer(a)redhat.com>
---
M lib/vdsm/profiling/cpu.py
M tests/cpu_profile_test.py
2 files changed, 37 insertions(+), 56 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/53/65253/1
diff --git a/lib/vdsm/profiling/cpu.py b/lib/vdsm/profiling/cpu.py
index 286fcdd..427f1db 100644
--- a/lib/vdsm/profiling/cpu.py
+++ b/lib/vdsm/profiling/cpu.py
@@ -39,10 +39,6 @@
# Defaults
_FILENAME = os.path.join(constants.P_VDSM_RUN, 'vdsmd.prof')
-_FORMAT = config.get('devel', 'cpu_profile_format')
-_BUILTINS = config.getboolean('devel', 'cpu_profile_builtins')
-_CLOCK = config.get('devel', 'cpu_profile_clock')
-_THREADS = True
_lock = threading.Lock()
_profiler = None
@@ -105,8 +101,12 @@
with _lock:
if _profiler:
raise UsageError('CPU profiler is already running')
- _profiler = Profiler(_FILENAME, format=_FORMAT, clock=_CLOCK,
- builtins=_BUILTINS, threads=_THREADS)
+ _profiler = Profiler(
+ _FILENAME,
+ format=config.get('devel', 'cpu_profile_format'),
+ clock=config.get('devel', 'cpu_profile_clock'),
+ builtins=config.getboolean('devel', 'cpu_profile_builtins'),
+ threads=True)
_profiler.start()
@@ -128,8 +128,8 @@
return yappi and yappi.is_running()
-def profile(filename, format=_FORMAT, clock=_CLOCK, builtins=_BUILTINS,
- threads=_THREADS):
+def profile(filename, format='pstat', clock='cpu', builtins=True,
+ threads=True):
"""
Profile decorated function, saving profile to filename using format.
diff --git a/tests/cpu_profile_test.py b/tests/cpu_profile_test.py
index 882b7b6..850d5e8 100644
--- a/tests/cpu_profile_test.py
+++ b/tests/cpu_profile_test.py
@@ -55,12 +55,19 @@
raise
+def config(enable='true', format='pstat', clock='cpu', builtins='false'):
+ return make_config([
+ ('devel', 'cpu_profile_enable', enable),
+ ('devel', 'cpu_profile_format', format),
+ ('devel', 'cpu_profile_clock', clock),
+ ('devel', 'cpu_profile_builtins', builtins),
+ ])
+
+
class ApplicationProfileTests(ProfileTests):
- @MonkeyPatch(cpu, 'config',
- make_config([('devel', 'cpu_profile_enable', 'true')]))
+ @MonkeyPatch(cpu, 'config', config())
@MonkeyPatch(cpu, '_FILENAME', FILENAME)
- @MonkeyPatch(cpu, '_FORMAT', 'pstat')
def test_pstats_format(self):
requires_yappi()
cpu.start()
@@ -68,10 +75,8 @@
cpu.stop()
self.assertNotRaises(pstats.Stats, FILENAME)
- @MonkeyPatch(cpu, 'config',
- make_config([('devel', 'cpu_profile_enable', 'true')]))
+ @MonkeyPatch(cpu, 'config', config(format='ystat'))
@MonkeyPatch(cpu, '_FILENAME', FILENAME)
- @MonkeyPatch(cpu, '_FORMAT', 'ystat')
def test_ystats_format(self):
requires_yappi()
cpu.start()
@@ -79,11 +84,8 @@
cpu.stop()
self.assertNotRaises(open_ystats, FILENAME)
- @MonkeyPatch(cpu, 'config',
- make_config([('devel', 'cpu_profile_enable', 'true')]))
+ @MonkeyPatch(cpu, 'config', config(format='ystat', builtins='true'))
@MonkeyPatch(cpu, '_FILENAME', FILENAME)
- @MonkeyPatch(cpu, '_FORMAT', 'ystat')
- @MonkeyPatch(cpu, '_BUILTINS', True)
def test_with_builtins(self):
requires_yappi()
cpu.start()
@@ -92,11 +94,8 @@
stats = open_ystats(FILENAME)
self.assertTrue(find_module(stats, '__builtin__'))
- @MonkeyPatch(cpu, 'config',
- make_config([('devel', 'cpu_profile_enable', 'true')]))
+ @MonkeyPatch(cpu, 'config', config(format='ystat', builtins='false'))
@MonkeyPatch(cpu, '_FILENAME', FILENAME)
- @MonkeyPatch(cpu, '_FORMAT', 'ystat')
- @MonkeyPatch(cpu, '_BUILTINS', False)
def test_without_builtins(self):
requires_yappi()
cpu.start()
@@ -106,10 +105,8 @@
self.assertFalse(find_module(stats, '__builtin__'))
@MonkeyPatch(cpu, 'config',
- make_config([('devel', 'cpu_profile_enable', 'true')]))
+ config(format='ystat', clock='cpu', builtins='false'))
@MonkeyPatch(cpu, '_FILENAME', FILENAME)
- @MonkeyPatch(cpu, '_FORMAT', 'ystat')
- @MonkeyPatch(cpu, '_CLOCK', 'cpu')
def test_cpu_clock(self):
requires_yappi()
cpu.start()
@@ -121,10 +118,8 @@
self.assertTrue(func.ttot < 0.1)
@MonkeyPatch(cpu, 'config',
- make_config([('devel', 'cpu_profile_enable', 'true')]))
+ config(format='ystat', clock='wall', builtins='false'))
@MonkeyPatch(cpu, '_FILENAME', FILENAME)
- @MonkeyPatch(cpu, '_FORMAT', 'ystat')
- @MonkeyPatch(cpu, '_CLOCK', 'wall')
def test_wall_clock(self):
requires_yappi()
cpu.start()
@@ -135,8 +130,7 @@
func = find_function(stats, __file__, name)
self.assertTrue(func.ttot > 0.1)
- @MonkeyPatch(cpu, 'config',
- make_config([('devel', 'cpu_profile_enable', 'true')]))
+ @MonkeyPatch(cpu, 'config', config())
@MonkeyPatch(cpu, '_FILENAME', FILENAME)
def test_is_running(self):
requires_yappi()
@@ -148,15 +142,13 @@
cpu.stop()
self.assertFalse(cpu.is_running())
- @MonkeyPatch(cpu, 'config',
- make_config([('devel', 'cpu_profile_enable', 'true')]))
+ @MonkeyPatch(cpu, 'config', config(enable='true'))
def test_is_enabled(self):
requires_yappi()
self.assertTrue(cpu.is_enabled())
# This must succeed even if yappi is not installed
- @MonkeyPatch(cpu, 'config',
- make_config([('devel', 'cpu_profile_enable', 'false')]))
+ @MonkeyPatch(cpu, 'config', config(enable='false'))
def test_disabled(self):
cpu.start()
try:
@@ -171,8 +163,7 @@
class FunctionProfileTests(ProfileTests):
# Function profile must succeed if profile is disabled in config.
- @MonkeyPatch(cpu, 'config',
- make_config([('devel', 'cpu_profile_enable', 'false')]))
+ @MonkeyPatch(cpu, 'config', config(enable='false'))
def test_profile_disabled(self):
requires_yappi()
self.profiled_function()
@@ -180,8 +171,7 @@
# Function profile must fail if profile is enabled in config - we cannot
# use application wide profile and function profile in the same time.
- @MonkeyPatch(cpu, 'config',
- make_config([('devel', 'cpu_profile_enable', 'true')]))
+ @MonkeyPatch(cpu, 'config', config(enable='true'))
@MonkeyPatch(cpu, '_FILENAME', FILENAME)
def test_fail_if_Profile_is_running(self):
requires_yappi()
@@ -193,38 +183,33 @@
cpu.stop()
# It is not possible to call a profiled function from a profiled function.
- @MonkeyPatch(cpu, 'config',
- make_config([('devel', 'cpu_profile_enable', 'false')]))
+ @MonkeyPatch(cpu, 'config', config(enable='false'))
def test_fail_recursive_profile(self):
requires_yappi()
self.assertRaises(UsageError,
self.recursive_profile)
- @MonkeyPatch(cpu, 'config',
- make_config([('devel', 'cpu_profile_enable', 'false')]))
+ @MonkeyPatch(cpu, 'config', config(enable='false'))
def test_ystat_format(self):
requires_yappi()
self.ystat_format()
self.assertNotRaises(open_ystats, FILENAME)
- @MonkeyPatch(cpu, 'config',
- make_config([('devel', 'cpu_profile_enable', 'false')]))
+ @MonkeyPatch(cpu, 'config', config(enable='false'))
def test_with_builtins(self):
requires_yappi()
self.with_builtins()
stats = open_ystats(FILENAME)
self.assertTrue(find_module(stats, '__builtin__'))
- @MonkeyPatch(cpu, 'config',
- make_config([('devel', 'cpu_profile_enable', 'false')]))
+ @MonkeyPatch(cpu, 'config', config(enable='false'))
def test_without_builtins(self):
requires_yappi()
self.without_builtins()
stats = open_ystats(FILENAME)
self.assertFalse(find_module(stats, '__builtin__'))
- @MonkeyPatch(cpu, 'config',
- make_config([('devel', 'cpu_profile_enable', 'false')]))
+ @MonkeyPatch(cpu, 'config', config(enable='false'))
def test_cpu_clock(self):
requires_yappi()
self.cpu_clock()
@@ -233,8 +218,7 @@
func = find_function(stats, __file__, name)
self.assertTrue(func.ttot < 0.1)
- @MonkeyPatch(cpu, 'config',
- make_config([('devel', 'cpu_profile_enable', 'false')]))
+ @MonkeyPatch(cpu, 'config', config(enable='false'))
def test_wall_clock(self):
requires_yappi()
self.wall_clock()
@@ -279,8 +263,7 @@
self.ready = threading.Event()
self.resume = threading.Event()
- @MonkeyPatch(cpu, 'config',
- make_config([('devel', 'cpu_profile_enable', 'false')]))
+ @MonkeyPatch(cpu, 'config', config(enable='false'))
def test_new_threads(self):
# The easy case - threads started after yappi was started
requires_yappi()
@@ -290,8 +273,7 @@
func = find_function(stats, __file__, name)
self.assertEquals(func.ncall, 1)
- @MonkeyPatch(cpu, 'config',
- make_config([('devel', 'cpu_profile_enable', 'false')]))
+ @MonkeyPatch(cpu, 'config', config(enable='false'))
def test_running_threads(self):
# The harder case - threads started before yappi was started
requires_yappi()
@@ -302,8 +284,7 @@
func = find_function(stats, __file__, name)
self.assertEquals(func.ncall, 1)
- @MonkeyPatch(cpu, 'config',
- make_config([('devel', 'cpu_profile_enable', 'false')]))
+ @MonkeyPatch(cpu, 'config', config(enable='false'))
def test_without_threads(self):
requires_yappi()
self.without_threads()
--
To view, visit https://gerrit.ovirt.org/65253
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I711c7947534841f77b88c6067c992ca1a3a42fdb
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Nir Soffer <nsoffer(a)redhat.com>
7 years, 8 months
Change in vdsm[master]: profiling: Add generic Profiler class
by Nir Soffer
Nir Soffer has uploaded a new change for review.
Change subject: profiling: Add generic Profiler class
......................................................................
profiling: Add generic Profiler class
Current profiling solution is usable only by vdsm, writing the profile
to /run/vdsm/vdsmd.prof, and assuming vdsm configuration.
This patch adds a generic Profiler class which can be used by any
application, for example supervdsm or ovirt-ha-agent.
Example usage:
from vdsm.profiling import cpu
...
profiler = cpu.Profiler("/run/myapp/profile.pstat")
profiler.start()
...
profiler.stop()
Change-Id: I66b7e872959ac2c26c003d26f1fcde2926f47969
Signed-off-by: Nir Soffer <nsoffer(a)redhat.com>
---
M lib/vdsm/profiling/cpu.py
1 file changed, 65 insertions(+), 32 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/52/65252/1
diff --git a/lib/vdsm/profiling/cpu.py b/lib/vdsm/profiling/cpu.py
index 47f0ecd..286fcdd 100644
--- a/lib/vdsm/profiling/cpu.py
+++ b/lib/vdsm/profiling/cpu.py
@@ -45,18 +45,78 @@
_THREADS = True
_lock = threading.Lock()
+_profiler = None
+
+
+class Profiler(object):
+
+ def __init__(self, filename, format='pstat', clock='cpu', builtins=True,
+ threads=True):
+ self.filename = filename
+ self.format = format
+ self.clock = clock
+ self.builtins = builtins
+ self.threads = threads
+
+ def start(self):
+ # Lazy import so we do not effect runtime environment if profiling is
+ # not used.
+ global yappi
+ import yappi
+
+ # yappi start semantics are a bit too liberal, returning success if
+ # yappi is already started, happily having too different code paths
+ # that thinks they own the single process profiler.
+ if yappi.is_running():
+ raise UsageError('CPU profiler is already running')
+
+ logging.info("Starting CPU profiling")
+ yappi.set_clock_type(self.clock)
+ yappi.start(builtins=self.builtins, profile_threads=self.threads)
+
+ def stop(self):
+ if not yappi.is_running():
+ raise UsageError("CPU profiler is not running")
+
+ logging.info("Stopping CPU profiling")
+ yappi.stop()
+ stats = yappi.get_func_stats()
+ stats.save(self.filename, self.format)
+ yappi.clear_stats()
+
+ def __enter__(self):
+ self.start()
+ return self
+
+ def __exit__(self, t, v, tb):
+ try:
+ self.stop()
+ except Exception:
+ if t is None:
+ raise
+ # Do not hide original exception
+ logging.exception("Error stopping profiler")
def start():
""" Starts application wide CPU profiling """
+ global _profiler
if is_enabled():
- _start_profiling(_CLOCK, _BUILTINS, _THREADS)
+ with _lock:
+ if _profiler:
+ raise UsageError('CPU profiler is already running')
+ _profiler = Profiler(_FILENAME, format=_FORMAT, clock=_CLOCK,
+ builtins=_BUILTINS, threads=_THREADS)
+ _profiler.start()
def stop():
""" Stops application wide CPU profiling """
+ global _profiler
if is_enabled():
- _stop_profiling(_FILENAME, _FORMAT)
+ with _lock:
+ _profiler.stop()
+ _profiler = None
def is_enabled():
@@ -79,36 +139,9 @@
def decorator(f):
@wraps(f)
def wrapper(*a, **kw):
- _start_profiling(clock, builtins, threads)
- try:
+ profiler = Profiler(filename, format=format, clock=clock,
+ builtins=builtins, threads=threads)
+ with profiler:
return f(*a, **kw)
- finally:
- _stop_profiling(filename, format)
return wrapper
return decorator
-
-
-def _start_profiling(clock, builtins, threads):
- global yappi
- logging.debug("Starting CPU profiling")
-
- import yappi
-
- with _lock:
- # yappi start semantics are a bit too liberal, returning success if
- # yappi is already started, happily having too different code paths
- # that thinks they own the single process profiler.
- if yappi.is_running():
- raise UsageError('CPU profiler is already running')
- yappi.set_clock_type(clock)
- yappi.start(builtins=builtins, profile_threads=threads)
-
-
-def _stop_profiling(filename, format):
- logging.debug("Stopping CPU profiling")
- with _lock:
- if yappi.is_running():
- yappi.stop()
- stats = yappi.get_func_stats()
- stats.save(filename, format)
- yappi.clear_stats()
--
To view, visit https://gerrit.ovirt.org/65252
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I66b7e872959ac2c26c003d26f1fcde2926f47969
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Nir Soffer <nsoffer(a)redhat.com>
7 years, 8 months
Change in vdsm[master]: properties: py3: properties.py and properties_test.py compli...
by automation@ovirt.org
gerrit-hooks has posted comments on this change.
Change subject: properties: py3: properties.py and properties_test.py compliance
......................................................................
Patch Set 3:
* Update tracker: IGNORE, no Bug-Url found
--
To view, visit https://gerrit.ovirt.org/63230
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: comment
Gerrit-Change-Id: Id3f49dd718d786c4a98b06c7b8757ce5a9eb6d2a
Gerrit-PatchSet: 3
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Leon Goldberg <leon.otium(a)gmail.com>
Gerrit-Reviewer: Dan Kenigsberg <danken(a)redhat.com>
Gerrit-Reviewer: Francesco Romani <fromani(a)redhat.com>
Gerrit-Reviewer: Jenkins CI
Gerrit-Reviewer: Leon Goldberg <leon.otium(a)gmail.com>
Gerrit-Reviewer: Nir Soffer <nsoffer(a)redhat.com>
Gerrit-Reviewer: Piotr Kliczewski <piotr.kliczewski(a)gmail.com>
Gerrit-Reviewer: Tomas Golembiovsky <tgolembi(a)redhat.com>
Gerrit-Reviewer: gerrit-hooks <automation(a)ovirt.org>
Gerrit-HasComments: No
7 years, 8 months
Change in vdsm[master]: properties: py3: properties.py and properties_test.py compli...
by Nir Soffer
Nir Soffer has abandoned this change.
Change subject: properties: py3: properties.py and properties_test.py compliance
......................................................................
Abandoned
All the changes in this patch are already merged in separate patches.
--
To view, visit https://gerrit.ovirt.org/63230
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: abandon
Gerrit-Change-Id: Id3f49dd718d786c4a98b06c7b8757ce5a9eb6d2a
Gerrit-PatchSet: 3
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Leon Goldberg <leon.otium(a)gmail.com>
Gerrit-Reviewer: Dan Kenigsberg <danken(a)redhat.com>
Gerrit-Reviewer: Francesco Romani <fromani(a)redhat.com>
Gerrit-Reviewer: Jenkins CI
Gerrit-Reviewer: Leon Goldberg <leon.otium(a)gmail.com>
Gerrit-Reviewer: Nir Soffer <nsoffer(a)redhat.com>
Gerrit-Reviewer: Piotr Kliczewski <piotr.kliczewski(a)gmail.com>
Gerrit-Reviewer: Tomas Golembiovsky <tgolembi(a)redhat.com>
Gerrit-Reviewer: gerrit-hooks <automation(a)ovirt.org>
7 years, 8 months
Change in vdsm[master]: properties: Enable tests on python 3
by Nir Soffer
Nir Soffer has uploaded a new change for review.
Change subject: properties: Enable tests on python 3
......................................................................
properties: Enable tests on python 3
Change-Id: I7f8f9f218a1bec57d9158a01a1a024adaa5e27b1
Signed-off-by: Nir Soffer <nsoffer(a)redhat.com>
---
M tests/Makefile.am
1 file changed, 0 insertions(+), 1 deletion(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/57/65257/1
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 1ee0b45..28a3cfe 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -207,7 +207,6 @@
outOfProcessTests.py \
periodicTests.py \
persistentDictTests.py \
- properties_test.py \
protocoldetectorTests.py \
qemuimg_test.py \
storage_resourcemanager_test.py \
--
To view, visit https://gerrit.ovirt.org/65257
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I7f8f9f218a1bec57d9158a01a1a024adaa5e27b1
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Nir Soffer <nsoffer(a)redhat.com>
7 years, 8 months
Change in vdsm[master]: properties: Python 3 compliant base64 usage
by automation@ovirt.org
gerrit-hooks has posted comments on this change.
Change subject: properties: Python 3 compliant base64 usage
......................................................................
Patch Set 3:
* Update tracker: IGNORE, no Bug-Url found
* Set MODIFIED::IGNORE, no Bug-Url found.
--
To view, visit https://gerrit.ovirt.org/63714
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: comment
Gerrit-Change-Id: I6f63b33a44e465806e00ed3de0b1e55e8a01005f
Gerrit-PatchSet: 3
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Leon Goldberg <leon.otium(a)gmail.com>
Gerrit-Reviewer: Jenkins CI
Gerrit-Reviewer: Nir Soffer <nsoffer(a)redhat.com>
Gerrit-Reviewer: gerrit-hooks <automation(a)ovirt.org>
Gerrit-HasComments: No
7 years, 8 months