diff options
-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) |