diff options
author | Seth Vidal <skvidal@fedoraproject.org> | 2007-09-24 11:45:08 -0400 |
---|---|---|
committer | Seth Vidal <skvidal@fedoraproject.org> | 2007-09-24 11:45:08 -0400 |
commit | a656879954105065b2fabed8f77993387c73f9b6 (patch) | |
tree | 904d37c4c2e4cb98460f2969bb61e0f632e82714 | |
parent | a4680ef456b87d73ccdb6a6a9beba1992ebdd7c6 (diff) | |
parent | 2d1bb13794d1f3e9dfca2047195e5ab368db628b (diff) | |
download | func-a656879954105065b2fabed8f77993387c73f9b6.tar.gz func-a656879954105065b2fabed8f77993387c73f9b6.tar.xz 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-- | .gitignore | 1 | ||||
-rw-r--r-- | client/test_func.py | 23 | ||||
-rwxr-xr-x | modules/func_module.py | 4 | ||||
-rwxr-xr-x | modules/hardware.py | 100 | ||||
-rwxr-xr-x | modules/process.py | 68 | ||||
-rwxr-xr-x | modules/reboot.py | 2 | ||||
-rwxr-xr-x | modules/service.py | 10 | ||||
-rwxr-xr-x | modules/test.py | 2 | ||||
-rwxr-xr-x | modules/virt.py | 28 | ||||
-rw-r--r-- | modules/yum.py (renamed from modules/yummod.py) | 2 | ||||
-rwxr-xr-x | server/module_loader.py | 53 | ||||
-rwxr-xr-x | server/server.py | 4 |
12 files changed, 255 insertions, 42 deletions
@@ -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) |