summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSeth Vidal <skvidal@fedoraproject.org>2007-09-24 11:45:08 -0400
committerSeth Vidal <skvidal@fedoraproject.org>2007-09-24 11:45:08 -0400
commita656879954105065b2fabed8f77993387c73f9b6 (patch)
tree904d37c4c2e4cb98460f2969bb61e0f632e82714
parenta4680ef456b87d73ccdb6a6a9beba1992ebdd7c6 (diff)
parent2d1bb13794d1f3e9dfca2047195e5ab368db628b (diff)
downloadthird_party-func-a656879954105065b2fabed8f77993387c73f9b6.tar.gz
third_party-func-a656879954105065b2fabed8f77993387c73f9b6.tar.xz
third_party-func-a656879954105065b2fabed8f77993387c73f9b6.zip
Merge branch 'master' of ssh://git.fedoraproject.org/git/hosted/func
* 'master' of ssh://git.fedoraproject.org/git/hosted/func: Rename yummod as yum so each module doesn't end up ending in mod :) Added kill and pkill to the process module Process module. Accepts flags to PS, returns nicely formatted tabular output. Added a smolt-based hardware profiler module. Remove underscores from exported function names as they are now redundant. update to new calling conventions Fix up virt code some more. change to module loader to allow subdirs in the module path. ignore the build/ dir
-rw-r--r--.gitignore1
-rw-r--r--client/test_func.py23
-rwxr-xr-xmodules/func_module.py4
-rwxr-xr-xmodules/hardware.py100
-rwxr-xr-xmodules/process.py68
-rwxr-xr-xmodules/reboot.py2
-rwxr-xr-xmodules/service.py10
-rwxr-xr-xmodules/test.py2
-rwxr-xr-xmodules/virt.py28
-rw-r--r--modules/yum.py (renamed from modules/yummod.py)2
-rwxr-xr-xserver/module_loader.py53
-rwxr-xr-xserver/server.py4
12 files changed, 255 insertions, 42 deletions
diff --git a/.gitignore b/.gitignore
index f5f30f4..0fef094 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
*.pyc
*.pyo
*.swp
+build
MANIFEST
rpm-build
dist
diff --git a/client/test_func.py b/client/test_func.py
index 19ec3af..6362b85 100644
--- a/client/test_func.py
+++ b/client/test_func.py
@@ -5,34 +5,43 @@
import xmlrpclib
-TEST_VIRT = True
+TEST_PROCESS = True
+TEST_VIRT = False
TEST_SERVICES = True
+TEST_HARDWARE = True
# get a connecton (to be replaced by client lib logic)
s = xmlrpclib.ServerProxy("http://127.0.0.1:51234")
# here's the basic test...
-print s.test_add(1, 2)
+print s.test.add(1, 2)
+
+if TEST_PROCESS:
+ print s.process.info()
+ print s.process.pkill("thunderbird")
# here's the service module testing
if TEST_SERVICES:
- print s.service_restart("httpd")
+ print s.service.restart("httpd")
+
+if TEST_HARDWARE:
+ print s.hardware.info()
# this is so I can remember how the virt module works
if TEST_VIRT:
# example of using koan to install a virtual machine
- # s.virt_install("mdehaan.rdu.redhat.com","fc7webserver",False)
+ #s.virt_install("mdehaan.rdu.redhat.com","profileX")
# wait ...
- vms = s.virt_list_vms()
+ vms = s.virt.list_vms()
# example of stopping all stopped virtual machines
print "list of virtual instances = %s" % vms
for vm in vms:
- status = s.virt_status(vm)
+ status = s.virt.status(vm)
print status
if status == "shutdown":
- s.virt_start(vm)
+ s.virt.start(vm)
# add more tests here
diff --git a/modules/func_module.py b/modules/func_module.py
index ec587c1..4bb06d2 100755
--- a/modules/func_module.py
+++ b/modules/func_module.py
@@ -35,9 +35,9 @@ class FuncModule(object):
log = logger.Logger()
self.logger = log.logger
- def register_rpc(self, handlers):
+ def register_rpc(self, handlers, module_name):
for meth in self.methods:
- handlers[meth] = self.methods[meth]
+ handlers["%s.%s" % (module_name,meth)] = self.methods[meth]
diff --git a/modules/hardware.py b/modules/hardware.py
new file mode 100755
index 0000000..2c41b9f
--- /dev/null
+++ b/modules/hardware.py
@@ -0,0 +1,100 @@
+#!/usr/bin/python
+
+##
+## Hardware profiler plugin
+## requires the "smolt" client package be installed
+##
+## Copyright 2007, Red Hat, Inc
+## Michael DeHaan <mdehaan@redhat.com>
+##
+## 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.
+##
+
+
+# other modules
+import sys
+# hack: smolt is not installed in site-packages
+sys.path.append("/usr/share/smolt/client")
+import smolt
+
+# our modules
+from codes import *
+from modules import func_module
+
+# =================================
+
+class HardwareModule(func_module.FuncModule):
+ def __init__(self):
+ self.methods = {
+ "info": self.info
+ }
+ func_module.FuncModule.__init__(self)
+
+ def info(self,with_devices=True):
+ """
+ Returns a struct of hardware information. By default, this pulls down
+ all of the devices. If you don't care about them, set with_devices to
+ False.
+ """
+ return hw_info(with_devices)
+
+# =================================
+
+def hw_info(with_devices=True):
+
+ hardware = smolt.Hardware()
+ host = hardware.host
+
+ # NOTE: casting is needed because these are DBusStrings, not real strings
+ data = {
+ 'os' : str(host.os),
+ 'defaultRunlevel' : str(host.defaultRunlevel),
+ 'bogomips' : str(host.bogomips),
+ 'cpuVendor' : str(host.cpuVendor),
+ 'cpuModel' : str(host.cpuModel),
+ 'numCpus' : str(host.numCpus),
+ 'cpuSpeed' : str(host.cpuSpeed),
+ 'systemMemory' : str(host.systemMemory),
+ 'systemSwap' : str(host.systemSwap),
+ 'kernelVersion' : str(host.kernelVersion),
+ 'language' : str(host.language),
+ 'platform' : str(host.platform),
+ 'systemVendor' : str(host.systemVendor),
+ 'systemModel' : str(host.systemModel),
+ 'formfactor' : str(host.formfactor),
+ 'selinux_enabled' : str(host.selinux_enabled),
+ 'selinux_enforce' : str(host.selinux_enforce)
+ }
+
+ # if no hardware info requested, just return the above bits
+ if not with_devices:
+ return data
+
+ collection = data["devices"] = []
+
+ for item in hardware.deviceIter():
+
+ (VendorID,DeviceID,SubsysVendorID,SubsysDeviceID,Bus,Driver,Type,Description) = item
+
+ collection.append({
+ "VendorID" : str(VendorID),
+ "DeviceID" : str(DeviceID),
+ "SubsysVendorID" : str(SubsysVendorID),
+ "Bus" : str(Bus),
+ "Driver" : str(Driver),
+ "Type" : str(Type),
+ "Description" : str(Description)
+ })
+
+ return data
+
+methods = HardwareModule()
+register_rpc = methods.register_rpc
+
+
+
diff --git a/modules/process.py b/modules/process.py
new file mode 100755
index 0000000..064b1b3
--- /dev/null
+++ b/modules/process.py
@@ -0,0 +1,68 @@
+#!/usr/bin/python
+
+##
+## Process lister (control TBA)
+##
+## Copyright 2007, Red Hat, Inc
+## Michael DeHaan <mdehaan@redhat.com>
+##
+## 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.
+##
+
+# other modules
+import subprocess
+
+# our modules
+from codes import *
+from modules import func_module
+
+# =================================
+
+class ProcessModule(func_module.FuncModule):
+ def __init__(self):
+ self.methods = {
+ "info" : self.info,
+ "kill" : self.kill,
+ "pkill" : self.pkill
+ }
+ func_module.FuncModule.__init__(self)
+
+ def info(self,flags="-aux"):
+ """
+ Returns a struct of hardware information. By default, this pulls down
+ all of the devices. If you don't care about them, set with_devices to
+ False.
+ """
+
+ flags.replace(";","") # prevent stupidity
+
+ cmd = subprocess.Popen("ps %s" % flags,stdout=subprocess.PIPE,shell=True)
+ data = cmd.communicate()[0]
+
+ results = []
+
+ for x in data.split("\n"):
+ tokens = x.split()
+ results.append(tokens)
+
+ return results
+
+ def kill(self,pid,level=""):
+ rc = subprocess.call("/bin/kill %s %s" % (pid, level), shell=True)
+ return rc
+
+ def pkill(self,name,level=""):
+ # example killall("thunderbird","-9")
+ rc = subprocess.call("/usr/bin/pkill %s %s" % (name, level), shell=True)
+ return rc
+
+methods = ProcessModule()
+register_rpc = methods.register_rpc
+
+
+
diff --git a/modules/reboot.py b/modules/reboot.py
index c2f39ba..ddc7651 100755
--- a/modules/reboot.py
+++ b/modules/reboot.py
@@ -17,7 +17,7 @@ class Reboot(func_module.FuncModule):
def __init__(self):
self.methods = {
- "reboot_reboot" : self.reboot
+ "reboot" : self.reboot
}
func_module.FuncModule.__init__(self)
diff --git a/modules/service.py b/modules/service.py
index eaea16e..bbc51e1 100755
--- a/modules/service.py
+++ b/modules/service.py
@@ -25,11 +25,11 @@ class Service(func_module.FuncModule):
def __init__(self):
self.methods = {
- "service_start" : self.start,
- "service_stop" : self.stop,
- "service_restart" : self.restart,
- "service_reload" : self.reload,
- "service_status" : self.status
+ "start" : self.start,
+ "stop" : self.stop,
+ "restart" : self.restart,
+ "reload" : self.reload,
+ "status" : self.status
}
func_module.FuncModule.__init__(self)
diff --git a/modules/test.py b/modules/test.py
index b742e31..31f1e94 100755
--- a/modules/test.py
+++ b/modules/test.py
@@ -6,7 +6,7 @@ from modules import func_module
class Test(func_module.FuncModule):
def __init__(self):
self.methods = {
- "test_add": self.add
+ "add": self.add
}
func_module.FuncModule.__init__(self)
diff --git a/modules/virt.py b/modules/virt.py
index dc9a13a..d345d75 100755
--- a/modules/virt.py
+++ b/modules/virt.py
@@ -53,7 +53,7 @@ class FuncLibvirtConnection():
conn = libvirt.open("qemu:///system")
if not conn:
- raise FuncException(comment="hypervisor connection failure")
+ raise codes.FuncException("hypervisor connection failure")
self.conn = conn
@@ -84,7 +84,7 @@ class FuncLibvirtConnection():
if vm.name() == vmid:
return vm
- raise FuncException(comment="virtual machine %s not found" % needle)
+ raise codes.FuncException("virtual machine %s not found" % needle)
def shutdown(self, vmid):
return self.find_vm(vmid).shutdown()
@@ -131,15 +131,15 @@ class Virt(func_module.FuncModule):
"""
self.methods = {
- "virt_install" : self.install,
- "virt_shutdown" : self.shutdown,
- "virt_destroy" : self.destroy,
- "virt_start" : self.create,
- "virt_pause" : self.pause,
- "virt_unpause" : self.unpause,
- "virt_delete" : self.undefine,
- "virt_status" : self.get_status,
- "virt_list_vms" : self.list_vms,
+ "install" : self.install,
+ "shutdown" : self.shutdown,
+ "destroy" : self.destroy,
+ "start" : self.create,
+ "pause" : self.pause,
+ "unpause" : self.unpause,
+ "delete" : self.undefine,
+ "status" : self.get_status,
+ "list_vms" : self.list_vms,
}
func_module.FuncModule.__init__(self)
@@ -171,10 +171,10 @@ class Virt(func_module.FuncModule):
conn = self.get_conn()
if conn is None:
- raise FuncException(comment="no connection")
+ raise codes.FuncException("no connection")
if not os.path.exists("/usr/bin/koan"):
- raise FuncException(comment="no /usr/bin/koan")
+ raise codes.FuncException("no /usr/bin/koan")
target = "profile"
if system:
target = "system"
@@ -192,7 +192,7 @@ class Virt(func_module.FuncModule):
if rc == 0:
return 0
else:
- raise FuncException(comment="koan returned %d" % rc)
+ raise codes.FuncException("koan returned %d" % rc)
def shutdown(self, vmid):
diff --git a/modules/yummod.py b/modules/yum.py
index 575b001..6600d47 100644
--- a/modules/yummod.py
+++ b/modules/yum.py
@@ -23,7 +23,7 @@ class Yum(func_module.FuncModule):
def __init__(self):
self.methods = {
- "yum_update" : self.update
+ "update" : self.update
}
func_module.FuncModule.__init__(self)
diff --git a/server/module_loader.py b/server/module_loader.py
index f189623..2b20429 100755
--- a/server/module_loader.py
+++ b/server/module_loader.py
@@ -22,6 +22,22 @@ import glob
from rhpl.translate import _, N_, textdomain, utf8
+def module_walker(topdir):
+ module_files = []
+ for root, dirs, files in os.walk(topdir):
+ # we should get here for each subdir
+ for filename in files:
+ # ASSUMPTION: all module files will end with .py, .pyc, .pyo
+ if filename[-3:] == ".py" or filename[-4:] == ".pyc" or filename[-4:] == ".pyo":
+ # we don't really care about __init__ files, though we do requure them
+ if filename[:8] == "__init__":
+ continue
+ # the normpath is important, since we
+ module_files.append(os.path.normpath("%s/%s" % (root, filename)))
+
+
+ return module_files
+
def load_modules(blacklist=None):
module_file_path="%s/func/server/modules/" % distutils.sysconfig.get_python_lib()
@@ -30,12 +46,14 @@ def load_modules(blacklist=None):
sys.path.insert(0, mod_path)
mods = {}
- filenames = glob.glob("%s/*.py" % module_file_path)
- filenames = filenames + glob.glob("%s/*.pyc" % module_file_path)
- filesnames = filenames + glob.glob("%s/*.pyo" % module_file_path)
+ filenames = module_walker(module_file_path)
+ # FIXME: this is probably more complicated than it needs to be -akl
for fn in filenames:
- basename = os.path.basename(fn)
+ # aka, everything after the module_file_path
+ module_name_part = fn[len(module_file_path):]
+ dirname, basename = os.path.split(module_name_part)
+
if basename == "__init__.py":
continue
if basename[-3:] == ".py":
@@ -43,14 +61,19 @@ def load_modules(blacklist=None):
elif basename[-4:] in [".pyc", ".pyo"]:
modname = basename[:-4]
-
+ pathname = modname
+ if dirname != "":
+ pathname = "%s/%s" % (dirname, modname)
+
+ mod_imp_name = pathname.replace("/", ".")
+
try:
- blip = __import__("modules.%s" % ( modname), globals(), locals(), [modname])
+ blip = __import__("modules.%s" % ( mod_imp_name), globals(), locals(), [mod_imp_name])
if not hasattr(blip, "register_rpc"):
errmsg = _("%(module_path)s%(modname)s module not a proper module")
- print errmsg % {'module_path': module_file_path, 'modname':modname}
+ print errmsg % {'module_path': module_file_path, 'modname':mod_imp_name}
continue
- mods[modname] = blip
+ mods[mod_imp_name] = blip
except ImportError, e:
# shouldn't this be fatal?
print e
@@ -59,5 +82,17 @@ def load_modules(blacklist=None):
return mods
+if __name__ == "__main__":
+
+ module_file_path = "/usr/lib/python2.5/site-packages/func/server/modules/"
+ bar = module_walker(module_file_path)
+ print bar
+ for f in bar:
+ print f
+ print os.path.basename(f)
+ print os.path.split(f)
+ g = f[len(module_file_path):]
+ print g
+ print os.path.split(g)
-
+ print load_modules()
diff --git a/server/server.py b/server/server.py
index b167938..4e320e9 100755
--- a/server/server.py
+++ b/server/server.py
@@ -56,7 +56,7 @@ class XmlRpcInterface(object):
self.handlers = {}
for x in self.modules.keys():
try:
- self.modules[x].register_rpc(self.handlers)
+ self.modules[x].register_rpc(self.handlers, x)
self.logger.debug("adding %s" % x)
except AttributeError, e:
self.logger.warning("module %s not loaded, missing register_rpc method" % self.modules[x])
@@ -174,7 +174,7 @@ def main(argv):
try:
websvc = XmlRpcInterface(modules=modules)
- except FuncException, e:
+ except codes.FuncException, e:
print >> sys.stderr, 'error: %s' % e
sys.exit(1)