#============================================================================ # This library is free software; you can redistribute it and/or # modify it under the terms of version 2.1 of the GNU Lesser General Public # License as published by the Free Software Foundation. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #============================================================================ # Copyright (C) 2006 Anthony Liguori # Copyright (C) 2006 XenSource Ltd. #============================================================================ import xmlrpclib from xen.xend import XendDomain, XendDomainInfo, XendNode, \ XendLogging, XendDmesg from xen.util.xmlrpclib2 import UnixXMLRPCServer, TCPXMLRPCServer from xen.xend.XendClient import XML_RPC_SOCKET, ERROR_INVALID_DOMAIN from xen.xend.XendError import * from xen.xend.XendLogging import log from types import ListType def lookup(domid): info = XendDomain.instance().domain_lookup_by_name_or_id(domid) if not info: raise XendInvalidDomain(str(domid)) return info def dispatch(domid, fn, args): info = lookup(domid) return getattr(info, fn)(*args) # vcpu_avail is a long and is not needed by the clients. It's far easier # to just remove it then to try and marshal the long. def fixup_sxpr(sexpr): ret = [] for k in sexpr: if type(k) is ListType: if len(k) != 2 or k[0] != 'vcpu_avail': ret.append(fixup_sxpr(k)) else: ret.append(k) return ret def domain(domid): info = lookup(domid) return fixup_sxpr(info.sxpr()) def domains(detail=1): if detail < 1: return XendDomain.instance().list_names() else: domains = XendDomain.instance().list_sorted() return map(lambda dom: fixup_sxpr(dom.sxpr()), domains) def domain_create(config): info = XendDomain.instance().domain_create(config) return fixup_sxpr(info.sxpr()) def domain_restore(src): info = XendDomain.instance().domain_restore(src) return fixup_sxpr(info.sxpr()) def get_log(): f = open(XendLogging.getLogFilename(), 'r') try: return f.read() finally: f.close() methods = ['device_create', 'destroyDevice', 'getDeviceSxprs', 'setMemoryTarget', 'setName', 'setVCpuCount', 'shutdown', 'send_sysrq', 'getVCPUInfo', 'waitForDevices'] exclude = ['domain_create', 'domain_restore'] class XMLRPCServer: def __init__(self, use_tcp=False): self.ready = False self.use_tcp = use_tcp def run(self): if self.use_tcp: self.server = TCPXMLRPCServer(("", 8005), logRequests=False) else: self.server = UnixXMLRPCServer(XML_RPC_SOCKET, False) def login(username, password): log.info("User %s logged in.", username); return { "Status" : "Success", "Value" : "SESSION" } self.server.register_function(login, 'Session.login_with_password') def logout(session): log.info("Session %s logged out.", session); return { "Status" : "Success", "Value" : "" } self.server.register_function(logout, 'Session.logout') def get_this_host(session): log.info("Get this host %s.", session); return { "Status" : "Success", "Value" : "THIS_HOST" } self.server.register_function(get_this_host, 'Session.get_this_host') def get_software_version(session, host): log.info("Get software version %s %s.", session, host); return { "Status" : "Success", "Value" : { "Xen": "3.0.2", "Xend" : "3.0.2.2" }} self.server.register_function(get_software_version, 'host.get_software_version') # Functions in XendDomainInfo for name in methods: fn = eval("lambda domid, *args: dispatch(domid, '%s', args)"%name) self.server.register_function(fn, "xend.domain.%s" % name) # Functions in XendDomain def vm_get_by_uuid(session, uuid): res = XendDomain.instance().domain_lookup_by_name_or_id("Domain-0") if res: return { 'Status' : 'Success', 'Value' : uuid } else: return { 'Status' : 'Failure', 'ErrorDescription' : [ 'NOSUCHUUID', uuid ] } self.server.register_function(vm_get_by_uuid, 'VM.get_by_uuid') def vm_get_record(session, uuid): res = XendDomain.instance().domain_lookup_by_name_or_id("Domain-0") host_uuid = "THIS_HOST" if res: return { 'Status' : 'Success', 'Value' : { 'uuid' : uuid, "power_state" : "Running", "name_label" : res.getName(), "name_description" : res.getName(), "user_version" : str(1), "is_a_template" : False, "resident_on" : host_uuid, "memory_static_max" : str(0), "memory_dynamic_max" : str(0), "memory_actual" : str(0), "memory_dynamic_min" : str(0), "memory_static_min" : str(0), "vcpus_policy" : "policy", "vcpus_params" : "params", "vcpus_number" : str(1), "vcpus_utilisation" : { "1" : 1.0, "2" : 1.3 }, "vcpus_features_required" : [], "vcpus_features_can_use" : [ "3DNOW" ], "vcpus_features_force_on" : [ "CMOV" ], "vcpus_features_force_off" : [ "MMX" ], "actions_after_shutdown" : "destroy", "actions_after_reboot" : "restart", "actions_after_suspend" : "destroy", "actions_after_crash" : "preserve", "vifs" : [ "VIF1_UUID", "VIF2_UUID" ], "vbds" : [ "VBD1_UUID", "VBD2_UUID" ], "tpm_instance" : "64101201201", "tpm_backend" : "-1", "bios_boot" : "VBD1_UUID", "platform_std_vga" : True, "platform_serial" : "shreddies", "platform_localtime" : False, "platform_clock_offset" : False, "platform_enable_audio" : False, "builder" : "Linux", "boot_method" : "kernel_external", "kernel_kernel" : "vmlinuz", "kernel_initrd" : "initrd.img", "kernel_args" : "nousb", "grub_cmdline" : "", "pci_bus" : "", "tools_version" : { "PV DISK" : "1.3.0" }, "otherconfig" : { "PV DISK SPEED" : "FAST" } } } else: return { 'Status' : 'Failure', 'ErrorDescription' : [ 'NOSUCHUUID', uuid ] } self.server.register_function(vm_get_record, 'VM.get_record') def vm_create(session, struct): log.info("VM.create got %s", struct) return { 'Status' : 'Success', 'Value' : "NEWVMUUID" } self.server.register_function(vm_create, 'VM.create') def vdi_create(session, struct): log.info("VDI.create got %s", struct) return { 'Status' : 'Success', 'Value' : "NEWVDIUUID" } self.server.register_function(vdi_create, 'VDI.create') def vbd_create(session, struct): log.info("VBD.create got %s", struct) return { 'Status' : 'Success', 'Value' : "NEWVBDUUID" } self.server.register_function(vbd_create, 'VBD.create') def sr_get_by_name_label(session, label): log.info("SR.get_by_name_label(%s)", label) return { 'Status' : 'Success', 'Value' : "SRUUID" } self.server.register_function(sr_get_by_name_label, 'SR.get_by_name_label') inst = XendDomain.instance() for name in dir(inst): fn = getattr(inst, name) if name.startswith("domain_") and callable(fn): if name not in exclude: self.server.register_function(fn, "xend.domain.%s" % name[7:]) # Functions in XendNode and XendDmesg for type, lst, n in [(XendNode, ['info', 'cpu_bvt_slice_set'], 'node'), (XendDmesg, ['info', 'clear'], 'node.dmesg')]: inst = type.instance() for name in lst: self.server.register_function(getattr(inst, name), "xend.%s.%s" % (n, name)) # A few special cases self.server.register_function(domain, 'xend.domain') self.server.register_function(domains, 'xend.domains') self.server.register_function(get_log, 'xend.node.log') self.server.register_function(domain_create, 'xend.domain.create') self.server.register_function(domain_restore, 'xend.domain.restore') self.server.register_introspection_functions() self.ready = True self.server.serve_forever()