# HG changeset patch
# User Alastair Tse <atse@xxxxxxxxxxxxx>
# Date 1169751265 0
# Node ID b111908dd70b82edda1a0e61de6a269a9bff890d
# Parent 3bb7136c8fb4be315e9cd7222c986e33442cbb71
[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@xxxxxxxxxxxxx>
---
tools/python/scripts/xapi.py | 29 ++++++++++
tools/python/xen/xend/XendAPI.py | 69 +++++++++++++++++++++++++-
tools/python/xen/xend/XendAPIConstants.py | 1
tools/python/xen/xend/XendConfig.py | 40 +++++++++++----
tools/python/xen/xend/XendDevices.py | 8 +--
tools/python/xen/xend/XendDomainInfo.py | 36 +++++++++++--
tools/python/xen/xend/server/DevController.py | 5 +
7 files changed, 164 insertions(+), 24 deletions(-)
diff -r 3bb7136c8fb4 -r b111908dd70b tools/python/scripts/xapi.py
--- a/tools/python/scripts/xapi.py Thu Jan 25 18:50:08 2007 +0000
+++ b/tools/python/scripts/xapi.py Thu Jan 25 18:54:25 2007 +0000
@@ -40,6 +40,7 @@ VBD_LIST_FORMAT = '%(device)-6s %(uuid)-
VBD_LIST_FORMAT = '%(device)-6s %(uuid)-36s %(VDI)-8s'
TASK_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(status)-8s %(progress)-4s'
VIF_LIST_FORMAT = '%(name)-8s %(device)-7s %(uuid)-36s %(MAC)-10s'
+CONSOLE_LIST_FORMAT = '%(uuid)-36s %(protocol)-8s %(uri)-32s'
COMMANDS = {
'host-info': ('', 'Get Xen Host Info'),
@@ -485,7 +486,8 @@ def xapi_vbd_list(args, async = False):
for vbd in vbds:
vbd_struct = execute(server, 'VBD.get_record', (session, vbd))
print VBD_LIST_FORMAT % vbd_struct
-
+
+
def xapi_vbd_stats(args, async = False):
server, session = connect()
domname = args[0]
@@ -518,6 +520,31 @@ def xapi_vif_list(args, async = False):
for vif in vifs:
vif_struct = execute(server, 'VIF.get_record', (session, vif))
pprint(vif_struct)
+
+def xapi_console_list(args, async = False):
+ server, session = connect()
+ opts, args = parse_args('vdi-list', args, set_defaults = True)
+ is_long = opts and opts.long
+
+ domname = args[0]
+
+ dom_uuid = resolve_vm(server, session, domname)
+ consoles = execute(server, 'VM.get_consoles', (session, dom_uuid))
+
+ if not is_long:
+ print CONSOLE_LIST_FORMAT % {'protocol': 'Protocol',
+ 'uri': 'URI',
+ 'uuid': 'UUID'}
+
+ for console in consoles:
+ console_struct = execute(server, 'console.get_record',
+ (session, console))
+ print CONSOLE_LIST_FORMAT % console_struct
+ else:
+ for console in consoles:
+ console_struct = execute(server, 'console.get_record',
+ (session, console))
+ pprint(console_struct)
def xapi_vdi_list(args, async = False):
diff -r 3bb7136c8fb4 -r b111908dd70b tools/python/xen/xend/XendAPI.py
--- a/tools/python/xen/xend/XendAPI.py Thu Jan 25 18:50:08 2007 +0000
+++ b/tools/python/xen/xend/XendAPI.py Thu Jan 25 18:54:25 2007 +0000
@@ -228,6 +228,18 @@ def valid_vtpm(func):
_check_ref(lambda r: XendDomain.instance().is_valid_dev('vtpm', r),
'VTPM_HANDLE_INVALID', func, *args, **kwargs)
+
+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
+ """
+ return lambda *args, **kwargs: \
+ _check_ref(lambda r: XendDomain.instance().is_valid_dev('console',
+ r),
+ 'CONSOLE_HANDLE_INVALID', func, *args, **kwargs)
+
def valid_sr(func):
"""Decorator to verify if sr_ref is valid before calling method.
@@ -346,6 +358,7 @@ class XendAPI(object):
'VIF' : valid_vif,
'VDI' : valid_vdi,
'VTPM' : valid_vtpm,
+ 'console' : valid_console,
'SR' : valid_sr,
'PIF' : valid_pif,
'task' : valid_task,
@@ -983,14 +996,18 @@ class XendAPI(object):
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):
@@ -1784,6 +1801,54 @@ class XendAPI(object):
vtpms = reduce(lambda x, y: x + y, vtpms)
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
# ----------------------------------------------------------------
diff -r 3bb7136c8fb4 -r b111908dd70b tools/python/xen/xend/XendAPIConstants.py
--- a/tools/python/xen/xend/XendAPIConstants.py Thu Jan 25 18:50:08 2007 +0000
+++ b/tools/python/xen/xend/XendAPIConstants.py Thu Jan 25 18:54:25 2007 +0000
@@ -75,3 +75,4 @@ XEN_API_DRIVER_TYPE = ['ioemu', 'paravir
XEN_API_DRIVER_TYPE = ['ioemu', 'paravirtualised']
XEN_API_VBD_TYPE = ['CD', 'Disk']
XEN_API_TASK_STATUS_TYPE = ['pending', 'success', 'failure']
+XEN_API_CONSOLE_PROTOCOL = ['vt100', 'rfb', 'rdp']
diff -r 3bb7136c8fb4 -r b111908dd70b tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py Thu Jan 25 18:50:08 2007 +0000
+++ b/tools/python/xen/xend/XendConfig.py Thu Jan 25 18:54:25 2007 +0000
@@ -918,8 +918,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)
@@ -927,10 +926,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':
@@ -971,7 +970,12 @@ 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
if cfg_xenapi:
@@ -1031,7 +1035,25 @@ class XendConfig(dict):
# no valid device to add
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.
@@ -1211,7 +1233,7 @@ class XendConfig(dict):
self[apikey] = val
-
+
#
# debugging
#
diff -r 3bb7136c8fb4 -r b111908dd70b tools/python/xen/xend/XendDevices.py
--- a/tools/python/xen/xend/XendDevices.py Thu Jan 25 18:50:08 2007 +0000
+++ b/tools/python/xen/xend/XendDevices.py Thu Jan 25 18:54:25 2007 +0000
@@ -21,6 +21,8 @@
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,17 +45,13 @@ class XendDevices:
'tap': BlktapController,
'vfb': vfbif.VfbifController,
'vkbd': vfbif.VkbdifController,
+ 'console': ConsoleController,
}
#@classmethod
def valid_devices(cls):
return cls.controllers.keys()
valid_devices = classmethod(valid_devices)
-
- #@classmethod
- def pseudo_devices(cls):
- return ['console']
- pseudo_devices = classmethod(pseudo_devices)
#@classmethod
def make_controller(cls, name, domain):
diff -r 3bb7136c8fb4 -r b111908dd70b tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Thu Jan 25 18:50:08 2007 +0000
+++ b/tools/python/xen/xend/XendDomainInfo.py Thu Jan 25 18:54:25 2007 +0000
@@ -682,6 +682,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/*
#
@@ -1892,7 +1915,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)
@@ -1904,11 +1928,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
diff -r 3bb7136c8fb4 -r b111908dd70b
tools/python/xen/xend/server/DevController.py
--- a/tools/python/xen/xend/server/DevController.py Thu Jan 25 18:50:08
2007 +0000
+++ b/tools/python/xen/xend/server/DevController.py Thu Jan 25 18:54:25
2007 +0000
@@ -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)
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|