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
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