663 lines
26 KiB
Diff
663 lines
26 KiB
Diff
# HG changeset patch
|
|
# User Alastair Tse <atse@xensource.com>
|
|
# Date 1170249636 0
|
|
# Node ID 3cccf8e6429666be58408972570dbd063a2bae1e
|
|
# Parent 7c992fd3b19ba3f7094e0c01205a481dc74661f8
|
|
[XEND] Merge VFB support for PV and HVM guests.
|
|
|
|
This patch merges the way VFB are represented inside Xend by making
|
|
HVM VNC consoles use the VFB as its configuration object.
|
|
|
|
It preserves the way options are specified through xm but will create
|
|
a new VFB device that is used by image.py to put vnc config into
|
|
qemu-dm's command line. The parsing is moved into image.py's
|
|
parseDeviceModel() rather than in configVNC().
|
|
|
|
Through the Xen API, you can create a 'console' of protocol 'rfb' and
|
|
end up with a VNC console, on both HVM and PV guests. The location of
|
|
the connecting port is stored in the location attribute of the console
|
|
object. This is updated on each XendDomainInfo.update() if it
|
|
changes.
|
|
|
|
Also fixes missing read of the vnclisten and HVM_boot from the
|
|
config when initialised via xm. Makes sure bootable attribute for VBD
|
|
is store as an int when making SXP config.
|
|
|
|
Signed-off-by: Alastair Tse <atse@xensource.com>
|
|
|
|
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
|
|
@@ -1511,8 +1511,9 @@ class XendAPI:
|
|
# ----------------------------------------------------------------
|
|
|
|
|
|
- console_attr_ro = ['uri', 'protocol', 'VM']
|
|
- console_attr_rw = []
|
|
+ console_attr_ro = ['location', 'protocol', 'VM']
|
|
+ console_attr_rw = ['other_config']
|
|
+ console_funcs = [('create', 'console')]
|
|
|
|
def console_get_all(self, session):
|
|
xendom = XendDomain.instance()
|
|
@@ -1520,10 +1521,10 @@ class XendAPI:
|
|
cons = reduce(lambda x, y: x + y, cons)
|
|
return xen_api_success(cons)
|
|
|
|
- def console_get_uri(self, session, console_ref):
|
|
+ def console_get_location(self, session, console_ref):
|
|
return xen_api_success(xendom.get_dev_property_by_uuid('console',
|
|
console_ref,
|
|
- 'uri'))
|
|
+ 'location'))
|
|
|
|
def console_get_protocol(self, session, console_ref):
|
|
return xen_api_success(xendom.get_dev_property_by_uuid('console',
|
|
@@ -1555,6 +1556,22 @@ class XendAPI:
|
|
|
|
return xen_api_success(return_cfg)
|
|
|
|
+ def console_create(self, session, console_struct):
|
|
+ xendom = XendDomain.instance()
|
|
+ if not xendom.is_valid_vm(console_struct['VM']):
|
|
+ return xen_api_error(['VM_HANDLE_INVALID', console_struct['VM']])
|
|
+
|
|
+ dom = xendom.get_vm_by_uuid(console_struct['VM'])
|
|
+ try:
|
|
+ if 'protocol' not in console_struct:
|
|
+ return xen_api_error(['CONSOLE_PROTOCOL_INVALID',
|
|
+ 'No protocol specified'])
|
|
+
|
|
+ console_ref = dom.create_console(console_struct)
|
|
+ xendom.managed_config_save(dom)
|
|
+ return xen_api_success(console_ref)
|
|
+ except XendError, e:
|
|
+ return xen_api_error([XEND_ERROR_TODO, str(e)])
|
|
|
|
# Xen API: Class SR
|
|
# ----------------------------------------------------------------
|
|
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
|
|
@@ -107,6 +107,7 @@ XENAPI_HVM_CFG = {
|
|
'platform_serial' : 'serial',
|
|
'platform_localtime': 'localtime',
|
|
'platform_keymap' : 'keymap',
|
|
+ 'HVM_boot': 'boot',
|
|
}
|
|
|
|
# List of XendConfig configuration keys that have no direct equivalent
|
|
@@ -230,7 +231,8 @@ LEGACY_IMAGE_CFG = [
|
|
('sdl', int),
|
|
('vncdisplay', int),
|
|
('vncunused', int),
|
|
- ('vncpasswd', str),
|
|
+ ('vncpasswd', str),
|
|
+ ('vnclisten', str),
|
|
]
|
|
|
|
LEGACY_IMAGE_HVM_CFG = [
|
|
@@ -362,6 +364,7 @@ class XendConfig(dict):
|
|
'vif_refs': [],
|
|
'vbd_refs': [],
|
|
'vtpm_refs': [],
|
|
+ 'other_config': {},
|
|
}
|
|
|
|
defaults['name_label'] = 'Domain-' + defaults['uuid']
|
|
@@ -643,6 +646,25 @@ class XendConfig(dict):
|
|
self['vbd_refs'] = cfg.get('vbd_refs', [])
|
|
self['vtpm_refs'] = cfg.get('vtpm_refs', [])
|
|
|
|
+ # coalesce hvm vnc frame buffer with vfb config
|
|
+ if self['image']['type'] == 'hvm' and self['image'].get('vnc', 0):
|
|
+ # add vfb device if it isn't there already
|
|
+ has_rfb = False
|
|
+ for console_uuid in self['console_refs']:
|
|
+ if self['devices'][console_uuid][1].get('protocol') == 'rfb':
|
|
+ has_rfb = True
|
|
+ break
|
|
+
|
|
+ if not has_rfb:
|
|
+ dev_config = ['vfb']
|
|
+ # copy VNC related params from image config to vfb dev conf
|
|
+ for key in ['vncpasswd', 'vncunused', 'vncdisplay',
|
|
+ 'vnclisten']:
|
|
+ if key in self['image']:
|
|
+ dev_config.append([key, self['image'][key]])
|
|
+
|
|
+ self.device_add('vfb', cfg_sxp = dev_config)
|
|
+
|
|
|
|
def _sxp_to_xapi_unsupported(self, sxp_cfg):
|
|
"""Read in an SXP configuration object and populate
|
|
@@ -951,6 +973,26 @@ class XendConfig(dict):
|
|
target['vbd_refs'] = []
|
|
if dev_uuid not in target['vbd_refs']:
|
|
target['vbd_refs'].append(dev_uuid)
|
|
+ elif dev_type == 'vfb':
|
|
+ # Populate other config with aux data that is associated
|
|
+ # with vfb
|
|
+
|
|
+ other_config = {}
|
|
+ for key in ['vncunused', 'vncdisplay', 'vnclisten',
|
|
+ 'vncpasswd', 'type', 'display', 'xauthority',
|
|
+ 'keymap']:
|
|
+ if key in dev_info:
|
|
+ other_config[key] = dev_info[key]
|
|
+ target['devices'][dev_uuid][1]['other_config'] = other_config
|
|
+
|
|
+
|
|
+ if 'console_refs' not in target:
|
|
+ target['console_refs'] = []
|
|
+
|
|
+ # Treat VFB devices as console devices so they are found
|
|
+ # through Xen API
|
|
+ if dev_uuid not in target['console_refs']:
|
|
+ target['console_refs'].append(dev_uuid)
|
|
elif dev_type in ('console',):
|
|
if 'console_refs' not in target:
|
|
target['console_refs'] = []
|
|
@@ -1010,49 +1052,118 @@ class XendConfig(dict):
|
|
target['devices'][dev_uuid] = (dev_type, dev_info)
|
|
target['vtpm_refs'].append(dev_uuid)
|
|
|
|
+ elif dev_type == 'console':
|
|
+ dev_uuid = cfg_xenapi.get('uuid', uuid.createString())
|
|
+ dev_info['uuid'] = dev_uuid
|
|
+ dev_info['protocol'] = cfg_xenapi.get('protocol', 'rfb')
|
|
+ dev_info['other_config'] = cfg_xenapi.get('other_config', {})
|
|
+ if dev_info['protocol'] == 'rfb':
|
|
+ # collapse other config into devinfo for things
|
|
+ # such as vncpasswd, vncunused, etc.
|
|
+ dev_info.update(cfg_xenapi.get('other_config', {}))
|
|
+ dev_info['type'] = 'vnc'
|
|
+ target['devices'][dev_uuid] = ('vfb', dev_info)
|
|
+ target['console_refs'].append(dev_uuid)
|
|
+
|
|
+ # Finally, if we are a pvfb, we need to make a vkbd
|
|
+ # as well that is not really exposed to Xen API
|
|
+ vkbd_uuid = uuid.createString()
|
|
+ target['devices'][vkbd_uuid] = ('vkbd', {})
|
|
+
|
|
+ elif dev_info['protocol'] == 'vt100':
|
|
+ # if someone tries to create a VT100 console
|
|
+ # via the Xen API, we'll have to ignore it
|
|
+ # because we create one automatically in
|
|
+ # XendDomainInfo._update_consoles
|
|
+ raise XendConfigError('Creating vt100 consoles via '
|
|
+ 'Xen API is unsupported')
|
|
+
|
|
return dev_uuid
|
|
|
|
# no valid device to add
|
|
return ''
|
|
|
|
|
|
- def console_add(self, protocol, uri):
|
|
+ def console_add(self, protocol, location, other_config = {}):
|
|
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
|
|
-
|
|
+ if protocol == 'vt100':
|
|
+ dev_info = {
|
|
+ 'uuid': dev_uuid,
|
|
+ 'protocol': protocol,
|
|
+ 'location': location,
|
|
+ 'other_config': other_config,
|
|
+ }
|
|
+
|
|
+ if 'devices' not in self:
|
|
+ self['devices'] = {}
|
|
+
|
|
+ self['devices'][dev_uuid] = ('console', dev_info)
|
|
+ self['console_refs'].append(dev_uuid)
|
|
+ return dev_info
|
|
+
|
|
+ return {}
|
|
+
|
|
+ def console_update(self, console_uuid, key, value):
|
|
+ for dev_uuid, (dev_type, dev_info) in self['devices'].items():
|
|
+ if dev_uuid == console_uuid:
|
|
+ dev_info[key] = value
|
|
+ break
|
|
+
|
|
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]
|
|
+ if protocol == 'vt100':
|
|
+ consoles = [dinfo for dtype, dinfo in self['devices'].values()
|
|
+ if dtype == 'console']
|
|
+ return [c for c in consoles if c.get('protocol') == protocol]
|
|
+
|
|
+ elif protocol == 'rfb':
|
|
+ vfbs = [dinfo for dtype, dinfo in self['devices'].values()
|
|
+ if dtype == 'vfb']
|
|
+
|
|
+ # move all non-console key values to other_config before
|
|
+ # returning console config
|
|
+ valid_keys = ['uuid', 'location']
|
|
+ for vfb in vfbs:
|
|
+ other_config = {}
|
|
+ for key, val in vfb.items():
|
|
+ if key not in valid_keys:
|
|
+ other_config[key] = vfb[key]
|
|
+ del vfb[key]
|
|
+ vfb['other_config'] = other_config
|
|
+ vfb['protocol'] = 'rfb'
|
|
+
|
|
+ return vfbs
|
|
+
|
|
+ else:
|
|
+ return []
|
|
|
|
- def device_update(self, dev_uuid, cfg_sxp):
|
|
- """Update an existing device with the new configuration.
|
|
+ def device_update(self, dev_uuid, cfg_sxp = [], cfg_xenapi = {}):
|
|
+ """Update an existing device with the new configuration.
|
|
|
|
@rtype: boolean
|
|
@return: Returns True if succesfully found and updated a device conf
|
|
"""
|
|
- if dev_uuid in self['devices']:
|
|
- config = sxp.child0(cfg_sxp)
|
|
- dev_type = sxp.name(config)
|
|
- dev_info = {}
|
|
+ if dev_uuid in self['devices'] and cfg_sxp:
|
|
+ if sxp.child0(cfg_sxp) == 'device':
|
|
+ config = sxp.child0(cfg_sxp)
|
|
+ else:
|
|
+ config = cfg_sxp
|
|
|
|
- try:
|
|
- for opt, val in config[1:]:
|
|
- self['devices'][opt] = val
|
|
- except ValueError:
|
|
- pass # SXP has no options for this device
|
|
-
|
|
+ dev_type, dev_info = self['devices'][dev_uuid]
|
|
+ for opt_val in config[1:]:
|
|
+ try:
|
|
+ opt, val = opt_val
|
|
+ dev_info[opt] = val
|
|
+ except (TypeError, ValueError):
|
|
+ pass # no value for this config option
|
|
+
|
|
+ self['devices'][dev_uuid] = (dev_type, dev_info)
|
|
return True
|
|
+
|
|
+ elif dev_uuid in self['devices'] and cfg_xenapi:
|
|
+ dev_type, dev_info = self['devices'][dev_uuid]
|
|
+ for key, val in cfg_xenapi.items():
|
|
+ dev_info[key] = val
|
|
+ self['devices'][dev_uuid] = (dev_type, dev_info)
|
|
|
|
return False
|
|
|
|
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
|
|
@@ -693,16 +693,29 @@ class XendDomainInfo:
|
|
if not serial_consoles:
|
|
cfg = self.info.console_add('vt100', self.console_port)
|
|
self._createDevice('console', cfg)
|
|
+ else:
|
|
+ console_uuid = serial_consoles[0].get('uuid')
|
|
+ self.info.console_update(console_uuid, 'location',
|
|
+ self.console_port)
|
|
+
|
|
|
|
- # Update VNC port if it exists
|
|
+ # Update VNC port if it exists and write to xenstore
|
|
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)
|
|
-
|
|
+ for dev_uuid, (dev_type, dev_info) in self.info['devices'].items():
|
|
+ if dev_type == 'vfb':
|
|
+ old_location = dev_info.get('location')
|
|
+ listen_host = dev_info.get('vnclisten', 'localhost')
|
|
+ new_location = '%s:%s' % (listen_host, str(vnc_port))
|
|
+ if old_location == new_location:
|
|
+ break
|
|
+
|
|
+ dev_info['location'] = new_location
|
|
+ self.info.device_update(dev_uuid, cfg_xenapi = dev_info)
|
|
+ vfb_ctrl = self.getDeviceController('vfb')
|
|
+ vfb_ctrl.reconfigureDevice(0, dev_info)
|
|
+ break
|
|
+
|
|
#
|
|
# Function to update xenstore /vm/*
|
|
#
|
|
@@ -1952,21 +1965,18 @@ class XendDomainInfo:
|
|
|
|
@rtype: dictionary
|
|
"""
|
|
- dev_type_config = self.info['devices'].get(dev_uuid)
|
|
+ dev_type, dev_config = self.info['devices'].get(dev_uuid, (None, None))
|
|
|
|
# shortcut if the domain isn't started because
|
|
# the devcontrollers will have no better information
|
|
# than XendConfig.
|
|
if self.state in (XEN_API_VM_POWER_STATE_HALTED,):
|
|
- if dev_type_config:
|
|
- return copy.deepcopy(dev_type_config[1])
|
|
+ if dev_config:
|
|
+ return copy.deepcopy(dev_config)
|
|
return None
|
|
|
|
# instead of using dev_class, we use the dev_type
|
|
# that is from XendConfig.
|
|
- # This will accomdate 'tap' as well as 'vbd'
|
|
- dev_type = dev_type_config[0]
|
|
-
|
|
controller = self.getDeviceController(dev_type)
|
|
if not controller:
|
|
return None
|
|
@@ -1975,14 +1985,14 @@ class XendDomainInfo:
|
|
if not all_configs:
|
|
return None
|
|
|
|
- dev_config = copy.deepcopy(dev_type_config[1])
|
|
+ updated_dev_config = copy.deepcopy(dev_config)
|
|
for _devid, _devcfg in all_configs.items():
|
|
if _devcfg.get('uuid') == dev_uuid:
|
|
- dev_config.update(_devcfg)
|
|
- dev_config['id'] = _devid
|
|
- return dev_config
|
|
+ updated_dev_config.update(_devcfg)
|
|
+ updated_dev_config['id'] = _devid
|
|
+ return updated_dev_config
|
|
|
|
- return dev_config
|
|
+ return updated_dev_config
|
|
|
|
def get_dev_xenapi_config(self, dev_class, dev_uuid):
|
|
config = self.get_dev_config_by_uuid(dev_class, dev_uuid)
|
|
@@ -2137,6 +2147,21 @@ class XendDomainInfo:
|
|
|
|
return dev_uuid
|
|
|
|
+ def create_console(self, xenapi_console):
|
|
+ """ Create a console device from a Xen API struct.
|
|
+
|
|
+ @return: uuid of device
|
|
+ @rtype: string
|
|
+ """
|
|
+ if self.state not in (DOM_STATE_HALTED,):
|
|
+ raise VmError("Can only add console to a halted domain.")
|
|
+
|
|
+ dev_uuid = self.info.device_add('console', cfg_xenapi = xenapi_console)
|
|
+ if not dev_uuid:
|
|
+ raise XendError('Failed to create device')
|
|
+
|
|
+ return dev_uuid
|
|
+
|
|
def destroy_device_by_uuid(self, dev_type, dev_uuid):
|
|
if dev_uuid not in self.info['devices']:
|
|
raise XendError('Device does not exist')
|
|
Index: xen-3.0.4-testing/tools/python/xen/xend/image.py
|
|
===================================================================
|
|
--- xen-3.0.4-testing.orig/tools/python/xen/xend/image.py
|
|
+++ xen-3.0.4-testing/tools/python/xen/xend/image.py
|
|
@@ -26,6 +26,7 @@ import xen.lowlevel.xc
|
|
from xen.xend.XendConstants import REVERSE_DOMAIN_SHUTDOWN_REASONS
|
|
from xen.xend.XendError import VmError, XendError
|
|
from xen.xend.XendLogging import log
|
|
+from xen.xend import XendRoot
|
|
from xen.xend.server.netif import randomMAC
|
|
from xen.xend.xenstore.xswatch import xswatch
|
|
from xen.xend import arch
|
|
@@ -361,8 +362,6 @@ class HVMImageHandler(ImageHandler):
|
|
|
|
self.pid = None
|
|
|
|
- self.dmargs += self.configVNC(imageConfig)
|
|
-
|
|
self.pae = imageConfig['hvm'].get('pae', 1)
|
|
self.apic = imageConfig['hvm'].get('apic', 0)
|
|
self.acpi = imageConfig['hvm']['devices'].get('acpi', 0)
|
|
@@ -462,49 +461,59 @@ class HVMImageHandler(ImageHandler):
|
|
net += ",bridge=%s" % (bridge,)
|
|
ret.append(net)
|
|
|
|
- return ret
|
|
|
|
- def configVNC(self, imageConfig):
|
|
- # Handle graphics library related options
|
|
- vnc = imageConfig.get('vnc')
|
|
- sdl = imageConfig.get('sdl')
|
|
- ret = []
|
|
- nographic = imageConfig.get('nographic')
|
|
+ #
|
|
+ # Find RFB console device, and if it exists, make QEMU enable
|
|
+ # the VNC console.
|
|
+ #
|
|
+ if vmConfig['image'].get('nographic'):
|
|
+ # skip vnc init if nographic is set
|
|
+ ret.append('-nographic')
|
|
+ return ret
|
|
|
|
- # get password from VM config (if password omitted, None)
|
|
- vncpasswd_vmconfig = imageConfig.get('vncpasswd')
|
|
+ vnc_config = {}
|
|
+ has_vfb = False
|
|
+ has_vnc = int(vmConfig['image'].get('vnc')) != 0
|
|
+ for dev_uuid in vmConfig['console_refs']:
|
|
+ dev_type, dev_info = vmConfig['devices'][devuuid]
|
|
+ if dev_type == 'rfb':
|
|
+ vnc_config = dev_info.get('other_config', {})
|
|
+ has_vfb = True
|
|
+ break
|
|
+
|
|
+ if not vnc_config:
|
|
+ for key in ('vncunused', 'vnclisten', 'vncdisplay', 'vncpasswd'):
|
|
+ if key in vmConfig['image']:
|
|
+ vnc_config[key] = vmConfig['image'][key]
|
|
|
|
- if nographic:
|
|
+ if not has_vfb and not has_vnc:
|
|
ret.append('-nographic')
|
|
return ret
|
|
|
|
- if vnc:
|
|
- vncdisplay = imageConfig.get('vncdisplay',
|
|
- int(self.vm.getDomid()))
|
|
- vncunused = imageConfig.get('vncunused')
|
|
-
|
|
- if vncunused:
|
|
- ret += ['-vncunused']
|
|
- else:
|
|
- ret += ['-vnc', '%d' % vncdisplay]
|
|
+
|
|
+ if not vnc_config.get('vncunused', 0) and \
|
|
+ vnc_config.get('vncdisplay', 0):
|
|
+ ret.append('-vnc')
|
|
+ ret.append(str(vncdisplay))
|
|
+ else:
|
|
+ ret.append('-vncunused')
|
|
|
|
- vnclisten = imageConfig.get('vnclisten')
|
|
+ vnclisten = vnc_config.get('vnclisten',
|
|
+ XendRoot.instance().get_vnclisten_address())
|
|
+ ret.append('-vnclisten')
|
|
+ ret.append(str(vnclisten))
|
|
+
|
|
+ # Store vncpassword in xenstore
|
|
+ vncpasswd = vnc_config.get('vncpasswd')
|
|
+ if not vncpasswd:
|
|
+ vncpasswd = XendRoot.instance().get_vncpasswd_default()
|
|
+
|
|
+ if vncpasswd is None:
|
|
+ raise VmError('vncpasswd is not setup in vmconfig or '
|
|
+ 'xend-config.sxp')
|
|
|
|
- if not(vnclisten):
|
|
- vnclisten = (xen.xend.XendRoot.instance().
|
|
- get_vnclisten_address())
|
|
- if vnclisten:
|
|
- ret += ['-vnclisten', vnclisten]
|
|
-
|
|
- vncpasswd = vncpasswd_vmconfig
|
|
- if vncpasswd is None:
|
|
- vncpasswd = (xen.xend.XendRoot.instance().
|
|
- get_vncpasswd_default())
|
|
- if vncpasswd is None:
|
|
- raise VmError('vncpasswd is not set up in ' +
|
|
- 'VMconfig and xend-config.')
|
|
- if vncpasswd != '':
|
|
- self.vm.storeVm("vncpasswd", vncpasswd)
|
|
+ if vncpasswd != '':
|
|
+ self.vm.storeVm('vncpasswd', vncpasswd)
|
|
|
|
return ret
|
|
|
|
Index: xen-3.0.4-testing/tools/python/xen/xend/server/ConsoleController.py
|
|
===================================================================
|
|
--- xen-3.0.4-testing.orig/tools/python/xen/xend/server/ConsoleController.py
|
|
+++ xen-3.0.4-testing/tools/python/xen/xend/server/ConsoleController.py
|
|
@@ -8,7 +8,7 @@ class ConsoleController(DevController):
|
|
console devices with persistent UUIDs.
|
|
"""
|
|
|
|
- valid_cfg = ['uri', 'uuid', 'protocol']
|
|
+ valid_cfg = ['location', 'uuid', 'protocol']
|
|
|
|
def __init__(self, vm):
|
|
DevController.__init__(self, vm)
|
|
@@ -29,3 +29,7 @@ class ConsoleController(DevController):
|
|
|
|
def migrate(self, deviceConfig, network, dst, step, domName):
|
|
return 0
|
|
+
|
|
+ def destroyDevice(self, devid, force):
|
|
+ DevController.destroyDevice(self, devid, True)
|
|
+
|
|
Index: xen-3.0.4-testing/tools/python/xen/xend/server/vfbif.py
|
|
===================================================================
|
|
--- xen-3.0.4-testing.orig/tools/python/xen/xend/server/vfbif.py
|
|
+++ xen-3.0.4-testing/tools/python/xen/xend/server/vfbif.py
|
|
@@ -14,7 +14,9 @@ def spawn_detached(path, args, env):
|
|
os.waitpid(p, 0)
|
|
|
|
CONFIG_ENTRIES = ['type', 'vncdisplay', 'vnclisten', 'vncpasswd', 'vncunused',
|
|
- 'display', 'xauthority']
|
|
+ 'display', 'xauthority', 'keymap',
|
|
+ 'uuid', 'location', 'protocol']
|
|
+
|
|
|
|
class VfbifController(DevController):
|
|
"""Virtual frame buffer controller. Handles all vfb devices for a domain.
|
|
@@ -27,10 +29,11 @@ class VfbifController(DevController):
|
|
def getDeviceDetails(self, config):
|
|
"""@see DevController.getDeviceDetails"""
|
|
|
|
- back = dict([(k, config[k]) for k in CONFIG_ENTRIES
|
|
+ back = dict([(k, str(config[k])) for k in CONFIG_ENTRIES
|
|
if config.has_key(k)])
|
|
|
|
- return (0, back, {})
|
|
+ devid = 0
|
|
+ return (devid, back, {})
|
|
|
|
|
|
def getDeviceConfiguration(self, devid):
|
|
@@ -44,6 +47,10 @@ class VfbifController(DevController):
|
|
|
|
def createDevice(self, config):
|
|
DevController.createDevice(self, config)
|
|
+ if self.vm.info.get('HVM_boot'):
|
|
+ # is HVM, so qemu-dm will handle the vfb.
|
|
+ return
|
|
+
|
|
std_args = [ "--domid", "%d" % self.vm.getDomid(),
|
|
"--title", self.vm.getName() ]
|
|
t = config.get("type", None)
|
|
@@ -80,6 +87,42 @@ class VfbifController(DevController):
|
|
else:
|
|
raise VmError('Unknown vfb type %s (%s)' % (t, repr(config)))
|
|
|
|
+
|
|
+ def waitForDevice(self, devid):
|
|
+ if self.vm.info.get('HVM_boot'):
|
|
+ log.debug('skip waiting for HVM vfb')
|
|
+ # is a qemu-dm managed device, don't wait for hotplug for these.
|
|
+ return
|
|
+
|
|
+ DevController.waitForDevice(self, devid)
|
|
+
|
|
+
|
|
+ def reconfigureDevice(self, _, config):
|
|
+ """ Only allow appending location information of vnc port into
|
|
+ xenstore."""
|
|
+
|
|
+ if 'location' in config:
|
|
+ (devid, back, front) = self.getDeviceDetails(config)
|
|
+ self.writeBackend(devid, 'location', config['location'])
|
|
+ return back.get('uuid')
|
|
+
|
|
+ raise VmError('Refusing to reconfigure device vfb:%d' % devid)
|
|
+
|
|
+ def destroyDevice(self, devid, force):
|
|
+ if self.vm.info.get('HVM_boot'):
|
|
+ # remove the backend xenstore entries for HVM guests no matter
|
|
+ # what
|
|
+ DevController.destroyDevice(self, devid, True)
|
|
+ else:
|
|
+ DevController.destroyDevice(self, devid, force)
|
|
+
|
|
+
|
|
+ def migrate(self, deviceConfig, network, dst, step, domName):
|
|
+ if self.vm.info.get('HVM_boot'):
|
|
+ return 0
|
|
+ return DevController.migrate(self, deviceConfig, network, dst, step,
|
|
+ domName)
|
|
+
|
|
class VkbdifController(DevController):
|
|
"""Virtual keyboard controller. Handles all vkbd devices for a domain.
|
|
"""
|
|
@@ -90,3 +133,24 @@ class VkbdifController(DevController):
|
|
back = {}
|
|
front = {}
|
|
return (devid, back, front)
|
|
+
|
|
+ def waitForDevice(self, config):
|
|
+ if self.vm.info.get('HVM_boot'):
|
|
+ # is a qemu-dm managed device, don't wait for hotplug for these.
|
|
+ return
|
|
+
|
|
+ DevController.waitForDevice(self, config)
|
|
+
|
|
+ def destroyDevice(self, devid, force):
|
|
+ if self.vm.info.get('HVM_boot'):
|
|
+ # remove the backend xenstore entries for HVM guests no matter
|
|
+ # what
|
|
+ DevController.destroyDevice(self, devid, True)
|
|
+ else:
|
|
+ DevController.destroyDevice(self, devid, force)
|
|
+
|
|
+ def migrate(self, deviceConfig, network, dst, step, domName):
|
|
+ if self.vm.info.get('HVM_boot'):
|
|
+ return 0
|
|
+ return DevController.migrate(self, deviceConfig, network, dst, step,
|
|
+ domName)
|