You are viewing a plain text version of this content. The canonical link for it is here.
Posted to tashi-commits@incubator.apache.org by mr...@apache.org on 2009/05/25 19:05:41 UTC
svn commit: r778468 - in /incubator/tashi/trunk: etc/TashiDefaults.cfg
src/tashi/nodemanager/vmcontrol/qemu.py
src/tashi/nodemanager/vmcontrol/vmcontrolinterface.py
Author: mryan3
Date: Mon May 25 19:05:41 2009
New Revision: 778468
URL: http://svn.apache.org/viewvc?rev=778468&view=rev
Log:
Initial code to collect stats on a per-vm basis with the Qemu backend
The code is currently disabled by default based on a config file parameter
Modified:
incubator/tashi/trunk/etc/TashiDefaults.cfg
incubator/tashi/trunk/src/tashi/nodemanager/vmcontrol/qemu.py
incubator/tashi/trunk/src/tashi/nodemanager/vmcontrol/vmcontrolinterface.py
Modified: incubator/tashi/trunk/etc/TashiDefaults.cfg
URL: http://svn.apache.org/viewvc/incubator/tashi/trunk/etc/TashiDefaults.cfg?rev=778468&r1=778467&r2=778468&view=diff
==============================================================================
--- incubator/tashi/trunk/etc/TashiDefaults.cfg (original)
+++ incubator/tashi/trunk/etc/TashiDefaults.cfg Mon May 25 19:05:41 2009
@@ -85,6 +85,7 @@
migrateTimeout = 300.0
maxParallelMigrations = 10
useMigrateArgument = False
+statsInterval = 0.0
[XenPV]
vmNamePrefix = tashi
Modified: incubator/tashi/trunk/src/tashi/nodemanager/vmcontrol/qemu.py
URL: http://svn.apache.org/viewvc/incubator/tashi/trunk/src/tashi/nodemanager/vmcontrol/qemu.py?rev=778468&r1=778467&r2=778468&view=diff
==============================================================================
--- incubator/tashi/trunk/src/tashi/nodemanager/vmcontrol/qemu.py (original)
+++ incubator/tashi/trunk/src/tashi/nodemanager/vmcontrol/qemu.py Mon May 25 19:05:41 2009
@@ -29,7 +29,7 @@
from tashi.services.ttypes import *
from tashi.util import broken, logged, scrubString, boolean
-from tashi import version
+from tashi import version, stringPartition
from vmcontrolinterface import VmControlInterface
log = logging.getLogger(__file__)
@@ -92,6 +92,7 @@
self.monitorTimeout = float(self.config.get("Qemu", "monitorTimeout"))
self.migrateTimeout = float(self.config.get("Qemu", "migrateTimeout"))
self.useMigrateArgument = boolean(self.config.get("Qemu", "useMigrateArgument"))
+ self.statsInterval = float(self.config.get("Qemu", "statsInterval"))
self.controlledVMs = {}
self.usedPorts = []
self.usedPortsLock = threading.Lock()
@@ -100,12 +101,15 @@
self.consolePort = 10000
self.consolePortLock = threading.Lock()
self.migrationSemaphore = threading.Semaphore(int(self.config.get("Qemu", "maxParallelMigrations")))
+ self.stats = {}
try:
os.mkdir(self.INFO_DIR)
except:
pass
self.scanInfoDir()
threading.Thread(target=self.pollVMsLoop).start()
+ if (self.statsInterval > 0):
+ threading.Thread(target=self.statsThread).start()
class anonClass:
def __init__(self, **attrs):
@@ -132,6 +136,10 @@
os.unlink(self.INFO_DIR + "/%d"%(vmId))
child = controlledVMs[vmId]
del controlledVMs[vmId]
+ try:
+ del self.stats[vmId]
+ except:
+ pass
if (child.vncPort >= 0):
self.vncPortLock.acquire()
self.vncPorts.remove(child.vncPort)
@@ -577,3 +585,65 @@
def listVms(self):
return self.controlledVMs.keys()
+
+ def statsThread(self):
+ ticksPerSecond = float(os.sysconf('SC_CLK_TCK'))
+ netStats = {}
+ cpuStats = {}
+ last = time.time() - self.statsInterval
+ while True:
+ now = time.time()
+ try:
+ f = open("/proc/net/dev")
+ netData = f.readlines()
+ f.close()
+ for l in netData:
+ if (l.find("tashi") != -1):
+ (dev, sep, ld) = stringPartition(l, ":")
+ dev = dev.strip()
+ ws = ld.split()
+ (recvMBs, sendMBs, lastRecvBytes, lastSendBytes) = netStats.get(dev, (0.0, 0.0, 0.0, 0.0))
+ recvBytes = float(ws[0])
+ sendBytes = float(ws[8])
+ if (recvBytes < lastRecvBytes):
+ if (lastRecvBytes > 2**32):
+ lastRecvBytes = lastRecvBytes - 2**64
+ else:
+ lastRecvBytes = lastRecvBytes - 2**32
+ if (sendBytes < lastSendBytes):
+ if (lastSendBytes > 2**32):
+ lastSendBytes = lastSendBytes - 2**64
+ else:
+ lastSendBytes = lastSendBytes - 2**32
+ recvMBs = (recvBytes-lastRecvBytes)/(now-last)/1024.0/1024.0
+ sendMBs = (sendBytes-lastSendBytes)/(now-last)/1024.0/1024.0
+ netStats[dev] = (recvMBs, sendMBs, recvBytes, sendBytes)
+ for vmId in self.controlledVMs:
+ f = open("/proc/%d/stat" % (vmId))
+ procData = f.read()
+ f.close()
+ ws = procData.strip().split()
+ userTicks = float(ws[13])
+ sysTicks = float(ws[14])
+ myTicks = userTicks + sysTicks
+ vsize = (int(ws[22]))/1024.0/1024.0
+ rss = (int(ws[23])*4096)/1024.0/1024.0
+ cpuSeconds = myTicks/ticksPerSecond
+ lastCpuSeconds = cpuStats.get(vmId, 0.0)
+ cpuLoad = (cpuSeconds - lastCpuSeconds)/(now - last)
+ cpuStats[vmId] = cpuSeconds
+ child = self.controlledVMs[vmId]
+ netDev = "tashi%d" % (child.instance.id)
+ (recvMBs, sendMBs, recvBytes, sendBytes) = netStats.get(netDev, (0.0, 0.0, 0.0, 0.0))
+ self.stats[vmId] = self.stats.get(vmId, {})
+ self.stats[vmId]['cpuLoad'] = cpuLoad
+ self.stats[vmId]['rss'] = rss
+ self.stats[vmId]['recvMBs'] = sendMBs
+ self.stats[vmId]['sendMBs'] = recvMBs
+ except:
+ log.exception("statsThread threw an exception")
+ last = now
+ time.sleep(self.statsInterval)
+
+ def getStats(self, vmId):
+ return self.stats.get(vmId, {})
Modified: incubator/tashi/trunk/src/tashi/nodemanager/vmcontrol/vmcontrolinterface.py
URL: http://svn.apache.org/viewvc/incubator/tashi/trunk/src/tashi/nodemanager/vmcontrol/vmcontrolinterface.py?rev=778468&r1=778467&r2=778468&view=diff
==============================================================================
--- incubator/tashi/trunk/src/tashi/nodemanager/vmcontrol/vmcontrolinterface.py (original)
+++ incubator/tashi/trunk/src/tashi/nodemanager/vmcontrol/vmcontrolinterface.py Mon May 25 19:05:41 2009
@@ -83,3 +83,8 @@
def getHostInfo(self, service):
"""Returns a Host object for the current host"""
raise NotImplementedError
+
+ def getStats(self, vmId):
+ """Returns a dictionary containing stats about the guest (ie.
+ CPU utilization, network utilization, memory usage, etc.)"""
+ raise NotImplementedError