[PATCH] CPU module, fixes to disk module and service module

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch introduces a new module, cpu.py and includes fixes for disk.py and service.py.

cpu.py exposes cpu information. It has two methods:
* cpu_sample_percentage - gets the average cpu usage, returns per cpu percentage for user, nice, system, idle, iowait and irq.
* jiffies - fetches cpu statistics from /proc/stat and returns them

disk.py modifications
* Add filesystem type returned by disk.usage()

service.py modifications
* chkconfig and /sbin/service now run with environment variable LANG=C, tools were returning internationalized strings which wouldn't parse correctly.
* Rewrote get_running(), now lists scripts from /etc/init.d and runs status itself instead of running /sbin/service --status-all. /sbin/service was returning internationalized strings and ignoring LANG variable.


--
Tomas Edwardsson





diff --git a/func/minion/modules/cpu.py b/func/minion/modules/cpu.py
new file mode 100644
index 0000000..724be31
--- /dev/null
+++ b/func/minion/modules/cpu.py
@@ -0,0 +1,113 @@
+#
+# Copyright 2011
+# Tomas Edwardsson <tommi@xxxxxxxxx>
+#
+# This software may be freely redistributed under the terms of the GNU
+# general public license.
+#
+# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+import func_module
+from timemodule import sleep
+from codes import FuncException
+
+class CpuModule(func_module.FuncModule):
+    version = "0.0.1"
+    api_version = "0.0.1"
+    description = "Gathering CPU related information"
+
+    def jiffies(self):
+
+        # Which fields we are parsing from /proc stat
+        fields = ['user', 'nice', 'system', 'idle', 'iowait', 'irq']
+
+        # Returning struct
+        res = {}
+
+        # Open the /proc/stat
+        try:
+            stat_fd = open("/proc/stat", "r")
+        except Exception, e:
+            raise FuncException("Unable to open /proc/stat: %s" % (e))
+
+        # Run through the contents of /proc/stat
+        for statline in stat_fd.readlines():
+            # We don't care about non CPU stuff
+            if statline[0:3] != 'cpu':
+                break
+            stat = (statline.split())[0:(len(fields) + 1)]
+
+            # Total jiffies for this cpu
+            total = 0
+
+            # Catch the cpu name
+            cpu = stat[0]
+
+            # Create the dictionary
+            res[cpu] = {}
+
+            # Run through the named fields above and store the results
+            for i in range(1, (len(fields)+1)):
+                total += int(stat[i])
+                res[cpu][fields[i-1]] = int(stat[i])
+
+            # Record total jiffies
+            res[cpu]['total'] = total
+
+        return res
+
+    def cpu_sample_percentage(self, sampletime=5):
+        """
+        Returns percentage CPU utilization in an given
+        timeperiod.
+        """
+        if int(sampletime) > 18:
+            raise FuncException("sampletime maximum is 18")
+
+        # Get CPU statistics
+        prestat = self.jiffies()
+
+        # Wait for some activity
+        sleep(int(sampletime))
+
+        # Re fetch CPU statistics
+        poststat = self.jiffies()
+
+        # Dict to store results
+        results = {}
+
+        # Run through each CPU entry
+        for cpu in prestat.keys():
+            total = poststat[cpu]['total'] - prestat[cpu]['total']
+            results[cpu] = {}
+            for k in prestat[cpu].keys():
+                if k == 'total': continue
+                # Calculate the percentage
+                results[cpu][k] = float(poststat[cpu][k] - prestat[cpu][k]) / float(total) * 100
+        return results
+
+    def register_method_args(self):
+        """
+        Register the CPU method arguments
+        """
+        return{
+            'cpu_sample_percentage':{
+                'args':{
+                    'sampletime':{
+                        'type': 'int',
+                        'default': 5,
+                        'optional':True,
+                        'description':'How long to sample CPU usage',
+                    },
+                },
+                'description':'Sample CPU and return percent averages',
+            },
+            'jiffies':{
+                'args':{},
+                'description':'Fetch the CPU jiffies from /proc/stat',
+            },
+        }
+
+# vi: ts=4 expandtab
diff --git a/func/minion/modules/disk.py b/func/minion/modules/disk.py
index a2f0767..8cc9743 100644
--- a/func/minion/modules/disk.py
+++ b/func/minion/modules/disk.py
@@ -19,12 +19,12 @@ class DiskModule(func_module.FuncModule):
 
     def usage(self, partition=None):
         """
-        Returns the results of df -P
+        Returns the results of df -PT
         """
         results = {}
         # splitting the command variable out into a list does not seem to function
         # in the tests I have run
-        command = '/bin/df -P'
+        command = '/bin/df -PT'
         if (partition):
             command += ' %s' % (partition)
         cmdref = sub_process.Popen(command, stdout=sub_process.PIPE,
@@ -34,11 +34,12 @@ class DiskModule(func_module.FuncModule):
         for disk in stdout.split('\n'):
             if (disk.startswith('Filesystem') or not disk):
                 continue
-            (device, total, used, available, percentage, mount) = disk.split()
+            (device, fstype, total, used, available, percentage, mount) = disk.split()
             results[mount] = {'device':device,
                               'total':str(total),
                               'used':str(used),
                               'available':str(available),
+                              'fstype':str(fstype),
                               'percentage':int(percentage[:-1])}
         return results
 
diff --git a/func/minion/modules/service.py b/func/minion/modules/service.py
index 38de51c..e61875d 100644
--- a/func/minion/modules/service.py
+++ b/func/minion/modules/service.py
@@ -28,9 +28,9 @@ class Service(func_module.FuncModule):
 
         service_name = service_name.strip() # remove useless spaces
 
-        filename = os.path.join("/etc/rc.d/init.d/",service_name)
+        filename = os.path.join("/etc/init.d/",service_name)
         if os.path.exists(filename):
-            return sub_process.call(["/sbin/service", service_name, command], close_fds=True)
+            return sub_process.call(["/sbin/service", service_name, command], close_fds=True, env={ 'LANG':'C' })
         else:
             raise codes.FuncException("Service not installed: %s" % service_name)
 
@@ -87,7 +87,7 @@ class Service(func_module.FuncModule):
         only provide whether or not they are running, not specific runlevel info.
         """
 
-        chkconfig = sub_process.Popen(["/sbin/chkconfig", "--list"], stdout=sub_process.PIPE, close_fds=True)
+        chkconfig = sub_process.Popen(["/sbin/chkconfig", "--list"], stdout=sub_process.PIPE, close_fds=True, env={ "LANG": "C" })
         data = chkconfig.communicate()[0]
         results = []
         for line in data.split("\n"):
@@ -106,13 +106,23 @@ class Service(func_module.FuncModule):
         """
         Get a list of which services are running, stopped, or disabled.
         """
-        chkconfig = sub_process.Popen(["/sbin/service", "--status-all"], stdout=sub_process.PIPE, close_fds=True)
-        data = chkconfig.communicate()[0]
         results = []
-        for line in data.split("\n"):
-            if line.find(" is ") != -1:
-                tokens = line.split()
-                results.append((tokens[0], tokens[-1].replace("...","")))
+        # enumerate service scripts
+        for init_script in os.listdir("/etc/init.d"):
+            # no status for these
+            if init_script in ['functions', 'halt', 'killall', 'single', 'linuxconf', 'kudzu']:
+                continue
+            filename = os.path.join("/etc/init.d/",init_script)
+            # Run status for service
+            try:
+                init_exec = sub_process.Popen([filename, "status"], stdout=sub_process.PIPE, close_fds=True, env={ "LANG": "C" })
+            except Exception, e:
+                raise codes.FuncException("Service status error %s on initscript %s" % (e, filename))
+            data = init_exec.communicate()[0]
+            for line in data.split("\n"):
+                if line.find(" is ") != -1:
+                    tokens = line.split()
+                    results.append((tokens[0], tokens[-1].replace("...","")))
         return results
 
     def register_method_args(self):
@@ -143,3 +153,5 @@ class Service(func_module.FuncModule):
 
 
                 }
+
+# vi: ts=4 expandtab
_______________________________________________
Func-list mailing list
Func-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/func-list

[Index of Archives]     [Fedora Users]     [Linux Networking]     [Fedora Legacy List]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]

  Powered by Linux