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