summaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
authorSeth Vidal <skvidal@fedoraproject.org>2007-09-20 21:28:51 -0400
committerSeth Vidal <skvidal@fedoraproject.org>2007-09-20 21:28:51 -0400
commit8d168259f1cb0af25a7ee342bd1c32cd5bfdd424 (patch)
tree9c1d80b6da18a902b03ba7b21ec6bd0a60aabbfa /modules
parenta83c4bcc40aae7c8b8058d831667ee1e07a969dc (diff)
parent98010f591948fb4bf297c1c0c32def42f766edca (diff)
Merge branch 'master' of ssh://git.fedoraproject.org/git/hosted/func
* 'master' of ssh://git.fedoraproject.org/git/hosted/func: (27 commits) just a friendly reminder we are not vf_server, change I!*N domain Add virt module. Add test code for virt. add a very simple, very dumb commandline client: Remove messages.pot from po dir, since its automatically generated Get rid of extra / in module loading error pychecker cleanups Add po dir to git Prevent XMLRPC server from printing to console. Catch FuncException when the config file is missing and exit gracefully Implement a quickie service control module Removing VF items + misc cleanup Clean up some speclint warnings Baseobj bites the dust. remove all the --debug "try to run from the src tree" crap debug spew cleanup to protect the unwashed masses from foo poisoning fix up config_data to use ConfigParser correctly attempt to let us run with --debug flag to run from src checkout attempts at letting us run from a installed, or local modules ...
Diffstat (limited to 'modules')
-rwxr-xr-xmodules/baseobj.py115
-rwxr-xr-xmodules/service.py60
-rwxr-xr-xmodules/test.py13
-rwxr-xr-xmodules/virt.py276
-rwxr-xr-xmodules/web_svc.py1
5 files changed, 338 insertions, 127 deletions
diff --git a/modules/baseobj.py b/modules/baseobj.py
deleted file mode 100755
index 702f0a7..0000000
--- a/modules/baseobj.py
+++ /dev/null
@@ -1,115 +0,0 @@
-"""
-Virt-factory backend code.
-
-Copyright 2006, Red Hat, Inc
-Michael DeHaan <mdehaan@redhat.com>
-Scott Seago <sseago@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.
-"""
-
-import string
-import exceptions
-import os
-
-class BaseObject(object):
-
- FIELDS = [] # subclasses should define a list of db column names here
-
- def load(self,hash,key,default=None):
- """
- Access a hash element safely...
- """
- # FIXME: it would be cool if load starts with a copy of the hash
- # and clears off entries as recieved, such that we can tell if any
- # entries are not loaded. This should result in a warning in the return
- # object.
- assert hash is not None, "hash is None"
- assert key is not None, "key is None"
- if hash.has_key(key):
- return hash[key]
- else:
- return default
-
- def to_datastruct(self,to_caller=False):
- """
- Return a hash representation of this object.
- Defers to self.to_datastruct_internal which subclasses must implement.
- """
- ds = self.to_datastruct_internal()
- if to_caller:
- # don't send NULLs
- ds = self.remove_nulls(ds)
- return ds
-
- def to_datastruct_internal(self):
- """
- Subclasses: implement this.
- """
- raise exceptions.NotImplementedError
-
- def deserialize(self, args):
- for x in self.FIELDS:
- if args.has_key(x):
- setattr(self, x, args[x])
- else:
- setattr(self, x, None)
-
- def serialize(self):
- result = {}
- for x in self.FIELDS:
- result[x] = getattr(self, x, None)
- return result
-
- def remove_nulls(self, x):
- """
- If any entries are None in the datastructure, prune them.
- XMLRPC can't marshall None and this is our workaround. Objects
- that are None are removed from the hash -- including hash keys that
- are not None and have None for the value. The WUI or other SW
- should know how to deal with these returns.
- """
- assert x is not None, "datastructure is None"
- if type(x) == list:
- newx = []
- for i in x:
- if type(i) == list or type(i) == dict:
- newx.append(self.remove_nulls(i))
- elif i is not None:
- newx.append(i)
- x = newx
- elif type(x) == dict:
- newx = {}
- for i,j in x.iteritems():
- if type(j) == list or type(j) == dict:
- newx[i] = self.remove_nulls(x)
- elif j is not None:
- newx[i] = j
- x = newx
- return x
-
- # ========================
- # random utility functions
-
- def is_printable(self, stringy):
- # FIXME: use regex package
-
- if stringy == None:
- return False
- if type(stringy) != str:
- stringy = "%s" % stringy
- try:
- for letter in stringy:
- if letter not in string.printable:
- return False
- return True
- except:
- return False
-
-
- \ No newline at end of file
diff --git a/modules/service.py b/modules/service.py
new file mode 100755
index 0000000..f0693b0
--- /dev/null
+++ b/modules/service.py
@@ -0,0 +1,60 @@
+#!/usr/bin/python
+
+## func
+##
+## 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.
+##
+##
+
+
+from codes import *
+from modules import web_svc
+
+import subprocess
+import os
+
+class Service(web_svc.WebSvc):
+
+ 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
+ }
+ web_svc.WebSvc.__init__(self)
+
+ def __command(self, service_name, command):
+
+ filename = os.path.join("/etc/rc.d/init.d/",service_name)
+ if os.path.exists(filename):
+ return subprocess.call(["/sbin/service", service_name, command])
+ else:
+ raise FuncException("Service not installed: %s" % service_name)
+
+ def start(self, service_name):
+ return self.__command(service_name, "start")
+
+ def stop(self, service_name):
+ return self.__command(service_name, "start")
+
+ def restart(self, service_name):
+ return self.__command(service_name, "restart")
+
+ def reload(self, service_name):
+ return self.__command(service_name, "reload")
+
+ def status(self, service_name):
+ return self.__command(service_name, "status")
+
+methods = Service()
+register_rpc = methods.register_rpc
diff --git a/modules/test.py b/modules/test.py
index 7783b4e..eb2e3f4 100755
--- a/modules/test.py
+++ b/modules/test.py
@@ -1,26 +1,17 @@
#!/usr/bin/python
-
from codes import *
from modules import web_svc
-
-
class Test(web_svc.WebSvc):
def __init__(self):
self.methods = {
- "test_add": self.add,
- "test_blippy": self.blippy,
+ "test_add": self.add
}
web_svc.WebSvc.__init__(self)
def add(self, numb1, numb2):
- return success(int(numb1) + int(numb2))
-
- def blippy(self, foo):
- fh = open("/tmp/blippy","w+")
- fh.close()
- return success(foo)
+ return numb1 + numb2
methods = Test()
register_rpc = methods.register_rpc
diff --git a/modules/virt.py b/modules/virt.py
new file mode 100755
index 0000000..7e642cf
--- /dev/null
+++ b/modules/virt.py
@@ -0,0 +1,276 @@
+#!/usr/bin/python
+
+"""
+Virt management features
+
+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.
+"""
+
+# warning: virt management is rather complicated
+# to see a simple example of func, look at the
+# service control module. API docs on how
+# to use this to come.
+
+# other modules
+import sys
+import os
+import subprocess
+import libvirt
+
+# our modules
+import codes
+import web_svc
+
+VIRT_STATE_NAME_MAP = {
+ 0 : "running",
+ 1 : "running",
+ 2 : "running",
+ 3 : "paused",
+ 4 : "shutdown",
+ 5 : "shutdown",
+ 6 : "crashed"
+}
+
+class FuncLibvirtConnection():
+
+ def __init__(self):
+
+
+ cmd = subprocess.Popen("uname -r", shell=True, stdout=subprocess.PIPE)
+ output = cmd.communicate()[0]
+
+ if output.find("xen") != -1:
+ conn = libvirt.open(None)
+ else:
+ conn = libvirt.open("qemu:///system")
+
+ if not conn:
+ raise FuncException(comment="hypervisor connection failure")
+
+ self.conn = conn
+
+ def find_vm(self, vmid):
+ """
+ Extra bonus feature: vmid = -1 returns a list of everything
+ """
+ conn = self.conn
+
+ vms = []
+
+ # this block of code borrowed from virt-manager:
+ # get working domain's name
+ ids = conn.listDomainsID();
+ for id in ids:
+ vm = conn.lookupByID(id)
+ vms.append(vm)
+ # get defined domain
+ names = conn.listDefinedDomains()
+ for name in names:
+ vm = conn.lookupByName(name)
+ vms.append(vm)
+
+ if vmid == -1:
+ return vms
+
+ for vm in vms:
+ if vm.name() == needle:
+ return vm
+
+ raise FuncException(comment="virtual machine %s not found" % needle)
+
+ def shutdown(self, vmid):
+ return self.find_vm(vmid).shutdown()
+
+ def pause(self, vmid):
+ return suspend(self.conn,vmid)
+
+ def unpause(self, vmid):
+ return resume(self.conn,vmid)
+
+ def suspend(self, vmid):
+ return self.find_vm(vmid).suspend()
+
+ def resume(self, vmid):
+ return self.find_vm(vmid).resume()
+
+ def create(self, vmid):
+ return self.find_vm(vmid).create()
+
+ def destroy(self, vmid):
+ return self.find_vm(vmid).destroy()
+
+ def undefine(self, vmid):
+ return self.find_vm(vmid).undefine()
+
+ def get_status2(self, vm):
+ state = vm.info()[0]
+ # print "DEBUG: state: %s" % state
+ return VIRT_STATE_NAME_MAP.get(state,"unknown")
+
+ def get_status(self, vmid):
+ state = self.find_vm(vmid).info()[0]
+ return VIRT_STATE_NAME_MAP.get(state,"unknown")
+
+
+
+class Virt(web_svc.WebSvc):
+
+
+ def __init__(self):
+
+ """
+ Constructor. Register methods and make them available.
+ """
+
+ 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,
+ }
+
+ web_svc.WebSvc.__init__(self)
+
+ def get_conn(self):
+ self.conn = FuncLibvirtConnection()
+ return self.conn
+
+ def list_vms(self):
+ self.conn = self.get_conn()
+ vms = self.conn.find_vm(-1)
+ results = []
+ for x in vms:
+ try:
+ results.append(x.name())
+ except:
+ pass
+ return results
+
+ def install(self, server_name, target_name, system=False):
+
+ """
+ Install a new virt system by way of a named cobbler profile.
+ """
+
+ # Example:
+ # install("bootserver.example.org", "fc7webserver", True)
+
+ conn = self.get_conn()
+
+ if conn is None:
+ raise FuncException(comment="no connection")
+
+ if not os.path.exists("/usr/bin/koan"):
+ raise FuncException(comment="no /usr/bin/koan")
+ target = "profile"
+ if system:
+ target = "system"
+
+ # TODO: FUTURE: set --virt-path in cobbler or here
+ koan_args = [
+ "/usr/bin/koan",
+ "--virt",
+ "--virt-graphics", # enable VNC
+ "--%s=%s" % (target, target_name),
+ "--server=%s" % server_name
+ ]
+
+ rc = subprocess.call(koan_args,shell=False)
+ if rc == 0:
+ return success(0)
+ else:
+ raise FuncException(comment="koan returned %d" % rc)
+
+
+ def shutdown(self, vmid):
+ """
+ Make the machine with the given vmid stop running.
+ Whatever that takes.
+ """
+ self.get_conn()
+ self.conn.shutdown(vmid)
+ return success()
+
+
+ def pause(self, vmid):
+
+ """
+ Pause the machine with the given vmid.
+ """
+ self.get_conn()
+ self.conn.suspend(vmid)
+ return success()
+
+
+ def unpause(self, vmid):
+
+ """
+ Unpause the machine with the given vmid.
+ """
+
+ self.get_conn()
+ self.conn.resume(vmid)
+ return success()
+
+
+ def create(self, vmid):
+
+ """
+ Start the machine via the given mac address.
+ """
+ self.get_conn()
+ self.conn.create(vmid)
+ return success()
+
+
+ def destroy(self, vmid):
+
+ """
+ Pull the virtual power from the virtual domain, giving it virtually no
+ time to virtually shut down.
+ """
+ self.get_conn()
+ self.conn.destroy(vmid)
+ return success()
+
+
+
+ def undefine(self, vmid):
+
+ """
+ Stop a domain, and then wipe it from the face of the earth.
+ by deleting the disk image and it's configuration file.
+ """
+
+ self.get_conn()
+ self.conn.undefine(vmid)
+ return success()
+
+
+ def get_status(self, vmid):
+
+ """
+ Return a state suitable for server consumption. Aka, codes.py values, not XM output.
+ """
+
+ self.get_conn()
+ return success("STATE=%s" % self.conn.get_status(vmid))
+
+
+methods = Virt()
+register_rpc = methods.register_rpc
+
+
diff --git a/modules/web_svc.py b/modules/web_svc.py
index ed4ec19..134af37 100755
--- a/modules/web_svc.py
+++ b/modules/web_svc.py
@@ -15,7 +15,6 @@
from codes import *
-import baseobj
from server import config_data
from server import logger