Index: xen-3.0.4-testing/tools/python/xen/xend/server/DevController.py =================================================================== --- xen-3.0.4-testing.orig/tools/python/xen/xend/server/DevController.py +++ xen-3.0.4-testing/tools/python/xen/xend/server/DevController.py @@ -75,7 +75,7 @@ class DevController: def __init__(self, vm): self.vm = vm - + self.hotplug = True def createDevice(self, config): """Trigger the creation of a device with the given configuration. @@ -151,6 +151,9 @@ class DevController: def waitForDevice(self, devid): log.debug("Waiting for %s.", devid) + + if not self.hotplug: + return status = self.waitForBackend(devid) Index: xen-3.0.4-testing/tools/python/xen/xend/XendAPIConstants.py =================================================================== --- xen-3.0.4-testing.orig/tools/python/xen/xend/XendAPIConstants.py +++ xen-3.0.4-testing/tools/python/xen/xend/XendAPIConstants.py @@ -74,3 +74,4 @@ XEN_API_VBD_MODE = ['RO', 'RW'] XEN_API_VDI_TYPE = ['system', 'user', 'ephemeral'] XEN_API_DRIVER_TYPE = ['ioemu', 'paravirtualised'] XEN_API_VBD_TYPE = ['CD', 'Disk'] +XEN_API_CONSOLE_PROTOCOL = ['vt100', 'rfb', 'rdp'] Index: xen-3.0.4-testing/tools/python/xen/xend/XendAPI.py =================================================================== --- xen-3.0.4-testing.orig/tools/python/xen/xend/XendAPI.py +++ xen-3.0.4-testing/tools/python/xen/xend/XendAPI.py @@ -227,6 +227,27 @@ def valid_vtpm(func): return check_vtpm_ref +def valid_console(func): + """Decorator to verify if console_ref is valid before calling method. + + @param func: function with params: (self, session, console_ref, ...) + @rtype: callable object + """ + def check_console_ref(self, session, console_ref, *args, **kwargs): + xendom = XendDomain.instance() + if type(console_ref) == type(str()) and \ + xendom.is_valid_dev('console', console_ref): + return func(self, session, console_ref, *args, **kwargs) + else: + return {'Status': 'Failure', + 'ErrorDescription': ('ECONSOLEINVALID', 'Console Invalid')} + + # make sure we keep the 'api' attribute + if hasattr(func, 'api'): + check_console_ref.api = func.api + + return check_console_ref + def valid_sr(func): """Decorator to verify if sr_ref is valid before calling method. @@ -299,6 +320,7 @@ class XendAPI: 'VIF': (valid_vif, session_required), 'VDI': (valid_vdi, session_required), 'VTPM':(valid_vtpm, session_required), + 'console':(valid_console, session_required), 'SR': (valid_sr, session_required)} # Cheat methods @@ -719,14 +741,18 @@ class XendAPI: def VM_get_VTPMs(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success(dom.get_vtpms()) + + def VM_get_consoles(self, session, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success(dom.get_consoles()) def VM_get_PCI_bus(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() # unsupported by xc + return dom.get_pci_bus() def VM_get_tools_version(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() + return dom.get_tools_version() # attributes (rw) def VM_get_name_label(self, session, vm_ref): @@ -1507,6 +1533,55 @@ class XendAPI: return xen_api_success(vtpms) + # Xen API: Class console + # ---------------------------------------------------------------- + + + console_attr_ro = ['uri', 'protocol', 'VM'] + console_attr_rw = [] + + def console_get_all(self, session): + xendom = XendDomain.instance() + cons = [d.get_consoles() for d in XendDomain.instance().list('all')] + cons = reduce(lambda x, y: x + y, cons) + return xen_api_success(cons) + + def console_get_uri(self, session, console_ref): + return xen_api_success(xendom.get_dev_property_by_uuid('console', + console_ref, + 'uri')) + + def console_get_protocol(self, session, console_ref): + return xen_api_success(xendom.get_dev_property_by_uuid('console', + console_ref, + 'protocol')) + + def console_get_VM(self, session, console_ref): + xendom = XendDomain.instance() + vm = xendom.get_vm_with_dev_uuid('console', console_ref) + return xen_api_success(vm.get_uuid()) + + # object methods + def console_get_record(self, session, console_ref): + xendom = XendDomain.instance() + vm = xendom.get_vm_with_dev_uuid('console', console_ref) + if not vm: + return xen_api_error(['CONSOLE_HANDLE_INVALID', console_ref]) + cfg = vm.get_dev_xenapi_config('console', console_ref) + if not cfg: + return xen_api_error(['CONSOLE_HANDLE_INVALID', console_ref]) + + valid_console_keys = self.console_attr_ro + self.console_attr_rw + \ + self.Base_attr_ro + self.Base_attr_rw + + return_cfg = {} + for k in cfg.keys(): + if k in valid_console_keys: + return_cfg[k] = cfg[k] + + return xen_api_success(return_cfg) + + # Xen API: Class SR # ---------------------------------------------------------------- SR_attr_ro = ['VDIs', Index: xen-3.0.4-testing/tools/python/xen/xend/XendConfig.py =================================================================== --- xen-3.0.4-testing.orig/tools/python/xen/xend/XendConfig.py +++ xen-3.0.4-testing/tools/python/xen/xend/XendConfig.py @@ -900,8 +900,7 @@ class XendConfig(dict): if target == None: target = self - if dev_type not in XendDevices.valid_devices() and \ - dev_type not in XendDevices.pseudo_devices(): + if dev_type not in XendDevices.valid_devices(): raise XendConfigError("XendConfig: %s not a valid device type" % dev_type) @@ -909,10 +908,10 @@ class XendConfig(dict): raise XendConfigError("XendConfig: device_add requires some " "config.") - if cfg_sxp: - log.debug("XendConfig.device_add: %s" % str(cfg_sxp)) - if cfg_xenapi: - log.debug("XendConfig.device_add: %s" % str(cfg_xenapi)) + #if cfg_sxp: + # log.debug("XendConfig.device_add: %s" % str(cfg_sxp)) + #if cfg_xenapi: + # log.debug("XendConfig.device_add: %s" % str(cfg_xenapi)) if cfg_sxp: if sxp.child0(cfg_sxp) == 'device': @@ -952,6 +951,11 @@ class XendConfig(dict): target['vbd_refs'] = [] if dev_uuid not in target['vbd_refs']: target['vbd_refs'].append(dev_uuid) + elif dev_type in ('console',): + if 'console_refs' not in target: + target['console_refs'] = [] + if dev_uuid not in target['console_refs']: + target['console_refs'].append(dev_uuid) return dev_uuid @@ -1012,6 +1016,25 @@ class XendConfig(dict): return '' + def console_add(self, protocol, uri): + dev_uuid = uuid.createString() + dev_info = { + 'uuid': dev_uuid, + 'protocol': protocol, + 'uri': uri + } + if 'devices' not in self: + self['devices'] = {} + + self['devices'][dev_uuid] = ('console', dev_info) + self['console_refs'].append(dev_uuid) + return dev_info + + def console_get_all(self, protocol): + consoles = [dinfo for dtype, dinfo in self['devices'].values() + if dtype == 'console'] + return [c for c in consoles if c.get('protocol') == protocol] + def device_update(self, dev_uuid, cfg_sxp): """Update an existing device with the new configuration. Index: xen-3.0.4-testing/tools/python/xen/xend/XendDevices.py =================================================================== --- xen-3.0.4-testing.orig/tools/python/xen/xend/XendDevices.py +++ xen-3.0.4-testing/tools/python/xen/xend/XendDevices.py @@ -21,6 +21,7 @@ from xen.xend.server import blkif, netif, tpmif, pciif, iopif, irqif, usbif, vfbif from xen.xend.server.BlktapController import BlktapController +from xen.xend.server.ConsoleController import ConsoleController class XendDevices: """ An ugly halfway point between the module local device name @@ -43,6 +44,7 @@ class XendDevices: 'tap': BlktapController, 'vfb': vfbif.VfbifController, 'vkbd': vfbif.VkbdifController, + 'console': ConsoleController, } #@classmethod @@ -51,11 +53,6 @@ class XendDevices: valid_devices = classmethod(valid_devices) #@classmethod - def pseudo_devices(cls): - return ['console'] - pseudo_devices = classmethod(pseudo_devices) - - #@classmethod def make_controller(cls, name, domain): """Factory function to make device controllers per domain. Index: xen-3.0.4-testing/tools/python/xen/xend/XendDomainInfo.py =================================================================== --- xen-3.0.4-testing.orig/tools/python/xen/xend/XendDomainInfo.py +++ xen-3.0.4-testing/tools/python/xen/xend/XendDomainInfo.py @@ -680,6 +680,29 @@ class XendDomainInfo: for device in devices: self.info.device_add(device[0], cfg_sxp = device) + self._update_consoles() + + def _update_consoles(self): + if self.domid == None or self.domid == 0: + return + + # Update VT100 port if it exists + self.console_port = self.readDom('console/port') + if self.console_port is not None: + serial_consoles = self.info.console_get_all('vt100') + if not serial_consoles: + cfg = self.info.console_add('vt100', self.console_port) + self._createDevice('console', cfg) + + # Update VNC port if it exists + vnc_port = self.readDom('console/vnc-port') + if vnc_port is not None: + vnc_consoles = self.info.console_get_all('rfb') + if not vnc_consoles: + cfg = self.info.console_add('rfb', 'localhost:%s' % + str(vnc_port)) + self._createDevice('console', cfg) + # # Function to update xenstore /vm/* # @@ -1825,7 +1848,8 @@ class XendDomainInfo: # TODO: we should eventually get rid of old_dom_states self.info.update_config(info) - + self._update_consoles() + if refresh: self.refreshShutdown(info) @@ -1837,11 +1861,11 @@ class XendDomainInfo: ignore_devices = ignore_store, legacy_only = legacy_only) - if not ignore_store and self.dompath: - vnc_port = self.readDom('console/vnc-port') - if vnc_port is not None: - result.append(['device', - ['console', ['vnc-port', str(vnc_port)]]]) + #if not ignore_store and self.dompath: + # vnc_port = self.readDom('console/vnc-port') + # if vnc_port is not None: + # result.append(['device', + # ['console', ['vnc-port', str(vnc_port)]]]) return result