$OpenBSD: patch-admin_SystemStats_py,v 1.1 2010/12/20 07:51:58 ajacoutot Exp $
--- admin/SystemStats.py.orig	Mon Dec 13 08:01:04 2010
+++ admin/SystemStats.py	Fri Dec 17 06:20:44 2010
@@ -45,6 +45,8 @@ def get_system_stats():
             _stats = System_stats__Darwin()
         elif sys.platform.startswith ('freebsd'):
             _stats = System_stats__FreeBSD()
+        elif sys.platform.startswith ('openbsd4'):
+            _stats = System_stats__OpenBSD()
 
     assert _stats, "Not implemented"
     return _stats
@@ -398,6 +400,119 @@ class System_stats__FreeBSD (Thread, System_stats):
 	if not len(values) == 18:
 		return
 
+        self.mem.free  = int(values[4])
+        self.mem.used  = self.mem.total - self.mem.free
+
+    def run (self):
+        while True:
+            self._read_cpu()
+            self._read_memory()
+            time.sleep (self.CHECK_INTERVAL)
+
+# OpenBSD implementation
+class System_stats__OpenBSD (Thread, System_stats):
+    CHECK_INTERVAL = 2
+
+    def __init__ (self):
+        Thread.__init__ (self)
+        System_stats.__init__ (self)
+
+        self.vmstat_fd = subprocess.Popen ("/usr/bin/vmstat -w%d" %(self.CHECK_INTERVAL),
+                                            shell=True, stdout = subprocess.PIPE, close_fds=True )
+
+        # Read valid values
+        self._read_hostname()
+        self._read_cpu()
+        self._read_memory()
+        self._read_cpu_and_mem_info()
+
+        self.start()
+
+    def _read_hostname (self):
+        # First try: uname()
+	self.hostname = os.uname()[1]
+        if self.hostname:
+            return
+
+        # Second try: sysctl()
+        ret = popen.popen_sync ("/sbin/sysctl -n kern.hostname")
+        self.hostname = ret['stdout'].rstrip()
+        if self.hostname:
+            return
+
+        # Could not figure it out
+        self.hostname = "Unknown"
+
+    def _read_cpu_and_mem_info (self):
+        # Execute sysctl
+        ret = popen.popen_sync ("/sbin/sysctl hw.ncpufound hw.ncpu hw.cpuspeed hw.physmem")
+        lines = filter (lambda x: x, ret['stdout'].split('\n'))
+
+        # Parse output
+
+	# cpu related
+        ncpus = 0
+        vcpus = 0
+	clock = ''
+
+        # mem related
+	pmem = 0
+
+	for line in lines:
+	    parts = line.split("=")
+	    if parts[0] == 'hw.ncpufound':
+		ncpus = int(parts[1])
+            elif parts[0] == 'hw.ncpu':
+		vcpus = parts[1]
+            elif parts[0] == 'hw.cpuspeed':
+		clock = parts[1]
+            elif parts[0] == 'hw.physmem':
+		pmem = parts[1]
+
+	# Deal with cores
+        if vcpus:
+            self.cpu.num   = ncpus
+            self.cpu.cores = vcpus
+        else:
+            self.cpu.num   = int (ncpus)
+            self.cpu.cores = int (ncpus)
+
+        # Global speed
+	self.cpu.speed = '%s MHz' %(clock)
+
+	# Physical mem
+	self.mem.total =  int (pmem) / 1024
+
+    def _read_cpu (self):
+	# Read a new line
+        line = self.vmstat_fd.stdout.readline().rstrip('\n')
+
+        # Skip headers
+	if len(filter (lambda x: x not in " .0123456789", line)):
+	    return
+
+        # Parse
+	parts = filter (lambda x: x, line.split(' '))
+        
+	# For OpenBSD there are 19 fields output from vmstat
+	if not len(parts) == 19:
+		return
+
+	self.cpu.idle  = int(parts[18])
+	self.cpu.usage = 100 - self.cpu.idle
+	
+    def _read_memory (self):
+	# Read a new line
+        line = self.vmstat_fd.stdout.readline().rstrip('\n')
+        # Skip headers
+        if len(filter (lambda x: x not in " .0123456789", line)):
+            return
+
+        # Parse
+        values = filter (lambda x: x, line.split(' '))
+
+	if not len(values) == 19:
+		return
         self.mem.free  = int(values[4])
         self.mem.used  = self.mem.total - self.mem.free
 
