X-Git-Url: https://pwan.org/git/?a=blobdiff_plain;f=certmaster%2Fminion%2Fmodules%2Fvirt.py;fp=certmaster%2Fminion%2Fmodules%2Fvirt.py;h=04d36bd761dd41f372c6724e82c40848f2b7f3ed;hb=8f2ff4d7c902d534d68ff1a16418b7be492033bf;hp=0000000000000000000000000000000000000000;hpb=5b2601a56907b02efc6567354fa051ef08d97b6f;p=certmaster.git diff --git a/certmaster/minion/modules/virt.py b/certmaster/minion/modules/virt.py new file mode 100644 index 0000000..04d36bd --- /dev/null +++ b/certmaster/minion/modules/virt.py @@ -0,0 +1,277 @@ +""" +Virt management features + +Copyright 2007, Red Hat, Inc +Michael DeHaan + +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 os +import sub_process +import libvirt + +# our modules +import codes +import func_module + +VIRT_STATE_NAME_MAP = { + 0 : "running", + 1 : "running", + 2 : "running", + 3 : "paused", + 4 : "shutdown", + 5 : "shutdown", + 6 : "crashed" +} + +class FuncLibvirtConnection(object): + + version = "0.0.1" + api_version = "0.0.1" + description = "Virtualization items through func." + + def __init__(self): + + cmd = sub_process.Popen("uname -r", shell=True, stdout=sub_process.PIPE) + output = cmd.communicate()[0] + + if output.find("xen") != -1: + conn = libvirt.open(None) + else: + conn = libvirt.open("qemu:///system") + + if not conn: + raise codes.FuncException("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() == vmid: + return vm + + raise codes.FuncException("virtual machine %s not found" % vmid) + + def shutdown(self, vmid): + return self.find_vm(vmid).shutdown() + + def pause(self, vmid): + return self.suspend(self.conn,vmid) + + def unpause(self, vmid): + return self.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(func_module.FuncModule): + + def __get_conn(self): + self.conn = FuncLibvirtConnection() + return self.conn + + def state(self): + vms = self.list_vms() + state = [] + for vm in vms: + state_blurb = self.conn.get_status(vm) + state.append("%s %s" % (vm,state_blurb)) + return state + + + def info(self): + vms = self.list_vms() + info = dict() + for vm in vms: + data = self.conn.find_vm(vm).info() + # libvirt returns maxMem, memory, and cpuTime as long()'s, which + # xmlrpclib tries to convert to regular int's during serialization. + # This throws exceptions, so convert them to strings here and + # assume the other end of the xmlrpc connection can figure things + # out or doesn't care. + info[vm] = { + "state" : VIRT_STATE_NAME_MAP.get(data[0],"unknown"), + "maxMem" : str(data[1]), + "memory" : str(data[2]), + "nrVirtCpu" : data[3], + "cpuTime" : str(data[4]) + } + return info + + + 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 codes.FuncException("no connection") + + if not os.path.exists("/usr/bin/koan"): + raise codes.FuncException("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 = sub_process.call(koan_args,shell=False) + if rc == 0: + return 0 + else: + raise codes.FuncException("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 0 + + + def pause(self, vmid): + + """ + Pause the machine with the given vmid. + """ + self.__get_conn() + self.conn.suspend(vmid) + return 0 + + + def unpause(self, vmid): + + """ + Unpause the machine with the given vmid. + """ + + self.__get_conn() + self.conn.resume(vmid) + return 0 + + + def create(self, vmid): + + """ + Start the machine via the given mac address. + """ + self.__get_conn() + self.conn.create(vmid) + return 0 + + + 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 0 + + + 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 0 + + + def get_status(self, vmid): + + """ + Return a state suitable for server consumption. Aka, codes.py values, not XM output. + """ + + self.__get_conn() + return self.conn.get_status(vmid)