# HG changeset patch
# User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
# Node ID e843c1fde3c2df049f9123b9998ca5cab1efad0f
# Parent a89599a12d4bf27e224135f0fe7c670526803a42
# Parent a330509abb20982fc75fb5fa66155d9bb09225f9
Merge
---
tools/examples/init.d/xendomains | 9 ++++-
tools/ioemu/hw/usb-hid.c | 19 +++++++++--
tools/ioemu/hw/usb-uhci.c | 42 ++++++++++++++++---------
tools/python/xen/web/httpserver.py | 44 +++++++++++++++++----------
tools/python/xen/xend/XendConfig.py | 37 +++++++++++++++++++++-
tools/python/xen/xend/XendDomainInfo.py | 19 ++++++-----
tools/python/xen/xend/server/SrvDomain.py | 13 +++++++
tools/python/xen/xend/server/SrvDomainDir.py | 37 ++++++++++++++++++++++
tools/python/xen/xm/create.py | 4 +-
tools/python/xen/xm/main.py | 17 +++++++---
10 files changed, 187 insertions(+), 54 deletions(-)
diff -r a89599a12d4b -r e843c1fde3c2 tools/examples/init.d/xendomains
--- a/tools/examples/init.d/xendomains Thu Dec 07 13:14:44 2006 +0000
+++ b/tools/examples/init.d/xendomains Thu Dec 07 13:18:08 2006 +0000
@@ -204,12 +204,14 @@ start()
return;
fi
+ saved_domains=" "
if [ "$XENDOMAINS_RESTORE" = "true" ] &&
contains_something "$XENDOMAINS_SAVE"
then
mkdir -p $(dirname "$LOCKFILE")
touch $LOCKFILE
echo -n "Restoring Xen domains:"
+ saved_domains=`ls $XENDOMAINS_SAVE`
for dom in $XENDOMAINS_SAVE/*; do
echo -n " ${dom##*/}"
xm restore $dom
@@ -234,9 +236,14 @@ start()
# Create all domains with config files in XENDOMAINS_AUTO.
# TODO: We should record which domain name belongs
# so we have the option to selectively shut down / migrate later
+ # If a domain statefile from $XENDOMAINS_SAVE matches a domain name
+ # in $XENDOMAINS_AUTO, do not try to start that domain; if it didn't
+ # restore correctly it requires administrative attention.
for dom in $XENDOMAINS_AUTO/*; do
echo -n " ${dom##*/}"
- if is_running $dom; then
+ shortdom=$(echo $dom | sed -n 's/^.*\/\(.*\)$/\1/p')
+ echo $saved_domains | grep -w $shortdom > /dev/null
+ if [ $? -eq 0 ] || is_running $dom; then
echo -n "(skip)"
else
xm create --quiet --defconfig $dom
diff -r a89599a12d4b -r e843c1fde3c2 tools/ioemu/hw/usb-hid.c
--- a/tools/ioemu/hw/usb-hid.c Thu Dec 07 13:14:44 2006 +0000
+++ b/tools/ioemu/hw/usb-hid.c Thu Dec 07 13:18:08 2006 +0000
@@ -39,6 +39,7 @@ typedef struct USBMouseState {
int x, y;
int kind;
int mouse_grabbed;
+ int status_changed;
} USBMouseState;
/* mostly the same values as the Bochs USB Mouse device */
@@ -231,6 +232,7 @@ static void usb_mouse_event(void *opaque
s->dy += dy1;
s->dz += dz1;
s->buttons_state = buttons_state;
+ s->status_changed = 1;
}
static void usb_tablet_event(void *opaque,
@@ -242,6 +244,7 @@ static void usb_tablet_event(void *opaqu
s->y = y;
s->dz += dz;
s->buttons_state = buttons_state;
+ s->status_changed = 1;
}
static inline int int_clamp(int val, int vmin, int vmax)
@@ -483,10 +486,16 @@ static int usb_mouse_handle_data(USBDevi
switch(pid) {
case USB_TOKEN_IN:
if (devep == 1) {
- if (s->kind == USB_MOUSE)
- ret = usb_mouse_poll(s, data, len);
- else if (s->kind == USB_TABLET)
- ret = usb_tablet_poll(s, data, len);
+ if (s->kind == USB_MOUSE)
+ ret = usb_mouse_poll(s, data, len);
+ else if (s->kind == USB_TABLET)
+ ret = usb_tablet_poll(s, data, len);
+
+ if (!s->status_changed)
+ ret = USB_RET_NAK;
+ else
+ s->status_changed = 0;
+
} else {
goto fail;
}
@@ -523,6 +532,7 @@ USBDevice *usb_tablet_init(void)
s->dev.handle_data = usb_mouse_handle_data;
s->dev.handle_destroy = usb_mouse_handle_destroy;
s->kind = USB_TABLET;
+ s->status_changed = 0;
pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");
@@ -544,6 +554,7 @@ USBDevice *usb_mouse_init(void)
s->dev.handle_data = usb_mouse_handle_data;
s->dev.handle_destroy = usb_mouse_handle_destroy;
s->kind = USB_MOUSE;
+ s->status_changed = 0;
pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse");
diff -r a89599a12d4b -r e843c1fde3c2 tools/ioemu/hw/usb-uhci.c
--- a/tools/ioemu/hw/usb-uhci.c Thu Dec 07 13:14:44 2006 +0000
+++ b/tools/ioemu/hw/usb-uhci.c Thu Dec 07 13:18:08 2006 +0000
@@ -424,12 +424,10 @@ static int uhci_handle_td(UHCIState *s,
uint8_t buf[2048];
int len, max_len, err, ret;
- if (td->ctrl & TD_CTRL_IOC) {
- *int_mask |= 0x01;
- }
-
- if (!(td->ctrl & TD_CTRL_ACTIVE))
- return 1;
+ if (!(td->ctrl & TD_CTRL_ACTIVE)){
+ ret = 1;
+ goto out;
+ }
/* TD is active */
max_len = ((td->token >> 21) + 1) & 0x7ff;
@@ -467,7 +465,8 @@ static int uhci_handle_td(UHCIState *s,
/* invalid pid : frame interrupted */
s->status |= UHCI_STS_HCPERR;
uhci_update_irq(s);
- return -1;
+ ret = -1;
+ goto out;
}
if (td->ctrl & TD_CTRL_IOS)
td->ctrl &= ~TD_CTRL_ACTIVE;
@@ -479,10 +478,12 @@ static int uhci_handle_td(UHCIState *s,
len < max_len) {
*int_mask |= 0x02;
/* short packet: do not update QH */
- return 1;
+ ret = 1;
+ goto out;
} else {
/* success */
- return 0;
+ ret = 0;
+ goto out;
}
} else {
switch(ret) {
@@ -501,23 +502,34 @@ static int uhci_handle_td(UHCIState *s,
}
td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) |
(err << TD_CTRL_ERROR_SHIFT);
- return 1;
+ ret = 1;
+ goto out;
case USB_RET_NAK:
td->ctrl |= TD_CTRL_NAK;
if (pid == USB_TOKEN_SETUP)
goto do_timeout;
- return 1;
+ ret = 1;
+ goto out;
case USB_RET_STALL:
td->ctrl |= TD_CTRL_STALL;
td->ctrl &= ~TD_CTRL_ACTIVE;
- return 1;
+ ret = 1;
+ goto out;
case USB_RET_BABBLE:
td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;
td->ctrl &= ~TD_CTRL_ACTIVE;
/* frame interrupted */
- return -1;
- }
- }
+ ret = -1;
+ goto out;
+ }
+ }
+
+out:
+ /* If TD is inactive and IOC bit set to 1 then update int_mask */
+ if ((td->ctrl & TD_CTRL_IOC) && (!(td->ctrl & TD_CTRL_ACTIVE))) {
+ *int_mask |= 0x01;
+ }
+ return ret;
}
static void uhci_frame_timer(void *opaque)
diff -r a89599a12d4b -r e843c1fde3c2 tools/python/xen/web/httpserver.py
--- a/tools/python/xen/web/httpserver.py Thu Dec 07 13:14:44 2006 +0000
+++ b/tools/python/xen/web/httpserver.py Thu Dec 07 13:18:08 2006 +0000
@@ -264,7 +264,32 @@ class HttpServerRequest(http.HttpRequest
s += x + "/"
self.write(' <a href="%s">%s</a>/' % (s, x))
self.write("</h1>")
-
+
+class HttpServerClient:
+
+ def __init__(self, server, sock, addr):
+ self.server = server
+ self.sock = sock
+ self.addr = addr
+
+ def process(self):
+ thread = threading.Thread(target=self.doProcess)
+ thread.setDaemon(True)
+ thread.start()
+
+ def doProcess(self):
+ try:
+ rp = RequestProcessor(self.server, self.sock, self.addr)
+ rp.process()
+ except SystemExit:
+ raise
+ except Exception, ex:
+ print 'HttpServer>processRequest> exception: ', ex
+ try:
+ self.sock.close()
+ except:
+ pass
+
class HttpServer:
backlog = 5
@@ -286,8 +311,8 @@ class HttpServer:
while not self.closed:
(sock, addr) = self.accept()
- self.processRequest(sock, addr)
-
+ cl = HttpServerClient(self, sock, addr)
+ cl.process()
def stop(self):
self.close()
@@ -313,19 +338,6 @@ class HttpServer:
self.socket.close()
except:
pass
-
- def processRequest(self, sock, addr):
- try:
- rp = RequestProcessor(self, sock, addr)
- rp.process()
- except SystemExit:
- raise
- except Exception, ex:
- print 'HttpServer>processRequest> exception: ', ex
- try:
- sock.close()
- except:
- pass
def getServerAddr(self):
return (socket.gethostname(), self.port)
diff -r a89599a12d4b -r e843c1fde3c2 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py Thu Dec 07 13:14:44 2006 +0000
+++ b/tools/python/xen/xend/XendConfig.py Thu Dec 07 13:18:08 2006 +0000
@@ -41,6 +41,39 @@ def reverse_dict(adict):
def bool0(v):
return v != '0' and bool(v)
+
+# Recursively copy a data struct, scrubbing out VNC passwords.
+# Will scrub any dict entry with a key of 'vncpasswd' or any
+# 2-element list whose first member is 'vncpasswd'. It will
+# also scrub a string matching '(vncpasswd XYZ)'. Everything
+# else is no-op passthrough
+def scrub_password(data):
+ if type(data) == dict or type(data) == XendConfig:
+ scrubbed = {}
+ for key in data.keys():
+ if key == "vncpasswd":
+ scrubbed[key] = "XXXXXXXX"
+ else:
+ scrubbed[key] = scrub_password(data[key])
+ return scrubbed
+ elif type(data) == list:
+ if len(data) == 2 and type(data[0]) == str and data[0] == 'vncpasswd':
+ return ['vncpasswd', 'XXXXXXXX']
+ else:
+ scrubbed = []
+ for entry in data:
+ scrubbed.append(scrub_password(entry))
+ return scrubbed
+ elif type(data) == tuple:
+ scrubbed = []
+ for entry in data:
+ scrubbed.append(scrub_password(entry))
+ return tuple(scrubbed)
+ elif type(data) == str:
+ return re.sub(r'\(vncpasswd\s+[^\)]+\)','(vncpasswd XXXXXX)', data)
+ else:
+ return data
+
# Mapping from XendConfig configuration keys to the old
# legacy configuration keys that map directly.
@@ -269,7 +302,7 @@ class XendConfig(dict):
# output from xc.domain_getinfo
self._dominfo_to_xapi(dominfo)
- log.debug('XendConfig.init: %s' % self)
+ log.debug('XendConfig.init: %s' % scrub_password(self))
# validators go here
self.validate()
@@ -478,7 +511,7 @@ class XendConfig(dict):
else:
for opt, val in config[1:]:
dev_info[opt] = val
- log.debug("XendConfig: reading device: %s" % dev_info)
+ log.debug("XendConfig: reading device: %s" %
scrub_password(dev_info))
# create uuid if it doesn't
dev_uuid = dev_info.get('uuid', uuid.createString())
dev_info['uuid'] = dev_uuid
diff -r a89599a12d4b -r e843c1fde3c2 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Thu Dec 07 13:14:44 2006 +0000
+++ b/tools/python/xen/xend/XendDomainInfo.py Thu Dec 07 13:18:08 2006 +0000
@@ -40,6 +40,7 @@ from xen.xend import balloon, sxp, uuid,
from xen.xend import balloon, sxp, uuid, image, arch
from xen.xend import XendRoot, XendNode, XendConfig
+from xen.xend.XendConfig import scrub_password
from xen.xend.XendBootloader import bootloader
from xen.xend.XendError import XendError, VmError
from xen.xend.XendDevices import XendDevices
@@ -148,7 +149,7 @@ def create(config):
@raise VmError: Invalid configuration or failure to start.
"""
- log.debug("XendDomainInfo.create(%s)", config)
+ log.debug("XendDomainInfo.create(%s)", scrub_password(config))
vm = XendDomainInfo(XendConfig.XendConfig(sxp_obj = config))
try:
vm.start()
@@ -175,7 +176,7 @@ def recreate(info, priv):
@raise XendError: Errors with configuration.
"""
- log.debug("XendDomainInfo.recreate(%s)", info)
+ log.debug("XendDomainInfo.recreate(%s)", scrub_password(info))
assert not info['dying']
@@ -257,7 +258,7 @@ def restore(config):
@raise XendError: Errors with configuration.
"""
- log.debug("XendDomainInfo.restore(%s)", config)
+ log.debug("XendDomainInfo.restore(%s)", scrub_password(config))
vm = XendDomainInfo(XendConfig.XendConfig(sxp_obj = config),
resume = True)
try:
@@ -280,7 +281,7 @@ def createDormant(domconfig):
@raise XendError: Errors with configuration.
"""
- log.debug("XendDomainInfo.createDormant(%s)", domconfig)
+ log.debug("XendDomainInfo.createDormant(%s)", scrub_password(domconfig))
# domid does not make sense for non-running domains.
domconfig.pop('domid', None)
@@ -520,11 +521,11 @@ class XendDomainInfo:
@param dev_config: device configuration
@type dev_config: SXP object (parsed config)
"""
- log.debug("XendDomainInfo.device_create: %s" % dev_config)
+ log.debug("XendDomainInfo.device_create: %s" %
scrub_password(dev_config))
dev_type = sxp.name(dev_config)
dev_uuid = self.info.device_add(dev_type, cfg_sxp = dev_config)
dev_config_dict = self.info['devices'][dev_uuid][1]
- log.debug("XendDomainInfo.device_create: %s" % dev_config_dict)
+ log.debug("XendDomainInfo.device_create: %s" %
scrub_password(dev_config_dict))
devid = self._createDevice(dev_type, dev_config_dict)
self._waitForDevice(dev_type, devid)
return self.getDeviceController(dev_type).sxpr(devid)
@@ -746,7 +747,7 @@ class XendDomainInfo:
to_store.update(self._vcpuDomDetails())
- log.debug("Storing domain details: %s", to_store)
+ log.debug("Storing domain details: %s", scrub_password(to_store))
self._writeDom(to_store)
@@ -1188,7 +1189,7 @@ class XendDomainInfo:
"""
for (devclass, config) in self.info.get('devices', {}).values():
if devclass in XendDevices.valid_devices():
- log.info("createDevice: %s : %s" % (devclass, config))
+ log.info("createDevice: %s : %s" % (devclass,
scrub_password(config)))
self._createDevice(devclass, config)
if self.image:
@@ -1667,7 +1668,7 @@ class XendDomainInfo:
if not self._readVm('xend/restart_count'):
to_store['xend/restart_count'] = str(0)
- log.debug("Storing VM details: %s", to_store)
+ log.debug("Storing VM details: %s", scrub_password(to_store))
self._writeVm(to_store)
self._setVmPermissions()
diff -r a89599a12d4b -r e843c1fde3c2 tools/python/xen/xend/server/SrvDomain.py
--- a/tools/python/xen/xend/server/SrvDomain.py Thu Dec 07 13:14:44 2006 +0000
+++ b/tools/python/xen/xend/server/SrvDomain.py Thu Dec 07 13:18:08 2006 +0000
@@ -21,6 +21,7 @@ from xen.xend import sxp
from xen.xend import sxp
from xen.xend import XendDomain
from xen.xend.Args import FormFn
+from xen.xend.XendLogging import log
from xen.web.SrvDir import SrvDir
@@ -62,6 +63,18 @@ class SrvDomain(SrvDir):
def op_shutdown(self, _, req):
self.acceptCommand(req)
return self.dom.shutdown(req.args['reason'][0])
+
+ def op_delete(self, _, req):
+ self.acceptCommand(req)
+ return self.xd.domain_delete(self.dom.getName())
+
+ def op_start(self, _, req):
+ self.acceptCommand(req)
+ paused = False
+ if 'paused' in req.args and req.args['paused'] == [1]:
+ paused = True
+ log.debug("Starting domain " + self.dom.getName() + " " + str(paused))
+ return self.xd.domain_start(self.dom.getName(), paused)
def op_sysrq(self, _, req):
self.acceptCommand(req)
diff -r a89599a12d4b -r e843c1fde3c2
tools/python/xen/xend/server/SrvDomainDir.py
--- a/tools/python/xen/xend/server/SrvDomainDir.py Thu Dec 07 13:14:44
2006 +0000
+++ b/tools/python/xen/xend/server/SrvDomainDir.py Thu Dec 07 13:18:08
2006 +0000
@@ -25,6 +25,8 @@ from xen.xend.XendDomainInfo import Xend
from xen.xend.XendDomainInfo import XendDomainInfo
from xen.xend.Args import FormFn
from xen.xend.XendError import XendError
+from xen.xend.XendLogging import log
+from xen.xend.XendConstants import DOM_STATE_RUNNING
from xen.web.SrvDir import SrvDir
from SrvDomain import SrvDomain
@@ -101,6 +103,35 @@ class SrvDomainDir(SrvDir):
out.close()
return val
+ def op_new(self, _, req):
+ """Define a new domain.
+ Expects the domain config in request parameter 'config' in SXP format.
+ """
+ ok = 0
+ errmsg = ''
+ try:
+ configstring = req.args.get('config')[0]
+ #print 'op_create>', 'config:', configstring
+ pin = sxp.Parser()
+ pin.input(configstring)
+ pin.input_eof()
+ config = pin.get_val()
+ ok = 1
+ except sxp.ParseError, ex:
+ errmsg = 'Invalid configuration ' + str(ex)
+ except Exception, ex:
+ print 'op_create> Exception in config', ex
+ traceback.print_exc()
+ errmsg = 'Configuration error ' + str(ex)
+ if not ok:
+ raise XendError(errmsg)
+ try:
+ self.xd.domain_new(config)
+ except Exception, ex:
+ print 'op_create> Exception creating domain:'
+ traceback.print_exc()
+ raise XendError("Error creating domain: " + str(ex))
+
def op_restore(self, op, req):
"""Restore a domain from file.
@@ -159,7 +190,11 @@ class SrvDomainDir(SrvDir):
if detail:
sxp.show(map(XendDomainInfo.sxpr, self.xd.list()), out=req)
else:
- sxp.show(self.xd.list_names(), out=req)
+ state = DOM_STATE_RUNNING
+ if 'state' in req.args and len(req.args['state']) > 0:
+ state = req.args['state'][0]
+ log.debug("Listing domains in state " + str(state))
+ sxp.show(self.xd.list_names(state), out=req)
else:
domains = self.xd.list_sorted()
req.write('<ul>')
diff -r a89599a12d4b -r e843c1fde3c2 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py Thu Dec 07 13:14:44 2006 +0000
+++ b/tools/python/xen/xm/create.py Thu Dec 07 13:18:08 2006 +0000
@@ -704,8 +704,10 @@ def configure_hvm(config_image, vals):
config_image.append(['vncpasswd', vals.vncpasswd])
def run_bootloader(vals, config_image):
+ if not os.access(vals.bootloader, os.F_OK):
+ err("Bootloader '%s' does not exist" % vals.bootloader)
if not os.access(vals.bootloader, os.X_OK):
- err("Bootloader isn't executable")
+ err("Bootloader '%s' isn't executable" % vals.bootloader)
if len(vals.disk) < 1:
err("No disks configured and boot loader requested")
(uname, dev, mode, backend) = vals.disk[0]
diff -r a89599a12d4b -r e843c1fde3c2 tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py Thu Dec 07 13:14:44 2006 +0000
+++ b/tools/python/xen/xm/main.py Thu Dec 07 13:18:08 2006 +0000
@@ -30,6 +30,7 @@ import traceback
import traceback
import xmlrpclib
import traceback
+import time
import datetime
from select import select
import xml.dom.minidom
@@ -626,7 +627,13 @@ def parse_doms_info(info):
def get_status(n, t, d):
return DOM_STATES[t(sxp.child_value(info, n, d))]
-
+
+ start_time = get_info('start_time', float, -1)
+ if start_time == -1:
+ up_time = float(-1)
+ else:
+ up_time = time.time() - start_time
+
return {
'domid' : get_info('domid', str, ''),
'name' : get_info('name', str, '??'),
@@ -634,7 +641,7 @@ def parse_doms_info(info):
'vcpus' : get_info('vcpus', int, 0),
'state' : get_info('state', str, ''),
'cpu_time' : get_info('cpu_time', float, 0),
- 'up_time' : get_info('up_time', float, -1),
+ 'up_time' : up_time,
'seclabel' : security.get_security_printlabel(info),
}
@@ -1209,7 +1216,7 @@ def xm_uptime(args):
for dom in doms:
d = parse_doms_info(dom)
- if d['domid'] > 0:
+ if int(d['domid']) > 0:
uptime = int(round(d['up_time']))
else:
f=open('/proc/uptime', 'r')
@@ -1236,10 +1243,10 @@ def xm_uptime(args):
if short_mode:
now = datetime.datetime.now()
upstring = now.strftime(" %H:%M:%S") + " up " + upstring
- upstring += ", " + d['name'] + " (" + str(d['domid']) + ")"
+ upstring += ", " + d['name'] + " (" + d['domid'] + ")"
else:
upstring += ':%(seconds)02d' % vars()
- upstring = ("%(name)-32s %(domid)3d " % d) + upstring
+ upstring = ("%(name)-32s %(domid)3s " % d) + upstring
print upstring
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|