diff options
author | Adrian Likins <alikins@redhat.com> | 2007-09-20 19:02:50 -0400 |
---|---|---|
committer | Adrian Likins <alikins@redhat.com> | 2007-09-20 19:02:50 -0400 |
commit | d21081735c98b717a6ba726fb7afb50a446d021a (patch) | |
tree | 028fe381072782c5ef30af10cee89e49fbe153c9 | |
parent | 895c2af960d789798884a2f4af4b941254ab83f6 (diff) | |
parent | c0d315b2fd35c4ca8291f9a8c7f7be7bcd1cfa89 (diff) | |
download | func-d21081735c98b717a6ba726fb7afb50a446d021a.tar.gz func-d21081735c98b717a6ba726fb7afb50a446d021a.tar.xz func-d21081735c98b717a6ba726fb7afb50a446d021a.zip |
Merge branch 'master' of ssh://git.fedoraproject.org/git/hosted/func
-rw-r--r-- | client/test_func.py | 25 | ||||
-rwxr-xr-x | modules/virt.py | 276 |
2 files changed, 300 insertions, 1 deletions
diff --git a/client/test_func.py b/client/test_func.py index ede9bbf..a108c47 100644 --- a/client/test_func.py +++ b/client/test_func.py @@ -5,10 +5,33 @@ import xmlrpclib +TEST_VIRT = True +TEST_SERVICES = 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.service_restart("httpd") +# here's the service module testing +if TEST_SERVICES: + print s.service_restart("httpd") + +# 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) + + # wait ... + 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) + if status == "stopped": + s.virt_start(vm) +# add more tests here 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 + + |