aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorawilliam@xenbuild2.aw <awilliam@xenbuild2.aw>2006-12-18 10:56:34 -0700
committerawilliam@xenbuild2.aw <awilliam@xenbuild2.aw>2006-12-18 10:56:34 -0700
commitf4556d236293d4b8965d47f2c9651d6f0f68e8a7 (patch)
treec0ae4cfe1d211725e43140faf2d69efb335b89e1
parent5fb6147b15fabf3ec20644ebcee07422633179b9 (diff)
parent75bbf9d488782d227fb6648adb351192dba5a7b5 (diff)
downloadxen-f4556d236293d4b8965d47f2c9651d6f0f68e8a7.tar.gz
xen-f4556d236293d4b8965d47f2c9651d6f0f68e8a7.tar.bz2
xen-f4556d236293d4b8965d47f2c9651d6f0f68e8a7.zip
merge with xen-unstable.hg
-rw-r--r--.hgignore1
-rw-r--r--config/x86_32.mk1
-rw-r--r--config/x86_64.mk1
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/fbfront/xenfb.c100
-rw-r--r--tools/ioemu/target-i386-dm/exec-dm.c35
-rw-r--r--tools/python/xen/xend/XendAPI.py5
-rw-r--r--tools/python/xen/xend/XendCheckpoint.py7
-rw-r--r--tools/python/xen/xend/XendConfig.py84
-rw-r--r--tools/python/xen/xend/XendDomain.py20
-rw-r--r--tools/python/xen/xend/XendDomainInfo.py5
-rw-r--r--tools/python/xen/xend/server/netif.py2
-rw-r--r--tools/python/xen/xend/server/vfbif.py40
-rw-r--r--tools/python/xen/xm/XenAPI.py14
-rw-r--r--tools/python/xen/xm/create.py4
-rw-r--r--tools/python/xen/xm/main.py10
-rw-r--r--tools/xenfb/vncfb.c104
-rw-r--r--tools/xm-test/lib/XmTestLib/acm.py2
17 files changed, 341 insertions, 94 deletions
diff --git a/.hgignore b/.hgignore
index b445a0d342..d4127b6d1f 100644
--- a/.hgignore
+++ b/.hgignore
@@ -229,3 +229,4 @@
^unmodified_drivers/linux-2.6/.*\.cmd$
^unmodified_drivers/linux-2.6/.*\.ko$
^unmodified_drivers/linux-2.6/.*\.mod\.c$
+^LibVNCServer.*
diff --git a/config/x86_32.mk b/config/x86_32.mk
index 4a0490afa8..ce0bb67ba1 100644
--- a/config/x86_32.mk
+++ b/config/x86_32.mk
@@ -1,4 +1,5 @@
CONFIG_X86 := y
+CONFIG_X86_32 := y
CONFIG_X86_$(XEN_OS) := y
CONFIG_HVM := y
diff --git a/config/x86_64.mk b/config/x86_64.mk
index e85b37ff91..99b25d8059 100644
--- a/config/x86_64.mk
+++ b/config/x86_64.mk
@@ -1,4 +1,5 @@
CONFIG_X86 := y
+CONFIG_X86_64 := y
CONFIG_X86_$(XEN_OS) := y
CONFIG_HVM := y
diff --git a/linux-2.6-xen-sparse/drivers/xen/fbfront/xenfb.c b/linux-2.6-xen-sparse/drivers/xen/fbfront/xenfb.c
index e16227c660..54f7b5c509 100644
--- a/linux-2.6-xen-sparse/drivers/xen/fbfront/xenfb.c
+++ b/linux-2.6-xen-sparse/drivers/xen/fbfront/xenfb.c
@@ -49,8 +49,9 @@ struct xenfb_info
struct timer_list refresh;
int dirty;
int x1, y1, x2, y2; /* dirty rectangle,
- protected by mm_lock */
- spinlock_t mm_lock;
+ protected by dirty_lock */
+ spinlock_t dirty_lock;
+ struct mutex mm_lock;
int nr_pages;
struct page **pages;
struct list_head mappings; /* protected by mm_lock */
@@ -64,6 +65,70 @@ struct xenfb_info
struct xenbus_device *xbdev;
};
+/*
+ * How the locks work together
+ *
+ * There are two locks: spinlock dirty_lock protecting the dirty
+ * rectangle, and mutex mm_lock protecting mappings.
+ *
+ * The problem is that dirty rectangle and mappings aren't
+ * independent: the dirty rectangle must cover all faulted pages in
+ * mappings. We need to prove that our locking maintains this
+ * invariant.
+ *
+ * There are several kinds of critical regions:
+ *
+ * 1. Holding only dirty_lock: xenfb_refresh(). May run in
+ * interrupts. Extends the dirty rectangle. Trivially preserves
+ * invariant.
+ *
+ * 2. Holding only mm_lock: xenfb_mmap() and xenfb_vm_close(). Touch
+ * only mappings. The former creates unfaulted pages. Preserves
+ * invariant. The latter removes pages. Preserves invariant.
+ *
+ * 3. Holding both locks: xenfb_vm_nopage(). Extends the dirty
+ * rectangle and updates mappings consistently. Preserves
+ * invariant.
+ *
+ * 4. The ugliest one: xenfb_update_screen(). Clear the dirty
+ * rectangle and update mappings consistently.
+ *
+ * We can't simply hold both locks, because zap_page_range() cannot
+ * be called with a spinlock held.
+ *
+ * Therefore, we first clear the dirty rectangle with both locks
+ * held. Then we unlock dirty_lock and update the mappings.
+ * Critical regions that hold only dirty_lock may interfere with
+ * that. This can only be region 1: xenfb_refresh(). But that
+ * just extends the dirty rectangle, which can't harm the
+ * invariant.
+ *
+ * But FIXME: the invariant is too weak. It misses that the fault
+ * record in mappings must be consistent with the mapping of pages in
+ * the associated address space! do_no_page() updates the PTE after
+ * xenfb_vm_nopage() returns, i.e. outside the critical region. This
+ * allows the following race:
+ *
+ * X writes to some address in the Xen frame buffer
+ * Fault - call do_no_page()
+ * call xenfb_vm_nopage()
+ * grab mm_lock
+ * map->faults++;
+ * release mm_lock
+ * return back to do_no_page()
+ * (preempted, or SMP)
+ * Xen worker thread runs.
+ * grab mm_lock
+ * look at mappings
+ * find this mapping, zaps its pages (but page not in pte yet)
+ * clear map->faults
+ * releases mm_lock
+ * (back to X process)
+ * put page in X's pte
+ *
+ * Oh well, we wont be updating the writes to this page anytime soon.
+ */
+
static int xenfb_fps = 20;
static unsigned long xenfb_mem_len = XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8;
@@ -105,6 +170,7 @@ static int xenfb_queue_full(struct xenfb_info *info)
static void xenfb_update_screen(struct xenfb_info *info)
{
+ unsigned long flags;
int y1, y2, x1, x2;
struct xenfb_mapping *map;
@@ -113,14 +179,16 @@ static void xenfb_update_screen(struct xenfb_info *info)
if (xenfb_queue_full(info))
return;
- spin_lock(&info->mm_lock);
+ mutex_lock(&info->mm_lock);
+ spin_lock_irqsave(&info->dirty_lock, flags);
y1 = info->y1;
y2 = info->y2;
x1 = info->x1;
x2 = info->x2;
info->x1 = info->y1 = INT_MAX;
info->x2 = info->y2 = 0;
+ spin_unlock_irqrestore(&info->dirty_lock, flags);
list_for_each_entry(map, &info->mappings, link) {
if (!map->faults)
@@ -130,7 +198,7 @@ static void xenfb_update_screen(struct xenfb_info *info)
map->faults = 0;
}
- spin_unlock(&info->mm_lock);
+ mutex_unlock(&info->mm_lock);
xenfb_do_update(info, x1, y1, x2 - x1, y2 - y1);
}
@@ -213,9 +281,11 @@ static void __xenfb_refresh(struct xenfb_info *info,
static void xenfb_refresh(struct xenfb_info *info,
int x1, int y1, int w, int h)
{
- spin_lock(&info->mm_lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->dirty_lock, flags);
__xenfb_refresh(info, x1, y1, w, h);
- spin_unlock(&info->mm_lock);
+ spin_unlock_irqrestore(&info->dirty_lock, flags);
}
static void xenfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
@@ -253,12 +323,12 @@ static void xenfb_vm_close(struct vm_area_struct *vma)
struct xenfb_mapping *map = vma->vm_private_data;
struct xenfb_info *info = map->info;
- spin_lock(&info->mm_lock);
+ mutex_lock(&info->mm_lock);
if (atomic_dec_and_test(&map->map_refs)) {
list_del(&map->link);
kfree(map);
}
- spin_unlock(&info->mm_lock);
+ mutex_unlock(&info->mm_lock);
}
static struct page *xenfb_vm_nopage(struct vm_area_struct *vma,
@@ -267,13 +337,15 @@ static struct page *xenfb_vm_nopage(struct vm_area_struct *vma,
struct xenfb_mapping *map = vma->vm_private_data;
struct xenfb_info *info = map->info;
int pgnr = (vaddr - vma->vm_start) >> PAGE_SHIFT;
+ unsigned long flags;
struct page *page;
int y1, y2;
if (pgnr >= info->nr_pages)
return NOPAGE_SIGBUS;
- spin_lock(&info->mm_lock);
+ mutex_lock(&info->mm_lock);
+ spin_lock_irqsave(&info->dirty_lock, flags);
page = info->pages[pgnr];
get_page(page);
map->faults++;
@@ -283,7 +355,8 @@ static struct page *xenfb_vm_nopage(struct vm_area_struct *vma,
if (y2 > info->fb_info->var.yres)
y2 = info->fb_info->var.yres;
__xenfb_refresh(info, 0, y1, info->fb_info->var.xres, y2 - y1);
- spin_unlock(&info->mm_lock);
+ spin_unlock_irqrestore(&info->dirty_lock, flags);
+ mutex_unlock(&info->mm_lock);
if (type)
*type = VM_FAULT_MINOR;
@@ -323,9 +396,9 @@ static int xenfb_mmap(struct fb_info *fb_info, struct vm_area_struct *vma)
map->info = info;
atomic_set(&map->map_refs, 1);
- spin_lock(&info->mm_lock);
+ mutex_lock(&info->mm_lock);
list_add(&map->link, &info->mappings);
- spin_unlock(&info->mm_lock);
+ mutex_unlock(&info->mm_lock);
vma->vm_ops = &xenfb_vm_ops;
vma->vm_flags |= (VM_DONTEXPAND | VM_RESERVED);
@@ -382,7 +455,8 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
info->xbdev = dev;
info->irq = -1;
info->x1 = info->y1 = INT_MAX;
- spin_lock_init(&info->mm_lock);
+ spin_lock_init(&info->dirty_lock);
+ mutex_init(&info->mm_lock);
init_waitqueue_head(&info->wq);
init_timer(&info->refresh);
info->refresh.function = xenfb_timer;
diff --git a/tools/ioemu/target-i386-dm/exec-dm.c b/tools/ioemu/target-i386-dm/exec-dm.c
index e27ecbc3a4..b3f9d3ae7d 100644
--- a/tools/ioemu/target-i386-dm/exec-dm.c
+++ b/tools/ioemu/target-i386-dm/exec-dm.c
@@ -128,10 +128,28 @@ char *logfilename = "/tmp/qemu.log";
FILE *logfile;
int loglevel;
+
+#if defined(__i386__) || defined(__x86_64__)
+#define MAPCACHE
+#endif
+
+#ifdef MAPCACHE
+static pthread_mutex_t mapcache_mutex;
+#define mapcache_lock() pthread_mutex_lock(&mapcache_mutex)
+#define mapcache_unlock() pthread_mutex_unlock(&mapcache_mutex)
+#else
+#define mapcache_lock() ( (void)0 )
+#define mapcache_unlock() ( (void)0 )
+#endif
+
+
void cpu_exec_init(CPUState *env)
{
CPUState **penv;
int cpu_index;
+#ifdef MAPCACHE
+ pthread_mutexattr_t mxattr;
+#endif
env->next_cpu = NULL;
penv = &first_cpu;
@@ -145,6 +163,14 @@ void cpu_exec_init(CPUState *env)
/* alloc dirty bits array */
phys_ram_dirty = qemu_malloc(phys_ram_size >> TARGET_PAGE_BITS);
+
+#ifdef MAPCACHE
+ /* setup memory access mutex to protect mapcache */
+ pthread_mutexattr_init(&mxattr);
+ pthread_mutexattr_settype(&mxattr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&mapcache_mutex, &mxattr);
+ pthread_mutexattr_destroy(&mxattr);
+#endif
}
/* enable or disable low levels log */
@@ -440,10 +466,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
uint8_t *ptr;
uint32_t val;
-#if defined(__i386__) || defined(__x86_64__)
- static pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
- pthread_mutex_lock(&mutex);
-#endif
+ mapcache_lock();
while (len > 0) {
/* How much can we copy before the next page boundary? */
@@ -510,9 +533,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
addr += l;
}
-#if defined(__i386__) || defined(__x86_64__)
- pthread_mutex_unlock(&mutex);
-#endif
+ mapcache_unlock();
}
#endif
diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py
index c43ae75976..540ab2e45d 100644
--- a/tools/python/xen/xend/XendAPI.py
+++ b/tools/python/xen/xend/XendAPI.py
@@ -663,7 +663,10 @@ class XendAPI:
XendDomain.instance().get_vm_by_uuid(vm_ref).info[name])
def VM_set(self, name, session, vm_ref, value):
- XendDomain.instance().get_vm_by_uuid(vm_ref).info[name] = value
+ xd = XendDomain.instance()
+ dominfo = xd.get_vm_by_uuid(vm_ref)
+ dominfo.info[name] = value
+ xd.managed_config_save(dominfo)
return xen_api_success_void()
# attributes (ro)
diff --git a/tools/python/xen/xend/XendCheckpoint.py b/tools/python/xen/xend/XendCheckpoint.py
index 21a323cdcc..85a59e5d22 100644
--- a/tools/python/xen/xend/XendCheckpoint.py
+++ b/tools/python/xen/xend/XendCheckpoint.py
@@ -218,18 +218,17 @@ def forkHelper(cmd, fd, inputHandler, closeToChild):
log.debug('%s', line)
inputHandler(line, child.tochild)
- thread.join()
-
except IOError, exn:
raise XendError('Error reading from child process for %s: %s' %
(cmd, exn))
finally:
child.fromchild.close()
- child.childerr.close()
if not closeToChild:
child.tochild.close()
+ thread.join()
+ child.childerr.close()
+ status = child.wait()
- status = child.wait()
if status >> 8 == 127:
raise XendError("%s failed: popen failed" % string.join(cmd))
elif status != 0:
diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py
index e80422eaaa..1d4587fa7e 100644
--- a/tools/python/xen/xend/XendConfig.py
+++ b/tools/python/xen/xend/XendConfig.py
@@ -15,6 +15,7 @@
# Copyright (C) 2006 XenSource Ltd
#============================================================================
+import logging
import re
import time
import types
@@ -23,10 +24,13 @@ from xen.xend import sxp
from xen.xend import uuid
from xen.xend.XendError import VmError
from xen.xend.XendDevices import XendDevices
-from xen.xend.XendLogging import log
from xen.xend.PrettyPrint import prettyprintstring
from xen.xend.XendConstants import DOM_STATE_HALTED
+log = logging.getLogger("xend.XendConfig")
+log.setLevel(logging.WARN)
+
+
"""
XendConfig API
@@ -182,18 +186,18 @@ LEGACY_CFG_TYPES = {
'shadow_memory': int,
'maxmem': int,
'start_time': float,
- 'cpu_cap': int,
- 'cpu_weight': int,
+ 'cpu_cap': int,
+ 'cpu_weight': int,
'cpu_time': float,
- 'features': str,
- 'localtime': int,
- 'name': str,
- 'on_poweroff': str,
- 'on_reboot': str,
- 'on_crash': str,
- 'on_xend_stop': str,
+ 'features': str,
+ 'localtime': int,
+ 'name': str,
+ 'on_poweroff': str,
+ 'on_reboot': str,
+ 'on_crash': str,
+ 'on_xend_stop': str,
'on_xend_start': str,
- 'online_vcpus': int,
+ 'online_vcpus': int,
}
# Values that should be stored in xenstore's /vm/<uuid> that is used
@@ -430,8 +434,12 @@ class XendConfig(dict):
"""
cfg = {}
- # First step is to convert deprecated options to
- # current equivalents.
+ for key, typ in XENAPI_CFG_TYPES.items():
+ val = sxp.child_value(sxp_cfg, key)
+ if val is not None:
+ cfg[key] = typ(val)
+
+ # Convert deprecated options to current equivalents.
restart = sxp.child_value(sxp_cfg, 'restart')
if restart:
@@ -574,8 +582,15 @@ class XendConfig(dict):
"""Read in an SXP Configuration object and
populate at much of the Xen API with valid values.
"""
+ log.debug('_sxp_to_xapi(%s)' % scrub_password(sxp_cfg))
+
cfg = self._parse_sxp(sxp_cfg)
+ for key, typ in XENAPI_CFG_TYPES.items():
+ val = cfg.get(key)
+ if val is not None:
+ self[key] = typ(val)
+
# Convert parameters that can be directly mapped from
# the Legacy Config to Xen API Config
@@ -590,9 +605,13 @@ class XendConfig(dict):
except KeyError:
pass
- self['PV_bootloader'] = cfg.get('bootloader', '')
- self['PV_bootloader_args'] = cfg.get('bootloader_args', '')
-
+ def update_with(n, o):
+ if not self.get(n):
+ self[n] = cfg.get(o, '')
+
+ update_with('PV_bootloader', 'bootloader')
+ update_with('PV_bootloader_args', 'bootloader_args')
+
image_sxp = sxp.child_value(sxp_cfg, 'image', [])
if image_sxp:
self.update_with_image_sxp(image_sxp)
@@ -635,6 +654,8 @@ class XendConfig(dict):
the Xen API.
"""
+ log.debug('_sxp_to_xapi_unsupported(%s)' % scrub_password(sxp_cfg))
+
# Parse and convert parameters used to configure
# the image (as well as HVM images)
image_sxp = sxp.child_value(sxp_cfg, 'image', [])
@@ -748,6 +769,9 @@ class XendConfig(dict):
@param xapi: Xen API VM Struct
@type xapi: dict
"""
+
+ log.debug('update_with_xenapi_config: %s' % scrub_password(xapi))
+
for key, val in xapi.items():
type_conv = XENAPI_CFG_TYPES.get(key)
if type_conv is None:
@@ -760,11 +784,8 @@ class XendConfig(dict):
self.validate()
- def to_xml(self):
- """Return an XML string representing the configuration."""
- pass
-
- def to_sxp(self, domain = None, ignore_devices = False, ignore = []):
+ def to_sxp(self, domain = None, ignore_devices = False, ignore = [],
+ legacy_only = True):
""" Get SXP representation of this config object.
Incompat: removed store_mfn, console_mfn
@@ -785,6 +806,11 @@ class XendConfig(dict):
if domain.getDomid() is not None:
sxpr.append(['domid', domain.getDomid()])
+ if not legacy_only:
+ for name in XENAPI_CFG_TYPES.keys():
+ if name in self and self[name] not in (None, []):
+ sxpr.append([name, str(self[name])])
+
for xenapi, legacy in XENAPI_CFG_TO_LEGACY_CFG.items():
if self.has_key(xenapi) and self[xenapi] not in (None, []):
if type(self[xenapi]) == bool:
@@ -1044,12 +1070,12 @@ class XendConfig(dict):
"""Returns a backwards compatible image SXP expression that is
used in xenstore's /vm/<uuid>/image value and xm list."""
image = [self['image'].get('type', 'linux')]
- if self.has_key('kernel_kernel'):
- image.append(['kernel', self['kernel_kernel']])
- if self.has_key('kernel_initrd') and self['kernel_initrd']:
- image.append(['ramdisk', self['kernel_initrd']])
- if self.has_key('kernel_args') and self['kernel_args']:
- image.append(['args', self['kernel_args']])
+ if self.has_key('PV_kernel'):
+ image.append(['kernel', self['PV_kernel']])
+ if self.has_key('PV_ramdisk') and self['PV_ramdisk']:
+ image.append(['ramdisk', self['PV_ramdisk']])
+ if self.has_key('PV_args') and self['PV_args']:
+ image.append(['args', self['PV_args']])
for arg, conv in LEGACY_IMAGE_CFG:
if self['image'].has_key(arg):
@@ -1069,8 +1095,10 @@ class XendConfig(dict):
return image
def update_with_image_sxp(self, image_sxp):
- # Convert Legacy "image" config to Xen API kernel_*
+ # Convert Legacy "image" config to Xen API PV_*
# configuration
+ log.debug("update_with_image_sxp(%s)" % scrub_password(image_sxp))
+
self['PV_kernel'] = sxp.child_value(image_sxp, 'kernel','')
self['PV_ramdisk'] = sxp.child_value(image_sxp, 'ramdisk','')
kernel_args = sxp.child_value(image_sxp, 'args', '')
diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py
index 4649525198..81c39384d4 100644
--- a/tools/python/xen/xend/XendDomain.py
+++ b/tools/python/xen/xend/XendDomain.py
@@ -26,6 +26,7 @@ import os
import stat
import shutil
import socket
+import tempfile
import threading
import xen.lowlevel.xc
@@ -280,16 +281,21 @@ class XendDomain:
make_or_raise(domain_config_dir)
try:
- sxp_cache_file = open(self._managed_config_path(dom_uuid),'w')
- prettyprint(dominfo.sxpr(), sxp_cache_file, width = 78)
- sxp_cache_file.close()
+ fd, fn = tempfile.mkstemp()
+ f = os.fdopen(fd, 'w+b')
+ try:
+ prettyprint(dominfo.sxpr(legacy_only = False), f,
+ width = 78)
+ finally:
+ f.close()
+ try:
+ os.rename(fn, self._managed_config_path(dom_uuid))
+ except:
+ log.exception("Renaming %s" % fn)
+ os.remove(fn)
except:
log.exception("Error occurred saving configuration file " +
"to %s" % domain_config_dir)
- try:
- self._managed_domain_remove(dom_uuid)
- except:
- pass
raise XendError("Failed to save configuration file to: %s" %
domain_config_dir)
else:
diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py
index 8b90814db2..27dcce7e71 100644
--- a/tools/python/xen/xend/XendDomainInfo.py
+++ b/tools/python/xen/xend/XendDomainInfo.py
@@ -1800,9 +1800,10 @@ class XendDomainInfo:
log.trace("XendDomainInfo.update done on domain %s: %s",
str(self.domid), self.info)
- def sxpr(self, ignore_store = False):
+ def sxpr(self, ignore_store = False, legacy_only = True):
result = self.info.to_sxp(domain = self,
- ignore_devices = ignore_store)
+ ignore_devices = ignore_store,
+ legacy_only = legacy_only)
if not ignore_store and self.dompath:
vnc_port = self.readDom('console/vnc-port')
diff --git a/tools/python/xen/xend/server/netif.py b/tools/python/xen/xend/server/netif.py
index 8b0a2ce66c..92e5626ade 100644
--- a/tools/python/xen/xend/server/netif.py
+++ b/tools/python/xen/xend/server/netif.py
@@ -140,7 +140,7 @@ class NetifController(DevController):
script = os.path.join(xroot.network_script_dir,
config.get('script', xroot.get_vif_script()))
- typ = config.get('type')
+ typ = config.get('type')
bridge = config.get('bridge')
mac = config.get('mac')
vifname = config.get('vifname')
diff --git a/tools/python/xen/xend/server/vfbif.py b/tools/python/xen/xend/server/vfbif.py
index e24c2284f6..d07cd2f9e8 100644
--- a/tools/python/xen/xend/server/vfbif.py
+++ b/tools/python/xen/xend/server/vfbif.py
@@ -1,4 +1,5 @@
from xen.xend.server.DevController import DevController
+from xen.xend.XendLogging import log
from xen.xend.XendError import VmError
import xen.xend
@@ -12,6 +13,9 @@ def spawn_detached(path, args, env):
else:
os.waitpid(p, 0)
+CONFIG_ENTRIES = ['type', 'vncdisplay', 'vnclisten', 'vncpasswd', 'vncunused',
+ 'display', 'xauthority']
+
class VfbifController(DevController):
"""Virtual frame buffer controller. Handles all vfb devices for a domain.
Note that we only support a single vfb per domain at the moment.
@@ -19,28 +23,42 @@ class VfbifController(DevController):
def __init__(self, vm):
DevController.__init__(self, vm)
- self.config = {}
def getDeviceDetails(self, config):
"""@see DevController.getDeviceDetails"""
- devid = 0
- back = {}
- front = {}
- return (devid, back, front)
+
+ back = dict([(k, config[k]) for k in CONFIG_ENTRIES
+ if config.has_key(k)])
+
+ return (0, back, {})
+
def getDeviceConfiguration(self, devid):
- r = DevController.getDeviceConfiguration(self, devid)
- for (k,v) in self.config.iteritems():
- r[k] = v
- return r
-
+ result = DevController.getDeviceConfiguration(self, devid)
+
+ devinfo = self.readBackend(devid, *CONFIG_ENTRIES)
+ return dict([(CONFIG_ENTRIES[i], devinfo[i])
+ for i in range(len(CONFIG_ENTRIES))
+ if devinfo[i] is not None])
+
+
def createDevice(self, config):
DevController.createDevice(self, config)
- self.config = config
std_args = [ "--domid", "%d" % self.vm.getDomid(),
"--title", self.vm.getName() ]
t = config.get("type", None)
if t == "vnc":
+ passwd = None
+ if config.has_key("vncpasswd"):
+ passwd = config["vncpasswd"]
+ else:
+ passwd = xen.xend.XendRoot.instance().get_vncpasswd_default()
+ if passwd:
+ self.vm.storeVm("vncpasswd", passwd)
+ log.debug("Stored a VNC password for vfb access")
+ else:
+ log.debug("No VNC passwd configured for vfb access")
+
# Try to start the vnc backend
args = [xen.util.auxbin.pathTo("xen-vncfb")]
if config.has_key("vncunused"):
diff --git a/tools/python/xen/xm/XenAPI.py b/tools/python/xen/xm/XenAPI.py
index a7835c0ebc..5cf929f48c 100644
--- a/tools/python/xen/xm/XenAPI.py
+++ b/tools/python/xen/xm/XenAPI.py
@@ -83,20 +83,24 @@ class Session(xen.util.xmlrpclib2.ServerProxy):
def xenapi_request(self, methodname, params):
- full_params = (self._session,) + params
- return _parse_result(getattr(self, methodname)(*full_params))
+ if methodname.startswith('login'):
+ self._login(methodname, params)
+ return None
+ else:
+ full_params = (self._session,) + params
+ return _parse_result(getattr(self, methodname)(*full_params))
- def _login(self, method, username, password):
+ def _login(self, method, params):
self._session = _parse_result(
- getattr(self, 'session.%s' % method)(username, password))
+ getattr(self, 'session.%s' % method)(*params))
def __getattr__(self, name):
if name == 'xenapi':
return _Dispatcher(self.xenapi_request, None)
elif name.startswith('login'):
- return lambda u, p: self._login(name, u, p)
+ return lambda *params: self._login(name, params)
else:
return xen.util.xmlrpclib2.ServerProxy.__getattr__(self, name)
diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py
index aa0c03cac3..b603b922d6 100644
--- a/tools/python/xen/xm/create.py
+++ b/tools/python/xen/xm/create.py
@@ -284,7 +284,7 @@ gopts.var('usbport', val='PATH',
use="""Add a physical USB port to a domain, as specified by the path
to that port. This option may be repeated to add more than one port.""")
-gopts.var('vfb', val="type={vnc,sdl},vncunused=1,vncdisplay=N,vnclisten=ADDR,display=DISPLAY,xauthority=XAUTHORITY",
+gopts.var('vfb', val="type={vnc,sdl},vncunused=1,vncdisplay=N,vnclisten=ADDR,display=DISPLAY,xauthority=XAUTHORITY,vncpasswd=PASSWORD",
fn=append_value, default=[],
use="""Make the domain a framebuffer backend.
The backend type should be either sdl or vnc.
@@ -584,7 +584,7 @@ def configure_vfbs(config_devs, vals):
d['type'] = 'sdl'
for (k,v) in d.iteritems():
if not k in [ 'vnclisten', 'vncunused', 'vncdisplay', 'display',
- 'xauthority', 'type' ]:
+ 'xauthority', 'type', 'vncpasswd' ]:
err("configuration option %s unknown to vfbs" % k)
config.append([k,v])
if not d.has_key("display") and os.environ.has_key("DISPLAY"):
diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py
index 059bbd46b2..3c118172ae 100644
--- a/tools/python/xen/xm/main.py
+++ b/tools/python/xen/xm/main.py
@@ -558,7 +558,7 @@ class Shell(cmd.Cmd):
ok, res = _run_cmd(lambda x: server.xenapi_request(words[0],
tuple(x)),
words[0], words[1:])
- if ok and res != '':
+ if ok and res is not None and res != '':
pprint.pprint(res)
else:
print '*** Unknown command: %s' % words[0]
@@ -1556,7 +1556,11 @@ def detach(args, command, deviceClass):
def xm_block_detach(args):
- detach(args, 'block-detach', 'vbd')
+ try:
+ detach(args, 'block-detach', 'vbd')
+ return
+ except:
+ pass
detach(args, 'block-detach', 'tap')
@@ -1798,7 +1802,7 @@ def _run_cmd(cmd, cmd_name, args):
except OptionError, e:
err(str(e))
_usage(cmd_name)
- print e.usage()
+ print e.usage
except security.ACMError, e:
err(str(e))
except:
diff --git a/tools/xenfb/vncfb.c b/tools/xenfb/vncfb.c
index 49fc730625..33f55eeb0d 100644
--- a/tools/xenfb/vncfb.c
+++ b/tools/xenfb/vncfb.c
@@ -148,6 +148,10 @@ static int xk2linux[0x10000] = {
[XK_plus] = KEY_EQUAL,
};
+static int btnmap[] = {
+ BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, BTN_FORWARD, BTN_BACK
+};
+
static void on_kbd_event(rfbBool down, rfbKeySym keycode, rfbClientPtr cl)
{
/*
@@ -184,8 +188,11 @@ static void on_ptr_event(int buttonMask, int x, int y, rfbClientPtr cl)
down = buttonMask & (1 << i);
if (down == last_down)
continue;
- /* FIXME this assumes buttons are numbered the same; verify they are */
- if (xenfb_send_key(xenfb, down != 0, BTN_MOUSE + i) < 0)
+ if (i >= sizeof(btnmap) / sizeof(*btnmap))
+ break;
+ if (btnmap[i] == 0)
+ break;
+ if (xenfb_send_key(xenfb, down != 0, btnmap[i]) < 0)
fprintf(stderr, "Button %d %s lost (%s)\n",
i, down ? "down" : "up", strerror(errno));
}
@@ -205,15 +212,10 @@ static void on_ptr_event(int buttonMask, int x, int y, rfbClientPtr cl)
last_y = y;
}
-static void xenstore_write_vncport(int port, int domid)
+static void xenstore_write_vncport(struct xs_handle *xsh, int port, int domid)
{
- char *buf = NULL, *path;
+ char *buf, *path;
char portstr[10];
- struct xs_handle *xsh = NULL;
-
- xsh = xs_daemon_open();
- if (xsh == NULL)
- return;
path = xs_get_domain_path(xsh, domid);
if (path == NULL) {
@@ -241,6 +243,56 @@ static void xenstore_write_vncport(int port, int domid)
}
+static int xenstore_read_vncpasswd(struct xs_handle *xsh, int domid, char *pwbuf, int pwbuflen)
+{
+ char buf[256], *path, *uuid = NULL, *passwd = NULL;
+ unsigned int len, rc = 0;
+
+ if (xsh == NULL) {
+ return -1;
+ }
+
+ path = xs_get_domain_path(xsh, domid);
+ if (path == NULL) {
+ fprintf(stderr, "xs_get_domain_path() error\n");
+ return -1;
+ }
+
+ snprintf(buf, 256, "%s/vm", path);
+ uuid = xs_read(xsh, XBT_NULL, buf, &len);
+ if (uuid == NULL) {
+ fprintf(stderr, "xs_read(): uuid get error\n");
+ free(path);
+ return -1;
+ }
+
+ snprintf(buf, 256, "%s/vncpasswd", uuid);
+ passwd = xs_read(xsh, XBT_NULL, buf, &len);
+ if (passwd == NULL) {
+ free(uuid);
+ free(path);
+ return rc;
+ }
+
+ strncpy(pwbuf, passwd, pwbuflen-1);
+ pwbuf[pwbuflen-1] = '\0';
+
+ fprintf(stderr, "Got a VNC password read from XenStore\n");
+
+ passwd[0] = '\0';
+ snprintf(buf, 256, "%s/vncpasswd", uuid);
+ if (xs_write(xsh, XBT_NULL, buf, passwd, len) == 0) {
+ fprintf(stderr, "xs_write() vncpasswd failed\n");
+ rc = -1;
+ }
+
+ free(passwd);
+ free(uuid);
+ free(path);
+
+ return rc;
+}
+
static void vnc_update(struct xenfb *xenfb, int x, int y, int w, int h)
{
rfbScreenInfoPtr server = xenfb->user_data;
@@ -274,6 +326,10 @@ int main(int argc, char **argv)
char portstr[10];
char *endp;
int r;
+ struct xs_handle *xsh;
+ char vncpasswd[1024];
+
+ vncpasswd[0] = '\0';
while ((opt = getopt_long(argc, argv, "d:p:t:u", options,
NULL)) != -1) {
@@ -346,6 +402,19 @@ int main(int argc, char **argv)
exit(1);
}
+ xsh = xs_daemon_open();
+ if (xsh == NULL) {
+ fprintf(stderr, "cannot open connection to xenstore\n");
+ exit(1);
+ }
+
+
+ if (xenstore_read_vncpasswd(xsh, domid, vncpasswd, sizeof(vncpasswd)/sizeof(char)) < 0) {
+ fprintf(stderr, "cannot read VNC password from xenstore\n");
+ exit(1);
+ }
+
+
server = rfbGetScreen(&fake_argc, fake_argv,
xenfb->width, xenfb->height,
8, 3, xenfb->depth / 8);
@@ -360,6 +429,21 @@ int main(int argc, char **argv)
if (unused)
server->autoPort = true;
+ if (vncpasswd[0]) {
+ char **passwds = malloc(sizeof(char**)*2);
+ if (!passwds) {
+ fprintf(stderr, "cannot allocate memory (%s)\n", strerror(errno));
+ exit(1);
+ }
+ fprintf(stderr, "Registered password\n");
+ passwds[0] = vncpasswd;
+ passwds[1] = NULL;
+
+ server->authPasswdData = passwds;
+ server->passwordCheck = rfbCheckPasswordByList;
+ } else {
+ fprintf(stderr, "Running with no password\n");
+ }
server->serverFormat.redShift = 16;
server->serverFormat.greenShift = 8;
server->serverFormat.blueShift = 0;
@@ -372,7 +456,7 @@ int main(int argc, char **argv)
rfbRunEventLoop(server, -1, true);
- xenstore_write_vncport(server->port, domid);
+ xenstore_write_vncport(xsh, server->port, domid);
for (;;) {
FD_ZERO(&readfds);
diff --git a/tools/xm-test/lib/XmTestLib/acm.py b/tools/xm-test/lib/XmTestLib/acm.py
index a0d8a43c09..c670bc039b 100644
--- a/tools/xm-test/lib/XmTestLib/acm.py
+++ b/tools/xm-test/lib/XmTestLib/acm.py
@@ -57,6 +57,8 @@ def ACMLabelResources(resources):
# Applications may label resources explicitly by calling this function
def ACMLabelResource(resource, label='red'):
+ if not isACMEnabled():
+ return
if acm_verbose:
print "labeling resource %s with label %s" % (resource, label)
if not ACM_LABEL_RESOURCES: