debuggers.hg
changeset 13654:b111908dd70b
[XEND] Preliminary console support in Xen API
Made serial/vnc consoles a 'fake' device so that we can take advantage
of storing state information in xenstore.
Signed-off-by: Alastair Tse <atse@xensource.com>
Made serial/vnc consoles a 'fake' device so that we can take advantage
of storing state information in xenstore.
Signed-off-by: Alastair Tse <atse@xensource.com>
author | Alastair Tse <atse@xensource.com> |
---|---|
date | Thu Jan 25 18:54:25 2007 +0000 (2007-01-25) |
parents | 3bb7136c8fb4 |
children | db3d03dfe92f |
files | tools/python/scripts/xapi.py tools/python/xen/xend/XendAPI.py tools/python/xen/xend/XendAPIConstants.py tools/python/xen/xend/XendConfig.py tools/python/xen/xend/XendDevices.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/server/DevController.py |
line diff
1.1 --- a/tools/python/scripts/xapi.py Thu Jan 25 18:50:08 2007 +0000 1.2 +++ b/tools/python/scripts/xapi.py Thu Jan 25 18:54:25 2007 +0000 1.3 @@ -40,6 +40,7 @@ VDI_LIST_FORMAT = '%(name_label)-18s %(u 1.4 VBD_LIST_FORMAT = '%(device)-6s %(uuid)-36s %(VDI)-8s' 1.5 TASK_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(status)-8s %(progress)-4s' 1.6 VIF_LIST_FORMAT = '%(name)-8s %(device)-7s %(uuid)-36s %(MAC)-10s' 1.7 +CONSOLE_LIST_FORMAT = '%(uuid)-36s %(protocol)-8s %(uri)-32s' 1.8 1.9 COMMANDS = { 1.10 'host-info': ('', 'Get Xen Host Info'), 1.11 @@ -485,7 +486,8 @@ def xapi_vbd_list(args, async = False): 1.12 for vbd in vbds: 1.13 vbd_struct = execute(server, 'VBD.get_record', (session, vbd)) 1.14 print VBD_LIST_FORMAT % vbd_struct 1.15 - 1.16 + 1.17 + 1.18 def xapi_vbd_stats(args, async = False): 1.19 server, session = connect() 1.20 domname = args[0] 1.21 @@ -519,6 +521,31 @@ def xapi_vif_list(args, async = False): 1.22 vif_struct = execute(server, 'VIF.get_record', (session, vif)) 1.23 pprint(vif_struct) 1.24 1.25 +def xapi_console_list(args, async = False): 1.26 + server, session = connect() 1.27 + opts, args = parse_args('vdi-list', args, set_defaults = True) 1.28 + is_long = opts and opts.long 1.29 + 1.30 + domname = args[0] 1.31 + 1.32 + dom_uuid = resolve_vm(server, session, domname) 1.33 + consoles = execute(server, 'VM.get_consoles', (session, dom_uuid)) 1.34 + 1.35 + if not is_long: 1.36 + print CONSOLE_LIST_FORMAT % {'protocol': 'Protocol', 1.37 + 'uri': 'URI', 1.38 + 'uuid': 'UUID'} 1.39 + 1.40 + for console in consoles: 1.41 + console_struct = execute(server, 'console.get_record', 1.42 + (session, console)) 1.43 + print CONSOLE_LIST_FORMAT % console_struct 1.44 + else: 1.45 + for console in consoles: 1.46 + console_struct = execute(server, 'console.get_record', 1.47 + (session, console)) 1.48 + pprint(console_struct) 1.49 + 1.50 1.51 def xapi_vdi_list(args, async = False): 1.52 opts, args = parse_args('vdi-list', args, set_defaults = True)
2.1 --- a/tools/python/xen/xend/XendAPI.py Thu Jan 25 18:50:08 2007 +0000 2.2 +++ b/tools/python/xen/xend/XendAPI.py Thu Jan 25 18:54:25 2007 +0000 2.3 @@ -228,6 +228,18 @@ def valid_vtpm(func): 2.4 _check_ref(lambda r: XendDomain.instance().is_valid_dev('vtpm', r), 2.5 'VTPM_HANDLE_INVALID', func, *args, **kwargs) 2.6 2.7 + 2.8 +def valid_console(func): 2.9 + """Decorator to verify if console_ref is valid before calling method. 2.10 + 2.11 + @param func: function with params: (self, session, console_ref, ...) 2.12 + @rtype: callable object 2.13 + """ 2.14 + return lambda *args, **kwargs: \ 2.15 + _check_ref(lambda r: XendDomain.instance().is_valid_dev('console', 2.16 + r), 2.17 + 'CONSOLE_HANDLE_INVALID', func, *args, **kwargs) 2.18 + 2.19 def valid_sr(func): 2.20 """Decorator to verify if sr_ref is valid before calling method. 2.21 2.22 @@ -346,6 +358,7 @@ class XendAPI(object): 2.23 'VIF' : valid_vif, 2.24 'VDI' : valid_vdi, 2.25 'VTPM' : valid_vtpm, 2.26 + 'console' : valid_console, 2.27 'SR' : valid_sr, 2.28 'PIF' : valid_pif, 2.29 'task' : valid_task, 2.30 @@ -983,14 +996,18 @@ class XendAPI(object): 2.31 def VM_get_VTPMs(self, session, vm_ref): 2.32 dom = XendDomain.instance().get_vm_by_uuid(vm_ref) 2.33 return xen_api_success(dom.get_vtpms()) 2.34 + 2.35 + def VM_get_consoles(self, session, vm_ref): 2.36 + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) 2.37 + return xen_api_success(dom.get_consoles()) 2.38 2.39 def VM_get_PCI_bus(self, session, vm_ref): 2.40 dom = XendDomain.instance().get_vm_by_uuid(vm_ref) 2.41 - return xen_api_todo() # unsupported by xc 2.42 + return dom.get_pci_bus() 2.43 2.44 def VM_get_tools_version(self, session, vm_ref): 2.45 dom = XendDomain.instance().get_vm_by_uuid(vm_ref) 2.46 - return xen_api_todo() 2.47 + return dom.get_tools_version() 2.48 2.49 # attributes (rw) 2.50 def VM_get_name_label(self, session, vm_ref): 2.51 @@ -1784,6 +1801,54 @@ class XendAPI(object): 2.52 vtpms = reduce(lambda x, y: x + y, vtpms) 2.53 return xen_api_success(vtpms) 2.54 2.55 + # Xen API: Class console 2.56 + # ---------------------------------------------------------------- 2.57 + 2.58 + 2.59 + console_attr_ro = ['uri', 'protocol', 'VM'] 2.60 + console_attr_rw = [] 2.61 + 2.62 + def console_get_all(self, session): 2.63 + xendom = XendDomain.instance() 2.64 + cons = [d.get_consoles() for d in XendDomain.instance().list('all')] 2.65 + cons = reduce(lambda x, y: x + y, cons) 2.66 + return xen_api_success(cons) 2.67 + 2.68 + def console_get_uri(self, session, console_ref): 2.69 + return xen_api_success(xendom.get_dev_property_by_uuid('console', 2.70 + console_ref, 2.71 + 'uri')) 2.72 + 2.73 + def console_get_protocol(self, session, console_ref): 2.74 + return xen_api_success(xendom.get_dev_property_by_uuid('console', 2.75 + console_ref, 2.76 + 'protocol')) 2.77 + 2.78 + def console_get_VM(self, session, console_ref): 2.79 + xendom = XendDomain.instance() 2.80 + vm = xendom.get_vm_with_dev_uuid('console', console_ref) 2.81 + return xen_api_success(vm.get_uuid()) 2.82 + 2.83 + # object methods 2.84 + def console_get_record(self, session, console_ref): 2.85 + xendom = XendDomain.instance() 2.86 + vm = xendom.get_vm_with_dev_uuid('console', console_ref) 2.87 + if not vm: 2.88 + return xen_api_error(['CONSOLE_HANDLE_INVALID', console_ref]) 2.89 + cfg = vm.get_dev_xenapi_config('console', console_ref) 2.90 + if not cfg: 2.91 + return xen_api_error(['CONSOLE_HANDLE_INVALID', console_ref]) 2.92 + 2.93 + valid_console_keys = self.console_attr_ro + self.console_attr_rw + \ 2.94 + self.Base_attr_ro + self.Base_attr_rw 2.95 + 2.96 + return_cfg = {} 2.97 + for k in cfg.keys(): 2.98 + if k in valid_console_keys: 2.99 + return_cfg[k] = cfg[k] 2.100 + 2.101 + return xen_api_success(return_cfg) 2.102 + 2.103 2.104 # Xen API: Class SR 2.105 # ----------------------------------------------------------------
3.1 --- a/tools/python/xen/xend/XendAPIConstants.py Thu Jan 25 18:50:08 2007 +0000 3.2 +++ b/tools/python/xen/xend/XendAPIConstants.py Thu Jan 25 18:54:25 2007 +0000 3.3 @@ -75,3 +75,4 @@ XEN_API_VDI_TYPE = ['system', 'user', 'e 3.4 XEN_API_DRIVER_TYPE = ['ioemu', 'paravirtualised'] 3.5 XEN_API_VBD_TYPE = ['CD', 'Disk'] 3.6 XEN_API_TASK_STATUS_TYPE = ['pending', 'success', 'failure'] 3.7 +XEN_API_CONSOLE_PROTOCOL = ['vt100', 'rfb', 'rdp']
4.1 --- a/tools/python/xen/xend/XendConfig.py Thu Jan 25 18:50:08 2007 +0000 4.2 +++ b/tools/python/xen/xend/XendConfig.py Thu Jan 25 18:54:25 2007 +0000 4.3 @@ -918,8 +918,7 @@ class XendConfig(dict): 4.4 if target == None: 4.5 target = self 4.6 4.7 - if dev_type not in XendDevices.valid_devices() and \ 4.8 - dev_type not in XendDevices.pseudo_devices(): 4.9 + if dev_type not in XendDevices.valid_devices(): 4.10 raise XendConfigError("XendConfig: %s not a valid device type" % 4.11 dev_type) 4.12 4.13 @@ -927,10 +926,10 @@ class XendConfig(dict): 4.14 raise XendConfigError("XendConfig: device_add requires some " 4.15 "config.") 4.16 4.17 - if cfg_sxp: 4.18 - log.debug("XendConfig.device_add: %s" % str(cfg_sxp)) 4.19 - if cfg_xenapi: 4.20 - log.debug("XendConfig.device_add: %s" % str(cfg_xenapi)) 4.21 + #if cfg_sxp: 4.22 + # log.debug("XendConfig.device_add: %s" % str(cfg_sxp)) 4.23 + #if cfg_xenapi: 4.24 + # log.debug("XendConfig.device_add: %s" % str(cfg_xenapi)) 4.25 4.26 if cfg_sxp: 4.27 if sxp.child0(cfg_sxp) == 'device': 4.28 @@ -971,7 +970,12 @@ class XendConfig(dict): 4.29 target['vbd_refs'] = [] 4.30 if dev_uuid not in target['vbd_refs']: 4.31 target['vbd_refs'].append(dev_uuid) 4.32 - 4.33 + elif dev_type in ('console',): 4.34 + if 'console_refs' not in target: 4.35 + target['console_refs'] = [] 4.36 + if dev_uuid not in target['console_refs']: 4.37 + target['console_refs'].append(dev_uuid) 4.38 + 4.39 return dev_uuid 4.40 4.41 if cfg_xenapi: 4.42 @@ -1031,7 +1035,25 @@ class XendConfig(dict): 4.43 4.44 # no valid device to add 4.45 return '' 4.46 - 4.47 + 4.48 + def console_add(self, protocol, uri): 4.49 + dev_uuid = uuid.createString() 4.50 + dev_info = { 4.51 + 'uuid': dev_uuid, 4.52 + 'protocol': protocol, 4.53 + 'uri': uri 4.54 + } 4.55 + if 'devices' not in self: 4.56 + self['devices'] = {} 4.57 + 4.58 + self['devices'][dev_uuid] = ('console', dev_info) 4.59 + self['console_refs'].append(dev_uuid) 4.60 + return dev_info 4.61 + 4.62 + def console_get_all(self, protocol): 4.63 + consoles = [dinfo for dtype, dinfo in self['devices'].values() 4.64 + if dtype == 'console'] 4.65 + return [c for c in consoles if c.get('protocol') == protocol] 4.66 4.67 def device_update(self, dev_uuid, cfg_sxp): 4.68 """Update an existing device with the new configuration. 4.69 @@ -1211,7 +1233,7 @@ class XendConfig(dict): 4.70 self[apikey] = val 4.71 4.72 4.73 - 4.74 + 4.75 # 4.76 # debugging 4.77 #
5.1 --- a/tools/python/xen/xend/XendDevices.py Thu Jan 25 18:50:08 2007 +0000 5.2 +++ b/tools/python/xen/xend/XendDevices.py Thu Jan 25 18:54:25 2007 +0000 5.3 @@ -21,6 +21,8 @@ 5.4 5.5 from xen.xend.server import blkif, netif, tpmif, pciif, iopif, irqif, usbif, vfbif 5.6 from xen.xend.server.BlktapController import BlktapController 5.7 +from xen.xend.server.ConsoleController import ConsoleController 5.8 + 5.9 5.10 class XendDevices: 5.11 """ An ugly halfway point between the module local device name 5.12 @@ -43,6 +45,7 @@ class XendDevices: 5.13 'tap': BlktapController, 5.14 'vfb': vfbif.VfbifController, 5.15 'vkbd': vfbif.VkbdifController, 5.16 + 'console': ConsoleController, 5.17 } 5.18 5.19 #@classmethod 5.20 @@ -51,11 +54,6 @@ class XendDevices: 5.21 valid_devices = classmethod(valid_devices) 5.22 5.23 #@classmethod 5.24 - def pseudo_devices(cls): 5.25 - return ['console'] 5.26 - pseudo_devices = classmethod(pseudo_devices) 5.27 - 5.28 - #@classmethod 5.29 def make_controller(cls, name, domain): 5.30 """Factory function to make device controllers per domain. 5.31
6.1 --- a/tools/python/xen/xend/XendDomainInfo.py Thu Jan 25 18:50:08 2007 +0000 6.2 +++ b/tools/python/xen/xend/XendDomainInfo.py Thu Jan 25 18:54:25 2007 +0000 6.3 @@ -682,6 +682,29 @@ class XendDomainInfo: 6.4 for device in devices: 6.5 self.info.device_add(device[0], cfg_sxp = device) 6.6 6.7 + self._update_consoles() 6.8 + 6.9 + def _update_consoles(self): 6.10 + if self.domid == None or self.domid == 0: 6.11 + return 6.12 + 6.13 + # Update VT100 port if it exists 6.14 + self.console_port = self.readDom('console/port') 6.15 + if self.console_port is not None: 6.16 + serial_consoles = self.info.console_get_all('vt100') 6.17 + if not serial_consoles: 6.18 + cfg = self.info.console_add('vt100', self.console_port) 6.19 + self._createDevice('console', cfg) 6.20 + 6.21 + # Update VNC port if it exists 6.22 + vnc_port = self.readDom('console/vnc-port') 6.23 + if vnc_port is not None: 6.24 + vnc_consoles = self.info.console_get_all('rfb') 6.25 + if not vnc_consoles: 6.26 + cfg = self.info.console_add('rfb', 'localhost:%s' % 6.27 + str(vnc_port)) 6.28 + self._createDevice('console', cfg) 6.29 + 6.30 # 6.31 # Function to update xenstore /vm/* 6.32 # 6.33 @@ -1892,7 +1915,8 @@ class XendDomainInfo: 6.34 # TODO: we should eventually get rid of old_dom_states 6.35 6.36 self.info.update_config(info) 6.37 - 6.38 + self._update_consoles() 6.39 + 6.40 if refresh: 6.41 self.refreshShutdown(info) 6.42 6.43 @@ -1904,11 +1928,11 @@ class XendDomainInfo: 6.44 ignore_devices = ignore_store, 6.45 legacy_only = legacy_only) 6.46 6.47 - if not ignore_store and self.dompath: 6.48 - vnc_port = self.readDom('console/vnc-port') 6.49 - if vnc_port is not None: 6.50 - result.append(['device', 6.51 - ['console', ['vnc-port', str(vnc_port)]]]) 6.52 + #if not ignore_store and self.dompath: 6.53 + # vnc_port = self.readDom('console/vnc-port') 6.54 + # if vnc_port is not None: 6.55 + # result.append(['device', 6.56 + # ['console', ['vnc-port', str(vnc_port)]]]) 6.57 6.58 return result 6.59
7.1 --- a/tools/python/xen/xend/server/DevController.py Thu Jan 25 18:50:08 2007 +0000 7.2 +++ b/tools/python/xen/xend/server/DevController.py Thu Jan 25 18:54:25 2007 +0000 7.3 @@ -75,7 +75,7 @@ class DevController: 7.4 7.5 def __init__(self, vm): 7.6 self.vm = vm 7.7 - 7.8 + self.hotplug = True 7.9 7.10 def createDevice(self, config): 7.11 """Trigger the creation of a device with the given configuration. 7.12 @@ -151,6 +151,9 @@ class DevController: 7.13 7.14 def waitForDevice(self, devid): 7.15 log.debug("Waiting for %s.", devid) 7.16 + 7.17 + if not self.hotplug: 7.18 + return 7.19 7.20 status = self.waitForBackend(devid) 7.21